8 #include <GLFW\glfw3.h>
10 #include "GLFWUtil.hpp"
12 // Engine header files
14 #include "Texture.hpp"
15 #include "FrameBuffer.hpp"
21 #include "cxxopts.hpp"
22 #include "interpolation.h"
23 #include "vfilesys.hpp"
26 #define STBI_MSC_SECURE_CRT
27 #define STB_IMAGE_WRITE_IMPLEMENTATION
28 #include "stb_image_write.h"
30 #include "GradientMap.hpp"
33 //#define TAR_EXPERIMENTAL
35 /* Grabs the currently bound framebuffer and saves it to a .png */
36 void render_to_png(int x
, int y
, const char* filepath
){
37 void* data
= malloc(4 * x
* y
);
39 glReadPixels(0, 0, x
, y
, GL_RGBA
, GL_UNSIGNED_BYTE
, data
);
41 stbi_flip_vertically_on_write(true);
42 stbi_write_png(filepath
, x
, y
, 4, data
, x
* 4);
47 /* Grabs the currently bound framebuffer and saves it to a .dds */
48 void save_to_dds(int x
, int y
, const char* filepath
, IMG imgmode
= IMG::MODE_DXT1
) {
49 void* data
= malloc(4 * x
* y
);
51 glReadPixels(0, 0, x
, y
, GL_RGB
, GL_UNSIGNED_BYTE
, data
);
53 dds_write((uint8_t*)data
, filepath
, x
, y
, imgmode
);
58 /* Renders opengl in opaque mode (normal) */
59 void opengl_render_opaque() {
61 glEnable(GL_DEPTH_TEST
);
65 /* Renders opengl in addative mode */
66 void opengl_render_additive() {
70 // I still do not fully understand OPENGL blend modes. However these equations looks nice for the grid floor.
71 glBlendEquationSeparate(GL_FUNC_ADD
, GL_FUNC_ADD
);
72 glBlendFuncSeparate(GL_ONE
, GL_ONE
, GL_ZERO
, GL_ONE
);
75 /* Command line variables */
77 std::string m_mapfile_path
;
78 std::string m_game_path
;
81 std::string m_mapfile_path
= "sample_stuff/de_tavr_test";
82 std::string m_game_path
= "D:/SteamLibrary/steamapps/common/Counter-Strike Global Offensive/csgo_dev";
86 std::string m_mapfile_name
;
87 std::string m_overviews_folder
;
88 std::string m_resources_folder
;
90 vfilesys
* filesys
= NULL
;
93 bool m_outputMasks
= true;
94 bool m_onlyOutputMasks
;
96 bool m_comp_shadows_enable
= true;
97 bool m_comp_ao_enable
= true;
102 bool m_onlyOutputMasks
;
104 bool m_comp_shadows_enable
;
105 bool m_comp_ao_enable
;
108 //tar_config overrides
109 uint32_t m_renderWidth
= 1024;
110 uint32_t m_renderHeight
= 1024;
111 bool m_enable_maskgen_supersample
= true;
113 bool tar_cfg_enableAO
= true;
114 int tar_cfg_aoSzie
= 16;
116 bool tar_cfg_enableShadows
= false;
118 bool tar_cfg_enableOutline
= false;
119 int tar_cfg_outlineSize
= 2;
121 Texture
* tar_cfg_gradientMap
;
124 int app(int argc
, const char** argv
) {
126 cxxopts::Options
options("AutoRadar", "Auto radar");
127 options
.add_options()
128 ("v,version", "Shows the software version")
129 ("g,game", "(REQUIRED) Specify game path", cxxopts::value
<std::string
>()->default_value(""))
130 ("m,mapfile", "(REQUIRED) Specify the map file (vmf)", cxxopts::value
<std::string
>()->default_value(""))
132 ("d,dumpMasks", "Toggles whether auto radar should output mask images (resources/map_file.resources/)")
133 ("o,onlyMasks", "Specift whether auto radar should only output mask images and do nothing else (resources/map_file.resources)")
135 ("ao", "[OBSOLETE] Turn on AO in the compisotor")
136 ("shadows", "[OBSOLETE] Turn on Shadows in the compositor")
138 ("w,width", "[OBSOLETE] Render width in pixels (experimental)", cxxopts::value
<uint32_t>()->default_value("1024"))
139 ("h,height", "[OBSOLETE] Render height in pixels (experimental)", cxxopts::value
<uint32_t>()->default_value("1024"))
142 ("autoModulate", "Enables automatic height modulation between two levels")
143 ("minHeightDiff", "Minumum height difference(units) to modulate between two levels", cxxopts::value
<int>()->default_value("128"))
146 ("useVBSP", "Use VBSP.exe to pre-process brush unions automatically")
147 ("useLightmaps", "Use lightmaps generated by vvis in the VBSP. (If this flag is set, Auto Radar must be ran after vvis.exe)")
149 ("positional", "Positional parameters", cxxopts::value
<std::vector
<std::string
>>());
151 options
.parse_positional("positional");
152 auto result
= options
.parse(argc
, argv
);
154 /* Check required parameters */
155 if (result
.count("game")) m_game_path
= sutil::ReplaceAll(result
["game"].as
<std::string
>(), "\n", "");
156 else throw cxxopts::option_required_exception("game");
158 if(result
.count("mapfile")) m_mapfile_path
= result
["mapfile"].as
<std::string
>();
159 else if (result
.count("positional")) {
160 auto& positional
= result
["positional"].as
<std::vector
<std::string
>>();
162 m_mapfile_path
= sutil::ReplaceAll(positional
[0], "\n", "");
164 else throw cxxopts::option_required_exception("mapfile"); // We need a map file
166 //Clean paths to what we can deal with
167 m_mapfile_path
= sutil::ReplaceAll(m_mapfile_path
, "\\", "/");
168 m_game_path
= sutil::ReplaceAll(m_game_path
, "\\", "/");
170 /* Check the rest of the flags */
171 m_onlyOutputMasks
= result
["onlyMasks"].as
<bool>();
172 m_outputMasks
= result
["dumpMasks"].as
<bool>() || m_onlyOutputMasks
;
175 m_renderWidth
= result
["width"].as
<uint32_t>();
176 m_renderHeight
= result
["height"].as
<uint32_t>();
178 m_comp_ao_enable
= result
["ao"].as
<bool>();
179 m_comp_shadows_enable
= result
["shadows"].as
<bool>();
184 m_mapfile_name
= split(m_mapfile_path
, '/').back();
185 m_overviews_folder
= m_game_path
+ "/resource/overviews/";
186 m_resources_folder
= m_overviews_folder
+ m_mapfile_name
+ ".resources/";
189 std::cout << "Launching with options:\n";
190 std::cout << " Render width: " << m_renderWidth << "\n";
191 std::cout << " Render height: " << m_renderHeight << "\n";
192 std::cout << " Save masks? " << (m_outputMasks ? "YES" : "NO") << "\n";
193 std::cout << " Output to game? " << (!m_onlyOutputMasks ? "YES" : "NO") << "\n\n";
194 std::cout << " Game path: " << m_game_path << "\n";
195 std::cout << " Map path: " << m_mapfile_path << "\n";
196 std::cout << "\n -------- RENDER SETTINGS -------\n";
197 std::cout << " AO: " << (m_comp_ao_enable ? "YES" : "NO") << "\n";
198 std::cout << " Shadows: " << (m_comp_shadows_enable ? "YES" : "NO") << "\n";
202 filesys
= new vfilesys(m_game_path
+ "/gameinfo.txt");
204 catch (std::exception e
) {
205 std::cout
<< "Error creating vfilesys:\n";
206 std::cout
<< e
.what() << "\n";
211 filesys
->debug_info();
213 std::cout
<< "Initializing OpenGL\n";
215 #pragma region init_opengl
218 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR
, 3); //We are using version 3.3 of openGL
219 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR
, 3);
220 glfwWindowHint(GLFW_OPENGL_PROFILE
, GLFW_OPENGL_CORE_PROFILE
);
221 glfwWindowHint(GLFW_RESIZABLE
, GL_FALSE
);
222 glfwWindowHint(GLFW_VISIBLE
, GL_FALSE
); // Window le nope
225 GLFWwindow
* window
= glfwCreateWindow(1, 1, "If you are seeing this window, something is broken", NULL
, NULL
);
227 //Check if window open
229 std::cout
<< "Failed to create GLFW window" << std::endl
;
230 glfwTerminate(); return -1;
232 glfwMakeContextCurrent(window
);
235 if (!gladLoadGLLoader((GLADloadproc
)glfwGetProcAddress
)){
236 std::cout
<< "Failed to initialize GLAD" << std::endl
; return -1;
239 const unsigned char* glver
= glGetString(GL_VERSION
);
240 std::cout
<< "(required: min core 3.3.0) opengl version: " << glver
<< "\n";
242 glEnable(GL_DEPTH_TEST
);
244 glViewport(0, 0, m_renderWidth
, m_renderHeight
);
246 glClearColor(0.00f
, 0.00f
, 0.00f
, 0.00f
);
248 std::cout
<< "Creating render buffers\n";
250 FrameBuffer fb_tex_playspace
= FrameBuffer(m_renderWidth
, m_renderHeight
);
251 FrameBuffer fb_tex_objectives
= FrameBuffer(m_renderWidth
, m_renderHeight
);
252 FrameBuffer fb_comp
= FrameBuffer(m_renderWidth
* 2, m_renderHeight
* 2);
253 FrameBuffer fb_comp_1
= FrameBuffer(m_renderWidth
* 2, m_renderHeight
* 2); //Reverse ordered frame buffer
254 FrameBuffer fb_final
= FrameBuffer(m_renderWidth
, m_renderHeight
);
257 std::cout
<< "Creating screenspace mesh\n";
259 std::vector
<float> __meshData
= {
268 Mesh
* mesh_screen_quad
= new Mesh(__meshData
, MeshMode::SCREEN_SPACE_UV
);
272 #pragma region shader_compilation
274 std::cout
<< "Compiling Shaders\n";
275 std::cout
<< "______________________________________________________________\n\n";
277 // Internal engine shaders
278 Shader
shader_depth("shaders/depth.vs", "shaders/depth.fs");
279 Shader
shader_unlit("shaders/unlit.vs", "shaders/unlit.fs");
281 // Compositing shaders
282 Shader
shader_comp_main("shaders/fullscreenbase.vs", "shaders/ss_comp_main.fs"); // le big one
283 Shader
shader_precomp_playspace("shaders/fullscreenbase.vs", "shaders/ss_precomp_playspace.fs"); // computes distance map
284 Shader
shader_precomp_objectives("shaders/fullscreenbase.vs", "shaders/ss_precomp_objectives.fs"); // computes distance map
286 if (shader_depth
.compileUnsuccessful
||
287 shader_unlit
.compileUnsuccessful
||
288 shader_comp_main
.compileUnsuccessful
||
289 shader_precomp_playspace
.compileUnsuccessful
||
290 shader_precomp_objectives
.compileUnsuccessful
) {
292 std::cout
<< "______________________________________________________________\n";
293 std::cout
<< "Shader compilation step failed.\n";
301 std::cout
<< "______________________________________________________________\n";
302 std::cout
<< "Shader compilation successful\n\n";
304 std::cout
<< "Loading textures... ";
306 Texture tex_background
= Texture("textures/grid.png");
307 //Texture tex_gradient = Texture("textures/gradients/gradientmap_6.png", true);
308 Texture tex_height_modulate
= Texture("textures/modulate.png");
310 //GradientTexture gtex_gradient = GradientTexture(std::string("32 68 136 255"), std::string("149 0 0 255"), std::string("178 113 65"));
312 std::cout
<< "done!\n\n";
316 #pragma region map_load
318 std::cout
<< "Loading map file...\n";
320 vmf::vmf
vmf_main(m_mapfile_path
+ ".vmf");
321 //vmf_main.setup_main();
322 //vmf_main.genVMFReferences(); // Load all our func_instances
324 //std::cout << "Generating Meshes...\n";
326 vmf_main
.ComputeGLMeshes();
327 vmf_main
.ComputeDisplacements();
330 std::vector
<vmf::Entity
*> tavr_ent_tar_config
= vmf_main
.findEntitiesByClassName("tar_config");
332 if (tavr_ent_tar_config
.size() > 1) {
333 std::cout
<< "More than 1 tar config found! Currently unsupported... Using last.\n";
336 vmf::Entity
* tar_config
= NULL
;
337 if (tavr_ent_tar_config
.size() > 0) {
338 tar_config
= tavr_ent_tar_config
.back();
341 std::string schemeNum
= kv::tryGetStringValue(tar_config
->keyValues
, "colorScheme", "0");
342 if (schemeNum
== "-1") { // Custom color scheme
343 tar_cfg_gradientMap
= new GradientTexture(
344 kv::tryGetStringValue(tar_config
->keyValues
, "customCol0", "0 0 0 255"),
345 kv::tryGetStringValue(tar_config
->keyValues
, "customCol1", "128 128 128 255"),
346 kv::tryGetStringValue(tar_config
->keyValues
, "customCol2", "255 255 255 255"));
348 tar_cfg_gradientMap
= new Texture("textures/gradients/gradientmap_" + schemeNum
+ ".png", true);
352 tar_cfg_enableAO
= (kv::tryGetStringValue(tar_config
->keyValues
, "enableAO", "1") == "1");
353 tar_cfg_aoSzie
= kv::tryGetValue(tar_config
->keyValues
, "aoSize", 16);
356 tar_cfg_enableOutline
= (kv::tryGetStringValue(tar_config
->keyValues
, "enableOutline", "0") == "1");
357 tar_cfg_outlineSize
= kv::tryGetValue(tar_config
->keyValues
, "outlineWidth", 2);
360 tar_cfg_enableShadows
= (kv::tryGetStringValue(tar_config
->keyValues
, "enableShadows", "0") == "1");
363 tar_cfg_gradientMap
= new Texture("textures/gradients/gradientmap_6.png", true);
366 std::cout
<< "Collecting Objects... \n";
367 std::vector
<vmf::Solid
*> tavr_solids
= vmf_main
.getAllBrushesInVisGroup(tar_config
== NULL
? "tar_layout" : kv::tryGetStringValue(tar_config
->keyValues
, "vgroup_layout", "tar_layout"));
368 std::vector
<vmf::Solid
*> tavr_solids_negative
= vmf_main
.getAllBrushesInVisGroup(tar_config
== NULL
? "tar_mask" : kv::tryGetStringValue(tar_config
->keyValues
, "vgroup_negative", "tar_mask"));
369 std::vector
<vmf::Solid
*> tavr_entire_brushlist
= vmf_main
.getAllRenderBrushes();
370 std::vector
<vmf::Solid
*> tavr_cover
= vmf_main
.getAllBrushesInVisGroup(tar_config
== NULL
? "tar_cover" : kv::tryGetStringValue(tar_config
->keyValues
, "vgroup_cover", "tar_cover"));
371 for (auto && v
: tavr_cover
) { v
->temp_mark
= true; tavr_solids
.push_back(v
); }
373 //std::vector<vmf::Solid*> tavr_solids_funcbrush = vmf_main.getAllBrushesByClassName("func_brush");
374 std::vector
<vmf::Solid
*> tavr_buyzones
= vmf_main
.getAllBrushesByClassName("func_buyzone");
375 std::vector
<vmf::Solid
*> tavr_bombtargets
= vmf_main
.getAllBrushesByClassName("func_bomb_target");
377 std::vector
<vmf::Entity
*> tavr_ent_tavr_height_min
= vmf_main
.findEntitiesByClassName("tar_min");
378 std::vector
<vmf::Entity
*> tavr_ent_tavr_height_max
= vmf_main
.findEntitiesByClassName("tar_max");
381 std::cout
<< "Collecting models... \n";
382 vmf_main
.populateModelDict(filesys
);
383 vmf_main
.populatePropList(tar_config
== NULL
? "tar_cover" : kv::tryGetStringValue(tar_config
->keyValues
, "vgroup_cover", "tar_cover"));
385 std::cout
<< "done!\n";
387 #pragma region bounds
388 std::cout
<< "Calculating bounds... ";
390 vmf::BoundingBox limits
= vmf::getSolidListBounds(tavr_solids
);
391 float z_render_min
= limits
.SEL
.y
;
392 float z_render_max
= limits
.NWU
.y
;
394 // Overide entity heights
395 if (tavr_ent_tavr_height_min
.size()) z_render_min
= tavr_ent_tavr_height_min
[0]->origin
.z
;
396 if (tavr_ent_tavr_height_max
.size()) z_render_max
= tavr_ent_tavr_height_max
[0]->origin
.z
;
398 float padding
= 128.0f
;
400 float x_bounds_min
= -limits
.NWU
.x
- padding
; //inflate distances slightly
401 float x_bounds_max
= -limits
.SEL
.x
+ padding
;
403 float y_bounds_min
= limits
.SEL
.z
- padding
;
404 float y_bounds_max
= limits
.NWU
.z
+ padding
;
406 float dist_x
= x_bounds_max
- x_bounds_min
;
407 float dist_y
= y_bounds_max
- y_bounds_min
;
409 float mx_dist
= glm::max(dist_x
, dist_y
);
411 float justify_x
= (mx_dist
- dist_x
) * 0.5f
;
412 float justify_y
= (mx_dist
- dist_y
) * 0.5f
;
414 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.
415 glm::vec2 view_origin
= glm::vec2(x_bounds_min
- justify_x
, y_bounds_max
+ justify_y
);
417 std::cout
<< "done\n\n";
422 #pragma region OpenGLRender
424 std::cout
<< "Starting OpenGL Render\n";
426 #pragma region render_playable_space
427 std::cout
<< "Rendering playable space... ";
429 // ======================================================== REGULAR ORDER ========================================================
431 glViewport(0, 0, m_renderWidth
* 2, m_renderHeight
* 2);
433 fb_comp
.Bind(); //Bind framebuffer
435 glClearColor(0.00f
, 0.00f
, 0.00f
, 1.00f
);
436 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
437 glPolygonMode(GL_FRONT
, GL_FILL
);
440 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
));
441 shader_depth
.setMatrix("view", glm::lookAt(glm::vec3(0, 0, 0), glm::vec3(0, -1.0f
, 0), glm::vec3(0, 0, 1)));
443 glm::mat4 model
= glm::mat4();
444 shader_depth
.setMatrix("model", model
);
446 shader_depth
.setFloat("HEIGHT_MIN", z_render_min
);
447 shader_depth
.setFloat("HEIGHT_MAX", z_render_max
);
448 shader_depth
.setFloat("write_playable", 0.0f
);
450 // Render entire map first
451 for (auto && brush
: tavr_entire_brushlist
) {
452 shader_depth
.setFloat("write_cover", brush
->temp_mark
? 1.0f
: 0.0f
);
455 glClear(GL_DEPTH_BUFFER_BIT
);
457 // Render playable area over it
458 shader_depth
.setFloat("write_playable", 1.0f
);
459 for (auto && s_solid
: tavr_solids
) {
460 shader_depth
.setFloat("write_cover", s_solid
->temp_mark
? 1.0f
: 0.0f
);
461 if (!s_solid
->containsDisplacements
)
462 s_solid
->mesh
->Draw();
464 for (auto && f
: s_solid
->faces
) {
465 if (f
.displacement
!= NULL
) {
466 f
.displacement
->glMesh
->Draw();
472 #ifdef TAR_EXPERIMENTAL
473 // Render instances (experimental)
474 for (auto && sub_vmf
: vmf_main
.findEntitiesByClassName("func_instance")) {
475 std::string mapname
= kv::tryGetStringValue(sub_vmf
->keyValues
, "file", "");
477 if (mapname
== "") continue; //Something went wrong...
482 model
= glm::translate(model
, glm::vec3(-sub_vmf
->origin
.x
, sub_vmf
->origin
.z
, sub_vmf
->origin
.y
));
485 shader_depth
.setMatrix("model", model
);
487 for (auto && solid
: vmf_main
.subvmf_references
[mapname
]->getAllBrushesInVisGroup("tar_cover")) {
488 shader_depth
.setFloat("write_cover", solid
->temp_mark
? 1.0f
: 1.0f
);
489 if (!solid
->containsDisplacements
)
492 for (auto && f
: solid
->faces
) {
493 if (f
.displacement
!= NULL
) {
494 f
.displacement
->glMesh
->Draw();
500 #endif // TAR_EXPERIMENTAL
503 std::cout
<< "Rendering props\n";
504 shader_depth
.setFloat("write_cover", 1.0f
);
505 for (auto && s_prop
: vmf_main
.props
) {
506 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.
509 model
= glm::translate(model
, s_prop
.origin
); // Position
510 model
= glm::rotate(model
, glm::radians(s_prop
.rotation
.y
), glm::vec3(0, 1, 0)); // Yaw
511 model
= glm::rotate(model
, glm::radians(s_prop
.rotation
.x
), glm::vec3(0, 0, 1)); // ROOOOOLLLLL
512 model
= glm::rotate(model
, -glm::radians(s_prop
.rotation
.z
), glm::vec3(1, 0, 0)); // Pitch
513 model
= glm::scale(model
, glm::vec3(s_prop
.unifromScale
)); // Scale
515 shader_depth
.setMatrix("model", model
);
516 vmf_main
.modelCache
[s_prop
.modelID
]->Draw();
520 shader_depth
.setMatrix("model", model
);
522 // Re render subtractive brushes
523 shader_depth
.setFloat("write_playable", 0.0f
);
524 for (auto && s_solid
: tavr_solids_negative
) {
525 shader_depth
.setFloat("write_cover", s_solid
->temp_mark
? 1.0f
: 0.0f
);
526 if (!s_solid
->containsDisplacements
)
527 s_solid
->mesh
->Draw();
529 for (auto && f
: s_solid
->faces
) {
530 if (f
.displacement
!= NULL
) {
531 f
.displacement
->glMesh
->Draw();
537 // ======================================================== REVERSE ORDER ========================================================
543 glEnable(GL_CULL_FACE
);
544 glDepthFunc(GL_GREATER
);
546 glClearColor(0.00f
, 0.00f
, 0.00f
, 1.00f
);
547 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
548 glPolygonMode(GL_FRONT
, GL_FILL
);
550 shader_depth
.setFloat("HEIGHT_MIN", z_render_min
);
551 shader_depth
.setFloat("HEIGHT_MAX", z_render_max
);
552 shader_depth
.setFloat("write_playable", 0.0f
);
554 for (auto && s_solid
: tavr_solids
) {
555 if (!s_solid
->containsDisplacements
)
556 s_solid
->mesh
->Draw();
558 for (auto && f
: s_solid
->faces
) {
559 if (f
.displacement
!= NULL
) {
560 f
.displacement
->glMesh
->Draw();
566 // regular depth testing
568 glDepthFunc(GL_LESS
);
569 glDisable(GL_CULL_FACE
);
571 // ========================================================== PRE-COMP ===========================================================
573 glViewport(0, 0, m_renderWidth
, m_renderHeight
);
576 fb_tex_playspace
.Bind();
578 glClearColor(0.00f
, 0.00f
, 0.00f
, 0.00f
);
579 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
580 glDisable(GL_DEPTH_TEST
);
581 glPolygonMode(GL_FRONT
, GL_FILL
);
583 shader_precomp_playspace
.use();
585 //shader_precomp_playspace.setFloat("HEIGHT_MIN", z_render_min);
586 //shader_precomp_playspace.setFloat("HEIGHT_MAX", z_render_max);
588 fb_comp
.BindRTtoTexSlot(0);
589 shader_precomp_playspace
.setInt("tex_in", 0);
591 fb_comp_1
.BindRTtoTexSlot(1);
592 shader_precomp_playspace
.setInt("tex_in_1", 1);
594 //tex_height_modulate.bindOnSlot(2);
595 //shader_precomp_playspace.setInt("tex_modulate", 2);
597 mesh_screen_quad
->Draw();
599 glEnable(GL_DEPTH_TEST
);
601 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());
603 std::cout
<< "done!\n";
606 #pragma region render_objectives
607 std::cout
<< "Rendering bombsites & buyzones space... ";
609 glViewport(0, 0, m_renderWidth
* 2, m_renderHeight
* 2);
613 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
614 glPolygonMode(GL_FRONT
, GL_FILL
);
615 //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
618 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
));
619 shader_unlit
.setMatrix("view", glm::lookAt(glm::vec3(0, 0, 0), glm::vec3(0, -1.0f
, 0), glm::vec3(0, 0, 1)));
620 shader_unlit
.setMatrix("model", model
);
622 shader_unlit
.setVec3("color", 0.0f
, 1.0f
, 0.0f
);
624 for (auto && s_solid
: tavr_buyzones
) {
625 s_solid
->mesh
->Draw();
629 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
631 shader_unlit
.setVec3("color", 1.0f
, 0.0f
, 0.0f
);
633 for (auto && s_solid
: tavr_bombtargets
) {
634 s_solid
->mesh
->Draw();
638 glViewport(0, 0, m_renderWidth
, m_renderHeight
);
640 fb_tex_objectives
.Bind();
642 glClearColor(0.00f
, 0.00f
, 0.00f
, 0.00f
);
643 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
644 glDisable(GL_DEPTH_TEST
);
645 glPolygonMode(GL_FRONT
, GL_FILL
);
647 shader_precomp_objectives
.use();
649 fb_comp
.BindRTtoTexSlot(0);
650 shader_precomp_objectives
.setInt("tex_in", 0);
652 fb_comp_1
.BindRTtoTexSlot(1);
653 shader_precomp_objectives
.setInt("tex_in_1", 1);
655 fb_tex_playspace
.BindRTtoTexSlot(2);
656 shader_precomp_objectives
.setInt("tex_in_2", 2);
658 mesh_screen_quad
->Draw();
660 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());
662 glEnable(GL_DEPTH_TEST
);
663 std::cout
<< "done!\n";
666 #pragma region compositing
667 std::cout
<< "Compositing... \n";
671 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
672 glPolygonMode(GL_FRONT
, GL_FILL
);
674 shader_comp_main
.use();
676 /* Fill out shader uniforms */
678 vec3 bounds_NWU North-West-Upper coordinate of the playspace (worldspace)
679 vec3 bounds_SEL South-East-Lower coordinate of the playspace (worldspace)
680 **vec2 bounds_NWU_SS North-West coordinate of the playspace (screen space)
681 **vec2 bounds_SEL_SS South-East coordinate of the playspace (screen space)
683 **vec2 pos_spawn_ct Location of the CT Spawn (0-1)
684 **vec2 pos_spawn_t Location of the T Spawn (0-1)
685 **vec2 bombsite_a Location of bomsite A (0-1)
686 **vec2 bombsite_b Location of bombsite B (0-1)
688 shader_comp_main
.setVec3("bounds_NWU", glm::vec3(x_bounds_min
, y_bounds_max
, z_render_max
));
689 shader_comp_main
.setVec3("bounds_SEL", glm::vec3(x_bounds_max
, y_bounds_min
, z_render_min
));
692 shader_comp_main
.setInt("cmdl_shadows_enable", tar_cfg_enableShadows
? 1 : 0);
693 shader_comp_main
.setInt("cmdl_ao_enable", tar_cfg_enableAO
? 1 : 0);
694 shader_comp_main
.setInt("cmdl_ao_size", tar_cfg_aoSzie
);
695 shader_comp_main
.setInt("cmdl_outline_enable", tar_cfg_enableOutline
);
696 shader_comp_main
.setInt("cmdl_outline_size", tar_cfg_outlineSize
);
698 shader_comp_main
.setVec4("outline_color", parseVec4(kv::tryGetStringValue(tar_config
->keyValues
, "zColOutline", "255 255 255 255")));
699 shader_comp_main
.setVec4("ao_color", parseVec4(kv::tryGetStringValue(tar_config
->keyValues
, "zColAO", "255 255 255 255")));
701 shader_comp_main
.setVec4("buyzone_color", parseVec4(kv::tryGetStringValue(tar_config
->keyValues
, "zColBuyzone", "255 255 255 255")));
702 shader_comp_main
.setVec4("objective_color", parseVec4(kv::tryGetStringValue(tar_config
->keyValues
, "zColObjective", "255 255 255 255")));
703 shader_comp_main
.setVec4("cover_color", parseVec4(kv::tryGetStringValue(tar_config
->keyValues
, "zColCover", "255 255 255 255")));
705 /* Bind texture samplers */
706 tex_background
.bindOnSlot(0);
707 shader_comp_main
.setInt("tex_background", 0);
709 fb_tex_playspace
.BindRTtoTexSlot(1);
710 shader_comp_main
.setInt("tex_playspace", 1);
712 fb_tex_objectives
.BindRTtoTexSlot(2);
713 shader_comp_main
.setInt("tex_objectives", 2);
715 tar_cfg_gradientMap
->bindOnSlot(4);
716 shader_comp_main
.setInt("tex_gradient", 4);
718 mesh_screen_quad
->Draw();
720 std::cout
<< "done!\n";
726 #pragma region auto_export_game
728 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
);
729 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());
731 #pragma region generate_radar_txt
733 std::cout
<< "Generating radar .TXT... ";
735 kv::DataBlock node_radar
= kv::DataBlock();
736 node_radar
.name
= m_mapfile_name
;
737 node_radar
.Values
.insert({ "material", "overviews/" + m_mapfile_name
});
739 node_radar
.Values
.insert({ "pos_x", std::to_string(view_origin
.x
) });
740 node_radar
.Values
.insert({ "pos_y", std::to_string(view_origin
.y
) });
741 node_radar
.Values
.insert({ "scale", std::to_string(render_ortho_scale
/ 1024.0f
) });
743 // Try resolve spawn positions
744 glm::vec3
* loc_spawnCT
= vmf_main
.calculateSpawnLocation(vmf::team::counter_terrorist
);
745 glm::vec3
* loc_spawnT
= vmf_main
.calculateSpawnLocation(vmf::team::terrorist
);
747 if (loc_spawnCT
!= NULL
) {
748 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
)) });
749 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
)) });
751 if (loc_spawnT
!= NULL
) {
752 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
)) });
753 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
)) });
756 std::ofstream
out(filesys
->create_output_filepath("resource/overviews/" + m_mapfile_name
+ ".txt", true).c_str());
757 out
<< "// TAVR - AUTO RADAR. v 2.0.0\n";
758 node_radar
.Serialize(out
);
761 std::cout
<< "done!";
766 std::cout
<< "\n- Radar generation successful... cleaning up. -\n";
778 #ifndef entry_point_testing
779 int main(int argc
, const char** argv
) {
781 return app(argc
, argv
);
783 catch (cxxopts::OptionException
& e
) {
784 std::cerr
<< "Parse error: " << e
.what() << "\n";