#version 300 es precision highp float; const float CAM_FAR = 20.0; const vec3 BACKGROUND = vec3(0.0, 0.0, 0.0); uniform float time; uniform vec2 resolution; uniform bool layer_snow; in vec4 vColor; layout (location = 0) out vec4 fragColor; vec3 artifactOffset; mat3 artifactRotation; vec3 artifactAxis; vec3 camFwd; vec3 camUp; float rand(float n) { return fract(sin(n) * 43758.5453); } float noise(float x) { float i = floor(x); float f = fract(x); return mix(rand(i), rand(i + 1.0), f * f * (3.0 - 2.0 * f)); } mat4 viewMatrix(vec3 dir, vec3 up) { vec3 f = normalize(dir); vec3 s = normalize(cross(f, up)); vec3 u = cross(s, f); return mat4( vec4(s, 0.0), vec4(u, 0.0), vec4(-f, 0.0), vec4(0.0, 0.0, 0.0, 1.0) ); } mat3 rotationAlign(vec3 d, vec3 z) { vec3 v = cross(z, d); float c = dot(z, d); float k = 1.0 / (1.0 + c); float k_vx = v.x * k; float k_vy = v.y * k; float k_vz = v.z * k; return mat3( k_vx * v.x + c, k_vx * v.y - v.z, k_vx * v.z + v.y, k_vy * v.x + v.z, k_vy * v.y + c, k_vy * v.z - v.x, k_vz * v.x - v.y, k_vz * v.y + v.x, k_vz * v.z + c ); } float intersectPlane(vec3 origin, vec3 direction, vec3 point, vec3 normal) { return clamp(dot(point - origin, normal) / dot(direction, normal), -1.0, 9991999.0); } vec3 calcRay(vec2 uv, float fov, float aspect) { uv = uv * 2.0 - 1.0; float d = 1.0 / tan(radians(fov) * 0.5); return normalize(vec3(aspect * uv.x, uv.y, d)); } float octahedron(vec3 p, float s) { const float factor = 0.57735027; p = abs(p); return (p.x + p.y + p.z - s) * factor; } void artifact(vec3 p, inout float currDist, inout vec3 glowColor, inout int id) { p -= artifactOffset; p = artifactRotation * p; float dist = octahedron(p, 0.8); const float glowDist = 4.8; if (dist < glowDist) { float d = dist + rand(dist) * 1.7; glowColor += vec3(0.75, 0.55, 0.45) * clamp(1.0 - pow((d * (1.0 / glowDist)), 5.0), 0.0, 1.0) * 0.035; } if (dist < currDist) { currDist = dist; id = 1; } } float objects(vec3 p, inout vec3 glowColor, inout int objId) { float dist = CAM_FAR; artifact(p, dist, glowColor, objId); return dist; } float artifactDist(vec3 p) { p -= artifactOffset; p = artifactRotation * p; return octahedron(p, 1.2); } vec3 objectsNormal(vec3 p, float eps) { vec2 h = vec2(eps, 0); return normalize(vec3(artifactDist(p + h.xyy) - artifactDist(p - h.xyy), eps * 2.0, artifactDist(p + h.yyx) - artifactDist(p - h.yyx))); } vec3 objectsColor(int id, vec3 normal, vec3 ray) { return id == 1 ? vec3(0.85, 0.65, 0.55) * mix(0.8, 1.5, dot(normal, normalize(vec3(0.0, 1.0, 0.5))) * 0.5 + 0.5) : id == 2 ? vec3(0.85, 0.65, 0.55) * 1.5 : vec3(1.0, 1.0, 0.0); } void marchObjects(vec3 eye, vec3 ray, float wDepth, inout vec4 color) { float dist = 0.0; int id; vec3 rayPos = eye; float depth = CAM_FAR; for (int i = 0; i < 30; i++) { dist = objects(rayPos, color.rgb, id); depth = distance(rayPos, eye); if (depth > wDepth || dist < 0.01) break; rayPos += ray * dist; } color = dist < 0.01 ? vec4(objectsColor(id, objectsNormal(rayPos, 0.01), ray), depth) : color; } vec3 march(vec2 uv, vec3 camPos) { mat4 vm = viewMatrix(camFwd, camUp); vec3 ray = (vm * vec4(calcRay(uv, 80.0, resolution.x / resolution.y), 1.0)).xyz; vec4 color = vec4(BACKGROUND, CAM_FAR); marchObjects(camPos, ray, color.w, color); return color.rgb; } float snow(vec2 uv, float scale) { float w = smoothstep(1.0, 0.0, -uv.y * (scale * 0.01)); if (w < 0.1) return 0.0; float timeScale = time / scale; uv += vec2(timeScale, timeScale); uv.x += sin(uv.y + time * 0.125) / scale; uv *= scale; vec2 s = floor(uv); vec2 f = fract(uv); float sinValueX = sin((s.x + scale) * 7.0) * 5.0; float sinValueY = sin((s.y + scale) * 5.0) * 5.0; float combinedSinValue = sinValueX + sinValueY; float lengthValue = length(0.5 + 0.5 * sin(11.0 * fract(combinedSinValue)) - f); return smoothstep(0.0, min(lengthValue, 3.0), sin(f.x + f.y) * 0.01) * w; } void mainImage(out vec4 fragColor, in vec2 fragCoord) { vec2 uv = fragCoord / resolution.xy; float s = sin(time); float c = cos(time); artifactRotation = mat3(c, 0, s, 0, 1, 0, -s, 0, c) * rotationAlign(vec3(0.0, 1.0, 0.0), vec3(s * 0.2, 1.0, c * 0.2 + 0.3)); artifactOffset = vec3(s * 0.4, c * 0.3 - 1.7, -6.0); camFwd = vec3(0.0, 0.7 + noise(time * 0.8 + 4.0) * 0.08 - 0.04, 1.0); camUp = vec3(noise(time * 1.2) * 0.02 - 0.01, 1.0, 0.0); fragColor = vec4(march(uv, vec3(0.0, 1.9, 1.0)) - (length(uv - 0.5) - 0.3) * 0.05, 1.0); if (layer_snow) { vec2 uvSnow = (fragCoord * 2.0 - resolution.xy) / min(resolution.x, resolution.y); fragColor += vec4(vec3(snow(uvSnow, 4.0)), 0.5) * 0.7; } } void main() { fragColor = vColor; mainImage(fragColor, gl_FragCoord.xy); }