4 #ifndef entry_point_testing
10 #include <glad\glad.h>
11 #include <GLFW\glfw3.h>
12 #include <glm\glm.hpp>
13 #include "GLFWUtil.hpp"
15 // Engine header files
17 #include "Texture.hpp"
18 #include "FrameBuffer.hpp"
24 #include "cxxopts.hpp"
25 #include "interpolation.h"
26 #include "vfilesys.hpp"
29 #define STBI_MSC_SECURE_CRT
30 #define STB_IMAGE_WRITE_IMPLEMENTATION
31 #include "stb_image_write.h"
33 #include "GradientMap.hpp"
36 //#define TAR_EXPERIMENTAL
38 /* Grabs the currently bound framebuffer and saves it to a .png */
39 void render_to_png(int x
, int y
, const char* filepath
){
40 void* data
= malloc(4 * x
* y
);
42 glReadPixels(0, 0, x
, y
, GL_RGBA
, GL_UNSIGNED_BYTE
, data
);
44 stbi_flip_vertically_on_write(true);
45 stbi_write_png(filepath
, x
, y
, 4, data
, x
* 4);
50 /* Grabs the currently bound framebuffer and saves it to a .dds */
51 void save_to_dds(int x
, int y
, const char* filepath
, IMG imgmode
= IMG::MODE_DXT1
) {
52 void* data
= malloc(4 * x
* y
);
54 glReadPixels(0, 0, x
, y
, GL_RGB
, GL_UNSIGNED_BYTE
, data
);
56 dds_write((uint8_t*)data
, filepath
, x
, y
, imgmode
);
61 /* Renders opengl in opaque mode (normal) */
62 void opengl_render_opaque() {
64 glEnable(GL_DEPTH_TEST
);
68 /* Renders opengl in addative mode */
69 void opengl_render_additive() {
73 // I still do not fully understand OPENGL blend modes. However these equations looks nice for the grid floor.
74 glBlendEquationSeparate(GL_FUNC_ADD
, GL_FUNC_ADD
);
75 glBlendFuncSeparate(GL_ONE
, GL_ONE
, GL_ZERO
, GL_ONE
);
78 /* Command line variables */
80 std::string m_mapfile_path
;
81 std::string m_game_path
;
84 std::string m_mapfile_path
= "sample_stuff/de_tavr_test";
85 std::string m_game_path
= "D:/SteamLibrary/steamapps/common/Counter-Strike Global Offensive/csgo";
89 std::string m_mapfile_name
;
90 std::string m_overviews_folder
;
91 std::string m_resources_folder
;
93 vfilesys
* filesys
= NULL
;
96 bool m_outputMasks
= true;
97 bool m_onlyOutputMasks
;
99 bool m_comp_shadows_enable
= true;
100 bool m_comp_ao_enable
= true;
105 bool m_onlyOutputMasks
;
107 bool m_comp_shadows_enable
;
108 bool m_comp_ao_enable
;
111 //tar_config overrides
112 uint32_t m_renderWidth
= 1024;
113 uint32_t m_renderHeight
= 1024;
114 bool m_enable_maskgen_supersample
= true;
116 bool tar_cfg_enableAO
= true;
117 int tar_cfg_aoSzie
= 16;
119 bool tar_cfg_enableShadows
= false;
121 bool tar_cfg_enableOutline
= false;
122 int tar_cfg_outlineSize
= 2;
124 Texture
* tar_cfg_gradientMap
;
127 int app(int argc
, const char** argv
) {
129 cxxopts::Options
options("AutoRadar", "Auto radar");
130 options
.add_options()
131 ("v,version", "Shows the software version")
132 ("g,game", "(REQUIRED) Specify game path", cxxopts::value
<std::string
>()->default_value(""))
133 ("m,mapfile", "(REQUIRED) Specify the map file (vmf)", cxxopts::value
<std::string
>()->default_value(""))
135 ("d,dumpMasks", "Toggles whether auto radar should output mask images (resources/map_file.resources/)")
136 ("o,onlyMasks", "Specift whether auto radar should only output mask images and do nothing else (resources/map_file.resources)")
138 ("ao", "[OBSOLETE] Turn on AO in the compisotor")
139 ("shadows", "[OBSOLETE] Turn on Shadows in the compositor")
141 ("w,width", "[OBSOLETE] Render width in pixels (experimental)", cxxopts::value
<uint32_t>()->default_value("1024"))
142 ("h,height", "[OBSOLETE] Render height in pixels (experimental)", cxxopts::value
<uint32_t>()->default_value("1024"))
145 ("autoModulate", "Enables automatic height modulation between two levels")
146 ("minHeightDiff", "Minumum height difference(units) to modulate between two levels", cxxopts::value
<int>()->default_value("128"))
149 ("useVBSP", "Use VBSP.exe to pre-process brush unions automatically")
150 ("useLightmaps", "Use lightmaps generated by vvis in the VBSP. (If this flag is set, Auto Radar must be ran after vvis.exe)")
152 ("positional", "Positional parameters", cxxopts::value
<std::vector
<std::string
>>());
154 options
.parse_positional("positional");
155 auto result
= options
.parse(argc
, argv
);
157 /* Check required parameters */
158 if (result
.count("game")) m_game_path
= sutil::ReplaceAll(result
["game"].as
<std::string
>(), "\n", "");
159 else throw cxxopts::option_required_exception("game");
161 if(result
.count("mapfile")) m_mapfile_path
= result
["mapfile"].as
<std::string
>();
162 else if (result
.count("positional")) {
163 auto& positional
= result
["positional"].as
<std::vector
<std::string
>>();
165 m_mapfile_path
= sutil::ReplaceAll(positional
[0], "\n", "");
167 else throw cxxopts::option_required_exception("mapfile"); // We need a map file
169 //Clean paths to what we can deal with
170 m_mapfile_path
= sutil::ReplaceAll(m_mapfile_path
, "\\", "/");
171 m_game_path
= sutil::ReplaceAll(m_game_path
, "\\", "/");
173 /* Check the rest of the flags */
174 m_onlyOutputMasks
= result
["onlyMasks"].as
<bool>();
175 m_outputMasks
= result
["dumpMasks"].as
<bool>() || m_onlyOutputMasks
;
178 m_renderWidth
= result
["width"].as
<uint32_t>();
179 m_renderHeight
= result
["height"].as
<uint32_t>();
181 m_comp_ao_enable
= result
["ao"].as
<bool>();
182 m_comp_shadows_enable
= result
["shadows"].as
<bool>();
187 m_mapfile_name
= split(m_mapfile_path
, '/').back();
188 m_overviews_folder
= m_game_path
+ "/resource/overviews/";
189 m_resources_folder
= m_overviews_folder
+ m_mapfile_name
+ ".resources/";
192 std::cout << "Launching with options:\n";
193 std::cout << " Render width: " << m_renderWidth << "\n";
194 std::cout << " Render height: " << m_renderHeight << "\n";
195 std::cout << " Save masks? " << (m_outputMasks ? "YES" : "NO") << "\n";
196 std::cout << " Output to game? " << (!m_onlyOutputMasks ? "YES" : "NO") << "\n\n";
197 std::cout << " Game path: " << m_game_path << "\n";
198 std::cout << " Map path: " << m_mapfile_path << "\n";
199 std::cout << "\n -------- RENDER SETTINGS -------\n";
200 std::cout << " AO: " << (m_comp_ao_enable ? "YES" : "NO") << "\n";
201 std::cout << " Shadows: " << (m_comp_shadows_enable ? "YES" : "NO") << "\n";
205 filesys
= new vfilesys(m_game_path
+ "/gameinfo.txt");
207 catch (std::exception e
) {
208 std::cout
<< "Error creating vfilesys:\n";
209 std::cout
<< e
.what() << "\n";
214 filesys
->debug_info();
216 std::cout
<< "Initializing OpenGL\n";
218 #pragma region init_opengl
221 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR
, 3); //We are using version 3.3 of openGL
222 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR
, 3);
223 glfwWindowHint(GLFW_OPENGL_PROFILE
, GLFW_OPENGL_CORE_PROFILE
);
224 glfwWindowHint(GLFW_RESIZABLE
, GL_FALSE
);
225 glfwWindowHint(GLFW_VISIBLE
, GL_FALSE
); // Window le nope
228 GLFWwindow
* window
= glfwCreateWindow(1, 1, "If you are seeing this window, something is broken", NULL
, NULL
);
230 //Check if window open
232 std::cout
<< "Failed to create GLFW window" << std::endl
;
233 glfwTerminate(); return -1;
235 glfwMakeContextCurrent(window
);
238 if (!gladLoadGLLoader((GLADloadproc
)glfwGetProcAddress
)){
239 std::cout
<< "Failed to initialize GLAD" << std::endl
; return -1;
242 const unsigned char* glver
= glGetString(GL_VERSION
);
243 std::cout
<< "(required: min core 3.3.0) opengl version: " << glver
<< "\n";
245 glEnable(GL_DEPTH_TEST
);
247 glViewport(0, 0, m_renderWidth
, m_renderHeight
);
249 glClearColor(0.00f
, 0.00f
, 0.00f
, 0.00f
);
251 std::cout
<< "Creating render buffers\n";
253 FrameBuffer fb_tex_playspace
= FrameBuffer(m_renderWidth
, m_renderHeight
);
254 FrameBuffer fb_tex_objectives
= FrameBuffer(m_renderWidth
, m_renderHeight
);
255 FrameBuffer fb_comp
= FrameBuffer(m_renderWidth
* 2, m_renderHeight
* 2);
256 FrameBuffer fb_comp_1
= FrameBuffer(m_renderWidth
* 2, m_renderHeight
* 2); //Reverse ordered frame buffer
257 FrameBuffer fb_final
= FrameBuffer(m_renderWidth
, m_renderHeight
);
260 std::cout
<< "Creating screenspace mesh\n";
262 std::vector
<float> __meshData
= {
271 Mesh
* mesh_screen_quad
= new Mesh(__meshData
, MeshMode::SCREEN_SPACE_UV
);
275 #pragma region shader_compilation
277 std::cout
<< "Compiling Shaders\n";
278 std::cout
<< "______________________________________________________________\n\n";
280 // Internal engine shaders
281 Shader
shader_depth("shaders/depth.vs", "shaders/depth.fs");
282 Shader
shader_unlit("shaders/unlit.vs", "shaders/unlit.fs");
284 // Compositing shaders
285 Shader
shader_comp_main("shaders/fullscreenbase.vs", "shaders/ss_comp_main.fs"); // le big one
286 Shader
shader_precomp_playspace("shaders/fullscreenbase.vs", "shaders/ss_precomp_playspace.fs"); // computes distance map
287 Shader
shader_precomp_objectives("shaders/fullscreenbase.vs", "shaders/ss_precomp_objectives.fs"); // computes distance map
289 if (shader_depth
.compileUnsuccessful
||
290 shader_unlit
.compileUnsuccessful
||
291 shader_comp_main
.compileUnsuccessful
||
292 shader_precomp_playspace
.compileUnsuccessful
||
293 shader_precomp_objectives
.compileUnsuccessful
) {
295 std::cout
<< "______________________________________________________________\n";
296 std::cout
<< "Shader compilation step failed.\n";
304 std::cout
<< "______________________________________________________________\n";
305 std::cout
<< "Shader compilation successful\n\n";
307 std::cout
<< "Loading textures... ";
309 Texture tex_background
= Texture("textures/grid.png");
310 //Texture tex_gradient = Texture("textures/gradients/gradientmap_6.png", true);
311 Texture tex_height_modulate
= Texture("textures/modulate.png");
313 //GradientTexture gtex_gradient = GradientTexture(std::string("32 68 136 255"), std::string("149 0 0 255"), std::string("178 113 65"));
315 std::cout
<< "done!\n\n";
319 #pragma region map_load
321 std::cout
<< "Loading map file...\n";
323 vmf::vmf
vmf_main(m_mapfile_path
+ ".vmf");
324 //vmf_main.setup_main();
325 //vmf_main.genVMFReferences(); // Load all our func_instances
327 //std::cout << "Generating Meshes...\n";
329 vmf_main
.ComputeGLMeshes();
330 vmf_main
.ComputeDisplacements();
333 std::vector
<vmf::Entity
*> tavr_ent_tar_config
= vmf_main
.findEntitiesByClassName("tar_config");
335 if (tavr_ent_tar_config
.size() > 1) {
336 std::cout
<< "More than 1 tar config found! Currently unsupported... Using last.\n";
339 vmf::Entity
* tar_config
= NULL
;
340 if (tavr_ent_tar_config
.size() > 0) {
341 tar_config
= tavr_ent_tar_config
.back();
344 std::string schemeNum
= kv::tryGetStringValue(tar_config
->keyValues
, "colorScheme", "0");
345 if (schemeNum
== "-1") { // Custom color scheme
346 tar_cfg_gradientMap
= new GradientTexture(
347 kv::tryGetStringValue(tar_config
->keyValues
, "customCol0", "0 0 0 255"),
348 kv::tryGetStringValue(tar_config
->keyValues
, "customCol1", "128 128 128 255"),
349 kv::tryGetStringValue(tar_config
->keyValues
, "customCol2", "255 255 255 255"));
351 tar_cfg_gradientMap
= new Texture("textures/gradients/gradientmap_" + schemeNum
+ ".png", true);
355 tar_cfg_enableAO
= (kv::tryGetStringValue(tar_config
->keyValues
, "enableAO", "1") == "1");
356 tar_cfg_aoSzie
= kv::tryGetValue(tar_config
->keyValues
, "aoSize", 16);
359 tar_cfg_enableOutline
= (kv::tryGetStringValue(tar_config
->keyValues
, "enableOutline", "0") == "1");
360 tar_cfg_outlineSize
= kv::tryGetValue(tar_config
->keyValues
, "outlineWidth", 2);
363 tar_cfg_enableShadows
= (kv::tryGetStringValue(tar_config
->keyValues
, "enableShadows", "0") == "1");
366 tar_cfg_gradientMap
= new Texture("textures/gradients/gradientmap_6.png", true);
369 std::cout
<< "Collecting Objects... \n";
370 std::vector
<vmf::Solid
*> tavr_solids
= vmf_main
.getAllBrushesInVisGroup(tar_config
== NULL
? "tar_layout" : kv::tryGetStringValue(tar_config
->keyValues
, "vgroup_layout", "tar_layout"));
371 std::vector
<vmf::Solid
*> tavr_solids_negative
= vmf_main
.getAllBrushesInVisGroup(tar_config
== NULL
? "tar_mask" : kv::tryGetStringValue(tar_config
->keyValues
, "vgroup_negative", "tar_mask"));
372 std::vector
<vmf::Solid
*> tavr_entire_brushlist
= vmf_main
.getAllRenderBrushes();
373 std::vector
<vmf::Solid
*> tavr_cover
= vmf_main
.getAllBrushesInVisGroup(tar_config
== NULL
? "tar_cover" : kv::tryGetStringValue(tar_config
->keyValues
, "vgroup_cover", "tar_cover"));
374 for (auto && v
: tavr_cover
) { v
->temp_mark
= true; tavr_solids
.push_back(v
); }
376 //std::vector<vmf::Solid*> tavr_solids_funcbrush = vmf_main.getAllBrushesByClassName("func_brush");
377 std::vector
<vmf::Solid
*> tavr_buyzones
= vmf_main
.getAllBrushesByClassName("func_buyzone");
378 std::vector
<vmf::Solid
*> tavr_bombtargets
= vmf_main
.getAllBrushesByClassName("func_bomb_target");
380 std::vector
<vmf::Entity
*> tavr_ent_tavr_height_min
= vmf_main
.findEntitiesByClassName("tar_min");
381 std::vector
<vmf::Entity
*> tavr_ent_tavr_height_max
= vmf_main
.findEntitiesByClassName("tar_max");
384 std::cout
<< "Collecting models... \n";
385 vmf_main
.populateModelDict(filesys
);
386 vmf_main
.populatePropList(tar_config
== NULL
? "tar_cover" : kv::tryGetStringValue(tar_config
->keyValues
, "vgroup_cover", "tar_cover"));
388 std::cout
<< "done!\n";
390 #pragma region bounds
391 std::cout
<< "Calculating bounds... ";
393 vmf::BoundingBox limits
= vmf::getSolidListBounds(tavr_solids
);
394 float z_render_min
= limits
.SEL
.y
;
395 float z_render_max
= limits
.NWU
.y
;
397 // Overide entity heights
398 if (tavr_ent_tavr_height_min
.size()) z_render_min
= tavr_ent_tavr_height_min
[0]->origin
.z
;
399 if (tavr_ent_tavr_height_max
.size()) z_render_max
= tavr_ent_tavr_height_max
[0]->origin
.z
;
401 float padding
= 128.0f
;
403 float x_bounds_min
= -limits
.NWU
.x
- padding
; //inflate distances slightly
404 float x_bounds_max
= -limits
.SEL
.x
+ padding
;
406 float y_bounds_min
= limits
.SEL
.z
- padding
;
407 float y_bounds_max
= limits
.NWU
.z
+ padding
;
409 float dist_x
= x_bounds_max
- x_bounds_min
;
410 float dist_y
= y_bounds_max
- y_bounds_min
;
412 float mx_dist
= glm::max(dist_x
, dist_y
);
414 float justify_x
= (mx_dist
- dist_x
) * 0.5f
;
415 float justify_y
= (mx_dist
- dist_y
) * 0.5f
;
417 float render_ortho_scale
= glm::round((mx_dist
/ 1024.0f
) / 0.01f
) * 0.01f
* 1024.0f
; // Take largest, scale up a tiny bit. Clamp to 1024 min. Do some rounding.
418 glm::vec2 view_origin
= glm::vec2(x_bounds_min
- justify_x
, y_bounds_max
+ justify_y
);
420 std::cout
<< "done\n\n";
425 #pragma region OpenGLRender
427 std::cout
<< "Starting OpenGL Render\n";
429 #pragma region render_playable_space
430 std::cout
<< "Rendering playable space... ";
432 // ======================================================== REGULAR ORDER ========================================================
434 glViewport(0, 0, m_renderWidth
* 2, m_renderHeight
* 2);
436 fb_comp
.Bind(); //Bind framebuffer
438 glClearColor(0.00f
, 0.00f
, 0.00f
, 1.00f
);
439 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
440 glPolygonMode(GL_FRONT
, GL_FILL
);
443 shader_depth
.setMatrix("projection", glm::ortho(view_origin
.x
, view_origin
.x
+ render_ortho_scale
, view_origin
.y
- render_ortho_scale
, view_origin
.y
, -1024.0f
, 1024.0f
));
444 shader_depth
.setMatrix("view", glm::lookAt(glm::vec3(0, 0, 0), glm::vec3(0, -1.0f
, 0), glm::vec3(0, 0, 1)));
446 glm::mat4 model
= glm::mat4();
447 shader_depth
.setMatrix("model", model
);
449 shader_depth
.setFloat("HEIGHT_MIN", z_render_min
);
450 shader_depth
.setFloat("HEIGHT_MAX", z_render_max
);
451 shader_depth
.setFloat("write_playable", 0.0f
);
453 // Render entire map first
454 for (auto && brush
: tavr_entire_brushlist
) {
455 shader_depth
.setFloat("write_cover", brush
->temp_mark
? 1.0f
: 0.0f
);
458 glClear(GL_DEPTH_BUFFER_BIT
);
460 // Render playable area over it
461 shader_depth
.setFloat("write_playable", 1.0f
);
462 for (auto && s_solid
: tavr_solids
) {
463 shader_depth
.setFloat("write_cover", s_solid
->temp_mark
? 1.0f
: 0.0f
);
464 if (!s_solid
->containsDisplacements
)
465 s_solid
->mesh
->Draw();
467 for (auto && f
: s_solid
->faces
) {
468 if (f
.displacement
!= NULL
) {
469 f
.displacement
->glMesh
->Draw();
475 #ifdef TAR_EXPERIMENTAL
476 // Render instances (experimental)
477 for (auto && sub_vmf
: vmf_main
.findEntitiesByClassName("func_instance")) {
478 std::string mapname
= kv::tryGetStringValue(sub_vmf
->keyValues
, "file", "");
480 if (mapname
== "") continue; //Something went wrong...
485 model
= glm::translate(model
, glm::vec3(-sub_vmf
->origin
.x
, sub_vmf
->origin
.z
, sub_vmf
->origin
.y
));
488 shader_depth
.setMatrix("model", model
);
490 for (auto && solid
: vmf_main
.subvmf_references
[mapname
]->getAllBrushesInVisGroup("tar_cover")) {
491 shader_depth
.setFloat("write_cover", solid
->temp_mark
? 1.0f
: 1.0f
);
492 if (!solid
->containsDisplacements
)
495 for (auto && f
: solid
->faces
) {
496 if (f
.displacement
!= NULL
) {
497 f
.displacement
->glMesh
->Draw();
503 #endif // TAR_EXPERIMENTAL
506 std::cout
<< "Rendering props\n";
507 shader_depth
.setFloat("write_cover", 1.0f
);
508 for (auto && s_prop
: vmf_main
.props
) {
509 if (vmf_main
.modelCache
[s_prop
.modelID
] == NULL
) continue; // Skip uncanched / errored models. This shouldn't happen if the vmf references everything normally and all files exist.
512 model
= glm::translate(model
, s_prop
.origin
); // Position
513 model
= glm::rotate(model
, glm::radians(s_prop
.rotation
.y
), glm::vec3(0, 1, 0)); // Yaw
514 model
= glm::rotate(model
, glm::radians(s_prop
.rotation
.x
), glm::vec3(0, 0, 1)); // ROOOOOLLLLL
515 model
= glm::rotate(model
, -glm::radians(s_prop
.rotation
.z
), glm::vec3(1, 0, 0)); // Pitch
516 model
= glm::scale(model
, glm::vec3(s_prop
.unifromScale
)); // Scale
518 shader_depth
.setMatrix("model", model
);
519 vmf_main
.modelCache
[s_prop
.modelID
]->Draw();
523 shader_depth
.setMatrix("model", model
);
525 // Re render subtractive brushes
526 shader_depth
.setFloat("write_playable", 0.0f
);
527 for (auto && s_solid
: tavr_solids_negative
) {
528 shader_depth
.setFloat("write_cover", s_solid
->temp_mark
? 1.0f
: 0.0f
);
529 if (!s_solid
->containsDisplacements
)
530 s_solid
->mesh
->Draw();
532 for (auto && f
: s_solid
->faces
) {
533 if (f
.displacement
!= NULL
) {
534 f
.displacement
->glMesh
->Draw();
540 // ======================================================== REVERSE ORDER ========================================================
546 glEnable(GL_CULL_FACE
);
547 glDepthFunc(GL_GREATER
);
549 glClearColor(0.00f
, 0.00f
, 0.00f
, 1.00f
);
550 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
551 glPolygonMode(GL_FRONT
, GL_FILL
);
553 shader_depth
.setFloat("HEIGHT_MIN", z_render_min
);
554 shader_depth
.setFloat("HEIGHT_MAX", z_render_max
);
555 shader_depth
.setFloat("write_playable", 0.0f
);
557 for (auto && s_solid
: tavr_solids
) {
558 if (!s_solid
->containsDisplacements
)
559 s_solid
->mesh
->Draw();
561 for (auto && f
: s_solid
->faces
) {
562 if (f
.displacement
!= NULL
) {
563 f
.displacement
->glMesh
->Draw();
569 // regular depth testing
571 glDepthFunc(GL_LESS
);
572 glDisable(GL_CULL_FACE
);
574 // ========================================================== PRE-COMP ===========================================================
576 glViewport(0, 0, m_renderWidth
, m_renderHeight
);
579 fb_tex_playspace
.Bind();
581 glClearColor(0.00f
, 0.00f
, 0.00f
, 0.00f
);
582 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
583 glDisable(GL_DEPTH_TEST
);
584 glPolygonMode(GL_FRONT
, GL_FILL
);
586 shader_precomp_playspace
.use();
588 //shader_precomp_playspace.setFloat("HEIGHT_MIN", z_render_min);
589 //shader_precomp_playspace.setFloat("HEIGHT_MAX", z_render_max);
591 fb_comp
.BindRTtoTexSlot(0);
592 shader_precomp_playspace
.setInt("tex_in", 0);
594 fb_comp_1
.BindRTtoTexSlot(1);
595 shader_precomp_playspace
.setInt("tex_in_1", 1);
597 //tex_height_modulate.bindOnSlot(2);
598 //shader_precomp_playspace.setInt("tex_modulate", 2);
600 mesh_screen_quad
->Draw();
602 glEnable(GL_DEPTH_TEST
);
604 if(m_outputMasks
) render_to_png(m_renderWidth
, m_renderHeight
, filesys
->create_output_filepath("resource/overviews/" + m_mapfile_name
+ ".resources/playspace.png", true).c_str());
606 std::cout
<< "done!\n";
609 #pragma region render_objectives
610 std::cout
<< "Rendering bombsites & buyzones space... ";
612 glViewport(0, 0, m_renderWidth
* 2, m_renderHeight
* 2);
616 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
617 glPolygonMode(GL_FRONT
, GL_FILL
);
618 //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
621 shader_unlit
.setMatrix("projection", glm::ortho(view_origin
.x
, view_origin
.x
+ render_ortho_scale
, view_origin
.y
- render_ortho_scale
, view_origin
.y
, -1024.0f
, 1024.0f
));
622 shader_unlit
.setMatrix("view", glm::lookAt(glm::vec3(0, 0, 0), glm::vec3(0, -1.0f
, 0), glm::vec3(0, 0, 1)));
623 shader_unlit
.setMatrix("model", model
);
625 shader_unlit
.setVec3("color", 0.0f
, 1.0f
, 0.0f
);
627 for (auto && s_solid
: tavr_buyzones
) {
628 s_solid
->mesh
->Draw();
632 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
634 shader_unlit
.setVec3("color", 1.0f
, 0.0f
, 0.0f
);
636 for (auto && s_solid
: tavr_bombtargets
) {
637 s_solid
->mesh
->Draw();
641 glViewport(0, 0, m_renderWidth
, m_renderHeight
);
643 fb_tex_objectives
.Bind();
645 glClearColor(0.00f
, 0.00f
, 0.00f
, 0.00f
);
646 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
647 glDisable(GL_DEPTH_TEST
);
648 glPolygonMode(GL_FRONT
, GL_FILL
);
650 shader_precomp_objectives
.use();
652 fb_comp
.BindRTtoTexSlot(0);
653 shader_precomp_objectives
.setInt("tex_in", 0);
655 fb_comp_1
.BindRTtoTexSlot(1);
656 shader_precomp_objectives
.setInt("tex_in_1", 1);
658 fb_tex_playspace
.BindRTtoTexSlot(2);
659 shader_precomp_objectives
.setInt("tex_in_2", 2);
661 mesh_screen_quad
->Draw();
663 if (m_outputMasks
) render_to_png(m_renderWidth
, m_renderHeight
, filesys
->create_output_filepath("resource/overviews/" + m_mapfile_name
+ ".resources/buyzones_bombtargets.png", true).c_str());
665 glEnable(GL_DEPTH_TEST
);
666 std::cout
<< "done!\n";
669 #pragma region compositing
670 std::cout
<< "Compositing... \n";
674 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
675 glPolygonMode(GL_FRONT
, GL_FILL
);
677 shader_comp_main
.use();
679 /* Fill out shader uniforms */
681 vec3 bounds_NWU North-West-Upper coordinate of the playspace (worldspace)
682 vec3 bounds_SEL South-East-Lower coordinate of the playspace (worldspace)
683 **vec2 bounds_NWU_SS North-West coordinate of the playspace (screen space)
684 **vec2 bounds_SEL_SS South-East coordinate of the playspace (screen space)
686 **vec2 pos_spawn_ct Location of the CT Spawn (0-1)
687 **vec2 pos_spawn_t Location of the T Spawn (0-1)
688 **vec2 bombsite_a Location of bomsite A (0-1)
689 **vec2 bombsite_b Location of bombsite B (0-1)
691 shader_comp_main
.setVec3("bounds_NWU", glm::vec3(x_bounds_min
, y_bounds_max
, z_render_max
));
692 shader_comp_main
.setVec3("bounds_SEL", glm::vec3(x_bounds_max
, y_bounds_min
, z_render_min
));
695 shader_comp_main
.setInt("cmdl_shadows_enable", tar_cfg_enableShadows
? 1 : 0);
696 shader_comp_main
.setInt("cmdl_ao_enable", tar_cfg_enableAO
? 1 : 0);
697 shader_comp_main
.setInt("cmdl_ao_size", tar_cfg_aoSzie
);
698 shader_comp_main
.setInt("cmdl_outline_enable", tar_cfg_enableOutline
);
699 shader_comp_main
.setInt("cmdl_outline_size", tar_cfg_outlineSize
);
701 shader_comp_main
.setVec4("outline_color", parseVec4(kv::tryGetStringValue(tar_config
->keyValues
, "zColOutline", "255 255 255 255")));
702 shader_comp_main
.setVec4("ao_color", parseVec4(kv::tryGetStringValue(tar_config
->keyValues
, "zColAO", "255 255 255 255")));
704 shader_comp_main
.setVec4("buyzone_color", parseVec4(kv::tryGetStringValue(tar_config
->keyValues
, "zColBuyzone", "255 255 255 255")));
705 shader_comp_main
.setVec4("objective_color", parseVec4(kv::tryGetStringValue(tar_config
->keyValues
, "zColObjective", "255 255 255 255")));
706 shader_comp_main
.setVec4("cover_color", parseVec4(kv::tryGetStringValue(tar_config
->keyValues
, "zColCover", "255 255 255 255")));
708 /* Bind texture samplers */
709 tex_background
.bindOnSlot(0);
710 shader_comp_main
.setInt("tex_background", 0);
712 fb_tex_playspace
.BindRTtoTexSlot(1);
713 shader_comp_main
.setInt("tex_playspace", 1);
715 fb_tex_objectives
.BindRTtoTexSlot(2);
716 shader_comp_main
.setInt("tex_objectives", 2);
718 tar_cfg_gradientMap
->bindOnSlot(4);
719 shader_comp_main
.setInt("tex_gradient", 4);
721 mesh_screen_quad
->Draw();
723 std::cout
<< "done!\n";
729 #pragma region auto_export_game
731 if (!m_onlyOutputMasks
) save_to_dds(m_renderWidth
, m_renderHeight
, filesys
->create_output_filepath("resource/overviews/" + m_mapfile_name
+ "_radar.dds", true).c_str(), IMG::MODE_DXT1
);
732 if (m_outputMasks
) render_to_png(m_renderWidth
, m_renderHeight
, filesys
->create_output_filepath("resource/overviews/" + m_mapfile_name
+ ".resources/raw.png", true).c_str());
734 #pragma region generate_radar_txt
736 std::cout
<< "Generating radar .TXT... ";
738 kv::DataBlock node_radar
= kv::DataBlock();
739 node_radar
.name
= m_mapfile_name
;
740 node_radar
.Values
.insert({ "material", "overviews/" + m_mapfile_name
});
742 node_radar
.Values
.insert({ "pos_x", std::to_string(view_origin
.x
) });
743 node_radar
.Values
.insert({ "pos_y", std::to_string(view_origin
.y
) });
744 node_radar
.Values
.insert({ "scale", std::to_string(render_ortho_scale
/ 1024.0f
) });
746 // Try resolve spawn positions
747 glm::vec3
* loc_spawnCT
= vmf_main
.calculateSpawnLocation(vmf::team::counter_terrorist
);
748 glm::vec3
* loc_spawnT
= vmf_main
.calculateSpawnLocation(vmf::team::terrorist
);
750 if (loc_spawnCT
!= NULL
) {
751 node_radar
.Values
.insert({ "CTSpawn_x", std::to_string(util::roundf(remap(loc_spawnCT
->x
, view_origin
.x
, view_origin
.x
+ render_ortho_scale
, 0.0f
, 1.0f
), 0.01f
)) });
752 node_radar
.Values
.insert({ "CTSpawn_y", std::to_string(util::roundf(remap(loc_spawnCT
->y
, view_origin
.y
, view_origin
.y
- render_ortho_scale
, 0.0f
, 1.0f
), 0.01f
)) });
754 if (loc_spawnT
!= NULL
) {
755 node_radar
.Values
.insert({ "TSpawn_x", std::to_string(util::roundf(remap(loc_spawnT
->x
, view_origin
.x
, view_origin
.x
+ render_ortho_scale
, 0.0f
, 1.0f
), 0.01f
)) });
756 node_radar
.Values
.insert({ "TSpawn_y", std::to_string(util::roundf(remap(loc_spawnT
->y
, view_origin
.y
, view_origin
.y
- render_ortho_scale
, 0.0f
, 1.0f
), 0.01f
)) });
759 std::ofstream
out(filesys
->create_output_filepath("resource/overviews/" + m_mapfile_name
+ ".txt", true).c_str());
760 out
<< "// TAVR - AUTO RADAR. v 2.0.0\n";
761 node_radar
.Serialize(out
);
764 std::cout
<< "done!";
769 std::cout
<< "\n- Radar generation successful... cleaning up. -\n";
781 int main(int argc
, const char** argv
) {
783 return app(argc
, argv
);
785 catch (cxxopts::OptionException
& e
) {
786 std::cerr
<< "Parse error: " << e
.what() << "\n";
795 NVIDIA optimus systems will default to intel integrated graphics chips.
796 These chips cause fatal memory issues when using opengl3.3 (even though they claim to generate correct contexts)
798 This export gets picked up by NVIDIA drivers (v 302+).
799 It will force usage of the dedicated video device in the machine, which likely has full coverage of 3.3
803 _declspec(dllexport
) DWORD NvOptimusEnablement
= 0x00000001;