How to create a reflection shader?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Diet Estus

I am trying to create a reflection shader attached to a ColorRect that reflects the portion of the screen immediately above it.

Here is a diagram showing the intended behavior:

enter image description here

What I have managed to achieve, however, looks like this:

enter image description here

I can only see the top of my triangle in the reflection.

In other words, I am not reflecting across the axis formed by the top of the ColorRect.

Here is my shader:

shader_type canvas_item;
render_mode unshaded;

void fragment(){

    vec2 uv = SCREEN_UV;
    float y = 1.0 - uv.y;

    COLOR = vec4(texture(SCREEN_TEXTURE, vec2(uv.x, y))); 
} 

How can I modify this shader to always reflect the screen across the top of the Color Rect?

:bust_in_silhouette: Reply From: ArdaE

With 1.0 - uv.y, you get something that’s mirrored at the center of your screen. So what you see in your ColorRect depends on where the triangle is. Change 1.0 to reflect at different locations (e.g. 0.8 - uv.y). You can then pass this as a parameter if needed.

Is there a way to calculate the correct value from the position of the ColorRect or some other way? If I use this effect a lot, I’d prefer to avoid trial and error.

Diet Estus | 2018-09-23 02:52

Yes. SCREEN_UV ranges from 0.0 at the bottom of your viewport to 1.0 at the top of it. So you can move your reflection point around from the bottom of the viewport using -uv.y to the top using -uv.y + 2. So simply multiply the ratio of the top Y of your ColorRect (measured from the bottom) to the height of your viewport by 2, and that should give the constant you need to add to -uv.y.

ArdaE | 2018-09-23 03:17

So 2.0 * TopY / ViewportHeight - uv.y, where TopY is the top Y coordinate of your ColorRect measured from the bottom of the viewport.

ArdaE | 2018-09-23 03:22