Fullscreen Raymarching with Depth Check
For Godot 4.3.
Modified from this fullscreen raymarching shader.
Allows raymarched objects to intersect with world objects.
Follow this guide to create a fullscreen quad for the effect.
Shader code
shader_type spatial;
render_mode unshaded;
const int MAX_STEPS = 300;
const float MAX_DISTANCE = 1000.0;
const float MIN_DISTANCE = 0.001;
uniform sampler2D DEPTH_TEXTURE : source_color, hint_depth_texture;
void vertex() {
POSITION = vec4(VERTEX.xy, 1.0, 1.0);
}
float sdSphere (vec3 p, vec3 centrum, float radius) {
return length(centrum-p) - radius;
}
// infinte repetitions
// adapted from https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm
vec3 opRep(vec3 p, vec3 c) {
vec3 q = mod(p+0.5*c,c)-0.5*c;
return q;
}
float get_distance(vec3 p) {
p = opRep(p, vec3(3)); // uncomment for repeating spheres
return sdSphere(p, vec3(0), 1.0);
}
vec3 get_normal(vec3 p) {
vec2 e = vec2(1e-3, 0);
vec3 n = get_distance(p) - vec3(
get_distance(p - e.xyy),
get_distance(p - e.yxy),
get_distance(p - e.yyx)
);
return normalize(n);
}
vec4 raymarch(vec3 ray_origin, vec3 ray_dir, float depth) {
float t = 0.0;
vec3 p = ray_origin;
for (int i = 0; i < MAX_STEPS; i++)
{
float d = get_distance(p);
t += d;
if (t > MAX_DISTANCE || t >= depth)
break;
p += d * ray_dir;
if (abs(d) < MIN_DISTANCE)
return vec4(get_normal(p), 1);
}
//return vec4(float(i) * 0.01); // uncomment for simple glow effect
return vec4(0.0);
}
void fragment() {
float depth = texture(DEPTH_TEXTURE, SCREEN_UV).x;
vec3 ndc = vec3(SCREEN_UV * 2.0 - 1.0, depth);
vec4 view = INV_PROJECTION_MATRIX * vec4(ndc, 1.0);
view.xyz /= view.w;
float linear_depth = -view.z;
vec3 weird_uv = vec3(SCREEN_UV * 2.0 - 1.0, 0.0);
vec4 camera = INV_VIEW_MATRIX * INV_PROJECTION_MATRIX * vec4(weird_uv, 1);
vec3 ray_origin = INV_VIEW_MATRIX[3].xyz;
vec3 ray_dir = normalize(camera.xyz);
vec4 col = raymarch(ray_origin, ray_dir, linear_depth);
ALPHA = col.a;
ALBEDO = col.rgb;
}
Not sure if it’s my setup, but there is a slight offset in perspective, mostly noticeable when translating the camera. SDF and polygon geometry will slightly shift away from eachother. Any ideas?