diff --git a/CMakeLists.txt b/CMakeLists.txt index 6e688f96..9a2c78d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -156,29 +156,31 @@ set(RENDERER_SOURCES src/renderer/environment/environment.h src/renderer/environment/environment_constants.h src/renderer/environment/environment_types.h - src/renderer/pipelines/deferred_mrt/deferred_mrt.cpp - src/renderer/pipelines/deferred_mrt/deferred_mrt.h - src/renderer/pipelines/deferred_resolve/deferred_resolve.cpp - src/renderer/pipelines/deferred_resolve/deferred_resolve.h - src/renderer/pipelines/environment/environment_pipeline.cpp - src/renderer/pipelines/environment/environment_pipeline.h - src/renderer/pipelines/post_process/post_process_pipeline.cpp - src/renderer/pipelines/post_process/post_process_pipeline.h - src/renderer/pipelines/visibility_pass/visibility_pass.cpp - src/renderer/pipelines/visibility_pass/visibility_pass.h - src/renderer/pipelines/temporal_antialiasing_pipeline/temporal_antialiasing_pipeline.cpp - src/renderer/pipelines/temporal_antialiasing_pipeline/temporal_antialiasing_pipeline.h - src/renderer/pipelines/basic_compute/basic_compute_pipeline.cpp - src/renderer/pipelines/basic_compute/basic_compute_pipeline.h - src/renderer/pipelines/basic_render/basic_render_pipeline.cpp - src/renderer/pipelines/basic_render/basic_render_pipeline.h + src/renderer/pipelines/geometry/deferred_mrt/deferred_mrt_pipeline.cpp + src/renderer/pipelines/geometry/deferred_mrt/deferred_mrt_pipeline.h + src/renderer/pipelines/geometry/deferred_mrt/deferred_mrt_pipeline_types.h + src/renderer/pipelines/geometry/deferred_resolve/deferred_resolve_pipeline.cpp + src/renderer/pipelines/geometry/deferred_resolve/deferred_resolve_pipeline.h + src/renderer/pipelines/geometry/deferred_resolve/deferred_resolve_pipeline_types.h + src/renderer/pipelines/geometry/environment/environment_pipeline.cpp + src/renderer/pipelines/geometry/environment/environment_pipeline.h + src/renderer/pipelines/post/post_process/post_process_pipeline.cpp + src/renderer/pipelines/post/post_process/post_process_pipeline.h + src/renderer/pipelines/visibility_pass/visibility_pass_pipeline.cpp + src/renderer/pipelines/visibility_pass/visibility_pass_pipeline.h + src/renderer/pipelines/post/temporal_antialiasing/temporal_antialiasing_pipeline.cpp + src/renderer/pipelines/post/temporal_antialiasing/temporal_antialiasing_pipeline.h + src/renderer/pipelines/basic/basic_compute/basic_compute_pipeline.cpp + src/renderer/pipelines/basic/basic_compute/basic_compute_pipeline.h + src/renderer/pipelines/basic/basic_render/basic_render_pipeline.cpp + src/renderer/pipelines/basic/basic_render/basic_render_pipeline.h src/renderer/lighting/directional_light.h src/renderer/lighting/directional_light.cpp - src/renderer/lighting/shadows/cascaded_shadow_map.cpp - src/renderer/lighting/shadows/cascaded_shadow_map.h - src/renderer/lighting/shadows/shadow_constants.cpp - src/renderer/lighting/shadows/shadow_constants.h - src/renderer/lighting/shadows/shadow_types.h + src/renderer/pipelines/shadows/cascaded_shadow_map/cascaded_shadow_map.cpp + src/renderer/pipelines/shadows/cascaded_shadow_map/cascaded_shadow_map.h + src/renderer/pipelines/shadows/cascaded_shadow_map/shadow_constants.cpp + src/renderer/pipelines/shadows/cascaded_shadow_map/shadow_constants.h + src/renderer/pipelines/shadows/cascaded_shadow_map/shadow_types.h src/renderer/descriptor_buffer/descriptor_buffer.cpp src/renderer/descriptor_buffer/descriptor_buffer.h src/renderer/descriptor_buffer/descriptor_buffer_sampler.cpp @@ -188,7 +190,6 @@ set(RENDERER_SOURCES src/renderer/descriptor_buffer/descriptor_buffer_uniform.cpp src/renderer/descriptor_buffer/descriptor_buffer_uniform.h src/renderer/assets/render_object/render_object_constants.h - src/renderer/post_process/post_process_types.h ) @@ -222,8 +223,8 @@ set(TEMP_SOURCES src/util/noise_utils.h src/renderer/terrain/terrain_chunk.cpp src/renderer/terrain/terrain_chunk.h - src/renderer/pipelines/terrain/terrain_pipeline.cpp - src/renderer/pipelines/terrain/terrain_pipeline.h + src/renderer/pipelines/geometry/terrain/terrain_pipeline.cpp + src/renderer/pipelines/geometry/terrain/terrain_pipeline.h src/core/scene/map.cpp src/core/scene/map.h src/core/game_object/terrain.h @@ -241,12 +242,24 @@ set(TEMP_SOURCES src/renderer/assets/texture/texture_resource.cpp src/renderer/assets/texture/texture_resource.h src/renderer/assets/texture/texture_types.h - src/renderer/lighting/ambient_occlusion/ground_truth/ground_truth_ambient_occlusion.cpp - src/renderer/lighting/ambient_occlusion/ground_truth/ground_truth_ambient_occlusion.h - src/renderer/lighting/ambient_occlusion/ambient_occlusion_types.h - src/renderer/pipelines/transparent_pipeline/transparent_pipeline.cpp - src/renderer/pipelines/transparent_pipeline/transparent_pipeline.h + src/renderer/pipelines/shadows/ground_truth_ambient_occlusion/ground_truth_ambient_occlusion_pipeline.cpp + src/renderer/pipelines/shadows/ground_truth_ambient_occlusion/ground_truth_ambient_occlusion_pipeline.h + src/renderer/pipelines/shadows/ground_truth_ambient_occlusion/ambient_occlusion_types.h + src/renderer/pipelines/geometry/transparent_pipeline/transparent_pipeline.cpp + src/renderer/pipelines/geometry/transparent_pipeline/transparent_pipeline.h src/engine_constants.h + src/renderer/pipelines/shadows/contact_shadow/contact_shadows_pipeline.cpp + src/renderer/pipelines/shadows/contact_shadow/contact_shadows_pipeline.h + src/renderer/pipelines/shadows/contact_shadow/contact_shadows_pipeline_types.h + + src/renderer/pipelines/geometry/environment/environment_pipeline_types.h + src/renderer/pipelines/basic/basic_render/basic_render_pipeline_types.h + src/renderer/pipelines/post/post_process/post_process_pipeline_types.h + src/renderer/pipelines/post/temporal_antialiasing/temporal_antialiasing_pipeline_types.h + src/renderer/pipelines/geometry/terrain/terrain_pipeline_types.h + src/renderer/pipelines/geometry/transparent_pipeline/transparent_pipeline_types.h + src/renderer/pipelines/basic/basic_compute/basic_compute_pipeline_types.h + src/renderer/pipelines/visibility_pass/visibility_pass_pipeline_types.h ) diff --git a/assets/maps/sampleScene.willmap b/assets/maps/sampleScene.willmap index a869bb05..2aedd3a7 100644 --- a/assets/maps/sampleScene.willmap +++ b/assets/maps/sampleScene.willmap @@ -6,7 +6,7 @@ }, "metadata": { "name": "sampleScene", - "created": "2025-04-06 11:32:54", + "created": "2025-04-21 21:26:24", "formatVersion": 1 }, "rootComponents": { @@ -236,7 +236,7 @@ "transform": { "position": { "x": 0.0, - "y": 41.5, + "y": 38.79999923706055, "z": 0.0 }, "rotation": { @@ -262,7 +262,7 @@ "RigidBodyComponent": { "properties": { "isActive": true, - "motionType": 1, + "motionType": 2, "layer": 1, "shapeType": 0, "shapeParams": { @@ -653,6 +653,96 @@ } } ] + }, + { + "id": 15, + "name": "GameObject_15", + "transform": { + "position": { + "x": 0.0, + "y": 37.70000076293945, + "z": 0.0 + }, + "rotation": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 1.0 + }, + "scale": { + "x": 20.0, + "y": 0.20000000298023224, + "z": 20.0 + } + }, + "components": { + "MeshRendererComponent": { + "renderReference": 3129368917, + "renderMeshIndex": 1, + "renderIsVisible": true, + "renderIsShadowCaster": true, + "componentName": "Mesh Renderer" + }, + "RigidBodyComponent": { + "properties": { + "isActive": true, + "motionType": 1, + "layer": 0, + "shapeType": 1, + "shapeParams": { + "x": 10.0, + "y": 0.10000000149011612, + "z": 10.0 + } + }, + "componentName": "New RigidBodyComponent" + } + } + }, + { + "id": 16, + "name": "GameObject_16", + "transform": { + "position": { + "x": -7.5, + "y": 38.79999923706055, + "z": 0.0 + }, + "rotation": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 1.0 + }, + "scale": { + "x": 1.0, + "y": 1.0, + "z": 1.0 + } + }, + "components": { + "MeshRendererComponent": { + "renderReference": 3129368917, + "renderMeshIndex": 0, + "renderIsVisible": true, + "renderIsShadowCaster": true, + "componentName": "Mesh Renderer" + }, + "RigidBodyComponent": { + "properties": { + "isActive": true, + "motionType": 2, + "layer": 1, + "shapeType": 0, + "shapeParams": { + "x": 1.0, + "y": 0.0, + "z": 0.0 + } + }, + "componentName": "New RigidBodyComponent" + } + } } ] } diff --git a/assets/settings.willengine b/assets/settings.willengine index c46a3a0b..d287a88a 100644 --- a/assets/settings.willengine +++ b/assets/settings.willengine @@ -6,32 +6,33 @@ }, "mainLight": { "direction": [ - 0.007031798828393221, - -0.9709741473197937, - -0.23908114433288574 + -0.005322144832462072, + -0.9349234104156494, + -0.35480964183807373 ], "color": [ - 1.0, - 1.0, + 0.20000000298023224, + 0.4000000059604645, 1.0 ], - "intensity": 1.0 + "intensity": 50.0 }, "cameraProperties": { "position": [ - -5.494653224945068, - 111.15990447998047, - 115.60420227050781 + 112.34994506835938, + 83.79894256591797, + -50.39910125732422 ], "rotation": [ - 0.15897978842258453, - 0.01722628064453602, - 0.002778323134407401, - -0.9871276021003723 + -0.4555923640727997, + -0.2922893166542053, + -0.16135302186012268, + 0.8252077102661133 ], "fov": 1.3089969158172607, "aspectRatio": 1.7777777910232544, "nearPlane": 1000.0, "farPlane": 0.10000000149011612 - } + }, + "environmentMapIndex": 3 } \ No newline at end of file diff --git a/shaders/ambient_occlusion/ground_truth/gtao_main_pass.comp b/shaders/ambient_occlusion/ground_truth/gtao_main_pass.comp index 6aff7c77..ad21dd10 100644 --- a/shaders/ambient_occlusion/ground_truth/gtao_main_pass.comp +++ b/shaders/ambient_occlusion/ground_truth/gtao_main_pass.comp @@ -1,5 +1,6 @@ #version 460 +#include "common.glsl" #include "scene.glsl" #include "gtao.glsl" @@ -102,15 +103,6 @@ vec4 reconstructViewSpacePosition(vec2 uv, float viewDepth) { return positionVS; } -mat3 adjugate(mat4 m) { - return mat3( - cross(m[1].xyz, m[2].xyz), - cross(m[2].xyz, m[0].xyz), - cross(m[0].xyz, m[1].xyz) - ); - -} - void main() { if (pushConstants.debug == -1){ return; @@ -129,8 +121,8 @@ void main() { vec4 valuesBR = textureGatherOffset(prefilteredDepth, gatherCenter, ivec2(1, 1), 0); float viewSpaceZM = valuesUL.y; const float viewSpaceZL = valuesUL.x; - const float viewSpaceZR = valuesUL.z; - const float viewSpaceZT = valuesBR.z; + const float viewSpaceZT = valuesUL.z; + const float viewSpaceZR = valuesBR.z; const float viewSpaceZB = valuesBR.x; vec4 edges = XE_GTAO_CalculateDepthEdges(viewSpaceZM, viewSpaceZL, viewSpaceZR, viewSpaceZT, viewSpaceZB); @@ -139,8 +131,7 @@ void main() { // Get view space normal by sampling normal buffer and converting from world to view (code not relevant) - vec3 worldNormal = texture(normalBuffer, uv).rgb; - vec3 viewNormal = adjugate(sceneData.view) * worldNormal; + vec3 viewNormal = texture(normalBuffer, uv).rgb; if (pushConstants.debug == 2){ imageStore(debugImage, screenPos, vec4(viewNormal, 1.0f)); diff --git a/shaders/deferredMrt.frag b/shaders/deferredMrt.frag index 0abd3e45..47eaca35 100644 --- a/shaders/deferredMrt.frag +++ b/shaders/deferredMrt.frag @@ -9,12 +9,12 @@ // world space -layout (location = 0) in vec3 inPosition; -layout (location = 1) in vec3 inNormal; +layout (location = 0) in vec3 inViewPosition; +layout (location = 1) in vec3 inViewNormal; layout (location = 2) in vec4 inColor; layout (location = 3) in vec2 inUV; layout (location = 4) in flat uint inMaterialIndex; -layout (location = 5) in flat uint inBHasTransparent; +layout (location = 5) in flat uint inHasTransparent; layout (location = 6) in vec4 inCurrMvpPosition; layout (location = 7) in vec4 inPrevMvpPosition; @@ -45,6 +45,8 @@ void main() { } albedo = albedo * inColor * m.colorFactor; + // Look into custom shaders specifically for these? More draw commands vs branching... + // 1 is transparent blend type if (m.alphaCutoff.y == 1) { // Draw only if alpha is close enough to 1 if (albedo.w <= 1.0 - TRANSPARENT_ALPHA_EPSILON) { @@ -52,6 +54,7 @@ void main() { } } + // 2 is "mask" (cutout) blend type if (m.alphaCutoff.y == 2){ // 2 is "mask" blend type if (albedo.w < m.alphaCutoff.x){ @@ -71,9 +74,9 @@ void main() { } - normalTarget = vec4(normalize(inNormal), 0.0f); + normalTarget = vec4(normalize(inViewNormal), 0.0f); albedoTarget = vec4(albedo.xyz, 1.0f); - pbrTarget = vec4(metallic, roughness, 0.0f, inBHasTransparent); + pbrTarget = vec4(metallic, roughness, 0.0f, inHasTransparent); vec2 currNdc = inCurrMvpPosition.xy / inCurrMvpPosition.w; vec2 prevNdc = inPrevMvpPosition.xy / inPrevMvpPosition.w; diff --git a/shaders/deferredMrt.vert b/shaders/deferredMrt.vert index 64aa3143..0a26b919 100644 --- a/shaders/deferredMrt.vert +++ b/shaders/deferredMrt.vert @@ -20,12 +20,12 @@ layout (location = 1) in vec3 normal; layout (location = 2) in vec4 color; layout (location = 3) in vec2 uv; -layout (location = 0) out vec3 outPosition; -layout (location = 1) out vec3 outNormal; +layout (location = 0) out vec3 outViewPosition; +layout (location = 1) out vec3 outViewNormal; layout (location = 2) out vec4 outColor; layout (location = 3) out vec2 outUV; layout (location = 4) out flat uint outMaterialIndex; -layout (location = 5) out flat uint inBHasTransparent; +layout (location = 5) out flat uint outHasTransparent; layout (location = 6) out vec4 outCurrMvpPosition; layout (location = 7) out vec4 outPrevMvpPosition; @@ -35,16 +35,16 @@ void main() { uint materialIndex = primitive.materialIndex; Model models = bufferAddresses.modelBufferDeviceAddress.models[modelIndex]; - vec4 worldPos = models.currentModelMatrix * vec4(position, 1.0); + vec4 viewPos = sceneData.view * models.currentModelMatrix * vec4(position, 1.0); - outPosition = worldPos.xyz; - outNormal = adjugate(models.currentModelMatrix) * normal; + outViewPosition = viewPos.xyz; + outViewNormal = mat3(sceneData.view) * adjugate(models.currentModelMatrix) * normal; outColor = color; outUV = uv; outMaterialIndex = materialIndex; - inBHasTransparent = primitive.bHasTransparent; + outHasTransparent = primitive.bHasTransparent; - vec4 currClipPos = sceneData.viewProj * worldPos; + vec4 currClipPos = sceneData.proj * viewPos; vec4 prevClipPos = sceneData.prevViewProj * models.previousModelMatrix * vec4(position, 1.0); currClipPos.xy += currClipPos.w * sceneData.jitter.xy; prevClipPos.xy += prevClipPos.w * sceneData.jitter.zw; diff --git a/shaders/deferredResolve.comp b/shaders/deferredResolve.comp index 2e07ec29..014c0c53 100644 --- a/shaders/deferredResolve.comp +++ b/shaders/deferredResolve.comp @@ -17,8 +17,9 @@ layout (set = 1, binding = 2) uniform sampler2D pbrRenderTarget; layout (set = 1, binding = 3) uniform sampler2D depthBuffer; layout (set = 1, binding = 4) uniform sampler2D velocityBuffer;// velocity buffer is not actually used in this deferred resolve layout (set = 1, binding = 5) uniform sampler2D aoBuffer; +layout (set = 1, binding = 6) uniform sampler2D contactShadowBuffer; -layout (rgba16f, set = 1, binding = 6) uniform image2D outputImage; +layout (rgba16f, set = 1, binding = 7) uniform image2D outputImage; layout (set = 2, binding = 0) uniform samplerCube environmentDiffuseAndSpecular; layout (set = 2, binding = 1) uniform sampler2D lut; @@ -46,6 +47,7 @@ layout (push_constant) uniform PushConstants { int height; int debug; int disableShadows; + int disableContactShadows; int pcfLevel; float nearPlane; float farPlane; @@ -59,14 +61,11 @@ vec3 reconstructPosition(vec2 uv, float ndcDepth) { vec4 positionVS = sceneData.invProjection * vec4(ndc, ndcDepth, 1.0); positionVS /= positionVS.w; - // Transform to world-space - vec4 positionWS = sceneData.invView * positionVS; - - return positionWS.xyz; + return positionVS.xyz; } void main() { - // All calculations are done in World Space unless explicitly declared otherwise + // All calculations are done in View Space unless explicitly declared otherwise ivec2 screenPos = ivec2(gl_GlobalInvocationID.xy); if (screenPos.x > pushConstants.width || screenPos.y > pushConstants.height) { return; @@ -86,9 +85,9 @@ void main() { return; } float depth = texture(depthBuffer, uv).r; - vec3 normal = texture(normalRenderTarget, uv).rgb; + vec3 viewNormal = texture(normalRenderTarget, uv).rgb; vec4 pbrData = texture(pbrRenderTarget, uv); - vec3 position = reconstructPosition(uv, depth); + vec3 viewPosition = reconstructPosition(uv, depth); float roughness = pbrData.g; float metallic = pbrData.r; @@ -96,10 +95,11 @@ void main() { bool hasTransparent = pbrData.a == 1; - vec3 N = normalize(normal); - vec3 V = normalize(sceneData.cameraPos.xyz - position); + vec3 N = normalize(viewNormal); + vec3 V = normalize(-viewPosition); - vec3 L = normalize(-shadowCascadeData.directionalLightData.direction);// for point lights, light.pos - inPosition + // for point lights, light.pos - inPosition + vec3 L = normalize(mat3(sceneData.view) * normalize(-shadowCascadeData.directionalLightData.direction)); vec3 H = normalize(V + L); // SPECULAR @@ -122,28 +122,38 @@ void main() { // SHADOWS float offset = 0.05f; - float normalOffsetScale = max(offset, dot(normal, L) * offset); - vec3 offsetPosition = position + normal * normalOffsetScale; - float _tempShadowFactor = getShadowFactorBlend(pushConstants.pcfLevel, position, sceneData.view, shadowCascadeData.cascadeSplits, shadowCascadeData.lightViewProj, shadowMapSampler, shadowCascadeData.nearShadowPlane, shadowCascadeData.farShadowPlane); - float shadowFactor = clamp(smoothstep(-0.15f, 0.5f, dot(N, L)) * _tempShadowFactor, 0, 1); - - if (pushConstants.disableShadows == 1) { + float normalOffsetScale = max(offset, dot(N, L) * offset); + vec3 offsetPosition = viewPosition + N * normalOffsetScale; + vec4 worldPosition = sceneData.invView * vec4(offsetPosition, 1.0f); + //float _tempShadowFactor = getShadowFactorBlend(pushConstants.pcfLevel, worldPosition.xyz, abs(viewPosition.z), shadowCascadeData.cascadeSplits, shadowCascadeData.lightViewProj, shadowMapSampler, shadowCascadeData.nearShadowPlane, shadowCascadeData.farShadowPlane); + //float shadowFactor = clamp(smoothstep(-0.15f, 0.5f, dot(N, L)) * _tempShadowFactor, 0, 1); + + float shadowFactor = getShadowFactorBlend(pushConstants.pcfLevel, worldPosition.xyz, abs(viewPosition.z), shadowCascadeData.cascadeSplits, shadowCascadeData.lightViewProj, shadowMapSampler, shadowCascadeData.nearShadowPlane, shadowCascadeData.farShadowPlane); + if (pushConstants.disableShadows == 1){ shadowFactor = 1.0f; } + float contactShadow = texture(contactShadowBuffer, uv).r; + if (pushConstants.disableContactShadows == 1){ + contactShadow = 1.0f; + } + + shadowFactor = min(shadowFactor, contactShadow); // Direct lighting with shadows vec3 directLight = (diffuse + specular) * nDotL * shadowFactor * shadowCascadeData.directionalLightData.intensity * shadowCascadeData.directionalLightData.color; // IBL Reflections - vec3 irradiance = DiffuseIrradiance(environmentDiffuseAndSpecular, N); + vec3 worldN = normalize(mat3(sceneData.invView) * N); + vec3 irradiance = DiffuseIrradiance(environmentDiffuseAndSpecular, worldN); vec3 reflectionDiffuse = irradiance * albedo.xyz; - vec3 reflectionSpecular = SpecularReflection(environmentDiffuseAndSpecular, lut, V, N, roughness, F); + vec3 reflectionSpecular = SpecularReflection(environmentDiffuseAndSpecular, lut, V, N, sceneData.invView, roughness, F); float ao = 1.0f; if (!hasTransparent) { ao = texture(aoBuffer, uv).r; } vec3 ambient = (kD * reflectionDiffuse + reflectionSpecular) * ao; + ambient *= mix(0.4, 1.0, min(shadowFactor, nDotL)); vec3 finalColor = directLight + ambient; imageStore(outputImage, screenPos, vec4(finalColor, albedo.w)); @@ -166,7 +176,7 @@ void main() { imageStore(outputImage, screenPos, albedo); break; case 4: - imageStore(outputImage, screenPos, vec4(normal, 1.0f)); + imageStore(outputImage, screenPos, vec4(worldN * 0.5f + 0.5f, 1.0f)); break; case 5: imageStore(outputImage, screenPos, pbrData); @@ -175,7 +185,7 @@ void main() { imageStore(outputImage, screenPos, vec4(vec3(shadowFactor), 1.0f)); break; case 7: - float viewDepth = getViewSpaceDepth(position, sceneData.view); + float viewDepth = abs(viewPosition.z); int cascadeLevel = selectCascadeLevel(viewDepth, shadowCascadeData.cascadeSplits); float value = viewDepth - shadowCascadeData.cascadeSplits[cascadeLevel].nearPlane; float diff = value / (shadowCascadeData.cascadeSplits[cascadeLevel].farPlane - shadowCascadeData.cascadeSplits[cascadeLevel].nearPlane); @@ -192,5 +202,10 @@ void main() { float ao = texture(aoBuffer, uv).r; imageStore(outputImage, screenPos, vec4(vec3(ao), 1.0f)); break; + case 10: + float contactShadow = texture(contactShadowBuffer, uv).r; + imageStore(outputImage, screenPos, vec4(vec3(contactShadow), 1.0f)); + break; + } } \ No newline at end of file diff --git a/shaders/environment/environment.frag b/shaders/environment/environment.frag index 5d408c4c..dd53a94c 100644 --- a/shaders/environment/environment.frag +++ b/shaders/environment/environment.frag @@ -1,4 +1,7 @@ #version 450 + +#include "scene.glsl" + layout (location = 0) in vec3 uv; layout (location = 1) in vec4 inCurrMvpPosition; layout (location = 2) in vec4 inPrevMvpPosition; @@ -8,6 +11,8 @@ layout (location = 1) out vec4 albedoTarget;// 10,10,10, (2 -> 0 = environment M layout (location = 2) out vec4 pbrTarget;// 8 metallic, 8 roughness, 8 emissive (unused), 8 unused layout (location = 3) out vec2 velocityTarget;// 16 X, 16 Y +// layout (std140, set = 0, binding = 0) uniform SceneData - scene.glsl + layout(set = 1, binding = 0) uniform samplerCube environmentMap; void main() @@ -19,7 +24,8 @@ void main() // 0 = environment map flag albedoTarget = vec4(envColor, 0.0); - normalTarget = vec4(-direction, 0.0f); + vec3 normal = mat3(sceneData.view) * -direction; + normalTarget = vec4(normal, 0.0f); pbrTarget = vec4(0.0f); vec2 currNdc = inCurrMvpPosition.xy / inCurrMvpPosition.w; diff --git a/shaders/include/environment.glsl b/shaders/include/environment.glsl index 198eaf5d..fee7cb47 100644 --- a/shaders/include/environment.glsl +++ b/shaders/include/environment.glsl @@ -2,21 +2,23 @@ const float MAX_REFLECTION_LOD = 4.0; const uint DIFF_IRRA_MIP_LEVEL = 5; const bool FLIP_ENVIRONMENT_MAP_Y = true; - -vec3 DiffuseIrradiance(samplerCube envDiffSpec, vec3 N) +vec3 DiffuseIrradiance(samplerCube envDiffSpec, vec3 worldNormal) { - vec3 ENV_N = N; + vec3 ENV_N = worldNormal; if (FLIP_ENVIRONMENT_MAP_Y) { ENV_N.y = -ENV_N.y; } return textureLod(envDiffSpec, ENV_N, DIFF_IRRA_MIP_LEVEL).rgb; } -vec3 SpecularReflection(samplerCube envDiffSpec, sampler2D lut, vec3 V, vec3 N, float roughness, vec3 F) { - vec3 R = reflect(-V, N); - if (FLIP_ENVIRONMENT_MAP_Y) { R.y = -R.y; } +vec3 SpecularReflection(samplerCube envDiffSpec, sampler2D lut, vec3 viewV, vec3 viewN, mat4 invView, float roughness, vec3 F) { + vec3 R = reflect(-viewV, viewN); + + vec3 worldR = normalize((invView * vec4(R, 0.0)).xyz); + + if (FLIP_ENVIRONMENT_MAP_Y) { worldR.y = -worldR.y; } // dont need to skip mip 5 because never goes above 4 - vec3 prefilteredColor = textureLod(envDiffSpec, R, roughness * MAX_REFLECTION_LOD).rgb; + vec3 prefilteredColor = textureLod(envDiffSpec, worldR, roughness * MAX_REFLECTION_LOD).rgb; - vec2 envBRDF = texture(lut, vec2(max(dot(N, V), 0.0f), roughness)).rg; + vec2 envBRDF = texture(lut, vec2(max(dot(viewN, viewV), 0.0f), roughness)).rg; return prefilteredColor * (F * envBRDF.x + envBRDF.y); } \ No newline at end of file diff --git a/shaders/include/pbr.glsl b/shaders/include/pbr.glsl index 4454743f..4bc39ca0 100644 --- a/shaders/include/pbr.glsl +++ b/shaders/include/pbr.glsl @@ -1,3 +1,6 @@ +#ifndef PBR_GLSL +#define PBR_GLSL + vec3 Lambert(vec3 kD, vec3 albedo) { return kD * albedo / 3.14159265359; @@ -52,4 +55,6 @@ vec3 F_SCHLICK(vec3 V, vec3 H, vec3 F0){ // unreal optimized return F0 + (1 - F0) * pow(2, FRESNEL_POWER_UNREAL(V, H)); -} \ No newline at end of file +} + +#endif // PBR_GLSL \ No newline at end of file diff --git a/shaders/include/shadows.glsl b/shaders/include/shadows.glsl index 98789c56..6a6dacd0 100644 --- a/shaders/include/shadows.glsl +++ b/shaders/include/shadows.glsl @@ -28,10 +28,7 @@ int getCascadeLevel(vec3 worldPos, mat4 viewMatrix, CascadeSplit cascadeSplits[4 return selectCascadeLevel(viewDepth, cascadeSplits); } -float getShadowFactorBlend(int pcfLevel, vec3 worldPos, mat4 sceneViewMatrix, CascadeSplit[4] splits, mat4[4] lightMatrices, sampler2DShadow[4] shadowMaps, float cascadeNearPlane, float cascadeFarPlane) { - vec4 viewPos = sceneViewMatrix * vec4(worldPos, 1.0); - float viewSpaceDepth = abs(viewPos.z); - +float getShadowFactorBlend(int pcfLevel, vec3 worldPos, float viewSpaceDepth, CascadeSplit[4] splits, mat4[4] lightMatrices, sampler2DShadow[4] shadowMaps, float cascadeNearPlane, float cascadeFarPlane) { if (viewSpaceDepth < cascadeNearPlane) { // Too close = shadowed return 0.0f; diff --git a/shaders/postProcess.comp b/shaders/postProcess.comp index c8de1622..25c39cb9 100644 --- a/shaders/postProcess.comp +++ b/shaders/postProcess.comp @@ -54,8 +54,8 @@ void main() { vec3 color = fullColor.rgb; if ((push.flags & 1) != 0) { - //color = reinhardTonemap(color); color = aces(color); + //color = aces(color); } if ((push.flags & 4) != 0) { @@ -67,8 +67,5 @@ void main() { color = sharpen(color, sceneData.texelSize, uv); } - - - imageStore(outputImage, pixel, vec4(color, fullColor.a)); } \ No newline at end of file diff --git a/shaders/shadows/contact_shadow_pass.comp b/shaders/shadows/contact_shadow_pass.comp new file mode 100644 index 00000000..b9602452 --- /dev/null +++ b/shaders/shadows/contact_shadow_pass.comp @@ -0,0 +1,383 @@ +#version 460 +//#extension GL_KHR_shader_subgroup_vote : require +//#extension GL_KHR_shader_subgroup_basic : require + +#include "scene.glsl" + +#define WAVE_SIZE 64 + +layout(local_size_x = WAVE_SIZE, local_size_y = 1, local_size_z = 1) in; + +// layout (std140, set = 0, binding = 0) uniform SceneData - scene.glsl + +layout (set = 1, binding = 0) uniform sampler2D depthImage; +layout (r8, set = 1, binding = 1) uniform image2D contactShadow; +layout (rgba8, set = 1, binding = 2) uniform image2D debugImage; + +#define SAMPLE_COUNT 60 + +// Number of bilinear sample reads performed per-thread +#define READ_COUNT (SAMPLE_COUNT / WAVE_SIZE + 2) + +// samples requires for hard shadow +#define HARD_SHADOW_SAMPLES 4 +// shadow fade at shadow edges +#define FADE_OUT_SAMPLES 8 + +// Main camera depth bounds +#define NEAR_DEPTH_VALUE 1 +#define FAR_DEPTH_VALUE 0 + +// Light VP dpeth bounds +#define DEPTH_BOUNDS vec2(0, 1) + +#define USE_HALF_PIXEL_OFFSET 1 + +layout (push_constant) uniform PushConstants { + float surfaceThickness; + float bilinearThreshold; + float shadowContrast; + + int bIgnoreEdgePixels; + int bUsePrecisionOffset; + int bilinearSamplingOffsetMode; + + vec2 depthBounds; + int bUseEarlyOut; + + int debugMode; + + ivec2 waveOffset; + vec4 lightCoordinate; + +} pushConstants; + +shared float DepthData[READ_COUNT * WAVE_SIZE]; +shared bool LdsEarlyOut; + +void ComputeWavefrontExtents(ivec2 waveOffset, vec4 lightCoordinate, ivec3 inGroupID, uint inGroupThreadID, +out vec2 outDeltaXY, out vec2 outPixelXY, out float outPixelDistance, out bool outMajorAxisX) +{ + ivec2 xy = inGroupID.yz * WAVE_SIZE + waveOffset.xy; + + // Integer light position / fractional component + vec2 light_xy = floor(lightCoordinate.xy) + 0.5; + vec2 light_xy_fraction = lightCoordinate.xy - light_xy; + bool reverse_direction = lightCoordinate.w > 0.0; + + ivec2 sign_xy = ivec2(sign(vec2(xy))); + bool horizontal = abs(xy.x + sign_xy.y) < abs(xy.y - sign_xy.x); + + ivec2 axis; + axis.x = horizontal ? (+sign_xy.y) : (0); + axis.y = horizontal ? (0) : (-sign_xy.x); + + // Apply wave offset + xy = axis * int(inGroupID.x) + xy; + vec2 xy_f = vec2(xy); + + // For interpolation to the light center, we only really care about the larger of the two axis + bool x_axis_major = abs(xy_f.x) > abs(xy_f.y); + float major_axis = x_axis_major ? xy_f.x : xy_f.y; + + float major_axis_start = abs(major_axis); + float major_axis_end = abs(major_axis) - float(WAVE_SIZE); + + float ma_light_frac = x_axis_major ? light_xy_fraction.x : light_xy_fraction.y; + ma_light_frac = major_axis > 0.0 ? -ma_light_frac : ma_light_frac; + + // Back in to screen direction + vec2 start_xy = xy_f + light_xy; + + // For the very inner most ring, we need to interpolate to a pixel centered UV, + // so the UV->pixel rounding doesn't skip output pixels + vec2 end_xy = mix(lightCoordinate.xy, start_xy, (major_axis_end + ma_light_frac) / (major_axis_start + ma_light_frac)); + + // The major axis should be a round number + vec2 xy_delta = (start_xy - end_xy); + + // Inverse the read order when reverse direction is true + float thread_step = float(inGroupThreadID ^ (reverse_direction ? 0u : (WAVE_SIZE - 1u))); + + vec2 pixel_xy = mix(start_xy, end_xy, thread_step / float(WAVE_SIZE)); + float pixel_distance = major_axis_start - thread_step + ma_light_frac; + + outPixelXY = pixel_xy; + outPixelDistance = pixel_distance; + outDeltaXY = xy_delta; + outMajorAxisX = x_axis_major; +} + + +bool EarlyOutPixel(vec2 depthBounds, vec2 pixel_xy, float depth) +{ + //OPTIONAL TODO; customize this function to return true if the pixel should early-out for custom reasons. E.g., A shadow map pass already found the pixel was in shadow / backfaced, etc. + // Recommended to keep this code very simple! + + // Example: + // return inParameters.CustomShadowMapTerm[pixel_xy] == 0; + + // (void)pixel_xy; //unused by this implementation, avoid potential compiler warning. + + // The compiled code will be more optimal if the 'depth' value is not referenced. + return depth >= depthBounds.y || depth <= depthBounds.x; +} + +void main() { + vec2 xy_delta; + vec2 pixel_xy; + float pixel_distance; + bool x_axis_major; + + ComputeWavefrontExtents(pushConstants.waveOffset, pushConstants.lightCoordinate, ivec3(gl_WorkGroupID), gl_LocalInvocationID.x, + xy_delta, pixel_xy, pixel_distance, x_axis_major); + + // Read in the depth values + float sampling_depth[READ_COUNT]; + float shadowing_depth[READ_COUNT]; + float depth_thickness_scale[READ_COUNT]; + float sample_distance[READ_COUNT]; + + const float direction = -pushConstants.lightCoordinate.w; + const float z_sign = NEAR_DEPTH_VALUE > FAR_DEPTH_VALUE ? -1 : +1; + + int i; + bool is_edge = false; + bool skip_pixel = false; + vec2 write_xy = floor(pixel_xy); + // Flip because of Vulkan + write_xy.y = sceneData.renderTargetSize.y - write_xy.y; + + for (i = 0; i < READ_COUNT; i++) + { + // We sample depth twice per pixel per sample, and interpolate with an edge detect filter + // Interpolation should only occur on the minor axis of the ray - major axis coordinates should be at pixel centers + vec2 read_xy = floor(pixel_xy); + float minor_axis = x_axis_major ? pixel_xy.y : pixel_xy.x; + + // If a pixel has been detected as an edge, then optionally (inParameters.IgnoreEdgePixels) don't include it in the shadow + const float edge_skip = 1e20;// if edge skipping is enabled, apply an extreme value/blend on edge samples to push the value out of range + + vec2 depths; + float bilinear = fract(minor_axis) - 0.5; + + #if USE_HALF_PIXEL_OFFSET + read_xy += 0.5; + #endif + + // HLSL enforces that a pixel offset is a compile-time constant, which isn't strictly required (and can sometimes be a bit faster) + // So this fallback will use a manual uv offset instead + int bias = bilinear > 0 ? 1 : -1; + vec2 offset_xy = vec2(x_axis_major ? 0 : bias, x_axis_major ? bias : 0); + + // Flip because vulkan + vec2 read_xy_one = read_xy * sceneData.texelSize; + read_xy_one.y = 1 - read_xy_one.y; + vec2 read_xy_two = (read_xy + offset_xy) * sceneData.texelSize; + read_xy_two.y = 1 - read_xy_two.y; + depths.x = textureLod(depthImage, read_xy_one, 0).r; + depths.y = textureLod(depthImage, read_xy_two, 0).r; + + // Depth thresholds (bilinear/shadow thickness) are based on a fractional ratio of the difference between sampled depth and the far clip depth + depth_thickness_scale[i] = abs(FAR_DEPTH_VALUE - depths.x); + + // If depth variance is more than a specific threshold, then just use point filtering + bool use_point_filter = abs(depths.x - depths.y) > depth_thickness_scale[i] * pushConstants.bilinearThreshold; + + // Store for debug output when inParameters.DebugOutputEdgeMask is true + if (i == 0) { + is_edge = use_point_filter; + } + + if (pushConstants.bilinearSamplingOffsetMode == 1) + { + bilinear = use_point_filter ? 0 : bilinear; + //both shadow depth and starting depth are the same in this mode, unless shadow skipping edges + sampling_depth[i] = mix(depths.x, depths.y, abs(bilinear)); + shadowing_depth[i] = (pushConstants.bIgnoreEdgePixels == 1 && use_point_filter) ? edge_skip : sampling_depth[i]; + } + else + { + // The pixel starts sampling at this depth + sampling_depth[i] = depths.x; + + float edge_depth = pushConstants.bIgnoreEdgePixels == 1 ? edge_skip : depths.x; + // Any sample in this wavefront is possibly interpolated towards the bilinear sample + // So use should use a shadowing depth that is further away, based on the difference between the two samples + float shadow_depth = depths.x + abs(depths.x - depths.y) * z_sign; + + // Shadows cast from this depth + shadowing_depth[i] = use_point_filter ? edge_depth : shadow_depth; + } + + // Store for later + sample_distance[i] = pixel_distance + (WAVE_SIZE * i) * direction; + + // Iterate to the next pixel along the ray. This will be WAVE_SIZE pixels along the ray... + pixel_xy += xy_delta * direction; + } + + // Commenting out early out code because I'm not able to figure out the glsl equivalent to the subgroup/wave lane shit + // Using early out, and no debug mode is enabled? + // if (pushConstants.bUseEarlyOut == 1 && pushConstants.debugMode == 0) + // { + // // read the depth of the pixel we are shadowing, and early-out + // // The compiler will typically rearrange this code to put it directly after the first depth read + // skip_pixel = EarlyOutPixel(DEPTH_BOUNDS, write_xy, sampling_depth[0]); + // + // // are all threads in this wave out of bounds? + // bool earl_out = subgroupAny(!skip_pixel) == false; + // + // // WaveGetLaneCount returns the hardware wave size + // if (gl_SubgroupSize == WAVE_SIZE) + // { + // // Optimal case: + // // If each wavefront is just a single wave, then we can trivially early-out. + // if (early_out == true){ + // return; + // } + // + // } + // else + // { + // // This wavefront is made up of multiple small waves, so we need to coordinate them for all to early-out together. + // // Doing this can make the worst case (all pixels drawn) a bit more expensive (~15%), but the best-case (all early-out) is typically 2-3x better. + // LdsEarlyOut = true; + // + // memoryBarrierShared(); + // barrier(); + // + // if (early_out == false){ + // LdsEarlyOut = false; + // } + // + // + // memoryBarrierShared(); + // barrier(); + // + // if (LdsEarlyOut) + // return; + // } + // } + + // Write the shadow depths to LDS + for (i = 0; i < READ_COUNT; i++) + { + // Perspective correct the shadowing depth, in this space, all light rays are parallel + float stored_depth = (shadowing_depth[i] - pushConstants.lightCoordinate.z) / sample_distance[i]; + + if (i != 0) + { + // For pixels within sampling distance of the light, it is possible that sampling will + // overshoot the light coordinate for extended reads. We want to ignore these samples + stored_depth = sample_distance[i] > 0 ? stored_depth : 1e10; + } + + // Store the depth values in groupshared + int idx = (i * WAVE_SIZE) + int(gl_LocalInvocationID.x); + DepthData[idx] = stored_depth; + } + + // Sync wavefronts now groupshared DepthData is written + memoryBarrierShared(); + barrier(); + + // If the starting depth isn't in depth bounds, then we don't need a shadow + if (skip_pixel){ + return; + } + + float start_depth = sampling_depth[0]; + + // lerp away from far depth by a tiny fraction? + if (pushConstants.bUsePrecisionOffset == 1){ + start_depth = mix(start_depth, FAR_DEPTH_VALUE, -1.0 / 0xFFFF); + } + + // perspective correct the depth + start_depth = (start_depth - pushConstants.lightCoordinate.z) / sample_distance[0]; + + // Start by reading the next value + int sample_index = int(gl_LocalInvocationID.x) + 1; + + vec4 shadow_value = vec4(1.0f); + float hard_shadow = 1; + + // This is the inverse of how large the shadowing window is for the projected sample data. + // All values in the LDS sample list are scaled by 1.0 / sample_distance, such that all light directions become parallel. + // The multiply by sample_distance[0] here is to compensate for the projection divide in the data. + // The 1.0 / inParameters.SurfaceThickness is to adjust user selected thickness. So a 0.5% thickness will scale depth values from [0,1] to [0,200]. The shadow window is always 1 wide. + // 1.0 / depth_thickness_scale[0] is because SurfaceThickness is percentage of remaining depth between the sample and the far clip - not a percentage of the full depth range. + // The min() function is to make sure the window is a minimum width when very close to the light. The +direction term will bias the result so the pixel at the very center of the light is either fully lit or shadowed + float depth_scale = min(sample_distance[0] + direction, 1.0 / pushConstants.surfaceThickness) * sample_distance[0] / depth_thickness_scale[0]; + + start_depth = start_depth * depth_scale - z_sign; + + // The first number of hard shadow samples, a single pixel can produce a full shadow + for (i = 0; i < HARD_SHADOW_SAMPLES; i++) + { + float depth_delta = abs(start_depth - DepthData[sample_index + i] * depth_scale); + + // We want to find the distance of the sample that is closest to the reference depth + hard_shadow = min(hard_shadow, depth_delta); + } + + // Brute force go! + // The main shadow samples, averaged in to a set of 4 shadow values + for (i = HARD_SHADOW_SAMPLES; i < SAMPLE_COUNT - FADE_OUT_SAMPLES; i++) + { + float depth_delta = abs(start_depth - DepthData[sample_index + i] * depth_scale); + + // Do the same as the hard_shadow code above, but this will accumulate to 4 separate values. + // By using 4 values, the average shadow can be taken, which can help soften single-pixel shadows. + shadow_value[i & 3] = min(shadow_value[i & 3], depth_delta); + } + + // Final fade out samples + for (i = SAMPLE_COUNT - FADE_OUT_SAMPLES; i < SAMPLE_COUNT; i++) + { + float depth_delta = abs(start_depth - DepthData[sample_index + i] * depth_scale); + + // Add the fade value to these samples + const float fade_out = float(i + 1 - (SAMPLE_COUNT - FADE_OUT_SAMPLES)) / float((FADE_OUT_SAMPLES + 1) * 0.75); + + shadow_value[i & 3] = min(shadow_value[i & 3], depth_delta + fade_out); + } + + // Apply the contrast value. + // A value of 0 indicates a sample was exactly matched to the reference depth (and the result is fully shadowed) + // We want some boost to this range, so samples don't have to exactly match to produce a full shadow. + shadow_value = clamp(shadow_value * (pushConstants.shadowContrast) + (1 - pushConstants.shadowContrast), 0, 1); + hard_shadow = clamp(hard_shadow * (pushConstants.shadowContrast) + (1 - pushConstants.shadowContrast), 0, 1); + + float result = 0; + + // Take the average of 4 samples, this is useful to reduces aliasing noise in the source depth, especially with long shadows. + result = dot(shadow_value, vec4(0.25)); + + // If the first samples are always producing a hard shadow, then compute this value separately. + result = min(hard_shadow, result); + + //write the result + { + switch (pushConstants.debugMode){ + case 1: + float edge = is_edge ? 1 : 0; + imageStore(debugImage, ivec2(write_xy), vec4(vec3(edge), 1.0f)); + break; + case 2: + float invocIndex = (gl_LocalInvocationID.x / float(WAVE_SIZE)); + imageStore(debugImage, ivec2(write_xy), vec4(vec3(invocIndex), 1.0f)); + break; + case 3: + float workGroup = fract(ivec3(gl_WorkGroupID).x / float(WAVE_SIZE)); + imageStore(debugImage, ivec2(write_xy), vec4(vec3(workGroup), 1.0f)); + break; + default: + imageStore(debugImage, ivec2(write_xy), vec4(vec3(result), 1.0f)); + break; + } + + imageStore(contactShadow, ivec2(write_xy), vec4(vec3(result), 1.0f)); + } +} diff --git a/shaders/shadows/shadow_pass.frag b/shaders/shadows/shadow_pass.frag index 2a921715..364e023b 100644 --- a/shaders/shadows/shadow_pass.frag +++ b/shaders/shadows/shadow_pass.frag @@ -1,5 +1,5 @@ #version 460 void main() { - + // todo: discard if the fragment is cutoff } \ No newline at end of file diff --git a/shaders/terrain/terrain.frag b/shaders/terrain/terrain.frag index 4aef3906..4f2dfd81 100644 --- a/shaders/terrain/terrain.frag +++ b/shaders/terrain/terrain.frag @@ -41,7 +41,7 @@ float smoothBlend(float value, float threshold, float range) { } void main() { - normalTarget = vec4(normalize(inNormal), 0.0f); + normalTarget = vec4(mat3(sceneData.view) * normalize(inNormal), 0.0f); float slope = 1.0 - abs(dot(normalize(inNormal), vec3(0.0, 1.0, 0.0))); float height = inPosition.y; diff --git a/shaders/transparent.frag b/shaders/transparent.frag index d5bc4dd0..5464375f 100644 --- a/shaders/transparent.frag +++ b/shaders/transparent.frag @@ -12,8 +12,8 @@ #include "transparent.glsl" // world space -layout (location = 0) in vec3 inPosition; -layout (location = 1) in vec3 inNormal; +layout (location = 0) in vec3 inViewPosition; +layout (location = 1) in vec3 inViewNormal; layout (location = 2) in vec4 inColor; layout (location = 3) in vec2 inUV; layout (location = 4) in flat uint inMaterialIndex; @@ -81,10 +81,11 @@ void main() { roughness *= metalRoughSample.g; } - vec3 N = normalize(inNormal); - vec3 V = normalize(sceneData.cameraPos.xyz - inPosition); + vec3 N = normalize(inViewNormal); + vec3 V = normalize(-inViewPosition); - vec3 L = normalize(-shadowCascadeData.directionalLightData.direction); // for point lights, light.pos - inPosition + // for point lights, light.pos - inPosition + vec3 L = normalize(mat3(sceneData.view) * normalize(-shadowCascadeData.directionalLightData.direction)); vec3 H = normalize(V + L); // SPECULAR @@ -107,9 +108,10 @@ void main() { // SHADOWS float offset = 0.05f; - float normalOffsetScale = max(offset, dot(inNormal, L) * offset); - vec3 offsetPosition = inPosition + inNormal * normalOffsetScale; - float _tempShadowFactor = getShadowFactorBlend(1, inPosition, sceneData.view, shadowCascadeData.cascadeSplits, shadowCascadeData.lightViewProj, shadowMapSampler, shadowCascadeData.nearShadowPlane, shadowCascadeData.farShadowPlane); + float normalOffsetScale = max(offset, dot(N, L) * offset); + vec3 offsetPosition = inViewPosition + N * normalOffsetScale; + vec4 worldPosition = sceneData.invView * vec4(offsetPosition, 1.0f); + float _tempShadowFactor = getShadowFactorBlend(1, worldPosition.xyz, abs(inViewPosition.z), shadowCascadeData.cascadeSplits, shadowCascadeData.lightViewProj, shadowMapSampler, shadowCascadeData.nearShadowPlane, shadowCascadeData.farShadowPlane); float shadowFactor = clamp(smoothstep(-0.15f, 0.5f, dot(N, L)) * _tempShadowFactor, 0, 1); if (pushConstants.receiveShadows == 0) { @@ -119,9 +121,10 @@ void main() { vec3 directLight = (diffuse + specular) * nDotL * shadowFactor * shadowCascadeData.directionalLightData.intensity * shadowCascadeData.directionalLightData.color; // IBL Reflections - vec3 irradiance = DiffuseIrradiance(environmentDiffuseAndSpecular, N); + vec3 worldN = normalize(mat3(sceneData.invView) * N); + vec3 irradiance = DiffuseIrradiance(environmentDiffuseAndSpecular, worldN); vec3 reflectionDiffuse = irradiance * albedo.xyz; - vec3 reflectionSpecular = SpecularReflection(environmentDiffuseAndSpecular, lut, V, N, roughness, F); + vec3 reflectionSpecular = SpecularReflection(environmentDiffuseAndSpecular, lut, V, N, sceneData.invView, roughness, F); float ao = 1.0f; vec3 ambient = (kD * reflectionDiffuse + reflectionSpecular) * ao; diff --git a/shaders/transparent.vert b/shaders/transparent.vert index d41c7f83..79846653 100644 --- a/shaders/transparent.vert +++ b/shaders/transparent.vert @@ -20,8 +20,8 @@ layout (location = 1) in vec3 normal; layout (location = 2) in vec4 color; layout (location = 3) in vec2 uv; -layout (location = 0) out vec3 outPosition; -layout (location = 1) out vec3 outNormal; +layout (location = 0) out vec3 outViewPosition; +layout (location = 1) out vec3 outViewNormal; layout (location = 2) out vec4 outColor; layout (location = 3) out vec2 outUV; layout (location = 4) out flat uint outMaterialIndex; @@ -32,16 +32,17 @@ void main() { uint materialIndex = primitive.materialIndex; Model models = bufferAddresses.modelBufferDeviceAddress.models[modelIndex]; - vec4 worldPos = models.currentModelMatrix * vec4(position, 1.0); + vec4 viewPos = sceneData.view * models.currentModelMatrix * vec4(position, 1.0); - outPosition = worldPos.xyz; - outNormal = adjugate(models.currentModelMatrix) * normal; + outViewPosition = viewPos.xyz; + outViewNormal = mat3(sceneData.view) * adjugate(models.currentModelMatrix) * normal; outColor = color; outUV = uv; outMaterialIndex = materialIndex; - vec4 currClipPos = sceneData.viewProj * worldPos; + vec4 currClipPos = sceneData.proj * viewPos; currClipPos.xy += currClipPos.w * sceneData.jitter.xy; + // do not calculate previous because transparents shouldn't contribute motion vectors gl_Position = currClipPos; } \ No newline at end of file diff --git a/src/core/engine.cpp b/src/core/engine.cpp index 13096278..0a9455b9 100644 --- a/src/core/engine.cpp +++ b/src/core/engine.cpp @@ -26,15 +26,22 @@ #include "src/renderer/assets/render_object/render_object.h" #include "src/renderer/descriptor_buffer/descriptor_buffer_uniform.h" #include "src/renderer/environment/environment.h" -#include "src/renderer/lighting/ambient_occlusion/ground_truth/ground_truth_ambient_occlusion.h" -#include "src/renderer/lighting/shadows/cascaded_shadow_map.h" -#include "src/renderer/pipelines/deferred_mrt/deferred_mrt.h" -#include "src/renderer/pipelines/deferred_resolve/deferred_resolve.h" -#include "src/renderer/pipelines/environment/environment_pipeline.h" -#include "src/renderer/pipelines/visibility_pass/visibility_pass.h" -#include "src/renderer/pipelines/post_process/post_process_pipeline.h" -#include "src/renderer/pipelines/temporal_antialiasing_pipeline/temporal_antialiasing_pipeline.h" -#include "src/renderer/pipelines/terrain/terrain_pipeline.h" +#include "../renderer/pipelines/shadows/cascaded_shadow_map/cascaded_shadow_map.h" +#include "src/renderer/pipelines/geometry/deferred_mrt/deferred_mrt_pipeline.h" +#include "src/renderer/pipelines/geometry/deferred_mrt/deferred_mrt_pipeline_types.h" +#include "src/renderer/pipelines/geometry/deferred_resolve/deferred_resolve_pipeline.h" +#include "src/renderer/pipelines/geometry/deferred_resolve/deferred_resolve_pipeline_types.h" +#include "src/renderer/pipelines/geometry/environment/environment_pipeline.h" +#include "src/renderer/pipelines/geometry/environment/environment_pipeline_types.h" +#include "src/renderer/pipelines/geometry/terrain/terrain_pipeline.h" +#include "src/renderer/pipelines/geometry/terrain/terrain_pipeline_types.h" +#include "src/renderer/pipelines/geometry/transparent_pipeline/transparent_pipeline_types.h" +#include "src/renderer/pipelines/post/post_process/post_process_pipeline.h" +#include "src/renderer/pipelines/post/temporal_antialiasing/temporal_antialiasing_pipeline.h" +#include "src/renderer/pipelines/shadows/contact_shadow/contact_shadows_pipeline_types.h" +#include "src/renderer/pipelines/shadows/ground_truth_ambient_occlusion/ground_truth_ambient_occlusion_pipeline.h" +#include "src/renderer/pipelines/visibility_pass/visibility_pass_pipeline.h" +#include "src/renderer/pipelines/visibility_pass/visibility_pass_pipeline_types.h" #include "src/util/file.h" #include "src/util/halton.h" @@ -149,14 +156,13 @@ void Engine::init() startupProfiler.beginTimer("5Load Environment"); environmentMap->loadEnvironment("Overcast Sky", (envMapSource / "kloofendal_overcast_puresky_4k.hdr").string().c_str(), 2); - environmentMap->loadEnvironment("Wasteland", (envMapSource / "wasteland_clouds_puresky_4k.hdr").string().c_str(), 1); - environmentMap->loadEnvironment("Belfast Sunset", (envMapSource / "belfast_sunset_puresky_4k.hdr").string().c_str(), 0); - environmentMap->loadEnvironment("Rogland Clear Night", (envMapSource / "rogland_clear_night_4k.hdr").string().c_str(), 4); + // environmentMap->loadEnvironment("Wasteland", (envMapSource / "wasteland_clouds_puresky_4k.hdr").string().c_str(), 1); + // environmentMap->loadEnvironment("Belfast Sunset", (envMapSource / "belfast_sunset_puresky_4k.hdr").string().c_str(), 0); + // environmentMap->loadEnvironment("Rogland Clear Night", (envMapSource / "rogland_clear_night_4k.hdr").string().c_str(), 4); startupProfiler.endTimer("5Load Environment"); - startupProfiler.beginTimer("7Load CSM"); + cascadedShadowMap = new cascaded_shadows::CascadedShadowMap(*resourceManager); - startupProfiler.endTimer("7Load CSM"); if (engine_constants::useImgui) { imguiWrapper = new ImguiWrapper(*context, {window, swapchainImageFormat}); @@ -199,11 +205,12 @@ void Engine::initRenderer() sceneDataBufferData[0] = DescriptorUniformData{.uniformBuffer = debugSceneDataBuffer, .allocSize = sizeof(SceneData)}; sceneDataDescriptorBuffer.setupData(context->device, sceneDataBufferData, FRAME_OVERLAP); - visibilityPassPipeline = new visibility_pass::VisibilityPassPipeline(*resourceManager); + visibilityPassPipeline = new visibility_pass_pipeline::VisibilityPassPipeline(*resourceManager); environmentPipeline = new environment_pipeline::EnvironmentPipeline(*resourceManager, environmentMap->getCubemapDescriptorSetLayout()); terrainPipeline = new terrain::TerrainPipeline(*resourceManager); deferredMrtPipeline = new deferred_mrt::DeferredMrtPipeline(*resourceManager); ambientOcclusionPipeline = new ambient_occlusion::GroundTruthAmbientOcclusionPipeline(*resourceManager); + contactShadowsPipeline = new contact_shadows_pipeline::ContactShadowsPipeline(*resourceManager); deferredResolvePipeline = new deferred_resolve::DeferredResolvePipeline(*resourceManager, environmentMap->getDiffSpecMapDescriptorSetlayout(), cascadedShadowMap->getCascadedShadowMapUniformLayout(), cascadedShadowMap->getCascadedShadowMapSamplerLayout()); @@ -216,6 +223,7 @@ void Engine::initRenderer() ambientOcclusionPipeline->setupDepthPrefilterDescriptorBuffer(depthImage.imageView); ambientOcclusionPipeline->setupAmbientOcclusionDescriptorBuffer(normalRenderTarget.imageView); ambientOcclusionPipeline->setupSpatialFilteringDescriptorBuffer(); + contactShadowsPipeline->setupDescriptorBuffer(depthImage.imageView); const deferred_resolve::DeferredResolveDescriptor deferredResolveDescriptor{ normalRenderTarget.imageView, @@ -224,6 +232,7 @@ void Engine::initRenderer() depthImage.imageView, velocityRenderTarget.imageView, ambientOcclusionPipeline->getAmbientOcclusionRenderTarget().imageView, + contactShadowsPipeline->getContactShadowRenderTarget().imageView, drawImage.imageView, resourceManager->getDefaultSamplerLinear() }; @@ -497,7 +506,7 @@ void Engine::draw(float deltaTime) // Updates Cascaded Shadow Map Properties cascadedShadowMap->update(mainLight, camera, currentFrameOverlap); - visibility_pass::VisibilityPassDrawInfo csmFrustumCullDrawInfo{ + visibility_pass_pipeline::VisibilityPassDrawInfo csmFrustumCullDrawInfo{ currentFrameOverlap, allRenderObjects, sceneDataDescriptorBuffer.getDescriptorBufferBindingInfo(), @@ -510,7 +519,7 @@ void Engine::draw(float deltaTime) cascadedShadowMap->draw(cmd, allRenderObjects, activeTerrains, currentFrameOverlap); - vk_helpers::clearColorImage(cmd, drawImage.image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + vk_helpers::clearColorImage(cmd, VK_IMAGE_ASPECT_COLOR_BIT, drawImage.image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); vk_helpers::transitionImage(cmd, depthImage.image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_DEPTH_BIT); @@ -538,7 +547,7 @@ void Engine::draw(float deltaTime) environmentPipeline->draw(cmd, environmentPipelineDrawInfo); - visibility_pass::VisibilityPassDrawInfo deferredFrustumCullDrawInfo{ + visibility_pass_pipeline::VisibilityPassDrawInfo deferredFrustumCullDrawInfo{ currentFrameOverlap, allRenderObjects, sceneDataDescriptorBuffer.getDescriptorBufferBindingInfo(), @@ -635,6 +644,16 @@ void Engine::draw(float deltaTime) }; ambientOcclusionPipeline->draw(cmd, gtaoDrawInfo); + contact_shadows_pipeline::ContactShadowsDrawInfo contactDrawInfo{ + camera, + mainLight, + sssPush, + sceneDataDescriptorBuffer.getDescriptorBufferBindingInfo(), + sceneDataDescriptorBuffer.getDescriptorBufferSize() * currentFrameOverlap + }; + + contactShadowsPipeline->draw(cmd, contactDrawInfo); + const deferred_resolve::DeferredResolveDrawInfo deferredResolveDrawInfo{ deferredDebug, csmPcf, @@ -647,6 +666,8 @@ void Engine::draw(float deltaTime) cascadedShadowMap->getCascadedShadowMapSamplerBuffer().getDescriptorBufferBindingInfo(), camera->getNearPlane(), camera->getFarPlane(), + bEnableShadows, + bEnableContactShadows }; deferredResolvePipeline->draw(cmd, deferredResolveDrawInfo); @@ -654,7 +675,9 @@ void Engine::draw(float deltaTime) transparent_pipeline::TransparentCompositeDrawInfo compositeDrawInfo{ drawImage.imageView }; - transparentPipeline->drawComposite(cmd, compositeDrawInfo); + if (!bHideTransparents) { + transparentPipeline->drawComposite(cmd, compositeDrawInfo); + } vk_helpers::transitionImage(cmd, drawImage.image, VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT); @@ -766,6 +789,7 @@ void Engine::cleanup() delete terrainPipeline; delete deferredMrtPipeline; delete ambientOcclusionPipeline; + delete contactShadowsPipeline; delete deferredResolvePipeline; delete temporalAntialiasingPipeline; delete transparentPipeline; @@ -1062,6 +1086,7 @@ void Engine::hotReloadShaders() const deferredMrtPipeline->reloadShaders(); transparentPipeline->reloadShaders(); ambientOcclusionPipeline->reloadShaders(); + contactShadowsPipeline->reloadShaders(); deferredResolvePipeline->reloadShaders(); temporalAntialiasingPipeline->reloadShaders(); postProcessPipeline->reloadShaders(); diff --git a/src/core/engine.h b/src/core/engine.h index f6d93500..7307fec2 100644 --- a/src/core/engine.h +++ b/src/core/engine.h @@ -20,8 +20,9 @@ #include "src/renderer/assets/asset_manager.h" #include "src/renderer/descriptor_buffer/descriptor_buffer_uniform.h" #include "src/renderer/lighting/directional_light.h" -#include "src/renderer/pipelines/transparent_pipeline/transparent_pipeline.h" -#include "src/renderer/post_process/post_process_types.h" +#include "src/renderer/pipelines/post/post_process/post_process_pipeline_types.h" +#include "src/renderer/pipelines/geometry/transparent_pipeline/transparent_pipeline.h" +#include "src/renderer/pipelines/shadows/contact_shadow/contact_shadows_pipeline.h" class ResourceManager; @@ -64,7 +65,7 @@ namespace deferred_mrt class DeferredMrtPipeline; } -namespace visibility_pass +namespace visibility_pass_pipeline { class VisibilityPassPipeline; } @@ -155,7 +156,6 @@ class Engine identifier::IdentifierManager* identifierManager = nullptr; environment::Environment* environmentMap{nullptr}; - cascaded_shadows::CascadedShadowMap* cascadedShadowMap{nullptr}; terrain::TerrainManager* terrainManager{nullptr}; ImguiWrapper* imguiWrapper = nullptr; @@ -182,10 +182,14 @@ class Engine int32_t csmPcf{1}; int32_t deferredDebug{0}; int32_t gtaoDebug{4}; + contact_shadows_pipeline::ContactShadowsPushConstants sssPush; bool bDrawTerrainLines{false}; bool bPausePhysics{true}; bool bDisableJitter{false}; - bool bRenderTransparents{true}; + bool bHideTransparents{true}; + bool bEnableGTAO{true}; + bool bEnableShadows{true}; + bool bEnableContactShadows{true}; void hotReloadShaders() const; @@ -194,6 +198,9 @@ class Engine DirectionalLight getMainLight() const { return mainLight; } void setMainLight(const DirectionalLight& newLight) { mainLight = newLight; } + int32_t getCurrentEnvironmentMapIndex() const { return environmentMapIndex; } + void setCurrentEnvironmentMapIndex(const int32_t index) { environmentMapIndex = index; } + private: // Scene Data DescriptorBufferUniform sceneDataDescriptorBuffer; AllocatedBuffer sceneDataBuffers[FRAME_OVERLAP]{}; @@ -203,7 +210,7 @@ class Engine DirectionalLight mainLight{glm::normalize(glm::vec3(-0.8f, -0.6f, -0.6f)), 1.5f, glm::vec3(1.0f)}; int32_t environmentMapIndex{1}; - post_process::PostProcessType postProcessData{post_process::PostProcessType::Tonemapping | post_process::PostProcessType::Sharpening}; + post_process_pipeline::PostProcessType postProcessData{post_process_pipeline::PostProcessType::Tonemapping | post_process_pipeline::PostProcessType::Sharpening}; std::unordered_set activeMaps; std::unordered_set activeTerrains; @@ -214,14 +221,20 @@ class Engine std::vector hierarchicalDeletionQueue{}; private: // Pipelines - visibility_pass::VisibilityPassPipeline* visibilityPassPipeline{nullptr}; + visibility_pass_pipeline::VisibilityPassPipeline* visibilityPassPipeline{nullptr}; + environment_pipeline::EnvironmentPipeline* environmentPipeline{nullptr}; terrain::TerrainPipeline* terrainPipeline{nullptr}; deferred_mrt::DeferredMrtPipeline* deferredMrtPipeline{nullptr}; deferred_resolve::DeferredResolvePipeline* deferredResolvePipeline{nullptr}; + transparent_pipeline::TransparentPipeline* transparentPipeline{nullptr}; + + cascaded_shadows::CascadedShadowMap* cascadedShadowMap{nullptr}; + contact_shadows_pipeline::ContactShadowsPipeline* contactShadowsPipeline{nullptr}; ambient_occlusion::GroundTruthAmbientOcclusionPipeline* ambientOcclusionPipeline{nullptr}; + temporal_antialiasing_pipeline::TemporalAntialiasingPipeline* temporalAntialiasingPipeline{nullptr}; - transparent_pipeline::TransparentPipeline* transparentPipeline{nullptr}; + post_process_pipeline::PostProcessPipeline* postProcessPipeline{nullptr}; private: // Draw Resources @@ -229,7 +242,7 @@ class Engine AllocatedImage depthImage{}; /** - * 8.8.8 Normals - 8 unused + * 8.8.8 View Normals - 8 unused */ AllocatedImage normalRenderTarget{}; /** diff --git a/src/core/scene/serializer.cpp b/src/core/scene/serializer.cpp index 2e9e2adb..e86ecd37 100644 --- a/src/core/scene/serializer.cpp +++ b/src/core/scene/serializer.cpp @@ -356,6 +356,8 @@ bool Serializer::serializeEngineSettings(Engine* engine) rootJ["cameraProperties"] = cameraProperties; + rootJ["environmentMapIndex"] = engine->getCurrentEnvironmentMapIndex(); + const std::filesystem::path filepath = {"assets/settings.willengine"}; @@ -457,6 +459,10 @@ bool Serializer::deserializeEngineSettings(Engine* engine) engine->setMainLight(light); } + if (rootJ.contains("environmentMapIndex")) { + engine->setCurrentEnvironmentMapIndex(rootJ["environmentMapIndex"]); + } + return true; } catch (const std::exception& e) { diff --git a/src/renderer/assets/asset_manager.cpp b/src/renderer/assets/asset_manager.cpp index 683572b8..d36c38d0 100644 --- a/src/renderer/assets/asset_manager.cpp +++ b/src/renderer/assets/asset_manager.cpp @@ -69,7 +69,7 @@ std::vector will_engine::AssetManager::getAllTextures() std::ranges::transform(textures, std::back_inserter(result), [](const auto& pair) { return pair.second.get(); }); - return std::move(result); + return result; } will_engine::Texture* will_engine::AssetManager::getAnyTexture() const diff --git a/src/renderer/assets/render_object/render_object.h b/src/renderer/assets/render_object/render_object.h index 487a2cbd..6c92e820 100644 --- a/src/renderer/assets/render_object/render_object.h +++ b/src/renderer/assets/render_object/render_object.h @@ -12,7 +12,6 @@ #include "src/core/game_object/renderable.h" #include "src/renderer/renderer_constants.h" #include "src/renderer/resource_manager.h" -#include "src/renderer/pipelines/basic_compute/basic_compute_pipeline.h" namespace will_engine diff --git a/src/renderer/imgui_wrapper.cpp b/src/renderer/imgui_wrapper.cpp index 0da4d065..1ab11205 100644 --- a/src/renderer/imgui_wrapper.cpp +++ b/src/renderer/imgui_wrapper.cpp @@ -12,9 +12,10 @@ #include "environment/environment.h" -#include "lighting/ambient_occlusion/ground_truth/ground_truth_ambient_occlusion.h" -#include "lighting/shadows/cascaded_shadow_map.h" -#include "lighting/shadows/shadow_constants.h" +#include "pipelines/post/post_process/post_process_pipeline_types.h" +#include "pipelines/shadows/cascaded_shadow_map/cascaded_shadow_map.h" +#include "pipelines/shadows/ground_truth_ambient_occlusion/ambient_occlusion_types.h" +#include "pipelines/shadows/ground_truth_ambient_occlusion/ground_truth_ambient_occlusion_pipeline.h" #include "src/core/engine.h" #include "src/core/time.h" #include "src/core/camera/free_camera.h" @@ -197,7 +198,18 @@ void ImguiWrapper::imguiInterface(Engine* engine) if (ImGui::Button("Hot-Reload Shaders")) { engine->hotReloadShaders(); } - ImGui::Checkbox("Enable Transparent Primitives", &engine->bRenderTransparents); + ImGui::Checkbox("Disable Transparent Primitives", &engine->bHideTransparents); + bool aoDisabled = engine->gtaoDebug == -1; + if (ImGui::Checkbox("Disable GTAO", &aoDisabled)) { + if (aoDisabled) { + engine->gtaoDebug = -1; + } else { + engine->gtaoDebug = 0; + } + } + ImGui::Checkbox("Enable Shadows", &engine->bEnableShadows); + ImGui::Checkbox("Enable Contact Shadows", &engine->bEnableContactShadows); + ImGui::Separator(); ImGui::Text("Main Directional Light"); float direction[3] = {engine->mainLight.direction.x, engine->mainLight.direction.y, engine->mainLight.direction.z}; @@ -210,13 +222,12 @@ void ImguiWrapper::imguiInterface(Engine* engine) } ImGui::DragFloat("Intensity", &engine->mainLight.intensity, 0.05f, 0.0f, 5.0f); - ImGui::Separator(); ImGui::Checkbox("Disable Physics", &engine->bPausePhysics); ImGui::Text("Deferred Debug"); - const char* deferredDebugOptions[]{"None", "Depth", "Velocity", "Albedo", "Normal", "PBR", "Shadows", "Cascade Level", "nDotL", "AO"}; + const char* deferredDebugOptions[]{"None", "Depth", "Velocity", "Albedo", "Normal", "PBR", "Shadows", "Cascade Level", "nDotL", "AO", "Contact Shadows"}; ImGui::Combo("Deferred Debug", &engine->deferredDebug, deferredDebugOptions, IM_ARRAYSIZE(deferredDebugOptions)); ImGui::Separator(); @@ -232,38 +243,38 @@ void ImguiWrapper::imguiInterface(Engine* engine) ImGui::Checkbox("Disable Jitter", &engine->bDisableJitter); } - static bool tonemapping = (engine->postProcessData & post_process::PostProcessType::Tonemapping) != - post_process::PostProcessType::None; + static bool tonemapping = (engine->postProcessData & post_process_pipeline::PostProcessType::Tonemapping) != + post_process_pipeline::PostProcessType::None; if (ImGui::CollapsingHeader("Tonemapping", ImGuiTreeNodeFlags_DefaultOpen)) { if (ImGui::Checkbox("Enable Tonemapping", &tonemapping)) { if (tonemapping) { - engine->postProcessData |= post_process::PostProcessType::Tonemapping; + engine->postProcessData |= post_process_pipeline::PostProcessType::Tonemapping; } else { - engine->postProcessData &= ~post_process::PostProcessType::Tonemapping; + engine->postProcessData &= ~post_process_pipeline::PostProcessType::Tonemapping; } } } if (ImGui::CollapsingHeader("Sharpening", ImGuiTreeNodeFlags_DefaultOpen)) { - static bool sharpening = (engine->postProcessData & post_process::PostProcessType::Sharpening) != - post_process::PostProcessType::None; + static bool sharpening = (engine->postProcessData & post_process_pipeline::PostProcessType::Sharpening) != + post_process_pipeline::PostProcessType::None; if (ImGui::Checkbox("Enable Sharpening", &sharpening)) { if (sharpening) { - engine->postProcessData |= post_process::PostProcessType::Sharpening; + engine->postProcessData |= post_process_pipeline::PostProcessType::Sharpening; } else { - engine->postProcessData &= ~post_process::PostProcessType::Sharpening; + engine->postProcessData &= ~post_process_pipeline::PostProcessType::Sharpening; } } } if (ImGui::CollapsingHeader("FXAA", ImGuiTreeNodeFlags_DefaultOpen)) { - static bool fxaa = (engine->postProcessData & post_process::PostProcessType::FXAA) != post_process::PostProcessType::None; + static bool fxaa = (engine->postProcessData & post_process_pipeline::PostProcessType::FXAA) != post_process_pipeline::PostProcessType::None; if (ImGui::Checkbox("Enable FXAA", &fxaa)) { if (fxaa) { - engine->postProcessData |= post_process::PostProcessType::FXAA; + engine->postProcessData |= post_process_pipeline::PostProcessType::FXAA; } else { - engine->postProcessData &= ~post_process::PostProcessType::FXAA; + engine->postProcessData &= ~post_process_pipeline::PostProcessType::FXAA; } } } @@ -349,7 +360,7 @@ void ImguiWrapper::imguiInterface(Engine* engine) ImGui::Spacing(); ImGui::Text("Other Parameters"); ImGui::Separator(); - ImGui::InputInt("Debug Mode", >ao.debug); + ImGui::InputInt("Debug Mode", &engine->gtaoDebug); ImGui::Spacing(); if (ImGui::Button("Reset to Defaults")) { @@ -1077,18 +1088,27 @@ void ImguiWrapper::imguiInterface(Engine* engine) ImGui::End(); if (ImGui::Begin("Discardable Debug")) { - if (transparentDebugTextureImguiId == VK_NULL_HANDLE) { - if (engine->transparentPipeline->debugImage.image != VK_NULL_HANDLE) { - transparentDebugTextureImguiId = ImGui_ImplVulkan_AddTexture( + ImGui::InputFloat("Blinear Threshold", &engine->sssPush.bilinearThreshold); + ImGui::InputFloat("Surface Thickness", &engine->sssPush.surfaceThickness); + ImGui::InputFloat("Shadow Contrast", &engine->sssPush.shadowContrast); + + ImGui::SliderInt("Contact Shadow Debug", &engine->sssPush.debugMode, 0, 3); + + ImGui::SliderInt("Ignore Edge Pixels", &engine->sssPush.bIgnoreEdgePixels, 0, 1); + ImGui::SliderInt("Use Precision Offset", &engine->sssPush.bUsePrecisionOffset, 0, 1); + ImGui::SliderInt("Bilinear Offset Sampling Mode", &engine->sssPush.bBilinearSamplingOffsetMode, 0, 1); + + + if (contactShadowsOutputImguiId == VK_NULL_HANDLE) { + if (engine->contactShadowsPipeline->debugImage.imageView != VK_NULL_HANDLE) { + contactShadowsOutputImguiId = ImGui_ImplVulkan_AddTexture( engine->resourceManager->getDefaultSamplerNearest(), - engine->transparentPipeline->debugImage.imageView, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + engine->contactShadowsPipeline->debugImage.imageView, + VK_IMAGE_LAYOUT_GENERAL); } } - ImGui::BeginChild("TransparentDebugPreview", ImVec2(0, 0), false, ImGuiWindowFlags_None); - - if (transparentDebugTextureImguiId == VK_NULL_HANDLE) { + if (contactShadowsOutputImguiId == VK_NULL_HANDLE) { ImGui::TextColored(ImVec4(1.0f, 0.3f, 0.3f, 1.0f), "Debug texture not available."); } else { @@ -1096,25 +1116,24 @@ void ImguiWrapper::imguiInterface(Engine* engine) float maxSize = ImGui::GetContentRegionAvail().x; maxSize = glm::min(maxSize, 1024.0f); - VkExtent3D imageExtent = engine->transparentPipeline->debugImage.imageExtent; + VkExtent3D imageExtent = engine->contactShadowsPipeline->debugImage.imageExtent; float width = std::min(maxSize, static_cast(imageExtent.width)); float aspectRatio = static_cast(imageExtent.width) / static_cast(imageExtent.height); float height = width / aspectRatio; - ImGui::Image(reinterpret_cast(transparentDebugTextureImguiId), ImVec2(width, height)); + ImGui::Image(reinterpret_cast(contactShadowsOutputImguiId), ImVec2(width, height)); - if (ImGui::Button("Save Transparency Debug Image")) { + if (ImGui::Button("Save SCSS Debug Image")) { if (file::getOrCreateDirectory(file::imagesSavePath)) { - const std::filesystem::path path = file::imagesSavePath / "transparent_debug.png"; + const std::filesystem::path path = file::imagesSavePath / "scss_debug.png"; - vk_helpers::saveImageRGBA16SFLOAT( + vk_helpers::saveImageR8G8B8A8UNORM( *engine->resourceManager, *engine->immediate, - engine->transparentPipeline->debugImage, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - VK_IMAGE_ASPECT_COLOR_BIT, + engine->contactShadowsPipeline->debugImage, + VK_IMAGE_LAYOUT_GENERAL, path.string().c_str(), - false + 0 ); ImGui::OpenPopup("SaveConfirmation"); @@ -1128,37 +1147,7 @@ void ImguiWrapper::imguiInterface(Engine* engine) } ImGui::EndPopup(); } - - ImGui::EndChild(); - } - - if (postProcessOutputImguiId == VK_NULL_HANDLE) { - if (engine->postProcessOutputBuffer.imageView != VK_NULL_HANDLE) { - postProcessOutputImguiId = ImGui_ImplVulkan_AddTexture( - engine->resourceManager->getDefaultSamplerNearest(), - engine->postProcessOutputBuffer.imageView, - VK_IMAGE_LAYOUT_GENERAL); - } } - - ImGui::Separator(); - - if (postProcessOutputImguiId == VK_NULL_HANDLE) { - ImGui::TextColored(ImVec4(1.0f, 0.3f, 0.3f, 1.0f), "Debug texture not available."); - } - else { - // Calculate best fit size - float maxSize = ImGui::GetContentRegionAvail().x; - maxSize = glm::min(maxSize, 1024.0f); - - VkExtent3D imageExtent = engine->postProcessOutputBuffer.imageExtent; - float width = std::min(maxSize, static_cast(imageExtent.width)); - float aspectRatio = static_cast(imageExtent.width) / static_cast(imageExtent.height); - float height = width / aspectRatio; - - ImGui::Image(reinterpret_cast(postProcessOutputImguiId), ImVec2(width, height)); - } - } ImGui::End(); diff --git a/src/renderer/imgui_wrapper.h b/src/renderer/imgui_wrapper.h index 92a203ee..a3aae996 100644 --- a/src/renderer/imgui_wrapper.h +++ b/src/renderer/imgui_wrapper.h @@ -85,9 +85,7 @@ class ImguiWrapper bool showGtaoDebugPreview = false; VkDescriptorSet aoDebugTextureImguiId{VK_NULL_HANDLE}; - VkDescriptorSet transparentDebugTextureImguiId{VK_NULL_HANDLE}; - - VkDescriptorSet postProcessOutputImguiId{VK_NULL_HANDLE}; + VkDescriptorSet contactShadowsOutputImguiId{VK_NULL_HANDLE}; }; } diff --git a/src/renderer/pipelines/basic_compute/basic_compute_pipeline.cpp b/src/renderer/pipelines/basic/basic_compute/basic_compute_pipeline.cpp similarity index 91% rename from src/renderer/pipelines/basic_compute/basic_compute_pipeline.cpp rename to src/renderer/pipelines/basic/basic_compute/basic_compute_pipeline.cpp index c66a0cc2..48d00cb7 100644 --- a/src/renderer/pipelines/basic_compute/basic_compute_pipeline.cpp +++ b/src/renderer/pipelines/basic/basic_compute/basic_compute_pipeline.cpp @@ -4,15 +4,12 @@ #include "basic_compute_pipeline.h" -#include - +#include "basic_compute_pipeline_types.h" #include "src/renderer/renderer_constants.h" +#include "src/renderer/resource_manager.h" #include "src/renderer/vk_descriptors.h" -#include "src/renderer/vk_helpers.h" -#include "src/renderer/descriptor_buffer/descriptor_buffer_sampler.h" -#include "src/renderer/descriptor_buffer/descriptor_buffer_types.h" -namespace will_engine::basic_compute +namespace will_engine::basic_compute_pipeline { BasicComputePipeline::BasicComputePipeline(ResourceManager& resourceManager) : resourceManager(resourceManager) @@ -57,7 +54,7 @@ void BasicComputePipeline::setupDescriptors(const ComputeDescriptorInfo& descrip resourceManager.setupDescriptorBufferSampler(samplerDescriptorBuffer, imageDescriptor, 0); } -void BasicComputePipeline::draw(VkCommandBuffer cmd, ComputeDrawInfo drawInfo) const +void BasicComputePipeline::draw(VkCommandBuffer cmd, const ComputeDrawInfo drawInfo) const { vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline); diff --git a/src/renderer/pipelines/basic_compute/basic_compute_pipeline.h b/src/renderer/pipelines/basic/basic_compute/basic_compute_pipeline.h similarity index 78% rename from src/renderer/pipelines/basic_compute/basic_compute_pipeline.h rename to src/renderer/pipelines/basic/basic_compute/basic_compute_pipeline.h index 9393507f..c3c5c5fe 100644 --- a/src/renderer/pipelines/basic_compute/basic_compute_pipeline.h +++ b/src/renderer/pipelines/basic/basic_compute/basic_compute_pipeline.h @@ -5,22 +5,19 @@ #ifndef BASIC_COMPUTE_PIPELINE_H #define BASIC_COMPUTE_PIPELINE_H -#include "src/renderer/resource_manager.h" -#include "src/renderer/vulkan_context.h" -#include "src/renderer/descriptor_buffer/descriptor_buffer_sampler.h" +#include +#include "src/renderer/descriptor_buffer/descriptor_buffer_sampler.h" -namespace will_engine::basic_compute -{ -struct ComputeDescriptorInfo +namespace will_engine { - VkImageView inputImage; -}; +class ResourceManager; +} -struct ComputeDrawInfo +namespace will_engine::basic_compute_pipeline { - VkExtent2D renderExtent; -}; +struct ComputeDrawInfo; +struct ComputeDescriptorInfo; class BasicComputePipeline { diff --git a/src/renderer/pipelines/basic/basic_compute/basic_compute_pipeline_types.h b/src/renderer/pipelines/basic/basic_compute/basic_compute_pipeline_types.h new file mode 100644 index 00000000..a6dfdf30 --- /dev/null +++ b/src/renderer/pipelines/basic/basic_compute/basic_compute_pipeline_types.h @@ -0,0 +1,23 @@ +// +// Created by William on 2025-04-14. +// + +#ifndef BASIC_COMPUTE_PIPELINE_TYPES_H +#define BASIC_COMPUTE_PIPELINE_TYPES_H + +#include + +namespace will_engine::basic_compute_pipeline +{ +struct ComputeDescriptorInfo +{ + VkImageView inputImage; +}; + +struct ComputeDrawInfo +{ + VkExtent2D renderExtent; +}; +} + +#endif //BASIC_COMPUTE_PIPELINE_TYPES_H diff --git a/src/renderer/pipelines/basic_render/basic_render_pipeline.cpp b/src/renderer/pipelines/basic/basic_render/basic_render_pipeline.cpp similarity index 90% rename from src/renderer/pipelines/basic_render/basic_render_pipeline.cpp rename to src/renderer/pipelines/basic/basic_render/basic_render_pipeline.cpp index d097a07d..44a7cd96 100644 --- a/src/renderer/pipelines/basic_render/basic_render_pipeline.cpp +++ b/src/renderer/pipelines/basic/basic_render/basic_render_pipeline.cpp @@ -4,14 +4,15 @@ #include "basic_render_pipeline.h" -#include "volk/volk.h" +#include "basic_render_pipeline_types.h" #include "src/renderer/renderer_constants.h" +#include "src/renderer/resource_manager.h" #include "src/renderer/vk_descriptors.h" #include "src/renderer/vk_helpers.h" #include "src/renderer/vk_pipelines.h" -will_engine::basic_render::BasicRenderPipeline::BasicRenderPipeline(ResourceManager& resourceManager) : resourceManager(resourceManager) +will_engine::basic_render_pipeline::BasicRenderPipeline::BasicRenderPipeline(ResourceManager& resourceManager) : resourceManager(resourceManager) { DescriptorLayoutBuilder layoutBuilder; layoutBuilder.addBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); @@ -37,7 +38,7 @@ will_engine::basic_render::BasicRenderPipeline::BasicRenderPipeline(ResourceMana createPipeline(); } -will_engine::basic_render::BasicRenderPipeline::~BasicRenderPipeline() +will_engine::basic_render_pipeline::BasicRenderPipeline::~BasicRenderPipeline() { resourceManager.destroyPipeline(pipeline); resourceManager.destroyPipelineLayout(pipelineLayout); @@ -45,7 +46,7 @@ will_engine::basic_render::BasicRenderPipeline::~BasicRenderPipeline() resourceManager.destroyDescriptorBuffer(samplerDescriptorBuffer); } -void will_engine::basic_render::BasicRenderPipeline::setupDescriptors(const RenderDescriptorInfo& descriptorInfo) +void will_engine::basic_render_pipeline::BasicRenderPipeline::setupDescriptors(const RenderDescriptorInfo& descriptorInfo) { std::vector imageDescriptor; imageDescriptor.reserve(1); @@ -59,7 +60,7 @@ void will_engine::basic_render::BasicRenderPipeline::setupDescriptors(const Rend resourceManager.setupDescriptorBufferSampler(samplerDescriptorBuffer, imageDescriptor, 0); } -void will_engine::basic_render::BasicRenderPipeline::draw(VkCommandBuffer cmd, const RenderDrawInfo& drawInfo) const +void will_engine::basic_render_pipeline::BasicRenderPipeline::draw(VkCommandBuffer cmd, const RenderDrawInfo& drawInfo) const { if (drawInfo.drawImage == VK_NULL_HANDLE || drawInfo.depthImage == VK_NULL_HANDLE) { return; } constexpr VkClearValue colorClear = {.color = {0.0f, 0.0f, 0.0f, 0.0f}}; @@ -102,7 +103,6 @@ void will_engine::basic_render::BasicRenderPipeline::draw(VkCommandBuffer cmd, c vkCmdSetDescriptorBufferOffsetsEXT(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &imageBufferIndex, &ZERO_DEVICE_SIZE); vkCmdSetDescriptorBufferOffsetsEXT(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 1, 1, &sceneDataIndex, &sceneDataOffset); - const float time = static_cast(SDL_GetTicks()) / 1000.0f; RenderPushConstant push{}; push.currentFrame = drawInfo.currentFrame; vkCmdPushConstants(cmd, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(RenderPushConstant), &push); @@ -110,7 +110,7 @@ void will_engine::basic_render::BasicRenderPipeline::draw(VkCommandBuffer cmd, c vkCmdEndRendering(cmd); } -void will_engine::basic_render::BasicRenderPipeline::createPipeline() +void will_engine::basic_render_pipeline::BasicRenderPipeline::createPipeline() { resourceManager.destroyPipeline(pipeline); VkShaderModule vertShader = resourceManager.createShaderModule("shaders/basic/vertex.vert"); diff --git a/src/renderer/pipelines/basic_render/basic_render_pipeline.h b/src/renderer/pipelines/basic/basic_render/basic_render_pipeline.h similarity index 60% rename from src/renderer/pipelines/basic_render/basic_render_pipeline.h rename to src/renderer/pipelines/basic/basic_render/basic_render_pipeline.h index e1362ea4..ff525c24 100644 --- a/src/renderer/pipelines/basic_render/basic_render_pipeline.h +++ b/src/renderer/pipelines/basic/basic_render/basic_render_pipeline.h @@ -4,34 +4,20 @@ #ifndef BASIC_RENDER_PIPELINE_H #define BASIC_RENDER_PIPELINE_H -#include "src/renderer/resource_manager.h" -#include "src/renderer/vulkan_context.h" -#include "src/renderer/descriptor_buffer/descriptor_buffer_sampler.h" +#include -namespace will_engine::basic_render -{ -struct RenderDescriptorInfo -{ - VkSampler sampler{VK_NULL_HANDLE}; - VkImageView texture{VK_NULL_HANDLE}; -}; +#include "src/renderer/descriptor_buffer/descriptor_buffer_sampler.h" -struct RenderDrawInfo +namespace will_engine { - VkExtent2D renderExtent{}; - VkImageView drawImage{VK_NULL_HANDLE}; - VkImageView depthImage{VK_NULL_HANDLE}; - VkDescriptorBufferBindingInfoEXT sceneDataBinding{}; - VkDeviceSize sceneDataOffset{0}; - int32_t currentFrame{}; -}; +class ResourceManager; +} -struct RenderPushConstant +namespace will_engine::basic_render_pipeline { - int32_t currentFrame; -}; - +struct RenderDrawInfo; +struct RenderDescriptorInfo; class BasicRenderPipeline { diff --git a/src/renderer/pipelines/basic/basic_render/basic_render_pipeline_types.h b/src/renderer/pipelines/basic/basic_render/basic_render_pipeline_types.h new file mode 100644 index 00000000..7a94ed1a --- /dev/null +++ b/src/renderer/pipelines/basic/basic_render/basic_render_pipeline_types.h @@ -0,0 +1,34 @@ +// +// Created by William on 2025-04-14. +// + +#ifndef BASIC_RENDER_PIPELINE_TYPES_H +#define BASIC_RENDER_PIPELINE_TYPES_H + +#include + +namespace will_engine::basic_render_pipeline +{ +struct RenderDescriptorInfo +{ + VkSampler sampler{VK_NULL_HANDLE}; + VkImageView texture{VK_NULL_HANDLE}; +}; + +struct RenderDrawInfo +{ + VkExtent2D renderExtent{}; + VkImageView drawImage{VK_NULL_HANDLE}; + VkImageView depthImage{VK_NULL_HANDLE}; + VkDescriptorBufferBindingInfoEXT sceneDataBinding{}; + VkDeviceSize sceneDataOffset{0}; + int32_t currentFrame{}; +}; + +struct RenderPushConstant +{ + int32_t currentFrame; +}; +} + +#endif //BASIC_RENDER_PIPELINE_TYPES_H diff --git a/src/renderer/pipelines/deferred_mrt/deferred_mrt.h b/src/renderer/pipelines/deferred_mrt/deferred_mrt.h deleted file mode 100644 index aa5b9dbf..00000000 --- a/src/renderer/pipelines/deferred_mrt/deferred_mrt.h +++ /dev/null @@ -1,53 +0,0 @@ -// -// Created by William on 2025-01-24. -// - -#ifndef DEFERRED_MRT_H -#define DEFERRED_MRT_H - -#include - -#include "src/renderer/resource_manager.h" -#include "src/renderer/assets/render_object/render_object.h" - -namespace will_engine::deferred_mrt -{ -struct DeferredMrtDrawInfo -{ - bool bClearColor{true}; - int32_t currentFrameOverlap{0}; - glm::vec2 viewportExtents{RENDER_EXTENT_WIDTH, RENDER_EXTENT_HEIGHT}; - const std::vector& renderObjects{}; - VkImageView normalTarget{VK_NULL_HANDLE}; - VkImageView albedoTarget{VK_NULL_HANDLE}; - VkImageView pbrTarget{VK_NULL_HANDLE}; - VkImageView velocityTarget{VK_NULL_HANDLE}; - VkImageView depthTarget{VK_NULL_HANDLE}; - VkDescriptorBufferBindingInfoEXT sceneDataBinding{}; - VkDeviceSize sceneDataOffset{0}; -}; - -class DeferredMrtPipeline -{ -public: - explicit DeferredMrtPipeline(ResourceManager& resourceManager); - - ~DeferredMrtPipeline(); - - void draw(VkCommandBuffer cmd, const DeferredMrtDrawInfo& drawInfo) const; - - void reloadShaders() { createPipeline(); } - -private: - void createPipeline(); - -private: - ResourceManager& resourceManager; - - VkPipelineLayout pipelineLayout{VK_NULL_HANDLE}; - VkPipeline pipeline{VK_NULL_HANDLE}; -}; -} - - -#endif //DEFERRED_MRT_H diff --git a/src/renderer/pipelines/deferred_mrt/deferred_mrt.cpp b/src/renderer/pipelines/geometry/deferred_mrt/deferred_mrt_pipeline.cpp similarity index 96% rename from src/renderer/pipelines/deferred_mrt/deferred_mrt.cpp rename to src/renderer/pipelines/geometry/deferred_mrt/deferred_mrt_pipeline.cpp index d8916ea7..99191ea4 100644 --- a/src/renderer/pipelines/deferred_mrt/deferred_mrt.cpp +++ b/src/renderer/pipelines/geometry/deferred_mrt/deferred_mrt_pipeline.cpp @@ -2,15 +2,14 @@ // Created by William on 2025-01-24. // -#include "deferred_mrt.h" +#include "deferred_mrt_pipeline.h" #include -#include - -#include "volk/volk.h" +#include "deferred_mrt_pipeline_types.h" #include "src/renderer/renderer_constants.h" #include "src/renderer/resource_manager.h" +#include "src/renderer/assets/render_object/render_object.h" #include "src/renderer/assets/render_object/render_object_types.h" will_engine::deferred_mrt::DeferredMrtPipeline::DeferredMrtPipeline(ResourceManager& resourceManager) : resourceManager(resourceManager) @@ -101,7 +100,7 @@ void will_engine::deferred_mrt::DeferredMrtPipeline::draw(VkCommandBuffer cmd, c for (RenderObject* renderObject : drawInfo.renderObjects) { if (!renderObject->canDraw()) { continue; } - std::array descriptorBufferBindingInfos{ + std::array descriptorBufferBindingInfos{ drawInfo.sceneDataBinding, renderObject->getAddressesDescriptorBuffer().getDescriptorBufferBindingInfo(), renderObject->getTextureDescriptorBuffer().getDescriptorBufferBindingInfo(), @@ -111,7 +110,7 @@ void will_engine::deferred_mrt::DeferredMrtPipeline::draw(VkCommandBuffer cmd, c constexpr std::array indices{0, 1, 2}; - std::array offsets{ + std::array offsets{ drawInfo.sceneDataOffset, renderObject->getAddressesDescriptorBuffer().getDescriptorBufferSize() * drawInfo.currentFrameOverlap, ZERO_DEVICE_SIZE diff --git a/src/renderer/pipelines/geometry/deferred_mrt/deferred_mrt_pipeline.h b/src/renderer/pipelines/geometry/deferred_mrt/deferred_mrt_pipeline.h new file mode 100644 index 00000000..757c2e5e --- /dev/null +++ b/src/renderer/pipelines/geometry/deferred_mrt/deferred_mrt_pipeline.h @@ -0,0 +1,43 @@ +// +// Created by William on 2025-01-24. +// + +#ifndef DEFERRED_MRT_H +#define DEFERRED_MRT_H + +#include + +namespace will_engine +{ +class ResourceManager; +class RenderObject; +} + +namespace will_engine::deferred_mrt +{ +struct DeferredMrtDrawInfo; + +class DeferredMrtPipeline +{ +public: + explicit DeferredMrtPipeline(ResourceManager& resourceManager); + + ~DeferredMrtPipeline(); + + void draw(VkCommandBuffer cmd, const DeferredMrtDrawInfo& drawInfo) const; + + void reloadShaders() { createPipeline(); } + +private: + void createPipeline(); + +private: + ResourceManager& resourceManager; + + VkPipelineLayout pipelineLayout{VK_NULL_HANDLE}; + VkPipeline pipeline{VK_NULL_HANDLE}; +}; +} + + +#endif //DEFERRED_MRT_H diff --git a/src/renderer/pipelines/geometry/deferred_mrt/deferred_mrt_pipeline_types.h b/src/renderer/pipelines/geometry/deferred_mrt/deferred_mrt_pipeline_types.h new file mode 100644 index 00000000..cc4f8cac --- /dev/null +++ b/src/renderer/pipelines/geometry/deferred_mrt/deferred_mrt_pipeline_types.h @@ -0,0 +1,30 @@ +// +// Created by William on 2025-04-14. +// + +#ifndef DEFERRED_MRT_TYPES_H +#define DEFERRED_MRT_TYPES_H + +#include + +#include "src/renderer/renderer_constants.h" + +namespace will_engine::deferred_mrt +{ +struct DeferredMrtDrawInfo +{ + bool bClearColor{true}; + int32_t currentFrameOverlap{0}; + glm::vec2 viewportExtents{RENDER_EXTENT_WIDTH, RENDER_EXTENT_HEIGHT}; + const std::vector& renderObjects{}; + VkImageView normalTarget{VK_NULL_HANDLE}; + VkImageView albedoTarget{VK_NULL_HANDLE}; + VkImageView pbrTarget{VK_NULL_HANDLE}; + VkImageView velocityTarget{VK_NULL_HANDLE}; + VkImageView depthTarget{VK_NULL_HANDLE}; + VkDescriptorBufferBindingInfoEXT sceneDataBinding{}; + VkDeviceSize sceneDataOffset{0}; +}; +} // deferred_mrt::will_engine + +#endif //DEFERRED_MRT_TYPES_H diff --git a/src/renderer/pipelines/deferred_resolve/deferred_resolve.cpp b/src/renderer/pipelines/geometry/deferred_resolve/deferred_resolve_pipeline.cpp similarity index 91% rename from src/renderer/pipelines/deferred_resolve/deferred_resolve.cpp rename to src/renderer/pipelines/geometry/deferred_resolve/deferred_resolve_pipeline.cpp index faea01fe..88a9e257 100644 --- a/src/renderer/pipelines/deferred_resolve/deferred_resolve.cpp +++ b/src/renderer/pipelines/geometry/deferred_resolve/deferred_resolve_pipeline.cpp @@ -2,14 +2,15 @@ // Created by William on 2025-01-25. // -#include "deferred_resolve.h" +#include "deferred_resolve_pipeline.h" #include -#include "volk/volk.h" +#include "deferred_resolve_pipeline_types.h" #include "src/renderer/renderer_constants.h" #include "src/renderer/resource_manager.h" + will_engine::deferred_resolve::DeferredResolvePipeline::DeferredResolvePipeline(ResourceManager& resourceManager, VkDescriptorSetLayout environmentIBLLayout, VkDescriptorSetLayout cascadeUniformLayout, @@ -53,7 +54,7 @@ will_engine::deferred_resolve::DeferredResolvePipeline::~DeferredResolvePipeline void will_engine::deferred_resolve::DeferredResolvePipeline::setupDescriptorBuffer(const DeferredResolveDescriptor& drawInfo) { std::vector renderTargetDescriptors; - renderTargetDescriptors.reserve(6); + renderTargetDescriptors.reserve(8); VkDescriptorImageInfo normalTarget = {}; normalTarget.sampler = drawInfo.sampler; @@ -85,6 +86,11 @@ void will_engine::deferred_resolve::DeferredResolvePipeline::setupDescriptorBuff aoTarget.imageView = drawInfo.aoTarget; aoTarget.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + VkDescriptorImageInfo contactShadow = {}; + contactShadow.sampler = drawInfo.sampler; + contactShadow.imageView = drawInfo.contactShadowsTarget; + contactShadow.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + VkDescriptorImageInfo drawImageTarget = {}; drawImageTarget.imageView = drawInfo.outputTarget; drawImageTarget.imageLayout = VK_IMAGE_LAYOUT_GENERAL; @@ -95,6 +101,7 @@ void will_engine::deferred_resolve::DeferredResolvePipeline::setupDescriptorBuff renderTargetDescriptors.push_back({VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, depthImageTarget, false}); renderTargetDescriptors.push_back({VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, velocityTarget, false}); renderTargetDescriptors.push_back({VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, aoTarget, false}); + renderTargetDescriptors.push_back({VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, contactShadow, false}); renderTargetDescriptors.push_back({VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, drawImageTarget, false}); resourceManager.setupDescriptorBufferSampler(resolveDescriptorBuffer, renderTargetDescriptors, 0); @@ -118,7 +125,8 @@ void will_engine::deferred_resolve::DeferredResolvePipeline::draw(VkCommandBuffe pushConstants.width = RENDER_EXTENT_WIDTH; pushConstants.height = RENDER_EXTENT_HEIGHT; pushConstants.deferredDebug = drawInfo.deferredDebug; - pushConstants.disableShadows = 0; + pushConstants.disableShadows = drawInfo.bEnableShadows ? 0 : 1; + pushConstants.disableContactShadows = drawInfo.bEnableContactShadows ? 0 : 1; pushConstants.pcfLevel = drawInfo.csmPcf; pushConstants.nearPlane = drawInfo.nearPlane; pushConstants.farPlane = drawInfo.farPlane; @@ -133,13 +141,7 @@ void will_engine::deferred_resolve::DeferredResolvePipeline::draw(VkCommandBuffe bindingInfos[4] = drawInfo.cascadeSamplerBinding; vkCmdBindDescriptorBuffersEXT(cmd, 5, bindingInfos); - constexpr std::array indices{ - 0, - 1, - 2, - 3, - 4 - }; + constexpr std::array indices{0, 1, 2, 3, 4}; const std::array offsets{ drawInfo.sceneDataOffset, ZERO_DEVICE_SIZE, diff --git a/src/renderer/pipelines/geometry/deferred_resolve/deferred_resolve_pipeline.h b/src/renderer/pipelines/geometry/deferred_resolve/deferred_resolve_pipeline.h new file mode 100644 index 00000000..a7f66eff --- /dev/null +++ b/src/renderer/pipelines/geometry/deferred_resolve/deferred_resolve_pipeline.h @@ -0,0 +1,53 @@ +// +// Created by William on 2025-01-25. +// + +#ifndef DEFERRED_RESOLVE_H +#define DEFERRED_RESOLVE_H + +#include + +#include "src/renderer/descriptor_buffer/descriptor_buffer_sampler.h" + +namespace will_engine +{ +class ResourceManager; +class DescriptorBuffer; +class DescriptorBufferSampler; +} + +namespace will_engine::deferred_resolve +{ +struct DeferredResolveDrawInfo; +struct DeferredResolveDescriptor; + +class DeferredResolvePipeline +{ +public: + explicit DeferredResolvePipeline(ResourceManager& resourceManager, VkDescriptorSetLayout environmentIBLLayout, + VkDescriptorSetLayout cascadeUniformLayout, + VkDescriptorSetLayout cascadeSamplerLayout); + + ~DeferredResolvePipeline(); + + void setupDescriptorBuffer(const DeferredResolveDescriptor& drawInfo); + + void draw(VkCommandBuffer cmd, const DeferredResolveDrawInfo& drawInfo) const; + + void reloadShaders() { createPipeline(); } + +private: + void createPipeline(); + +private: + ResourceManager& resourceManager; + + VkPipelineLayout pipelineLayout{VK_NULL_HANDLE}; + VkPipeline pipeline{VK_NULL_HANDLE}; + + DescriptorBufferSampler resolveDescriptorBuffer; +}; +} + + +#endif //DEFERRED_RESOLVE_H diff --git a/src/renderer/pipelines/deferred_resolve/deferred_resolve.h b/src/renderer/pipelines/geometry/deferred_resolve/deferred_resolve_pipeline_types.h similarity index 50% rename from src/renderer/pipelines/deferred_resolve/deferred_resolve.h rename to src/renderer/pipelines/geometry/deferred_resolve/deferred_resolve_pipeline_types.h index ada68554..eb8cbdf6 100644 --- a/src/renderer/pipelines/deferred_resolve/deferred_resolve.h +++ b/src/renderer/pipelines/geometry/deferred_resolve/deferred_resolve_pipeline_types.h @@ -1,14 +1,11 @@ // -// Created by William on 2025-01-25. +// Created by William on 2025-04-14. // -#ifndef DEFERRED_RESOLVE_H -#define DEFERRED_RESOLVE_H -#include - -#include "src/renderer/resource_manager.h" -#include "src/renderer/descriptor_buffer/descriptor_buffer_sampler.h" +#ifndef DEFERRED_RESOLVE_TYPES_H +#define DEFERRED_RESOLVE_TYPES_H +#include namespace will_engine::deferred_resolve { @@ -20,6 +17,7 @@ struct DeferredResolveDescriptor VkImageView depthTarget; VkImageView velocityTarget; VkImageView aoTarget; + VkImageView contactShadowsTarget; VkImageView outputTarget; VkSampler sampler; @@ -31,6 +29,7 @@ struct DeferredResolvePushConstants int32_t height{900}; int32_t deferredDebug{0}; int32_t disableShadows{0}; + int32_t disableContactShadows{0}; int32_t pcfLevel{5}; float nearPlane{1000.0f}; float farPlane{0.1f}; @@ -49,34 +48,9 @@ struct DeferredResolveDrawInfo VkDescriptorBufferBindingInfoEXT cascadeSamplerBinding{}; float nearPlane{1000.0f}; float farPlane{0.1f}; -}; - -class DeferredResolvePipeline -{ -public: - explicit DeferredResolvePipeline(ResourceManager& resourceManager, VkDescriptorSetLayout environmentIBLLayout, VkDescriptorSetLayout cascadeUniformLayout, - VkDescriptorSetLayout cascadeSamplerLayout); - - ~DeferredResolvePipeline(); - - void setupDescriptorBuffer(const DeferredResolveDescriptor& drawInfo); - - void draw(VkCommandBuffer cmd, const DeferredResolveDrawInfo& drawInfo) const; - - void reloadShaders() { createPipeline(); } - -private: - void createPipeline(); - -private: - ResourceManager& resourceManager; - - VkPipelineLayout pipelineLayout{VK_NULL_HANDLE}; - VkPipeline pipeline{VK_NULL_HANDLE}; - - DescriptorBufferSampler resolveDescriptorBuffer; + bool bEnableShadows{true}; + bool bEnableContactShadows{true}; }; } - -#endif //DEFERRED_RESOLVE_H +#endif //DEFERRED_RESOLVE_TYPES_H diff --git a/src/renderer/pipelines/environment/environment_pipeline.cpp b/src/renderer/pipelines/geometry/environment/environment_pipeline.cpp similarity index 97% rename from src/renderer/pipelines/environment/environment_pipeline.cpp rename to src/renderer/pipelines/geometry/environment/environment_pipeline.cpp index 8fe74266..7acab329 100644 --- a/src/renderer/pipelines/environment/environment_pipeline.cpp +++ b/src/renderer/pipelines/geometry/environment/environment_pipeline.cpp @@ -4,9 +4,11 @@ #include "environment_pipeline.h" -#include "volk/volk.h" +#include "environment_pipeline_types.h" #include "src/renderer/renderer_constants.h" #include "src/renderer/resource_manager.h" +#include "src/renderer/vk_helpers.h" +#include "src/renderer/vk_pipelines.h" will_engine::environment_pipeline::EnvironmentPipeline::EnvironmentPipeline(ResourceManager& resourceManager, VkDescriptorSetLayout environmentMapLayout) : resourceManager(resourceManager) { diff --git a/src/renderer/pipelines/environment/environment_pipeline.h b/src/renderer/pipelines/geometry/environment/environment_pipeline.h similarity index 54% rename from src/renderer/pipelines/environment/environment_pipeline.h rename to src/renderer/pipelines/geometry/environment/environment_pipeline.h index c734eaa7..9be9e7c6 100644 --- a/src/renderer/pipelines/environment/environment_pipeline.h +++ b/src/renderer/pipelines/geometry/environment/environment_pipeline.h @@ -4,27 +4,17 @@ #ifndef ENVIRONMENT_PIPELINE_H #define ENVIRONMENT_PIPELINE_H -#include -#include "src/renderer/resource_manager.h" +#include +namespace will_engine +{ +class ResourceManager; +} namespace will_engine::environment_pipeline { -struct EnvironmentDrawInfo -{ - bool bClearColor{false}; - VkImageView normalTarget{VK_NULL_HANDLE}; - VkImageView albedoTarget{VK_NULL_HANDLE}; - VkImageView pbrTarget{VK_NULL_HANDLE}; - VkImageView velocityTarget{VK_NULL_HANDLE}; - VkImageView depthTarget{VK_NULL_HANDLE}; - VkDescriptorBufferBindingInfoEXT sceneDataBinding{}; - VkDeviceSize sceneDataOffset; - VkDescriptorBufferBindingInfoEXT environmentMapBinding{}; - VkDeviceSize environmentMapOffset; -}; - +struct EnvironmentDrawInfo; class EnvironmentPipeline { diff --git a/src/renderer/pipelines/geometry/environment/environment_pipeline_types.h b/src/renderer/pipelines/geometry/environment/environment_pipeline_types.h new file mode 100644 index 00000000..cd86a5f6 --- /dev/null +++ b/src/renderer/pipelines/geometry/environment/environment_pipeline_types.h @@ -0,0 +1,27 @@ +// +// Created by William on 2025-04-14. +// + +#ifndef ENVIRONMENT_PIPELINE_TYPES_H +#define ENVIRONMENT_PIPELINE_TYPES_H + +#include + +namespace will_engine::environment_pipeline +{ +struct EnvironmentDrawInfo +{ + bool bClearColor{false}; + VkImageView normalTarget{VK_NULL_HANDLE}; + VkImageView albedoTarget{VK_NULL_HANDLE}; + VkImageView pbrTarget{VK_NULL_HANDLE}; + VkImageView velocityTarget{VK_NULL_HANDLE}; + VkImageView depthTarget{VK_NULL_HANDLE}; + VkDescriptorBufferBindingInfoEXT sceneDataBinding{}; + VkDeviceSize sceneDataOffset{}; + VkDescriptorBufferBindingInfoEXT environmentMapBinding{}; + VkDeviceSize environmentMapOffset{}; +}; +} + +#endif //ENVIRONMENT_PIPELINE_TYPES_H diff --git a/src/renderer/pipelines/terrain/terrain_pipeline.cpp b/src/renderer/pipelines/geometry/terrain/terrain_pipeline.cpp similarity index 98% rename from src/renderer/pipelines/terrain/terrain_pipeline.cpp rename to src/renderer/pipelines/geometry/terrain/terrain_pipeline.cpp index cd9eeebe..cb112f2f 100644 --- a/src/renderer/pipelines/terrain/terrain_pipeline.cpp +++ b/src/renderer/pipelines/geometry/terrain/terrain_pipeline.cpp @@ -4,9 +4,11 @@ #include "terrain_pipeline.h" -#include - -#include "src/renderer/renderer_constants.h" +#include "terrain_pipeline_types.h" +#include "src/core/game_object/terrain.h" +#include "src/renderer/resource_manager.h" +#include "src/renderer/vk_helpers.h" +#include "src/renderer/vk_pipelines.h" #include "src/renderer/terrain/terrain_chunk.h" #include "src/renderer/terrain/terrain_types.h" diff --git a/src/renderer/pipelines/terrain/terrain_pipeline.h b/src/renderer/pipelines/geometry/terrain/terrain_pipeline.h similarity index 50% rename from src/renderer/pipelines/terrain/terrain_pipeline.h rename to src/renderer/pipelines/geometry/terrain/terrain_pipeline.h index 15b63813..9a86e0e4 100644 --- a/src/renderer/pipelines/terrain/terrain_pipeline.h +++ b/src/renderer/pipelines/geometry/terrain/terrain_pipeline.h @@ -4,35 +4,20 @@ #ifndef TERRAIN_PIPELINE_H #define TERRAIN_PIPELINE_H -#include "src/core/game_object/terrain.h" -#include "src/renderer/renderer_constants.h" -#include "src/renderer/resource_manager.h" +#include -namespace will_engine::terrain -{ -class TerrainChunk; +#include "src/renderer/descriptor_buffer/descriptor_buffer_sampler.h" -struct TerrainPushConstants +namespace will_engine { - float tessLevel; -}; +class ResourceManager; +} -struct TerrainDrawInfo +namespace will_engine::terrain { - bool bClearColor{true}; - bool bDrawLinesOnly{false}; - int32_t currentFrameOverlap{0}; - glm::vec2 viewportExtents{RENDER_EXTENT_WIDTH, RENDER_EXTENT_HEIGHT}; - const std::unordered_set& terrains; - VkImageView normalTarget{VK_NULL_HANDLE}; - VkImageView albedoTarget{VK_NULL_HANDLE}; - VkImageView pbrTarget{VK_NULL_HANDLE}; - VkImageView velocityTarget{VK_NULL_HANDLE}; - VkImageView depthTarget{VK_NULL_HANDLE}; - VkDescriptorBufferBindingInfoEXT sceneDataBinding{}; - VkDeviceSize sceneDataOffset{0}; -}; +struct TerrainDrawInfo; +class TerrainChunk; class TerrainPipeline { @@ -41,8 +26,6 @@ class TerrainPipeline ~TerrainPipeline(); - //void setupDescriptorBuffer(const TerrainDescriptor& descriptor); - void draw(VkCommandBuffer cmd, const TerrainDrawInfo& drawInfo) const; void reloadShaders() diff --git a/src/renderer/pipelines/geometry/terrain/terrain_pipeline_types.h b/src/renderer/pipelines/geometry/terrain/terrain_pipeline_types.h new file mode 100644 index 00000000..0feacbc9 --- /dev/null +++ b/src/renderer/pipelines/geometry/terrain/terrain_pipeline_types.h @@ -0,0 +1,43 @@ +// +// Created by William on 2025-04-14. +// + +#ifndef TERRAIN_PIPELINE_TYPES_H +#define TERRAIN_PIPELINE_TYPES_H + +#include +#include +#include + +#include "src/renderer/renderer_constants.h" + +namespace will_engine +{ +class ITerrain; +} + +namespace will_engine::terrain +{ +struct TerrainPushConstants +{ + float tessLevel; +}; + +struct TerrainDrawInfo +{ + bool bClearColor{true}; + bool bDrawLinesOnly{false}; + int32_t currentFrameOverlap{0}; + glm::vec2 viewportExtents{RENDER_EXTENT_WIDTH, RENDER_EXTENT_HEIGHT}; + const std::unordered_set& terrains; + VkImageView normalTarget{VK_NULL_HANDLE}; + VkImageView albedoTarget{VK_NULL_HANDLE}; + VkImageView pbrTarget{VK_NULL_HANDLE}; + VkImageView velocityTarget{VK_NULL_HANDLE}; + VkImageView depthTarget{VK_NULL_HANDLE}; + VkDescriptorBufferBindingInfoEXT sceneDataBinding{}; + VkDeviceSize sceneDataOffset{0}; +}; +} + +#endif //TERRAIN_PIPELINE_TYPES_H diff --git a/src/renderer/pipelines/transparent_pipeline/transparent_pipeline.cpp b/src/renderer/pipelines/geometry/transparent_pipeline/transparent_pipeline.cpp similarity index 98% rename from src/renderer/pipelines/transparent_pipeline/transparent_pipeline.cpp rename to src/renderer/pipelines/geometry/transparent_pipeline/transparent_pipeline.cpp index d297b08d..e95902b7 100644 --- a/src/renderer/pipelines/transparent_pipeline/transparent_pipeline.cpp +++ b/src/renderer/pipelines/geometry/transparent_pipeline/transparent_pipeline.cpp @@ -5,9 +5,13 @@ #include "transparent_pipeline.h" #include -#include +#include "transparent_pipeline_types.h" #include "src/renderer/renderer_constants.h" +#include "src/renderer/resource_manager.h" +#include "src/renderer/vk_descriptors.h" +#include "src/renderer/vk_helpers.h" +#include "src/renderer/vk_pipelines.h" #include "src/renderer/assets/render_object/render_object.h" #include "src/renderer/assets/render_object/render_object_types.h" @@ -127,7 +131,6 @@ void TransparentPipeline::drawAccumulate(VkCommandBuffer cmd, const TransparentA constexpr VkClearValue revealageClear = {.color = {1.0f, 1.0f, 1.0f, 1.0f}}; - VkRenderingAttachmentInfo accumulationAttachment = vk_helpers::attachmentInfo(accumulationImage.imageView, &colorClear, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); VkRenderingAttachmentInfo revealageAttachment = vk_helpers::attachmentInfo(revealageImage.imageView, &revealageClear, diff --git a/src/renderer/pipelines/transparent_pipeline/transparent_pipeline.h b/src/renderer/pipelines/geometry/transparent_pipeline/transparent_pipeline.h similarity index 64% rename from src/renderer/pipelines/transparent_pipeline/transparent_pipeline.h rename to src/renderer/pipelines/geometry/transparent_pipeline/transparent_pipeline.h index 2bebe982..a9062ac0 100644 --- a/src/renderer/pipelines/transparent_pipeline/transparent_pipeline.h +++ b/src/renderer/pipelines/geometry/transparent_pipeline/transparent_pipeline.h @@ -4,41 +4,22 @@ #ifndef TRANSPARENT_PIPELINE_H #define TRANSPARENT_PIPELINE_H -#include "src/renderer/imgui_wrapper.h" -#include "src/renderer/resource_manager.h" + +#include + +#include "src/renderer/vk_types.h" +#include "src/renderer/descriptor_buffer/descriptor_buffer_sampler.h" namespace will_engine { +class ResourceManager; class RenderObject; } namespace will_engine::transparent_pipeline { -struct TransparentsPushConstants -{ - int32_t bEnabled; - int32_t bReceivesShadows{true}; -}; - -struct TransparentAccumulateDrawInfo -{ - bool enabled{true}; - VkImageView depthTarget{VK_NULL_HANDLE}; - int32_t currentFrameOverlap{0}; - const std::vector& renderObjects{}; - VkDescriptorBufferBindingInfoEXT sceneDataBinding{}; - VkDeviceSize sceneDataOffset{0}; - VkDescriptorBufferBindingInfoEXT environmentIBLBinding{}; - VkDeviceSize environmentIBLOffset{0}; - VkDescriptorBufferBindingInfoEXT cascadeUniformBinding{}; - VkDeviceSize cascadeUniformOffset{0}; - VkDescriptorBufferBindingInfoEXT cascadeSamplerBinding{}; -}; - -struct TransparentCompositeDrawInfo -{ - VkImageView opaqueImage; -}; +struct TransparentCompositeDrawInfo; +struct TransparentAccumulateDrawInfo; class TransparentPipeline { @@ -82,8 +63,6 @@ class TransparentPipeline void createCompositePipeline(); - // todo: remove - friend void ImguiWrapper::imguiInterface(Engine* engine); }; } diff --git a/src/renderer/pipelines/geometry/transparent_pipeline/transparent_pipeline_types.h b/src/renderer/pipelines/geometry/transparent_pipeline/transparent_pipeline_types.h new file mode 100644 index 00000000..c5e7414a --- /dev/null +++ b/src/renderer/pipelines/geometry/transparent_pipeline/transparent_pipeline_types.h @@ -0,0 +1,46 @@ +// +// Created by William on 2025-04-14. +// + +#ifndef TRANSPARENT_PIPELINE_TYPES_H +#define TRANSPARENT_PIPELINE_TYPES_H + +#include + +#include "volk/volk.h" + +namespace will_engine +{ +class RenderObject; +} + +namespace will_engine::transparent_pipeline +{ +struct TransparentsPushConstants +{ + int32_t bEnabled{true}; + int32_t bReceivesShadows{true}; +}; + +struct TransparentAccumulateDrawInfo +{ + bool enabled{true}; + VkImageView depthTarget{VK_NULL_HANDLE}; + int32_t currentFrameOverlap{0}; + const std::vector& renderObjects{}; + VkDescriptorBufferBindingInfoEXT sceneDataBinding{}; + VkDeviceSize sceneDataOffset{0}; + VkDescriptorBufferBindingInfoEXT environmentIBLBinding{}; + VkDeviceSize environmentIBLOffset{0}; + VkDescriptorBufferBindingInfoEXT cascadeUniformBinding{}; + VkDeviceSize cascadeUniformOffset{0}; + VkDescriptorBufferBindingInfoEXT cascadeSamplerBinding{}; +}; + +struct TransparentCompositeDrawInfo +{ + VkImageView opaqueImage; +}; +} + +#endif //TRANSPARENT_PIPELINE_TYPES_H diff --git a/src/renderer/pipelines/post_process/post_process_pipeline.cpp b/src/renderer/pipelines/post/post_process/post_process_pipeline.cpp similarity index 94% rename from src/renderer/pipelines/post_process/post_process_pipeline.cpp rename to src/renderer/pipelines/post/post_process/post_process_pipeline.cpp index 6810c0ed..33c10344 100644 --- a/src/renderer/pipelines/post_process/post_process_pipeline.cpp +++ b/src/renderer/pipelines/post/post_process/post_process_pipeline.cpp @@ -5,9 +5,11 @@ #include "post_process_pipeline.h" #include +#include -#include "volk/volk.h" #include "src/renderer/renderer_constants.h" +#include "src/renderer/resource_manager.h" +#include "src/renderer/vk_descriptors.h" will_engine::post_process_pipeline::PostProcessPipeline::PostProcessPipeline(ResourceManager& resourceManager) : resourceManager(resourceManager) @@ -16,7 +18,8 @@ will_engine::post_process_pipeline::PostProcessPipeline::PostProcessPipeline(Res layoutBuilder.addBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); // taa resolve image layoutBuilder.addBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE); // post process result - descriptorSetLayout = resourceManager.createDescriptorSetLayout(layoutBuilder, VK_SHADER_STAGE_COMPUTE_BIT, VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT); + descriptorSetLayout = resourceManager.createDescriptorSetLayout(layoutBuilder, VK_SHADER_STAGE_COMPUTE_BIT, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT); VkPushConstantRange pushConstants{}; pushConstants.offset = 0; diff --git a/src/renderer/pipelines/post_process/post_process_pipeline.h b/src/renderer/pipelines/post/post_process/post_process_pipeline.h similarity index 59% rename from src/renderer/pipelines/post_process/post_process_pipeline.h rename to src/renderer/pipelines/post/post_process/post_process_pipeline.h index d28a2659..c55b8f46 100644 --- a/src/renderer/pipelines/post_process/post_process_pipeline.h +++ b/src/renderer/pipelines/post/post_process/post_process_pipeline.h @@ -4,34 +4,19 @@ #ifndef POST_PROCESS_PIPELINE_H #define POST_PROCESS_PIPELINE_H -#include "src/renderer/resource_manager.h" -#include "src/renderer/post_process/post_process_types.h" +#include -namespace will_engine::post_process_pipeline -{ -struct PostProcessDescriptor -{ - VkImageView inputImage; - VkImageView outputImage; - VkSampler sampler; -}; +#include "post_process_pipeline_types.h" +#include "src/renderer/descriptor_buffer/descriptor_buffer_sampler.h" -struct PostProcessPushConstants +namespace will_engine { - int32_t width; - int32_t height; - uint32_t postProcessFlags; - int32_t padding; -}; +class ResourceManager; +} -struct PostProcessDrawInfo +namespace will_engine::post_process_pipeline { - post_process::PostProcessType postProcessFlags{post_process::PostProcessType::ALL}; - VkDescriptorBufferBindingInfoEXT sceneDataBinding{}; - VkDeviceSize sceneDataOffset{0}; -}; - class PostProcessPipeline { public: diff --git a/src/renderer/pipelines/post/post_process/post_process_pipeline_types.h b/src/renderer/pipelines/post/post_process/post_process_pipeline_types.h new file mode 100644 index 00000000..908abf66 --- /dev/null +++ b/src/renderer/pipelines/post/post_process/post_process_pipeline_types.h @@ -0,0 +1,70 @@ +// +// Created by William on 2025-04-14. +// + +#ifndef POST_PROCESS_PIPELINE_TYPES_H +#define POST_PROCESS_PIPELINE_TYPES_H + +#include + +namespace will_engine::post_process_pipeline +{ +enum class PostProcessType : uint32_t +{ + None = 0x00000000, + Tonemapping = 1 << 0, + Sharpening = 1 << 1, + FXAA = 1 << 2, + ALL = 0xFFFFFFFF +}; + +inline PostProcessType operator|(PostProcessType a, PostProcessType b) +{ + return static_cast(static_cast(a) | static_cast(b)); +} + +inline PostProcessType operator&(PostProcessType a, PostProcessType b) +{ + return static_cast(static_cast(a) & static_cast(b)); +} + +inline PostProcessType operator~(PostProcessType a) +{ + return static_cast(~static_cast(a)); +} + +inline PostProcessType& operator|=(PostProcessType& a, PostProcessType b) +{ + return a = a | b; +} + +inline PostProcessType& operator&=(PostProcessType& a, PostProcessType b) +{ + return a = a & b; +} + + +struct PostProcessDescriptor +{ + VkImageView inputImage; + VkImageView outputImage; + VkSampler sampler; +}; + +struct PostProcessPushConstants +{ + int32_t width; + int32_t height; + uint32_t postProcessFlags; + int32_t padding; +}; + +struct PostProcessDrawInfo +{ + PostProcessType postProcessFlags{PostProcessType::ALL}; + VkDescriptorBufferBindingInfoEXT sceneDataBinding{}; + VkDeviceSize sceneDataOffset{0}; +}; +} + +#endif //POST_PROCESS_PIPELINE_TYPES_H diff --git a/src/renderer/pipelines/temporal_antialiasing_pipeline/temporal_antialiasing_pipeline.cpp b/src/renderer/pipelines/post/temporal_antialiasing/temporal_antialiasing_pipeline.cpp similarity index 98% rename from src/renderer/pipelines/temporal_antialiasing_pipeline/temporal_antialiasing_pipeline.cpp rename to src/renderer/pipelines/post/temporal_antialiasing/temporal_antialiasing_pipeline.cpp index 3b188961..54521d61 100644 --- a/src/renderer/pipelines/temporal_antialiasing_pipeline/temporal_antialiasing_pipeline.cpp +++ b/src/renderer/pipelines/post/temporal_antialiasing/temporal_antialiasing_pipeline.cpp @@ -4,8 +4,10 @@ #include "temporal_antialiasing_pipeline.h" -#include "volk/volk.h" #include "src/renderer/renderer_constants.h" +#include "src/renderer/resource_manager.h" +#include "src/renderer/vk_descriptors.h" + will_engine::temporal_antialiasing_pipeline::TemporalAntialiasingPipeline::TemporalAntialiasingPipeline(ResourceManager& resourceManager) : resourceManager(resourceManager) diff --git a/src/renderer/pipelines/temporal_antialiasing_pipeline/temporal_antialiasing_pipeline.h b/src/renderer/pipelines/post/temporal_antialiasing/temporal_antialiasing_pipeline.h similarity index 63% rename from src/renderer/pipelines/temporal_antialiasing_pipeline/temporal_antialiasing_pipeline.h rename to src/renderer/pipelines/post/temporal_antialiasing/temporal_antialiasing_pipeline.h index e3541bbc..e52e3ba6 100644 --- a/src/renderer/pipelines/temporal_antialiasing_pipeline/temporal_antialiasing_pipeline.h +++ b/src/renderer/pipelines/post/temporal_antialiasing/temporal_antialiasing_pipeline.h @@ -4,35 +4,19 @@ #ifndef TEMPORAL_ANTIALIASING_PIPELINE_H #define TEMPORAL_ANTIALIASING_PIPELINE_H -#include "src/renderer/resource_manager.h" +#include -namespace will_engine::temporal_antialiasing_pipeline -{ -struct TemporalAntialiasingPushConstants -{ - float blendValue; - int32_t taaDebug; -}; +#include "temporal_antialiasing_pipeline_types.h" +#include "src/renderer/descriptor_buffer/descriptor_buffer_sampler.h" -struct TemporalAntialiasingDescriptor +namespace will_engine { - VkImageView drawImage; - VkImageView historyBuffer; - VkImageView depthBuffer; - VkImageView velocityBuffer; - VkImageView outputTarget; - VkSampler sampler; -}; +class ResourceManager; +} -struct TemporalAntialiasingDrawInfo +namespace will_engine::temporal_antialiasing_pipeline { - float blendValue{}; - int32_t debugMode{}; - VkDescriptorBufferBindingInfoEXT sceneDataBinding{}; - VkDeviceSize sceneDataOffset{0}; -}; - class TemporalAntialiasingPipeline { public: diff --git a/src/renderer/pipelines/post/temporal_antialiasing/temporal_antialiasing_pipeline_types.h b/src/renderer/pipelines/post/temporal_antialiasing/temporal_antialiasing_pipeline_types.h new file mode 100644 index 00000000..1bf125a6 --- /dev/null +++ b/src/renderer/pipelines/post/temporal_antialiasing/temporal_antialiasing_pipeline_types.h @@ -0,0 +1,37 @@ +// +// Created by William on 2025-04-14. +// + +#ifndef TEMPORAL_ANTIALIASING_PIPELINE_TYPES_H +#define TEMPORAL_ANTIALIASING_PIPELINE_TYPES_H + +#include + +namespace will_engine::temporal_antialiasing_pipeline +{ +struct TemporalAntialiasingPushConstants +{ + float blendValue{0.1f}; + int32_t taaDebug{0}; +}; + +struct TemporalAntialiasingDescriptor +{ + VkImageView drawImage{VK_NULL_HANDLE}; + VkImageView historyBuffer{VK_NULL_HANDLE}; + VkImageView depthBuffer{VK_NULL_HANDLE}; + VkImageView velocityBuffer{VK_NULL_HANDLE}; + VkImageView outputTarget{VK_NULL_HANDLE}; + VkSampler sampler{VK_NULL_HANDLE}; +}; + +struct TemporalAntialiasingDrawInfo +{ + float blendValue{}; + int32_t debugMode{}; + VkDescriptorBufferBindingInfoEXT sceneDataBinding{}; + VkDeviceSize sceneDataOffset{0}; +}; +} // temporal_antialiasing_pipeline + +#endif //TEMPORAL_ANTIALIASING_PIPELINE_TYPES_H diff --git a/src/renderer/lighting/shadows/cascaded_shadow_map.cpp b/src/renderer/pipelines/shadows/cascaded_shadow_map/cascaded_shadow_map.cpp similarity index 99% rename from src/renderer/lighting/shadows/cascaded_shadow_map.cpp rename to src/renderer/pipelines/shadows/cascaded_shadow_map/cascaded_shadow_map.cpp index 0b2e6c45..2c40ad18 100644 --- a/src/renderer/lighting/shadows/cascaded_shadow_map.cpp +++ b/src/renderer/pipelines/shadows/cascaded_shadow_map/cascaded_shadow_map.cpp @@ -9,7 +9,6 @@ #include "volk/volk.h" #include "src/core/camera/camera.h" #include "src/renderer/renderer_constants.h" -#include "src/renderer/pipelines/terrain/terrain_pipeline.h" #include "src/renderer/assets/render_object/render_object_types.h" #include "src/renderer/terrain/terrain_chunk.h" #include "src/util/math_constants.h" diff --git a/src/renderer/lighting/shadows/cascaded_shadow_map.h b/src/renderer/pipelines/shadows/cascaded_shadow_map/cascaded_shadow_map.h similarity index 100% rename from src/renderer/lighting/shadows/cascaded_shadow_map.h rename to src/renderer/pipelines/shadows/cascaded_shadow_map/cascaded_shadow_map.h diff --git a/src/renderer/lighting/shadows/shadow_constants.cpp b/src/renderer/pipelines/shadows/cascaded_shadow_map/shadow_constants.cpp similarity index 82% rename from src/renderer/lighting/shadows/shadow_constants.cpp rename to src/renderer/pipelines/shadows/cascaded_shadow_map/shadow_constants.cpp index be3b3e17..2571d972 100644 --- a/src/renderer/lighting/shadows/shadow_constants.cpp +++ b/src/renderer/pipelines/shadows/cascaded_shadow_map/shadow_constants.cpp @@ -5,8 +5,8 @@ #include "shadow_constants.h" float will_engine::shadows::CASCADE_BIAS[SHADOW_CASCADE_COUNT][2] = { - {500.0f, 2.0f}, - {500.0f, 1.0f}, + {500.0f, 0.7f}, + {500.0f, 0.6f}, {600.0f, 1.0f}, {300.0f, 1.0f}, }; diff --git a/src/renderer/lighting/shadows/shadow_constants.h b/src/renderer/pipelines/shadows/cascaded_shadow_map/shadow_constants.h similarity index 92% rename from src/renderer/lighting/shadows/shadow_constants.h rename to src/renderer/pipelines/shadows/cascaded_shadow_map/shadow_constants.h index 0d04db8b..34c03185 100644 --- a/src/renderer/lighting/shadows/shadow_constants.h +++ b/src/renderer/pipelines/shadows/cascaded_shadow_map/shadow_constants.h @@ -13,7 +13,7 @@ static constexpr float LAMBDA = 0.8f; static constexpr float OVERLAP = 1.05f; static constexpr uint32_t SHADOW_CASCADE_COUNT = 4; static constexpr float CASCADE_NEAR_PLANE = 0.1f; -static constexpr float CASCADE_FAR_PLANE = 1000.0f; +static constexpr float CASCADE_FAR_PLANE = 400.0f; extern float CASCADE_BIAS[SHADOW_CASCADE_COUNT][2]; static constexpr int32_t CASCADE_WIDTH{2048}; static constexpr int32_t CASCADE_HEIGHT{2048}; diff --git a/src/renderer/lighting/shadows/shadow_types.h b/src/renderer/pipelines/shadows/cascaded_shadow_map/shadow_types.h similarity index 100% rename from src/renderer/lighting/shadows/shadow_types.h rename to src/renderer/pipelines/shadows/cascaded_shadow_map/shadow_types.h diff --git a/src/renderer/pipelines/shadows/contact_shadow/contact_shadows_pipeline.cpp b/src/renderer/pipelines/shadows/contact_shadow/contact_shadows_pipeline.cpp new file mode 100644 index 00000000..b946f7da --- /dev/null +++ b/src/renderer/pipelines/shadows/contact_shadow/contact_shadows_pipeline.cpp @@ -0,0 +1,299 @@ +// +// Created by William on 2025-04-14. +// + +#include "contact_shadows_pipeline.h" + +#include "contact_shadows_pipeline_types.h" +#include "src/renderer/resource_manager.h" +#include "src/core/camera/camera.h" +#include "src/renderer/lighting/directional_light.h" + +namespace will_engine::contact_shadows_pipeline +{ +ContactShadowsPipeline::ContactShadowsPipeline(ResourceManager& resourceManager) : resourceManager(resourceManager) +{ + DescriptorLayoutBuilder layoutBuilder; + layoutBuilder.addBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); // MRT depth buffer + layoutBuilder.addBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE); // ss contact shadows image + layoutBuilder.addBinding(2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE); // debug image + + descriptorSetLayout = resourceManager.createDescriptorSetLayout(layoutBuilder, VK_SHADER_STAGE_COMPUTE_BIT, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT); + + VkPushConstantRange pushConstants{}; + pushConstants.offset = 0; + pushConstants.size = sizeof(ContactShadowsPushConstants); + pushConstants.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; + + VkDescriptorSetLayout setLayouts[2]; + setLayouts[0] = resourceManager.getSceneDataLayout(); + setLayouts[1] = descriptorSetLayout; + + VkPipelineLayoutCreateInfo layoutInfo{}; + layoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + layoutInfo.pNext = nullptr; + layoutInfo.pSetLayouts = setLayouts; + layoutInfo.setLayoutCount = 2; + layoutInfo.pPushConstantRanges = &pushConstants; + layoutInfo.pushConstantRangeCount = 1; + + pipelineLayout = resourceManager.createPipelineLayout(layoutInfo); + createPipeline(); + + VkSamplerCreateInfo samplerInfo = {.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO}; + samplerInfo.magFilter = VK_FILTER_NEAREST; + samplerInfo.minFilter = VK_FILTER_NEAREST; + samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; + samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; + samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; + samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; + samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK; + samplerInfo.anisotropyEnable = VK_FALSE; + samplerInfo.maxAnisotropy = 1.0f; + samplerInfo.compareEnable = VK_FALSE; + samplerInfo.minLod = 0.0f; + samplerInfo.maxLod = 0.0f; + + depthSampler = resourceManager.createSampler(samplerInfo); + + VkImageUsageFlags usage{}; + usage |= VK_IMAGE_USAGE_STORAGE_BIT; + usage |= VK_IMAGE_USAGE_SAMPLED_BIT; + usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; + + VkImageCreateInfo imgInfo = vk_helpers::imageCreateInfo(contactShadowFormat, usage, {RENDER_EXTENTS.width, RENDER_EXTENTS.height, 1}); + contactShadowImage = resourceManager.createImage(imgInfo); + + usage = {}; + usage |= VK_IMAGE_USAGE_STORAGE_BIT; + usage |= VK_IMAGE_USAGE_SAMPLED_BIT; + usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; + + imgInfo = vk_helpers::imageCreateInfo(debugFormat, usage, {RENDER_EXTENTS.width, RENDER_EXTENTS.height, 1}); + debugImage = resourceManager.createImage(imgInfo); + + descriptorBufferSampler = resourceManager.createDescriptorBufferSampler(descriptorSetLayout, 1); +} + +ContactShadowsPipeline::~ContactShadowsPipeline() +{ + resourceManager.destroyPipeline(pipeline); + resourceManager.destroyPipelineLayout(pipelineLayout); + resourceManager.destroyDescriptorSetLayout(descriptorSetLayout); + + resourceManager.destroySampler(depthSampler); + + resourceManager.destroyImage(contactShadowImage); + resourceManager.destroyImage(debugImage); + resourceManager.destroyDescriptorBuffer(descriptorBufferSampler); +} + +void ContactShadowsPipeline::setupDescriptorBuffer(const VkImageView& depthImageView) +{ + std::vector imageDescriptors{}; + imageDescriptors.reserve(3); + + imageDescriptors.push_back( + { + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + {depthSampler, depthImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL}, + false + }); + imageDescriptors.push_back( + { + VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + {VK_NULL_HANDLE, contactShadowImage.imageView, VK_IMAGE_LAYOUT_GENERAL}, + false + }); + imageDescriptors.push_back({ + VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + {VK_NULL_HANDLE, debugImage.imageView, VK_IMAGE_LAYOUT_GENERAL}, + false + }); + + resourceManager.setupDescriptorBufferSampler(descriptorBufferSampler, imageDescriptors, 0); +} + +void ContactShadowsPipeline::draw(VkCommandBuffer cmd, const ContactShadowsDrawInfo& drawInfo) +{ + vk_helpers::transitionImage(cmd, debugImage.image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_ASPECT_COLOR_BIT); + vk_helpers::clearColorImage(cmd, VK_IMAGE_ASPECT_COLOR_BIT, contactShadowImage.image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL); + + vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline); + + ContactShadowsPushConstants push{drawInfo.push}; + + const DispatchList dispatchList = buildDispatchList(drawInfo.camera, drawInfo.light); + + push.lightCoordinate = glm::vec4(dispatchList.LightCoordinate_Shader[0], dispatchList.LightCoordinate_Shader[1], dispatchList.LightCoordinate_Shader[2], dispatchList.LightCoordinate_Shader[3]); + for (int32_t i = 0; i < dispatchList.DispatchCount; ++i) { + push.waveOffset = glm::ivec2(dispatchList.Dispatch[i].WaveOffset_Shader[0], dispatchList.Dispatch[i].WaveOffset_Shader[1]); + + vkCmdPushConstants(cmd, pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(ContactShadowsPushConstants), &push); + + VkDescriptorBufferBindingInfoEXT bindingInfos[2] = {}; + bindingInfos[0] = drawInfo.sceneDataBinding; + bindingInfos[1] = descriptorBufferSampler.getDescriptorBufferBindingInfo(); + vkCmdBindDescriptorBuffersEXT(cmd, 2, bindingInfos); + + constexpr std::array indices{0, 1}; + const std::array offsets{drawInfo.sceneDataOffset, ZERO_DEVICE_SIZE}; + + vkCmdSetDescriptorBufferOffsetsEXT(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0, 2, indices.data(), offsets.data()); + + const int32_t* waveCount = dispatchList.Dispatch[i].WaveCount; + vkCmdDispatch(cmd, waveCount[0], waveCount[1], waveCount[2]); + } +} + +void ContactShadowsPipeline::createPipeline() +{ + resourceManager.destroyPipeline(pipeline); + VkShaderModule computeShader = resourceManager.createShaderModule("shaders/shadows/contact_shadow_pass.comp"); + + VkPipelineShaderStageCreateInfo stageInfo{}; + stageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stageInfo.pNext = nullptr; + stageInfo.stage = VK_SHADER_STAGE_COMPUTE_BIT; + stageInfo.module = computeShader; + stageInfo.pName = "main"; + + VkComputePipelineCreateInfo pipelineInfo{}; + pipelineInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; + pipelineInfo.pNext = nullptr; + pipelineInfo.layout = pipelineLayout; + pipelineInfo.stage = stageInfo; + pipelineInfo.flags = VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT; + + pipeline = resourceManager.createComputePipeline(pipelineInfo); + resourceManager.destroyShaderModule(computeShader); +} + +DispatchList ContactShadowsPipeline::buildDispatchList(const Camera* camera, const DirectionalLight& mainLight) +{ + DispatchList result = {}; + + glm::vec4 lightProjection = camera->getViewProjMatrix() * glm::vec4(-mainLight.getDirection(), 0.0f); + + // Floating point division in the shader has a practical limit for precision when the light is *very* far off screen (~1m pixels+) + // So when computing the light XY coordinate, use an adjusted w value to handle these extreme values + float xy_light_w = lightProjection[3]; + const float FP_limit = 0.000002f * static_cast(CONTACT_SHADOW_WAVE_SIZE); + + if (xy_light_w >= 0 && xy_light_w < FP_limit) xy_light_w = FP_limit; + else if (xy_light_w < 0 && xy_light_w > -FP_limit) xy_light_w = -FP_limit; + + // Need precise XY pixel coordinates of the light + result.LightCoordinate_Shader[0] = ((lightProjection[0] / xy_light_w) * +0.5f + 0.5f) * RENDER_EXTENT_WIDTH; + result.LightCoordinate_Shader[1] = ((lightProjection[1] / xy_light_w) * -0.5f + 0.5f) * RENDER_EXTENT_HEIGHT; + result.LightCoordinate_Shader[2] = lightProjection[3] == 0 ? 0 : (lightProjection[2] / lightProjection[3]); + result.LightCoordinate_Shader[3] = lightProjection[3] > 0 ? 1 : -1; + + int32_t light_xy[2] = {static_cast(result.LightCoordinate_Shader[0] + 0.5f), static_cast(result.LightCoordinate_Shader[1] + 0.5f)}; + + // Make the bounds inclusive, relative to the light + const int32_t biased_bounds[4] = + { + 0 - light_xy[0], + -static_cast(RENDER_EXTENT_HEIGHT - light_xy[1]), + static_cast(RENDER_EXTENT_WIDTH - light_xy[0]), + -(0 - light_xy[1]), + }; + + // Process 4 quadrants around the light center, + // They each form a rectangle with one corner on the light XY coordinate + // If the rectangle isn't square, it will need breaking in two on the larger axis + // 0 = bottom left, 1 = bottom right, 2 = top left, 2 = top right + for (int q = 0; q < 4; q++) { + // Quads 0 and 3 needs to be +1 vertically, 1 and 2 need to be +1 horizontally + bool vertical = q == 0 || q == 3; + + // Bounds relative to the quadrant + const int bounds[4] = + { + bend_max(0, ((q & 1) ? biased_bounds[0] : -biased_bounds[2])) / CONTACT_SHADOW_WAVE_SIZE, + bend_max(0, ((q & 2) ? biased_bounds[1] : -biased_bounds[3])) / CONTACT_SHADOW_WAVE_SIZE, + bend_max(0, (((q & 1) ? biased_bounds[2] : -biased_bounds[0]) + CONTACT_SHADOW_WAVE_SIZE * (vertical ? 1 : 2) - 1)) / CONTACT_SHADOW_WAVE_SIZE, + bend_max(0, (((q & 2) ? biased_bounds[3] : -biased_bounds[1]) + CONTACT_SHADOW_WAVE_SIZE * (vertical ? 2 : 1) - 1)) / CONTACT_SHADOW_WAVE_SIZE, + }; + + if ((bounds[2] - bounds[0]) > 0 && (bounds[3] - bounds[1]) > 0) { + int bias_x = (q == 2 || q == 3) ? 1 : 0; + int bias_y = (q == 1 || q == 3) ? 1 : 0; + + DispatchData& disp = result.Dispatch[result.DispatchCount++]; + + disp.WaveCount[0] = CONTACT_SHADOW_WAVE_SIZE; + disp.WaveCount[1] = bounds[2] - bounds[0]; + disp.WaveCount[2] = bounds[3] - bounds[1]; + disp.WaveOffset_Shader[0] = ((q & 1) ? bounds[0] : -bounds[2]) + bias_x; + disp.WaveOffset_Shader[1] = ((q & 2) ? -bounds[3] : bounds[1]) + bias_y; + + // We want the far corner of this quadrant relative to the light, + // as we need to know where the diagonal light ray intersects with the edge of the bounds + int axis_delta = +biased_bounds[0] - biased_bounds[1]; + if (q == 1) axis_delta = +biased_bounds[2] + biased_bounds[1]; + if (q == 2) axis_delta = -biased_bounds[0] - biased_bounds[3]; + if (q == 3) axis_delta = -biased_bounds[2] + biased_bounds[3]; + + axis_delta = (axis_delta + CONTACT_SHADOW_WAVE_SIZE - 1) / CONTACT_SHADOW_WAVE_SIZE; + + if (axis_delta > 0) { + DispatchData& disp2 = result.Dispatch[result.DispatchCount++]; + + // Take copy of current volume + disp2 = disp; + + if (q == 0) { + // Split on Y, split becomes -1 larger on x + disp2.WaveCount[2] = bend_min(disp.WaveCount[2], axis_delta); + disp.WaveCount[2] -= disp2.WaveCount[2]; + disp2.WaveOffset_Shader[1] = disp.WaveOffset_Shader[1] + disp.WaveCount[2]; + disp2.WaveOffset_Shader[0]--; + disp2.WaveCount[1]++; + } + if (q == 1) { + // Split on X, split becomes +1 larger on y + disp2.WaveCount[1] = bend_min(disp.WaveCount[1], axis_delta); + disp.WaveCount[1] -= disp2.WaveCount[1]; + disp2.WaveOffset_Shader[0] = disp.WaveOffset_Shader[0] + disp.WaveCount[1]; + disp2.WaveCount[2]++; + } + if (q == 2) { + // Split on X, split becomes -1 larger on y + disp2.WaveCount[1] = bend_min(disp.WaveCount[1], axis_delta); + disp.WaveCount[1] -= disp2.WaveCount[1]; + disp.WaveOffset_Shader[0] += disp2.WaveCount[1]; + disp2.WaveCount[2]++; + disp2.WaveOffset_Shader[1]--; + } + if (q == 3) { + // Split on Y, split becomes +1 larger on x + disp2.WaveCount[2] = bend_min(disp.WaveCount[2], axis_delta); + disp.WaveCount[2] -= disp2.WaveCount[2]; + disp.WaveOffset_Shader[1] += disp2.WaveCount[2]; + disp2.WaveCount[1]++; + } + + // Remove if too small + if (disp2.WaveCount[1] <= 0 || disp2.WaveCount[2] <= 0) { + disp2 = result.Dispatch[--result.DispatchCount]; + } + if (disp.WaveCount[1] <= 0 || disp.WaveCount[2] <= 0) { + disp = result.Dispatch[--result.DispatchCount]; + } + } + } + } + + // Scale the shader values by the wave count, the shader expects this + for (int i = 0; i < result.DispatchCount; i++) { + result.Dispatch[i].WaveOffset_Shader[0] *= CONTACT_SHADOW_WAVE_SIZE; + result.Dispatch[i].WaveOffset_Shader[1] *= CONTACT_SHADOW_WAVE_SIZE; + } + + return result; +} +} diff --git a/src/renderer/pipelines/shadows/contact_shadow/contact_shadows_pipeline.h b/src/renderer/pipelines/shadows/contact_shadow/contact_shadows_pipeline.h new file mode 100644 index 00000000..7138c05c --- /dev/null +++ b/src/renderer/pipelines/shadows/contact_shadow/contact_shadows_pipeline.h @@ -0,0 +1,74 @@ +// +// Created by William on 2025-04-14. +// + +#ifndef CONTACT_SHADOWS_H +#define CONTACT_SHADOWS_H + +#include + +#include "contact_shadows_pipeline_types.h" +#include "src/renderer/imgui_wrapper.h" +#include "src/renderer/vk_types.h" +#include "src/renderer/descriptor_buffer/descriptor_buffer_sampler.h" + + +namespace will_engine +{ +class Camera; +class DirectionalLight; +} + +namespace will_engine::contact_shadows_pipeline +{ +class ContactShadowsPipeline { +public: + explicit ContactShadowsPipeline(ResourceManager& resourceManager); + + ~ContactShadowsPipeline(); + + void setupDescriptorBuffer(const VkImageView& depthImageView); + + void draw(VkCommandBuffer cmd, const ContactShadowsDrawInfo& drawInfo); + + void reloadShaders() + { + createPipeline(); + } + + AllocatedImage getContactShadowRenderTarget() const { return contactShadowImage; } + +private: + void createPipeline(); + + static DispatchList buildDispatchList(const Camera* camera, const DirectionalLight& mainLight); + + static int32_t bend_min(const int32_t a, const int32_t b) { return a > b ? b : a; } + static int32_t bend_max(const int32_t a, const int32_t b) { return a > b ? a : b; } + +private: + VkDescriptorSetLayout descriptorSetLayout{VK_NULL_HANDLE}; + VkPipelineLayout pipelineLayout{VK_NULL_HANDLE}; + VkPipeline pipeline{VK_NULL_HANDLE}; + + VkSampler depthSampler{VK_NULL_HANDLE}; + + VkFormat contactShadowFormat{VK_FORMAT_R8_UNORM}; + AllocatedImage contactShadowImage{VK_NULL_HANDLE}; + + DescriptorBufferSampler descriptorBufferSampler; + +private: // Debug + VkFormat debugFormat{VK_FORMAT_R8G8B8A8_UNORM}; + AllocatedImage debugImage{VK_NULL_HANDLE}; + + ResourceManager& resourceManager; + +private: + //todo: remove + friend void ImguiWrapper::imguiInterface(Engine* engine); +}; + +} + +#endif //CONTACT_SHADOWS_H diff --git a/src/renderer/pipelines/shadows/contact_shadow/contact_shadows_pipeline_types.h b/src/renderer/pipelines/shadows/contact_shadow/contact_shadows_pipeline_types.h new file mode 100644 index 00000000..0311463a --- /dev/null +++ b/src/renderer/pipelines/shadows/contact_shadow/contact_shadows_pipeline_types.h @@ -0,0 +1,72 @@ +// +// Created by William on 2025-04-14. +// + +#ifndef CONTACT_SHADOW_TYPES_H +#define CONTACT_SHADOW_TYPES_H + +#include +#include + +#include "src/core/camera/camera.h" +#include "src/renderer/lighting/directional_light.h" + +namespace will_engine::contact_shadows_pipeline +{ + +static constexpr int32_t CONTACT_SHADOW_WAVE_SIZE = 64; + +enum class ContactShadowsDebugMode : int32_t +{ + NONE = 0, + EDGE = 1, + INVOCATION_ID = 2, + WORK_GROUP_ID = 3 +}; + +struct DispatchData +{ + int32_t WaveCount[3]; // Compute Shader Dispatch(X,Y,Z) wave counts X/Y/Z + int32_t WaveOffset_Shader[2]; // This value is passed in to shader. It will be different for each dispatch +}; + +struct DispatchList +{ + float LightCoordinate_Shader[4]; // This value is passed in to shader, this will be the same value for all dispatches for this light + + DispatchData Dispatch[8]; // List of dispatches (max count is 8) + int32_t DispatchCount; // Number of compute dispatches written to the list +}; + + +struct ContactShadowsPushConstants +{ + float surfaceThickness{0.005}; + float bilinearThreshold{0.05}; + float shadowContrast{2}; + + int32_t bIgnoreEdgePixels{1}; + int32_t bUsePrecisionOffset{0}; + int32_t bBilinearSamplingOffsetMode{0}; + + glm::vec2 depthBounds{0, 1}; + int32_t bUseEarlyOut{1}; + + //ContactShadowsDebugMode debugMode{ContactShadowsDebugMode::NONE}; + int32_t debugMode{0}; + + glm::ivec2 waveOffset{0}; + glm::vec4 lightCoordinate{0.0f}; +}; + +struct ContactShadowsDrawInfo +{ + Camera* camera; + DirectionalLight light; + ContactShadowsPushConstants push; + VkDescriptorBufferBindingInfoEXT sceneDataBinding{}; + VkDeviceSize sceneDataOffset{0}; +}; +} + +#endif //CONTACT_SHADOW_TYPES_H diff --git a/src/renderer/lighting/ambient_occlusion/ambient_occlusion_types.h b/src/renderer/pipelines/shadows/ground_truth_ambient_occlusion/ambient_occlusion_types.h similarity index 100% rename from src/renderer/lighting/ambient_occlusion/ambient_occlusion_types.h rename to src/renderer/pipelines/shadows/ground_truth_ambient_occlusion/ambient_occlusion_types.h diff --git a/src/renderer/lighting/ambient_occlusion/ground_truth/ground_truth_ambient_occlusion.cpp b/src/renderer/pipelines/shadows/ground_truth_ambient_occlusion/ground_truth_ambient_occlusion_pipeline.cpp similarity index 97% rename from src/renderer/lighting/ambient_occlusion/ground_truth/ground_truth_ambient_occlusion.cpp rename to src/renderer/pipelines/shadows/ground_truth_ambient_occlusion/ground_truth_ambient_occlusion_pipeline.cpp index 513a116d..016cc3f1 100644 --- a/src/renderer/lighting/ambient_occlusion/ground_truth/ground_truth_ambient_occlusion.cpp +++ b/src/renderer/pipelines/shadows/ground_truth_ambient_occlusion/ground_truth_ambient_occlusion_pipeline.cpp @@ -2,13 +2,13 @@ // Created by William on 2025-03-23. // -#include "ground_truth_ambient_occlusion.h" +#include "ground_truth_ambient_occlusion_pipeline.h" #include #include "src/renderer/renderer_constants.h" #include "src/renderer/vk_descriptors.h" -#include "src/renderer/lighting/ambient_occlusion/ambient_occlusion_types.h" +#include "ambient_occlusion_types.h" will_engine::ambient_occlusion::GroundTruthAmbientOcclusionPipeline::GroundTruthAmbientOcclusionPipeline( ResourceManager& resourceManager) : resourceManager(resourceManager) @@ -370,6 +370,8 @@ void will_engine::ambient_occlusion::GroundTruthAmbientOcclusionPipeline::draw(V label.pLabelName = "GT Ambient Occlusion"; vkCmdBeginDebugUtilsLabelEXT(cmd, &label); + gtaoPush.debug = drawInfo.pushConstants.debug; + glm::mat4 projMatrix = drawInfo.camera->getProjMatrix(); gtaoPush.depthLinearizeMult = -projMatrix[3][2]; gtaoPush.depthLinearizeAdd = projMatrix[2][2]; @@ -390,7 +392,7 @@ void will_engine::ambient_occlusion::GroundTruthAmbientOcclusionPipeline::draw(V vk_helpers::transitionImage(cmd, debugImage.image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_ASPECT_COLOR_BIT); - vk_helpers::clearColorImage(cmd, depthPrefilterImage.image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL); + vk_helpers::clearColorImage(cmd, VK_IMAGE_ASPECT_COLOR_BIT, depthPrefilterImage.image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL); // Depth Prefilter { vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, depthPrefilterPipeline); @@ -406,11 +408,9 @@ void will_engine::ambient_occlusion::GroundTruthAmbientOcclusionPipeline::draw(V vkCmdSetDescriptorBufferOffsetsEXT(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, depthPrefilterPipelineLayout, 0, 2, indices.data(), offsets.data()); - auto x = static_cast(std::ceil(RENDER_EXTENT_WIDTH / 16.0f)); - auto y = static_cast(std::ceil(RENDER_EXTENT_HEIGHT / 16.0f)); - // shader only operates on 8,8 work groups, mip 0 will operate on 2x2 texels - // x = x / 2 + 1; - // y = y / 2 + 1; + // shader only operates on 8,8 work groups, mip 0 will operate on 2x2 texels, so its 16x16 as expected + const auto x = static_cast(std::ceil(RENDER_EXTENT_WIDTH / 16.0f)); + const auto y = static_cast(std::ceil(RENDER_EXTENT_HEIGHT / 16.0f)); vkCmdDispatch(cmd, x, y, 1); } diff --git a/src/renderer/lighting/ambient_occlusion/ground_truth/ground_truth_ambient_occlusion.h b/src/renderer/pipelines/shadows/ground_truth_ambient_occlusion/ground_truth_ambient_occlusion_pipeline.h similarity index 97% rename from src/renderer/lighting/ambient_occlusion/ground_truth/ground_truth_ambient_occlusion.h rename to src/renderer/pipelines/shadows/ground_truth_ambient_occlusion/ground_truth_ambient_occlusion_pipeline.h index 9e96e565..192d26be 100644 --- a/src/renderer/lighting/ambient_occlusion/ground_truth/ground_truth_ambient_occlusion.h +++ b/src/renderer/pipelines/shadows/ground_truth_ambient_occlusion/ground_truth_ambient_occlusion_pipeline.h @@ -9,7 +9,7 @@ #include "src/renderer/imgui_wrapper.h" #include "src/renderer/resource_manager.h" -#include "src/renderer/lighting/ambient_occlusion/ambient_occlusion_types.h" +#include "ambient_occlusion_types.h" namespace will_engine::ambient_occlusion diff --git a/src/renderer/pipelines/visibility_pass/visibility_pass.cpp b/src/renderer/pipelines/visibility_pass/visibility_pass_pipeline.cpp similarity index 80% rename from src/renderer/pipelines/visibility_pass/visibility_pass.cpp rename to src/renderer/pipelines/visibility_pass/visibility_pass_pipeline.cpp index 528fce14..d2c3223c 100644 --- a/src/renderer/pipelines/visibility_pass/visibility_pass.cpp +++ b/src/renderer/pipelines/visibility_pass/visibility_pass_pipeline.cpp @@ -2,16 +2,17 @@ // Created by William on 2025-01-26. // -#include "visibility_pass.h" +#include "visibility_pass_pipeline.h" #include -#include - -#include "volk/volk.h" +#include +#include "visibility_pass_pipeline_types.h" +#include "src/renderer/resource_manager.h" +#include "src/renderer/vk_helpers.h" #include "src/renderer/assets/render_object/render_object.h" -will_engine::visibility_pass::VisibilityPassPipeline::VisibilityPassPipeline(ResourceManager& resourceManager) +will_engine::visibility_pass_pipeline::VisibilityPassPipeline::VisibilityPassPipeline(ResourceManager& resourceManager) : resourceManager(resourceManager) { VkDescriptorSetLayout layouts[3]; @@ -36,13 +37,13 @@ will_engine::visibility_pass::VisibilityPassPipeline::VisibilityPassPipeline(Res createPipeline(); } -will_engine::visibility_pass::VisibilityPassPipeline::~VisibilityPassPipeline() +will_engine::visibility_pass_pipeline::VisibilityPassPipeline::~VisibilityPassPipeline() { resourceManager.destroyPipeline(pipeline); resourceManager.destroyPipelineLayout(pipelineLayout); } -void will_engine::visibility_pass::VisibilityPassPipeline::draw(VkCommandBuffer cmd, const VisibilityPassDrawInfo& drawInfo) const +void will_engine::visibility_pass_pipeline::VisibilityPassPipeline::draw(VkCommandBuffer cmd, const VisibilityPassDrawInfo& drawInfo) const { VkDebugUtilsLabelEXT label = {}; label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT; @@ -61,7 +62,8 @@ void will_engine::visibility_pass::VisibilityPassPipeline::draw(VkCommandBuffer for (RenderObject* renderObject : drawInfo.renderObjects) { if (drawInfo.bIsOpaque) { if (!renderObject->canDrawOpaque()) { continue; } - } else { + } + else { if (!renderObject->canDrawTransparent()) { continue; } } @@ -84,14 +86,16 @@ void will_engine::visibility_pass::VisibilityPassPipeline::draw(VkCommandBuffer vkCmdDispatch(cmd, static_cast(std::ceil(static_cast(renderObject->getOpaqueDrawIndirectCommandCount()) / 64.0f)), 1, 1); - vk_helpers::synchronizeUniform(cmd, renderObject->getOpaqueIndirectBuffer(drawInfo.currentFrameOverlap), VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_WRITE_BIT, VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT, VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT); + vk_helpers::synchronizeUniform(cmd, renderObject->getOpaqueIndirectBuffer(drawInfo.currentFrameOverlap), + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_WRITE_BIT, VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT, + VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT); } vkCmdEndDebugUtilsLabelEXT(cmd); } -void will_engine::visibility_pass::VisibilityPassPipeline::createPipeline() +void will_engine::visibility_pass_pipeline::VisibilityPassPipeline::createPipeline() { resourceManager.destroyPipeline(pipeline); VkShaderModule computeShader = resourceManager.createShaderModule("shaders/visibility_pass.comp"); diff --git a/src/renderer/pipelines/visibility_pass/visibility_pass.h b/src/renderer/pipelines/visibility_pass/visibility_pass_pipeline.h similarity index 58% rename from src/renderer/pipelines/visibility_pass/visibility_pass.h rename to src/renderer/pipelines/visibility_pass/visibility_pass_pipeline.h index 071e7d1a..cd31dfcd 100644 --- a/src/renderer/pipelines/visibility_pass/visibility_pass.h +++ b/src/renderer/pipelines/visibility_pass/visibility_pass_pipeline.h @@ -4,32 +4,19 @@ #ifndef VISIBILITY_PASS_PIPELINE_H #define VISIBILITY_PASS_PIPELINE_H -#include "src/renderer/resource_manager.h" +#include namespace will_engine { +class ResourceManager; class RenderObject; } -namespace will_engine::visibility_pass +namespace will_engine::visibility_pass_pipeline { -struct VisibilityPassPushConstants -{ - int32_t enable{}; - int32_t shadowPass{}; -}; +struct VisibilityPassDrawInfo; -struct VisibilityPassDrawInfo -{ - int32_t currentFrameOverlap{0}; - const std::vector& renderObjects{}; - VkDescriptorBufferBindingInfoEXT sceneDataBinding{}; - VkDeviceSize sceneDataOffset{0}; - bool bEnableFrustumCulling{}; - bool bIsShadowPass{}; - bool bIsOpaque{}; -}; class VisibilityPassPipeline { diff --git a/src/renderer/pipelines/visibility_pass/visibility_pass_pipeline_types.h b/src/renderer/pipelines/visibility_pass/visibility_pass_pipeline_types.h new file mode 100644 index 00000000..0d65a5a6 --- /dev/null +++ b/src/renderer/pipelines/visibility_pass/visibility_pass_pipeline_types.h @@ -0,0 +1,36 @@ +// +// Created by William on 2025-04-14. +// + +#ifndef VISIBILITY_PASS_PIPELINE_TYPES_H +#define VISIBILITY_PASS_PIPELINE_TYPES_H + +#include +#include + +namespace will_engine +{ +class RenderObject; +} + +namespace will_engine::visibility_pass_pipeline +{ +struct VisibilityPassPushConstants +{ + int32_t enable{}; + int32_t shadowPass{}; +}; + +struct VisibilityPassDrawInfo +{ + int32_t currentFrameOverlap{0}; + const std::vector& renderObjects{}; + VkDescriptorBufferBindingInfoEXT sceneDataBinding{}; + VkDeviceSize sceneDataOffset{0}; + bool bEnableFrustumCulling{}; + bool bIsShadowPass{}; + bool bIsOpaque{}; +}; +} + +#endif //VISIBILITY_PASS_PIPELINE_TYPES_H diff --git a/src/renderer/post_process/post_process_types.h b/src/renderer/post_process/post_process_types.h deleted file mode 100644 index 1067a186..00000000 --- a/src/renderer/post_process/post_process_types.h +++ /dev/null @@ -1,41 +0,0 @@ -// -// Created by William on 2025-01-25. -// - -#ifndef POST_PROCESS_TYPES_H -#define POST_PROCESS_TYPES_H - -namespace post_process -{ -enum class PostProcessType : uint32_t -{ - None = 0x00000000, - Tonemapping = 1 << 0, - Sharpening = 1 << 1, - FXAA = 1 << 2, - ALL = 0xFFFFFFFF -}; - -inline PostProcessType operator|(PostProcessType a, PostProcessType b) { - return static_cast(static_cast(a) | static_cast(b)); -} - -inline PostProcessType operator&(PostProcessType a, PostProcessType b) { - return static_cast(static_cast(a) & static_cast(b)); -} - -inline PostProcessType operator~(PostProcessType a) { - return static_cast(~static_cast(a)); -} - -inline PostProcessType& operator|=(PostProcessType& a, PostProcessType b) { - return a = a | b; -} - -inline PostProcessType& operator&=(PostProcessType& a, PostProcessType b) { - return a = a & b; -} - -} - -#endif //POST_PROCESS_TYPES_H diff --git a/src/renderer/renderer_constants.h b/src/renderer/renderer_constants.h index 3dfd19e9..e77c7791 100644 --- a/src/renderer/renderer_constants.h +++ b/src/renderer/renderer_constants.h @@ -5,17 +5,17 @@ #ifndef RENDERER_CONSTANTS_H #define RENDERER_CONSTANTS_H #include - +namespace will_engine +{ constexpr int32_t FRAME_OVERLAP = 2; constexpr char ENGINE_NAME[] = "Will Engine"; constexpr bool USING_REVERSED_DEPTH_BUFFER = true; constexpr VkDeviceSize ZERO_DEVICE_SIZE = 0; -constexpr VkExtent2D RENDER_EXTENTS{1920, 1080}; -//constexpr VkExtent2D RENDER_EXTENTS{2140, 1440}; +//constexpr VkExtent2D RENDER_EXTENTS{1920, 1080}; +constexpr VkExtent2D RENDER_EXTENTS{2140, 1440}; //constexpr VkExtent2D RENDER_EXTENTS{3840, 2160}; constexpr float RENDER_EXTENT_WIDTH{RENDER_EXTENTS.width}; constexpr float RENDER_EXTENT_HEIGHT{RENDER_EXTENTS.height}; - constexpr VkFormat DRAW_FORMAT{VK_FORMAT_R16G16B16A16_SFLOAT}; constexpr VkFormat DEPTH_FORMAT{VK_FORMAT_D32_SFLOAT}; constexpr VkFormat VELOCITY_FORMAT{VK_FORMAT_R16G16_SFLOAT}; @@ -23,5 +23,7 @@ constexpr VkFormat NORMAL_FORMAT{VK_FORMAT_R16G16B16A16_SNORM}; // Be careful, environment map is in HDR format, so non-float formats wont work constexpr VkFormat ALBEDO_FORMAT{VK_FORMAT_R16G16B16A16_SFLOAT}; constexpr VkFormat PBR_FORMAT{VK_FORMAT_R8G8B8A8_UNORM}; +} + #endif // RENDERER_CONSTANTS_H diff --git a/src/renderer/resource_manager.cpp b/src/renderer/resource_manager.cpp index 59a4b1a4..ce6d907a 100644 --- a/src/renderer/resource_manager.cpp +++ b/src/renderer/resource_manager.cpp @@ -122,7 +122,8 @@ will_engine::ResourceManager::ResourceManager(const VulkanContext& context, Imme layoutBuilder.addBinding(3, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); // Depth layoutBuilder.addBinding(4, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); // Velocity layoutBuilder.addBinding(5, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); // AO - layoutBuilder.addBinding(6, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE); // Output + layoutBuilder.addBinding(6, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); // Screen Space Contact Shadows + layoutBuilder.addBinding(7, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE); // Output renderTargetsLayout = layoutBuilder.build(context.device, VK_SHADER_STAGE_COMPUTE_BIT, nullptr, VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT); } diff --git a/src/renderer/vk_helpers.cpp b/src/renderer/vk_helpers.cpp index 19ffca52..770aa956 100644 --- a/src/renderer/vk_helpers.cpp +++ b/src/renderer/vk_helpers.cpp @@ -265,7 +265,7 @@ VkDeviceSize will_engine::vk_helpers::getAlignedSize(const VkDeviceSize value, V return (value + alignment - 1) & ~(alignment - 1); } -void will_engine::vk_helpers::clearColorImage(VkCommandBuffer cmd, VkImage image, VkImageLayout srcLayout, VkImageLayout dstLayout, VkClearColorValue clearColor) +void will_engine::vk_helpers::clearColorImage(VkCommandBuffer cmd, VkImageAspectFlagBits aspectFlag, VkImage image, VkImageLayout srcLayout, VkImageLayout dstLayout, VkClearColorValue clearColor) { transitionImage(cmd, image, srcLayout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT); constexpr VkImageSubresourceRange range{ diff --git a/src/renderer/vk_helpers.h b/src/renderer/vk_helpers.h index 87c73eeb..9da7d68f 100644 --- a/src/renderer/vk_helpers.h +++ b/src/renderer/vk_helpers.h @@ -80,7 +80,7 @@ namespace vk_helpers */ VkDeviceSize getAlignedSize(VkDeviceSize value, VkDeviceSize alignment); - void clearColorImage(VkCommandBuffer cmd, VkImage image, VkImageLayout srcLayout, VkImageLayout dstLayout, + void clearColorImage(VkCommandBuffer cmd, VkImageAspectFlagBits aspectFlag, VkImage image, VkImageLayout srcLayout, VkImageLayout dstLayout, VkClearColorValue clearColor = {0.0f, 0.0f, 0.0f, 1.0f}); void transitionImage(VkCommandBuffer cmd, VkImage image, VkImageLayout currentLayout, VkImageLayout targetLayout, VkImageAspectFlags aspectMask);