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;
|
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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Reference in a new issue