precision highp float; #define DEBUG 0 #define SHADER_TOY 0 // uniforms #if SHADER_TOY == 0 uniform float time; uniform vec2 mouse; uniform vec2 resolution; #endif // debug for camera #if DEBUG uniform bool debugCamera; uniform vec3 cameraPos; uniform vec3 cameraDir; #endif // consts const float INF = 1e+10; const float EPS = 1e-2; const float EPS_N = 1e-3; const float OFFSET = EPS * 100.0; const float PI = 3.14159265359; const float PI2 = 6.28318530718; const float PIH = 1.57079632679; const float PIQ = 0.78539816339; // globals const vec3 lightDir = vec3( -0.48666426339228763, 0.8111071056538127, -0.3244428422615251 ); float lTime; // ray struct Ray { vec3 origin; vec3 direction; }; // camera struct Camera { vec3 eye, target; vec3 forward, right, up; float zoom; }; Ray cameraShootRay(Camera c, vec2 uv) { c.forward = normalize(c.target - c.eye); c.right = normalize(cross(c.forward, c.up)); c.up = normalize(cross(c.right, c.forward)); Ray r; r.origin = c.eye; r.direction = normalize(uv.x * c.right + uv.y * c.up + c.zoom * c.forward); return r; } // intersection struct Intersection { bool hit; vec3 position; float distance; vec3 normal; vec2 uv; float count; //int material; vec3 color; float metalness; }; //#define METAL_MATERIAL 0 //#define MIRROR_MATERIAL 1 // util #define saturate(x) clamp(x, 0.0, 1.0) float hash(vec2 p) { return fract(1e4 * sin(17.0 * p.x + p.y * 0.1) * (0.1 + abs(sin(p.y * 13.0 + p.x)))); } float noise(vec2 x) { vec2 i = floor(x), f = fract(x); float a = hash(i); float b = hash(i + vec2(1.0, 0.0)); float c = hash(i + vec2(0.0, 1.0)); float d = hash(i + vec2(1.0, 1.0)); vec2 u = f * f * (3.0 - 2.0 * f); return mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y; } #define HASHSCALE1 .1031 #define HASHSCALE3 vec3(.1031, .1030, .0973) #define HASHSCALE4 vec4(1031, .1030, .0973, .1099) // 1 out, 3 in... float hash13(vec3 p3) { p3 = fract(p3 * HASHSCALE1); p3 += dot(p3, p3.yzx + 19.19); return fract((p3.x + p3.y) * p3.z); } float fbm(vec2 p) { const mat2 m2 = mat2(0.8, -0.6, 0.6, 0.8); p.xy += 0.1 * lTime; float f = 0.5000 * noise(p); p = m2 * p * 2.02; f += 0.2500 * noise(p); p = m2 * p * 2.03; f += 0.1250 * noise(p); p = m2 * p * 2.01; f += 0.0625 * noise(p); return f / 0.9375; } float easeInCubic( float t ) { return t * t * t; } float easeInOutCubic(float t) { return t < 0.5 ? 4.0 * t * t * t : (t - 1.0) * (2.0 * t - 2.0) * (2.0 * t - 2.0) + 1.0; } float gauss(float x) { float a = 50.0; return exp(-x * x / a); } // Distance Functions // operations //vec3 opRep( vec3 p, float interval ) { // return mod( p, interval ) - 0.5 * interval; //} #define opRep(p, interval) (mod(p, interval) - 0.5 * interval) //vec2 opRepLimit(vec2 p, float interval, float limit) { // return mod(clamp(p, -limit, limit), interval) - 0.5 * interval; //} #define opRepLimit(p, interval, limit) (mod(clamp(p, -limit, limit), interval) - 0.5 * interval) // https://www.shadertoy.com/view/Mlf3Wj mat2 rotate(in float a) { float s=sin(a),c=cos(a); return mat2(c,s,-s,c); } vec2 fold(in vec2 p, in float s) { float a = PI / s - atan(p.x, p.y); float n = PI2 / s; a = floor(a / n) * n; p *= rotate(a); return p; } float smin(float d1, float d2, float k) { float h = exp(-k * d1) + exp(-k * d2); return -log(h) / k; } // Distance Functions float sdBox( vec3 p, vec3 b ) { vec3 d = abs(p) - b; return min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0)); } float dSphere(vec3 p, float r) { return length(p) - r; } float dBar( vec2 p, float interval, float width) { return length( max( abs( opRep( p, interval ) ) - width, 0.0 ) ); } #define META_SCENE_END_TIME (32.0) #define UFO_SCENE_END_TIME (117.0) #define SNOW_SCENE_END_TIME (182.0) float dFract(inout vec3 p) { float radius = 1.0; float radiusScale = 0.45 * abs(sin(0.3 * lTime)); float d = sdBox(p, vec3(radius)); for (int i = 0; i < 5; i++) { vec3 q = abs(p) + normalize(vec3(-1.0)) * radius * (1.0 + radiusScale); d = min(d, sdBox(p, vec3(radius))); p = q; radius *= radiusScale; } return d; } float dTree(vec3 p) { float scale = 0.6 * saturate(1.5 * sin(0.05 * (lTime - UFO_SCENE_END_TIME - 2.0))); float width = mix(0.3 * scale, 0.0, saturate(p.y)); vec3 size = vec3(width, 1.0, width); float d = sdBox(p, size); for (int i = 0; i < 10; i++) { vec3 q = p; q.x = abs(q.x); q.y -= 0.5 * size.y; q.xy *= rotate(-1.2); d = min(d, sdBox(p, size)); p = q; size *= scale; } return d; } float dSnowCrystal(inout vec3 p) { p.xy = fold(p.xy, 6.0); return dTree(p); } float dMix(inout vec3 p) { float sphere = dSphere(p, 1.5); float box = sdBox(p, vec3(1.1)); float d = mix(sphere, box, 0.5 + clamp(sin(PIQ * lTime), -0.5, 0.5)); return d; } float dMeta(inout vec3 p) { // copy from cameraControl vec3 target = vec3(0.0); float t1 = lTime - META_SCENE_END_TIME; target.y = clamp(-0.7 * t1, -2.8, 100.0); float a = max(0.0, 2.0 - lTime * 0.1) + cos(lTime * 0.3); float b = 0.2 * sin(lTime); float d1 = dSphere(p - target - vec3(a, 0, b), 1.0); float d2 = dSphere(p - target + vec3(a, 0, b), 1.0); float d = smin(d1, d2, 1.0); return d; } float hWave(vec2 p, float t) { float h = 1.0; float a = 1.0; float b = 6.0; for(float i = 0.0; i < 3.0; i++) { float f = pow(2.0, i); h += 1.0 / f * (sin(f * a * p.x + b * t) + sin(f * a * p.y + b * t)); } return h; } float dWing(in vec3 p) { float t = lTime - META_SCENE_END_TIME; float l = length(p.xz); float fusion = gauss((lTime - META_SCENE_END_TIME - 5.0) * 2.0); float a = 0.1 + 0.06 * (1.0 + sin(PI * t + l)); float b = min(0.2 * t, 10.0) * gauss(l) + 0.1 * fusion * hWave(p.xz, t); p.y += -b + 15.0; vec3 p1 = p; p1.xz = opRepLimit(p.xz, 1.0, 20.0); vec3 p2 = p; p2 = opRep(p, 0.5); float d = sdBox(p1, vec3(0.2 + a * 3.0, 12.0 - a, 0.2 + a)); d = min(d, sdBox(p1, vec3(0.4 - a, 13.0 - 4.0 * a, 0.1 + a))); d = max(d, -sdBox(p1, vec3(0.3 - a, 14.0 - 4.0 * a, a))); d = max(d, -sdBox(p2, vec3(0.8 * a, 1.0 - a, 0.8 * a))); return d; } float dUfo(inout vec3 p) { float t = max((lTime - META_SCENE_END_TIME - 10.0) * 0.5, 1.0); float t1 = floor(t); float t2 = t1 + easeInOutCubic(t - t1); p.xz = fold(p.xz, min(t2, 10.0)); p.z -= 0.5; float d = dWing(p); //float t3 = lTime - META_SCENE_END_TIME; //if (t3 < 10.0) { // d -= mix(0.08, 0.0, saturate(t3 * 0.1)) * fbm(10.0 * p.xz + 5.0 * p.y); //} return d; } float dScene(vec3 p) { if (lTime < UFO_SCENE_END_TIME - 2.0) { float d = dMeta(p); d = smin(d, dUfo(p), clamp(lTime - META_SCENE_END_TIME, 1.0, 15.0)); return d; } else { //return dFract(p); return dSnowCrystal(p); } } float dSceneBump(vec3 p) { float d = dScene(p); float t3 = lTime - META_SCENE_END_TIME; if (t3 < 10.0) { d -= mix(0.08, 0.0, saturate(t3 * 0.1)) * fbm(10.0 * p.xz + 5.0 * p.y); } return d; } // color functions vec3 hsv2rgb(vec3 c) { vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); return c.z * mix(K.xxx, saturate(p - K.xxx), c.y); } //vec3 calcNormal( vec3 p ) { // vec2 e = vec2( 1.0, -1.0 ) * 0.001; // return normalize( // e.xyy * dScene( p + e.xyy ) + e.yyx * dScene( p + e.yyx ) + // e.yxy * dScene( p + e.yxy ) + e.xxx * dScene( p + e.xxx ) ); //} #define calcNormal(p, dFunc) normalize(vec2(EPS_N, -EPS_N).xyy * dFunc(p + vec2(EPS_N, -EPS_N).xyy) + vec2(EPS_N, -EPS_N).yyx * dFunc(p + vec2(EPS_N, -EPS_N).yyx ) + vec2(EPS_N, -EPS_N).yxy * dFunc(p + vec2(EPS_N, -EPS_N).yxy) + vec2(EPS_N, -EPS_N).xxx * dFunc(p + vec2(EPS_N, -EPS_N).xxx)) float calcRate(float a, float b) { return a / (a + b); } void setMaterialAndUv(inout Intersection intersection, vec3 p) { //intersection.material = METAL_MATERIAL; float d1 = dUfo(p); float d2 = dMeta(p); float rate = calcRate(abs(d1), abs(d2)); intersection.metalness = rate; float t = lTime - META_SCENE_END_TIME; intersection.metalness = mix(intersection.metalness, 1.0, saturate(t * 0.05)); intersection.metalness = mix(intersection.metalness, 2.0, gauss((t - 13.0) * 3.0)); //if ( false && lTime <= META_SCENE_END_TIME ) { // intersection.material = MIRROR_MATERIAL; //} else { // dUfo(p); // intersection.material = METAL_MATERIAL; // intersection.uv = p.xz; //} } void intersectScene(inout Intersection intersection, inout Ray ray ) { float d; intersection.distance = 0.0; vec3 p = ray.origin; for (float i = 0.0; i < 128.0; i++) { d = dScene(p); intersection.distance += d; p = ray.origin + intersection.distance * ray.direction; intersection.count = i; if (abs(d) < EPS || intersection.distance > 100.0) break; } if (abs(d) < EPS) { intersection.hit = true; intersection.position = p; intersection.normal = calcNormal(p, dScene); setMaterialAndUv(intersection, p); } } float calcAo(in vec3 p, in vec3 n){ float sca = 1.0, occ = 0.0; for(float i=0.; i<5.; i++){ float hr = 0.05 + i * 0.08; float dd = dScene(n * hr + p); occ += (hr - dd) * sca; sca *= 0.5; } return saturate(1.0 - occ); } float calcShadow(in vec3 p, in vec3 rd) { float d; float distance = OFFSET; float bright = 1.0; float shadowIntensity = 0.5; float shadowSharpness = 16.0; for (int i = 0; i < 30; i++) { d = dScene(p + rd * distance); if (d < EPS) return shadowIntensity; bright = min(bright, shadowSharpness * d / distance); distance += d; } return shadowIntensity + (1.0 - shadowIntensity) * bright; } // Just snow by baldand // https://www.shadertoy.com/view/ldsGDn #define LAYERS 50 #define DEPTH .5 #define WIDTH .3 #define SPEED .6 float screenSpaceSnow(vec2 uv) { const mat3 p = mat3(13.323122,23.5112,21.71123,21.1212,28.7312,11.9312,21.8112,14.7212,61.3934); float acc = 0.0; float dof = 5.*sin(lTime*.1); for (int i=0;i