#I need help with edge detection within my shader

1 messages · Page 1 of 1 (latest)

wild nacelle
#

I wanna make it so that any object which intersects with my water plane causes a foam or in this case white cricle on the surface of water.
Now i looked at some tutorials such as this one (https://youtu.be/7L6ZUYj1hs8?t=677) but its not explained whats actually happening as well as it being outdated, please give some advice or maybe a better tutorial

In this Godot 4 tutorial, you will learn how to create a high quality water shader script from scratch and apply it to a single plane mesh.

I go through basic shader setup, albedo, roughness, and metallic settings, and normal map setup and animation.

I also cover more advanced water shader features like vertex noise displacement, depth color, ...

▶ Play video
atomic glen
#

My favorite tutorial for this is an old unity one that walks you through all the steps: https://ameye.dev/notes/stylized-water-shader/

#

The shadergraph code shouldn't be too hard to mentally translate to visualshaders or text shaders. Or you can read this one for an understanding of what each step is doing, then look at godot shader code again

wild nacelle
atomic glen
atomic glen
#

In 4.3, they changed how the depth buffer is stored - now it's stored in reverse order, with near and far planes being flipped. It's called "reverse-z" because the z value is depth in some built-in variables

#

A lot of older shaders which sample the depth buffer, including water shaders that use shore detection, are affected

wild nacelle
#

nope im not affected

atomic glen
#

So if the 4.0, 4.1, or 4.2 tutorial you followed has edges in the video and not in your shader, it might need a fix from that link.

#

Cool

wild nacelle
#

but still i have o idea how to detect edges

atomic glen
#

So you have a working shoreline edge shader, you're just curious how it actually works?

wild nacelle
atomic glen
#

I see

wild nacelle
#

dont particularly care how it works as long as i can make it work

atomic glen
#

Sorry, I don't have any good godot-specific tutorials for water

wild nacelle
#

damn

atomic glen
#

Yeah, most of the really good tutorial makers haven't switched over to godot yet

#

Are you following how the shore depth detection actually works, though?

wild nacelle
#

no

#

how does it work

#

i was thinking that i might just fake it by making the depth fade really shallow and overlay it

atomic glen
#

At a very broad level, it's comparing how far from the camera two points are: the water surface, and the thing behind the water. One of these you can sample from the depth texture, and one of them you can construct just by knowing where your water surface is in the world. Then if the distance between them is very small, draw white instead of water color

wild nacelle
#

in godot

atomic glen
wild nacelle
#

example?

atomic glen
#

If a water tutorial has sharp white shoreline waves they are probably this. You'll probably see a depth_texture that gets sampled

wild nacelle
#

i know im already sampling it to make them dissaper when objects are deep

atomic glen
#

your screenshot samples depth, the tutorial you're following has water edges

#

in your case it's probably a second usage of it

#

let me see if i can find a minimal example on godotshaders

wild nacelle
#

like im not sure how to overlay my foam depth without fucking up the normal depth

atomic glen
#

Post the shader you have now and I may be able to take a look at it later

wild nacelle
# atomic glen Post the shader you have now and I may be able to take a look at it later
uniform sampler2D depth_texture : hint_depth_texture;
uniform float depth_distance : hint_range(0.0, 50.0, 1.0) = 0.5;
uniform float transparency : hint_range(0.0, 1.0, 0.1) = 0.5;
uniform sampler2D screen_texture : hint_screen_texture;
uniform vec3 watercolor : source_color;



void fragment() {
float depth_red = textureLod(depth_texture, SCREEN_UV, 0.0).r;
    vec4 world = INV_PROJECTION_MATRIX * vec4(SCREEN_UV * 2.0 - 1.0, depth_red, 1.0);
    world.xyz /= world.w;
    float depth_blend = smoothstep(world.z + depth_distance, world.z, VERTEX.z);
    vec3 screen = textureLod(screen_texture, SCREEN_UV, 0.0).rgb;
    ALBEDO = mix(vec3(depth_blend) * screen, watercolor, transparency);
}
wild nacelle
atomic glen
#

If I check out your code and add in depth I'll try to name things ad add comments

#

IIRC I already have a working water shader with most these features

#

I'll try to get back by tomorrow

wild nacelle
#

thank you

atomic glen
#

It is very confusing and relies on established hacks

#

But once you know what they mean, every water shader starts to look the same

wild nacelle
#

there is also this thing where i can see the vaves trough other vaves from one side

#

but not the other

atomic glen
#

That's some kind of transparency sorting thing

#

Also the fact that you're changing the vertex position might matter. I remember seeing this somewhere before

#

If I remember I'll link it

atomic glen
#
shader_type spatial;

uniform sampler2D depth_texture : hint_depth_texture;
uniform float depth_distance : hint_range(0.0, 50.0, 1.0) = 0.5;
uniform float transparency : hint_range(0.0, 1.0, 0.1) = 0.5;
uniform sampler2D screen_texture : hint_screen_texture;
uniform vec3 watercolor : source_color;

uniform vec3 foam_color : source_color;
uniform float foam_distance : hint_range(0.0, 5.0) = 0.5;

void fragment() {
    float raw_depth = textureLod(depth_texture, SCREEN_UV, 0.0).r;
    vec4 world = INV_PROJECTION_MATRIX * vec4(SCREEN_UV * 2.0 - 1.0, raw_depth, 1.0);
    world.xyz /= world.w;
    
    // linear_depth is the linear depth of the fragment behind the water.
    float linear_depth = world.z;
    // VERTEX.z is the linear depth of the current fragment in the water surface.
    float depth_blend = smoothstep(linear_depth + depth_distance, linear_depth, VERTEX.z);
    
    // Subtract the two values to get the difference in linear distance.
    //float difference = (VERTEX.z - linear_depth);
    // Then divide by the foam distance.
    //float divided = ((difference) / foam_distance);
    // Then clamp to the 0-1 range so you can use it in mix(), and flip the values.
    //float clamped = 1.0 - clamp(divided, 0.0,1.0);
    // All together:
    float foam_blend = 1.0 - clamp(((VERTEX.z - linear_depth) / foam_distance), 0.0, 1.0);
    
    vec3 screen = textureLod(screen_texture, SCREEN_UV, 0.0).rgb;
    
    // This is the color of the water, based on depth.
    vec3 final_color = mix(vec3(depth_blend) * screen, watercolor, transparency);
    
    // This mixes in the shoreline edge foam.
    final_color = mix(final_color,foam_color, foam_blend);
    
    // Output
    ALBEDO = final_color;
}```
#

Best I can do for right now. You can make it look better, less toony, by mixing in some foam noise pattern somewhere along the way

#

I hope this can explain some of the math a bit

wild nacelle
#

unfortunately ill have to postpone it cuz im having depth sorting issues

atomic glen
#

Still the waves showing up behind themselves?