Shkyera Engine
Easy to use, game engine for Python
Loading...
Searching...
No Matches
RenderingSystem.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <chrono>
4#include <memory>
5#include <random>
6
10#include <Common/Assert.hpp>
11#include <Common/Logger.hpp>
12#include <Common/Profiler.hpp>
13#include <Common/Random.hpp>
14#include <Common/Types.hpp>
31#include <ECS/Registry.hpp>
33#include <Math/AABB.hpp>
37#include <Rendering/Utils.hpp>
38#include <Utils/AssetUtils.hpp>
40
41#include <type_traits>
43
44namespace shkyera {
45
46template <typename MainCameraTag>
48 public:
49 RenderingSystem(std::shared_ptr<Registry> registry);
50 std::optional<GLuint> update();
51
53
54 private:
55 void clearFrameBuffers();
57
58 // Supporting Textures
59 void renderViewPosition();
60 void renderViewNormals();
61 void renderSSAO(float strength, float radius);
65
66 // Main Rendering
67 void renderWorldObjects();
68 void renderParticles();
69 void renderBillboards();
72 void renderWireframes();
74 void renderOutline(const std::set<Entity>& entities);
75 void renderSkybox();
77
78 // Post-Processing
79 void bloom(float threshold, float weight);
80 void toneMapping();
81 void gammaCorrection(float gamma);
82 void antiAliasing();
83
84 // Helper methods
85 void setMaterial(Material const* material);
86 void setTexture(Material const* material, const std::string& textureName, auto textureMember);
89
90 // Data
91 std::shared_ptr<Registry> _registry;
92
93 // Rendering Pipeline
95
96 // Main Rendering
100
101 // Anti-Aliasing
104
105 // Screen-Space Ambient Occlusion
112 std::vector<glm::vec3> _ssaoKernel;
114
115 // Tone Mapping
118
119 // Gamma Correction
122
123 // Bloom
124 inline static constexpr size_t BloomSteps = 4;
125 std::array<SceneFrameBuffer, BloomSteps> _downscaledFrameBuffers;
126 std::array<SceneFrameBuffer, BloomSteps> _horizontallyBluredDownscaledFrameBuffers;
127 std::array<SceneFrameBuffer, BloomSteps> _fullyBluredDownscaledFrameBuffers;
133
134 // Rendering Object Outline
144
145 // Skybox Rendering
148
149 // Light rendering
150 std::unordered_map<Entity, DepthAtlasFrameBuffer> _directionalLightToShadowMap;
152
153 std::unordered_map<Entity, DepthAtlasFrameBuffer> _pointLightToShadowMap;
155
156 std::unordered_map<Entity, DepthAtlasFrameBuffer> _spotLightToShadowMap;
157
158 // Debug Rendering
160
168};
169
170template <typename MainCameraTag>
173 registry,
179 _registry(registry) {
181 utils::assets::readPermanent<Shader>("resources/shaders/vertex/position_and_normal.glsl", Shader::Type::Vertex);
182 const auto& modelFragmentShader =
183 utils::assets::readPermanent<Shader>("resources/shaders/fragment/uber.glsl", Shader::Type::Fragment);
187
188 const auto& distanceVertexShader =
189 utils::assets::readPermanent<Shader>("resources/shaders/vertex/distance.glsl", Shader::Type::Vertex);
190 const auto& distanceFragmentShader =
191 utils::assets::readPermanent<Shader>("resources/shaders/fragment/distance.glsl", Shader::Type::Fragment);
195
196 const auto& viewSpaceNormalVertexShader =
197 utils::assets::readPermanent<Shader>("resources/shaders/vertex/viewspace_normal.glsl", Shader::Type::Vertex);
199 utils::assets::readPermanent<Shader>("resources/shaders/fragment/viewspace_normal.glsl", Shader::Type::Fragment);
203
204 const auto& viewSpaceDepthVertexShader =
205 utils::assets::readPermanent<Shader>("resources/shaders/vertex/viewspace_position.glsl", Shader::Type::Vertex);
206 const auto& viewSpaceDepthFragmentShader = utils::assets::readPermanent<Shader>(
207 "resources/shaders/fragment/viewspace_position.glsl", Shader::Type::Fragment);
211
212 const auto& texCoordsVertexShader =
213 utils::assets::readPermanent<Shader>("resources/shaders/vertex/texcoords.glsl", Shader::Type::Vertex);
214 const auto& ssaoFragmentShader =
215 utils::assets::readPermanent<Shader>("resources/shaders/fragment/ssao.glsl", Shader::Type::Fragment);
219
220 const auto& toneMappingFragmentShader =
221 utils::assets::readPermanent<Shader>("resources/shaders/fragment/tonemapping_aces.glsl", Shader::Type::Fragment);
225
227 utils::assets::readPermanent<Shader>("resources/shaders/fragment/gamma_correction.glsl", Shader::Type::Fragment);
231
232 const auto& luminosityThresholdFragmentShader = utils::assets::readPermanent<Shader>(
233 "resources/shaders/fragment/luminosity_threshold.glsl", Shader::Type::Fragment);
237
238 const auto& horizontalGaussianBlur5FragmentShader = utils::assets::readPermanent<Shader>(
239 "resources/shaders/fragment/horizontal_gaussianblur_5.glsl", Shader::Type::Fragment);
243
244 const auto& verticalGaussianBlur5FragmentShader = utils::assets::readPermanent<Shader>(
245 "resources/shaders/fragment/vertical_gaussianblur_5.glsl", Shader::Type::Fragment);
249
251 utils::assets::readPermanent<Shader>("resources/shaders/fragment/weighted_addition.glsl", Shader::Type::Fragment);
255
256 const auto& positionVertexShader =
257 utils::assets::readPermanent<Shader>("resources/shaders/vertex/position.glsl", Shader::Type::Vertex);
258 const auto& fixedColorFragmentShader =
259 utils::assets::readPermanent<Shader>("resources/shaders/fragment/color.glsl", Shader::Type::Fragment);
263
267
268 const auto& dilateFragmentShader =
269 utils::assets::readPermanent<Shader>("resources/shaders/fragment/dilate.glsl", Shader::Type::Fragment);
273
274 const auto& subtractFragmentShader =
275 utils::assets::readPermanent<Shader>("resources/shaders/fragment/subtract.glsl", Shader::Type::Fragment);
279
280 const auto& overlayFragmentShader =
281 utils::assets::readPermanent<Shader>("resources/shaders/fragment/overlay.glsl", Shader::Type::Fragment);
285
286 const auto& fxaaFragmentShader =
287 utils::assets::readPermanent<Shader>("resources/shaders/fragment/fxaa.glsl", Shader::Type::Fragment);
291
292 const auto& skyboxVertexShader =
293 utils::assets::readPermanent<Shader>("resources/shaders/vertex/skybox.glsl", Shader::Type::Vertex);
294 const auto& cubeMapFragmentShader =
295 utils::assets::readPermanent<Shader>("resources/shaders/fragment/cubemap.glsl", Shader::Type::Fragment);
299
300 const auto& depthVertexShader =
301 utils::assets::readPermanent<Shader>("resources/shaders/vertex/depth.glsl", Shader::Type::Vertex);
302 const auto& depthFragmentShader =
303 utils::assets::readPermanent<Shader>("resources/shaders/fragment/depth.glsl", Shader::Type::Fragment);
307
308 _defaultMaterial.lit = false;
309 _defaultMaterial.albedo = glm::vec3{1, 0, 1};
310
312 debugBillboardMaterial.lit = false;
316
317 std::get<AssetRef<Texture>>(_pointLightDebugMaterial.albedoTexture) =
318 utils::assets::readPermanent<Texture>("resources/icons/components/point_light.png");
319 std::get<AssetRef<Texture>>(_spotLightDebugMaterial.albedoTexture) =
320 utils::assets::readPermanent<Texture>("resources/icons/components/spot_light.png");
321 std::get<AssetRef<Texture>>(_directionalLightDebugMaterial.albedoTexture) =
322 utils::assets::readPermanent<Texture>("resources/icons/components/directional_light.png");
323 std::get<AssetRef<Texture>>(_ambientLightDebugMaterial.albedoTexture) =
324 utils::assets::readPermanent<Texture>("resources/icons/components/ambient_light.png");
325 std::get<AssetRef<Texture>>(_particleEmitterDebugMaterial.albedoTexture) =
326 utils::assets::readPermanent<Texture>("resources/icons/components/particles_gray.png");
327 std::get<AssetRef<Texture>>(_postProcessingVolumeDebugMaterial.albedoTexture) =
328 utils::assets::readPermanent<Texture>("resources/icons/components/post_processing_gray.png");
329 std::get<AssetRef<Texture>>(_audioSourceDebugMaterial.albedoTexture) =
330 utils::assets::readPermanent<Texture>("resources/icons/components/audio_source_gray.png");
331}
332
333template <typename MainCameraTag>
335 SHKYERA_PROFILE("RenderingSystem<MainCameraTag>::setSize");
336
337 if (const auto cameraOpt = _registry->getEntity<MainCameraTag>()) {
338 const auto aspectRatio = static_cast<float>(width) / height;
339 RegistryViewer::write<CameraComponent>(*cameraOpt).aspectRatio = aspectRatio;
340 }
341
342 _litModelsFrameBuffer.setSize(width, height);
343 _silhouetteFrameBuffer.setSize(width, height);
344 _horizontallyDilatedFrameBuffer.setSize(width, height);
345 _fullyDilatedFrameBuffer.setSize(width, height);
346 _toneMappedFrameBuffer.setSize(width, height);
347 _gammaCorrectedFrameBuffer.setSize(width, height);
348 _differenceFrameBuffer.setSize(width, height);
349 _bloomedFrameBuffer.setSize(width, height);
350 _antiAliasedFrameBuffer.setSize(width, height);
351 _outlinedObjectsFrameBuffer.setSize(width, height);
352 _viewSpaceNormalFrameBuffer.setSize(width, height);
353 _viewSpacePositionFrameBuffer.setSize(width, height);
354 _ssaoFrameBuffer.setSize(width, height);
355
356 size_t downscaleFactor = 2;
357 for (size_t i = 0; i < BloomSteps; ++i) {
358 _downscaledFrameBuffers[i].setSize(width / downscaleFactor, height / downscaleFactor);
359 _horizontallyBluredDownscaledFrameBuffers[i].setSize(width / downscaleFactor, height / downscaleFactor);
360 _fullyBluredDownscaledFrameBuffers[i].setSize(width / downscaleFactor, height / downscaleFactor);
361 downscaleFactor *= 1.5;
362 }
363}
364
365template <typename MainCameraTag>
367 return _mostRecentFrameBufferPtr->getTexture().getID();
368}
369
370template <typename MainCameraTag>
372 SHKYERA_PROFILE("RenderingSystem<MainCameraTag>::clearFrameBuffers");
373
374 _litModelsFrameBuffer.clear();
375 _bloomedFrameBuffer.clear();
376 _antiAliasedFrameBuffer.clear();
377 _outlinedObjectsFrameBuffer.clear();
378 _silhouetteFrameBuffer.clear();
379 _horizontallyDilatedFrameBuffer.clear();
380 _fullyDilatedFrameBuffer.clear();
381 _differenceFrameBuffer.clear();
382 _toneMappedFrameBuffer.clear();
383 _gammaCorrectedFrameBuffer.clear();
384 _viewSpaceNormalFrameBuffer.clear();
385 _viewSpacePositionFrameBuffer.clear();
386 _ssaoFrameBuffer.clear(glm::vec3{1.0, 1.0, 1.0});
387
388 for (auto& buffer : _downscaledFrameBuffers) {
389 buffer.clear();
390 }
391 for (auto& buffer : _horizontallyBluredDownscaledFrameBuffers) {
392 buffer.clear();
393 }
394 for (auto& buffer : _fullyBluredDownscaledFrameBuffers) {
395 buffer.clear();
396 }
397}
398
399template <typename MainCameraTag>
401 auto* mainCameraComponent = RegistryViewer::write<MainCameraTag>();
402
403 if (!mainCameraComponent) {
404 Logger::ERROR("There is no Camera with registered type. Cannot render anything");
405 return std::nullopt;
406 }
407
408 setSize(mainCameraComponent->renderWidth, mainCameraComponent->renderHeight);
409
410 constexpr auto DrawDebugInfo = std::is_same_v<MainCameraTag, SceneCamera>;
411
412 _textureIndex = 0;
413 SHKYERA_PROFILE("RenderingSystem<MainCameraTag>::render");
414
415 _mostRecentFrameBufferPtr = &_litModelsFrameBuffer;
416 const auto postProcessing = getPostProcessingSettings();
417
418 // Rendering Preparation
419 clearFrameBuffers();
420
421 // Rendering Supporting Textures
422 renderViewPosition();
423 renderViewNormals();
424 renderSSAO(postProcessing.ssaoStrength, postProcessing.ssaoRadius);
425 renderDirectionalLightShadowMaps();
426 renderPointLightShadowMaps();
427 renderSpotLightShadowMaps();
428
429 // Main Rendering Pass
430 renderSkybox();
431 renderWorldObjects();
432 renderParticles();
433 renderBillboards();
434 renderWireframes();
435
436 // Post-Processing
437 if (postProcessing.bloomWeight > 0.0f)
438 bloom(postProcessing.bloomThreshold, postProcessing.bloomWeight);
439 if (postProcessing.toneMapping)
440 toneMapping();
441 if (postProcessing.gamma != 1.0f)
442 gammaCorrection(postProcessing.gamma);
443 if (postProcessing.antiAliasing)
444 antiAliasing();
445
446 if constexpr (DrawDebugInfo) {
447 renderPostProcessingVolumes();
448 renderOutlineOfSelectedEntities();
449 renderDebugBillboards();
450 renderOverlayModels();
451 }
452
453 mainCameraComponent->renderedTextureId = _mostRecentFrameBufferPtr->getTexture().getID();
454
455 return mainCameraComponent->renderedTextureId;
456}
457
458template <typename MainCameraTag>
460 SHKYERA_PROFILE("RenderingSystem<MainCameraTag>::renderViewPosition");
461
462 _viewSpacePositionShaderProgram.use();
463 _viewSpacePositionFrameBuffer.bind();
464
465 const auto& cameraTransform = RegistryViewer::read<TransformComponent>(*_registry->getEntity<MainCameraTag>());
466 const auto& cameraComponent = RegistryViewer::read<CameraComponent>(*_registry->getEntity<MainCameraTag>());
467
468 const glm::mat4& viewMatrix =
469 RegistryViewer::read<CameraComponent>(*_registry->getEntity<MainCameraTag>()).getViewMatrix(cameraTransform);
470 const glm::mat4& projectionMatrix =
471 RegistryViewer::read<CameraComponent>(*_registry->getEntity<MainCameraTag>()).getProjectionMatrix();
472
473 _viewSpacePositionShaderProgram.setUniform("projection", projectionMatrix);
474 _viewSpacePositionShaderProgram.setUniform("view", viewMatrix);
475
476 for (const auto& [entity, modelComponent] : RegistryViewer::readAll<ModelComponent>()) {
478 _viewSpacePositionShaderProgram.setUniform("model", transformMatrix);
479
480 modelComponent.updateImpl();
481 }
482
483 _viewSpacePositionFrameBuffer.unbind();
484 _viewSpacePositionShaderProgram.stopUsing();
485}
486
487template <typename MainCameraTag>
489 SHKYERA_PROFILE("RenderingSystem<MainCameraTag>::renderViewNormals");
490
491 _viewSpaceNormalShaderProgram.use();
492 _viewSpaceNormalFrameBuffer.bind();
493
494 const auto& cameraTransform = RegistryViewer::read<TransformComponent>(*_registry->getEntity<MainCameraTag>());
495 const auto& cameraComponent = RegistryViewer::read<CameraComponent>(*_registry->getEntity<MainCameraTag>());
496
497 const glm::mat4& viewMatrix =
498 RegistryViewer::read<CameraComponent>(*_registry->getEntity<MainCameraTag>()).getViewMatrix(cameraTransform);
499 const glm::mat4& projectionMatrix =
500 RegistryViewer::read<CameraComponent>(*_registry->getEntity<MainCameraTag>()).getProjectionMatrix();
501
502 _viewSpaceNormalShaderProgram.setUniform("projection", projectionMatrix);
503 _viewSpaceNormalShaderProgram.setUniform("view", viewMatrix);
504
505 for (const auto& [entity, modelComponent] : RegistryViewer::readAll<ModelComponent>()) {
507 _viewSpaceNormalShaderProgram.setUniform("model", transformMatrix);
508
509 modelComponent.updateImpl();
510 }
511
512 _viewSpaceNormalFrameBuffer.unbind();
513 _viewSpaceNormalShaderProgram.stopUsing();
514}
515
516template <typename MainCameraTag>
518 SHKYERA_PROFILE("RenderingSystem<MainCameraTag>::renderSSAO");
519
520 constexpr int SSAOSamples = 32;
521
522 bool updatedKernel = false;
523 if (_ssaoKernel.empty() || radius != _usedSsaoRadius) {
524 updatedKernel = true;
525 _usedSsaoRadius = radius;
526
527 _ssaoKernel.resize(SSAOSamples);
529 for (int i = 0; i < SSAOSamples; ++i) {
530 glm::vec3 sample(sampler() * 2.0 - 1.0, sampler() * 2.0 - 1.0, sampler() * 0.95 + 0.05);
531 sample = glm::normalize(sample);
532
533 float scale = (float)i / SSAOSamples;
534 scale = glm::mix(0.05f, _usedSsaoRadius, scale * scale);
535 sample *= scale;
536
537 _ssaoKernel[i] = sample;
538 }
539 }
540
541 const glm::mat4& projectionMatrix =
542 RegistryViewer::read<CameraComponent>(*_registry->getEntity<MainCameraTag>()).getProjectionMatrix();
543
544 UseShader ssaoShaderUsage(_ssaoShaderProgram);
545
546 _ssaoShaderProgram.setUniform("strength", strength);
547
548 _viewSpacePositionFrameBuffer.getTexture().activate(GL_TEXTURE0);
549 _ssaoShaderProgram.setUniform("depthTexture", 0);
550 _viewSpaceNormalFrameBuffer.getTexture().activate(GL_TEXTURE1);
551 _ssaoShaderProgram.setUniform("normalTexture", 1);
552
553 if (updatedKernel) {
554 for (int i = 0; i < SSAOSamples; i++) {
555 _ssaoShaderProgram.setUniform("samples[" + std::to_string(i) + "]", _ssaoKernel[i]);
556 }
557 }
558
559 // Set uniforms using the parameter pack
560 _ssaoShaderProgram.setUniform("projection", projectionMatrix);
561
562 // Draw fullscreen quad
563 _ssaoFrameBuffer.bind();
565 _ssaoFrameBuffer.unbind();
566}
567
568template <typename MainCameraTag>
570 std::set<Entity> selectedEntities;
571 for (const auto& [entity, _] : RegistryViewer::readAll<SelectedEntityComponent>()) {
572 selectedEntities.insert(entity);
573 }
574}
575
576template <typename MainCameraTag>
578 if (std::none_of(entities.begin(), entities.end(),
579 [this](auto e) { return _registry->hasComponent<NameComponent>(e); })) {
580 return;
581 }
582
583 SHKYERA_PROFILE("RenderingSystem<MainCameraTag>::renderOutline");
584
585 for (const auto& entity : entities) {
586 const auto& children = _registry->getHierarchy().getChildren(entity);
587 renderOutline(children);
588 }
589
591
592 // Drawing a silhouette
593 _silhouetteFrameBuffer.bind();
594 const auto& cameraTransform = RegistryViewer::read<TransformComponent>(*_registry->getEntity<MainCameraTag>());
595 const glm::mat4& viewMatrix =
596 RegistryViewer::read<CameraComponent>(*_registry->getEntity<MainCameraTag>()).getViewMatrix(cameraTransform);
597 const glm::mat4& projectionMatrix =
598 RegistryViewer::read<CameraComponent>(*_registry->getEntity<MainCameraTag>()).getProjectionMatrix();
600
601 _silhouetteShaderProgram.use();
602 _silhouetteShaderProgram.setUniform("fixedColor", glm::vec3{1.0, 0.1, 1.0});
603 for (const auto& entity : entities) {
604 if (_registry->hasComponents<TransformComponent, ModelComponent>(entity)) {
605 const auto& modelComponent = RegistryViewer::read<ModelComponent>(entity);
607 _silhouetteShaderProgram.setUniform("projectionViewModelMatrix", projectionViewMatrix * transformMatrix);
608 modelComponent.updateImpl();
609 }
610 }
611 _silhouetteShaderProgram.stopUsing();
612 _silhouetteFrameBuffer.unbind();
613
614 utils::applyShaderToFrameBuffer(_horizontallyDilatedFrameBuffer, _dilateShaderProgram,
615 {{"silhouetteTexture", &_silhouetteFrameBuffer.getTexture()}},
616 utils::Uniform("horizontal", true), utils::Uniform("kernelSize", 3));
617
618 utils::applyShaderToFrameBuffer(_fullyDilatedFrameBuffer, _dilateShaderProgram,
619 {{"silhouetteTexture", &_horizontallyDilatedFrameBuffer.getTexture()}},
620 utils::Uniform("horizontal", false), utils::Uniform("kernelSize", 3));
621
623 _differenceFrameBuffer, _subtractShaderProgram,
624 {{"first", &_fullyDilatedFrameBuffer.getTexture()}, {"second", &_silhouetteFrameBuffer.getTexture()}});
625
627 _outlinedObjectsFrameBuffer, _overlayShaderProgram,
628 {{"background", &_mostRecentFrameBufferPtr->getTexture()}, {"overlay", &_differenceFrameBuffer.getTexture()}});
629
631
632 _mostRecentFrameBufferPtr = &_outlinedObjectsFrameBuffer;
633}
634
635template <typename MainCameraTag>
637 SHKYERA_PROFILE("RenderingSystem<MainCameraTag>::renderDirectionalLightShadowMaps");
638
640
641 const auto& cameraTransform = RegistryViewer::read<TransformComponent>(*_registry->getEntity<MainCameraTag>());
642 const auto& cameraComponent = RegistryViewer::read<CameraComponent>(*_registry->getEntity<MainCameraTag>());
643
644 std::unordered_set<Entity> directionalLightEntities;
645 for (const auto& [entity, directionalLightComponent] : RegistryViewer::readAll<DirectionalLightComponent>()) {
647 if (_directionalLightToShadowMap.find(entity) == _directionalLightToShadowMap.end()) {
648 _directionalLightToShadowMap.emplace(entity, DepthAtlasFrameBuffer(DirectionalLightComponent::LevelsOfDetail));
649 auto& newShadowMap = _directionalLightToShadowMap.at(entity);
650
651 newShadowMap.bind();
653 newShadowMap.clear();
654 newShadowMap.unbind();
655 }
656 }
657
658 std::vector<Entity> entitiesWithFrameBuffersToRemove;
659 for (const auto& [entity, _buffer] : _directionalLightToShadowMap) {
662 }
663 }
664
666 _directionalLightToShadowMap.erase(entityToRemove);
667 }
668
669 for (auto& [lightEntity, shadowMapAtlas] : _directionalLightToShadowMap) {
670 shadowMapAtlas.bind();
671 shadowMapAtlas.clear();
672 shadowMapAtlas.unbind();
673
674 const auto& directionalLightComponent = RegistryViewer::read<DirectionalLightComponent>(lightEntity);
676
679 _depthShaderProgram.use();
680
681 const glm::mat4& lightSpaceMatrix = directionalLightComponent.getLightSpaceMatrix(
683
684 _depthShaderProgram.setUniform("projectionViewMatrix", lightSpaceMatrix);
685 for (const auto& [modelEntity, modelComponent] : RegistryViewer::readAll<ModelComponent>()) {
687 _depthShaderProgram.setUniform("modelMatrix", transformMatrix);
688
689 modelComponent.updateImpl();
690 }
691
692 _depthShaderProgram.stopUsing();
693 shadowMapAtlas.unbind();
694 }
695 }
696}
697
698template <typename MainCameraTag>
700 SHKYERA_PROFILE("RenderingSystem<MainCameraTag>::renderPointLightShadowMaps");
701
703
704 const auto& cameraTransform = RegistryViewer::read<TransformComponent>(*_registry->getEntity<MainCameraTag>());
705 const auto& cameraComponent = RegistryViewer::read<CameraComponent>(*_registry->getEntity<MainCameraTag>());
706
707 std::unordered_set<Entity> pointLightEntities;
708 for (const auto& [entity, pointLightComponent] : RegistryViewer::readAll<PointLightComponent>()) {
710 if (_pointLightToShadowMap.find(entity) == _pointLightToShadowMap.end()) {
711 _pointLightToShadowMap.emplace(entity, DepthAtlasFrameBuffer(6));
712 auto& newShadowMap = _pointLightToShadowMap.at(entity);
713
714 newShadowMap.bind();
715 newShadowMap.setSize(6 * 1024, 1024);
716 newShadowMap.clear();
717 newShadowMap.unbind();
718 }
719 }
720
721 std::vector<Entity> entitiesWithFrameBuffersToRemove;
722 for (const auto& [entity, _buffer] : _pointLightToShadowMap) {
723 if (pointLightEntities.find(entity) == pointLightEntities.end()) {
725 }
726 }
727
729 _pointLightToShadowMap.erase(entityToRemove);
730 }
731
732 for (auto& [lightEntity, shadowMapCubeAtlas] : _pointLightToShadowMap) {
733 shadowMapCubeAtlas.bind();
734 shadowMapCubeAtlas.clear();
735 shadowMapCubeAtlas.unbind();
736
737 // TODO: Use global position
738 const auto& lightPosition = RegistryViewer::read<TransformComponent>(lightEntity).getPosition();
739 const auto& lightRange = RegistryViewer::read<PointLightComponent>(lightEntity).range;
740
741 glm::mat4 projection = glm::perspective(glm::radians(90.0f), 1.0f, 0.01f, lightRange);
742 glm::mat4 captureViews[6] = {
743 projection * glm::lookAt(lightPosition, lightPosition + glm::vec3(1.0f, 0.0f, 0.0f),
744 glm::vec3(0.0f, -1.0f, 0.0f)), // +X
745 projection * glm::lookAt(lightPosition, lightPosition + glm::vec3(-1.0f, 0.0f, 0.0f),
746 glm::vec3(0.0f, -1.0f, 0.0f)), // -X
747 projection *
748 glm::lookAt(lightPosition, lightPosition + glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)), // +Y
749 projection * glm::lookAt(lightPosition, lightPosition + glm::vec3(0.0f, -1.0f, 0.0f),
750 glm::vec3(0.0f, 0.0f, -1.0f)), // -Y
751 projection * glm::lookAt(lightPosition, lightPosition + glm::vec3(0.0f, 0.0f, 1.0f),
752 glm::vec3(0.0f, -1.0f, 0.0f)), // +Z
753 projection * glm::lookAt(lightPosition, lightPosition + glm::vec3(0.0f, 0.0f, -1.0f),
754 glm::vec3(0.0f, -1.0f, 0.0f)) // -Z
755 };
756
757 _distanceShaderProgram.use();
758
759 for (uint8_t face = 0; face < 6; ++face) {
761
762 const glm::mat4& lightSpaceMatrix = captureViews[face];
763 _distanceShaderProgram.setUniform("projectionViewMatrix", lightSpaceMatrix);
764
765 for (const auto& [modelEntity, modelComponent] : RegistryViewer::readAll<ModelComponent>()) {
767 _distanceShaderProgram.setUniform("modelMatrix", transformMatrix);
768
769 modelComponent.updateImpl();
770 }
771
772 shadowMapCubeAtlas.unbind();
773 }
774
775 _distanceShaderProgram.stopUsing();
776 }
777}
778
779template <typename MainCameraTag>
781 SHKYERA_PROFILE("RenderingSystem<MainCameraTag>::renderSpotLightShadowMaps");
782
784
785 const auto& cameraTransform = RegistryViewer::read<TransformComponent>(*_registry->getEntity<MainCameraTag>());
786 const auto& cameraComponent = RegistryViewer::read<CameraComponent>(*_registry->getEntity<MainCameraTag>());
787
788 std::unordered_set<Entity> spotLightEntities;
789 for (const auto& [entity, spotLightComponent] : RegistryViewer::readAll<SpotLightComponent>()) {
791 if (_spotLightToShadowMap.find(entity) == _spotLightToShadowMap.end()) {
792 _spotLightToShadowMap.emplace(entity, DepthAtlasFrameBuffer(1));
793 auto& newShadowMap = _spotLightToShadowMap.at(entity);
794
795 newShadowMap.bind();
796 newShadowMap.setSize(1500, 1500);
797 newShadowMap.clear();
798 newShadowMap.unbind();
799 }
800 }
801
802 std::vector<Entity> entitiesWithFrameBuffersToRemove;
803 for (const auto& [entity, _buffer] : _spotLightToShadowMap) {
804 if (spotLightEntities.find(entity) == spotLightEntities.end()) {
806 }
807 }
808
810 _spotLightToShadowMap.erase(entityToRemove);
811 }
812
813 for (auto& [lightEntity, shadowMap] : _spotLightToShadowMap) {
814 shadowMap.bind();
815 shadowMap.clear();
816 shadowMap.unbind();
817
819 const auto lightPosition = glm::vec3{lightTransformMatrix[3]};
820 const auto& lightRange = RegistryViewer::read<SpotLightComponent>(lightEntity).range;
821 const auto& lightOuterCutoff = RegistryViewer::read<SpotLightComponent>(lightEntity).outerCutoff;
822 const auto lightSpaceMatrix =
823 RegistryViewer::read<SpotLightComponent>(lightEntity).getLightSpaceMatrix(lightTransformMatrix);
824
825 _distanceShaderProgram.use();
826
827 shadowMap.bind(0);
828 _distanceShaderProgram.setUniform("projectionViewMatrix", lightSpaceMatrix);
829 for (const auto& [modelEntity, modelComponent] : RegistryViewer::readAll<ModelComponent>()) {
831 _distanceShaderProgram.setUniform("modelMatrix", transformMatrix);
832 modelComponent.updateImpl();
833 }
834 shadowMap.unbind();
835
836 _distanceShaderProgram.stopUsing();
837 }
838}
839
840template <typename MainCameraTag>
842 SHKYERA_PROFILE("RenderingSystem<MainCameraTag>::renderWorldObjects");
843
845
846 const auto& cameraTransform = RegistryViewer::read<TransformComponent>(*_registry->getEntity<MainCameraTag>());
847 const auto& cameraTransformMatrix =
848 TransformComponent::getGlobalTransformMatrix(*_registry->getEntity<MainCameraTag>(), _registry);
849 const auto& cameraPosition = glm::vec3{cameraTransformMatrix[3]};
850 const auto& cameraComponent = RegistryViewer::read<CameraComponent>(*_registry->getEntity<MainCameraTag>());
851
852 // ********* Rendering the world *********
853 UseShader modelShaderUsage(_modelShaderProgram);
854 _mostRecentFrameBufferPtr->bind();
855
856 const glm::mat4& viewMatrix =
857 RegistryViewer::read<CameraComponent>(*_registry->getEntity<MainCameraTag>()).getViewMatrix(cameraTransform);
858 const glm::mat4& projectionMatrix =
859 RegistryViewer::read<CameraComponent>(*_registry->getEntity<MainCameraTag>()).getProjectionMatrix();
860
861 _modelShaderProgram.setUniform("projectionViewMatrix", projectionMatrix * viewMatrix);
862 _modelShaderProgram.setUniform("viewPos", cameraPosition);
863
864 glm::vec3 ambientColor{0, 0, 0};
865 for (const auto& ambientLightComponent : RegistryViewer::read<AmbientLightComponent>()) {
867 }
868 _modelShaderProgram.setUniform("ambientLight", ambientColor);
869
870 int pointLightIndex = 0;
871 for (const auto& [entity, pointLightComponent] : RegistryViewer::readAll<PointLightComponent>()) {
872 auto& depthCubeMap = _pointLightToShadowMap.at(entity);
873 depthCubeMap.getTexture().activate(GL_TEXTURE0 + _textureIndex);
874 _modelShaderProgram.setUniform("pointLightsDepthCubeMap[" + std::to_string(pointLightIndex) + "]", _textureIndex);
875 ++_textureIndex;
876
877 const auto& transformComponent = RegistryViewer::read<TransformComponent>(entity);
878 _modelShaderProgram.setUniform("pointLights[" + std::to_string(pointLightIndex) + "].position",
879 transformComponent.getPosition());
880 _modelShaderProgram.setUniform("pointLights[" + std::to_string(pointLightIndex) + "].color",
881 pointLightComponent.intensity * pointLightComponent.color);
882 _modelShaderProgram.setUniform("pointLights[" + std::to_string(pointLightIndex) + "].range",
883 pointLightComponent.range);
885 }
886 _modelShaderProgram.setUniform("numPointLights", pointLightIndex);
887
888 int directionalLightIndex = 0;
889 for (const auto& [entity, directionalLightComponent] : RegistryViewer::readAll<DirectionalLightComponent>()) {
890 const auto& lightTransform = RegistryViewer::read<TransformComponent>(entity);
891 const auto& depthAtlasFrameBuffer = _directionalLightToShadowMap.at(entity);
893
895 const glm::mat4 lightSpaceMatrix = directionalLightComponent.getLightSpaceMatrix(
897 _modelShaderProgram.setUniform("directionalLights[" + std::to_string(directionalLightIndex) +
898 "].lightSpaceMatrix[" + std::to_string(levelOfDetail) + "]",
900 }
901
902 depthAtlasFrameBuffer.getTexture().activate(GL_TEXTURE0 + _textureIndex);
903 _modelShaderProgram.setUniform("directionalLightsDepthMap[" + std::to_string(directionalLightIndex) + "]",
904 _textureIndex);
905 ++_textureIndex;
906
908 _modelShaderProgram.setUniform("directionalLights[" + std::to_string(directionalLightIndex) + "].direction",
910 _modelShaderProgram.setUniform("directionalLights[" + std::to_string(directionalLightIndex) + "].color",
913 }
914 _modelShaderProgram.setUniform("numDirectionalLights", directionalLightIndex);
915
916 int spotLightIndex = 0;
917 for (const auto& [entity, spotLightComponent] : RegistryViewer::readAll<SpotLightComponent>()) {
918 {
919 const auto& lightTransform = RegistryViewer::read<TransformComponent>(entity);
921 const auto globalLightPosition = glm::vec3{lightTransformMatrix[3]};
922 const auto lightDirection = glm::normalize(glm::vec3{1, 0, 0} * glm::mat3{glm::inverse(lightTransformMatrix)});
923 const auto lightSpaceMatrix =
924 RegistryViewer::read<SpotLightComponent>(entity).getLightSpaceMatrix(lightTransformMatrix);
925
926 _modelShaderProgram.setUniform("spotLights[" + std::to_string(spotLightIndex) + "].lightSpaceMatrix",
928 _modelShaderProgram.setUniform("spotLights[" + std::to_string(spotLightIndex) + "].position",
930 _modelShaderProgram.setUniform("spotLights[" + std::to_string(spotLightIndex) + "].direction", lightDirection);
931 _modelShaderProgram.setUniform("spotLights[" + std::to_string(spotLightIndex) + "].color",
932 spotLightComponent.intensity * spotLightComponent.color);
933 _modelShaderProgram.setUniform("spotLights[" + std::to_string(spotLightIndex) + "].range",
934 spotLightComponent.range);
935 _modelShaderProgram.setUniform("spotLights[" + std::to_string(spotLightIndex) + "].innerCutoffCosine",
936 std::cos(spotLightComponent.innerCutoff));
937 _modelShaderProgram.setUniform("spotLights[" + std::to_string(spotLightIndex) + "].outerCutoffCosine",
938 std::cos(spotLightComponent.outerCutoff));
939 }
940
941 {
942 const auto& depthBuffer = _spotLightToShadowMap.at(entity);
943 depthBuffer.getTexture().activate(GL_TEXTURE0 + _textureIndex);
944 _modelShaderProgram.setUniform("spotLightsShadowMap[" + std::to_string(spotLightIndex) + "]", _textureIndex);
945 ++_textureIndex;
946 }
947
949 }
950 _modelShaderProgram.setUniform("numSpotLights", spotLightIndex);
951
952 { // SSAO
953 _ssaoFrameBuffer.getTexture().activate(GL_TEXTURE0 + _textureIndex);
954 _modelShaderProgram.setUniform("ssao", _textureIndex);
955 ++_textureIndex;
956
957 _modelShaderProgram.setUniform("viewportSize", _mostRecentFrameBufferPtr->getSize());
958 }
959
960 {
961 SHKYERA_PROFILE("RenderingSystem<MainCameraTag>::renderWorldObjects - Models");
962 for (const auto& [entity, modelComponent] : RegistryViewer::readAll<ModelComponent>()) {
963
965 _modelShaderProgram.setUniform("modelMatrix", transformMatrix);
966
967 const auto& material = std::get<AssetRef<Material>>(modelComponent.material);
968 setMaterial(material.get());
969
970 modelComponent.updateImpl();
971 }
972 }
973}
974
975template <typename MainCameraTag>
977 SHKYERA_PROFILE("RenderingSystem<MainCameraTag>::renderParticles");
978
982
983 UseShader modelShaderUsage(_modelShaderProgram);
984
985 const auto& cameraTransform = RegistryViewer::read<TransformComponent>(*_registry->getEntity<MainCameraTag>());
986 const auto& cameraTransformMatrix =
987 TransformComponent::getGlobalTransformMatrix(*_registry->getEntity<MainCameraTag>(), _registry);
988 const auto& cameraPosition = glm::vec3{cameraTransformMatrix[3]};
989 const glm::mat4& viewMatrix =
990 RegistryViewer::read<CameraComponent>(*_registry->getEntity<MainCameraTag>()).getViewMatrix(cameraTransform);
991
992 static const auto billboardPlane = utils::assets::readPermanent<Mesh>(Mesh::Factory::Type::PLANE);
993 billboardPlane->bind();
994
995 for (const auto& [entity, emitter] : RegistryViewer::readAll<ParticleEmitterComponent>()) {
996 if (!emitter.enabled) {
997 continue;
998 }
999
1000 auto cameraFacingTransform = glm::mat4{1.0};
1003
1004 const auto& material = std::get<AssetRef<Material>>(emitter.material);
1005 setMaterial(material.get());
1006
1007 const auto& state = emitter.state;
1008
1009 for (size_t i = 0; i < state.lifetimes.size(); ++i) {
1010 if (state.lifetimes[i] < 0) {
1011 continue;
1012 }
1013
1014 const auto particleScale = state.sizes[i];
1015 auto cameraFacingTransformOfParticle = glm::scale(cameraFacingTransform, glm::vec3{state.sizes[i]});
1016 cameraFacingTransformOfParticle[3] = glm::vec4{state.positions[i], 1.0f};
1017 _modelShaderProgram.setUniform("modelMatrix", cameraFacingTransformOfParticle);
1018 _modelShaderProgram.setUniform("material.alphaMultiplier", state.transparencies[i]);
1019
1020 glDrawElements(GL_TRIANGLES, billboardPlane->getMeshSize(), GL_UNSIGNED_INT, nullptr);
1021 }
1022 }
1023
1024 billboardPlane->unbind();
1025
1028}
1029
1030template <typename MainCameraTag>
1032 SHKYERA_PROFILE("RenderingSystem<MainCameraTag>::renderBillboards");
1033
1034 UseShader modelShaderUsage(_modelShaderProgram);
1035 _mostRecentFrameBufferPtr->bind();
1036
1041
1042 const auto& cameraTransform = RegistryViewer::read<TransformComponent>(*_registry->getEntity<MainCameraTag>());
1043 const auto& cameraTransformMatrix =
1044 TransformComponent::getGlobalTransformMatrix(*_registry->getEntity<MainCameraTag>(), _registry);
1045 const auto& cameraPosition = glm::vec3{cameraTransformMatrix[3]};
1046 const glm::mat4& viewMatrix =
1047 RegistryViewer::read<CameraComponent>(*_registry->getEntity<MainCameraTag>()).getViewMatrix(cameraTransform);
1048
1049 static const auto billboardPlane = utils::assets::readPermanent<Mesh>(Mesh::Factory::Type::PLANE);
1050
1051 billboardPlane->bind();
1052 for (const auto& [entity, billboardComponent] :
1053 RegistryViewer::readAll<BillboardComponent<RuntimeMode::PRODUCTION>>()) {
1056 } else {
1058 }
1059
1062 _modelShaderProgram.setUniform("modelMatrix", modelMatrix);
1063
1064 const auto& material = std::get<AssetRef<Material>>(billboardComponent.material);
1065 setMaterial(material.get());
1066
1067 glDrawElements(GL_TRIANGLES, billboardPlane->getMeshSize(), GL_UNSIGNED_INT, nullptr);
1068 }
1069 billboardPlane->unbind();
1070
1074
1075 _mostRecentFrameBufferPtr->unbind();
1076}
1077
1078template <typename MainCameraTag>
1080 SHKYERA_PROFILE("RenderingSystem<MainCameraTag>::renderBillboards");
1081
1082 UseShader modelShaderUsage(_modelShaderProgram);
1083 _mostRecentFrameBufferPtr->bind();
1084
1089
1090 const auto& cameraTransform = RegistryViewer::read<TransformComponent>(*_registry->getEntity<MainCameraTag>());
1091 const auto& cameraTransformMatrix =
1092 TransformComponent::getGlobalTransformMatrix(*_registry->getEntity<MainCameraTag>(), _registry);
1093 const auto& cameraPosition = glm::vec3{cameraTransformMatrix[3]};
1094 const glm::mat4& viewMatrix =
1095 RegistryViewer::read<CameraComponent>(*_registry->getEntity<MainCameraTag>()).getViewMatrix(cameraTransform);
1096
1097 static const auto billboardPlane = utils::assets::readPermanent<Mesh>(Mesh::Factory::Type::PLANE);
1098 billboardPlane->bind();
1099
1100 const auto drawDebugBillboard = [this, &cameraPosition, &viewMatrix](const auto& componentSet,
1101 Material const* material) {
1105
1106 for (const auto& [entity, _] : componentSet) {
1108
1109 glm::vec3 translation = glm::vec3(baseTransform[3]); // Extract translation
1110 glm::vec3 right = glm::normalize(glm::vec3(baseTransform[0])); // X-axis
1111 glm::vec3 up = glm::normalize(glm::vec3(baseTransform[1])); // Y-axis
1112 glm::vec3 forward = glm::normalize(glm::vec3(baseTransform[2])); // Z-axis
1113
1114 baseTransform = glm::mat4(1.0f);
1115 baseTransform[0] = glm::vec4(right, 0.0f);
1116 baseTransform[1] = glm::vec4(up, 0.0f);
1117 baseTransform[2] = glm::vec4(forward, 0.0f);
1118 baseTransform[3] = glm::vec4(translation, 1.0f);
1119
1121
1122 _modelShaderProgram.setUniform("modelMatrix", modelMatrix);
1123
1124 setMaterial(material);
1125
1126 // Draw the billboard quad.
1127 glDrawElements(GL_TRIANGLES, billboardPlane->getMeshSize(), GL_UNSIGNED_INT, nullptr);
1128 }
1129 };
1130
1131 {
1132 drawDebugBillboard(RegistryViewer::readAll<PointLightComponent>(), &_pointLightDebugMaterial);
1133 drawDebugBillboard(RegistryViewer::readAll<DirectionalLightComponent>(), &_directionalLightDebugMaterial);
1134 drawDebugBillboard(RegistryViewer::readAll<SpotLightComponent>(), &_spotLightDebugMaterial);
1135 drawDebugBillboard(RegistryViewer::readAll<AmbientLightComponent>(), &_ambientLightDebugMaterial);
1136 drawDebugBillboard(RegistryViewer::readAll<ParticleEmitterComponent>(), &_particleEmitterDebugMaterial);
1137 drawDebugBillboard(RegistryViewer::readAll<PostProcessingVolumeComponent>(), &_postProcessingVolumeDebugMaterial);
1138 drawDebugBillboard(RegistryViewer::readAll<AudioSourceComponent>(), &_audioSourceDebugMaterial);
1139 }
1140
1141 billboardPlane->unbind();
1142
1146 _mostRecentFrameBufferPtr->unbind();
1147}
1148template <typename MainCameraTag>
1151
1152 UseShader modelShaderUsage(_wireframeShaderProgram);
1153 _mostRecentFrameBufferPtr->bind();
1154
1155 static const glm::vec3 volumeWireframeColor{0.8, 0.8, 0.8};
1156 _wireframeShaderProgram.setUniform("fixedColor", volumeWireframeColor);
1157
1158 const auto& cameraTransform = RegistryViewer::read<TransformComponent>(*_registry->getEntity<MainCameraTag>());
1159 const glm::mat4& viewMatrix =
1160 RegistryViewer::read<CameraComponent>(*_registry->getEntity<MainCameraTag>()).getViewMatrix(cameraTransform);
1161 const glm::mat4& projectionMatrix =
1162 RegistryViewer::read<CameraComponent>(*_registry->getEntity<MainCameraTag>()).getProjectionMatrix();
1164
1165 static const auto volumeCube = utils::assets::readPermanent<Wireframe>(Wireframe::Factory::Type::CUBE);
1166
1167 volumeCube->bind();
1168 for (const auto& [entity, _volumeComponent] : RegistryViewer::readAll<PostProcessingVolumeComponent>()) {
1170 _wireframeShaderProgram.setUniform("projectionViewModelMatrix", projectionViewMatrix * transformMatrix);
1171 glDrawArrays(GL_LINES, 0, volumeCube->getEdgeCount());
1172 }
1173 volumeCube->unbind();
1174
1175 _mostRecentFrameBufferPtr->unbind();
1176}
1177
1178template <typename MainCameraTag>
1180 SHKYERA_PROFILE("RenderingSystem<MainCameraTag>::renderBloom");
1181
1183
1184 // Downscaling Pass
1185 utils::applyShaderToFrameBuffer(_downscaledFrameBuffers[0], _thresholdShaderProgram,
1186 {{"sceneTexture", &_mostRecentFrameBufferPtr->getTexture()}},
1187 utils::Uniform("threshold", threshold));
1188 for (size_t i = 1; i < BloomSteps; ++i) {
1189 utils::applyShaderToFrameBuffer(_downscaledFrameBuffers[i], _thresholdShaderProgram,
1190 {{"sceneTexture", &_downscaledFrameBuffers[i - 1].getTexture()}},
1191 utils::Uniform("threshold", 0.0f));
1192 }
1193
1194 // Horizontal Blur Pass
1195 for (size_t i = 0; i < BloomSteps; ++i) {
1196 utils::applyShaderToFrameBuffer(_horizontallyBluredDownscaledFrameBuffers[i], _horizontalBlurShaderProgram,
1197 {{"textureToBlur", &_downscaledFrameBuffers[i].getTexture()}},
1198 utils::Uniform("resolution", _downscaledFrameBuffers[i].getSize()));
1199 }
1200
1201 // Vertical Blur Pass
1202 for (size_t i = 0; i < BloomSteps; ++i) {
1204 _fullyBluredDownscaledFrameBuffers[i], _verticalBlurShaderProgram,
1205 {{"textureToBlur", &_horizontallyBluredDownscaledFrameBuffers[i].getTexture()}},
1206 utils::Uniform("resolution", _horizontallyBluredDownscaledFrameBuffers[i].getSize()));
1207 }
1208
1209 // Blur Combination Pass
1210 auto* currentBuffer = &_fullyBluredDownscaledFrameBuffers[BloomSteps - 1];
1211 float currentWeight = 1.0f / (1 << (BloomSteps - 1));
1212
1213 for (int i = BloomSteps - 2; i >= 0; --i) {
1214 auto* nextBuffer = &_fullyBluredDownscaledFrameBuffers[i];
1215 float nextWeight = 1.0f / (1 << i);
1216
1218 *currentBuffer, _weightedAdditionShaderProgram,
1219 {{"firstTexture", &currentBuffer->getTexture()}, {"secondTexture", &nextBuffer->getTexture()}},
1220 utils::Uniform("firstWeight", currentWeight), utils::Uniform("secondWeight", nextWeight));
1221
1223 }
1224
1225 // Composite bloom with the original scene
1227 _bloomedFrameBuffer, _weightedAdditionShaderProgram,
1228 {{"firstTexture", &_mostRecentFrameBufferPtr->getTexture()}, {"secondTexture", &currentBuffer->getTexture()}},
1229 utils::Uniform("firstWeight", 1.0f), utils::Uniform("secondWeight", weight));
1230
1232 _mostRecentFrameBufferPtr = &_bloomedFrameBuffer;
1233}
1234
1235template <typename MainCameraTag>
1237 SHKYERA_PROFILE("RenderingSystem<MainCameraTag>::toneMapping");
1238
1240
1241 utils::applyShaderToFrameBuffer(_toneMappedFrameBuffer, _toneMappingShaderProgram,
1242 {{"original", &_mostRecentFrameBufferPtr->getTexture()}});
1243
1245 _mostRecentFrameBufferPtr = &_toneMappedFrameBuffer;
1246}
1247
1248template <typename MainCameraTag>
1250 SHKYERA_PROFILE("RenderingSystem<MainCameraTag>::gammaCorrection");
1251
1253
1254 utils::applyShaderToFrameBuffer(_gammaCorrectedFrameBuffer, _gammaCorrectionShaderProgram,
1255 {{"original", &_mostRecentFrameBufferPtr->getTexture()}},
1256 utils::Uniform("gamma", gamma));
1257
1259 _mostRecentFrameBufferPtr = &_gammaCorrectedFrameBuffer;
1260}
1261
1262template <typename MainCameraTag>
1264 SHKYERA_PROFILE("RenderingSystem<MainCameraTag>::renderWireframes");
1265
1267
1268 _mostRecentFrameBufferPtr->bind();
1269
1270 const auto& cameraTransform = RegistryViewer::read<TransformComponent>(*_registry->getEntity<MainCameraTag>());
1271 const glm::mat4& viewMatrix =
1272 RegistryViewer::read<CameraComponent>(*_registry->getEntity<MainCameraTag>()).getViewMatrix(cameraTransform);
1273 const glm::mat4& projectionMatrix =
1274 RegistryViewer::read<CameraComponent>(*_registry->getEntity<MainCameraTag>()).getProjectionMatrix();
1275
1276 _wireframeShaderProgram.use();
1277
1279
1280 static const glm::vec3 wireframeColor{0.08, 0.7, 0.15};
1281
1282 for (const auto& [entity, wireframeComponent] : RegistryViewer::readAll<WireframeComponent>()) {
1284 _wireframeShaderProgram.setUniform("projectionViewModelMatrix", projectionViewMatrix * transformMatrix);
1285 _wireframeShaderProgram.setUniform("fixedColor", wireframeColor);
1286 wireframeComponent.updateImpl();
1287 }
1288
1289 _wireframeShaderProgram.stopUsing();
1290 _mostRecentFrameBufferPtr->unbind();
1291}
1292
1293template <typename MainCameraTag>
1295 SHKYERA_PROFILE("RenderingSystem<MainCameraTag>::renderSkybox");
1296
1297 const auto& cameraTransform = RegistryViewer::read<TransformComponent>(*_registry->getEntity<MainCameraTag>());
1298 const glm::mat4& viewMatrix =
1299 RegistryViewer::read<CameraComponent>(*_registry->getEntity<MainCameraTag>()).getViewMatrix(cameraTransform);
1300 const glm::mat4& projectionMatrix =
1301 RegistryViewer::read<CameraComponent>(*_registry->getEntity<MainCameraTag>()).getProjectionMatrix();
1302 static auto cubemapMesh = utils::assets::readPermanent<Mesh>(Mesh::Factory::Type::CUBEMAP);
1303
1305
1306 _mostRecentFrameBufferPtr->bind();
1307 _skyboxShaderProgram.use();
1308 _skyboxShaderProgram.setUniform("viewMatrix", glm::mat4(viewMatrix));
1309 _skyboxShaderProgram.setUniform("projectionMatrix", projectionMatrix);
1310
1311 for (const auto& skybox : RegistryViewer::read<SkyboxComponent>()) {
1312 const auto& skyboxCubeMap = std::get<AssetRef<CubeMap>>(skybox.skyboxCubeMap);
1313 SHKYERA_ASSERT(skyboxCubeMap, "Skybox CubeMap Asset is not loaded");
1314
1315 skyboxCubeMap->activate(GL_TEXTURE0);
1316 _skyboxShaderProgram.setUniform("skybox", 0);
1317 cubemapMesh->draw();
1318 }
1319
1320 _skyboxShaderProgram.stopUsing();
1321 _mostRecentFrameBufferPtr->unbind();
1322
1324}
1325
1326template <typename MainCameraTag>
1328 SHKYERA_PROFILE("RenderingSystem<MainCameraTag>::renderOverlayModels");
1329
1331
1332 _mostRecentFrameBufferPtr->bind();
1333
1334 const auto& cameraTransform = RegistryViewer::read<TransformComponent>(*_registry->getEntity<MainCameraTag>());
1335 const glm::mat4& viewMatrix =
1336 RegistryViewer::read<CameraComponent>(*_registry->getEntity<MainCameraTag>()).getViewMatrix(cameraTransform);
1337 const glm::mat4& projectionMatrix =
1338 RegistryViewer::read<CameraComponent>(*_registry->getEntity<MainCameraTag>()).getProjectionMatrix();
1339
1340 _wireframeShaderProgram.use();
1341
1343
1344 for (const auto& [entity, overlayModelComponent] : RegistryViewer::readAll<OverlayModelComponent>()) {
1346 _wireframeShaderProgram.setUniform("projectionViewModelMatrix", projectionViewMatrix * transformMatrix);
1347 _wireframeShaderProgram.setUniform("fixedColor", overlayModelComponent.getMaterial()->albedo);
1348 overlayModelComponent.updateImpl();
1349 }
1350
1351 _wireframeShaderProgram.stopUsing();
1352 _mostRecentFrameBufferPtr->unbind();
1353
1355}
1356
1357template <typename MainCameraTag>
1359 SHKYERA_PROFILE("RenderingSystem<MainCameraTag>::antiAliasing");
1361 utils::applyShaderToFrameBuffer(_antiAliasedFrameBuffer, _antiAliasingShaderProgram,
1362 {{"sceneTexture", &_mostRecentFrameBufferPtr->getTexture()}});
1363
1365 _mostRecentFrameBufferPtr = &_antiAliasedFrameBuffer;
1366}
1367
1368template <typename MainCameraTag>
1369void RenderingSystem<MainCameraTag>::setTexture(Material const* material, const std::string& textureName,
1370 auto textureMember) {
1371 UseShader modelShaderUsage(_modelShaderProgram);
1372 if (const auto& textureAsset = std::get<AssetRef<Texture>>((*material).*textureMember)) {
1373 _modelShaderProgram.setUniform("material." + textureName + "TextureLoaded", true);
1374
1375 textureAsset->activate(GL_TEXTURE0 + _textureIndex);
1376 _modelShaderProgram.setUniform("material." + textureName + "Texture", _textureIndex);
1377 ++_textureIndex;
1378 } else {
1379 _modelShaderProgram.setUniform("material." + textureName + "TextureLoaded", false);
1380 }
1381}
1382
1383template <typename MainCameraTag>
1385 UseShader modelShaderUsage(_modelShaderProgram);
1386 if (material == nullptr) {
1387 material = &_defaultMaterial;
1388 }
1389
1390 _modelShaderProgram.setUniform("material.lit", material->lit);
1391 _modelShaderProgram.setUniform("material.alphaMultiplier", material->alphaMultiplier);
1392 _modelShaderProgram.setUniform("material.albedoColor", material->albedo);
1393 _modelShaderProgram.setUniform("material.emissive", material->emissive * material->emissiveStrength);
1394 _modelShaderProgram.setUniform("material.roughness", material->roughness);
1395 _modelShaderProgram.setUniform("material.metallic", material->metallic);
1396 _modelShaderProgram.setUniform("material.normalMapStrength", material->normalMapStrength);
1397
1398 setTexture(material, "roughness", &Material::roughnessTexture);
1399 setTexture(material, "albedo", &Material::albedoTexture);
1400 setTexture(material, "normal", &Material::normalTexture);
1401 setTexture(material, "metallic", &Material::metallicTexture);
1402 setTexture(material, "emissive", &Material::emissiveTexture);
1403}
1404
1405template <typename MainCameraTag>
1407 static const auto volume = AABB{.center = {0, 0, 0}, .extents = {1.0, 1.0, 1.0}};
1408
1409 const auto& cameraTransform = RegistryViewer::read<TransformComponent>(*_registry->getEntity<MainCameraTag>());
1410 const auto& cameraTransformMatrix =
1411 TransformComponent::getGlobalTransformMatrix(*_registry->getEntity<MainCameraTag>(), _registry);
1412 const auto& cameraPosition = glm::vec3{cameraTransformMatrix[3]};
1413
1414 for (const auto& [entity, postProcessingVolume] : RegistryViewer::readAll<PostProcessingVolumeComponent>()) {
1416 if (volume.isInside(transformMatrix, cameraPosition)) {
1417 return postProcessingVolume;
1418 }
1419 }
1420
1421 for (const auto& postProcessingVolume : RegistryViewer::read<PostProcessingVolumeComponent>()) {
1422 if (postProcessingVolume.global) {
1423 return postProcessingVolume;
1424 }
1425 }
1426
1428}
1429
1430} // namespace shkyera
#define SHKYERA_ASSERT(predicate,...)
Definition Assert.hpp:7
#define SHKYERA_PROFILE(name)
Definition Profiler.hpp:45
Component that enables audio playback for an entity.
Definition AudioSourceComponent.hpp:13
Definition CameraComponent.hpp:10
Definition CubeMap.hpp:12
Definition DepthAtlasFrameBuffer.hpp:10
Definition EntityHierarchy.hpp:20
Definition ModelComponent.hpp:12
Definition NameComponent.hpp:9
Definition OverlayModelComponent.hpp:12
Definition RegistryViewer.hpp:51
Definition RenderingSystem.hpp:47
Material _spotLightDebugMaterial
Definition RenderingSystem.hpp:162
std::optional< GLuint > update()
Definition RenderingSystem.hpp:400
void renderBillboards()
Definition RenderingSystem.hpp:1031
SceneFrameBuffer _gammaCorrectedFrameBuffer
Definition RenderingSystem.hpp:121
void renderSSAO(float strength, float radius)
Definition RenderingSystem.hpp:517
void setSize(uint32_t width, uint32_t height)
Definition RenderingSystem.hpp:334
ShaderProgram _ssaoShaderProgram
Definition RenderingSystem.hpp:111
PostProcessingVolumeComponent getPostProcessingSettings()
Definition RenderingSystem.hpp:1406
ShaderProgram _viewSpacePositionShaderProgram
Definition RenderingSystem.hpp:110
SceneFrameBuffer _differenceFrameBuffer
Definition RenderingSystem.hpp:138
SceneFrameBuffer _horizontallyDilatedFrameBuffer
Definition RenderingSystem.hpp:136
int _textureIndex
Definition RenderingSystem.hpp:88
void setTexture(Material const *material, const std::string &textureName, auto textureMember)
Definition RenderingSystem.hpp:1369
void renderSkybox()
Definition RenderingSystem.hpp:1294
void renderWireframes()
Definition RenderingSystem.hpp:1263
Material _defaultMaterial
Definition RenderingSystem.hpp:159
static constexpr size_t BloomSteps
Definition RenderingSystem.hpp:124
SceneFrameBuffer _outlinedObjectsFrameBuffer
Definition RenderingSystem.hpp:139
SceneFrameBuffer _antiAliasedFrameBuffer
Definition RenderingSystem.hpp:102
SceneFrameBuffer _litModelsFrameBuffer
Definition RenderingSystem.hpp:97
ShaderProgram _skyboxShaderProgram
Definition RenderingSystem.hpp:147
ShaderProgram _modelShaderProgram
Definition RenderingSystem.hpp:98
Material _pointLightDebugMaterial
Definition RenderingSystem.hpp:163
SceneFrameBuffer _toneMappedFrameBuffer
Definition RenderingSystem.hpp:117
std::unordered_map< Entity, DepthAtlasFrameBuffer > _directionalLightToShadowMap
Definition RenderingSystem.hpp:150
ShaderProgram _viewSpaceNormalShaderProgram
Definition RenderingSystem.hpp:109
SceneFrameBuffer _fullyDilatedFrameBuffer
Definition RenderingSystem.hpp:137
void renderDebugBillboards()
Definition RenderingSystem.hpp:1079
SceneFrameBuffer _bloomedFrameBuffer
Definition RenderingSystem.hpp:128
std::vector< glm::vec3 > _ssaoKernel
Definition RenderingSystem.hpp:112
void renderPointLightShadowMaps()
Definition RenderingSystem.hpp:699
ShaderProgram _overlayShaderProgram
Definition RenderingSystem.hpp:143
ShaderProgram _wireframeShaderProgram
Definition RenderingSystem.hpp:99
ShaderProgram _distanceShaderProgram
Definition RenderingSystem.hpp:154
float _usedSsaoRadius
Definition RenderingSystem.hpp:113
void renderDirectionalLightShadowMaps()
Definition RenderingSystem.hpp:636
void clearFrameBuffers()
Definition RenderingSystem.hpp:371
void antiAliasing()
Definition RenderingSystem.hpp:1358
std::unordered_map< Entity, DepthAtlasFrameBuffer > _spotLightToShadowMap
Definition RenderingSystem.hpp:156
std::unordered_map< Entity, DepthAtlasFrameBuffer > _pointLightToShadowMap
Definition RenderingSystem.hpp:153
void renderOutlineOfSelectedEntities()
Definition RenderingSystem.hpp:569
void renderViewNormals()
Definition RenderingSystem.hpp:488
void renderViewPosition()
Definition RenderingSystem.hpp:459
SceneFrameBuffer * _mostRecentFrameBufferPtr
Definition RenderingSystem.hpp:94
RenderingSystem(std::shared_ptr< Registry > registry)
Definition RenderingSystem.hpp:171
void renderSpotLightShadowMaps()
Definition RenderingSystem.hpp:780
void renderParticles()
Definition RenderingSystem.hpp:976
GLuint getRenderFrameBuffer()
Definition RenderingSystem.hpp:366
CubeMap _skyboxCubeMap
Definition RenderingSystem.hpp:146
ShaderProgram _antiAliasingShaderProgram
Definition RenderingSystem.hpp:103
ShaderProgram _thresholdShaderProgram
Definition RenderingSystem.hpp:129
SceneFrameBuffer _silhouetteFrameBuffer
Definition RenderingSystem.hpp:135
Material _particleEmitterDebugMaterial
Definition RenderingSystem.hpp:165
void renderPostProcessingVolumes()
Definition RenderingSystem.hpp:1149
Material _directionalLightDebugMaterial
Definition RenderingSystem.hpp:161
std::shared_ptr< Registry > _registry
Definition RenderingSystem.hpp:91
ShaderProgram _dilateShaderProgram
Definition RenderingSystem.hpp:141
SceneFrameBuffer _viewSpaceNormalFrameBuffer
Definition RenderingSystem.hpp:107
void toneMapping()
Definition RenderingSystem.hpp:1236
void renderOverlayModels()
Definition RenderingSystem.hpp:1327
void bloom(float threshold, float weight)
Definition RenderingSystem.hpp:1179
SceneFrameBuffer _viewSpacePositionFrameBuffer
Definition RenderingSystem.hpp:106
ShaderProgram _horizontalBlurShaderProgram
Definition RenderingSystem.hpp:130
SceneFrameBuffer _ssaoFrameBuffer
Definition RenderingSystem.hpp:108
ShaderProgram _subtractShaderProgram
Definition RenderingSystem.hpp:142
void setMaterial(Material const *material)
Definition RenderingSystem.hpp:1384
void renderWorldObjects()
Definition RenderingSystem.hpp:841
ShaderProgram _silhouetteShaderProgram
Definition RenderingSystem.hpp:140
ShaderProgram _weightedAdditionShaderProgram
Definition RenderingSystem.hpp:132
std::array< SceneFrameBuffer, BloomSteps > _horizontallyBluredDownscaledFrameBuffers
Definition RenderingSystem.hpp:126
std::array< SceneFrameBuffer, BloomSteps > _downscaledFrameBuffers
Definition RenderingSystem.hpp:125
ShaderProgram _gammaCorrectionShaderProgram
Definition RenderingSystem.hpp:120
void renderOutline(const std::set< Entity > &entities)
Definition RenderingSystem.hpp:577
Material _postProcessingVolumeDebugMaterial
Definition RenderingSystem.hpp:166
std::array< SceneFrameBuffer, BloomSteps > _fullyBluredDownscaledFrameBuffers
Definition RenderingSystem.hpp:127
void gammaCorrection(float gamma)
Definition RenderingSystem.hpp:1249
ShaderProgram _toneMappingShaderProgram
Definition RenderingSystem.hpp:116
Material _audioSourceDebugMaterial
Definition RenderingSystem.hpp:167
Material _ambientLightDebugMaterial
Definition RenderingSystem.hpp:164
ShaderProgram _depthShaderProgram
Definition RenderingSystem.hpp:151
ShaderProgram _verticalBlurShaderProgram
Definition RenderingSystem.hpp:131
Definition SceneFrameBuffer.hpp:11
Definition ShaderProgram.hpp:15
void attachShader(const std::shared_ptr< Shader > &shader)
Definition ShaderProgram.cpp:14
void link()
Definition ShaderProgram.cpp:18
Definition TransformComponent.hpp:21
static glm::mat4 getGlobalTransformMatrix(Entity entity, std::shared_ptr< Registry > registry)
Definition TransformComponent.hpp:73
Definition ShaderProgram.hpp:43
Definition Random.hpp:11
glm::mat4 getCameraFacingModelMatrix(const glm::mat4 &baseMatrix, const glm::vec3 &cameraPosition, const glm::mat4 &viewMatrix)
Definition TransformUtils.cpp:43
glm::mat4 getGlobalTransformMatrix(Entity entity, const RegistryViewer &viewer)
Definition TransformUtils.cpp:22
std::pair< std::string, ValueType > Uniform(const std::string &name, const ValueType &value)
Definition Utils.hpp:12
void drawFullscreenQuad()
Definition Utils.cpp:5
void applyShaderToFrameBuffer(SceneFrameBuffer &frameBuffer, ShaderProgram &shaderProgram, std::vector< std::pair< const char *, const Texture * > > textures, Uniforms... uniforms)
Definition Utils.hpp:17
Definition Asset.hpp:6
Definition AABB.hpp:8
glm::vec3 center
Definition AABB.hpp:9
Definition AmbientLightComponent.hpp:8
Definition BillboardComponent.hpp:16
Occlusion occlusion
Definition BillboardComponent.hpp:26
Scale scale
Definition BillboardComponent.hpp:25
Definition Clock.hpp:9
Definition DirectionalLightComponent.hpp:13
static glm::vec3 getDirection(const glm::mat4 &lightTransformMatrix)
Definition DirectionalLightComponent.hpp:49
static uint8_t LevelsOfDetail
Definition DirectionalLightComponent.hpp:18
Definition Material.hpp:10
float metallic
Definition Material.hpp:20
HandleAndAsset< Texture > roughnessTexture
Definition Material.hpp:23
HandleAndAsset< Texture > normalTexture
Definition Material.hpp:22
bool lit
Definition Material.hpp:13
HandleAndAsset< Texture > metallicTexture
Definition Material.hpp:24
HandleAndAsset< Texture > albedoTexture
Definition Material.hpp:21
float emissiveStrength
Definition Material.hpp:17
float alphaMultiplier
Definition Material.hpp:14
glm::vec3 emissive
Definition Material.hpp:16
HandleAndAsset< Texture > emissiveTexture
Definition Material.hpp:25
glm::vec3 albedo
Definition Material.hpp:15
float roughness
Definition Material.hpp:19
float normalMapStrength
Definition Material.hpp:18
Definition ParticleEmitterComponent.hpp:11
Definition PointLightComponent.hpp:11
Definition PostProcessingVolumeComponent.hpp:5
Definition RegistryViewer.hpp:14
Definition SelectedEntityComponent.hpp:7
Definition SkyboxComponent.hpp:10
Definition SpotLightComponent.hpp:11
Definition WireframeComponent.hpp:10
Definition RegistryViewer.hpp:24