nix-config/config/analys.frag

224 lines
6.3 KiB
GLSL

precision mediump float;
varying vec2 v_texcoord;
uniform sampler2D tex;
uniform float time;
// Analys cube
// (c) 2019 FMS_Cat, MIT License
// == tweak these numbers, yee =====================================================================
#define SIZE 0.5
#define FX_NYOOOM 0.0
#define FX_FORWARD 1.0
#define FX_KICK (0.1*exp(-3.0*mod(BEAT,4.0)))
#define FX_TWIST (20.0*exp(-3.0*mod(BEAT-2.0,4.0)))
#define FX_SKEW 0.0
#define FX_DEFORM (0.2*0.0)
#define FX_DEFORM_FREQ 0.1
// == raymarch related constants ===================================================================
#define MARCH_ITER 64
#define MARCH_EPSILON 1E-4
#define MARCH_NEAR 0.01
#define MARCH_FAR 40.0
#define MARCH_MULP 0.6
// == common macros ================================================================================
#define HALF_PI 1.57079632679
#define PI 3.14159265359
#define TAU 6.28318530718
#define BEAT (time*170.0/60.0)
#define saturate(i) clamp(i,0.,1.)
#define linearstep(a,b,t) saturate(((t)-(a))/((b)-(a)))
// == common functions =============================================================================
mat2 rotate2D( float t ) {
return mat2( cos( t ), -sin( t ), sin( t ), cos( t ) );
}
// == camera =======================================================================================
struct Camera {
vec3 pos;
vec3 dir;
vec3 up;
float roll;
float fov;
};
Camera newCamera( vec3 pos, vec3 dir ) {
Camera camera;
camera.pos = pos;
camera.dir = dir;
camera.up = vec3( 0.0, 1.0, 0.0 );
camera.roll = 0.0;
camera.fov = 0.5;
return camera;
}
// == ray ==========================================================================================
struct Ray {
vec3 orig;
vec3 dir;
};
Ray newRay( vec3 ori, vec3 dir ) {
Ray ray;
ray.orig = ori;
ray.dir = dir;
return ray;
}
Ray rayFromCamera( Camera camera, vec2 p ) {
vec3 dirX = normalize( cross( camera.dir, camera.up ) );
vec3 dirY = cross( dirX, camera.dir );
vec2 pt = rotate2D( camera.roll ) * p;
return newRay(
camera.pos,
normalize( pt.x * dirX + pt.y * dirY + camera.dir / tan( camera.fov ) )
);
}
vec3 getRayPosition( Ray ray, float len ) {
return ray.orig + ray.dir * len;
}
// == isect ========================================================================================
struct Intersection {
Ray ray;
float len;
vec3 pos;
};
Intersection newIntersection( Ray ray, float len ) {
Intersection isect;
isect.ray = ray;
isect.len = len;
isect.pos = getRayPosition( ray, len );
return isect;
}
// == march result =================================================================================
struct MarchResult {
float dist;
vec2 uv;
};
// == distFuncs ====================================================================================
float distFuncBox( vec3 p, vec3 b ) {
vec3 d = abs( p ) - b;
return length( max( d, 0.0 ) ) + min( max( d.x, max( d.y, d.z ) ), 0.0 );
}
vec3 deform( vec3 p ) {
vec3 pt = p;
pt.xy = rotate2D( FX_SKEW * pt.z ) * pt.xy;
pt.x *= 1.0 - sqrt( FX_NYOOOM );
pt.yz = rotate2D( FX_NYOOOM * exp( 5.0 * FX_NYOOOM ) * pt.x ) * pt.yz;
pt.y += 2.0 * FX_SKEW * pt.x;
pt += FX_DEFORM * (
texture2D( tex, FX_DEFORM_FREQ * ( pt.xy ) + 0.5 ).xyz - 0.5
);
pt.zx = rotate2D( mod( 2.5 * time + PI, TAU ) + FX_TWIST * pt.y ) * pt.zx;
pt.xy = rotate2D( 0.6 * sin( 0.9 * time ) ) * pt.xy;
pt.yz = rotate2D( 0.6 * sin( 1.4 * time ) ) * pt.yz;
pt -= normalize( pt ) * FX_KICK * sin( 15.0 * length( pt ) - 40.0 * time );
return pt;
}
MarchResult distFunc( vec3 p ) {
MarchResult result;
vec3 pt = p;
pt = deform( pt );
result.dist = distFuncBox( pt, vec3( SIZE ) );
vec3 spt = vec3( 1.0 );
if ( FX_FORWARD > 0.0 ) {
vec3 ptIfs = p;
ptIfs.z = mod( ptIfs.z - 16.0 * time + 3.0 * sin( HALF_PI * BEAT + 0.5 ), 6.0 ) - 3.0;
for ( int i = 0; i < 6; i ++ ) {
float fi = float( i );
spt *= sign( ptIfs );
ptIfs = abs( ptIfs ) - vec3( 3.2, 4.5, 1.2 ) / max( 1E-2, FX_FORWARD ) * pow( 0.5, fi );
ptIfs.xy = rotate2D( 1.1 ) * ptIfs.xy;
ptIfs.zx = rotate2D( 2.1 ) * ptIfs.zx;
}
ptIfs = deform( ptIfs );
float distIfs = distFuncBox( ptIfs, vec3( SIZE ) );
if ( result.dist < distIfs ) {
spt = vec3( 1.0 );
} else {
result.dist = distIfs;
pt = ptIfs;
}
}
vec3 abspt = abs( pt );
float n = max( abspt.x, max( abspt.y, abspt.z ) );
result.uv = 0.5 + (
( n == abspt.z ) ? ( pt.xy * vec2( sign( pt.z ), 1.0 ) ) :
( n == abspt.x ) ? ( pt.zy * vec2( -sign( pt.x ), 1.0 ) ) :
( pt.xz * vec2( 1.0, -sign( pt.y ) ) )
) * spt.x * spt.y * spt.z * 0.5 / SIZE;
return result;
}
vec3 normalFunc( vec3 p, float dd ) {
vec2 d = vec2( 0.0, dd );
return normalize( vec3(
distFunc( p + d.yxx ).dist - distFunc( p - d.yxx ).dist,
distFunc( p + d.xyx ).dist - distFunc( p - d.xyx ).dist,
distFunc( p + d.xxy ).dist - distFunc( p - d.xxy ).dist
) );
}
vec3 normalFunc( vec3 p ) {
return normalFunc( p, MARCH_NEAR );
}
// == main procedure ===============================================================================
void main() {
vec2 p = v_texcoord - 0.5;
Camera camera = newCamera( vec3( 0.0, 0.0, 0.0 ), vec3( 0.0, 0.0, -1.0 ) );
camera.fov = 0.6 + 0.9 * FX_FORWARD * ( 0.5 + 0.5 * sin( HALF_PI * BEAT - 0.5 ) );
camera.pos.z = 0.5 + 1.5 / camera.fov;
Ray ray = rayFromCamera( camera, p );
Intersection isect;
float rayLen = MARCH_NEAR;
vec3 rayPos = getRayPosition( ray, rayLen );
MarchResult result;
for ( int i = 0; i < MARCH_ITER; i ++ ) {
result = distFunc( rayPos );
if ( abs( result.dist ) < MARCH_NEAR ) { break; }
rayLen += result.dist * MARCH_MULP;
if ( MARCH_FAR < rayLen ) { break; }
rayPos = getRayPosition( ray, rayLen );
}
vec3 bg = vec3( 0.0 );
if ( abs( result.dist ) < MARCH_NEAR ) {
vec3 normal = normalFunc( rayPos );
float edge = linearstep( 0.498, 0.499, abs( result.uv.x - 0.5 ) );
edge += linearstep( 0.495, 0.497, abs( result.uv.y - 0.5 ) );
vec2 uv = result.uv;
vec4 tex = texture2D( tex, uv );
float fog = exp( -0.2 * max( 0.0, rayLen - 3.0 ) );
gl_FragColor = vec4( fog * mix(
0.1 + 0.1 * normal + 0.8 * tex.rgb,
1.0 + 1.0 * sin( vec3( 0.0, 1.0, 2.0 ) + 10.0 * length( result.uv - 0.5 ) - 10.0 * time ),
edge
), 1.0 );
} else {
discard;
//gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );
}
}