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:
parent
2f30a9e18e
commit
78078e92cd
6 changed files with 24 additions and 21 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() {
|
||||
|
|
Reference in a new issue