From 2622b09b456eb53dc3d95096ef7a0b163ce548f3 Mon Sep 17 00:00:00 2001 From: Matthew Zegar Date: Fri, 11 Oct 2024 06:37:22 -0700 Subject: [PATCH 1/3] Shadow shaders... setup shadow map --- shaders/model.ps.hlsl | 3 +- shaders/shadow.ps.hlsl | 9 +++++ shaders/shadow.vs.hlsl | 25 ++++++++++++++ shaders/shadow_map.hlsl | 4 +++ src/components/model/texture.hpp | 3 +- src/render/constant_buffer.hpp | 7 ++-- src/render/shadow_map.cpp | 56 ++++++++++++++++++++++++++++++ src/render/shadow_map.hpp | 29 ++++++++++++++++ src/scene.cpp | 59 ++++++++++++++++++++++++++------ src/scene.hpp | 10 +++++- 10 files changed, 188 insertions(+), 17 deletions(-) create mode 100644 shaders/shadow.ps.hlsl create mode 100644 shaders/shadow.vs.hlsl create mode 100644 shaders/shadow_map.hlsl create mode 100644 src/render/shadow_map.cpp create mode 100644 src/render/shadow_map.hpp diff --git a/shaders/model.ps.hlsl b/shaders/model.ps.hlsl index 7cc7a06..f69738c 100644 --- a/shaders/model.ps.hlsl +++ b/shaders/model.ps.hlsl @@ -16,6 +16,7 @@ struct PSOutput Texture2D Texture : register(t0); TextureCube CubeMapTexture : register(t1); +Texture2D ShadowMap : register(t2); SamplerState TextureSampler : register(s0); float4 CalculateDirectionalLight(PSInput input) @@ -52,7 +53,7 @@ PSOutput Main(PSInput input) { PSOutput output; - float4 modelTexture = float4(Texture.Sample(TextureSampler, input.TexCoords).rgb, 1.0f); + float4 modelTexture = float4(ShadowMap.Sample(TextureSampler, input.TexCoords).rgb, 1.0f); float4 cubeMapReflection = CalculateCubeMapReflection(input); float4 lighting = CalculateDirectionalLight(input); diff --git a/shaders/shadow.ps.hlsl b/shaders/shadow.ps.hlsl new file mode 100644 index 0000000..0722d8b --- /dev/null +++ b/shaders/shadow.ps.hlsl @@ -0,0 +1,9 @@ +// We only use the depth map for shadow mapping. +struct PSInput +{ + float4 Position : SV_Position; +}; + +void Main(PSInput input) +{ +} diff --git a/shaders/shadow.vs.hlsl b/shaders/shadow.vs.hlsl new file mode 100644 index 0000000..c046aeb --- /dev/null +++ b/shaders/shadow.vs.hlsl @@ -0,0 +1,25 @@ +#include "util.hlsl" +#include "camera_matrix.hlsl" +#include "model_matrix.hlsl" +#include "shadow_map.hlsl" + +struct VSInput +{ + float3 Position : POSITION; + float3 Normal : NORMAL; + float2 TexCoords : TEXCOORD; +}; + +struct VSOutput +{ + float4 Position : SV_Position; +}; + +VSOutput Main(VSInput input) +{ + float4 worldPosition = mul(ModelMatrix, float4(input.Position, 1.0f)); + + VSOutput output; + output.Position = mul(LightSpaceMatrix, worldPosition); + return output; +} diff --git a/shaders/shadow_map.hlsl b/shaders/shadow_map.hlsl new file mode 100644 index 0000000..6e4c0bc --- /dev/null +++ b/shaders/shadow_map.hlsl @@ -0,0 +1,4 @@ +cbuffer ShadowMap : register(b3) +{ + matrix LightSpaceMatrix; +}; diff --git a/src/components/model/texture.hpp b/src/components/model/texture.hpp index 99ed21f..d36e705 100644 --- a/src/components/model/texture.hpp +++ b/src/components/model/texture.hpp @@ -9,7 +9,8 @@ enum class TextureType { DIFFUSE, - SKYBOX + SKYBOX, + SHADOW_MAP }; class Texture diff --git a/src/render/constant_buffer.hpp b/src/render/constant_buffer.hpp index 4c850a9..734cda0 100644 --- a/src/render/constant_buffer.hpp +++ b/src/render/constant_buffer.hpp @@ -8,9 +8,10 @@ enum class ConstantType { - CAMERA_MATRIX = 0, - MODEL_MATRIX = 1, - DIRECTIONAL_LIGHT = 2, + CAMERA_MATRIX, + MODEL_MATRIX, + DIRECTIONAL_LIGHT, + SHADOW_MAP, }; template diff --git a/src/render/shadow_map.cpp b/src/render/shadow_map.cpp new file mode 100644 index 0000000..d47338e --- /dev/null +++ b/src/render/shadow_map.cpp @@ -0,0 +1,56 @@ +#include "shadow_map.hpp" + +#include "components/model/texture.hpp" +#include "renderer.hpp" +#include "log.hpp" + +ShadowMap::ShadowMap() : _constantBuffer(ConstantType::SHADOW_MAP, ShadowMapBuffer{}) +{ + Microsoft::WRL::ComPtr depthStencilTexture; + + D3D11_TEXTURE2D_DESC shadowMapDesc = {}; + shadowMapDesc.Width = 4096; + shadowMapDesc.Height = 4096; + shadowMapDesc.MipLevels = 1; + shadowMapDesc.ArraySize = 1; + shadowMapDesc.Format = DXGI_FORMAT_R24G8_TYPELESS; + shadowMapDesc.SampleDesc.Count = 1; + shadowMapDesc.Usage = D3D11_USAGE_DEFAULT; + shadowMapDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE; + + if (FAILED(Renderer::GetDevice()->CreateTexture2D(&shadowMapDesc, nullptr, &depthStencilTexture))) + LOG(ERROR) << "Failed to create depth stencil texture"; + + D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc = {}; + shaderResourceViewDesc.Format = DXGI_FORMAT_R24_UNORM_X8_TYPELESS; + shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + shaderResourceViewDesc.Texture2D.MostDetailedMip = 0; + shaderResourceViewDesc.Texture2D.MipLevels = 1; + + if (FAILED(Renderer::GetDevice()->CreateShaderResourceView(depthStencilTexture.Get(), &shaderResourceViewDesc, &_shaderResourceView))) + LOG(ERROR) << "Failed to create shader resource view description"; + + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc = {}; + dsvDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; + dsvDesc.Texture2D.MipSlice = 0; + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + + if (FAILED(Renderer::GetDevice()->CreateDepthStencilView(depthStencilTexture.Get(), &dsvDesc, &_depthStencilView))) + LOG(ERROR) << "Failed to create depth stencil resource view"; +} + +void ShadowMap::Bind() +{ + Renderer::GetDeviceContext()->OMSetRenderTargets(0, nullptr, _depthStencilView.Get()); +} + +void ShadowMap::AssignMap() +{ + Renderer::GetDeviceContext()->PSSetShaderResources((int)TextureType::SHADOW_MAP, 1, _shaderResourceView.GetAddressOf()); +} + +void ShadowMap::SetLightSpaceMatrix(const glm::mat4 &matrix) +{ + _constantBuffer.Update(ShadowMapBuffer{matrix}); + _constantBuffer.Bind(); +} diff --git a/src/render/shadow_map.hpp b/src/render/shadow_map.hpp new file mode 100644 index 0000000..a551ebc --- /dev/null +++ b/src/render/shadow_map.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include "constant_buffer.hpp" + +#include + +#include +#include +#include + +class ShadowMap +{ +public: + struct ShadowMapBuffer + { + glm::mat4 LightSpaceMatrix; + }; + + ShadowMap(); + + void Bind(); + void AssignMap(); + void SetLightSpaceMatrix(const glm::mat4 &matrix); + +private: + ConstantBuffer _constantBuffer; + Microsoft::WRL::ComPtr _shaderResourceView; + Microsoft::WRL::ComPtr _depthStencilView; +}; diff --git a/src/scene.cpp b/src/scene.cpp index acac690..081c491 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -7,12 +7,16 @@ #include "components/model/model_component.hpp" #include +#include Scene::Scene() : _renderTarget(RenderTarget()), + _shadowMap(ShadowMap()), _camera(Camera()), _skybox(SkyBox()), _modelVertexShader(L"shaders/model.vs.hlsl"), - _modelPixelShader(L"shaders/model.ps.hlsl") + _modelPixelShader(L"shaders/model.ps.hlsl"), + _shadowVertexShader(L"shaders/shadow.vs.hlsl"), + _shadowPixelShader(L"shaders/shadow.ps.hlsl") { ActiveScene = this; @@ -78,17 +82,42 @@ void Scene::Render() _camera.Update(); CalculateDeltaTime(); + ShadowPass(); + NormalPass(); + + _pxScene->simulate(1.0f / 60.0f); + _pxScene->fetchResults(true); +} + +void Scene::ShadowPass() +{ + _shadowMap.Bind(); + + auto matrix = glm::mat4(); + + const auto lightGroup = Scene::ActiveScene->Registry.view(entt::exclude); + for (const auto &entity : lightGroup) + { + auto &transform = lightGroup.get(entity); + + const auto lightProjection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, 0.1f, 10.0f); + const auto lightView = glm::lookAt(transform.GetPosition(), transform.GetPosition() + transform.GetDirection(), glm::vec3(0.0, 1.0, 0.0)); + _shadowMap.SetLightSpaceMatrix(lightProjection * lightView); + } + + RenderModels(_shadowVertexShader, _shadowPixelShader); +} + +void Scene::NormalPass() +{ _renderTarget.Bind(); - RenderModels(); + RenderModels(_modelVertexShader, _modelPixelShader); RenderSkyBox(); RenderLight(); - - _pxScene->simulate(1.0f / 60.0f); - _pxScene->fetchResults(true); } -void Scene::RenderModels() +void Scene::RenderModels(const VertexShader &vs, const PixelShader &ps) { _renderTarget.SetMode(RenderTarget::Mode::Default); @@ -98,10 +127,12 @@ void Scene::RenderModels() auto &transform = modelGroup.get(entity); const auto &model = modelGroup.get(entity); - _modelVertexShader.Bind(); - _modelPixelShader.Bind(); - transform.Bind(); + vs.Bind(); + ps.Bind(); + _shadowMap.AssignMap(); + + transform.Bind(); model.Render(); } } @@ -169,10 +200,16 @@ void Scene::InitializeDefaultScene() Registry.get(floor).SetPosition(glm::vec3(0.0f, -1.0f, 0.0f)); Registry.emplace(floor, floor).LoadModel("models\\plane\\plane.obj"); + // Temp cube + auto cube = CreateNewEntity(); + Registry.get(cube).Name = "Cube"; + Registry.get(cube).SetPosition(glm::vec3(0.0f, -0.5f, 3.2f)); + Registry.emplace(cube, cube).LoadModel("models\\dev_orange_cube\\dev_orange_cube.obj"); + // Sun auto sun = CreateNewEntity(); Registry.get(sun).Name = "Sun"; - Registry.get(sun).SetPosition(glm::vec3(-10.0f, 0.0f, 0.0f)); - Registry.get(sun).SetRotation(glm::vec3(2.0f, 0.0f, 0.4f)); + Registry.get(sun).SetPosition(glm::vec3(0.0f, 0.0f, 4.0f)); + Registry.get(sun).SetRotation(glm::vec3(1.5f, 0.0f, 0.0f)); Registry.emplace(sun, sun); } diff --git a/src/scene.hpp b/src/scene.hpp index 70e7939..c245095 100644 --- a/src/scene.hpp +++ b/src/scene.hpp @@ -5,6 +5,7 @@ #include "render/vertex_shader.hpp" #include "render/pixel_shader.hpp" #include "render/render_target.hpp" +#include "render/shadow_map.hpp" #include "render/skybox.hpp" #include @@ -41,9 +42,13 @@ class Scene VertexShader _modelVertexShader; PixelShader _modelPixelShader; + VertexShader _shadowVertexShader; + PixelShader _shadowPixelShader; + SkyBox _skybox; RenderTarget _renderTarget; + ShadowMap _shadowMap; physx::PxDefaultAllocator _pxAllocator; physx::PxDefaultErrorCallback _pxErrorCallback; @@ -56,7 +61,10 @@ class Scene float _previousFrameTime; float _deltaTime; - void RenderModels(); + void ShadowPass(); + void NormalPass(); + + void RenderModels(const VertexShader &vs, const PixelShader &ps); void RenderSkyBox(); void RenderLight(); From d055e87475fc48e7e5c0987da61a548fd2d2881d Mon Sep 17 00:00:00 2001 From: Matthew Zegar Date: Mon, 14 Oct 2024 11:25:55 -0700 Subject: [PATCH 2/3] Update shaders to support shadows --- shaders/model.ps.hlsl | 18 ++++++++++++++---- shaders/model.vs.hlsl | 5 ++++- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/shaders/model.ps.hlsl b/shaders/model.ps.hlsl index f69738c..19694d2 100644 --- a/shaders/model.ps.hlsl +++ b/shaders/model.ps.hlsl @@ -4,7 +4,8 @@ struct PSInput { float4 Position : SV_Position; - float3 FragPosition : POSITION; + float3 FragPosition : POSITION0; + float4 FragPositionLightSpace : POSITION1; float3 Normal : NORMAL; float2 TexCoords : TEXCOORD; }; @@ -19,6 +20,15 @@ TextureCube CubeMapTexture : register(t1); Texture2D ShadowMap : register(t2); SamplerState TextureSampler : register(s0); +float CalculateShadows(PSInput input) +{ + float3 projCoords = input.FragPositionLightSpace.xyz / input.FragPositionLightSpace.w; + projCoords = projCoords * 0.5f + 0.5f; + float closestDepth = ShadowMap.Sample(TextureSampler, projCoords.xy).r; + float currentDepth = projCoords.z; + return currentDepth > closestDepth ? 1.0 : 0.0f; +} + float4 CalculateDirectionalLight(PSInput input) { // ambient @@ -36,9 +46,9 @@ float4 CalculateDirectionalLight(PSInput input) float spec = pow(max(dot(normal, halfWayDirection), 0.0f), 32.0f); // material shininess float3 specular = DirectionalLightSpecular * spec; - // TODO: calculate shadows here. + float shadow = CalculateShadows(input); - float3 result = ambient * (diffuse + specular); + float3 result = ambient + (1.0 - shadow) * (diffuse + specular); return float4(result, 1.0f); } @@ -53,7 +63,7 @@ PSOutput Main(PSInput input) { PSOutput output; - float4 modelTexture = float4(ShadowMap.Sample(TextureSampler, input.TexCoords).rgb, 1.0f); + float4 modelTexture = float4(Texture.Sample(TextureSampler, input.TexCoords).rgb, 1.0f); float4 cubeMapReflection = CalculateCubeMapReflection(input); float4 lighting = CalculateDirectionalLight(input); diff --git a/shaders/model.vs.hlsl b/shaders/model.vs.hlsl index 991ca59..7cde889 100644 --- a/shaders/model.vs.hlsl +++ b/shaders/model.vs.hlsl @@ -1,6 +1,7 @@ #include "util.hlsl" #include "camera_matrix.hlsl" #include "model_matrix.hlsl" +#include "shadow_map.hlsl" struct VSInput { @@ -12,7 +13,8 @@ struct VSInput struct VSOutput { float4 Position : SV_Position; - float3 FragPosition : POSITION; + float3 FragPosition : POSITION0; + float4 FragPositionLightSpace : POSITION1; float3 Normal : NORMAL; float2 TexCoords : TEXCOORD; }; @@ -25,6 +27,7 @@ VSOutput Main(VSInput input) VSOutput output; output.Position = mul(viewProjectionMatrix, worldPosition); output.FragPosition = worldPosition.xyz; + output.FragPositionLightSpace = mul(LightSpaceMatrix, worldPosition); output.Normal = mul(transpose(inverse(ModelMatrix)), input.Normal); output.TexCoords = input.TexCoords; return output; From 33935813249d0e26c9936820574d30b4fbdc224b Mon Sep 17 00:00:00 2001 From: Matthew Zegar Date: Thu, 17 Oct 2024 13:15:52 -0700 Subject: [PATCH 3/3] Position light source --- imgui.ini | 16 ++++++++-------- src/scene.cpp | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/imgui.ini b/imgui.ini index 4a93b37..a0a897b 100644 --- a/imgui.ini +++ b/imgui.ini @@ -1,17 +1,17 @@ [Window][InvisibleWindow] Pos=0,0 -Size=1400,900 +Size=2560,1351 Collapsed=0 [Window][Console] -Pos=230,715 -Size=828,185 +Pos=230,1166 +Size=1988,185 Collapsed=0 DockId=0x00000002,0 [Window][Scene] Pos=230,0 -Size=828,713 +Size=1988,1164 Collapsed=0 DockId=0x00000001,0 @@ -22,18 +22,18 @@ Collapsed=0 [Window][Entities] Pos=0,0 -Size=228,900 +Size=228,1351 Collapsed=0 DockId=0x00000003,0 [Window][Inspector] -Pos=1060,0 -Size=340,900 +Pos=2220,0 +Size=340,1351 Collapsed=0 DockId=0x00000006,0 [Docking][Data] -DockSpace ID=0xF442860A Window=0xD8117908 Pos=329,358 Size=1400,900 Split=X Selected=0xE192E354 +DockSpace ID=0xF442860A Window=0xD8117908 Pos=0,29 Size=2560,1351 Split=X Selected=0xE192E354 DockNode ID=0x00000005 Parent=0xF442860A SizeRef=1058,900 Split=X DockNode ID=0x00000003 Parent=0x00000005 SizeRef=228,900 Selected=0xA628E342 DockNode ID=0x00000004 Parent=0x00000005 SizeRef=1988,900 Split=Y diff --git a/src/scene.cpp b/src/scene.cpp index 081c491..a14e9f6 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -209,7 +209,7 @@ void Scene::InitializeDefaultScene() // Sun auto sun = CreateNewEntity(); Registry.get(sun).Name = "Sun"; - Registry.get(sun).SetPosition(glm::vec3(0.0f, 0.0f, 4.0f)); - Registry.get(sun).SetRotation(glm::vec3(1.5f, 0.0f, 0.0f)); + Registry.get(sun).SetPosition(glm::vec3(0.0f, -20.0f, 30.0f)); + Registry.get(sun).SetRotation(glm::vec3(0.7f, 0.0f, 0.0f)); Registry.emplace(sun, sun); }