marcelb / GodotSSRWater

Godot SSR Shader that also supports transparency and fake refraction
MIT License
48 stars 4 forks source link

Proposal for screen limits fading #2

Closed farfalk closed 2 months ago

farfalk commented 10 months ago

Hi, thank you very much for your work! I'm using your ssr code in a project of mine and works quite well. I've got a proposal for a simple fading effect to reduce the abrupt interruption of the SSR near the screen limits. Here it comes:

vec3 get_ssr_color(vec3 surface_view_position, vec3 normal_view_space, vec3 view_view_space, mat4 proj_m, mat4 inv_proj_m)
{
    vec3 current_position_view_space = surface_view_position;
    vec3 view_direction_view_space = view_view_space * -1.0;
    vec3 reflect_vector_view_space = normalize(reflect(view_direction_view_space.xyz, normal_view_space.xyz));
    vec2 current_screen_position = vec2(0.0);

    vec3 resulting_color = vec3(0.0);
    for(float travel=0.0; resulting_color.x <= 0.0 && travel < ssr_max_travel; travel = travel + ssr_resolution)
    {
        current_position_view_space += reflect_vector_view_space * ssr_resolution;
        current_screen_position = get_uv_from_view_position(current_position_view_space, proj_m);

        float depth_texture_probe_raw = texture(DEPTH_TEXTURE, current_screen_position).x;
        //float corrected_depth = vertex.z + (proj_m[3][2] / (depth_texture_probe_raw + proj_m[2][2]));
        vec3 depth_texture_probe_view_position = get_view_position_from_uv(current_screen_position, depth_texture_probe_raw, inv_proj_m);

        float depth_diff = depth_texture_probe_view_position.z - current_position_view_space.z;

        // inspired by https://imanolfotia.com/blog/1
        vec2 centered_screen_coords = smoothstep(0.2, 0.6, abs(vec2(0.5, 0.5) - current_screen_position.xy));
        float screen_edge_factor = clamp(1.0 - (centered_screen_coords.x + centered_screen_coords.y), 0.0, 1.0);
        vec3 resulting_color_0 = texture(SCREEN_TEXTURE, current_screen_position).rgb * screen_edge_factor;
        resulting_color = (depth_diff >= 0.0 && depth_diff < ssr_max_diff) ? resulting_color_0 : vec3(0.0); 
    }
    return resulting_color;
}

[...]

vec3 ssr_color = get_ssr_color(surface_view_position, NORMAL, VIEW, PROJECTION_MATRIX, INV_PROJECTION_MATRIX);
vec3 water_color = depth_color+ssr_mix_strength*ssr_color;

I hope it will be helpful. I'm also working on introducing some jittering linked to surface roughness, will update in case.

Thank you again

marcelb commented 8 months ago

Looks nice! Sorry, I was very busy the last months. I also started working on it recently. My next step is to find a good way to create a smooth overwater/underwater transition. Also there might be Stencil Buffers coming to godot soon, which could also improve everything a lot.

marcelb commented 2 months ago

We also have a PR here, proposing something very similar: https://github.com/marcelb/GodotSSRWater/pull/3

Going to get that in.

farfalk commented 2 months ago

Closing this in favour of the new proposals and PRs.

Unfortunately I had to disable and remove this kind of SSR in my project because it tanked fps with very little visual impact (also, sometimes it unfortunately just didn't look good enough with objects not touching the water surface, with lots of artifacts) so I haven't got any updates on the jittering stuff. Sorry!

Thanks again