Skip to content

Instantly share code, notes, and snippets.

@t-karcher
Last active August 24, 2023 15:08
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save t-karcher/4e78645021bc43a6ce377d9a18c2b1f5 to your computer and use it in GitHub Desktop.
Save t-karcher/4e78645021bc43a6ce377d9a18c2b1f5 to your computer and use it in GitHub Desktop.
Godot shader bending a flat 2d world (e.g. a platformer) to a tiny planet.
shader_type canvas_item;
uniform sampler2D screen_texture : hint_screen_texture, filter_nearest;
uniform float radius = 3.0;
void fragment() {
vec2 uv = SCREEN_UV;
uv.y = 1.0 - uv.y; // seems like the origin changed in Godot 4.
vec2 surface = vec2(0.5, 0.2);
vec2 center = surface - vec2(0, radius);
float base = length(uv - center);
float height = base - radius;
float xdiff = (uv.x - surface.x) / base * height;
uv = clamp(vec2 (uv.x - xdiff, surface.y + height), vec2(0.0, 0.0), vec2(1.0, 1.0));
uv.y = 1.0 - uv.y; // flip back after all calculations
COLOR.rgb = textureLod(screen_texture, uv, 0.0).rgb;
}
@t-karcher
Copy link
Author

Before:
image

After:
image

@caburet
Copy link

caburet commented Feb 19, 2021

Very nice! It just what i need!

@thatsmaik
Copy link

Thanks a lot for sharing this. It's weird - in Godot 4.0 this Shader bends the world but with the center on the top, so the opposite direction then your distortion in the screenshot. Any idea why?

@t-karcher
Copy link
Author

t-karcher commented Aug 19, 2023

Weird indeed. It seems like the origin of SCREEN_UV changed between Godot 3 and 4, but I couldn't find any hint regarding this. I added a quick fix now.

@thatsmaik
Copy link

Thanks so much for the quick reply and the quick fix. Works! I was assuming the same but couldn't find any hint regarding the origin change too but I don't know much about shaders so I couldn't get it to work on my own. The solution is shockingly simple haha.

May I ask how your scene setup looks like? I currently use a ColorRect for the shader code in combination with a CanvasLayer parent. But this approach gives visible bending seems in the corners and it distorts everything in an uncomfortable way when the camera moves along the Y-axis. I am wondering - is this just the nature of the shader code or is it my setup? Looking at your screenshot it looks like you have a different approach.

@t-karcher
Copy link
Author

Regarding the project setup / implementation: I never actually used this shader in an own project, but only wrote it as an answer for a request in some forum years ago. The screenshot you see above is taken from https://github.com/godotengine/godot-demo-projects/tree/master/2d/screen_space_shaders , where I just added the curved fragment shader in my local copy. So I cannot say much about practical implementation issues.

Regarding the origin change - let's ask an expert. :-) @Calinou: Do you know why I had to flip the Y-axis of SCREEN_UV for this shader to work in Godot 4? (The code was working perfectly fine without lines 8 and 15 in Godot 3.x)

@Calinou
Copy link

Calinou commented Aug 23, 2023

@Calinou: Do you know why I had to flip the Y-axis of SCREEN_UV for this shader to work in Godot 4? (The code was working perfectly fine without lines 8 and 15 in Godot 3.x)

Godot 3.x used flipped viewports (it followed OpenGL convention), but this is no longer required in Godot 4 as we could break compatibility to make it the right way around.

@t-karcher
Copy link
Author

t-karcher commented Aug 23, 2023

Thanks for the confirmation/clarification! Since neither Maik nor myself were able to find this info, I just proposed to add it to the official migration tutorial: godotengine/godot-docs#7833

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment