Skip to content

Instantly share code, notes, and snippets.

@wrightwriter
Created November 18, 2023 19:37
Show Gist options
  • Save wrightwriter/45c8c5fff1706b8ed4e0c88e0d1408b1 to your computer and use it in GitHub Desktop.
Save wrightwriter/45c8c5fff1706b8ed4e0c88e0d1408b1 to your computer and use it in GitHub Desktop.
#version 420 core
uniform float fGlobalTime; // in seconds
uniform vec2 v2Resolution; // viewport resolution (in pixels)
uniform float fFrameTime; // duration of the last frame, in seconds
uniform sampler1D texFFT; // towards 0.0 is bass / lower freq, towards 1.0 is higher / treble freq
uniform sampler1D texFFTSmoothed; // this one has longer falloff and less harsh transients
uniform sampler1D texFFTIntegrated; // this is continually increasing
uniform sampler2D texPreviousFrame; // screenshot of the previous frame
uniform sampler2D texChecker;
uniform sampler2D texNoise;
uniform sampler2D texTex1;
uniform sampler2D texTex2;
uniform sampler2D texTex3;
uniform sampler2D texTex4;
layout(r32ui) uniform coherent restrict uimage2D[3] computeTex;
layout(r32ui) uniform coherent restrict uimage2D[3] computeTexBack;
layout(location = 0) out vec4 out_color; // out_color must be written in order to see anything
#define U gl_FragCoord.xy
#define R vec2(v2Resolution.xy)
#define T fGlobalTime
#define pi acos(-1.)
#define tau (acos(-1.)*2.)
#define rot(a) mat2(cos(a),-sin(a),sin(a),cos(a))
// hashes
uint seed = 12512;
uint hashi( uint x){
x ^= x >> 16;x *= 0x7feb352dU;x ^= x >> 15;x *= 0x846ca68bU;x ^= x >> 16;
return x;
}
#define hash_f_s(s) ( float( hashi(uint(s)) ) / float( 0xffffffffU ) )
#define hash_f() ( float( seed = hashi(seed) ) / float( 0xffffffffU ) )
#define hash_v2() vec2(hash_f(),hash_f())
#define hash_v3() vec3(hash_f(),hash_f(),hash_f())
#define hash_v4() vec3(hash_f(),hash_f(),hash_f(),hash_f())
vec2 sample_disk(){
vec2 r = hash_v2();
return vec2(sin(r.x*tau),cos(r.x*tau))*sqrt(r.y);
}
// point projection
ivec2 proj_p(vec3 p, float t){
// arbitrary camera stuff
float tt = t*2;
p += sin(vec3(1.1,0.78,0.6)*tt*0.3)*0.1;
p += sin(vec3(1.1,0.78,0.6)*tt*1.)*0.1;
p.xz *= rot(tt*0.25 + sin(tt*0.25));
p.xy *= rot(sin(tt*0.3)*0.2);
p.z -= -5.5;
// perspective proj
p.xy /= p.z*0.5;
// depth of field
p.xy += sample_disk() * abs(p.z - 5. + sin(T))*0.01;
// convert point to ivec2. From 0 to resolution.xy
ivec2 q = ivec2((p.xy + vec2(R.x/R.y,1)*0.5)*vec2(R.y/R.x,1)*R);
if(any(greaterThan(q, ivec2(R))) || any(lessThan(q, ivec2(0)))){
q = ivec2(-1);
}
return q;
}
void store_pixel(ivec2 px_coord, vec3 col){
// colour quantized to integer.
ivec3 quant_col = ivec3(col * 1000);
// no clue why it wants ivec4() here...
imageStore(computeTex[0], px_coord, ivec4(quant_col.x));
imageStore(computeTex[1], px_coord, ivec4(quant_col.y));
imageStore(computeTex[2], px_coord, ivec4(quant_col.z));
}
void add_to_pixel(ivec2 px_coord, vec3 col){
// colour quantized to integer.
ivec3 quant_col = ivec3(col * 1000);
imageAtomicAdd(computeTex[0], px_coord, quant_col.x);
imageAtomicAdd(computeTex[1], px_coord, quant_col.y);
imageAtomicAdd(computeTex[2], px_coord, quant_col.z);
}
vec3 read_pixel(ivec2 px_coord){
return 0.001*vec3(
imageLoad(computeTexBack[0],px_coord).x,
imageLoad(computeTexBack[1],px_coord).x,
imageLoad(computeTexBack[2],px_coord).x
);
}
void main(void){
vec2 uv = vec2(gl_FragCoord.x / v2Resolution.x, gl_FragCoord.y / v2Resolution.y);
uv -= 0.5;
uv /= vec2(v2Resolution.y / v2Resolution.x, 1);
// Init hash
seed = 215125125;
seed += hashi(uint(U.x)) + hashi(uint(U.y)*125);
vec3 col = vec3(0);
// Only run for the first 400 horizontal pixels
if(gl_FragCoord.x < 400){
int iters = 30;
float t = T - hash_f()*1./30;
float env = t + sin(t)*0.5;
float envb = sin(t*0.45);
vec3 p = hash_v3();
vec3 acc = vec3(1);
for(int i = 0; i < iters; i++){
float r = hash_f();
// basic Chaos Game stuff. Pick randomly from a couple of transforms, can be anything.
// Computerphile video or my article explains it.
vec3 dest = vec3(1);
if(r<.25){
dest = vec3(-1,-1,-0.5 );
} else if(r<.0){
dest = vec3(-1,1,-0.5 + cos(T));
} else if (r < 0.75){
dest = vec3(1,-1,-0.5);
} else {
dest = vec3(0,0,2.);
}
if(hash_f() < 0.5){
dest = -dest;
}
if(hash_f() < 0.5){
p = mix(p,dest,hash_f()*1.5);
} else{
p = mix(p,dest,0.5);
}
// some arbitrary colouring algorithm.
acc += (1.0 + sin(T*0.2))/dot(p,p);
ivec2 q = proj_p(p,t);
// if inside screen
if(q.x >= 0){
add_to_pixel(
q, 0.5 + 0.5 * sin(vec3(3,2,1)*acc*0.6)
);
}
}
}
vec3 s = read_pixel(ivec2(gl_FragCoord.xy))*0.1;
// tonemap stuff
s = s/(1+s*1.);
s = mix(s,smoothstep(0.,1.,s),0.);
s *= 1.2;
col = vec3(1)*1.0;
col -= s;
col = pow(col,vec3(.45454));
out_color = vec4(col,0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment