Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Camera zooming issues #57

Open
morr opened this issue Apr 13, 2024 · 7 comments
Open

Camera zooming issues #57

morr opened this issue Apr 13, 2024 · 7 comments

Comments

@morr
Copy link

morr commented Apr 13, 2024

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 main...morr:bevy-magic-light-2d:zoom-out-issue)
image

And this is how the issue looks in my bevy app where I try very large zoom.
image
image
image
image

@morr
Copy link
Author

morr commented Apr 13, 2024

Updated the description of the issue, removed unnecessary details.

@zaycev
Copy link
Owner

zaycev commented Apr 14, 2024

Known issue. The problem is likely due to a bug in SDF. Thanks for putting all details.

@zaycev
Copy link
Owner

zaycev commented Apr 14, 2024

@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));
}
  1. 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:

Screenshot 2024-04-13 at 10 05 37 PM Screenshot 2024-04-13 at 10 04 48 PM

@morr
Copy link
Author

morr commented Apr 14, 2024

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

@zaycev
Copy link
Owner

zaycev commented Apr 14, 2024

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.

@csandven
Copy link
Contributor

@morr were you able to fix this? I am experiencing the same issue.

@tigerplush
Copy link
Collaborator

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants