parade/shaders/parade_fs.glsl

172 lines
4.7 KiB
Plaintext
Raw Normal View History

2023-11-06 22:02:45 -05:00
#version 400
uniform mat4 P;
uniform mat4 V;
uniform mat4 M;
uniform vec3 cam_pos;
uniform int window_width;
uniform int window_height;
uniform vec3 la;
uniform vec3 ld;
uniform vec3 ls;
uniform vec3 ka;
uniform vec3 kd;
uniform vec3 ks;
2023-11-07 00:15:16 -05:00
uniform float smoothing;
2023-11-06 22:02:45 -05:00
in vec3 v_pos;
out vec4 FragColor;
struct Torus
{
float R;
float r;
};
Torus torus;
struct Sphere
{
vec3 center;
float r;
};
Sphere sphere;
void initTorus()
{
torus.R = 0.5;
torus.r = 0.15;
}
void initSphere()
{
sphere.center = vec3(0.0, 0.25, 0.0);
sphere.r = 0.25;
}
float sphereSDF(vec3 p, vec3 center, float r) {
return length(p - center) - r;
}
float torusSDF(vec3 p, float R, float r) {
vec2 q = vec2(length(p.xz) - R, p.y);
return length(q) - r;
}
vec3 estimateNormalsSphere(vec3 p)
{
float epsilon = 0.001;
float x = sphereSDF(vec3(p.x + epsilon, p.y, p.z), sphere.center, sphere.r) - sphereSDF(vec3(p.x - epsilon, p.y, p.z), sphere.center, sphere.r);
float y = sphereSDF(vec3(p.x, p.y + epsilon, p.z), sphere.center, sphere.r) - sphereSDF(vec3(p.x, p.y - epsilon, p.z), sphere.center, sphere.r);
float z = sphereSDF(vec3(p.x, p.y, p.z + epsilon), sphere.center, sphere.r) - sphereSDF(vec3(p.x, p.y, p.z - epsilon), sphere.center, sphere.r);
return normalize(vec3(x, y, z));
}
vec3 estimateNormalsTorus(vec3 p)
{
float epsilon = 0.001;
float x = torusSDF(vec3(p.x + epsilon, p.y, p.z), torus.R, torus.r) - torusSDF(vec3(p.x - epsilon, p.y, p.z), torus.R, torus.r);
float y = torusSDF(vec3(p.x, p.y + epsilon, p.z), torus.R, torus.r) - torusSDF(vec3(p.x, p.y - epsilon, p.z), torus.R, torus.r);
float z = torusSDF(vec3(p.x, p.y, p.z + epsilon), torus.R, torus.r) - torusSDF(vec3(p.x, p.y, p.z - epsilon), torus.R, torus.r);
return normalize(vec3(x, y, z));
}
float smoothMinSDF(float d1, float d2, float k) {
float h = max(k - abs(d1 - d2), 0) / k;
return min(d1, d2) - h * h * h * k * 1.0 / 6.0;
}
float smoothMaxSDF(float d1, float d2, float k) {
float h = clamp(0.5 + 0.5 * (d2 - d1) / k, 0.0, 1.0);
return mix(d2, d1, h) - k * h * (1.0 - h);
}
float blendSDF(float d1, float d2) {
return (d1 * d2) / (d1 + d2);
}
vec3 estimateSmoothNormals(vec3 p, float smoothness) {
float epsilon = 0.001;
float d = smoothMinSDF(torusSDF(p, torus.R, torus.r), sphereSDF(p, sphere.center, sphere.r), smoothness);
float nx = smoothMinSDF(torusSDF(vec3(p.x + epsilon, p.y, p.z), torus.R, torus.r), sphereSDF(vec3(p.x + epsilon, p.y, p.z), sphere.center, sphere.r), smoothness) - d;
float ny = smoothMinSDF(torusSDF(vec3(p.x, p.y + epsilon, p.z), torus.R, torus.r), sphereSDF(vec3(p.x, p.y + epsilon, p.z), sphere.center, sphere.r), smoothness) - d;
float nz = smoothMinSDF(torusSDF(vec3(p.x, p.y, p.z + epsilon), torus.R, torus.r), sphereSDF(vec3(p.x, p.y, p.z + epsilon), sphere.center, sphere.r), smoothness) - d;
return normalize(vec3(nx, ny, nz));
}
void main(void)
{
vec3 normals;
vec3 color = la;
vec4 ray_pos = vec4(cam_pos, 1.0);
float ray_dist = 0.0;
float max_dist = 100.0;
float epsilon = 0.001;
int steps = 0;
int max_steps = 1000;
vec3 light_pos = vec3(0.0, 1.0, 0.0);
int spec_exponent = 40;
2023-11-07 00:15:16 -05:00
float k = smoothing;
2023-11-06 22:02:45 -05:00
initTorus();
initSphere();
vec2 ndc_pos = 2.0 * vec2(gl_FragCoord.x / window_width, gl_FragCoord.y / window_height) - 1.0;
vec4 cam_dir = inverse(P) * vec4(ndc_pos, 1.0, 1.0);
cam_dir /= cam_dir.w;
cam_dir = vec4(cam_dir.xyz, 0.0);
vec4 ray_dir = normalize(inverse(V) * cam_dir);
while (ray_dist < max_dist && steps < max_steps)
{
steps++;
float distTorus = torusSDF(ray_pos.xyz, torus.R, torus.r);
float distSphere = sphereSDF(ray_pos.xyz, sphere.center, sphere.r);
2023-11-07 00:15:16 -05:00
float minDist = smoothMinSDF(distTorus, distSphere, k);
2023-11-06 22:02:45 -05:00
//bool isTorus = distTorus < distSphere;
//float minDist = min(distTorus, distSphere);
if (minDist <= epsilon)
{
vec4 ambient_color, diffuse_color;
ambient_color = vec4(ka, 1.0);
diffuse_color = vec4(kd, 1.0);
vec4 ambient = vec4(la, 1.0) * ambient_color;
2023-11-07 00:15:16 -05:00
normals = estimateSmoothNormals(ray_pos.xyz, k);
2023-11-06 22:02:45 -05:00
//if (isTorus)
// normals = estimateNormalsTorus(ray_pos.xyz);
//else
// normals = estimateNormalsSphere(ray_pos.xyz);
vec3 nw = normalize(normals);
vec3 lw = normalize(light_pos - ray_pos.xyz);
float dist = length(vec4(ray_pos.xyz - light_pos, 1.0));
vec4 diffuse = max(dot(nw, lw), 0) * diffuse_color * vec4(ld, 1.0);
float spec;
vec3 vw = normalize(cam_pos - ray_pos.xyz);
vec3 halfwayDir = normalize(lw + vw);
spec = pow(max(dot(halfwayDir, nw), 0), spec_exponent);
vec4 specular = spec * vec4(ks * ls, 1.0);
color = (ambient + (1.0 / (dist * dist) * (diffuse + specular))).xyz;
break;
}
ray_pos += ray_dir * minDist;
ray_dist += minDist;
}
FragColor = vec4(color, 1.0);
}