Archived
1
Fork 0

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
This commit is contained in:
Joshua Goins 2022-02-07 18:36:23 -05:00
parent 2f30a9e18e
commit 78078e92cd
6 changed files with 24 additions and 21 deletions

View file

@ -45,7 +45,7 @@ private:
GFXFramebuffer* offscreen_framebuffer = nullptr; GFXFramebuffer* offscreen_framebuffer = nullptr;
GFXBuffer* point_location_buffer = nullptr; GFXBuffer* point_location_buffer = nullptr;
prism::float3* point_location_map = nullptr; prism::float4* point_location_map = nullptr;
// sun // sun
GFXPipeline* static_sun_pipeline = nullptr; GFXPipeline* static_sun_pipeline = nullptr;

View file

@ -372,7 +372,8 @@ void renderer::render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Obj
sceneInfo.camPos = scene.get<Transform>(camera_object).get_world_position(); sceneInfo.camPos = scene.get<Transform>(camera_object).get_world_position();
sceneInfo.camPos.w = 2.0f * camera.near * std::tan(camera.fov * 0.5f) * (static_cast<float>(extent.width) / static_cast<float>(extent.height)); sceneInfo.camPos.w = 2.0f * camera.near * std::tan(camera.fov * 0.5f) * (static_cast<float>(extent.width) / static_cast<float>(extent.height));
sceneInfo.vp = camera.perspective * camera.view; sceneInfo.vp = camera.perspective * camera.view;
int last_point_light = 0;
for(const auto& [obj, light] : scene.get_all<Light>()) { for(const auto& [obj, light] : scene.get_all<Light>()) {
SceneLight sl; SceneLight sl;
sl.positionType = prism::float4(scene.get<Transform>(obj).get_world_position(), static_cast<float>(light.type)); sl.positionType = prism::float4(scene.get<Transform>(obj).get_world_position(), static_cast<float>(light.type));
@ -381,8 +382,12 @@ void renderer::render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Obj
sl.directionPower = prism::float4(-front, light.power); sl.directionPower = prism::float4(-front, light.power);
sl.colorSize = prism::float4(utility::from_srgb_to_linear(light.color), radians(light.spot_size)); 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; sceneInfo.lights[sceneInfo.numLights++] = sl;
} }

View file

@ -141,7 +141,7 @@ void ShadowPass::render_meshes(GFXCommandBuffer* command_buffer, Scene& scene, c
break; 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_push_constant(&pc, sizeof(PushConstant));
command_buffer->set_depth_bias(1.25f, 0.00f, 1.75f); 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; 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_push_constant(&pc, sizeof(PushConstant));
@ -266,7 +266,9 @@ void ShadowPass::render_point(GFXCommandBuffer* command_buffer, Scene& scene, Ob
return; return;
if(scene.point_light_dirty[last_point_light] || light.use_dynamic_shadows) { if(scene.point_light_dirty[last_point_light] || light.use_dynamic_shadows) {
*(point_location_map + last_point_light) = scene.get<Transform>(light_object).get_world_position(); const prism::float3 lightPos = scene.get<Transform>(light_object).get_world_position();
(point_location_map + last_point_light)->xyz = lightPos;
for(int face = 0; face < 6; face++) { for(int face = 0; face < 6; face++) {
GFXRenderPassBeginInfo info = {}; GFXRenderPassBeginInfo info = {};
@ -281,9 +283,7 @@ void ShadowPass::render_point(GFXCommandBuffer* command_buffer, Scene& scene, Ob
viewport.height = render_options.shadow_resolution; viewport.height = render_options.shadow_resolution;
command_buffer->set_viewport(viewport); command_buffer->set_viewport(viewport);
const prism::float3 lightPos = scene.get<Transform>(light_object).get_world_position();
const Matrix4x4 projection = prism::perspective(radians(90.0f), 1.0f, 0.1f, 100.0f); const Matrix4x4 projection = prism::perspective(radians(90.0f), 1.0f, 0.1f, 100.0f);
const Matrix4x4 model = inverse(scene.get<Transform>(light_object).model); const Matrix4x4 model = inverse(scene.get<Transform>(light_object).model);
@ -408,6 +408,6 @@ void ShadowPass::create_offscreen_resources() {
offscreen_framebuffer = gfx->create_framebuffer(info); offscreen_framebuffer = gfx->create_framebuffer(info);
point_location_buffer = gfx->create_buffer(nullptr, sizeof(prism::float3) * max_point_shadows, false, GFXBufferUsage::Storage); point_location_buffer = gfx->create_buffer(nullptr, sizeof(prism::float4) * max_point_shadows, false, GFXBufferUsage::Storage);
point_location_map = reinterpret_cast<prism::float3*>(gfx->get_buffer_contents(point_location_buffer)); point_location_map = reinterpret_cast<prism::float4*>(gfx->get_buffer_contents(point_location_buffer));
} }

View file

@ -6,9 +6,9 @@ layout (location = 1) flat in int index;
layout (location = 0) out float outFragColor; layout (location = 0) out float outFragColor;
layout(std430, binding = 2) buffer readonly LightInformation { layout(std430, binding = 2) buffer readonly LightInformation {
vec3 light_locations[max_lights]; vec4 light_locations[max_lights];
}; };
void main() { void main() {
outFragColor = length(inPos - light_locations[index]); outFragColor = length(inPos - light_locations[index].xyz);
} }

View file

@ -269,8 +269,6 @@ float pcss_point(const vec3 shadowCoords, const int index, float light_size_uv)
#endif #endif
int last_point_light = 0;
ComputedLightInformation calculate_point(Light light) { ComputedLightInformation calculate_point(Light light) {
ComputedLightInformation light_info; ComputedLightInformation light_info;
light_info.direction = normalize(light.positionType.xyz - in_frag_pos); light_info.direction = normalize(light.positionType.xyz - in_frag_pos);
@ -282,16 +280,16 @@ ComputedLightInformation calculate_point(Light light) {
#ifdef POINT_SHADOWS_SUPPORTED #ifdef POINT_SHADOWS_SUPPORTED
if(light.shadowsEnable.x == 1.0) { if(light.shadowsEnable.x == 1.0) {
#ifdef SHADOW_FILTER_NONE #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); const float dist = length(lightVec);
shadow = (dist <= sampledDist + 0.05) ? 1.0 : 0.0; shadow = (dist <= sampledDist + 0.05) ? 1.0 : 0.0;
#endif #endif
#ifdef SHADOW_FILTER_PCF #ifdef SHADOW_FILTER_PCF
shadow = pcf_point(lightVec, last_point_light++, 1.0); shadow = pcf_point(lightVec, int(light.shadowsEnable.z), 1.0);
#endif #endif
#ifdef SHADOW_FILTER_PCSS #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
} }
#endif #endif

View file

@ -21,7 +21,7 @@ layout(std430, binding = 14) buffer readonly BoneInformation {
#endif #endif
layout(std430, binding = 2) buffer readonly LightInformation { layout(std430, binding = 2) buffer readonly LightInformation {
vec3 light_locations[max_lights]; vec4 light_locations[max_lights];
}; };
void main() { void main() {
@ -36,7 +36,7 @@ void main() {
gl_Position = mvp * BoneTransform * vec4(inPosition, 1.0); gl_Position = mvp * BoneTransform * vec4(inPosition, 1.0);
outPos = vec3(model * vec4(inPosition, 1.0)); outPos = vec3(model * vec4(inPosition, 1.0));
#else #else
gl_Position = mvp * vec4(inPosition, 1.0); gl_Position = mvp * vec4(inPosition, 1.0);
outPos = vec3(model * vec4(inPosition, 1.0)); outPos = vec3(model * vec4(inPosition, 1.0));
#endif #endif
index = gl_BaseInstance; index = gl_BaseInstance;