241 lines
5.4 KiB
GLSL
241 lines
5.4 KiB
GLSL
/*
|
|
|
|
Hyper Tunnel from "Sailing Beyond" (demoscene producion)
|
|
|
|
https://www.youtube.com/watch?v=oITx9xMrAcM&
|
|
https://www.pouet.net/prod.php?which=77899
|
|
|
|
|
|
*/
|
|
|
|
|
|
/*
|
|
http://bit.ly/shadertoy-plugin
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#pragma optimize(off)
|
|
|
|
|
|
|
|
|
|
|
|
#define getNormal getNormalHex
|
|
|
|
#define FAR 1e3
|
|
#define INFINITY 1e32
|
|
|
|
#define T iTime
|
|
#define mt (iChannelTime[0] > 0. ? iChannelTime[0] : iTime)
|
|
#define FOV 70.0
|
|
#define FOG .06
|
|
|
|
#define PI 3.14159265
|
|
#define TAU (2*PI)
|
|
#define PHI (1.618033988749895)
|
|
|
|
float vol = 0.;
|
|
|
|
float hash12(vec2 p) {
|
|
float h = dot(p,vec2(127.1,311.7));
|
|
return fract(sin(h)*43758.5453123);
|
|
}
|
|
|
|
// 3d noise
|
|
float noise_3(in vec3 p) {
|
|
vec3 i = floor(p);
|
|
vec3 f = fract(p);
|
|
vec3 u = 1.-(--f)*f*f*f*-f;
|
|
|
|
vec2 ii = i.xy + i.z * vec2(5.0);
|
|
float a = hash12( ii + vec2(0.0,0.0) );
|
|
float b = hash12( ii + vec2(1.0,0.0) );
|
|
float c = hash12( ii + vec2(0.0,1.0) );
|
|
float d = hash12( ii + vec2(1.0,1.0) );
|
|
float v1 = mix(mix(a,b,u.x), mix(c,d,u.x), u.y);
|
|
|
|
ii += vec2(5.0);
|
|
a = hash12( ii + vec2(0.0,0.0) );
|
|
b = hash12( ii + vec2(1.0,0.0) );
|
|
c = hash12( ii + vec2(0.0,1.0) );
|
|
d = hash12( ii + vec2(1.0,1.0) );
|
|
float v2 = mix(mix(a,b,u.x), mix(c,d,u.x), u.y);
|
|
|
|
return max(mix(v1,v2,u.z),0.);
|
|
}
|
|
|
|
float fbm(vec3 x)
|
|
{
|
|
float r = 0.0;
|
|
float w = 1.0, s = 1.0;
|
|
for (int i=0; i<4; i++)
|
|
{
|
|
w *= 0.25;
|
|
s *= 3.;
|
|
r += w * noise_3(s * x);
|
|
}
|
|
return r;
|
|
}
|
|
|
|
float yC(float x) {
|
|
return cos(x * -.134) * 1. * sin(x * .13) * 15.+ fbm(vec3(x * .1, 0., 0.) * 55.4);
|
|
}
|
|
|
|
void pR(inout vec2 p, float a) {
|
|
p = cos(a)*p + sin(a)*vec2(p.y, -p.x);
|
|
}
|
|
|
|
struct geometry {
|
|
float dist;
|
|
vec3 hit;
|
|
int iterations;
|
|
};
|
|
|
|
|
|
// Cylinder with infinite height
|
|
float fCylinderInf(vec3 p, float r) {
|
|
return length(p.xz) - r;
|
|
}
|
|
|
|
geometry map(vec3 p) {
|
|
p.x -= yC(p.y * .1) * 3.;
|
|
p.z += yC(p.y * .01) * 4.;
|
|
|
|
float n = pow(abs(fbm(p * .06 )) * 12., 1.3);
|
|
float s = fbm(p * 0.01 + vec3(0., T * 0.14, 0.)) * 128.;
|
|
|
|
geometry obj;
|
|
|
|
obj.dist = max(0., -fCylinderInf(p, s + 18. -n));
|
|
|
|
p.x -= sin(p.y * .02) * 34. + cos(p.z * 0.01) * 62.;
|
|
|
|
obj.dist = max(obj.dist, -fCylinderInf(p, s + 28. + n * 2.));
|
|
|
|
return obj;
|
|
}
|
|
|
|
|
|
float t_min = 10.0;
|
|
float t_max = FAR;
|
|
const int MAX_ITERATIONS = 100;
|
|
|
|
geometry trace(vec3 o, vec3 d) {
|
|
float omega = 1.3;
|
|
float t = t_min;
|
|
float candidate_error = INFINITY;
|
|
float candidate_t = t_min;
|
|
float previousRadius = 0.;
|
|
float stepLength = 0.;
|
|
float pixelRadius = 1./ 1000.;
|
|
|
|
geometry mp = map(o);
|
|
|
|
float functionSign = mp.dist < 0. ? -1. : +1.;
|
|
float minDist = FAR;
|
|
|
|
for (int i = 0; i < MAX_ITERATIONS; ++i) {
|
|
|
|
mp = map(d * t + o);
|
|
mp.iterations = i;
|
|
|
|
float signedRadius = functionSign * mp.dist;
|
|
float radius = abs(signedRadius);
|
|
bool sorFail = omega > 1. &&
|
|
(radius + previousRadius) < stepLength;
|
|
|
|
if (sorFail) {
|
|
stepLength -= omega * stepLength;
|
|
omega = 1.;
|
|
} else {
|
|
stepLength = signedRadius * omega;
|
|
}
|
|
previousRadius = radius;
|
|
float error = radius / t;
|
|
|
|
if (!sorFail && error < candidate_error) {
|
|
candidate_t = t;
|
|
candidate_error = error;
|
|
}
|
|
|
|
if (!sorFail && error < pixelRadius || t > t_max) break;
|
|
|
|
t += stepLength * .5; // ;(
|
|
}
|
|
|
|
mp.dist = candidate_t;
|
|
|
|
if (
|
|
(t > t_max || candidate_error > pixelRadius)
|
|
) mp.dist = INFINITY;
|
|
|
|
|
|
return mp;
|
|
}
|
|
|
|
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
|
|
|
vec2 ouv = fragCoord.xy / iResolution.xy;
|
|
vec2 uv = ouv - .5;
|
|
|
|
uv *= tan(radians (FOV) / 2.0) * 4.;
|
|
|
|
vec3
|
|
vuv = normalize(vec3(cos(T), sin(T * .11), sin(T * .41))), // up
|
|
ro = vec3(0., 30. + iTime * 100., -.1);
|
|
|
|
ro.x += yC(ro.y * .1) * 3.;
|
|
ro.z -= yC(ro.y * .01) * 4.;
|
|
|
|
vec3 vrp = vec3(0., 50. + iTime * 100., 2.);
|
|
|
|
vrp.x += yC(vrp.y * .1) * 3.;
|
|
vrp.z -= yC(vrp.y * .01) * 4.;
|
|
|
|
vec3
|
|
vpn = normalize(vrp - ro),
|
|
u = normalize(cross(vuv, vpn)),
|
|
v = cross(vpn, u),
|
|
vcv = (ro + vpn),
|
|
scrCoord = (vcv + uv.x * u * iResolution.x/iResolution.y + uv.y * v),
|
|
rd = normalize(scrCoord - ro),
|
|
oro = ro;
|
|
|
|
vec3 sceneColor = vec3(0.);
|
|
|
|
geometry tr = trace(ro, rd);
|
|
|
|
tr.hit = ro + rd * tr.dist;
|
|
|
|
vec3 col = vec3(1., 0.5, .4) * fbm(tr.hit.xzy * .01) * 20.;
|
|
col.b *= fbm(tr.hit * .01) * 10.;
|
|
|
|
sceneColor += min(.8, float(tr.iterations) / 90.) * col + col * .03;
|
|
sceneColor *= 1. + .9 * (abs(fbm(tr.hit * .002 + 3.) * 10.) * (fbm(vec3(0.,0.,iTime * .05) * 2.)) * 1.);
|
|
sceneColor = pow(sceneColor, vec3(1.)) * (iChannelTime[0] > 0. ? texelFetch(iChannel0, ivec2(128, 0), 0).r * min(1., mt * .1) : 0.6);
|
|
|
|
vec3 steamColor1 = vec3(.0, .4, .5);
|
|
vec3 rro = oro;
|
|
|
|
ro = tr.hit;
|
|
|
|
float distC = tr.dist, f = 0., st = .9;
|
|
|
|
for (float i = 0.; i < 24.; i++) {
|
|
rro = ro - rd * distC;
|
|
f += fbm(rro * vec3(.1, .1, .1) * .3) * .1;
|
|
distC -= 3.;
|
|
if (distC < 3.) break;
|
|
}
|
|
|
|
steamColor1 *= iChannelTime[0] > 0. ? texelFetch(iChannel0, ivec2(32, 0), 0).r : 1.;
|
|
sceneColor += steamColor1 * pow(abs(f * 1.5), 3.) * 4.;
|
|
|
|
fragColor = vec4(clamp(sceneColor * (1. - length(uv) / 2.), 0.0, 1.0), 1.0);
|
|
fragColor = pow(abs(fragColor / tr.dist * 130.), vec4(.8));
|
|
|
|
}
|