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"
25 #define STBI_MSC_SECURE_CRT
26 #define STB_IMAGE_WRITE_IMPLEMENTATION
27 #include "stb_image_write.h"
29 #include "GradientMap.hpp"
31 /* Grabs the currently bound framebuffer and saves it to a .png */
32 void render_to_png(int x
, int y
, const char* filepath
){
33 void* data
= malloc(4 * x
* y
);
35 glReadPixels(0, 0, x
, y
, GL_RGBA
, GL_UNSIGNED_BYTE
, data
);
37 stbi_flip_vertically_on_write(true);
38 stbi_write_png(filepath
, x
, y
, 4, data
, x
* 4);
43 /* Grabs the currently bound framebuffer and saves it to a .dds */
44 void save_to_dds(int x
, int y
, const char* filepath
) {
45 void* data
= malloc(4 * x
* y
);
47 glReadPixels(0, 0, x
, y
, GL_RGB
, GL_UNSIGNED_BYTE
, data
);
49 dds_write((uint8_t*)data
, filepath
, x
, y
, IMG::MODE_DXT1
);
54 /* Renders opengl in opaque mode (normal) */
55 void opengl_render_opaque() {
57 glEnable(GL_DEPTH_TEST
);
61 /* Renders opengl in addative mode */
62 void opengl_render_additive() {
66 // I still do not fully understand OPENGL blend modes. However these equations looks nice for the grid floor.
67 glBlendEquationSeparate(GL_FUNC_ADD
, GL_FUNC_ADD
);
68 glBlendFuncSeparate(GL_ONE
, GL_ONE
, GL_ZERO
, GL_ONE
);
71 /* Command line variables */
73 std::string m_mapfile_path
;
74 std::string m_game_path
;
77 std::string m_mapfile_path
= "sample_stuff/de_crimson_v16";
78 std::string m_game_path
= "D:/SteamLibrary/steamapps/common/Counter-Strike Global Offensive/csgo";
82 std::string m_mapfile_name
;
83 std::string m_overviews_folder
;
84 std::string m_resources_folder
;
87 bool m_outputMasks
= true;
88 bool m_onlyOutputMasks
;
90 bool m_comp_shadows_enable
= true;
91 bool m_comp_ao_enable
= true;
96 bool m_onlyOutputMasks
;
98 bool m_comp_shadows_enable
;
99 bool m_comp_ao_enable
;
102 //tar_config overrides
103 uint32_t m_renderWidth
= 1024;
104 uint32_t m_renderHeight
= 1024;
105 bool m_enable_maskgen_supersample
= true;
107 bool tar_cfg_enableAO
= true;
108 int tar_cfg_aoSzie
= 16;
110 bool tar_cfg_enableShadows
= false;
112 bool tar_cfg_enableOutline
= false;
113 int tar_cfg_outlineSize
= 2;
115 Texture
* tar_cfg_gradientMap
;
118 int app(int argc
, const char** argv
) {
120 cxxopts::Options
options("AutoRadar", "Auto radar");
121 options
.add_options()
122 ("v,version", "Shows the software version")
123 ("g,game", "(REQUIRED) Specify game path", cxxopts::value
<std::string
>()->default_value(""))
124 ("m,mapfile", "(REQUIRED) Specify the map file (vmf)", cxxopts::value
<std::string
>()->default_value(""))
126 ("d,dumpMasks", "Toggles whether auto radar should output mask images (resources/map_file.resources/)")
127 ("o,onlyMasks", "Specift whether auto radar should only output mask images and do nothing else (resources/map_file.resources)")
129 ("ao", "[OBSOLETE] Turn on AO in the compisotor")
130 ("shadows", "[OBSOLETE] Turn on Shadows in the compositor")
132 ("w,width", "[OBSOLETE] Render width in pixels (experimental)", cxxopts::value
<uint32_t>()->default_value("1024"))
133 ("h,height", "[OBSOLETE] Render height in pixels (experimental)", cxxopts::value
<uint32_t>()->default_value("1024"))
136 ("autoModulate", "Enables automatic height modulation between two levels")
137 ("minHeightDiff", "Minumum height difference(units) to modulate between two levels", cxxopts::value
<int>()->default_value("128"))
140 ("useVBSP", "Use VBSP.exe to pre-process brush unions automatically")
141 ("useLightmaps", "Use lightmaps generated by vvis in the VBSP. (If this flag is set, Auto Radar must be ran after vvis.exe)")
143 ("positional", "Positional parameters", cxxopts::value
<std::vector
<std::string
>>());
145 options
.parse_positional("positional");
146 auto result
= options
.parse(argc
, argv
);
148 /* Check required parameters */
149 if (result
.count("game")) m_game_path
= sutil::ReplaceAll(result
["game"].as
<std::string
>(), "\n", "");
150 else throw cxxopts::option_required_exception("game");
152 if(result
.count("mapfile")) m_mapfile_path
= result
["mapfile"].as
<std::string
>();
153 else if (result
.count("positional")) {
154 auto& positional
= result
["positional"].as
<std::vector
<std::string
>>();
156 m_mapfile_path
= sutil::ReplaceAll(positional
[0], "\n", "");
158 else throw cxxopts::option_required_exception("mapfile"); // We need a map file
160 //Clean paths to what we can deal with
161 m_mapfile_path
= sutil::ReplaceAll(m_mapfile_path
, "\\", "/");
162 m_game_path
= sutil::ReplaceAll(m_game_path
, "\\", "/");
164 /* Check the rest of the flags */
165 m_onlyOutputMasks
= result
["onlyMasks"].as
<bool>();
166 m_outputMasks
= result
["dumpMasks"].as
<bool>() || m_onlyOutputMasks
;
169 m_renderWidth
= result
["width"].as
<uint32_t>();
170 m_renderHeight
= result
["height"].as
<uint32_t>();
172 m_comp_ao_enable
= result
["ao"].as
<bool>();
173 m_comp_shadows_enable
= result
["shadows"].as
<bool>();
178 m_mapfile_name
= split(m_mapfile_path
, '/').back();
179 m_overviews_folder
= m_game_path
+ "/resource/overviews/";
180 m_resources_folder
= m_overviews_folder
+ m_mapfile_name
+ ".resources/";
182 std::cout
<< "Launching with options:\n";
183 std::cout
<< " Render width: " << m_renderWidth
<< "\n";
184 std::cout
<< " Render height: " << m_renderHeight
<< "\n";
185 std::cout
<< " Save masks? " << (m_outputMasks
? "YES" : "NO") << "\n";
186 std::cout
<< " Output to game? " << (!m_onlyOutputMasks
? "YES" : "NO") << "\n\n";
187 std::cout
<< " Game path: " << m_game_path
<< "\n";
188 std::cout
<< " Map path: " << m_mapfile_path
<< "\n";
189 std::cout
<< "\n -------- RENDER SETTINGS -------\n";
190 std::cout
<< " AO: " << (m_comp_ao_enable
? "YES" : "NO") << "\n";
191 std::cout
<< " Shadows: " << (m_comp_shadows_enable
? "YES" : "NO") << "\n";
193 std::cout
<< "Initializing OpenGL\n";
195 #pragma region init_opengl
198 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR
, 3); //We are using version 3.3 of openGL
199 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR
, 3);
200 glfwWindowHint(GLFW_OPENGL_PROFILE
, GLFW_OPENGL_CORE_PROFILE
);
201 glfwWindowHint(GLFW_RESIZABLE
, GL_FALSE
);
202 glfwWindowHint(GLFW_VISIBLE
, GL_FALSE
); // Window le nope
205 GLFWwindow
* window
= glfwCreateWindow(1, 1, "If you are seeing this window, something is broken", NULL
, NULL
);
207 //Check if window open
209 std::cout
<< "Failed to create GLFW window" << std::endl
;
210 glfwTerminate(); return -1;
212 glfwMakeContextCurrent(window
);
215 if (!gladLoadGLLoader((GLADloadproc
)glfwGetProcAddress
)){
216 std::cout
<< "Failed to initialize GLAD" << std::endl
; return -1;
219 const unsigned char* glver
= glGetString(GL_VERSION
);
220 std::cout
<< "(required: min core 3.3.0) opengl version: " << glver
<< "\n";
222 glEnable(GL_DEPTH_TEST
);
224 glViewport(0, 0, m_renderWidth
, m_renderHeight
);
226 glClearColor(0.00f
, 0.00f
, 0.00f
, 0.00f
);
228 std::cout
<< "Creating render buffers\n";
230 FrameBuffer fb_tex_playspace
= FrameBuffer(m_renderWidth
, m_renderHeight
);
231 FrameBuffer fb_tex_objectives
= FrameBuffer(m_renderWidth
, m_renderHeight
);
232 FrameBuffer fb_comp
= FrameBuffer(m_renderWidth
, m_renderHeight
);
233 FrameBuffer fb_comp_1
= FrameBuffer(m_renderWidth
, m_renderHeight
); //Reverse ordered frame buffer
236 std::cout
<< "Creating screenspace mesh\n";
238 std::vector
<float> __meshData
= {
247 Mesh
* mesh_screen_quad
= new Mesh(__meshData
, MeshMode::SCREEN_SPACE_UV
);
251 #pragma region shader_compilation
253 std::cout
<< "Compiling Shaders\n";
254 std::cout
<< "______________________________________________________________\n\n";
256 // Internal engine shaders
257 Shader
shader_depth("shaders/depth.vs", "shaders/depth.fs");
258 Shader
shader_unlit("shaders/unlit.vs", "shaders/unlit.fs");
260 // Compositing shaders
261 Shader
shader_comp_main("shaders/fullscreenbase.vs", "shaders/ss_comp_main.fs"); // le big one
262 Shader
shader_precomp_playspace("shaders/fullscreenbase.vs", "shaders/ss_precomp_playspace.fs"); // computes distance map
263 Shader
shader_precomp_objectives("shaders/fullscreenbase.vs", "shaders/ss_precomp_objectives.fs"); // computes distance map
265 if (shader_depth
.compileUnsuccessful
||
266 shader_unlit
.compileUnsuccessful
||
267 shader_comp_main
.compileUnsuccessful
||
268 shader_precomp_playspace
.compileUnsuccessful
||
269 shader_precomp_objectives
.compileUnsuccessful
) {
271 std::cout
<< "______________________________________________________________\n";
272 std::cout
<< "Shader compilation step failed.\n";
280 std::cout
<< "______________________________________________________________\n";
281 std::cout
<< "Shader compilation successful\n\n";
283 std::cout
<< "Loading textures... ";
285 Texture tex_background
= Texture("textures/grid.png");
286 //Texture tex_gradient = Texture("textures/gradients/gradientmap_6.png", true);
287 Texture tex_height_modulate
= Texture("textures/modulate.png");
289 //GradientTexture gtex_gradient = GradientTexture(std::string("32 68 136 255"), std::string("149 0 0 255"), std::string("178 113 65"));
291 std::cout
<< "done!\n\n";
295 #pragma region map_load
297 std::cout
<< "Loading map file...\n";
299 vmf::vmf
vmf_main(m_mapfile_path
+ ".vmf");
301 std::cout
<< "Generating Meshes...\n";
303 vmf_main
.ComputeGLMeshes();
304 vmf_main
.ComputeDisplacements();
307 std::vector
<vmf::Entity
*> tavr_ent_tar_config
= vmf_main
.findEntitiesByClassName("tar_config");
309 if (tavr_ent_tar_config
.size() > 1) {
310 std::cout
<< "More than 1 tar config found! Currently unsupported... Using last.\n";
313 vmf::Entity
* tar_config
= NULL
;
314 if (tavr_ent_tar_config
.size() > 0) {
315 tar_config
= tavr_ent_tar_config
.back();
318 std::string schemeNum
= kv::tryGetStringValue(tar_config
->keyValues
, "colorScheme", "0");
319 if (schemeNum
== "-1") { // Custom color scheme
320 tar_cfg_gradientMap
= new GradientTexture(
321 kv::tryGetStringValue(tar_config
->keyValues
, "customCol0", "0 0 0 255"),
322 kv::tryGetStringValue(tar_config
->keyValues
, "customCol1", "128 128 128 255"),
323 kv::tryGetStringValue(tar_config
->keyValues
, "customCol2", "255 255 255 255"));
325 tar_cfg_gradientMap
= new Texture("textures/gradients/gradientmap_" + schemeNum
+ ".png", true);
329 tar_cfg_enableAO
= (kv::tryGetStringValue(tar_config
->keyValues
, "enableAO", "1") == "1");
330 tar_cfg_aoSzie
= kv::tryGetValue(tar_config
->keyValues
, "aoSize", 16);
333 tar_cfg_enableOutline
= (kv::tryGetStringValue(tar_config
->keyValues
, "enableOutline", "0") == "1");
334 tar_cfg_outlineSize
= kv::tryGetValue(tar_config
->keyValues
, "outlineWidth", 2);
337 tar_cfg_enableShadows
= (kv::tryGetStringValue(tar_config
->keyValues
, "enableShadows", "0") == "1");
340 tar_cfg_gradientMap
= new Texture("textures/gradients/gradientmap_6.png", true);
343 std::cout
<< "Collecting Objects... \n";
344 std::vector
<vmf::Solid
*> tavr_solids
= vmf_main
.getAllBrushesInVisGroup(tar_config
== NULL
? "tar_layout" : kv::tryGetStringValue(tar_config
->keyValues
, "vgroup_layout", "tar_layout"));
345 std::vector
<vmf::Solid
*> tavr_solids_negative
= vmf_main
.getAllBrushesInVisGroup(tar_config
== NULL
? "tar_mask" : kv::tryGetStringValue(tar_config
->keyValues
, "vgroup_negative", "tar_mask"));
346 std::vector
<vmf::Solid
*> tavr_entire_brushlist
= vmf_main
.getAllRenderBrushes();
347 std::vector
<vmf::Solid
*> tavr_cover
= vmf_main
.getAllBrushesInVisGroup(tar_config
== NULL
? "tar_cover" : kv::tryGetStringValue(tar_config
->keyValues
, "vgroup_cover", "tar_cover"));
348 for (auto && v
: tavr_cover
) { v
->temp_mark
= true; tavr_solids
.push_back(v
); }
350 //std::vector<vmf::Solid*> tavr_solids_funcbrush = vmf_main.getAllBrushesByClassName("func_brush");
351 std::vector
<vmf::Solid
*> tavr_buyzones
= vmf_main
.getAllBrushesByClassName("func_buyzone");
352 std::vector
<vmf::Solid
*> tavr_bombtargets
= vmf_main
.getAllBrushesByClassName("func_bomb_target");
354 std::vector
<vmf::Entity
*> tavr_ent_tavr_height_min
= vmf_main
.findEntitiesByClassName("tar_min");
355 std::vector
<vmf::Entity
*> tavr_ent_tavr_height_max
= vmf_main
.findEntitiesByClassName("tar_max");
358 std::cout
<< "Collecting models... \n";
359 vmf_main
.populateModelDict(m_game_path
+ "/");
360 vmf_main
.populatePropList(tar_config
== NULL
? "tar_cover" : kv::tryGetStringValue(tar_config
->keyValues
, "vgroup_cover", "tar_cover"));
362 std::cout
<< "done!\n";
364 #pragma region bounds
365 std::cout
<< "Calculating bounds... ";
367 vmf::BoundingBox limits
= vmf::getSolidListBounds(tavr_solids
);
368 float z_render_min
= limits
.SEL
.y
;
369 float z_render_max
= limits
.NWU
.y
;
371 // Overide entity heights
372 if (tavr_ent_tavr_height_min
.size()) z_render_min
= tavr_ent_tavr_height_min
[0]->origin
.z
;
373 if (tavr_ent_tavr_height_max
.size()) z_render_max
= tavr_ent_tavr_height_max
[0]->origin
.z
;
375 float padding
= 128.0f
;
377 float x_bounds_min
= -limits
.NWU
.x
- padding
; //inflate distances slightly
378 float x_bounds_max
= -limits
.SEL
.x
+ padding
;
380 float y_bounds_min
= limits
.SEL
.z
- padding
;
381 float y_bounds_max
= limits
.NWU
.z
+ padding
;
383 float dist_x
= x_bounds_max
- x_bounds_min
;
384 float dist_y
= y_bounds_max
- y_bounds_min
;
386 float mx_dist
= glm::max(dist_x
, dist_y
);
388 float justify_x
= (mx_dist
- dist_x
) * 0.5f
;
389 float justify_y
= (mx_dist
- dist_y
) * 0.5f
;
391 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.
392 glm::vec2 view_origin
= glm::vec2(x_bounds_min
- justify_x
, y_bounds_max
+ justify_y
);
394 std::cout
<< "done\n\n";
399 #pragma region OpenGLRender
401 std::cout
<< "Starting OpenGL Render\n";
403 #pragma region render_playable_space
404 std::cout
<< "Rendering playable space... ";
406 // ======================================================== REGULAR ORDER ========================================================
408 fb_comp
.Bind(); //Bind framebuffer
410 glClearColor(0.00f
, 0.00f
, 0.00f
, 1.00f
);
411 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
412 glPolygonMode(GL_FRONT
, GL_FILL
);
415 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
));
416 shader_depth
.setMatrix("view", glm::lookAt(glm::vec3(0, 0, 0), glm::vec3(0, -1.0f
, 0), glm::vec3(0, 0, 1)));
418 glm::mat4 model
= glm::mat4();
419 shader_depth
.setMatrix("model", model
);
421 shader_depth
.setFloat("HEIGHT_MIN", z_render_min
);
422 shader_depth
.setFloat("HEIGHT_MAX", z_render_max
);
423 shader_depth
.setFloat("write_playable", 0.0f
);
425 // Render entire map first
426 for (auto && brush
: tavr_entire_brushlist
) {
427 shader_depth
.setFloat("write_cover", brush
->temp_mark
? 1.0f
: 0.0f
);
430 glClear(GL_DEPTH_BUFFER_BIT
);
432 // Render playable area over it
433 shader_depth
.setFloat("write_playable", 1.0f
);
434 for (auto && s_solid
: tavr_solids
) {
435 shader_depth
.setFloat("write_cover", s_solid
->temp_mark
? 1.0f
: 0.0f
);
436 if (!s_solid
->containsDisplacements
)
437 s_solid
->mesh
->Draw();
439 for (auto && f
: s_solid
->faces
) {
440 if (f
.displacement
!= NULL
) {
441 f
.displacement
->glMesh
->Draw();
448 std::cout
<< "Rendering props\n";
449 shader_depth
.setFloat("write_cover", 1.0f
);
450 for (auto && s_prop
: vmf_main
.props
) {
451 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.
454 model
= glm::translate(model
, s_prop
.origin
); // Position
455 model
= glm::rotate(model
, glm::radians(s_prop
.rotation
.y
), glm::vec3(0, 1, 0)); // Yaw
456 model
= glm::rotate(model
, glm::radians(s_prop
.rotation
.x
), glm::vec3(0, 0, 1)); // ROOOOOLLLLL
457 model
= glm::rotate(model
, -glm::radians(s_prop
.rotation
.z
), glm::vec3(1, 0, 0)); // Pitch
458 model
= glm::scale(model
, glm::vec3(s_prop
.unifromScale
)); // Scale
460 shader_depth
.setMatrix("model", model
);
461 vmf_main
.modelCache
[s_prop
.modelID
]->Draw();
465 shader_depth
.setMatrix("model", model
);
467 // Re render subtractive brushes
468 shader_depth
.setFloat("write_playable", 0.0f
);
469 for (auto && s_solid
: tavr_solids_negative
) {
470 shader_depth
.setFloat("write_cover", s_solid
->temp_mark
? 1.0f
: 0.0f
);
471 if (!s_solid
->containsDisplacements
)
472 s_solid
->mesh
->Draw();
474 for (auto && f
: s_solid
->faces
) {
475 if (f
.displacement
!= NULL
) {
476 f
.displacement
->glMesh
->Draw();
482 // ======================================================== REVERSE ORDER ========================================================
488 glEnable(GL_CULL_FACE
);
489 glDepthFunc(GL_GREATER
);
491 glClearColor(0.00f
, 0.00f
, 0.00f
, 1.00f
);
492 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
493 glPolygonMode(GL_FRONT
, GL_FILL
);
495 shader_depth
.setFloat("HEIGHT_MIN", z_render_min
);
496 shader_depth
.setFloat("HEIGHT_MAX", z_render_max
);
497 shader_depth
.setFloat("write_playable", 0.0f
);
499 for (auto && s_solid
: tavr_solids
) {
500 if (!s_solid
->containsDisplacements
)
501 s_solid
->mesh
->Draw();
503 for (auto && f
: s_solid
->faces
) {
504 if (f
.displacement
!= NULL
) {
505 f
.displacement
->glMesh
->Draw();
511 // regular depth testing
513 glDepthFunc(GL_LESS
);
514 glDisable(GL_CULL_FACE
);
516 // ========================================================== PRE-COMP ===========================================================
519 fb_tex_playspace
.Bind();
521 glClearColor(0.00f
, 0.00f
, 0.00f
, 0.00f
);
522 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
523 glDisable(GL_DEPTH_TEST
);
524 glPolygonMode(GL_FRONT
, GL_FILL
);
526 shader_precomp_playspace
.use();
528 //shader_precomp_playspace.setFloat("HEIGHT_MIN", z_render_min);
529 //shader_precomp_playspace.setFloat("HEIGHT_MAX", z_render_max);
531 fb_comp
.BindRTtoTexSlot(0);
532 shader_precomp_playspace
.setInt("tex_in", 0);
534 fb_comp_1
.BindRTtoTexSlot(1);
535 shader_precomp_playspace
.setInt("tex_in_1", 1);
537 //tex_height_modulate.bindOnSlot(2);
538 //shader_precomp_playspace.setInt("tex_modulate", 2);
540 mesh_screen_quad
->Draw();
542 glEnable(GL_DEPTH_TEST
);
545 render_to_png(m_renderWidth
, m_renderHeight
, std::string(m_overviews_folder
+ m_mapfile_name
+ ".resources.playable_space.png").c_str());
547 std::cout
<< "done!\n";
550 #pragma region render_objectives
551 std::cout
<< "Rendering bombsites & buyzones space... ";
555 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
556 glPolygonMode(GL_FRONT
, GL_FILL
);
557 //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
560 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
));
561 shader_unlit
.setMatrix("view", glm::lookAt(glm::vec3(0, 0, 0), glm::vec3(0, -1.0f
, 0), glm::vec3(0, 0, 1)));
562 shader_unlit
.setMatrix("model", model
);
564 shader_unlit
.setVec3("color", 0.0f
, 1.0f
, 0.0f
);
566 for (auto && s_solid
: tavr_buyzones
) {
567 s_solid
->mesh
->Draw();
571 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
573 shader_unlit
.setVec3("color", 1.0f
, 0.0f
, 0.0f
);
575 for (auto && s_solid
: tavr_bombtargets
) {
576 s_solid
->mesh
->Draw();
580 fb_tex_objectives
.Bind();
582 glClearColor(0.00f
, 0.00f
, 0.00f
, 0.00f
);
583 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
584 glDisable(GL_DEPTH_TEST
);
585 glPolygonMode(GL_FRONT
, GL_FILL
);
587 shader_precomp_objectives
.use();
589 fb_comp
.BindRTtoTexSlot(0);
590 shader_precomp_objectives
.setInt("tex_in", 0);
592 fb_comp_1
.BindRTtoTexSlot(1);
593 shader_precomp_objectives
.setInt("tex_in_1", 1);
595 mesh_screen_quad
->Draw();
598 render_to_png(m_renderWidth
, m_renderHeight
, std::string(m_overviews_folder
+ m_mapfile_name
+ ".resources.buyzone_bombtargets.png").c_str());
600 glEnable(GL_DEPTH_TEST
);
601 std::cout
<< "done!\n";
604 #pragma region compositing
605 std::cout
<< "Compositing... \n";
609 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
610 glPolygonMode(GL_FRONT
, GL_FILL
);
612 shader_comp_main
.use();
614 /* Fill out shader uniforms */
616 vec3 bounds_NWU North-West-Upper coordinate of the playspace (worldspace)
617 vec3 bounds_SEL South-East-Lower coordinate of the playspace (worldspace)
618 **vec2 bounds_NWU_SS North-West coordinate of the playspace (screen space)
619 **vec2 bounds_SEL_SS South-East coordinate of the playspace (screen space)
621 **vec2 pos_spawn_ct Location of the CT Spawn (0-1)
622 **vec2 pos_spawn_t Location of the T Spawn (0-1)
623 **vec2 bombsite_a Location of bomsite A (0-1)
624 **vec2 bombsite_b Location of bombsite B (0-1)
626 shader_comp_main
.setVec3("bounds_NWU", glm::vec3(x_bounds_min
, y_bounds_max
, z_render_max
));
627 shader_comp_main
.setVec3("bounds_SEL", glm::vec3(x_bounds_max
, y_bounds_min
, z_render_min
));
630 shader_comp_main
.setInt("cmdl_shadows_enable", tar_cfg_enableShadows
? 1 : 0);
631 shader_comp_main
.setInt("cmdl_ao_enable", tar_cfg_enableAO
? 1 : 0);
632 shader_comp_main
.setInt("cmdl_ao_size", tar_cfg_aoSzie
);
633 shader_comp_main
.setInt("cmdl_outline_enable", tar_cfg_enableOutline
);
634 shader_comp_main
.setInt("cmdl_outline_size", tar_cfg_outlineSize
);
636 /* Bind texture samplers */
637 tex_background
.bindOnSlot(0);
638 shader_comp_main
.setInt("tex_background", 0);
640 fb_tex_playspace
.BindRTtoTexSlot(1);
641 shader_comp_main
.setInt("tex_playspace", 1);
643 fb_tex_objectives
.BindRTtoTexSlot(2);
644 shader_comp_main
.setInt("tex_objectives", 2);
646 tar_cfg_gradientMap
->bindOnSlot(4);
647 shader_comp_main
.setInt("tex_gradient", 4);
649 mesh_screen_quad
->Draw();
651 std::cout
<< "done!\n";
657 #pragma region auto_export_game
658 if (!m_onlyOutputMasks
) {
659 save_to_dds(m_renderWidth
, m_renderHeight
, std::string(m_overviews_folder
+ m_mapfile_name
+ "_radar.dds").c_str());
663 render_to_png(m_renderWidth
, m_renderHeight
, std::string(m_overviews_folder
+ m_mapfile_name
+ ".resources.final_raw.png").c_str());
665 #pragma region generate_radar_txt
667 std::cout
<< "Generating radar .TXT... ";
669 kv::DataBlock node_radar
= kv::DataBlock();
670 node_radar
.name
= m_mapfile_name
;
671 node_radar
.Values
.insert({ "material", "overviews/" + m_mapfile_name
});
673 node_radar
.Values
.insert({ "pos_x", std::to_string(view_origin
.x
) });
674 node_radar
.Values
.insert({ "pos_y", std::to_string(view_origin
.y
) });
675 node_radar
.Values
.insert({ "scale", std::to_string(render_ortho_scale
/ 1024.0f
) });
677 // Try resolve spawn positions
678 glm::vec3
* loc_spawnCT
= vmf_main
.calculateSpawnLocation(vmf::team::counter_terrorist
);
679 glm::vec3
* loc_spawnT
= vmf_main
.calculateSpawnLocation(vmf::team::terrorist
);
681 if (loc_spawnCT
!= NULL
) {
682 node_radar
.Values
.insert({ "CTSpawn_x", std::to_string(glm::round(remap(loc_spawnCT
->x
, view_origin
.x
, view_origin
.x
+ render_ortho_scale
, 0.0f
, 1.0f
) / 0.01f
) * 0.01f
) });
683 node_radar
.Values
.insert({ "CTSpawn_y", std::to_string(glm::round(remap(loc_spawnCT
->y
, view_origin
.y
, view_origin
.y
- render_ortho_scale
, 0.0f
, 1.0f
) / 0.01f
) * 0.01f
) });
685 if (loc_spawnT
!= NULL
) {
686 node_radar
.Values
.insert({ "TSpawn_x", std::to_string(glm::round(remap(loc_spawnT
->x
, view_origin
.x
, view_origin
.x
+ render_ortho_scale
, 0.0f
, 1.0f
) / 0.01f
) * 0.01f
) });
687 node_radar
.Values
.insert({ "TSpawn_y", std::to_string(glm::round(remap(loc_spawnT
->y
, view_origin
.y
, view_origin
.y
- render_ortho_scale
, 0.0f
, 1.0f
) / 0.01f
) * 0.01f
) });
690 std::ofstream
out(std::string(m_overviews_folder
+ m_mapfile_name
+ ".txt").c_str());
691 out
<< "// TAVR - AUTO RADAR. v 2.0.0\n";
692 node_radar
.Serialize(out
);
695 std::cout
<< "done!";
700 std::cout
<< "\n- Radar generation successful... cleaning up. -\n";
712 #ifndef entry_point_testing
713 int main(int argc
, const char** argv
) {
715 return app(argc
, argv
);
717 catch (cxxopts::OptionException
& e
) {
718 std::cerr
<< "Parse error: " << e
.what() << "\n";