shader_type spatial; uniform bool disable_threshold = false; uniform float threshold = 0.001f; uniform int max_iterations = 300; uniform vec4 colour : source_color; uniform float epsilon = 0.1f; uniform vec3 sphere_pos = vec3(0.2f, -0.2f, -0.1f); uniform vec3 cube_pos = vec3(0.3f, 0, 0); uniform vec3 plane_dir = vec3(0, 1.0f, 0); // polynomial smooth min float sminCubic( float a, float b, float k ) { float h = max( k-abs(a-b), 0.0 )/k; return min( a, b ) - h*h*h*k*(1.0/6.0); } float intersectSDF(float distA, float distB) { return max(distA, distB); } float unionSDF(float distA, float distB) { return min(distA, distB); } float differenceSDF(float distA, float distB) { return max(distA, -distB); } void vertex() { //POSITION = vec4(VERTEX, 1.0); } float sdEllipsoid( vec3 p, vec3 r ) { float k0 = length(p/r); float k1 = length(p/(r*r)); return (k0<1.0) ? (k0-1.0)*min(min(r.x,r.y),r.z) : k0*(k0-1.0)/k1; } float sdPlane(vec3 p, vec3 n, float h) { return dot(n, p) + h; } float sdBox( vec3 b, vec3 p ) { vec3 q = abs(p) - b; return length(max(q,0.0)) + min(max(q.x,max(q.y,q.z)),0.0); } float dstFromSphere(vec3 target, vec3 pos, float r) { return distance(target, pos) - r; } float sdVerticalCapsule( vec3 p, float h, float r ) { p.y -= clamp( p.y, 0.0, h ); return length( p ) - r; } float get_distance(vec3 p) { //return sdEllipsoid(p + sphere_pos, vec3(0.01f, 0.01f, 0.015f)); //return sdVerticalCapsule(p + sphere_pos, 0.015f, 0.01f); return sminCubic( sdVerticalCapsule(p + sphere_pos, 0.015f, 0.01f), sdVerticalCapsule(p + cube_pos, 0.015f, 0.01f), epsilon ); /*return sminCubic( sdBox(vec3(0.2f), p + cube_pos), //sdPlane(p + cube_pos, plane_dir, 0), //dstFromSphere(p + sphere_pos, vec3(0), 0.199f), sdEllipsoid(p + sphere_pos, vec3(0.01f, 0.01f, 0.015f)), epsilon );*/ /*return sminCubic( sdEllipsoid(p + cube_pos, vec3(0.01f, 0.01f, 0.015f)), sdEllipsoid(p + sphere_pos, vec3(0.01f, 0.01f, 0.015f)), 0.1 );*/ } vec3 get_normal(vec3 p) { vec2 e = vec2(1e-5, 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 orig, vec3 dir) { vec3 sphere_orig = vec3(0, 0, 0); float dst = get_distance(orig); int inc = 0; for (int i = 0; i < max_iterations; i++) { if (dst <= threshold && !disable_threshold) { break; } orig += dst * dir; dst = get_distance(orig); } if (dst <= threshold) { // We touched a shape return vec4(orig, 1.0f); } else { // Render some white transparent background so we can still see the quad return vec4(vec3(1), 0); } } void fragment() { vec2 uv = SCREEN_UV * 2.0 - 1.0; vec4 camera = INV_VIEW_MATRIX * INV_PROJECTION_MATRIX * vec4(uv, 1, 1); vec3 orig = INV_VIEW_MATRIX[3].xyz; vec3 dir = normalize(camera.xyz); vec4 point = rayMarch(orig, dir); // Render white transparent background by default vec4 col = vec4(1, 1, 1, 0.1f); // The w member of the vec4 is used to convey that we hit something. // Let put a colour on that and compute the normal if (point.w > 0.0f) { col = colour; col.a = point.w; NORMAL = (vec4(get_normal(point.xyz), 1) * INV_VIEW_MATRIX).xyz; } ALPHA = col.a; ALBEDO = col.rgb; }