content/hifi-content/caitlyn/scratch/cloudTunnel.fs
2022-02-13 22:19:19 +01:00

394 lines
No EOL
9.7 KiB
GLSL

// srtuss, 2015
// volumetric cloud tunnel, a single light source, lightning and something that is supposed
// to look like raindrops. :)
// visuals are inspired by a piece of music, 2d-texture based 3d noise function by iq.
// the code could need some cleaning, but i don't want to do that right now.
// *******************************************************************************************
// Please do NOT use this shader in your own productions/videos/games without my permission!
// If you'd still like to do so, please drop me a mail (stral@aon.at)
// *******************************************************************************************
#line 2
#define pi 3.1415926535897932384626433832795
vec3 iResolution = iWorldScale.xyz;
vec2 iMouse = vec2(0);
struct ITSC
{
vec3 p;
float dist;
vec3 n;
vec2 uv;
};
ITSC raycylh(vec3 ro, vec3 rd, vec3 c, float r)
{
ITSC i;
i.dist = 1e38;
vec3 e = ro - c;
float a = dot(rd.xy, rd.xy);
float b = 2.0 * dot(e.xy, rd.xy);
float cc = dot(e.xy, e.xy) - r;
float f = b * b - 4.0 * a * cc;
if(f > 0.0)
{
f = sqrt(f);
float t = (-b + f) / (2.0 * a);
if(t > 0.001)
{
i.dist = t;
i.p = e + rd * t;
i.n = -vec3(normalize(i.p.xy), 0.0);
}
}
return i;
}
void tPlane(inout ITSC hit, vec3 ro, vec3 rd, vec3 o, vec3 n, vec3 tg, vec2 si)
{
vec2 uv;
ro -= o;
float t = -dot(ro, n) / dot(rd, n);
if(t < 0.0)
return;
vec3 its = ro + rd * t;
uv.x = dot(its, tg);
uv.y = dot(its, cross(tg, n));
if(abs(uv.x) > si.x || abs(uv.y) > si.y)
return;
//if(t < hit.dist)
{
hit.dist = t;
hit.uv = uv;
}
return;
}
float hsh(float x)
{
return fract(sin(x * 297.9712) * 90872.2961);
}
float nseI(float x)
{
float fl = floor(x);
return mix(hsh(fl), hsh(fl + 1.0), smoothstep(0.0, 1.0, fract(x)));
}
vec2 rotate(vec2 p, float a)
{
return vec2(p.x * cos(a) - p.y * sin(a), p.x * sin(a) + p.y * cos(a));
}
float nse3d(in vec3 x)
{
vec3 p = floor(x);
vec3 f = fract(x);
f = f * f * (3.0 - 2.0 * f);
vec2 uv = (p.xy + vec2(37.0, 17.0) * p.z) + f.xy;
vec2 rg = textureLod( iChannel0, (uv+.5)/256., 0.).yx;
return mix(rg.x, rg.y, f.z);
}
float nse(vec2 p)
{
return texture(iChannel0, p).x;
}
float density2(vec2 p, float z, float t)
{
float v = 0.0;
float fq = 1.0, am = 0.5, mvfd = 1.0;
vec2 rnd = vec2(0.3, 0.7);
for(int i = 0; i < 7; i++)
{
rnd = fract(sin(rnd * 14.4982) * 2987253.28612);
v += nse(p * fq + t * (rnd - 0.5)) * am;
fq *= 2.0;
am *= 0.5;
mvfd *= 1.3;
}
return v * exp(z * z * -2.0);
}
float densA = 1.0, densB = 2.0;
float fbm(vec3 p)
{
vec3 q = p;
//q.xy = rotate(p.xy, iTime);
p += (nse3d(p * 3.0) - 0.5) * 0.3;
//float v = nse3d(p) * 0.5 + nse3d(p * 2.0) * 0.25 + nse3d(p * 4.0) * 0.125 + nse3d(p * 8.0) * 0.0625;
//p.y += iTime * 0.2;
float mtn = iTime * 0.15;
float v = 0.0;
float fq = 1.0, am = 0.5;
for(int i = 0; i < 6; i++)
{
v += nse3d(p * fq + mtn * fq) * am;
fq *= 2.0;
am *= 0.5;
}
return v;
}
float fbmHQ(vec3 p)
{
vec3 q = p;
q.xy = rotate(p.xy, iTime);
p += (nse3d(p * 3.0) - 0.5) * 0.4;
//float v = nse3d(p) * 0.5 + nse3d(p * 2.0) * 0.25 + nse3d(p * 4.0) * 0.125 + nse3d(p * 8.0) * 0.0625;
//p.y += iTime * 0.2;
float mtn = iTime * 0.2;
float v = 0.0;
float fq = 1.0, am = 0.5;
for(int i = 0; i < 9; i++)
{
v += nse3d(p * fq + mtn * fq) * am;
fq *= 2.0;
am *= 0.5;
}
return v;
}
float density(vec3 p)
{
vec2 pol = vec2(atan(p.y, p.x), length(p.yx));
float v = fbm(p);
float fo = (pol.y - 1.5);//(densA + densB) * 0.5);
//fo *= (densB - densA);
v *= exp(fo * fo * -5.0);
float edg = 0.3;
return smoothstep(edg, edg + 0.1, v);
}
float densityHQ(vec3 p)
{
vec2 pol = vec2(atan(p.y, p.x), length(p.yx));
float v = fbmHQ(p);
float fo = (pol.y - 1.5);//(densA + densB) * 0.5);
//fo *= (densB - densA);
v *= exp(fo * fo * -5.0);
float edg = 0.3;
return smoothstep(edg, edg + 0.1, v);
}
vec2 drop(inout vec2 p)
{
vec2 mv = iTime * vec2(0.5, -1.0) * 0.15;
float drh = 0.0;
float hl = 0.0;
vec4 rnd = vec4(0.1, 0.2, 0.3, 0.4);
for(int i = 0; i < 20; i++)
{
rnd = fract(sin(rnd * 2.184972) * 190723.58961);
float fd = fract(iTime * 0.2 + rnd.w);
fd = exp(fd * -4.0);
float r = 0.025 * (rnd.w * 1.5 + 1.0);
float sz = 0.35;
vec2 q = (fract((p - mv) * sz + rnd.xy) - 0.5) / sz;
mv *= 1.06;
q.y *= -1.0;
float l = length(q + pow(abs(dot(q, vec2(1.0, 0.4))), 0.7) * (fd * 0.2 + 0.1));
if(l < r)
{
float h = sqrt(r * r - l * l);
drh = max(drh, h * fd);
}
hl += exp(length(q - vec2(-0.02, 0.01)) * -30.0) * 0.4 * fd;
}
p += drh * 5.0;
return vec2(drh, hl);
}
float hash1(float p)
{
return fract(sin(p * 172.435) * 29572.683) - 0.5;
}
float hash2(vec2 p)
{
vec2 r = (456.789 * sin(789.123 * p.xy));
return fract(r.x * r.y * (1.0 + p.x));
}
float ns(float p)
{
float fr = fract(p);
float fl = floor(p);
return mix(hash1(fl), hash1(fl + 1.0), fr);
}
float fbm(float p)
{
return (ns(p) * 0.4 + ns(p * 2.0 - 10.0) * 0.125 + ns(p * 8.0 + 10.0) * 0.025);
}
float fbmd(float p)
{
float h = 0.01;
return atan(fbm(p + h) - fbm(p - h), h);
}
float arcsmp(float x, float seed)
{
return fbm(x * 3.0 + seed * 1111.111) * (1.0 - exp(-x * 5.0));
}
float arc(vec2 p, float seed, float len)
{
p *= len;
//p = rotate(p, iTime);
float v = abs(p.y - arcsmp(p.x, seed));
v += exp((2.0 - p.x) * -4.0);
v = exp(v * -60.0) + exp(v * -10.0) * 0.6;
//v += exp(p.x * -2.0);
v *= smoothstep(0.0, 0.05, p.x);
return v;
}
float arcc(vec2 p, float sd)
{
float v = 0.0;
float rnd = fract(sd);
float sp = 0.0;
v += arc(p, sd, 1.0);
for(int i = 0; i < 4; i ++)
{
sp = rnd + 0.01;
vec2 mrk = vec2(sp, arcsmp(sp, sd));
v += arc(rotate(p - mrk, fbmd(sp)), mrk.x, mrk.x * 0.4 + 1.5);
rnd = fract(sin(rnd * 195.2837) * 1720.938);
}
return v;
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = fragCoord.xy / iResolution.xy;
uv = 2.0 * uv - 1.0;
uv.x *= iResolution.x / iResolution.y;
vec2 drh = drop(uv);
float camtm = iTime * 0.15;
vec3 ro = vec3(cos(camtm), 0.0, camtm);
vec3 rd = normalize(vec3(uv, 1.2));
rd.xz = rotate(rd.xz, sin(camtm) * 0.4);
rd.yz = rotate(rd.yz, sin(camtm * 1.3) * 0.4);
vec3 sun = normalize(vec3(0.2, 1.0, 0.1));
float sd = sin(fragCoord.x * 0.01 + fragCoord.y * 3.333333333 + iTime) * 1298729.146861;
vec3 col;
float dacc = 0.0, lacc = 0.0;
vec3 light = vec3(cos(iTime * 8.0) * 0.5, sin(iTime * 4.0) * 0.5, ro.z + 4.0 + sin(iTime));
ITSC tunRef;
#define STP 15
for(int i = 0; i < STP; i++)
{
ITSC itsc = raycylh(ro, rd, vec3(0.0), densB + float(i) * (densA - densB) / float(STP) + fract(sd) * 0.07);
float d = density(itsc.p);
vec3 tol = light - itsc.p;
float dtol = length(tol);
tol = tol * 0.1 / dtol;
float dl = density(itsc.p + tol);
lacc += max(d - dl, 0.0) * exp(dtol * -0.2);
dacc += d;
tunRef = itsc;
}
dacc /= float(STP);
ITSC itsc = raycylh(ro, rd, vec3(0.0), 4.0);
vec3 sky = vec3(0.6, 0.3, 0.2);
sky *= 0.9 * pow(fbmHQ(itsc.p), 2.0);
lacc = max(lacc * 0.3 + 0.3, 0.0);
vec3 cloud = pow(vec3(lacc), vec3(0.7, 1.0, 1.0) * 1.0);
col = mix(sky, cloud, dacc);
col *= exp(tunRef.dist * -0.1);
col += drh.y;
vec4 rnd = vec4(0.1, 0.2, 0.3, 0.4);
float arcv = 0.0, arclight = 0.0;
for(int i = 0; i < 3; i++)
{
float v = 0.0;
rnd = fract(sin(rnd * 1.111111) * 298729.258972);
float ts = rnd.z * 4.0 * 1.61803398875 + 1.0;
float arcfl = floor(iTime / ts + rnd.y) * ts;
float arcfr = fract(iTime / ts + rnd.y) * ts;
ITSC arcits;
arcits.dist = 1e38;
float arca = rnd.x + arcfl * 2.39996;
float arcz = ro.z + 1.0 + rnd.x * 12.0;
tPlane(arcits, ro, rd, vec3(0.0, 0.0, arcz), vec3(0.0, 0.0, -1.0), vec3(cos(arca), sin(arca), 0.0), vec2(2.0));
float arcseed = floor(iTime * 17.0 + rnd.y);
if(arcits.dist < 20.0)
{
arcits.uv *= 0.8;
v = arcc(vec2(1.0 - abs(arcits.uv.x), arcits.uv.y * sign(arcits.uv.x)) * 1.4, arcseed * 0.033333);
}
float arcdur = rnd.x * 0.2 + 0.05;
float arcint = smoothstep(0.1 + arcdur, arcdur, arcfr);
v *= arcint;
arcv += v;
arclight += exp(abs(arcz - tunRef.p.z) * -0.3) * fract(sin(arcseed) * 198721.6231) * arcint;
}
vec3 arccol = vec3(0.9, 0.7, 0.7);
col += arclight * arccol * 0.5;
col = mix(col, arccol, clamp(arcv, 0.0, 1.0));
col = pow(col, vec3(1.0, 0.8, 0.5) * 1.5) * 1.5;
col = pow(col, vec3(1.0 / 2.2));
fragColor = vec4(col, 1.0);
}
vec3 getSkyboxColor()
{
vec3 rayDirection = normalize(_normal);
vec2 position = rayDirection.xy;
position += 0.5;
position.y = 1.0 - position.y;
//position.y = 0 + position.y; //180° turn
vec4 result;
mainImage(result, position * iWorldScale.xy);
return result.xyz;
}