mirror of
https://github.com/antopilo/Nuake.git
synced 2026-09-15 20:08:54 +03:00
CSM first cascade working
This commit is contained in:
@@ -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++;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user