From 6cd6f40ea3340641ffa2c955488f4ecb1aad05fa Mon Sep 17 00:00:00 2001 From: Voldie Date: Wed, 8 Jan 2025 17:38:00 +0100 Subject: [PATCH] Fixed Skinned Mesh, improvements and other changes --- CMakeLists.txt | 6 +- LICENSE | 2 +- .../FrustumCullingCompute.cpp | 18 ++- Samples/SimpleOcean/SimpleOcean.cpp | 53 ++++++-- Samples/SkinnedMesh/SkinnedMesh.cpp | 60 +++++---- Samples/Terrain/Terrain.cpp | 4 + Shaders/common/common.glsl | 16 ++- Shaders/common/scene.glsl | 17 +++ Shaders/compute/irradiance_env.comp | 3 + Shaders/gameoflife/gameoflife.comp | 5 +- Shaders/gammacorrection/gammacorrection.frag | 29 ----- Shaders/gammacorrection/gammacorrection.vert | 13 -- Shaders/mandelbrot/mandelbrot.comp | 12 +- Shaders/postprocessingeffects/bloom.frag | 1 - .../colorspace/KhronosPBRNeutral.comp | 4 +- .../colorspace/aces.comp | 3 + .../colorspace/gamma.comp | 4 +- .../colorspace/heatmap.comp | 3 + .../postprocessingeffects/gaussian_blur.comp | 120 ++++++++++++++++++ Shaders/postprocessingeffects/mistfog.frag | 20 +-- .../sobeledgedetection.comp | 44 +++---- Shaders/simpleocean/simple_water.frag | 18 ++- Shaders/simpleocean/simpleocean.frag | 18 ++- Shaders/skinnedmesh/skinnedmesh.vert | 34 +++-- Shaders/skinnedmesh/skinnedmesh_common.glsl | 4 +- Shaders/skybox/panoramic.frag | 6 +- common/Common.h | 12 +- common/FPSCounter.h | 2 +- common/GLSample.h | 40 ++++-- common/GLSampleSession.h | 12 +- common/GLSampleWindow.cpp | 72 ++++++++++- common/GLSampleWindow.h | 7 +- common/GLUIComponent.h | 4 +- common/IOUtil.h | 2 +- common/Importer/ImageImport.h | 2 +- common/Importer/ImportHelper.cpp | 2 +- common/Importer/ImportHelper.h | 2 +- common/Importer/ModelImporter.cpp | 92 +++++++++----- common/Importer/ModelImporter.h | 19 +-- common/Importer/Scene.cpp | 53 +++++++- common/Importer/Scene.h | 18 ++- common/PostProcessing/BloomPostProcessing.cpp | 94 ++++++++++++++ common/PostProcessing/BloomPostProcessing.h | 45 +++++++ common/PostProcessing/BlurPostProcessing.cpp | 94 ++++++++++++++ common/PostProcessing/BlurPostProcessing.h | 45 +++++++ .../ColorGradePostProcessing.cpp | 11 ++ .../PostProcessing/ColorGradePostProcessing.h | 37 ++++++ common/PostProcessing/ColorSpaceConverter.cpp | 2 +- common/PostProcessing/ColorSpaceConverter.h | 2 +- .../DepthOfFieldPostProcessing.cpp | 0 .../DepthOfFieldPostProcessing.h | 44 +++++++ common/PostProcessing/MistPostProcessing.cpp | 36 ++++-- common/PostProcessing/MistPostProcessing.h | 8 +- common/PostProcessing/PostProcessing.h | 8 +- .../PostProcessing/PostProcessingManager.cpp | 34 +++++ common/PostProcessing/PostProcessingManager.h | 23 +++- common/PostProcessing/SSSPostProcessing.h | 44 +++++++ common/PostProcessing/SobelPostProcessing.cpp | 71 ++++++++++- common/PostProcessing/SobelPostProcessing.h | 8 +- common/SampleHelper.h | 45 ++++--- common/ShaderLoader.cpp | 2 +- common/ShaderLoader.h | 2 +- common/Skybox.h | 2 +- common/Util/Camera.h | 2 +- common/Util/CameraController.h | 2 +- common/Util/Frustum.h | 2 +- common/Util/ProcessDataUtil.cpp | 4 +- common/Util/ProcessDataUtil.h | 2 +- 68 files changed, 1235 insertions(+), 290 deletions(-) delete mode 100644 Shaders/gammacorrection/gammacorrection.frag delete mode 100644 Shaders/gammacorrection/gammacorrection.vert create mode 100644 Shaders/postprocessingeffects/gaussian_blur.comp create mode 100644 common/PostProcessing/BloomPostProcessing.cpp create mode 100644 common/PostProcessing/BloomPostProcessing.h create mode 100644 common/PostProcessing/BlurPostProcessing.cpp create mode 100644 common/PostProcessing/BlurPostProcessing.h create mode 100644 common/PostProcessing/ColorGradePostProcessing.cpp create mode 100644 common/PostProcessing/ColorGradePostProcessing.h create mode 100644 common/PostProcessing/DepthOfFieldPostProcessing.cpp create mode 100644 common/PostProcessing/DepthOfFieldPostProcessing.h create mode 100644 common/PostProcessing/PostProcessingManager.cpp create mode 100644 common/PostProcessing/SSSPostProcessing.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e739b4e..82cff72 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -191,14 +191,14 @@ FOREACH(GLSL ${GLSL_SOURCE_FILES}) SET(SPIRV "${FILE_NAME}.spv") IF(GLSLLANGVALIDATOR) IF(CMAKE_BUILD_TYPE STREQUAL "Release") - SET(SPIRV_BUILD_SETTINGS "") + SET(SPIRV_BUILD_SETTINGS -g0) ELSE() - SET(SPIRV_BUILD_SETTINGS -g -Od) + SET(SPIRV_BUILD_SETTINGS -g -gVS -Od) ENDIF() ADD_CUSTOM_COMMAND( OUTPUT ${SPIRV} COMMAND ${CMAKE_COMMAND} -E make_directory "${EXECUTABLE_OUTPUT_PATH}/Shaders/" - COMMAND ${GLSLLANGVALIDATOR} -Dgl_InstanceID=gl_InstanceIndex -Dgl_VertexID=gl_VertexIndex -I${CMAKE_CURRENT_SOURCE_DIR}/Shaders/common --target-env vulkan1.1 ${SPIRV_BUILD_SETTINGS} -o ${SPIRV} ${GLSL} + COMMAND ${GLSLLANGVALIDATOR} --define-macro gl_InstanceID=gl_InstanceIndex --define-macro gl_VertexID=gl_VertexIndex -I${CMAKE_CURRENT_SOURCE_DIR}/Shaders/common --target-env vulkan1.1 ${SPIRV_BUILD_SETTINGS} -o ${SPIRV} ${GLSL} DEPENDS ${GLSL}) ELSEIF(GLSLC) IF(CMAKE_BUILD_TYPE STREQUAL "Release") diff --git a/LICENSE b/LICENSE index 0f80545..b0963ba 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2024 Valdemar Lindberg +Copyright (c) 2025 Valdemar Lindberg Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Samples/FrustumCullingCompute/FrustumCullingCompute.cpp b/Samples/FrustumCullingCompute/FrustumCullingCompute.cpp index 55ee3c7..74ba68d 100644 --- a/Samples/FrustumCullingCompute/FrustumCullingCompute.cpp +++ b/Samples/FrustumCullingCompute/FrustumCullingCompute.cpp @@ -77,8 +77,10 @@ namespace glsample { ImGui::TextUnformatted("Frustum Culling Settings"); ImGui::DragFloat("Shadow Strength", &this->uniform.shadowStrength, 1, 0.0f, 1.0f); ImGui::DragFloat("Shadow Bias", &this->uniform.bias, 1, 0.0f, 1.0f); - ImGui::ColorEdit4("Light", &this->uniform.lightColor[0], ImGuiColorEditFlags_Float | ImGuiColorEditFlags_HDR); - ImGui::ColorEdit4("Ambient", &this->uniform.ambientColor[0], ImGuiColorEditFlags_Float | ImGuiColorEditFlags_HDR); + ImGui::ColorEdit4("Light", &this->uniform.lightColor[0], + ImGuiColorEditFlags_Float | ImGuiColorEditFlags_HDR); + ImGui::ColorEdit4("Ambient", &this->uniform.ambientColor[0], + ImGuiColorEditFlags_Float | ImGuiColorEditFlags_HDR); ImGui::DragFloat3("Direction", &this->uniform.direction[0]); ImGui::DragFloat("Distance", &this->distance); ImGui::Checkbox("WireFrame", &this->showWireFrame); @@ -162,12 +164,14 @@ namespace glsample { /* Align uniform buffer in respect to driver requirement. */ GLint minMapBufferSize; glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &minMapBufferSize); - this->uniformAlignBufferSize = fragcore::Math::align(this->uniformAlignBufferSize, (size_t)minMapBufferSize); + this->uniformAlignBufferSize = + fragcore::Math::align(this->uniformAlignBufferSize, (size_t)minMapBufferSize); // Create uniform buffer. glGenBuffers(1, &this->uniform_buffer); glBindBufferARB(GL_UNIFORM_BUFFER, this->uniform_buffer); - glBufferData(GL_UNIFORM_BUFFER, this->uniformAlignBufferSize * this->nrUniformBuffer, nullptr, GL_DYNAMIC_DRAW); + glBufferData(GL_UNIFORM_BUFFER, this->uniformAlignBufferSize * this->nrUniformBuffer, nullptr, + GL_DYNAMIC_DRAW); glBindBufferARB(GL_UNIFORM_BUFFER, 0); { @@ -227,7 +231,8 @@ namespace glsample { /* */ glBindBufferRange(GL_UNIFORM_BUFFER, this->uniform_buffer_index, uniform_buffer, - (getFrameCount() % nrUniformBuffer) * this->uniformAlignBufferSize, this->uniformAlignBufferSize); + (getFrameCount() % nrUniformBuffer) * this->uniformAlignBufferSize, + this->uniformAlignBufferSize); { @@ -298,7 +303,8 @@ namespace glsample { glBindBufferARB(GL_UNIFORM_BUFFER, this->uniform_buffer); void *uniformPointer = glMapBufferRange( GL_UNIFORM_BUFFER, ((this->getFrameCount() + 1) % this->nrUniformBuffer) * this->uniformAlignBufferSize, - this->uniformAlignBufferSize, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_UNSYNCHRONIZED_BIT); + this->uniformAlignBufferSize, + GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_UNSYNCHRONIZED_BIT); memcpy(uniformPointer, &this->uniform, sizeof(uniform)); glUnmapBufferARB(GL_UNIFORM_BUFFER); } diff --git a/Samples/SimpleOcean/SimpleOcean.cpp b/Samples/SimpleOcean/SimpleOcean.cpp index df90011..e183780 100644 --- a/Samples/SimpleOcean/SimpleOcean.cpp +++ b/Samples/SimpleOcean/SimpleOcean.cpp @@ -1,3 +1,4 @@ +#include "GLUIComponent.h" #include "PostProcessing/MistPostProcessing.h" #include "SampleHelper.h" #include "Skybox.h" @@ -23,8 +24,7 @@ namespace glsample { SimpleOcean() : GLSampleWindow() { this->setTitle("Simple Ocean"); - this->simpleOceanSettingComponent = - std::make_shared(this->uniform_stage_buffer); + this->simpleOceanSettingComponent = std::make_shared(*this); this->addUIComponent(this->simpleOceanSettingComponent); /* Default camera position and orientation. */ @@ -97,9 +97,10 @@ namespace glsample { size_t uniformAlignBufferSize = sizeof(uniform_buffer_block); size_t oceanUniformSize = 0; - class SimpleOceanSettingComponent : public nekomimi::UIComponent { + class SimpleOceanSettingComponent : public GLUIComponent { public: - SimpleOceanSettingComponent(struct uniform_buffer_block &uniform) : uniform(uniform) { + SimpleOceanSettingComponent(SimpleOcean &sample) + : GLUIComponent(sample), uniform(this->getRefSample().uniform_stage_buffer) { this->setName("Simple Ocean Settings"); } @@ -149,13 +150,24 @@ namespace glsample { ImGui::ColorEdit4("Ocean Base Color", &this->uniform.ocean.oceanColor[0], ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_Float); + ImGui::TextUnformatted("Fog Settings"); + ImGui::DragInt("Fog Type", (int *)&this->getRefSample().mistprocessing.mistsettings.fogSettings.fogType); + ImGui::ColorEdit4("Fog Color", &this->getRefSample().mistprocessing.mistsettings.fogSettings.fogColor[0], + ImGuiColorEditFlags_Float | ImGuiColorEditFlags_HDR); + ImGui::DragFloat("Fog Density", &this->getRefSample().mistprocessing.mistsettings.fogSettings.fogDensity); + ImGui::DragFloat("Fog Intensity", &this->getRefSample().mistprocessing.mistsettings.fogSettings.fogIntensity); + ImGui::DragFloat("Fog Start", &this->getRefSample().mistprocessing.mistsettings.fogSettings.fogStart); + ImGui::DragFloat("Fog End", &this->getRefSample().mistprocessing.mistsettings.fogSettings.fogEnd); + /* */ ImGui::TextUnformatted("Debug"); ImGui::Checkbox("WireFrame", &this->showWireFrame); + ImGui::Checkbox("Use MistFog", &this->useMistFogPost); } bool showWireFrame = false; bool useGerstner = false; + bool useMistFogPost = false; private: struct uniform_buffer_block &uniform; @@ -295,7 +307,7 @@ namespace glsample { } /* */ - glDisable(GL_CULL_FACE); + glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glDepthFunc(GL_LESS); @@ -318,6 +330,20 @@ namespace glsample { glActiveTexture(GL_TEXTURE0 + 10); glBindTexture(GL_TEXTURE_2D, this->irradiance_texture); + /* */ + glActiveTexture(GL_TEXTURE0 + (int)GBuffer::Depth); + glBindTexture(GL_TEXTURE_2D, this->getFrameBuffer()->depthbuffer); + + glCullFace(GL_FRONT); + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + /* Draw triangle. */ + glBindVertexArray(this->plan.vao); + glDrawElements(GL_TRIANGLES, this->plan.nrIndicesElements, GL_UNSIGNED_INT, nullptr); + + /* */ + + glCullFace(GL_BACK); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); /* Draw triangle. */ glBindVertexArray(this->plan.vao); glDrawElements(GL_TRIANGLES, this->plan.nrIndicesElements, GL_UNSIGNED_INT, nullptr); @@ -341,8 +367,10 @@ namespace glsample { } /* Post processing. */ - this->mistprocessing.render(this->irradiance_texture, this->getFrameBuffer()->attachement0, - this->getFrameBuffer()->depthbuffer); + if (this->simpleOceanSettingComponent->useMistFogPost) { + this->mistprocessing.render(this->irradiance_texture, this->getFrameBuffer()->attachement0, + this->getFrameBuffer()->depthbuffer); + } } void update() override { @@ -365,10 +393,19 @@ namespace glsample { this->uniform_stage_buffer.ocean.modelViewProjection = this->uniform_stage_buffer.ocean.proj * this->uniform_stage_buffer.ocean.view * this->uniform_stage_buffer.ocean.model; - this->uniform_stage_buffer.ocean.camera.position = glm::vec4(this->camera.getPosition(), 0); + this->uniform_stage_buffer.ocean.time = elapsedTime; + + this->uniform_stage_buffer.ocean.camera.position = glm::vec4(this->camera.getPosition(), 0); + this->uniform_stage_buffer.ocean.camera.near = this->camera.getNear(); + this->uniform_stage_buffer.ocean.camera.far = this->camera.getFar(); } + this->mistprocessing.mistsettings.proj = this->camera.getProjectionMatrix(); + this->mistprocessing.mistsettings.fogSettings.cameraNear = this->camera.getNear(); + this->mistprocessing.mistsettings.fogSettings.cameraFar = this->camera.getFar(); + this->mistprocessing.mistsettings.viewRotation = camera.getRotationMatrix(); + /* */ glBindBuffer(GL_UNIFORM_BUFFER, this->uniform_buffer); uint8_t *uniformPointer = static_cast(glMapBufferRange( diff --git a/Samples/SkinnedMesh/SkinnedMesh.cpp b/Samples/SkinnedMesh/SkinnedMesh.cpp index 04370b9..811c872 100644 --- a/Samples/SkinnedMesh/SkinnedMesh.cpp +++ b/Samples/SkinnedMesh/SkinnedMesh.cpp @@ -1,3 +1,4 @@ +#include "GLUIComponent.h" #include #include #include @@ -20,29 +21,29 @@ namespace glsample { SkinnedMesh() : GLSampleWindow() { this->setTitle("Skinned Mesh"); - this->skinnedSettingComponent = std::make_shared(this->uniformStageBuffer); + this->skinnedSettingComponent = std::make_shared(*this); this->addUIComponent(this->skinnedSettingComponent); - this->camera.setPosition(glm::vec3(18.5f)); + this->camera.setPosition(glm::vec3(25.5f)); this->camera.lookAt(glm::vec3(0.f)); this->camera.enableLook(true); this->camera.enableNavigation(true); } struct uniform_buffer_block { - glm::mat4 model; - glm::mat4 view; - glm::mat4 proj; - glm::mat4 modelView; - glm::mat4 ViewProj; - glm::mat4 modelViewProjection; + glm::mat4 model{}; + glm::mat4 view{}; + glm::mat4 proj{}; + glm::mat4 modelView{}; + glm::mat4 ViewProj{}; + glm::mat4 modelViewProjection{}; /* light source. */ glm::vec4 direction = glm::vec4(1.0f / sqrt(2.0f), -1.0f / sqrt(2.0f), 0, 0.0f); glm::vec4 lightColor = glm::vec4(0.5f, 0.5f, 0.6f, 1.0f); - glm::vec4 ambientColor = glm::vec4(0.05, 0.05, 0.05, 1.0f); /* Material color. */ + glm::vec4 ambientColor = glm::vec4(0.05, 0.05, 0.05, 1.0f); glm::vec4 tintColor = glm::vec4(1); } uniformStageBuffer; @@ -51,16 +52,16 @@ namespace glsample { Scene scene; - unsigned int skinned_graphic_program; - unsigned int skinned_debug_weight_program; - unsigned int skinned_bone_program; - unsigned int axis_orientation_program; + unsigned int skinned_graphic_program{}; + unsigned int skinned_debug_weight_program{}; + unsigned int skinned_bone_program{}; + unsigned int axis_orientation_program{}; /* */ unsigned int uniform_buffer_binding = 0; unsigned int uniform_skeleton_buffer_binding = 1; - unsigned int uniform_buffer; - unsigned int uniform_skeleton_buffer; + unsigned int uniform_buffer{}; + unsigned int uniform_skeleton_buffer{}; const size_t nrUniformBuffer = 3; size_t uniformAlignBufferSize = sizeof(uniform_buffer_block); size_t uniformSkeletonBufferSize = 0; @@ -79,12 +80,11 @@ namespace glsample { const std::string vertexAxisShaderPath = "Shaders/skinnedmesh/skinnedmesh_debug.vert.spv"; const std::string fragmentAxisShaderPath = "Shaders/skinnedmesh/skinnedmesh_debug.frag.spv"; - class SkinnedMeshSettingComponent : public nekomimi::UIComponent { + class SkinnedMeshSettingComponent : public GLUIComponent { public: - SkinnedMeshSettingComponent(struct uniform_buffer_block &uniform) : uniform(uniform) { - this->setName("Skinned Mesh"); - } + SkinnedMeshSettingComponent(SkinnedMesh &sample) + : GLUIComponent(sample, "SkinnedMesh"), uniform(this->getRefSample().uniformStageBuffer) {} void draw() override { ImGui::TextUnformatted("Light Settings"); ImGui::ColorEdit4("Light", &this->uniform.lightColor[0], @@ -100,6 +100,8 @@ namespace glsample { ImGui::Checkbox("Show Bone", &this->showBone); ImGui::Checkbox("Show Weight", &this->showWeight); ImGui::Checkbox("Show Axis", &this->showAxis); + + this->getRefSample().scene.renderUI(); } bool showWireFrame = false; @@ -178,8 +180,8 @@ namespace glsample { int uniform_buffer_index = glGetUniformBlockIndex(this->skinned_graphic_program, "UniformBufferBlock"); int uniform_skeleton_buffer_index = glGetUniformBlockIndex(this->skinned_graphic_program, "UniformSkeletonBufferBlock"); - glUniform1i(glGetUniformLocation(this->skinned_graphic_program, "DiffuseTexture"), 0); - glUniform1i(glGetUniformLocation(this->skinned_graphic_program, "NormalTexture"), 1); + glUniform1i(glGetUniformLocation(this->skinned_graphic_program, "DiffuseTexture"), TextureType::Diffuse); + glUniform1i(glGetUniformLocation(this->skinned_graphic_program, "NormalTexture"), TextureType::Normal); glUniformBlockBinding(this->skinned_graphic_program, uniform_buffer_index, this->uniform_buffer_binding); glUniformBlockBinding(this->skinned_graphic_program, uniform_skeleton_buffer_index, this->uniform_skeleton_buffer_binding); @@ -316,6 +318,17 @@ namespace glsample { this->uniformStageBuffer.proj * this->uniformStageBuffer.view * this->uniformStageBuffer.model; } + /* Update Bone Transformation. */ + for (auto it = skeleton.bones.begin(); it != skeleton.bones.end(); it++) { + glm::mat4 nodeGlobalTransform = glm::mat4(1); + Bone *bone = &(*it).second; + if (bone->armature_bone) { + nodeGlobalTransform = bone->armature_bone->modelGlobalTransform; + } + + bone->finalTransform = nodeGlobalTransform * bone->offsetBoneMatrix; + } + /* */ { glBindBuffer(GL_UNIFORM_BUFFER, this->uniform_buffer); @@ -339,7 +352,10 @@ namespace glsample { int i = 0; for (auto it = skeleton.bones.begin(); it != skeleton.bones.end(); it++) { - memcpy(&uniformPointer[i++][0], &(*it).second.inverseBoneMatrix[0][0], sizeof(uniformPointer[0])); + const size_t bone_index = (*it).second.boneIndex; + + memcpy(&uniformPointer[bone_index][0][0], &(*it).second.finalTransform[0][0], + sizeof(uniformPointer[0])); } } glUnmapBuffer(GL_UNIFORM_BUFFER); diff --git a/Samples/Terrain/Terrain.cpp b/Samples/Terrain/Terrain.cpp index af812b4..a975c8b 100644 --- a/Samples/Terrain/Terrain.cpp +++ b/Samples/Terrain/Terrain.cpp @@ -374,6 +374,10 @@ namespace glsample { glActiveTexture(GL_TEXTURE0 + TextureType::Displacement); glBindTexture(GL_TEXTURE_2D, this->terrain_heightMap); + /* */ + glActiveTexture(GL_TEXTURE0 + TextureType::DepthBuffer); + glBindTexture(GL_TEXTURE_2D, this->getFrameBuffer()->depthbuffer); + /* */ glActiveTexture(GL_TEXTURE0 + TextureType::Irradiance); glBindTexture(GL_TEXTURE_2D, this->irradiance_texture); diff --git a/Shaders/common/common.glsl b/Shaders/common/common.glsl index d0492b9..d4967c4 100644 --- a/Shaders/common/common.glsl +++ b/Shaders/common/common.glsl @@ -16,16 +16,18 @@ /* Constants. */ #define PI 3.1415926535897932384626433832795 #define PI_HALF 1.5707963267948966192313216916398 +#define E_CONSTANT 2.7182818284590 layout(constant_id = 0) const float EPSILON = 1.19209e-07; struct Camera { - float near; - float far; - float aspect; - float fov; - vec4 position; - vec4 viewDir; - vec4 position_size; + float near; /* */ + float far; /* */ + float aspect; /* */ + float fov; /* */ + vec4 position; /* */ + vec4 viewDir; /* */ + vec4 position_size; /* */ + ivec4 screen_width_padding; }; struct FogSettings { diff --git a/Shaders/common/scene.glsl b/Shaders/common/scene.glsl index 8798edf..5de3d63 100644 --- a/Shaders/common/scene.glsl +++ b/Shaders/common/scene.glsl @@ -1,9 +1,26 @@ +#include "common.glsl" #include "material.glsl" +struct common_data { + Camera camera; + Frustum frustum; +}; + struct Node { mat4 model; }; +layout(set = 1, binding = 0, std140) uniform UniformCommonBufferBlock { + common_data constant; + + mat4 view; + mat4 proj; +} +constantCommon; + +layout(set = 1, binding = 2, std140) uniform UniformSkeletonBufferBlock { mat4 gBones[512]; } +skeletonUBO2; + layout(binding = 0) uniform sampler2D DiffuseTexture; layout(binding = 1) uniform sampler2D NormalTexture; layout(binding = 2) uniform sampler2D AlphaMaskedTexture; diff --git a/Shaders/compute/irradiance_env.comp b/Shaders/compute/irradiance_env.comp index 1f081c3..45046c4 100644 --- a/Shaders/compute/irradiance_env.comp +++ b/Shaders/compute/irradiance_env.comp @@ -2,6 +2,9 @@ #extension GL_ARB_shading_language_include : enable #extension GL_GOOGLE_include_directive : enable +precision mediump float; +precision mediump int; + layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; layout(set = 0, binding = 0) uniform sampler2D sourceEnvTexture; diff --git a/Shaders/gameoflife/gameoflife.comp b/Shaders/gameoflife/gameoflife.comp index f266d41..dc49f9c 100644 --- a/Shaders/gameoflife/gameoflife.comp +++ b/Shaders/gameoflife/gameoflife.comp @@ -3,7 +3,7 @@ #extension GL_ARB_compute_shader : enable #extension GL_EXT_control_flow_attributes : enable -layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; +layout(local_size_x = 32, local_size_y = 32, local_size_z = 1) in; layout(set = 0, binding = 0, r8ui) uniform restrict readonly uimage2D previousCellsTexture; @@ -62,8 +62,7 @@ void main() { imageStore(currentCellsTexture, pixel_coords, uvec4(result)); /* Apply gamma correction. */ - const float gamma = 2.2; - const vec3 finalColor = pow(color[sum], vec3(1.0 / gamma)); + const vec3 finalColor = color[sum]; /* Update the render texture in order to display as a texture. */ imageStore(renderTexture, pixel_coords, vec4(finalColor.rgb, 1)); diff --git a/Shaders/gammacorrection/gammacorrection.frag b/Shaders/gammacorrection/gammacorrection.frag deleted file mode 100644 index 852b548..0000000 --- a/Shaders/gammacorrection/gammacorrection.frag +++ /dev/null @@ -1,29 +0,0 @@ -#version 460 -#extension GL_ARB_separate_shader_objects : enable -#extension GL_ARB_explicit_attrib_location : enable -#extension GL_ARB_uniform_buffer_object : enable - -layout(location = 0) out vec4 fragColor; - -layout(location = 0) in vec2 uv; - -layout(binding = 1) uniform sampler2D AlbedoTexture; - -layout(binding = 0, std140) uniform UniformBufferBlock { - float exposure; - float gamma; -} -ubo; - -void main() { - - /* */ - fragColor = textureLod(AlbedoTexture, uv, 0); - /* */ - fragColor = vec4(1.0) - exp(-fragColor * ubo.exposure); - /* */ - fragColor = pow(fragColor, vec4(1.0 / ubo.gamma)); - - /* */ - fragColor = texture(AlbedoTexture, uv); -} \ No newline at end of file diff --git a/Shaders/gammacorrection/gammacorrection.vert b/Shaders/gammacorrection/gammacorrection.vert deleted file mode 100644 index 373f5c4..0000000 --- a/Shaders/gammacorrection/gammacorrection.vert +++ /dev/null @@ -1,13 +0,0 @@ -#version 460 -#extension GL_ARB_separate_shader_objects : enable -#extension GL_ARB_explicit_attrib_location : enable -#extension GL_ARB_uniform_buffer_object : enable - -layout(location = 0) in vec3 Vertex; -layout(location = 0) out vec2 uv; - -void main() { - gl_Position = vec4(Vertex.x, Vertex.y, 0, 1.0); - /* */ - uv = (vec2(Vertex.x, Vertex.y) + vec2(1, 1)) / 2.0; -} diff --git a/Shaders/mandelbrot/mandelbrot.comp b/Shaders/mandelbrot/mandelbrot.comp index 529fbaa..5b30a45 100644 --- a/Shaders/mandelbrot/mandelbrot.comp +++ b/Shaders/mandelbrot/mandelbrot.comp @@ -1,12 +1,16 @@ #version 460 #extension GL_ARB_separate_shader_objects : enable #extension GL_ARB_compute_shader : enable +#extension GL_ARB_shading_language_include : enable +#extension GL_GOOGLE_include_directive : enable layout(local_size_x = 32, local_size_y = 32, local_size_z = 1) in; layout(rgba8, binding = 0) uniform writeonly image2D img_output; -layout(constant_id = 0) const float lthreadhold = 2.0; +layout(constant_id = 16) const float lthreadhold = 2.0; + +#include "common.glsl" /* */ layout(set = 0, binding = 1, std140) uniform UniformBufferBlock { @@ -19,6 +23,8 @@ layout(set = 0, binding = 1, std140) uniform UniformBufferBlock { } ubo; + + /* */ vec2 squareImaginary(in const vec2 number) { return vec2((number.x * number.x) - (number.y * number.y), 2 * number.x * number.y); @@ -59,7 +65,7 @@ vec4 computeMandel(in vec2 uv) { const vec3 f = vec3(2.1, 2.0, 3.0); const vec3 g = vec3(0.0, 0.1, 0.0); - return vec4(d + e * cos(6.28318 * (f * t + g)), 1.0); + return vec4(d + e * cos(2 * PI * (f * t + g)), 1.0); } void main() { @@ -79,5 +85,5 @@ void main() { /* Apply gamma correction. */ const float gamma = 2.2; - imageStore(img_output, pixel_coords, pow(pixel, vec4(1.0 / gamma)) ); + imageStore(img_output, pixel_coords, pow(pixel, vec4(1.0 / gamma))); } \ No newline at end of file diff --git a/Shaders/postprocessingeffects/bloom.frag b/Shaders/postprocessingeffects/bloom.frag index 3b57925..9fcd0fb 100644 --- a/Shaders/postprocessingeffects/bloom.frag +++ b/Shaders/postprocessingeffects/bloom.frag @@ -13,7 +13,6 @@ layout(set = 0, binding = 0) uniform sampler2D texture0; layout(set = 0, binding = 1) uniform sampler2D depth0; layout(set = 0, binding = 2) uniform sampler2D IrradianceTexture; -#include "fog.glsl" #include "fog_frag.glsl" #include "postprocessing_base.glsl" diff --git a/Shaders/postprocessingeffects/colorspace/KhronosPBRNeutral.comp b/Shaders/postprocessingeffects/colorspace/KhronosPBRNeutral.comp index afda6af..f65c01a 100644 --- a/Shaders/postprocessingeffects/colorspace/KhronosPBRNeutral.comp +++ b/Shaders/postprocessingeffects/colorspace/KhronosPBRNeutral.comp @@ -6,11 +6,13 @@ #extension GL_ARB_shading_language_include : enable #extension GL_GOOGLE_include_directive : enable +precision mediump float; +precision mediump int; + layout(local_size_x = 32, local_size_y = 32, local_size_z = 1) in; layout(set = 0, binding = 1, rgba16f) uniform image2D texture0; - #include "colorspace.glsl" void main() { diff --git a/Shaders/postprocessingeffects/colorspace/aces.comp b/Shaders/postprocessingeffects/colorspace/aces.comp index 816dcd4..9284ed6 100644 --- a/Shaders/postprocessingeffects/colorspace/aces.comp +++ b/Shaders/postprocessingeffects/colorspace/aces.comp @@ -6,6 +6,9 @@ #extension GL_ARB_shading_language_include : enable #extension GL_GOOGLE_include_directive : enable +precision mediump float; +precision mediump int; + layout(local_size_x = 32, local_size_y = 32, local_size_z = 1) in; layout(set = 0, binding = 1, rgba16f) uniform image2D texture0; diff --git a/Shaders/postprocessingeffects/colorspace/gamma.comp b/Shaders/postprocessingeffects/colorspace/gamma.comp index 27dfaa8..961ed2f 100644 --- a/Shaders/postprocessingeffects/colorspace/gamma.comp +++ b/Shaders/postprocessingeffects/colorspace/gamma.comp @@ -4,6 +4,9 @@ #extension GL_ARB_shader_image_load_store : enable #extension GL_ARB_explicit_attrib_location : enable +precision mediump float; +precision mediump int; + layout(local_size_x = 32, local_size_y = 32, local_size_z = 1) in; layout(set = 0, binding = 1, rgba16f) uniform image2D texture0; @@ -21,7 +24,6 @@ void main() { return; } - // Get output fragcolor texture coordinate. const ivec2 TexCoord = ivec2(gl_GlobalInvocationID.xy); vec4 fragColor = imageLoad(texture0, TexCoord); diff --git a/Shaders/postprocessingeffects/colorspace/heatmap.comp b/Shaders/postprocessingeffects/colorspace/heatmap.comp index f54b410..e9cfece 100644 --- a/Shaders/postprocessingeffects/colorspace/heatmap.comp +++ b/Shaders/postprocessingeffects/colorspace/heatmap.comp @@ -7,6 +7,9 @@ #extension GL_ARB_shading_language_include : enable #extension GL_GOOGLE_include_directive : enable +precision mediump float; +precision mediump int; + layout(local_size_x = 32, local_size_y = 32, local_size_z = 1) in; layout(set = 0, binding = 1, rgba16f) uniform image2D texture0; diff --git a/Shaders/postprocessingeffects/gaussian_blur.comp b/Shaders/postprocessingeffects/gaussian_blur.comp new file mode 100644 index 0000000..76881e3 --- /dev/null +++ b/Shaders/postprocessingeffects/gaussian_blur.comp @@ -0,0 +1,120 @@ +#version 460 core +#extension GL_ARB_enhanced_layouts : enable +#extension GL_ARB_shader_image_load_store : enable +#extension GL_ARB_explicit_attrib_location : enable +#extension GL_EXT_shader_explicit_arithmetic_types_float16 : require +#extension GL_EXT_shader_16bit_storage : require +#extension GL_ARB_shading_language_include : enable +#extension GL_GOOGLE_include_directive : enable + +precision mediump float; +precision mediump int; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + +layout(set = 0, binding = 1, rgba16f) uniform image2D texture0; + +layout(push_constant) uniform Settings { + layout(offset = 0) float variance; + layout(offset = 4) float mean; + layout(offset = 8) float radius; + layout(offset = 12) int samples; +} +settings; + +#include "postprocessing_base.glsl" +layout(constant_id = 16) const int MAX_SAMPLES = 10; + +// const T exp_inverse = (static_cast(1.0) / (static_cast(2.0) * standard_deviation * standard_deviation)); +// const T sqr_2_pi_inverse = 1.0 / (standard_deviation * static_cast(std::sqrt(2 * Math::PI))); +// const T exp_num_sqrt = (i - theta + offset); + +// const T exponent = exp_inverse * -(exp_num_sqrt * exp_num_sqrt); +// const T value = sqr_2_pi_inverse * std::exp(exponent); + +float getGuas2D(const in float x, const in float y, const in float variance) { + return (1.0 / (2 * PI * variance * variance)) * pow(E_CONSTANT, -0.5 * ((x * x) + (y * y)) / (variance * variance)); +} + +vec4 blurHorizontal(const in float radius, const in float variance, const in int samples) { + int y; + + const ivec2 resolution = imageSize(texture0); + + const ivec2 TexCoord = ivec2(gl_GlobalInvocationID.xy); + + const int start = clamp(-((samples - 1) / 2), -MAX_SAMPLES, -1); + const int end = clamp(((samples - 1) / 2), 1, MAX_SAMPLES); + + vec4 color1 = vec4(0.0); + float total = EPSILON; + + for (y = start; y <= end; y++) { + + const ivec2 uv = TexCoord + ivec2(vec2(0, y) * radius); + + const float guas = getGuas2D(0, y, variance); + + color1 += imageLoad(texture0, uv).rgba * vec4(guas.xxx, 1.0); + total += guas; + } + + return color1 / total; +} + +vec4 blurVertical(const in float radius, const in float variance, const in int samples) { + int x; + + const ivec2 resolution = imageSize(texture0); + + const ivec2 TexCoord = ivec2(gl_GlobalInvocationID.xy); + + const int start = clamp(-((samples - 1) / 2), -MAX_SAMPLES, -1); + const int end = clamp(((samples - 1) / 2), 1, MAX_SAMPLES); + + vec4 color1 = vec4(0.0); + float total = EPSILON; + + for (x = start; x <= end; x++) { + const ivec2 uv = TexCoord + ivec2(vec2(x, 0) * radius); + const float guas = getGuas2D(x, 0, variance); + + color1 += imageLoad(texture0, uv).rgba * vec4(vec3(guas), 1.0); + total += guas; + } + + // Normalize color. + return color1 / total; +} + +void main() { + + /* */ + if (any(greaterThan(gl_GlobalInvocationID.xy, imageSize(texture0)))) { + return; + } + + const ivec2 TexCoord = ivec2(gl_GlobalInvocationID.xy); + + /* */ + { + + const vec4 verticalBlur = blurVertical(settings.radius, settings.variance, settings.samples); + + memoryBarrierImage(); + + imageStore(texture0, TexCoord, vec4(verticalBlur.rgb, 1.0)); + + memoryBarrierImage(); + } + + /* */ + { + + const vec4 blurHorizontalBlur = blurHorizontal(settings.radius, settings.variance, settings.samples); + + memoryBarrierImage(); + + imageStore(texture0, TexCoord, vec4(blurHorizontalBlur.rgb, 1.0)); + } +} \ No newline at end of file diff --git a/Shaders/postprocessingeffects/mistfog.frag b/Shaders/postprocessingeffects/mistfog.frag index b99a503..f1168c7 100644 --- a/Shaders/postprocessingeffects/mistfog.frag +++ b/Shaders/postprocessingeffects/mistfog.frag @@ -18,25 +18,29 @@ layout(set = 0, binding = 2) uniform sampler2D IrradianceTexture; layout(set = 0, binding = 0, std140) uniform UniformBufferBlock { mat4 proj; - mat4 modelViewProjection; - vec4 tintColor; - FogSettings fogSettings; + mat4 viewRotation; Camera camera; + FogSettings fogSettings; } ubo; void main() { - const vec3 direction = vec3(1); + const vec3 direction = normalize(mat3(ubo.viewRotation) * vec3(2 * uv - 1, 1)); //(ubo.proj * ).xyz; + + vec3 cr = normalize(cross(direction, vec3(0, -1, 0))); + + const float aat = 1;// clamp(pow(abs(1 - dot(direction, vec3(0, 1, 0))), 1.05), 0, 1); - /* */ - const vec2 irradiance_uv = inverse_equirectangular(normalize(direction)); + /* */ + const vec2 irradiance_uv = inverse_equirectangular(direction); const vec4 irradiance_color = texture(IrradianceTexture, irradiance_uv).rgba; - const float depth = texture(DepthTexture, gl_FragCoord.xy).r; + const float depth = texture(DepthTexture, uv).r; const float fogFactor = getFogFactor(ubo.fogSettings, depth); - fragColor.rgb = mix(texture(texture0, uv).rgb, irradiance_color.rgb, fogFactor); + fragColor.rgb = mix(texture(texture0, uv).rgb, irradiance_color.rgb * ubo.fogSettings.fogColor.rgb, clamp(fogFactor * aat, 0, 1)); + // fragColor.rgb = vec3(aat); // direction; fragColor.a = 1; } diff --git a/Shaders/postprocessingeffects/sobeledgedetection.comp b/Shaders/postprocessingeffects/sobeledgedetection.comp index 81b1344..a874ab5 100644 --- a/Shaders/postprocessingeffects/sobeledgedetection.comp +++ b/Shaders/postprocessingeffects/sobeledgedetection.comp @@ -4,54 +4,50 @@ #extension GL_ARB_shader_image_load_store : enable #extension GL_ARB_explicit_attrib_location : enable -layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; +layout(local_size_x = 32, local_size_y = 32, local_size_z = 1) in; -layout(set = 0, binding = 1, rgba8) uniform readonly image2D texture0; - -layout(set = 0, binding = 0, rgba8) uniform writeonly image2D fragColor; +layout(set = 0, binding = 1, rgba16) uniform coherent image2D texture0; void main() { /* */ - if (any(greaterThan(gl_GlobalInvocationID.xy, imageSize(fragColor)))) { + if (any(greaterThan(gl_GlobalInvocationID.xy, imageSize(texture0)))) { return; } - - // Get output fragcolor texture coordinate. - ivec2 TexCoord = ivec2(gl_GlobalInvocationID.xy); - ivec2 fragSize = imageSize(fragColor); - ivec2 TexSize = imageSize(texture0); - + // Compute sample coordinate. - vec2 TexDiff = vec2(TexSize) / vec2(fragSize); - ivec2 sampleTexCoord = ivec2(TexDiff * TexCoord); + ivec2 TexDiff = ivec2(1, 1); + ivec2 sampleTexCoord = ivec2(gl_GlobalInvocationID.xy); // TODO add recompute of the sample kernel coordinates. - const ivec2 lb = ivec2(-1.0 * TexDiff.x, -1.0 * TexDiff.y); + const ivec2 lb = ivec2(-1 * TexDiff.x, -1 * TexDiff.y); const vec4 p00 = imageLoad(texture0, sampleTexCoord + lb); - const ivec2 b = ivec2(0.0 * TexDiff.x, -1.0 * TexDiff.y); + const ivec2 b = ivec2(0.0 * TexDiff.x, -1 * TexDiff.y); const vec4 p10 = imageLoad(texture0, sampleTexCoord + b); - const ivec2 rb = ivec2(1.0 * TexDiff.x, -1.0 * TexDiff.y); + const ivec2 rb = ivec2(1 * TexDiff.x, -1 * TexDiff.y); const vec4 p20 = imageLoad(texture0, sampleTexCoord + rb); - const ivec2 l = ivec2(-1.0 * TexDiff.x, 0.0 * TexDiff.y); + const ivec2 l = ivec2(-1 * TexDiff.x, 0.0 * TexDiff.y); const vec4 p01 = imageLoad(texture0, sampleTexCoord + l); - const ivec2 r = ivec2(1.0 * TexDiff.x, 0.0 * TexDiff.y); + const ivec2 r = ivec2(1 * TexDiff.x, 0.0 * TexDiff.y); const vec4 p21 = imageLoad(texture0, sampleTexCoord + r); - const ivec2 lt = ivec2(-1.0 * TexDiff.x, 1.0 * TexDiff.y); + const ivec2 lt = ivec2(-1 * TexDiff.x, 1 * TexDiff.y); const vec4 p02 = imageLoad(texture0, sampleTexCoord + lt); - const ivec2 t = ivec2(-1.0 * TexDiff.x, 1.0 * TexDiff.y); + const ivec2 t = ivec2(-1 * TexDiff.x, 1 * TexDiff.y); const vec4 p12 = imageLoad(texture0, sampleTexCoord + t); - const ivec2 rt = ivec2(1.0 * TexDiff.x, 1.0 * TexDiff.y); + const ivec2 rt = ivec2(1 * TexDiff.x, 1 * TexDiff.y); const vec4 p22 = imageLoad(texture0, sampleTexCoord + rt); /* Compute Matrix X and Y. */ - const vec3 gx = -p00.xyz + p20.xyz + 2.0f * (p21.xyz - p01.xyz) - p02.xyz + p22.xyz; - const vec3 gy = -p00.xyz - p20.xyz + 2.0f * (p12.xyz - p10.xyz) + p02.xyz + p22.xyz; + const vec3 gx = -p00.xyz + p20.xyz + 2.0 * (p21.xyz - p01.xyz) - p02.xyz + p22.xyz; + const vec3 gy = -p00.xyz - p20.xyz + 2.0 * (p12.xyz - p10.xyz) + p02.xyz + p22.xyz; /* Compute the final. */ const vec3 g = sqrt(gx * gx + gy * gy); - imageStore(fragColor, TexCoord, vec4(g.rgb, 1.0)); + /* */ + memoryBarrierImage(); + + imageStore(texture0, sampleTexCoord, vec4(g.rgb, 1)); } \ No newline at end of file diff --git a/Shaders/simpleocean/simple_water.frag b/Shaders/simpleocean/simple_water.frag index 14101cc..91309d1 100644 --- a/Shaders/simpleocean/simple_water.frag +++ b/Shaders/simpleocean/simple_water.frag @@ -14,7 +14,7 @@ layout(location = 3) in vec3 tangent; #include "phongblinn.glsl" layout(set = 0, binding = 0) uniform sampler2D ReflectionTexture; -layout(set = 0, binding = 1) uniform sampler2D DepthTexture; +layout(set = 0, binding = 11) uniform sampler2D DepthTexture; struct Terrain { ivec2 size; @@ -79,11 +79,19 @@ void main() { computePhongDirectional(ubo.directional, heightNormal.xyz, viewDir.xyz, ubo.shininess.r, ubo.specularColor.rgb); /* Compute depth difference */ - const float current_z = getExpToLinear(ubo.camera.near, ubo.camera.far, texture(DepthTexture, gl_FragCoord.xy).r); + const vec2 screen_uv = gl_FragCoord.xy / vec2(2560, 1440); + const float current_z = getExpToLinear(ubo.camera.near, ubo.camera.far, texture(DepthTexture, screen_uv).r); const float shader_z = getExpToLinear(ubo.camera.near, ubo.camera.far, gl_FragCoord.z); - float inter = clamp((shader_z - current_z) / 100.0, 0.2, 1); + const float diff_depth = min(shader_z - current_z, 0) * 0.001; + const float translucent = smoothstep(0.0, 1, 8 * diff_depth * 0.00000001); // clamp( (1 / 0.02) * diff_depth *2, 0, 1); - fragColor = (lightColor + ubo.ambientColor); - fragColor.a = inter; + const vec4 bottomOceanColor = vec4(0.5373, 0.6353, 0.9529, 1.0); + const vec4 surfaceOceanColor = vec4(0.3804, 0.8706, 0.9922, 1.0); + + const vec4 mixColor = mix(bottomOceanColor, surfaceOceanColor, translucent * 10); + + fragColor = (lightColor + ubo.ambientColor) * mixColor; + // fragColor = vec4(1 - translucent); + fragColor.a = 1 - translucent; } \ No newline at end of file diff --git a/Shaders/simpleocean/simpleocean.frag b/Shaders/simpleocean/simpleocean.frag index 876ba26..faa5479 100644 --- a/Shaders/simpleocean/simpleocean.frag +++ b/Shaders/simpleocean/simpleocean.frag @@ -9,6 +9,8 @@ layout(location = 0) in vec3 vertex; layout(location = 1) in vec2 UV; layout(location = 2) in vec3 normal; +layout(origin_upper_left) in vec4 gl_FragCoord; + #include "common.glsl" #include "phongblinn.glsl" @@ -50,9 +52,10 @@ layout(binding = 0, std140) uniform UniformBufferBlock { } ubo; -layout(binding = 0) uniform sampler2D ReflectionTexture; +layout(set = 0, binding = 0) uniform sampler2D ReflectionTexture; -layout(binding = 10) uniform sampler2D IrradianceTexture; +layout(set = 0, binding = 10) uniform sampler2D IrradianceTexture; +layout(set = 0, binding = 6) uniform sampler2D DepthTexture; void main() { @@ -76,9 +79,16 @@ void main() { /* */ const vec3 fresnel = FresnelSchlick(vec3(0.02) * ubo.fresnelPower, viewDir, normal); - const vec4 gradientWaterDepth = vec4(0); + const vec2 screen_uv = gl_FragCoord.xy / vec2(2560, 1440); + const float current_z = getExpToLinear(ubo.camera.near, ubo.camera.far, texture(DepthTexture, screen_uv).r); + const float shader_z = getExpToLinear(ubo.camera.near, ubo.camera.far, gl_FragCoord.z); + + // const vec4 gradientWaterDepth = vec4(shader_z - current_z < 1.8 ? pow(shader_z - current_z, 1.2) : 0.001) * 100; const vec4 color = mix(ubo.oceanColor, texture(ReflectionTexture, reflection_uv), vec4(fresnel.rgb, 1)); fragColor = color * (ubo.ambientColor * irradiance_color + lightColor); - fragColor.a = 1; + // fragColor = vec4(0, 0, 0, 0); + // fragColor.a = 1; + + // fragColor.r = gradientWaterDepth.r; } \ No newline at end of file diff --git a/Shaders/skinnedmesh/skinnedmesh.vert b/Shaders/skinnedmesh/skinnedmesh.vert index a1a2084..592c34c 100644 --- a/Shaders/skinnedmesh/skinnedmesh.vert +++ b/Shaders/skinnedmesh/skinnedmesh.vert @@ -3,6 +3,7 @@ #extension GL_ARB_separate_shader_objects : enable #extension GL_ARB_shading_language_include : enable #extension GL_GOOGLE_include_directive : enable +#extension GL_EXT_control_flow_attributes : enable layout(location = 0) in vec3 Vertex; layout(location = 1) in vec2 TextureCoord; @@ -18,17 +19,32 @@ layout(location = 3) out vec3 FragIN_tangent; #include "skinnedmesh_common.glsl" + void main() { - mat4 BoneTransform = skeletonUBO.gBones[BoneIDs[0]] * Weights[0]; - BoneTransform += skeletonUBO.gBones[BoneIDs[1]] * Weights[1]; - BoneTransform += skeletonUBO.gBones[BoneIDs[2]] * Weights[2]; - BoneTransform += skeletonUBO.gBones[BoneIDs[3]] * Weights[3]; + /* */ + vec4 deformedVertex = vec4(0.0f); + vec3 deformedNormal = vec3(0.0); + vec3 deformedTangent = vec3(0.0); + [[unroll]] for (uint i = 0; i < MAX_BONE_INFLUENCE; i++) { + + if (BoneIDs[i] >= MAX_BONES) { + deformedVertex = vec4(Vertex, 1.0f); + break; + } + + const vec4 localPosition = skeletonUBO.gBones[BoneIDs[i]] * vec4(Vertex, 1.0f); + deformedVertex += localPosition * Weights[i]; + + const vec3 localNormal = mat3(skeletonUBO.gBones[BoneIDs[i]]) * Normal; + deformedNormal += localNormal * Weights[i]; - const vec4 boneVertex = BoneTransform * vec4(Vertex, 1.0); + const vec3 localTangent = mat3(skeletonUBO.gBones[BoneIDs[i]]) * Tangent; + deformedTangent += localTangent * Weights[i]; + } - gl_Position = ubo.modelViewProjection * boneVertex; - FragIN_normal = (ubo.model * vec4(Normal, 0.0)).xyz; - FragIN_tangent = (ubo.model * vec4(Tangent, 0.0)).xyz; + gl_Position = ubo.modelViewProjection * deformedVertex; + FragIN_normal = normalize((ubo.model * vec4(deformedNormal, 0.0)).xyz); + FragIN_tangent = normalize((ubo.model * vec4(deformedTangent, 0.0)).xyz); FragIN_uv = TextureCoord; -} \ No newline at end of file +} diff --git a/Shaders/skinnedmesh/skinnedmesh_common.glsl b/Shaders/skinnedmesh/skinnedmesh_common.glsl index 12f8cfb..8a6fb4f 100644 --- a/Shaders/skinnedmesh/skinnedmesh_common.glsl +++ b/Shaders/skinnedmesh/skinnedmesh_common.glsl @@ -1,7 +1,9 @@ #include "common.glsl" #include "light.glsl" -layout(constant_id = 1) const int MAX_BONES = 512; +/* */ +layout(constant_id = 16) const int MAX_BONES = 512; +layout(constant_id = 17) const int MAX_BONE_INFLUENCE = 4; layout(binding = 0, std140) uniform UniformBufferBlock { mat4 model; diff --git a/Shaders/skybox/panoramic.frag b/Shaders/skybox/panoramic.frag index eb2ee7e..7a42a4b 100644 --- a/Shaders/skybox/panoramic.frag +++ b/Shaders/skybox/panoramic.frag @@ -26,9 +26,9 @@ void main() { fragColor = textureLod(PanoramaTexture, uv, 0) * ubo.tintColor; - fragColor = vec4(1.0) - exp(-fragColor * ubo.exposure); - const float gamma = ubo.gamma; - fragColor = pow(fragColor, vec4(1.0 / gamma)); + // fragColor = vec4(1.0) - exp(-fragColor * ubo.exposure); + // const float gamma = ubo.gamma; + // fragColor = pow(fragColor, vec4(1.0 / gamma)); fragColor = fragColor * ubo.tintColor; } \ No newline at end of file diff --git a/common/Common.h b/common/Common.h index 0885a56..ef50795 100644 --- a/common/Common.h +++ b/common/Common.h @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2024 Valdemar Lindberg + * Copyright (c) 2025 Valdemar Lindberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -20,11 +20,11 @@ namespace glsample { enum class ColorSpace : unsigned int { - Raw = 0, /* Linear. */ - SRGB, /* SRGB encoded. */ - ACES, /* */ - FalseColor, - KhronosPBRNeutral, + Raw = 0, /* Linear. */ + SRGB, /* SRGB encoded. */ + ACES, /* */ + KhronosPBRNeutral, /* */ + FalseColor, /* */ MaxColorSpaces }; diff --git a/common/FPSCounter.h b/common/FPSCounter.h index 3453aa6..83af343 100644 --- a/common/FPSCounter.h +++ b/common/FPSCounter.h @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2024 Valdemar Lindberg + * Copyright (c) 2025 Valdemar Lindberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/common/GLSample.h b/common/GLSample.h index afdda71..7632847 100644 --- a/common/GLSample.h +++ b/common/GLSample.h @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2024 Valdemar Lindberg + * Copyright (c) 2025 Valdemar Lindberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -44,7 +44,12 @@ template class GLSample : public glsample::GLSampl GLSample &operator=(const GLSample &) = delete; GLSample &operator=(GLSample &&) = delete; explicit GLSample(T *sampleRef) : sampleRef(sampleRef) {} - ~GLSample() override { this->sampleRef->Release(); } + ~GLSample() override { + this->sampleRef->Release(); + delete this->sampleRef; + delete this->getFileSystem(); + delete this->getSchedular(); + } void run(int argc, const char **argv, const std::vector &requiredExtension = {}) override { @@ -90,6 +95,7 @@ template class GLSample : public glsample::GLSampl const bool gammacorrection = result["gamma-correction"].as(); /* Default window size. */ + int window_x = 0, window_y = 0; int width = result["width"].as(); int height = result["height"].as(); const int msaa = result["multi-sample"].as(); @@ -156,26 +162,34 @@ template class GLSample : public glsample::GLSampl /* Set debugging state. */ this->sampleRef->debug(debug); + fragcore::SDLDisplay display = fragcore::SDLDisplay::getPrimaryDisplay(); + if (display_index >= 0) { + display = fragcore::SDLDisplay::getDisplay(display_index); + } + /* */ if (fullscreen) { - /* Compute window size */ - fragcore::SDLDisplay display = fragcore::SDLDisplay::getPrimaryDisplay(); - if (display_index >= 0) { - display = fragcore::SDLDisplay::getDisplay(display_index); - } + /* Compute window size */ width = display.width(); height = display.height(); - } - /* */ - if (width == -1 || height == -1) { - fragcore::SDLDisplay display = fragcore::SDLDisplay::getPrimaryDisplay(); + + window_x = display.x(); + window_y = display.y(); + } else if (width == -1 || height == -1) { + + /* Compute window size */ width = display.width() / 2; height = display.height() / 2; + + window_x = display.x() + width; + window_y = display.y() + height; } + this->sampleRef->setPosition(window_x, window_y); this->sampleRef->setSize(width, height); + this->sampleRef->vsync(vsync); - // this->sampleRef->setColorSpace(gammacorrection); + // this->sampleRef->setColorSpace(gammacorrection);* this->sampleRef->setFullScreen(fullscreen); if (result.count("time") > 0) { @@ -196,5 +210,5 @@ template class GLSample : public glsample::GLSampl } private: - T *sampleRef; + T *sampleRef = nullptr; }; diff --git a/common/GLSampleSession.h b/common/GLSampleSession.h index d75da61..dd028ed 100644 --- a/common/GLSampleSession.h +++ b/common/GLSampleSession.h @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2024 Valdemar Lindberg + * Copyright (c) 2025 Valdemar Lindberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -58,9 +58,9 @@ namespace glsample { }; using TextureObject = struct texture_object_t { - unsigned int width{}; - unsigned int height{}; - unsigned int depth{}; + unsigned int width = 0; + unsigned int height = 0; + unsigned int depth = 0; unsigned int texture = 0; }; @@ -78,7 +78,7 @@ namespace glsample { fragcore::IScheduler *getSchedular() noexcept { return this->schedular; } protected: - fragcore::IFileSystem *activeFileSystem{}; - fragcore::IScheduler *schedular{}; + fragcore::IFileSystem *activeFileSystem = nullptr; + fragcore::IScheduler *schedular = nullptr; }; } // namespace glsample \ No newline at end of file diff --git a/common/GLSampleWindow.cpp b/common/GLSampleWindow.cpp index 33297db..38e5070 100644 --- a/common/GLSampleWindow.cpp +++ b/common/GLSampleWindow.cpp @@ -5,9 +5,17 @@ #include "FPSCounter.h" #include "GLHelper.h" #include "GLUIComponent.h" +#include "PostProcessing/BlurPostProcessing.h" +#include "PostProcessing/ColorGradePostProcessing.h" #include "PostProcessing/ColorSpaceConverter.h" +#include "PostProcessing/PostProcessing.h" + +#include "PostProcessing/BloomPostProcessing.h" +#include "PostProcessing/PostProcessingManager.h" +#include "PostProcessing/SobelPostProcessing.h" #include "SDL_scancode.h" #include "SDL_video.h" +#include "SampleHelper.h" #include "imgui.h" #include "magic_enum.hpp" #include "spdlog/common.h" @@ -84,16 +92,42 @@ class SampleSettingComponent : public GLUIComponent { } ImGui::EndCombo(); } - + ImGui::BeginGroup(); ImGui::TextUnformatted("Gamma Correction Settings"); ImGui::DragFloat("Exposure", &this->getRefSample().getColorSpaceConverter()->getGammeSettings().exposure); -// ImGui::SameLine(); + // ImGui::SameLine(); ImGui::DragFloat("Gamma", &this->getRefSample().getColorSpaceConverter()->getGammeSettings().gamma); ImGui::EndGroup(); } + /* Display All Framebuffer textures. */ + + /* List all builtin post processing. */ if (this->getRefSample().getPostProcessingManager()) { + // ImGui::BeginChild(); + ImGui::BeginGroup(); + PostProcessingManager *manager = this->getRefSample().getPostProcessingManager(); + /* */ + for (size_t post_index = 0; post_index < manager->getNrPostProcessing(); post_index++) { + PostProcessing &postEffect = manager->getPostProcessing(post_index); + + ImGui::PushID(post_index); + + /* */ + ImGui::TextUnformatted(postEffect.getName().c_str()); + // if (ImGui::BeginChild(postEffect.getName().c_str())) { + bool isEnabled = manager->isEnabled(post_index); + if (ImGui::Checkbox("Enabled", &isEnabled)) { + manager->enablePostProcessing(post_index, isEnabled); + } + //} + // ImGui::EndChild(); + + ImGui::PopID(); + } + + ImGui::EndGroup(); } } @@ -110,6 +144,7 @@ GLSampleWindow::GLSampleWindow() stdout_sink->set_color_mode(spdlog::color_mode::always); stdout_sink->set_pattern("[%Y-%m-%d %T.%e] [%^%l%$] %v"); stdout_sink->set_pattern("%g:%# [%^%l%$] %v"); + /* */ this->logger = new spdlog::logger("glsample", {stdout_sink}); this->logger->set_level(spdlog::level::trace); @@ -155,6 +190,12 @@ GLSampleWindow::GLSampleWindow() this->addUIComponent(settingComponent); } +GLSampleWindow::~GLSampleWindow() { + delete this->colorSpace; + delete this->postprocessingManager; + /* */ +} + void GLSampleWindow::displayMenuBar() {} void GLSampleWindow::renderUI() { @@ -163,6 +204,24 @@ void GLSampleWindow::renderUI() { if (this->colorSpace == nullptr) { this->colorSpace = new ColorSpaceConverter(); this->colorSpace->initialize(getFileSystem()); + + this->postprocessingManager = new PostProcessingManager(); + + SobelProcessing *sobelPostProcessing = new SobelProcessing(); + sobelPostProcessing->initialize(getFileSystem()); + this->postprocessingManager->addPostProcessing(*sobelPostProcessing); + + ColorGradePostProcessing *colorgrade = new ColorGradePostProcessing(); + colorgrade->initialize(getFileSystem()); + this->postprocessingManager->addPostProcessing(*colorgrade); + + BlurPostProcessing *blur = new BlurPostProcessing(); + blur->initialize(getFileSystem()); + this->postprocessingManager->addPostProcessing(*blur); + + BloomPostProcessing *bloom = new BloomPostProcessing(); + bloom->initialize(getFileSystem()); + this->postprocessingManager->addPostProcessing(*bloom); } // TODO: relocate to init @@ -206,8 +265,15 @@ void GLSampleWindow::renderUI() { /* */ this->draw(); - if (this->defaultFramebuffer) { + /* */ + if (this->postprocessingManager) { + this->postprocessingManager->render( + {std::make_tuple(GBuffer::Albedo, this->defaultFramebuffer->attachement0), + std::make_tuple(GBuffer::Depth, this->defaultFramebuffer->depthbuffer)}); + } + /* */ + if (this->defaultFramebuffer) { if (this->colorSpace) { this->colorSpace->convert(this->defaultFramebuffer->attachement0); } diff --git a/common/GLSampleWindow.h b/common/GLSampleWindow.h index ce5a47b..963fd19 100644 --- a/common/GLSampleWindow.h +++ b/common/GLSampleWindow.h @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2024 Valdemar Lindberg + * Copyright (c) 2025 Valdemar Lindberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -34,6 +34,7 @@ class FVDECLSPEC GLSampleWindow : public nekomimi::MIMIWindow { GLSampleWindow &operator=(GLSampleWindow &&) = delete; GLSampleWindow(const GLSampleWindow &other) = delete; GLSampleWindow(GLSampleWindow &&other) = delete; + ~GLSampleWindow() override; /** * @brief @@ -133,7 +134,7 @@ class FVDECLSPEC GLSampleWindow : public nekomimi::MIMIWindow { fragcore::SDLInput input; bool debugGL = true; - glsample::PostProcessingManager *postprocessingManager; + glsample::PostProcessingManager *postprocessingManager = nullptr; glsample::ColorSpaceConverter *colorSpace = nullptr; /* */ @@ -141,7 +142,7 @@ class FVDECLSPEC GLSampleWindow : public nekomimi::MIMIWindow { size_t frameBufferIndex = 0; size_t frameBufferCount = 0; unsigned int queries[10]; - fragcore::IFileSystem *filesystem; + fragcore::IFileSystem *filesystem; /* */ int preWidth = -1; int preHeight = -1; diff --git a/common/GLUIComponent.h b/common/GLUIComponent.h index f6f932b..2ca0c48 100644 --- a/common/GLUIComponent.h +++ b/common/GLUIComponent.h @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2024 Valdemar Lindberg + * Copyright (c) 2025 Valdemar Lindberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,7 +24,7 @@ namespace glsample { public: GLUIComponent(T &base, const std::string &name = "Sample Settings") : base(base) { this->setName(name); } - void draw() override {} + void draw() override = 0; protected: T &getRefSample() const { return this->base; } diff --git a/common/IOUtil.h b/common/IOUtil.h index 0347d6a..d4aa5ec 100644 --- a/common/IOUtil.h +++ b/common/IOUtil.h @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2024 Valdemar Lindberg + * Copyright (c) 2025 Valdemar Lindberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/common/Importer/ImageImport.h b/common/Importer/ImageImport.h index 6a7143e..bb4c0db 100644 --- a/common/Importer/ImageImport.h +++ b/common/Importer/ImageImport.h @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2024 Valdemar Lindberg + * Copyright (c) 2025 Valdemar Lindberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/common/Importer/ImportHelper.cpp b/common/Importer/ImportHelper.cpp index 78cb975..4196163 100644 --- a/common/Importer/ImportHelper.cpp +++ b/common/Importer/ImportHelper.cpp @@ -145,7 +145,7 @@ void ImportHelper::loadModelBuffer(ModelImporter &modelLoader, std::vector(refModel_base.boneIndexOffset)); /* Weight. */ diff --git a/common/Importer/ImportHelper.h b/common/Importer/ImportHelper.h index 7c680af..28e74e1 100644 --- a/common/Importer/ImportHelper.h +++ b/common/Importer/ImportHelper.h @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2024 Valdemar Lindberg + * Copyright (c) 2025 Valdemar Lindberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/common/Importer/ModelImporter.cpp b/common/Importer/ModelImporter.cpp index 00c17f7..a2ce844 100644 --- a/common/Importer/ModelImporter.cpp +++ b/common/Importer/ModelImporter.cpp @@ -5,6 +5,7 @@ #include "assimp/Importer.hpp" #include "assimp/ProgressHandler.hpp" #include "assimp/config.h" +#include "assimp/scene.h" #include #include #include @@ -91,7 +92,8 @@ void ModelImporter::loadContent(const std::string &path, unsigned long int suppo /* */ const aiScene *pScene = - importer.ReadFile(path.c_str(), aiProcessPreset_TargetRealtime_Quality | aiProcess_GenBoundingBoxes); + importer.ReadFile(path.c_str(), aiProcessPreset_TargetRealtime_Quality | aiProcess_GenBoundingBoxes | + aiProcess_PopulateArmatureData); if (pScene == nullptr) { throw RuntimeException("Failed to load file: {} - Error: {}", path, importer.GetErrorString()); @@ -171,18 +173,18 @@ void ModelImporter::initScene(const aiScene *scene) { // process_textures_thread.detach(); const size_t nr_threads = fragcore::Math::clamp(scene->mNumMeshes / 4, 1, SystemInfo::getCPUCoreCount()); - std::vector threads(nr_threads); + std::vector model_threads(nr_threads); /* Multithread the loading of all the geometry data. */ - for (size_t index_thread = 0; index_thread < threads.size(); index_thread++) { + for (size_t index_thread = 0; index_thread < model_threads.size(); index_thread++) { const size_t start_mesh = (scene->mNumMeshes / nr_threads) * index_thread; size_t num_mesh = (scene->mNumMeshes / nr_threads); - if (index_thread == threads.size() - 1) { + if (index_thread == model_threads.size() - 1) { num_mesh *= 2; } - threads[index_thread] = std::thread([&, start_mesh, num_mesh]() { + model_threads[index_thread] = std::thread([&, start_mesh, num_mesh]() { if (scene->HasMeshes()) { for (size_t x = start_mesh; x < fragcore::Math::min(start_mesh + num_mesh, scene->mNumMeshes); @@ -194,11 +196,6 @@ void ModelImporter::initScene(const aiScene *scene) { } /* */ std::thread process_animation_light_camera_thread([&]() { - /* */ - for (size_t x = 0; x < scene->mNumMeshes; x++) { - this->initBoneSkeleton(scene->mMeshes[x], x); - } - if (scene->HasAnimations()) { for (size_t x = 0; x < scene->mNumAnimations; x++) { this->initAnimation(scene->mAnimations[x], x); @@ -206,6 +203,7 @@ void ModelImporter::initScene(const aiScene *scene) { } if (scene->HasLights()) { + this->lights.resize(scene->mNumLights); for (unsigned int x = 0; x < scene->mNumLights; x++) { this->initLight(scene->mLights[x], x); } @@ -218,14 +216,11 @@ void ModelImporter::initScene(const aiScene *scene) { }); // process_animation_light_camera_thread.detach(); - /* Wait intill done. */ - // process_model_thread.join(); - process_textures_thread.join(); process_animation_light_camera_thread.join(); - for (size_t i = 0; i < threads.size(); i++) { - threads[i].join(); + for (size_t i = 0; i < model_threads.size(); i++) { + model_threads[i].join(); } /* */ @@ -239,6 +234,11 @@ void ModelImporter::initScene(const aiScene *scene) { } this->initNoodeRoot(scene->mRootNode, nullptr); + + /* */ + for (size_t x = 0; x < scene->mNumMeshes; x++) { + this->initBoneSkeleton(scene->mMeshes[x], x); + } } void ModelImporter::initNoodeRoot(const aiNode *node, NodeObject *parent) { @@ -247,6 +247,8 @@ void ModelImporter::initNoodeRoot(const aiNode *node, NodeObject *parent) { /* iterate through each child of parent node. */ for (size_t node_index = 0; node_index < node->mNumChildren; node_index++) { + aiNode *child_node = node->mChildren[node_index]; + unsigned int meshCount = 0; aiVector3D position, scale; aiQuaternion rotation; @@ -254,7 +256,7 @@ void ModelImporter::initNoodeRoot(const aiNode *node, NodeObject *parent) { NodeObject *pobject = new NodeObject(); /* extract position, rotation, position from transformation matrix. */ - node->mChildren[node_index]->mTransformation.Decompose(scale, rotation, position); + child_node->mTransformation.Decompose(scale, rotation, position); if (parent) { pobject->parent = parent; } else { @@ -266,7 +268,7 @@ void ModelImporter::initNoodeRoot(const aiNode *node, NodeObject *parent) { pobject->localRotation = glm::quat(rotation.w, rotation.x, rotation.y, rotation.z); pobject->localScale = glm::vec3(scale.x, scale.y, scale.z); - pobject->modelLocalTransform = aiMatrix4x4ToGlm(&node->mChildren[node_index]->mTransformation); + pobject->modelLocalTransform = aiMatrix4x4ToGlm(&child_node->mTransformation); if (parent) { pobject->modelGlobalTransform = parent->modelGlobalTransform * pobject->modelLocalTransform; @@ -280,14 +282,14 @@ void ModelImporter::initNoodeRoot(const aiNode *node, NodeObject *parent) { if (node->mChildren[node_index]->mMeshes) { /* */ - for (size_t y = 0; y < node->mChildren[node_index]->mNumMeshes; y++) { + for (size_t y = 0; y < child_node->mNumMeshes; y++) { /* Get material for mesh object. */ const MaterialObject &materialRef = - getMaterials()[this->sceneRef->mMeshes[*node->mChildren[node_index]->mMeshes]->mMaterialIndex]; + getMaterials()[this->sceneRef->mMeshes[*child_node->mMeshes]->mMaterialIndex]; /* */ - const int meshIndex = node->mChildren[node_index]->mMeshes[y]; + const int meshIndex = child_node->mMeshes[y]; pobject->materialIndex.push_back(this->sceneRef->mMeshes[meshIndex]->mMaterialIndex); pobject->geometryObjectIndex.push_back(meshIndex); @@ -297,10 +299,12 @@ void ModelImporter::initNoodeRoot(const aiNode *node, NodeObject *parent) { } } + /* */ this->nodes.push_back(pobject); + this->nodeByName[std::string(child_node->mName.C_Str())] = pobject; /* */ - this->initNoodeRoot(node->mChildren[node_index], pobject); + this->initNoodeRoot(child_node, pobject); } } @@ -311,18 +315,29 @@ SkeletonSystem *ModelImporter::initBoneSkeleton(const aiMesh *mesh, unsigned int /* Load bones. */ if (mesh->HasBones()) { - for (uint32_t i = 0; i < mesh->mNumBones; i++) { - const uint32_t BoneIndex = 0; - const std::string BoneName(mesh->mBones[i]->mName.data); + for (uint32_t bone_index = 0; bone_index < mesh->mNumBones; bone_index++) { + + const std::string BoneName(mesh->mBones[bone_index]->mName.data); - glm::mat4 to = aiMatrix4x4ToGlm(&mesh->mBones[i]->mOffsetMatrix); + if (skeleton.bones.find(BoneName) == skeleton.bones.end()) { - Bone bone; - bone.inverseBoneMatrix = to; - bone.name = BoneName; - bone.boneIndex = i; + NodeObject *nodeObj = this->getNodeByName(BoneName); - skeleton.bones[BoneName] = bone; + glm::mat4 nodeGlobalTransform = glm::mat4(1); + if (nodeObj) { + nodeGlobalTransform = nodeObj->modelGlobalTransform; + } + + Bone bone; + bone.name = BoneName; + bone.boneIndex = bone_index; + bone.offsetBoneMatrix = aiMatrix4x4ToGlm(&mesh->mBones[bone_index]->mOffsetMatrix); + bone.finalTransform = + nodeGlobalTransform * bone.offsetBoneMatrix; /* Compute default final transformation*/ + bone.armature_bone = nodeObj; + + skeleton.bones[BoneName] = bone; + } } this->skeletons.push_back(skeleton); @@ -848,8 +863,16 @@ AnimationObject *ModelImporter::initAnimation(const aiAnimation *pAnimation, uns return &this->animations.back(); } + LightObject *ModelImporter::initLight(const aiLight *light, unsigned int index) { - LightObject *lightOb = nullptr; + LightObject *lightOb = &this->lights[index]; + + lightOb->name = light->mName.C_Str(); + lightOb->position = glm::vec3(light->mPosition.x, light->mPosition.y, light->mPosition.z); + lightOb->direction = glm::vec3(light->mDirection.x, light->mDirection.y, light->mDirection.z); + lightOb->mUp = glm::vec3(light->mUp.x, light->mUp.y, light->mUp.z); + + lightOb->mColorDiffuse = glm::vec4(light->mColorDiffuse.r, light->mColorDiffuse.g, light->mColorDiffuse.b, 1); return lightOb; } @@ -923,6 +946,13 @@ struct Face { void ModelImporter::convert2Adjcent(const aiMesh *paiMesh, std::vector &Indices) {} +NodeObject *ModelImporter::getNodeByName(const std::string &name) const noexcept { + if (this->nodeByName.find(name) != this->nodeByName.end()) { + return nodeByName.at(name); + } + return nullptr; +} + std::vector ModelImporter::getMaterials(const size_t texture_index) noexcept { std::vector ref_materials; diff --git a/common/Importer/ModelImporter.h b/common/Importer/ModelImporter.h index 7f7d61e..0093f47 100644 --- a/common/Importer/ModelImporter.h +++ b/common/Importer/ModelImporter.h @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2024 Valdemar Lindberg + * Copyright (c) 2025 Valdemar Lindberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -102,7 +102,6 @@ using MaterialObject = struct material_object_t : public AssetObject { }; using NodeObject = struct node_object_t : public AssetObject { - /* */ glm::vec3 localPosition; glm::quat localRotation; @@ -165,8 +164,10 @@ using ModelSystemObject = struct model_system_object : public AssetObject { }; using Bone = struct bone_t : public AssetObject { - glm::mat4 inverseBoneMatrix{}; + glm::mat4 finalTransform{}; + glm::mat4 offsetBoneMatrix; size_t boneIndex{}; + NodeObject *armature_bone; }; using SkeletonSystem = struct model_skeleton_t : public AssetObject { @@ -203,11 +204,8 @@ using AnimationObject = struct animation_object_t : public AssetObject { using LightObject = struct light_object_t : public AssetObject { // C_ENUM aiLightSourceType mType; - - glm::vec3 mPosition; - - glm::vec3 mDirection; - + glm::vec3 position; + glm::vec3 direction; glm::vec3 mUp; float mAttenuationConstant; @@ -269,6 +267,8 @@ class FVDECLSPEC ModelImporter { void convert2Adjcent(const aiMesh *mesh, std::vector &indices); + NodeObject *getNodeByName(const std::string &name) const noexcept; + public: std::vector getNodes() const noexcept { return this->nodes; } const std::vector &getModels() const noexcept { return this->models; } @@ -295,6 +295,7 @@ class FVDECLSPEC ModelImporter { std::string filepath; aiScene *sceneRef{}; std::vector nodes; + std::map nodeByName; std::vector models; std::vector materials; @@ -308,6 +309,8 @@ class FVDECLSPEC ModelImporter { std::vector animations; std::map vertexBoneData; + std::vector lights; + NodeObject *rootNode{}; glm::mat4 global{}; }; diff --git a/common/Importer/Scene.cpp b/common/Importer/Scene.cpp index 9e55dd9..c177a2e 100644 --- a/common/Importer/Scene.cpp +++ b/common/Importer/Scene.cpp @@ -4,6 +4,8 @@ #include "UIComponent.h" #include "imgui.h" #include +#include +#include #include #include @@ -57,6 +59,7 @@ namespace glsample { for (size_t i = 0; i < arrs.size(); i++) { + // TODO: use common FVALIDATE_GL_CALL(glGenTextures(1, (GLuint *)texRef[i])); FVALIDATE_GL_CALL(glBindTexture(GL_TEXTURE_2D, *texRef[i])); FVALIDATE_GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, arrs[i])); @@ -75,10 +78,20 @@ namespace glsample { glBindTexture(GL_TEXTURE_2D, 0); } + /* Align the uniform buffer size to hardware specific. */ + GLint minMapBufferSize = 0; + glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &minMapBufferSize); + + const size_t node_ubo_size = 100; + const size_t common_ubo_size = Math::align(sizeof(CommonConstantData), minMapBufferSize); + /* */ - glGenBuffers(1, &this->node_uniform_buffer); - glBindBuffer(GL_UNIFORM_BUFFER, this->node_uniform_buffer); + glGenBuffers(1, &this->node_and_common_uniform_buffer); + glBindBuffer(GL_UNIFORM_BUFFER, this->node_and_common_uniform_buffer); glBufferData(GL_UNIFORM_BUFFER, 1 << 16, nullptr, GL_DYNAMIC_DRAW); + + this->stageCommonBuffer = (CommonConstantData *)glMapBufferRange(GL_UNIFORM_BUFFER, 0, common_ubo_size, + GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT); glBindBuffer(GL_UNIFORM_BUFFER, 0); } @@ -89,6 +102,10 @@ namespace glsample { } } + void Scene::updateBuffers() {} + + void Scene::render(Camera *camera) {} + void Scene::render() { // TODO: sort materials and geometry. @@ -242,10 +259,40 @@ namespace glsample { void Scene::renderUI() { - /* */ + /* */ // TODO: add if (ImGui::TreeNode("Nodes")) { + + for (size_t i = 0; i < nodes.size(); i++) { + ImGui::PushID(i); + + ImGui::TextUnformatted(nodes[i]->name.c_str()); + if (ImGui::DragFloat3("Position", &nodes[i]->localPosition[0])) { + glm::mat4 globaMat = + nodes[i]->parent == nullptr ? glm::mat4(1) : nodes[i]->parent->modelGlobalTransform; + nodes[i]->modelGlobalTransform = glm::translate(globaMat, nodes[i]->localPosition); + } + + if (ImGui::DragFloat4("Rotation (Quat)", &nodes[i]->localRotation[0])) { + nodes[i]->localRotation = glm::normalize(nodes[i]->localRotation); + glm::mat4 globaMat = + nodes[i]->parent == nullptr ? glm::mat4(1) : nodes[i]->parent->modelGlobalTransform; + nodes[i]->modelGlobalTransform = + glm::translate(globaMat, nodes[i]->localPosition) * glm::mat4_cast(nodes[i]->localRotation); + } + + ImGui::PopID(); + } + /* */ + ImGui::TreePop(); + } + if (ImGui::BeginChild("Materials")) { + } + ImGui::EndChild(); + + if (ImGui::BeginChild("Textures")) { } + ImGui::EndChild(); } } // namespace glsample \ No newline at end of file diff --git a/common/Importer/Scene.h b/common/Importer/Scene.h index 9c5ea31..13c0fe6 100644 --- a/common/Importer/Scene.h +++ b/common/Importer/Scene.h @@ -18,6 +18,7 @@ #include "GLSampleSession.h" #include "ImportHelper.h" #include "ModelImporter.h" +#include "SampleHelper.h" #include "Skybox.h" #include @@ -73,9 +74,10 @@ namespace glsample { virtual void update(const float deltaTime); - // virtual void updateBuffers(); + virtual void updateBuffers(); - virtual void render(); // TODO, add camera. + virtual void render(Camera *camera); // TODO, add camera. + virtual void render(); virtual void renderNode(const NodeObject *node); @@ -97,6 +99,12 @@ namespace glsample { int computeMaterialPriority(const MaterialObject &material) const noexcept; protected: + using CommonConstantData = struct _common_constant_data_t { + CameraInstance camera; + FrustumInstance frustum; + }; + CommonConstantData* stageCommonBuffer; + /* TODO add queue structure. */ std::deque renderQueue; @@ -110,14 +118,10 @@ namespace glsample { protected: /* Default texture if texture from material is missing.*/ std::array default_textures; - int normalDefault = -1; - int diffuseDefault = -1; - int roughnessSpecularDefault = -1; - int emissionDefault = -1; DebugMode debugMode; - unsigned int node_uniform_buffer; + unsigned int node_and_common_uniform_buffer; public: template static T loadFrom(ModelImporter &importer) { diff --git a/common/PostProcessing/BloomPostProcessing.cpp b/common/PostProcessing/BloomPostProcessing.cpp new file mode 100644 index 0000000..440b159 --- /dev/null +++ b/common/PostProcessing/BloomPostProcessing.cpp @@ -0,0 +1,94 @@ +#include "PostProcessing/BloomPostProcessing.h" +#include "SampleHelper.h" +#include "ShaderLoader.h" +#include + +using namespace glsample; + +BloomPostProcessing::BloomPostProcessing() { this->setName("Bloom"); } + +BloomPostProcessing::~BloomPostProcessing() { + if (this->guassian_blur_compute_program >= 0) { + glDeleteProgram(this->guassian_blur_compute_program); + } +} + +void BloomPostProcessing::initialize(fragcore::IFileSystem *filesystem) { + const char *sobel_compute_path = "Shaders/postprocessingeffects/gaussian_blur.comp.spv"; + + if (this->guassian_blur_compute_program == -1) { + /* */ + const std::vector guassian_blur_compute_binary = + IOUtil::readFileData(sobel_compute_path, filesystem); + + fragcore::ShaderCompiler::CompilerConvertOption compilerOptions; + compilerOptions.target = fragcore::ShaderLanguage::GLSL; + compilerOptions.glslVersion = 420; + + /* */ + this->guassian_blur_compute_program = + ShaderLoader::loadComputeProgram(compilerOptions, &guassian_blur_compute_binary); + } + + glUseProgram(this->guassian_blur_compute_program); + + glGetProgramiv(this->guassian_blur_compute_program, GL_COMPUTE_WORK_GROUP_SIZE, localWorkGroupSize); + + glUniform1i(glGetUniformLocation(this->guassian_blur_compute_program, "texture0"), 0); + + glUseProgram(0); + + // glGenVertexArrays(1, &this->vao); +} + +void BloomPostProcessing::draw(const std::initializer_list> &render_targets) { + unsigned int texture = std::get<1>(*render_targets.begin()); + + /* */ // TODO: relocate + for (auto it = render_targets.begin(); it != render_targets.end(); it++) { + GBuffer target = std::get<0>(*it); + unsigned int texture = std::get<1>(*it); + if (glBindTextureUnit) { + glBindTextureUnit(static_cast(target), texture); + } else { + glActiveTexture(GL_TEXTURE0 + static_cast(target)); + glBindTexture(GL_TEXTURE_2D, texture); + } + } + + this->convert(texture); +} + +void BloomPostProcessing::convert(unsigned int texture) { + + glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); + + GLint width = 0; + GLint height = 0; + + glBindTexture(GL_TEXTURE_2D, texture); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height); + + glUseProgram(this->guassian_blur_compute_program); + + /* */ + glUniform1f(glGetUniformLocation(this->guassian_blur_compute_program, "settings.variance"), 1); + glUniform1f(glGetUniformLocation(this->guassian_blur_compute_program, "settings.mean"), 0); + glUniform1f(glGetUniformLocation(this->guassian_blur_compute_program, "settings.radius"), 2); + glUniform1i(glGetUniformLocation(this->guassian_blur_compute_program, "settings.samples"), 7); + + /* The image where the graphic version will be stored as. */ + glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA16F); + + const unsigned int WorkGroupX = std::ceil(width / (float)localWorkGroupSize[0]); + const unsigned int WorkGroupY = std::ceil(height / (float)localWorkGroupSize[1]); + + if (WorkGroupX > 0 && WorkGroupY > 0) { + + glDispatchCompute(WorkGroupX, WorkGroupY, 1); + } + glUseProgram(0); + + glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); +} diff --git a/common/PostProcessing/BloomPostProcessing.h b/common/PostProcessing/BloomPostProcessing.h new file mode 100644 index 0000000..4534ee9 --- /dev/null +++ b/common/PostProcessing/BloomPostProcessing.h @@ -0,0 +1,45 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 Valdemar Lindberg + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + */ +#pragma once +#include "PostProcessing.h" + +namespace glsample { + + class FVDECLSPEC BloomPostProcessing : public PostProcessing { + + public: + BloomPostProcessing(); + ~BloomPostProcessing() override; + + void initialize(fragcore::IFileSystem *filesystem) override; + + void draw(const std::initializer_list> &render_targets) override; + + public: + void convert(unsigned int texture); + + private: + int guassian_blur_compute_program = -1; + + /* */ + float variance; + int samples; + float radius; + float mean = 0; + + int localWorkGroupSize[3]; + }; +} // namespace glsample diff --git a/common/PostProcessing/BlurPostProcessing.cpp b/common/PostProcessing/BlurPostProcessing.cpp new file mode 100644 index 0000000..49d0615 --- /dev/null +++ b/common/PostProcessing/BlurPostProcessing.cpp @@ -0,0 +1,94 @@ +#include "BlurPostProcessing.h" +#include "SampleHelper.h" +#include "ShaderLoader.h" +#include + +using namespace glsample; + +BlurPostProcessing::BlurPostProcessing() { this->setName("Blur"); } + +BlurPostProcessing::~BlurPostProcessing() { + if (this->guassian_blur_compute_program >= 0) { + glDeleteProgram(this->guassian_blur_compute_program); + } +} + +void BlurPostProcessing::initialize(fragcore::IFileSystem *filesystem) { + const char *sobel_compute_path = "Shaders/postprocessingeffects/gaussian_blur.comp.spv"; + + if (this->guassian_blur_compute_program == -1) { + /* */ + const std::vector guassian_blur_compute_binary = + IOUtil::readFileData(sobel_compute_path, filesystem); + + fragcore::ShaderCompiler::CompilerConvertOption compilerOptions; + compilerOptions.target = fragcore::ShaderLanguage::GLSL; + compilerOptions.glslVersion = 420; + + /* */ + this->guassian_blur_compute_program = + ShaderLoader::loadComputeProgram(compilerOptions, &guassian_blur_compute_binary); + } + + glUseProgram(this->guassian_blur_compute_program); + + glGetProgramiv(this->guassian_blur_compute_program, GL_COMPUTE_WORK_GROUP_SIZE, localWorkGroupSize); + + glUniform1i(glGetUniformLocation(this->guassian_blur_compute_program, "texture0"), 0); + + glUseProgram(0); + + // glGenVertexArrays(1, &this->vao); +} + +void BlurPostProcessing::draw(const std::initializer_list> &render_targets) { + unsigned int texture = std::get<1>(*render_targets.begin()); + + /* */ // TODO: relocate + for (auto it = render_targets.begin(); it != render_targets.end(); it++) { + GBuffer target = std::get<0>(*it); + unsigned int texture = std::get<1>(*it); + if (glBindTextureUnit) { + glBindTextureUnit(static_cast(target), texture); + } else { + glActiveTexture(GL_TEXTURE0 + static_cast(target)); + glBindTexture(GL_TEXTURE_2D, texture); + } + } + + this->convert(texture); +} + +void BlurPostProcessing::convert(unsigned int texture) { + + glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); + + GLint width = 0; + GLint height = 0; + + glBindTexture(GL_TEXTURE_2D, texture); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height); + + glUseProgram(this->guassian_blur_compute_program); + + /* */ + glUniform1f(glGetUniformLocation(this->guassian_blur_compute_program, "settings.variance"), 1); + glUniform1f(glGetUniformLocation(this->guassian_blur_compute_program, "settings.mean"), 0); + glUniform1f(glGetUniformLocation(this->guassian_blur_compute_program, "settings.radius"), 2); + glUniform1i(glGetUniformLocation(this->guassian_blur_compute_program, "settings.samples"), 7); + + /* The image where the graphic version will be stored as. */ + glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA16F); + + const unsigned int WorkGroupX = std::ceil(width / (float)localWorkGroupSize[0]); + const unsigned int WorkGroupY = std::ceil(height / (float)localWorkGroupSize[1]); + + if (WorkGroupX > 0 && WorkGroupY > 0) { + + glDispatchCompute(WorkGroupX, WorkGroupY, 1); + } + glUseProgram(0); + + glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); +} diff --git a/common/PostProcessing/BlurPostProcessing.h b/common/PostProcessing/BlurPostProcessing.h new file mode 100644 index 0000000..56502ca --- /dev/null +++ b/common/PostProcessing/BlurPostProcessing.h @@ -0,0 +1,45 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 Valdemar Lindberg + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + */ +#pragma once +#include "PostProcessing.h" + +namespace glsample { + + class FVDECLSPEC BlurPostProcessing : public PostProcessing { + + public: + BlurPostProcessing(); + ~BlurPostProcessing() override; + + void initialize(fragcore::IFileSystem *filesystem) override; + + void draw(const std::initializer_list> &render_targets) override; + + public: + void convert(unsigned int texture); + + private: + int guassian_blur_compute_program = -1; + + /* */ + float variance; + int samples; + float radius; + float mean = 0; + + int localWorkGroupSize[3]; + }; +} // namespace glsample diff --git a/common/PostProcessing/ColorGradePostProcessing.cpp b/common/PostProcessing/ColorGradePostProcessing.cpp new file mode 100644 index 0000000..fafe899 --- /dev/null +++ b/common/PostProcessing/ColorGradePostProcessing.cpp @@ -0,0 +1,11 @@ +#include "PostProcessing/ColorGradePostProcessing.h" +using namespace glsample; + +ColorGradePostProcessing::ColorGradePostProcessing() { this->setName("ColorGrade"); } +ColorGradePostProcessing::~ColorGradePostProcessing() { + if (this->hue_color_grade_program >= 0) { + glDeleteProgram(this->hue_color_grade_program); + } +} + +void ColorGradePostProcessing::initialize(fragcore::IFileSystem *filesystem) {} diff --git a/common/PostProcessing/ColorGradePostProcessing.h b/common/PostProcessing/ColorGradePostProcessing.h new file mode 100644 index 0000000..2069281 --- /dev/null +++ b/common/PostProcessing/ColorGradePostProcessing.h @@ -0,0 +1,37 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 Valdemar Lindberg + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + */ +#pragma once +#include "PostProcessing.h" + +namespace glsample { + + class FVDECLSPEC ColorGradePostProcessing : public PostProcessing { + + public: + ColorGradePostProcessing(); + ~ColorGradePostProcessing() override; + + void initialize(fragcore::IFileSystem *filesystem) override; + + public: + void convert(unsigned int texture); + + private: + int hue_color_grade_program = -1; + + // int localWorkGroupSize[3]; + }; +} // namespace glsample diff --git a/common/PostProcessing/ColorSpaceConverter.cpp b/common/PostProcessing/ColorSpaceConverter.cpp index 05d8021..e465fa5 100644 --- a/common/PostProcessing/ColorSpaceConverter.cpp +++ b/common/PostProcessing/ColorSpaceConverter.cpp @@ -35,7 +35,7 @@ void ColorSpaceConverter::initialize(fragcore::IFileSystem *filesystem) { fragcore::ShaderCompiler::CompilerConvertOption compilerOptions; compilerOptions.target = fragcore::ShaderLanguage::GLSL; - compilerOptions.glslVersion = 410; + compilerOptions.glslVersion = 420; /* */ this->aes_program = ShaderLoader::loadComputeProgram(compilerOptions, &compute_AES_binary); diff --git a/common/PostProcessing/ColorSpaceConverter.h b/common/PostProcessing/ColorSpaceConverter.h index 592612b..39f6a38 100644 --- a/common/PostProcessing/ColorSpaceConverter.h +++ b/common/PostProcessing/ColorSpaceConverter.h @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2024 Valdemar Lindberg + * Copyright (c) 2025 Valdemar Lindberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/common/PostProcessing/DepthOfFieldPostProcessing.cpp b/common/PostProcessing/DepthOfFieldPostProcessing.cpp new file mode 100644 index 0000000..e69de29 diff --git a/common/PostProcessing/DepthOfFieldPostProcessing.h b/common/PostProcessing/DepthOfFieldPostProcessing.h new file mode 100644 index 0000000..74f6fdd --- /dev/null +++ b/common/PostProcessing/DepthOfFieldPostProcessing.h @@ -0,0 +1,44 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 Valdemar Lindberg + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + */ +#pragma once +#include "PostProcessing.h" + +namespace glsample { + + class FVDECLSPEC DepthOfFieldProcessing : public PostProcessing { + + public: + DepthOfFieldProcessing(); + ~DepthOfFieldProcessing() override; + + void initialize(fragcore::IFileSystem *filesystem) override; + + void draw(const std::initializer_list> &render_targets) override; + + public: + void convert(unsigned int texture); + + private: + int guassian_blur_compute_program = -1; + + /* */ + float variance; + int samples; + float radius; + + // int localWorkGroupSize[3]; + }; +} // namespace glsample diff --git a/common/PostProcessing/MistPostProcessing.cpp b/common/PostProcessing/MistPostProcessing.cpp index 4f41936..e226c61 100644 --- a/common/PostProcessing/MistPostProcessing.cpp +++ b/common/PostProcessing/MistPostProcessing.cpp @@ -1,13 +1,11 @@ #include "MistPostProcessing.h" -#include "Core/Object.h" +#include "SampleHelper.h" #include "ShaderLoader.h" #include using namespace glsample; -MistPostProcessing::MistPostProcessing() { - this->setName("MistFog"); -} +MistPostProcessing::MistPostProcessing() { this->setName("MistFog"); } MistPostProcessing::~MistPostProcessing() { if (this->mist_program >= 0) { @@ -38,12 +36,23 @@ void MistPostProcessing::initialize(fragcore::IFileSystem *filesystem) { glUseProgram(this->mist_program); - glUniform1i(glGetUniformLocation(this->mist_program, "texture0"), 0); - glUniform1i(glGetUniformLocation(this->mist_program, "DepthTexture"), 1); + glUniform1i(glGetUniformLocation(this->mist_program, "texture0"), (int)GBuffer::Albedo); + glUniform1i(glGetUniformLocation(this->mist_program, "DepthTexture"), (int)GBuffer::Depth); glUniform1i(glGetUniformLocation(this->mist_program, "IrradianceTexture"), 2); glUseProgram(0); + /* */ + GLint minMapBufferSize = 0; + glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &minMapBufferSize); + this->uniformAlignSize = Math::align(sizeof(MistUniformBuffer), (size_t)minMapBufferSize); + + /* Create uniform buffer. */ + glGenBuffers(1, &this->uniform_buffer); + glBindBuffer(GL_UNIFORM_BUFFER, this->uniform_buffer); + glBufferData(GL_UNIFORM_BUFFER, this->uniformAlignSize * 1, nullptr, GL_DYNAMIC_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + glGenVertexArrays(1, &this->vao); } @@ -53,6 +62,17 @@ void MistPostProcessing::render(unsigned int skybox, unsigned int frame_texture, glBindVertexArray(this->vao); + /* Update uniform values. */ + glBindBuffer(GL_UNIFORM_BUFFER, this->uniform_buffer); + void *uniformPointer = + glMapBufferRange(GL_UNIFORM_BUFFER, 0 * this->uniformAlignSize, + this->uniformAlignSize, GL_MAP_WRITE_BIT); + memcpy(uniformPointer, &this->mistsettings, sizeof(this->mistsettings)); + glUnmapBuffer(GL_UNIFORM_BUFFER); + + glBindBufferRange(GL_UNIFORM_BUFFER, this->uniform_buffer_binding, this->uniform_buffer, + (1 % 1) * this->uniformAlignSize, this->uniformAlignSize); + glUseProgram(this->mist_program); /* */ @@ -61,11 +81,11 @@ void MistPostProcessing::render(unsigned int skybox, unsigned int frame_texture, glDisable(GL_DEPTH_TEST); /* */ - glActiveTexture(GL_TEXTURE0 + 0); + glActiveTexture(GL_TEXTURE0 + (int)GBuffer::Albedo); glBindTexture(GL_TEXTURE_2D, frame_texture); /* */ - glActiveTexture(GL_TEXTURE0 + 1); + glActiveTexture(GL_TEXTURE0 + (int)GBuffer::Depth); glBindTexture(GL_TEXTURE_2D, depth_texture); /* */ diff --git a/common/PostProcessing/MistPostProcessing.h b/common/PostProcessing/MistPostProcessing.h index c22a732..18a6878 100644 --- a/common/PostProcessing/MistPostProcessing.h +++ b/common/PostProcessing/MistPostProcessing.h @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2024 Valdemar Lindberg + * Copyright (c) 2025 Valdemar Lindberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,6 +25,8 @@ namespace glsample { ~MistPostProcessing() override; using MistUniformBuffer = struct mist_uniform_buffer_t { + glm::mat4 proj; + glm::mat4 viewRotation; CameraInstance instance; FogSettings fogSettings; }; @@ -33,9 +35,13 @@ namespace glsample { void render(unsigned int skybox, unsigned int frame_texture, unsigned int depth_texture); + MistUniformBuffer mistsettings; + private: int mist_program = -1; unsigned int vao = 0; unsigned int uniform_buffer = 0; + unsigned int uniform_buffer_binding; + size_t uniformAlignSize = sizeof(MistUniformBuffer); }; } // namespace glsample diff --git a/common/PostProcessing/PostProcessing.h b/common/PostProcessing/PostProcessing.h index 5c8535f..55ee9fe 100644 --- a/common/PostProcessing/PostProcessing.h +++ b/common/PostProcessing/PostProcessing.h @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2024 Valdemar Lindberg + * Copyright (c) 2025 Valdemar Lindberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -17,6 +17,7 @@ #include "GLSampleSession.h" #include "IO/IFileSystem.h" #include "Math3D/Color.h" +#include "SampleHelper.h" namespace glsample { @@ -29,11 +30,10 @@ namespace glsample { virtual void bind() {}; - virtual void draw() {}; - - virtual bool isEnabled() { return false; } + virtual void draw(const std::initializer_list> &render_targets) {}; protected: + std::vector required_buffer; bool computeShaderSupported = true; }; } // namespace glsample diff --git a/common/PostProcessing/PostProcessingManager.cpp b/common/PostProcessing/PostProcessingManager.cpp new file mode 100644 index 0000000..e915fad --- /dev/null +++ b/common/PostProcessing/PostProcessingManager.cpp @@ -0,0 +1,34 @@ +#include "PostProcessing/PostProcessingManager.h" +#include "PostProcessing/PostProcessing.h" + +using namespace glsample; + +void PostProcessingManager::addPostProcessing(PostProcessing &postProcessing) { + this->postProcessings.push_back(&postProcessing); + this->post_enabled.push_back(false); +} + +size_t PostProcessingManager::getNrPostProcessing() const noexcept { return this->postProcessings.size(); } +PostProcessing &PostProcessingManager::getPostProcessing(const size_t index) { return *this->postProcessings[index]; } + +bool PostProcessingManager::isEnabled(const size_t index) const noexcept { return this->post_enabled[index]; } + +void PostProcessingManager::enablePostProcessing(const size_t index, const bool enabled) { + this->post_enabled[index] = enabled; +} + +void PostProcessingManager::render( + const std::initializer_list> &render_targets) { /* */ + + /* */ + for (size_t i = 0; i < this->getNrPostProcessing(); i++) { + if (this->isEnabled(i)) { + PostProcessing &postprocessing = getPostProcessing(i); + + postprocessing.bind(); + + /* Render. */ + postprocessing.draw(render_targets); + } + } +} \ No newline at end of file diff --git a/common/PostProcessing/PostProcessingManager.h b/common/PostProcessing/PostProcessingManager.h index 84d150d..72eba30 100644 --- a/common/PostProcessing/PostProcessingManager.h +++ b/common/PostProcessing/PostProcessingManager.h @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2024 Valdemar Lindberg + * Copyright (c) 2025 Valdemar Lindberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -14,13 +14,16 @@ * all copies or substantial portions of the Software. */ #pragma once -#include "GLSampleSession.h" -#include "IO/IFileSystem.h" -#include "Math3D/Color.h" #include "PostProcessing.h" +#include "SampleHelper.h" +#include namespace glsample { + /** + * @brief + * + */ class FVDECLSPEC PostProcessingManager : public fragcore::Object { public: PostProcessingManager() = default; @@ -29,8 +32,18 @@ namespace glsample { void addPostProcessing(PostProcessing &postProcessing); size_t getNrPostProcessing() const noexcept; - PostProcessing &getPostProcessing(const size_t index) const noexcept; + PostProcessing &getPostProcessing(const size_t index); + + bool isEnabled(const size_t index) const noexcept; + void enablePostProcessing(const size_t index, const bool enabled); + + /*TODO: Add Swap supported*/ + + void render(const std::initializer_list> &render_targets); protected: + // TODO: shared_pointer + std::vector postProcessings; + std::vector post_enabled; }; } // namespace glsample diff --git a/common/PostProcessing/SSSPostProcessing.h b/common/PostProcessing/SSSPostProcessing.h new file mode 100644 index 0000000..f648456 --- /dev/null +++ b/common/PostProcessing/SSSPostProcessing.h @@ -0,0 +1,44 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 Valdemar Lindberg + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + */ +#pragma once +#include "PostProcessing.h" + +namespace glsample { + + class FVDECLSPEC SSSPostProcessing : public PostProcessing { + + public: + SSSPostProcessing(); + ~SSSPostProcessing() override; + + void initialize(fragcore::IFileSystem *filesystem) override; + + void draw(const std::initializer_list> &render_targets) override; + + public: + void convert(unsigned int texture); + + private: + int guassian_blur_compute_program = -1; + + /* */ + float variance; + int samples; + float radius; + + // int localWorkGroupSize[3]; + }; +} // namespace glsample diff --git a/common/PostProcessing/SobelPostProcessing.cpp b/common/PostProcessing/SobelPostProcessing.cpp index b3c1126..626bb9f 100644 --- a/common/PostProcessing/SobelPostProcessing.cpp +++ b/common/PostProcessing/SobelPostProcessing.cpp @@ -1,7 +1,74 @@ #include "SobelPostProcessing.h" +#include "ShaderLoader.h" +#include using namespace glsample; -SobelProcessing::~SobelProcessing() {} +SobelProcessing::SobelProcessing() { this->setName("Sobel Edge Detection"); } -void SobelProcessing::initialize(fragcore::IFileSystem *filesystem) {} +SobelProcessing::~SobelProcessing() { + if (this->sobel_program >= 0) { + glDeleteProgram(this->sobel_program); + } +} + +void SobelProcessing::initialize(fragcore::IFileSystem *filesystem) { + const char *sobel_compute_path = "Shaders/postprocessingeffects/sobeledgedetection.comp.spv"; + + if (this->sobel_program == -1) { + /* */ + const std::vector sobel_edeg_detection_compute_post_processing_binary = + IOUtil::readFileData(sobel_compute_path, filesystem); + + fragcore::ShaderCompiler::CompilerConvertOption compilerOptions; + compilerOptions.target = fragcore::ShaderLanguage::GLSL; + compilerOptions.glslVersion = 420; + + /* */ + this->sobel_program = ShaderLoader::loadComputeProgram(compilerOptions, &sobel_edeg_detection_compute_post_processing_binary); + } + + glUseProgram(this->sobel_program); + + glUniform1i(glGetUniformLocation(this->sobel_program, "texture0"), 0); + + glUseProgram(0); + + // glGenVertexArrays(1, &this->vao); +} + +void SobelProcessing::draw(const std::initializer_list> &render_targets) { + unsigned int texture = std::get<1>(*render_targets.begin()); + this->render(texture); +} + +void SobelProcessing::render(unsigned int texture) { + glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); + + GLint width = 0; + GLint height = 0; + + glBindTexture(GL_TEXTURE_2D, texture); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height); + + GLint localWorkGroupSize[3]; + + glUseProgram(this->sobel_program); + + glGetProgramiv(this->sobel_program, GL_COMPUTE_WORK_GROUP_SIZE, localWorkGroupSize); + + /* The image where the graphic version will be stored as. */ + glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA16F); + + const unsigned int WorkGroupX = std::ceil(width / (float)localWorkGroupSize[0]); + const unsigned int WorkGroupY = std::ceil(height / (float)localWorkGroupSize[1]); + + if (WorkGroupX > 0 && WorkGroupY > 0) { + + glDispatchCompute(WorkGroupX, WorkGroupY, 1); + } + glUseProgram(0); + + glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); +} diff --git a/common/PostProcessing/SobelPostProcessing.h b/common/PostProcessing/SobelPostProcessing.h index 3b991ec..bdb16e2 100644 --- a/common/PostProcessing/SobelPostProcessing.h +++ b/common/PostProcessing/SobelPostProcessing.h @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2024 Valdemar Lindberg + * Copyright (c) 2025 Valdemar Lindberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -20,12 +20,14 @@ namespace glsample { class FVDECLSPEC SobelProcessing : public PostProcessing { public: - SobelProcessing() = default; + SobelProcessing(); ~SobelProcessing() override; void initialize(fragcore::IFileSystem *filesystem) override; - void convert(unsigned int texture); + void draw(const std::initializer_list> &render_targets) override; + + void render(unsigned int texture); private: int sobel_program = -1; diff --git a/common/SampleHelper.h b/common/SampleHelper.h index f0c3db1..cdfb576 100644 --- a/common/SampleHelper.h +++ b/common/SampleHelper.h @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2024 Valdemar Lindberg + * Copyright (c) 2025 Valdemar Lindberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -21,12 +21,14 @@ namespace glsample { enum class GBuffer : unsigned int { + Albedo = 0, /* */ WorldSpace = 1, /* */ TextureCoordinate = 2, /* */ - Albedo = 0, /* */ Normal = 3, /* */ Specular = 4, /* Roughness*/ Emission = 5, /* */ + Velocity = 7, + Depth = 6 }; // TODO: relocate @@ -38,6 +40,8 @@ namespace glsample { Height /* */ }; + using UnfiformSubBuffer = struct uniform_sub_buffer_t {}; + using GammaCorrectionSettings = struct gamme_correct_settings_t { float exposure = 1.0f; float gamma = 2.2f; @@ -45,12 +49,13 @@ namespace glsample { using FogSettings = struct fog_settings_t { glm::vec4 fogColor = glm::vec4(0.3, 0.3, 0.45, 1); - + /* */ float cameraNear = 0.15f; float cameraFar = 1000.0f; float fogStart = 100; float fogEnd = 1000; + /* */ float fogDensity = 0.1f; FogType fogType = FogType::Exp; float fogIntensity = 1.0f; @@ -88,28 +93,34 @@ namespace glsample { }; using CameraInstance = struct camera_instance_t { - float near; - float far; - float aspect; - float fov; - glm::vec4 position; - glm::vec4 viewDir; - glm::vec4 position_size; + float near = 0.15; + float far = 1000; + float aspect = 1.0; + float fov_radian = 0.9; + glm::vec4 position = glm::vec4(0); + glm::vec4 viewDir = glm::vec4(0, 0, 1, 0); + glm::vec4 position_size = glm::vec4(0); + glm::ivec4 screen_width_padding = glm::ivec4(1); + }; + + using FrustumInstance = struct frustum_instance_t { + glm::vec4 planes[6]; }; - /* Default framebuffer. */ using FrameBuffer = struct framebuffer_t { unsigned int framebuffer; + /* */ unsigned int attachement0; unsigned int intermediate; + unsigned int depthbuffer; }; template inline glm::mat E2GLM(const Eigen::Matrix &em) noexcept { glm::mat mat; - for (int i = 0; i < m; ++i) { - for (int j = 0; j < n; ++j) { + for (unsigned int i = 0; i < m; ++i) { + for (unsigned int j = 0; j < n; ++j) { mat[j][i] = em(i, j); } } @@ -121,7 +132,7 @@ namespace glsample { template inline glm::vec E2GLM(const Eigen::Matrix &em) noexcept { glm::vec v; - for (int i = 0; i < m; ++i) { + for (unsigned int i = 0; i < m; ++i) { v[i] = em(i); } return v; @@ -129,7 +140,7 @@ namespace glsample { template inline Eigen::Matrix GLM2E(const glm::vec &em) noexcept { Eigen::Matrix v; - for (int i = 0; i < m; ++i) { + for (unsigned int i = 0; i < m; ++i) { v(i) = em[i]; } return v; @@ -137,8 +148,8 @@ namespace glsample { template inline Eigen::Matrix GLM2E(const glm::mat &em) noexcept { Eigen::Matrix mat; - for (int i = 0; i < m; ++i) { - for (int j = 0; j < n; ++j) { + for (unsigned int i = 0; i < m; ++i) { + for (unsigned int j = 0; j < n; ++j) { mat(j, i) = em[i][j]; } } diff --git a/common/ShaderLoader.cpp b/common/ShaderLoader.cpp index 1f43966..63b1598 100644 --- a/common/ShaderLoader.cpp +++ b/common/ShaderLoader.cpp @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2024 Valdemar Lindberg + * Copyright (c) 2025 Valdemar Lindberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/common/ShaderLoader.h b/common/ShaderLoader.h index 68c5e25..2d3f761 100644 --- a/common/ShaderLoader.h +++ b/common/ShaderLoader.h @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2024 Valdemar Lindberg + * Copyright (c) 2025 Valdemar Lindberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/common/Skybox.h b/common/Skybox.h index 4c121d4..90fb79b 100644 --- a/common/Skybox.h +++ b/common/Skybox.h @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2024 Valdemar Lindberg + * Copyright (c) 2025 Valdemar Lindberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/common/Util/Camera.h b/common/Util/Camera.h index 79eb8ef..3966e38 100644 --- a/common/Util/Camera.h +++ b/common/Util/Camera.h @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2024 Valdemar Lindberg + * Copyright (c) 2025 Valdemar Lindberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/common/Util/CameraController.h b/common/Util/CameraController.h index a104bfb..33942af 100644 --- a/common/Util/CameraController.h +++ b/common/Util/CameraController.h @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2024 Valdemar Lindberg + * Copyright (c) 2025 Valdemar Lindberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/common/Util/Frustum.h b/common/Util/Frustum.h index 1332ea6..8ca24f6 100644 --- a/common/Util/Frustum.h +++ b/common/Util/Frustum.h @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2024 Valdemar Lindberg + * Copyright (c) 2025 Valdemar Lindberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/common/Util/ProcessDataUtil.cpp b/common/Util/ProcessDataUtil.cpp index 8412db8..7f29292 100644 --- a/common/Util/ProcessDataUtil.cpp +++ b/common/Util/ProcessDataUtil.cpp @@ -46,7 +46,7 @@ void ProcessData::computeIrradiance(unsigned int env_source, unsigned int irradi fragcore::ShaderCompiler::CompilerConvertOption compilerOptions; compilerOptions.target = fragcore::ShaderLanguage::GLSL; - compilerOptions.glslVersion = 410; + compilerOptions.glslVersion = 420; /* */ this->irradiance_program = ShaderLoader::loadComputeProgram(compilerOptions, &compute_irradiance_env_binary); @@ -117,7 +117,7 @@ void ProcessData::computeBump2Normal(unsigned int bump_source, unsigned int norm fragcore::ShaderCompiler::CompilerConvertOption compilerOptions; compilerOptions.target = fragcore::ShaderLanguage::GLSL; - compilerOptions.glslVersion = 410; + compilerOptions.glslVersion = 420; /* */ this->bump2normal_program = diff --git a/common/Util/ProcessDataUtil.h b/common/Util/ProcessDataUtil.h index 10c4f1f..ab94ea8 100644 --- a/common/Util/ProcessDataUtil.h +++ b/common/Util/ProcessDataUtil.h @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2024 Valdemar Lindberg + * Copyright (c) 2025 Valdemar Lindberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal