CSM first cascade working

This commit is contained in:
antopilo
2025-01-11 21:23:49 -05:00
parent 3193ebd062
commit 890b1c44b2
4 changed files with 130 additions and 26 deletions

View File

@@ -62,13 +62,14 @@ void VkSceneRenderer::Init()
void VkSceneRenderer::BeginScene(RenderContext inContext)
{
GPUResources::Get().ClearCameras();
Context.CommandBuffer = inContext.CommandBuffer;
Context.CurrentScene = inContext.CurrentScene;
Context.CameraID = inContext.CameraID;
// Collect all global transform of things we will render
BuildMatrixBuffer();
UpdateTransformBuffer();
auto& cmd = Context.CommandBuffer;
auto& scene = Context.CurrentScene;
@@ -115,6 +116,7 @@ void VkSceneRenderer::BeginScene(RenderContext inContext)
}
// Build light view list
{
auto view = scene->m_Registry.view<TransformComponent, LightComponent>();
for (auto e : view)
@@ -136,13 +138,21 @@ void VkSceneRenderer::BeginScene(RenderContext inContext)
}
}
}
BuildMatrixBuffer();
UpdateTransformBuffer();
{
auto view = scene->m_Registry.view<TransformComponent, LightComponent>();
for (auto e : view)
{
auto [transform, light] = view.get<TransformComponent, LightComponent>(e);
auto cam = GPUResources::Get().GetCamera(inContext.CameraID);
light.CalculateViewProjection(cam.View, cam.Projection);
if (light.Type == LightType::Directional)
{
light.CalculateViewProjection(cam.View, cam.Projection);
}
}
}
@@ -154,6 +164,7 @@ void VkSceneRenderer::BeginScene(RenderContext inContext)
passCtx.commandBuffer = inContext.CommandBuffer;
passCtx.resolution = Context.Size;
auto view = scene->m_Registry.view<TransformComponent, LightComponent>();
for (auto e : view)
{
@@ -166,10 +177,13 @@ void VkSceneRenderer::BeginScene(RenderContext inContext)
passCtx.cameraID = GPUResources::Get().GetBindlessCameraID(light.m_LightViews[0].CameraID);
ShadowPipeline.Execute(passCtx);
light.LightMapID = ShadowPipeline.GetRenderPass("Shadow").GetDepthAttachment().Image->GetID();
//passCtx.cameraID = GPUResources::Get().GetBindlessCameraID(light.m_LightViews[0].CameraID);
for (int i = 0; i < CSM_AMOUNT; i++)
{
//ShadowPipeline.Execute(passCtx);
}
}
@@ -192,11 +206,12 @@ void VkSceneRenderer::EndScene()
auto& selectedOutput = shading;
selectedOutput.Image->TransitionLayout(cmd, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
vk.DrawImage->TransitionLayout(cmd, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
shadow.Image->TransitionLayout(cmd, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
VulkanUtil::CopyImageToImage(cmd, selectedOutput.Image->GetImage(), vk.GetDrawImage()->GetImage(), selectedOutput.Image->GetSize(), vk.DrawImage->GetSize());
vk.DrawImage->TransitionLayout(cmd, VK_IMAGE_LAYOUT_GENERAL);
selectedOutput.Image->TransitionLayout(cmd, VK_IMAGE_LAYOUT_GENERAL);
GPUResources::Get().ClearCameras();
}
void VkSceneRenderer::CreateBuffers()
@@ -835,6 +850,9 @@ void VkSceneRenderer::BuildMatrixBuffer()
light.type = lightComp.Type;
light.color = Vector4(lightComp.Color * lightComp.Strength, 1.0);
light.castShadow = lightComp.CastShadows;
light.transformId = GPUResources::Get().GetBindlessCameraID(lightComp.m_LightViews[0].CameraID);
light.shadowMapTextureId = GPUResources::Get().GetBindlessTextureID(lightComp.LightMapID);
allLights[currentIndex] = light;
currentIndex++;

View File

@@ -51,9 +51,11 @@ namespace Nuake
float mCascadeSplits[CSM_AMOUNT];
public:
LightComponent();
~LightComponent() = default;
UUID LightMapID;
void SetCastShadows(bool toggle);
Matrix4 GetProjection();
@@ -62,13 +64,18 @@ namespace Nuake
void CalculateViewProjection(glm::mat4& view, const glm::mat4& projection)
{
Matrix4 normalProj = projection;
// Convert to normal Z
//normalProj[2][2] = -normalProj[2][2]; // Restore the sign
//normalProj[2][3] = -normalProj[2][3]; // Restore the far depth term sign
//normalProj *= -1.0f;
glm::mat4 viewProjection = normalProj * view;
glm::mat4 inverseViewProjection = glm::inverse(viewProjection);
// TODO: Automate this
const float nearClip = 0.01f;
const float farClip = 800.0f;
const float farClip = 200.0f;
const float clipRange = farClip - nearClip;
const float mCascadeNearPlaneOffset = -100.0f;
@@ -100,16 +107,16 @@ namespace Nuake
glm::vec4 frustumCorners[8] =
{
//Near face
{ 1.0f, 1.0f, -1.0f, 1.0f },
{ -1.0f, 1.0f, -1.0f, 1.0f },
{ 1.0f, -1.0f, -1.0f, 1.0f },
{ -1.0f, -1.0f, -1.0f, 1.0f },
{ 1.0f, -1.0f, 1.0f, 1.0f },
{ -1.0f, -1.0f, 1.0f, 1.0f },
{ 1.0f, 1.0f, 1.0f, 1.0f },
{ -1.0f, 1.0f, 1.0f, 1.0f },
//Far face
{ 1.0f, 1.0f, 1.0f, 1.0f },
{ -1.0f, 1.0f, 1.0f, 1.0f },
{ 1.0f, -1.0f, 1.0f, 1.0f },
{ -1.0f, -1.0f, 1.0f, 1.0f },
// Far face (z = 0.0)
{ 1.0f, -1.0f, 0.0f, 1.0f },
{ -1.0f, -1.0f, 0.0f, 1.0f },
{ 1.0f, 1.0f, 0.0f, 1.0f },
{ -1.0f, 1.0f, 0.0f, 1.0f },
};
// Project frustum corners into world space from clip space
@@ -144,19 +151,41 @@ namespace Nuake
// Calculate the view and projection matrix
glm::vec3 lightDir = -this->Direction;
glm::mat4 lightViewMatrix = glm::lookAt(frustumCenter - lightDir * -minExtents.z, frustumCenter, glm::vec3(0.0f, 0.0f, 1.0f));
lightDir.y *= -1.0f;
lightDir.x *= -1.0f;
lightDir.z *= -1.0f;
glm::mat4 lightViewMatrix = glm::lookAt(frustumCenter - lightDir * -minExtents.z, frustumCenter, glm::vec3(0.0f, 1.0, 0.0f));
glm::mat4 lightProjectionMatrix = glm::ortho(minExtents.x, maxExtents.x, minExtents.y, maxExtents.y, 0.0f + mCascadeNearPlaneOffset, maxExtents.z - minExtents.z + mCascadeFarPlaneOffset);
//lightDir.y *= -1.0f;
//
//glm::mat4 lightViewMatrix = glm::lookAt(
// frustumCenter + lightDir * -minExtents.z,
// frustumCenter,
// glm::vec3(0.0f, 1.0f, 0.0f)
//);
//glm::mat4 lightProjectionMatrix = glm::ortho(
// minExtents.x, maxExtents.x,
// minExtents.y, maxExtents.y, // Y-flip for Vulkan
// 0.0f + mCascadeNearPlaneOffset,
// maxExtents.z - minExtents.z + mCascadeFarPlaneOffset
//);
//lightProjectionMatrix = glm::ortho(-25.0f, 25.0f, -25.0f, 25.0f, 100.0f, -100.0f);
// Offset to texel space to avoid shimmering ->(https://stackoverflow.com/questions/33499053/cascaded-shadow-map-shimmering)
glm::mat4 shadowMatrix = lightProjectionMatrix * lightViewMatrix;
const float ShadowMapResolution = 4096;
glm::vec4 shadowOrigin = (shadowMatrix * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)) * ShadowMapResolution / 2.0f;
glm::vec4 roundedOrigin = glm::round(shadowOrigin);
glm::vec4 roundOffset = roundedOrigin - shadowOrigin;
roundOffset = roundOffset * 2.0f / ShadowMapResolution;
roundOffset.z = 0.0f;
roundOffset.w = 0.0f;
lightProjectionMatrix[3] += roundOffset;
//const float ShadowMapResolution = 4096;
//glm::vec4 shadowOrigin = (shadowMatrix * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)) * ShadowMapResolution / 2.0f;
//glm::vec4 roundedOrigin = glm::round(shadowOrigin);
//glm::vec4 roundOffset = roundedOrigin - shadowOrigin;
//roundOffset = roundOffset * 2.0f / ShadowMapResolution;
//roundOffset.z = 0.0f;
//roundOffset.w = 0.0f;
//lightProjectionMatrix[3] += roundOffset;
float near_plane = 0.01f, far_plane = 100.0f;
//glm::mat4 lightProjection = glm::ortho(-25.0f, 25.0f, -25.0f, 25.0f, 25.0f, -25.0f);
//lightProjectionMatrix[2][2] = -lightProjectionMatrix[2][2]; // Flip the sign
//lightProjectionMatrix[2][3] = -lightProjectionMatrix[2][3]; // Flip the sign of the far depth term
m_LightViews[cascade].View = lightViewMatrix;
m_LightViews[cascade].Proj = lightProjectionMatrix;
@@ -166,6 +195,8 @@ namespace Nuake
mViewProjections[cascade] = shadowMatrix;
lastSplitDist = mCascadeSplits[cascade];
// -----------------------Debug only-----------------------
// RendererDebug::BeginScene(viewProjection);
// RendererDebug::SubmitCameraFrustum(frustumCorners, glm::mat4(1.0f), GetColor(cascade)); // Draws the divided camera frustums

View File

@@ -150,6 +150,32 @@ float3 fresnelSchlickRoughness(float cosTheta, float3 F0, float roughness)
return F0 + (max(float3(roughnessTerm, roughnessTerm, roughnessTerm), F0) - F0) * pow(max(1.0 - cosTheta, 0.0), 5.0);
}
float linearDepth(float z, float near, float far) {
return near * far / (far - z * (far - near));
}
float ShadowCalculation(Light light, float3 fragPos, float3 normal)
{
CameraView camView = cameras[pushConstants.CameraID];
float depth = length(fragPos - camView.Position);
CameraView lightView = cameras[light.transformId];
int shadowMap = light.shadowMapTextureId;
float4 fragLightSpace = mul(lightView.Projection, mul(lightView.View, float4(fragPos, 1.0)));
float3 projCoords = fragLightSpace.xyz / fragLightSpace.w;
projCoords.xy = projCoords.xy * 0.5 + 0.5;
if (projCoords.x < 0.0 || projCoords.x > 1.0 || projCoords.y < 0.0 || projCoords.y > 1.0) {
return 1.0;
}
//projCoords.y = 1.0 - projCoords.y;
float currentDepth = projCoords.z;
float bias = max(0.005 * (1.0 - dot(normal, light.direction)), 0.0005);
float shadowMapDepth = textures[light.shadowMapTextureId].Sample(mySampler, projCoords.xy).r;
return (currentDepth > shadowMapDepth);//> 0.0 ? 1.0 : 0.0;
}
PSOutput main(PSInput input)
{
PSOutput output;
@@ -193,6 +219,13 @@ PSOutput main(PSInput input)
const float PI = 3.141592653589793f;
float3 Lo = float3(0.0, 0.0, 0.0);
float shadow = 1.0f;
if(foundDirectional == false)
{
shadow = 1.0f;
}
//Directional
if(foundDirectional)
{
@@ -200,6 +233,13 @@ PSOutput main(PSInput input)
float3 L = normalize(light.direction);
float attenuation = 1.0f;
if(light.castShadow == true)
{
shadow *= ShadowCalculation(light, worldPos, N);
//output.oColor0 = float4(albedo * 0.1 + float3(shadow, shadow, shadow), 1);
//return output;
}
// TODO: Shadow
float3 radiance = light.color.rgb * attenuation;
float3 H = normalize(V + L);
@@ -216,7 +256,7 @@ PSOutput main(PSInput input)
kD *= 1.0 - metallic;
float NdotL = max(dot(N, L), 0.0);
Lo += (kD * albedo / PI + specular) * radiance * NdotL;
Lo += (kD * albedo / PI + specular) * radiance * NdotL * shadow;
}
// other lights

View File

@@ -73,6 +73,20 @@ struct VSOutput {
float4 Position : SV_Position;
};
float LinearizeDepth(float depth, float nearPlane, float farPlane, bool reverseDepth)
{
if (reverseDepth)
{
// Reverse depth (near plane = 1.0, far plane = 0.0)
return nearPlane * farPlane / lerp(farPlane, nearPlane, depth);
}
else
{
// Standard depth (near plane = 0.0, far plane = 1.0)
return (2.0 * nearPlane * farPlane) / (farPlane + nearPlane - depth * (farPlane - nearPlane));
}
}
// Main vertex shader
VSOutput main(uint vertexIndex : SV_VertexID)
{
@@ -89,5 +103,6 @@ VSOutput main(uint vertexIndex : SV_VertexID)
// Output the position of each vertex
output.Position = mul(camView.Projection, mul(camView.View,mul(modelData.model, float4(v.position, 1.0f))));
//output.Position.z = LinearizeDepth(output.Position.z, camView.Near, camView.Far, false);
return output;
}