Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Signed Distance Fields for 2D shaders #43886

Merged
merged 1 commit into from
Nov 26, 2020

Conversation

reduz
Copy link
Member

@reduz reduz commented Nov 26, 2020

SDF Support

  • 2D Occluder Polygons now have the option to become geometry to generate the SDF
  • New functions added to 2D shaders:
vec2 screen_uv_to_sdf(vec2 screen_uv);
vec2 sdf_to_screen_uv(vec2 sdf_pos);
float texture_sdf(vec2 sdf_pos);
vec2 texture_sdf_normal(vec2 sdf_pos);

SDF operates in screen-relative global coordinates (pre-canvas transform), so its easy to measure distances in your shaders, as they use the same units as your game.

Example:

The following shader allows to make long drop shadows.

image

Code:

shader_type canvas_item;
render_mode unshaded;

uniform vec4 color : hint_color;
uniform float angle : hint_range(0,360);
uniform float len : hint_range(0,1000) = 300;
uniform float fade_margin : hint_range(0,100) = 5;

void fragment() {
	
	float ang_rad = angle * 3.1416 / 360.0;
	vec2 dir = vec2(sin(ang_rad),cos(ang_rad));
	float max_dist = len;
	vec2 at = screen_uv_to_sdf(SCREEN_UV);
	float accum = 0.0;
	
	while(accum < max_dist) {
	    float d = texture_sdf(at);
	    accum+=d;
	    if (d < 0.01) {
	        break;
	    }
	    at += d * dir;
	}
	float alpha = 1.0-min(1.0,accum/max_dist);
	if (accum < fade_margin) {
		alpha *= max(0.0,accum / fade_margin);
	}
	
	COLOR = vec4(color.rgb,alpha * color.a);
}

TODO

In the future it may be possible to optionally toggle a canvaslayer for sdf generation, so its not only limited to occluder polygons, but this will most likely have an increased cost, given rendering the screen oversized (like 1.x to 2.x the margins) is required to have useful SDFs (and this also requires more shader variants compiled). Most likely post 4.0 material.

@starry-abyss
Copy link
Contributor

Can this implementation also be used to smooth edges of vector shapes?

@akien-mga akien-mga merged commit 0a54dcb into godotengine:master Nov 26, 2020
@reduz
Copy link
Member Author

reduz commented Nov 26, 2020

@starry-abyss no, while it is possible to convert vector shapes to SDF to some extent (and I would like to work on that at some point), that is something entirely different.

@akien-mga
Copy link
Member

Thanks!

@dreamsComeTrue
Copy link
Contributor

Will there be any documentation/sample/demo in the Godot's docs explaining SDFs for newbies, and also - their potential use cases?

@clayjohn
Copy link
Member

clayjohn commented Dec 2, 2020

@dreamsComeTrue Yes, we will work on docs and demos once the API is finalized. Expect them close to release.

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

Successfully merging this pull request may close these issues.

5 participants