Open morr opened 5 months ago
Updated the description of the issue, removed unnecessary details.
Known issue. The problem is likely due to a bug in SDF. Thanks for putting all details.
@morr I would try something like this for your game.
1) Change SDF to min operator instead of round merge. That would make walls completely black as no light can go into negative space:
@compute @workgroup_size(8, 8, 1)
fn main(@builtin(global_invocation_id) invocation_id: vec3<u32>) {
let texel_pos = vec2<i32>(invocation_id.xy);
let dims = textureDimensions(sdf_out);
let uv = (vec2<f32>(texel_pos) + 0.5) / vec2<f32>(dims);
let world_pose = sdf_uv_to_world(uv,
camera_params.inverse_view_proj,
camera_params.sdf_scale);
let r = 1.2;
var sdf_merged = sdf_aabb_occluder(world_pose.xy, 0);
for (var i: i32 = 1; i < i32(light_occluder_buffer.count); i++) {
sdf_merged = min(sdf_merged, sdf_aabb_occluder(world_pose.xy, i));
}
textureStore(sdf_out, texel_pos, vec4<f32>(sdf_merged, 0.0, 0.0, 0.0));
}
2) To fix zero irradiance for walls, try to sample it from neighbor pixels (in gi_post_processing.wgsl
):
@fragment
fn fragment(in: VertexOutput) -> @location(0) vec4<f32> {
let position = in.position;
let uv = coords_to_viewport_uv(position.xy, view.viewport);
// Read diffuse textures.
let in_floor_diffuse = textureSample(in_floor_texture, in_floor_sampler, uv);
let in_walls_diffuse = textureSample(in_walls_texture, in_walls_sampler, uv);
let in_objects_diffuse = textureSample(in_objects_texture, in_objects_sampler, uv);
let in_irradiance = textureSample(in_irradiance_texture, in_irradiance_texture_sampler, uv).xyz;
// Calculate object irradiance.
// TODO: parametrize this filter.
// TODO: we don't really need to do this per pixel.
var object_irradiance = in_irradiance;
var walls_irradiance = in_irradiance;
var k_size = 3;
var k_width = 28;
for (var i = -k_size; i <= k_size; i++) {
for (var j = -k_size; j < 0; j++) {
let offset = vec2<f32>(f32(i * k_width), f32(j * k_width));
let irradiance_uv = coords_to_viewport_uv(position.xy - offset, view.viewport);
let sample_irradiance = textureSample(
in_irradiance_texture,
in_irradiance_texture_sampler,
irradiance_uv
).xyz;
// TODO: Might also need a visibility check here.
if any(irradiance_uv < vec2<f32>(0.0)) || any(irradiance_uv > vec2<f32>(1.0)) {
continue;
}
object_irradiance = max(object_irradiance, sample_irradiance);
}
}
k_size = 4;
k_width = 16;
for (var i = -k_size; i <= k_size; i++) {
for (var j = -k_size; j < k_size; j++) {
let offset = vec2<f32>(f32(i * k_width), f32(j * k_width));
let irradiance_uv = coords_to_viewport_uv(position.xy - offset, view.viewport);
let sample_irradiance = textureSample(
in_irradiance_texture,
in_irradiance_texture_sampler,
irradiance_uv
).xyz;
// TODO: Might also need a visibility check here.
if any(irradiance_uv < vec2<f32>(0.0)) || any(irradiance_uv > vec2<f32>(1.0)) {
continue;
}
walls_irradiance += sample_irradiance;
}
}
walls_irradiance /= 16.0;
let floor_irradiance_srgb = lin_to_srgb(in_irradiance);
let objects_irradiance_srgb = lin_to_srgb(object_irradiance);
let final_floor = in_floor_diffuse.xyz * floor_irradiance_srgb;
let final_walls = in_walls_diffuse.xyz * walls_irradiance;
let final_objects = in_objects_diffuse.xyz * objects_irradiance_srgb;
var out = vec4<f32>(final_floor, 1.0);
out = vec4<f32>(mix(out.xyz, final_walls.xyz, in_walls_diffuse.w), 1.0);
out = vec4<f32>(mix(out.xyz, final_objects.xyz, in_objects_diffuse.w), 1.0);
return out;
}
It's very hacky, but might work for you. This is what I've got:
@zaycev thanks for quick response! The demo looks better with such fixes.
In my app I started getting black screen after changed shaders code, but this looks like my own fault, probably I did set up something incorrectly.
In my app I started getting black screen after changed shaders code, but this looks like my own fault, probably I did set up something incorrectly.
Naga should tell you in the log if you have syntax error in shaders.
@morr were you able to fix this? I am experiencing the same issue.
@csandven the krypta example now supports zooming and I can't reproduce this issue - can you check if it's still available with 0.8.0 or 0.8.1?
Hi!
While zooming scene out the screen is being "split" into a "grid" and around each "grid cell" I observe black areas. The more I zoom out the larger black areas become.
Any ideas how to fix this?
Details provided below:
Here it is illustrated in
krypta
demo app (I added zoom to fork https://github.com/zaycev/bevy-magic-light-2d/compare/main...morr:bevy-magic-light-2d:zoom-out-issue)And this is how the issue looks in my bevy app where I try very large zoom.