diff --git a/res/shaders/BasePass.slang b/res/shaders/BasePass.slang index 137316c..1b1426a 100644 --- a/res/shaders/BasePass.slang +++ b/res/shaders/BasePass.slang @@ -17,15 +17,24 @@ float4 fragmentMain(in FragmentParameter params) : SV_Target LightingParameter lightingParams = params.getLightingParameter(); MaterialParameter materialParams = params.getMaterialParameter(); var brdf = Material.prepare(materialParams); + brdf.setNormal(normalize(params.normal_WS)); uint2 tileIndex = uint2(floor(params.position_CS.xy / BLOCK_SIZE)); uint startOffset = pLightCullingData.lightGrid[tileIndex].x; uint lightCount = pLightCullingData.lightGrid[tileIndex].y; float3 result = float3(0, 0, 0); for(int i = 0; i < pLightEnv.numDirectionalLights; ++i) { - result += pLightEnv.directionalLights[i].illuminate(lightingParams, brdf); + float4 lightSpacePos = mul(pLightEnv.directionalLights[i].lightSpaceMatrix, float4(params.position_WS, 1)); + float3 projCoords = lightSpacePos.xyz / lightSpacePos.w; + projCoords = projCoords * 0.5 + 0.5; + float closestDepth = pLightEnv.shadowMap.Sample(pLightEnv.shadowSampler, projCoords.xy).r; + float currentDepth = projCoords.z; + float bias = max(0.05 * (1.0 - dot(brdf.getNormal(), pLightEnv.directionalLights[i].direction.xyz)), 0.005); + float shadow = currentDepth > closestDepth - bias ? 1.0 : 0.0; + + result += shadow * pLightEnv.directionalLights[i].illuminate(lightingParams, brdf); } - for (uint i = 0; i < lightCount; ++i) + for (uint i = 0; i < pLightEnv.numPo; ++i) { uint lightIndex = pLightCullingData.lightIndexList[startOffset + i]; result += pLightEnv.pointLights[lightIndex].illuminate(lightingParams, brdf); diff --git a/res/shaders/lib/Common.slang b/res/shaders/lib/Common.slang index c1bbf84..80ddad3 100644 --- a/res/shaders/lib/Common.slang +++ b/res/shaders/lib/Common.slang @@ -19,7 +19,7 @@ struct ViewParameter uint frameIndex; float time; }; -layout(set = 0) +layout(set=0) ParameterBlock pViewParams; float4 worldToModel(float4x4 inverseTransform, float4 world) diff --git a/res/shaders/lib/LightEnv.slang b/res/shaders/lib/LightEnv.slang index 86b3874..c3d6017 100644 --- a/res/shaders/lib/LightEnv.slang +++ b/res/shaders/lib/LightEnv.slang @@ -11,25 +11,11 @@ struct DirectionalLight : ILightEnv float4 color; float4 direction; float4x4 lightSpaceMatrix; - Texture2D shadowMap; - SamplerState shadowSampler; float3 illuminate(LightingParameter params, B brdf) { float3 dir_WS = -normalize(direction.xyz); - float3 color = brdf.evaluate(params.viewDir_WS, dir_WS, color.xyz * color.w); - - float4 lightSpacePos = mul(lightSpaceMatrix, float4(params.position_WS, 1)); - float3 projCoords = lightSpacePos.xyz / lightSpacePos.w; - projCoords = projCoords * 0.5 + 0.5; - float closestDepth = shadowMap.Sample(shadowSampler, projCoords.xy).r; - float currentDepth = projCoords.z; - float bias = max(0.05 * (1.0 - dot(brdf.getNormal(), direction.xyz)), 0.005); - float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0; - if (projCoords.z > 1.0) - shadow = 0; - - return shadow * color; + return brdf.evaluate(params.viewDir_WS, dir_WS, color.xyz); } }; @@ -76,6 +62,8 @@ struct PointLight : ILightEnv struct LightEnv { StructuredBuffer directionalLights; + Texture2D shadowMap; // todo: not an array + SamplerState shadowSampler; uint numDirectionalLights; StructuredBuffer pointLights; uint numPointLights; diff --git a/res/shaders/lib/MaterialParameter.slang b/res/shaders/lib/MaterialParameter.slang index 8bc6282..6d201a9 100644 --- a/res/shaders/lib/MaterialParameter.slang +++ b/res/shaders/lib/MaterialParameter.slang @@ -136,8 +136,7 @@ struct VertexAttributes { float4 modelPos = float4(position_MS, 1); float4 worldPos = mul(transformMatrix, modelPos); - float4 viewPos = mul(pViewParams.viewMatrix, worldPos); - float4 clipPos = mul(pViewParams.projectionMatrix, viewPos); + float4 clipPos = mul(pViewParams.viewProjectionMatrix, worldPos); FragmentParameter result; result.position_CS = clipPos; #ifndef POS_ONLY diff --git a/src/Editor/main.cpp b/src/Editor/main.cpp index 25c9362..bbdc059 100644 --- a/src/Editor/main.cpp +++ b/src/Editor/main.cpp @@ -10,8 +10,8 @@ #include "Graphics/Metal/Graphics.h" #else #endif -#include "Graphics/Vulkan/Graphics.h" #include "Graphics/StaticMeshVertexData.h" +#include "Graphics/Vulkan/Graphics.h" #include "Window/InspectorView.h" #include "Window/PlayView.h" #include "Window/WindowManager.h" @@ -57,13 +57,17 @@ int main() { AssetImporter::importEnvironmentMap(EnvironmentImportArgs{ .filePath = sourcePath / "import" / "textures" / "newport_loft.hdr", }); - //AssetImporter::importTexture(TextureImportArgs{ - // .filePath = sourcePath / "import" / "textures" / "grass_block_side.png", - // .importPath = "", + // AssetImporter::importTexture(TextureImportArgs{ + // .filePath = sourcePath / "import" / "textures" / "grass_block_side.png", + // .importPath = "", + // }); + //AssetImporter::importMesh(MeshImportArgs{ + // .filePath = sourcePath / "import" / "models" / "main1_sponza" / "sponza.gltf", + // .importPath = "sponza", //}); AssetImporter::importMesh(MeshImportArgs{ - .filePath = sourcePath / "import" / "models" / "main1_sponza" / "floor.glb", - .importPath = "sponza", + .filePath = sourcePath / "import" / "models" / "rttest.glb", + .importPath = "rttest", }); getThreadPool().waitIdle(); diff --git a/src/Engine/Actor/DirectionalLightActor.cpp b/src/Engine/Actor/DirectionalLightActor.cpp index e5fa4b0..4055ec7 100644 --- a/src/Engine/Actor/DirectionalLightActor.cpp +++ b/src/Engine/Actor/DirectionalLightActor.cpp @@ -6,7 +6,7 @@ DirectionalLightActor::DirectionalLightActor(PScene scene) : Actor(scene) { atta DirectionalLightActor::DirectionalLightActor(PScene scene, Vector color, float intensity, Vector direction) : Actor(scene) { attachComponent(Vector4(color, intensity)); - Vector lightDirection = Vector(direction); + Vector lightDirection = glm::normalize(direction); float dot = glm::dot(lightDirection, Math::Transform::FORWARD); Quaternion rotation = Quaternion(1, 0, 0, 0); // Handle the edge cases first diff --git a/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp b/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp index 9e91b2e..4c4ce38 100644 --- a/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp +++ b/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp @@ -71,6 +71,7 @@ void DepthCullingPass::beginFrame(const Component::Camera& cam, const Component: void DepthCullingPass::render() { graphics->beginDebugRegion("DepthCullingPass"); + Gfx::PDescriptorSet set = depthAttachmentLayout->allocateDescriptorSet(); { graphics->beginDebugRegion("MipGeneration"); query->beginQuery(); @@ -79,7 +80,6 @@ void DepthCullingPass::render() { Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT); depthMipBuffer->rotateBuffer(depthMipBuffer->getNumElements() * sizeof(uint32)); - Gfx::PDescriptorSet set = depthAttachmentLayout->allocateDescriptorSet(); set->updateTexture(DEPTHTEXTURE_NAME, 0, depthAttachment.getTexture()); set->updateBuffer(DEPTHMIP_NAME, 0, depthMipBuffer); set->writeChanges(); @@ -127,10 +127,6 @@ void DepthCullingPass::render() { graphics->beginDebugRegion("DepthCulling"); graphics->beginRenderPass(renderPass); Array commands; - Gfx::PDescriptorSet set = depthAttachmentLayout->allocateDescriptorSet(); - set->updateTexture(DEPTHTEXTURE_NAME, 0, depthAttachment.getTexture()); - set->updateBuffer(DEPTHMIP_NAME, 0, depthMipBuffer); - set->writeChanges(); Gfx::ShaderPermutation permutation = graphics->getShaderCompiler()->getTemplate("DepthPass"); permutation.setPositionOnly(true); permutation.setDepthCulling(getGlobals().useDepthCulling); diff --git a/src/Engine/Graphics/RenderPass/ShadowPass.cpp b/src/Engine/Graphics/RenderPass/ShadowPass.cpp index 1974e3b..91d8d5c 100644 --- a/src/Engine/Graphics/RenderPass/ShadowPass.cpp +++ b/src/Engine/Graphics/RenderPass/ShadowPass.cpp @@ -79,15 +79,13 @@ void ShadowPass::render() { .offset = {0, 0}, }, "Shadow"); - graphics->beginRenderPass(renderPass); auto light = scene->getLightEnvironment()->getDirectionalLight(shadowIndex); - - Component::Camera lightCamera = Component::Camera{ - .nearPlane = 0.f, - .farPlane = 1000.0f, + .nearPlane = -20.f, + .farPlane = 10.0f, }; Gfx::PDescriptorSet viewParamsSet = createViewParamsSet(lightCamera, scene->getLightEnvironment()->getDirectionalTransform(shadowIndex)); + graphics->beginRenderPass(renderPass); for (VertexData* vertexData : VertexData::getList()) { permutation.setVertexData(vertexData->getTypeName()); Gfx::PermutationId id(permutation); @@ -105,7 +103,7 @@ void ShadowPass::render() { .pipelineLayout = collection->pipelineLayout, .rasterizationState = { - .cullMode = Gfx::SE_CULL_MODE_FRONT_BIT, + .cullMode = Gfx::SE_CULL_MODE_NONE, }, .colorBlend = { @@ -122,7 +120,7 @@ void ShadowPass::render() { .pipelineLayout = collection->pipelineLayout, .rasterizationState = { - .cullMode = Gfx::SE_CULL_MODE_FRONT_BIT, + .cullMode = Gfx::SE_CULL_MODE_NONE, }, .colorBlend = { @@ -161,6 +159,7 @@ void ShadowPass::render() { } graphics->executeCommands(std::move(commands)); graphics->endRenderPass(); + graphics->waitDeviceIdle(); } graphics->endDebugRegion(); } @@ -174,10 +173,10 @@ void ShadowPass::publishOutputs() { .offset = {0, 0}, }, .fieldOfView = 0, - .left = -10, - .right = 10, - .top = -10, - .bottom = 10}); + .left = -20, + .right = 20, + .top = -20, + .bottom = 20}); viewport = shadowViewport; } diff --git a/src/Engine/Graphics/Vulkan/Window.cpp b/src/Engine/Graphics/Vulkan/Window.cpp index cb97ef2..e6cf8e9 100644 --- a/src/Engine/Graphics/Vulkan/Window.cpp +++ b/src/Engine/Graphics/Vulkan/Window.cpp @@ -313,5 +313,5 @@ void Viewport::move(uint32 newOffsetX, uint32 newOffsetY) { offsetX = newOffsetX; offsetY = newOffsetY; handle.x = static_cast(offsetX); - handle.y = static_cast(offsetY + sizeY); + handle.y = static_cast(offsetY); } diff --git a/src/Engine/Graphics/Window.cpp b/src/Engine/Graphics/Window.cpp index 4d77643..be15e05 100644 --- a/src/Engine/Graphics/Window.cpp +++ b/src/Engine/Graphics/Window.cpp @@ -26,6 +26,6 @@ Matrix4 Viewport::getProjectionMatrix(float nearPlane, float farPlane) const { Matrix4 projectionMatrix = glm::perspective(fieldOfView, sizeX / static_cast(sizeY), nearPlane, farPlane); return correctionMatrix * projectionMatrix; } else { - return correctionMatrix * glm::ortho(orthoLeft, orthoRight, orthoTop, orthoBottom, farPlane, nearPlane); + return correctionMatrix * glm::ortho(orthoLeft, orthoRight, orthoBottom, orthoTop, farPlane, nearPlane); } } \ No newline at end of file diff --git a/src/Engine/Scene/LightEnvironment.cpp b/src/Engine/Scene/LightEnvironment.cpp index 95cfadb..bde9bd1 100644 --- a/src/Engine/Scene/LightEnvironment.cpp +++ b/src/Engine/Scene/LightEnvironment.cpp @@ -12,6 +12,14 @@ LightEnvironment::LightEnvironment(Gfx::PGraphics graphics) .name = "directionalLights", .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, }); + layout->addDescriptorBinding(Gfx::DescriptorBinding{ + .name = "shadowMap", + .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE, + }); + layout->addDescriptorBinding(Gfx::DescriptorBinding{ + .name = "shadowSampler", + .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLER, + }); layout->addDescriptorBinding(Gfx::DescriptorBinding{ .name = "numDirectionalLights", .uniformLength = sizeof(uint32), @@ -60,10 +68,14 @@ void LightEnvironment::reset() { } void LightEnvironment::addDirectionalLight(const Component::DirectionalLight& dirLight, const Component::Transform& transform) { + Vector eyePos = transform.getPosition(); + Vector lookAt = eyePos + transform.getForward(); + Matrix4 cameraMatrix = glm::lookAt(eyePos, lookAt, Vector(0, 1, 0)); + Matrix4 correctionMatrix = Matrix4(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1 / 2.f, 0, 0, 0, 1 / 2.f, 1); dirs.add(ShaderDirectionalLight{ .color = Vector4(dirLight.color, dirLight.intensity), .direction = Vector4(transform.getForward(), 0), - .lightSpaceMatrix = transform.toMatrix(), + .lightSpaceMatrix = correctionMatrix * glm::ortho(-20.f, 20.f, 20.f, -20.f, 10.0f, -20.0f) * cameraMatrix, }); directionalTransforms.add(transform); if (shadowMaps.size() < dirs.size()) { @@ -75,6 +87,8 @@ void LightEnvironment::addDirectionalLight(const Component::DirectionalLight& di .usage = Gfx::SE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | Gfx::SE_IMAGE_USAGE_SAMPLED_BIT, .name = "ShadowMap", })); + shadowMaps.back()->changeLayout(Gfx::SE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, Gfx::SE_ACCESS_NONE, Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT); shadowSamplers.add(graphics->createSampler(SamplerCreateInfo{ .addressModeU = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, .addressModeV = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, @@ -92,24 +106,26 @@ void LightEnvironment::addPointLight(const Component::PointLight& pointLight, co } void LightEnvironment::commit() { - directionalLights->rotateBuffer(sizeof(Component::DirectionalLight) * dirs.size()); - directionalLights->updateContents(0, sizeof(Component::DirectionalLight) * dirs.size(), dirs.data()); + directionalLights->rotateBuffer(sizeof(ShaderDirectionalLight) * dirs.size()); + directionalLights->updateContents(0, sizeof(ShaderDirectionalLight) * dirs.size(), dirs.data()); directionalLights->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT | Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT | Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT); - pointLights->rotateBuffer(sizeof(Component::PointLight) * points.size()); - pointLights->updateContents(0, sizeof(Component::PointLight) * points.size(), points.data()); + pointLights->rotateBuffer(sizeof(ShaderPointLight) * points.size()); + pointLights->updateContents(0, sizeof(ShaderPointLight) * points.size(), points.data()); pointLights->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT | Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT | Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT); uint32 numPointLights = (uint32)points.size(); uint32 numDirectionalLights = (uint32)dirs.size(); - set->updateConstants("numPointLights", 0, &numPointLights); - set->updateBuffer("pointLights", 0, pointLights); set->updateConstants("numDirectionalLights", 0, &numDirectionalLights); set->updateBuffer("directionalLights", 0, directionalLights); + set->updateTexture("shadowMap", 0, Gfx::PTexture2D(shadowMaps[0])); + set->updateSampler("shadowSampler", 0, Gfx::PSampler(shadowSamplers[0])); + set->updateConstants("numPointLights", 0, &numPointLights); + set->updateBuffer("pointLights", 0, pointLights); set->updateTexture("irradianceMap", 0, environment->getIrradianceMap()); set->updateSampler("irradianceSampler", 0, environmentSampler); set->writeChanges();