- Sign In
- Sign Up
Happy Halloween (2021)
This is a tiny (but not so much anymore) ray marcher that I wrote to celebrate Halloween in 2021! Happy Halloween!
Created by marcogomez on Sun, 31 Oct 2021 20:16:38 GMT.
#version 300 es // ╔═════════════╦════════════════╗ // ║ Marco Gomez ║ https://mgz.me ║ // ╚═════════════╩════════════════╝ precision highp float; uniform sampler2D prgm4Texture; uniform vec2 resolution; uniform float time; out vec4 fragColor; void main(void) { vec2 uv = gl_FragCoord.xy / resolution.xy; vec4 tex = texture(prgm4Texture, uv); fragColor = tex; }
#version 300 es // ╔═════════════╦════════════════╗ // ║ Marco Gomez ║ https://mgz.me ║ // ╚═════════════╩════════════════╝ precision highp float; uniform vec2 resolution; uniform vec2 mouselerp; uniform float time; out vec4 fragColor; #define marchSteps 40 const float PI = acos(-1.0); const float TAU = PI * 2.0; const float cos30 = sqrt(3.0) / 2.0; // for triPrismSDF mat4 rotationMatrix(vec3 axis, float angle) { axis = normalize(axis); float s = sin(angle); float c = cos(angle); float oc = 1.0 - c; return mat4( oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0, oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0, oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0, 0.0, 0.0, 0.0, 1.0 ); } vec3 rotate(vec3 v, vec3 axis, float angle) { mat4 m = rotationMatrix(axis, angle); return (m * vec4(v, 1.0)).xyz; } vec2 rotate(vec2 v, float angle) { float co = cos(angle), si = sin(angle); return v * mat2(co, -si, si, co); } float gaussian(float z, float u, float o) { return ( (1.0 / (o * sqrt(TAU))) * (exp(-(((z - u) * (z - u)) / (2.0 * (o * o))))) ); } vec3 gaussGrain(float t) { vec2 ps = vec2(1.0) / resolution.xy; vec2 uv = gl_FragCoord.xy * ps; float seed = dot(uv, vec2(12.9898, 78.233)); float noise = fract(sin(seed) * 43758.5453123 + t); noise = gaussian(noise, 0.0, 0.5); return vec3(noise); } float disturbRadius(float radius, vec3 axis) { float mul = 2.0; float mag = 3.0; float minRes = min(resolution.x, resolution.y); vec2 fc = gl_FragCoord.xy / minRes; float waveTime = time * 2.0; vec2 distortOffset = vec2( sin(waveTime + fc.y * TAU), sin(waveTime + fc.x * TAU) ) * vec2(0.5); axis.xy += distortOffset; axis.yz += distortOffset * -0.5; float disturbed = ( radius * 1.0 + 0.005 * sin((mul - 1.0) * time + axis.x * (mag)) + 0.010 * sin((mul - 2.0) * time + axis.y * (mag - 1.0)) + 0.015 * sin((mul - 3.0) * time + axis.z * (mag - 2.0)) ); return disturbed; } float sphereSDF(vec3 p, float radius) { radius = disturbRadius(radius, p); p *= vec3(0.92, 0.97, 0.99); return length(p) - radius; } float triPrismSDF(vec3 p, vec3 h) { vec3 q = abs(p); return max(q.y - h.y, max(q.z * cos30 + p.x * h.z, -p.x) - h.x * 0.5); } float un(float a, float b) { return min(a, b); } float sub(float a, float b) { return max(a, -b); } float subRound(float a, float b, float r) { vec2 u = max(vec2(r + a, r - b), vec2(0.0)); return min(-r, max(a, -b)) + length(u); } float mapDistance(vec3 p, inout float inner) { #define c(A) cos(A) #define s(A) sin(A) float tA = 0.5 * PI; float tB = PI * 0.5; float tC = -0.5 * PI; mat3 rXA = mat3(vec3(+c(tA), s(tA), 0.0), vec3(-s(tA), c(tA), 0.0), vec3(0.0, 0.0, 1.0)); mat3 rXB = mat3(vec3(+c(tC), s(tC), 0.0), vec3(-s(tC), c(tC), 0.0), vec3(0.0, 0.0, 1.0)); mat3 rYA = mat3(vec3(1.0, 0.0, 0.0), vec3(0.0, +c(tB), s(tB)), vec3(0.0, -s(tB), c(tB))); mat3 rotA = rXA * rYA; mat3 rotB = rXB * rYA; float disturb = atan(p.x, p.z); float disturbSin = sin(disturb * 9.0); disturbSin = 1.0 - (abs(disturbSin)); vec3 spherePos = vec3(0.0, 1.75, 0.0); float sphereRadius = 1.0; float sphereDist = sphereSDF(p - spherePos, sphereRadius); float sphereCarve = sphereSDF(p - spherePos, sphereRadius - 0.1); sphereDist = sub(sphereDist, sphereCarve); sphereDist = sphereDist + disturbSin * 0.021; float zOff = -0.7; float eDepth = 0.35; float e = triPrismSDF((p + vec3(+0.350, -2.250, zOff)) * rotA, vec3(0.22, eDepth, 0.5)); float e2 = triPrismSDF((p + vec3(-0.350, -2.250, zOff)) * rotA, vec3(0.22, eDepth, 0.5)); float e3 = triPrismSDF((p + vec3(+0.000, -2.000, zOff)) * rotA, vec3(0.15, eDepth, 0.5)); float e4 = triPrismSDF((p + vec3(-0.100, -1.700, zOff)) * rotA, vec3(0.16, eDepth, 0.5)); float e5 = triPrismSDF((p + vec3(+0.100, -1.700, zOff)) * rotA, vec3(0.16, eDepth, 0.5)); float e6 = triPrismSDF((p + vec3(+0.270, -1.750, zOff)) * rotA, vec3(0.16, eDepth, 0.6)); float e7 = triPrismSDF((p + vec3(-0.270, -1.750, zOff)) * rotA, vec3(0.16, eDepth, 0.6)); float e8 = triPrismSDF((p + vec3(+0.420, -1.800, zOff)) * rotA, vec3(0.16, eDepth, 0.4)); float e9 = triPrismSDF((p + vec3(-0.420, -1.800, zOff)) * rotA, vec3(0.16, eDepth, 0.4)); float e10 = triPrismSDF((p + vec3(+0.000, -1.570, zOff)) * rotB, vec3(0.18, eDepth, 0.7)); float e11 = triPrismSDF((p + vec3(-0.210, -1.610, zOff)) * rotB, vec3(0.17, eDepth, 0.5)); float e12 = triPrismSDF((p + vec3(+0.210, -1.610, zOff)) * rotB, vec3(0.17, eDepth, 0.5)); float e13 = triPrismSDF((p + vec3(+0.405, -1.655, zOff)) * rotB, vec3(0.17, eDepth, 0.5)); float e14 = triPrismSDF((p + vec3(-0.405, -1.655, zOff)) * rotB, vec3(0.17, eDepth, 0.5)); e = un(e, e2); e = un(e, e3); e = un(e, e4); e = un(e, e5); e = un(e, e6); e = un(e, e7); e = un(e, e8); e = un(e, e9); e = un(e, e10); e = un(e, e11); e = un(e, e12); e = un(e, e13); e = un(e, e14); sphereDist = sub(sphereDist, e); float groundDist = p.y + 2.2 - disturbRadius(0.5, p * 0.75) * 5.0; float dist = min(sphereDist, groundDist); inner = sphereSDF(p - spherePos, sphereRadius - 0.05); return dist; } float rayMarch(vec3 ro, vec3 rd, inout float inner) { float dist = 0.0; float innerDist; for (int i = 0; i < marchSteps; i++) { float inn; vec3 p = ro + rd * dist; float sceneDist = mapDistance(p, inn); innerDist += inn; dist += sceneDist; if (dist > 10.0 || sceneDist <= 0.003) { break; } } inner = innerDist; return dist; } vec3 getNormal(vec3 p) { float inner; float dist = mapDistance(p, inner); vec2 closeSample = vec2(0.01, 0.0); vec3 closeSampleV3 = vec3( mapDistance(p - closeSample.xyy, inner), mapDistance(p - closeSample.yxy, inner), mapDistance(p - closeSample.yyx, inner) ); vec3 normal = dist - closeSampleV3; return normalize(normal); } float getAmbientOcclusion(vec3 pos, vec3 nor) { float occ = 0.0; float sca = 1.0; float inner; for (int i = 0; i < 4; i++) { float h = 0.001 + 0.25 * float(i) / 4.0; float d = mapDistance(pos + h * nor, inner); occ += (h - d) * sca; sca *= 0.98; } return clamp(1.0 - 1.6 * occ, 0.0, 1.0); } float getSoftShadow(vec3 ro, vec3 rd, float tmin, float tmax) { float res = 1.0; float t = tmin; float ph = 1e10; float inner; for (int i = 0; i < 15; i++) { float h = mapDistance(ro + rd * t, inner); res = min(res, 10.0 * h / t); t += h; if (res < tmin || t > tmax) { break; } } return clamp(res, 0.0, 1.0); } vec3 getCameraPosition(void) { float acc = 0.0; const float camHeight = 3.0; const float camDistanceRadius = 3.5; float camPosX = sin(mouselerp.x * PI) * camDistanceRadius; float camPosY = camHeight; float camPosZ = cos(mouselerp.x * PI) * camDistanceRadius; vec3 ro = vec3(camPosX, camPosY, camPosZ); return ro; } mat3 calcLookAtMatrix(vec3 origin, vec3 target, float roll) { vec3 rr = vec3(sin(roll), cos(roll), 0.0); vec3 ww = normalize(target - origin); vec3 uu = normalize(cross(ww, rr)); vec3 vv = normalize(cross(uu, ww)); return mat3(uu, vv, ww); } vec3 getCameraTarget(vec2 uv, vec3 ro) { vec3 camTarget = vec3(0.0, 1.5, 0.0); float camRoll = 0.0; float fov = 1.0; mat3 camMatrix = calcLookAtMatrix(ro, camTarget, camRoll); vec3 rd = normalize(camMatrix * vec3(uv.x, uv.y, fov)); return rd; } vec4 render(vec2 uv) { float ambient = 0.15; float spec = 0.3; vec3 col = vec3(0.0); vec3 material = vec3(1.0, 0.5, 0.2) * 0.6; vec3 ro = getCameraPosition(); vec3 rd = getCameraTarget(uv, ro); float innerDist; float dist = rayMarch(ro, rd, innerDist); vec3 p = ro + rd * dist; vec3 ip = ro + rd * innerDist; vec3 normal = getNormal(p); vec3 light = normalize(vec3(2.5, 2.5, 3.0)); float l = clamp(dot(light, normal), 0.0, 1.0); vec3 ref = normalize(reflect(rd, -normal)); float r = clamp(dot(ref, light), 0.0, 1.0); float occlusion = getAmbientOcclusion(p, normal); float shadow = getSoftShadow(p, light, 0.2, 5.0); vec3 vShadow = vec3(max(shadow, ambient)); l = max(l, ambient); occlusion = max(occlusion, ambient); col += min(vShadow, l) * occlusion * material + pow(abs(r), 64.0) * spec; if (dist > 9.0) discard; if (p.y < 0.6) { col.bg *= 0.1; col *= 1.5; } col = mix(col, col * vec3(p.y), 0.6); vec3 ic = clamp((abs(ip) - innerDist), 0.0, 1.0) * 3.0; col += clamp((ic.x + ic.y + ic.z) / 3.0, 0.0, 1.0) * vec3(1.0, 0.9, 0.5); return vec4(col, 1.0); } void main(void) { vec2 uv = (gl_FragCoord.xy - resolution.xy * 0.5) / resolution.y; vec4 color = render(uv); vec3 grain = gaussGrain(time) * 0.03; color.xyz -= grain; fragColor = color; }
#version 300 es // ╔═════════════╦════════════════╗ // ║ Marco Gomez ║ https://mgz.me ║ // ╚═════════════╩════════════════╝ precision highp float; uniform sampler2D prgm1Texture; uniform vec2 resolution; uniform float time; uniform int frame; out vec4 fragColor; vec3 hash33(vec3 p3) { p3 = fract(p3 * vec3(0.1031, 0.1030, 0.0973)); p3 += dot(p3, p3.yxz + 19.19); return fract((p3.xxy + p3.yxx) * p3.zyx); } void main(void) { vec2 uv = gl_FragCoord.xy / resolution.xy; vec4 col = vec4(0.0); float w = 0.1; vec2 a = vec2(uv.x - 0.5, uv.y - 0.66); vec2 b = a * 0.15 / float(10.0); vec3 h = hash33(vec3(gl_FragCoord.xy, frame)); uv += b * h.x * 0.1; for (float i = 1.0; i > 0.985; i-= 0.0005) { uv -= 0.5; uv *= i; uv += 0.5; vec4 tex = texture(prgm1Texture, uv) * w * 1.2; if ((tex.r + tex.g) / 2.5 > tex.b) col += tex * 0.6; w *= 0.95; } col *= 0.95; fragColor = clamp(col, 0.0, 1.0); }
#version 300 es // ╔═════════════╦════════════════╗ // ║ Marco Gomez ║ https://mgz.me ║ // ╚═════════════╩════════════════╝ precision highp float; #define inputTexture prgm2Texture uniform sampler2D prgm1Texture; uniform sampler2D prgm2Texture; uniform vec2 resolution; uniform float time; uniform float fft; out vec4 fragColor; const float amount = 1.0; const float reinhardAmount = 1.0; const float contrast = 0.9; const float brightness = 1.7; const float saturation = 0.6; const vec2 vignetteSize = vec2(0.25, 0.25); const float vignetteRoundness = 0.5; const float vignetteMix = 0.7; const float vignetteSmoothness = 0.42; const float W = 1.2; const float T = 7.5; float filmicReinhardCurve(float x) { float q = (T * T + 1.0) * x * x; return q / (q + x + T * T); } vec3 filmicReinhard(vec3 c) { float w = filmicReinhardCurve(W); return vec3( filmicReinhardCurve(c.r), filmicReinhardCurve(c.g), filmicReinhardCurve(c.b) ) / w; } vec3 contrastSaturationBrightness(vec3 color, float brt, float sat, float con) { const float AvgLumR = 0.5; const float AvgLumG = 0.5; const float AvgLumB = 0.5; const vec3 LumCoeff = vec3(0.2125, 0.7154, 0.0721); vec3 AvgLumin = vec3(AvgLumR, AvgLumG, AvgLumB); vec3 brtColor = color * brt; vec3 intensity = vec3(dot(brtColor, LumCoeff)); vec3 satColor = mix(intensity, brtColor, sat); vec3 conColor = mix(AvgLumin, satColor, con); return conColor; } float sdSquare(vec2 point, float width) { vec2 d = abs(point) - width; return min(max(d.x, d.y), 0.0) + length(max(d, 0.0)); } float vignette(vec2 uv, vec2 size, float roundness, float smoothness) { uv -= 0.5; float minWidth = min(size.x, size.y); uv.x = sign(uv.x) * clamp(abs(uv.x) - abs(minWidth - size.x), 0.0, 1.0); uv.y = sign(uv.y) * clamp(abs(uv.y) - abs(minWidth - size.y), 0.0, 1.0); float boxSize = minWidth * (1.0 - roundness); float dist = sdSquare(uv, boxSize) - (minWidth * roundness); return 1.0 - smoothstep(0.0, smoothness, dist); } void main(void) { vec2 uv = gl_FragCoord.xy / resolution.xy; vec4 tex = texture(inputTexture, uv); vec3 reinhard = filmicReinhard(tex.rgb); vec3 color = tex.rgb; color = mix(color, reinhard, reinhardAmount); color = contrastSaturationBrightness(color, brightness, saturation, contrast); float v = vignette(uv, vignetteSize, vignetteRoundness, vignetteSmoothness); vec3 vig = color * v; color = mix(color, vig, vignetteMix); color = mix(tex.xyz, color, amount); color = clamp(color, 0.0, 1.0); color = clamp(mix(texture(prgm1Texture, uv).rgb, color, 0.7), 0.0, 1.0); fragColor = vec4(color, 1.0); }
#version 300 es // ╔═════════════╦════════════════╗ // ║ Marco Gomez ║ https://mgz.me ║ // ╚═════════════╩════════════════╝ precision highp float; #define inputTexture prgm3Texture uniform sampler2D prgm3Texture; uniform vec2 resolution; uniform float time; out vec4 fragColor; const float PI = acos(-1.0); const float TAU = PI * 2.0; const float hardscan = -8.0; const float hardPix = -2.0; const float maskDark = 0.5; const float maskLight = 1.5; float toLinear(float c) { return (c <= 0.04045) ? c / 12.92 : pow(abs((c + 0.055) / 1.055), 2.4); } vec3 toLinear(vec3 c) { return vec3(toLinear(c.r), toLinear(c.g), toLinear(c.b)); } float toSRGB(float c) { return(c < 0.0031308 ? c * 12.92 : 1.055 * pow(abs(c), 0.41666) - 0.055); } vec3 toSRGB(vec3 c) { return vec3(toSRGB(c.r), toSRGB(c.g), toSRGB(c.b)); } vec3 fetch(vec2 pos, vec2 off, vec2 res) { pos = floor(pos * res + off) / res; if (max(abs(pos.x - 0.5), abs(pos.y - 0.5)) > 0.5) { return vec3(0.0); } return toLinear(texture(inputTexture, pos.xy, -16.0).xyz); } vec2 dist(vec2 pos, vec2 res) { pos = pos * res; return -((pos - floor(pos)) - vec2(0.5)); } float gauss(float pos, float scale) { return exp2(scale * pos * pos); } vec3 horz3(vec2 pos, float off, vec2 res) { vec3 b = fetch(pos, vec2(-1.0, off), res); vec3 c = fetch(pos, vec2(+0.0, off), res); vec3 d = fetch(pos, vec2(+1.0, off), res); float dst = dist(pos, res).x; float scale = hardPix; float wb = gauss(dst - 1.0, scale); float wc = gauss(dst + 0.0, scale); float wd = gauss(dst + 1.0, scale); return (b * wb + c * wc + d * wd) / (wb + wc + wd); } vec3 horz5(vec2 pos, float off, vec2 res) { vec3 a = fetch(pos, vec2(-2.0, off), res); vec3 b = fetch(pos, vec2(-1.0, off), res); vec3 c = fetch(pos, vec2(+0.0, off), res); vec3 d = fetch(pos, vec2(+1.0, off), res); vec3 e = fetch(pos, vec2(+2.0, off), res); float dst = dist(pos, res).x; float scale = hardPix; float wa = gauss(dst - 2.0, scale); float wb = gauss(dst - 1.0, scale); float wc = gauss(dst + 0.0, scale); float wd = gauss(dst + 1.0, scale); float we = gauss(dst + 2.0, scale); return (a * wa + b * wb + c * wc + d * wd + e * we) / (wa + wb + wc + wd + we); } float scan(vec2 pos, float off, vec2 res) { float dst = dist(pos, res).y; return gauss(dst + off, hardscan); } vec3 tri(vec2 pos, vec2 res) { vec3 a = horz3(pos, -1.0, res); vec3 b = horz5(pos, +0.0, res); vec3 c = horz3(pos, +1.0, res); float wa = scan(pos, -1.0, res); float wb = scan(pos, +0.0, res); float wc = scan(pos, +1.0, res); return a * wa + b * wb + c * wc; } vec3 mask(vec2 pos) { pos.x += pos.y * 3.0; vec3 m = vec3(maskDark, maskDark, maskDark); pos.x = fract(pos.x / 6.0); if (pos.x < 0.333) { m.r = maskLight; } else if (pos.x < 0.666) { m.g = maskLight; } else { m.b = maskLight; } return m; } float bar(float pos, float bar) { pos -= bar; return pos * pos < 4.0 ? 0.0 : 1.0; } float rand(vec2 uv, float t) { float seed = dot(uv, vec2(12.9898, 78.233)); return fract(sin(seed) * 43758.5453123 + t); } float gaussian(float z, float u, float o) { return ( (1.0 / (o * sqrt(TAU))) * (exp(-(((z - u) * (z - u)) / (2.0 * (o * o))))) ); } vec3 gaussgrain(float t) { vec2 ps = vec2(1.0) / resolution.xy; vec2 uv = gl_FragCoord.xy * ps; float noise = rand(uv, t); noise = gaussian(noise, 0.0, 0.5); return vec3(noise); } void drawVig(inout vec3 color, vec2 uv) { float vignette = uv.x * uv.y * (1.0 - uv.x) * (1.0 - uv.y); vignette = clamp(pow(abs(16.0 * vignette), 0.1), 0.0, 1.0); color = mix(color, color * vignette, 0.7); } void main(void) { vec2 res = vec2(800.0, 600.0); vec2 uv = gl_FragCoord.xy / resolution.xy; float vig = (0.0 + 1.0 * 21.0 * uv.x * uv.y * (1.0 - uv.x) * (1.0 - uv.y)); float v = exp(-0.01 * length(uv)) * vig; float frameScale = 29.97; float frameTime = floor(time * frameScale) / frameScale; vec3 g = gaussgrain(frameTime) * 0.07; vec4 color = vec4(tri(uv, res) * mask(gl_FragCoord.xy), 1.0); color.xyz = toSRGB(color.xyz * 2.0) - g; color = mix(color, color * v, 0.7); drawVig(color.xyz, uv); fragColor = color; }
xxxxxxxxxx
// ╔═════════════╦════════════════╗
// ║ Marco Gomez ║ https://mgz.me ║
// ╚═════════════╩════════════════╝
precision highp float;
uniform sampler2D prgm4Texture;
uniform vec2 resolution;
uniform float time;
out vec4 fragColor;
void main(void) {
vec2 uv = gl_FragCoord.xy / resolution.xy;
vec4 tex = texture(prgm4Texture, uv);
fragColor = tex;
}
87 fps 15ms
00:00:00.40
0.00