Files
4kintro/shader2d.frag

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.);
}