146 lines
3.5 KiB
GLSL
146 lines
3.5 KiB
GLSL
#ifdef GL_ES
|
|
precision mediump float;
|
|
#endif
|
|
|
|
const float PI = 3.14159265;
|
|
uniform vec2 u_resolution;
|
|
uniform float u_time;
|
|
|
|
vec3 palette(float t) {
|
|
vec3 a = vec3(0.5, 0.5, 0.5);
|
|
vec3 b = vec3(1.0, 1.0, 1.0);
|
|
vec3 c = vec3(1.0, 1.0, 1.0);
|
|
vec3 d = vec3(0.0, 0.6666, 0.3333);
|
|
return a + b * cos(6.28318 * (c*t+d));
|
|
}
|
|
|
|
|
|
mat2 rotate(float angle){
|
|
return mat2(cos(angle), -sin(angle), sin(angle), cos(angle));
|
|
}
|
|
|
|
|
|
float star(vec2 position, float radius, float sides){
|
|
float a = atan(position.x, position.y);
|
|
float slice = PI * 2. / sides;
|
|
return 1. - step(radius, cos(floor(-2.0 + a / slice) * slice - a));
|
|
}
|
|
|
|
float polygon(vec2 position, float radius, float sides){
|
|
float a = atan(position.x, position.y);
|
|
float slice = PI * 2.0 / sides;
|
|
return 1. - step(radius, cos(floor(0.5 + a / slice) * slice - a) * length(position));
|
|
}
|
|
|
|
float sdSphere(vec3 p, float s) {
|
|
return length(p) - s; // renders sphere
|
|
}
|
|
|
|
float sdBox(vec3 p, vec3 b) {
|
|
vec3 q = abs(p) - b;
|
|
return length(max(q,0.0)) + min(max(q.x,max(q.y, q.z)), 0.);
|
|
}
|
|
|
|
/** smooth minimum */
|
|
float smin( float a, float b, float k) {
|
|
float h = max(k-abs(a-b), 0.)/k;
|
|
return min(a,b) - h*h*h*k*(1./6.);
|
|
}
|
|
|
|
vec3 rot3d(vec3 p, vec3 axis, float angle) {
|
|
return mix(dot(axis,p)*axis, p, cos(angle)) + cross(axis, p ) * sin(angle);
|
|
}
|
|
|
|
mat2 rot2d(float angle) {
|
|
float s = sin(angle);
|
|
float c = cos(angle);
|
|
return mat2(c,-s,s,c);
|
|
}
|
|
|
|
// distance to scene
|
|
float getDist(vec3 p) {
|
|
// vec3 pos = vec3(sin(u_time)*1.2, 0., -.7);
|
|
// float sphere = sdSphere(p - pos, 1.);
|
|
|
|
// float scale = 10.;
|
|
// mod(p, 1.) == fract(p)... no gap
|
|
|
|
//p.z += u_time;
|
|
|
|
//p = fract(p) - 0.5;
|
|
|
|
//p.xy *= rot2d(u_time);
|
|
//p.yz *= rot2d(u_time);
|
|
|
|
float box = sdSphere(p-vec3(0.,0., -1.), .3);
|
|
float ground = p.y + 0.5;
|
|
|
|
return min(ground, box);
|
|
//return min(ground, min(sphere, box)); // normal union
|
|
/**
|
|
other functions are:
|
|
substract: return max(-d1, d2);
|
|
intersetion: return max(d1, d2);
|
|
*/
|
|
}
|
|
|
|
|
|
vec3 getNormal(vec3 p) {
|
|
float d = getDist(p);
|
|
vec2 e = vec2(.01, 0.);
|
|
vec3 n = d - vec3(
|
|
getDist(p-e.xyy),
|
|
getDist(p-e.yxy),
|
|
getDist(p-e.yyx)
|
|
);
|
|
return normalize(n);
|
|
}
|
|
|
|
float rayMarch(vec3 ro, vec3 rd) {
|
|
float t = 0.; // total distance travelled
|
|
|
|
// raymarching
|
|
for (int i = 0; i < 100; i++) {
|
|
vec3 p = ro + rd * t; // position at the ray
|
|
// p.xy *= rot2d(-u_time);
|
|
|
|
// p.xy *= rot2d(2. * sin(u_time + t *.2));
|
|
//p.y += sin(t)*0.6;
|
|
//p.x += cos(t)*0.6;
|
|
|
|
float d = getDist(p); // current distance to scene
|
|
|
|
t +=d; // "march" of the ray
|
|
if (t > 100. || d < 0.01 ) break; // stop if ray hits, or distance too long
|
|
}
|
|
|
|
return t;
|
|
}
|
|
|
|
|
|
float getLight(vec3 p, vec3 lightPos) {
|
|
vec3 l = normalize(lightPos - p);
|
|
vec3 n = getNormal(p);
|
|
float dif = clamp(dot(n,l), 0., 1.);
|
|
float d = rayMarch(p + n*0.02,l);
|
|
if (d<length(lightPos-p)) dif *= 0.3;
|
|
return dif;
|
|
}
|
|
|
|
|
|
void main() {
|
|
vec2 uv = (gl_FragCoord.xy * 2. - u_resolution.xy) / u_resolution.y;
|
|
|
|
vec3 ro = vec3(0., 0., -2.); // ray origin
|
|
float fov = .9;
|
|
vec3 rd = normalize(vec3(uv * fov, 1.));
|
|
vec3 col = vec3(0.); // final pixel color
|
|
float d = rayMarch(ro, rd);
|
|
vec3 p = ro + rd * d;
|
|
float dif = getLight(p, vec3(5.*sin(u_time), 7., 4.*cos(u_time)));
|
|
|
|
col = vec3(dif);
|
|
//col = vec3(d*0.1);
|
|
gl_FragColor = vec4(col, 1.);
|
|
|
|
} |