├── shaders ├── corridor.channel1 ├── glass.channel0 ├── accretion2.channel0 ├── corridor.channel0 ├── fluff.channel0 ├── glass.channel1 ├── spiral1.channel0 ├── synthwave.channel0 ├── voronoi.channel0 ├── wretched.channel0 ├── stars2.channel0 ├── voxel1.channel0 ├── mandle_brot.glsl ├── clouds3.glsl ├── lines.glsl ├── drops.glsl ├── wretched.glsl ├── accretion.glsl ├── blood.glsl ├── mandle_brot2.glsl ├── fract_pyramid.glsl ├── water.glsl ├── beer.glsl ├── flame.glsl ├── lava.glsl ├── bubbles.glsl ├── mobius_torus.glsl ├── mandle_brot3.glsl ├── tube4.glsl ├── whirlpool.glsl ├── particle1.glsl ├── shiny2.glsl ├── inversion.glsl ├── tube3.glsl ├── shiny.glsl ├── grind_torus.glsl ├── clouds.glsl ├── tube2.glsl ├── smoke.glsl ├── rolling.glsl ├── whisper.glsl ├── halo.glsl ├── dragon_torus.glsl ├── stars.glsl ├── cyber.glsl ├── cartoon.glsl ├── ghost.glsl ├── fluff.glsl ├── tree.glsl ├── clouds2.glsl ├── soap_bubbles.glsl ├── nebula_mesh.glsl ├── lights.glsl ├── raster.glsl ├── nebula_orbs.glsl ├── trippy.glsl ├── clouds4.glsl ├── spiral2.glsl ├── accretion2.glsl ├── voxel1.glsl └── synthwave.glsl ├── assets ├── skull.mp4 ├── stars.jpg ├── weave.png ├── wood.png ├── london.png ├── random.png ├── shader_1.jpg ├── shader_2.jpg ├── stones.png ├── happy_jump.mp4 ├── noise_brown.png └── noise_medium.png ├── src ├── .rpihub75.c.swp ├── colors.c └── video.c ├── include ├── gpu.h ├── video.h ├── mymath.h └── util.h ├── detect_flags.sh ├── calibration.html ├── example.c └── Makefile /shaders/corridor.channel1: -------------------------------------------------------------------------------- 1 | ../assets/wood.png -------------------------------------------------------------------------------- /shaders/glass.channel0: -------------------------------------------------------------------------------- 1 | ../assets/stones.png -------------------------------------------------------------------------------- /shaders/accretion2.channel0: -------------------------------------------------------------------------------- 1 | ../assets/stars.jpg -------------------------------------------------------------------------------- /shaders/corridor.channel0: -------------------------------------------------------------------------------- 1 | ../assets/weave.png -------------------------------------------------------------------------------- /shaders/fluff.channel0: -------------------------------------------------------------------------------- 1 | ../assets/noise_medium.png -------------------------------------------------------------------------------- /shaders/glass.channel1: -------------------------------------------------------------------------------- 1 | ../assets/noise_brown.png -------------------------------------------------------------------------------- /shaders/spiral1.channel0: -------------------------------------------------------------------------------- 1 | ../assets/london.png -------------------------------------------------------------------------------- /shaders/synthwave.channel0: -------------------------------------------------------------------------------- 1 | ../assets/london.png -------------------------------------------------------------------------------- /shaders/voronoi.channel0: -------------------------------------------------------------------------------- 1 | ../assets/london.png -------------------------------------------------------------------------------- /shaders/wretched.channel0: -------------------------------------------------------------------------------- 1 | ../assets/random.png -------------------------------------------------------------------------------- /shaders/stars2.channel0: -------------------------------------------------------------------------------- 1 | ../assets/noise_medium.png -------------------------------------------------------------------------------- /shaders/voxel1.channel0: -------------------------------------------------------------------------------- 1 | ../assets/noise_medium.png -------------------------------------------------------------------------------- /assets/skull.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitslip6/rpi-gpu-hub75-matrix/HEAD/assets/skull.mp4 -------------------------------------------------------------------------------- /assets/stars.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitslip6/rpi-gpu-hub75-matrix/HEAD/assets/stars.jpg -------------------------------------------------------------------------------- /assets/weave.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitslip6/rpi-gpu-hub75-matrix/HEAD/assets/weave.png -------------------------------------------------------------------------------- /assets/wood.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitslip6/rpi-gpu-hub75-matrix/HEAD/assets/wood.png -------------------------------------------------------------------------------- /assets/london.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitslip6/rpi-gpu-hub75-matrix/HEAD/assets/london.png -------------------------------------------------------------------------------- /assets/random.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitslip6/rpi-gpu-hub75-matrix/HEAD/assets/random.png -------------------------------------------------------------------------------- /assets/shader_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitslip6/rpi-gpu-hub75-matrix/HEAD/assets/shader_1.jpg -------------------------------------------------------------------------------- /assets/shader_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitslip6/rpi-gpu-hub75-matrix/HEAD/assets/shader_2.jpg -------------------------------------------------------------------------------- /assets/stones.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitslip6/rpi-gpu-hub75-matrix/HEAD/assets/stones.png -------------------------------------------------------------------------------- /src/.rpihub75.c.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitslip6/rpi-gpu-hub75-matrix/HEAD/src/.rpihub75.c.swp -------------------------------------------------------------------------------- /assets/happy_jump.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitslip6/rpi-gpu-hub75-matrix/HEAD/assets/happy_jump.mp4 -------------------------------------------------------------------------------- /assets/noise_brown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitslip6/rpi-gpu-hub75-matrix/HEAD/assets/noise_brown.png -------------------------------------------------------------------------------- /assets/noise_medium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitslip6/rpi-gpu-hub75-matrix/HEAD/assets/noise_medium.png -------------------------------------------------------------------------------- /shaders/mandle_brot.glsl: -------------------------------------------------------------------------------- 1 | 2 | void mainImage(out vec4 O, vec2 U) { 3 | vec2 R = iResolution.xy, z; 4 | U = ( U+U - R ) / R.y; 5 | U.x -= .5; 6 | for( O *= 0. ; O.r < 1. && dot(z,z)<6.; O += .02 ) 7 | z = mat2( z, -z.y, z ) * z + U; 8 | } 9 | -------------------------------------------------------------------------------- /include/gpu.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief render the shadertoy compatible shader source code in the 3 | * file pointed to by scene->shader_file 4 | * 5 | * exits if shader is unable to be loaded, compiled or rendered 6 | * 7 | * loop exits and memory is freed if/when scene->do_render becomes false 8 | * 9 | * frame delay is adaptive and updates to current scene->fps on each frame update 10 | * 11 | * @param arg pointer to the current scene_info object 12 | */ 13 | void *render_shader(void *arg); -------------------------------------------------------------------------------- /shaders/clouds3.glsl: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | -7 chars by @iapafoto 4 | -2 chars by @bug + fix for div by zero 5 | 6 | thanks!! :D 7 | 8 | */ 9 | 10 | void mainImage(out vec4 o, vec2 u) { 11 | float i,d,s,t = iTime; 12 | vec3 p = iResolution; 13 | u = (u-p.xy/2.)/p.y; 14 | for(o*=i; i++<1e2; 15 | d += s = .05+.2*abs(6.+p.y), 16 | o += 1./s + 1./length(u+u-.8)) 17 | for (p = vec3(u * d, d + t), 18 | s = .01; s < 2.; s += s ) 19 | p.yz -= abs(dot(sin(.2*t + .3*p / s ), p-p+s)); 20 | o = tanh(o/1e3); 21 | } 22 | 23 | -------------------------------------------------------------------------------- /include/video.h: -------------------------------------------------------------------------------- 1 | #include "rpihub75.h" 2 | 3 | /** 4 | * @brief pass this function to your pthread_create() call to render a video file 5 | * will render the video file pointed to by scene->shader_file until 6 | * scene->do_render is false; 7 | * 8 | * @param arg 9 | * @return void* 10 | */ 11 | void* render_video_fn(void *arg); 12 | 13 | /** 14 | * @brief pass this function to your pthread_create() call to render a video file 15 | * will render the video file pointed to by scene->shader_file until 16 | * scene->do_render is false; returns once the video is done rendering 17 | * 18 | * @param arg 19 | * @return void* 20 | */ 21 | bool hub_render_video(scene_info *scene, const char *filename); 22 | -------------------------------------------------------------------------------- /shaders/lines.glsl: -------------------------------------------------------------------------------- 1 | 2 | #define MI 7 // max iteration 3 | #define LW 12.0 // line width 4 | #define LI 1.2 // line indensity 5 | #define AS 0.5 // animation speed 6 | #define BI 1.0 // background indensity 7 | 8 | void mainImage(out vec4 fragColor, in vec2 fragCoord) { 9 | float time = iTime * .05; // slow the time 10 | 11 | vec2 uv = fragCoord.xy / iResolution.xy; 12 | 13 | vec2 p = uv; 14 | vec2 i = p; 15 | float bi = BI; 16 | 17 | for (int n = 0; n < MI; n++) { 18 | float t = time * float(n) * AS; 19 | i = p + vec2(cos(t - i.x) + sin(t + i.y), 20 | sin(t - i.y) + cos(t + i.x)); 21 | bi += length(vec2( 22 | p.x / (sin(i.x + t) / LI), 23 | p.y / (cos(i.y + t) / LI))); 24 | } 25 | 26 | bi /= float(MI); 27 | bi /= LW; 28 | 29 | vec3 color = vec3(bi); 30 | vec3 color_base = vec3(0.0, 0.05, 0.2); 31 | color = clamp(color_base + color, 0.0, 1.0); 32 | fragColor = vec4(color, 1.0); 33 | } 34 | -------------------------------------------------------------------------------- /shaders/drops.glsl: -------------------------------------------------------------------------------- 1 | float getCopper(vec2 uv) 2 | { 3 | uv.x*=3.0; 4 | float t0=texture(iChannel0,uv.xy*0.4+iTime*vec2(0,1)*0.05).r; 5 | float t1=texture(iChannel0,uv.xy*0.5+iTime*vec2(0,1)*0.01).r*0.2; 6 | return smoothstep(0.15,0.25,t0*t1*2.0); 7 | } 8 | 9 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) 10 | { 11 | vec2 uv = fragCoord/iResolution.xy; 12 | 13 | float eps=0.005; 14 | float p0=getCopper(uv); 15 | float p1=getCopper(uv+vec2(0.0,eps)); 16 | float p2=getCopper(uv+vec2(eps,eps)); 17 | vec3 normal=normalize(vec3(p0-p1,p2-p1,0.5)); 18 | 19 | vec3 lightDir=vec3(0.25,0.75,0.2); 20 | if(iMouse.z>0.0)lightDir.xy=vec2(iMouse.xy/iResolution.xy); 21 | lightDir-=vec3((uv*0.5)*2.0,0); 22 | lightDir.x*=iResolution.x/iResolution.y; 23 | lightDir=normalize(lightDir); 24 | 25 | vec3 color=(pow(dot(lightDir,normal)+0.1,3.0)+0.15)*vec3(1,0.7,0.5); 26 | 27 | fragColor=vec4(color,1); 28 | } 29 | -------------------------------------------------------------------------------- /shaders/wretched.glsl: -------------------------------------------------------------------------------- 1 | // https://www.shadertoy.com/view/tXsyR8 2 | 3 | vec4 fire(vec3 p) { 4 | float s, i, d, n, T = iTime; 5 | vec4 o = vec4(0); 6 | p += cos(p.z+T+p.yzx*.5)*.6; 7 | s = 6.-length(p.xy); 8 | p.xy *= mat2(cos(.3*T+vec4(0,33,11,0))); 9 | for (n = 1.6; n < 32.; n += n ) 10 | s -= abs(dot(sin( p.z + T + p*n ), vec3(1.12))) / n; 11 | s = (.01 + abs(s)*.15); 12 | o += 1. / s; 13 | return (vec4(7,2,1,1) * o * o ); 14 | } 15 | 16 | void mainImage(out vec4 o, vec2 u) { 17 | float d=4.*texelFetch(iChannel0, ivec2(u)%1024, 0).a, 18 | i,s,w,l, T = iTime*.3; 19 | vec3 q,p = iResolution; 20 | u = ( u - p.xy/2. ) / p.y; 21 | for(o*=i; i++ < 64.; o += d / s + 4.*fire(q)) { 22 | q = p = vec3( u*d, d + T * 4.), 23 | p.xy *= mat2(cos(.001*T+p.z*.1+vec4(0,33,11,0))); 24 | p *= .3; 25 | w = .25; 26 | p.x-=1.5; 27 | p += cos(T+p.yzx); 28 | for (int i; i++ < 7; w *= l ) 29 | p *= l = 1.25/dot( p = abs(sin(p))-1. , p); 30 | d += s = .002+.5*abs(length(p)/w) ; 31 | } 32 | o = tanh(o/2e5); 33 | } 34 | 35 | -------------------------------------------------------------------------------- /shaders/accretion.glsl: -------------------------------------------------------------------------------- 1 | // https://www.shadertoy.com/view/WcKXDV 2 | /* 3 | "Accretion" by @XorDev 4 | 5 | I discovered an interesting refraction effect 6 | by adding the raymarch iterator to the turbulence! 7 | https://x.com/XorDev/status/1936884244128661986 8 | */ 9 | 10 | void mainImage(out vec4 O, vec2 I) 11 | { 12 | //Raymarch depth 13 | float z, 14 | //Step distance 15 | d, 16 | //Raymarch iterator 17 | i; 18 | //Clear fragColor and raymarch 20 steps 19 | for(O*=i; i++<2e1; ) 20 | { 21 | //Sample point (from ray direction) 22 | vec3 p = z*normalize(vec3(I+I,0)-iResolution.xyx)+.1; 23 | 24 | //Polar coordinates and additional transformations 25 | p = vec3(atan(p.y/.2,p.x)*2., p.z/3., length(p.xy)-5.-z*.2); 26 | 27 | //Apply turbulence and refraction effect 28 | for(d=0.; d++<7.;) 29 | p += sin(p.yzx*d+iTime+.3*i)/d; 30 | 31 | //Distance to cylinder and waves with refraction 32 | z += d = length(vec4(.4*cos(p)-.4, p.z)); 33 | 34 | //Coloring and brightness 35 | O += (1.+cos(p.x+i*.4+z+vec4(6,1,2,0)))/d; 36 | } 37 | //Tanh tonemap 38 | O = tanh(O*O/4e2); 39 | } 40 | -------------------------------------------------------------------------------- /shaders/blood.glsl: -------------------------------------------------------------------------------- 1 | // https://www.shadertoy.com/view/tcSfRc 2 | #define T (iTime) 3 | 4 | vec4 blood(vec2 u) { 5 | float i,a,d,s,t=.4*iTime; 6 | vec3 p; 7 | vec4 o = vec4(0); 8 | for(o*=i; i++<64.; 9 | d += s = .01 + abs(s) * .4, 10 | o.r+=d/s) 11 | for (p = vec3(u * d, d + t), 12 | s = min(cos(p.z), 6. - length(p.xy)), 13 | a = .8; a < 16.; a += a) 14 | p += cos(t+p.yzx)*.2, 15 | s += abs(dot(sin(t+.2*p.z+p * a), .6+p-p)) / a; 16 | return o * 2e1; 17 | } 18 | 19 | vec4 fire(vec2 u) { 20 | float i, d, s, n; 21 | vec3 p; 22 | vec4 o = vec4(0); 23 | for(; i++<1e2; ) { 24 | p = vec3(u * d, d); 25 | p += cos(p.z+T+p.yzx*.5)*.6; 26 | s = 6.-length(p.xy); 27 | p.xy *= mat2(cos(.3*T+vec4(0,33,11,0))); 28 | for (n = 1.6; n < 32.; n += n ) 29 | s -= abs(dot(sin( p.z + T + p*n ), vec3(1.12))) / n; 30 | d += s = .01 + abs(s)*.1; 31 | o += 1. / s; 32 | } 33 | return (vec4(5,2,1,1) * o * o / d); 34 | } 35 | 36 | void mainImage(out vec4 o, in vec2 u) { 37 | float s=.1,d=0.,i=0.; 38 | vec3 p = iResolution; 39 | u = (u-p.xy/2.)/p.y; 40 | 41 | o = mix(fire(u), blood(u), .9); 42 | o = tanh(o / 5e5 ); 43 | 44 | } 45 | -------------------------------------------------------------------------------- /shaders/mandle_brot2.glsl: -------------------------------------------------------------------------------- 1 | // https://www.shadertoy.com/view/4tyBWh 2 | 3 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) 4 | { 5 | // Normalized pixel coordinates (from 0 to 1) 6 | vec2 uv = fragCoord/iResolution.xy; 7 | int bitdepth = 4; 8 | int res = int(pow(2.0, float(bitdepth))); 9 | 10 | // Time varying pixel color 11 | //vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4)); 12 | 13 | float zoom = 0.5 + (pow(iTime, 3.0) / 8.0); 14 | //zoom = 0.5; 15 | float xoffset = -(zoom / 1.0) * (iResolution.x / 2.85); 16 | float yoffset = -(zoom / 4.0) * (iResolution.x / 18.0); 17 | yoffset = 1.0; 18 | 19 | float c_re = ((fragCoord.x + xoffset) - iResolution.x/2.0)*4.0/(iResolution.x * zoom); 20 | float c_im = ((fragCoord.y + yoffset) - iResolution.y/2.0)*4.0/(iResolution.x * zoom); 21 | float x = 0.0; 22 | float y = 0.0; 23 | 24 | int max = int(pow(2.0, float(bitdepth * 3))) - 1; 25 | 26 | int iteration = 0; 27 | while (((x*x+y*y) <= 4.0) && (iteration < max)) { 28 | float x_new = x*x - y*y + c_re; 29 | y = 2.0*x*y + c_im; 30 | x = x_new; 31 | iteration++; 32 | } 33 | 34 | float b = float(iteration % int(res)) / float(res); 35 | float g = float((iteration >> bitdepth) % int(res)) / float(res); 36 | float r = float((iteration >> (bitdepth * 2)) % int(res)) / float(res); 37 | 38 | vec3 col = vec3(r,g,b); 39 | 40 | //col = vec3(1.0,1.0,1.0) - col; 41 | 42 | fragColor = vec4(col,1.0); 43 | 44 | // Output to screen 45 | 46 | } 47 | -------------------------------------------------------------------------------- /detect_flags.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | set -eu 3 | 4 | arch="$(uname -m 2>/dev/null || echo unknown)" 5 | 6 | # default safe flags 7 | fallback_arm64="-march=armv8-a" 8 | fallback_arm32="-mcpu=cortex-a53 -mfpu=neon-vfpv4 -mfloat-abi=hard" 9 | 10 | case "$arch" in 11 | aarch64) 12 | # try Model name first, which your Pi 5 provides 13 | model="$(lscpu 2>/dev/null | awk -F: '/Model name/ {gsub(/^[ \t]+|[ \t]+$/,"",$2); print $2; exit}')" 14 | case "$model" in 15 | *Cortex-A76*) echo "-mcpu=cortex-a76 -mtune=cortex-a76"; exit 0 ;; 16 | *Cortex-A72*) echo "-mcpu=cortex-a72 -mtune=cortex-a72"; exit 0 ;; 17 | *Cortex-A53*) echo "-mcpu=cortex-a53 -mtune=cortex-a53"; exit 0 ;; 18 | esac 19 | 20 | # fallback: parse CPU part codes if present 21 | cpu_part="$(awk -F: '/CPU part/ {gsub(/^[ \t]+|[ \t]+$/,"",$2); print tolower($2); exit}' /proc/cpuinfo 2>/dev/null || true)" 22 | case "$cpu_part" in 23 | 0xd0b) echo "-mcpu=cortex-a76 -mtune=cortex-a76"; exit 0 ;; # Pi 5 24 | 0xd08) echo "-mcpu=cortex-a72 -mtune=cortex-a72"; exit 0 ;; # Pi 4 25 | 0xd03) echo "-mcpu=cortex-a53 -mtune=cortex-a53"; exit 0 ;; # Pi 3 64-bit userspace 26 | esac 27 | 28 | # last fallback: let the compiler decide 29 | if printf "" | ${CC:-cc} -mcpu=native -x c -c - -o /dev/null >/dev/null 2>&1; then 30 | echo "-mcpu=native"; exit 0 31 | fi 32 | echo "$fallback_arm64";; 33 | armv7l) 34 | echo "$fallback_arm32";; 35 | *) 36 | # dev boxes and everything else 37 | if printf "" | ${CC:-cc} -march=native -x c -c - -o /dev/null >/dev/null 2>&1; then 38 | echo "-march=native"; exit 0 39 | fi 40 | echo "";; 41 | esac 42 | 43 | -------------------------------------------------------------------------------- /shaders/fract_pyramid.glsl: -------------------------------------------------------------------------------- 1 | // https://www.shadertoy.com/view/tsXBzS 2 | 3 | vec3 palette(float d){ 4 | return mix(vec3(0.2,0.7,0.9),vec3(1.,0.,1.),d); 5 | } 6 | 7 | vec2 rotate(vec2 p,float a){ 8 | float c = cos(a); 9 | float s = sin(a); 10 | return p*mat2(c,s,-s,c); 11 | } 12 | 13 | float map(vec3 p){ 14 | for( int i = 0; i<8; ++i){ 15 | float t = iTime*0.2; 16 | p.xz =rotate(p.xz,t); 17 | p.xy =rotate(p.xy,t*1.89); 18 | p.xz = abs(p.xz); 19 | p.xz-=.5; 20 | } 21 | return dot(sign(p),p)/5.; 22 | } 23 | 24 | vec4 rm (vec3 ro, vec3 rd){ 25 | float t = 0.; 26 | vec3 col = vec3(0.); 27 | float d; 28 | for(float i =0.; i<64.; i++){ 29 | vec3 p = ro + rd*t; 30 | d = map(p)*.5; 31 | if(d<0.02){ 32 | break; 33 | } 34 | if(d>100.){ 35 | break; 36 | } 37 | //col+=vec3(0.6,0.8,0.8)/(400.*(d)); 38 | col+=palette(length(p)*.1)/(400.*(d)); 39 | t+=d; 40 | } 41 | return vec4(col,1./(d*100.)); 42 | } 43 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) 44 | { 45 | vec2 uv = (fragCoord-(iResolution.xy/2.))/iResolution.x; 46 | vec3 ro = vec3(0.,0.,-50.); 47 | ro.xz = rotate(ro.xz,iTime); 48 | vec3 cf = normalize(-ro); 49 | vec3 cs = normalize(cross(cf,vec3(0.,1.,0.))); 50 | vec3 cu = normalize(cross(cf,cs)); 51 | 52 | vec3 uuv = ro+cf*6. + uv.x*cs + uv.y*cu; 53 | 54 | vec3 rd = normalize(uuv-ro); 55 | 56 | vec4 col = rm(ro,rd); 57 | 58 | 59 | fragColor = col; 60 | } 61 | 62 | /** SHADERDATA 63 | { 64 | "title": "fractal pyramid", 65 | "description": "", 66 | "model": "car" 67 | } 68 | */ 69 | -------------------------------------------------------------------------------- /shaders/water.glsl: -------------------------------------------------------------------------------- 1 | // https://www.shadertoy.com/view/MdlXz8 2 | // Found this on GLSL sandbox. I really liked it, changed a few things and made it tileable. 3 | // :) 4 | // by David Hoskins. 5 | // Original water turbulence effect by joltz0r 6 | 7 | 8 | // Redefine below to see the tiling... 9 | //#define SHOW_TILING 10 | 11 | #define TAU 6.28318530718 12 | #define MAX_ITER 5 13 | 14 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) 15 | { 16 | float time = iTime * .5+23.0; 17 | // uv should be the 0-1 uv of texture... 18 | vec2 uv = fragCoord.xy / iResolution.xy; 19 | 20 | #ifdef SHOW_TILING 21 | vec2 p = mod(uv*TAU*2.0, TAU)-250.0; 22 | #else 23 | vec2 p = mod(uv*TAU, TAU)-250.0; 24 | #endif 25 | vec2 i = vec2(p); 26 | float c = 1.0; 27 | float inten = .005; 28 | 29 | for (int n = 0; n < MAX_ITER; n++) 30 | { 31 | float t = time * (1.0 - (3.5 / float(n+1))); 32 | i = p + vec2(cos(t - i.x) + sin(t + i.y), sin(t - i.y) + cos(t + i.x)); 33 | c += 1.0/length(vec2(p.x / (sin(i.x+t)/inten),p.y / (cos(i.y+t)/inten))); 34 | } 35 | c /= float(MAX_ITER); 36 | c = 1.17-pow(c, 1.4); 37 | vec3 colour = vec3(pow(abs(c), 8.0)); 38 | colour = clamp(colour + vec3(0.0, 0.35, 0.5), 0.0, 1.0); 39 | 40 | #ifdef SHOW_TILING 41 | // Flash tile borders... 42 | vec2 pixel = 2.0 / iResolution.xy; 43 | uv *= 2.0; 44 | float f = floor(mod(iTime*.5, 2.0)); // Flash value. 45 | vec2 first = step(pixel, uv) * f; // Rule out first screen pixels and flash. 46 | uv = step(fract(uv), pixel); // Add one line of pixels per tile. 47 | colour = mix(colour, vec3(1.0, 1.0, 0.0), (uv.x + uv.y) * first.x * first.y); // Yellow line 48 | #endif 49 | 50 | fragColor = vec4(colour, 1.0); 51 | } 52 | -------------------------------------------------------------------------------- /shaders/beer.glsl: -------------------------------------------------------------------------------- 1 | // https://www.shadertoy.com/view/WtlGzS 2 | // Add more life to previous shader https://www.shadertoy.com/view/WllGRn 3 | // Very similar to https://www.shadertoy.com/view/Wll3RS 4 | 5 | // Force range [.1, .3] 6 | #define FORCE .35 7 | #define INIT_SPEED 14. 8 | #define AMOUNT 8. 9 | // #define WATER_COL vec3(18,140,200)/255. 10 | #define WATER_COL vec3(135,123,3)/255. 11 | 12 | float rand(vec2 co) { 13 | return fract(sin(dot(co.xy , vec2(12.9898, 78.233))) * 43758.5453); 14 | } 15 | 16 | float bubbles( vec2 uv, float size, float speed, float timeOfst, float blur, float time) 17 | { 18 | vec2 ruv = uv*size + .05; 19 | vec2 id = ceil(ruv) + speed; 20 | 21 | float t = (time + timeOfst)*speed; 22 | 23 | ruv.y -= t * (rand(vec2(id.x))*0.5+.5)*.1; 24 | vec2 guv = fract(ruv) - 0.5; 25 | 26 | ruv = ceil(ruv); 27 | float g = length(guv); 28 | 29 | float v = rand(ruv)*0.5; 30 | v *= step(v, clamp(FORCE, .1, .3)); 31 | 32 | float m = smoothstep(v,v - blur, g); 33 | 34 | v*=.85; 35 | m -= smoothstep(v,v- .1, g); 36 | 37 | g = length(guv - vec2(v*.35, v*.35)); 38 | float hlSize = v*.75; 39 | m += smoothstep(hlSize, 0., g)*.75; 40 | 41 | return m; 42 | } 43 | 44 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) 45 | { 46 | vec2 uv = (fragCoord - .5*iResolution.xy)/iResolution.y; 47 | 48 | float m = 0.; 49 | 50 | float sizeFactor = iResolution.y / 10.; 51 | 52 | float fstep = .1/AMOUNT; 53 | for(float i=-1.0; i<=0.; i+=fstep){ 54 | vec2 iuv = uv + vec2(cos(uv.y*2. + i*20. + iTime*.5)*.1, 0.); 55 | float size = (i*.15+0.2) * sizeFactor + 2.; 56 | m += bubbles(iuv + vec2(i*.1, 0.), size, INIT_SPEED + i*5., i*10., .3 + i*.25, iTime) * abs(i); 57 | } 58 | 59 | vec3 col = WATER_COL + m*.4; 60 | 61 | fragColor = vec4(col,1.0); 62 | } 63 | -------------------------------------------------------------------------------- /shaders/flame.glsl: -------------------------------------------------------------------------------- 1 | // https://www.shadertoy.com/view/MdX3zr 2 | // Created by anatole duprat - XT95/2013 3 | // License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 4 | 5 | float noise(vec3 p) //Thx to Las^Mercury 6 | { 7 | vec3 i = floor(p); 8 | vec4 a = dot(i, vec3(1., 57., 21.)) + vec4(0., 57., 21., 78.); 9 | vec3 f = cos((p-i)*acos(-1.))*(-.5)+.5; 10 | a = mix(sin(cos(a)*a),sin(cos(1.+a)*(1.+a)), f.x); 11 | a.xy = mix(a.xz, a.yw, f.y); 12 | return mix(a.x, a.y, f.z); 13 | } 14 | 15 | float sphere(vec3 p, vec4 spr) 16 | { 17 | return length(spr.xyz-p) - spr.w; 18 | } 19 | 20 | float flame(vec3 p) 21 | { 22 | float d = sphere(p*vec3(1.,.5,1.), vec4(.0,-1.,.0,1.)); 23 | return d + (noise(p+vec3(.0,iTime*4.5,.0)) + noise(p*3.)*.5)*.25*(p.y) ; 24 | } 25 | 26 | float scene(vec3 p) 27 | { 28 | return min(100.-length(p) , abs(flame(p)) ); 29 | } 30 | 31 | vec4 raymarch(vec3 org, vec3 dir) 32 | { 33 | float d = 0.0, glow = 0.0, eps = 0.02; 34 | vec3 p = org; 35 | bool glowed = false; 36 | 37 | for(int i=0; i<64; i++) 38 | { 39 | d = scene(p) + eps; 40 | p += d * dir; 41 | if( d>eps ) 42 | { 43 | if(flame(p) < .0) 44 | glowed=true; 45 | if(glowed) 46 | glow = float(i)/64.; 47 | } 48 | } 49 | return vec4(p,glow); 50 | } 51 | 52 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) 53 | { 54 | vec2 v = -1.0 + 2.0 * fragCoord.xy / iResolution.xy; 55 | v.x *= iResolution.x/iResolution.y; 56 | 57 | vec3 org = vec3(0., -2., 4.); 58 | vec3 dir = normalize(vec3(v.x*1.6, -v.y, -1.5)); 59 | 60 | vec4 p = raymarch(org, dir); 61 | float glow = p.w; 62 | 63 | vec4 col = mix(vec4(1.,.5,.1,1.), vec4(0.1,.5,1.,1.), p.y*.02+.4); 64 | 65 | fragColor = mix(vec4(0.), col, pow(glow*2.,4.)); 66 | //fragColor = mix(vec4(1.), mix(vec4(1.,.5,.1,1.),vec4(0.1,.5,1.,1.),p.y*.02+.4), pow(glow*2.,4.)); 67 | 68 | } 69 | 70 | 71 | -------------------------------------------------------------------------------- /shaders/lava.glsl: -------------------------------------------------------------------------------- 1 | float opSmoothUnion( float d1, float d2, float k ) 2 | { 3 | float h = clamp( 0.5 + 0.5*(d2-d1)/k, 0.0, 1.0 ); 4 | return mix( d2, d1, h ) - k*h*(1.0-h); 5 | } 6 | 7 | float sdSphere( vec3 p, float s ) 8 | { 9 | return length(p)-s; 10 | } 11 | 12 | float map(vec3 p) 13 | { 14 | float d = 2.0; 15 | for (int i = 0; i < 16; i++) { 16 | float fi = float(i); 17 | float time = iTime * (fract(fi * 412.531 + 0.513) - 0.5) * 2.0; 18 | d = opSmoothUnion( 19 | sdSphere(p + sin(time + fi * vec3(52.5126, 64.62744, 632.25)) * vec3(2.0, 2.0, 0.8), mix(0.5, 1.0, fract(fi * 412.531 + 0.5124))), 20 | d, 21 | 0.4 22 | ); 23 | } 24 | return d; 25 | } 26 | 27 | vec3 calcNormal( in vec3 p ) 28 | { 29 | const float h = 0.01; // or some other value 30 | const vec2 k = vec2(1,-1); 31 | return normalize( k.xyy*map( p + k.xyy*h ) + 32 | k.yyx*map( p + k.yyx*h ) + 33 | k.yxy*map( p + k.yxy*h ) + 34 | k.xxx*map( p + k.xxx*h ) ); 35 | } 36 | 37 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) 38 | { 39 | vec2 uv = fragCoord/iResolution.xy; 40 | 41 | // screen size is 6m x 6m 42 | vec3 rayOri = vec3((uv - 0.5) * vec2(iResolution.x/iResolution.y, 1.0) * 6.0, 3.0); 43 | vec3 rayDir = vec3(0.0, 0.0, -1.0); 44 | 45 | float depth = 0.0; 46 | vec3 p; 47 | 48 | for(int i = 0; i < 42; i++) { 49 | p = rayOri + rayDir * depth; 50 | float dist = map(p); 51 | depth += dist; 52 | if (dist < 0.01) { 53 | break; 54 | } 55 | } 56 | 57 | depth = min(6.0, depth); 58 | vec3 n = calcNormal(p); 59 | float b = max(0.0, dot(n, vec3(0.577))); 60 | vec3 col = (0.5 + 0.5 * cos((b + iTime * 3.0) + uv.xyx * 2.0 + vec3(0,2,4))) * (0.85 + b * 0.35); 61 | col *= exp( -depth * 0.15 ); 62 | 63 | // maximum thickness is 2m in alpha channel 64 | fragColor = vec4(col, 1.0 - (depth - 0.5) / 2.0); 65 | } 66 | -------------------------------------------------------------------------------- /shaders/bubbles.glsl: -------------------------------------------------------------------------------- 1 | 2 | // Copyright Inigo Quilez, 2013 - https://iquilezles.org/ 3 | // I am the sole copyright owner of this Work. 4 | // You cannot host, display, distribute or share this Work neither 5 | // as it is or altered, here on Shadertoy or anywhere else, in any 6 | // form including physical and digital. You cannot use this Work in any 7 | // commercial or non-commercial product, website or project. You cannot 8 | // sell this Work and you cannot mint an NFTs of it or train a neural 9 | // network with it without permission. I share this Work for educational 10 | // purposes, and you can link to it, through an URL, proper attribution 11 | // and unmodified screenshot, as part of your educational material. If 12 | // these conditions are too restrictive please contact me and we'll 13 | // definitely work it out. 14 | 15 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) 16 | { 17 | vec2 uv = (2.0*fragCoord-iResolution.xy) / iResolution.y; 18 | 19 | // background 20 | vec3 color = vec3(0.8 + 0.2*uv.y); 21 | 22 | // bubbles 23 | for( int i=0; i<40; i++ ) 24 | { 25 | // bubble seeds 26 | float pha = sin(float(i)*546.13+1.0)*0.5 + 0.5; 27 | float siz = pow( sin(float(i)*651.74+5.0)*0.5 + 0.5, 4.0 ); 28 | float pox = sin(float(i)*321.55+4.1) * iResolution.x / iResolution.y; 29 | 30 | // bubble size, position and color 31 | float rad = 0.1 + 0.5*siz; 32 | vec2 pos = vec2( pox, -1.0-rad + (2.0+2.0*rad)*mod(pha+0.1*iTime*(0.6+0.8*siz),1.0)); 33 | float dis = length( uv - pos ); 34 | vec3 col = mix( vec3(0.94,0.3,0.0), vec3(0.1,0.4,0.8), 0.5+0.5*sin(float(i)*1.2+1.9)); 35 | // col+= 8.0*smoothstep( rad*0.95, rad, dis ); 36 | 37 | // render 38 | float f = length(uv-pos)/rad; 39 | f = sqrt(clamp(1.0-f*f,0.0,1.0)); 40 | color -= col.zyx *(1.0-smoothstep( rad*0.95, rad, dis )) * f; 41 | } 42 | 43 | // vigneting 44 | color *= sqrt(1.5-0.5*length(uv)); 45 | 46 | fragColor = vec4(color,1.0); 47 | } 48 | -------------------------------------------------------------------------------- /shaders/mobius_torus.glsl: -------------------------------------------------------------------------------- 1 | // https://www.shadertoy.com/view/X3BBWt 2 | float DistTorus(vec3 p, float fat, float radius) 3 | { 4 | return length(vec2(length(p.xz)-radius, p.y)) - fat; 5 | } 6 | 7 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) 8 | { 9 | // Normalized pixel coordinates (from 0 to 1) 10 | vec2 uv = (fragCoord-.5*iResolution.xy)/iResolution.y; 11 | float t = iTime * 0.2; 12 | 13 | uv *= mat2(cos(t), -sin(t), sin(t), cos(t)); 14 | 15 | vec3 ro = vec3(0.,0.,-1); 16 | vec3 lookat = mix( vec3(0.), vec3(-1, 0., -1), sin(t*1.56)*.5+.5); 17 | float zoom = mix(.2,.7, sin(t)*.5+.5); 18 | 19 | vec3 f = normalize(lookat-ro), 20 | r = normalize(cross(vec3(0,1.,0),f)), 21 | u = normalize(cross(f, r)), 22 | c = ro + f*zoom, 23 | i = c + r*uv.x + u*uv.y, 24 | rd = normalize(i-ro); 25 | 26 | float fat = mix(.3, 1.5, sin(t*.4)*.5+.5); 27 | float distOrigin, distSurface; 28 | vec3 p; 29 | for(int i = 0; i <100; i++) 30 | { 31 | p = ro + rd*distOrigin; 32 | distSurface = -DistTorus(p, fat, 1.); 33 | 34 | if(distSurface < .001) break; 35 | distOrigin += distSurface; 36 | } 37 | 38 | vec3 col = vec3(0.); 39 | 40 | if( distSurface < .001) 41 | { 42 | float x = atan(p.x, p.z)+t*.5; 43 | float y = atan(length(p.xz)-1., p.y); 44 | 45 | float bands = sin(y*10. + x*20.); 46 | float ripples = sin((x*10. - y*30.)*3.)*.5+.5; 47 | float waves = sin(x*2. - y*6. + t*20.); 48 | 49 | float b1 = smoothstep(-.2, .2, bands); 50 | float b2 = smoothstep(-.2, .2, bands-.5); 51 | 52 | float m = b1*(1.-b2); 53 | m = max(m, ripples*b2*max(0., waves)); 54 | m += max(0., waves*.3*b2); 55 | 56 | col += mix(m, 1.-m, smoothstep(-.3, .3, sin(x*2.+t))); 57 | } 58 | 59 | // Output to screen 60 | fragColor = vec4(col,1.0); 61 | } 62 | -------------------------------------------------------------------------------- /shaders/mandle_brot3.glsl: -------------------------------------------------------------------------------- 1 | // https://www.shadertoy.com/view/WljyDw 2 | #define TAU 6.28318 3 | 4 | #define NUM_COLOR 50.0 5 | #define MAX_ITER 500 6 | 7 | int mandlebrot( vec2 c ) { 8 | 9 | int i = 0; 10 | vec2 z = vec2(0); 11 | 12 | for (int i = 0; i < MAX_ITER; i++) { 13 | z = vec2(z.x*z.x-z.y*z.y, 2.0*z.x*z.y) + c; 14 | if (length(z) >= 2.0) { return i; } 15 | } 16 | 17 | return -1; 18 | 19 | } 20 | 21 | #define RAINBOW 1 22 | #define COVFEFE 0 23 | #define ZEBRA 1 24 | 25 | vec3 color( int scheme, float x ) { 26 | 27 | if (scheme == RAINBOW) { 28 | return sqrt((sin(TAU*(x+vec3(0,1,2)/3.))+1.0)/2.0); 29 | } 30 | 31 | if (scheme == COVFEFE) { 32 | return 0.5 + 0.5*cos(2.7+x*TAU + vec3(0.0,.6,1.0)); 33 | } 34 | 35 | if (scheme == ZEBRA) { 36 | return 0.5 + 0.5*cos(vec3(x*TAU*NUM_COLOR*0.5)); 37 | } 38 | 39 | } 40 | 41 | vec3 simulate( vec2 coord ) { 42 | 43 | int iterations = mandlebrot(coord); 44 | 45 | if (iterations < 0) { 46 | return vec3(0); 47 | } else { 48 | return color(ZEBRA, mod(float(iterations), NUM_COLOR) / NUM_COLOR); 49 | } 50 | 51 | } 52 | 53 | // Frame Coordinates: (zoom, lowerLeft, upperRight, origin) 54 | #define ZR 1.5 55 | #define LL vec2(-2.0, -1.0) 56 | #define UR vec2(1.0, 1.0) 57 | #define OR vec2(0.001643721971153, 0.822467633298876) 58 | 59 | vec2 map( vec2 fragCoord, vec2 resolution, float time ) { 60 | 61 | vec2 lowerLeft = (LL-OR)*pow(ZR,-time)+OR; 62 | vec2 upperRight = (UR-OR)*pow(ZR,-time)+OR; 63 | 64 | return lowerLeft + (upperRight - lowerLeft) * fragCoord/resolution; 65 | 66 | } 67 | 68 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) { 69 | vec3 avgColor = ( 70 | simulate(map(fragCoord, iResolution.xy, iTime)) 71 | + simulate(map(fragCoord + vec2(0, 0.5), iResolution.xy, iTime)) 72 | + simulate(map(fragCoord + vec2(0.5, 0), iResolution.xy, iTime)) 73 | + simulate(map(fragCoord + vec2(0.5, 0.5), iResolution.xy, iTime)) 74 | ) / 4.0; 75 | 76 | fragColor = vec4(avgColor, 1.0); 77 | 78 | } 79 | 80 | -------------------------------------------------------------------------------- /shaders/tube4.glsl: -------------------------------------------------------------------------------- 1 | #define hash(x) fract(sin(x) * 43758.5453123) 2 | vec3 pal(float t){return .5+.5*cos(6.28*(1.*t+vec3(.0,.1,.1)));} 3 | float stepNoise(float x, float n) { // From Kamoshika shader 4 | const float factor = 0.3; 5 | float i = floor(x); 6 | float f = x - i; 7 | float u = smoothstep(0.5 - factor, 0.5 + factor, f); 8 | float res = mix(floor(hash(i) * n), floor(hash(i + 1.) * n), u); 9 | res /= (n - 1.) * 0.5; 10 | return res - 1.; 11 | } 12 | vec3 path(vec3 p){ 13 | 14 | vec3 o = vec3(0.); 15 | o.x += stepNoise(p.z*.05,5.)*5.; 16 | o.y += stepNoise(p.z*.07,3.975)*5.; 17 | return o; 18 | } 19 | float diam2(vec2 p,float s){p=abs(p); return (p.x+p.y-s)*inversesqrt(3.);} 20 | vec3 erot(vec3 p,vec3 ax,float t){return mix(dot(ax,p)*ax,p,cos(t))+cross(ax,p)*sin(t);} 21 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) 22 | { 23 | // Normalized pixel coordinates (from 0 to 1) 24 | vec2 uv = (fragCoord-.5*iResolution.xy)/iResolution.y; 25 | 26 | vec3 col = vec3(0.); 27 | 28 | vec3 ro = vec3(0.,0.,-1.),rt=vec3(0.); 29 | ro.z+=iTime*5.; 30 | rt.z += iTime*5.; 31 | ro+=path(ro); 32 | rt+=path(rt); 33 | vec3 z = normalize(rt-ro); 34 | vec3 x = vec3(z.z,0.,-z.x); 35 | float i=0.,e=0.,g=0.; 36 | vec3 rd = mat3(x,cross(z,x),z)*erot(normalize(vec3(uv,1.)),vec3(0.,0.,1.),stepNoise(iTime+hash(uv.x*uv.y*iTime)*.05,6.)); 37 | for(;i++<99.;){ 38 | vec3 p= ro+rd*g; 39 | 40 | p-=path(p); 41 | float r = 0.;; 42 | vec3 pp=p; 43 | float sc=1.; 44 | for(float j=0.;j++<4.;){ 45 | r = clamp(r+abs(dot(sin(pp*3.),cos(pp.yzx*2.))*.3-.1)/sc,-.5,.5); 46 | pp=erot(pp,normalize(vec3(.1,.2,.3)),.785+j); 47 | pp+=pp.yzx+j*50.; 48 | sc*=1.5; 49 | pp*=1.5; 50 | } 51 | 52 | float h = abs(diam2(p.xy,7.))-3.-r; 53 | 54 | p=erot(p,vec3(0.,0.,1.),path(p).x*.5+p.z*.2); 55 | float t = length(abs(p.xy)-.5)-.1; 56 | h= min(t,h); 57 | g+=e=max(.001,t==h ?abs(h):(h)); 58 | col +=(t==h ?vec3(.3,.2,.1)*(100.*exp(-20.*fract(p.z*.25+iTime)))*mod(floor(p.z*4.)+mod(floor(p.y*4.),2.),2.) :vec3(.1))*.0325/exp(i*i*e);; 59 | } 60 | col = mix(col,vec3(.9,.9,1.1),1.-exp(-.01*g*g*g)); 61 | // Output to screen 62 | fragColor = vec4(col,1.0); 63 | } 64 | -------------------------------------------------------------------------------- /shaders/whirlpool.glsl: -------------------------------------------------------------------------------- 1 | // alternate version of Segmented spiral whirlpool: https://www.shadertoy.com/view/4ctcRl 2 | 3 | #define T (iTime/2e2) 4 | #define A(v) mat2(cos((v)*3.1416 + vec4(0, -1.5708, 1.5708, 0))) // rotate 5 | #define H(v) (cos(((v)+.5)*6.2832 + radians(vec3(0, 60, 120)))*.5+.5) // hue 6 | 7 | float map(vec3 u) 8 | { 9 | float t = T, // speed 10 | l = 4., // loop to reduce clipping 11 | s = .4, // object radius (max) 12 | a = 3., // amplitude 13 | f = 1e20, i = 0., y, z; 14 | 15 | u.xy = vec2(atan(u.x, u.y), length(u.xy)); // polar transform 16 | u.x += t*133.; // counter rotation 17 | 18 | vec3 p; 19 | for (; i++ 0.) ? // clicking? 42 | (iMouse.xy - R/2.)/R.y: // coords from mouse 43 | vec2(cos(iTime/4. - vec2(0, 1.5708)))*.2; // coords from time 44 | 45 | vec3 o = vec3(0, -10.*sqrt(1.-abs(m.y*2.)), -90./(m.y+1.)), // camera 46 | u = normalize(vec3(U - R/2., R.y)), // 3d coords 47 | c = vec3(0), p; 48 | 49 | mat2 h = A(m.x/2.), // rotate horizontal 50 | v = A((m.y+.5)/2.); // vertical 51 | 52 | for (; i++ 1e3) break; 64 | d += s*.7; 65 | } 66 | 67 | C = vec4(exp(log(c)/2.2), 1); 68 | } 69 | -------------------------------------------------------------------------------- /shaders/particle1.glsl: -------------------------------------------------------------------------------- 1 | // Random function 2 | float random(vec2 st) { 3 | return fract(sin(dot(st.xy, vec2(12.9898,78.233))) * 43758.5453123); 4 | } 5 | 6 | // Returns velocity vector for a particle 7 | vec2 getParticleVelocity(float index, float seed) { 8 | float angle = random(vec2(index, seed)) * 6.28; // Random angle 9 | 10 | // Base speed reduced by 30% with wider variation 11 | float baseSpeed = 0.56; // 0.8 * 0.7 = 0.56 12 | float speedVariation = random(vec2(index, seed + 1.0)) * 0.6 + 0.7; // 0.7 to 1.3 multiplier 13 | float speed = baseSpeed * speedVariation; 14 | 15 | return vec2(cos(angle), sin(angle)) * speed; 16 | } 17 | 18 | void mainImage(out vec4 fragColor, in vec2 fragCoord) { 19 | // Normalize coordinates 20 | vec2 uv = (fragCoord - 0.5 * iResolution.xy) / iResolution.y; 21 | 22 | // Create explosion seed based on time 23 | float seed = floor(iTime); 24 | float t = fract(iTime); 25 | 26 | // Initialize color 27 | vec3 color = vec3(0.0); 28 | 29 | // Number of particles 30 | const int NUM_PARTICLES = 25; 31 | 32 | // Gravity effect (pulls particles down over time) 33 | float gravity = 0.8; 34 | 35 | // Generate particles 36 | for(int i = 0; i < NUM_PARTICLES; i++) { 37 | float fi = float(i); 38 | 39 | // Get random velocity for this particle 40 | vec2 velocity = getParticleVelocity(fi, seed); 41 | 42 | // Apply gravity effect to particle position 43 | vec2 particlePos = velocity * t * 2.0; 44 | particlePos.y -= gravity * t * t; // Quadratic fall-off for gravity 45 | 46 | // Distance from current pixel to particle 47 | float dist = length(uv - particlePos); 48 | 49 | // Particle size shrinks over time 50 | float size = 0.05 * (1.0 - t * 0.5); 51 | 52 | // Create soft particles with falloff 53 | float brightness = smoothstep(size, 0.0, dist); 54 | 55 | // Fade out over time 56 | brightness *= 1.0 - t; 57 | 58 | // Random color variation for each particle 59 | vec3 particleColor = mix( 60 | vec3(1.0, 0.3, 0.1), // Orange/red core 61 | vec3(1.0, 0.8, 0.3), // Yellow/white hot 62 | random(vec2(fi, seed + 2.0)) 63 | ); 64 | 65 | // Add this particle's contribution 66 | color += particleColor * brightness; 67 | } 68 | 69 | // Add glow effect 70 | color *= 1.2; 71 | 72 | // Output final color 73 | fragColor = vec4(color, 1.0); 74 | } 75 | -------------------------------------------------------------------------------- /shaders/shiny2.glsl: -------------------------------------------------------------------------------- 1 | // https://www.shadertoy.com/view/w3SSWd 2 | /* 3 | Inspired by Xor's recent raymarchers with comments! 4 | https://www.shadertoy.com/view/tXlXDX 5 | */ 6 | 7 | #define OPT_FAST_TONEMAP 0 8 | 9 | // explicit, readable version of your shader 10 | void mainImage(out vec4 frag_color, in vec2 frag_coord) 11 | { 12 | // constants 13 | const int OUTER_STEPS = 70; 14 | const float INNER_S_START = 0.10; 15 | const float INNER_S_LIMIT = 2.00; 16 | const float INNER_S_SCALE = 1.42; 17 | const float DEFORM_MULTIPLIER = 16.0; 18 | const float DEFORMATION_MIX = 0.30; 19 | const float DIST_BASE_INCREMENT = 0.02; 20 | const float DIST_SCALE = 0.10; 21 | const float DIST_RADIUS = 3.00; 22 | const vec4 COSINE_PHASE = vec4(4.0, 2.0, 1.0, 0.0); 23 | const float TONE_DIVISOR = 2000.0; 24 | 25 | // uniforms 26 | float time_seconds = iTime; 27 | 28 | // accumulators 29 | float distance_along_ray = 0.0; 30 | vec4 accum_color = vec4(0.0); 31 | 32 | // replicate original camera mapping: normalize(vec3(2*u,0) - iResolution.xyy) 33 | // requires iResolution to be a vec3 34 | vec3 resolution_xyy = vec3(iResolution.x, iResolution.y, iResolution.y); 35 | 36 | for (int step = 0; step < OUTER_STEPS; ++step) 37 | { 38 | vec3 ray_dir = normalize(vec3(2.0 * frag_coord, 0.0) - resolution_xyy); 39 | vec3 p = distance_along_ray * ray_dir; 40 | p.z -= time_seconds; 41 | 42 | // inner deformation loop 43 | float s = INNER_S_START; 44 | while (s < INNER_S_LIMIT) 45 | { 46 | vec3 cos_term = cos(time_seconds + p * (s * DEFORM_MULTIPLIER)); 47 | float dot_term = dot(cos_term, vec3(0.01)); 48 | p -= (dot_term / s); 49 | p += sin(p.yzx * 0.90) * DEFORMATION_MIX; 50 | s *= INNER_S_SCALE; 51 | } 52 | 53 | float step_size = DIST_BASE_INCREMENT 54 | + abs(DIST_RADIUS - length(p.yx)) * DIST_SCALE; 55 | 56 | distance_along_ray += step_size; 57 | 58 | vec4 step_color = (1.0 + cos(distance_along_ray + COSINE_PHASE)) / step_size; 59 | accum_color += step_color; 60 | } 61 | 62 | // frag_color = tanh(accum_color / TONE_DIVISOR); 63 | 64 | #if OPT_FAST_TONEMAP 65 | // micro-opt 3: cheaper tanh approximation 66 | vec4 x = accum_color / TONE_DIVISOR; 67 | frag_color = x / (1.0 + abs(x)); 68 | #else 69 | frag_color = tanh(accum_color / TONE_DIVISOR); 70 | #endif 71 | } 72 | -------------------------------------------------------------------------------- /calibration.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | HUB75 Calibration Bars 8 | 22 | 23 | 24 | 25 |
26 |
27 |
3
28 |
29 |
30 | 31 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /include/mymath.h: -------------------------------------------------------------------------------- 1 | #include 2 | #if defined(__ARM_NEON) 3 | #include 4 | #elif defined(__SSE2__) 5 | #include 6 | #endif 7 | 8 | extern int32_t __builtin_arm_qadd (int32_t, int32_t); // ARM intrinsic for saturated addition 9 | 10 | 11 | 12 | /** 13 | * @brief clamp a float to the range 0-1 14 | */ 15 | static inline float clamp1f(float x) { 16 | return fminf(1.0f, fmaxf(0.0f, x)); 17 | } 18 | 19 | /** 20 | * @brief one step of Newton refinement helps ARM accuracy if you enable -ffast-math 21 | * @return float 22 | */ 23 | static inline float safe_rcp(float x) { 24 | float r = 1.0f / x; 25 | // r = r * (2 - x*r); // uncomment if you use a fast approx to start 26 | return r; 27 | } 28 | 29 | 30 | /** 31 | * @brief return just the fractional part of x 32 | * @return float - x - floorf(x) 33 | */ 34 | static inline float fract(float x) { 35 | return x - floorf(x); 36 | } 37 | 38 | /** 39 | * @brief linear interpolate between two floats 40 | * 41 | * @param x value A 42 | * @param y value B 43 | * @param a Normal 0-1 interpolation amount 44 | * @return float 45 | */ 46 | __attribute__((pure)) 47 | static inline float mixf(const float x, const float y, const Normal a) { 48 | return x * (1.0f - a) + y * a; 49 | } 50 | 51 | /** 52 | * @brief clamp a value between >= lower and <= upper 53 | * 54 | * @param x value to clamp 55 | * @param lower lower bound inclusive 56 | * @param upper upper bound inclusive 57 | * @return float 58 | */ 59 | __attribute__((pure)) 60 | static inline float clampf(const float x, const float lower, const float upper) { 61 | return fmaxf(lower, fminf(x, upper)); 62 | } 63 | 64 | 65 | /** 66 | * @brief hardware saturated addition of two int32_t values 67 | * @param a 68 | * @param b 69 | * @return int32_t 70 | */ 71 | static inline int32_t saturating_add(int32_t a, int32_t b) { 72 | #if defined(__arm__) || defined(__aarch64__) 73 | return __builtin_arm_qadd(a, b); // GCC/Clang built-in for ARM saturated add 74 | 75 | 76 | #elif defined(__SSE2__) // x86 with SSE2 77 | __m128i va = _mm_set1_epi32(a); 78 | __m128i vb = _mm_set1_epi32(b); 79 | __m128i result = _mm_add_epi32(va, vb); // SSE2 saturated add 80 | return _mm_cvtsi128_si32(result); 81 | 82 | #else // Portable software-based saturated arithmetic 83 | int32_t result = a + b; 84 | if (((b > 0) && (result < a)) || ((b < 0) && (result > a))) { 85 | result = (b > 0) ? INT32_MAX : INT32_MIN; // Saturate on overflow or underflow 86 | } 87 | return result; 88 | #endif 89 | } 90 | 91 | #define bit_count(x) __builtin_popcount(x) // GCC/Clang built-in for counting set bits 92 | -------------------------------------------------------------------------------- /shaders/inversion.glsl: -------------------------------------------------------------------------------- 1 | // Copyright Inigo Quilez, 2013 - https://iquilezles.org/ 2 | // I am the sole copyright owner of this Work. 3 | // You cannot host, display, distribute or share this Work in any form, 4 | // including physical and digital. You cannot use this Work in any 5 | // commercial or non-commercial product, website or project. You cannot 6 | // sell this Work and you cannot mint an NFTs of it. 7 | // I share this Work for educational purposes, and you can link to it, 8 | // through an URL, proper attribution and unmodified screenshot, as part 9 | // of your educational material. If these conditions are too restrictive 10 | // please contact me and we'll definitely work it out. 11 | 12 | // Other "Iterations" shaders: 13 | // 14 | // "trigonometric" : https://www.shadertoy.com/view/Mdl3RH 15 | // "trigonometric 2" : https://www.shadertoy.com/view/Wss3zB 16 | // "circles" : https://www.shadertoy.com/view/MdVGWR 17 | // "coral" : https://www.shadertoy.com/view/4sXGDN 18 | // "guts" : https://www.shadertoy.com/view/MssGW4 19 | // "inversion" : https://www.shadertoy.com/view/XdXGDS 20 | // "inversion 2" : https://www.shadertoy.com/view/4t3SzN 21 | // "shiny" : https://www.shadertoy.com/view/MslXz8 22 | // "worms" : https://www.shadertoy.com/view/ldl3W4 23 | // "stripes" : https://www.shadertoy.com/view/wlsfRn 24 | 25 | 26 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) 27 | { 28 | vec2 uv = fragCoord.xy/iResolution.xy; 29 | 30 | // shape (16 points) 31 | float time = iTime + 47.0; 32 | vec2 z = -1.0 + 2.0*uv; 33 | vec3 col = vec3(1.0); 34 | for( int j=0; j<16; j++ ) 35 | { 36 | // deform 37 | float s = float(j)/16.0; 38 | float f = 0.2*(0.5 + 1.0*fract(sin(s*113.1)*43758.5453123)); 39 | vec2 c = 0.5*vec2( cos(f*time+17.0*s),sin(f*time+19.0*s) ); 40 | z -= c; 41 | float zr = length( z ); 42 | float ar = atan( z.y, z.x ) + zr*0.6; 43 | z = vec2( cos(ar), sin(ar) )/zr; 44 | z += c; 45 | z += 0.05*sin(2.0*z.x); 46 | 47 | // color 48 | col -= 0.7*exp( -8.0*dot(z,z) )* (0.5+0.5*sin( 4.2*s + vec3(1.6,0.9,0.3) )); 49 | } 50 | col *= 0.75 + 0.25*clamp(length(z-uv)*0.6,0.0,1.0); 51 | 52 | // 3d effect 53 | float h = dot(col,vec3(0.333)); 54 | vec3 nor = normalize( vec3( dFdx(h), dFdy(h), 1.0/iResolution.x ) ); 55 | col -= 0.05*vec3(1.0,0.9,0.5)*dot(nor,vec3(0.8,0.4,0.2));; 56 | col += 0.25*(1.0-0.8*col)*nor.z*nor.z; 57 | 58 | // 2d postpro 59 | col *= 1.12; 60 | col = pow( clamp(col,0.0,1.0), vec3(0.8) ); 61 | col *= 0.8 + 0.2*pow( 16.0*uv.x*uv.y*(1.0-uv.x)*(1.0-uv.y), 0.1 ); 62 | fragColor = vec4( col, 1.0 ); 63 | } 64 | -------------------------------------------------------------------------------- /shaders/tube3.glsl: -------------------------------------------------------------------------------- 1 | // Mirror-like "Happy Accident" Shader (CC0) 2 | // A shiny reflective variation of a raymarched fractal accident 3 | // ATTRIBUTION: Shader techniques inspired by (alphabetical): 4 | // @byt3_m3chanic 5 | // @FabriceNeyrat2 6 | // @iq 7 | // @shane 8 | // @XorDev 9 | // + many more 10 | 11 | float map(vec3 p) { 12 | // Domain repetition 13 | p = abs(fract(p) - 0.5); 14 | // Cylinder + planes SDF 15 | return abs(min(length(p.xy) - 0.175, min(p.x, p.y) + 1e-3)) + 1e-3; 16 | } 17 | 18 | vec3 estimateNormal(vec3 p) { 19 | float eps = 0.001; 20 | return normalize(vec3( 21 | map(p + vec3(eps, 0.0, 0.0)) - map(p - vec3(eps, 0.0, 0.0)), 22 | map(p + vec3(0.0, eps, 0.0)) - map(p - vec3(0.0, eps, 0.0)), 23 | map(p + vec3(0.0, 0.0, eps)) - map(p - vec3(0.0, 0.0, eps)) 24 | )); 25 | } 26 | 27 | void mainImage(out vec4 O, in vec2 C) { 28 | vec2 r = iResolution.xy; 29 | vec2 uv = (C - 0.5 * r) / r.y; 30 | 31 | float t = iTime; 32 | float z = fract(dot(C, sin(C))) - 0.5; 33 | vec4 col = vec4(0.0); 34 | vec4 p; 35 | 36 | for (float i = 0.0; i < 77.0; i++) { 37 | // Ray direction 38 | p = vec4(z * normalize(vec3(C - 0.7 * r, r.y)), 0.1 * t); 39 | p.z += t; 40 | 41 | vec4 q = p; 42 | 43 | // Apply "bugged" rotation matrices for glitchy fractal distortion 44 | p.xy *= mat2(cos(2.0 + q.z + vec4(0,11,33,0))); 45 | p.xy *= mat2(cos(q + vec4(0,11,33,0))); 46 | 47 | // Distance estimation 48 | float d = map(p.xyz); 49 | 50 | // Estimate lighting 51 | vec3 pos = p.xyz; 52 | vec3 lightDir = normalize(vec3(0.3, 0.5, 1.0)); 53 | vec3 viewDir = normalize(vec3(uv, 1.0)); 54 | vec3 n = estimateNormal(pos); 55 | vec3 reflectDir = reflect(viewDir, n); 56 | 57 | // Fake environment reflection (sky blue + fade to white) 58 | vec3 envColor = mix(vec3(0.8, 0.4, 0.8), vec3(1.0), 0.5 + 0.5 * reflectDir.y); 59 | 60 | // Specular highlight 61 | float spec = pow(max(dot(reflectDir, lightDir), 0.0), 32.0); 62 | 63 | // Funky palette color using original method 64 | vec4 baseColor = (1.0 + sin(0.5 * q.z + length(p.xyz - q.xyz) + vec4(0,4,3,6))) 65 | / (0.5 + 2.0 * dot(q.xy, q.xy)); 66 | 67 | // Combine base color + environment reflection + specular highlight 68 | vec3 finalColor = baseColor.rgb * 0.1 + envColor * 0.9 + vec3(spec) * 1.2; 69 | 70 | // Brightness weighted accumulation 71 | col.rgb += finalColor / d; 72 | 73 | z += 0.6 * d; 74 | } 75 | 76 | // Compress brightness range 77 | O = vec4(tanh(col.rgb / 2e4), 1.0); 78 | } 79 | -------------------------------------------------------------------------------- /shaders/shiny.glsl: -------------------------------------------------------------------------------- 1 | 2 | // Copyright Inigo Quilez, 2014 - https://iquilezles.org/ 3 | // I am the sole copyright owner of this Work. 4 | // You cannot host, display, distribute or share this Work neither 5 | // as it is or altered, here on Shadertoy or anywhere else, in any 6 | // form including physical and digital. You cannot use this Work in any 7 | // commercial or non-commercial product, website or project. You cannot 8 | // sell this Work and you cannot mint an NFTs of it or train a neural 9 | // network with it without permission. I share this Work for educational 10 | // purposes, and you can link to it, through an URL, proper attribution 11 | // and unmodified screenshot, as part of your educational material. If 12 | // these conditions are too restrictive please contact me and we'll 13 | // definitely work it out. 14 | 15 | 16 | // Other "Iterations" shaders: 17 | // 18 | // "trigonometric" : https://www.shadertoy.com/view/Mdl3RH 19 | // "trigonometric 2" : https://www.shadertoy.com/view/Wss3zB 20 | // "circles" : https://www.shadertoy.com/view/MdVGWR 21 | // "coral" : https://www.shadertoy.com/view/4sXGDN 22 | // "guts" : https://www.shadertoy.com/view/MssGW4 23 | // "inversion" : https://www.shadertoy.com/view/XdXGDS 24 | // "inversion 2" : https://www.shadertoy.com/view/4t3SzN 25 | // "shiny" : https://www.shadertoy.com/view/MslXz8 26 | // "worms" : https://www.shadertoy.com/view/ldl3W4 27 | // "stripes" : https://www.shadertoy.com/view/wlsfRn 28 | 29 | 30 | vec3 shape( in vec2 p ) 31 | { 32 | p *= 2.0; 33 | 34 | vec3 s = vec3( 0.0 ); 35 | vec2 z = p; 36 | for( int i=0; i<8; i++ ) 37 | { 38 | // transform 39 | z += cos(z.yx + cos(z.yx + cos(z.yx+0.5*iTime) ) ); 40 | 41 | // orbit traps 42 | float d = dot( z-p, z-p ); 43 | s.x += 1.0/(1.0+d); 44 | s.y += d; 45 | s.z += sin(atan(z.y-p.y,z.x-p.x)); 46 | 47 | } 48 | 49 | return s / 8.0; 50 | } 51 | 52 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) 53 | { 54 | vec2 pc = (2.0*fragCoord.xy-iResolution.xy)/min(iResolution.y,iResolution.x); 55 | 56 | vec2 pa = pc + vec2(0.04,0.0); 57 | vec2 pb = pc + vec2(0.0,0.04); 58 | 59 | // shape (3 times for diferentials) 60 | vec3 sc = shape( pc ); 61 | vec3 sa = shape( pa ); 62 | vec3 sb = shape( pb ); 63 | 64 | // color 65 | vec3 col = mix( vec3(0.08,0.02,0.15), vec3(0.6,1.1,1.6), sc.x ); 66 | col = mix( col, col.zxy, smoothstep(-0.5,0.5,cos(0.5*iTime)) ); 67 | col *= 0.15*sc.y; 68 | col += 0.4*abs(sc.z) - 0.1; 69 | 70 | // light 71 | vec3 nor = normalize( vec3( sa.x-sc.x, 0.01, sb.x-sc.x ) ); 72 | float dif = clamp(0.5 + 0.5*dot( nor,vec3(0.5773) ),0.0,1.0); 73 | col *= 1.0 + 0.7*dif*col; 74 | col += 0.3 * pow(nor.y,128.0); 75 | 76 | // vignetting 77 | col *= 1.0 - 0.1*length(pc); 78 | 79 | fragColor = vec4( col, 1.0 ); 80 | } 81 | -------------------------------------------------------------------------------- /shaders/grind_torus.glsl: -------------------------------------------------------------------------------- 1 | // https://www.shadertoy.com/view/NsdXzf 2 | // Code by Flopine 3 | 4 | // Thanks to wsmind, leon, XT95, lsdlive, lamogui, 5 | // Coyhot, Alkama,YX, NuSan, slerpy, wwrighter 6 | // BigWings, FabriceNeyret and Blackle for teaching me 7 | 8 | // Thanks LJ for giving me the spark :3 9 | 10 | // Thanks to the Cookie Collective, which build a cozy and safe environment for me 11 | // and other to sprout :) 12 | // https://twitter.com/CookieDemoparty 13 | 14 | 15 | // Based on BigWings tuts ~ https://youtu.be/2dzJZx0yngg 16 | 17 | 18 | #define PI acos(-1.) 19 | #define TAU (2.*PI) 20 | #define rot(a) mat2(cos(a),sin(a),-sin(a),cos(a)) 21 | 22 | #define hash21(x) fract(sin(dot(x,vec2(26.4,32.87)))*467.5) 23 | #define dt(sp) fract(iTime*sp) 24 | 25 | float hexa (vec2 p) 26 | { 27 | p=abs(p); 28 | return max(p.x,dot(p,normalize(vec2(1.,sqrt(3.))))); 29 | } 30 | 31 | float torus (vec3 p, vec2 rs) 32 | { 33 | vec2 q = vec2(hexa(p.xy)-rs.x,p.z); 34 | float a = atan(p.y, p.x); 35 | q *= rot(a+iTime); 36 | q = abs(abs(q)-.6)-0.3; 37 | 38 | return hexa(q)-rs.y; 39 | } 40 | 41 | float g1=0.; 42 | float SDF (vec3 p) 43 | { 44 | p.yz *= rot(-atan(1./sqrt(2.))); 45 | p.xz*=rot(PI/4.); 46 | 47 | float t = torus(p.xzy,vec2(3.,0.3)); 48 | p.y -= sin(dt(0.1)*TAU)*.5+.5; 49 | float s = length(p)-0.8; 50 | g1 += 0.01/(0.01+s*s); 51 | 52 | float d = min(t,s); 53 | 54 | return d; 55 | } 56 | 57 | vec3 getnorm(vec3 p) 58 | { 59 | vec2 eps = vec2(0.001,0.); 60 | return normalize(SDF(p)-vec3(SDF(p-eps.xyy),SDF(p-eps.yxy),SDF(p-eps.yyx))); 61 | } 62 | 63 | float AO (float eps, vec3 p, vec3 n) 64 | {return clamp(SDF(p+eps*n)/eps,0.,1.);} 65 | 66 | float spec (vec3 n, vec3 l, vec3 rd) 67 | { 68 | vec3 h = normalize(l-rd); 69 | return pow(max(dot(n,h),0.),35.); 70 | } 71 | 72 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) 73 | { 74 | vec2 uv = (2.*fragCoord-iResolution.xy)/iResolution.y; 75 | 76 | float dither = hash21(uv); 77 | vec3 ro=vec3(uv*3.8,-50.),rd=normalize(vec3(0.,0.0,1.)),p=ro, 78 | col=vec3(0.),l=vec3(1.,2.,-2.); 79 | 80 | bool hit=false; 81 | for (float i=0.; i<100.; i++) 82 | { 83 | float d = SDF(p); 84 | if (d<0.01) 85 | { 86 | hit=true;break; 87 | } 88 | d *= .75+dither*0.15; 89 | p += d*rd; 90 | } 91 | 92 | if (hit) 93 | { 94 | vec3 n = getnorm(p); 95 | 96 | float light = max(dot(n,normalize(l)),0.), 97 | ao=AO(0.1,p,n)+AO(0.25,p,n)+AO(0.65,p,n), 98 | s = spec(n,l,rd); 99 | 100 | col = mix(vec3(0.5,0.1,0.5),vec3(0.,0.3,0.8),light)*ao/3.+s*vec3(0.,0.8,0.2); 101 | } 102 | col += g1*0.5; 103 | 104 | fragColor = vec4(sqrt(col),1.0); 105 | } 106 | -------------------------------------------------------------------------------- /shaders/clouds.glsl: -------------------------------------------------------------------------------- 1 | // referred https://www.shadertoy.com/view/4sXGRM 2 | 3 | vec3 skytop = vec3(0.05, 0.2, 0.5); 4 | 5 | vec3 light = normalize(vec3(0.1, 0.25, 0.9)); 6 | 7 | vec2 cloudrange = vec2(0.0, 10000.0); 8 | 9 | mat3 m = mat3(0.00, 1.60, 1.20, -1.60, 0.72, -0.96, -1.20, -0.96, 1.28); 10 | 11 | // hash function 12 | float hash(float n) 13 | { 14 | return fract(cos(n) * 114514.1919); 15 | } 16 | 17 | // 3d noise function 18 | float noise(in vec3 x) 19 | { 20 | vec3 p = floor(x); 21 | vec3 f = smoothstep(0.0, 1.0, fract(x)); 22 | 23 | float n = p.x + p.y * 10.0 + p.z * 100.0; 24 | 25 | return mix( 26 | mix(mix(hash(n + 0.0), hash(n + 1.0), f.x), 27 | mix(hash(n + 10.0), hash(n + 11.0), f.x), f.y), 28 | mix(mix(hash(n + 100.0), hash(n + 101.0), f.x), 29 | mix(hash(n + 110.0), hash(n + 111.0), f.x), f.y), f.z); 30 | } 31 | 32 | // Fractional Brownian motion 33 | float fbm(vec3 p) 34 | { 35 | float f = 0.5000 * noise(p); 36 | p = m * p; 37 | f += 0.2500 * noise(p); 38 | p = m * p; 39 | f += 0.1666 * noise(p); 40 | p = m * p; 41 | f += 0.0834 * noise(p); 42 | return f; 43 | } 44 | 45 | vec3 camera(float time) 46 | { 47 | return vec3(5000.0 * sin(1.0 * time), 5000. + 1500. * sin(0.5 * time), 6000.0 * time); 48 | } 49 | 50 | void mainImage(out vec4 fragColor, in vec2 fragCoord) 51 | { 52 | vec2 uv = 2. * fragCoord.xy / iResolution.xy - 1.0; 53 | uv.x *= iResolution.x / iResolution.y; 54 | 55 | float time = (iTime + 13.5 + 44.) * 1.0; 56 | vec3 campos = camera(time); 57 | vec3 camtar = camera(time + 0.4); 58 | 59 | vec3 front = normalize(camtar - campos); 60 | vec3 right = normalize(cross(front, vec3(0.0, 1.0, 0.0))); 61 | vec3 up = normalize(cross(right, front)); 62 | vec3 fragAt = normalize(uv.x * right + uv.y * up + front); 63 | 64 | // clouds 65 | vec4 sum = vec4(0, 0, 0, 0); 66 | for (float depth = 0.0; depth < 100000.0; depth += 200.0) 67 | { 68 | vec3 ray = campos + fragAt * depth; 69 | if (cloudrange.x < ray.y && ray.y < cloudrange.y) 70 | { 71 | float alpha = smoothstep(0.5, 1.0, fbm(ray * 0.00025)); 72 | vec3 localcolor = mix(vec3(1.1, 1.05, 1.0), vec3(0.3, 0.3, 0.2), alpha); 73 | alpha = (1.0 - sum.a) * alpha; 74 | sum += vec4(localcolor * alpha, alpha); 75 | } 76 | } 77 | 78 | float alpha = smoothstep(0.7, 1.0, sum.a); 79 | sum.rgb /= sum.a + 0.0001; 80 | 81 | float sundot = clamp(dot(fragAt, light), 0.0, 1.0); 82 | vec3 col = 0.8 * (skytop); 83 | col += 0.47 * vec3(1.6, 1.4, 1.0) * pow(sundot, 350.0); 84 | col += 0.4 * vec3(0.8, 0.9, 1.0) * pow(sundot, 2.0); 85 | 86 | sum.rgb -= 0.6 * vec3(0.8, 0.75, 0.7) * pow(sundot, 13.0) * alpha; 87 | 88 | sum.rgb += 0.2 * vec3(1.3, 1.2, 1.0) * pow(sundot, 5.0) * (1.0 - alpha); 89 | 90 | col = mix(col, sum.rgb, sum.a); 91 | 92 | fragColor = vec4(col, 1.0); 93 | } 94 | -------------------------------------------------------------------------------- /shaders/tube2.glsl: -------------------------------------------------------------------------------- 1 | // CC0: Clearly a bug 2 | // A "Happy Accident" Shader 3 | 4 | // Twigl: https://twigl.app?ol=true&ss=-OUOudmBPJ57CIb7rAxS 5 | 6 | // This shader uses a technique called "raymarching" to render 3D 7 | // Think of it like casting rays from your eye through each pixel into a 3D world, 8 | // then stepping along each ray until we hit something interesting. 9 | // 10 | // Key concepts for C developers: 11 | // - vec4/vec3/vec2: Like structs with x,y,z,w components (SIMD-style) 12 | // - Swizzling: p.xy means "give me just the x,y parts of vector p" 13 | // - mat2(): Creates a 2x2 rotation matrix from an angle 14 | // - All math operations work on vectors component-wise 15 | // 16 | // ATTRIBUTION: Shader techniques inspired by (alphabetical): 17 | // @byt3_m3chanic 18 | // @FabriceNeyrat2 19 | // @iq 20 | // @shane 21 | // @XorDev 22 | // + many more 23 | 24 | void mainImage(out vec4 O, vec2 C) { 25 | float 26 | i // Loop counter (starts at 0) 27 | , d // Distance to nearest surface 28 | , z = fract(dot(C,sin(C)))-.5 // Ray distance + noise for anti-banding 29 | ; 30 | vec4 31 | o // Accumulated color/lighting 32 | , p // Current 3D position along ray 33 | ; 34 | for( 35 | vec2 r = iResolution.xy // Screen resolution 36 | ; ++i < 77. 37 | ; z += .6*d // Step forward (larger steps when far from surfaces) 38 | ) 39 | // Convert 2D pixel to 3D ray direction 40 | p = vec4(z*normalize(vec3(C-.5*r,r.y)),.1*iTime) 41 | 42 | // Move through 3D space over time 43 | , p.z += iTime 44 | 45 | // Save position for lighting calculations 46 | , O = p 47 | 48 | // Apply rotation matrices to create fractal patterns 49 | // (These transform the 3D coordinates in interesting ways) 50 | , p.xy *= mat2(cos(2.+O.z+vec4(0,11,33,0))) 51 | 52 | // This was originally a bug in the matrix calculation 53 | // The incorrect transformation created an unexpectedly interesting pattern 54 | // Bob Ross would call this a "happy little accident" 55 | , p.xy *= mat2(cos(O+vec4(0,11,33,0))) 56 | 57 | // Calculate color based on position and space distortion 58 | // The sin() creates a nice looking palette, division by dot() creates falloff 59 | , O = (1.+sin(.5*O.z+length(p-O)+vec4(0,4,3,6))) 60 | / (.5+2.*dot(O.xy,O.xy)) 61 | 62 | // Domain repetition, repeats the single line and the 2 planes infinitely 63 | , p = abs(fract(p)-.5) 64 | 65 | // Calculate distance to nearest surface 66 | // This combines a cylinder (length(p.xy)-.125) with 2 planesbox (min(p.x,p.y)) 67 | , d = abs(min(length(p.xy)-.125,min(p.x,p.y)+1e-3))+1e-3 68 | 69 | // Add lighting contribution (brighter when closer to surfaces) 70 | , o += O.w/d*O 71 | ; 72 | 73 | // tanh() compresses the accumulated brightness to 0-1 range 74 | // (Like HDR tone mapping in photography) 75 | O = tanh(o/2e4); 76 | } 77 | -------------------------------------------------------------------------------- /shaders/smoke.glsl: -------------------------------------------------------------------------------- 1 | 2 | //License: CC BY 3.0 3 | //Author: Jan Mróz (jaszunio15) 4 | 5 | /* 6 | Originally I wanted to make noise based on Voronoise by Inigo Quilez, 7 | but without reading his code. 8 | (reference shader: https://www.shadertoy.com/view/Xd23Dh) 9 | 10 | My shader quicky became something different. My concept wasn't 11 | nearly close to what Inigo did. Maybe next time :) 12 | */ 13 | 14 | #define TIME (iTime * 5.0) 15 | 16 | vec2 hash22(vec2 x) 17 | { 18 | return fract(sin(x * mat2(43.37862, 24.58974, 32.37621, 53.32761)) * 4534.3897); 19 | } 20 | 21 | float hash12(vec2 x) 22 | { 23 | return fract(sin(dot(x, vec2(43.37861, 34.58761))) * 342.538772); 24 | } 25 | 26 | vec2 getCellPoint(vec2 cell) 27 | { 28 | float time = TIME * (hash12(cell + 0.123) - 0.5) * 0.5; 29 | float c = cos(time), s = sin(time); 30 | vec2 hash = (hash22(cell) - 0.5) * mat2(c, s, -s, c) + 0.5;; 31 | return hash + cell; 32 | } 33 | 34 | float getCellValue(vec2 cell) 35 | { 36 | return hash12(cell); 37 | } 38 | 39 | float makeSmooth(float x) 40 | { 41 | float mouse = (iMouse.x / iResolution.x); 42 | if (mouse == 0.0) mouse = 1.0 - (cos(iTime * 0.5) * 0.5 + 0.5); 43 | return mix(x * x * (3.0 - 2.0 * x), sqrt(x), mouse); 44 | } 45 | 46 | float modifiedVoronoiNoise12(vec2 uv) 47 | { 48 | vec2 rootCell = floor(uv); 49 | 50 | float value = 0.0; 51 | 52 | for (float x = -1.0; x <= 1.0; x++) 53 | { 54 | for(float y = -1.0; y <= 1.0; y++) 55 | { 56 | vec2 cell = rootCell + vec2(x, y); 57 | vec2 cellPoint = getCellPoint(cell); 58 | float cellValue = getCellValue(cell); 59 | float cellDist = distance(uv, cellPoint); 60 | value += makeSmooth(clamp(1.0 - cellDist, 0.0, 1.0)) * cellValue; 61 | } 62 | } 63 | 64 | return value * 0.5; 65 | } 66 | 67 | float layeredNoise12(vec2 x) 68 | { 69 | float sum = 0.0; 70 | float maxValue = 0.0; 71 | 72 | for (float i = 1.0; i <= 2.0; i *= 2.0) 73 | { 74 | float noise = modifiedVoronoiNoise12(x * i) / i; 75 | sum += noise; 76 | maxValue += 1.0 / i; 77 | } 78 | 79 | return sum / maxValue; 80 | } 81 | 82 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) 83 | { 84 | vec2 uv = (fragCoord.xy - 0.5 * iResolution.xy) / iResolution.y; 85 | vec2 stretchedUV = (fragCoord.xy - 0.5 * iResolution.xy) / iResolution.xy; 86 | float vignette = smoothstep(0.55, 0.0, length(stretchedUV)); 87 | uv.y -= TIME * 0.05; 88 | 89 | uv *= 6.0; 90 | 91 | //just simplified hue shifting stuff with uv based offset 92 | vec4 col = sin(TIME * 0.1 + uv.y * 0.2 + vec4(0,2,4,6)) * 0.5 + 0.5; 93 | vec4 col2 = sin(TIME * 0.1 + 0.6 + uv.y * 0.2 + vec4(0,2,4,6)) * 0.5 + 0.5; 94 | 95 | uv += layeredNoise12(uv); 96 | //uv -= layeredNoise12(uv + 43.0) * 0.5; 97 | float noise = layeredNoise12(uv); 98 | noise *= vignette; 99 | fragColor = mix(col, col2 * 0.2, 1.0 - noise * 2.0); 100 | fragColor = smoothstep(-0.14, 1.1, fragColor); 101 | } 102 | -------------------------------------------------------------------------------- /shaders/rolling.glsl: -------------------------------------------------------------------------------- 1 | // Infection parameters 2 | const float VIRUS_SPEED = 0.1; 3 | const float INFECTION_SPREAD = 4.0; 4 | const float REALITY_FOLD_ITERATIONS = 4.0; 5 | const float DNA_MUTATION_RATE = 8.0; 6 | const vec3 VIRUS_COLOR = vec3(0.9, 0.2, 0.3); 7 | 8 | // Helper for viral DNA patterns 9 | vec2 viralDNA(vec2 uv, float time) { 10 | vec2 dna = uv; 11 | float t = time * VIRUS_SPEED; 12 | 13 | for(float i = 0.0; i < 5.0; i++) { 14 | dna = abs(dna) / dot(dna,dna) - DNA_MUTATION_RATE; 15 | dna *= mat2(cos(t), sin(t), -sin(t), cos(t)); 16 | dna += vec2(sin(t * 0.7), cos(t * 0.8)) * 0.2; 17 | } 18 | return dna; 19 | } 20 | 21 | // Viral growth pattern 22 | float viralGrowth(vec2 p, float time) { 23 | float growth = 0.0; 24 | p *= 1.0; 25 | 26 | for(float i = 0.0; i < 6.0; i++) { 27 | p = abs(p) / dot(p,p) - 1.0; 28 | p = p * mat2(cos(time), sin(time), -sin(time), cos(time)); 29 | growth += exp(-length(p) * 4.0); 30 | } 31 | return growth / 6.0; 32 | } 33 | 34 | // Reality fold with infection 35 | vec3 foldReality(vec2 uv, float time) { 36 | vec2 p = uv; 37 | vec3 infected = vec3(0.0); 38 | float total = 0.0; 39 | 40 | for(float i = 0.0; i < REALITY_FOLD_ITERATIONS; i++) { 41 | // Mutate space 42 | p = viralDNA(p, time + i); 43 | 44 | // Sample infected reality 45 | vec2 samplePoint = fract(p * 0.5 + 0.5); 46 | vec3 texColor = texture(iChannel0, samplePoint).rgb; 47 | 48 | // Calculate infection strength 49 | float infection = viralGrowth(p, time - i); 50 | float weight = exp(-i * 0.3); 51 | 52 | // Infect texColor 53 | vec3 infectedColor = mix(texColor, VIRUS_COLOR, infection); 54 | infected += infectedColor * weight; 55 | total += weight; 56 | } 57 | 58 | return infected / total; 59 | } 60 | 61 | void mainImage(out vec4 fragColor, in vec2 fragCoord) { 62 | vec2 uv = (fragCoord - 0.5 * iResolution.xy) / iResolution.y; 63 | vec2 texUV = fragCoord/iResolution.xy; 64 | 65 | // Get base reality 66 | vec3 reality = texture(iChannel0, texUV).rgb; 67 | 68 | // Generate viral infection 69 | vec2 dna = viralDNA(uv, iTime); 70 | float growth = viralGrowth(uv, iTime); 71 | 72 | // Create infection spread 73 | vec2 infected_uv = texUV + dna * growth * INFECTION_SPREAD; 74 | vec3 infected_reality = foldReality(uv, iTime); 75 | 76 | // Viral pulse 77 | float pulse = sin(length(uv) * 10.0 - iTime * 2.0) * 0.5 + 0.5; 78 | pulse *= growth; 79 | 80 | // Create reality tears 81 | float tear = length(dna) * 0.5; 82 | vec3 tear_color = vec3(1.0, 0.2, 0.3) * pulse; 83 | 84 | // Combine effects 85 | vec3 final = mix(reality, infected_reality, growth); 86 | final += tear_color * tear; 87 | 88 | // Add viral glow 89 | final += VIRUS_COLOR * pulse * 0.3; 90 | 91 | // Reality decomposition 92 | final *= 1.0 + growth * sin(iTime * 5.0) * 0.2; 93 | 94 | fragColor = vec4(final, 1.0); 95 | } 96 | -------------------------------------------------------------------------------- /shaders/whisper.glsl: -------------------------------------------------------------------------------- 1 | // https://www.shadertoy.com/view/XcdczX 2 | // title: Ethereal Whispers 2 3 | // Made with Hatch.one 4 | // License: MIT 5 | 6 | /* Hatch uniforms 7 | uniform float pulseRate; // default: 0.5, min: 0.1, max: 2.0, step: 0.1, title: "Ethereal Pulse" 8 | uniform float voidDepth; // default: 0.7, min: 0.1, max: 2.0, step: 0.1, title: "Void Depth" 9 | uniform float mysteryLevel; // default: 0.6, min: 0.0, max: 1.0, step: 0.01, title: "Mystery Level" 10 | uniform float spiritFlow; // default: 1.0, min: 0.1, max: 3.0, step: 0.1, title: "Spirit Flow" 11 | uniform vec4 auraColor1; // default: #330066, type: Color, title: "Deep Aura" 12 | uniform vec4 auraColor2; // default: #6600ff, type: Color, title: "Spirit Aura" 13 | */ 14 | 15 | #define pulseRate 0.5 16 | #define voidDepth 0.9 17 | #define mysteryLevel 0.6 18 | #define spiritFlow 1.0 19 | #define auraColor1 vec4(0.2, 0.0, 0.4, 1.0) 20 | #define auraColor2 vec4(0.4, 0.0, 1.0, 1.0) 21 | 22 | float getEtherealField(vec2 uv) { 23 | // Create a flowing, organic pattern 24 | float time = iTime * pulseRate; 25 | vec2 moved = uv + vec2( 26 | sin(time * 0.5 + uv.y * 4.0) * 0.1, 27 | cos(time * 0.7 + uv.x * 4.0) * 0.1 28 | ); 29 | 30 | // Multiple layers of ethereal waves 31 | float spirit = sin(moved.x * 6.0 + time) * cos(moved.y * 6.0 + time); 32 | spirit += sin(length(moved * 8.0 + sin(time * 0.5)) * 4.0) * 0.5; 33 | spirit += sin(length(moved * 4.0 - cos(time * 0.7)) * 3.0) * 0.25; 34 | 35 | // Add mouse influence as mysterious force 36 | vec2 mouse = iMouse.xy / iResolution.xy; 37 | float distToMouse = length(uv - mouse); 38 | float mouseForce = sin(distToMouse * 10.0 - time * 2.0) * exp(-distToMouse * 3.0); 39 | 40 | return spirit * 0.5 + mouseForce * mysteryLevel; 41 | } 42 | 43 | vec3 getNormal(vec2 uv, float field) { 44 | vec2 e = vec2(0.01, 0.0); 45 | float dx = getEtherealField(uv + e.xy) - getEtherealField(uv - e.xy); 46 | float dy = getEtherealField(uv + e.yx) - getEtherealField(uv - e.yx); 47 | return normalize(vec3(-dx, -dy, e.x * 2.0)); 48 | } 49 | 50 | void mainImage(out vec4 fragColor, in vec2 fragCoord) { 51 | vec2 uv = fragCoord / iResolution.xy; 52 | 53 | // Get the ethereal field value 54 | float field = getEtherealField(uv) * voidDepth; 55 | 56 | // Calculate ethereal lighting 57 | vec3 normal = getNormal(uv, field); 58 | vec3 lightDir = normalize(vec3( 59 | sin(iTime * spiritFlow) * 0.5, 60 | cos(iTime * spiritFlow * 0.7) * 0.5, 61 | 1.0 62 | )); 63 | 64 | // Create mysterious lighting effect 65 | float diffuse = max(dot(normal, lightDir), 0.0); 66 | float glow = exp(-length(uv - vec2(0.5)) * 2.0); 67 | 68 | // Mix colors based on field value and lighting 69 | vec3 color1 = auraColor1.rgb; 70 | vec3 color2 = auraColor2.rgb; 71 | vec3 finalColor = mix(color1, color2, field * 0.5 + 0.5); 72 | 73 | // Add ethereal glow and lighting 74 | finalColor += vec3(diffuse * 0.8); 75 | finalColor += vec3(glow * 0.2) * color2; 76 | 77 | // Add mysterious shimmer 78 | float shimmer = sin(iTime * 5.0 + field * 10.0) * 0.1 + 0.9; 79 | finalColor *= shimmer; 80 | 81 | // Add depth-based transparency for ethereal effect 82 | float alpha = 0.8 + field * 0.2; 83 | 84 | fragColor = vec4(finalColor, alpha); 85 | } 86 | 87 | -------------------------------------------------------------------------------- /src/colors.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "rpihub75.h" 4 | 5 | 6 | #ifndef BF_EPS 7 | #define BF_EPS 1e-7f 8 | #endif 9 | 10 | 11 | /** 12 | * @brief Branch-lean RGB→HSL. h ∈ [0,1), s ∈ [0,1], l ∈ [0,1]. 13 | * convert RGB to HSL color space 14 | * 15 | * @param in 16 | * @param out 17 | */ 18 | static inline void rgb_to_hsl(const RGBF *in, HSLF *out) { 19 | float r = clamp1f(in->r); 20 | float g = clamp1f(in->g); 21 | float b = clamp1f(in->b); 22 | 23 | // pairwise min/max are cheap and compile well on ARM 24 | float max_rg = fmaxf(r, g); 25 | float min_rg = fminf(r, g); 26 | float max_v = fmaxf(max_rg, b); 27 | float min_v = fminf(min_rg, b); 28 | 29 | float chroma = max_v - min_v; 30 | float l = 0.5f * (max_v + min_v); 31 | out->l = l; 32 | 33 | // Fast path for gray, still a single predictable branch 34 | if (chroma <= BF_EPS) { 35 | out->h = 0.0f; 36 | out->s = 0.0f; 37 | return; 38 | } 39 | 40 | // Branchless saturation: s = chroma / (1 - |2l - 1|) 41 | float denom_s = 1.0f - fabsf(2.0f * l - 1.0f); 42 | denom_s = fmaxf(denom_s, BF_EPS); 43 | out->s = chroma * safe_rcp(denom_s); 44 | 45 | // Choose hue sector without cascaded if/else. 46 | // Break ties deterministically to avoid double matches. 47 | int r_is_max = (r >= g) & (r >= b); 48 | int g_is_max = (!r_is_max) & (g >= b); 49 | // b_is_max is implied when both above are zero. 50 | 51 | float inv_chroma = safe_rcp(chroma); 52 | 53 | // Compute each candidate hue base, then blend using masks. 54 | float h_r = (g - b) * inv_chroma; // sector 0 55 | float h_g = (b - r) * inv_chroma + 2.0f; // sector 2 56 | float h_b = (r - g) * inv_chroma + 4.0f; // sector 4 57 | 58 | // Convert masks to floats, then blend without branches. 59 | float fr = (float)r_is_max; 60 | float fg = (float)g_is_max; 61 | float fb = 1.0f - fr - fg; 62 | 63 | float h = (fr * h_r + fg * h_g + fb * h_b) * (1.0f / 6.0f); 64 | 65 | // Normalize to [0,1) with branchless corrections 66 | h += (h < 0.0f); 67 | h -= (h >= 1.0f); 68 | 69 | out->h = h; 70 | } 71 | 72 | 73 | 74 | /** 75 | * @brief triangular wave that maps hue to channel weight in [0,1] 76 | * @param h 77 | * @return float 78 | */ 79 | static inline float hue_tri_unit(float h) { 80 | // assume h is any real, we wrap using fract 81 | float t = fabsf(fract(h) * 6.0f - 3.0f) - 1.0f; // in [-1,1] 82 | // branchless clamp to [0,1] 83 | return fminf(fmaxf(t, 0.0f), 1.0f); 84 | } 85 | 86 | /** 87 | * @brief Branch-lean HSL -> RGB. h in [0,1) preferred, s,l in [0,1]. 88 | */ 89 | void hsl_to_rgb_fast(HSLF *in, RGBF *out) { 90 | 91 | // optional input clamp if upstream may overshoot 92 | in->h = in->h - floorf(in->h); // wrap to [0,1) 93 | in->s = clamp1f(in->s); 94 | in->l = clamp1f(in->l); 95 | 96 | // chroma and match term 97 | // c = (1 - |2l - 1|) * s 98 | float c = (1.0f - fabsf(2.0f * in->l - 1.0f)) * in->s; 99 | float m = in->l - 0.5f * c; 100 | 101 | // channel weights via shifted hue triangular waves 102 | float r1 = hue_tri_unit(in->h + 1.0f / 3.0f); 103 | float g1 = hue_tri_unit(in->h); 104 | float b1 = hue_tri_unit(in->h - 1.0f / 3.0f); 105 | 106 | // scale and add match 107 | out->r = m + c * r1; 108 | out->g = m + c * g1; 109 | out->b = m + c * b1; 110 | } -------------------------------------------------------------------------------- /shaders/halo.glsl: -------------------------------------------------------------------------------- 1 | // https://www.shadertoy.com/view/3tBGRm 2 | 3 | // noise from https://www.shadertoy.com/view/4sc3z2 4 | vec3 hash33(vec3 p3) 5 | { 6 | p3 = fract(p3 * vec3(.1031,.11369,.13787)); 7 | p3 += dot(p3, p3.yxz+19.19); 8 | return -1.0 + 2.0 * fract(vec3(p3.x+p3.y, p3.x+p3.z, p3.y+p3.z)*p3.zyx); 9 | } 10 | float snoise3(vec3 p) 11 | { 12 | const float K1 = 0.333333333; 13 | const float K2 = 0.166666667; 14 | 15 | vec3 i = floor(p + (p.x + p.y + p.z) * K1); 16 | vec3 d0 = p - (i - (i.x + i.y + i.z) * K2); 17 | 18 | vec3 e = step(vec3(0.0), d0 - d0.yzx); 19 | vec3 i1 = e * (1.0 - e.zxy); 20 | vec3 i2 = 1.0 - e.zxy * (1.0 - e); 21 | 22 | vec3 d1 = d0 - (i1 - K2); 23 | vec3 d2 = d0 - (i2 - K1); 24 | vec3 d3 = d0 - 0.5; 25 | 26 | vec4 h = max(0.6 - vec4(dot(d0, d0), dot(d1, d1), dot(d2, d2), dot(d3, d3)), 0.0); 27 | vec4 n = h * h * h * h * vec4(dot(d0, hash33(i)), dot(d1, hash33(i + i1)), dot(d2, hash33(i + i2)), dot(d3, hash33(i + 1.0))); 28 | 29 | return dot(vec4(31.316), n); 30 | } 31 | 32 | vec4 extractAlpha(vec3 colorIn) 33 | { 34 | vec4 colorOut; 35 | float maxValue = min(max(max(colorIn.r, colorIn.g), colorIn.b), 1.0); 36 | if (maxValue > 1e-5) 37 | { 38 | colorOut.rgb = colorIn.rgb * (1.0 / maxValue); 39 | colorOut.a = maxValue; 40 | } 41 | else 42 | { 43 | colorOut = vec4(0.0); 44 | } 45 | return colorOut; 46 | } 47 | 48 | #define BG_COLOR (vec3(sin(iTime)*0.5+0.5) * 0.0 + vec3(0.0)) 49 | #define time iTime 50 | const vec3 color1 = vec3(0.611765, 0.262745, 0.996078); 51 | const vec3 color2 = vec3(0.298039, 0.760784, 0.913725); 52 | const vec3 color3 = vec3(0.062745, 0.078431, 0.600000); 53 | const float innerRadius = 0.6; 54 | const float noiseScale = 0.65; 55 | 56 | float light1(float intensity, float attenuation, float dist) 57 | { 58 | return intensity / (1.0 + dist * attenuation); 59 | } 60 | float light2(float intensity, float attenuation, float dist) 61 | { 62 | return intensity / (1.0 + dist * dist * attenuation); 63 | } 64 | 65 | void draw( out vec4 _FragColor, in vec2 vUv ) 66 | { 67 | vec2 uv = vUv; 68 | float ang = atan(uv.y, uv.x); 69 | float len = length(uv); 70 | float v0, v1, v2, v3, cl; 71 | float r0, d0, n0; 72 | float r, d; 73 | 74 | // ring 75 | n0 = snoise3( vec3(uv * noiseScale, time * 0.5) ) * 0.5 + 0.5; 76 | r0 = mix(mix(innerRadius, 1.0, 0.4), mix(innerRadius, 1.0, 0.6), n0); 77 | d0 = distance(uv, r0 / len * uv); 78 | v0 = light1(1.0, 10.0, d0); 79 | v0 *= smoothstep(r0 * 1.05, r0, len); 80 | cl = cos(ang + time * 2.0) * 0.5 + 0.5; 81 | 82 | // high light 83 | float a = time * -1.0; 84 | vec2 pos = vec2(cos(a), sin(a)) * r0; 85 | d = distance(uv, pos); 86 | v1 = light2(1.5, 5.0, d); 87 | v1 *= light1(1.0, 50.0 , d0); 88 | 89 | // back decay 90 | v2 = smoothstep(1.0, mix(innerRadius, 1.0, n0 * 0.5), len); 91 | 92 | // hole 93 | v3 = smoothstep(innerRadius, mix(innerRadius, 1.0, 0.5), len); 94 | 95 | // color 96 | vec3 c = mix(color1, color2, cl); 97 | vec3 col = mix(color1, color2, cl); 98 | col = mix(color3, col, v0); 99 | col = (col + v1) * v2 * v3; 100 | col.rgb = clamp(col.rgb, 0.0, 1.0); 101 | 102 | //gl_FragColor = extractAlpha(col); 103 | _FragColor = extractAlpha(col); 104 | } 105 | 106 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) 107 | { 108 | vec2 uv = (fragCoord*2.-iResolution.xy)/iResolution.y; 109 | 110 | vec4 col; 111 | draw(col, uv); 112 | 113 | vec3 bg = BG_COLOR; 114 | 115 | fragColor.rgb = mix(bg, col.rgb, col.a); //normal blend 116 | } 117 | 118 | -------------------------------------------------------------------------------- /shaders/dragon_torus.glsl: -------------------------------------------------------------------------------- 1 | // https://www.shadertoy.com/view/lt2fDz 2 | /* 3 | * License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 4 | * Created by bal-khan 5 | */ 6 | 7 | vec2 march(vec3 pos, vec3 dir); 8 | vec3 camera(vec2 uv); 9 | void rotate(inout vec2 v, float angle); 10 | 11 | float t; // time 12 | vec3 ret_col; // torus color 13 | vec3 h; // light amount 14 | 15 | #define I_MAX 400. 16 | #define E 0.00001 17 | #define FAR 50. 18 | #define PI 3.14 19 | 20 | // blackbody by aiekick : https://www.shadertoy.com/view/lttXDn 21 | 22 | // -------------blackbody----------------- // 23 | 24 | // return color from temperature 25 | //http://www.physics.sfasu.edu/astro/color/blackbody.html 26 | //http://www.vendian.org/mncharity/dir3/blackbody/ 27 | //http://www.vendian.org/mncharity/dir3/blackbody/UnstableURLs/bbr_color.html 28 | 29 | vec3 blackbody(float Temp) 30 | { 31 | vec3 col = vec3(255.); 32 | col.x = 56100000. * pow(Temp,(-3. / 2.)) + 148.; 33 | col.y = 100.04 * log(Temp) - 623.6; 34 | if (Temp > 6500.) col.y = 35200000. * pow(Temp,(-3. / 2.)) + 184.; 35 | col.z = 194.18 * log(Temp) - 1448.6; 36 | col = clamp(col, 0., 255.)/255.; 37 | if (Temp < 1000.) col *= Temp/1000.; 38 | return col; 39 | } 40 | 41 | // -------------blackbody----------------- // 42 | 43 | void mainImage(out vec4 c_out, in vec2 f) 44 | { 45 | t = iTime*.125; 46 | vec3 col = vec3(0., 0., 0.); 47 | vec2 R = iResolution.xy, 48 | uv = vec2(f-R/2.) / R.y; 49 | vec3 dir = camera(uv); 50 | vec3 pos = vec3(.0, .0, 0.0); 51 | 52 | pos.z = 4.5+1.5*sin(t*10.); 53 | h*=0.; 54 | vec2 inter = (march(pos, dir)); 55 | col.xyz = ret_col*(1.-inter.x*.0125); 56 | col += h * .4; 57 | c_out = vec4(col,1.0); 58 | } 59 | 60 | float scene(vec3 p) 61 | { 62 | float var; 63 | float mind = 1e5; 64 | p.z += 10.; 65 | 66 | rotate(p.xz, 1.57-.5*iTime ); 67 | rotate(p.yz, 1.57-.5*iTime ); 68 | var = atan(p.x,p.y); 69 | vec2 q = vec2( ( length(p.xy) )-6.,p.z); 70 | rotate(q, var*.25+iTime*2.*0.); 71 | vec2 oq = q ; 72 | q = abs(q)-2.5; 73 | if (oq.x < q.x && oq.y > q.y) 74 | rotate(q, ( (var*1.)+iTime*0.)*3.14+iTime*0.); 75 | else 76 | rotate(q, ( .28-(var*1.)+iTime*0.)*3.14+iTime*0.); 77 | ret_col = 1.-vec3(.350, .2, .3); 78 | mind = length(q)+.5+1.05*(length(fract(q*.5*(3.+3.*sin(var*1. - iTime*2.)) )-.5)-1.215); 79 | h -= vec3(-3.20,.20,1.0)*vec3(1.)*.0025/(.051+(mind-sin(var*1. - iTime*2. + 3.14)*.125 )*(mind-sin(var*1. - iTime*2. + 3.14)*.125 ) ); 80 | h -= vec3(1.20,-.50,-.50)*vec3(1.)*.025/(.501+(mind-sin(var*1. - iTime*2.)*.5 )*(mind-sin(var*1. - iTime*2.)*.5 ) ); 81 | h += vec3(.25, .4, .5)*.0025/(.021+mind*mind); 82 | 83 | return (mind); 84 | } 85 | 86 | vec2 march(vec3 pos, vec3 dir) 87 | { 88 | vec2 dist = vec2(0.0, 0.0); 89 | vec3 p = vec3(0.0, 0.0, 0.0); 90 | vec2 s = vec2(0.0, 0.0); 91 | 92 | for (float i = -1.; i < I_MAX; ++i) 93 | { 94 | p = pos + dir * dist.y; 95 | dist.x = scene(p); 96 | dist.y += dist.x*.2; // makes artefacts disappear 97 | // log trick by aiekick 98 | if (log(dist.y*dist.y/dist.x/1e5) > .0 || dist.x < E || dist.y > FAR) 99 | { 100 | break; 101 | } 102 | s.x++; 103 | } 104 | s.y = dist.y; 105 | return (s); 106 | } 107 | 108 | // Utilities 109 | 110 | void rotate(inout vec2 v, float angle) 111 | { 112 | v = vec2(cos(angle)*v.x+sin(angle)*v.y,-sin(angle)*v.x+cos(angle)*v.y); 113 | } 114 | 115 | vec3 camera(vec2 uv) 116 | { 117 | float fov = 1.; 118 | vec3 forw = vec3(0.0, 0.0, -1.0); 119 | vec3 right = vec3(1.0, 0.0, 0.0); 120 | vec3 up = vec3(0.0, 1.0, 0.0); 121 | 122 | return (normalize((uv.x) * right + (uv.y) * up + fov * forw)); 123 | } 124 | 125 | -------------------------------------------------------------------------------- /shaders/stars.glsl: -------------------------------------------------------------------------------- 1 | // https://www.shadertoy.com/view/MXjBRK 2 | 3 | const float pi = 3.1415926535897; 4 | 5 | float rand2(vec2 uv) { 6 | return fract(sin(dot(uv, vec2(13.337, 61.998))) * 48675.75647); 7 | } 8 | 9 | vec2 rotate(vec2 uv, float a) { 10 | return vec2(uv.y * cos(a) + uv.x * sin(a), uv.x * cos(a) - uv.y * sin(a)); 11 | } 12 | 13 | vec2 rand2x2(vec2 uv) { 14 | return vec2(rand2(uv), rand2(-uv)); 15 | } 16 | 17 | vec3 rand2x3(vec2 uv) { 18 | return vec3(rand2(uv), rand2(-uv), rand2(vec2(-uv.x - 5., uv.y + 1.))); 19 | } 20 | 21 | float perl(vec2 uv, float t) { 22 | vec2 id = floor(uv); 23 | vec2 loc = fract(uv); 24 | vec2 sloc = smoothstep(0., 1., loc); 25 | return mix( 26 | mix( 27 | dot(loc, rotate(vec2(1.), rand2(id) * (pi * 2. + t))), 28 | dot(loc - vec2(1., 0.), rotate(vec2(1.), rand2(id + vec2(1., 0.)) * (pi * 2. + t))), 29 | sloc.x 30 | ), 31 | mix( 32 | dot(loc - vec2(0., 1.), rotate(vec2(1.), rand2(id + vec2(0., 1.)) * (pi * 2. + t))), 33 | dot(loc - vec2(1., 1.), rotate(vec2(1.), rand2(id + vec2(1., 1.)) * (pi * 2. + t))), 34 | sloc.x 35 | ), 36 | sloc.y 37 | ); 38 | } 39 | 40 | float fperl(vec2 uv, float t, float iter) { 41 | float o = 0., k = 0.; 42 | for (float i = 0.; i < iter; i++) { 43 | o += perl(uv * pow(2., i), t * pow(2., i)) / pow(2., i); 44 | k += 1. / pow(2., i); 45 | } 46 | return o / k; 47 | } 48 | 49 | float vor(vec2 uv) { 50 | vec2 id = floor(uv); 51 | vec2 loc = fract(uv); 52 | float o = 100.; 53 | for (float x = -1.; x <= 1.; x++) { 54 | for (float y = -1.; y <= 1.; y++) { 55 | o = min(o, distance(sin(2.5 * pi * rand2x2(id + vec2(x, y))) * 0.8 + 0.2, loc - vec2(x, y))); 56 | } 57 | } 58 | return o; 59 | } 60 | 61 | vec3 vorid3(vec2 uv) { 62 | vec2 id = floor(uv); 63 | vec2 loc = fract(uv); 64 | float o = 1000.; 65 | vec3 ou = vec3(0); 66 | for (float x = -1.; x <= 1.; x++) { 67 | for (float y = -1.; y <= 1.; y++) { 68 | float d = distance(sin(2.5 * pi * rand2x2(id + vec2(x, y))) * 0.8 + 0.2, loc - vec2(x, y)); 69 | if (o > d) { 70 | o = d; 71 | ou = rand2x3(id + vec2(x, y)); 72 | } 73 | } 74 | } 75 | return ou; 76 | } 77 | 78 | vec3 star(vec2 uv) { 79 | float val = vor(uv * 3.); 80 | val = 0.01 / val; 81 | val = pow(val, 1.7); 82 | vec3 col = vec3(val) * (vorid3(uv * 3.)); 83 | return col * fperl(uv / 2., 0., 2.); 84 | } 85 | 86 | vec3 fstar(vec2 uv, float iter, float t) { 87 | vec3 o = vec3(0); 88 | for (float i = 0.; i < iter; i++) { 89 | o += star(rotate(uv + vec2(t, 0.) / pow(1.5, i), i) * pow(1.5, i)); 90 | } 91 | return o; 92 | } 93 | 94 | float fnebula(vec2 uv, float iter, float t) { 95 | float o = 0.; 96 | for (float i = 0.; i < iter; i++) { 97 | o += fperl(rotate(uv + vec2(t, 0.) / pow(1.5, i), i) * pow(1.5, i) / 2., 0., 6.); 98 | } 99 | return o; 100 | } 101 | 102 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) 103 | { 104 | vec2 uv = gl_FragCoord.xy / iResolution.xy; 105 | uv = uv * 2. - 1.; 106 | if (iResolution.x > iResolution.y) { 107 | uv.x = uv.x * iResolution.x / iResolution.y; 108 | } 109 | if (iResolution.y > iResolution.x) { 110 | uv.y = uv.y * iResolution.y / iResolution.x; 111 | } 112 | 113 | vec3 col = fstar(uv, 7., iTime / 5.); 114 | col *= 10.; 115 | col = pow(col, vec3(1)); 116 | col = col.r * vec3(1, 0.45, 0.4) + col.g * vec3(0.4, 0.4, 1) + col.b * vec3(1); 117 | col = vec3(0, 0, 0.05) + clamp(vec3(0), vec3(1), vec3(0, 0, 0.03) + col); 118 | 119 | float n = fnebula(uv, 7., iTime / 5.); 120 | 121 | n = n * 0.4; 122 | n = clamp(n, 0., 1.); 123 | 124 | n = 1. - n; 125 | n = 0.5 / n; 126 | n = n - 0.5; 127 | 128 | vec3 vnb = n * vec3(0.7, 0.1, 1); 129 | vnb = clamp(vnb, vec3(0), vec3(1)); 130 | fragColor = vec4(vnb + col, 1); 131 | } 132 | -------------------------------------------------------------------------------- /shaders/cyber.glsl: -------------------------------------------------------------------------------- 1 | // https://www.shadertoy.com/view/XcXXzS 2 | 3 | int hexid; 4 | vec3 hpos, point, pt; 5 | float tcol, bcol, hitbol, hexpos, fparam=0.; 6 | 7 | mat2 rot(float a) { 8 | float s=sin(a),c=cos(a); 9 | return mat2(c,s,-s,c); 10 | } 11 | 12 | vec3 path(float t) { 13 | return vec3(sin(t*.3+cos(t*.2)*.5)*4.,cos(t*.2)*3.,t); 14 | } 15 | 16 | float hexagon( in vec2 p, in float r ) 17 | { 18 | const vec3 k = vec3(-0.866025404,0.5,0.577350269); 19 | p = abs(p); 20 | p -= 2.0*min(dot(k.xy,p),0.0)*k.xy; 21 | p -= vec2(clamp(p.x, -k.z*r, k.z*r), r); 22 | return length(p)*sign(p.y); 23 | } 24 | 25 | float hex(vec2 p) { 26 | p.x *= 0.57735*2.0; 27 | p.y+=mod(floor(p.x),2.0)*0.5; 28 | p=abs((mod(p,1.0)-0.5)); 29 | return abs(max(p.x*1.5 + p.y, p.y*2.0) - 1.0); 30 | } 31 | 32 | mat3 lookat(vec3 dir) { 33 | vec3 up=vec3(0.,1.,0.); 34 | vec3 rt=normalize(cross(dir,up)); 35 | return mat3(rt, cross(rt,dir), dir); 36 | } 37 | 38 | float hash12(vec2 p) 39 | { 40 | p*=1000.; 41 | vec3 p3 = fract(vec3(p.xyx) * .1031); 42 | p3 += dot(p3, p3.yzx + 33.33); 43 | return fract((p3.x + p3.y) * p3.z); 44 | } 45 | 46 | float de(vec3 p) { 47 | pt=vec3(p.xy-path(p.z).xy,p.z); 48 | float h=abs(hexagon(pt.xy,3.+fparam)); 49 | hexpos=hex(pt.yz); 50 | tcol=smoothstep(.0,.15,hexpos); 51 | h-=tcol*.1; 52 | vec3 pp=p-hpos; 53 | pp=lookat(point)*pp; 54 | pp.y-=abs(sin(iTime))*3.+(fparam-(2.-fparam)); 55 | pp.yz*=rot(-iTime); 56 | float bola=length(pp)-1.; 57 | bcol=smoothstep(0.,.5,hex(pp.xy*3.)); 58 | bola-=bcol*.1; 59 | vec3 pr=p; 60 | pr.z=mod(p.z,6.)-3.; 61 | float d=min(h,bola); 62 | if (d==bola) { 63 | tcol=1.; 64 | hitbol=1.; 65 | } 66 | else { 67 | hitbol=0.; 68 | bcol=1.; 69 | } 70 | return d*.5; 71 | } 72 | 73 | vec3 normal(vec3 p) { 74 | vec2 e=vec2(0.,.005); 75 | return normalize(vec3(de(p+e.yxx),de(p+e.xyx),de(p+e.xxy))-de(p)); 76 | } 77 | 78 | vec3 march(vec3 from, vec3 dir) { 79 | vec3 odir=dir; 80 | vec3 p=from,col=vec3(0.); 81 | float d,td=0.; 82 | vec3 g=vec3(0.); 83 | for (int i=0; i<200; i++) { 84 | d=de(p); 85 | if (d<.001||td>200.) break; 86 | p+=dir*d; 87 | td+=d; 88 | g+=.1/(.1+d)*hitbol*abs(normalize(point)); 89 | } 90 | float hp=hexpos*(1.-hitbol); 91 | p-=dir*.01; 92 | vec3 n=normal(p); 93 | if (d<.001) { 94 | col=pow(max(0.,dot(-dir,n)),2.)*vec3(.6,.7,.8)*tcol*bcol; 95 | } 96 | col+=float(hexid); 97 | vec3 pr=pt; 98 | dir=reflect(dir,n); 99 | td=0.; 100 | for (int i=0; i<200; i++) { 101 | d=de(p); 102 | if (d<.001||td>200.) break; 103 | p+=dir*d; 104 | td+=d; 105 | g+=.1/(.1+d)*abs(normalize(point)); 106 | } 107 | float zz=p.z; 108 | if (d<.001) { 109 | vec3 refcol=pow(max(0.,dot(-odir,n)),2.)*vec3(.6,.7,.8)*tcol*bcol; 110 | p=pr; 111 | p=abs(.5-fract(p*.1)); 112 | float m=100.; 113 | for (int i=0; i<10; i++) { 114 | p=abs(p)/dot(p,p)-.8; 115 | m=min(m,length(p)); 116 | } 117 | col=mix(col,refcol,m)-m*.3; 118 | col+=step(.3,hp)*step(.9,fract(pr.z*.05+iTime*.5+hp*.1))*.7; 119 | col+=step(.3,hexpos)*step(.9,fract(zz*.05+iTime+hexpos*.1))*.3; 120 | } 121 | col+=g*.03; 122 | col.rb*=rot(odir.y*.5); 123 | return col; 124 | } 125 | 126 | 127 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) 128 | { 129 | vec2 uv = fragCoord/iResolution.xy-.5; 130 | uv.x*=iResolution.x/iResolution.y; 131 | float t=iTime*2.; 132 | vec3 from=path(t); 133 | if (mod(iTime-10.,20.)>10.) { 134 | from=path(floor(t/20.)*20.+10.); 135 | from.x+=2.; 136 | } 137 | hpos=path(t+3.); 138 | vec3 adv=path(t+2.); 139 | vec3 dir=normalize(vec3(uv,.7)); 140 | vec3 dd=normalize(adv-from); 141 | point=normalize(adv-hpos); 142 | point.xz*=rot(sin(iTime)*.2); 143 | dir=lookat(dd)*dir; 144 | vec3 col = march(from, dir); 145 | col*=vec3(1.,.9,.8); 146 | fragColor = vec4(col,1.0); 147 | } 148 | -------------------------------------------------------------------------------- /shaders/cartoon.glsl: -------------------------------------------------------------------------------- 1 | 2 | // Fast Edge detection by nimitz (twitter: @stormoid) 3 | // https://www.shadertoy.com/view/4s2XRd 4 | // License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License 5 | // Contact the author for other licensing options 6 | 7 | #define EDGE_SIZE 0.14 8 | #define SMOOTH 0.025 9 | 10 | #define ITR 80 11 | #define FAR 40. 12 | #define time iTime 13 | float hash( float n ) { return fract(sin(n)*43758.5453); } 14 | 15 | vec3 rotx(vec3 p, float a) 16 | { 17 | float s = sin(a), c = cos(a); 18 | return vec3(p.x, c*p.y - s*p.z, s*p.y + c*p.z); 19 | } 20 | vec3 roty(vec3 p, float a) 21 | { 22 | float s = sin(a), c = cos(a); 23 | return vec3(c*p.x + s*p.z, p.y, -s*p.x + c*p.z); 24 | } 25 | 26 | vec2 map(vec3 p) 27 | { 28 | vec3 id = floor( (p+3.)/6.0); 29 | p = mod( p+3., 6.0 ) - 3.; 30 | float rid = hash(dot(id,vec3(7.,43,113))); 31 | p = rotx(p,time*1.0+rid+sin(rid*5.+time)); 32 | p = roty(p,time*1.0+rid*1.1); 33 | 34 | float d = mix((max(abs(p.x),max(abs(p.y),abs(p.z)))-0.5),max(length(p)-1.,-(length(p)-0.4)),rid); 35 | return vec2(d*.85,rid); 36 | } 37 | 38 | 39 | /* 40 | Keeping track of min distance, then, when the min distance 41 | is both under a given threshold and starts increasing (meaning that 42 | a fold was just passed) then I mark that pixel as an edge. The min 43 | distance can then be smoothed allowing for arbitrarily smooth edges. 44 | */ 45 | vec4 march(in vec3 ro, in vec3 rd) 46 | { 47 | float precis = 0.001; 48 | float h=precis*2.0; 49 | vec2 d = vec2(0.,10000.); 50 | float md = 1.; 51 | float id = 0.;; 52 | bool stp = false; 53 | for( int i=0; i=FAR ) break; 56 | d.x += h; 57 | vec2 res = map(ro+rd*d.x); 58 | if (!stp) 59 | { 60 | md = min(md,res.x); 61 | if (h < EDGE_SIZE && h < res.x && i>0) 62 | { 63 | stp = true; 64 | d.y = d.x; 65 | } 66 | } 67 | h = res.x; 68 | id = res.y; 69 | } 70 | 71 | if (stp) md = smoothstep(EDGE_SIZE-SMOOTH, EDGE_SIZE+0.01, md); 72 | else md = 1.; 73 | return vec4(d, md, id); 74 | } 75 | 76 | vec3 normal(in vec3 p, in float d) 77 | { 78 | vec2 e = vec2(-1., 1.)*0.003*d; 79 | return normalize(e.yxx*map(p + e.yxx).x + e.xxy*map(p + e.xxy).x + 80 | e.xyx*map(p + e.xyx).x + e.yyy*map(p + e.yyy).x ); 81 | } 82 | 83 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) 84 | { 85 | vec2 q = fragCoord.xy/iResolution.xy; 86 | vec2 p = -1.0 + 2.0*q; 87 | p.x*=iResolution.x/iResolution.y; 88 | vec2 mo = iMouse.xy/iResolution.xy*2.-1.; 89 | mo = (mo==vec2(-1.))?mo=vec2(0.):mo; 90 | mo.x *= iResolution.x/iResolution.y; 91 | 92 | //camera 93 | vec3 ro = vec3(4.1,-time*4.,time-0.5); 94 | vec3 rd = normalize(vec3(p,2.5)); 95 | rd = roty(rd,sin(time*0.4)*0.5+0.9+mo.x); 96 | rd = rotx(rd,sin(time*0.24+sin(time*1.0)*1.)+0.9); 97 | 98 | vec4 rz = march(ro,rd); 99 | vec3 ligt = normalize( vec3(-.5, 0.2, -0.2) ); 100 | float sun = dot(rd,ligt); 101 | vec3 bg = vec3(0.5,0.6,.9)*sun*0.5+0.6; 102 | vec3 col = bg; 103 | 104 | if ( rz.x < FAR ) 105 | { 106 | vec3 pos = ro+rz.x*rd; 107 | float d = distance(ro,pos); 108 | vec3 nor= normal(pos,d); 109 | vec3 h = normalize(ligt - rd); 110 | col = sqrt(col); 111 | col = mix(sin(vec3(1,2,3)*rz.w*1.9)*0.5+0.35,col,0.2); 112 | 113 | float dif = clamp( dot(nor, ligt), 0., 1.); 114 | float spe = pow(clamp(dot(nor,h), 0., 1.),70.); 115 | float fre = 0.1*pow(clamp(1. + dot(nor, rd), 0., 1.), 2.); 116 | vec3 brdf = 1.5*vec3(.10, .11, .11); 117 | brdf += 1.30*dif*vec3(1., .9, .75); 118 | col = col*brdf + col*spe + fre*col; 119 | } 120 | 121 | col = mix(col,bg,smoothstep(30.,40.,rz.x)); //Distance fog 122 | col *= mix(rz.z,1.,smoothstep(30.,40.,rz.y)); //Edges + Fog (using edge-eye distance) 123 | 124 | col = pow(col, vec3(.8))*1.; 125 | //vignetting from iq 126 | col *= 0.4 + 0.6*pow( 16.0*q.x*q.y*(1.0-q.x)*(1.0-q.y), 0.2 ); 127 | 128 | fragColor = vec4( col, 1.0 ); 129 | } 130 | -------------------------------------------------------------------------------- /shaders/ghost.glsl: -------------------------------------------------------------------------------- 1 | // https://www.shadertoy.com/view/Mc3yRs 2 | // Funzione di supporto per smooth min 3 | float smin(float a, float b, float k) { 4 | float h = clamp(0.5 + 0.5 * (b - a) / k, 0.0, 1.0); 5 | return mix(b, a, h) - k * h * (1.0 - h); 6 | } 7 | 8 | void mainImage(out vec4 fragColor, in vec2 fragCoord) { 9 | // Normalizza le coordinate 10 | vec2 uv = (fragCoord - 0.5 * iResolution.xy) / iResolution.y; 11 | 12 | // Aggiungi un movimento più complesso e variabile 13 | float time = iTime * 0.5; 14 | vec2 ghostPos = vec2( 15 | cos(time * 1.2) * 0.4 + sin(time * 0.9) * 0.1, 16 | sin(time * 1.1) * 0.4 + cos(time * 0.7) * 0.15 17 | ); 18 | 19 | // Aggiungi distorsione ondulata 20 | uv -= ghostPos; 21 | uv.x += sin(uv.y * 10.0 + time * 2.0) * 0.02; 22 | uv.y += cos(uv.x * 8.0 + time * 1.5) * 0.015; 23 | 24 | // Forma base più complessa 25 | float ghost = length(uv - vec2(0.0, 0.1)) - 0.22; 26 | 27 | // Corpo più elaborato con multiple onde 28 | float bodyWave = sin(uv.x * 12.0 + time * 2.5) * 0.03 + 29 | sin(uv.x * 16.0 + time * 1.8) * 0.02; 30 | float bodyPulse = sin(time * 1.8) * 0.02; 31 | float body = length(vec2(uv.x * (1.0 + sin(uv.y * 4.0) * 0.12), 32 | uv.y + 0.12 + bodyWave + bodyPulse)) - 0.22; 33 | 34 | // Sfuma il collegamento tra testa e corpo 35 | ghost = smin(ghost, body, 0.12); 36 | 37 | // Occhi più elaborati con movimenti 38 | vec2 eyeUV = uv - vec2(-0.06, 0.13); 39 | float leftEye = length(eyeUV) - 0.035 - sin(time * 3.0) * 0.005; 40 | float leftPupil = length(eyeUV - vec2(0.01, -0.01 - sin(time * 4.0) * 0.003)) - 0.015; 41 | 42 | eyeUV = uv - vec2(0.06, 0.13); 43 | float rightEye = length(eyeUV) - 0.035 - sin(time * 3.2) * 0.005; 44 | float rightPupil = length(eyeUV - vec2(-0.01, -0.01 - sin(time * 4.2) * 0.003)) - 0.015; 45 | 46 | // Bocca ovale nera con movimento ondulante 47 | vec2 mouthUV = uv - vec2(0.0, 0.05); 48 | float mouth = length(vec2(mouthUV.x * 1.5 + sin(time * 2.8) * 0.01, mouthUV.y)) - 0.02; 49 | 50 | // Effetto nebuloso intorno al fantasma 51 | float fog = 0.0; 52 | for(int i = 0; i < 8; i++) { 53 | float angle = float(i) * 3.14159 * 2.0 / 8.0; 54 | vec2 offset = vec2(cos(angle), sin(angle)) * 0.22; 55 | fog += smoothstep(0.22, 0.0, length(uv - offset * (0.5 + sin(iTime + float(i)) * 0.25))); 56 | } 57 | 58 | // Parte inferiore più elaborata e nebulosa 59 | float bottom = -1.0; 60 | for(int i = 0; i < 7; i++) { 61 | float x = float(i) * 0.08 - 0.24; 62 | float wave = sin(iTime * 1.8 + float(i) * 3.14) * 0.05; 63 | float size = 0.07 + sin(iTime + float(i)) * 0.012; 64 | bottom = max(bottom, smoothstep(0.035, 0.0, length(uv - vec2(x, -0.18 + wave)) - size)); 65 | } 66 | 67 | // Effetti di luce e ombra 68 | vec3 col = vec3(0.0); 69 | float ghostShape = smoothstep(0.01, -0.01, ghost); 70 | ghostShape = max(ghostShape, bottom); 71 | 72 | // Gradiente di colore per effetto spettrale 73 | vec3 ghostColor = mix( 74 | vec3(0.7, 0.78, 1.0), // Blu più chiaro 75 | vec3(0.95, 0.95, 1.0), // Bianco spettrale 76 | uv.y + 0.5 77 | ); 78 | 79 | // Aggiungi luminescenza interna 80 | float innerGlow = smoothstep(0.35, 0.0, ghost) * 0.6; 81 | ghostColor += vec3(0.25, 0.35, 0.45) * innerGlow; 82 | 83 | // Applica il colore base del fantasma 84 | col += ghostColor * (ghostShape + fog * 0.24); 85 | 86 | // Aggiungi gli occhi e la bocca 87 | col *= 1.0 - smoothstep(0.01, -0.01, leftEye) * 0.85; 88 | col *= 1.0 - smoothstep(0.01, -0.01, rightEye) * 0.85; 89 | col *= 1.0 - smoothstep(0.01, -0.01, mouth) * 1.0; 90 | 91 | // Aggiungi le pupille 92 | col *= 1.0 - smoothstep(0.01, -0.01, leftPupil); 93 | col *= 1.0 - smoothstep(0.01, -0.01, rightPupil); 94 | 95 | // Effetto di bagliore 96 | float glow = smoothstep(0.35, 0.22, ghost) * 0.8; 97 | col += vec3(0.45, 0.55, 0.8) * glow * (0.6 + sin(iTime) * 0.15); 98 | 99 | // Sfondo con nebbia atmosferica 100 | vec3 bgColor = vec3(0.08, 0.1, 0.13); 101 | bgColor += fog * vec3(0.06, 0.08, 0.12); 102 | 103 | // Miscela il fantasma con lo sfondo 104 | float alpha = ghostShape * (0.85 + fog * 0.15); 105 | col = mix(bgColor, col, alpha); 106 | 107 | fragColor = vec4(col, 1.0); 108 | } 109 | -------------------------------------------------------------------------------- /example.c: -------------------------------------------------------------------------------- 1 | /** 2 | * This is an example program using the rpi-gpu-hub75 library. 3 | * To compile: 4 | * gcc -O3 -Wall -lrpihub75_gpu example.c -o example 5 | * ./example 6 | * # this should display command line options 7 | * # example for 4 64x64 panels (128x128 pixels) 2 chains connected to 2 ports, 8 | * # 48 pwm color bits, 192 brightness, 2.2 gamma, render the cartoon.glsl shader 9 | * # at 120 fps with 10 | * ./example -w 128 -h 128 -p 2 -c 2 -d 48 -b 192 -g 2.2 -f 120 -s shaders/cartoon.glsl 11 | * 12 | */ 13 | // TODO: add make file flag for enabling asserts 14 | //#define ENABLE_ASSEERTS 0 15 | // replace #define with scene debug printing options... 16 | // NOTE: this is defined in rpihub75.h and must be recompiled and reinstalled with the lib.... 17 | //#define CONSOLE_DEBUG 1 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | unsigned int ri(unsigned int max) { 27 | return rand() % max; 28 | } 29 | 30 | // our CPU rendering implementation, see gpu.c for shader rendering details 31 | void* render_cpu(void *arg) { 32 | // get the current scene info 33 | scene_info *scene = (scene_info*)arg; 34 | // allocate memory for image data, we can also use the preallocated scene->image if that's easier 35 | uint8_t *img = malloc(scene->width * scene->height * scene->stride); 36 | memset(img, 0, scene->width * scene->height * scene->stride); 37 | 38 | debug("rendering on CPU\n"); 39 | // need to pause a second for gpio to be setup 40 | usleep(50000); 41 | for(;;) { 42 | // darken every pixel in the image for each byte of R,G,B data 43 | if (1) { 44 | for (int i=0; iheight*scene->width*scene->stride; i++) { 45 | scene->image[i] = (uint8_t)scene->image[i] * 0.96f; 46 | } 47 | } 48 | 49 | 50 | // generate some random points on the screen 51 | uint16_t x1 = ri(scene->width); 52 | uint16_t x2 = ri(scene->width); 53 | uint16_t x3 = ri(scene->width); 54 | uint16_t y1 = ri(scene->height); 55 | uint16_t y2 = ri(scene->height); 56 | uint16_t y3 = ri(scene->height); 57 | 58 | // generate a random color 59 | RGB color = {ri(250), ri(250), ri(250)}; 60 | 61 | hub_triangle_aa(scene, x1, y1, x2, y2, x3, y3, color); 62 | 63 | // draw a line 64 | //hub_line(scene, x1, y1, x2, y2, color); 65 | 66 | // draw a rectangle 67 | //hub_fill(scene, x1, y1, x2, y2, color); 68 | 69 | // draw a rectangle 70 | //hub_circle(scene, x1, y1, y3 % 20, color); 71 | 72 | // render the RGB data to the active BCM buffers. 73 | scene->bcm_mapper(scene, NULL); 74 | 75 | // calcualte_fps will delay execution to achieve the desired frames per second 76 | calculate_fps(scene->fps, scene->show_fps); 77 | } 78 | } 79 | 80 | 81 | int main(int argc, char **argv) 82 | { 83 | printf("rpi-gpu-hub75 v0.2 example program %s pin out configuration\n", ADDRESS_TYPE); 84 | srand(time(NULL)); 85 | 86 | // parse command line options to define the scene 87 | // use -h for help, see this function in util.c for more information on command line parsing 88 | scene_info *scene = default_scene(argc, argv); 89 | 90 | // ensure that the scene is valid 91 | check_scene(scene); 92 | 93 | 94 | // create another thread to run the frame drawing function (GPU or CPU) 95 | pthread_t update_thread; 96 | // use the CPU renderer if no shader or video file was passed 97 | if (scene->shader_file == NULL) { 98 | pthread_create(&update_thread, NULL, render_cpu, scene); 99 | } 100 | // use the gpu shader or video renderer if we have one, else use the cpu renderer above 101 | else if (access(scene->shader_file, R_OK) == 0) { 102 | if (has_extension(scene->shader_file, "glsl")) { 103 | printf("render shader [%s]\n", scene->shader_file); 104 | scene->stride = 4; 105 | pthread_create(&update_thread, NULL, render_shader, scene); 106 | } else { 107 | printf("render video [%s]", scene->shader_file); 108 | pthread_create(&update_thread, NULL, render_video_fn, scene); 109 | } 110 | } else { 111 | die("unable to open file %s\n", scene->shader_file); 112 | } 113 | 114 | 115 | // this function will never return. make sure you have already forked your drawing thread 116 | // before calling this function 117 | render_forever(scene); 118 | } 119 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS_BASE := -O3 -g -pipe -fno-math-errno -ffast-math 2 | CFLAGS_CPU ?= $(shell sh detect_flags.sh) 3 | CFLAGS := $(CFLAGS_BASE) $(CFLAGS_CPU) 4 | 5 | # Compiler and flags 6 | CC = gcc 7 | #CFLAGS = -DNDEBUG=1 -std=gnu2x -fPIC -ffast-math -fopt-info-vec -funroll-loops -ftree-vectorize -mtune=native -O3 -Wall -Wpedantic -Wdouble-promotion -Iinclude 8 | CFLAGS = -DNDEBUG=1 -std=gnu2x -fPIC -funroll-loops -ftree-vectorize -Wall -Wpedantic -Iinclude 9 | LDFLAGS = -lpthread -lrt -lm -lc -lavformat -lavcodec -lswscale -lavutil 10 | CFLAGS += $(DEF) 11 | CFLAGS += $(CFLAGS_BASE) 12 | CFLAGS += `pkg-config --cflags libavcodec` 13 | 14 | # Directories 15 | PREFIX = /usr/local 16 | INCLUDEDIR = $(PREFIX)/include/rpihub75 17 | LIBDIR = $(PREFIX)/lib 18 | BUILDDIR = build 19 | 20 | # Source files 21 | SRC_COMMON = src/util.c src/pixels.c src/rpihub75.c 22 | SRC_GPU = src/gpu.c src/video.c 23 | 24 | # Library output names 25 | LIB_NO_GPU = librpihub75.so 26 | LIB_GPU = librpihub75_gpu.so 27 | 28 | # Object files 29 | # OBJ_COMMON = $(SRC_COMMON:%.c=$(BUILDDIR)/%.o) 30 | # OBJ_GPU = $(SRC_GPU:%.c=$(BUILDDIR)/%.o) 31 | OBJ_COMMON = $(patsubst src/%.c,$(BUILDDIR)/%.o,$(SRC_COMMON)) 32 | OBJ_GPU = $(patsubst src/%.c,$(BUILDDIR)/%.o,$(SRC_GPU)) 33 | 34 | # Check for OpenGL ES, GBM, and EGL libraries 35 | GLESV2_FOUND := $(shell pkg-config --exists glesv2 && echo yes || echo no) 36 | GBM_FOUND := $(shell pkg-config --exists gbm && echo yes || echo no) 37 | EGL_FOUND := $(shell pkg-config --exists egl && echo yes || echo no) 38 | AVCODEC_FOUND := $(shell pkg-config --exists libavcodec && echo yes || echo no) 39 | SWSCALE_FOUND := $(shell pkg-config --exists libswscale && echo yes || echo no) 40 | AVUTIL_FOUND := $(shell pkg-config --exists libavutil && echo yes || echo no) 41 | 42 | # Targets 43 | .PHONY: all clean install check-libs example 44 | 45 | # Default target to build both libraries 46 | all: check-libs $(LIB_NO_GPU) $(LIB_GPU) 47 | 48 | lib: $(LIB_NO_GPU) 49 | 50 | libgpu: $(LIB_GPU) 51 | 52 | # Create build directory if not exists 53 | $(BUILDDIR): 54 | mkdir -p $(BUILDDIR) 55 | 56 | # Check for required GPU libraries 57 | check-libs: 58 | ifeq ($(GLESV2_FOUND),no) 59 | $(error "GLESv2 library not found. Please install it. sudo apt-get install libgles2-mesa-dev") 60 | endif 61 | ifeq ($(GBM_FOUND),no) 62 | $(error "GBM library not found. Please install it. sudo apt-get install libgbm-dev") 63 | endif 64 | ifeq ($(EGL_FOUND),no) 65 | $(error "EGL library not found. Please install it. sudo apt-get install libegl1-mesa-dev") 66 | endif 67 | ifeq ($(AVCODEC_FOUND),no) 68 | $(error "AVCodec library not found. Please install it. sudo apt-get install libavcodec-dev") 69 | endif 70 | ifeq ($(SWSCALE_FOUND),no) 71 | $(error "SWscale library not found. Please install it. sudo apt-get install libswscale-dev") 72 | endif 73 | ifeq ($(AVUTIL_FOUND),no) 74 | $(error "SWscale library not found. Please install it. sudo apt-get install libavutil-dev") 75 | endif 76 | 77 | # No-GPU library (without gpu.c, no OpenGL) 78 | $(LIB_NO_GPU): $(OBJ_COMMON) | $(BUILDDIR) 79 | $(CC) $(CFLAGS) $(CFLAGS_CPU) -shared -o $@ $(OBJ_COMMON) $(LDFLAGS) 80 | 81 | # GPU-enabled library (with gpu.c, linked to OpenGL) 82 | $(LIB_GPU): $(OBJ_COMMON) $(OBJ_GPU) | $(BUILDDIR) 83 | $(CC) $(CFLAGS) $(CFLAGS_CPU) -shared -o $@ $(OBJ_COMMON) $(OBJ_GPU) $(LDFLAGS) `pkg-config --libs glesv2 gbm egl` 84 | 85 | # New example target to compile example.c 86 | example: example.c $(LIB_GPU) 87 | $(CC) example.c -Wall -O3 -lrpihub75_gpu -o example 88 | 89 | # New example target to compile scratch.c 90 | scratch: tests/scratch.c $(LIB_GPU) 91 | $(CC) tests/scratch.c -Wall -O3 -lrpihub75_gpu -o scratch 92 | 93 | 94 | # Install target 95 | install: all 96 | # Create directories 97 | mkdir -p $(INCLUDEDIR) 98 | mkdir -p $(LIBDIR) 99 | # Copy header files 100 | chmod +x *.so 101 | cp include/rpihub75.h $(INCLUDEDIR) 102 | cp include/util.h $(INCLUDEDIR) 103 | cp include/gpu.h $(INCLUDEDIR) 104 | cp include/pixels.h $(INCLUDEDIR) 105 | cp include/video.h $(INCLUDEDIR) 106 | # Copy libraries 107 | cp $(LIB_NO_GPU) $(LIB_GPU) $(LIBDIR) 108 | ldconfig 109 | 110 | # Clean target 111 | clean: 112 | rm -rf $(BUILDDIR) 113 | rm -f $(OBJ_COMMON) $(OBJ_GPU) $(LIB_NO_GPU) $(LIB_GPU) example 114 | 115 | 116 | 117 | # Object file compilation rules 118 | $(BUILDDIR)/%.o: src/%.c | $(BUILDDIR) 119 | $(CC) $(CFLAGS) $(CFLAGS_CPU) -c $< -o $@ 120 | 121 | # Dependencies (optional) 122 | $(BUILDDIR)/util.o: src/util.c include/util.h 123 | $(BUILDDIR)/pixels.o: src/pixels.c include/rpihub75.h include/pixels.h 124 | $(BUILDDIR)/video.o: src/video.c include/rpihub75.h 125 | $(BUILDDIR)/gpio.o: src/gpio.c include/rpihub75.h 126 | $(BUILDDIR)/gpu.o: src/gpu.c include/rpihub75.h include/stb_image.h 127 | -------------------------------------------------------------------------------- /shaders/fluff.glsl: -------------------------------------------------------------------------------- 1 | // Copyright Inigo Quilez, 2013 - https://iquilezles.org/ 2 | // I am the sole copyright owner of this Work. 3 | // You cannot host, display, distribute or share this Work neither 4 | // as it is or altered, here on Shadertoy or anywhere else, in any 5 | // form including physical and digital. You cannot use this Work in any 6 | // commercial or non-commercial product, website or project. You cannot 7 | // sell this Work and you cannot mint an NFTs of it or train a neural 8 | // network with it without permission. I share this Work for educational 9 | // purposes, and you can link to it, through an URL, proper attribution 10 | // and unmodified screenshot, as part of your educational material. If 11 | // these conditions are too restrictive please contact me and we'll 12 | // definitely work it out. 13 | 14 | // You can buy a metal print of this shader here: 15 | // https://www.redbubble.com/i/metal-print/Flames-by-InigoQuilez/39844894.0JXQP 16 | 17 | 18 | //#if HW_PERFORMANCE==0 19 | //#define HIGH_QUALITY 20 | //#else 21 | //#define HIGH_QUALITY 22 | //#endif 23 | #define HIGH_QUALITY 0 24 | 25 | 26 | float noise( in vec3 x ) 27 | { 28 | vec3 p = floor(x); 29 | vec3 f = fract(x); 30 | f = f*f*(3.0-2.0*f); 31 | 32 | #ifndef HIGH_QUALITY 33 | vec2 uv = (p.xy+vec2(37.0,17.0)*p.z) + f.xy; 34 | vec2 rg = textureLod( iChannel0, (uv+ 0.5)/256.0, 0.0 ).yx; 35 | return mix( rg.x, rg.y, f.z ); 36 | #else 37 | ivec3 q = ivec3(p); 38 | ivec2 uv = q.xy + ivec2(37,17)*q.z; 39 | vec2 rg = mix(mix(texelFetch(iChannel0,(uv )&255,0).yx, 40 | texelFetch(iChannel0,(uv+ivec2(1,0))&255,0).yx,f.x), 41 | mix(texelFetch(iChannel0,(uv+ivec2(0,1))&255,0).yx, 42 | texelFetch(iChannel0,(uv+ivec2(1,1))&255,0).yx,f.x),f.y); 43 | return mix( rg.x, rg.y, f.z ); 44 | #endif 45 | } 46 | 47 | vec4 map( in vec3 p ) 48 | { 49 | vec3 r = p; p.y += 0.6; 50 | // invert space 51 | p = -4.0*p/dot(p,p); 52 | // twist space 53 | float an = -1.0*sin(0.1*iTime + length(p.xz) + p.y); 54 | float co = cos(an); 55 | float si = sin(an); 56 | p.xz = mat2(co,-si,si,co)*p.xz; 57 | 58 | // distort 59 | p.xz += -1.0 + 2.0*noise( p*1.1 ); 60 | // pattern 61 | float f; 62 | vec3 q = p*0.85 - vec3(0.0,1.0,0.0)*iTime*0.12; 63 | f = 0.50000*noise( q ); q = q*2.02 - vec3(0.0,1.0,0.0)*iTime*0.12; 64 | f += 0.25000*noise( q ); q = q*2.03 - vec3(0.0,1.0,0.0)*iTime*0.12; 65 | f += 0.12500*noise( q ); q = q*2.01 - vec3(0.0,1.0,0.0)*iTime*0.12; 66 | f += 0.06250*noise( q ); q = q*2.02 - vec3(0.0,1.0,0.0)*iTime*0.12; 67 | f += 0.04000*noise( q ); q = q*2.00 - vec3(0.0,1.0,0.0)*iTime*0.12; 68 | float den = clamp( (-r.y-0.6 + 4.0*f)*1.2, 0.0, 1.0 ); 69 | vec3 col = 1.2*mix( vec3(1.0,0.8,0.6), 0.9*vec3(0.3,0.2,0.35), den ) ; 70 | col += 0.05*sin(0.05*q); 71 | col *= 1.0 - 0.8*smoothstep(0.6,1.0,sin(0.7*q.x)*sin(0.7*q.y)*sin(0.7*q.z))*vec3(0.6,1.0,0.8); 72 | col *= 1.0 + 1.0*smoothstep(0.5,1.0,1.0-length( (fract(q.xz*0.12)-0.5)/0.5 ))*vec3(1.0,0.9,0.8); 73 | col = mix( vec3(0.8,0.32,0.2), col, clamp( (r.y+0.1)/1.5, 0.0, 1.0 ) ); 74 | return vec4( col, den ); 75 | } 76 | 77 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) 78 | { 79 | // inputs 80 | vec2 q = fragCoord.xy / iResolution.xy; 81 | vec2 p = (-1.0 + 2.0*q) * vec2( iResolution.x/ iResolution.y, 1.0 ); 82 | vec2 mo = iMouse.xy / iResolution.xy; 83 | if( iMouse.w<=0.00001 ) mo=vec2(0.0); 84 | 85 | //-------------------------------------- 86 | // cameran 87 | //-------------------------------------- 88 | float an = -0.07*iTime + 3.0*mo.x; 89 | vec3 ro = 4.5*normalize(vec3(cos(an), 0.5, sin(an))); 90 | ro.y += 1.0; 91 | vec3 ta = vec3(0.0, 0.5, 0.0); 92 | float cr = -0.4*cos(0.02*iTime); 93 | 94 | // build rayn 95 | vec3 ww = normalize( ta - ro ); 96 | vec3 uu = normalize( cross( vec3(sin(cr),cos(cr),0.0), ww ) ); 97 | vec3 vv = normalize( cross(ww,uu) ); 98 | vec3 rd = normalize( p.x*uu + p.y*vv + 2.5*ww ); 99 | 100 | //-------------------------------------- 101 | // raymarch 102 | //-------------------------------------- 103 | vec4 sum = vec4( 0.0 ); 104 | vec3 bg = vec3(0.4,0.5,0.5)*1.3; 105 | // dithering 106 | float t = 0.05*fract( 10.5421*dot(vec2(0.0149451,0.038921),fragCoord)); 107 | 108 | for( int i=0; i<128; i++ ) 109 | { 110 | if( sum.a > 0.99 ) break; 111 | vec3 pos = ro + t*rd; 112 | vec4 col = map( pos ); 113 | col.a *= 0.5; 114 | col.rgb = mix( bg, col.rgb, exp(-0.002*t*t*t) ) * col.a; 115 | sum = sum + col*(1.0 - sum.a); 116 | t += 0.05; 117 | } 118 | 119 | vec3 col = clamp( mix( bg, sum.xyz/(0.001+sum.w), sum.w ), 0.0, 1.0 ); 120 | 121 | //-------------------------------------- 122 | // contrast + vignetting 123 | //-------------------------------------- 124 | col = col*col*(3.0-2.0*col)*1.4 - 0.4; 125 | col *= 0.25 + 0.75*pow( 16.0*q.x*q.y*(1.0-q.x)*(1.0-q.y), 0.1 ); 126 | fragColor = vec4( col, 1.0 ); 127 | } 128 | -------------------------------------------------------------------------------- /include/util.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "rpihub75.h" 5 | 6 | #ifndef _UTIL_H 7 | #define _UTIL_H 1 8 | 9 | 10 | /** 11 | * @brief used to set the pin mode of a GPIO pin using mmaped /dev/gpiomem0 12 | * 13 | */ 14 | typedef struct{ 15 | uint32_t status; 16 | uint32_t ctrl; 17 | }GPIOregs; 18 | #define GPIO ((GPIOregs*)GPIOBase) 19 | 20 | /** 21 | * @brief helper struct for accessing the RIO registers of a GPIO pin 22 | * 23 | */ 24 | typedef struct 25 | { 26 | volatile uint32_t Out; 27 | volatile uint32_t OE; 28 | volatile uint32_t In; 29 | volatile uint32_t InSync; 30 | } rioregs; 31 | 32 | 33 | /** 34 | * @brief printf() a message to stderr and exit with a non-zero status 35 | * 36 | * @param message 37 | * @param ... 38 | */ 39 | void die(const char *message, ...); 40 | 41 | /** 42 | * @brief display a message to stderr if CONSOLE_DEBUG is defined 43 | * 44 | * @param format 45 | * @param ... 46 | */ 47 | void debug(const char *format, ...); 48 | 49 | 50 | /** 51 | * @brief calculate a jitter mask for the OE pin that should randomly toggle the OE pin on/off acording to brightness 52 | * TODO: look for rows of > 3 bits that are all the same and spread these bits out. this will reduce flicker on the display 53 | * 54 | * @param jitter_size prime number > 1024 < 4096 55 | * @param brightness larger values produce brighter output, max 255 56 | * @return uint32_t* a pointer to the jitter mask. caller must release memory 57 | */ 58 | uint32_t *create_jitter_mask(const uint16_t jitter_size, const uint8_t brightness); 59 | 60 | /** 61 | * @brief write data to a file, exit on any failure 62 | * 63 | * @param filename filename to write to (wb) 64 | * @param data data to write 65 | * @param size number of bytes to write 66 | * @return int number of bytes written, -1 on error 67 | */ 68 | 69 | int file_put_contents(const char *filename, const void *data, const size_t size); 70 | 71 | /** 72 | * @brief read in a file, allocate memory and return the data. caller must free. 73 | * this function will set filesize, you do not need to pass in filesize. 74 | * exit on any failure 75 | * 76 | * @param filename - file to read 77 | * @param filesize - pointer to the size of the file. will be set after the call. ugly i know 78 | * @return char* - pointer to read data. NOTE: caller must free 79 | */ 80 | char *file_get_contents(const char *filename, long *filesize); 81 | 82 | /** 83 | * @brief print a 32 bit number in binary format to stdout 84 | * 85 | * @param fd 86 | * @param number 87 | */ 88 | void binary32(FILE *fd, const uint32_t number); 89 | 90 | /** 91 | * @brief print a 64 bit number in binary format to stdout 92 | * 93 | * @param fd 94 | * @param number 95 | */ 96 | void binary64(FILE *fd, const uint64_t number); 97 | 98 | /** 99 | * @brief read size random data from /dev/urandom into the buffer 100 | * 101 | * @param buffer 102 | * @param size 103 | * @return int - always 0 104 | */ 105 | int rnd(unsigned char *buffer, const size_t size); 106 | 107 | /** 108 | * @brief count number of times this function is called, 1 every second output 109 | * the number of times called and reset the counter. This function can not 110 | * be called from multiple locations. It is not thread safe. 111 | * 112 | * @param target_fps - target a sleep time to achieve this fps 113 | * @return long - returns sleep time in microseconds 114 | */ 115 | long calculate_fps(const uint16_t target_fps, const bool show_fps); 116 | 117 | /** 118 | * @brief map the gpio pins to memory 119 | * 120 | * @param offset 121 | * @return uint32_t* 122 | */ 123 | uint32_t* map_gpio(uint32_t offset, int version); 124 | 125 | /** 126 | * @brief remove whitespace from string 127 | * @param s 128 | * @return char* 129 | */ 130 | char *str_trim_spaces(char *s); 131 | 132 | int parse_float(const char *s, float *out); 133 | uint8_t math_norm_q8(float x); 134 | 135 | /** 136 | * @brief set the GPIO pins for hub75 operation. this is based on hzeller's active board pinouts 137 | * @see https://github.com/hzeller/rpi-rgb-led-matrix 138 | * 139 | * @param PERIBase 140 | */ 141 | void configure_gpio(uint32_t *PERIBase, int version); 142 | 143 | /** 144 | * @brief display command line scene configuration options and exit 145 | * 146 | * @param argc 147 | * @param argv 148 | */ 149 | void usage(int argc, char **argv); 150 | 151 | /** 152 | * @brief create a default scene setup using the #DEFINE values 153 | * parse command line options to override. This is a great way 154 | * to test your setup easily from command line 155 | * @see usage() for details 156 | * 157 | * @param argc 158 | * @param argv 159 | * @return scene_info* 160 | */ 161 | scene_info *default_scene(int argc, char **argv); 162 | 163 | /** 164 | * @brief draw various test patterns to the display 165 | * 166 | * @param arg 167 | * @return void* 168 | */ 169 | void *calibrate_panels(void *arg); 170 | 171 | /** 172 | * @brief function to crete a udp server and pull raw frame data. see the udp_packet struct 173 | * for info on the data format 174 | * 175 | * exits on any error 176 | * @param arg 177 | * @return void* 178 | */ 179 | void* receive_udp_data(void *arg); 180 | 181 | /** 182 | * @brief test if a file has a specific extension 183 | * 184 | * @param filename 185 | * @param extension 186 | * @return true|false 187 | */ 188 | bool has_extension(const char *filename, const char *extension); 189 | 190 | #endif 191 | -------------------------------------------------------------------------------- /src/video.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "rpihub75.h" 11 | #include "video.h" 12 | #include "pixels.h" 13 | #include "util.h" 14 | 15 | /** 16 | * @brief pass this function to your pthread_create() call to render a video file 17 | * will render the video file pointed to by scene->shader_file until 18 | * scene->do_render is false; 19 | * 20 | * @param arg 21 | * @return void* 22 | */ 23 | 24 | void* render_video_fn(void *arg) { 25 | scene_info *scene = (scene_info*)arg; 26 | while (scene->do_render) { 27 | if (!hub_render_video(scene, scene->shader_file)) { 28 | break; 29 | } 30 | } 31 | 32 | return NULL; 33 | } 34 | 35 | #define FAIL(MSG) do { fprintf(stderr, "%s\n", MSG); ok = false; goto cleanup; } while (0) 36 | 37 | 38 | 39 | bool hub_render_video(scene_info *scene, const char *filename) { 40 | AVFormatContext *format_ctx = NULL; 41 | AVCodecContext *codec_ctx = NULL; 42 | const AVCodec *codec = NULL; 43 | AVFrame *frame = NULL, *frame_rgb = NULL; 44 | AVPacket *packet = NULL; 45 | struct SwsContext *sws_ctx = NULL; 46 | uint8_t *rgb_tight = NULL; 47 | bool ok = true; 48 | 49 | int video_stream_index = -1; 50 | scene->stride = 3; 51 | 52 | if (avformat_open_input(&format_ctx, filename, NULL, NULL) != 0) { FAIL("Could not open video file"); } 53 | if (avformat_find_stream_info(format_ctx, NULL) < 0) { FAIL("Could not find stream information"); } 54 | 55 | // best stream selection 56 | codec = NULL; 57 | video_stream_index = av_find_best_stream(format_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &codec, 0); 58 | if (video_stream_index < 0 || !codec) { FAIL("No video stream found"); } 59 | 60 | // codec ctx 61 | codec_ctx = avcodec_alloc_context3(codec); 62 | if (!codec_ctx) { FAIL("Failed to allocate codec context"); } 63 | if (avcodec_parameters_to_context(codec_ctx, format_ctx->streams[video_stream_index]->codecpar) < 0) { 64 | FAIL("avcodec_parameters_to_context failed"); 65 | } 66 | codec_ctx->thread_type = FF_THREAD_FRAME; 67 | codec_ctx->thread_count = 2; 68 | if (avcodec_open2(codec_ctx, codec, NULL) < 0) { FAIL("Could not open codec"); } 69 | 70 | // frames and packet 71 | frame = av_frame_alloc(); 72 | frame_rgb = av_frame_alloc(); 73 | packet = av_packet_alloc(); 74 | if (!frame || !frame_rgb || !packet) { FAIL("Could not allocate frame/packet"); } 75 | 76 | // tightly packed RGB24 dest 77 | int tight_row_bytes = scene->width * 3; 78 | rgb_tight = av_malloc((size_t)scene->height * tight_row_bytes); 79 | if (!rgb_tight) { FAIL("rgb_tight alloc failed"); } 80 | frame_rgb->data[0] = rgb_tight; 81 | frame_rgb->linesize[0] = tight_row_bytes; 82 | 83 | // scaler 84 | int sws_flags = SWS_POINT; // or SWS_FAST_BILINEAR 85 | sws_ctx = sws_getContext(codec_ctx->width, codec_ctx->height, codec_ctx->pix_fmt, 86 | scene->width, scene->height, AV_PIX_FMT_RGB24, 87 | sws_flags, NULL, NULL, NULL); 88 | if (!sws_ctx) { FAIL("sws_getContext failed"); } 89 | 90 | // proper colorspace setup (no bogus casts) 91 | const int *src_mat = sws_getCoefficients(SWS_CS_ITU601); 92 | const int *dst_mat = sws_getCoefficients(SWS_CS_DEFAULT); 93 | // srcRange=0, dstRange=0 (limited), brightness=0, contrast=1.0, saturation=1.0 94 | if (sws_setColorspaceDetails(sws_ctx, src_mat, 0, dst_mat, 0, 0, 1<<16, 1<<16) < 0) { 95 | // not fatal, continue 96 | } 97 | 98 | while (av_read_frame(format_ctx, packet) >= 0) { // NOTE: packet (not &packet) 99 | if (!scene->do_render) break; 100 | 101 | if (packet->stream_index == video_stream_index) { 102 | int response = avcodec_send_packet(codec_ctx, packet); // NOTE: packet (not &packet) 103 | if (response < 0) { FAIL("Error sending packet for decoding"); } 104 | 105 | while (response >= 0) { 106 | response = avcodec_receive_frame(codec_ctx, frame); 107 | if (response == AVERROR(EAGAIN) || response == AVERROR_EOF) break; 108 | if (response < 0) { FAIL("Error during decoding"); } 109 | 110 | sws_scale(sws_ctx, 111 | (const uint8_t * const*)frame->data, frame->linesize, 112 | 0, codec_ctx->height, 113 | frame_rgb->data, frame_rgb->linesize); 114 | 115 | map_byte_image_to_bcm(scene, frame_rgb->data[0]); 116 | 117 | // optional: show fps 118 | AVRational fr = format_ctx->streams[video_stream_index]->avg_frame_rate; 119 | float fps = (float)av_q2d(fr); 120 | calculate_fps(fps > 1e-3f ? fps : 30.0f, scene->show_fps); 121 | } 122 | } 123 | av_packet_unref(packet); // NOTE: packet (not &packet) 124 | } 125 | 126 | cleanup: 127 | if (packet) av_packet_free(&packet); // expects &packet 128 | if (sws_ctx) sws_freeContext(sws_ctx); 129 | if (rgb_tight) av_free(rgb_tight); 130 | if (frame_rgb) av_frame_free(&frame_rgb); 131 | if (frame) av_frame_free(&frame); 132 | if (codec_ctx) avcodec_free_context(&codec_ctx); 133 | if (format_ctx) avformat_close_input(&format_ctx); 134 | return ok; 135 | } 136 | -------------------------------------------------------------------------------- /shaders/tree.glsl: -------------------------------------------------------------------------------- 1 | // https://www.shadertoy.com/view/llXfRr 2 | #define MAXDIST 50. 3 | 4 | struct Ray { 5 | vec3 ro; 6 | vec3 rd; 7 | }; 8 | 9 | // from netgrind 10 | vec3 hue(vec3 color, float shift) { 11 | 12 | const vec3 kRGBToYPrime = vec3 (0.299, 0.587, 0.114); 13 | const vec3 kRGBToI = vec3 (0.596, -0.275, -0.321); 14 | const vec3 kRGBToQ = vec3 (0.212, -0.523, 0.311); 15 | 16 | const vec3 kYIQToR = vec3 (1.0, 0.956, 0.621); 17 | const vec3 kYIQToG = vec3 (1.0, -0.272, -0.647); 18 | const vec3 kYIQToB = vec3 (1.0, -1.107, 1.704); 19 | 20 | // Convert to YIQ 21 | float YPrime = dot (color, kRGBToYPrime); 22 | float I = dot (color, kRGBToI); 23 | float Q = dot (color, kRGBToQ); 24 | 25 | // Calculate the hue and chroma 26 | float hue = atan (Q, I); 27 | float chroma = sqrt (I * I + Q * Q); 28 | 29 | // Make the user's adjustments 30 | hue += shift; 31 | 32 | // Convert back to YIQ 33 | Q = chroma * sin (hue); 34 | I = chroma * cos (hue); 35 | 36 | // Convert back to RGB 37 | vec3 yIQ = vec3 (YPrime, I, Q); 38 | color.r = dot (yIQ, kYIQToR); 39 | color.g = dot (yIQ, kYIQToG); 40 | color.b = dot (yIQ, kYIQToB); 41 | 42 | return color; 43 | } 44 | 45 | // ------ 46 | 47 | // by iq 48 | 49 | float opU( float d1, float d2 ) 50 | { 51 | return min(d1,d2); 52 | } 53 | 54 | float smin( float a, float b, float k ){ 55 | float h = clamp( 0.5+0.5*(b-a)/k, 0.0, 1.0 ); 56 | return mix( b, a, h ) - k*h*(1.0-h); 57 | } 58 | 59 | float length6( vec3 p ) 60 | { 61 | p = p*p*p; p = p*p; 62 | return pow( p.x + p.y + p.z, 1.0/6.0 ); 63 | } 64 | 65 | // ------ 66 | 67 | // from hg_sdf 68 | 69 | float fPlane(vec3 p, vec3 n, float distanceFromOrigin) { 70 | return dot(p, n) + distanceFromOrigin; 71 | } 72 | 73 | void pR(inout vec2 p, float a) { 74 | p = cos(a)*p + sin(a)*vec2(p.y, -p.x); 75 | } 76 | 77 | // ------- 78 | 79 | 80 | float fractal(vec3 p) 81 | { 82 | const int iterations = 20; 83 | 84 | float d = iTime*5. - p.z; 85 | p=p.yxz; 86 | pR(p.yz, 1.570795); 87 | p.x += 6.5; 88 | 89 | p.yz = mod(abs(p.yz)-.0, 20.) - 10.; 90 | float scale = 1.25; 91 | 92 | p.xy /= (1.+d*d*0.0005); 93 | 94 | float l = 0.; 95 | 96 | for (int i=0; i .01) break; 126 | p += ray.rd*.015; 127 | vec3 col = c; 128 | col.rgb *= smoothstep(.0,0.15,-r.x); 129 | sum += abs(col)*.5; 130 | } 131 | return sum; 132 | } 133 | 134 | vec2 march(Ray ray) 135 | { 136 | const int steps = 50; 137 | const float prec = 0.001; 138 | vec2 res = vec2(0.); 139 | 140 | for (int i = 0; i < steps; i++) 141 | { 142 | vec2 s = map(ray.ro + ray.rd * res.x); 143 | 144 | if (res.x > MAXDIST || s.x < prec) 145 | { 146 | break; 147 | } 148 | 149 | res.x += s.x; 150 | res.y = s.y; 151 | 152 | } 153 | 154 | return res; 155 | } 156 | 157 | vec3 calcNormal(vec3 pos) 158 | { 159 | const vec3 eps = vec3(0.005, 0.0, 0.0); 160 | 161 | return normalize( 162 | vec3(map(pos + eps).x - map(pos - eps).x, 163 | map(pos + eps.yxz).x - map(pos - eps.yxz).x, 164 | map(pos + eps.yzx).x - map(pos - eps.yzx).x ) 165 | ); 166 | } 167 | 168 | vec4 render(Ray ray) 169 | { 170 | vec3 col = vec3(0.); 171 | vec2 res = march(ray); 172 | 173 | if (res.x > MAXDIST) 174 | { 175 | return vec4(col, 50.); 176 | } 177 | 178 | vec3 pos = ray.ro+res.x*ray.rd; 179 | ray.ro = pos; 180 | col = vmarch(ray, res.x); 181 | 182 | col = mix(col, vec3(0.), clamp(res.x/50., 0., 1.)); 183 | return vec4(col, res.x); 184 | } 185 | 186 | mat3 camera(in vec3 ro, in vec3 rd, float rot) 187 | { 188 | vec3 forward = normalize(rd - ro); 189 | vec3 worldUp = vec3(sin(rot), cos(rot), 0.0); 190 | vec3 x = normalize(cross(forward, worldUp)); 191 | vec3 y = normalize(cross(x, forward)); 192 | return mat3(x, y, forward); 193 | } 194 | 195 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) 196 | { 197 | vec2 uv = fragCoord.xy / iResolution.xy; 198 | uv = uv * 2.0 - 1.0; 199 | uv.x *= iResolution.x / iResolution.y; 200 | uv.y -= uv.x*uv.x*0.15; 201 | vec3 camPos = vec3(3., -1.5, iTime*5.); 202 | vec3 camDir = camPos+vec3(-1.25,0.1, 1.); 203 | mat3 cam = camera(camPos, camDir, 0.); 204 | vec3 rayDir = cam * normalize( vec3(uv, .8)); 205 | 206 | Ray ray; 207 | ray.ro = camPos; 208 | ray.rd = rayDir; 209 | 210 | vec4 col = render(ray); 211 | 212 | fragColor = vec4(1.-col.xyz,clamp(1.-col.w/MAXDIST, 0., 1.)); 213 | } 214 | -------------------------------------------------------------------------------- /shaders/clouds2.glsl: -------------------------------------------------------------------------------- 1 | 2 | // Protean clouds by nimitz (twitter: @stormoid) 3 | // https://www.shadertoy.com/view/3l23Rh 4 | // License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License 5 | // Contact the author for other licensing options 6 | 7 | /* 8 | Technical details: 9 | 10 | The main volume noise is generated from a deformed periodic grid, which can produce 11 | a large range of noise-like patterns at very cheap evalutation cost. Allowing for multiple 12 | fetches of volume gradient computation for improved lighting. 13 | 14 | To further accelerate marching, since the volume is smooth, more than half the the density 15 | information isn't used to rendering or shading but only as an underlying volume distance to 16 | determine dynamic step size, by carefully selecting an equation (polynomial for speed) to 17 | step as a function of overall density (not necessarily rendered) the visual results can be 18 | the same as a naive implementation with ~40% increase in rendering performance. 19 | 20 | Since the dynamic marching step size is even less uniform due to steps not being rendered at all 21 | the fog is evaluated as the difference of the fog integral at each rendered step. 22 | 23 | */ 24 | 25 | precision mediump float; 26 | 27 | mat2 rot(in float a){float c = cos(a), s = sin(a);return mat2(c,s,-s,c);} 28 | const mat3 m3 = mat3(0.33338, 0.56034, -0.71817, -0.87887, 0.32651, -0.15323, 0.15162, 0.69596, 0.61339)*1.93; 29 | float mag2(vec2 p){return dot(p,p);} 30 | float linstep(in float mn, in float mx, in float x){ return clamp((x - mn)/(mx - mn), 0., 1.); } 31 | float prm1 = 0.; 32 | vec2 bsMo = vec2(0); 33 | 34 | vec2 disp(float t){ return vec2(sin(t*0.22)*1., cos(t*0.175)*1.)*2.; } 35 | 36 | vec2 map(vec3 p) 37 | { 38 | vec3 p2 = p; 39 | p2.xy -= disp(p.z).xy; 40 | p.xy *= rot(sin(p.z+iTime)*(0.1 + prm1*0.05) + iTime*0.09); 41 | float cl = mag2(p2.xy); 42 | float d = 0.; 43 | p *= .61; 44 | float z = 1.; 45 | float trk = 1.; 46 | float dspAmp = 0.1 + prm1*0.2; 47 | for(int i = 0; i < 3; i++) 48 | { 49 | p += sin(p.zxy*0.75*trk + iTime*trk*.8)*dspAmp; 50 | d -= abs(dot(cos(p), sin(p.yzx))*z); 51 | z *= 0.57; 52 | trk *= 1.4; 53 | p = p*m3; 54 | } 55 | d = abs(d + prm1*3.)+ prm1*.3 - 2.5 + bsMo.y; 56 | return vec2(d + cl*.2 + 0.25, cl); 57 | } 58 | 59 | vec4 render( in vec3 ro, in vec3 rd, float time ) 60 | { 61 | vec4 rez = vec4(0); 62 | const float ldst = 8.; 63 | vec3 lpos = vec3(disp(time + ldst)*0.5, time + ldst); 64 | float t = 1.5; 65 | float fogT = 0.; 66 | for(int i=0; i<72; i++) 67 | { 68 | if(rez.a > 0.99)break; 69 | 70 | vec3 pos = ro + t*rd; 71 | vec2 mpv = map(pos); 72 | float den = clamp(mpv.x-0.3,0.,1.)*1.12; 73 | float dn = clamp((mpv.x + 2.),0.,3.); 74 | 75 | vec4 col = vec4(0); 76 | if (mpv.x > 0.6) 77 | { 78 | 79 | col = vec4(sin(vec3(5.,0.4,0.2) + mpv.y*0.1 +sin(pos.z*0.4)*0.5 + 1.8)*0.5 + 0.5,0.08); 80 | col *= den*den*den; 81 | col.rgb *= linstep(4.,-2.5, mpv.x)*2.3; 82 | float dif = clamp((den - map(pos+.8).x)/9., 0.001, 1. ); 83 | dif += clamp((den - map(pos+.35).x)/2.5, 0.001, 1. ); 84 | col.xyz *= den*(vec3(0.005,.045,.075) + 1.5*vec3(0.033,0.07,0.03)*dif); 85 | } 86 | 87 | float fogC = exp(t*0.2 - 2.2); 88 | col.rgba += vec4(0.06,0.11,0.11, 0.1)*clamp(fogC-fogT, 0., 1.); 89 | fogT = fogC; 90 | rez = rez + col*(1. - rez.a); 91 | t += clamp(0.5 - dn*dn*.05, 0.09, 0.3); 92 | } 93 | return clamp(rez, 0.0, 1.0); 94 | } 95 | 96 | float getsat(vec3 c) 97 | { 98 | float mi = min(min(c.x, c.y), c.z); 99 | float ma = max(max(c.x, c.y), c.z); 100 | return (ma - mi)/(ma+ 1e-7); 101 | } 102 | 103 | //from my "Will it blend" shader (https://www.shadertoy.com/view/lsdGzN) 104 | vec3 iLerp(in vec3 a, in vec3 b, in float x) 105 | { 106 | vec3 ic = mix(a, b, x) + vec3(1e-6,0.,0.); 107 | float sd = abs(getsat(ic) - mix(getsat(a), getsat(b), x)); 108 | vec3 dir = normalize(vec3(2.*ic.x - ic.y - ic.z, 2.*ic.y - ic.x - ic.z, 2.*ic.z - ic.y - ic.x)); 109 | float lgt = dot(vec3(1.0), ic); 110 | float ff = dot(dir, normalize(ic)); 111 | ic += 1.5*dir*sd*ff*lgt; 112 | return clamp(ic,0.,1.); 113 | } 114 | 115 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) 116 | { 117 | vec2 q = fragCoord.xy/iResolution.xy; 118 | vec2 p = (gl_FragCoord.xy - 0.5*iResolution.xy)/iResolution.y; 119 | bsMo = (iMouse.xy - 0.5*iResolution.xy)/iResolution.y; 120 | 121 | float time = iTime*3.; 122 | vec3 ro = vec3(0,0,time); 123 | 124 | ro += vec3(sin(iTime)*0.5,sin(iTime*1.)*0.,0); 125 | 126 | float dspAmp = .85; 127 | ro.xy += disp(ro.z)*dspAmp; 128 | float tgtDst = 3.5; 129 | 130 | vec3 target = normalize(ro - vec3(disp(time + tgtDst)*dspAmp, time + tgtDst)); 131 | ro.x -= bsMo.x*2.; 132 | vec3 rightdir = normalize(cross(target, vec3(0,1,0))); 133 | vec3 updir = normalize(cross(rightdir, target)); 134 | rightdir = normalize(cross(updir, target)); 135 | vec3 rd=normalize((p.x*rightdir + p.y*updir)*1. - target); 136 | rd.xy *= rot(-disp(time + 3.5).x*0.2 + bsMo.x); 137 | prm1 = smoothstep(-0.4, 0.4,sin(iTime*0.3)); 138 | vec4 scn = render(ro, rd, time); 139 | 140 | vec3 col = scn.rgb; 141 | col = iLerp(col.bgr, col.rgb, clamp(1.-prm1,0.05,1.)); 142 | 143 | col = pow(col, vec3(.55,0.65,0.6))*vec3(1.,.97,.9); 144 | 145 | col *= pow( 16.0*q.x*q.y*(1.0-q.x)*(1.0-q.y), 0.12)*0.7+0.3; //Vign 146 | 147 | fragColor = vec4( col, 1.0 ); 148 | } 149 | -------------------------------------------------------------------------------- /shaders/soap_bubbles.glsl: -------------------------------------------------------------------------------- 1 | // https://www.shadertoy.com/view/llsSDf 2 | 3 | vec2 uv; 4 | 5 | vec2 hash2a(vec2 x,float anim) 6 | { 7 | float r = 523.0*sin(dot(x, vec2(53.3158, 43.6143))); 8 | float xa1=fract(anim); 9 | float xb1=anim-xa1; 10 | anim+=0.5; 11 | float xa2=fract(anim); 12 | float xb2=anim-xa2; 13 | 14 | vec2 z1=vec2(fract(15.32354 * (r+xb1)), fract(17.25865 * (r+xb1))); 15 | r=r+1.0; 16 | vec2 z2=vec2(fract(15.32354 * (r+xb1)), fract(17.25865 * (r+xb1))); 17 | r=r+1.0; 18 | vec2 z3=vec2(fract(15.32354 * (r+xb2)), fract(17.25865 * (r+xb2))); 19 | r=r+1.0; 20 | vec2 z4=vec2(fract(15.32354 * (r+xb2)), fract(17.25865 * (r+xb2))); 21 | return (mix(z1,z2,xa1)+mix(z3,z4,xa2))*0.5; 22 | } 23 | 24 | float hashNull(vec2 x) 25 | { 26 | float r = fract(523.0*sin(dot(x, vec2(53.3158, 43.6143)))); 27 | return r; 28 | } 29 | 30 | vec4 NC0=vec4(0.0,157.0,113.0,270.0); 31 | vec4 NC1=vec4(1.0,158.0,114.0,271.0); 32 | 33 | vec4 hash4( vec4 n ) { return fract(sin(n)*753.5453123); } 34 | vec2 hash2( vec2 n ) { return fract(sin(n)*753.5453123); } 35 | float noise2( vec2 x ) 36 | { 37 | vec2 p = floor(x); 38 | vec2 f = fract(x); 39 | f = f*f*(3.0-2.0*f); 40 | 41 | float n = p.x + p.y*157.0; 42 | vec2 s1=mix(hash2(vec2(n)+NC0.xy),hash2(vec2(n)+NC1.xy),vec2(f.x)); 43 | return mix(s1.x,s1.y,f.y); 44 | } 45 | 46 | float noise3( vec3 x ) 47 | { 48 | vec3 p = floor(x); 49 | vec3 f = fract(x); 50 | f = f*f*(3.0-2.0*f); 51 | 52 | float n = p.x + dot(p.yz,vec2(157.0,113.0)); 53 | vec4 s1=mix(hash4(vec4(n)+NC0),hash4(vec4(n)+NC1),vec4(f.x)); 54 | return mix(mix(s1.x,s1.y,f.y),mix(s1.z,s1.w,f.y),f.z); 55 | } 56 | 57 | vec4 booble(vec2 te,vec2 pos,float numCells) 58 | { 59 | float d=dot(te, te); 60 | //if (d>=0.06) return vec4(0.0); 61 | 62 | vec2 te1=te+(pos-vec2(0.5,0.5))*0.4/numCells; 63 | vec2 te2=-te1; 64 | float zb1=max(pow(noise2(te2*1000.11*d),10.0),0.01); 65 | float zb2=noise2(te1*1000.11*d); 66 | float zb3=noise2(te1*200.11*d); 67 | float zb4=noise2(te1*200.11*d+vec2(20.0)); 68 | 69 | vec4 colorb=vec4(1.0); 70 | colorb.xyz=colorb.xyz*(0.7+noise2(te1*1000.11*d)*0.3); 71 | 72 | zb2=max(pow(zb2,20.1),0.01); 73 | colorb.xyz=colorb.xyz*(zb2*1.9); 74 | 75 | vec4 color=vec4(noise2(te2*10.8),noise2(te2*9.5+vec2(15.0,15.0)),noise2(te2*11.2+vec2(12.0,12.0)),1.0); 76 | color=mix(color,vec4(1.0),noise2(te2*20.5+vec2(200.0,200.0))); 77 | color.xyz=color.xyz*(0.7+noise2(te2*1000.11*d)*0.3); 78 | color.xyz=color.xyz*(0.2+zb1*1.9); 79 | 80 | float r1=max(min((0.033-min(0.04,d))*100.0/sqrt(numCells),1.0),-1.6); 81 | float d2=(0.06-min(0.06,d))*10.0; 82 | d=(0.04-min(0.04,d))*10.0; 83 | color.xyz=color.xyz+colorb.xyz*d*1.5; 84 | 85 | float f1=min(d*10.0,0.5-d)*2.2; 86 | f1=pow(f1,4.0); 87 | float f2=min(min(d*4.1,0.9-d)*2.0*r1,1.0); 88 | 89 | float f3=min(d2*2.0,0.7-d2)*2.2; 90 | f3=pow(f3,4.0); 91 | 92 | return vec4(color*max(min(f1+f2,1.0),-0.5)+vec4(zb3)*f3-vec4(zb4)*(f2*0.5+f1)*0.5); 93 | } 94 | 95 | // base from https://www.shadertoy.com/view/4djGRh 96 | vec4 Cells(vec2 p,vec2 move, in float numCells,in float count,float blur) 97 | { 98 | vec2 inp=p+move; 99 | inp *= numCells; 100 | float d = 1.0; 101 | vec2 te; 102 | vec2 pos; 103 | for (int xo = -1; xo <= 1; xo++) 104 | { 105 | for (int yo = -1; yo <= 1; yo++) 106 | { 107 | vec2 tp = floor(inp) + vec2(xo, yo); 108 | vec2 rr=mod(tp, numCells); 109 | tp=tp + (hash2a(rr,iTime*0.1)+hash2a(rr,iTime*0.1+0.25))*0.5; 110 | vec2 l = inp - tp; 111 | float dr=dot(l, l); 112 | if (hashNull(rr)>count) 113 | if (d>dr) { 114 | d = dr; 115 | pos=tp; 116 | } 117 | } 118 | } 119 | if (d>=0.06) return vec4(0.0); 120 | te=inp-pos; 121 | 122 | //te=te+(te*noise3(vec3(te*5.9,iTime*40.0))*0.02); 123 | //te=te+(te*(noise3(vec3(te*3.9+p,iTime*0.2))+noise3(vec3(te*3.9+p,iTime*0.2+0.25))+noise3(vec3(te*3.9+p,iTime*0.2+0.5))+noise3(vec3(te*3.9+p,iTime*0.2+0.75)))*0.05); 124 | 125 | if (d<0.04) uv=uv+te*(d)*2.0; 126 | if (blur>0.0001) { 127 | vec4 c=vec4(0.0); 128 | for (float x=-1.0;x<1.0;x+=0.5) { 129 | for (float y=-1.0;y<1.0;y+=0.5) { 130 | c+=booble(te+vec2(x,y)*blur,p,numCells); 131 | } 132 | } 133 | return c*0.05; 134 | } 135 | 136 | return booble(te,p,numCells); 137 | } 138 | 139 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) 140 | { 141 | uv = (fragCoord.xy) / iResolution.y*0.5; 142 | 143 | vec2 l1=vec2(iTime*0.02,iTime*0.02); 144 | vec2 l2=vec2(-iTime*0.01,iTime*0.007); 145 | vec2 l3=vec2(0.0,iTime*0.01); 146 | 147 | //vec4 e=vec4(noise2(uv*2.0),noise2(uv*2.0+vec2(200.0)),noise2(uv*2.0+vec2(50.0)),0.0); 148 | vec4 e=vec4(noise3(vec3(uv*2.0,iTime*0.1)),noise3(vec3(uv*2.0+vec2(200.0),iTime*0.1)),noise3(vec3(uv*2.0+vec2(50.0),iTime*0.1)),0.0); 149 | 150 | vec4 cr1=Cells(uv,vec2(20.2449,93.78)+l1,2.0,0.5,0.005); 151 | vec4 cr2=Cells(uv,vec2(0.0,0.0),3.0,0.5,0.003); 152 | vec4 cr3=Cells(uv,vec2(230.79,193.2)+l2,4.0,0.5,0.0); 153 | vec4 cr4=Cells(uv,vec2(200.19,393.2)+l3,7.0,0.8,0.01); 154 | vec4 cr5=Cells(uv,vec2(10.3245,233.645)+l3,9.2,0.9,0.02); 155 | vec4 cr6=Cells(uv,vec2(10.3245,233.645)+l3,14.2,0.95,0.05); 156 | 157 | e=max(e-vec4(dot(cr6,cr6))*0.1,0.0)+cr6*1.6; 158 | e=max(e-vec4(dot(cr5,cr5))*0.1,0.0)+cr5*1.6; 159 | e=max(e-vec4(dot(cr4,cr4))*0.1,0.0)+cr4*1.3; 160 | e=max(e-vec4(dot(cr3,cr3))*0.1,0.0)+cr3*1.1; 161 | e=max(e-vec4(dot(cr2,cr2))*0.1,0.0)+cr2*1.4; 162 | 163 | e=max(e-vec4(dot(cr1,cr1))*0.1,0.0)+cr1*1.8; 164 | 165 | //e=e*(3.0+sin(iTime*10.0)*0.4+sin(iTime*5.0)*0.5+sin(iTime*100.0)*0.05 )*0.25; 166 | 167 | fragColor= e; 168 | } 169 | 170 | -------------------------------------------------------------------------------- /shaders/nebula_mesh.glsl: -------------------------------------------------------------------------------- 1 | // https://www.shadertoy.com/view/M3SfRG 2 | 3 | const float FLIGHT_SPEED = 6.0; 4 | 5 | const float FIELD_OF_VIEW = 1.05; 6 | 7 | 8 | vec3 getRayDirection(vec2 fragCoord, vec3 cameraDirection) { 9 | vec2 uv = fragCoord.xy / iResolution.xy; 10 | 11 | const float screenWidth = 1.0; 12 | float originToScreen = screenWidth / 2.0 / tan(FIELD_OF_VIEW / 2.0); 13 | 14 | vec3 screenCenter = originToScreen * cameraDirection; 15 | vec3 baseX = normalize(cross(screenCenter, vec3(0, -1.0, 0))); 16 | vec3 baseY = normalize(cross(screenCenter, baseX)); 17 | 18 | return normalize(screenCenter + (uv.x - 0.5) * baseX + (uv.y - 0.5) * iResolution.y / iResolution.x * baseY); 19 | } 20 | 21 | vec4 getNebulaColor(vec3 globalPosition, vec3 rayDirection) { 22 | vec3 color = vec3(0.0); 23 | float spaceLeft = 1.0; 24 | 25 | const float layerDistance = 10.0; 26 | float rayLayerStep = rayDirection.z / layerDistance; 27 | 28 | const int steps = 4; 29 | for (int i = 0; i <= steps; i++) { 30 | vec3 noiseeval = globalPosition + rayDirection * ((1.0 - fract(globalPosition.z / layerDistance) + float(i)) * layerDistance / rayDirection.z); 31 | noiseeval.xy += noiseeval.z; 32 | 33 | 34 | float value = 0.06 * texture(iChannel0, fract(noiseeval.xy / 60.0)).r; 35 | 36 | if (i == 0) { 37 | value *= 1.0 - fract(globalPosition.z / layerDistance); 38 | } else if (i == steps) { 39 | value *= fract(globalPosition.z / layerDistance); 40 | } 41 | 42 | color += spaceLeft * 2. * vec3(value, value, value) * vec3(.1, .5, 0.3); 43 | spaceLeft = max(0.0, spaceLeft - value * 2.0); 44 | } 45 | return vec4(color, 1.0); 46 | } 47 | 48 | #define S(a, b, t) smoothstep(a, b, t) 49 | 50 | float distLine(vec2 p, vec2 a, vec2 b){ 51 | vec2 pa = p - a; 52 | vec2 ba = b - a; 53 | float t = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0); 54 | return length(pa - ba*t); 55 | } 56 | 57 | float line(vec2 p, vec2 a, vec2 b){ 58 | float d = distLine(p, a, b); 59 | float m = S(0.03, 0.01, d); 60 | float d2 = length(a - b); 61 | m *= S(1.2, 0.8, d2) * 0.5 + S(0.05, 0.03, abs(d2 - 0.75)); 62 | return m; 63 | } 64 | 65 | float distTriangle(in vec2 p, in vec2 p0, in vec2 p1, in vec2 p2 ) 66 | { 67 | vec2 e0 = p1 - p0; 68 | vec2 e1 = p2 - p1; 69 | vec2 e2 = p0 - p2; 70 | 71 | vec2 v0 = p - p0; 72 | vec2 v1 = p - p1; 73 | vec2 v2 = p - p2; 74 | 75 | vec2 pq0 = v0 - e0*clamp( dot(v0,e0)/dot(e0,e0), 0.0, 1.0 ); 76 | vec2 pq1 = v1 - e1*clamp( dot(v1,e1)/dot(e1,e1), 0.0, 1.0 ); 77 | vec2 pq2 = v2 - e2*clamp( dot(v2,e2)/dot(e2,e2), 0.0, 1.0 ); 78 | 79 | float s = sign( e0.x*e2.y - e0.y*e2.x ); 80 | vec2 d = min( min( vec2( dot( pq0, pq0 ), s*(v0.x*e0.y-v0.y*e0.x) ), 81 | vec2( dot( pq1, pq1 ), s*(v1.x*e1.y-v1.y*e1.x) )), 82 | vec2( dot( pq2, pq2 ), s*(v2.x*e2.y-v2.y*e2.x) )); 83 | 84 | return -sqrt(d.x)*sign(d.y); 85 | } 86 | 87 | float triangle(vec2 p, vec2 a, vec2 b, vec2 c){ 88 | float d = distTriangle(p, a, b, c); 89 | float m = S(0.03, 0.01, d); 90 | float d2 = length(a - b); 91 | m *= S(1.2, 0.8, d2) * 0.5 + S(0.05, 0.03, abs(d2 - 0.75)); 92 | return m; 93 | } 94 | 95 | float N21(vec2 p){ 96 | p = fract(p * vec2(233.34, 851.73)); 97 | p += dot(p, p + 23.45); 98 | return fract(p.x * p.y); 99 | } 100 | 101 | vec2 N22(vec2 p){ 102 | float n = N21(p); 103 | return vec2(n, N21(p + n)); 104 | } 105 | 106 | vec2 getPos(vec2 id, vec2 offset){ 107 | vec2 n = N22(id + offset) * iTime; 108 | return offset + sin(n) * 0.4; 109 | } 110 | 111 | float layer(vec2 uv){ 112 | vec2 gv = fract(uv) - 0.5; 113 | vec2 id = floor(uv); 114 | vec2 p[9]; 115 | int i = 0; 116 | for(float y = -1.0; y <= 1.0; y++){ 117 | for(float x = -1.0; x <= 1.0; x++){ 118 | p[i++] = getPos(id, vec2(x, y)); 119 | } 120 | } 121 | 122 | 123 | float t = iTime * 10.0; 124 | float m = 0.0; 125 | for(int i = 0; i < 9; i++){ 126 | m += line(gv, p[4], p[i]); 127 | 128 | vec2 j = (p[i] - gv) * 20.0; 129 | float sparkle = 1.0 / dot(j, j); 130 | 131 | m += sparkle * (sin(t + fract(p[i].x) * 10.0) * 0.5 + 0.5); 132 | 133 | for(int yi= i + 1; yi < 9; yi++){ 134 | for(int zi= yi + 1; zi < 9; zi++){ 135 | 136 | float len1 = abs(length(p[i] - p[yi])); 137 | float len2 = abs(length(p[yi] - p[zi])); 138 | float len3 = abs(length(p[i] - p[zi])); 139 | 140 | if((len1 + len2 + len3) < 2.8){ 141 | m += triangle(gv, p[i], p[yi], p[zi]) * 0.8; 142 | } 143 | } 144 | } 145 | } 146 | m += line(gv, p[1], p[3]); 147 | m += line(gv, p[1], p[5]); 148 | m += line(gv, p[7], p[3]); 149 | m += line(gv, p[7], p[5]); 150 | 151 | return m; 152 | } 153 | 154 | 155 | void mainImage(out vec4 fragColor, in vec2 fragCoord) { 156 | //nebula 157 | vec3 movementDirection = normalize(vec3(0.01, 0.0, 1.0)); 158 | 159 | vec3 rayDirection = getRayDirection(fragCoord, movementDirection); 160 | 161 | vec3 globalPosition = vec3(3.14159, 3.14159, 0.0) + (iTime + 1000.0) * FLIGHT_SPEED * movementDirection; 162 | 163 | fragColor = getNebulaColor(globalPosition, rayDirection); 164 | 165 | // plexus 166 | vec2 uv = (fragCoord - 0.5 * iResolution.xy) / iResolution.y; 167 | 168 | float m = 0.0; 169 | float t = iTime * 0.1; 170 | 171 | for(float i = 0.0; i < 1.0; i += 1.0 / 4.0){ 172 | float z = fract(i + t); 173 | float size = mix(10.0, 0.5, z); 174 | float fade = S(0.0, 0.1, z) * S(1.0, 0.8, z); 175 | 176 | m += layer(uv * size + i * 20.0) * fade; 177 | } 178 | 179 | 180 | vec3 base = vec3(0.1, 0.5, 0.3); 181 | vec3 col = m * base * 0.1; 182 | 183 | col -= uv.y * 0.5 * base; 184 | 185 | fragColor += vec4(col,1.0); 186 | } 187 | -------------------------------------------------------------------------------- /shaders/lights.glsl: -------------------------------------------------------------------------------- 1 | 2 | // Auroras by nimitz 2017 (twitter: @stormoid) 3 | // License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License 4 | // Contact the author for other licensing options 5 | 6 | /* 7 | 8 | There are two main hurdles I encountered rendering this effect. 9 | First, the nature of the texture that needs to be generated to get a believable effect 10 | needs to be very specific, with large scale band-like structures, small scale non-smooth variations 11 | to create the trail-like effect, a method for animating said texture smoothly and finally doing all 12 | of this cheaply enough to be able to evaluate it several times per fragment/pixel. 13 | 14 | The second obstacle is the need to render a large volume while keeping the computational cost low. 15 | Since the effect requires the trails to extend way up in the atmosphere to look good, this means 16 | that the evaluated volume cannot be as constrained as with cloud effects. My solution was to make 17 | the sample stride increase polynomially, which works very well as long as the trails are lower opcaity than 18 | the rest of the effect. Which is always the case for auroras. 19 | 20 | After that, there were some issues with getting the correct emission curves and removing banding at lowered 21 | sample densities, this was fixed by a combination of sample number influenced dithering and slight sample blending. 22 | 23 | N.B. the base setup is from an old shader and ideally the effect would take an arbitrary ray origin and 24 | direction. But this was not required for this demo and would be trivial to fix. 25 | */ 26 | 27 | #define time iTime 28 | 29 | mat2 mm2(in float a){float c = cos(a), s = sin(a);return mat2(c,s,-s,c);} 30 | mat2 m2 = mat2(0.95534, 0.29552, -0.29552, 0.95534); 31 | float tri(in float x){return clamp(abs(fract(x)-.5),0.01,0.49);} 32 | vec2 tri2(in vec2 p){return vec2(tri(p.x)+tri(p.y),tri(p.y+tri(p.x)));} 33 | 34 | float triNoise2d(in vec2 p, float spd) 35 | { 36 | float z=1.8; 37 | float z2=2.5; 38 | float rz = 0.; 39 | p *= mm2(p.x*0.06); 40 | vec2 bp = p; 41 | for (float i=0.; i<5.; i++ ) 42 | { 43 | vec2 dg = tri2(bp*1.85)*.75; 44 | dg *= mm2(time*spd); 45 | p -= dg/z2; 46 | 47 | bp *= 1.3; 48 | z2 *= .45; 49 | z *= .42; 50 | p *= 1.21 + (rz-1.0)*.02; 51 | 52 | rz += tri(p.x+tri(p.y))*z; 53 | p*= -m2; 54 | } 55 | return clamp(1./pow(rz*29., 1.3),0.,.55); 56 | } 57 | 58 | float hash21(in vec2 n){ return fract(sin(dot(n, vec2(12.9898, 4.1414))) * 43758.5453); } 59 | vec4 aurora(vec3 ro, vec3 rd) 60 | { 61 | vec4 col = vec4(0); 62 | vec4 avgCol = vec4(0); 63 | 64 | for(float i=0.;i<50.;i++) 65 | { 66 | float of = 0.006*hash21(gl_FragCoord.xy)*smoothstep(0.,15., i); 67 | float pt = ((.8+pow(i,1.4)*.002)-ro.y)/(rd.y*2.+0.4); 68 | pt -= of; 69 | vec3 bpos = ro + pt*rd; 70 | vec2 p = bpos.zx; 71 | float rzt = triNoise2d(p, 0.06); 72 | vec4 col2 = vec4(0,0,0, rzt); 73 | col2.rgb = (sin(1.-vec3(2.15,-.5, 1.2)+i*0.043)*0.5+0.5)*rzt; 74 | avgCol = mix(avgCol, col2, .5); 75 | col += avgCol*exp2(-i*0.065 - 2.5)*smoothstep(0.,5., i); 76 | 77 | } 78 | 79 | col *= (clamp(rd.y*15.+.4,0.,1.)); 80 | 81 | 82 | //return clamp(pow(col,vec4(1.3))*1.5,0.,1.); 83 | //return clamp(pow(col,vec4(1.7))*2.,0.,1.); 84 | //return clamp(pow(col,vec4(1.5))*2.5,0.,1.); 85 | //return clamp(pow(col,vec4(1.8))*1.5,0.,1.); 86 | 87 | //return smoothstep(0.,1.1,pow(col,vec4(1.))*1.5); 88 | return col*1.8; 89 | //return pow(col,vec4(1.))*2. 90 | } 91 | 92 | 93 | //-------------------Background and Stars-------------------- 94 | 95 | vec3 nmzHash33(vec3 q) 96 | { 97 | uvec3 p = uvec3(ivec3(q)); 98 | p = p*uvec3(374761393U, 1103515245U, 668265263U) + p.zxy + p.yzx; 99 | p = p.yzx*(p.zxy^(p >> 3U)); 100 | return vec3(p^(p >> 16U))*(1.0/vec3(0xffffffffU)); 101 | } 102 | 103 | vec3 stars(in vec3 p) 104 | { 105 | vec3 c = vec3(0.); 106 | float res = iResolution.x*1.; 107 | 108 | for (float i=0.;i<4.;i++) 109 | { 110 | vec3 q = fract(p*(.15*res))-0.5; 111 | vec3 id = floor(p*(.15*res)); 112 | vec2 rn = nmzHash33(id).xy; 113 | float c2 = 1.-smoothstep(0.,.6,length(q)); 114 | c2 *= step(rn.x,.0005+i*i*0.001); 115 | c += c2*(mix(vec3(1.0,0.49,0.1),vec3(0.75,0.9,1.),rn.y)*0.1+0.9); 116 | p *= 1.3; 117 | } 118 | return c*c*.8; 119 | } 120 | 121 | vec3 bg(in vec3 rd) 122 | { 123 | float sd = dot(normalize(vec3(-0.5, -0.6, 0.9)), rd)*0.5+0.5; 124 | sd = pow(sd, 5.); 125 | vec3 col = mix(vec3(0.05,0.1,0.2), vec3(0.1,0.05,0.2), sd); 126 | return col*.63; 127 | } 128 | //----------------------------------------------------------- 129 | 130 | 131 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) 132 | { 133 | vec2 q = fragCoord.xy / iResolution.xy; 134 | vec2 p = q - 0.5; 135 | p.x*=iResolution.x/iResolution.y; 136 | 137 | vec3 ro = vec3(0,0,-6.7); 138 | vec3 rd = normalize(vec3(p,1.3)); 139 | vec2 mo = iMouse.xy / iResolution.xy-.5; 140 | mo = (mo==vec2(-.5))?mo=vec2(-0.1,0.1):mo; 141 | mo.x *= iResolution.x/iResolution.y; 142 | rd.yz *= mm2(mo.y); 143 | rd.xz *= mm2(mo.x + sin(time*0.05)*0.2); 144 | 145 | vec3 col = vec3(0.); 146 | vec3 brd = rd; 147 | float fade = smoothstep(0.,0.01,abs(brd.y))*0.1+0.9; 148 | 149 | col = bg(rd)*fade; 150 | 151 | if (rd.y > 0.){ 152 | vec4 aur = smoothstep(0.,1.5,aurora(ro,rd))*fade; 153 | col += stars(rd); 154 | col = col*(1.-aur.a) + aur.rgb; 155 | } 156 | else //Reflections 157 | { 158 | rd.y = abs(rd.y); 159 | col = bg(rd)*fade*0.6; 160 | vec4 aur = smoothstep(0.0,2.5,aurora(ro,rd)); 161 | col += stars(rd)*0.1; 162 | col = col*(1.-aur.a) + aur.rgb; 163 | vec3 pos = ro + ((0.5-ro.y)/rd.y)*rd; 164 | float nz2 = triNoise2d(pos.xz*vec2(.5,.7), 0.); 165 | col += mix(vec3(0.2,0.25,0.5)*0.08,vec3(0.3,0.3,0.5)*0.7, nz2*0.4); 166 | } 167 | 168 | fragColor = vec4(col, 1.); 169 | } 170 | 171 | -------------------------------------------------------------------------------- /shaders/raster.glsl: -------------------------------------------------------------------------------- 1 | #define LINEAR_ROTATION 2 | 3 | #define WEIGHT (3.0 / iResolution.x) 4 | const vec3 RED = vec3(1.0,0.0,0.0); 5 | const vec3 GREEN = vec3(0.0,1.0,0.0); 6 | const vec3 BLUE = vec3(0.0,0.8,1.0); 7 | const vec3 WHITE = vec3(1.0,1.0,0.97); 8 | const vec3 YELLOW = vec3(1.0,1.0,0.0); 9 | 10 | // rasterize functions 11 | float line(vec2 p, vec2 p0, vec2 p1, float w) { 12 | vec2 d = p1 - p0; 13 | float t = clamp(dot(d,p-p0) / dot(d,d), 0.0,1.0); 14 | vec2 proj = p0 + d * t; 15 | float dist = length(p - proj); 16 | dist = 1.0/dist*WEIGHT*w; 17 | return min(dist*dist,1.0); 18 | } 19 | float circle(vec2 p, vec2 c, float r, float w) { 20 | float dist = abs(length(p - c)) + r; 21 | dist = 1.0/dist*WEIGHT*w; 22 | return min(dist*dist,1.0); 23 | } 24 | 25 | // matrices 26 | mat4 getRotMatrix(vec3 a) { 27 | vec3 s = sin(a); 28 | vec3 c = cos(a); 29 | mat4 ret; 30 | ret[0] = vec4(c.y*c.z,c.y*s.z,-s.y,0.0); 31 | ret[1] = vec4(s.x*s.y*c.z-c.x*s.z,s.x*s.y*s.z+c.x*c.z,s.x*c.y,0.0); 32 | ret[2] = vec4(c.x*s.y*c.z+s.x*s.z, c.x*s.y*s.z-s.x*c.z, c.x*c.y,0.0); 33 | ret[3] = vec4(0.0,0.0,0.0,1.0); 34 | return ret; 35 | } 36 | mat4 getPosMatrix(vec3 p) { 37 | mat4 ret; 38 | ret[0] = vec4(1.0,0.0,0.0,p.x); 39 | ret[1] = vec4(0.0,1.0,0.0,p.y); 40 | ret[2] = vec4(0.0,0.0,1.0,p.z); 41 | ret[3] = vec4(0.0,0.0,0.0,1.0); 42 | return ret; 43 | } 44 | 45 | // utils 46 | vec3 mix3(vec3 a, vec3 b, vec3 c, float t) { 47 | if(t>0.5) return mix(b,c,t*2.0-1.0); 48 | else return mix(a,b,t*2.0); 49 | } 50 | vec3 fragment(vec3 p) { 51 | float t = sin(p.x*0.8+iTime*0.5)*0.5+0.5; 52 | float fog = min(pow(p.z,3.0)*400.0,1.0); 53 | return mix3(RED,GREEN,BLUE,t) * fog; 54 | } 55 | 56 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) { 57 | vec2 uv = fragCoord.xy / iResolution.xy; 58 | uv = uv * 2.0 - 1.0; 59 | uv.x *= iResolution.x / iResolution.y; 60 | //uv = uv * (1.0 + pow(length(uv)*0.4,0.5)) * 0.6; 61 | 62 | float line_width = 0.4; 63 | float time = iTime * 0.11415; 64 | vec3 c = vec3(mix(vec3(0.19,0.13,0.1),vec3(1.0), 0.5*pow(length(uv)*0.5,2.0))); 65 | mat4 cam = getPosMatrix(vec3(0.0,0.0,10.0)); 66 | 67 | #ifdef LINEAR_ROTATION 68 | mat4 rot = getRotMatrix(vec3(time,time*0.86,time*0.473)); 69 | #else 70 | float p = 0.02; 71 | mat4 rot = getRotMatrix(vec3(time +sin(time*30.0)*p, 72 | time*0.860 +sin(time*20.0)*p*1.24, 73 | time*0.473 +sin(time*10.0)*p)); 74 | #endif 75 | 76 | vec3 instances[18]; 77 | instances[0] = vec3( 0.0, 0.0,-1.0); 78 | instances[1] = vec3(-1.0, 0.0,-1.0); 79 | instances[2] = vec3( 1.0, 0.0,-1.0); 80 | instances[3] = vec3( 0.0, 1.0,-1.0); 81 | instances[4] = vec3( 0.0,-1.0,-1.0); 82 | instances[5] = vec3(-1.0, 0.0, 0.0); 83 | instances[6] = vec3( 1.0, 0.0, 0.0); 84 | instances[7] = vec3( 0.0, 1.0, 0.0); 85 | instances[8] = vec3( 0.0,-1.0, 0.0); 86 | instances[9] = vec3(-1.0,-1.0, 0.0); 87 | instances[10] = vec3( 1.0, 1.0, 0.0); 88 | instances[11] = vec3(-1.0, 1.0, 0.0); 89 | instances[12] = vec3( 1.0,-1.0, 0.0); 90 | instances[13] = vec3( 0.0, 0.0, 1.0); 91 | instances[14] = vec3(-1.0, 0.0, 1.0); 92 | instances[15] = vec3( 1.0, 0.0, 1.0); 93 | instances[16] = vec3( 0.0, 1.0, 1.0); 94 | instances[17] = vec3( 0.0,-1.0, 1.0); 95 | 96 | // box pipeline 97 | for(int dip = 0; dip < 18; dip++) { 98 | 99 | // input assembly 100 | vec3 vert[8]; 101 | vert[0] = vec3(-1.0,-1.0, 1.0); 102 | vert[1] = vec3(-1.0, 1.0, 1.0); 103 | vert[2] = vec3( 1.0, 1.0, 1.0); 104 | vert[3] = vec3( 1.0,-1.0, 1.0); 105 | vert[4] = vec3(-1.0,-1.0,-1.0); 106 | vert[5] = vec3(-1.0, 1.0,-1.0); 107 | vert[6] = vec3( 1.0, 1.0,-1.0); 108 | vert[7] = vec3( 1.0,-1.0,-1.0); 109 | 110 | // vertex processing 111 | mat4 pos = getPosMatrix(instances[dip] * 4.0); 112 | mat4 mat = pos * rot * cam; 113 | 114 | for(int i = 0; i < 8; i++) { 115 | 116 | // transform 117 | vert[i] = (vec4(vert[i],1.0) * mat).xyz; 118 | 119 | // perspective 120 | vert[i].z = 1.0 / vert[i].z; 121 | vert[i].xy *= vert[i].z; 122 | } 123 | 124 | // primitive assembly and rasterize 125 | float i; 126 | i = line(uv,vert[0].xy,vert[1].xy,line_width); 127 | i += line(uv,vert[1].xy,vert[2].xy,line_width); 128 | i += line(uv,vert[2].xy,vert[3].xy,line_width); 129 | i += line(uv,vert[3].xy,vert[0].xy,line_width); 130 | i += line(uv,vert[4].xy,vert[5].xy,line_width); 131 | i += line(uv,vert[5].xy,vert[6].xy,line_width); 132 | i += line(uv,vert[6].xy,vert[7].xy,line_width); 133 | i += line(uv,vert[7].xy,vert[4].xy,line_width); 134 | i += line(uv,vert[0].xy,vert[4].xy,line_width); 135 | i += line(uv,vert[1].xy,vert[5].xy,line_width); 136 | i += line(uv,vert[2].xy,vert[6].xy,line_width); 137 | i += line(uv,vert[3].xy,vert[7].xy,line_width); 138 | c += fragment(vert[0]) * min(i,1.0); 139 | } 140 | 141 | instances[0] = vec3(-1.0, 1.0,-1.0); 142 | instances[1] = vec3( 1.0, 1.0,-1.0); 143 | instances[2] = vec3(-1.0,-1.0,-1.0); 144 | instances[3] = vec3( 1.0,-1.0,-1.0); 145 | instances[4] = vec3(-1.0, 1.0, 1.0); 146 | instances[5] = vec3( 1.0, 1.0, 1.0); 147 | instances[6] = vec3(-1.0,-1.0, 1.0); 148 | instances[7] = vec3( 1.0,-1.0, 1.0); 149 | 150 | // cicle pipeline 151 | for(int dip = 0; dip < 8; dip++) { 152 | 153 | // input assembly 154 | vec3 vert = vec3(0.0); 155 | 156 | // vertex processing 157 | mat4 pos = getPosMatrix(instances[dip] * 4.0); 158 | mat4 mat = pos * rot * cam; 159 | 160 | // transform 161 | vert = (vec4(vert,1.0) * mat).xyz; 162 | 163 | // perspective 164 | vert.z = 1.0 / vert.z; 165 | vert.xy *= vert.z; 166 | 167 | // rasterize 168 | c += fragment(vert) * circle(uv,vert.xy,-vert.z,line_width); 169 | } 170 | 171 | // fragment 172 | fragColor = vec4(c,1.0); 173 | } 174 | -------------------------------------------------------------------------------- /shaders/nebula_orbs.glsl: -------------------------------------------------------------------------------- 1 | // https://www.shadertoy.com/view/4XjfRy 2 | 3 | #define iterations 13 4 | #define formuparam 0.53 5 | 6 | #define volsteps 20 7 | #define stepsize 0.1 8 | 9 | #define zoom 0.800 10 | #define tile 0.850 11 | #define speed 0.000 12 | 13 | #define brightness 0.0015 14 | #define darkmatter 0.300 15 | #define distfading 0.730 16 | #define saturation 0.850 17 | 18 | 19 | void mainVR( out vec4 fragColor, in vec2 fragCoord, in vec3 ro, in vec3 rd ) 20 | { 21 | //get coords and direction 22 | vec3 dir=rd; 23 | vec3 from=ro; 24 | 25 | //volumetric rendering 26 | float s=0.1,fade=1.; 27 | vec3 v=vec3(0.); 28 | for (int r=0; r6) fade*=1.2-dm; // dark matter, don't render near 41 | //v+=vec3(dm,dm*.5,0.); 42 | v+=fade; 43 | v+=vec3(s,s*s,s*s*s*s)*a*brightness*fade; // coloring based on distance 44 | fade*=distfading; // distance fading 45 | s+=stepsize; 46 | } 47 | v=mix(vec3(length(v)),v,saturation); //color adjust 48 | fragColor = vec4(v*.03,1.); 49 | } 50 | #define time iTime 51 | #define resolution iResolution.xy 52 | 53 | 54 | 55 | mat3 rotX(float a) { 56 | float c = cos(a); 57 | float s = sin(a); 58 | return mat3( 59 | 1, 0, 0, 60 | 0, c, -s, 61 | 0, s, c 62 | ); 63 | } 64 | 65 | mat3 rotY(float a) { 66 | float c = cos(a); 67 | float s = sin(a); 68 | return mat3( 69 | c, 0, -s, 70 | 0, 1, 0, 71 | s, 0, c 72 | ); 73 | } 74 | 75 | float random(vec2 pos) { 76 | return fract(sin(dot(pos.xy, vec2(13.9898, 78.233))) * 43758.5453123); 77 | } 78 | 79 | float noise(vec2 pos) { 80 | vec2 i = floor(pos); 81 | vec2 f = fract(pos); 82 | float a = random(i + vec2(0.0, 0.0)); 83 | float b = random(i + vec2(1.0, 0.0)); 84 | float c = random(i + vec2(0.0, 1.0)); 85 | float d = random(i + vec2(1.0, 1.0)); 86 | vec2 u = f * f * (3.0 - 2.0 * f); 87 | return mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y; 88 | } 89 | #define NUM_OCTAVES 6 90 | float fbm(vec2 pos) { 91 | float v = 0.0; 92 | float a = 0.5; 93 | vec2 shift = vec2(100.0); 94 | mat2 rot = mat2(cos(0.5), sin(0.5), -sin(0.5), cos(0.5)); 95 | for (int i = 0; i < NUM_OCTAVES; i++) { 96 | float dir = mod(float(i), 2.0) > 0.5 ? 1.0 : -1.0; 97 | v += a * noise(pos - 0.05 * dir * time); 98 | 99 | pos = rot * pos * 2.0 + shift; 100 | a *= 0.5; 101 | } 102 | return v; 103 | } 104 | 105 | const float PI = 3.1415; 106 | const float TWOPI = 2.0*PI; 107 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) 108 | { 109 | //get coords and direction 110 | vec2 uv=fragCoord.xy/iResolution.xy-.5; 111 | uv.y*=iResolution.y/iResolution.x; 112 | vec3 dir=vec3(uv*zoom,1.); 113 | ; 114 | vec2 uPos = ( gl_FragCoord.xy / resolution.y );//normalize wrt y axis 115 | uPos -= vec2((resolution.x/resolution.y)/2.0, 0.5);//shift origin to center 116 | 117 | float multiplier = 0.0005; // Grosseur 118 | const float step = 0.006; //segmentation 119 | const float loop = 80.0; //Longueur 120 | const float timeSCale = 0.5; // Vitesse 121 | 122 | vec3 blueGodColor = vec3(0.0); 123 | for(float i=1.0;i MAX_D) break; 155 | p += d*r; 156 | it = i; 157 | } 158 | rmRes res; 159 | res.pos = p; 160 | res.it = it; 161 | res.hit = hit; 162 | return res; 163 | } 164 | 165 | vec3 plane2sphere(in vec2 p) { 166 | float t = -4./(dot(p,p) + 4.); 167 | return vec3(-p*t, 1. + 2.*t); 168 | } 169 | 170 | void mainImage(out vec4 fragColor, in vec2 fragCoord) { 171 | int max_freq = 100; 172 | for(int i=1; i < max_freq; i++){ 173 | snd +=FFT(i)*float(i); 174 | } 175 | snd /=float(max_freq*20); 176 | snd*=1.6; 177 | 178 | vec2 st = (fragCoord.xy - iResolution.xy*.5)/iResolution.x; 179 | t = iTime < 0.01 ? 98. : iTime*5. ; 180 | 181 | c = vec3(0.,0.,t); 182 | vec3 r = -plane2sphere(st*5.); 183 | r.xz *= rot(cos(t*spiralspeed/3.)*.75); 184 | r.xy *= rot(-cos(t*spiralspeed)*1.75); 185 | 186 | rmRes res = rm(c,r); 187 | 188 | vec3 n = vec3(0.), b = vec3(.88); 189 | float whichroom = step(.5,fract(roomId/2.)); 190 | vec3 c1 = mix(n,b,whichroom), c2 = mix(b,n,whichroom); 191 | c2*=palette(pattern(st)); 192 | 193 | vec3 rd = normalize(vec3(st,-1.5)); 194 | vec3 bg = stars(rd)*(1.+30.*snd); 195 | //c2+=bg; 196 | 197 | if(whichroom>0.5){ 198 | c2+=bg; 199 | }else{ 200 | } 201 | 202 | vec3 color = c2; 203 | if(res.hit) 204 | if(matid == 1) color = doorpart == 1 ? c2/palette(pattern(st)) : c1; 205 | else if(matid == 2) color = c2; 206 | else { 207 | if(map.y < -1.45) { 208 | if(map.z > .1 || map.z < 0.) { 209 | map.xz *= rot(3.14*.25); 210 | map.xz *= 10.; 211 | color = mix(c1,c2/palette(pattern(st)),step(0.,cos(map.x)*cos(map.z)));//*palette(snd*2.); 212 | } else 213 | color = c2/palette(pattern(st));//*palette(snd*2.); 214 | } else color = c1;//*palette(snd*2.); 215 | } 216 | 217 | float l = length(st); 218 | fragColor = vec4(color - l*l*.5,1.0); 219 | } 220 | 221 | -------------------------------------------------------------------------------- /shaders/clouds4.glsl: -------------------------------------------------------------------------------- 1 | // Protean clouds by nimitz (twitter: @stormoid) 2 | // CC BY-NC-SA 3.0 3 | 4 | #define MARCH_STEPS 110 5 | #define NOISE_OCTAVES 5 6 | 7 | // New: toggle this optimization (2 = use previous-step density for lighting) 8 | #define OPT_LIGHT_FROM_PREV 1 9 | 10 | #define OPT_COARSE_PREPASS 1 // set to 0 to disable quickly 11 | 12 | #define PREPASS_STEPS 5 // small, cheap loop 13 | 14 | #define PREPASS_DT_MIN 0.25 // bigger steps than main march 15 | 16 | #define PREPASS_DT_MAX 0.45 17 | 18 | #define PREPASS_THRESH 0.55 // stop prepass when close to density 19 | 20 | #define ALPHA_BREAK 0.97 21 | 22 | 23 | #ifndef OPT_ADAPTIVE_OCTAVES 24 | #define OPT_ADAPTIVE_OCTAVES 1 // set to 0 to disable quickly 25 | #endif 26 | 27 | #ifndef OCT_GATE 28 | #define OCT_GATE 3 // compute first 3 octaves always, gate 4–5 29 | #endif 30 | 31 | #ifndef ADAPT_THRESH 32 | #define ADAPT_THRESH 0.52 // conservative: below this, skip remaining octaves 33 | #endif 34 | 35 | 36 | 37 | #ifndef OPT_STEP_TWEAK 38 | #define OPT_STEP_TWEAK 1 // set to 0 to restore original stepping 39 | #endif 40 | 41 | #ifndef STEP_MIN 42 | #define STEP_MIN 0.10 // original 0.09 43 | #endif 44 | #ifndef STEP_MAX 45 | #define STEP_MAX 0.32 // original 0.30 46 | #endif 47 | #ifndef STEP_A 48 | #define STEP_A 0.52 // original 0.50 49 | #endif 50 | #ifndef STEP_B 51 | #define STEP_B 0.045 // original 0.05 52 | #endif 53 | 54 | 55 | 56 | 57 | mat2 rot(in float a){float c = cos(a), s = sin(a);return mat2(c,s,-s,c);} 58 | const mat3 m3 = mat3(0.33338, 0.56034, -0.71817, -0.87887, 0.32651, -0.15323, 0.15162, 0.69596, 0.61339)*1.93; 59 | float mag2(vec2 p){return dot(p,p);} 60 | float linstep(in float mn, in float mx, in float x){ return clamp((x - mn)/(mx - mn), 0., 1.); } 61 | float prm1 = 0.; 62 | vec2 bsMo = vec2(0); 63 | 64 | vec2 disp(float t){ return vec2(sin(t*0.22)*1., cos(t*0.175)*1.)*2.; } 65 | 66 | 67 | 68 | vec2 map(vec3 p) 69 | { 70 | vec3 p2 = p; 71 | p2.xy -= disp(p.z).xy; 72 | p.xy *= rot(sin(p.z+iTime)*(0.1 + prm1*0.05) + iTime*0.09); 73 | 74 | float cl = dot(p2.xy, p2.xy); // same as mag2(p2.xy) 75 | float d = 0.0; 76 | p *= 0.61; 77 | float z = 1.0; 78 | float trk = 1.0; 79 | float dspAmp = 0.1 + prm1*0.2; 80 | 81 | for (int i = 0; i < NOISE_OCTAVES; i++) 82 | { 83 | p += sin(p.zxy*0.75*trk + iTime*trk*0.8) * dspAmp; 84 | d -= abs(dot(cos(p), sin(p.yzx)) * z); 85 | z *= 0.57; 86 | trk *= 1.4; 87 | p = p * m3; 88 | 89 | #if OPT_ADAPTIVE_OCTAVES 90 | // After OCT_GATE octaves, estimate the final density and bail if it's “empty” 91 | if (i + 1 == OCT_GATE) { 92 | float d_est = abs(d + prm1*3.0) + prm1*0.3 - 2.5 + bsMo.y; 93 | d_est += cl*0.2 + 0.25; // same post terms used below 94 | if (d_est < ADAPT_THRESH) { 95 | // Skip remaining octaves, they won't change step/shade decisions much 96 | break; 97 | } 98 | } 99 | #endif 100 | } 101 | 102 | d = abs(d + prm1*3.0) + prm1*0.3 - 2.5 + bsMo.y; 103 | return vec2(d + cl*0.2 + 0.25, cl); 104 | } 105 | 106 | 107 | 108 | 109 | 110 | vec4 render( in vec3 ro, in vec3 rd, float time ) 111 | { 112 | vec4 rez = vec4(0); 113 | const float ldst = 8.; 114 | vec3 lpos = vec3(disp(time + ldst)*0.5, time + ldst); 115 | float t = 1.5; 116 | float fogT = 0.; 117 | 118 | 119 | #if OPT_COARSE_PREPASS 120 | // coarse skip through empty space 121 | for (int k = 0; k < PREPASS_STEPS; k++) { 122 | vec3 p = ro + t * rd; 123 | float d = map(p).x; 124 | if (d > PREPASS_THRESH) break; 125 | 126 | float dn = clamp(d + 2.0, 0.0, 3.0); 127 | t += clamp(0.6 - dn*dn*0.05, PREPASS_DT_MIN, PREPASS_DT_MAX); 128 | } 129 | #endif 130 | 131 | #if OPT_LIGHT_FROM_PREV 132 | // seed previous-step density for cheap lighting 133 | float prev_mpvx = map(ro + t*rd - rd*0.6).x; 134 | #endif 135 | 136 | 137 | 138 | for(int i=0; i ALPHA_BREAK) break; 141 | 142 | vec3 pos = ro + t*rd; 143 | vec2 mpv = map(pos); 144 | float den = clamp(mpv.x-0.3,0.,1.)*1.12; 145 | float dn = clamp((mpv.x + 2.),0.,3.); 146 | 147 | vec4 col = vec4(0); 148 | if (mpv.x > 0.6) 149 | { 150 | col = vec4(sin(vec3(5.,0.4,0.2) + mpv.y*0.1 + sin(pos.z*0.4)*0.5 + 1.8)*0.5 + 0.5,0.08); 151 | col *= den*den*den; 152 | col.rgb *= linstep(4.,-2.5, mpv.x)*2.3; 153 | 154 | #if OPT_LIGHT_FROM_PREV 155 | // New: reuse previous-step density as a cheap gradient proxy 156 | float grad = prev_mpvx - mpv.x; // >0 when entering denser region 157 | float dif = clamp(grad*0.8 + 0.35, 0.001, 1.0); // tuned scale/bias 158 | #else 159 | // Baseline from your last step: single forward sample 160 | float dif = clamp((den - map(pos + rd*0.6).x)/5.0, 0.001, 1.0); 161 | #endif 162 | col.xyz *= den*(vec3(0.005,.045,.075) + 1.5*vec3(0.033,0.07,0.03)*dif); 163 | } 164 | 165 | //float fogC = exp(t*0.2 - 2.2); 166 | const float inv_ln2 = 1.4426950408889634; // 1 / ln(2) 167 | float fogC = exp2((t*0.2 - 2.2) * inv_ln2); 168 | 169 | col.rgba += vec4(0.06,0.11,0.11, 0.1)*clamp(fogC-fogT, 0., 1.); 170 | fogT = fogC; 171 | rez = rez + col*(1. - rez.a); 172 | // t += clamp(0.5 - dn*dn*.05, 0.10, 0.31); 173 | #if OPT_STEP_TWEAK 174 | t += clamp(STEP_A - dn*dn*STEP_B, STEP_MIN, STEP_MAX); 175 | #else 176 | t += clamp(0.5 - dn*dn*.05, 0.09, 0.3); 177 | #endif 178 | 179 | 180 | #if OPT_LIGHT_FROM_PREV 181 | prev_mpvx = mpv.x; // advance light proxy 182 | #endif 183 | } 184 | return clamp(rez, 0.0, 1.0); 185 | } 186 | 187 | float getsat(vec3 c) 188 | { 189 | float mi = min(min(c.x, c.y), c.z); 190 | float ma = max(max(c.x, c.y), c.z); 191 | return (ma - mi)/(ma+ 1e-7); 192 | } 193 | 194 | vec3 iLerp(in vec3 a, in vec3 b, in float x) 195 | { 196 | vec3 ic = mix(a, b, x) + vec3(1e-6,0.,0.); 197 | float sd = abs(getsat(ic) - mix(getsat(a), getsat(b), x)); 198 | vec3 dir = normalize(vec3(2.*ic.x - ic.y - ic.z, 2.*ic.y - ic.x - ic.z, 2.*ic.z - ic.y - ic.x)); 199 | float lgt = dot(vec3(1.0), ic); 200 | float ff = dot(dir, normalize(ic)); 201 | ic += 1.5*dir*sd*ff*lgt; 202 | return clamp(ic,0.,1.); 203 | } 204 | 205 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) 206 | { 207 | vec2 q = fragCoord.xy/iResolution.xy; 208 | vec2 p = (gl_FragCoord.xy - 0.5*iResolution.xy)/iResolution.y; 209 | bsMo = (iMouse.xy - 0.5*iResolution.xy)/iResolution.y; 210 | 211 | float time = iTime*3.; 212 | vec3 ro = vec3(0,0,time); 213 | ro += vec3(sin(iTime)*0.5,sin(iTime*1.)*0.,0); 214 | 215 | float dspAmp = .85; 216 | ro.xy += disp(ro.z)*dspAmp; 217 | float tgtDst = 3.5; 218 | 219 | vec3 target = normalize(ro - vec3(disp(time + tgtDst)*dspAmp, time + tgtDst)); 220 | ro.x -= bsMo.x*2.; 221 | vec3 rightdir = normalize(cross(target, vec3(0,1,0))); 222 | vec3 updir = normalize(cross(rightdir, target)); 223 | rightdir = normalize(cross(updir, target)); 224 | vec3 rd=normalize((p.x*rightdir + p.y*updir)*1. - target); 225 | rd.xy *= rot(-disp(time + 3.5).x*0.2 + bsMo.x); 226 | prm1 = smoothstep(-0.4, 0.4,sin(iTime*0.3)); 227 | vec4 scn = render(ro, rd, time); 228 | 229 | vec3 col = scn.rgb; 230 | col = iLerp(col.bgr, col.rgb, clamp(1.-prm1,0.05,1.)); 231 | col = pow(col, vec3(.55,0.65,0.6))*vec3(1.,.97,.9); 232 | col *= pow( 16.0*q.x*q.y*(1.0-q.x)*(1.0-q.y), 0.12)*0.7+0.3; //Vign 233 | fragColor = vec4( col, 1.0 ); 234 | } 235 | 236 | -------------------------------------------------------------------------------- /shaders/spiral2.glsl: -------------------------------------------------------------------------------- 1 | // https://www.shadertoy.com/view/Xc3czX 2 | 3 | #define MAX_STEPS 100 4 | #define MAX_DIST 100.0 5 | #define SURF_DIST 0.0001 6 | 7 | #define PI 3.14159265359 8 | 9 | 10 | // Custom gradient - https://iquilezles.org/articles/palettes/ 11 | vec3 palette(float t) { 12 | return .5+.5*cos((PI*2.0)*(t+vec3(.4,.2,.1))); 13 | } 14 | 15 | //sdLink - exact=https://iquilezles.org/articles/distfunctions/ 16 | float sdLink( vec3 p, float le, float r1, float r2 ) 17 | { 18 | vec3 q = vec3( p.x, max(abs(p.y)-le,0.0), p.z ); 19 | return length(vec2(length(q.xy)-r1,q.z)) - r2; 20 | } 21 | 22 | // Rotation function for 3D vectors around an arbitrary axis 23 | vec3 rotate3d(vec3 p, vec3 axis, float angle) { 24 | axis = normalize(axis); 25 | float cosAngle = cos(angle); 26 | float sinAngle = sin(angle); 27 | return p * cosAngle + cross(axis, p) * sinAngle + axis * dot(axis, p) * (1.0 - cosAngle); 28 | } 29 | 30 | // Smooth min function (smin) 31 | float smin(float d1, float d2, float k) { 32 | float h = clamp(0.5 + 0.5 * (d2 - d1) / k, 0.0, 1.0); 33 | return mix(d2, d1, h) - k * h * (1.0 - h); 34 | } 35 | 36 | // 3D rotation around the X-axis 37 | mat3 rotationX(float angle) { 38 | float s = sin(angle); 39 | float c = cos(angle); 40 | return mat3(1.0, 0.0, 0.0, 0.0, c, -s, 0.0, s, c); 41 | } 42 | 43 | // 3D rotation around the Y-axis 44 | mat3 rotationY(float angle) { 45 | float s = sin(angle); 46 | float c = cos(angle); 47 | return mat3(c, 0.0, s, 0.0, 1.0, 0.0, -s, 0.0, c); 48 | } 49 | 50 | // 3D rotation around the Z-axis 51 | mat3 rotationZ(float angle) { 52 | float s = sin(angle); 53 | float c = cos(angle); 54 | return mat3(c, -s, 0.0, s, c, 0.0, 0.0, 0.0, 1.0); 55 | } 56 | // 2D rotation function 57 | mat2 rot2D(float a) { 58 | return mat2(cos(a), -sin(a), sin(a), cos(a)); 59 | } 60 | float BASE_Y = -.7; 61 | float CONE_HEIGHT = 3.5; 62 | float CONE_Y = .75; 63 | float CONE_VOL = 1.125; 64 | float SMIN_BLEND = 0.333; 65 | float RIPPLE_AMOUNT = 2.; 66 | // Scene function, combining the objects with smooth union (smin) 67 | float sceneSDF(vec3 p, out vec3 color) { 68 | float teet = (1.5*abs(sin(iTime*.125)))+.1; 69 | p.z -= iTime * 1.; // Forward movement 70 | // Space repetition 71 | p.z = fract(p.z) - .5; // spacing: 1 72 | 73 | p.xy*=rot2D((PI*.5)); 74 | float link = sdLink(p, 2.,2.5, .2); 75 | vec3 col = palette(p.z*p.y);//*vec3(.7+abs(cos(iTime*.1)), .5+(abs(sin(p.y+iTime))*.666), 0.97); 76 | // Color the sphere white 77 | color = col; 78 | 79 | return link; 80 | } 81 | 82 | // Scene function without color (for normal calculation) 83 | float sceneSDF(vec3 p) { 84 | float teet = (1.5*abs(sin(iTime*.125)))+.1; 85 | p.z -= iTime * 1.; // Forward movement 86 | // Space repetition 87 | p.z = fract(p.z) - .5; // spacing: 1 88 | 89 | p.xy*=rot2D((PI*.5)); 90 | float link = sdLink(p, 2.,2.5, .2); 91 | return link; 92 | } 93 | 94 | 95 | 96 | 97 | 98 | // Normal calculation for lighting 99 | vec3 getNormal(vec3 p) { 100 | float d = sceneSDF(p); // Use the version without the color output 101 | vec2 e = vec2(0.01, 0.0); 102 | vec3 n = d - vec3( 103 | sceneSDF(p - e.xyy), 104 | sceneSDF(p - e.yxy), 105 | sceneSDF(p - e.yyx) 106 | ); 107 | return normalize(n); 108 | } 109 | 110 | // Fresnel-Schlick approximation 111 | vec3 fresnelSchlick(float cosTheta, vec3 F0) { 112 | return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); 113 | } 114 | 115 | // Distribution function for specular reflection (GGX/Trowbridge-Reitz) 116 | float distributionGGX(vec3 N, vec3 H, float roughness) { 117 | float a = roughness * roughness; 118 | float a2 = a * a; 119 | float NdotH = max(dot(N, H), 0.0); 120 | float NdotH2 = NdotH * NdotH; 121 | 122 | float num = a2; 123 | float denom = (NdotH2 * (a2 - 1.0) + 1.0); 124 | denom = 3.14159 * denom * denom; // π * denom^2 125 | return num / denom; 126 | } 127 | 128 | // Geometry function (Smith's Schlick-GGX) 129 | float geometrySchlickGGX(float NdotV, float roughness) { 130 | float r = (roughness + 1.0); 131 | float k = (r * r) / 8.0; 132 | return NdotV / (NdotV * (1.0 - k) + k); 133 | } 134 | 135 | // Geometry term (combination of both view and light shadowing) 136 | float geometrySmith(vec3 N, vec3 V, vec3 L, float roughness) { 137 | float NdotV = max(dot(N, V), 0.0); 138 | float NdotL = max(dot(N, L), 0.0); 139 | float ggx1 = geometrySchlickGGX(NdotV, roughness); 140 | float ggx2 = geometrySchlickGGX(NdotL, roughness); 141 | return ggx1 * ggx2; 142 | } 143 | 144 | // Cook-Torrance BRDF 145 | vec3 cookTorranceBRDF(vec3 N, vec3 V, vec3 L, vec3 F0, float roughness, vec3 albedo, float metallic) { 146 | vec3 H = normalize(V + L); 147 | float NDF = distributionGGX(N, H, roughness); // Normal Distribution Function 148 | float G = geometrySmith(N, V, L, roughness); // Geometry function 149 | vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0); // Fresnel term 150 | 151 | float NdotL = max(dot(N, L), 0.0); 152 | float NdotV = max(dot(N, V), 0.0); 153 | 154 | // Specular component 155 | vec3 numerator = NDF * G * F; 156 | float denominator = 4.0 * NdotV * NdotL + 0.0001; // Avoid division by zero 157 | vec3 specular = numerator / denominator; 158 | 159 | // Diffuse component (Lambertian) 160 | vec3 kD = vec3(1.0) - F; // Fresnel term reduces diffuse contribution 161 | kD *= (1.0 - metallic); // No diffuse component for metals 162 | vec3 diffuse = kD * albedo / 3.14159; 163 | 164 | // Final outgoing light (radiance) 165 | return (diffuse + specular) * NdotL; 166 | } 167 | 168 | // PBR lighting function 169 | vec3 pbrLighting(vec3 p, vec3 V, vec3 L, vec3 albedo, float metallic, float roughness) { 170 | vec3 N = getNormal(p); // Surface normal 171 | vec3 F0 = mix(vec3(0.04), albedo, metallic); // Fresnel reflectance at normal incidence 172 | // Light intensity adjustment (increase this factor to make the light brighter) 173 | float lightIntensity = 6.0; // Increase this value to brighten the light 174 | 175 | // Cook-Torrance BRDF 176 | vec3 radiance = cookTorranceBRDF(N, V, L, F0, roughness, albedo, metallic); 177 | 178 | return radiance * lightIntensity; 179 | } 180 | // Raymarching function 181 | float rayMarch(vec3 ro, vec3 rd, out vec3 color, float s) { 182 | float dist = 0.0; 183 | 184 | for (int i = 0; i < MAX_STEPS; i++) { 185 | vec3 p = ro + dist * rd; 186 | p.x += sin(dist*.15)*2.75; // wiggle ray 187 | p.y -= cos(dist*.1)*.75; // wiggle ray 188 | p.xy *= rot2D(PI*(dist*.025)+iTime*.25); 189 | float d = sceneSDF(p, color); 190 | if (d < SURF_DIST) { 191 | return dist; 192 | } 193 | dist += d; 194 | if (dist > MAX_DIST) { 195 | return MAX_DIST; 196 | } 197 | } 198 | return MAX_DIST; 199 | } 200 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) { 201 | vec2 uv = (fragCoord.xy - iResolution.xy * 0.5) / iResolution.y; 202 | vec3 snd = texture(iChannel0, uv).rgb; 203 | // Camera setup 204 | vec3 ro = vec3(0.0, 0.0, 2.0); // Ray origin (camera position) 205 | vec3 rd = normalize(vec3(uv, -1.)); // Ray direction 206 | // Rotate the scene by applying the rotation matrices 207 | //ro = rotationX(-0.125) * rotationY(.15333) * ro; 208 | // rd = rotationY(0.5) * rotationX(-.333) * rd; 209 | 210 | // Perform raymarching 211 | vec3 objColor; 212 | float d = rayMarch(ro, rd, objColor, snd.x); 213 | 214 | vec3 color = vec3(0.0); 215 | if (d < MAX_DIST) { 216 | // Compute position of hit 217 | vec3 p = ro + d * rd; 218 | p.x += sin(d*.15)*2.75; // wiggle ray 219 | p.y -= cos(d*.1)*.75; // wiggle ray 220 | p.xy *= rot2D(PI*(d*.025)+iTime*.25); 221 | // PBR material parameters 222 | objColor = palette(p.z*.0665);//*vec3(.7+abs(cos(iTime*.1)), .5+(abs(sin(p.y+iTime))*.666), 0.97); 223 | 224 | float metallic = .24; // Non-metallic surface 225 | float roughness = .4; // Mid-level roughness 226 | //p.yz *= rot2D(iTime*.125); // rotate ray around z-axis 227 | // Lighting parameters 228 | vec3 lightPos = vec3(10.0, 2.0, 5.0); 229 | vec3 L = normalize(lightPos - p); 230 | vec3 V = normalize(ro - p); 231 | 232 | // Apply PBR lighting 233 | color = pbrLighting(p, V, L, objColor, metallic, roughness); 234 | } 235 | 236 | fragColor = vec4(color, 1.0); 237 | } 238 | 239 | -------------------------------------------------------------------------------- /shaders/accretion2.glsl: -------------------------------------------------------------------------------- 1 | // https://www.shadertoy.com/view/tsBXW3 2 | #define AA 1 //change to 1 to increase performance 3 | 4 | #define _Speed 3.8 //disk rotation speed 5 | 6 | #define _Steps 6. //disk texture layers 7 | #define _Size 0.45 //size of BH 8 | 9 | 10 | 11 | float hash(float x){ return fract(sin(x)*152754.742);} 12 | float hash(vec2 x){ return hash(x.x + hash(x.y));} 13 | 14 | float value(vec2 p, float f) //value noise 15 | { 16 | float bl = hash(floor(p*f + vec2(0.,0.))); 17 | float br = hash(floor(p*f + vec2(1.,0.))); 18 | float tl = hash(floor(p*f + vec2(0.,1.))); 19 | float tr = hash(floor(p*f + vec2(1.,1.))); 20 | 21 | vec2 fr = fract(p*f); 22 | fr = (3. - 2.*fr)*fr*fr; 23 | float b = mix(bl, br, fr.x); 24 | float t = mix(tl, tr, fr.x); 25 | return mix(b,t, fr.y); 26 | } 27 | 28 | 29 | 30 | 31 | 32 | vec4 background(vec3 ray) 33 | { 34 | vec2 uv = ray.xy; 35 | 36 | if( abs(ray.x) > 0.5) 37 | uv.x = ray.z; 38 | else if( abs(ray.y) > 0.5) 39 | uv.y = ray.z; 40 | 41 | 42 | float brightness = value( uv*.5, 100.); //(poor quality) "stars" created from value noise 43 | float color = value( uv*2., 20.); 44 | brightness = pow(brightness, 256.); 45 | 46 | brightness = brightness*100.; 47 | brightness = clamp(brightness, 0., 1.); 48 | 49 | vec3 stars = brightness * mix(vec3(1., .6, .2), vec3(.2, .6, 1), color); 50 | 51 | vec4 nebulae = texture(iChannel0, (uv*1.5 )); 52 | nebulae.xyz += nebulae.xxx + nebulae.yyy + nebulae.zzz; //average color 53 | nebulae.xyz *= 0.25; 54 | 55 | nebulae*= nebulae; 56 | nebulae*= nebulae; 57 | nebulae*= nebulae; 58 | nebulae*= nebulae; 59 | 60 | nebulae.xyz += stars; 61 | return nebulae; 62 | } 63 | 64 | 65 | vec4 raymarchDisk(vec3 ray, vec3 zeroPos) 66 | { 67 | //return vec4(1.,1.,1.,0.); //no disk 68 | 69 | vec3 position = zeroPos; 70 | float lengthPos = length(position.xz); 71 | float dist = min(1., lengthPos*(1./_Size) *0.5) * _Size * 0.4 *(1./_Steps) /( abs(ray.y) ); 72 | 73 | position += dist*_Steps*ray*0.5; 74 | 75 | vec2 deltaPos; 76 | deltaPos.x = -zeroPos.z*0.01 + zeroPos.x; 77 | deltaPos.y = zeroPos.x*0.01 + zeroPos.z; 78 | deltaPos = normalize(deltaPos - zeroPos.xz); 79 | 80 | float parallel = dot(ray.xz, deltaPos); 81 | parallel /= sqrt(lengthPos); 82 | parallel *= 0.5; 83 | float redShift = parallel +0.3; 84 | redShift *= redShift; 85 | 86 | redShift = clamp(redShift, 0., 1.); 87 | 88 | float disMix = clamp((lengthPos - _Size * 2.)*(1./_Size)*0.24, 0., 1.); 89 | vec3 insideCol = mix(vec3(1.0,0.8,0.0), vec3(0.5,0.13,0.02)*0.2, disMix); 90 | 91 | insideCol *= mix(vec3(0.4, 0.2, 0.1), vec3(1.6, 2.4, 4.0), redShift); 92 | insideCol *= 1.25; 93 | redShift += 0.12; 94 | redShift *= redShift; 95 | 96 | vec4 o = vec4(0.); 97 | 98 | for(float i = 0. ; i < _Steps; i++) 99 | { 100 | position -= dist * ray ; 101 | 102 | float intensity =clamp( 1. - abs((i - 0.8) * (1./_Steps) * 2.), 0., 1.); 103 | float lengthPos = length(position.xz); 104 | float distMult = 1.; 105 | 106 | distMult *= clamp((lengthPos - _Size * 0.75) * (1./_Size) * 1.5, 0., 1.); 107 | distMult *= clamp(( _Size * 10. -lengthPos) * (1./_Size) * 0.20, 0., 1.); 108 | distMult *= distMult; 109 | 110 | float u = lengthPos + iTime* _Size*0.3 + intensity * _Size * 0.2; 111 | 112 | vec2 xy ; 113 | float rot = mod(iTime*_Speed, 8192.); 114 | xy.x = -position.z*sin(rot) + position.x*cos(rot); 115 | xy.y = position.x*sin(rot) + position.z*cos(rot); 116 | 117 | float x = abs( xy.x/(xy.y)); 118 | float angle = 0.02*atan(x); 119 | 120 | const float f = 70.; 121 | float noise = value( vec2( angle, u * (1./_Size) * 0.05), f); 122 | noise = noise*0.66 + 0.33*value( vec2( angle, u * (1./_Size) * 0.05), f*2.); 123 | 124 | float extraWidth = noise * 1. * (1. - clamp(i * (1./_Steps)*2. - 1., 0., 1.)); 125 | 126 | float alpha = clamp(noise*(intensity + extraWidth)*( (1./_Size) * 10. + 0.01 ) * dist * distMult , 0., 1.); 127 | 128 | vec3 col = 2.*mix(vec3(0.3,0.2,0.15)*insideCol, insideCol, min(1.,intensity*2.)); 129 | o = clamp(vec4(col*alpha + o.rgb*(1.-alpha), o.a*(1.-alpha) + alpha), vec4(0.), vec4(1.)); 130 | 131 | lengthPos *= (1./_Size); 132 | 133 | o.rgb+= redShift*(intensity*1. + 0.5)* (1./_Steps) * 100.*distMult/(lengthPos*lengthPos); 134 | } 135 | 136 | o.rgb = clamp(o.rgb - 0.005, 0., 1.); 137 | return o ; 138 | } 139 | 140 | 141 | void Rotate( inout vec3 vector, vec2 angle ) 142 | { 143 | vector.yz = cos(angle.y)*vector.yz 144 | +sin(angle.y)*vec2(-1,1)*vector.zy; 145 | vector.xz = cos(angle.x)*vector.xz 146 | +sin(angle.x)*vec2(-1,1)*vector.zx; 147 | } 148 | 149 | void mainImage( out vec4 colOut, in vec2 fragCoord ) 150 | { 151 | colOut = vec4(0.);; 152 | 153 | vec2 fragCoordRot; 154 | fragCoordRot.x = fragCoord.x*0.985 + fragCoord.y * 0.174; 155 | fragCoordRot.y = fragCoord.y*0.985 - fragCoord.x * 0.174; 156 | fragCoordRot += vec2(-0.06, 0.12) * iResolution.xy; 157 | 158 | for( int j=0; j _Size * 1000.) //ray escaped BH 205 | { 206 | vec4 bg = background (ray); 207 | outCol = vec4(col.rgb*col.a + bg.rgb*(1.-col.a) + glow.rgb *(1.-col.a ), 1.); 208 | break; 209 | } 210 | 211 | else if (abs(pos.y) <= _Size * 0.002 ) //ray hit accretion disk 212 | { 213 | vec4 diskCol = raymarchDisk(ray, pos); //render disk 214 | pos.y = 0.; 215 | pos += abs(_Size * 0.001 /ray.y) * ray; 216 | col = vec4(diskCol.rgb*(1.-col.a) + col.rgb, col.a + diskCol.a*(1.-col.a)); 217 | } 218 | } 219 | 220 | //if the ray never escaped or got sucked in 221 | if(outCol.r == 100.) 222 | outCol = vec4(col.rgb + glow.rgb *(col.a + glow.a) , 1.); 223 | 224 | col = outCol; 225 | col.rgb = pow( col.rgb, vec3(0.6) ); 226 | 227 | colOut += col/float(AA*AA); 228 | } 229 | } 230 | 231 | -------------------------------------------------------------------------------- /shaders/voxel1.glsl: -------------------------------------------------------------------------------- 1 | // https://www.shadertoy.com/view/4dfGzs 2 | // Copyright Inigo Quilez, 2013 - https://iquilezles.org/ 3 | // I am the sole copyright owner of this Work. 4 | // You cannot host, display, distribute or share this Work neither 5 | // as it is or altered, here on Shadertoy or anywhere else, in any 6 | // form including physical and digital. You cannot use this Work in any 7 | // commercial or non-commercial product, website or project. You cannot 8 | // sell this Work and you cannot mint an NFTs of it or train a neural 9 | // network with it without permission. I share this Work for educational 10 | // purposes, and you can link to it, through an URL, proper attribution 11 | // and unmodified screenshot, as part of your educational material. If 12 | // these conditions are too restrictive please contact me and we'll 13 | // definitely work it out. 14 | 15 | // Shading technique explained here: 16 | // 17 | // https://iquilezles.org/articles/voxellines 18 | 19 | 20 | 21 | // consider replacing this by a proper noise function 22 | float noise( in vec3 x ) 23 | { 24 | vec3 i = floor(x); 25 | vec3 f = fract(x); 26 | f = f*f*(3.0-2.0*f); 27 | vec2 uv = (i.xy+vec2(37.0,17.0)*i.z) + f.xy; 28 | vec2 rg = textureLod( iChannel0, (uv+0.5)/256.0, 0.0 ).yx; 29 | return mix( rg.x, rg.y, f.z ); 30 | } 31 | 32 | float mapTerrain( vec3 p ) 33 | { 34 | p *= 0.1; 35 | p.xz *= 0.6; // 0.6 36 | 37 | float time = 0.5 + 0.15*iTime; 38 | float ft = fract( time ); 39 | float it = floor( time ); 40 | ft = smoothstep( 0.7, 1.0, ft ); 41 | time = it + ft; 42 | float spe = 0.2; 43 | 44 | float f; 45 | f = 0.5000*noise( p*1.00 + vec3(0.0,1.0,0.0)*spe*time ); 46 | f += 0.2500*noise( p*2.02 + vec3(0.0,2.0,0.0)*spe*time ); 47 | f += 0.1250*noise( p*4.01 ); 48 | return 45.0*f-10.0; 49 | } 50 | 51 | vec3 gro = vec3(0.0); 52 | 53 | float map(in vec3 c) 54 | { 55 | vec3 p = c + 0.5; 56 | 57 | float f = mapTerrain( p ) + 0.25*p.y; 58 | 59 | f = mix( f, 1.0, step( length(gro-p), 5.0 ) ); 60 | 61 | return step( f, 0.5 ); 62 | } 63 | 64 | const vec3 lig = normalize( vec3(-0.4,0.3,0.7) ); 65 | 66 | float raycast( in vec3 ro, in vec3 rd, out vec3 oVos, out vec3 oDir ) 67 | { 68 | vec3 pos = floor(ro); 69 | vec3 ri = 1.0/rd; 70 | vec3 rs = sign(rd); 71 | vec3 dis = (pos-ro + 0.5 + rs*0.5) * ri; 72 | 73 | float res = -1.0; 74 | vec3 mm = vec3(0.0); 75 | for( int i=0; i<128; i++ ) 76 | { 77 | if( map(pos)>0.5 ) { res=1.0; break; } 78 | mm = step(dis.xyz, dis.yzx) * step(dis.xyz, dis.zxy); 79 | dis += mm * rs * ri; 80 | pos += mm * rs; 81 | } 82 | 83 | vec3 nor = -mm*rs; 84 | vec3 vos = pos; 85 | 86 | // intersect the cube 87 | vec3 mini = (pos-ro + 0.5 - 0.5*vec3(rs))*ri; 88 | float t = max ( mini.x, max ( mini.y, mini.z ) ); 89 | 90 | oDir = mm; 91 | oVos = vos; 92 | 93 | return t*res; 94 | } 95 | 96 | vec3 path( float t, float ya ) 97 | { 98 | vec2 p = 100.0*sin( 0.02*t*vec2(1.0,1.2) + vec2(0.1,0.9) ); 99 | p += 50.0*sin( 0.04*t*vec2(1.3,1.0) + vec2(1.0,4.5) ); 100 | 101 | return vec3( p.x, 18.0 + ya*4.0*sin(0.05*t), p.y ); 102 | } 103 | 104 | mat3 setCamera( in vec3 ro, in vec3 ta, float cr ) 105 | { 106 | vec3 cw = normalize(ta-ro); 107 | vec3 cp = vec3(sin(cr), cos(cr),0.0); 108 | vec3 cu = normalize( cross(cw,cp) ); 109 | vec3 cv = normalize( cross(cu,cw) ); 110 | return mat3( cu, cv, -cw ); 111 | } 112 | 113 | float maxcomp( in vec4 v ) 114 | { 115 | return max( max(v.x,v.y), max(v.z,v.w) ); 116 | } 117 | 118 | float isEdge( in vec2 uv, vec4 va, vec4 vb, vec4 vc, vec4 vd ) 119 | { 120 | vec2 st = 1.0 - uv; 121 | 122 | // edges 123 | vec4 wb = smoothstep( 0.85, 0.99, vec4(uv.x, 124 | st.x, 125 | uv.y, 126 | st.y) ) * ( 1.0 - va + va*vc ); 127 | // corners 128 | vec4 wc = smoothstep( 0.85, 0.99, vec4(uv.x*uv.y, 129 | st.x*uv.y, 130 | st.x*st.y, 131 | uv.x*st.y) ) * ( 1.0 - vb + vd*vb ); 132 | return maxcomp( max(wb,wc) ); 133 | } 134 | 135 | 136 | vec3 render( in vec3 ro, in vec3 rd ) 137 | { 138 | vec3 col = vec3(0.0); 139 | 140 | // raymarch 141 | vec3 vos, dir; 142 | float t = raycast( ro, rd, vos, dir ); 143 | if( t>0.0 ) 144 | { 145 | vec3 nor = -dir*sign(rd); 146 | vec3 pos = ro + rd*t; 147 | vec3 uvw = pos - vos; 148 | 149 | vec3 v1 = vos + nor + dir.yzx; 150 | vec3 v2 = vos + nor - dir.yzx; 151 | vec3 v3 = vos + nor + dir.zxy; 152 | vec3 v4 = vos + nor - dir.zxy; 153 | vec3 v5 = vos + nor + dir.yzx + dir.zxy; 154 | vec3 v6 = vos + nor - dir.yzx + dir.zxy; 155 | vec3 v7 = vos + nor - dir.yzx - dir.zxy; 156 | vec3 v8 = vos + nor + dir.yzx - dir.zxy; 157 | vec3 v9 = vos + dir.yzx; 158 | vec3 v10 = vos - dir.yzx; 159 | vec3 v11 = vos + dir.zxy; 160 | vec3 v12 = vos - dir.zxy; 161 | vec3 v13 = vos + dir.yzx + dir.zxy; 162 | vec3 v14 = vos - dir.yzx + dir.zxy ; 163 | vec3 v15 = vos - dir.yzx - dir.zxy; 164 | vec3 v16 = vos + dir.yzx - dir.zxy; 165 | 166 | vec4 vc = vec4( map(v1), map(v2), map(v3), map(v4) ); 167 | vec4 vd = vec4( map(v5), map(v6), map(v7), map(v8) ); 168 | vec4 va = vec4( map(v9), map(v10), map(v11), map(v12) ); 169 | vec4 vb = vec4( map(v13), map(v14), map(v15), map(v16) ); 170 | 171 | vec2 uv = vec2( dot(dir.yzx, uvw), dot(dir.zxy, uvw) ); 172 | 173 | // wireframe 174 | float www = 1.0 - isEdge( uv, va, vb, vc, vd ); 175 | 176 | vec3 wir = smoothstep( 0.4, 0.5, abs(uvw-0.5) ); 177 | float vvv = (1.0-wir.x*wir.y)*(1.0-wir.x*wir.z)*(1.0-wir.y*wir.z); 178 | 179 | col = vec3(0.5); 180 | col += 0.8*vec3(0.1,0.3,0.4); 181 | col *= 1.0 - 0.75*(1.0-vvv)*www; 182 | 183 | // lighting 184 | float dif = clamp( dot( nor, lig ), 0.0, 1.0 ); 185 | float bac = clamp( dot( nor, normalize(lig*vec3(-1.0,0.0,-1.0)) ), 0.0, 1.0 ); 186 | float sky = 0.5 + 0.5*nor.y; 187 | float amb = clamp(0.75 + pos.y/25.0,0.0,1.0); 188 | float occ = 1.0; 189 | 190 | // ambient occlusion (https://iquilezles.org/articles/voxellines/) 191 | vec2 st = 1.0 - uv; 192 | // edges 193 | vec4 wa = vec4( uv.x, st.x, uv.y, st.y ) * vc; 194 | // corners 195 | vec4 wb = vec4(uv.x*uv.y, 196 | st.x*uv.y, 197 | st.x*st.y, 198 | uv.x*st.y)*vd*(1.0-vc.xzyw)*(1.0-vc.zywx); 199 | occ = wa.x + wa.y + wa.z + wa.w + 200 | wb.x + wb.y + wb.z + wb.w; 201 | 202 | 203 | occ = 1.0 - occ/8.0; 204 | occ = occ*occ; 205 | occ = occ*occ; 206 | occ *= amb; 207 | 208 | // lighting 209 | vec3 lin = vec3(0.0); 210 | lin += 2.5*dif*vec3(1.00,0.90,0.70)*(0.5+0.5*occ); 211 | lin += 0.5*bac*vec3(0.15,0.10,0.10)*occ; 212 | lin += 2.0*sky*vec3(0.40,0.30,0.15)*occ; 213 | 214 | // line glow 215 | float lineglow = 0.0; 216 | lineglow += smoothstep( 0.4, 1.0, uv.x )*(1.0-va.x*(1.0-vc.x)); 217 | lineglow += smoothstep( 0.4, 1.0, 1.0-uv.x )*(1.0-va.y*(1.0-vc.y)); 218 | lineglow += smoothstep( 0.4, 1.0, uv.y )*(1.0-va.z*(1.0-vc.z)); 219 | lineglow += smoothstep( 0.4, 1.0, 1.0-uv.y )*(1.0-va.w*(1.0-vc.w)); 220 | lineglow += smoothstep( 0.4, 1.0, uv.y* uv.x )*(1.0-vb.x*(1.0-vd.x)); 221 | lineglow += smoothstep( 0.4, 1.0, uv.y* (1.0-uv.x))*(1.0-vb.y*(1.0-vd.y)); 222 | lineglow += smoothstep( 0.4, 1.0, (1.0-uv.y)*(1.0-uv.x))*(1.0-vb.z*(1.0-vd.z)); 223 | lineglow += smoothstep( 0.4, 1.0, (1.0-uv.y)* uv.x )*(1.0-vb.w*(1.0-vd.w)); 224 | 225 | vec3 linCol = 2.0*vec3(5.0,0.6,0.0); 226 | linCol *= (0.5+0.5*occ)*0.5; 227 | lin += lineglow*linCol; 228 | 229 | col = col*lin; 230 | col += 8.0*linCol*vec3(1.0,2.0,3.0)*(1.0-www);//*(0.5+1.0*sha); 231 | col += 0.1*lineglow*linCol; 232 | col *= min(0.1,exp( -0.07*t )); 233 | 234 | // blend to black & white 235 | vec3 col2 = vec3(1.3)*(0.5+0.5*nor.y)*occ*exp( -0.04*t );; 236 | float mi = cos(-0.7+0.5*iTime); 237 | mi = smoothstep( 0.70, 0.75, mi ); 238 | col = mix( col, col2, mi ); 239 | } 240 | 241 | // gamma 242 | col = pow( col, vec3(0.45) ); 243 | 244 | return col; 245 | } 246 | 247 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) 248 | { 249 | // inputs 250 | vec2 p = (2.0*fragCoord-iResolution.xy)/iResolution.y; 251 | vec2 mo = iMouse.xy / iResolution.xy; 252 | if( iMouse.z<=0.00001 ) mo=vec2(0.0); 253 | float time = 2.0*iTime + 50.0*mo.x; 254 | 255 | // camera 256 | float cr = 0.2*cos(0.1*iTime); 257 | vec3 ro = path( time+0.0, 1.0 ); 258 | vec3 ta = path( time+5.0, 1.0 ) - vec3(0.0,6.0,0.0); 259 | gro = ro; 260 | 261 | mat3 cam = setCamera( ro, ta, cr ); 262 | 263 | // build ray 264 | float r2 = p.x*p.x*0.32 + p.y*p.y; 265 | p *= (7.0-sqrt(37.5-11.5*r2))/(r2+1.0); 266 | vec3 rd = normalize( cam * vec3(p.xy,-2.5) ); 267 | 268 | vec3 col = render( ro, rd ); 269 | 270 | // vignetting 271 | vec2 q = fragCoord / iResolution.xy; 272 | col *= 0.5 + 0.5*pow( 16.0*q.x*q.y*(1.0-q.x)*(1.0-q.y), 0.1 ); 273 | 274 | fragColor = vec4( col, 1.0 ); 275 | } 276 | 277 | void mainVR( out vec4 fragColor, in vec2 fragCoord, in vec3 fragRayOri, in vec3 fragRayDir ) 278 | { 279 | float time = 1.0*iTime; 280 | 281 | float cr = 0.0; 282 | vec3 ro = path( time+0.0, 0.0 ) + vec3(0.0,0.7,0.0); 283 | vec3 ta = path( time+2.5, 0.0 ) + vec3(0.0,0.7,0.0); 284 | 285 | mat3 cam = setCamera( ro, ta, cr ); 286 | 287 | vec3 col = render( ro + cam*fragRayOri, cam*fragRayDir ); 288 | 289 | fragColor = vec4( col, 1.0 ); 290 | } 291 | -------------------------------------------------------------------------------- /shaders/synthwave.glsl: -------------------------------------------------------------------------------- 1 | // https://www.shadertoy.com/view/tsfyzn 2 | // credits to @spalmer for grid smooth function https://www.shadertoy.com/view/wl3Sz2 3 | #define MAX_STEPS 156 4 | #define MIN_DISTANCE 0.01 5 | #define MAX_DISTANCE 16. 6 | #define GRID_SIZE 4. 7 | #define speed 6. 8 | #define MOUNTAIN_COLOR vec3(0.54, 0.11, 1.) 9 | #define COLOR_PURPLE vec3(0.81, 0.19, 0.78) 10 | #define COLOR_LIGHT vec3(0.14, 0.91, 0.98) 11 | #define COLOR_SUN vec3(1., 0.56, 0.098) 12 | #define MATERIAL_PLANE 1. 13 | #define MATERIAL_BACK 2. 14 | #define GRID_THICKNESS .2 15 | #define COLOR_NIGHT_GRID vec3(0., .15, 0.) 16 | #define COLOR_NIGHT_SUN vec3(0.5, .0, 0.) 17 | #define COLOR_NIGHT_MOUNTAIN vec3(0.9, .3, 0.1) 18 | #define SUNSET_SPEED 3. 19 | 20 | vec3 lightPos = vec3(0., 3., -10.); 21 | 22 | struct traceResult { 23 | bool isHit; 24 | float distanceTo; 25 | float material; 26 | float planeHeight; 27 | vec3 planeNormal; 28 | }; 29 | 30 | struct getDistResult { 31 | float distanceTo; 32 | float material; 33 | float planeHeight; 34 | vec3 planeNormal; 35 | }; 36 | 37 | float sdPlane(vec3 p, float h) { 38 | return p.y - h; 39 | } 40 | 41 | float N21(vec2 p) { 42 | return fract(sin(p.x*223.32+p.y*5677.)*4332.23); 43 | } 44 | 45 | mat2 rot2d(float a) { 46 | float c = cos(a); 47 | float s = sin(a); 48 | return mat2(vec2(c,-s), vec2(s,c)); 49 | } 50 | 51 | float getHeight(vec2 id) { 52 | //return 0.; 53 | float ax = abs(id.x); 54 | if (ax < GRID_SIZE) { 55 | return 0.; 56 | } 57 | 58 | float n = N21(id); 59 | 60 | float wave = sin(id.y/9. + cos(id.x/3.))*sin(id.x/9. + sin(id.y/4.)); 61 | 62 | wave = clamp((wave * .5 + .5) + n*.15 - .6, 0., 1.); 63 | if (ax < (GRID_SIZE + 5.) && ax >= GRID_SIZE) { 64 | wave *= (ax - GRID_SIZE + 1.)*.2; 65 | } 66 | return (wave*10.); 67 | } 68 | 69 | 70 | getDistResult getDist(vec3 p) { 71 | float size = GRID_SIZE; 72 | vec3 nuv = p * size + vec3(0., 0., iTime * speed); 73 | vec2 uv = fract(nuv).xz; 74 | vec2 id = floor(nuv).xz; 75 | 76 | vec2 lv = uv; 77 | 78 | float bl = getHeight(id); 79 | float br = getHeight(id + vec2(1., 0.)); 80 | float b = mix(bl, br, lv.x); 81 | 82 | float tl = getHeight(id + vec2(0., 1.)); 83 | float tr = getHeight(id + vec2(1., 1.)); 84 | float t = mix(tl, tr, lv.x); 85 | 86 | float height = mix(b,t, lv.y); 87 | 88 | float O = bl; 89 | float R = br; 90 | float T = getHeight(id + vec2(0. -1.)); 91 | float B = tl; 92 | float L = getHeight(id + vec2(-1., 0)); 93 | 94 | vec3 n = vec3(2.*(R-L), 2.*(B-T), -4.); 95 | 96 | 97 | float d = sdPlane(p, -.5 + 0.3*height); 98 | 99 | float db = -p.z + MAX_DISTANCE*.4; 100 | d = min(d, db); 101 | 102 | getDistResult result; 103 | 104 | result.distanceTo = d; 105 | result.material = MATERIAL_PLANE; 106 | result.planeHeight = height; 107 | result.planeNormal = normalize(n); 108 | 109 | if (d == db) { 110 | result.material = MATERIAL_BACK; 111 | } 112 | 113 | return result; 114 | } 115 | 116 | traceResult trace(vec3 ro, vec3 rd) { 117 | traceResult result; 118 | float ds, dt; 119 | getDistResult dist; 120 | for(int i = 0 ; i < MAX_STEPS ; i++) { 121 | vec3 p = ro + rd * ds; 122 | dist = getDist(p); 123 | dt = dist.distanceTo; 124 | ds += dt * .6; 125 | if (abs(dt) < MIN_DISTANCE || ds > MAX_DISTANCE) { 126 | break; 127 | } 128 | } 129 | result.isHit = abs(dt) < MIN_DISTANCE; 130 | result.distanceTo = ds; 131 | result.material = dist.material; 132 | result.planeHeight = dist.planeHeight; 133 | result.planeNormal = dist.planeNormal; 134 | return result; 135 | } 136 | 137 | float getLightDiffuse(vec3 p, float material, float height, vec3 normal) { 138 | vec3 l = normalize(lightPos - p); 139 | float dif = clamp(dot(normal, l), 0., 1.); 140 | return dif; 141 | } 142 | 143 | vec3 starsLayer(vec2 ouv) { 144 | vec3 col = vec3(0.); 145 | 146 | vec2 uv = fract(ouv) - .5; 147 | 148 | float d; 149 | 150 | for(int x = -1 ; x <= 1; x++) { 151 | for(int y = -1 ; y <= 1; y++) { 152 | vec2 offset = vec2(x,y); 153 | vec2 id = floor(ouv) + offset; 154 | float n = N21(id); 155 | if (n > .6) { 156 | float n1 = fract(n*123.432); 157 | float n2 = fract(n*1234.2432); 158 | 159 | float size = .01 + 0.05 * (n1 - .5); 160 | 161 | vec2 shift = vec2(n1 - .5, n2 - .5); 162 | d = max(d, size/length(uv - offset + shift)); 163 | } 164 | } 165 | } 166 | 167 | 168 | return col + d*vec3(.1, .9, .1); 169 | } 170 | 171 | vec3 backgroundStars(vec2 uv) { 172 | vec3 col = vec3(0.); 173 | 174 | float t = iTime * (speed / 30.); 175 | 176 | float layers = 3.; 177 | 178 | for(float i = 0. ; i < 1. ; i+= 1./layers) { 179 | float depth = fract(i + t); 180 | float scale = mix(20., .5, depth); 181 | float fade = depth * smoothstep(1., .9, depth); 182 | 183 | col += starsLayer(uv * scale + i * 456.32) * fade; 184 | } 185 | return col; 186 | } 187 | 188 | vec3 getOthersideBackground(vec2 uv) { 189 | return backgroundStars(uv/8. + sin(iTime/(speed))); 190 | } 191 | 192 | vec3 getBackground(vec2 uv) { 193 | float set = 0. - clamp(sin(iTime/SUNSET_SPEED)*3., -1., 2.); 194 | 195 | float sunDist = length(uv + vec2(0., -2.5 - set)); 196 | float sun = 1. - smoothstep(2.35, 2.5, sunDist); 197 | 198 | float gradient = sin(uv.y/4. - 3.14/32. + set/3.)*2.; 199 | float bands = abs(sin(uv.y * 8. + iTime*2.)) * (1. - step(2.5 + set, uv.y)); 200 | 201 | float skyTop = 2.12/distance(uv, vec2(uv.x, 9.5)); 202 | float skyBottom = 1.12/distance(uv, vec2(uv.x, -1.5)); 203 | 204 | vec3 result; 205 | 206 | // sun 207 | 208 | if (set < -1.8) { 209 | result = vec3(sun) * (bands > 0. ? bands : 1.) * mix(vec3(0.), COLOR_NIGHT_SUN, ((abs(set) - 1.6) -.2) * 15.); 210 | float glow = smoothstep(.1, .5, (1.1)/sunDist); 211 | result += glow * COLOR_NIGHT_SUN; 212 | } else { 213 | result = vec3(sun * gradient * (bands > 0. ? bands : 1.)) * COLOR_SUN; 214 | //glow 215 | float glow = smoothstep(.1, .5, (1.1)/sunDist) + clamp(-1., 1., set); 216 | // result += glow * COLOR_PURPLE; 217 | 218 | // sky 219 | result += max(glow * COLOR_PURPLE, ((skyTop * MOUNTAIN_COLOR) + (skyBottom * COLOR_PURPLE))*(1. + set)); 220 | } 221 | 222 | 223 | 224 | if (sun < .5) { 225 | // stars 226 | vec2 nuv = uv*2.;// + vec2(iTime, 0.); 227 | vec2 rize = vec2(-10., 12.); 228 | nuv -= rize; 229 | nuv *= rot2d(mod(-iTime/15., 6.28)); 230 | nuv += rize; 231 | uv = fract(nuv); 232 | vec2 id = floor(nuv); 233 | uv -= .5; 234 | 235 | float n = N21(id); 236 | uv.x += fract(n*100.32) - .5; 237 | uv.y += fract(n*11323.432) - .5; 238 | 239 | float star = smoothstep(.5, 1., (0.03 + (0.02 * (fract(n*353.32) - .5)))/length(uv)); 240 | 241 | result += star * step(.8, n); 242 | } 243 | 244 | return result; 245 | } 246 | float filterWidth2(vec2 uv) 247 | { 248 | vec2 dx = dFdx(uv), dy = dFdy(uv); 249 | return dot(dx, dx) + dot(dy, dy) + .0001; 250 | } 251 | 252 | // (c) spalmer https://www.shadertoy.com/view/wl3Sz2 253 | float gridPow(vec2 uv) 254 | { 255 | vec2 p = uv * GRID_SIZE + vec2(0., iTime * speed); 256 | const float fadePower = 16.; 257 | vec2 f = fract(p); 258 | f = .5 - abs(.5 - f); 259 | f = max(vec2(0), 1. - f + .5*GRID_THICKNESS); 260 | f = pow(f, vec2(fadePower)); 261 | float g = f.x+f.y; //max(f.x, f.y); // 262 | float s = sqrt(GRID_THICKNESS); 263 | return mix(g, s, exp2(-.01 / filterWidth2(p))); 264 | } 265 | 266 | vec3 getAlbedo(vec3 p, float material, float height, vec3 normal) { 267 | if (material == MATERIAL_BACK) { 268 | return getBackground(p.xy); 269 | } 270 | 271 | float sunSet = sin(iTime/SUNSET_SPEED)*.5 + .5; 272 | 273 | vec3 col = vec3(0.); 274 | float grid = gridPow(p.xz); 275 | 276 | float maxHeight = 2.5; 277 | 278 | vec3 grid_color = COLOR_PURPLE; 279 | vec3 cell_color = vec3(0.); 280 | vec3 mountain_color = MOUNTAIN_COLOR; 281 | mountain_color = mix(mountain_color, COLOR_NIGHT_MOUNTAIN, sunSet); 282 | 283 | 284 | 285 | if (height > 0.) { 286 | grid_color = mix(COLOR_PURPLE, COLOR_LIGHT, height/maxHeight); 287 | cell_color = mountain_color * mix(vec3(0.), mountain_color, height/maxHeight); 288 | } 289 | 290 | grid_color = mix(grid_color, COLOR_NIGHT_GRID, sunSet); 291 | 292 | col = mix(vec3(0.), grid_color, grid) + cell_color; 293 | 294 | return vec3(col); 295 | } 296 | 297 | float polarTriangle(vec2 uv, float offset) { 298 | float a = atan(uv.x, uv.y) + offset; 299 | float b = 6.28 / 3.; 300 | float l = length(uv); 301 | 302 | float d = cos(a - floor(.5 + a/b) * b) * l; 303 | 304 | return d; 305 | } 306 | 307 | float triangleMask(vec2 uv) { 308 | return polarTriangle(uv + vec2(0., -.1),3.14 + .5*sin(iTime)); 309 | } 310 | 311 | 312 | void mainImage(out vec4 fragColor, in vec2 fragCoords) { 313 | vec2 uv = fragCoords.xy / iResolution.xy; 314 | uv -= .5; 315 | uv.x *= iResolution.x / iResolution.y; 316 | 317 | vec2 mouse = iMouse.xy / iResolution.xy; 318 | 319 | // lightPos.z = sin(iTime/3.)*100.; 320 | 321 | mouse.x = 0.5; 322 | mouse.y = 0.; 323 | 324 | vec3 col = vec3(0.); 325 | 326 | vec3 ro = vec3(0., .5, -.4); 327 | vec3 lookat = vec3(mouse.x*2.-1., 1. - mouse.y - .6, 0.); 328 | float zoom = .4; 329 | 330 | 331 | vec3 f = normalize(lookat - ro); 332 | vec3 r = normalize(cross(vec3(0., 1., 0), f)); 333 | vec3 u = cross(f, r); 334 | vec3 c = ro + f * zoom; 335 | vec3 i = c + uv.x * r + uv.y * u; 336 | 337 | vec3 rd = normalize(i - ro); 338 | 339 | vec3 p = vec3(0.); 340 | 341 | traceResult tr = trace(ro, rd); 342 | 343 | if (tr.isHit) { 344 | 345 | p = ro + rd * tr.distanceTo; 346 | 347 | vec3 albedo = getAlbedo(p, tr.material, tr.planeHeight, tr.planeNormal); 348 | 349 | float diffuse = getLightDiffuse(p, tr.material, tr.planeHeight, tr.planeNormal); 350 | 351 | float fade = 1.;// - clamp((p.z-ro.z)/(MAX_DISTANCE * .8), 0., 1.); 352 | 353 | if (tr.material == MATERIAL_BACK) { 354 | col = albedo; 355 | } else { 356 | col = diffuse * albedo * fade; 357 | } 358 | 359 | float triangle = triangleMask(uv); 360 | float fd = fract(triangle - clamp(sin(iTime/3.), 0., 2.)); 361 | float bc = (1. - step(.2, fd)); 362 | 363 | col *= (tr.material == MATERIAL_BACK) ? bc : 1.; 364 | if (bc == 0.) { 365 | if (tr.material == MATERIAL_BACK) { 366 | col = getOthersideBackground(p.xy); 367 | } else { 368 | col *= vec3(.8); 369 | } 370 | } 371 | 372 | col += ((1. - step(.2, fd)) - (1. - step(.19, fd)))*.3; 373 | 374 | } 375 | 376 | 377 | fragColor = vec4(col, 1.); 378 | // fragColor.rgb = pow(fragColor.rgb, vec3(1.0/2.2)); 379 | } 380 | --------------------------------------------------------------------------------