From 78078e92cdc70ab3e3639b4f4415d08d4778be8f Mon Sep 17 00:00:00 2001 From: Joshua Goins Date: Mon, 7 Feb 2022 18:36:23 -0500 Subject: [PATCH] Fix multiple point light shadows on Vulkan Light locations had to be padded properly, that ended up being the ultimate fix. Leading to this bug though I ended up patching a lot of stuff that was mysteriously missing from the Vulkan backend like specialization constants and --- engine/renderer/include/shadowpass.hpp | 2 +- engine/renderer/src/renderer.cpp | 11 ++++++++--- engine/renderer/src/shadowpass.cpp | 16 ++++++++-------- engine/shaders/omnishadow.frag.glsl | 4 ++-- engine/shaders/rendering.nocompile.glsl | 8 +++----- engine/shaders/shadow.vert.nocompile.glsl | 4 ++-- 6 files changed, 24 insertions(+), 21 deletions(-) diff --git a/engine/renderer/include/shadowpass.hpp b/engine/renderer/include/shadowpass.hpp index 74cd87a..7e2551d 100755 --- a/engine/renderer/include/shadowpass.hpp +++ b/engine/renderer/include/shadowpass.hpp @@ -45,7 +45,7 @@ private: GFXFramebuffer* offscreen_framebuffer = nullptr; GFXBuffer* point_location_buffer = nullptr; - prism::float3* point_location_map = nullptr; + prism::float4* point_location_map = nullptr; // sun GFXPipeline* static_sun_pipeline = nullptr; diff --git a/engine/renderer/src/renderer.cpp b/engine/renderer/src/renderer.cpp index 5507f67..7a58aea 100755 --- a/engine/renderer/src/renderer.cpp +++ b/engine/renderer/src/renderer.cpp @@ -372,7 +372,8 @@ void renderer::render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Obj sceneInfo.camPos = scene.get(camera_object).get_world_position(); sceneInfo.camPos.w = 2.0f * camera.near * std::tan(camera.fov * 0.5f) * (static_cast(extent.width) / static_cast(extent.height)); sceneInfo.vp = camera.perspective * camera.view; - + + int last_point_light = 0; for(const auto& [obj, light] : scene.get_all()) { SceneLight sl; sl.positionType = prism::float4(scene.get(obj).get_world_position(), static_cast(light.type)); @@ -381,8 +382,12 @@ void renderer::render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Obj sl.directionPower = prism::float4(-front, light.power); sl.colorSize = prism::float4(utility::from_srgb_to_linear(light.color), radians(light.spot_size)); - sl.shadowsEnable = prism::float4(light.enable_shadows, radians(light.size), 0, 0); - + + sl.shadowsEnable = prism::float4(light.enable_shadows, radians(light.size), last_point_light, 0); + + if(light.enable_shadows) + last_point_light++; + sceneInfo.lights[sceneInfo.numLights++] = sl; } diff --git a/engine/renderer/src/shadowpass.cpp b/engine/renderer/src/shadowpass.cpp index 400aff4..db98e17 100755 --- a/engine/renderer/src/shadowpass.cpp +++ b/engine/renderer/src/shadowpass.cpp @@ -141,7 +141,7 @@ void ShadowPass::render_meshes(GFXCommandBuffer* command_buffer, Scene& scene, c break; } - command_buffer->bind_shader_buffer(point_location_buffer, 0, 2, sizeof(prism::float3) * max_point_shadows); + command_buffer->bind_shader_buffer(point_location_buffer, 0, 2, sizeof(prism::float4) * max_point_shadows); command_buffer->set_push_constant(&pc, sizeof(PushConstant)); command_buffer->set_depth_bias(1.25f, 0.00f, 1.75f); @@ -165,7 +165,7 @@ void ShadowPass::render_meshes(GFXCommandBuffer* command_buffer, Scene& scene, c break; } - command_buffer->bind_shader_buffer(point_location_buffer, 0, 2, sizeof(prism::float3) * max_point_shadows); + command_buffer->bind_shader_buffer(point_location_buffer, 0, 2, sizeof(prism::float4) * max_point_shadows); command_buffer->set_push_constant(&pc, sizeof(PushConstant)); @@ -266,7 +266,9 @@ void ShadowPass::render_point(GFXCommandBuffer* command_buffer, Scene& scene, Ob return; if(scene.point_light_dirty[last_point_light] || light.use_dynamic_shadows) { - *(point_location_map + last_point_light) = scene.get(light_object).get_world_position(); + const prism::float3 lightPos = scene.get(light_object).get_world_position(); + + (point_location_map + last_point_light)->xyz = lightPos; for(int face = 0; face < 6; face++) { GFXRenderPassBeginInfo info = {}; @@ -281,9 +283,7 @@ void ShadowPass::render_point(GFXCommandBuffer* command_buffer, Scene& scene, Ob viewport.height = render_options.shadow_resolution; command_buffer->set_viewport(viewport); - - const prism::float3 lightPos = scene.get(light_object).get_world_position(); - + const Matrix4x4 projection = prism::perspective(radians(90.0f), 1.0f, 0.1f, 100.0f); const Matrix4x4 model = inverse(scene.get(light_object).model); @@ -408,6 +408,6 @@ void ShadowPass::create_offscreen_resources() { offscreen_framebuffer = gfx->create_framebuffer(info); - point_location_buffer = gfx->create_buffer(nullptr, sizeof(prism::float3) * max_point_shadows, false, GFXBufferUsage::Storage); - point_location_map = reinterpret_cast(gfx->get_buffer_contents(point_location_buffer)); + point_location_buffer = gfx->create_buffer(nullptr, sizeof(prism::float4) * max_point_shadows, false, GFXBufferUsage::Storage); + point_location_map = reinterpret_cast(gfx->get_buffer_contents(point_location_buffer)); } diff --git a/engine/shaders/omnishadow.frag.glsl b/engine/shaders/omnishadow.frag.glsl index 61e4d2c..309630b 100644 --- a/engine/shaders/omnishadow.frag.glsl +++ b/engine/shaders/omnishadow.frag.glsl @@ -6,9 +6,9 @@ layout (location = 1) flat in int index; layout (location = 0) out float outFragColor; layout(std430, binding = 2) buffer readonly LightInformation { - vec3 light_locations[max_lights]; + vec4 light_locations[max_lights]; }; void main() { - outFragColor = length(inPos - light_locations[index]); + outFragColor = length(inPos - light_locations[index].xyz); } diff --git a/engine/shaders/rendering.nocompile.glsl b/engine/shaders/rendering.nocompile.glsl index 966ac03..a3a8e2e 100644 --- a/engine/shaders/rendering.nocompile.glsl +++ b/engine/shaders/rendering.nocompile.glsl @@ -269,8 +269,6 @@ float pcss_point(const vec3 shadowCoords, const int index, float light_size_uv) #endif -int last_point_light = 0; - ComputedLightInformation calculate_point(Light light) { ComputedLightInformation light_info; light_info.direction = normalize(light.positionType.xyz - in_frag_pos); @@ -282,16 +280,16 @@ ComputedLightInformation calculate_point(Light light) { #ifdef POINT_SHADOWS_SUPPORTED if(light.shadowsEnable.x == 1.0) { #ifdef SHADOW_FILTER_NONE - const float sampledDist = texture(point_shadow, vec4(lightVec, last_point_light++)).r; + const float sampledDist = texture(point_shadow, vec4(lightVec, int(light.shadowsEnable.z))).r; const float dist = length(lightVec); shadow = (dist <= sampledDist + 0.05) ? 1.0 : 0.0; #endif #ifdef SHADOW_FILTER_PCF - shadow = pcf_point(lightVec, last_point_light++, 1.0); + shadow = pcf_point(lightVec, int(light.shadowsEnable.z), 1.0); #endif #ifdef SHADOW_FILTER_PCSS - shadow = pcss_point(lightVec, last_point_light++, light.shadowsEnable.y); + shadow = pcss_point(lightVec, int(light.shadowsEnable.z), light.shadowsEnable.y); #endif } #endif diff --git a/engine/shaders/shadow.vert.nocompile.glsl b/engine/shaders/shadow.vert.nocompile.glsl index 7b300fa..25ecb7a 100644 --- a/engine/shaders/shadow.vert.nocompile.glsl +++ b/engine/shaders/shadow.vert.nocompile.glsl @@ -21,7 +21,7 @@ layout(std430, binding = 14) buffer readonly BoneInformation { #endif layout(std430, binding = 2) buffer readonly LightInformation { - vec3 light_locations[max_lights]; + vec4 light_locations[max_lights]; }; void main() { @@ -36,7 +36,7 @@ void main() { gl_Position = mvp * BoneTransform * vec4(inPosition, 1.0); outPos = vec3(model * vec4(inPosition, 1.0)); #else - gl_Position = mvp * vec4(inPosition, 1.0); + gl_Position = mvp * vec4(inPosition, 1.0); outPos = vec3(model * vec4(inPosition, 1.0)); #endif index = gl_BaseInstance;