• Shaders
  • Trouble with reflective shader [2D]

Hello,

I come forward with a bit of a matter when trying to implement a reflective shader into a top down game. Disclaimer : I am quite new to using godot and game making, so forgive me if I am not really clear, and let me know if I can add some info to help you help me.

So I have a scene with a Camera2D attached to a KinematicBody2D (the player) and a tileMap. The tilemap size is bigger than the size of the root viewport (defined as 400 x 200 px in the project parameters), so when the player move around the tilemap, I change the position of the Camera2D so that it is always centered on the player.

Now I tried to implement a little pool of water with a reflective shader. I followed this tutorial :

When the player is on top of the water pool, the shader is working properly, as seen in this picture :

However when I try to go under the pool of water, the shader is not working properly :

From my understanding, what is happening is that the shader isn't able anymore to make its calculation based on the texture of the viewport, because the viewport doesn't anymore display what the shader needs : the portion of the picture above the pool of water is truncated because the camera moved down with the player.

Now I dont have any idea what I could do to resolve this issue... Any pointers would be gladly accepted.

Sincerly, Sleeper

Can you post the shader code?

My guess is that its an issue where the UV is outside of the 0-1 range, and so that is leading to the pixels stretching. A simple, though perhaps not visually correct, solution would be to clamp the UV used for the reflection to the 0-1 range so it cannot stretch pixels.

7 days later

Sure, here is the shader code

shader_type canvas_item;

void fragment() {
	float uv_height = SCREEN_PIXEL_SIZE.y / TEXTURE_PIXEL_SIZE.y*2.0;
	vec2 reflected_screenuv = vec2(SCREEN_UV.x,SCREEN_UV.y + uv_height * UV.y*2.0);
	COLOR = texture(SCREEN_TEXTURE,reflected_screenuv);
	}

Hmm, my guess is that adding uv_height may be causing the issue when near the edges of the screen, as it would go over the 0-1 range. Maybe try clamping the reflected_screenuv variable and see if that fixes it (though it will not reflect things above the viewport):

shader_type canvas_item;

void fragment() {
	float uv_height = SCREEN_PIXEL_SIZE.y / TEXTURE_PIXEL_SIZE.y * 2.0
	vec2 reflected_screenuv = vec2(SCREEN_UV.x, SCREEN_UV.y + uv_height * UV.y*2.0);
	
	// Clamp to the proper UV range
	if (reflected_screenuv.x > 1) {
		reflected_screenuv.x = 1;
	} else if (reflected_screenuv.x < 0) {
		reflected_screenuv.x = 0;
	}
	if (reflected_screenuv.y > 1) {
		reflected_screenuv.y = 1;
	} else if (reflected_screenuv.y < 0) {
		reflected_screenuv.y = 0;
	}
	
	COLOR = texture(SCREEN_TEXTURE, reflected_screenuv);
}

Thank you for your answer. I implemented your solution, but it still yields the same result. As you said, the shader is not able to reflect things above the viewport, so I think this is my problem here. Do you have any idea about it ?

In ye olden days, one way to do planar reflections was to simply hold a copy of the whole scene and flip it...

@sleeper said: Thank you for your answer. I implemented your solution, but it still yields the same result. As you said, the shader is not able to reflect things above the viewport, so I think this is my problem here. Do you have any idea about it ?

Hmm, I'm not sure then. I would have thought that would have solved the issue, but I guess it was something else...

Unfortunately, my shader experience is rather slim. I will keep thinking about it though, and if I think of a potential solution, I'll let you know.

@Megalomaniak said: In ye olden days, one way to do planar reflections was to simply hold a copy of the whole scene and flip it...

Yeah, that's actually what I was aiming for. Would you have any idea how I could do that in godot ?

@TwistedTwigleg said:

@sleeper said: Thank you for your answer. I implemented your solution, but it still yields the same result. As you said, the shader is not able to reflect things above the viewport, so I think this is my problem here. Do you have any idea about it ?

Hmm, I'm not sure then. I would have thought that would have solved the issue, but I guess it was something else...

Unfortunately, my shader experience is rather slim. I will keep thinking about it though, and if I think of a potential solution, I'll let you know.

Okay well, I appreciate your effort. Thanks for trying to help.

Write a Reply...