A Shader which simply flips whatever is above it on the Y axis without following the screen

Godot Version

v4.2.2.stable.mono.official [15073afe3]

Question

To start off with it, I’m not very good with Shaders yet, I’m still learning, but I’m trying to figure out how to write a shader which I put on a Polygon2D, which should simply flip everything directly above it on the Y axis. This is what I got so far:

shader_type canvas_item;

uniform sampler2D screen : hint_screen_texture, filter_nearest;

void fragment() {
	vec4 ref = texture(screen, vec2(SCREEN_UV.x, 1.0 - SCREEN_UV.y + 0.3));
	COLOR = ref;
}

However, there’s one big issue with this. As I understand it, SCREEN_UV, as the name suggests, uses the viewport as reference. This causes the illusion to completely fall apart as soon as the camera moves up or down for any reason.

How can I modify this shader so it “ignores” the viewport moving up and down, and simply reflect CanvasItems?

you sure the node this shader applied to is following the camera?

The node this shader is attached to is not following the camera, that’s the whole point. This is attached to a simple Polygon2D which sits just under the player.

ok, i tested myself with movement up down, left right with camera on characterbody2d on water reflection shader. it kinda doesnt work only if i removed BackBufferCopy Node before the node with shader.

image

I’ll provide a bit more context to the post. I’m working on a 2D beat-em-up / platformer game, and this is supposed to be a somewhat simple but more flexible reflection method I can fine-tune. However, as it stands right now, it’s behavior is not correct, see the following example:

i suggest to check this video if you want a real working water reflection:

my code now has this line:

	float uv_height= SCREEN_PIXEL_SIZE.y/TEXTURE_PIXEL_SIZE.y;
	vec2 reflected_screen_uv = vec2(SCREEN_UV.x -(distortion*intensity*y_zoom*gradient.r), SCREEN_UV.y - uv_height * UV.y * y_zoom * scale.y * 2.0);

it actually calculate the uv_height, instead of just SCREEN_UV

which i see lacking from your code, hence results in weird behaviour when moving around

The video linked and the code provided does indeed seem to work with a Sprite2D, but does not work when using a Polygon2D, which is the main reason I needed a custom solution.

Using an empty AtlasTexture resource seem to do the trick, marking the last post as a solution.

well yes, i use texture masking so it can look any way i like instead of just rectangle shape