A 3D game engine from scratch.
at main 1370 lines 51 kB view raw
1// (c) 2020 Vlad-Stefan Harbuz <vlad@vladh.net> 2 3#include "../src_external/pstr.h" 4#include "renderer.hpp" 5#include "engine.hpp" 6#include "mats.hpp" 7#include "debug.hpp" 8#include "util.hpp" 9#include "glutil.hpp" 10#include "logs.hpp" 11#include "debug_ui.hpp" 12#include "debugdraw.hpp" 13#include "intrinsics.hpp" 14 15 16renderer::State *renderer::state = nullptr; 17 18 19GLFWwindow * 20renderer::init_window(WindowSize *window_size) 21{ 22 glfwInit(); 23 24 logs::info("Using OpenGL 4.1"); 25 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); 26 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); 27 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 28 29#if defined(PLATFORM_MACOS) 30 // macOS requires a forward compatible context 31 // This means the highest OpenGL version will be used that is at least the version 32 // we specified, and that contains no breaking changes from the version we specified 33 glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); 34#endif 35 36 if (SETTINGS.opengl_debug_on) { 37 logs::info("Using OpenGL debug context"); 38 glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, true); 39 } 40 41 // Remove window decorations (border etc.) 42 glfwWindowHint(GLFW_DECORATED, GLFW_FALSE); 43 44 // For fullscreen windows, do not discard our video mode when minimised 45 glfwWindowHint(GLFW_AUTO_ICONIFY, GLFW_FALSE); 46 47 // Create the window. Right now we're working with screencoord sizes, 48 // not pixels! 49 50 GLFWwindow *window; 51 52 if (SETTINGS.fullscreen_on) { 53 i32 n_monitors; 54 GLFWmonitor **monitors = glfwGetMonitors(&n_monitors); 55 GLFWmonitor *target_monitor = monitors[SETTINGS.target_monitor]; 56 const GLFWvidmode *video_mode = glfwGetVideoMode(target_monitor); 57 glfwWindowHint(GLFW_RED_BITS, video_mode->redBits); 58 glfwWindowHint(GLFW_GREEN_BITS, video_mode->greenBits); 59 glfwWindowHint(GLFW_BLUE_BITS, video_mode->blueBits); 60 glfwWindowHint(GLFW_REFRESH_RATE, video_mode->refreshRate); 61 62 window_size->screencoord_width = video_mode->width; 63 window_size->screencoord_height = video_mode->height; 64 65 if (SETTINGS.windowed_fullscreen_on) { 66 window = glfwCreateWindow( 67 window_size->screencoord_width, window_size->screencoord_height, 68 WINDOW_TITLE, 69 nullptr, nullptr); 70 } else { 71 window = glfwCreateWindow( 72 window_size->screencoord_width, window_size->screencoord_height, 73 WINDOW_TITLE, 74 target_monitor, nullptr); 75 } 76 } else { 77 window_size->screencoord_width = 1920; 78 window_size->screencoord_height = 1080; 79 80 window = glfwCreateWindow( 81 window_size->screencoord_width, window_size->screencoord_height, 82 WINDOW_TITLE, 83 nullptr, nullptr); 84 85 glfwSetWindowPos(window, 200, 200); 86 } 87 88 if (!window) { 89 logs::fatal("Failed to create GLFW window"); 90 return nullptr; 91 } 92 93 glfwMakeContextCurrent(window); 94 95 if (!SETTINGS.vsync_on) { 96 glfwSwapInterval(0); 97 } 98 99 if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { 100 logs::fatal("Failed to initialize GLAD"); 101 return nullptr; 102 } 103 104 if (!GLAD_GL_ARB_texture_cube_map_array) { 105 logs::fatal("No support for GLAD_GL_ARB_texture_cube_map_array"); 106 } 107 if (!GLAD_GL_ARB_texture_storage) { 108 logs::fatal("No support for GLAD_GL_ARB_texture_storage"); 109 } 110 if (!GLAD_GL_ARB_buffer_storage) { 111 logs::warning("No support for GLAD_GL_ARB_buffer_storage"); 112 } 113 114 // TODO: Remove GL_EXT_debug_marker from GLAD 115 // TODO: Remove GL_EXT_debug_label from GLAD 116 // TODO: Remove GL_ARB_texture_storage_multisample from GLAD 117 118 if (SETTINGS.opengl_debug_on) { 119 if (GLAD_GL_AMD_debug_output || GLAD_GL_ARB_debug_output || GLAD_GL_KHR_debug) { 120 GLint flags; 121 glGetIntegerv(GL_CONTEXT_FLAGS, &flags); 122 123 if (flags & GL_CONTEXT_FLAG_DEBUG_BIT) { 124 glEnable(GL_DEBUG_OUTPUT); 125 glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); 126 glDebugMessageCallback(glutil::debug_message_callback, nullptr); 127 glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE); 128 } else { 129 logs::fatal("Tried to initialise OpenGL debug output but couldn't"); 130 } 131 } else { 132 logs::warning( 133 "Tried to initialise OpenGL debug output but none of " 134 "[GL_AMD_debug_output, GL_ARB_debug_output, GL_KHR_debug] " 135 "are supported on this system. Skipping."); 136 } 137 } 138 139 // Enable multisampling 140 glEnable(GL_MULTISAMPLE); 141 glfwWindowHint(GLFW_SAMPLES, 4); 142 143 glEnable(GL_DEPTH_TEST); 144 glEnable(GL_CULL_FACE); 145 glCullFace(GL_BACK); 146 glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 147#if !defined(PLATFORM_MACOS) 148 glLineWidth(2.0f); 149#endif 150 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 151 152 // Get the framebuffer size. This is the actual window size in pixels. 153 glfwGetFramebufferSize(window, &window_size->width, &window_size->height); 154 glViewport(0, 0, window_size->width, window_size->height); 155 156 glfwSetFramebufferSizeCallback(window, core::framebuffer_size_callback); 157 glfwSetCursorPosCallback(window, core::mouse_callback); 158 glfwSetMouseButtonCallback(window, core::mouse_button_callback); 159 glfwSetKeyCallback(window, core::key_callback); 160 glfwSetCharCallback(window, core::char_callback); 161 162 return window; 163} 164 165 166void 167renderer::resize_renderer_buffers( 168 memory::Pool *memory_pool, 169 BuiltinTextures *builtin_textures, 170 u32 width, 171 u32 height 172) { 173 // TODO: Only regenerate once we're done resizing, not for every little bit 174 // of the resize. 175 init_g_buffer( 176 memory_pool, 177 &builtin_textures->g_buffer, 178 &builtin_textures->g_position_texture, 179 &builtin_textures->g_normal_texture, 180 &builtin_textures->g_albedo_texture, 181 &builtin_textures->g_pbr_texture, 182 width, height); 183 init_l_buffer( 184 memory_pool, 185 &builtin_textures->l_buffer, 186 &builtin_textures->l_color_texture, 187 &builtin_textures->l_bright_color_texture, 188 &builtin_textures->l_depth_texture, 189 width, height); 190 init_blur_buffers( 191 memory_pool, 192 &builtin_textures->blur1_buffer, 193 &builtin_textures->blur2_buffer, 194 &builtin_textures->blur1_texture, 195 &builtin_textures->blur2_texture, 196 width, height); 197 198 each (material, *mats::get_materials()) { 199 if (material->n_textures > 0 && material->is_screensize_dependent) { 200 for (u32 idx_texture = 0; idx_texture < material->n_textures; idx_texture++) { 201 mats::Texture *texture = &material->textures[idx_texture]; 202 if (texture->type == mats::TextureType::g_position) { 203 material->textures[idx_texture] = *builtin_textures->g_position_texture; 204 } else if (texture->type == mats::TextureType::g_normal) { 205 material->textures[idx_texture] = *builtin_textures->g_normal_texture; 206 } else if (texture->type == mats::TextureType::g_albedo) { 207 material->textures[idx_texture] = *builtin_textures->g_albedo_texture; 208 } else if (texture->type == mats::TextureType::g_pbr) { 209 material->textures[idx_texture] = *builtin_textures->g_pbr_texture; 210 } else if (texture->type == mats::TextureType::l_color) { 211 material->textures[idx_texture] = *builtin_textures->l_color_texture; 212 } else if (texture->type == mats::TextureType::l_bright_color) { 213 material->textures[idx_texture] = *builtin_textures->l_bright_color_texture; 214 } else if (texture->type == mats::TextureType::l_depth) { 215 material->textures[idx_texture] = *builtin_textures->l_depth_texture; 216 } else if (texture->type == mats::TextureType::blur1) { 217 material->textures[idx_texture] = *builtin_textures->blur1_texture; 218 } else if (texture->type == mats::TextureType::blur2) { 219 material->textures[idx_texture] = *builtin_textures->blur2_texture; 220 } 221 } 222 mats::bind_texture_uniforms(material); 223 } 224 } 225} 226 227 228void 229renderer::update_drawing_options(GLFWwindow *window) 230{ 231 if (input::is_cursor_enabled()) { 232 glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); 233 } else { 234 glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); 235 } 236 237 if (renderer::state->should_use_wireframe) { 238 // This will be handled in the rendering loop. 239 } else { 240 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 241 } 242} 243 244 245void 246renderer::render(GLFWwindow *window) 247{ 248 // Block rendering until all previous OpenGL operations have been completed. 249 // This prevents issues where we have multiple frames queued up for drawing on the GPU, 250 // in which case we will get all sorts of unpleasant stutter. This problem will only 251 // realistically happen when the CPU has way less to do than the GPU and so is issuing 252 // a lot of frames. 253 // In the future, we might want to remove this, because it does block our CPU time 254 // until the GPU is done. However, for now, we don't have that much in our scene, 255 // and the stuttering is more of a problem. 256 // If we're using vsync, this is not really a problem, so we don't need to glFinish(). 257 // There is an issue that can arise: it might be the case that we think we're using 258 // vsync, but actually a graphics driver has forced it off, in which case we won't be 259 // using glFinish(), but we should be...probably not going to be a real problem, 260 // though. 261 if (!SETTINGS.vsync_on) { 262 glFinish(); 263 } 264 265 WindowSize *window_size = core::get_window_size(); 266 267 copy_scene_data_to_ubo(0, 0, false); 268 269 // Clear framebuffers 270 { 271 glBindFramebuffer(GL_FRAMEBUFFER, 0); 272 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 273 glBindFramebuffer(GL_FRAMEBUFFER, renderer::state->builtin_textures.g_buffer); 274 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 275 glBindFramebuffer(GL_FRAMEBUFFER, renderer::state->builtin_textures.l_buffer); 276 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 277 if (SETTINGS.bloom_on) { 278 glBindFramebuffer(GL_FRAMEBUFFER, renderer::state->builtin_textures.blur1_buffer); 279 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 280 glBindFramebuffer(GL_FRAMEBUFFER, renderer::state->builtin_textures.blur2_buffer); 281 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 282 } 283 } 284 285 // Render shadow map 286 if (SETTINGS.shadows_on) { 287 // Point lights 288 { 289 f32 ratio = (f32)renderer::state->builtin_textures.shadowmap_3d_width / 290 (f32)renderer::state->builtin_textures.shadowmap_3d_height; 291 m4 perspective_projection = glm::perspective( 292 radians(90.0f), ratio, 293 renderer::state->builtin_textures.shadowmap_near_clip_dist, 294 renderer::state->builtin_textures.shadowmap_far_clip_dist); 295 296 u32 idx_light = 0; 297 298 each (light_component, *lights::get_components()) { 299 if (light_component->entity_handle == entities::NO_ENTITY_HANDLE) { 300 continue; 301 } 302 303 spatial::Component *spatial_component = 304 spatial::get_component(light_component->entity_handle); 305 306 if (!( 307 lights::is_light_component_valid(light_component) && 308 light_component->type == lights::LightType::point && 309 spatial::is_spatial_component_valid(spatial_component) 310 )) { 311 continue; 312 } 313 314 v3 position = spatial_component->position; 315 316 for (u32 idx_face = 0; idx_face < 6; idx_face++) { 317 renderer::state->shadowmap_3d_transforms[(idx_light * 6) + idx_face] = 318 perspective_projection * glm::lookAt( 319 position, 320 position + models::CUBEMAP_OFFSETS[idx_face], 321 models::CUBEMAP_UPS[idx_face]); 322 } 323 324 glViewport(0, 0, 325 renderer::state->builtin_textures.shadowmap_3d_width, 326 renderer::state->builtin_textures.shadowmap_3d_height); 327 glBindFramebuffer(GL_FRAMEBUFFER, 328 renderer::state->builtin_textures.shadowmaps_3d_framebuffer); 329 glClear(GL_DEPTH_BUFFER_BIT); 330 331 copy_scene_data_to_ubo( 332 idx_light, lights::light_type_to_int(light_component->type), 333 false); 334 render_scene(drawable::Pass::shadowcaster, drawable::Mode::depth); 335 336 idx_light++; 337 } 338 } 339 340 // Directional lights 341 { 342 f32 ortho_ratio = ( 343 (f32)renderer::state->builtin_textures.shadowmap_2d_width / 344 (f32)renderer::state->builtin_textures.shadowmap_2d_height); 345 f32 ortho_width = 100.0f; 346 f32 ortho_height = ortho_width / ortho_ratio; 347 m4 ortho_projection = glm::ortho( 348 -ortho_width, ortho_width, -ortho_height, ortho_height, 349 renderer::state->builtin_textures.shadowmap_near_clip_dist, 350 renderer::state->builtin_textures.shadowmap_far_clip_dist); 351 352 u32 idx_light = 0; 353 354 each (light_component, *lights::get_components()) { 355 if (light_component->entity_handle == entities::NO_ENTITY_HANDLE) { 356 continue; 357 } 358 359 spatial::Component *spatial_component = 360 spatial::get_component(light_component->entity_handle); 361 362 if (!( 363 lights::is_light_component_valid(light_component) && 364 light_component->type == lights::LightType::directional && 365 spatial::is_spatial_component_valid(spatial_component) 366 )) { 367 continue; 368 } 369 370 renderer::state->shadowmap_2d_transforms[idx_light] = ortho_projection * 371 glm::lookAt(spatial_component->position, 372 spatial_component->position + light_component->direction, 373 v3(0.0f, -1.0f, 0.0f)); 374 375 glViewport(0, 0, 376 renderer::state->builtin_textures.shadowmap_2d_width, 377 renderer::state->builtin_textures.shadowmap_2d_height); 378 glBindFramebuffer(GL_FRAMEBUFFER, 379 renderer::state->builtin_textures.shadowmaps_2d_framebuffer); 380 glClear(GL_DEPTH_BUFFER_BIT); 381 382 copy_scene_data_to_ubo( 383 idx_light, lights::light_type_to_int(light_component->type), 384 false); 385 render_scene(drawable::Pass::shadowcaster, drawable::Mode::depth); 386 387 idx_light++; 388 } 389 } 390 } 391 392 glViewport(0, 0, window_size->width, window_size->height); 393 394 // Geometry pass 395 { 396 if (renderer::state->should_use_wireframe) { 397 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 398 } 399 glBindFramebuffer(GL_FRAMEBUFFER, renderer::state->builtin_textures.g_buffer); 400 render_scene(drawable::Pass::deferred, drawable::Mode::regular); 401 if (renderer::state->should_use_wireframe) { 402 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 403 } 404 } 405 406 // Copy depth from geometry pass to lighting pass 407 { 408 glBindFramebuffer(GL_READ_FRAMEBUFFER, renderer::state->builtin_textures.g_buffer); 409 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, renderer::state->builtin_textures.l_buffer); 410 glBlitFramebuffer(0, 0, window_size->width, window_size->height, 411 0, 0, window_size->width, window_size->height, 412 GL_DEPTH_BUFFER_BIT, GL_NEAREST); 413 } 414 415 glBindFramebuffer(GL_FRAMEBUFFER, renderer::state->builtin_textures.l_buffer); 416 417 // Lighting pass 418 { 419 glDisable(GL_DEPTH_TEST); 420 render_scene(drawable::Pass::lighting, drawable::Mode::regular); 421 glEnable(GL_DEPTH_TEST); 422 } 423 424 425 // Forward pass 426 { 427 // Skysphere 428 { 429 // Cull outside, not inside, of sphere. 430 glCullFace(GL_FRONT); 431 // Do not write to depth buffer. 432 glDepthMask(GL_FALSE); 433 // Draw at the very back of our depth range, so as to be behind everything. 434 glDepthRange(0.9999f, 1.0f); 435 436 render_scene(drawable::Pass::forward_skybox, drawable::Mode::regular); 437 438 glDepthRange(0.0f, 1.0f); 439 glDepthMask(GL_TRUE); 440 glCullFace(GL_BACK); 441 } 442 443 // Forward 444 { 445 if (renderer::state->should_use_wireframe) { 446 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 447 } 448 render_scene(drawable::Pass::forward_depth, drawable::Mode::regular); 449 glDisable(GL_DEPTH_TEST); 450 render_scene(drawable::Pass::forward_nodepth, drawable::Mode::regular); 451 glEnable(GL_DEPTH_TEST); 452 if (renderer::state->should_use_wireframe) { 453 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 454 } 455 } 456 457 // Debug draw pass 458 { 459 debugdraw::render(); 460 } 461 } 462 463 glDisable(GL_DEPTH_TEST); 464 465 // Blur pass 466 if (SETTINGS.bloom_on) { 467 glBindFramebuffer(GL_FRAMEBUFFER, renderer::state->builtin_textures.blur1_buffer); 468 copy_scene_data_to_ubo(0, 0, true); 469 render_scene(drawable::Pass::preblur, drawable::Mode::regular); 470 471 glBindFramebuffer(GL_FRAMEBUFFER, renderer::state->builtin_textures.blur2_buffer); 472 copy_scene_data_to_ubo(0, 0, false); 473 render_scene(drawable::Pass::blur2, drawable::Mode::regular); 474 475 for (u32 idx = 0; idx < 3; idx++) { 476 glBindFramebuffer(GL_FRAMEBUFFER, renderer::state->builtin_textures.blur1_buffer); 477 copy_scene_data_to_ubo(0, 0, true); 478 render_scene(drawable::Pass::blur1, drawable::Mode::regular); 479 480 glBindFramebuffer(GL_FRAMEBUFFER, renderer::state->builtin_textures.blur2_buffer); 481 copy_scene_data_to_ubo(0, 0, false); 482 render_scene(drawable::Pass::blur2, drawable::Mode::regular); 483 } 484 } 485 486 glBindFramebuffer(GL_FRAMEBUFFER, 0); 487 488 // Postprocessing pass 489 { 490 render_scene(drawable::Pass::postprocessing, drawable::Mode::regular); 491 } 492 493 // Render debug pass 494 { 495 render_scene(drawable::Pass::renderdebug, drawable::Mode::regular); 496 } 497 498 // UI pass 499 { 500 if (!renderer::state->should_hide_ui) { 501 glEnable(GL_BLEND); 502 debug_ui::render_debug_ui(); 503 glDisable(GL_BLEND); 504 } 505 } 506 507 glEnable(GL_DEPTH_TEST); 508 509 START_TIMER(swap_buffers); 510 glfwSwapBuffers(window); 511 END_TIMER_MIN(swap_buffers, 10); 512 513 // Do any needed post-render cleanup 514 debugdraw::clear(); 515 clear_gui_vertices(); 516} 517 518 519void 520renderer::init( 521 renderer::State *renderer_state, 522 memory::Pool *memory_pool, 523 u32 width, 524 u32 height, 525 GLFWwindow *window 526) { 527 renderer::state = renderer_state; 528 BuiltinTextures *builtin_textures = &renderer::state->builtin_textures; 529 if (SETTINGS.graphics_quality == GraphicsQuality::high) { 530 *builtin_textures = { 531 .shadowmap_3d_width = min((u32)width, (u32)2000), 532 .shadowmap_3d_height = min((u32)width, (u32)2000), 533 .shadowmap_2d_width = 2560 * 2, 534 .shadowmap_2d_height = 1440 * 2, 535 .shadowmap_near_clip_dist = 0.05f, 536 .shadowmap_far_clip_dist = 200.0f, 537 }; 538 } else if (SETTINGS.graphics_quality == GraphicsQuality::low) { 539 *builtin_textures = { 540 .shadowmap_3d_width = 500, 541 .shadowmap_3d_height = 500, 542 .shadowmap_2d_width = 800, 543 .shadowmap_2d_height = 600, 544 .shadowmap_near_clip_dist = 0.05f, 545 .shadowmap_far_clip_dist = 200.0f, 546 }; 547 } 548 init_g_buffer(memory_pool, 549 &builtin_textures->g_buffer, 550 &builtin_textures->g_position_texture, 551 &builtin_textures->g_normal_texture, 552 &builtin_textures->g_albedo_texture, 553 &builtin_textures->g_pbr_texture, 554 width, height); 555 init_l_buffer(memory_pool, 556 &builtin_textures->l_buffer, 557 &builtin_textures->l_color_texture, 558 &builtin_textures->l_bright_color_texture, 559 &builtin_textures->l_depth_texture, 560 width, height); 561 init_blur_buffers(memory_pool, 562 &builtin_textures->blur1_buffer, 563 &builtin_textures->blur2_buffer, 564 &builtin_textures->blur1_texture, 565 &builtin_textures->blur2_texture, 566 width, height); 567 init_3d_shadowmaps(memory_pool, 568 &builtin_textures->shadowmaps_3d_framebuffer, 569 &builtin_textures->shadowmaps_3d, 570 &builtin_textures->shadowmaps_3d_texture, 571 builtin_textures->shadowmap_3d_width, 572 builtin_textures->shadowmap_3d_height); 573 init_2d_shadowmaps(memory_pool, 574 &builtin_textures->shadowmaps_2d_framebuffer, 575 &builtin_textures->shadowmaps_2d, 576 &builtin_textures->shadowmaps_2d_texture, 577 builtin_textures->shadowmap_2d_width, 578 builtin_textures->shadowmap_2d_height); 579 init_ubo(&renderer::state->ubo_shader_common); 580 update_drawing_options(window); 581 init_gui(memory_pool); 582} 583 584 585void 586renderer::start_drawing_gui() 587{ 588 glBindVertexArray(renderer::state->gui_vao); 589 glBindBuffer(GL_ARRAY_BUFFER, renderer::state->gui_vbo); 590} 591 592 593void 594renderer::push_gui_vertices(f32 *vertices, u32 n_vertices) 595{ 596 // VAO/VBO must have been bound by start_drawing() 597 if (renderer::state->gui_n_vertices_pushed + n_vertices > GUI_MAX_N_VERTICES) { 598 logs::error("Pushed too many GUI vertices, did you forget to call renderer::clear_gui_vertices()?"); 599 return; 600 } 601 glBufferSubData(GL_ARRAY_BUFFER, 602 GUI_VERTEX_SIZE * renderer::state->gui_n_vertices_pushed, 603 GUI_VERTEX_SIZE * n_vertices, vertices); 604 605 renderer::state->gui_n_vertices_pushed += n_vertices; 606} 607 608 609void 610renderer::clear_gui_vertices() 611{ 612 renderer::state->gui_n_vertices_pushed = 0; 613} 614 615 616void 617renderer::render_gui() 618{ 619 glUseProgram(renderer::state->gui_shader_asset.program); 620 621 glActiveTexture(GL_TEXTURE0); 622 glBindTexture(GL_TEXTURE_2D, renderer::state->gui_texture_atlas.texture_name); 623 624 if (!renderer::state->gui_shader_asset.did_set_texture_uniforms) { 625 shaders::set_int(&renderer::state->gui_shader_asset, "atlas_texture", 0); 626 renderer::state->gui_shader_asset.did_set_texture_uniforms = true; 627 } 628 629 glDrawArrays(GL_TRIANGLES, 0, renderer::state->gui_n_vertices_pushed); 630} 631 632 633bool 634renderer::should_use_wireframe() 635{ 636 return renderer::state->should_use_wireframe; 637} 638 639 640void 641renderer::set_should_use_wireframe(bool val) 642{ 643 renderer::state->should_use_wireframe = val; 644} 645 646 647renderer::BuiltinTextures * 648renderer::get_builtin_textures() 649{ 650 return &renderer::state->builtin_textures; 651} 652 653 654shaders::Asset * 655renderer::get_standard_depth_shader_asset() 656{ 657 return &renderer::state->standard_depth_shader_asset; 658} 659 660 661iv2 662renderer::get_gui_texture_atlas_size() 663{ 664 return renderer::state->gui_texture_atlas.size; 665} 666 667 668Array<fonts::FontAsset> * 669renderer::get_gui_font_assets() 670{ 671 return &renderer::state->gui_font_assets; 672} 673 674 675void 676renderer::set_renderdebug_displayed_texture_type(mats::TextureType val) 677{ 678 renderer::state->renderdebug_displayed_texture_type = val; 679} 680 681 682bool 683renderer::should_hide_ui() 684{ 685 return renderer::state->should_hide_ui; 686} 687 688 689void 690renderer::set_should_hide_ui(bool val) 691{ 692 renderer::state->should_hide_ui = val; 693} 694 695 696void 697renderer::init_g_buffer( 698 memory::Pool *memory_pool, 699 u32 *g_buffer, 700 mats::Texture **g_position_texture, 701 mats::Texture **g_normal_texture, 702 mats::Texture **g_albedo_texture, 703 mats::Texture **g_pbr_texture, 704 u32 width, 705 u32 height 706) { 707 glGenFramebuffers(1, g_buffer); 708 glBindFramebuffer(GL_FRAMEBUFFER, *g_buffer); 709 710 u32 g_position_texture_name; 711 u32 g_normal_texture_name; 712 u32 g_albedo_texture_name; 713 u32 g_pbr_texture_name; 714 715 glGenTextures(1, &g_position_texture_name); 716 glGenTextures(1, &g_normal_texture_name); 717 glGenTextures(1, &g_albedo_texture_name); 718 glGenTextures(1, &g_pbr_texture_name); 719 720 *g_position_texture = mats::init_texture( 721 MEMORY_PUSH(memory_pool, mats::Texture, "g_position_texture"), 722 GL_TEXTURE_2D, mats::TextureType::g_position, g_position_texture_name, width, height, 4); 723 (*g_position_texture)->is_builtin = true; 724 725 *g_normal_texture = mats::init_texture( 726 MEMORY_PUSH(memory_pool, mats::Texture, "g_normal_texture"), 727 GL_TEXTURE_2D, mats::TextureType::g_normal, g_normal_texture_name, width, height, 4); 728 (*g_normal_texture)->is_builtin = true; 729 730 *g_albedo_texture = mats::init_texture( 731 MEMORY_PUSH(memory_pool, mats::Texture, "g_albedo_texture"), 732 GL_TEXTURE_2D, mats::TextureType::g_albedo, g_albedo_texture_name, width, height, 4); 733 (*g_albedo_texture)->is_builtin = true; 734 735 *g_pbr_texture = mats::init_texture( 736 MEMORY_PUSH(memory_pool, mats::Texture, "g_pbr_texture"), 737 GL_TEXTURE_2D, mats::TextureType::g_pbr, g_pbr_texture_name, width, height, 4); 738 (*g_pbr_texture)->is_builtin = true; 739 740 glBindTexture(GL_TEXTURE_2D, (*g_position_texture)->texture_name); 741 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 742 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 743 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, 744 (*g_position_texture)->width, (*g_position_texture)->height, 745 0, GL_RGBA, GL_FLOAT, NULL); 746 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 747 (*g_position_texture)->texture_name, 0); 748 749 glBindTexture(GL_TEXTURE_2D, (*g_normal_texture)->texture_name); 750 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 751 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 752 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, 753 (*g_normal_texture)->width, (*g_normal_texture)->height, 754 0, GL_RGBA, GL_FLOAT, NULL); 755 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, 756 (*g_normal_texture)->texture_name, 0); 757 758 glBindTexture(GL_TEXTURE_2D, (*g_albedo_texture)->texture_name); 759 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 760 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 761 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 762 (*g_albedo_texture)->width, (*g_albedo_texture)->height, 763 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 764 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, 765 (*g_albedo_texture)->texture_name, 0); 766 767 glBindTexture(GL_TEXTURE_2D, (*g_pbr_texture)->texture_name); 768 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 769 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 770 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 771 (*g_pbr_texture)->width, (*g_pbr_texture)->height, 772 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 773 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, 774 (*g_pbr_texture)->texture_name, 0); 775 776 u32 attachments[4] = { 777 GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, 778 GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 779 }; 780 glDrawBuffers(4, attachments); 781 782 u32 rbo_depth; 783 glGenRenderbuffers(1, &rbo_depth); 784 glBindRenderbuffer(GL_RENDERBUFFER, rbo_depth); 785 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height); 786 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 787 rbo_depth); 788 789 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { 790 logs::fatal("Framebuffer not complete!"); 791 } 792} 793 794 795void 796renderer::init_l_buffer( 797 memory::Pool *memory_pool, 798 u32 *l_buffer, 799 mats::Texture **l_color_texture, 800 mats::Texture **l_bright_color_texture, 801 mats::Texture **l_depth_texture, 802 u32 width, 803 u32 height 804) { 805 glGenFramebuffers(1, l_buffer); 806 glBindFramebuffer(GL_FRAMEBUFFER, *l_buffer); 807 808 // l_color_texture 809 { 810 u32 l_color_texture_name; 811 glGenTextures(1, &l_color_texture_name); 812 813 *l_color_texture = mats::init_texture( 814 MEMORY_PUSH(memory_pool, mats::Texture, "l_color_texture"), 815 GL_TEXTURE_2D, mats::TextureType::l_color, l_color_texture_name, 816 width, height, 4); 817 (*l_color_texture)->is_builtin = true; 818 819 glBindTexture(GL_TEXTURE_2D, (*l_color_texture)->texture_name); 820 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 821 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 822 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 823 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 824 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, 825 (*l_color_texture)->width, (*l_color_texture)->height, 826 0, GL_RGBA, GL_FLOAT, NULL); 827 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 828 (*l_color_texture)->texture_name, 0); 829 } 830 831 // l_bright_color_texture 832 { 833 u32 l_bright_color_texture_name; 834 glGenTextures(1, &l_bright_color_texture_name); 835 836 *l_bright_color_texture = mats::init_texture( 837 MEMORY_PUSH(memory_pool, mats::Texture, "l_bright_color_texture"), 838 GL_TEXTURE_2D, mats::TextureType::l_bright_color, l_bright_color_texture_name, 839 width, height, 4); 840 (*l_bright_color_texture)->is_builtin = true; 841 842 glBindTexture(GL_TEXTURE_2D, (*l_bright_color_texture)->texture_name); 843 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 844 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 845 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 846 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 847 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, 848 (*l_bright_color_texture)->width, 849 (*l_bright_color_texture)->height, 850 0, GL_RGBA, GL_FLOAT, NULL); 851 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, 852 (*l_bright_color_texture)->texture_name, 0); 853 } 854 855 // Attach textures 856 { 857 u32 attachments[2] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1}; 858 glDrawBuffers(2, attachments); 859 } 860 861 if (SETTINGS.fog_on) { 862 // l_depth_texture 863 // NOTE: Either this or the depth buffer should be enabled, not both 864 // NOTE: This does not work on macOS. The most likely reason is that in 865 // the render() function, we copy the depth framebuffer from the 866 // g_buffer to the "depth framebuffer" of the l_buffer (this one). Of 867 // course, the l_buffer does not have a depth framebuffer, but it has a 868 // depth texture. It looks like some machines are capable of doing the 869 // right thing, but we can't rely on being able to do this. The solution 870 // would probably be to use a depth texture for the g_buffer as well. 871 // That way, we know we can copy the depth from one to the other without 872 // issues. For the moment, we're not using fog, so this is just 873 // commented out. 874 u32 l_depth_texture_name; 875 glGenTextures(1, &l_depth_texture_name); 876 877 *l_depth_texture = mats::init_texture( 878 MEMORY_PUSH(memory_pool, mats::Texture, "l_depth_texture"), 879 GL_TEXTURE_2D, mats::TextureType::l_depth, l_depth_texture_name, 880 width, height, 1); 881 (*l_depth_texture)->is_builtin = true; 882 883 glBindTexture(GL_TEXTURE_2D, (*l_depth_texture)->texture_name); 884 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 885 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 886 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 887 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 888 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 889 (*l_depth_texture)->width, (*l_depth_texture)->height, 890 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); 891 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 892 (*l_depth_texture)->texture_name, 0); 893 } else { 894 // Depth buffer 895 // NOTE: Either this or the l_depth_texure should be enabled, not both 896 u32 rbo_depth; 897 glGenRenderbuffers(1, &rbo_depth); 898 glBindRenderbuffer(GL_RENDERBUFFER, rbo_depth); 899 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height); 900 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 901 rbo_depth); 902 } 903 904 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { 905 logs::fatal("Framebuffer not complete!"); 906 } 907} 908 909 910void 911renderer::init_blur_buffers( 912 memory::Pool *memory_pool, 913 u32 *blur1_buffer, 914 u32 *blur2_buffer, 915 mats::Texture **blur1_texture, 916 mats::Texture **blur2_texture, 917 u32 width, 918 u32 height 919) { 920 if (!SETTINGS.bloom_on) { 921 return; 922 } 923 glGenFramebuffers(1, blur1_buffer); 924 glBindFramebuffer(GL_FRAMEBUFFER, *blur1_buffer); 925 u32 blur1_texture_name; 926 glGenTextures(1, &blur1_texture_name); 927 928 *blur1_texture = mats::init_texture( 929 MEMORY_PUSH(memory_pool, mats::Texture, "blur1_texture"), 930 GL_TEXTURE_2D, mats::TextureType::blur1, blur1_texture_name, 931 width, height, 4); 932 (*blur1_texture)->is_builtin = true; 933 934 glBindTexture(GL_TEXTURE_2D, (*blur1_texture)->texture_name); 935 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 936 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 937 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 938 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 939 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, 940 (*blur1_texture)->width, (*blur1_texture)->height, 941 0, GL_RGBA, GL_FLOAT, NULL); 942 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 943 (*blur1_texture)->texture_name, 0); 944 945 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { 946 logs::fatal("Framebuffer not complete!"); 947 } 948 949 glGenFramebuffers(1, blur2_buffer); 950 glBindFramebuffer(GL_FRAMEBUFFER, *blur2_buffer); 951 u32 blur2_texture_name; 952 glGenTextures(1, &blur2_texture_name); 953 954 *blur2_texture = mats::init_texture( 955 MEMORY_PUSH(memory_pool, mats::Texture, "blur2_texture"), 956 GL_TEXTURE_2D, mats::TextureType::blur2, blur2_texture_name, 957 width, height, 4); 958 (*blur2_texture)->is_builtin = true; 959 960 glBindTexture(GL_TEXTURE_2D, (*blur2_texture)->texture_name); 961 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 962 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 963 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 964 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 965 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, 966 (*blur2_texture)->width, (*blur2_texture)->height, 967 0, GL_RGBA, GL_FLOAT, NULL); 968 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 969 (*blur2_texture)->texture_name, 0); 970 971 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { 972 logs::fatal("Framebuffer not complete!"); 973 } 974} 975 976 977void 978renderer::init_ubo(u32 *ubo_shader_common) 979{ 980 glGenBuffers(1, ubo_shader_common); 981 glBindBuffer(GL_UNIFORM_BUFFER, *ubo_shader_common); 982 glBufferData(GL_UNIFORM_BUFFER, sizeof(ShaderCommon), NULL, GL_STATIC_DRAW); 983 glBindBuffer(GL_UNIFORM_BUFFER, 0); 984 glBindBufferRange(GL_UNIFORM_BUFFER, 0, *ubo_shader_common, 0, sizeof(ShaderCommon)); 985} 986 987 988void 989renderer::init_3d_shadowmaps( 990 memory::Pool *memory_pool, 991 u32 *shadowmaps_3d_framebuffer, 992 u32 *shadowmaps_3d, 993 mats::Texture **shadowmaps_3d_texture, 994 u32 shadowmap_3d_width, 995 u32 shadowmap_3d_height 996) { 997 glGenFramebuffers(1, shadowmaps_3d_framebuffer); 998 glGenTextures(1, shadowmaps_3d); 999 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, *shadowmaps_3d); 1000 1001 glTexStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 1, GL_DEPTH_COMPONENT32F, 1002 shadowmap_3d_width, shadowmap_3d_height, 1003 6 * MAX_N_LIGHTS); 1004 1005 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1006 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1007 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 1008 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 1009 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); 1010 glBindFramebuffer(GL_FRAMEBUFFER, *shadowmaps_3d_framebuffer); 1011 glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, *shadowmaps_3d, 0); 1012 1013 // #slow 1014 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { 1015 logs::fatal("Framebuffer not complete!"); 1016 } 1017 1018 *shadowmaps_3d_texture = mats::init_texture( 1019 MEMORY_PUSH(memory_pool, mats::Texture, "shadowmaps_3d_texture"), 1020 GL_TEXTURE_CUBE_MAP_ARRAY, 1021 mats::TextureType::shadowmaps_3d, *shadowmaps_3d, 1022 shadowmap_3d_width, shadowmap_3d_height, 1); 1023 (*shadowmaps_3d_texture)->is_builtin = true; 1024} 1025 1026 1027void 1028renderer::init_2d_shadowmaps( 1029 memory::Pool *memory_pool, 1030 u32 *shadowmaps_2d_framebuffer, 1031 u32 *shadowmaps_2d, 1032 mats::Texture **shadowmaps_2d_texture, 1033 u32 shadowmap_2d_width, 1034 u32 shadowmap_2d_height 1035) { 1036 glGenFramebuffers(1, shadowmaps_2d_framebuffer); 1037 glGenTextures(1, shadowmaps_2d); 1038 glBindTexture(GL_TEXTURE_2D_ARRAY, *shadowmaps_2d); 1039 1040 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_DEPTH_COMPONENT32F, 1041 shadowmap_2d_width, shadowmap_2d_height, MAX_N_LIGHTS); 1042 1043 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1044 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1045 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); 1046 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); 1047 f32 border_color[] = { 1.0f, 1.0f, 1.0f, 1.0f }; 1048 glTexParameterfv(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BORDER_COLOR, border_color); 1049 glBindFramebuffer(GL_FRAMEBUFFER, *shadowmaps_2d_framebuffer); 1050 glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, *shadowmaps_2d, 0); 1051 1052 // #slow 1053 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { 1054 logs::fatal("Framebuffer not complete!"); 1055 } 1056 1057 *shadowmaps_2d_texture = mats::init_texture( 1058 MEMORY_PUSH(memory_pool, mats::Texture, "shadowmaps_2d_texture"), 1059 GL_TEXTURE_2D_ARRAY, 1060 mats::TextureType::shadowmaps_2d, *shadowmaps_2d, 1061 shadowmap_2d_width, 1062 shadowmap_2d_height, 1); 1063 (*shadowmaps_2d_texture)->is_builtin = true; 1064} 1065 1066 1067void 1068renderer::init_gui(memory::Pool *memory_pool) 1069{ 1070 memory::Pool temp_memory_pool = {}; 1071 1072 // VAO 1073 { 1074 glGenVertexArrays(1, &renderer::state->gui_vao); 1075 glGenBuffers(1, &renderer::state->gui_vbo); 1076 glBindVertexArray(renderer::state->gui_vao); 1077 glBindBuffer(GL_ARRAY_BUFFER, renderer::state->gui_vbo); 1078 glBufferData(GL_ARRAY_BUFFER, GUI_VERTEX_SIZE * GUI_MAX_N_VERTICES, NULL, GL_DYNAMIC_DRAW); 1079 u32 location; 1080 1081 // position (vec2) 1082 location = 0; 1083 glEnableVertexAttribArray(location); 1084 glVertexAttribPointer(location, 2, GL_FLOAT, GL_FALSE, GUI_VERTEX_SIZE, 1085 (void*)(0)); 1086 1087 // tex_coords (vec2) 1088 location = 1; 1089 glEnableVertexAttribArray(location); 1090 glVertexAttribPointer(location, 2, GL_FLOAT, GL_FALSE, GUI_VERTEX_SIZE, 1091 (void*)(2 * sizeof(f32))); 1092 1093 // color (vec4) 1094 location = 2; 1095 glEnableVertexAttribArray(location); 1096 glVertexAttribPointer(location, 4, GL_FLOAT, GL_FALSE, GUI_VERTEX_SIZE, 1097 (void*)(4 * sizeof(f32))); 1098 } 1099 1100 // Shaders 1101 shaders::init_shader_asset(&renderer::state->gui_shader_asset, &temp_memory_pool, 1102 "gui_generic", shaders::Type::standard, "gui_generic.vert", "gui_generic.frag", ""); 1103 1104 // Materials 1105 mats::init_texture_atlas(&renderer::state->gui_texture_atlas, iv2(2000, 2000)); 1106 1107 // Fonts 1108 { 1109 renderer::state->gui_font_assets = Array<fonts::FontAsset>(memory_pool, 8, "gui_font_assets"); 1110 FT_Library ft_library; 1111 if (FT_Init_FreeType(&ft_library)) { 1112 logs::error("Could not init FreeType"); 1113 return; 1114 } 1115 fonts::init_font_asset(renderer::state->gui_font_assets.push(), 1116 memory_pool, &renderer::state->gui_texture_atlas, 1117 &ft_library, "body", gui::MAIN_FONT_REGULAR, 18); 1118 fonts::init_font_asset(renderer::state->gui_font_assets.push(), 1119 memory_pool, &renderer::state->gui_texture_atlas, 1120 &ft_library, "body-bold", gui::MAIN_FONT_BOLD, 18); 1121 fonts::init_font_asset(renderer::state->gui_font_assets.push(), 1122 memory_pool, &renderer::state->gui_texture_atlas, 1123 &ft_library, "heading", gui::MAIN_FONT_REGULAR, 42); 1124 fonts::init_font_asset(renderer::state->gui_font_assets.push(), 1125 memory_pool, &renderer::state->gui_texture_atlas, 1126 &ft_library, "title", gui::MAIN_FONT_REGULAR, 64); 1127 FT_Done_FreeType(ft_library); 1128 } 1129 1130 memory::destroy_memory_pool(&temp_memory_pool); 1131} 1132 1133 1134void 1135renderer::copy_scene_data_to_ubo( 1136 u32 current_shadow_light_idx, 1137 u32 current_shadow_light_type, 1138 bool is_blur_horizontal 1139) { 1140 WindowSize *window_size = core::get_window_size(); 1141 ShaderCommon *shader_common = &renderer::state->shader_common; 1142 cameras::Camera *camera = cameras::get_main(); 1143 1144 shader_common->view = camera->view; 1145 shader_common->projection = camera->projection; 1146 shader_common->ui_projection = camera->ui_projection; 1147 memcpy(shader_common->shadowmap_3d_transforms, 1148 renderer::state->shadowmap_3d_transforms, 1149 sizeof(renderer::state->shadowmap_3d_transforms)); 1150 memcpy(shader_common->shadowmap_2d_transforms, 1151 renderer::state->shadowmap_2d_transforms, 1152 sizeof(renderer::state->shadowmap_2d_transforms)); 1153 1154 shader_common->camera_position = v4(camera->position, 1.0f); 1155 shader_common->camera_pitch = (float)camera->pitch; 1156 1157 shader_common->camera_horizontal_fov = camera->horizontal_fov; 1158 shader_common->camera_vertical_fov = camera->vertical_fov; 1159 shader_common->camera_near_clip_dist = camera->near_clip_dist; 1160 shader_common->camera_far_clip_dist = camera->far_clip_dist; 1161 1162 shader_common->current_shadow_light_idx = current_shadow_light_idx; 1163 shader_common->current_shadow_light_type = current_shadow_light_type; 1164 1165 shader_common->shadow_far_clip_dist = 1166 renderer::state->builtin_textures.shadowmap_far_clip_dist; 1167 shader_common->is_blur_horizontal = is_blur_horizontal; 1168 shader_common->renderdebug_displayed_texture_type = 1169 renderer::state->renderdebug_displayed_texture_type; 1170 shader_common->unused_pad = 0; 1171 1172 shader_common->exposure = camera->exposure; 1173 shader_common->t = (float)(engine::get_t()); 1174 shader_common->window_width = window_size->width; 1175 shader_common->window_height = window_size->height; 1176 1177 u32 n_point_lights = 0; 1178 u32 n_directional_lights = 0; 1179 1180 each (light_component, *lights::get_components()) { 1181 if (light_component->entity_handle == entities::NO_ENTITY_HANDLE) { 1182 continue; 1183 } 1184 1185 spatial::Component *spatial_component = 1186 spatial::get_component(light_component->entity_handle); 1187 1188 if (!( 1189 lights::is_light_component_valid(light_component) && 1190 spatial::is_spatial_component_valid(spatial_component) 1191 )) { 1192 continue; 1193 } 1194 1195 if (light_component->type == lights::LightType::point) { 1196 shader_common->point_light_position[n_point_lights] = v4( 1197 spatial_component->position, 1.0f 1198 ); 1199 shader_common->point_light_color[n_point_lights] = 1200 light_component->color; 1201 shader_common->point_light_attenuation[n_point_lights] = 1202 light_component->attenuation; 1203 n_point_lights++; 1204 } else if (light_component->type == lights::LightType::directional) { 1205 shader_common->directional_light_position[n_directional_lights] = 1206 v4(spatial_component->position, 1.0f); 1207 shader_common->directional_light_direction[n_directional_lights] = 1208 v4(light_component->direction, 1.0f); 1209 shader_common->directional_light_color[n_directional_lights] = 1210 light_component->color; 1211 shader_common->directional_light_attenuation[n_directional_lights] = 1212 light_component->attenuation; 1213 n_directional_lights++; 1214 } 1215 } 1216 1217 shader_common->n_point_lights = n_point_lights; 1218 shader_common->n_directional_lights = n_directional_lights; 1219 1220 glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(ShaderCommon), shader_common); 1221} 1222 1223 1224void 1225renderer::draw( 1226 drawable::Mode render_mode, 1227 drawable::Component *drawable_component, 1228 mats::Material *material, 1229 m4 *model_matrix, 1230 m3 *model_normal_matrix, 1231 m4 *bone_matrices, 1232 shaders::Asset *standard_depth_shader_asset 1233) { 1234 shaders::Asset *shader_asset = nullptr; 1235 1236 if (render_mode == drawable::Mode::regular) { 1237 shader_asset = &material->shader_asset; 1238 } else if (render_mode == drawable::Mode::depth) { 1239 if (shaders::is_shader_asset_valid(&material->depth_shader_asset)) { 1240 shader_asset = &material->depth_shader_asset; 1241 } else { 1242 shader_asset = standard_depth_shader_asset; 1243 } 1244 } 1245 1246 assert(shader_asset); 1247 1248 // If our shader program has changed since our last mesh, tell OpenGL about it. 1249 if (shader_asset->program != drawable::get_last_drawn_shader_program()) { 1250 glUseProgram(shader_asset->program); 1251 drawable::set_last_drawn_shader_program(shader_asset->program); 1252 1253 if (render_mode == drawable::Mode::regular) { 1254 for ( 1255 u32 texture_idx = 1; 1256 texture_idx < shader_asset->n_texture_units + 1; texture_idx++ 1257 ) { 1258 if (shader_asset->texture_units[texture_idx] != 0) { 1259 glActiveTexture(GL_TEXTURE0 + texture_idx); 1260 glBindTexture(shader_asset->texture_unit_types[texture_idx], 1261 shader_asset->texture_units[texture_idx]); 1262 } 1263 } 1264 } 1265 } 1266 1267 for ( 1268 u32 uniform_idx = 0; 1269 uniform_idx < shader_asset->n_intrinsic_uniforms; 1270 uniform_idx++ 1271 ) { 1272 const char *uniform_name = shader_asset->intrinsic_uniform_names[uniform_idx]; 1273 if (pstr_eq(uniform_name, "model_matrix")) { 1274 shaders::set_mat4(shader_asset, "model_matrix", model_matrix); 1275 } else if (pstr_eq(uniform_name, "model_normal_matrix")) { 1276 shaders::set_mat3(shader_asset, "model_normal_matrix", model_normal_matrix); 1277 } else if (bone_matrices && pstr_eq(uniform_name, "bone_matrices[0]")) { 1278 shaders::set_mat4_multiple(shader_asset, MAX_N_BONES, 1279 "bone_matrices[0]", bone_matrices); 1280 } 1281 } 1282 1283 geom::Mesh *mesh = &drawable_component->mesh; 1284 glBindVertexArray(mesh->vao); 1285 if (mesh->n_indices > 0) { 1286 glDrawElements(mesh->mode, mesh->n_indices, GL_UNSIGNED_INT, 0); 1287 } else { 1288 glDrawArrays(mesh->mode, 0, mesh->n_vertices); 1289 } 1290} 1291 1292 1293void 1294renderer::draw_all( 1295 drawable::Pass render_pass, 1296 drawable::Mode render_mode, 1297 shaders::Asset *standard_depth_shader_asset 1298) { 1299 spatial::ModelMatrixCache cache = { m4(1.0f), nullptr }; 1300 1301 each (drawable_component, *drawable::get_components()) { 1302 if (!drawable::is_component_valid(drawable_component)) { 1303 continue; 1304 } 1305 1306 if (!((u32)render_pass & (u32)drawable_component->target_render_pass)) { 1307 continue; 1308 } 1309 1310#if 0 1311 logs::info("Drawing %s", 1312 engine::get_entity(drawable_component->entity_handle)->debug_name); 1313#endif 1314 1315 mats::Material *material = mats::get_material_by_name( 1316 drawable_component->mesh.material_name); 1317 1318 if (!material || material->state != mats::MaterialState::complete) { 1319 material = mats::get_material_by_name("unknown"); 1320 } 1321 1322 spatial::Component *spatial_component = spatial::get_component(drawable_component->entity_handle); 1323 1324 m4 model_matrix = m4(1.0f); 1325 m3 model_normal_matrix = m3(1.0f); 1326 m4 *bone_matrices = nullptr; 1327 1328 if (spatial::is_spatial_component_valid(spatial_component)) { 1329 // We only need to calculate the normal matrix if we have non-uniform 1330 // scaling. 1331 model_matrix = spatial::make_model_matrix(spatial_component, &cache); 1332 1333 // TODO: Even though we have a uniform scaling in the transformation for 1334 // our spatial component itself, when accumulating it with the parent 1335 // spatial components, we might (possibly) get non-uniform scaling, 1336 // in which case we want to calculate the model normal matrix! 1337 // Oops! We should be looking at the model_matrix and not at 1338 // spatial_component->scale. 1339 if ( 1340 spatial_component->scale.x == spatial_component->scale.y && 1341 spatial_component->scale.y == spatial_component->scale.z 1342 ) { 1343 model_normal_matrix = m3(model_matrix); 1344 } else { 1345 model_normal_matrix = m3(transpose(inverse(model_matrix))); 1346 } 1347 1348 // Animations 1349 anim::Component *animation_component = anim::find_animation_component( 1350 spatial_component); 1351 if (animation_component) { 1352 bone_matrices = animation_component->bone_matrices; 1353 } 1354 } 1355 1356 draw(render_mode, drawable_component, material, 1357 &model_matrix, &model_normal_matrix, bone_matrices, standard_depth_shader_asset); 1358 } 1359} 1360 1361 1362void 1363renderer::render_scene(drawable::Pass render_pass, drawable::Mode render_mode) 1364{ 1365#if 0 1366 logs::info("drawable::Pass: %s", render_pass_to_string(render_pass)); 1367#endif 1368 draw_all(render_pass, render_mode, 1369 &renderer::state->standard_depth_shader_asset); 1370}