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;
GFXBuffer* point_location_buffer = nullptr;
prism::float3* point_location_map = nullptr;
prism::float4* point_location_map = nullptr;
// sun
GFXPipeline* static_sun_pipeline = nullptr;

View file

@ -373,6 +373,7 @@ void renderer::render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Obj
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;
int last_point_light = 0;
for(const auto& [obj, light] : scene.get_all<Light>()) {
SceneLight sl;
sl.positionType = prism::float4(scene.get<Transform>(obj).get_world_position(), static_cast<float>(light.type));
@ -381,7 +382,11 @@ 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;
}

View file

@ -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<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++) {
GFXRenderPassBeginInfo info = {};
@ -282,8 +284,6 @@ void ShadowPass::render_point(GFXCommandBuffer* command_buffer, Scene& scene, Ob
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 model = inverse(scene.get<Transform>(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<prism::float3*>(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<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(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);
}

View file

@ -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

View file

@ -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() {