139 lines
3.2 KiB
Plaintext
139 lines
3.2 KiB
Plaintext
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;
|
|
} |