174 lines
4.4 KiB
GLSL
174 lines
4.4 KiB
GLSL
#ifdef GL_ES
|
|
precision mediump float;
|
|
#endif
|
|
|
|
#define MAX_STEPS 100
|
|
#define MAX_DIST 80.
|
|
#define SURF_DIST .001
|
|
#define TAU 6.283185
|
|
#define PI 3.141592
|
|
|
|
//#define SUN_DIR vec3(0.5, 0.4, 2.)
|
|
#define FOG_DENSITY 0.02
|
|
|
|
uniform vec2 u_resolution;
|
|
uniform float u_time;
|
|
|
|
struct Obj {
|
|
float distance; // distance map
|
|
int material; // material Id
|
|
};
|
|
|
|
|
|
mat2 Rot(float a) {
|
|
float s=sin(a), c=cos(a);
|
|
return mat2(c, -s, s, c);
|
|
}
|
|
|
|
float sdBox(vec3 p, vec3 s) {
|
|
p = abs(p)-s;
|
|
return length(max(p, 0.))+min(max(p.x, max(p.y, p.z)), 0.);
|
|
}
|
|
|
|
vec3 applyFog(in vec3 color, in float distance) {
|
|
|
|
float fogAmount = 1.0 - exp(-distance*FOG_DENSITY);
|
|
vec3 fogColor = vec3(0.1, 0.18, 0.43);
|
|
return mix( color, fogColor, fogAmount );
|
|
}
|
|
|
|
vec3 translate(vec3 p) {
|
|
p.xy *= Rot(u_time*0.4);
|
|
p.yz *= Rot(u_time*0.4);
|
|
return p;
|
|
}
|
|
|
|
|
|
float opExtrusion( in vec3 p, in float sdf, in float h )
|
|
{
|
|
vec2 w = vec2( sdf, abs(p.z) - h);
|
|
return min(max(w.x,w.y),0.0) + length(max(w,0.0));
|
|
}
|
|
|
|
|
|
vec2 opRevolution( in vec3 p, float w )
|
|
{
|
|
return vec2( length(p.xz) - w, p.y );
|
|
}
|
|
|
|
vec4 opElongate( in vec3 p, in vec3 h )
|
|
{
|
|
vec3 q = abs(p)-h;
|
|
return vec4( max(q,0.0), min(max(q.x,max(q.y,q.z)),0.0) );
|
|
}
|
|
|
|
|
|
// Scene
|
|
Obj mapScene(vec3 p) {
|
|
|
|
vec3 p0 = p;
|
|
|
|
float dGround = p.y - 0.5*(sin(0.4*p.x+u_time*1.)+sin(1.0*p.z+u_time*1.));
|
|
dGround *=0.8;
|
|
|
|
Obj ground = Obj(dGround, 0);
|
|
|
|
|
|
p0.y = dGround + 0.1;
|
|
|
|
float d1 = length(p0) - 0.3;
|
|
Obj ob1 = Obj(d1, 1);
|
|
|
|
if (ground.distance > ob1.distance) return ob1;
|
|
return ground;
|
|
}
|
|
|
|
Obj castRay(vec3 ro, vec3 rd) {
|
|
float t = 0.0;
|
|
|
|
Obj res = Obj(-1., -1);
|
|
for(int i=0; i<MAX_STEPS; i++) {
|
|
vec3 p = ro + rd * t;
|
|
res = mapScene(p);
|
|
t += res.distance;
|
|
if (t > MAX_DIST || res.distance < abs(SURF_DIST*t) ) break;
|
|
}
|
|
if (t > MAX_DIST) t = -1.0;
|
|
res.distance = t;
|
|
return res;
|
|
}
|
|
|
|
float castShadow(vec3 ro, vec3 rd) {
|
|
float res = 1.0;
|
|
float t = 0.0001;
|
|
for(int i=0; i<MAX_STEPS; i++) {
|
|
vec3 pos = ro + t* rd;
|
|
float h = mapScene(pos).distance;
|
|
res = min(res, 10.0*h/t);
|
|
if (abs(h) < (0.001*t) ) break;
|
|
t += h;
|
|
if (t > 20.) break;
|
|
}
|
|
return clamp(res,0., 1.);
|
|
}
|
|
|
|
vec3 calcNormal(vec3 pos) {
|
|
vec2 e = vec2(.0001, 0.);
|
|
vec3 n = vec3( mapScene(pos+e.xyy).distance - mapScene(pos-e.xyy).distance,
|
|
mapScene(pos+e.yxy).distance - mapScene(pos-e.yxy).distance,
|
|
mapScene(pos+e.yyx).distance - mapScene(pos-e.yyx).distance
|
|
);
|
|
return normalize(n);
|
|
}
|
|
|
|
void main()
|
|
{
|
|
vec2 p = (2.0 * gl_FragCoord.xy - u_resolution.xy) / u_resolution.y;
|
|
float angle = u_time*0.2;
|
|
angle = 4.6; // comment to rotate
|
|
|
|
// camera
|
|
vec3 ta = vec3(0.0, .5, 0.0);
|
|
vec3 ro = ta + vec3(1.*sin(angle), .7, 2.); // *cos(angle))
|
|
|
|
vec3 ww = normalize(ta-ro);
|
|
vec3 uu = normalize(cross(ww, vec3(0,1,0)));
|
|
vec3 vv = normalize(cross(uu,ww));
|
|
|
|
vec3 rd = normalize(p.x * uu + p.y*vv + 1.3*ww); // camera
|
|
|
|
// global light
|
|
vec3 col = vec3(0.1216, 0.2863, 0.5529) - 0.5*rd.y;
|
|
Obj t = castRay(ro, rd);
|
|
|
|
if (t.distance > 0.) {
|
|
vec3 pos = ro + rd * t.distance;
|
|
vec3 nor = calcNormal(pos);
|
|
// vec3 r = reflect(rd, nor);
|
|
vec3 outMaterial = vec3(0.1255, 0.1176, 0.1176);
|
|
|
|
if (t.material == 0) {
|
|
outMaterial = vec3(0.0039, 0.2235, 0.4) + sin(t.distance)*0.1;
|
|
} else if (t.material == 1) {
|
|
outMaterial = vec3(0.8392, 0.0118, 0.0118);
|
|
}
|
|
vec3 SUN_DIR = vec3(0.5+sin(u_time*0.1), 0.4, 2.0+sin(u_time*0.2)*0.5);
|
|
|
|
float sun_dif = clamp(dot(nor, SUN_DIR), 0., 1.);
|
|
float sun_sha = castShadow(pos + nor*0.02, SUN_DIR);
|
|
float sky_dif = clamp(0.5 + 0.5 * dot(nor, vec3(0.,1.,0.)), 0., 1.);
|
|
float bounce_dif = clamp(0.5 + 0.5 * dot(nor, vec3(.7,.5, 0.)), 0., 1.);
|
|
|
|
// format color + what to apply
|
|
col = outMaterial * vec3(2.0,1.5, .2) * sun_dif * sun_dif * sun_sha;
|
|
col += outMaterial * vec3(0.0196, 0.2078, 0.4196) * sky_dif;
|
|
col += outMaterial * vec3(0.051, 0.0588, 0.5686) * bounce_dif;
|
|
|
|
// apply fog
|
|
col = applyFog(col, t.distance);
|
|
}
|
|
|
|
col = pow(col, vec3(.4545)); // gamma correction
|
|
|
|
gl_FragColor = vec4(col,1.0);
|
|
} |