new shaders
This commit is contained in:
parent
938fdd5ad6
commit
696a9ba9b3
@ -84,6 +84,8 @@ function App() {
|
||||
<option value="blackhole">Blackhole Theme</option>
|
||||
<option value="star">Star Theme</option>
|
||||
<option value="ball">Universe Ball Theme</option>
|
||||
<option value="reflect">Ball Cage Theme</option>
|
||||
<option value="clouds">Clouds Theme</option>
|
||||
</select>
|
||||
</div>
|
||||
{isShaderTheme && <ShaderBackground theme= {theme} />}
|
||||
|
||||
@ -3,6 +3,8 @@ import { useEffect, useRef } from "react";
|
||||
import BLACKHOLE_SHADER_CODE from "./assets/blackhole.glsl?raw";
|
||||
import STAR_SHADER_CODE from "./assets/star.glsl?raw";
|
||||
import BALL_SHADER_CODE from "./assets/ball.glsl?raw";
|
||||
import REFLECT_BALL_SHADER_CODE from "./assets/reflect.glsl?raw";
|
||||
import CLOUDS_SHADER_CODE from "./assets/clouds.glsl?raw";
|
||||
|
||||
function buildProgram(
|
||||
ctx: WebGL2RenderingContext,
|
||||
@ -145,6 +147,12 @@ export const ShaderBackground: React.FC<ShaderBackgroundProps> = ({
|
||||
case "ball":
|
||||
shader_code = BALL_SHADER_CODE;
|
||||
break;
|
||||
case "reflect":
|
||||
shader_code = REFLECT_BALL_SHADER_CODE;
|
||||
break;
|
||||
case "clouds":
|
||||
shader_code = CLOUDS_SHADER_CODE;
|
||||
break;
|
||||
default:
|
||||
console.error("Unknown shader theme:", theme);
|
||||
return;
|
||||
|
||||
62
frontend/src/assets/clouds.glsl
Normal file
62
frontend/src/assets/clouds.glsl
Normal file
@ -0,0 +1,62 @@
|
||||
#version 300 es
|
||||
precision highp float;
|
||||
uniform vec3 iResolution;
|
||||
uniform float iTime;
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
#define T (iTime)
|
||||
|
||||
float orb(vec3 p) {
|
||||
// orb time
|
||||
float t = T * 4.;
|
||||
return length(p - vec3(sin(sin(t * .2) + t * .4) * 6., 1. + sin(sin(t * .5) + t * .2) * 4., 12. + T + cos(t * .3) * 8.));
|
||||
}
|
||||
|
||||
void mainImage(out vec4 o, vec2 u) {
|
||||
float d, a, e, i, s, t = T;
|
||||
vec3 p = iResolution;
|
||||
|
||||
// scale coords
|
||||
u = (u + u - p.xy) / p.y;
|
||||
|
||||
// camera movement
|
||||
u += vec2(cos(t * .1) * .3, cos(t * .3) * .1);
|
||||
|
||||
for(o *= i; i++ < 128.;
|
||||
|
||||
// accumulate distance
|
||||
d += s = min(.03 + .2 * abs(s), e = max(.5 * e, .01)),
|
||||
|
||||
// grayscale color and orb light
|
||||
o += 1. / (s + e * 3.))
|
||||
|
||||
// noise loop start, march
|
||||
for(p = vec3(u * d, d + t), // p = ro + rd *d, p.z + t;
|
||||
|
||||
// entity (orb)
|
||||
e = orb(p) - .1,
|
||||
|
||||
// spin by t, twist by p.z
|
||||
p.xy *= mat2(cos(.1 * t + p.z / 8. + vec4(0, 33, 11, 0))),
|
||||
|
||||
// mirrored planes 4 units apart
|
||||
s = 4. - abs(p.y),
|
||||
|
||||
// noise starts at .8 up to 32., grow by a+=a
|
||||
a = .8; a < 32.; a += a)
|
||||
|
||||
// apply turbulence
|
||||
p += cos(.7 * t + p.yzx) * .2,
|
||||
|
||||
// apply noise
|
||||
s -= abs(dot(sin(.1 * t + p * a), .6 + p - p)) / a;
|
||||
|
||||
// tanh tonemap, brightness, light off-screen
|
||||
o = tanh(o / 1e1);
|
||||
}
|
||||
|
||||
|
||||
void main() {
|
||||
mainImage(FragColor, gl_FragCoord.xy);
|
||||
}
|
||||
375
frontend/src/assets/reflect.glsl
Normal file
375
frontend/src/assets/reflect.glsl
Normal file
@ -0,0 +1,375 @@
|
||||
#version 300 es
|
||||
precision highp float;
|
||||
uniform vec3 iResolution;
|
||||
uniform float iTime;
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
// CC0: Let's self reflect
|
||||
// Always enjoyed the videos of Platonic solids with inner mirrors
|
||||
// I made some previous attempts but thought I make another attempt it
|
||||
|
||||
// Reducing the alias effects on the inner reflections turned out to be a bit tricky.
|
||||
// Simplest solution is just to run run fullscreen on a 4K screen ;)
|
||||
|
||||
// Function to generate the solid found here: https://www.shadertoy.com/view/MsKGzw
|
||||
|
||||
// Tinker with these parameters to create different solids
|
||||
// -------------------------------------------------------
|
||||
const float rotation_speed = 0.25f;
|
||||
|
||||
const float poly_U = 1.f; // [0, inf]
|
||||
const float poly_V = 0.5f; // [0, inf]
|
||||
const float poly_W = 1.0f; // [0, inf]
|
||||
const int poly_type = 5; // [2, 5]
|
||||
const float poly_zoom = 2.5f;
|
||||
|
||||
const float inner_sphere = 1.f;
|
||||
|
||||
const float refr_index = 0.9f;
|
||||
|
||||
#define MAX_BOUNCES2 6
|
||||
// -------------------------------------------------------
|
||||
|
||||
#define TIME iTime
|
||||
#define RESOLUTION iResolution
|
||||
#define PI 3.141592654
|
||||
#define TAU (2.0*PI)
|
||||
|
||||
// License: WTFPL, author: sam hocevar, found: https://stackoverflow.com/a/17897228/418488
|
||||
const vec4 hsv2rgb_K = vec4(1.0f, 2.0f / 3.0f, 1.0f / 3.0f, 3.0f);
|
||||
vec3 hsv2rgb(vec3 c) {
|
||||
vec3 p = abs(fract(c.xxx + hsv2rgb_K.xyz) * 6.0f - hsv2rgb_K.www);
|
||||
return c.z * mix(hsv2rgb_K.xxx, clamp(p - hsv2rgb_K.xxx, 0.0f, 1.0f), c.y);
|
||||
}
|
||||
// License: WTFPL, author: sam hocevar, found: https://stackoverflow.com/a/17897228/418488
|
||||
// Macro version of above to enable compile-time constants
|
||||
#define HSV2RGB(c) (c.z * mix(hsv2rgb_K.xxx, clamp(abs(fract(c.xxx + hsv2rgb_K.xyz) * 6.0 - hsv2rgb_K.www) - hsv2rgb_K.xxx, 0.0, 1.0), c.y))
|
||||
|
||||
#define TOLERANCE2 0.0005
|
||||
//#define MAX_RAY_LENGTH2 10.0
|
||||
#define MAX_RAY_MARCHES2 50
|
||||
#define NORM_OFF2 0.005
|
||||
#define BACKSTEP2
|
||||
|
||||
#define TOLERANCE3 0.0005
|
||||
#define MAX_RAY_LENGTH3 10.0
|
||||
#define MAX_RAY_MARCHES3 90
|
||||
#define NORM_OFF3 0.005
|
||||
|
||||
const vec3 rayOrigin = vec3(0.0f, 1.f, -5.f);
|
||||
const vec3 sunDir = normalize(-rayOrigin);
|
||||
|
||||
const vec3 sunCol = HSV2RGB(vec3(0.06f, 0.90f, 1E-2f)) * 1.f;
|
||||
const vec3 bottomBoxCol = HSV2RGB(vec3(0.66f, 0.80f, 0.5f)) * 1.f;
|
||||
const vec3 topBoxCol = HSV2RGB(vec3(0.60f, 0.90f, 1.f)) * 1.f;
|
||||
const vec3 glowCol0 = HSV2RGB(vec3(0.05f, 0.7f, 1E-3f)) * 1.f;
|
||||
const vec3 glowCol1 = HSV2RGB(vec3(0.95f, 0.7f, 1E-3f)) * 1.f;
|
||||
const vec3 beerCol = -HSV2RGB(vec3(0.15f + 0.5f, 0.7f, 2.f));
|
||||
const float rrefr_index = 1.f / refr_index;
|
||||
|
||||
// License: Unknown, author: knighty, found: https://www.shadertoy.com/view/MsKGzw
|
||||
const float poly_cospin = cos(PI / float(poly_type));
|
||||
const float poly_scospin = sqrt(0.75f - poly_cospin * poly_cospin);
|
||||
const vec3 poly_nc = vec3(-0.5f, -poly_cospin, poly_scospin);
|
||||
const vec3 poly_pab = vec3(0.f, 0.f, 1.f);
|
||||
const vec3 poly_pbc_ = vec3(poly_scospin, 0.f, 0.5f);
|
||||
const vec3 poly_pca_ = vec3(0.f, poly_scospin, poly_cospin);
|
||||
const vec3 poly_p = normalize((poly_U * poly_pab + poly_V * poly_pbc_ + poly_W * poly_pca_));
|
||||
const vec3 poly_pbc = normalize(poly_pbc_);
|
||||
const vec3 poly_pca = normalize(poly_pca_);
|
||||
|
||||
mat3 g_rot;
|
||||
vec2 g_gd;
|
||||
|
||||
// License: MIT, author: Inigo Quilez, found: https://iquilezles.org/articles/noacos/
|
||||
mat3 rot(vec3 d, vec3 z) {
|
||||
vec3 v = cross(z, d);
|
||||
float c = dot(z, d);
|
||||
float k = 1.0f / (1.0f + c);
|
||||
|
||||
return mat3(v.x * v.x * k + c, v.y * v.x * k - v.z, v.z * v.x * k + v.y, v.x * v.y * k + v.z, v.y * v.y * k + c, v.z * v.y * k - v.x, v.x * v.z * k - v.y, v.y * v.z * k + v.x, v.z * v.z * k + c);
|
||||
}
|
||||
|
||||
// License: Unknown, author: Matt Taylor (https://github.com/64), found: https://64.github.io/tonemapping/
|
||||
vec3 aces_approx(vec3 v) {
|
||||
v = max(v, 0.0f);
|
||||
v *= 0.6f;
|
||||
float a = 2.51f;
|
||||
float b = 0.03f;
|
||||
float c = 2.43f;
|
||||
float d = 0.59f;
|
||||
float e = 0.14f;
|
||||
return clamp((v * (a * v + b)) / (v * (c * v + d) + e), 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
float sphere(vec3 p, float r) {
|
||||
return length(p) - r;
|
||||
}
|
||||
|
||||
// License: MIT, author: Inigo Quilez, found: https://iquilezles.org/articles/distfunctions/
|
||||
float box(vec2 p, vec2 b) {
|
||||
vec2 d = abs(p) - b;
|
||||
return length(max(d, 0.0f)) + min(max(d.x, d.y), 0.0f);
|
||||
}
|
||||
|
||||
// License: Unknown, author: knighty, found: https://www.shadertoy.com/view/MsKGzw
|
||||
void poly_fold(inout vec3 pos) {
|
||||
vec3 p = pos;
|
||||
|
||||
for(int i = 0; i < poly_type; ++i) {
|
||||
p.xy = abs(p.xy);
|
||||
p -= 2.f * min(0.f, dot(p, poly_nc)) * poly_nc;
|
||||
}
|
||||
|
||||
pos = p;
|
||||
}
|
||||
|
||||
float poly_plane(vec3 pos) {
|
||||
float d0 = dot(pos, poly_pab);
|
||||
float d1 = dot(pos, poly_pbc);
|
||||
float d2 = dot(pos, poly_pca);
|
||||
float d = d0;
|
||||
d = max(d, d1);
|
||||
d = max(d, d2);
|
||||
return d;
|
||||
}
|
||||
|
||||
float poly_corner(vec3 pos) {
|
||||
float d = length(pos) - .0125f;
|
||||
return d;
|
||||
}
|
||||
|
||||
float dot2(vec3 p) {
|
||||
return dot(p, p);
|
||||
}
|
||||
|
||||
float poly_edge(vec3 pos) {
|
||||
float dla = dot2(pos - min(0.f, pos.x) * vec3(1.f, 0.f, 0.f));
|
||||
float dlb = dot2(pos - min(0.f, pos.y) * vec3(0.f, 1.f, 0.f));
|
||||
float dlc = dot2(pos - min(0.f, dot(pos, poly_nc)) * poly_nc);
|
||||
return sqrt(min(min(dla, dlb), dlc)) - 2E-3f;
|
||||
}
|
||||
|
||||
vec3 shape(vec3 pos) {
|
||||
pos *= g_rot;
|
||||
pos /= poly_zoom;
|
||||
poly_fold(pos);
|
||||
pos -= poly_p;
|
||||
|
||||
return vec3(poly_plane(pos), poly_edge(pos), poly_corner(pos)) * poly_zoom;
|
||||
}
|
||||
|
||||
vec3 render0(vec3 ro, vec3 rd) {
|
||||
vec3 col = vec3(0.0f);
|
||||
|
||||
float srd = sign(rd.y);
|
||||
float tp = -(ro.y - 6.f) / abs(rd.y);
|
||||
|
||||
if(srd < 0.f) {
|
||||
col += bottomBoxCol * exp(-0.5f * (length((ro + tp * rd).xz)));
|
||||
}
|
||||
|
||||
if(srd > 0.0f) {
|
||||
vec3 pos = ro + tp * rd;
|
||||
vec2 pp = pos.xz;
|
||||
float db = box(pp, vec2(5.0f, 9.0f)) - 3.0f;
|
||||
|
||||
col += topBoxCol * rd.y * rd.y * smoothstep(0.25f, 0.0f, db);
|
||||
col += 0.2f * topBoxCol * exp(-0.5f * max(db, 0.0f));
|
||||
col += 0.05f * sqrt(topBoxCol) * max(-db, 0.0f);
|
||||
}
|
||||
|
||||
col += sunCol / (1.001f - dot(sunDir, rd));
|
||||
return col;
|
||||
}
|
||||
|
||||
float df2(vec3 p) {
|
||||
vec3 ds = shape(p);
|
||||
float d2 = ds.y - 5E-3f;
|
||||
float d0 = min(-ds.x, d2);
|
||||
float d1 = sphere(p, inner_sphere);
|
||||
g_gd = min(g_gd, vec2(d2, d1));
|
||||
float d = (min(d0, d1));
|
||||
return d;
|
||||
}
|
||||
|
||||
float rayMarch2(vec3 ro, vec3 rd, float tinit) {
|
||||
float t = tinit;
|
||||
#if defined(BACKSTEP2)
|
||||
vec2 dti = vec2(1e10f, 0.0f);
|
||||
#endif
|
||||
int i;
|
||||
for(i = 0; i < MAX_RAY_MARCHES2; ++i) {
|
||||
float d = df2(ro + rd * t);
|
||||
#if defined(BACKSTEP2)
|
||||
if(d < dti.x) {
|
||||
dti = vec2(d, t);
|
||||
}
|
||||
#endif
|
||||
// Bouncing in a closed shell, will never miss
|
||||
if(d < TOLERANCE2/* || t > MAX_RAY_LENGTH3 */) {
|
||||
break;
|
||||
}
|
||||
t += d;
|
||||
}
|
||||
#if defined(BACKSTEP2)
|
||||
if(i == MAX_RAY_MARCHES2) {
|
||||
t = dti.y;
|
||||
};
|
||||
#endif
|
||||
return t;
|
||||
}
|
||||
|
||||
vec3 normal2(vec3 pos) {
|
||||
vec2 eps = vec2(NORM_OFF2, 0.0f);
|
||||
vec3 nor;
|
||||
nor.x = df2(pos + eps.xyy) - df2(pos - eps.xyy);
|
||||
nor.y = df2(pos + eps.yxy) - df2(pos - eps.yxy);
|
||||
nor.z = df2(pos + eps.yyx) - df2(pos - eps.yyx);
|
||||
return normalize(nor);
|
||||
}
|
||||
|
||||
vec3 render2(vec3 ro, vec3 rd, float db) {
|
||||
vec3 agg = vec3(0.0f);
|
||||
float ragg = 1.f;
|
||||
float tagg = 0.f;
|
||||
|
||||
for(int bounce = 0; bounce < MAX_BOUNCES2; ++bounce) {
|
||||
if(ragg < 0.1f)
|
||||
break;
|
||||
g_gd = vec2(1E3f);
|
||||
float t2 = rayMarch2(ro, rd, min(db + 0.05f, 0.3f));
|
||||
vec2 gd2 = g_gd;
|
||||
tagg += t2;
|
||||
|
||||
vec3 p2 = ro + rd * t2;
|
||||
vec3 n2 = normal2(p2);
|
||||
vec3 r2 = reflect(rd, n2);
|
||||
vec3 rr2 = refract(rd, n2, rrefr_index);
|
||||
float fre2 = 1.f + dot(n2, rd);
|
||||
|
||||
vec3 beer = ragg * exp(0.2f * beerCol * tagg);
|
||||
agg += glowCol1 * beer * ((1.f + tagg * tagg * 4E-2f) * 6.f / max(gd2.x, 5E-4f + tagg * tagg * 2E-4f / ragg));
|
||||
vec3 ocol = 0.2f * beer * render0(p2, rr2);
|
||||
if(gd2.y <= TOLERANCE2) {
|
||||
ragg *= 1.f - 0.9f * fre2;
|
||||
} else {
|
||||
agg += ocol;
|
||||
ragg *= 0.8f;
|
||||
}
|
||||
|
||||
ro = p2;
|
||||
rd = r2;
|
||||
db = gd2.x;
|
||||
}
|
||||
|
||||
return agg;
|
||||
}
|
||||
|
||||
float df3(vec3 p) {
|
||||
vec3 ds = shape(p);
|
||||
g_gd = min(g_gd, ds.yz);
|
||||
const float sw = 0.02f;
|
||||
float d1 = min(ds.y, ds.z) - sw;
|
||||
float d0 = ds.x;
|
||||
d0 = min(d0, ds.y);
|
||||
d0 = min(d0, ds.z);
|
||||
return d0;
|
||||
}
|
||||
|
||||
float rayMarch3(vec3 ro, vec3 rd, float tinit, out int iter) {
|
||||
float t = tinit;
|
||||
int i;
|
||||
for(i = 0; i < MAX_RAY_MARCHES3; ++i) {
|
||||
float d = df3(ro + rd * t);
|
||||
if(d < TOLERANCE3 || t > MAX_RAY_LENGTH3) {
|
||||
break;
|
||||
}
|
||||
t += d;
|
||||
}
|
||||
iter = i;
|
||||
return t;
|
||||
}
|
||||
|
||||
vec3 normal3(vec3 pos) {
|
||||
vec2 eps = vec2(NORM_OFF3, 0.0f);
|
||||
vec3 nor;
|
||||
nor.x = df3(pos + eps.xyy) - df3(pos - eps.xyy);
|
||||
nor.y = df3(pos + eps.yxy) - df3(pos - eps.yxy);
|
||||
nor.z = df3(pos + eps.yyx) - df3(pos - eps.yyx);
|
||||
return normalize(nor);
|
||||
}
|
||||
|
||||
vec3 render3(vec3 ro, vec3 rd) {
|
||||
int iter;
|
||||
|
||||
vec3 skyCol = render0(ro, rd);
|
||||
vec3 col = skyCol;
|
||||
|
||||
g_gd = vec2(1E3f);
|
||||
float t1 = rayMarch3(ro, rd, 0.1f, iter);
|
||||
vec2 gd1 = g_gd;
|
||||
vec3 p1 = ro + t1 * rd;
|
||||
vec3 n1 = normal3(p1);
|
||||
vec3 r1 = reflect(rd, n1);
|
||||
vec3 rr1 = refract(rd, n1, refr_index);
|
||||
float fre1 = 1.f + dot(rd, n1);
|
||||
fre1 *= fre1;
|
||||
|
||||
float ifo = mix(0.5f, 1.f, smoothstep(1.0f, 0.9f, float(iter) / float(MAX_RAY_MARCHES3)));
|
||||
|
||||
if(t1 < MAX_RAY_LENGTH3) {
|
||||
col = render0(p1, r1) * (0.5f + 0.5f * fre1) * ifo;
|
||||
vec3 icol = render2(p1, rr1, gd1.x);
|
||||
if(gd1.x > TOLERANCE3 && gd1.y > TOLERANCE3 && rr1 != vec3(0.f)) {
|
||||
col += icol * (1.f - 0.75f * fre1) * ifo;
|
||||
}
|
||||
}
|
||||
|
||||
col += (glowCol0 + 1.f * fre1 * (glowCol0)) / max(gd1.x, 3E-4f);
|
||||
return col;
|
||||
|
||||
}
|
||||
|
||||
vec3 effect(vec2 p, vec2 pp) {
|
||||
const float fov = 2.0f;
|
||||
|
||||
const vec3 up = vec3(0.f, 1.f, 0.f);
|
||||
const vec3 la = vec3(0.0f);
|
||||
|
||||
const vec3 ww = normalize(normalize(la - rayOrigin));
|
||||
const vec3 uu = normalize(cross(up, ww));
|
||||
const vec3 vv = cross(ww, uu);
|
||||
|
||||
vec3 rd = normalize(-p.x * uu + p.y * vv + fov * ww);
|
||||
|
||||
vec3 col = vec3(0.0f);
|
||||
col = render3(rayOrigin, rd);
|
||||
|
||||
col -= 2E-2f * vec3(2.f, 3.f, 1.f) * (length(p) + 0.25f);
|
||||
col = aces_approx(col);
|
||||
col = sqrt(col);
|
||||
return col;
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
||||
vec2 q = fragCoord / RESOLUTION.xy;
|
||||
vec2 p = -1.f + 2.f * q;
|
||||
vec2 pp = p;
|
||||
p.x *= RESOLUTION.x / RESOLUTION.y;
|
||||
|
||||
float a = TIME * rotation_speed;
|
||||
vec3 r0 = vec3(1.0f, sin(vec2(sqrt(0.5f), 1.0f) * a));
|
||||
vec3 r1 = vec3(cos(vec2(sqrt(0.5f), 1.0f) * 0.913f * a), 1.0f);
|
||||
mat3 rot = rot(normalize(r0), normalize(r1));
|
||||
g_rot = rot;
|
||||
|
||||
vec3 col = effect(p, pp);
|
||||
|
||||
fragColor = vec4(col, 1.0f);
|
||||
}
|
||||
|
||||
void main() {
|
||||
mainImage(FragColor, gl_FragCoord.xy);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user