init
This commit is contained in:
commit
3fa75abfb2
42 changed files with 5634 additions and 0 deletions
40
ghostty-shaders/animated-gradient-shader.glsl
Normal file
40
ghostty-shaders/animated-gradient-shader.glsl
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
// credits: https://github.com/unkn0wncode
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord)
|
||||
{
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
|
||||
// Create seamless gradient animation
|
||||
float speed = 0.2;
|
||||
float gradientFactor = (uv.x + uv.y) / 2.0;
|
||||
|
||||
// Use smoothstep and multiple sin waves for smoother transition
|
||||
float t = sin(iTime * speed) * 0.5 + 0.5;
|
||||
gradientFactor = smoothstep(0.0, 1.0, gradientFactor);
|
||||
|
||||
// Create smooth circular animation
|
||||
float angle = iTime * speed;
|
||||
vec3 color1 = vec3(0.1, 0.1, 0.5);
|
||||
vec3 color2 = vec3(0.5, 0.1, 0.1);
|
||||
vec3 color3 = vec3(0.1, 0.5, 0.1);
|
||||
|
||||
// Smooth interpolation between colors using multiple mix operations
|
||||
vec3 gradientStartColor = mix(
|
||||
mix(color1, color2, smoothstep(0.0, 1.0, sin(angle) * 0.5 + 0.5)),
|
||||
color3,
|
||||
smoothstep(0.0, 1.0, sin(angle + 2.0) * 0.5 + 0.5)
|
||||
);
|
||||
|
||||
vec3 gradientEndColor = mix(
|
||||
mix(color2, color3, smoothstep(0.0, 1.0, sin(angle + 1.0) * 0.5 + 0.5)),
|
||||
color1,
|
||||
smoothstep(0.0, 1.0, sin(angle + 3.0) * 0.5 + 0.5)
|
||||
);
|
||||
|
||||
vec3 gradientColor = mix(gradientStartColor, gradientEndColor, gradientFactor);
|
||||
|
||||
vec4 terminalColor = texture(iChannel0, uv);
|
||||
float mask = 1.0 - step(0.5, dot(terminalColor.rgb, vec3(1.0)));
|
||||
vec3 blendedColor = mix(terminalColor.rgb, gradientColor, mask);
|
||||
|
||||
fragColor = vec4(blendedColor, terminalColor.a);
|
||||
}
|
||||
33
ghostty-shaders/bettercrt.glsl
Normal file
33
ghostty-shaders/bettercrt.glsl
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// Original shader collected from: https://www.shadertoy.com/view/WsVSzV
|
||||
// Licensed under Shadertoy's default since the original creator didn't provide any license. (CC BY NC SA 3.0)
|
||||
// Slight modifications were made to give a green-ish effect.
|
||||
|
||||
// This shader was modified by April Hall (arithefirst)
|
||||
// Sourced from https://github.com/m-ahdal/ghostty-shaders/blob/main/retro-terminal.glsl
|
||||
// Changes made:
|
||||
// - Removed tint
|
||||
// - Made the boundaries match ghostty's background color
|
||||
|
||||
float warp = 0.25; // simulate curvature of CRT monitor
|
||||
float scan = 0.50; // simulate darkness between scanlines
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord)
|
||||
{
|
||||
// squared distance from center
|
||||
vec2 uv = fragCoord / iResolution.xy;
|
||||
vec2 dc = abs(0.5 - uv);
|
||||
dc *= dc;
|
||||
|
||||
// warp the fragment coordinates
|
||||
uv.x -= 0.5; uv.x *= 1.0 + (dc.y * (0.3 * warp)); uv.x += 0.5;
|
||||
uv.y -= 0.5; uv.y *= 1.0 + (dc.x * (0.4 * warp)); uv.y += 0.5;
|
||||
|
||||
// determine if we are drawing in a scanline
|
||||
float apply = abs(sin(fragCoord.y) * 0.25 * scan);
|
||||
|
||||
// sample the texture
|
||||
vec3 color = texture(iChannel0, uv).rgb;
|
||||
|
||||
// mix the sampled color with the scanline intensity
|
||||
fragColor = vec4(mix(color, vec3(0.0), apply), 1.0);
|
||||
}
|
||||
52
ghostty-shaders/bloom.glsl
Normal file
52
ghostty-shaders/bloom.glsl
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
// source: https://gist.github.com/qwerasd205/c3da6c610c8ffe17d6d2d3cc7068f17f
|
||||
// credits: https://github.com/qwerasd205
|
||||
// Golden spiral samples, [x, y, weight] weight is inverse of distance.
|
||||
const vec3[24] samples = {
|
||||
vec3(0.1693761725038636, 0.9855514761735895, 1),
|
||||
vec3(-1.333070830962943, 0.4721463328627773, 0.7071067811865475),
|
||||
vec3(-0.8464394909806497, -1.51113870578065, 0.5773502691896258),
|
||||
vec3(1.554155680728463, -1.2588090085709776, 0.5),
|
||||
vec3(1.681364377589461, 1.4741145918052656, 0.4472135954999579),
|
||||
vec3(-1.2795157692199817, 2.088741103228784, 0.4082482904638631),
|
||||
vec3(-2.4575847530631187, -0.9799373355024756, 0.3779644730092272),
|
||||
vec3(0.5874641440200847, -2.7667464429345077, 0.35355339059327373),
|
||||
vec3(2.997715703369726, 0.11704939884745152, 0.3333333333333333),
|
||||
vec3(0.41360842451688395, 3.1351121305574803, 0.31622776601683794),
|
||||
vec3(-3.167149933769243, 0.9844599011770256, 0.30151134457776363),
|
||||
vec3(-1.5736713846521535, -3.0860263079123245, 0.2886751345948129),
|
||||
vec3(2.888202648340422, -2.1583061557896213, 0.2773500981126146),
|
||||
vec3(2.7150778983300325, 2.5745586041105715, 0.2672612419124244),
|
||||
vec3(-2.1504069972377464, 3.2211410627650165, 0.2581988897471611),
|
||||
vec3(-3.6548858794907493, -1.6253643308191343, 0.25),
|
||||
vec3(1.0130775986052671, -3.9967078676335834, 0.24253562503633297),
|
||||
vec3(4.229723673607257, 0.33081361055181563, 0.23570226039551587),
|
||||
vec3(0.40107790291173834, 4.340407413572593, 0.22941573387056174),
|
||||
vec3(-4.319124570236028, 1.159811599693438, 0.22360679774997896),
|
||||
vec3(-1.9209044802827355, -4.160543952132907, 0.2182178902359924),
|
||||
vec3(3.8639122286635708, -2.6589814382925123, 0.21320071635561041),
|
||||
vec3(3.3486228404946234, 3.4331800232609, 0.20851441405707477),
|
||||
vec3(-2.8769733643574344, 3.9652268864187157, 0.20412414523193154)
|
||||
};
|
||||
|
||||
float lum(vec4 c) {
|
||||
return 0.299 * c.r + 0.587 * c.g + 0.114 * c.b;
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
|
||||
vec4 color = texture(iChannel0, uv);
|
||||
|
||||
vec2 step = vec2(1.414) / iResolution.xy;
|
||||
|
||||
for (int i = 0; i < 24; i++) {
|
||||
vec3 s = samples[i];
|
||||
vec4 c = texture(iChannel0, uv + s.xy * step);
|
||||
float l = lum(c);
|
||||
if (l > 0.2) {
|
||||
color += l * s.z * c * 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
fragColor = color;
|
||||
}
|
||||
76
ghostty-shaders/cineShader-Lava.glsl
Normal file
76
ghostty-shaders/cineShader-Lava.glsl
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
// INFO: This shader is a port of https://www.shadertoy.com/view/3sySRK
|
||||
|
||||
// INFO: Change these variables to create some variation in the animation
|
||||
#define BLACK_BLEND_THRESHOLD .4 // This is controls the dim of the screen
|
||||
#define COLOR_SPEED 0.1 // This controls the speed at which the colors change
|
||||
#define MOVEMENT_SPEED 0.1 // This controls the speed at which the balls move
|
||||
|
||||
float opSmoothUnion(float d1, float d2, float k)
|
||||
{
|
||||
float h = clamp(0.5 + 0.5 * (d2 - d1) / k, 0.0, 1.0);
|
||||
return mix(d2, d1, h) - k * h * (1.0 - h);
|
||||
}
|
||||
|
||||
float sdSphere(vec3 p, float s)
|
||||
{
|
||||
return length(p) - s;
|
||||
}
|
||||
|
||||
float map(vec3 p)
|
||||
{
|
||||
float d = 2.0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
float fi = float(i);
|
||||
float time = iTime * (fract(fi * 412.531 + 0.513) - 0.5) * 2.0;
|
||||
d = opSmoothUnion(
|
||||
sdSphere(p + sin(time * MOVEMENT_SPEED + 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))),
|
||||
d,
|
||||
0.4
|
||||
);
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
vec3 calcNormal(in vec3 p)
|
||||
{
|
||||
const float h = 1e-5; // or some other value
|
||||
const vec2 k = vec2(1, -1);
|
||||
return normalize(k.xyy * map(p + k.xyy * h) +
|
||||
k.yyx * map(p + k.yyx * h) +
|
||||
k.yxy * map(p + k.yxy * h) +
|
||||
k.xxx * map(p + k.xxx * h));
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord)
|
||||
{
|
||||
vec2 uv = fragCoord / iResolution.xy;
|
||||
|
||||
vec3 rayOri = vec3((uv - 0.5) * vec2(iResolution.x / iResolution.y, 1.0) * 6.0, 3.0);
|
||||
vec3 rayDir = vec3(0.0, 0.0, -1.0);
|
||||
|
||||
float depth = 0.0;
|
||||
vec3 p;
|
||||
|
||||
for (int i = 0; i < 64; i++) {
|
||||
p = rayOri + rayDir * depth;
|
||||
float dist = map(p);
|
||||
depth += dist;
|
||||
if (dist < 1e-6) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
depth = min(6.0, depth);
|
||||
vec3 n = calcNormal(p);
|
||||
float b = max(0.0, dot(n, vec3(0.577)));
|
||||
vec3 col = (0.5 + 0.5 * cos((b + iTime * COLOR_SPEED * 3.0) + uv.xyx * 2.0 + vec3(0, 2, 4))) * (0.85 + b * 0.35);
|
||||
col *= exp(-depth * 0.15);
|
||||
|
||||
vec2 termUV = fragCoord.xy / iResolution.xy;
|
||||
vec4 terminalColor = texture(iChannel0, termUV);
|
||||
|
||||
float alpha = step(length(terminalColor.rgb), BLACK_BLEND_THRESHOLD);
|
||||
vec3 blendedColor = mix(terminalColor.rgb * 1.0, col.rgb * 0.3, alpha);
|
||||
|
||||
fragColor = vec4(blendedColor, terminalColor.a);
|
||||
}
|
||||
192
ghostty-shaders/clocks.glsl
Normal file
192
ghostty-shaders/clocks.glsl
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
// Author: Rigel rui@gil.com
|
||||
// licence: https://creativecommons.org/licenses/by/4.0/
|
||||
// link: https://www.shadertoy.com/view/lljfRD
|
||||
|
||||
#define BLACK_BLEND_THRESHOLD .4 // This is controls the dim of the screen
|
||||
const float timeMultiplier = 0.1f;
|
||||
|
||||
/*
|
||||
This was a study on circles, inspired by this artwork
|
||||
http://www.dailymail.co.uk/news/article-1236380/Worlds-largest-artwork-etched-desert-sand.html
|
||||
|
||||
and implemented with the help of this article
|
||||
http://www.ams.org/samplings/feature-column/fcarc-kissing
|
||||
|
||||
The structure is called an apollonian packing (or gasket)
|
||||
https://en.m.wikipedia.org/wiki/Apollonian_gasket
|
||||
|
||||
There is a lot of apollonians in shadertoy, but not many quite like the image above.
|
||||
This one by klems is really cool. He uses a technique called a soddy circle.
|
||||
https://www.shadertoy.com/view/4s2czK
|
||||
|
||||
This shader uses another technique called a Descartes Configuration.
|
||||
The only thing that makes this technique interesting is that it can be generalized to higher dimensions.
|
||||
*/
|
||||
|
||||
// a few utility functions
|
||||
// a signed distance function for a rectangle
|
||||
float sdfRect(vec2 uv, vec2 s) {
|
||||
vec2 auv = abs(uv);
|
||||
return max(auv.x - s.x, auv.y - s.y);
|
||||
}
|
||||
// a signed distance function for a circle
|
||||
float sdfCircle(vec2 uv, vec2 c, float r) {
|
||||
return length(uv - c) - r;
|
||||
}
|
||||
// fills an sdf in 2d
|
||||
float fill(float d, float s, float i) {
|
||||
return abs(smoothstep(0., s, d) - i);
|
||||
}
|
||||
// makes a stroke of an sdf at the zero boundary
|
||||
float stroke(float d, float w, float s, float i) {
|
||||
return abs(smoothstep(0., s, abs(d) - (w * .5)) - i);
|
||||
}
|
||||
// a simple palette
|
||||
vec3 pal(float d) {
|
||||
return .5 * (cos(6.283 * d * vec3(2., 2., 1.) + vec3(.0, 1.4, .0)) + 1.);
|
||||
}
|
||||
// 2d rotation matrix
|
||||
mat2 uvRotate(float a) {
|
||||
return mat2(cos(a), sin(a), -sin(a), cos(a));
|
||||
}
|
||||
// circle inversion
|
||||
vec2 inversion(vec2 uv, float r) {
|
||||
return (r * r * uv) / vec2(dot(uv, uv));
|
||||
}
|
||||
// seeded random number
|
||||
float hash(vec2 s) {
|
||||
return fract(sin(dot(s, vec2(12.9898, 78.2333))) * 43758.5453123);
|
||||
}
|
||||
|
||||
// this is an algorithm to construct an apollonian packing with a descartes configuration
|
||||
// remaps the plane to a circle at the origin and a specific radius. vec3(x,y,radius)
|
||||
vec3 apollonian(vec2 uv) {
|
||||
// the algorithm is recursive and must start with a initial descartes configuration
|
||||
// each vec3 represents a circle with the form vec3(centerx, centery, 1./radius)
|
||||
// the signed inverse radius is also called the bend (refer to the article above)
|
||||
vec3 dec[4];
|
||||
// a DEC is a configuration of 4 circles tangent to each other
|
||||
// the easiest way to build the initial one it to construct a symetric Steiner Chain.
|
||||
// http://mathworld.wolfram.com/SteinerChain.html
|
||||
float a = 6.283 / 3.;
|
||||
float ra = 1. + sin(a * .5);
|
||||
float rb = 1. - sin(a * .5);
|
||||
dec[0] = vec3(0., 0., -1. / ra);
|
||||
float radius = .5 * (ra - rb);
|
||||
float bend = 1. / radius;
|
||||
for (int i = 1; i < 4; i++) {
|
||||
dec[i] = vec3(cos(float(i) * a), sin(float(i) * a), bend);
|
||||
// if the point is in one of the starting circles we have already found our solution
|
||||
if (length(uv - dec[i].xy) < radius) return vec3(uv - dec[i].xy, radius);
|
||||
}
|
||||
|
||||
// Now that we have a starting DEC we are going to try to
|
||||
// find the solution for the current point
|
||||
for (int i = 0; i < 7; i++) {
|
||||
// find the circle that is further away from the point uv, using euclidean distance
|
||||
int fi = 0;
|
||||
float d = distance(uv, dec[0].xy) - abs(1. / dec[0].z);
|
||||
// for some reason, the euclidean distance doesn't work for the circle with negative bend
|
||||
// can anyone with proper math skills, explain me why?
|
||||
d *= dec[0].z < 0. ? -.5 : 1.; // just scale it to make it work...
|
||||
for (int i = 1; i < 4; i++) {
|
||||
float fd = distance(uv, dec[i].xy) - abs(1. / dec[i].z);
|
||||
fd *= dec[i].z < 0. ? -.5 : 1.;
|
||||
if (fd > d) {
|
||||
fi = i;
|
||||
d = fd;
|
||||
}
|
||||
}
|
||||
// put the cicle found in the last slot, to generate a solution
|
||||
// in the "direction" of the point
|
||||
vec3 c = dec[3];
|
||||
dec[3] = dec[fi];
|
||||
dec[fi] = c;
|
||||
// generate a new solution
|
||||
float bend = (2. * (dec[0].z + dec[1].z + dec[2].z)) - dec[3].z;
|
||||
vec2 center = vec2((2. * (dec[0].z * dec[0].xy
|
||||
+ dec[1].z * dec[1].xy
|
||||
+ dec[2].z * dec[2].xy)
|
||||
- dec[3].z * dec[3].xy) / bend);
|
||||
|
||||
vec3 solution = vec3(center, bend);
|
||||
// is the solution radius is to small, quit
|
||||
if (abs(1. / bend) < 0.01) break;
|
||||
// if the solution contains the point return the circle
|
||||
if (length(uv - solution.xy) < 1. / bend) return vec3(uv - solution.xy, 1. / bend);
|
||||
// else update the descartes configuration,
|
||||
dec[3] = solution;
|
||||
// and repeat...
|
||||
}
|
||||
// if nothing is found we return by default the inner circle of the Steiner chain
|
||||
return vec3(uv, rb);
|
||||
}
|
||||
|
||||
vec3 scene(vec2 uv, vec4 ms) {
|
||||
vec2 ci = vec2(.0);
|
||||
|
||||
// drag your mouse to apply circle inversion
|
||||
if (ms.y != -2. && ms.z > -2.) {
|
||||
uv = inversion(uv, cos(radians(60.)));
|
||||
ci = ms.xy;
|
||||
}
|
||||
|
||||
// remap uv to appolonian packing
|
||||
vec3 uvApo = apollonian(uv - ci);
|
||||
|
||||
float d = 6.2830 / 360.;
|
||||
float a = atan(uvApo.y, uvApo.x);
|
||||
float r = length(uvApo.xy);
|
||||
|
||||
float circle = sdfCircle(uv, uv - uvApo.xy, uvApo.z);
|
||||
|
||||
// background
|
||||
vec3 c = length(uv) * pal(.7) * .2;
|
||||
|
||||
// drawing the clocks
|
||||
if (uvApo.z > .3) {
|
||||
c = mix(c, pal(.75 - r * .1) * .8, fill(circle + .02, .01, 1.)); // clock
|
||||
c = mix(c, pal(.4 + r * .1), stroke(circle + (uvApo.z * .03), uvApo.z * .01, .005, 1.)); // dial
|
||||
|
||||
float h = stroke(mod(a + d * 15., d * 30.) - d * 15., .02, 0.01, 1.);
|
||||
c = mix(c, pal(.4 + r * .1), h * stroke(circle + (uvApo.z * .16), uvApo.z * .25, .005, 1.0)); // hours
|
||||
|
||||
float m = stroke(mod(a + d * 15., d * 6.) - d * 3., .005, 0.01, 1.);
|
||||
c = mix(c, pal(.45 + r * .1), (1. - h) * m * stroke(circle + (uvApo.z * .15), uvApo.z * .1, .005, 1.0)); // minutes,
|
||||
|
||||
// needles rotation
|
||||
vec2 uvrh = uvApo.xy * uvRotate(sign(cos(hash(vec2(uvApo.z)) * d * 180.)) * d * iTime * timeMultiplier * (1. / uvApo.z * 10.) - d * 90.);
|
||||
vec2 uvrm = uvApo.xy * uvRotate(sign(cos(hash(vec2(uvApo.z) * 4.) * d * 180.)) * d * iTime * timeMultiplier * (1. / uvApo.z * 120.) - d * 90.);
|
||||
// draw needles
|
||||
c = mix(c, pal(.85), stroke(sdfRect(uvrh + vec2(uvApo.z - (uvApo.z * .8), .0), uvApo.z * vec2(.4, .03)), uvApo.z * .01, 0.005, 1.));
|
||||
c = mix(c, pal(.9), fill(sdfRect(uvrm + vec2(uvApo.z - (uvApo.z * .65), .0), uvApo.z * vec2(.5, .002)), 0.005, 1.));
|
||||
c = mix(c, pal(.5 + r * 10.), fill(circle + uvApo.z - .02, 0.005, 1.)); // center
|
||||
// drawing the gears
|
||||
} else if (uvApo.z > .05) {
|
||||
vec2 uvrg = uvApo.xy * uvRotate(sign(cos(hash(vec2(uvApo.z + 2.)) * d * 180.)) * d * iTime * timeMultiplier * (1. / uvApo.z * 20.));
|
||||
float g = stroke(mod(atan(uvrg.y, uvrg.x) + d * 22.5, d * 45.) - d * 22.5, .3, .05, 1.0);
|
||||
vec2 size = uvApo.z * vec2(.45, .08);
|
||||
c = mix(c, pal(.55 - r * .6), fill(circle + g * (uvApo.z * .2) + .01, .001, 1.) * fill(circle + (uvApo.z * .6), .005, .0));
|
||||
c = mix(c, pal(.55 - r * .6), fill(min(sdfRect(uvrg, size.xy), sdfRect(uvrg, size.yx)), .005, 1.));
|
||||
// drawing the screws
|
||||
} else {
|
||||
vec2 size = uvApo.z * vec2(.5, .1);
|
||||
c = mix(c, pal(.85 - (uvApo.z * 2.)), fill(circle + 0.01, .007, 1.));
|
||||
c = mix(c, pal(.8 - (uvApo.z * 3.)), fill(min(sdfRect(uvApo.xy, size.xy), sdfRect(uvApo.xy, size.yx)), .002, 1.));
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
||||
vec2 uv = (fragCoord.xy - iResolution.xy * .5) / iResolution.y;
|
||||
vec4 ms = (iMouse - iResolution.xyxy * .5) / iResolution.y;
|
||||
vec4 col = vec4(scene(uv * 4., ms * 4.), 1.0);
|
||||
|
||||
vec2 termUV = fragCoord.xy / iResolution.xy;
|
||||
vec4 terminalColor = texture(iChannel0, termUV);
|
||||
|
||||
float alpha = step(length(terminalColor.rgb), BLACK_BLEND_THRESHOLD);
|
||||
vec3 blendedColor = mix(terminalColor.rgb * 1.0, col.rgb * 0.3, alpha);
|
||||
|
||||
fragColor = vec4(blendedColor, terminalColor.a);
|
||||
}
|
||||
311
ghostty-shaders/crt.glsl
Normal file
311
ghostty-shaders/crt.glsl
Normal file
|
|
@ -0,0 +1,311 @@
|
|||
// source: https://gist.github.com/qwerasd205/c3da6c610c8ffe17d6d2d3cc7068f17f
|
||||
// credits: https://github.com/qwerasd205
|
||||
//==============================================================
|
||||
//
|
||||
// [CRTS] PUBLIC DOMAIN CRT-STYLED SCALAR by Timothy Lottes
|
||||
//
|
||||
// [+] Adapted with alterations for use in Ghostty by Qwerasd.
|
||||
// For more information on changes, see comment below license.
|
||||
//
|
||||
//==============================================================
|
||||
//
|
||||
// LICENSE = UNLICENSE (aka PUBLIC DOMAIN)
|
||||
//
|
||||
//--------------------------------------------------------------
|
||||
// This is free and unencumbered software released into the
|
||||
// public domain.
|
||||
//--------------------------------------------------------------
|
||||
// Anyone is free to copy, modify, publish, use, compile, sell,
|
||||
// or distribute this software, either in source code form or as
|
||||
// a compiled binary, for any purpose, commercial or
|
||||
// non-commercial, and by any means.
|
||||
//--------------------------------------------------------------
|
||||
// In jurisdictions that recognize copyright laws, the author or
|
||||
// authors of this software dedicate any and all copyright
|
||||
// interest in the software to the public domain. We make this
|
||||
// dedication for the benefit of the public at large and to the
|
||||
// detriment of our heirs and successors. We intend this
|
||||
// dedication to be an overt act of relinquishment in perpetuity
|
||||
// of all present and future rights to this software under
|
||||
// copyright law.
|
||||
//--------------------------------------------------------------
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
||||
// KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||
// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//--------------------------------------------------------------
|
||||
// For more information, please refer to
|
||||
// <http://unlicense.org/>
|
||||
//==============================================================
|
||||
|
||||
// This shader is a modified version of the excellent
|
||||
// FixingPixelArtFast by Timothy Lottes on Shadertoy.
|
||||
//
|
||||
// The original shader can be found at:
|
||||
// https://www.shadertoy.com/view/MtSfRK
|
||||
//
|
||||
// Modifications have been made to reduce the verbosity,
|
||||
// and many of the comments have been removed / reworded.
|
||||
// Additionally, the license has been moved to the top of
|
||||
// the file, and can be read above. I (Qwerasd) choose to
|
||||
// release the modified version under the same license.
|
||||
|
||||
// The appearance of this shader can be altered
|
||||
// by adjusting the parameters defined below.
|
||||
|
||||
// "Scanlines" per real screen pixel.
|
||||
// e.g. SCALE 0.5 means each scanline is 2 pixels.
|
||||
// Recommended values:
|
||||
// o High DPI displays: 0.33333333
|
||||
// - Low DPI displays: 0.66666666
|
||||
#define SCALE 0.33333333
|
||||
|
||||
// "Tube" warp
|
||||
#define CRTS_WARP 1
|
||||
|
||||
// Darkness of vignette in corners after warping
|
||||
// 0.0 = completely black
|
||||
// 1.0 = no vignetting
|
||||
#define MIN_VIN 0.5
|
||||
|
||||
// Try different masks
|
||||
// #define CRTS_MASK_GRILLE 1
|
||||
// #define CRTS_MASK_GRILLE_LITE 1
|
||||
// #define CRTS_MASK_NONE 1
|
||||
#define CRTS_MASK_SHADOW 1
|
||||
|
||||
// Scanline thinness
|
||||
// 0.50 = fused scanlines
|
||||
// 0.70 = recommended default
|
||||
// 1.00 = thinner scanlines (too thin)
|
||||
#define INPUT_THIN 0.75
|
||||
|
||||
// Horizonal scan blur
|
||||
// -3.0 = pixely
|
||||
// -2.5 = default
|
||||
// -2.0 = smooth
|
||||
// -1.0 = too blurry
|
||||
#define INPUT_BLUR -2.75
|
||||
|
||||
// Shadow mask effect, ranges from,
|
||||
// 0.25 = large amount of mask (not recommended, too dark)
|
||||
// 0.50 = recommended default
|
||||
// 1.00 = no shadow mask
|
||||
#define INPUT_MASK 0.65
|
||||
|
||||
float FromSrgb1(float c) {
|
||||
return (c <= 0.04045) ? c * (1.0 / 12.92) :
|
||||
pow(c * (1.0 / 1.055) + (0.055 / 1.055), 2.4);
|
||||
}
|
||||
vec3 FromSrgb(vec3 c) {
|
||||
return vec3(
|
||||
FromSrgb1(c.r), FromSrgb1(c.g), FromSrgb1(c.b));
|
||||
}
|
||||
|
||||
vec3 CrtsFetch(vec2 uv) {
|
||||
return FromSrgb(texture(iChannel0, uv.xy).rgb);
|
||||
}
|
||||
|
||||
#define CrtsRcpF1(x) (1.0/(x))
|
||||
#define CrtsSatF1(x) clamp((x),0.0,1.0)
|
||||
|
||||
float CrtsMax3F1(float a, float b, float c) {
|
||||
return max(a, max(b, c));
|
||||
}
|
||||
|
||||
vec2 CrtsTone(
|
||||
float thin,
|
||||
float mask) {
|
||||
#ifdef CRTS_MASK_NONE
|
||||
mask = 1.0;
|
||||
#endif
|
||||
|
||||
#ifdef CRTS_MASK_GRILLE_LITE
|
||||
// Normal R mask is {1.0,mask,mask}
|
||||
// LITE R mask is {mask,1.0,1.0}
|
||||
mask = 0.5 + mask * 0.5;
|
||||
#endif
|
||||
|
||||
vec2 ret;
|
||||
float midOut = 0.18 / ((1.5 - thin) * (0.5 * mask + 0.5));
|
||||
float pMidIn = 0.18;
|
||||
ret.x = ((-pMidIn) + midOut) / ((1.0 - pMidIn) * midOut);
|
||||
ret.y = ((-pMidIn) * midOut + pMidIn) / (midOut * (-pMidIn) + midOut);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
vec3 CrtsMask(vec2 pos, float dark) {
|
||||
#ifdef CRTS_MASK_GRILLE
|
||||
vec3 m = vec3(dark, dark, dark);
|
||||
float x = fract(pos.x * (1.0 / 3.0));
|
||||
if (x < (1.0 / 3.0)) m.r = 1.0;
|
||||
else if (x < (2.0 / 3.0)) m.g = 1.0;
|
||||
else m.b = 1.0;
|
||||
return m;
|
||||
#endif
|
||||
|
||||
#ifdef CRTS_MASK_GRILLE_LITE
|
||||
vec3 m = vec3(1.0, 1.0, 1.0);
|
||||
float x = fract(pos.x * (1.0 / 3.0));
|
||||
if (x < (1.0 / 3.0)) m.r = dark;
|
||||
else if (x < (2.0 / 3.0)) m.g = dark;
|
||||
else m.b = dark;
|
||||
return m;
|
||||
#endif
|
||||
|
||||
#ifdef CRTS_MASK_NONE
|
||||
return vec3(1.0, 1.0, 1.0);
|
||||
#endif
|
||||
|
||||
#ifdef CRTS_MASK_SHADOW
|
||||
pos.x += pos.y * 3.0;
|
||||
vec3 m = vec3(dark, dark, dark);
|
||||
float x = fract(pos.x * (1.0 / 6.0));
|
||||
if (x < (1.0 / 3.0)) m.r = 1.0;
|
||||
else if (x < (2.0 / 3.0)) m.g = 1.0;
|
||||
else m.b = 1.0;
|
||||
return m;
|
||||
#endif
|
||||
}
|
||||
|
||||
vec3 CrtsFilter(
|
||||
vec2 ipos,
|
||||
vec2 inputSizeDivOutputSize,
|
||||
vec2 halfInputSize,
|
||||
vec2 rcpInputSize,
|
||||
vec2 rcpOutputSize,
|
||||
vec2 twoDivOutputSize,
|
||||
float inputHeight,
|
||||
vec2 warp,
|
||||
float thin,
|
||||
float blur,
|
||||
float mask,
|
||||
vec2 tone
|
||||
) {
|
||||
// Optional apply warp
|
||||
vec2 pos;
|
||||
#ifdef CRTS_WARP
|
||||
// Convert to {-1 to 1} range
|
||||
pos = ipos * twoDivOutputSize - vec2(1.0, 1.0);
|
||||
|
||||
// Distort pushes image outside {-1 to 1} range
|
||||
pos *= vec2(
|
||||
1.0 + (pos.y * pos.y) * warp.x,
|
||||
1.0 + (pos.x * pos.x) * warp.y);
|
||||
|
||||
// TODO: Vignette needs optimization
|
||||
float vin = 1.0 - (
|
||||
(1.0 - CrtsSatF1(pos.x * pos.x)) * (1.0 - CrtsSatF1(pos.y * pos.y)));
|
||||
vin = CrtsSatF1((-vin) * inputHeight + inputHeight);
|
||||
|
||||
// Leave in {0 to inputSize}
|
||||
pos = pos * halfInputSize + halfInputSize;
|
||||
#else
|
||||
pos = ipos * inputSizeDivOutputSize;
|
||||
#endif
|
||||
|
||||
// Snap to center of first scanline
|
||||
float y0 = floor(pos.y - 0.5) + 0.5;
|
||||
// Snap to center of one of four pixels
|
||||
float x0 = floor(pos.x - 1.5) + 0.5;
|
||||
|
||||
// Inital UV position
|
||||
vec2 p = vec2(x0 * rcpInputSize.x, y0 * rcpInputSize.y);
|
||||
// Fetch 4 nearest texels from 2 nearest scanlines
|
||||
vec3 colA0 = CrtsFetch(p);
|
||||
p.x += rcpInputSize.x;
|
||||
vec3 colA1 = CrtsFetch(p);
|
||||
p.x += rcpInputSize.x;
|
||||
vec3 colA2 = CrtsFetch(p);
|
||||
p.x += rcpInputSize.x;
|
||||
vec3 colA3 = CrtsFetch(p);
|
||||
p.y += rcpInputSize.y;
|
||||
vec3 colB3 = CrtsFetch(p);
|
||||
p.x -= rcpInputSize.x;
|
||||
vec3 colB2 = CrtsFetch(p);
|
||||
p.x -= rcpInputSize.x;
|
||||
vec3 colB1 = CrtsFetch(p);
|
||||
p.x -= rcpInputSize.x;
|
||||
vec3 colB0 = CrtsFetch(p);
|
||||
|
||||
// Vertical filter
|
||||
// Scanline intensity is using sine wave
|
||||
// Easy filter window and integral used later in exposure
|
||||
float off = pos.y - y0;
|
||||
float pi2 = 6.28318530717958;
|
||||
float hlf = 0.5;
|
||||
float scanA = cos(min(0.5, off * thin) * pi2) * hlf + hlf;
|
||||
float scanB = cos(min(0.5, (-off) * thin + thin) * pi2) * hlf + hlf;
|
||||
|
||||
// Horizontal kernel is simple gaussian filter
|
||||
float off0 = pos.x - x0;
|
||||
float off1 = off0 - 1.0;
|
||||
float off2 = off0 - 2.0;
|
||||
float off3 = off0 - 3.0;
|
||||
float pix0 = exp2(blur * off0 * off0);
|
||||
float pix1 = exp2(blur * off1 * off1);
|
||||
float pix2 = exp2(blur * off2 * off2);
|
||||
float pix3 = exp2(blur * off3 * off3);
|
||||
float pixT = CrtsRcpF1(pix0 + pix1 + pix2 + pix3);
|
||||
|
||||
#ifdef CRTS_WARP
|
||||
// Get rid of wrong pixels on edge
|
||||
pixT *= max(MIN_VIN, vin);
|
||||
#endif
|
||||
|
||||
scanA *= pixT;
|
||||
scanB *= pixT;
|
||||
|
||||
// Apply horizontal and vertical filters
|
||||
vec3 color =
|
||||
(colA0 * pix0 + colA1 * pix1 + colA2 * pix2 + colA3 * pix3) * scanA +
|
||||
(colB0 * pix0 + colB1 * pix1 + colB2 * pix2 + colB3 * pix3) * scanB;
|
||||
|
||||
// Apply phosphor mask
|
||||
color *= CrtsMask(ipos, mask);
|
||||
|
||||
// Tonal control, start by protecting from /0
|
||||
float peak = max(1.0 / (256.0 * 65536.0),
|
||||
CrtsMax3F1(color.r, color.g, color.b));
|
||||
// Compute the ratios of {R,G,B}
|
||||
vec3 ratio = color * CrtsRcpF1(peak);
|
||||
// Apply tonal curve to peak value
|
||||
peak = peak * CrtsRcpF1(peak * tone.x + tone.y);
|
||||
// Reconstruct color
|
||||
return ratio * peak;
|
||||
}
|
||||
|
||||
float ToSrgb1(float c) {
|
||||
return (c < 0.0031308 ? c * 12.92 : 1.055 * pow(c, 0.41666) - 0.055);
|
||||
}
|
||||
vec3 ToSrgb(vec3 c) {
|
||||
return vec3(
|
||||
ToSrgb1(c.r), ToSrgb1(c.g), ToSrgb1(c.b));
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
||||
float aspect = iResolution.x / iResolution.y;
|
||||
fragColor.rgb = CrtsFilter(
|
||||
fragCoord.xy,
|
||||
vec2(1.0),
|
||||
iResolution.xy * SCALE * 0.5,
|
||||
1.0 / (iResolution.xy * SCALE),
|
||||
1.0 / iResolution.xy,
|
||||
2.0 / iResolution.xy,
|
||||
iResolution.y,
|
||||
vec2(1.0 / (50.0 * aspect), 1.0 / 50.0),
|
||||
INPUT_THIN,
|
||||
INPUT_BLUR,
|
||||
INPUT_MASK,
|
||||
CrtsTone(INPUT_THIN, INPUT_MASK)
|
||||
);
|
||||
|
||||
// Linear to SRGB for output.
|
||||
fragColor.rgb = ToSrgb(fragColor.rgb);
|
||||
}
|
||||
|
||||
111
ghostty-shaders/cubes.glsl
Normal file
111
ghostty-shaders/cubes.glsl
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
// credits: https://github.com/rymdlego
|
||||
|
||||
const float speed = 0.2;
|
||||
const float cube_size = 1.0;
|
||||
const float cube_brightness = 1.0;
|
||||
const float cube_rotation_speed = 2.8;
|
||||
const float camera_rotation_speed = 0.1;
|
||||
|
||||
mat3 rotationMatrix(vec3 m, float a) {
|
||||
m = normalize(m);
|
||||
float c = cos(a), s = sin(a);
|
||||
return mat3(c + (1. - c) * m.x * m.x,
|
||||
(1. - c) * m.x * m.y - s * m.z,
|
||||
(1. - c) * m.x * m.z + s * m.y,
|
||||
(1. - c) * m.x * m.y + s * m.z,
|
||||
c + (1. - c) * m.y * m.y,
|
||||
(1. - c) * m.y * m.z - s * m.x,
|
||||
(1. - c) * m.x * m.z - s * m.y,
|
||||
(1. - c) * m.y * m.z + s * m.x,
|
||||
c + (1. - c) * m.z * m.z);
|
||||
}
|
||||
|
||||
float sphere(vec3 pos, float radius)
|
||||
{
|
||||
return length(pos) - radius;
|
||||
}
|
||||
|
||||
float box(vec3 pos, vec3 size)
|
||||
{
|
||||
float t = iTime;
|
||||
pos = pos * 0.9 * rotationMatrix(vec3(sin(t / 4.0 * speed) * 10., cos(t / 4.0 * speed) * 12., 2.7), t * 2.4 / 4.0 * speed * cube_rotation_speed);
|
||||
return length(max(abs(pos) - size, 0.0));
|
||||
}
|
||||
|
||||
float distfunc(vec3 pos)
|
||||
{
|
||||
float t = iTime;
|
||||
|
||||
float size = 0.45 + 0.25 * abs(16.0 * sin(t * speed / 4.0));
|
||||
// float size = 2.3 + 1.8*tan((t-5.4)*6.549);
|
||||
size = cube_size * 0.16 * clamp(size, 2.0, 4.0);
|
||||
|
||||
//pos = pos * rotationMatrix(vec3(0.,-3.,0.7), 3.3 * mod(t/30.0, 4.0));
|
||||
vec3 q = mod(pos, 5.0) - 2.5;
|
||||
float obj1 = box(q, vec3(size));
|
||||
return obj1;
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord)
|
||||
{
|
||||
float t = iTime;
|
||||
vec2 screenPos = -1.0 + 2.0 * fragCoord.xy / iResolution.xy;
|
||||
screenPos.x *= iResolution.x / iResolution.y;
|
||||
vec3 cameraOrigin = vec3(t * 1.0 * speed, 0.0, 0.0);
|
||||
// vec3 cameraOrigin = vec3(t*1.8*speed, 3.0+t*0.02*speed, 0.0);
|
||||
vec3 cameraTarget = vec3(t * 100., 0.0, 0.0);
|
||||
cameraTarget = vec3(t * 20.0, 0.0, 0.0) * rotationMatrix(vec3(0.0, 0.0, 1.0), t * speed * camera_rotation_speed);
|
||||
|
||||
vec3 upDirection = vec3(0.5, 1.0, 0.6);
|
||||
|
||||
vec3 cameraDir = normalize(cameraTarget - cameraOrigin);
|
||||
vec3 cameraRight = normalize(cross(upDirection, cameraOrigin));
|
||||
vec3 cameraUp = cross(cameraDir, cameraRight);
|
||||
|
||||
vec3 rayDir = normalize(cameraRight * screenPos.x + cameraUp * screenPos.y + cameraDir);
|
||||
|
||||
const int MAX_ITER = 16;
|
||||
const float MAX_DIST = 48.0;
|
||||
const float EPSILON = 0.01;
|
||||
|
||||
float totalDist = 0.0;
|
||||
vec3 pos = cameraOrigin;
|
||||
float dist = EPSILON;
|
||||
|
||||
for (int i = 0; i < MAX_ITER; i++)
|
||||
{
|
||||
if (dist < EPSILON || totalDist > MAX_DIST)
|
||||
break;
|
||||
dist = distfunc(pos);
|
||||
totalDist += dist;
|
||||
pos += dist * rayDir;
|
||||
}
|
||||
|
||||
vec4 cubes;
|
||||
|
||||
if (dist < EPSILON)
|
||||
{
|
||||
// Lighting Code
|
||||
vec2 eps = vec2(0.0, EPSILON);
|
||||
vec3 normal = normalize(vec3(
|
||||
distfunc(pos + eps.yxx) - distfunc(pos - eps.yxx),
|
||||
distfunc(pos + eps.xyx) - distfunc(pos - eps.xyx),
|
||||
distfunc(pos + eps.xxy) - distfunc(pos - eps.xxy)));
|
||||
float diffuse = max(0., dot(-rayDir, normal));
|
||||
float specular = pow(diffuse, 32.0);
|
||||
vec3 color = vec3(diffuse + specular);
|
||||
vec3 cubeColor = vec3(abs(screenPos), 0.5 + 0.5 * sin(t * 2.0)) * 0.8;
|
||||
cubeColor = mix(cubeColor.rgb, vec3(0.0, 0.0, 0.0), 1.0);
|
||||
color += cubeColor;
|
||||
cubes = vec4(color, 1.0) * vec4(1.0 - (totalDist / MAX_DIST));
|
||||
cubes = vec4(cubes.rgb * 0.02 * cube_brightness, 0.1);
|
||||
}
|
||||
else {
|
||||
cubes = vec4(0.0);
|
||||
}
|
||||
|
||||
vec2 uv = fragCoord / iResolution.xy;
|
||||
vec4 terminalColor = texture(iChannel0, uv);
|
||||
vec3 blendedColor = terminalColor.rgb + cubes.rgb;
|
||||
fragColor = vec4(blendedColor, terminalColor.a);
|
||||
}
|
||||
164
ghostty-shaders/cyber-fuji.glsl
Normal file
164
ghostty-shaders/cyber-fuji.glsl
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
#define BLACK_BLEND_THRESHOLD .4 // This is controls the dim of the screen
|
||||
const float timeMultiplier = 0.1f;
|
||||
|
||||
float sun(vec2 uv, float battery)
|
||||
{
|
||||
float val = smoothstep(0.3, 0.29, length(uv));
|
||||
float bloom = smoothstep(0.7, 0.0, length(uv));
|
||||
float cut = 3.0 * sin((uv.y + iTime * timeMultiplier * 0.2 * (battery + 0.02)) * 100.0)
|
||||
+ clamp(uv.y * 14.0 + 1.0, -6.0, 6.0);
|
||||
cut = clamp(cut, 0.0, 1.0);
|
||||
return clamp(val * cut, 0.0, 1.0) + bloom * 0.6;
|
||||
}
|
||||
|
||||
float grid(vec2 uv, float battery)
|
||||
{
|
||||
vec2 size = vec2(uv.y, uv.y * uv.y * 0.2) * 0.01;
|
||||
uv += vec2(0.0, iTime * timeMultiplier * 4.0 * (battery + 0.05));
|
||||
uv = abs(fract(uv) - 0.5);
|
||||
vec2 lines = smoothstep(size, vec2(0.0), uv);
|
||||
lines += smoothstep(size * 5.0, vec2(0.0), uv) * 0.4 * battery;
|
||||
return clamp(lines.x + lines.y, 0.0, 3.0);
|
||||
}
|
||||
|
||||
float dot2(in vec2 v) {
|
||||
return dot(v, v);
|
||||
}
|
||||
|
||||
float sdTrapezoid(in vec2 p, in float r1, float r2, float he)
|
||||
{
|
||||
vec2 k1 = vec2(r2, he);
|
||||
vec2 k2 = vec2(r2 - r1, 2.0 * he);
|
||||
p.x = abs(p.x);
|
||||
vec2 ca = vec2(p.x - min(p.x, (p.y < 0.0) ? r1 : r2), abs(p.y) - he);
|
||||
vec2 cb = p - k1 + k2 * clamp(dot(k1 - p, k2) / dot2(k2), 0.0, 1.0);
|
||||
float s = (cb.x < 0.0 && ca.y < 0.0) ? -1.0 : 1.0;
|
||||
return s * sqrt(min(dot2(ca), dot2(cb)));
|
||||
}
|
||||
|
||||
float sdLine(in vec2 p, in vec2 a, in vec2 b)
|
||||
{
|
||||
vec2 pa = p - a, ba = b - a;
|
||||
float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);
|
||||
return length(pa - ba * h);
|
||||
}
|
||||
|
||||
float sdBox(in vec2 p, in vec2 b)
|
||||
{
|
||||
vec2 d = abs(p) - b;
|
||||
return length(max(d, vec2(0))) + min(max(d.x, d.y), 0.0);
|
||||
}
|
||||
|
||||
float opSmoothUnion(float d1, float d2, float k) {
|
||||
float h = clamp(0.5 + 0.5 * (d2 - d1) / k, 0.0, 1.0);
|
||||
return mix(d2, d1, h) - k * h * (1.0 - h);
|
||||
}
|
||||
|
||||
float sdCloud(in vec2 p, in vec2 a1, in vec2 b1, in vec2 a2, in vec2 b2, float w)
|
||||
{
|
||||
//float lineVal1 = smoothstep(w - 0.0001, w, sdLine(p, a1, b1));
|
||||
float lineVal1 = sdLine(p, a1, b1);
|
||||
float lineVal2 = sdLine(p, a2, b2);
|
||||
vec2 ww = vec2(w * 1.5, 0.0);
|
||||
vec2 left = max(a1 + ww, a2 + ww);
|
||||
vec2 right = min(b1 - ww, b2 - ww);
|
||||
vec2 boxCenter = (left + right) * 0.5;
|
||||
//float boxW = right.x - left.x;
|
||||
float boxH = abs(a2.y - a1.y) * 0.5;
|
||||
//float boxVal = sdBox(p - boxCenter, vec2(boxW, boxH)) + w;
|
||||
float boxVal = sdBox(p - boxCenter, vec2(0.04, boxH)) + w;
|
||||
|
||||
float uniVal1 = opSmoothUnion(lineVal1, boxVal, 0.05);
|
||||
float uniVal2 = opSmoothUnion(lineVal2, boxVal, 0.05);
|
||||
|
||||
return min(uniVal1, uniVal2);
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord)
|
||||
{
|
||||
vec2 uv = (2.0 * fragCoord.xy - iResolution.xy) / iResolution.y;
|
||||
float battery = 1.0;
|
||||
//if (iMouse.x > 1.0 && iMouse.y > 1.0) battery = iMouse.y / iResolution.y;
|
||||
//else battery = 0.8;
|
||||
|
||||
//if (abs(uv.x) < (9.0 / 16.0))
|
||||
|
||||
// Grid
|
||||
float fog = smoothstep(0.1, -0.02, abs(uv.y + 0.2));
|
||||
vec3 col = vec3(0.0, 0.1, 0.2);
|
||||
if (uv.y < -0.2)
|
||||
{
|
||||
uv.y = 3.0 / (abs(uv.y + 0.2) + 0.05);
|
||||
uv.x *= uv.y * 1.0;
|
||||
float gridVal = grid(uv, battery);
|
||||
col = mix(col, vec3(1.0, 0.5, 1.0), gridVal);
|
||||
}
|
||||
else
|
||||
{
|
||||
float fujiD = min(uv.y * 4.5 - 0.5, 1.0);
|
||||
uv.y -= battery * 1.1 - 0.51;
|
||||
|
||||
vec2 sunUV = uv;
|
||||
vec2 fujiUV = uv;
|
||||
|
||||
// Sun
|
||||
sunUV += vec2(0.75, 0.2);
|
||||
//uv.y -= 1.1 - 0.51;
|
||||
col = vec3(1.0, 0.2, 1.0);
|
||||
float sunVal = sun(sunUV, battery);
|
||||
|
||||
col = mix(col, vec3(1.0, 0.4, 0.1), sunUV.y * 2.0 + 0.2);
|
||||
col = mix(vec3(0.0, 0.0, 0.0), col, sunVal);
|
||||
|
||||
// fuji
|
||||
float fujiVal = sdTrapezoid(uv + vec2(-0.75 + sunUV.y * 0.0, 0.5), 1.75 + pow(uv.y * uv.y, 2.1), 0.2, 0.5);
|
||||
float waveVal = uv.y + sin(uv.x * 20.0 + iTime * timeMultiplier * 2.0) * 0.05 + 0.2;
|
||||
float wave_width = smoothstep(0.0, 0.01, (waveVal));
|
||||
|
||||
// fuji color
|
||||
col = mix(col, mix(vec3(0.0, 0.0, 0.25), vec3(1.0, 0.0, 0.5), fujiD), step(fujiVal, 0.0));
|
||||
// fuji top snow
|
||||
col = mix(col, vec3(1.0, 0.5, 1.0), wave_width * step(fujiVal, 0.0));
|
||||
// fuji outline
|
||||
col = mix(col, vec3(1.0, 0.5, 1.0), 1.0 - smoothstep(0.0, 0.01, abs(fujiVal)));
|
||||
//col = mix( col, vec3(1.0, 1.0, 1.0), 1.0-smoothstep(0.03,0.04,abs(fujiVal)) );
|
||||
//col = vec3(1.0, 1.0, 1.0) *(1.0-smoothstep(0.03,0.04,abs(fujiVal)));
|
||||
|
||||
// horizon color
|
||||
col += mix(col, mix(vec3(1.0, 0.12, 0.8), vec3(0.0, 0.0, 0.2), clamp(uv.y * 3.5 + 3.0, 0.0, 1.0)), step(0.0, fujiVal));
|
||||
|
||||
// cloud
|
||||
vec2 cloudUV = uv;
|
||||
cloudUV.x = mod(cloudUV.x + iTime * timeMultiplier * 0.1, 4.0) - 2.0;
|
||||
float cloudTime = iTime * timeMultiplier * 0.5;
|
||||
float cloudY = -0.5;
|
||||
float cloudVal1 = sdCloud(cloudUV,
|
||||
vec2(0.1 + sin(cloudTime + 140.5) * 0.1, cloudY),
|
||||
vec2(1.05 + cos(cloudTime * 0.9 - 36.56) * 0.1, cloudY),
|
||||
vec2(0.2 + cos(cloudTime * 0.867 + 387.165) * 0.1, 0.25 + cloudY),
|
||||
vec2(0.5 + cos(cloudTime * 0.9675 - 15.162) * 0.09, 0.25 + cloudY), 0.075);
|
||||
cloudY = -0.6;
|
||||
float cloudVal2 = sdCloud(cloudUV,
|
||||
vec2(-0.9 + cos(cloudTime * 1.02 + 541.75) * 0.1, cloudY),
|
||||
vec2(-0.5 + sin(cloudTime * 0.9 - 316.56) * 0.1, cloudY),
|
||||
vec2(-1.5 + cos(cloudTime * 0.867 + 37.165) * 0.1, 0.25 + cloudY),
|
||||
vec2(-0.6 + sin(cloudTime * 0.9675 + 665.162) * 0.09, 0.25 + cloudY), 0.075);
|
||||
|
||||
float cloudVal = min(cloudVal1, cloudVal2);
|
||||
|
||||
//col = mix(col, vec3(1.0,1.0,0.0), smoothstep(0.0751, 0.075, cloudVal));
|
||||
col = mix(col, vec3(0.0, 0.0, 0.2), 1.0 - smoothstep(0.075 - 0.0001, 0.075, cloudVal));
|
||||
col += vec3(1.0, 1.0, 1.0) * (1.0 - smoothstep(0.0, 0.01, abs(cloudVal - 0.075)));
|
||||
}
|
||||
|
||||
col += fog * fog * fog;
|
||||
col = mix(vec3(col.r, col.r, col.r) * 0.5, col, battery * 0.7);
|
||||
|
||||
vec2 termUV = fragCoord.xy / iResolution.xy;
|
||||
vec4 terminalColor = texture(iChannel0, termUV);
|
||||
//
|
||||
float alpha = step(length(terminalColor.rgb), BLACK_BLEND_THRESHOLD);
|
||||
vec3 blendedColor = mix(terminalColor.rgb * 1.0, col.rgb * 0.1, alpha);
|
||||
//
|
||||
fragColor = vec4(blendedColor, terminalColor.a);
|
||||
}
|
||||
30
ghostty-shaders/dither.glsl
Normal file
30
ghostty-shaders/dither.glsl
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
// Simple "dithering" effect
|
||||
// (c) moni-dz (https://github.com/moni-dz)
|
||||
// CC BY-NC-SA 4.0 (https://creativecommons.org/licenses/by-nc-sa/4.0/)
|
||||
|
||||
// Packed bayer pattern using bit manipulation
|
||||
const float bayerPattern[4] = float[4](
|
||||
0x0514, // Encoding 0,8,2,10
|
||||
0xC4E6, // Encoding 12,4,14,6
|
||||
0x3B19, // Encoding 3,11,1,9
|
||||
0xF7D5 // Encoding 15,7,13,5
|
||||
);
|
||||
|
||||
float getBayerFromPacked(int x, int y) {
|
||||
int idx = (x & 3) + ((y & 3) << 2);
|
||||
return float((int(bayerPattern[y & 3]) >> ((x & 3) << 2)) & 0xF) * (1.0 / 16.0);
|
||||
}
|
||||
|
||||
#define LEVELS 2.0 // Available color steps per channel
|
||||
#define INV_LEVELS (1.0 / LEVELS)
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord)
|
||||
{
|
||||
vec2 uv = fragCoord * (1.0 / iResolution.xy);
|
||||
vec3 color = texture(iChannel0, uv).rgb;
|
||||
|
||||
float threshold = getBayerFromPacked(int(fragCoord.x), int(fragCoord.y));
|
||||
vec3 dithered = floor(color * LEVELS + threshold) * INV_LEVELS;
|
||||
|
||||
fragColor = vec4(dithered, 1.0);
|
||||
}
|
||||
68
ghostty-shaders/drunkard.glsl
Normal file
68
ghostty-shaders/drunkard.glsl
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
// Drunken stupor effect using fractal Brownian motion and Perlin noise
|
||||
// (c) moni-dz (https://github.com/moni-dz)
|
||||
// CC BY-NC-SA 4.0 (https://creativecommons.org/licenses/by-nc-sa/4.0/)
|
||||
|
||||
vec2 hash2(vec2 p) {
|
||||
uvec2 q = uvec2(floatBitsToUint(p.x), floatBitsToUint(p.y));
|
||||
q = (q * uvec2(1597334673U, 3812015801U)) ^ (q.yx * uvec2(2798796415U, 1979697793U));
|
||||
return vec2(q) * (1.0/float(0xffffffffU)) * 2.0 - 1.0;
|
||||
}
|
||||
|
||||
float perlin2d(vec2 p) {
|
||||
vec2 i = floor(p);
|
||||
vec2 f = fract(p);
|
||||
vec2 u = f*f*(3.0-2.0*f);
|
||||
|
||||
return mix(mix(dot(hash2(i + vec2(0.0,0.0)), f - vec2(0.0,0.0)),
|
||||
dot(hash2(i + vec2(1.0,0.0)), f - vec2(1.0,0.0)), u.x),
|
||||
mix(dot(hash2(i + vec2(0.0,1.0)), f - vec2(0.0,1.0)),
|
||||
dot(hash2(i + vec2(1.0,1.0)), f - vec2(1.0,1.0)), u.x), u.y);
|
||||
}
|
||||
|
||||
#define OCTAVES 10 // How many passes of fractal Brownian motion to perform
|
||||
#define GAIN 0.5 // How much should each pixel move
|
||||
#define LACUNARITY 2.0 // How fast should each ripple be per pass
|
||||
|
||||
float fbm(vec2 p) {
|
||||
float sum = 0.0;
|
||||
float amp = 0.5;
|
||||
float freq = 1.0;
|
||||
|
||||
for(int i = 0; i < OCTAVES; i++) {
|
||||
sum += amp * perlin2d(p * freq);
|
||||
freq *= LACUNARITY;
|
||||
amp *= GAIN;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
|
||||
#define NOISE_SCALE 1.0 // How distorted the image you want to be
|
||||
#define NOISE_INTENSITY 0.05 // How strong the noise effect is
|
||||
#define ABERRATION true // Chromatic aberration
|
||||
#define ABERRATION_DELTA 0.1 // How strong the chromatic aberration effect is
|
||||
#define ANIMATE true
|
||||
#define SPEED 0.4 // Animation speed
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord)
|
||||
{
|
||||
vec2 uv = fragCoord/iResolution.xy;
|
||||
float time = ANIMATE ? iTime * SPEED : 0.0;
|
||||
|
||||
vec2 noisePos = uv * NOISE_SCALE + vec2(time);
|
||||
float noise = fbm(noisePos) * NOISE_INTENSITY;
|
||||
|
||||
vec3 col;
|
||||
|
||||
if (ABERRATION) {
|
||||
col.r = texture(iChannel0, uv + vec2(noise * (1.0 + ABERRATION_DELTA))).r;
|
||||
col.g = texture(iChannel0, uv + vec2(noise)).g;
|
||||
col.b = texture(iChannel0, uv + vec2(noise * (1.0 - ABERRATION_DELTA))).b;
|
||||
} else {
|
||||
vec2 distortedUV = uv + vec2(noise);
|
||||
col = texture(iChannel0, distortedUV).rgb;
|
||||
}
|
||||
|
||||
fragColor = vec4(col, 1.0);
|
||||
}
|
||||
109
ghostty-shaders/fireworks-rockets.glsl
Normal file
109
ghostty-shaders/fireworks-rockets.glsl
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
// This Ghostty shader is a lightly modified port of https://www.shadertoy.com/view/4dBGRw
|
||||
|
||||
#define BLACK_BLEND_THRESHOLD .4
|
||||
|
||||
//Creates a diagonal red-and-white striped pattern.
|
||||
vec3 barberpole(vec2 pos, vec2 rocketpos) {
|
||||
float d = (pos.x - rocketpos.x) + (pos.y - rocketpos.y);
|
||||
vec3 col = vec3(1.0);
|
||||
|
||||
d = mod(d * 20., 2.0);
|
||||
if (d > 1.0) {
|
||||
col = vec3(1.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
vec3 rocket(vec2 pos, vec2 rocketpos) {
|
||||
vec3 col = vec3(0.0);
|
||||
float f = 0.;
|
||||
float absx = abs(rocketpos.x - pos.x);
|
||||
float absy = abs(rocketpos.y - pos.y);
|
||||
|
||||
// Wooden stick
|
||||
if (absx < 0.01 && absy < 0.22) {
|
||||
col = vec3(1.0, 0.5, 0.5);
|
||||
}
|
||||
|
||||
// Barberpole
|
||||
if (absx < 0.05 && absy < 0.15) {
|
||||
col = barberpole(pos, rocketpos);
|
||||
}
|
||||
|
||||
// Rocket Point
|
||||
float pointw = (rocketpos.y - pos.y - 0.25) * -0.7;
|
||||
if ((rocketpos.y - pos.y) > 0.1) {
|
||||
f = smoothstep(pointw - 0.001, pointw + 0.001, absx);
|
||||
|
||||
col = mix(vec3(1.0, 0.0, 0.0), col, f);
|
||||
}
|
||||
|
||||
// Shadow
|
||||
f = -.5 + smoothstep(-0.05, 0.05, (rocketpos.x - pos.x));
|
||||
col *= 0.7 + f;
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
float rand(float val, float seed) {
|
||||
return cos(val * sin(val * seed) * seed);
|
||||
}
|
||||
|
||||
float distance2(in vec2 a, in vec2 b) {
|
||||
return dot(a - b, a - b);
|
||||
}
|
||||
|
||||
mat2 rr = mat2(cos(1.0), -sin(1.0), sin(1.0), cos(1.0));
|
||||
|
||||
vec3 drawParticles(vec2 pos, vec3 particolor, float time, vec2 cpos, float gravity, float seed, float timelength) {
|
||||
vec3 col = vec3(0.0);
|
||||
vec2 pp = vec2(1.0, 0.0);
|
||||
for (float i = 1.0; i <= 128.0; i++) {
|
||||
float d = rand(i, seed);
|
||||
float fade = (i / 128.0) * time;
|
||||
vec2 particpos = cpos + time * pp * d;
|
||||
pp = rr * pp;
|
||||
col = mix(particolor / fade, col, smoothstep(0.0, 0.0001, distance2(particpos, pos)));
|
||||
}
|
||||
col *= smoothstep(0.0, 1.0, (timelength - time) / timelength);
|
||||
|
||||
return col;
|
||||
}
|
||||
vec3 drawFireworks(float time, vec2 uv, vec3 particolor, float seed) {
|
||||
float timeoffset = 2.0;
|
||||
vec3 col = vec3(0.0);
|
||||
if (time <= 0.) {
|
||||
return col;
|
||||
}
|
||||
if (mod(time, 6.0) > timeoffset) {
|
||||
col = drawParticles(uv, particolor, mod(time, 6.0) - timeoffset, vec2(rand(ceil(time / 6.0), seed), -0.5), 0.5, ceil(time / 6.0), seed);
|
||||
} else {
|
||||
col = rocket(uv * 3., vec2(3. * rand(ceil(time / 6.0), seed), 3. * (-0.5 + (timeoffset - mod(time, 6.0)))));
|
||||
}
|
||||
return col;
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord)
|
||||
{
|
||||
vec2 uv = 1.0 - 2.0 * fragCoord.xy / iResolution.xy;
|
||||
uv.x *= iResolution.x / iResolution.y;
|
||||
vec3 col = vec3(0.1, 0.1, 0.2);
|
||||
|
||||
// Flip the y-axis so that the rocket is drawn from the bottom of the screen
|
||||
uv.y = -uv.y;
|
||||
|
||||
col += 0.1 * uv.y;
|
||||
|
||||
col += drawFireworks(iTime, uv, vec3(1.0, 0.1, 0.1), 1.);
|
||||
col += drawFireworks(iTime - 2.0, uv, vec3(0.0, 1.0, 0.5), 2.);
|
||||
col += drawFireworks(iTime - 4.0, uv, vec3(1.0, 1.0, 0.1), 3.);
|
||||
|
||||
vec2 termUV = fragCoord.xy / iResolution.xy;
|
||||
vec4 terminalColor = texture(iChannel0, termUV);
|
||||
|
||||
float alpha = step(length(terminalColor.rgb), BLACK_BLEND_THRESHOLD);
|
||||
vec3 blendedColor = mix(terminalColor.rgb * 1.0, col.rgb * 0.3, alpha);
|
||||
|
||||
fragColor = vec4(blendedColor, terminalColor.a);
|
||||
}
|
||||
116
ghostty-shaders/fireworks.glsl
Normal file
116
ghostty-shaders/fireworks.glsl
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
// This Ghostty shader is a port of https://www.shadertoy.com/view/lscGRl
|
||||
|
||||
// "Fireworks" by Martijn Steinrucken aka BigWings - 2015
|
||||
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
|
||||
// Email:countfrolic@gmail.com Twitter:@The_ArtOfCode
|
||||
|
||||
#define BLACK_BLEND_THRESHOLD .4
|
||||
#define PI 3.141592653589793238
|
||||
#define TWOPI 6.283185307179586
|
||||
#define S(x,y,z) smoothstep(x,y,z)
|
||||
#define B(x,y,z,w) S(x-z, x+z, w)*S(y+z, y-z, w)
|
||||
#define saturate(x) clamp(x,0.,1.)
|
||||
|
||||
#define NUM_EXPLOSIONS 3.
|
||||
#define NUM_PARTICLES 42.
|
||||
|
||||
// Noise functions by Dave Hoskins
|
||||
#define MOD3 vec3(.1031,.11369,.13787)
|
||||
vec3 hash31(float p) {
|
||||
vec3 p3 = fract(vec3(p) * MOD3);
|
||||
p3 += dot(p3, p3.yzx + 19.19);
|
||||
return fract(vec3((p3.x + p3.y) * p3.z, (p3.x + p3.z) * p3.y, (p3.y + p3.z) * p3.x));
|
||||
}
|
||||
float hash12(vec2 p) {
|
||||
vec3 p3 = fract(vec3(p.xyx) * MOD3);
|
||||
p3 += dot(p3, p3.yzx + 19.19);
|
||||
return fract((p3.x + p3.y) * p3.z);
|
||||
}
|
||||
|
||||
float circ(vec2 uv, vec2 pos, float size) {
|
||||
uv -= pos;
|
||||
|
||||
size *= size;
|
||||
return S(size * 1.1, size, dot(uv, uv));
|
||||
}
|
||||
|
||||
float light(vec2 uv, vec2 pos, float size) {
|
||||
uv -= pos;
|
||||
|
||||
size *= size;
|
||||
return size / dot(uv, uv);
|
||||
}
|
||||
|
||||
vec3 explosion(vec2 uv, vec2 p, float seed, float t) {
|
||||
vec3 col = vec3(0.);
|
||||
|
||||
vec3 en = hash31(seed);
|
||||
vec3 baseCol = en;
|
||||
for (float i = 0.; i < NUM_PARTICLES; i++) {
|
||||
vec3 n = hash31(i) - .5;
|
||||
|
||||
vec2 startP = p - vec2(0., t * t * .1);
|
||||
vec2 endP = startP + normalize(n.xy) * n.z - vec2(0., t * .2);
|
||||
|
||||
float pt = 1. - pow(t - 1., 2.);
|
||||
vec2 pos = mix(p, endP, pt);
|
||||
float size = mix(.01, .005, S(0., .1, pt));
|
||||
size *= S(1., .1, pt);
|
||||
|
||||
float sparkle = (sin((pt + n.z) * 21.) * .5 + .5);
|
||||
sparkle = pow(sparkle, pow(en.x, 3.) * 50.) * mix(0.01, .01, en.y * n.y);
|
||||
|
||||
//size += sparkle*B(.6, 1., .1, t);
|
||||
size += sparkle * B(en.x, en.y, en.z, t);
|
||||
|
||||
col += baseCol * light(uv, pos, size);
|
||||
}
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
vec3 Rainbow(vec3 c) {
|
||||
float t = iTime;
|
||||
|
||||
float avg = (c.r + c.g + c.b) / 3.;
|
||||
c = avg + (c - avg) * sin(vec3(0., .333, .666) + t);
|
||||
|
||||
c += sin(vec3(.4, .3, .3) * t + vec3(1.1244, 3.43215, 6.435)) * vec3(.4, .1, .5);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord)
|
||||
{
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
uv.x -= .5;
|
||||
uv.x *= iResolution.x / iResolution.y;
|
||||
|
||||
// Flip the y-axis so that the gravity is downwards
|
||||
uv.y = -uv.y + 1.;
|
||||
|
||||
float n = hash12(uv + 10.);
|
||||
float t = iTime * .5;
|
||||
|
||||
vec3 c = vec3(0.);
|
||||
|
||||
for (float i = 0.; i < NUM_EXPLOSIONS; i++) {
|
||||
float et = t + i * 1234.45235;
|
||||
float id = floor(et);
|
||||
et -= id;
|
||||
|
||||
vec2 p = hash31(id).xy;
|
||||
p.x -= .5;
|
||||
p.x *= 1.6;
|
||||
c += explosion(uv, p, id, et);
|
||||
}
|
||||
c = Rainbow(c);
|
||||
|
||||
vec2 termUV = fragCoord.xy / iResolution.xy;
|
||||
vec4 terminalColor = texture(iChannel0, termUV);
|
||||
|
||||
float alpha = step(length(terminalColor.rgb), BLACK_BLEND_THRESHOLD);
|
||||
vec3 blendedColor = mix(terminalColor.rgb * 1.0, c.rgb * 0.3, alpha);
|
||||
|
||||
fragColor = vec4(blendedColor, terminalColor.a);
|
||||
}
|
||||
141
ghostty-shaders/galaxy.glsl
Normal file
141
ghostty-shaders/galaxy.glsl
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
const float timeMultiplier = 0.1f;
|
||||
|
||||
float triangle(float x, float period) {
|
||||
return 2.0 * abs(3.0* ((x / period) - floor((x / period) + 0.5))) - 1.0;
|
||||
}
|
||||
|
||||
float field(in vec3 position) {
|
||||
float strength = 7.0 + 0.03 * log(1.0e-6 + fract(sin(iTime*timeMultiplier) * 373.11));
|
||||
float accumulated = 0.0;
|
||||
float previousMagnitude = 0.0;
|
||||
float totalWeight = 0.0;
|
||||
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
float magnitude = dot(position, position);
|
||||
position = abs(position) / magnitude + vec3(-0.5, -0.8 + 0.1 * sin(-iTime*timeMultiplier * 0.1 + 2.0), -1.1 + 0.3 * cos(iTime*timeMultiplier * 0.3));
|
||||
float weight = exp(-float(i) / 7.0);
|
||||
accumulated += weight * exp(-strength * pow(abs(magnitude - previousMagnitude), 2.3));
|
||||
totalWeight += weight;
|
||||
previousMagnitude = magnitude;
|
||||
}
|
||||
|
||||
return max(0.0, 5.0 * accumulated / totalWeight - 0.7);
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
||||
const float baseSpeed = 0.02;
|
||||
const int maxIterations = 16;
|
||||
const float formulaParameter = 0.79;
|
||||
const float volumeSteps = 7.0;
|
||||
const float stepSize = 0.24;
|
||||
const float zoomFactor = 0.1;
|
||||
const float tilingFactor = 0.85;
|
||||
const float baseBrightness = 0.0008;
|
||||
const float darkMatter = 0.2;
|
||||
const float distanceFading = 0.56;
|
||||
const float colorSaturation = 0.9;
|
||||
const float transverseMotion = 0.2;
|
||||
const float cloudOpacity = 0.48;
|
||||
const float zoomSpeed = 0.0002;
|
||||
|
||||
vec2 normalizedCoordinates = 2.0 * fragCoord.xy / vec2(512) - 1.0;
|
||||
vec2 scaledCoordinates = normalizedCoordinates * vec2(512) / 512.0;
|
||||
|
||||
float timeElapsed = iTime*timeMultiplier;
|
||||
float speedAdjustment = -baseSpeed;
|
||||
float formulaAdjustment = formulaParameter;
|
||||
|
||||
speedAdjustment = zoomSpeed * cos(iTime*timeMultiplier * 0.02 + 3.1415926 / 4.0);
|
||||
|
||||
vec2 uvCoordinates = scaledCoordinates;
|
||||
|
||||
float rotationXZ = 0.9;
|
||||
float rotationYZ = -0.6;
|
||||
float rotationXY = 0.9 + iTime * timeMultiplier * 0.08;
|
||||
|
||||
mat2 rotationMatrixXZ = mat2(vec2(cos(rotationXZ), sin(rotationXZ)), vec2(-sin(rotationXZ), cos(rotationXZ)));
|
||||
mat2 rotationMatrixYZ = mat2(vec2(cos(rotationYZ), sin(rotationYZ)), vec2(-sin(rotationYZ), cos(rotationYZ)));
|
||||
mat2 rotationMatrixXY = mat2(vec2(cos(rotationXY), sin(rotationXY)), vec2(-sin(rotationXY), cos(rotationXY)));
|
||||
|
||||
vec2 canvasCenter = vec2(0.5, 0.5);
|
||||
vec3 rayDirection = vec3(uvCoordinates * zoomFactor, 1.0);
|
||||
vec3 cameraPosition = vec3(0.0, 0.0, 0.0);
|
||||
cameraPosition.x -= 2.0 * (canvasCenter.x - 0.5);
|
||||
cameraPosition.y -= 2.0 * (canvasCenter.y - 0.5);
|
||||
|
||||
vec3 forwardVector = vec3(0.0, 0.0, 1.0);
|
||||
cameraPosition.x += transverseMotion * cos(0.01 * iTime*timeMultiplier) + 0.001 * iTime * timeMultiplier;
|
||||
cameraPosition.y += transverseMotion * sin(0.01 * iTime*timeMultiplier) + 0.001 * iTime * timeMultiplier;
|
||||
cameraPosition.z += 0.003 * iTime*timeMultiplier;
|
||||
|
||||
rayDirection.xz *= rotationMatrixXZ;
|
||||
forwardVector.xz *= rotationMatrixXZ;
|
||||
rayDirection.yz *= rotationMatrixYZ;
|
||||
forwardVector.yz *= rotationMatrixYZ;
|
||||
|
||||
cameraPosition.xy *= -1.0 * rotationMatrixXY;
|
||||
cameraPosition.xz *= rotationMatrixXZ;
|
||||
cameraPosition.yz *= rotationMatrixYZ;
|
||||
|
||||
float zoomOffset = (timeElapsed - 3311.0) * speedAdjustment;
|
||||
cameraPosition += forwardVector * zoomOffset;
|
||||
float sampleOffset = mod(zoomOffset, stepSize);
|
||||
float normalizedSampleOffset = sampleOffset / stepSize;
|
||||
|
||||
float stepDistance = 0.24;
|
||||
float secondaryStepDistance = stepDistance + stepSize / 2.0;
|
||||
vec3 accumulatedColor = vec3(0.0);
|
||||
float fieldContribution = 0.0;
|
||||
vec3 backgroundColor = vec3(0.0);
|
||||
|
||||
for (float stepIndex = 0.0; stepIndex < volumeSteps; ++stepIndex) {
|
||||
vec3 primaryPosition = cameraPosition + (stepDistance + sampleOffset) * rayDirection;
|
||||
vec3 secondaryPosition = cameraPosition + (secondaryStepDistance + sampleOffset) * rayDirection;
|
||||
|
||||
primaryPosition = abs(vec3(tilingFactor) - mod(primaryPosition, vec3(tilingFactor * 2.0)));
|
||||
secondaryPosition = abs(vec3(tilingFactor) - mod(secondaryPosition, vec3(tilingFactor * 2.0)));
|
||||
|
||||
fieldContribution = field(secondaryPosition);
|
||||
|
||||
float particleAccumulator = 0.0, particleDistance = 0.0;
|
||||
for (int i = 0; i < maxIterations; ++i) {
|
||||
primaryPosition = abs(primaryPosition) / dot(primaryPosition, primaryPosition) - formulaAdjustment;
|
||||
float distanceChange = abs(length(primaryPosition) - particleDistance);
|
||||
particleAccumulator += i > 2 ? min(12.0, distanceChange) : distanceChange;
|
||||
particleDistance = length(primaryPosition);
|
||||
}
|
||||
particleAccumulator *= particleAccumulator * particleAccumulator;
|
||||
|
||||
float fadeFactor = pow(distanceFading, max(0.0, float(stepIndex) - normalizedSampleOffset));
|
||||
accumulatedColor += vec3(stepDistance, stepDistance * stepDistance, stepDistance * stepDistance * stepDistance * stepDistance)
|
||||
* particleAccumulator * baseBrightness * fadeFactor;
|
||||
backgroundColor += mix(0.4, 1.0, cloudOpacity) * vec3(1.8 * fieldContribution * fieldContribution * fieldContribution,
|
||||
1.4 * fieldContribution * fieldContribution, fieldContribution) * fadeFactor;
|
||||
stepDistance += stepSize;
|
||||
secondaryStepDistance += stepSize;
|
||||
}
|
||||
|
||||
accumulatedColor = mix(vec3(length(accumulatedColor)), accumulatedColor, colorSaturation);
|
||||
|
||||
vec4 foregroundColor = vec4(accumulatedColor * 0.01, 1.0);
|
||||
backgroundColor *= cloudOpacity;
|
||||
backgroundColor.b *= 1.8;
|
||||
backgroundColor.r *= 0.05;
|
||||
|
||||
backgroundColor.b = 0.5 * mix(backgroundColor.g, backgroundColor.b, 0.8);
|
||||
backgroundColor.g = 0.0;
|
||||
backgroundColor.bg = mix(backgroundColor.gb, backgroundColor.bg, 0.5 * (cos(iTime*timeMultiplier * 0.01) + 1.0));
|
||||
|
||||
vec2 terminalUV = fragCoord.xy / iResolution.xy;
|
||||
vec4 terminalColor = texture(iChannel0, terminalUV);
|
||||
|
||||
float brightnessThreshold = 0.1;
|
||||
float terminalBrightness = dot(terminalColor.rgb, vec3(0.2126, 0.7152, 0.0722));
|
||||
|
||||
if (terminalBrightness < brightnessThreshold) {
|
||||
fragColor = mix(terminalColor, vec4(foregroundColor.rgb + backgroundColor, 1.0), 0.24);
|
||||
} else {
|
||||
fragColor = terminalColor;
|
||||
}
|
||||
}
|
||||
|
||||
376
ghostty-shaders/gears-and-belts.glsl
Normal file
376
ghostty-shaders/gears-and-belts.glsl
Normal file
|
|
@ -0,0 +1,376 @@
|
|||
// sligltly modified version of https://www.shadertoy.com/view/DsVSDV
|
||||
// The only changes are done in the mainImage function
|
||||
// Ive added comments on what to modify
|
||||
// works really well with most colorschemes
|
||||
|
||||
const float timeMultiplier = 0.5f;
|
||||
|
||||
#define Rot(a) mat2(cos(a),-sin(a),sin(a),cos(a))
|
||||
#define antialiasing(n) n/min(iResolution.y,iResolution.x)
|
||||
#define S(d,b) smoothstep(antialiasing(3.0),b,d)
|
||||
#define B(p,s) max(abs(p).x-s.x,abs(p).y-s.y)
|
||||
#define deg45 .707
|
||||
#define R45(p) (( p + vec2(p.y,-p.x) ) *deg45)
|
||||
#define Tri(p,s) max(R45(p).x,max(R45(p).y,B(p,s)))
|
||||
#define DF(a,b) length(a) * cos( mod( atan(a.y,a.x)+6.28/(b*8.0), 6.28/((b*8.0)*0.5))+(b-1.)*6.28/(b*8.0) + vec2(0,11) )
|
||||
|
||||
float random(vec2 p) {
|
||||
return fract(sin(dot(p.xy, vec2(12.9898, 78.233))) * 43758.5453123);
|
||||
}
|
||||
|
||||
float innerGear(vec2 p, float dir) {
|
||||
p *= Rot(radians(-iTime * timeMultiplier * 45. + 45.) * dir);
|
||||
vec2 prevP = p;
|
||||
|
||||
//p*=Rot(radians(iTime*timeMultiplier*45.+20.));
|
||||
p = DF(p, 7.);
|
||||
p -= vec2(0.24);
|
||||
p *= Rot(deg45);
|
||||
float d = B(p, vec2(0.01, 0.06));
|
||||
p = prevP;
|
||||
float d2 = abs(length(p) - 0.42) - 0.02;
|
||||
d = min(d, d2);
|
||||
d2 = abs(length(p) - 0.578) - 0.02;
|
||||
d = min(d, d2);
|
||||
d2 = abs(length(p) - 0.499) - 0.005;
|
||||
d = min(d, d2);
|
||||
|
||||
p = DF(p, 7.);
|
||||
p -= vec2(0.43);
|
||||
p *= Rot(deg45);
|
||||
d2 = B(p, vec2(0.01, 0.04));
|
||||
d = min(d, d2);
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
vec3 pattern1(vec2 p, vec3 col, float dir) {
|
||||
vec2 prevP = p;
|
||||
float size = 0.499;
|
||||
float thick = 0.15;
|
||||
|
||||
p += vec2(size);
|
||||
float d = abs(length(p) - size) - thick;
|
||||
d = max(d, innerGear(p, dir));
|
||||
col = mix(col, vec3(1.), S(d, 0.0));
|
||||
|
||||
p = prevP;
|
||||
p -= vec2(size);
|
||||
d = abs(length(p) - size) - thick;
|
||||
d = max(d, innerGear(p, dir));
|
||||
col = mix(col, vec3(1.), S(d, 0.0));
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
vec3 pattern2(vec2 p, vec3 col, float dir) {
|
||||
vec2 prevP = p;
|
||||
float size = 0.33;
|
||||
float thick = 0.15;
|
||||
float thift = 0.0;
|
||||
float speed = 0.3;
|
||||
|
||||
p -= vec2(size, 0.);
|
||||
float d = B(p, vec2(size, thick));
|
||||
|
||||
p.x += thift;
|
||||
p.x -= iTime * timeMultiplier * speed * dir;
|
||||
p.x = mod(p.x, 0.08) - 0.04;
|
||||
d = max(d, B(p, vec2(0.011, thick)));
|
||||
p = prevP;
|
||||
d = max(-(abs(p.y) - 0.1), d);
|
||||
//d = min(B(p,vec2(1.,0.1)),d);
|
||||
p.y = abs(p.y) - 0.079;
|
||||
d = min(B(p, vec2(1., 0.02)), d);
|
||||
|
||||
p = prevP;
|
||||
p -= vec2(0.0, size);
|
||||
float d2 = B(p, vec2(thick, size));
|
||||
|
||||
p.y += thift;
|
||||
p.y += iTime * timeMultiplier * speed * dir;
|
||||
p.y = mod(p.y, 0.08) - 0.04;
|
||||
d2 = max(d2, B(p, vec2(thick, 0.011)));
|
||||
|
||||
p = prevP;
|
||||
d2 = max(-(abs(p.x) - 0.1), d2);
|
||||
d2 = min(B(p, vec2(0.005, 1.)), d2);
|
||||
p.x = abs(p.x) - 0.079;
|
||||
d2 = min(B(p, vec2(0.02, 1.)), d2);
|
||||
|
||||
d = min(d, d2);
|
||||
|
||||
p = prevP;
|
||||
p += vec2(0.0, size);
|
||||
d2 = B(p, vec2(thick, size));
|
||||
|
||||
p.y += thift;
|
||||
p.y -= iTime * timeMultiplier * speed * dir;
|
||||
p.y = mod(p.y, 0.08) - 0.04;
|
||||
d2 = max(d2, B(p, vec2(thick, 0.011)));
|
||||
|
||||
p = prevP;
|
||||
d2 = max(-(abs(p.x) - 0.1), d2);
|
||||
d2 = min(B(p, vec2(0.005, 1.)), d2);
|
||||
p.x = abs(p.x) - 0.079;
|
||||
d2 = min(B(p, vec2(0.02, 1.)), d2);
|
||||
|
||||
d = min(d, d2);
|
||||
|
||||
p = prevP;
|
||||
p += vec2(size, 0.0);
|
||||
d2 = B(p, vec2(size, thick));
|
||||
|
||||
p.x += thift;
|
||||
p.x += iTime * timeMultiplier * speed * dir;
|
||||
p.x = mod(p.x, 0.08) - 0.04;
|
||||
d2 = max(d2, B(p, vec2(0.011, thick)));
|
||||
d = min(d, d2);
|
||||
p = prevP;
|
||||
d = max(-(abs(p.y) - 0.1), d);
|
||||
d = min(B(p, vec2(1., 0.005)), d);
|
||||
p.y = abs(p.y) - 0.079;
|
||||
d = min(B(p, vec2(1., 0.02)), d);
|
||||
|
||||
p = prevP;
|
||||
d2 = abs(B(p, vec2(size * 0.3))) - 0.05;
|
||||
d = min(d, d2);
|
||||
|
||||
col = mix(col, vec3(1.), S(d, 0.0));
|
||||
|
||||
d = B(p, vec2(0.08));
|
||||
col = mix(col, vec3(0.), S(d, 0.0));
|
||||
|
||||
p *= Rot(radians(60. * iTime * timeMultiplier * dir));
|
||||
d = B(p, vec2(0.03));
|
||||
col = mix(col, vec3(1.), S(d, 0.0));
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
vec3 drawBelt(vec2 p, vec3 col, float size) {
|
||||
vec2 prevP = p;
|
||||
|
||||
p *= size;
|
||||
vec2 id = floor(p);
|
||||
vec2 gr = fract(p) - 0.5;
|
||||
float dir = mod(id.x + id.y, 2.) * 2. - 1.;
|
||||
float n = random(id);
|
||||
|
||||
if (n < 0.5) {
|
||||
if (n < 0.25) {
|
||||
gr.x *= -1.;
|
||||
}
|
||||
col = pattern1(gr, col, dir);
|
||||
} else {
|
||||
if (n > 0.75) {
|
||||
gr.x *= -1.;
|
||||
}
|
||||
col = pattern2(gr, col, dir);
|
||||
}
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
vec3 gear(vec2 p, vec3 col, float dir) {
|
||||
vec2 prevP = p;
|
||||
|
||||
p *= Rot(radians(iTime * timeMultiplier * 45. + 13.) * -dir);
|
||||
p = DF(p, 7.);
|
||||
p -= vec2(0.23);
|
||||
p *= Rot(deg45);
|
||||
float d = B(p, vec2(0.01, 0.04));
|
||||
p = prevP;
|
||||
float d2 = abs(length(p) - 0.29) - 0.02;
|
||||
d = min(d, d2);
|
||||
col = mix(col, vec3(1.), S(d, 0.0));
|
||||
|
||||
p *= Rot(radians(iTime * timeMultiplier * 30. - 30.) * dir);
|
||||
p = DF(p, 6.);
|
||||
p -= vec2(0.14);
|
||||
p *= Rot(radians(45.));
|
||||
d = B(p, vec2(0.01, 0.03));
|
||||
p = prevP;
|
||||
d2 = abs(length(p) - 0.1) - 0.02;
|
||||
p *= Rot(radians(iTime * timeMultiplier * 25. + 30.) * -dir);
|
||||
d2 = max(-(abs(p.x) - 0.05), d2);
|
||||
d = min(d, d2);
|
||||
col = mix(col, vec3(1.), S(d, 0.0));
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
vec3 item0(vec2 p, vec3 col, float dir) {
|
||||
vec2 prevP = p;
|
||||
p.x *= dir;
|
||||
p *= Rot(radians(iTime * timeMultiplier * 30. + 30.));
|
||||
float d = abs(length(p) - 0.2) - 0.05;
|
||||
col = mix(col, vec3(0.3), S(d, 0.0));
|
||||
|
||||
d = abs(length(p) - 0.2) - 0.05;
|
||||
d = max(-p.x, d);
|
||||
float a = clamp(atan(p.x, p.y) * 0.5, 0.3, 1.);
|
||||
|
||||
col = mix(col, vec3(a), S(d, 0.0));
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
vec3 item1(vec2 p, vec3 col, float dir) {
|
||||
p.x *= dir;
|
||||
vec2 prevP = p;
|
||||
p *= Rot(radians(iTime * timeMultiplier * 30. + 30.));
|
||||
float d = abs(length(p) - 0.25) - 0.04;
|
||||
d = abs(max((abs(p.y) - 0.15), d)) - 0.005;
|
||||
float d2 = abs(length(p) - 0.25) - 0.01;
|
||||
d2 = max((abs(p.y) - 0.12), d2);
|
||||
d = min(d, d2);
|
||||
|
||||
d2 = abs(length(p) - 0.27) - 0.01;
|
||||
d2 = max(-(abs(p.y) - 0.22), d2);
|
||||
d = min(d, d2);
|
||||
d2 = B(p, vec2(0.01, 0.32));
|
||||
d2 = max(-(abs(p.y) - 0.22), d2);
|
||||
d = min(d, d2);
|
||||
|
||||
p = prevP;
|
||||
p *= Rot(radians(iTime * timeMultiplier * -20. + 30.));
|
||||
p = DF(p, 2.);
|
||||
p -= vec2(0.105);
|
||||
p *= Rot(radians(45.));
|
||||
d2 = B(p, vec2(0.03, 0.01));
|
||||
d = min(d, d2);
|
||||
|
||||
p = prevP;
|
||||
d2 = abs(length(p) - 0.09) - 0.005;
|
||||
d2 = max(-(abs(p.x) - 0.03), d2);
|
||||
d2 = max(-(abs(p.y) - 0.03), d2);
|
||||
d = min(d, d2);
|
||||
|
||||
col = mix(col, vec3(0.6), S(d, 0.0));
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
vec3 item2(vec2 p, vec3 col, float dir) {
|
||||
p.x *= dir;
|
||||
p *= Rot(radians(iTime * timeMultiplier * 50. - 10.));
|
||||
vec2 prevP = p;
|
||||
float d = abs(length(p) - 0.15) - 0.005;
|
||||
float d2 = abs(length(p) - 0.2) - 0.01;
|
||||
d2 = max((abs(p.y) - 0.15), d2);
|
||||
d = min(d, d2);
|
||||
|
||||
p = DF(p, 1.);
|
||||
p -= vec2(0.13);
|
||||
p *= Rot(radians(45.));
|
||||
d2 = B(p, vec2(0.008, 0.1));
|
||||
d = min(d, d2);
|
||||
|
||||
p = prevP;
|
||||
p = DF(p, 4.);
|
||||
p -= vec2(0.18);
|
||||
p *= Rot(radians(45.));
|
||||
d2 = B(p, vec2(0.005, 0.02));
|
||||
d = min(d, d2);
|
||||
|
||||
col = mix(col, vec3(0.6), S(d, 0.0));
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
float needle(vec2 p) {
|
||||
p.y -= 0.05;
|
||||
p *= 1.5;
|
||||
vec2 prevP = p;
|
||||
p.y -= 0.3;
|
||||
p.x *= 6.;
|
||||
float d = Tri(p, vec2(0.3));
|
||||
p = prevP;
|
||||
p.y += 0.1;
|
||||
p.x *= 2.;
|
||||
p.y *= -1.;
|
||||
float d2 = Tri(p, vec2(0.1));
|
||||
d = min(d, d2);
|
||||
return d;
|
||||
}
|
||||
|
||||
vec3 item3(vec2 p, vec3 col, float dir) {
|
||||
p *= Rot(radians(sin(iTime * timeMultiplier * dir) * 120.));
|
||||
vec2 prevP = p;
|
||||
|
||||
p.y = abs(p.y) - 0.05;
|
||||
float d = needle(p);
|
||||
p = prevP;
|
||||
float d2 = abs(length(p) - 0.1) - 0.003;
|
||||
d2 = max(-(abs(p.x) - 0.05), d2);
|
||||
d = min(d, d2);
|
||||
d2 = abs(length(p) - 0.2) - 0.005;
|
||||
d2 = max(-(abs(p.x) - 0.08), d2);
|
||||
d = min(d, d2);
|
||||
|
||||
p = DF(p, 4.);
|
||||
p -= vec2(0.18);
|
||||
d2 = length(p) - 0.01;
|
||||
p = prevP;
|
||||
d2 = max(-(abs(p.x) - 0.03), d2);
|
||||
d = min(d, d2);
|
||||
|
||||
col = mix(col, vec3(0.6), S(d, 0.0));
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
vec3 drawGearsAndItems(vec2 p, vec3 col, float size) {
|
||||
vec2 prevP = p;
|
||||
p *= size;
|
||||
p += vec2(0.5);
|
||||
|
||||
vec2 id = floor(p);
|
||||
vec2 gr = fract(p) - 0.5;
|
||||
|
||||
float n = random(id);
|
||||
float dir = mod(id.x + id.y, 2.) * 2. - 1.;
|
||||
if (n < 0.3) {
|
||||
col = gear(gr, col, dir);
|
||||
} else if (n >= 0.3 && n < 0.5) {
|
||||
col = item0(gr, col, dir);
|
||||
} else if (n >= 0.5 && n < 0.7) {
|
||||
col = item1(gr, col, dir);
|
||||
} else if (n >= 0.7 && n < 0.8) {
|
||||
col = item2(gr, col, dir);
|
||||
} else if (n >= 0.8) {
|
||||
col = item3(gr, col, dir);
|
||||
}
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord)
|
||||
{
|
||||
vec2 p = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;
|
||||
// set speed of downwards motion
|
||||
p.y += iTime * timeMultiplier * 0.02;
|
||||
|
||||
float size = 4.;
|
||||
vec3 col = vec3(0.);
|
||||
|
||||
// Modify the colors to be darker by multiplying with a small factor
|
||||
vec3 darkFactor = vec3(.5); // This makes everything 50% as bright
|
||||
|
||||
// Get the original colors but make them darker
|
||||
col = drawBelt(p, col, size) * darkFactor;
|
||||
col = drawGearsAndItems(p, col, size) * darkFactor;
|
||||
|
||||
// Additional option: you can add a color tint to make it less stark white
|
||||
vec3 tint = vec3(0.1, 0.12, 0.15); // Slight blue-ish dark tint
|
||||
col = col * tint;
|
||||
|
||||
vec2 uv = fragCoord / iResolution.xy;
|
||||
vec4 terminalColor = texture(iChannel0, uv);
|
||||
|
||||
// Blend with reduced opacity for the shader elements
|
||||
vec3 blendedColor = terminalColor.rgb + col.rgb * 0.7; // Reduced blend factor
|
||||
|
||||
fragColor = vec4(blendedColor, terminalColor.a);
|
||||
}
|
||||
117
ghostty-shaders/glitchy.glsl
Normal file
117
ghostty-shaders/glitchy.glsl
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
// modified version of https://www.shadertoy.com/view/wld3WN
|
||||
// amount of seconds for which the glitch loop occurs
|
||||
#define DURATION 10.
|
||||
// percentage of the duration for which the glitch is triggered
|
||||
#define AMT .1
|
||||
|
||||
#define SS(a, b, x) (smoothstep(a, b, x) * smoothstep(b, a, x))
|
||||
|
||||
#define UI0 1597334673U
|
||||
#define UI1 3812015801U
|
||||
#define UI2 uvec2(UI0, UI1)
|
||||
#define UI3 uvec3(UI0, UI1, 2798796415U)
|
||||
#define UIF (1. / float(0xffffffffU))
|
||||
|
||||
// Hash by David_Hoskins
|
||||
vec3 hash33(vec3 p)
|
||||
{
|
||||
uvec3 q = uvec3(ivec3(p)) * UI3;
|
||||
q = (q.x ^ q.y ^ q.z)*UI3;
|
||||
return -1. + 2. * vec3(q) * UIF;
|
||||
}
|
||||
|
||||
// Gradient noise by iq
|
||||
float gnoise(vec3 x)
|
||||
{
|
||||
// grid
|
||||
vec3 p = floor(x);
|
||||
vec3 w = fract(x);
|
||||
|
||||
// quintic interpolant
|
||||
vec3 u = w * w * w * (w * (w * 6. - 15.) + 10.);
|
||||
|
||||
// gradients
|
||||
vec3 ga = hash33(p + vec3(0., 0., 0.));
|
||||
vec3 gb = hash33(p + vec3(1., 0., 0.));
|
||||
vec3 gc = hash33(p + vec3(0., 1., 0.));
|
||||
vec3 gd = hash33(p + vec3(1., 1., 0.));
|
||||
vec3 ge = hash33(p + vec3(0., 0., 1.));
|
||||
vec3 gf = hash33(p + vec3(1., 0., 1.));
|
||||
vec3 gg = hash33(p + vec3(0., 1., 1.));
|
||||
vec3 gh = hash33(p + vec3(1., 1., 1.));
|
||||
|
||||
// projections
|
||||
float va = dot(ga, w - vec3(0., 0., 0.));
|
||||
float vb = dot(gb, w - vec3(1., 0., 0.));
|
||||
float vc = dot(gc, w - vec3(0., 1., 0.));
|
||||
float vd = dot(gd, w - vec3(1., 1., 0.));
|
||||
float ve = dot(ge, w - vec3(0., 0., 1.));
|
||||
float vf = dot(gf, w - vec3(1., 0., 1.));
|
||||
float vg = dot(gg, w - vec3(0., 1., 1.));
|
||||
float vh = dot(gh, w - vec3(1., 1., 1.));
|
||||
|
||||
// interpolation
|
||||
float gNoise = va + u.x * (vb - va) +
|
||||
u.y * (vc - va) +
|
||||
u.z * (ve - va) +
|
||||
u.x * u.y * (va - vb - vc + vd) +
|
||||
u.y * u.z * (va - vc - ve + vg) +
|
||||
u.z * u.x * (va - vb - ve + vf) +
|
||||
u.x * u.y * u.z * (-va + vb + vc - vd + ve - vf - vg + vh);
|
||||
|
||||
return 2. * gNoise;
|
||||
}
|
||||
|
||||
// gradient noise in range [0, 1]
|
||||
float gnoise01(vec3 x)
|
||||
{
|
||||
return .5 + .5 * gnoise(x);
|
||||
}
|
||||
|
||||
// warp uvs for the crt effect
|
||||
vec2 crt(vec2 uv)
|
||||
{
|
||||
float tht = atan(uv.y, uv.x);
|
||||
float r = length(uv);
|
||||
// curve without distorting the center
|
||||
r /= (1. - .1 * r * r);
|
||||
uv.x = r * cos(tht);
|
||||
uv.y = r * sin(tht);
|
||||
return .5 * (uv + 1.);
|
||||
}
|
||||
|
||||
|
||||
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||
{
|
||||
vec2 uv = fragCoord / iResolution.xy;
|
||||
float t = iTime;
|
||||
|
||||
// smoothed interval for which the glitch gets triggered
|
||||
float glitchAmount = SS(DURATION * .001, DURATION * AMT, mod(t, DURATION));
|
||||
float displayNoise = 0.;
|
||||
vec3 col = vec3(0.);
|
||||
vec2 eps = vec2(5. / iResolution.x, 0.);
|
||||
vec2 st = vec2(0.);
|
||||
|
||||
// analog distortion
|
||||
float y = uv.y * iResolution.y;
|
||||
float distortion = gnoise(vec3(0., y * .01, t * 500.)) * (glitchAmount * 4. + .1);
|
||||
distortion *= gnoise(vec3(0., y * .02, t * 250.)) * (glitchAmount * 2. + .025);
|
||||
|
||||
++displayNoise;
|
||||
distortion += smoothstep(.999, 1., sin((uv.y + t * 1.6) * 2.)) * .02;
|
||||
distortion -= smoothstep(.999, 1., sin((uv.y + t) * 2.)) * .02;
|
||||
st = uv + vec2(distortion, 0.);
|
||||
// chromatic aberration
|
||||
col.r += textureLod(iChannel0, st + eps + distortion, 0.).r;
|
||||
col.g += textureLod(iChannel0, st, 0.).g;
|
||||
col.b += textureLod(iChannel0, st - eps - distortion, 0.).b;
|
||||
|
||||
// white noise + scanlines
|
||||
displayNoise = 0.2 * clamp(displayNoise, 0., 1.);
|
||||
col += (.15 + .65 * glitchAmount) * (hash33(vec3(fragCoord, mod(float(iFrame),
|
||||
1000.))).r) * displayNoise;
|
||||
col -= (.25 + .75 * glitchAmount) * (sin(4. * t + uv.y * iResolution.y * 1.75))
|
||||
* displayNoise;
|
||||
fragColor = vec4(col, 1.0);
|
||||
}
|
||||
144
ghostty-shaders/glow-rgbsplit-twitchy.glsl
Normal file
144
ghostty-shaders/glow-rgbsplit-twitchy.glsl
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
// First it does a "chromatic aberration" by splitting the rgb signals by a product of sin functions
|
||||
// over time, then it does a glow effect in a perceptual color space
|
||||
// Based on kalgynirae's Ghostty passable glow shader and NickWest's Chromatic Aberration shader demo
|
||||
// Passable glow: https://github.com/kalgynirae/dotfiles/blob/main/ghostty/glow.glsl
|
||||
// "Chromatic Aberration": https://www.shadertoy.com/view/Mds3zn
|
||||
|
||||
// sRGB linear -> nonlinear transform from https://bottosson.github.io/posts/colorwrong/
|
||||
float f(float x) {
|
||||
if (x >= 0.0031308) {
|
||||
return 1.055 * pow(x, 1.0 / 2.4) - 0.055;
|
||||
} else {
|
||||
return 12.92 * x;
|
||||
}
|
||||
}
|
||||
|
||||
float f_inv(float x) {
|
||||
if (x >= 0.04045) {
|
||||
return pow((x + 0.055) / 1.055, 2.4);
|
||||
} else {
|
||||
return x / 12.92;
|
||||
}
|
||||
}
|
||||
|
||||
// Oklab <-> linear sRGB conversions from https://bottosson.github.io/posts/oklab/
|
||||
vec4 toOklab(vec4 rgb) {
|
||||
vec3 c = vec3(f_inv(rgb.r), f_inv(rgb.g), f_inv(rgb.b));
|
||||
float l = 0.4122214708 * c.r + 0.5363325363 * c.g + 0.0514459929 * c.b;
|
||||
float m = 0.2119034982 * c.r + 0.6806995451 * c.g + 0.1073969566 * c.b;
|
||||
float s = 0.0883024619 * c.r + 0.2817188376 * c.g + 0.6299787005 * c.b;
|
||||
float l_ = pow(l, 1.0 / 3.0);
|
||||
float m_ = pow(m, 1.0 / 3.0);
|
||||
float s_ = pow(s, 1.0 / 3.0);
|
||||
return vec4(
|
||||
0.2104542553 * l_ + 0.7936177850 * m_ - 0.0040720468 * s_,
|
||||
1.9779984951 * l_ - 2.4285922050 * m_ + 0.4505937099 * s_,
|
||||
0.0259040371 * l_ + 0.7827717662 * m_ - 0.8086757660 * s_,
|
||||
rgb.a
|
||||
);
|
||||
}
|
||||
|
||||
vec4 toRgb(vec4 oklab) {
|
||||
vec3 c = oklab.rgb;
|
||||
float l_ = c.r + 0.3963377774 * c.g + 0.2158037573 * c.b;
|
||||
float m_ = c.r - 0.1055613458 * c.g - 0.0638541728 * c.b;
|
||||
float s_ = c.r - 0.0894841775 * c.g - 1.2914855480 * c.b;
|
||||
float l = l_ * l_ * l_;
|
||||
float m = m_ * m_ * m_;
|
||||
float s = s_ * s_ * s_;
|
||||
vec3 linear_srgb = vec3(
|
||||
4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,
|
||||
-1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,
|
||||
-0.0041960863 * l - 0.7034186147 * m + 1.7076147010 * s
|
||||
);
|
||||
return vec4(
|
||||
clamp(f(linear_srgb.r), 0.0, 1.0),
|
||||
clamp(f(linear_srgb.g), 0.0, 1.0),
|
||||
clamp(f(linear_srgb.b), 0.0, 1.0),
|
||||
oklab.a
|
||||
);
|
||||
}
|
||||
|
||||
// Bloom samples from https://gist.github.com/qwerasd205/c3da6c610c8ffe17d6d2d3cc7068f17f
|
||||
const vec3[24] samples = {
|
||||
vec3(0.1693761725038636, 0.9855514761735895, 1),
|
||||
vec3(-1.333070830962943, 0.4721463328627773, 0.7071067811865475),
|
||||
vec3(-0.8464394909806497, -1.51113870578065, 0.5773502691896258),
|
||||
vec3(1.554155680728463, -1.2588090085709776, 0.5),
|
||||
vec3(1.681364377589461, 1.4741145918052656, 0.4472135954999579),
|
||||
vec3(-1.2795157692199817, 2.088741103228784, 0.4082482904638631),
|
||||
vec3(-2.4575847530631187, -0.9799373355024756, 0.3779644730092272),
|
||||
vec3(0.5874641440200847, -2.7667464429345077, 0.35355339059327373),
|
||||
vec3(2.997715703369726, 0.11704939884745152, 0.3333333333333333),
|
||||
vec3(0.41360842451688395, 3.1351121305574803, 0.31622776601683794),
|
||||
vec3(-3.167149933769243, 0.9844599011770256, 0.30151134457776363),
|
||||
vec3(-1.5736713846521535, -3.0860263079123245, 0.2886751345948129),
|
||||
vec3(2.888202648340422, -2.1583061557896213, 0.2773500981126146),
|
||||
vec3(2.7150778983300325, 2.5745586041105715, 0.2672612419124244),
|
||||
vec3(-2.1504069972377464, 3.2211410627650165, 0.2581988897471611),
|
||||
vec3(-3.6548858794907493, -1.6253643308191343, 0.25),
|
||||
vec3(1.0130775986052671, -3.9967078676335834, 0.24253562503633297),
|
||||
vec3(4.229723673607257, 0.33081361055181563, 0.23570226039551587),
|
||||
vec3(0.40107790291173834, 4.340407413572593, 0.22941573387056174),
|
||||
vec3(-4.319124570236028, 1.159811599693438, 0.22360679774997896),
|
||||
vec3(-1.9209044802827355, -4.160543952132907, 0.2182178902359924),
|
||||
vec3(3.8639122286635708, -2.6589814382925123, 0.21320071635561041),
|
||||
vec3(3.3486228404946234, 3.4331800232609, 0.20851441405707477),
|
||||
vec3(-2.8769733643574344, 3.9652268864187157, 0.20412414523193154)
|
||||
};
|
||||
|
||||
float offsetFunction(float iTime) {
|
||||
float amount = 1.0;
|
||||
const float periods[4] = {6.0, 16.0, 19.0, 27.0};
|
||||
for (int i = 0; i < 4; i++) {
|
||||
amount *= 1.0 + 0.5 * sin(iTime*periods[i]);
|
||||
}
|
||||
//return amount;
|
||||
return amount * periods[3];
|
||||
}
|
||||
|
||||
const float DIM_CUTOFF = 0.35;
|
||||
const float BRIGHT_CUTOFF = 0.65;
|
||||
const float ABBERATION_FACTOR = 0.05;
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
|
||||
float amount = offsetFunction(iTime);
|
||||
|
||||
vec3 col;
|
||||
col.r = texture( iChannel0, vec2(uv.x-ABBERATION_FACTOR*amount / iResolution.x, uv.y) ).r;
|
||||
col.g = texture( iChannel0, uv ).g;
|
||||
col.b = texture( iChannel0, vec2(uv.x+ABBERATION_FACTOR*amount / iResolution.x, uv.y) ).b;
|
||||
|
||||
vec4 splittedColor = vec4(col, 1.0);
|
||||
vec4 source = toOklab(splittedColor);
|
||||
vec4 dest = source;
|
||||
|
||||
if (source.x > DIM_CUTOFF) {
|
||||
dest.x *= 1.2;
|
||||
// dest.x = 1.2;
|
||||
} else {
|
||||
vec2 step = vec2(1.414) / iResolution.xy;
|
||||
vec3 glow = vec3(0.0);
|
||||
for (int i = 0; i < 24; i++) {
|
||||
vec3 s = samples[i];
|
||||
float weight = s.z;
|
||||
vec4 c = toOklab(texture(iChannel0, uv + s.xy * step));
|
||||
if (c.x > DIM_CUTOFF) {
|
||||
glow.yz += c.yz * weight * 0.3;
|
||||
if (c.x <= BRIGHT_CUTOFF) {
|
||||
glow.x += c.x * weight * 0.05;
|
||||
} else {
|
||||
glow.x += c.x * weight * 0.10;
|
||||
}
|
||||
}
|
||||
}
|
||||
// float lightness_diff = clamp(glow.x - dest.x, 0.0, 1.0);
|
||||
// dest.x = lightness_diff;
|
||||
// dest.yz = dest.yz * (1.0 - lightness_diff) + glow.yz * lightness_diff;
|
||||
dest.xyz += glow.xyz;
|
||||
}
|
||||
|
||||
fragColor = toRgb(dest);
|
||||
}
|
||||
25
ghostty-shaders/gradient-background.glsl
Normal file
25
ghostty-shaders/gradient-background.glsl
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
// credits: https://github.com/unkn0wncode
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord)
|
||||
{
|
||||
// Normalize pixel coordinates (range from 0 to 1)
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
|
||||
// Create a gradient from bottom right to top left as a function (x + y)/2
|
||||
float gradientFactor = (uv.x + uv.y) / 2.0;
|
||||
|
||||
// Define gradient colors (adjust to your preference)
|
||||
vec3 gradientStartColor = vec3(0.1, 0.1, 0.5); // Start color (e.g., dark blue)
|
||||
vec3 gradientEndColor = vec3(0.5, 0.1, 0.1); // End color (e.g., dark red)
|
||||
|
||||
vec3 gradientColor = mix(gradientStartColor, gradientEndColor, gradientFactor);
|
||||
|
||||
// Sample the terminal screen texture including alpha channel
|
||||
vec4 terminalColor = texture(iChannel0, uv);
|
||||
|
||||
// Make a mask that is 1.0 where the terminal content is not black
|
||||
float mask = 1 - step(0.5, dot(terminalColor.rgb, vec3(1.0)));
|
||||
vec3 blendedColor = mix(terminalColor.rgb, gradientColor, mask);
|
||||
|
||||
// Apply terminal's alpha to control overall opacity
|
||||
fragColor = vec4(blendedColor, terminalColor.a);
|
||||
}
|
||||
304
ghostty-shaders/in-game-crt.glsl
Normal file
304
ghostty-shaders/in-game-crt.glsl
Normal file
|
|
@ -0,0 +1,304 @@
|
|||
// In-game CRT shader
|
||||
// Author: sarphiv
|
||||
// License: CC BY-NC-SA 4.0
|
||||
// Description:
|
||||
// Shader for ghostty that is focussed on being usable while looking like a stylized CRT terminal in a modern video game.
|
||||
// I know a tiny bit about shaders, and nothing about GLSL,
|
||||
// so this is a Frakenstein's monster combination of other shaders together with a lot of surgery.
|
||||
// On the bright side, i've cleaned up the body parts and surgery a lot.
|
||||
|
||||
// Based on:
|
||||
// 1. https://gist.github.com/mitchellh/39d62186910dcc27cad097fed16eb882 (forces the choice of license)
|
||||
// 2. https://gist.github.com/qwerasd205/c3da6c610c8ffe17d6d2d3cc7068f17f
|
||||
// 3. https://gist.github.com/seanwcom/0fbe6b270aaa5f28823e053d3dbb14ca
|
||||
|
||||
|
||||
// Settings:
|
||||
// How straight the terminal is in each axis
|
||||
// (x, y) \in R^2 : x, y > 0
|
||||
#define CURVE 13.0, 11.0
|
||||
|
||||
// How far apart the different colors are from each other
|
||||
// x \in R
|
||||
#define COLOR_FRINGING_SPREAD 1.0
|
||||
|
||||
// How much the ghost images are spread out
|
||||
// x \in R : x >= 0
|
||||
#define GHOSTING_SPREAD 0.75
|
||||
// How visible ghost images are
|
||||
// x \in R : x >= 0
|
||||
#define GHOSTING_STRENGTH 1.0
|
||||
|
||||
// How much of the non-linearly darkened colors are mixed in
|
||||
// [0, 1]
|
||||
#define DARKEN_MIX 0.4
|
||||
|
||||
// How far in the vignette spreads
|
||||
// x \in R : x >= 0
|
||||
#define VIGNETTE_SPREAD 0.3
|
||||
// How bright the vignette is
|
||||
// x \in R : x >= 0
|
||||
#define VIGNETTE_BRIGHTNESS 6.4
|
||||
|
||||
// Tint all colors
|
||||
// [0, 1]^3
|
||||
#define TINT 0.93, 1.00, 0.96
|
||||
|
||||
// How visible the scan line effect is
|
||||
// NOTE: Technically these are not scan lines, but rather the lack of them
|
||||
// [0, 1]
|
||||
#define SCAN_LINES_STRENGTH 0.15
|
||||
// How bright the spaces between the lines are
|
||||
// [0, 1]
|
||||
#define SCAN_LINES_VARIANCE 0.35
|
||||
// Pixels per scan line effect
|
||||
// x \in R : x > 0
|
||||
#define SCAN_LINES_PERIOD 4.0
|
||||
|
||||
// How visible the aperture grille is
|
||||
// x \in R : x >= 0
|
||||
#define APERTURE_GRILLE_STRENGTH 0.2
|
||||
// Pixels per aperture grille
|
||||
// x \in R : x > 0
|
||||
#define APERTURE_GRILLE_PERIOD 2.0
|
||||
|
||||
// How much the screen flickers
|
||||
// x \in R : x >= 0
|
||||
#define FLICKER_STRENGTH 0.05
|
||||
// How fast the screen flickers
|
||||
// x \in R : x > 0
|
||||
#define FLICKER_FREQUENCY 15.0
|
||||
|
||||
// How much noise is added to filled areas
|
||||
// [0, 1]
|
||||
#define NOISE_CONTENT_STRENGTH 0.15
|
||||
// How much noise is added everywhere
|
||||
// [0, 1]
|
||||
#define NOISE_UNIFORM_STRENGTH 0.03
|
||||
|
||||
// How big the bloom is
|
||||
// x \in R : x >= 0
|
||||
#define BLOOM_SPREAD 8.0
|
||||
// How visible the bloom is
|
||||
// [0, 1]
|
||||
#define BLOOM_STRENGTH 0.04
|
||||
|
||||
// How fast colors fade in and out
|
||||
// [0, 1]
|
||||
#define FADE_FACTOR 0.55
|
||||
|
||||
|
||||
|
||||
// Disabled values for when the settings are not defined
|
||||
#ifndef COLOR_FRINGING_SPREAD
|
||||
#define COLOR_FRINGING_SPREAD 0.0
|
||||
#endif
|
||||
|
||||
#if !defined(GHOSTING_SPREAD) || !defined(GHOSTING_STRENGTH)
|
||||
#undef GHOSTING_SPREAD
|
||||
#undef GHOSTING_STRENGTH
|
||||
#define GHOSTING_SPREAD 0.0
|
||||
#define GHOSTING_STRENGTH 0.0
|
||||
#endif
|
||||
|
||||
#ifndef DARKEN_MIX
|
||||
#define DARKEN_MIX 0.0
|
||||
#endif
|
||||
|
||||
#if !defined(VIGNETTE_SPREAD) || !defined(VIGNETTE_BRIGHTNESS)
|
||||
#undef VIGNETTE_SPREAD
|
||||
#undef VIGNETTE_BRIGHTNESS
|
||||
#define VIGNETTE_SPREAD 0.0
|
||||
#define VIGNETTE_BRIGHTNESS 1.0
|
||||
#endif
|
||||
|
||||
#ifndef TINT
|
||||
#define TINT 1.00, 1.00, 1.00
|
||||
#endif
|
||||
|
||||
#if !defined(SCAN_LINES_STRENGTH) || !defined(SCAN_LINES_VARIANCE) || !defined(SCAN_LINES_PERIOD)
|
||||
#undef SCAN_LINES_STRENGTH
|
||||
#undef SCAN_LINES_VARIANCE
|
||||
#undef SCAN_LINES_PERIOD
|
||||
#define SCAN_LINES_STRENGTH 0.0
|
||||
#define SCAN_LINES_VARIANCE 1.0
|
||||
#define SCAN_LINES_PERIOD 1.0
|
||||
#endif
|
||||
|
||||
#if !defined(APERTURE_GRILLE_STRENGTH) || !defined(APERTURE_GRILLE_PERIOD)
|
||||
#undef APERTURE_GRILLE_STRENGTH
|
||||
#undef APERTURE_GRILLE_PERIOD
|
||||
#define APERTURE_GRILLE_STRENGTH 0.0
|
||||
#define APERTURE_GRILLE_PERIOD 1.0
|
||||
#endif
|
||||
|
||||
#if !defined(FLICKER_STRENGTH) || !defined(FLICKER_FREQUENCY)
|
||||
#undef FLICKER_STRENGTH
|
||||
#undef FLICKER_FREQUENCY
|
||||
#define FLICKER_STRENGTH 0.0
|
||||
#define FLICKER_FREQUENCY 1.0
|
||||
#endif
|
||||
|
||||
#if !defined(NOISE_CONTENT_STRENGTH) || !defined(NOISE_UNIFORM_STRENGTH)
|
||||
#undef NOISE_CONTENT_STRENGTH
|
||||
#undef NOISE_UNIFORM_STRENGTH
|
||||
#define NOISE_CONTENT_STRENGTH 0.0
|
||||
#define NOISE_UNIFORM_STRENGTH 0.0
|
||||
#endif
|
||||
|
||||
#if !defined(BLOOM_SPREAD) || !defined(BLOOM_STRENGTH)
|
||||
#undef BLOOM_SPREAD
|
||||
#undef BLOOM_STRENGTH
|
||||
#define BLOOM_SPREAD 0.0
|
||||
#define BLOOM_STRENGTH 0.0
|
||||
#endif
|
||||
|
||||
#ifndef FADE_FACTOR
|
||||
#define FADE_FACTOR 1.00
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// Constants
|
||||
#define PI 3.1415926535897932384626433832795
|
||||
|
||||
#ifdef BLOOM_SPREAD
|
||||
// Golden spiral samples used for bloom.
|
||||
// [x, y, weight] weight is inverse of distance.
|
||||
const vec3[24] bloom_samples = {
|
||||
vec3( 0.1693761725038636, 0.9855514761735895, 1),
|
||||
vec3(-1.333070830962943, 0.4721463328627773, 0.7071067811865475),
|
||||
vec3(-0.8464394909806497, -1.51113870578065, 0.5773502691896258),
|
||||
vec3( 1.554155680728463, -1.2588090085709776, 0.5),
|
||||
vec3( 1.681364377589461, 1.4741145918052656, 0.4472135954999579),
|
||||
vec3(-1.2795157692199817, 2.088741103228784, 0.4082482904638631),
|
||||
vec3(-2.4575847530631187, -0.9799373355024756, 0.3779644730092272),
|
||||
vec3( 0.5874641440200847, -2.7667464429345077, 0.35355339059327373),
|
||||
vec3( 2.997715703369726, 0.11704939884745152, 0.3333333333333333),
|
||||
vec3( 0.41360842451688395, 3.1351121305574803, 0.31622776601683794),
|
||||
vec3(-3.167149933769243, 0.9844599011770256, 0.30151134457776363),
|
||||
vec3(-1.5736713846521535, -3.0860263079123245, 0.2886751345948129),
|
||||
vec3( 2.888202648340422, -2.1583061557896213, 0.2773500981126146),
|
||||
vec3( 2.7150778983300325, 2.5745586041105715, 0.2672612419124244),
|
||||
vec3(-2.1504069972377464, 3.2211410627650165, 0.2581988897471611),
|
||||
vec3(-3.6548858794907493, -1.6253643308191343, 0.25),
|
||||
vec3( 1.0130775986052671, -3.9967078676335834, 0.24253562503633297),
|
||||
vec3( 4.229723673607257, 0.33081361055181563, 0.23570226039551587),
|
||||
vec3( 0.40107790291173834, 4.340407413572593, 0.22941573387056174),
|
||||
vec3(-4.319124570236028, 1.159811599693438, 0.22360679774997896),
|
||||
vec3(-1.9209044802827355, -4.160543952132907, 0.2182178902359924),
|
||||
vec3( 3.8639122286635708, -2.6589814382925123, 0.21320071635561041),
|
||||
vec3( 3.3486228404946234, 3.4331800232609, 0.20851441405707477),
|
||||
vec3(-2.8769733643574344, 3.9652268864187157, 0.20412414523193154)
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
||||
// Get texture coordinates
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
|
||||
#ifdef CURVE
|
||||
// Curve texture coordinates to mimic non-flat CRT monior
|
||||
uv = (uv - 0.5) * 2.0;
|
||||
uv.xy *= 1.0 + pow((abs(vec2(uv.y, uv.x)) / vec2(CURVE)), vec2(2.0));
|
||||
uv = (uv / 2.0) + 0.5;
|
||||
#endif
|
||||
|
||||
|
||||
// Retrieve colors from appropriate locations
|
||||
fragColor.r = texture(iChannel0, vec2(uv.x + 0.0003 * COLOR_FRINGING_SPREAD, uv.y + 0.0003 * COLOR_FRINGING_SPREAD)).x;
|
||||
fragColor.g = texture(iChannel0, vec2(uv.x + 0.0000 * COLOR_FRINGING_SPREAD, uv.y - 0.0006 * COLOR_FRINGING_SPREAD)).y;
|
||||
fragColor.b = texture(iChannel0, vec2(uv.x - 0.0006 * COLOR_FRINGING_SPREAD, uv.y + 0.0000 * COLOR_FRINGING_SPREAD)).z;
|
||||
fragColor.a = texture(iChannel0, uv).a;
|
||||
|
||||
|
||||
// Add faint ghost images
|
||||
fragColor.r += 0.04 * GHOSTING_STRENGTH * texture(iChannel0, GHOSTING_SPREAD * vec2(+0.025, -0.027) + uv.xy).x;
|
||||
fragColor.g += 0.02 * GHOSTING_STRENGTH * texture(iChannel0, GHOSTING_SPREAD * vec2(-0.022, -0.020) + uv.xy).y;
|
||||
fragColor.b += 0.04 * GHOSTING_STRENGTH * texture(iChannel0, GHOSTING_SPREAD * vec2(-0.020, -0.018) + uv.xy).z;
|
||||
|
||||
|
||||
// Quadratically darken everything
|
||||
fragColor.rgb = mix(fragColor.rgb, fragColor.rgb*fragColor.rgb, DARKEN_MIX);
|
||||
|
||||
|
||||
// Vignette effect
|
||||
fragColor.rgb *= VIGNETTE_BRIGHTNESS * pow(uv.x * uv.y * (1.0-uv.x) * (1.0-uv.y), VIGNETTE_SPREAD);
|
||||
|
||||
|
||||
// Tint all colors
|
||||
fragColor.rgb *= vec3(TINT);
|
||||
|
||||
|
||||
// NOTE: At this point, RGB values may be above 1
|
||||
|
||||
|
||||
// Add scan lines effect
|
||||
fragColor.rgb *= mix(
|
||||
1.0,
|
||||
SCAN_LINES_VARIANCE/2.0*(1.0 + sin(2*PI* uv.y * iResolution.y/SCAN_LINES_PERIOD)),
|
||||
SCAN_LINES_STRENGTH
|
||||
);
|
||||
|
||||
|
||||
// Add aperture grille
|
||||
int aperture_grille_step = int(8 * mod(fragCoord.x, APERTURE_GRILLE_PERIOD) / APERTURE_GRILLE_PERIOD);
|
||||
float aperture_grille_mask;
|
||||
|
||||
if (aperture_grille_step < 3)
|
||||
aperture_grille_mask = 0.0;
|
||||
else if (aperture_grille_step < 4)
|
||||
aperture_grille_mask = mod(8*fragCoord.x, APERTURE_GRILLE_PERIOD) / APERTURE_GRILLE_PERIOD;
|
||||
else if (aperture_grille_step < 7)
|
||||
aperture_grille_mask = 1.0;
|
||||
else if (aperture_grille_step < 8)
|
||||
aperture_grille_mask = mod(-8*fragCoord.x, APERTURE_GRILLE_PERIOD) / APERTURE_GRILLE_PERIOD;
|
||||
|
||||
fragColor.rgb *= 1.0 - APERTURE_GRILLE_STRENGTH*aperture_grille_mask;
|
||||
|
||||
|
||||
// Add flicker
|
||||
fragColor *= 1.0 - FLICKER_STRENGTH/2.0*(1.0 + sin(2*PI*FLICKER_FREQUENCY*iTime));
|
||||
|
||||
|
||||
// Add noise
|
||||
// NOTE: Hard-coded noise distributions
|
||||
float noiseContent = smoothstep(0.4, 0.6, fract(sin(uv.x * uv.y * (1.0-uv.x) * (1.0-uv.y) * iTime * 4096.0) * 65536.0));
|
||||
float noiseUniform = smoothstep(0.4, 0.6, fract(sin(uv.x * uv.y * (1.0-uv.x) * (1.0-uv.y) * iTime * 8192.0) * 65536.0));
|
||||
fragColor.rgb *= clamp(noiseContent + 1.0 - NOISE_CONTENT_STRENGTH, 0.0, 1.0);
|
||||
fragColor.rgb = clamp(fragColor.rgb + noiseUniform * NOISE_UNIFORM_STRENGTH, 0.0, 1.0);
|
||||
|
||||
|
||||
// NOTE: At this point, RGB values are again within [0, 1]
|
||||
|
||||
|
||||
// Remove output outside of screen bounds
|
||||
if (uv.x < 0.0 || uv.x > 1.0)
|
||||
fragColor.rgb *= 0.0;
|
||||
if (uv.y < 0.0 || uv.y > 1.0)
|
||||
fragColor.rgb *= 0.0;
|
||||
|
||||
|
||||
#ifdef BLOOM_SPREAD
|
||||
// Add bloom
|
||||
vec2 step = BLOOM_SPREAD * vec2(1.414) / iResolution.xy;
|
||||
|
||||
for (int i = 0; i < 24; i++) {
|
||||
vec3 bloom_sample = bloom_samples[i];
|
||||
vec4 neighbor = texture(iChannel0, uv + bloom_sample.xy * step);
|
||||
float luminance = 0.299 * neighbor.r + 0.587 * neighbor.g + 0.114 * neighbor.b;
|
||||
|
||||
fragColor += luminance * bloom_sample.z * neighbor * BLOOM_STRENGTH;
|
||||
}
|
||||
|
||||
fragColor = clamp(fragColor, 0.0, 1.0);
|
||||
#endif
|
||||
|
||||
|
||||
// Add fade effect to smoothen out color transitions
|
||||
// NOTE: May need to be iTime/iTimeDelta dependent
|
||||
fragColor = vec4(FADE_FACTOR*fragColor.rgb, FADE_FACTOR);
|
||||
}
|
||||
413
ghostty-shaders/inside-the-matrix.glsl
Normal file
413
ghostty-shaders/inside-the-matrix.glsl
Normal file
|
|
@ -0,0 +1,413 @@
|
|||
/*
|
||||
Feel free to do anything you want with this code.
|
||||
This shader uses "runes" code by FabriceNeyret2 (https://www.shadertoy.com/view/4ltyDM)
|
||||
which is based on "runes" by otaviogood (https://shadertoy.com/view/MsXSRn).
|
||||
These random runes look good as matrix symbols and have acceptable performance.
|
||||
|
||||
@pkazmier modified this shader to work in Ghostty.
|
||||
*/
|
||||
|
||||
const int ITERATIONS = 40; //use less value if you need more performance
|
||||
const float SPEED = .5;
|
||||
|
||||
const float STRIP_CHARS_MIN = 7.;
|
||||
const float STRIP_CHARS_MAX = 40.;
|
||||
const float STRIP_CHAR_HEIGHT = 0.15;
|
||||
const float STRIP_CHAR_WIDTH = 0.10;
|
||||
const float ZCELL_SIZE = 1. * (STRIP_CHAR_HEIGHT * STRIP_CHARS_MAX); //the multiplier can't be less than 1.
|
||||
const float XYCELL_SIZE = 12. * STRIP_CHAR_WIDTH; //the multiplier can't be less than 1.
|
||||
|
||||
const int BLOCK_SIZE = 10; //in cells
|
||||
const int BLOCK_GAP = 2; //in cells
|
||||
|
||||
const float WALK_SPEED = 0.5 * XYCELL_SIZE;
|
||||
const float BLOCKS_BEFORE_TURN = 3.;
|
||||
|
||||
|
||||
const float PI = 3.14159265359;
|
||||
|
||||
|
||||
// ---- random ----
|
||||
|
||||
float hash(float v) {
|
||||
return fract(sin(v)*43758.5453123);
|
||||
}
|
||||
|
||||
float hash(vec2 v) {
|
||||
return hash(dot(v, vec2(5.3983, 5.4427)));
|
||||
}
|
||||
|
||||
vec2 hash2(vec2 v)
|
||||
{
|
||||
v = vec2(v * mat2(127.1, 311.7, 269.5, 183.3));
|
||||
return fract(sin(v)*43758.5453123);
|
||||
}
|
||||
|
||||
vec4 hash4(vec2 v)
|
||||
{
|
||||
vec4 p = vec4(v * mat4x2( 127.1, 311.7,
|
||||
269.5, 183.3,
|
||||
113.5, 271.9,
|
||||
246.1, 124.6 ));
|
||||
return fract(sin(p)*43758.5453123);
|
||||
}
|
||||
|
||||
vec4 hash4(vec3 v)
|
||||
{
|
||||
vec4 p = vec4(v * mat4x3( 127.1, 311.7, 74.7,
|
||||
269.5, 183.3, 246.1,
|
||||
113.5, 271.9, 124.6,
|
||||
271.9, 269.5, 311.7 ) );
|
||||
return fract(sin(p)*43758.5453123);
|
||||
}
|
||||
|
||||
|
||||
// ---- symbols ----
|
||||
// Slightly modified version of "runes" by FabriceNeyret2 - https://www.shadertoy.com/view/4ltyDM
|
||||
// Which is based on "runes" by otaviogood - https://shadertoy.com/view/MsXSRn
|
||||
|
||||
float rune_line(vec2 p, vec2 a, vec2 b) { // from https://www.shadertoy.com/view/4dcfW8
|
||||
p -= a, b -= a;
|
||||
float h = clamp(dot(p, b) / dot(b, b), 0., 1.); // proj coord on line
|
||||
return length(p - b * h); // dist to segment
|
||||
}
|
||||
|
||||
float rune(vec2 U, vec2 seed, float highlight)
|
||||
{
|
||||
float d = 1e5;
|
||||
for (int i = 0; i < 4; i++) // number of strokes
|
||||
{
|
||||
vec4 pos = hash4(seed);
|
||||
seed += 1.;
|
||||
|
||||
// each rune touches the edge of its box on all 4 sides
|
||||
if (i == 0) pos.y = .0;
|
||||
if (i == 1) pos.x = .999;
|
||||
if (i == 2) pos.x = .0;
|
||||
if (i == 3) pos.y = .999;
|
||||
// snap the random line endpoints to a grid 2x3
|
||||
vec4 snaps = vec4(2, 3, 2, 3);
|
||||
pos = ( floor(pos * snaps) + .5) / snaps;
|
||||
|
||||
if (pos.xy != pos.zw) //filter out single points (when start and end are the same)
|
||||
d = min(d, rune_line(U, pos.xy, pos.zw + .001) ); // closest line
|
||||
}
|
||||
return smoothstep(0.1, 0., d) + highlight*smoothstep(0.4, 0., d);
|
||||
}
|
||||
|
||||
float random_char(vec2 outer, vec2 inner, float highlight) {
|
||||
vec2 seed = vec2(dot(outer, vec2(269.5, 183.3)), dot(outer, vec2(113.5, 271.9)));
|
||||
return rune(inner, seed, highlight);
|
||||
}
|
||||
|
||||
|
||||
// ---- digital rain ----
|
||||
|
||||
// xy - horizontal, z - vertical
|
||||
vec3 rain(vec3 ro3, vec3 rd3, float time) {
|
||||
vec4 result = vec4(0.);
|
||||
|
||||
// normalized 2d projection
|
||||
vec2 ro2 = vec2(ro3);
|
||||
vec2 rd2 = normalize(vec2(rd3));
|
||||
|
||||
// we use formulas `ro3 + rd3 * t3` and `ro2 + rd2 * t2`, `t3_to_t2` is a multiplier to convert t3 to t2
|
||||
bool prefer_dx = abs(rd2.x) > abs(rd2.y);
|
||||
float t3_to_t2 = prefer_dx ? rd3.x / rd2.x : rd3.y / rd2.y;
|
||||
|
||||
// at first, horizontal space (xy) is divided into cells (which are columns in 3D)
|
||||
// then each xy-cell is divided into vertical cells (along z) - each of these cells contains one raindrop
|
||||
|
||||
ivec3 cell_side = ivec3(step(0., rd3)); //for positive rd.x use cell side with higher x (1) as the next side, for negative - with lower x (0), the same for y and z
|
||||
ivec3 cell_shift = ivec3(sign(rd3)); //shift to move to the next cell
|
||||
|
||||
// move through xy-cells in the ray direction
|
||||
float t2 = 0.; // the ray formula is: ro2 + rd2 * t2, where t2 is positive as the ray has a direction.
|
||||
ivec2 next_cell = ivec2(floor(ro2/XYCELL_SIZE)); //first cell index where ray origin is located
|
||||
for (int i=0; i<ITERATIONS; i++) {
|
||||
ivec2 cell = next_cell; //save cell value before changing
|
||||
float t2s = t2; //and t
|
||||
|
||||
// find the intersection with the nearest side of the current xy-cell (since we know the direction, we only need to check one vertical side and one horizontal side)
|
||||
vec2 side = vec2(next_cell + cell_side.xy) * XYCELL_SIZE; //side.x is x coord of the y-axis side, side.y - y of the x-axis side
|
||||
vec2 t2_side = (side - ro2) / rd2; // t2_side.x and t2_side.y are two candidates for the next value of t2, we need the nearest
|
||||
if (t2_side.x < t2_side.y) {
|
||||
t2 = t2_side.x;
|
||||
next_cell.x += cell_shift.x; //cross through the y-axis side
|
||||
} else {
|
||||
t2 = t2_side.y;
|
||||
next_cell.y += cell_shift.y; //cross through the x-axis side
|
||||
}
|
||||
//now t2 is the value of the end point in the current cell (and the same point is the start value in the next cell)
|
||||
|
||||
// gap cells
|
||||
vec2 cell_in_block = fract(vec2(cell) / float(BLOCK_SIZE));
|
||||
float gap = float(BLOCK_GAP) / float(BLOCK_SIZE);
|
||||
if (cell_in_block.x < gap || cell_in_block.y < gap || (cell_in_block.x < (gap+0.1) && cell_in_block.y < (gap+0.1))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// return to 3d - we have start and end points of the ray segment inside the column (t3s and t3e)
|
||||
float t3s = t2s / t3_to_t2;
|
||||
|
||||
// move through z-cells of the current column in the ray direction (don't need much to check, two nearest cells are enough)
|
||||
float pos_z = ro3.z + rd3.z * t3s;
|
||||
float xycell_hash = hash(vec2(cell));
|
||||
float z_shift = xycell_hash*11. - time * (0.5 + xycell_hash * 1.0 + xycell_hash * xycell_hash * 1.0 + pow(xycell_hash, 16.) * 3.0); //a different z shift for each xy column
|
||||
float char_z_shift = floor(z_shift / STRIP_CHAR_HEIGHT);
|
||||
z_shift = char_z_shift * STRIP_CHAR_HEIGHT;
|
||||
int zcell = int(floor((pos_z - z_shift)/ZCELL_SIZE)); //z-cell index
|
||||
for (int j=0; j<2; j++) { //2 iterations is enough if camera doesn't look much up or down
|
||||
// calcaulate coordinates of the target (raindrop)
|
||||
vec4 cell_hash = hash4(vec3(ivec3(cell, zcell)));
|
||||
vec4 cell_hash2 = fract(cell_hash * vec4(127.1, 311.7, 271.9, 124.6));
|
||||
|
||||
float chars_count = cell_hash.w * (STRIP_CHARS_MAX - STRIP_CHARS_MIN) + STRIP_CHARS_MIN;
|
||||
float target_length = chars_count * STRIP_CHAR_HEIGHT;
|
||||
float target_rad = STRIP_CHAR_WIDTH / 2.;
|
||||
float target_z = (float(zcell)*ZCELL_SIZE + z_shift) + cell_hash.z * (ZCELL_SIZE - target_length);
|
||||
vec2 target = vec2(cell) * XYCELL_SIZE + target_rad + cell_hash.xy * (XYCELL_SIZE - target_rad*2.);
|
||||
|
||||
// We have a line segment (t0,t). Now calculate the distance between line segment and cell target (it's easier in 2d)
|
||||
vec2 s = target - ro2;
|
||||
float tmin = dot(s, rd2); //tmin - point with minimal distance to target
|
||||
if (tmin >= t2s && tmin <= t2) {
|
||||
float u = s.x * rd2.y - s.y * rd2.x; //horizontal coord in the matrix strip
|
||||
if (abs(u) < target_rad) {
|
||||
u = (u/target_rad + 1.) / 2.;
|
||||
float z = ro3.z + rd3.z * tmin/t3_to_t2;
|
||||
float v = (z - target_z) / target_length; //vertical coord in the matrix strip
|
||||
if (v >= 0.0 && v < 1.0) {
|
||||
float c = floor(v * chars_count); //symbol index relative to the start of the strip, with addition of char_z_shift it becomes an index relative to the whole cell
|
||||
float q = fract(v * chars_count);
|
||||
vec2 char_hash = hash2(vec2(c+char_z_shift, cell_hash2.x));
|
||||
if (char_hash.x >= 0.1 || c == 0.) { //10% of missed symbols
|
||||
float time_factor = floor(c == 0. ? time*5.0 : //first symbol is changed fast
|
||||
time*(1.0*cell_hash2.z + //strips are changed sometime with different speed
|
||||
cell_hash2.w*cell_hash2.w*4.*pow(char_hash.y, 4.))); //some symbols in some strips are changed relatively often
|
||||
float a = random_char(vec2(char_hash.x, time_factor), vec2(u,q), max(1., 3. - c/2.)*0.2); //alpha
|
||||
a *= clamp((chars_count - 0.5 - c) / 2., 0., 1.); //tail fade
|
||||
if (a > 0.) {
|
||||
float attenuation = 1. + pow(0.06*tmin/t3_to_t2, 2.);
|
||||
vec3 col = (c == 0. ? vec3(0.67, 1.0, 0.82) : vec3(0.25, 0.80, 0.40)) / attenuation;
|
||||
float a1 = result.a;
|
||||
result.a = a1 + (1. - a1) * a;
|
||||
result.xyz = (result.xyz * a1 + col * (1. - a1) * a) / result.a;
|
||||
if (result.a > 0.98) return result.xyz;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// not found in this cell - go to next vertical cell
|
||||
zcell += cell_shift.z;
|
||||
}
|
||||
// go to next horizontal cell
|
||||
}
|
||||
|
||||
return result.xyz * result.a;
|
||||
}
|
||||
|
||||
|
||||
// ---- main, camera ----
|
||||
|
||||
vec2 rotate(vec2 v, float a) {
|
||||
float s = sin(a);
|
||||
float c = cos(a);
|
||||
mat2 m = mat2(c, -s, s, c);
|
||||
return m * v;
|
||||
}
|
||||
|
||||
vec3 rotateX(vec3 v, float a) {
|
||||
float s = sin(a);
|
||||
float c = cos(a);
|
||||
return mat3(1.,0.,0.,0.,c,-s,0.,s,c) * v;
|
||||
}
|
||||
|
||||
vec3 rotateY(vec3 v, float a) {
|
||||
float s = sin(a);
|
||||
float c = cos(a);
|
||||
return mat3(c,0.,-s,0.,1.,0.,s,0.,c) * v;
|
||||
}
|
||||
|
||||
vec3 rotateZ(vec3 v, float a) {
|
||||
float s = sin(a);
|
||||
float c = cos(a);
|
||||
return mat3(c,-s,0.,s,c,0.,0.,0.,1.) * v;
|
||||
}
|
||||
|
||||
float smoothstep1(float x) {
|
||||
return smoothstep(0., 1., x);
|
||||
}
|
||||
|
||||
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||
{
|
||||
if (STRIP_CHAR_WIDTH > XYCELL_SIZE || STRIP_CHAR_HEIGHT * STRIP_CHARS_MAX > ZCELL_SIZE) {
|
||||
// error
|
||||
fragColor = vec4(1., 0., 0., 1.);
|
||||
return;
|
||||
}
|
||||
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
|
||||
float time = iTime * SPEED;
|
||||
|
||||
const float turn_rad = 0.25 / BLOCKS_BEFORE_TURN; //0 .. 0.5
|
||||
const float turn_abs_time = (PI/2.*turn_rad) * 1.5; //multiplier different than 1 means a slow down on turns
|
||||
const float turn_time = turn_abs_time / (1. - 2.*turn_rad + turn_abs_time); //0..1, but should be <= 0.5
|
||||
|
||||
float level1_size = float(BLOCK_SIZE) * BLOCKS_BEFORE_TURN * XYCELL_SIZE;
|
||||
float level2_size = 4. * level1_size;
|
||||
float gap_size = float(BLOCK_GAP) * XYCELL_SIZE;
|
||||
|
||||
vec3 ro = vec3(gap_size/2., gap_size/2., 0.);
|
||||
vec3 rd = vec3(uv.x, 2.0, uv.y);
|
||||
|
||||
float tq = fract(time / (level2_size*4.) * WALK_SPEED); //the whole cycle time counter
|
||||
float t8 = fract(tq*4.); //time counter while walking on one of the four big sides
|
||||
float t1 = fract(t8*8.); //time counter while walking on one of the eight sides of the big side
|
||||
|
||||
vec2 prev;
|
||||
vec2 dir;
|
||||
if (tq < 0.25) {
|
||||
prev = vec2(0.,0.);
|
||||
dir = vec2(0.,1.);
|
||||
} else if (tq < 0.5) {
|
||||
prev = vec2(0.,1.);
|
||||
dir = vec2(1.,0.);
|
||||
} else if (tq < 0.75) {
|
||||
prev = vec2(1.,1.);
|
||||
dir = vec2(0.,-1.);
|
||||
} else {
|
||||
prev = vec2(1.,0.);
|
||||
dir = vec2(-1.,0.);
|
||||
}
|
||||
float angle = floor(tq * 4.); //0..4 wich means 0..2*PI
|
||||
|
||||
prev *= 4.;
|
||||
|
||||
const float first_turn_look_angle = 0.4;
|
||||
const float second_turn_drift_angle = 0.5;
|
||||
const float fifth_turn_drift_angle = 0.25;
|
||||
|
||||
vec2 turn;
|
||||
float turn_sign = 0.;
|
||||
vec2 dirL = rotate(dir, -PI/2.);
|
||||
vec2 dirR = -dirL;
|
||||
float up_down = 0.;
|
||||
float rotate_on_turns = 1.;
|
||||
float roll_on_turns = 1.;
|
||||
float add_angel = 0.;
|
||||
if (t8 < 0.125) {
|
||||
turn = dirL;
|
||||
//dir = dir;
|
||||
turn_sign = -1.;
|
||||
angle -= first_turn_look_angle * (max(0., t1 - (1. - turn_time*2.)) / turn_time - max(0., t1 - (1. - turn_time)) / turn_time * 2.5);
|
||||
roll_on_turns = 0.;
|
||||
} else if (t8 < 0.250) {
|
||||
prev += dir;
|
||||
turn = dir;
|
||||
dir = dirL;
|
||||
angle -= 1.;
|
||||
turn_sign = 1.;
|
||||
add_angel += first_turn_look_angle*0.5 + (-first_turn_look_angle*0.5+1.0+second_turn_drift_angle)*t1;
|
||||
rotate_on_turns = 0.;
|
||||
roll_on_turns = 0.;
|
||||
} else if (t8 < 0.375) {
|
||||
prev += dir + dirL;
|
||||
turn = dirR;
|
||||
//dir = dir;
|
||||
turn_sign = 1.;
|
||||
add_angel += second_turn_drift_angle*sqrt(1.-t1);
|
||||
//roll_on_turns = 0.;
|
||||
} else if (t8 < 0.5) {
|
||||
prev += dir + dir + dirL;
|
||||
turn = dirR;
|
||||
dir = dirR;
|
||||
angle += 1.;
|
||||
turn_sign = 0.;
|
||||
up_down = sin(t1*PI) * 0.37;
|
||||
} else if (t8 < 0.625) {
|
||||
prev += dir + dir;
|
||||
turn = dir;
|
||||
dir = dirR;
|
||||
angle += 1.;
|
||||
turn_sign = -1.;
|
||||
up_down = sin(-min(1., t1/(1.-turn_time))*PI) * 0.37;
|
||||
} else if (t8 < 0.750) {
|
||||
prev += dir + dir + dirR;
|
||||
turn = dirL;
|
||||
//dir = dir;
|
||||
turn_sign = -1.;
|
||||
add_angel -= (fifth_turn_drift_angle + 1.) * smoothstep1(t1);
|
||||
rotate_on_turns = 0.;
|
||||
roll_on_turns = 0.;
|
||||
} else if (t8 < 0.875) {
|
||||
prev += dir + dir + dir + dirR;
|
||||
turn = dir;
|
||||
dir = dirL;
|
||||
angle -= 1.;
|
||||
turn_sign = 1.;
|
||||
add_angel -= fifth_turn_drift_angle - smoothstep1(t1) * (fifth_turn_drift_angle * 2. + 1.);
|
||||
rotate_on_turns = 0.;
|
||||
roll_on_turns = 0.;
|
||||
} else {
|
||||
prev += dir + dir + dir;
|
||||
turn = dirR;
|
||||
//dir = dir;
|
||||
turn_sign = 1.;
|
||||
angle += fifth_turn_drift_angle * (1.5*min(1., (1.-t1)/turn_time) - 0.5*smoothstep1(1. - min(1.,t1/(1.-turn_time))));
|
||||
}
|
||||
|
||||
if (iMouse.x > 10. || iMouse.y > 10.) {
|
||||
vec2 mouse = iMouse.xy / iResolution.xy * 2. - 1.;
|
||||
up_down = -0.7 * mouse.y;
|
||||
angle += mouse.x;
|
||||
rotate_on_turns = 1.;
|
||||
roll_on_turns = 0.;
|
||||
} else {
|
||||
angle += add_angel;
|
||||
}
|
||||
|
||||
rd = rotateX(rd, up_down);
|
||||
|
||||
vec2 p;
|
||||
if (turn_sign == 0.) {
|
||||
// move forward
|
||||
p = prev + dir * (turn_rad + 1. * t1);
|
||||
}
|
||||
else if (t1 > (1. - turn_time)) {
|
||||
// turn
|
||||
float tr = (t1 - (1. - turn_time)) / turn_time;
|
||||
vec2 c = prev + dir * (1. - turn_rad) + turn * turn_rad;
|
||||
p = c + turn_rad * rotate(dir, (tr - 1.) * turn_sign * PI/2.);
|
||||
angle += tr * turn_sign * rotate_on_turns;
|
||||
rd = rotateY(rd, sin(tr*turn_sign*PI) * 0.2 * roll_on_turns); //roll
|
||||
} else {
|
||||
// move forward
|
||||
t1 /= (1. - turn_time);
|
||||
p = prev + dir * (turn_rad + (1. - turn_rad*2.) * t1);
|
||||
}
|
||||
|
||||
rd = rotateZ(rd, angle * PI/2.);
|
||||
|
||||
ro.xy += level1_size * p;
|
||||
|
||||
ro += rd * 0.2;
|
||||
rd = normalize(rd);
|
||||
|
||||
// vec3 col = rain(ro, rd, time);
|
||||
vec3 col = rain(ro, rd, time) * 0.25;
|
||||
|
||||
// Sample the terminal screen texture including alpha channel
|
||||
vec4 terminalColor = texture(iChannel0, uv);
|
||||
|
||||
// Combine the matrix effect with the terminal color
|
||||
// vec3 blendedColor = terminalColor.rgb + col;
|
||||
|
||||
// Make a mask that is 1.0 where the terminal content is not black
|
||||
float mask = 1.2 - step(0.5, dot(terminalColor.rgb, vec3(1.0)));
|
||||
vec3 blendedColor = mix(terminalColor.rgb * 1.2, col, mask);
|
||||
|
||||
fragColor = vec4(blendedColor, terminalColor.a);
|
||||
}
|
||||
322
ghostty-shaders/iso-city.glsl
Normal file
322
ghostty-shaders/iso-city.glsl
Normal file
|
|
@ -0,0 +1,322 @@
|
|||
// Stolen from cmgriffing ghostty shaders repo
|
||||
// This Ghostty shader is a port of https://www.shadertoy.com/view/MljXzz
|
||||
|
||||
const float timeMultiplier = 0.8f;
|
||||
|
||||
#define RGB( r, g, b ) vec3( float( r ) / 255.0, float( g ) / 255.0, float( b ) / 255.0 )
|
||||
const vec3 RGB_WATER = RGB(52, 166, 202);
|
||||
const vec3 RGB_BUILDING = RGB(219, 180, 144);
|
||||
const vec3 RGB_RIGHT_WALL = RGB_BUILDING * 1.1;
|
||||
const vec3 RGB_LEFT_WALL = RGB_BUILDING * 0.7;
|
||||
const vec3 RGB_WINDOWS = RGB(90, 100, 180);
|
||||
const vec3 RGB_ROAD = RGB(110, 125, 120) * 0.7;
|
||||
const vec3 RGB_LANE = RGB(255, 255, 255) * 0.8;
|
||||
const vec3 RGB_GRASS = RGB(129, 164, 66);
|
||||
const vec3 RGB_TREE_LEAVES = RGB(129, 164, 66) * 0.6;
|
||||
const vec3 RGB_TREE_TRUNK = RGB(80, 42, 42);
|
||||
const float TILE_WATER = 0.0;
|
||||
const float TILE_GRASS = 1.0;
|
||||
const float TILE_ISLAND = 2.0;
|
||||
const float TILE_ROAD_X = 3.0;
|
||||
const float TILE_ROAD_Y = 4.0;
|
||||
const float TILE_ROAD_XY = 5.0;
|
||||
const float ISO_TILE = 13.0 * 8.0;
|
||||
const float LARGE_FLOAT = 1e8;
|
||||
|
||||
void DrawBuilding(inout vec3 color, inout float zbuffer, vec2 tile, vec2 pixel, vec2 buildingTile, float h)
|
||||
{
|
||||
float depth = buildingTile.x + buildingTile.y;
|
||||
if (depth > zbuffer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
buildingTile.x += h;
|
||||
buildingTile.y += h;
|
||||
|
||||
pixel.y -= ISO_TILE * 0.25;
|
||||
vec2 iso = vec2((pixel.x + 2.0 * pixel.y) / ISO_TILE, (pixel.x - 2.0 * pixel.y) / -ISO_TILE);
|
||||
tile = floor(iso);
|
||||
vec2 off = iso - tile;
|
||||
|
||||
// roof
|
||||
if (tile.x == buildingTile.x && tile.y == buildingTile.y && off.x > 0.2 && off.y > 0.2 && off.x < 0.98 && off.y < 0.98)
|
||||
{
|
||||
zbuffer = depth;
|
||||
color = RGB_BUILDING;
|
||||
|
||||
if (off.x < 0.28 || off.y < 0.28 || off.x > 1.0 - 0.08 || off.y > 1.0 - 0.08)
|
||||
{
|
||||
color *= 1.2;
|
||||
}
|
||||
}
|
||||
|
||||
float px = (buildingTile.x - buildingTile.y) * ISO_TILE * 0.5;
|
||||
|
||||
// right wall
|
||||
if (pixel.x >= px && pixel.x < px + 0.39 * ISO_TILE && iso.y < buildingTile.y + 0.20 && iso.y > buildingTile.y - h - 0.4)
|
||||
{
|
||||
zbuffer = depth;
|
||||
color = RGB_RIGHT_WALL;
|
||||
|
||||
if (mod(iso.y + 0.2, 0.5) < 0.25)
|
||||
{
|
||||
color *= RGB_WINDOWS;
|
||||
color *= mod(pixel.x, 16.0) < 8.0 ? 1.0 : 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
// left wall
|
||||
if (pixel.x >= px - 0.39 * ISO_TILE && pixel.x < px && iso.x < buildingTile.x + 0.20 && iso.x > buildingTile.x - h - 0.4)
|
||||
{
|
||||
zbuffer = depth;
|
||||
color = RGB_LEFT_WALL;
|
||||
|
||||
if (mod(iso.x + 0.2, 0.5) < 0.25)
|
||||
{
|
||||
color *= RGB_WINDOWS;
|
||||
color *= mod(pixel.x, 16.0) < 8.0 ? 1.0 : 0.8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrawTree(inout vec3 color, inout float zbuffer, vec2 tile, vec2 pixel, vec2 treeTile)
|
||||
{
|
||||
float depth = treeTile.x + treeTile.y;
|
||||
if (depth > zbuffer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pixel.y -= ISO_TILE * 0.25;
|
||||
vec2 iso = vec2((pixel.x + 2.0 * pixel.y) / ISO_TILE, (pixel.x - 2.0 * pixel.y) / -ISO_TILE);
|
||||
tile = floor(iso);
|
||||
vec2 off = iso - tile;
|
||||
|
||||
float px = (treeTile.x - treeTile.y) * ISO_TILE * 0.5;
|
||||
|
||||
// top leaves
|
||||
if (iso.x > treeTile.x + 0.2 && iso.y > treeTile.y + 0.2 && iso.x < treeTile.x + 0.45 && iso.y < treeTile.y + 0.45)
|
||||
{
|
||||
zbuffer = depth;
|
||||
color = RGB_TREE_LEAVES * 1.0;
|
||||
}
|
||||
|
||||
// left leaves
|
||||
if (pixel.x >= px - 0.125 * ISO_TILE && pixel.x < px && iso.x > treeTile.x - 0.1 && iso.x < treeTile.x + 0.2 && iso.x > treeTile.x - 0.1)
|
||||
{
|
||||
zbuffer = depth;
|
||||
color = RGB_TREE_LEAVES * 0.8;
|
||||
}
|
||||
|
||||
// right leaves
|
||||
if (pixel.x >= px && pixel.x < px + 0.125 * ISO_TILE && iso.y < treeTile.y + 0.2 && iso.y > treeTile.y - 0.1)
|
||||
{
|
||||
zbuffer = depth;
|
||||
color = RGB_TREE_LEAVES * 1.2;
|
||||
}
|
||||
|
||||
// left trunk
|
||||
if (pixel.x >= px - 0.039 * ISO_TILE && pixel.x < px && iso.x <= treeTile.x - 0.1 && iso.x > treeTile.x - 0.4)
|
||||
{
|
||||
zbuffer = depth;
|
||||
color = RGB_TREE_TRUNK * 0.8;
|
||||
}
|
||||
|
||||
// right trunk
|
||||
if (pixel.x >= px && pixel.x < px + 0.039 * ISO_TILE && iso.y <= treeTile.y - 0.1 && iso.y > treeTile.y - 0.4)
|
||||
{
|
||||
zbuffer = depth;
|
||||
color = RGB_TREE_TRUNK * 1.1;
|
||||
}
|
||||
}
|
||||
|
||||
float TileID(vec2 tile)
|
||||
{
|
||||
float id = TILE_WATER;
|
||||
vec4 tex = texture(iChannel0, tile / (iChannelResolution[0].xy * 4.0));
|
||||
id = tex.y > 0.5 ? TILE_WATER : TILE_GRASS;
|
||||
id = tex.y > 0.9 ? TILE_ISLAND : id;
|
||||
|
||||
if (id == TILE_GRASS && mod(tile.x + 1.0, 4.0) == 0.0)
|
||||
{
|
||||
id = TILE_ROAD_X;
|
||||
}
|
||||
|
||||
if (mod(tile.y + 1.0, 4.0) == 0.0)
|
||||
{
|
||||
if (id == TILE_GRASS)
|
||||
{
|
||||
id = TILE_ROAD_Y;
|
||||
}
|
||||
|
||||
if (id == TILE_ROAD_X)
|
||||
{
|
||||
id = TILE_ROAD_XY;
|
||||
}
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord)
|
||||
{
|
||||
float resMult = floor(max(iResolution.x, iResolution.y) / 800.0);
|
||||
float resRcp = 1.0 / max(resMult, 1.0);
|
||||
float cameraOffset = iTime * timeMultiplier * 10.0 + 0.5;
|
||||
// float cameraOffset = float(iFrame);
|
||||
vec2 pixel = fragCoord * resRcp + cameraOffset - iMouse.xy + vec2(-2000, -2000.0);
|
||||
|
||||
vec2 iso = vec2((pixel.x + 2.0 * pixel.y) / ISO_TILE, (pixel.x - 2.0 * pixel.y) / -ISO_TILE);
|
||||
vec2 waterIso = vec2((pixel.x + 2.0 * pixel.y + 0.15625 * ISO_TILE) / ISO_TILE, (pixel.x - 2.0 * pixel.y - 0.15625 * ISO_TILE) / -ISO_TILE);
|
||||
vec2 isoR = vec2((pixel.x + 2.0 * pixel.y - ISO_TILE * 0.5) / ISO_TILE, (pixel.x - 2.0 * pixel.y + ISO_TILE * 0.5) / -ISO_TILE);
|
||||
vec2 tile = floor(iso);
|
||||
vec2 tileR = floor(isoR);
|
||||
vec2 waterTile = floor(waterIso);
|
||||
vec2 off = iso - tile;
|
||||
vec2 offR = isoR - tileR;
|
||||
vec2 waterOff = waterIso - waterTile;
|
||||
|
||||
vec2 buildingTile0 = 2.0 * floor(tile / 2.0);
|
||||
vec2 buildingTile1 = 3.0 * floor(tile / 3.0);
|
||||
vec2 buildingTile2 = 4.0 * floor(tile / 4.0);
|
||||
vec2 buildingTile3 = 5.0 * floor(tile / 5.0);
|
||||
|
||||
float tileId = TileID(tile);
|
||||
float tileLId = TileID(vec2(tile.x - 1.0, tile.y));
|
||||
float tileRId = TileID(vec2(tile.x + 1.0, tile.y));
|
||||
float tileTId = TileID(vec2(tile.x, tile.y - 1.0));
|
||||
float tileBId = TileID(vec2(tile.x, tile.y + 1.0));
|
||||
float tileB0Id = TileID(buildingTile0);
|
||||
float tileB1Id = TileID(buildingTile1);
|
||||
float tileB2Id = TileID(buildingTile2);
|
||||
float tileB3Id = TileID(buildingTile3);
|
||||
|
||||
// water
|
||||
vec3 waterTexNoise = texture(iChannel0, waterTile / iChannelResolution[0].xy + fract(iTime * timeMultiplier * 0.005)).xyz;
|
||||
vec3 color = RGB_WATER * mix(0.8, 1.1, waterTexNoise.z);
|
||||
|
||||
float waterTileId = TileID(waterTile);
|
||||
float waterTileLId = TileID(vec2(waterTile.x - 1.0, waterTile.y));
|
||||
float waterTileRId = TileID(vec2(waterTile.x + 1.0, waterTile.y));
|
||||
float waterTileTId = TileID(vec2(waterTile.x, waterTile.y - 1.0));
|
||||
float waterTileBId = TileID(vec2(waterTile.x, waterTile.y + 1.0));
|
||||
float waterTileLTId = TileID(vec2(waterTile.x - 1.0, waterTile.y - 1.0));
|
||||
float waterTileLBId = TileID(vec2(waterTile.x - 1.0, waterTile.y + 1.0));
|
||||
float waterTileRTId = TileID(vec2(waterTile.x + 1.0, waterTile.y - 1.0));
|
||||
float waterTileRBId = TileID(vec2(waterTile.x + 1.0, waterTile.y + 1.0));
|
||||
|
||||
// water shore shadow
|
||||
if (waterTileId == TILE_WATER)
|
||||
{
|
||||
if ((waterTileLId != TILE_WATER && waterOff.x < 8.0 / 32.0)
|
||||
|| (waterTileRId != TILE_WATER && waterOff.x > 24.0 / 32.0)
|
||||
|| (waterTileTId != TILE_WATER && waterOff.y < 8.0 / 32.0)
|
||||
|| (waterTileBId != TILE_WATER && waterOff.y > 24.0 / 32.0)
|
||||
|| (waterTileLTId != TILE_WATER && waterOff.x < 8.0 / 32.0 && waterOff.y < 8.0 / 32.0)
|
||||
|| (waterTileLBId != TILE_WATER && waterOff.x < 8.0 / 32.0 && waterOff.y > 24.0 / 32.0)
|
||||
|| (waterTileRTId != TILE_WATER && waterOff.x > 24.0 / 32.0 && waterOff.y < 8.0 / 32.0)
|
||||
|| (waterTileRBId != TILE_WATER && waterOff.x > 24.0 / 32.0 && waterOff.y > 24.0 / 32.0)
|
||||
)
|
||||
{
|
||||
color *= vec3(0.8);
|
||||
}
|
||||
}
|
||||
|
||||
// shores
|
||||
float waterPX = (waterTile.x - waterTile.y) * ISO_TILE * 0.5;
|
||||
if ((waterTileId != TILE_WATER && pixel.x <= waterPX && waterTileLId == TILE_WATER)
|
||||
|| (waterTileTId != TILE_WATER && pixel.x > waterPX && waterOff.x < 5.0 / 32.0))
|
||||
{
|
||||
color = RGB_GRASS * 0.7;
|
||||
}
|
||||
if ((waterTileId != TILE_WATER && pixel.x > waterPX && waterTileTId == TILE_WATER)
|
||||
|| (waterTileLId != TILE_WATER && pixel.x <= waterPX && waterOff.x < 5.0 / 32.0))
|
||||
{
|
||||
color = RGB_GRASS * 0.9;
|
||||
}
|
||||
|
||||
// grass and road
|
||||
if (tileId != TILE_WATER)
|
||||
{
|
||||
color = RGB_GRASS;
|
||||
}
|
||||
|
||||
float roadWidth = 0.3;
|
||||
float laneWidth = 0.03;
|
||||
if (((tileId == TILE_ROAD_X || tileId == TILE_ROAD_XY) && abs(0.5 - off.x) < roadWidth)
|
||||
&& (tileTId != TILE_WATER || tileBId != TILE_WATER)
|
||||
&& (tileTId != TILE_WATER || off.y >= 0.20)
|
||||
&& (tileBId != TILE_WATER || off.y <= 0.80)
|
||||
)
|
||||
{
|
||||
color = RGB_ROAD;
|
||||
if (abs(0.5 - off.x) < laneWidth && mod(off.y, 0.5) < 0.2 && tileId != TILE_ROAD_XY)
|
||||
{
|
||||
color = RGB_LANE;
|
||||
}
|
||||
}
|
||||
if ((tileId == TILE_ROAD_Y || tileId == TILE_ROAD_XY) && abs(0.5 - off.y) < roadWidth
|
||||
&& (tileLId != TILE_WATER || tileRId != TILE_WATER)
|
||||
&& (tileLId != TILE_WATER || off.x >= 0.20)
|
||||
&& (tileRId != TILE_WATER || off.x <= 0.80))
|
||||
{
|
||||
color = RGB_ROAD;
|
||||
if (abs(0.5 - off.y) < laneWidth && mod(off.x, 0.5) < 0.2 && tileId != TILE_ROAD_XY)
|
||||
{
|
||||
color = RGB_LANE;
|
||||
}
|
||||
}
|
||||
|
||||
if (tileId == TILE_GRASS && (
|
||||
(buildingTile0.x == tile.x && buildingTile0.y == tile.y)
|
||||
|| (buildingTile1.x == tile.x && buildingTile1.y == tile.y)
|
||||
|| (buildingTile2.x == tile.x && buildingTile2.y == tile.y)
|
||||
|| (buildingTile3.x == tile.x && buildingTile3.y == tile.y)))
|
||||
{
|
||||
// building AO
|
||||
vec2 offAO = 7.0 * clamp((abs(0.5 - off) - 0.35), 0.0, 1.0);
|
||||
color *= clamp(max(offAO.x, offAO.y), 0.0, 1.0);
|
||||
}
|
||||
else if (tileId == TILE_GRASS || tileId == TILE_ISLAND)
|
||||
{
|
||||
// tree AO
|
||||
color *= clamp(max(8.0 * abs(0.15 - off.x), 8.0 * abs(0.15 - off.y)), 0.0, 1.0);
|
||||
}
|
||||
|
||||
float zbuffer = LARGE_FLOAT;
|
||||
if (tileB0Id == TILE_GRASS)
|
||||
{
|
||||
DrawBuilding(color, zbuffer, tile, pixel, buildingTile0, 0.0);
|
||||
}
|
||||
|
||||
if (tileB1Id == TILE_GRASS)
|
||||
{
|
||||
DrawBuilding(color, zbuffer, tile, pixel, buildingTile1, 1.0);
|
||||
}
|
||||
|
||||
if (tileB2Id == TILE_GRASS)
|
||||
{
|
||||
DrawBuilding(color, zbuffer, tile, pixel, buildingTile2, 2.0);
|
||||
}
|
||||
|
||||
if (tileB3Id == TILE_GRASS)
|
||||
{
|
||||
DrawBuilding(color, zbuffer, tile, pixel, buildingTile3, 3.0);
|
||||
}
|
||||
|
||||
if ((tileId == TILE_GRASS || tileId == TILE_ISLAND) && zbuffer >= LARGE_FLOAT)
|
||||
{
|
||||
DrawTree(color, zbuffer, tile, pixel, tile);
|
||||
}
|
||||
|
||||
fragColor = vec4(sqrt(color), 1.0);
|
||||
|
||||
vec2 termUV = fragCoord.xy / iResolution.xy;
|
||||
vec4 terminalColor = texture(iChannel0, termUV);
|
||||
|
||||
float alpha = step(length(terminalColor.rgb), 0.4);
|
||||
vec3 blendedColor = mix(terminalColor.rgb * 1.0, fragColor.rgb * 0.2, alpha);
|
||||
|
||||
fragColor = vec4(blendedColor, terminalColor.a);
|
||||
}
|
||||
52
ghostty-shaders/just-snow.glsl
Normal file
52
ghostty-shaders/just-snow.glsl
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
// Copyright (c) 2013 Andrew Baldwin (twitter: baldand, www: http://thndl.com)
|
||||
// License = Attribution-NonCommercial-ShareAlike (http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_US)
|
||||
|
||||
// "Just snow"
|
||||
// Simple (but not cheap) snow made from multiple parallax layers with randomly positioned
|
||||
// flakes and directions. Also includes a DoF effect. Pan around with mouse.
|
||||
|
||||
#define LIGHT_SNOW // Comment this out for a blizzard
|
||||
|
||||
#ifdef LIGHT_SNOW
|
||||
#define LAYERS 50
|
||||
#define DEPTH .5
|
||||
#define WIDTH .3
|
||||
#define SPEED .6
|
||||
#else // BLIZZARD
|
||||
#define LAYERS 200
|
||||
#define DEPTH .1
|
||||
#define WIDTH .8
|
||||
#define SPEED 1.5
|
||||
#endif
|
||||
|
||||
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||
{
|
||||
const mat3 p = mat3(13.323122,23.5112,21.71123,21.1212,28.7312,11.9312,21.8112,14.7212,61.3934);
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
|
||||
vec3 acc = vec3(0.0);
|
||||
float dof = 5.0 * sin(iTime * 0.1);
|
||||
for (int i = 0; i < LAYERS; i++) {
|
||||
float fi = float(i);
|
||||
vec2 q =-uv*(1.0 + fi * DEPTH);
|
||||
q += vec2(q.y * (WIDTH * mod(fi * 7.238917, 1.0) - WIDTH * 0.5), -SPEED * iTime / (1.0 + fi * DEPTH * 0.03));
|
||||
vec3 n = vec3(floor(q), 31.189 + fi);
|
||||
vec3 m = floor(n) * 0.00001 + fract(n);
|
||||
vec3 mp = (31415.9 + m) / fract(p * m);
|
||||
vec3 r = fract(mp);
|
||||
vec2 s = abs(mod(q, 1.0) - 0.5 + 0.9 * r.xy - 0.45);
|
||||
s += 0.01 * abs(2.0 * fract(10.0 * q.yx) - 1.0);
|
||||
float d = 0.6 * max(s.x - s.y, s.x + s.y) + max(s.x, s.y) - 0.01;
|
||||
float edge = 0.005 + 0.05 * min(0.5 * abs(fi - 5.0 - dof), 1.0);
|
||||
acc += vec3(smoothstep(edge, -edge, d) * (r.x / (1.0 + 0.02 * fi * DEPTH)));
|
||||
}
|
||||
|
||||
// Sample the terminal screen texture including alpha channel
|
||||
vec4 terminalColor = texture(iChannel0, uv);
|
||||
|
||||
// Combine the snow effect with the terminal color
|
||||
vec3 blendedColor = terminalColor.rgb + acc;
|
||||
|
||||
// Use the terminal's original alpha
|
||||
fragColor = vec4(blendedColor, terminalColor.a);
|
||||
}
|
||||
35
ghostty-shaders/lightings.glsl
Normal file
35
ghostty-shaders/lightings.glsl
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
#define BLACK_BLEND_THRESHOLD .4 // This is controls the dim of the screen
|
||||
const float timeMultiplier = 0.1f;
|
||||
|
||||
void mainImage(out vec4 o, vec2 u)
|
||||
{
|
||||
vec2 termUV = u.xy / iResolution.xy;
|
||||
vec2 v = iResolution.xy;
|
||||
u = .2 * (u + u - v) / v.y;
|
||||
|
||||
vec4 z = o = vec4(1, 2, 3, 0);
|
||||
|
||||
for (float a = .5, t = iTime * timeMultiplier, i;
|
||||
++i < 19.;
|
||||
o += (1. + cos(z + t))
|
||||
/ length((1. + i * dot(v, v))
|
||||
* sin(1.5 * u / (.5 - dot(u, u)) - 9. * u.yx + t))
|
||||
)
|
||||
v = cos(++t - 7. * u * pow(a += .03, i)) - 5. * u,
|
||||
// use stanh here if shader has black artifacts
|
||||
// vvvv
|
||||
u += tanh(40. * dot(u *= mat2(cos(i + .02 * t - vec4(0, 11, 33, 0))), u)
|
||||
* cos(1e2 * u.yx + t)) / 2e2
|
||||
+ .2 * a * u
|
||||
+ cos(4. / exp(dot(o, o) / 1e2) + t) / 3e2;
|
||||
|
||||
o = 25.6 / (min(o, 13.) + 164. / o)
|
||||
- dot(u, u) / 250.;
|
||||
|
||||
vec4 terminalColor = texture(iChannel0, termUV);
|
||||
|
||||
float alpha = step(length(terminalColor.rgb), BLACK_BLEND_THRESHOLD);
|
||||
vec3 blendedColor = mix(terminalColor.rgb, o.rgb * 0.2, alpha);
|
||||
|
||||
o = vec4(blendedColor, terminalColor.a);
|
||||
}
|
||||
40
ghostty-shaders/matrix-hallway.glsl
Normal file
40
ghostty-shaders/matrix-hallway.glsl
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
// based on the following Shader Toy entry
|
||||
//
|
||||
// [SH17A] Matrix rain. Created by Reinder Nijhoff 2017
|
||||
// Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
|
||||
// @reindernijhoff
|
||||
//
|
||||
// https://www.shadertoy.com/view/ldjBW1
|
||||
//
|
||||
|
||||
#define SPEED_MULTIPLIER 1.
|
||||
#define GREEN_ALPHA .33
|
||||
|
||||
#define BLACK_BLEND_THRESHOLD .4
|
||||
|
||||
#define R fract(1e2 * sin(p.x * 8. + p.y))
|
||||
|
||||
void mainImage(out vec4 fragColor, vec2 fragCoord) {
|
||||
vec3 v = vec3(fragCoord, 1) / iResolution - .5;
|
||||
// vec3 s = .5 / abs(v);
|
||||
// scale?
|
||||
vec3 s = .9 / abs(v);
|
||||
s.z = min(s.y, s.x);
|
||||
vec3 i = ceil( 8e2 * s.z * ( s.y < s.x ? v.xzz : v.zyz ) ) * .1;
|
||||
vec3 j = fract(i);
|
||||
i -= j;
|
||||
vec3 p = vec3(9, int(iTime * SPEED_MULTIPLIER * (9. + 8. * sin(i).x)), 0) + i;
|
||||
vec3 col = fragColor.rgb;
|
||||
col.g = R / s.z;
|
||||
p *= j;
|
||||
col *= (R >.5 && j.x < .6 && j.y < .8) ? GREEN_ALPHA : 0.;
|
||||
|
||||
// Sample the terminal screen texture including alpha channel
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
vec4 terminalColor = texture(iChannel0, uv);
|
||||
|
||||
float alpha = step(length(terminalColor.rgb), BLACK_BLEND_THRESHOLD);
|
||||
vec3 blendedColor = mix(terminalColor.rgb * 1.2, col, alpha);
|
||||
|
||||
fragColor = vec4(blendedColor, terminalColor.a);
|
||||
}
|
||||
119
ghostty-shaders/mnoise.glsl
Normal file
119
ghostty-shaders/mnoise.glsl
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
vec3 mod289(vec3 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }
|
||||
vec4 mod289(vec4 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }
|
||||
vec4 permute(vec4 x) { return mod289(((x * 34.0) + 10.0) * x); }
|
||||
vec4 taylorInvSqrt(vec4 r) { return 1.79284291400159 - 0.85373472095314 * r; }
|
||||
float snoise(vec3 v) {
|
||||
const vec2 C = vec2(1.0 / 6.0, 1.0 / 3.0);
|
||||
const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);
|
||||
|
||||
// First corner
|
||||
vec3 i = floor(v + dot(v, C.yyy));
|
||||
vec3 x0 = v - i + dot(i, C.xxx);
|
||||
|
||||
// Other corners
|
||||
vec3 g = step(x0.yzx, x0.xyz);
|
||||
vec3 l = 1.0 - g;
|
||||
vec3 i1 = min(g.xyz, l.zxy);
|
||||
vec3 i2 = max(g.xyz, l.zxy);
|
||||
|
||||
// x0 = x0 - 0.0 + 0.0 * C.xxx;
|
||||
// x1 = x0 - i1 + 1.0 * C.xxx;
|
||||
// x2 = x0 - i2 + 2.0 * C.xxx;
|
||||
// x3 = x0 - 1.0 + 3.0 * C.xxx;
|
||||
vec3 x1 = x0 - i1 + C.xxx;
|
||||
vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y
|
||||
vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y
|
||||
|
||||
// Permutations
|
||||
i = mod289(i);
|
||||
vec4 p = permute(permute(permute(i.z + vec4(0.0, i1.z, i2.z, 1.0)) + i.y +
|
||||
vec4(0.0, i1.y, i2.y, 1.0)) +
|
||||
i.x + vec4(0.0, i1.x, i2.x, 1.0));
|
||||
|
||||
// Gradients: 7x7 points over a square, mapped onto an octahedron.
|
||||
// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
|
||||
float n_ = 0.142857142857; // 1.0/7.0
|
||||
vec3 ns = n_ * D.wyz - D.xzx;
|
||||
|
||||
vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7)
|
||||
|
||||
vec4 x_ = floor(j * ns.z);
|
||||
vec4 y_ = floor(j - 7.0 * x_); // mod(j,N)
|
||||
|
||||
vec4 x = x_ * ns.x + ns.yyyy;
|
||||
vec4 y = y_ * ns.x + ns.yyyy;
|
||||
vec4 h = 1.0 - abs(x) - abs(y);
|
||||
|
||||
vec4 b0 = vec4(x.xy, y.xy);
|
||||
vec4 b1 = vec4(x.zw, y.zw);
|
||||
|
||||
// vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;
|
||||
// vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;
|
||||
vec4 s0 = floor(b0) * 2.0 + 1.0;
|
||||
vec4 s1 = floor(b1) * 2.0 + 1.0;
|
||||
vec4 sh = -step(h, vec4(0.0));
|
||||
|
||||
vec4 a0 = b0.xzyw + s0.xzyw * sh.xxyy;
|
||||
vec4 a1 = b1.xzyw + s1.xzyw * sh.zzww;
|
||||
|
||||
vec3 p0 = vec3(a0.xy, h.x);
|
||||
vec3 p1 = vec3(a0.zw, h.y);
|
||||
vec3 p2 = vec3(a1.xy, h.z);
|
||||
vec3 p3 = vec3(a1.zw, h.w);
|
||||
|
||||
// Normalise gradients
|
||||
vec4 norm =
|
||||
taylorInvSqrt(vec4(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3)));
|
||||
p0 *= norm.x;
|
||||
p1 *= norm.y;
|
||||
p2 *= norm.z;
|
||||
p3 *= norm.w;
|
||||
|
||||
// Mix final noise value
|
||||
vec4 m =
|
||||
max(0.5 - vec4(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), 0.0);
|
||||
m = m * m;
|
||||
return 105.0 *
|
||||
dot(m * m, vec4(dot(p0, x0), dot(p1, x1), dot(p2, x2), dot(p3, x3)));
|
||||
}
|
||||
|
||||
float noise2D(vec2 uv) {
|
||||
uvec2 pos = uvec2(floor(uv * 1000.));
|
||||
return float((pos.x * 68657387u ^ pos.y * 361524851u + pos.x) % 890129u) *
|
||||
(1.0 / 890128.0);
|
||||
}
|
||||
|
||||
float roundRectSDF(vec2 center, vec2 size, float radius) {
|
||||
return length(max(abs(center) - size + radius, 0.)) - radius;
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
||||
vec2 uv = fragCoord / iResolution.xy, sd = vec2(2.), sdh = vec2(1.);
|
||||
vec4 ghosttyCol = texture(iChannel0, uv);
|
||||
float ratio = iResolution.y / iResolution.x,
|
||||
fw = max(fwidth(uv.x), fwidth(uv.y));
|
||||
|
||||
vec2 puv = floor(uv * vec2(60., 60. * ratio)) / 60.;
|
||||
puv +=
|
||||
(smoothstep(0., 0.7, noise2D(puv)) - 0.5) * 0.05 - vec2(0., iTime * 0.08);
|
||||
|
||||
uv = fract(vec2(uv.x, uv.y * ratio) * 10.);
|
||||
float d = roundRectSDF((sd + 0.01) * (uv - .5), sdh, 0.075),
|
||||
d2 = roundRectSDF((sd + 0.065) * (fract(uv * 6.) - .5), sdh, 0.2),
|
||||
noiseTime = iTime * 0.03, noise = snoise(vec3(puv, noiseTime));
|
||||
|
||||
noise += snoise(vec3(puv * 1.1, noiseTime + 0.5)) + .1;
|
||||
noise += snoise(vec3(puv * 2., noiseTime + 0.8));
|
||||
noise = pow(noise, 2.);
|
||||
|
||||
vec3 col1 = vec3(0.), col2 = vec3(0.), col3 = vec3(0.07898),
|
||||
col4 = vec3(0.089184),
|
||||
fcol = mix(mix(mix(col1, col3, smoothstep(0.0, 0.3, noise)), col2,
|
||||
smoothstep(0.0, 0.5, noise)),
|
||||
col4, smoothstep(0.0, 1.0, noise));
|
||||
|
||||
fragColor = vec4(
|
||||
ghosttyCol.rgb +
|
||||
mix(col4, fcol, smoothstep(fw, -fw, d) * smoothstep(fw, -fw, d2)),
|
||||
ghosttyCol.a);
|
||||
}
|
||||
8
ghostty-shaders/negative.glsl
Normal file
8
ghostty-shaders/negative.glsl
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||
{
|
||||
vec2 uv = fragCoord/iResolution.xy;
|
||||
vec4 color = texture(iChannel0, uv);
|
||||
fragColor = vec4(1.0 - color.x, 1.0 - color.y, 1.0 - color.z, color.w);
|
||||
}
|
||||
|
||||
257
ghostty-shaders/proto-disk.glsl
Normal file
257
ghostty-shaders/proto-disk.glsl
Normal file
|
|
@ -0,0 +1,257 @@
|
|||
// "Protoplanetary disk" by Duke
|
||||
// https://www.shadertoy.com/view/MdtGRl
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Based on "Dusty nebula 1" (https://www.shadertoy.com/view/4lSXD1)
|
||||
// and Shane's "Cheap Cloud Flythrough" (https://www.shadertoy.com/view/Xsc3R4) shaders
|
||||
// Some ideas came from other shaders from this wonderful site
|
||||
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0
|
||||
//-------------------------------------------------------------------------------------
|
||||
|
||||
#define BLACK_BLEND_THRESHOLD .4 // This is controls the dim of the screen
|
||||
const float timeMultiplier = 0.1f;
|
||||
//-------------------
|
||||
#define pi 3.14159265
|
||||
#define R(p, a) p=cos(a)*p+sin(a)*vec2(p.y, -p.x)
|
||||
|
||||
mat2 Spin(float angle)
|
||||
{
|
||||
return mat2(cos(angle), -sin(angle), sin(angle), cos(angle));
|
||||
}
|
||||
|
||||
// iq's noise
|
||||
float pn(in vec3 x)
|
||||
{
|
||||
vec3 p = floor(x);
|
||||
vec3 f = fract(x);
|
||||
f = f * f * (3.0 - 2.0 * f);
|
||||
vec2 uv = (p.xy + vec2(37.0, 17.0) * p.z) + f.xy;
|
||||
vec2 rg = textureLod(iChannel0, (uv + 0.5) / 256.0, 0.0).yx;
|
||||
return -1.0 + 2.4 * mix(rg.x, rg.y, f.z);
|
||||
}
|
||||
|
||||
float fpn(vec3 p)
|
||||
{
|
||||
return pn(p * .06125) * .5 + pn(p * .125) * .25 + pn(p * .25) * .125; // + pn(p*.5)*.625;
|
||||
}
|
||||
|
||||
float rand(vec2 co)
|
||||
{
|
||||
return fract(sin(dot(co * 0.123, vec2(12.9898, 78.233))) * 43758.5453);
|
||||
}
|
||||
|
||||
float Ring(vec3 p)
|
||||
{
|
||||
vec2 q = vec2(length(p.xy) - 2.3, p.z);
|
||||
return length(q) - 0.01;
|
||||
}
|
||||
|
||||
float length2(vec2 p)
|
||||
{
|
||||
return sqrt(p.x * p.x + p.y * p.y);
|
||||
}
|
||||
|
||||
float length8(vec2 p)
|
||||
{
|
||||
p = p * p;
|
||||
p = p * p;
|
||||
p = p * p;
|
||||
return pow(p.x + p.y, 1.0 / 8.0);
|
||||
}
|
||||
|
||||
float Disk(vec3 p, vec3 t)
|
||||
{
|
||||
vec2 q = vec2(length2(p.xy) - t.x, p.z * 0.5);
|
||||
return max(length8(q) - t.y, abs(p.z) - t.z);
|
||||
}
|
||||
|
||||
float smin(float a, float b, float k)
|
||||
{
|
||||
float h = clamp(0.5 + 0.5 * (b - a) / k, 0.0, 1.0);
|
||||
return mix(b, a, h) - k * h * (1.0 - h);
|
||||
}
|
||||
|
||||
float map(vec3 p)
|
||||
{
|
||||
float t = 0.7 * iTime;
|
||||
float d1 = Disk(p, vec3(2.0, 1., 0.05)) + fpn(vec3(Spin(t * 0.25 + p.z * .10) * p.xy * 20., p.z * 20. - t) * 5.0) * 0.545;
|
||||
float d2 = Ring(p);
|
||||
return smin(d1, d2, 1.0);
|
||||
}
|
||||
|
||||
// assign color to the media
|
||||
vec3 computeColor(float density, float radius)
|
||||
{
|
||||
// color based on density alone, gives impression of occlusion within
|
||||
// the media
|
||||
vec3 result = mix(1.1 * vec3(1.0, 0.9, 0.8), vec3(0.4, 0.15, 0.1), density);
|
||||
|
||||
// color added for disk
|
||||
vec3 colCenter = 6. * vec3(0.8, 1.0, 1.0);
|
||||
vec3 colEdge = 2. * vec3(0.48, 0.53, 0.5);
|
||||
result *= mix(colCenter, colEdge, min((radius + .5) / 2.0, 1.15));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Raycylinderintersect(vec3 org, vec3 dir, out float near, out float far)
|
||||
{
|
||||
// quadratic x^2 + y^2 = 0.5^2 => (org.x + t*dir.x)^2 + (org.y + t*dir.y)^2 = 0.5
|
||||
float a = dot(dir.xy, dir.xy);
|
||||
float b = dot(org.xy, dir.xy);
|
||||
float c = dot(org.xy, org.xy) - 12.;
|
||||
|
||||
float delta = b * b - a * c;
|
||||
if (delta < 0.0)
|
||||
return false;
|
||||
|
||||
// 2 roots
|
||||
float deltasqrt = sqrt(delta);
|
||||
float arcp = 1.0 / a;
|
||||
near = (-b - deltasqrt) * arcp;
|
||||
far = (-b + deltasqrt) * arcp;
|
||||
|
||||
// order roots
|
||||
float temp = min(far, near);
|
||||
far = max(far, near);
|
||||
near = temp;
|
||||
|
||||
float znear = org.z + near * dir.z;
|
||||
float zfar = org.z + far * dir.z;
|
||||
|
||||
// top, bottom
|
||||
vec2 zcap = vec2(1.85, -1.85);
|
||||
vec2 cap = (zcap - org.z) / dir.z;
|
||||
|
||||
if (znear < zcap.y)
|
||||
near = cap.y;
|
||||
else if (znear > zcap.x)
|
||||
near = cap.x;
|
||||
|
||||
if (zfar < zcap.y)
|
||||
far = cap.y;
|
||||
else if (zfar > zcap.x)
|
||||
far = cap.x;
|
||||
|
||||
return far > 0.0 && far > near;
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord)
|
||||
{
|
||||
const float KEY_1 = 49.5 / 256.0;
|
||||
const float KEY_2 = 50.5 / 256.0;
|
||||
const float KEY_3 = 51.5 / 256.0;
|
||||
float key = 0.0;
|
||||
key += 0.7 * texture(iChannel1, vec2(KEY_1, 0.25)).x;
|
||||
key += 0.7 * texture(iChannel1, vec2(KEY_2, 0.25)).x;
|
||||
key += 0.7 * texture(iChannel1, vec2(KEY_3, 0.25)).x;
|
||||
|
||||
// ro: ray origin
|
||||
// rd: direction of the ray
|
||||
vec3 rd = normalize(vec3((gl_FragCoord.xy - 0.5 * iResolution.xy) / iResolution.y, 1.));
|
||||
vec3 ro = vec3(0., 0., -6. + key * 1.6);
|
||||
|
||||
// ld, td: local, total density
|
||||
// w: weighting factor
|
||||
float ld = 0., td = 0., w = 0.;
|
||||
|
||||
// t: length of the ray
|
||||
// d: distance function
|
||||
float d = 1., t = 0.;
|
||||
|
||||
vec4 sum = vec4(0.0);
|
||||
|
||||
float min_dist = 0.0, max_dist = 0.0;
|
||||
|
||||
if (Raycylinderintersect(ro, rd, min_dist, max_dist))
|
||||
{
|
||||
t = min_dist * step(t, min_dist);
|
||||
|
||||
// raymarch loop
|
||||
for (int i = 0; i < 56; i++)
|
||||
{
|
||||
vec3 pos = ro + t * rd;
|
||||
|
||||
float fld = 0.0;
|
||||
|
||||
// Loop break conditions.
|
||||
if (td > (1. - 1. / 80.) || d < 0.008 * t || t > 10. || sum.a > 0.99 || t > max_dist) break;
|
||||
|
||||
// evaluate distance function
|
||||
d = map(pos);
|
||||
|
||||
// direction to center
|
||||
vec3 stardir = normalize(vec3(0.0) - pos);
|
||||
|
||||
// change this string to control density
|
||||
d = max(d, 0.08);
|
||||
|
||||
if (d < 0.1)
|
||||
{
|
||||
// compute local density
|
||||
ld = 0.1 - d;
|
||||
|
||||
// compute weighting factor
|
||||
w = (1. - td) * ld;
|
||||
|
||||
// accumulate density
|
||||
td += w + 1. / 200.;
|
||||
|
||||
float radiusFromCenter = length(pos - vec3(0.0));
|
||||
vec4 col = vec4(computeColor(td, radiusFromCenter), td);
|
||||
|
||||
// uniform scale density
|
||||
col.a *= 0.2;
|
||||
// colour by alpha
|
||||
col.rgb *= col.a / 0.8;
|
||||
// alpha blend in contribution
|
||||
sum = sum + col * (1.0 - sum.a);
|
||||
}
|
||||
|
||||
td += 1. / 70.;
|
||||
|
||||
// point light calculations
|
||||
vec3 ldst = vec3(0.0) - pos;
|
||||
float lDist = max(length(ldst), 0.001);
|
||||
|
||||
// star in center
|
||||
vec3 lightColor = vec3(1.0, 0.5, 0.25);
|
||||
sum.rgb += lightColor / (lDist * lDist * lDist * 7.); //*10.); //add a bloom around the light
|
||||
|
||||
// using the light distance to perform some falloff
|
||||
//float atten = 1./(1. + lDist*0.125 + lDist*lDist*0.4);
|
||||
// accumulating the color
|
||||
//sum += w*atten*fld;
|
||||
|
||||
// enforce minimum stepsize
|
||||
d = max(d, 0.04);
|
||||
t += max(d * 0.3, 0.02);
|
||||
}
|
||||
|
||||
//scattering test
|
||||
//sum *= 1. / exp( ld * 0.2 ) * 1.05;
|
||||
|
||||
sum = clamp(sum, 0.0, 1.0);
|
||||
|
||||
sum.xyz = sum.xyz * sum.xyz * (3.0 - 2.0 * sum.xyz);
|
||||
}
|
||||
|
||||
// stars background
|
||||
if (td < .8)
|
||||
{
|
||||
vec3 stars = vec3(pn(rd * 300.0) * 0.4 + 0.5);
|
||||
vec3 starbg = vec3(0.0);
|
||||
starbg = mix(starbg, vec3(0.8, 0.9, 1.0), smoothstep(0.99, 1.0, stars) * clamp(dot(vec3(0.0), rd) + 0.75, 0.0, 1.0));
|
||||
starbg = clamp(starbg, 0.0, 1.0);
|
||||
sum.xyz += starbg;
|
||||
}
|
||||
|
||||
fragColor = vec4(sum.xyz, 1.0);
|
||||
|
||||
// vec2 termUV = fragCoord.xy / iResolution.xy;
|
||||
// vec4 terminalColor = texture(iChannel0, termUV);
|
||||
//
|
||||
// float alpha = step(length(terminalColor.rgb), BLACK_BLEND_THRESHOLD);
|
||||
// vec3 blendedColor = mix(terminalColor.rgb * 1.0, col.rgb * 0.3, alpha);
|
||||
//
|
||||
// fragColor = vec4(blendedColor, terminalColor.a);
|
||||
}
|
||||
34
ghostty-shaders/retro-terminal.glsl
Normal file
34
ghostty-shaders/retro-terminal.glsl
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
// Original shader collected from: https://www.shadertoy.com/view/WsVSzV
|
||||
// Licensed under Shadertoy's default since the original creator didn't provide any license. (CC BY NC SA 3.0)
|
||||
// Slight modifications were made to give a green-ish effect.
|
||||
|
||||
float warp = 0.25; // simulate curvature of CRT monitor
|
||||
float scan = 0.50; // simulate darkness between scanlines
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord)
|
||||
{
|
||||
// squared distance from center
|
||||
vec2 uv = fragCoord / iResolution.xy;
|
||||
vec2 dc = abs(0.5 - uv);
|
||||
dc *= dc;
|
||||
|
||||
// warp the fragment coordinates
|
||||
uv.x -= 0.5; uv.x *= 1.0 + (dc.y * (0.3 * warp)); uv.x += 0.5;
|
||||
uv.y -= 0.5; uv.y *= 1.0 + (dc.x * (0.4 * warp)); uv.y += 0.5;
|
||||
|
||||
// sample inside boundaries, otherwise set to black
|
||||
if (uv.y > 1.0 || uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0)
|
||||
fragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
else
|
||||
{
|
||||
// determine if we are drawing in a scanline
|
||||
float apply = abs(sin(fragCoord.y) * 0.5 * scan);
|
||||
|
||||
// sample the texture and apply a teal tint
|
||||
vec3 color = texture(iChannel0, uv).rgb;
|
||||
vec3 tealTint = vec3(0.0, 0.8, 0.6); // teal color (slightly more green than blue)
|
||||
|
||||
// mix the sampled color with the teal tint based on scanline intensity
|
||||
fragColor = vec4(mix(color * tealTint, vec3(0.0), apply), 1.0);
|
||||
}
|
||||
}
|
||||
47
ghostty-shaders/shader-art.glsl
Normal file
47
ghostty-shaders/shader-art.glsl
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/* This animation is the material of my first youtube tutorial about creative
|
||||
coding, which is a video in which I try to introduce programmers to GLSL
|
||||
and to the wonderful world of shaders, while also trying to share my recent
|
||||
passion for this community.
|
||||
Video URL: https://youtu.be/f4s1h2YETNY
|
||||
*/
|
||||
const float timeMultiplier = 0.1f;
|
||||
#define BLACK_BLEND_THRESHOLD .4 // This is controls the dim of the screen
|
||||
//https://iquilezles.org/articles/palettes/
|
||||
vec3 palette(float t) {
|
||||
vec3 a = vec3(0.5, 0.5, 0.5);
|
||||
vec3 b = vec3(0.5, 0.5, 0.5);
|
||||
vec3 c = vec3(1.0, 1.0, 1.0);
|
||||
vec3 d = vec3(0.263, 0.416, 0.557);
|
||||
|
||||
return a + b * cos(6.28318 * (c * t + d));
|
||||
}
|
||||
|
||||
//https://www.shadertoy.com/view/mtyGWy
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
||||
vec2 uv = (fragCoord * 2.0 - iResolution.xy) / iResolution.y;
|
||||
vec2 uv0 = uv;
|
||||
vec3 finalColor = vec3(0.0);
|
||||
|
||||
for (float i = 0.0; i < 4.0; i++) {
|
||||
uv = fract(uv * 1.5) - 0.5;
|
||||
|
||||
float d = length(uv) * exp(-length(uv0));
|
||||
|
||||
vec3 col = palette(length(uv0) + i * .4 + iTime * timeMultiplier * .4);
|
||||
|
||||
d = sin(d * 8. + iTime * timeMultiplier) / 8.;
|
||||
d = abs(d);
|
||||
|
||||
d = pow(0.01 / d, 1.2);
|
||||
|
||||
finalColor += col * d;
|
||||
}
|
||||
|
||||
vec2 termUV = fragCoord.xy / iResolution.xy;
|
||||
vec4 terminalColor = texture(iChannel0, termUV);
|
||||
|
||||
float alpha = step(length(terminalColor.rgb), BLACK_BLEND_THRESHOLD);
|
||||
vec3 blendedColor = mix(terminalColor.rgb * 1.0, finalColor.rgb * 0.3, alpha);
|
||||
|
||||
fragColor = vec4(blendedColor, terminalColor.a);
|
||||
}
|
||||
28
ghostty-shaders/sin-interference.glsl
Normal file
28
ghostty-shaders/sin-interference.glsl
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// Based on https://www.shadertoy.com/view/ms3cWn
|
||||
float map(float value, float min1, float max1, float min2, float max2) {
|
||||
return min2 + (value - min1) * (max2 - min2) / (max1 - min1);
|
||||
}
|
||||
|
||||
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||
{
|
||||
vec2 uv = fragCoord / iResolution.xy;
|
||||
float d = length(uv - 0.5) * 2.0;
|
||||
float t = d * d * 25.0 - iTime * 2.0;
|
||||
vec3 col = 0.5 + 0.5 * cos(t / 20.0 + uv.xyx + vec3(0.0,2.0,4.0));
|
||||
|
||||
vec2 center = iResolution.xy * 0.5;
|
||||
float distCentre = distance(fragCoord.xy, center);
|
||||
float dCSin = sin(distCentre * 0.05);
|
||||
|
||||
vec2 anim = vec2(map(sin(iTime),-1.0,1.0,0.0,iResolution.x),map(sin(iTime*1.25),-1.0,1.0,0.0,iResolution.y));
|
||||
float distMouse = distance(fragCoord.xy, anim);
|
||||
float dMSin = sin(distMouse * 0.05);
|
||||
|
||||
float greycol = (((dMSin * dCSin) + 1.0) * 0.5);
|
||||
greycol = greycol * map(d, 0.0, 1.4142135623730951, 0.5, 0.0);
|
||||
|
||||
vec4 terminalColor = texture(iChannel0, uv);
|
||||
vec3 blendedColor = mix(terminalColor.rgb, vec3(greycol * col.x, greycol * col.y, greycol * col.z), 0.25);
|
||||
|
||||
fragColor = vec4(blendedColor, terminalColor.a);
|
||||
}
|
||||
68
ghostty-shaders/singularity.glsl
Normal file
68
ghostty-shaders/singularity.glsl
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
|
||||
/*
|
||||
"Singularity" by @XorDev
|
||||
|
||||
A whirling blackhole.
|
||||
Feel free to code golf!
|
||||
|
||||
FabriceNeyret2: -19
|
||||
dean_the_coder: -12
|
||||
iq: -4
|
||||
*/
|
||||
|
||||
#define BLACK_BLEND_THRESHOLD .4 // This is controls the dim of the screen
|
||||
const float timeMultiplier = 0.6f;
|
||||
const float diagonaleBand = 1.0f;
|
||||
void mainImage(out vec4 O, in vec2 F)
|
||||
{
|
||||
vec2 uv = F.xy / iResolution.xy;
|
||||
vec4 col = vec4(0.0);
|
||||
float a = max(iResolution.y / iResolution.x, 1.0);
|
||||
// Avoid useless calcul for performance
|
||||
if (uv.x < uv.y + diagonaleBand * a && uv.x > uv.y - diagonaleBand * a) {
|
||||
//Iterator and attenuation (distance-squared)
|
||||
float i = .2, a;
|
||||
//Resolution for scaling and centering
|
||||
vec2 r = iResolution.xy,
|
||||
//Centered ratio-corrected coordinates
|
||||
p = (F + F - r) / r.y / .7,
|
||||
//Diagonal vector for skewing
|
||||
d = vec2(-1, 1),
|
||||
//Blackhole center
|
||||
b = p - i * d,
|
||||
//Rotate and apply perspective
|
||||
c = p * mat2(1, 1, d / (.1 + i / dot(b, b))),
|
||||
//Rotate into spiraling coordinates
|
||||
v = c * mat2(cos(.5 * log(a = dot(c, c)) + iTime * i * timeMultiplier + vec4(0, 33, 11, 0))) / i,
|
||||
//Waves cumulative total for coloring
|
||||
w;
|
||||
|
||||
//Loop through waves
|
||||
for (; i++ < 9.; w += 1. + sin(v))
|
||||
//Distort coordinates
|
||||
v += .7 * sin(v.yx * i + iTime * timeMultiplier) / i + .5;
|
||||
//Acretion disk radius
|
||||
i = length(sin(v / .3) * .4 + c * (3. + d));
|
||||
//Red/blue gradient
|
||||
O = 1. - exp(-exp(c.x * vec4(.6, -.4, -1, 0.0))
|
||||
//Wave coloring
|
||||
/ w.xyyx
|
||||
//Acretion disk brightness
|
||||
/ (2. + i * i / 4. - i)
|
||||
//Center darkness
|
||||
/ (.5 + 1. / a)
|
||||
//Rim highlight
|
||||
/ (.03 + abs(length(p) - .7))
|
||||
);
|
||||
col = O;
|
||||
}
|
||||
vec2 fragCoord = F;
|
||||
|
||||
vec2 termUV = fragCoord.xy / iResolution.xy;
|
||||
vec4 terminalColor = texture(iChannel0, termUV);
|
||||
|
||||
float alpha = step(length(terminalColor.rgb), BLACK_BLEND_THRESHOLD);
|
||||
vec3 blendedColor = mix(terminalColor.rgb * 1.0, col.rgb * 0.3, alpha);
|
||||
|
||||
O = vec4(blendedColor, terminalColor.a);
|
||||
}
|
||||
193
ghostty-shaders/smoke-and-ghost.glsl
Normal file
193
ghostty-shaders/smoke-and-ghost.glsl
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
// Settings for detection
|
||||
#define TARGET_COLOR vec3(0.0, 0.0, 0.0) // RGB target pixels to transform
|
||||
#define REPLACE_COLOR vec3(0.0, 0.0, 0.0) // Color to replace target pixels
|
||||
#define COLOR_TOLERANCE 0.001 // Color matching tolerance
|
||||
|
||||
// Smoke effect settings
|
||||
#define SMOKE_COLOR vec3(1., 1., 1.0) // Base color of smoke
|
||||
#define SMOKE_RADIUS 0.011 // How far the smoke spreads
|
||||
#define SMOKE_SPEED 0.5 // Speed of smoke movement
|
||||
#define SMOKE_SCALE 25.0 // Scale of smoke detail
|
||||
#define SMOKE_INTENSITY 0.2 // Intensity of the smoke effect
|
||||
#define SMOKE_RISE_HEIGHT 0.14 // How high the smoke rises
|
||||
#define ALPHA_MAX 0.5 // Maximum opacity for smoke
|
||||
#define VERTICAL_BIAS 1.0
|
||||
|
||||
// Ghost face settings
|
||||
#define FACE_COUNT 1 // Number of ghost faces
|
||||
#define FACE_SCALE vec2(0.03, 0.05) // Size of faces, can be wider/elongated
|
||||
#define FACE_DURATION 1.2 // How long faces last, can be wider/elongated
|
||||
#define FACE_TRANSITION 1.5 // Face fade in/out duration
|
||||
#define FACE_COLOR vec3(0.0, 0.0, 0.0)
|
||||
#define GHOST_BG_COLOR vec3(1.0, 1.0, 1.0)
|
||||
#define GHOST_BG_SCALE vec2(0.03, 0.06)
|
||||
|
||||
float random(vec2 st) {
|
||||
return fract(sin(dot(st.xy, vec2(12.9898,78.233))) * 43758.5453123);
|
||||
}
|
||||
|
||||
float random1(float n) {
|
||||
return fract(sin(n) * 43758.5453123);
|
||||
}
|
||||
|
||||
vec2 random2(float n) {
|
||||
return vec2(
|
||||
random1(n),
|
||||
random1(n + 1234.5678)
|
||||
);
|
||||
}
|
||||
|
||||
float noise(vec2 st) {
|
||||
vec2 i = floor(st);
|
||||
vec2 f = fract(st);
|
||||
|
||||
float a = random(i);
|
||||
float b = random(i + vec2(1.0, 0.0));
|
||||
float c = random(i + vec2(0.0, 1.0));
|
||||
float d = random(i + vec2(1.0, 1.0));
|
||||
|
||||
vec2 u = f * f * (3.0 - 2.0 * f);
|
||||
return mix(a, b, u.x) + (c - a)* u.y * (1.0 - u.x) + (d - b) * u.x * u.y;
|
||||
}
|
||||
|
||||
// Modified elongated ellipse for more cartoon-like shapes
|
||||
float cartoonEllipse(vec2 uv, vec2 center, vec2 scale) {
|
||||
vec2 d = (uv - center) / scale;
|
||||
float len = length(d);
|
||||
// Add cartoon-like falloff
|
||||
return smoothstep(1.0, 0.8, len);
|
||||
}
|
||||
|
||||
// Function to create ghost background shape
|
||||
float ghostBackground(vec2 uv, vec2 center) {
|
||||
vec2 d = (uv - center) / GHOST_BG_SCALE;
|
||||
float baseShape = length(d * vec2(1.0, 0.8)); // Slightly oval
|
||||
|
||||
// Add wavy bottom
|
||||
float wave = sin(d.x * 6.28 + iTime) * 0.2;
|
||||
float bottomWave = smoothstep(0.0, -0.5, d.y + wave);
|
||||
|
||||
return smoothstep(1.0, 0.8, baseShape) + bottomWave;
|
||||
}
|
||||
|
||||
float ghostFace(vec2 uv, vec2 center, float time, float seed) {
|
||||
vec2 faceUV = (uv - center) / FACE_SCALE;
|
||||
|
||||
float eyeSize = 0.25 + random1(seed) * 0.05;
|
||||
float eyeSpacing = 0.35;
|
||||
vec2 leftEyePos = vec2(-eyeSpacing, 0.2);
|
||||
vec2 rightEyePos = vec2(eyeSpacing, 0.2);
|
||||
|
||||
float leftEye = cartoonEllipse(faceUV, leftEyePos, vec2(eyeSize));
|
||||
float rightEye = cartoonEllipse(faceUV, rightEyePos, vec2(eyeSize));
|
||||
|
||||
// Add simple eye highlights
|
||||
float leftHighlight = cartoonEllipse(faceUV, leftEyePos + vec2(0.1, 0.1), vec2(eyeSize * 0.3));
|
||||
float rightHighlight = cartoonEllipse(faceUV, rightEyePos + vec2(0.1, 0.1), vec2(eyeSize * 0.3));
|
||||
|
||||
vec2 mouthUV = faceUV - vec2(0.0, -0.9);
|
||||
float mouthWidth = 0.5 + random1(seed + 3.0) * 0.1;
|
||||
float mouthHeight = 0.8 + random1(seed + 7.0) * 0.1;
|
||||
|
||||
float mouth = cartoonEllipse(mouthUV, vec2(0.0), vec2(mouthWidth, mouthHeight));
|
||||
|
||||
// Combine features
|
||||
float face = max(max(leftEye, rightEye), mouth);
|
||||
face = max(face, max(leftHighlight, rightHighlight));
|
||||
|
||||
// Add border falloff
|
||||
face *= smoothstep(1.2, 0.8, length(faceUV));
|
||||
|
||||
return face;
|
||||
}
|
||||
|
||||
float calculateSmoke(vec2 uv, vec2 sourcePos) {
|
||||
float verticalDisp = (uv.y - sourcePos.y) * VERTICAL_BIAS;
|
||||
vec2 smokeUV = uv * SMOKE_SCALE;
|
||||
smokeUV.y -= iTime * SMOKE_SPEED * (1.0 + verticalDisp);
|
||||
smokeUV.x += sin(iTime * 0.5 + uv.y * 4.0) * 0.1;
|
||||
|
||||
float n = noise(smokeUV) * 0.5 + 0.5;
|
||||
n += noise(smokeUV * 2.0 + iTime * 0.1) * 0.25;
|
||||
|
||||
float verticalFalloff = 1.0 - smoothstep(0.0, SMOKE_RISE_HEIGHT, verticalDisp);
|
||||
return n * verticalFalloff;
|
||||
}
|
||||
|
||||
float isTargetPixel(vec2 uv) {
|
||||
vec4 color = texture(iChannel0, uv);
|
||||
return float(all(lessThan(abs(color.rgb - TARGET_COLOR), vec3(COLOR_TOLERANCE))));
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
||||
vec2 uv = fragCoord/iResolution.xy;
|
||||
vec4 originalColor = texture(iChannel0, uv);
|
||||
|
||||
// Calculate smoke effect
|
||||
float smokeAccum = 0.0;
|
||||
float targetInfluence = 0.0;
|
||||
|
||||
float stepSize = SMOKE_RADIUS / 4.0;
|
||||
for (float x = -SMOKE_RADIUS; x <= SMOKE_RADIUS; x += stepSize) {
|
||||
for (float y = -SMOKE_RADIUS; y <= 0.0; y += stepSize) {
|
||||
vec2 offset = vec2(x, y);
|
||||
vec2 sampleUV = uv + offset;
|
||||
|
||||
if (sampleUV.x >= 0.0 && sampleUV.x <= 1.0 &&
|
||||
sampleUV.y >= 0.0 && sampleUV.y <= 1.0) {
|
||||
float isTarget = isTargetPixel(sampleUV);
|
||||
if (isTarget > 0.0) {
|
||||
float dist = length(offset);
|
||||
float falloff = 1.0 - smoothstep(0.0, SMOKE_RADIUS, dist);
|
||||
float smoke = calculateSmoke(uv, sampleUV);
|
||||
smokeAccum += smoke * falloff;
|
||||
targetInfluence += falloff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
smokeAccum /= max(targetInfluence, 1.0);
|
||||
targetInfluence = smoothstep(0.0, 1.0, targetInfluence);
|
||||
float smokePresence = smokeAccum * targetInfluence;
|
||||
|
||||
// Calculate ghost faces with backgrounds
|
||||
float faceAccum = 0.0;
|
||||
float bgAccum = 0.0;
|
||||
float timeBlock = floor(iTime / FACE_DURATION);
|
||||
|
||||
if (smokePresence > 0.2) {
|
||||
for (int i = 0; i < FACE_COUNT; i++) {
|
||||
vec2 facePos = random2(timeBlock + float(i) * 1234.5);
|
||||
facePos = facePos * 0.8 + 0.1;
|
||||
|
||||
float faceTime = mod(iTime, FACE_DURATION);
|
||||
float fadeFactor = smoothstep(0.0, FACE_TRANSITION, faceTime) *
|
||||
(1.0 - smoothstep(FACE_DURATION - FACE_TRANSITION, FACE_DURATION, faceTime));
|
||||
|
||||
// Add ghost background
|
||||
float ghostBg = ghostBackground(uv, facePos) * fadeFactor;
|
||||
bgAccum = max(bgAccum, ghostBg);
|
||||
|
||||
// Add face features
|
||||
float face = ghostFace(uv, facePos, iTime, timeBlock + float(i) * 100.0) * fadeFactor;
|
||||
faceAccum = max(faceAccum, face);
|
||||
}
|
||||
|
||||
bgAccum *= smoothstep(0.2, 0.4, smokePresence);
|
||||
faceAccum *= smoothstep(0.2, 0.4, smokePresence);
|
||||
}
|
||||
|
||||
// Combine all elements
|
||||
bool isTarget = all(lessThan(abs(originalColor.rgb - TARGET_COLOR), vec3(COLOR_TOLERANCE)));
|
||||
vec3 baseColor = isTarget ? REPLACE_COLOR : originalColor.rgb;
|
||||
|
||||
// Layer the effects: base -> smoke -> ghost background -> face features
|
||||
vec3 smokeEffect = mix(baseColor, SMOKE_COLOR, smokeAccum * SMOKE_INTENSITY * targetInfluence * (1.0 - faceAccum));
|
||||
vec3 withBackground = mix(smokeEffect, GHOST_BG_COLOR, bgAccum * 0.7);
|
||||
vec3 finalColor = mix(withBackground, FACE_COLOR, faceAccum);
|
||||
|
||||
float alpha = mix(originalColor.a, ALPHA_MAX, max(smokePresence, max(bgAccum, faceAccum) * smokePresence));
|
||||
|
||||
fragColor = vec4(finalColor, alpha);
|
||||
}
|
||||
242
ghostty-shaders/sparks-from-fire.glsl
Normal file
242
ghostty-shaders/sparks-from-fire.glsl
Normal file
|
|
@ -0,0 +1,242 @@
|
|||
// adapted by Alex Sherwin for Ghstty from https://www.shadertoy.com/view/wl2Gzc
|
||||
|
||||
//Shader License: CC BY 3.0
|
||||
//Author: Jan Mróz (jaszunio15)
|
||||
|
||||
#define SMOKE_INTENSITY_MULTIPLIER 0.9
|
||||
#define PARTICLES_ALPHA_MOD 0.9
|
||||
#define SMOKE_ALPHA_MOD 0.5
|
||||
#define LAYERS_COUNT 8
|
||||
|
||||
#define BLACK_BLEND_THRESHOLD .4
|
||||
|
||||
#define VEC3_1 (vec3(1.0))
|
||||
|
||||
#define PI 3.1415927
|
||||
#define TWO_PI 6.283185
|
||||
|
||||
#define ANIMATION_SPEED 1.0
|
||||
#define MOVEMENT_SPEED .33
|
||||
#define MOVEMENT_DIRECTION vec2(0.7, 1.0)
|
||||
|
||||
#define PARTICLE_SIZE 0.0025
|
||||
|
||||
#define PARTICLE_SCALE (vec2(0.5, 1.6))
|
||||
#define PARTICLE_SCALE_VAR (vec2(0.25, 0.2))
|
||||
|
||||
#define PARTICLE_BLOOM_SCALE (vec2(0.5, 0.8))
|
||||
#define PARTICLE_BLOOM_SCALE_VAR (vec2(0.3, 0.1))
|
||||
|
||||
#define SPARK_COLOR vec3(1.0, 0.4, 0.05) * 1.5
|
||||
#define BLOOM_COLOR vec3(1.0, 0.4, 0.05) * 0.8
|
||||
#define SMOKE_COLOR vec3(1.0, 0.43, 0.1) * 0.8
|
||||
|
||||
#define SIZE_MOD 1.05
|
||||
|
||||
|
||||
float hash1_2(in vec2 x)
|
||||
{
|
||||
return fract(sin(dot(x, vec2(52.127, 61.2871))) * 521.582);
|
||||
}
|
||||
|
||||
vec2 hash2_2(in vec2 x)
|
||||
{
|
||||
return fract(sin(x * mat2x2(20.52, 24.1994, 70.291, 80.171)) * 492.194);
|
||||
}
|
||||
|
||||
//Simple interpolated noise
|
||||
vec2 noise2_2(vec2 uv)
|
||||
{
|
||||
//vec2 f = fract(uv);
|
||||
vec2 f = smoothstep(0.0, 1.0, fract(uv));
|
||||
|
||||
vec2 uv00 = floor(uv);
|
||||
vec2 uv01 = uv00 + vec2(0,1);
|
||||
vec2 uv10 = uv00 + vec2(1,0);
|
||||
vec2 uv11 = uv00 + 1.0;
|
||||
vec2 v00 = hash2_2(uv00);
|
||||
vec2 v01 = hash2_2(uv01);
|
||||
vec2 v10 = hash2_2(uv10);
|
||||
vec2 v11 = hash2_2(uv11);
|
||||
|
||||
vec2 v0 = mix(v00, v01, f.y);
|
||||
vec2 v1 = mix(v10, v11, f.y);
|
||||
vec2 v = mix(v0, v1, f.x);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
//Simple interpolated noise
|
||||
float noise1_2(in vec2 uv)
|
||||
{
|
||||
// vec2 f = fract(uv);
|
||||
vec2 f = smoothstep(0.0, 1.0, fract(uv));
|
||||
|
||||
vec2 uv00 = floor(uv);
|
||||
vec2 uv01 = uv00 + vec2(0,1);
|
||||
vec2 uv10 = uv00 + vec2(1,0);
|
||||
vec2 uv11 = uv00 + 1.0;
|
||||
|
||||
float v00 = hash1_2(uv00);
|
||||
float v01 = hash1_2(uv01);
|
||||
float v10 = hash1_2(uv10);
|
||||
float v11 = hash1_2(uv11);
|
||||
|
||||
float v0 = mix(v00, v01, f.y);
|
||||
float v1 = mix(v10, v11, f.y);
|
||||
float v = mix(v0, v1, f.x);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
float layeredNoise1_2(in vec2 uv, in float sizeMod, in float alphaMod, in int layers, in float animation)
|
||||
{
|
||||
float noise = 0.0;
|
||||
float alpha = 1.0;
|
||||
float size = 1.0;
|
||||
vec2 offset;
|
||||
for (int i = 0; i < layers; i++)
|
||||
{
|
||||
offset += hash2_2(vec2(alpha, size)) * 10.0;
|
||||
|
||||
//Adding noise with movement
|
||||
noise += noise1_2(uv * size + iTime * animation * 8.0 * MOVEMENT_DIRECTION * MOVEMENT_SPEED + offset) * alpha;
|
||||
alpha *= alphaMod;
|
||||
size *= sizeMod;
|
||||
}
|
||||
|
||||
noise *= (1.0 - alphaMod)/(1.0 - pow(alphaMod, float(layers)));
|
||||
return noise;
|
||||
}
|
||||
|
||||
//Rotates point around 0,0
|
||||
vec2 rotate(in vec2 point, in float deg)
|
||||
{
|
||||
float s = sin(deg);
|
||||
float c = cos(deg);
|
||||
return mat2x2(s, c, -c, s) * point;
|
||||
}
|
||||
|
||||
//Cell center from point on the grid
|
||||
vec2 voronoiPointFromRoot(in vec2 root, in float deg)
|
||||
{
|
||||
vec2 point = hash2_2(root) - 0.5;
|
||||
float s = sin(deg);
|
||||
float c = cos(deg);
|
||||
point = mat2x2(s, c, -c, s) * point * 0.66;
|
||||
point += root + 0.5;
|
||||
return point;
|
||||
}
|
||||
|
||||
//Voronoi cell point rotation degrees
|
||||
float degFromRootUV(in vec2 uv)
|
||||
{
|
||||
return iTime * ANIMATION_SPEED * (hash1_2(uv) - 0.5) * 2.0;
|
||||
}
|
||||
|
||||
vec2 randomAround2_2(in vec2 point, in vec2 range, in vec2 uv)
|
||||
{
|
||||
return point + (hash2_2(uv) - 0.5) * range;
|
||||
}
|
||||
|
||||
|
||||
vec3 fireParticles(in vec2 uv, in vec2 originalUV)
|
||||
{
|
||||
vec3 particles = vec3(0.0);
|
||||
vec2 rootUV = floor(uv);
|
||||
float deg = degFromRootUV(rootUV);
|
||||
vec2 pointUV = voronoiPointFromRoot(rootUV, deg);
|
||||
float dist = 2.0;
|
||||
float distBloom = 0.0;
|
||||
|
||||
//UV manipulation for the faster particle movement
|
||||
vec2 tempUV = uv + (noise2_2(uv * 2.0) - 0.5) * 0.1;
|
||||
tempUV += -(noise2_2(uv * 3.0 + iTime) - 0.5) * 0.07;
|
||||
|
||||
//Sparks sdf
|
||||
dist = length(rotate(tempUV - pointUV, 0.7) * randomAround2_2(PARTICLE_SCALE, PARTICLE_SCALE_VAR, rootUV));
|
||||
|
||||
//Bloom sdf
|
||||
distBloom = length(rotate(tempUV - pointUV, 0.7) * randomAround2_2(PARTICLE_BLOOM_SCALE, PARTICLE_BLOOM_SCALE_VAR, rootUV));
|
||||
|
||||
//Add sparks
|
||||
particles += (1.0 - smoothstep(PARTICLE_SIZE * 0.6, PARTICLE_SIZE * 3.0, dist)) * SPARK_COLOR;
|
||||
|
||||
//Add bloom
|
||||
particles += pow((1.0 - smoothstep(0.0, PARTICLE_SIZE * 6.0, distBloom)) * 1.0, 3.0) * BLOOM_COLOR;
|
||||
|
||||
//Upper disappear curve randomization
|
||||
float border = (hash1_2(rootUV) - 0.5) * 2.0;
|
||||
float disappear = 1.0 - smoothstep(border, border + 0.5, originalUV.y);
|
||||
|
||||
//Lower appear curve randomization
|
||||
border = (hash1_2(rootUV + 0.214) - 1.8) * 0.7;
|
||||
float appear = smoothstep(border, border + 0.4, originalUV.y);
|
||||
|
||||
return particles * disappear * appear;
|
||||
}
|
||||
|
||||
|
||||
//Layering particles to imitate 3D view
|
||||
vec3 layeredParticles(in vec2 uv, in float sizeMod, in float alphaMod, in int layers, in float smoke)
|
||||
{
|
||||
vec3 particles = vec3(0);
|
||||
float size = 1.0;
|
||||
// float alpha = 1.0;
|
||||
float alpha = 1.0;
|
||||
vec2 offset = vec2(0.0);
|
||||
vec2 noiseOffset;
|
||||
vec2 bokehUV;
|
||||
|
||||
for (int i = 0; i < layers; i++)
|
||||
{
|
||||
//Particle noise movement
|
||||
noiseOffset = (noise2_2(uv * size * 2.0 + 0.5) - 0.5) * 0.15;
|
||||
|
||||
//UV with applied movement
|
||||
bokehUV = (uv * size + iTime * MOVEMENT_DIRECTION * MOVEMENT_SPEED) + offset + noiseOffset;
|
||||
|
||||
//Adding particles if there is more smoke, remove smaller particles
|
||||
particles += fireParticles(bokehUV, uv) * alpha * (1.0 - smoothstep(0.0, 1.0, smoke) * (float(i) / float(layers)));
|
||||
|
||||
//Moving uv origin to avoid generating the same particles
|
||||
offset += hash2_2(vec2(alpha, alpha)) * 10.0;
|
||||
|
||||
alpha *= alphaMod;
|
||||
size *= sizeMod;
|
||||
}
|
||||
|
||||
return particles;
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
||||
vec2 uv = (2.0 * fragCoord - iResolution.xy) / iResolution.x;
|
||||
|
||||
// float vignette = 1.1 - smoothstep(0.4, 1.4, length(uv + vec2(0.0, 0.3)));
|
||||
float vignette = 1.3 - smoothstep(0.4, 1.4, length(uv + vec2(0.0, 0.3)));
|
||||
|
||||
uv *= 2.5;
|
||||
|
||||
float smokeIntensity = layeredNoise1_2(uv * 10.0 + iTime * 4.0 * MOVEMENT_DIRECTION * MOVEMENT_SPEED, 1.7, 0.7, 6, 0.2);
|
||||
smokeIntensity *= pow(smoothstep(-1.0, 1.6, uv.y), 2.0);
|
||||
vec3 smoke = smokeIntensity * SMOKE_COLOR * vignette * SMOKE_INTENSITY_MULTIPLIER * SMOKE_ALPHA_MOD;
|
||||
|
||||
//Cutting holes in smoke
|
||||
smoke *= pow(layeredNoise1_2(uv * 4.0 + iTime * 0.5 * MOVEMENT_DIRECTION * MOVEMENT_SPEED, 1.8, 0.5, 3, 0.2), 2.0) * 1.5;
|
||||
|
||||
vec3 particles = layeredParticles(uv, SIZE_MOD, PARTICLES_ALPHA_MOD, LAYERS_COUNT, smokeIntensity);
|
||||
|
||||
vec3 col = particles + smoke + SMOKE_COLOR * 0.02;
|
||||
col *= vignette;
|
||||
|
||||
col = smoothstep(-0.08, 1.0, col);
|
||||
|
||||
vec2 termUV = fragCoord.xy / iResolution.xy;
|
||||
vec4 terminalColor = texture(iChannel0, termUV);
|
||||
|
||||
float alpha = step(length(terminalColor.rgb), BLACK_BLEND_THRESHOLD);
|
||||
vec3 blendedColor = mix(terminalColor.rgb, col, alpha);
|
||||
|
||||
fragColor = vec4(blendedColor, terminalColor.a);
|
||||
}
|
||||
42
ghostty-shaders/spotlight.glsl
Normal file
42
ghostty-shaders/spotlight.glsl
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
// Created by Paul Robello
|
||||
|
||||
|
||||
// Smooth oscillating function that varies over time
|
||||
float smoothOscillation(float t, float frequency, float phase) {
|
||||
return sin(t * frequency + phase);
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
||||
// Resolution and UV coordinates
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
|
||||
// Used to fix distortion when calculating distance to circle center
|
||||
vec2 ratio = vec2(iResolution.x / iResolution.y, 1.0);
|
||||
|
||||
// Get the texture from iChannel0
|
||||
vec4 texColor = texture(iChannel0, uv);
|
||||
|
||||
// Spotlight center moving based on a smooth random pattern
|
||||
float time = iTime * 1.0; // Control speed of motion
|
||||
vec2 spotlightCenter = vec2(
|
||||
0.5 + 0.4 * smoothOscillation(time, 1.0, 0.0), // Smooth X motion
|
||||
0.5 + 0.4 * smoothOscillation(time, 1.3, 3.14159) // Smooth Y motion with different frequency and phase
|
||||
);
|
||||
|
||||
// Distance from the spotlight center
|
||||
float distanceToCenter = distance(uv * ratio, spotlightCenter);
|
||||
|
||||
// Spotlight intensity based on distance
|
||||
float spotlightRadius = 0.25; // Spotlight radius
|
||||
float softness = 20.0; // Spotlight edge softness. Higher values have sharper edge
|
||||
float spotlightIntensity = smoothstep(spotlightRadius, spotlightRadius - (1.0 / softness), distanceToCenter);
|
||||
|
||||
// Ambient light level
|
||||
float ambientLight = 0.5; // Controls the minimum brightness across the texture
|
||||
|
||||
// Combine the spotlight effect with the texture
|
||||
vec3 spotlightEffect = texColor.rgb * mix(vec3(ambientLight), vec3(1.0), spotlightIntensity);
|
||||
|
||||
// Final color output
|
||||
fragColor = vec4(spotlightEffect, texColor.a);
|
||||
}
|
||||
159
ghostty-shaders/starfield-colors.glsl
Normal file
159
ghostty-shaders/starfield-colors.glsl
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
// transparent background
|
||||
const bool transparent = false;
|
||||
const float timeMultiplier = 0.1f;
|
||||
|
||||
// terminal contents luminance threshold to be considered background (0.0 to 1.0)
|
||||
const float threshold = 0.15;
|
||||
|
||||
// divisions of grid
|
||||
const float repeats = 30.;
|
||||
|
||||
// number of layers
|
||||
const float layers = 5.;
|
||||
|
||||
// star colours
|
||||
const vec3 blue = vec3(51., 64., 195.) / 255.;
|
||||
const vec3 cyan = vec3(117., 250., 254.) / 255.;
|
||||
const vec3 white = vec3(255., 255., 255.) / 255.;
|
||||
const vec3 yellow = vec3(251., 245., 44.) / 255.;
|
||||
const vec3 red = vec3(247, 2., 20.) / 255.;
|
||||
|
||||
float luminance(vec3 color) {
|
||||
return dot(color, vec3(0.2126, 0.7152, 0.0722));
|
||||
}
|
||||
|
||||
// spectrum function
|
||||
vec3 spectrum(vec2 pos) {
|
||||
pos.x *= 4.;
|
||||
vec3 outCol = vec3(0);
|
||||
if (pos.x > 0.) {
|
||||
outCol = mix(blue, cyan, fract(pos.x));
|
||||
}
|
||||
if (pos.x > 1.) {
|
||||
outCol = mix(cyan, white, fract(pos.x));
|
||||
}
|
||||
if (pos.x > 2.) {
|
||||
outCol = mix(white, yellow, fract(pos.x));
|
||||
}
|
||||
if (pos.x > 3.) {
|
||||
outCol = mix(yellow, red, fract(pos.x));
|
||||
}
|
||||
|
||||
return 1. - (pos.y * (1. - outCol));
|
||||
}
|
||||
|
||||
float N21(vec2 p) {
|
||||
p = fract(p * vec2(233.34, 851.73));
|
||||
p += dot(p, p + 23.45);
|
||||
return fract(p.x * p.y);
|
||||
}
|
||||
|
||||
vec2 N22(vec2 p) {
|
||||
float n = N21(p);
|
||||
return vec2(n, N21(p + n));
|
||||
}
|
||||
|
||||
mat2 scale(vec2 _scale) {
|
||||
return mat2(_scale.x, 0.0,
|
||||
0.0, _scale.y);
|
||||
}
|
||||
|
||||
// 2D Noise based on Morgan McGuire
|
||||
float noise(in vec2 st) {
|
||||
vec2 i = floor(st);
|
||||
vec2 f = fract(st);
|
||||
|
||||
// Four corners in 2D of a tile
|
||||
float a = N21(i);
|
||||
float b = N21(i + vec2(1.0, 0.0));
|
||||
float c = N21(i + vec2(0.0, 1.0));
|
||||
float d = N21(i + vec2(1.0, 1.0));
|
||||
|
||||
// Smooth Interpolation
|
||||
vec2 u = f * f * (3.0 - 2.0 * f); // Cubic Hermite Curve
|
||||
|
||||
// Mix 4 corners percentages
|
||||
return mix(a, b, u.x) +
|
||||
(c - a) * u.y * (1.0 - u.x) +
|
||||
(d - b) * u.x * u.y;
|
||||
}
|
||||
|
||||
float perlin2(vec2 uv, int octaves, float pscale) {
|
||||
float col = 1.;
|
||||
float initScale = 4.;
|
||||
for (int l; l < octaves; l++) {
|
||||
float val = noise(uv * initScale);
|
||||
if (col <= 0.01) {
|
||||
col = 0.;
|
||||
break;
|
||||
}
|
||||
val -= 0.01;
|
||||
val *= 0.5;
|
||||
col *= val;
|
||||
initScale *= pscale;
|
||||
}
|
||||
return col;
|
||||
}
|
||||
|
||||
vec3 stars(vec2 uv, float offset) {
|
||||
float timeScale = -(iTime * timeMultiplier + offset) / layers;
|
||||
float trans = fract(timeScale);
|
||||
float newRnd = floor(timeScale);
|
||||
vec3 col = vec3(0.);
|
||||
|
||||
// Translate uv then scale for center
|
||||
uv -= vec2(0.5);
|
||||
uv = scale(vec2(trans)) * uv;
|
||||
uv += vec2(0.5);
|
||||
|
||||
// Create square aspect ratio
|
||||
uv.x *= iResolution.x / iResolution.y;
|
||||
|
||||
// Create boxes
|
||||
uv *= repeats;
|
||||
|
||||
// Get position
|
||||
vec2 ipos = floor(uv);
|
||||
|
||||
// Return uv as 0 to 1
|
||||
uv = fract(uv);
|
||||
|
||||
// Calculate random xy and size
|
||||
vec2 rndXY = N22(newRnd + ipos * (offset + 1.)) * 0.9 + 0.05;
|
||||
float rndSize = N21(ipos) * 100. + 200.;
|
||||
|
||||
vec2 j = (rndXY - uv) * rndSize;
|
||||
float sparkle = 1. / dot(j, j);
|
||||
|
||||
// Set stars to be pure white
|
||||
col += spectrum(fract(rndXY * newRnd * ipos)) * vec3(sparkle);
|
||||
|
||||
col *= smoothstep(1., 0.8, trans);
|
||||
return col; // Return pure white stars only
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord)
|
||||
{
|
||||
// Normalized pixel coordinates (from 0 to 1)
|
||||
vec2 uv = fragCoord / iResolution.xy;
|
||||
|
||||
vec3 col = vec3(0.);
|
||||
|
||||
for (float i = 0.; i < layers; i++) {
|
||||
col += stars(uv, i);
|
||||
}
|
||||
|
||||
// Sample the terminal screen texture including alpha channel
|
||||
vec4 terminalColor = texture(iChannel0, uv);
|
||||
|
||||
if (transparent) {
|
||||
col += terminalColor.rgb;
|
||||
}
|
||||
|
||||
// Make a mask that is 1.0 where the terminal content is not black
|
||||
float mask = 1 - step(threshold, luminance(terminalColor.rgb));
|
||||
vec3 blendedColor = mix(terminalColor.rgb, col, mask);
|
||||
|
||||
// Apply terminal's alpha to control overall opacity
|
||||
fragColor = vec4(blendedColor, terminalColor.a);
|
||||
}
|
||||
135
ghostty-shaders/starfield.glsl
Normal file
135
ghostty-shaders/starfield.glsl
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
// transparent background
|
||||
const bool transparent = false;
|
||||
|
||||
// terminal contents luminance threshold to be considered background (0.0 to 1.0)
|
||||
const float threshold = 0.15;
|
||||
|
||||
// divisions of grid
|
||||
const float repeats = 30.;
|
||||
|
||||
// number of layers
|
||||
const float layers = 21.;
|
||||
|
||||
// star colors
|
||||
const vec3 white = vec3(1.0); // Set star color to pure white
|
||||
|
||||
float luminance(vec3 color) {
|
||||
return dot(color, vec3(0.2126, 0.7152, 0.0722));
|
||||
}
|
||||
|
||||
float N21(vec2 p) {
|
||||
p = fract(p * vec2(233.34, 851.73));
|
||||
p += dot(p, p + 23.45);
|
||||
return fract(p.x * p.y);
|
||||
}
|
||||
|
||||
vec2 N22(vec2 p) {
|
||||
float n = N21(p);
|
||||
return vec2(n, N21(p + n));
|
||||
}
|
||||
|
||||
mat2 scale(vec2 _scale) {
|
||||
return mat2(_scale.x, 0.0,
|
||||
0.0, _scale.y);
|
||||
}
|
||||
|
||||
// 2D Noise based on Morgan McGuire
|
||||
float noise(in vec2 st) {
|
||||
vec2 i = floor(st);
|
||||
vec2 f = fract(st);
|
||||
|
||||
// Four corners in 2D of a tile
|
||||
float a = N21(i);
|
||||
float b = N21(i + vec2(1.0, 0.0));
|
||||
float c = N21(i + vec2(0.0, 1.0));
|
||||
float d = N21(i + vec2(1.0, 1.0));
|
||||
|
||||
// Smooth Interpolation
|
||||
vec2 u = f * f * (3.0 - 2.0 * f); // Cubic Hermite Curve
|
||||
|
||||
// Mix 4 corners percentages
|
||||
return mix(a, b, u.x) +
|
||||
(c - a) * u.y * (1.0 - u.x) +
|
||||
(d - b) * u.x * u.y;
|
||||
}
|
||||
|
||||
float perlin2(vec2 uv, int octaves, float pscale) {
|
||||
float col = 1.;
|
||||
float initScale = 4.;
|
||||
for (int l; l < octaves; l++) {
|
||||
float val = noise(uv * initScale);
|
||||
if (col <= 0.01) {
|
||||
col = 0.;
|
||||
break;
|
||||
}
|
||||
val -= 0.01;
|
||||
val *= 0.5;
|
||||
col *= val;
|
||||
initScale *= pscale;
|
||||
}
|
||||
return col;
|
||||
}
|
||||
|
||||
vec3 stars(vec2 uv, float offset) {
|
||||
float timeScale = -(iTime + offset) / layers;
|
||||
float trans = fract(timeScale);
|
||||
float newRnd = floor(timeScale);
|
||||
vec3 col = vec3(0.);
|
||||
|
||||
// Translate uv then scale for center
|
||||
uv -= vec2(0.5);
|
||||
uv = scale(vec2(trans)) * uv;
|
||||
uv += vec2(0.5);
|
||||
|
||||
// Create square aspect ratio
|
||||
uv.x *= iResolution.x / iResolution.y;
|
||||
|
||||
// Create boxes
|
||||
uv *= repeats;
|
||||
|
||||
// Get position
|
||||
vec2 ipos = floor(uv);
|
||||
|
||||
// Return uv as 0 to 1
|
||||
uv = fract(uv);
|
||||
|
||||
// Calculate random xy and size
|
||||
vec2 rndXY = N22(newRnd + ipos * (offset + 1.)) * 0.9 + 0.05;
|
||||
float rndSize = N21(ipos) * 100. + 200.;
|
||||
|
||||
vec2 j = (rndXY - uv) * rndSize;
|
||||
float sparkle = 1. / dot(j, j);
|
||||
|
||||
// Set stars to be pure white
|
||||
col += white * sparkle;
|
||||
|
||||
col *= smoothstep(1., 0.8, trans);
|
||||
return col; // Return pure white stars only
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord)
|
||||
{
|
||||
// Normalized pixel coordinates (from 0 to 1)
|
||||
vec2 uv = fragCoord / iResolution.xy;
|
||||
|
||||
vec3 col = vec3(0.);
|
||||
|
||||
for (float i = 0.; i < layers; i++) {
|
||||
col += stars(uv, i);
|
||||
}
|
||||
|
||||
// Sample the terminal screen texture including alpha channel
|
||||
vec4 terminalColor = texture(iChannel0, uv);
|
||||
|
||||
if (transparent) {
|
||||
col += terminalColor.rgb;
|
||||
}
|
||||
|
||||
// Make a mask that is 1.0 where the terminal content is not black
|
||||
float mask = 1 - step(threshold, luminance(terminalColor.rgb));
|
||||
|
||||
vec3 blendedColor = mix(terminalColor.rgb, col, mask);
|
||||
|
||||
// Apply terminal's alpha to control overall opacity
|
||||
fragColor = vec4(blendedColor, terminalColor.a);
|
||||
}
|
||||
581
ghostty-shaders/synthwave.glsl
Normal file
581
ghostty-shaders/synthwave.glsl
Normal file
|
|
@ -0,0 +1,581 @@
|
|||
// CC0: For the neon style enjoyers
|
||||
// Or is it synthwave style? Don't know!
|
||||
// Anyone been tinkering with this for awhile and now want to get on with other stuff
|
||||
// Hopefully someone enjoys it.
|
||||
|
||||
//#define THAT_CRT_FEELING
|
||||
|
||||
#define BLACK_BLEND_THRESHOLD .4 // This is controls the dim of the screen
|
||||
const float timeMultiplier = 0.3f;
|
||||
|
||||
#define TIME iTime*timeMultiplier
|
||||
#define RESOLUTION iResolution
|
||||
#define PI 3.141592654
|
||||
#define PI_2 (0.5*PI)
|
||||
#define TAU (2.0*PI)
|
||||
#define SCA(a) vec2(sin(a), cos(a))
|
||||
#define ROT(a) mat2(cos(a), sin(a), -sin(a), cos(a))
|
||||
|
||||
// License: WTFPL, author: sam hocevar, found: https://stackoverflow.com/a/17897228/418488
|
||||
const vec4 hsv2rgb_K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
||||
vec3 hsv2rgb(vec3 c) {
|
||||
vec3 p = abs(fract(c.xxx + hsv2rgb_K.xyz) * 6.0 - hsv2rgb_K.www);
|
||||
return c.z * mix(hsv2rgb_K.xxx, clamp(p - hsv2rgb_K.xxx, 0.0, 1.0), 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))
|
||||
// License: WTFPL, author: sam hocevar, found: https://stackoverflow.com/a/17897228/418488
|
||||
vec3 rgb2hsv(vec3 c) {
|
||||
const vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
|
||||
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
|
||||
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
|
||||
|
||||
float d = q.x - min(q.w, q.y);
|
||||
float e = 1.0e-10;
|
||||
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
|
||||
}
|
||||
|
||||
const vec3 skyCol = HSV2RGB(vec3(0.58, 0.86, 1.0));
|
||||
const vec3 speCol1 = HSV2RGB(vec3(0.60, 0.25, 1.0));
|
||||
const vec3 speCol2 = HSV2RGB(vec3(0.55, 0.25, 1.0));
|
||||
const vec3 diffCol1 = HSV2RGB(vec3(0.60, 0.90, 1.0));
|
||||
const vec3 diffCol2 = HSV2RGB(vec3(0.55, 0.90, 1.0));
|
||||
const vec3 sunCol1 = HSV2RGB(vec3(0.60, 0.50, 0.5));
|
||||
const vec3 sunDir2 = normalize(vec3(0., 0.82, 1.0));
|
||||
const vec3 sunDir = normalize(vec3(0.0, 0.05, 1.0));
|
||||
const vec3 sunCol = HSV2RGB(vec3(0.58, 0.86, 0.0005));
|
||||
const float mountainPos = -20.0;
|
||||
|
||||
// License: MIT, author: Pascal Gilcher, found: https://www.shadertoy.com/view/flSXRV
|
||||
float atan_approx(float y, float x) {
|
||||
float cosatan2 = x / (abs(x) + abs(y));
|
||||
float t = PI_2 - cosatan2 * PI_2;
|
||||
return y < 0.0 ? -t : t;
|
||||
}
|
||||
|
||||
// License: Unknown, author: Unknown, found: don't remember
|
||||
float tanh_approx(float x) {
|
||||
// Found this somewhere on the interwebs
|
||||
// return tanh(x);
|
||||
float x2 = x * x;
|
||||
return clamp(x * (27.0 + x2) / (27.0 + 9.0 * x2), -1.0, 1.0);
|
||||
}
|
||||
|
||||
vec3 toSpherical(vec3 p) {
|
||||
float r = length(p);
|
||||
float t = acos(p.z / r);
|
||||
float ph = atan_approx(p.y, p.x);
|
||||
return vec3(r, t, ph);
|
||||
}
|
||||
|
||||
// License: Unknown, author: nmz (twitter: @stormoid), found: https://www.shadertoy.com/view/NdfyRM
|
||||
vec3 sRGB(vec3 t) {
|
||||
return mix(1.055 * pow(t, vec3(1. / 2.4)) - 0.055, 12.92 * t, step(t, vec3(0.0031308)));
|
||||
}
|
||||
|
||||
// License: Unknown, author: Matt Taylor (https://github.com/64), found: https://64.github.io/tonemapping/
|
||||
vec3 aces_approx(vec3 v) {
|
||||
v = max(v, 0.0);
|
||||
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);
|
||||
}
|
||||
|
||||
// License: MIT OR CC-BY-NC-4.0, author: mercury, found: https://mercury.sexy/hg_sdf/
|
||||
float mod1(inout float p, float size) {
|
||||
float halfsize = size * 0.5;
|
||||
float c = floor((p + halfsize) / size);
|
||||
p = mod(p + halfsize, size) - halfsize;
|
||||
return c;
|
||||
}
|
||||
|
||||
// License: MIT OR CC-BY-NC-4.0, author: mercury, found: https://mercury.sexy/hg_sdf/
|
||||
vec2 mod2(inout vec2 p, vec2 size) {
|
||||
vec2 c = floor((p + size * 0.5) / size);
|
||||
p = mod(p + size * 0.5, size) - size * 0.5;
|
||||
return c;
|
||||
}
|
||||
|
||||
// License: MIT, author: Inigo Quilez, found: https://iquilezles.org/www/articles/intersectors/intersectors.htm
|
||||
float rayPlane(vec3 ro, vec3 rd, vec4 p) {
|
||||
return -(dot(ro, p.xyz) + p.w) / dot(rd, p.xyz);
|
||||
}
|
||||
|
||||
// License: MIT, author: Inigo Quilez, found: https://iquilezles.org/www/articles/distfunctions2d/distfunctions2d.htm
|
||||
float equilateralTriangle(vec2 p) {
|
||||
const float k = sqrt(3.0);
|
||||
p.x = abs(p.x) - 1.0;
|
||||
p.y = p.y + 1.0 / k;
|
||||
if (p.x + k * p.y > 0.0) p = vec2(p.x - k * p.y, -k * p.x - p.y) / 2.0;
|
||||
p.x -= clamp(p.x, -2.0, 0.0);
|
||||
return -length(p) * sign(p.y);
|
||||
}
|
||||
|
||||
// License: MIT, author: Inigo Quilez, found: https://iquilezles.org/www/articles/distfunctions2d/distfunctions2d.htm
|
||||
float box(vec2 p, vec2 b) {
|
||||
vec2 d = abs(p) - b;
|
||||
return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0);
|
||||
}
|
||||
|
||||
// License: MIT, author: Inigo Quilez, found: https://iquilezles.org/www/articles/distfunctions2d/distfunctions2d.htm
|
||||
float segment(vec2 p, vec2 a, vec2 b) {
|
||||
vec2 pa = p - a, ba = b - a;
|
||||
float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);
|
||||
return length(pa - ba * h);
|
||||
}
|
||||
|
||||
// License: Unknown, author: Unknown, found: don't remember
|
||||
float hash(vec2 co) {
|
||||
return fract(sin(dot(co.xy, vec2(12.9898, 58.233))) * 13758.5453);
|
||||
}
|
||||
|
||||
// License: MIT, author: Inigo Quilez, found: https://www.shadertoy.com/view/XslGRr
|
||||
float vnoise(vec2 p) {
|
||||
vec2 i = floor(p);
|
||||
vec2 f = fract(p);
|
||||
|
||||
vec2 u = f * f * (3.0 - 2.0 * f);
|
||||
|
||||
float a = hash(i + vec2(0.0, 0.0));
|
||||
float b = hash(i + vec2(1.0, 0.0));
|
||||
float c = hash(i + vec2(0.0, 1.0));
|
||||
float d = hash(i + vec2(1.0, 1.0));
|
||||
|
||||
float m0 = mix(a, b, u.x);
|
||||
float m1 = mix(c, d, u.x);
|
||||
float m2 = mix(m0, m1, u.y);
|
||||
|
||||
return m2;
|
||||
}
|
||||
|
||||
// License: MIT, author: Inigo Quilez, found: https://www.iquilezles.org/www/articles/spherefunctions/spherefunctions.htm
|
||||
vec2 raySphere(vec3 ro, vec3 rd, vec4 dim) {
|
||||
vec3 ce = dim.xyz;
|
||||
float ra = dim.w;
|
||||
vec3 oc = ro - ce;
|
||||
float b = dot(oc, rd);
|
||||
float c = dot(oc, oc) - ra * ra;
|
||||
float h = b * b - c;
|
||||
if (h < 0.0) return vec2(-1.0); // no intersection
|
||||
h = sqrt(h);
|
||||
return vec2(-b - h, -b + h);
|
||||
}
|
||||
|
||||
vec3 skyRender(vec3 ro, vec3 rd) {
|
||||
vec3 col = vec3(0.0);
|
||||
col += 0.025 * skyCol;
|
||||
col += skyCol * 0.0033 / pow((1.001 + ((dot(sunDir2, rd)))), 2.0);
|
||||
|
||||
float tp0 = rayPlane(ro, rd, vec4(vec3(0.0, 1.0, 0.0), 4.0));
|
||||
float tp1 = rayPlane(ro, rd, vec4(vec3(0.0, -1.0, 0.0), 6.0));
|
||||
float tp = tp1;
|
||||
tp = max(tp0, tp1);
|
||||
|
||||
if (tp1 > 0.0) {
|
||||
vec3 pos = ro + tp1 * rd;
|
||||
vec2 pp = pos.xz;
|
||||
float db = box(pp, vec2(5.0, 9.0)) - 3.0;
|
||||
|
||||
col += vec3(4.0) * skyCol * rd.y * rd.y * smoothstep(0.25, 0.0, db);
|
||||
col += vec3(0.8) * skyCol * exp(-0.5 * max(db, 0.0));
|
||||
col += 0.25 * sqrt(skyCol) * max(-db, 0.0);
|
||||
}
|
||||
|
||||
if (tp0 > 0.0) {
|
||||
vec3 pos = ro + tp0 * rd;
|
||||
vec2 pp = pos.xz;
|
||||
float ds = length(pp) - 0.5;
|
||||
|
||||
col += (0.25) * skyCol * exp(-.5 * max(ds, 0.0));
|
||||
}
|
||||
|
||||
return clamp(col, 0.0, 10.0);
|
||||
}
|
||||
|
||||
vec4 sphere(vec3 ro, vec3 rd, vec4 sdim) {
|
||||
vec2 si = raySphere(ro, rd, sdim);
|
||||
|
||||
vec3 nsp = ro + rd * si.x;
|
||||
|
||||
const vec3 lightPos1 = vec3(0.0, 10.0, 10.0);
|
||||
const vec3 lightPos2 = vec3(0.0, -80.0, 10.0);
|
||||
|
||||
vec3 nld1 = normalize(lightPos1 - nsp);
|
||||
vec3 nld2 = normalize(lightPos2 - nsp);
|
||||
|
||||
vec3 nnor = normalize(nsp - sdim.xyz);
|
||||
|
||||
vec3 nref = reflect(rd, nnor);
|
||||
|
||||
const float sf = 4.0;
|
||||
float ndif1 = max(dot(nld1, nnor), 0.0);
|
||||
ndif1 *= ndif1;
|
||||
vec3 nspe1 = pow(speCol1 * max(dot(nld1, nref), 0.0), sf * vec3(1.0, 0.8, 0.5));
|
||||
|
||||
float ndif2 = max(dot(nld2, nnor), 0.0);
|
||||
ndif2 *= ndif2;
|
||||
vec3 nspe2 = pow(speCol2 * max(dot(nld2, nref), 0.0), sf * vec3(0.9, 0.5, 0.5));
|
||||
|
||||
vec3 nsky = skyRender(nsp, nref);
|
||||
float nfre = 1.0 + dot(rd, nnor);
|
||||
nfre *= nfre;
|
||||
|
||||
vec3 scol = vec3(0.0);
|
||||
scol += nsky * mix(vec3(0.25), vec3(0.5, 0.5, 1.0), nfre);
|
||||
scol += diffCol1 * ndif1;
|
||||
scol += diffCol2 * ndif2;
|
||||
scol += nspe1;
|
||||
scol += nspe2;
|
||||
|
||||
float t = tanh_approx(2.0 * (si.y - si.x) / sdim.w);
|
||||
|
||||
return vec4(scol, t);
|
||||
}
|
||||
|
||||
vec3 sphereRender(vec3 ro, vec3 rd) {
|
||||
vec3 skyCol = skyRender(ro, rd);
|
||||
vec3 col = skyCol;
|
||||
const vec4 sdim0 = vec4(vec3(0.0), 2.0);
|
||||
vec4 scol0 = sphere(ro, rd, sdim0);
|
||||
col = mix(col, scol0.xyz, scol0.w);
|
||||
return col;
|
||||
}
|
||||
|
||||
vec3 sphereEffect(vec2 p) {
|
||||
const float fov = tan(TAU / 6.0);
|
||||
const vec3 ro = 1.0 * vec3(0.0, 2.0, 5.0);
|
||||
const vec3 la = vec3(0.0, 0.0, 0.0);
|
||||
const vec3 up = vec3(0.0, 1.0, 0.0);
|
||||
|
||||
vec3 ww = normalize(la - ro);
|
||||
vec3 uu = normalize(cross(up, ww));
|
||||
vec3 vv = cross(ww, uu);
|
||||
vec3 rd = normalize(-p.x * uu + p.y * vv + fov * ww);
|
||||
|
||||
vec3 col = sphereRender(ro, rd);
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
vec3 cityOfKali(vec2 p) {
|
||||
vec2 c = -vec2(0.5, 0.5) * 1.12;
|
||||
|
||||
float s = 2.0;
|
||||
vec2 kp = p / s;
|
||||
|
||||
const float a = PI / 4.0;
|
||||
const vec2 n = vec2(cos(a), sin(a));
|
||||
|
||||
float ot2 = 1E6;
|
||||
float ot3 = 1E6;
|
||||
float n2 = 0.0;
|
||||
float n3 = 0.0;
|
||||
|
||||
const float mx = 12.0;
|
||||
for (float i = 0.0; i < mx; ++i) {
|
||||
float m = (dot(kp, kp));
|
||||
s *= m;
|
||||
kp = abs(kp) / m + c;
|
||||
float d2 = (abs(dot(kp, n))) * s;
|
||||
if (d2 < ot2) {
|
||||
n2 = i;
|
||||
ot2 = d2;
|
||||
}
|
||||
float d3 = (dot(kp, kp));
|
||||
if (d3 < ot3) {
|
||||
n3 = i;
|
||||
ot3 = d3;
|
||||
}
|
||||
}
|
||||
vec3 col = vec3(0.0);
|
||||
n2 /= mx;
|
||||
n3 /= mx;
|
||||
col += 0.25 * (hsv2rgb(vec3(0.8 - 0.2 * n2 * n2, 0.90, 0.025)) / (sqrt(ot2) + 0.0025));
|
||||
col += hsv2rgb(vec3(0.55 + 0.8 * n3, 0.85, 0.00000025)) / (ot3 * ot3 + 0.000000025);
|
||||
return col;
|
||||
}
|
||||
|
||||
vec3 outerSkyRender(vec3 ro, vec3 rd) {
|
||||
vec3 center = ro + vec3(-100.0, 40.0, 100.0);
|
||||
vec4 sdim = vec4(center, 50);
|
||||
vec2 pi = raySphere(ro, rd, sdim);
|
||||
const vec3 pn = normalize(vec3(0., 1.0, -0.8));
|
||||
vec4 pdim = vec4(pn, -dot(pn, center));
|
||||
float ri = rayPlane(ro, rd, pdim);
|
||||
|
||||
vec3 col = vec3(0.0);
|
||||
|
||||
col += sunCol / pow((1.001 - ((dot(sunDir, rd)))), 2.0);
|
||||
|
||||
if (pi.x != -1.0) {
|
||||
vec3 pp = ro + rd * pi.x;
|
||||
vec3 psp = pp - sdim.xyz;
|
||||
vec3 pn = normalize(pp - sdim.xyz);
|
||||
psp = psp.zxy;
|
||||
psp.yz *= ROT(-0.5);
|
||||
psp.xy *= ROT(0.025 * TIME);
|
||||
vec3 pss = toSpherical(psp);
|
||||
vec3 pcol = vec3(0.0);
|
||||
float dif = max(dot(pn, sunDir), 0.0);
|
||||
vec3 sc = 2000.0 * sunCol;
|
||||
pcol += sc * dif;
|
||||
pcol += (cityOfKali(pss.yz)) * smoothstep(0.125, 0.0, dif);
|
||||
pcol += pow(max(dot(reflect(rd, pn), sunDir), 0.0), 9.0) * sc;
|
||||
col = mix(col, pcol, tanh_approx(0.125 * (pi.y - pi.x)));
|
||||
}
|
||||
|
||||
vec3 gcol = vec3(0.0);
|
||||
|
||||
vec3 rp = ro + rd * ri;
|
||||
float rl = length(rp - center);
|
||||
float rb = 1.55 * sdim.w;
|
||||
float re = 2.45 * sdim.w;
|
||||
float rw = 0.1 * sdim.w;
|
||||
vec3 rcol = hsv2rgb(vec3(clamp((0.005 * (rl + 32.0)), 0.6, 0.8), 0.9, 1.0));
|
||||
gcol = rcol * 0.025;
|
||||
if (ri > 0.0 && (pi.x == -1.0 || ri < pi.x)) {
|
||||
float mrl = rl;
|
||||
float nrl = mod1(mrl, rw);
|
||||
float rfre = 1.0 + dot(rd, pn);
|
||||
vec3 rrcol = (rcol / max(abs(mrl), 0.1 + smoothstep(0.7, 1.0, rfre)));
|
||||
rrcol *= smoothstep(1.0, 0.3, rfre);
|
||||
rrcol *= smoothstep(re, re - 0.5 * rw, rl);
|
||||
rrcol *= smoothstep(rb - 0.5 * rw, rb, rl);
|
||||
col += rrcol;
|
||||
;
|
||||
}
|
||||
|
||||
col += gcol / max(abs(rd.y), 0.0033);
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
vec3 triRender(vec3 col, vec3 ro, vec3 rd, inout float maxt) {
|
||||
const vec3 tpn = normalize(vec3(0.0, 0.0, 1.0));
|
||||
const vec4 tpdim = vec4(tpn, -2.0);
|
||||
float tpd = rayPlane(ro, rd, tpdim);
|
||||
|
||||
if (tpd < 0.0 || tpd > maxt) {
|
||||
return col;
|
||||
}
|
||||
|
||||
vec3 pp = ro + rd * tpd;
|
||||
vec2 p = pp.xy;
|
||||
p *= 0.5;
|
||||
|
||||
const float off = 1.2 - 0.02;
|
||||
vec2 op = p;
|
||||
p.y -= off;
|
||||
const vec2 n = SCA(-PI / 3.0);
|
||||
vec2 gp = p;
|
||||
float hoff = 0.15 * dot(n, p);
|
||||
vec3 gcol = hsv2rgb(vec3(clamp(0.7 + hoff, 0.6, 0.8), 0.90, 0.02));
|
||||
vec2 pt = p;
|
||||
pt.y = -pt.y;
|
||||
const float zt = 1.0;
|
||||
float dt = equilateralTriangle(pt / zt) * zt;
|
||||
// col += 2.0*gcol;
|
||||
col = dt < 0.0 ? sphereEffect(1.5 * (p)) : col;
|
||||
col += (gcol / max(abs(dt), 0.001)) * smoothstep(0.25, 0.0, dt);
|
||||
if (dt < 0.0) {
|
||||
maxt = tpd;
|
||||
}
|
||||
return col;
|
||||
}
|
||||
|
||||
float heightFactor(vec2 p) {
|
||||
return 4.0 * smoothstep(7.0, 0.5, abs(p.x)) + .5;
|
||||
}
|
||||
|
||||
float hifbm(vec2 p) {
|
||||
p *= 0.25;
|
||||
float hf = heightFactor(p);
|
||||
const float aa = 0.5;
|
||||
const float pp = 2.0 - 0.;
|
||||
|
||||
float sum = 0.0;
|
||||
float a = 1.0;
|
||||
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
sum += a * vnoise(p);
|
||||
a *= aa;
|
||||
p *= pp;
|
||||
}
|
||||
|
||||
return hf * sum;
|
||||
}
|
||||
|
||||
float hiheight(vec2 p) {
|
||||
return hifbm(p);
|
||||
}
|
||||
|
||||
float lofbm(vec2 p) {
|
||||
p *= 0.25;
|
||||
float hf = heightFactor(p);
|
||||
const float aa = 0.5;
|
||||
const float pp = 2.0 - 0.;
|
||||
|
||||
float sum = 0.0;
|
||||
float a = 1.0;
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
sum += a * vnoise(p);
|
||||
a *= aa;
|
||||
p *= pp;
|
||||
}
|
||||
|
||||
return hf * sum;
|
||||
}
|
||||
|
||||
float loheight(vec2 p) {
|
||||
return lofbm(p) - 0.5;
|
||||
}
|
||||
|
||||
vec3 mountainRender(vec3 col, vec3 ro, vec3 rd, bool flip, inout float maxt) {
|
||||
const vec3 tpn = normalize(vec3(0.0, 0.0, 1.0));
|
||||
const vec4 tpdim = vec4(tpn, mountainPos);
|
||||
float tpd = rayPlane(ro, rd, tpdim);
|
||||
|
||||
if (tpd < 0.0 || tpd > maxt) {
|
||||
return col;
|
||||
}
|
||||
|
||||
vec3 pp = ro + rd * tpd;
|
||||
vec2 p = pp.xy;
|
||||
const float cw = 1.0 - 0.25;
|
||||
float hz = 0.0 * TIME + 1.0;
|
||||
float lo = loheight(vec2(p.x, hz));
|
||||
vec2 cp = p;
|
||||
float cn = mod1(cp.x, cw);
|
||||
|
||||
const float reps = 1.0;
|
||||
|
||||
float d = 1E3;
|
||||
|
||||
for (float i = -reps; i <= reps; ++i) {
|
||||
float x0 = (cn - 0.5 + (i)) * cw;
|
||||
float x1 = (cn - 0.5 + (i + 1.0)) * cw;
|
||||
|
||||
float y0 = hiheight(vec2(x0, hz));
|
||||
float y1 = hiheight(vec2(x1, hz));
|
||||
|
||||
float dd = segment(cp, vec2(-cw * 0.5 + cw * float(i), y0), vec2(cw * 0.5 + cw * float(i), y1));
|
||||
|
||||
d = min(d, dd);
|
||||
}
|
||||
|
||||
vec3 rcol = hsv2rgb(vec3(clamp(0.7 + (0.5 * (rd.x)), 0.6, 0.8), 0.95, 0.125));
|
||||
|
||||
float sd = 1.0001 - ((dot(sunDir, rd)));
|
||||
|
||||
vec3 mcol = col;
|
||||
float aa = fwidth(p.y);
|
||||
if ((dFdy(d) < 0.0) == !flip) {
|
||||
mcol *= mix(0.0, 1.0, smoothstep(aa, -aa, d - aa));
|
||||
mcol += HSV2RGB(vec3(0.55, 0.85, 0.8)) * smoothstep(0.0, 5.0, lo - p.y);
|
||||
col = mcol;
|
||||
maxt = tpd;
|
||||
}
|
||||
col += 3. * rcol / (abs(d) + 0.005 + 800. * sd * sd * sd * sd);
|
||||
col += HSV2RGB(vec3(0.55, 0.96, 0.075)) / (abs(p.y) + 0.05);
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
vec3 groundRender(vec3 col, vec3 ro, vec3 rd, inout float maxt) {
|
||||
const vec3 gpn = normalize(vec3(0.0, 1.0, 0.0));
|
||||
const vec4 gpdim = vec4(gpn, 0.0);
|
||||
float gpd = rayPlane(ro, rd, gpdim);
|
||||
|
||||
if (gpd < 0.0) {
|
||||
return col;
|
||||
}
|
||||
|
||||
maxt = gpd;
|
||||
|
||||
vec3 gp = ro + rd * gpd;
|
||||
float gpfre = 1.0 + dot(rd, gpn);
|
||||
gpfre *= gpfre;
|
||||
gpfre *= gpfre;
|
||||
gpfre *= gpfre;
|
||||
|
||||
vec3 grr = reflect(rd, gpn);
|
||||
|
||||
vec2 ggp = gp.xz;
|
||||
ggp.y += TIME;
|
||||
float dfy = dFdy(ggp.y);
|
||||
float gcf = sin(ggp.x) * sin(ggp.y);
|
||||
vec2 ggn = mod2(ggp, vec2(1.0));
|
||||
float ggd = min(abs(ggp.x), abs(ggp.y));
|
||||
|
||||
vec3 gcol = hsv2rgb(vec3(0.7 + 0.1 * gcf, 0.90, 0.02));
|
||||
|
||||
float rmaxt = 1E6;
|
||||
vec3 rcol = outerSkyRender(gp, grr);
|
||||
rcol = mountainRender(rcol, gp, grr, true, rmaxt);
|
||||
rcol = triRender(rcol, gp, grr, rmaxt);
|
||||
|
||||
col = gcol / max(ggd, 0.0 + 0.25 * dfy) * exp(-0.25 * gpd);
|
||||
rcol += HSV2RGB(vec3(0.65, 0.85, 1.0)) * gpfre;
|
||||
rcol = 4.0 * tanh(rcol * 0.25);
|
||||
col += rcol * gpfre;
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
vec3 render(vec3 ro, vec3 rd) {
|
||||
float maxt = 1E6;
|
||||
|
||||
vec3 col = outerSkyRender(ro, rd);
|
||||
col = groundRender(col, ro, rd, maxt);
|
||||
col = mountainRender(col, ro, rd, false, maxt);
|
||||
col = triRender(col, ro, rd, maxt);
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
vec3 effect(vec2 p, vec2 pp) {
|
||||
const float fov = tan(TAU / 6.0);
|
||||
const vec3 ro = 1.0 * vec3(0.0, 1.0, -4.);
|
||||
const vec3 la = vec3(0.0, 1.0, 0.0);
|
||||
const vec3 up = vec3(0.0, 1.0, 0.0);
|
||||
|
||||
vec3 ww = normalize(la - ro);
|
||||
vec3 uu = normalize(cross(up, ww));
|
||||
vec3 vv = cross(ww, uu);
|
||||
vec3 rd = normalize(-p.x * uu + p.y * vv + fov * ww);
|
||||
|
||||
float aa = 2.0 / RESOLUTION.y;
|
||||
|
||||
vec3 col = render(ro, rd);
|
||||
#if defined(THAT_CRT_FEELING)
|
||||
col *= smoothstep(1.5, 0.5, length(pp));
|
||||
col *= 1.25 * mix(vec3(0.5), vec3(1.0), smoothstep(-0.9, 0.9, sin(0.25 * TAU * p.y / aa + TAU * vec3(0.0, 1., 2.0) / 3.0)));
|
||||
#endif
|
||||
col -= 0.05 * vec3(.00, 1.0, 2.0).zyx;
|
||||
col = aces_approx(col);
|
||||
col = sRGB(col);
|
||||
return col;
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
||||
vec2 q = fragCoord / RESOLUTION.xy;
|
||||
|
||||
vec2 p = -1. + 2. * q;
|
||||
vec2 pp = p;
|
||||
p.x *= RESOLUTION.x / RESOLUTION.y;
|
||||
vec3 col = effect(p, pp);
|
||||
|
||||
vec2 termUV = fragCoord.xy / iResolution.xy;
|
||||
vec4 terminalColor = texture(iChannel0, termUV);
|
||||
|
||||
float alpha = step(length(terminalColor.rgb), BLACK_BLEND_THRESHOLD);
|
||||
vec3 blendedColor = mix(terminalColor.rgb * 1.0, col.rgb * 0.2, alpha);
|
||||
|
||||
fragColor = vec4(blendedColor, terminalColor.a);
|
||||
}
|
||||
23
ghostty-shaders/tft.glsl
Normal file
23
ghostty-shaders/tft.glsl
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/** Size of TFT "pixels" */
|
||||
float resolution = 4.0;
|
||||
|
||||
/** Strength of effect */
|
||||
float strength = 0.5;
|
||||
|
||||
void _scanline(inout vec3 color, vec2 uv)
|
||||
{
|
||||
float scanline = step(1.2, mod(uv.y * iResolution.y, resolution));
|
||||
float grille = step(1.2, mod(uv.x * iResolution.x, resolution));
|
||||
color *= max(1.0 - strength, scanline * grille);
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord)
|
||||
{
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
vec3 color = texture(iChannel0, uv).rgb;
|
||||
|
||||
_scanline(color, uv);
|
||||
|
||||
fragColor.xyz = color;
|
||||
fragColor.w = 1.0;
|
||||
}
|
||||
126
ghostty-shaders/ui-noise-halo.glsl
Normal file
126
ghostty-shaders/ui-noise-halo.glsl
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
|
||||
#define BLACK_BLEND_THRESHOLD .4 // This is controls the dim of the screen
|
||||
// noise from https://www.shadertoy.com/view/4sc3z2
|
||||
vec3 hash33(vec3 p3)
|
||||
{
|
||||
p3 = fract(p3 * vec3(.1031, .11369, .13787));
|
||||
p3 += dot(p3, p3.yxz + 19.19);
|
||||
return -1.0 + 2.0 * fract(vec3(p3.x + p3.y, p3.x + p3.z, p3.y + p3.z) * p3.zyx);
|
||||
}
|
||||
float snoise3(vec3 p)
|
||||
{
|
||||
const float K1 = 0.333333333;
|
||||
const float K2 = 0.166666667;
|
||||
|
||||
vec3 i = floor(p + (p.x + p.y + p.z) * K1);
|
||||
vec3 d0 = p - (i - (i.x + i.y + i.z) * K2);
|
||||
|
||||
vec3 e = step(vec3(0.0), d0 - d0.yzx);
|
||||
vec3 i1 = e * (1.0 - e.zxy);
|
||||
vec3 i2 = 1.0 - e.zxy * (1.0 - e);
|
||||
|
||||
vec3 d1 = d0 - (i1 - K2);
|
||||
vec3 d2 = d0 - (i2 - K1);
|
||||
vec3 d3 = d0 - 0.5;
|
||||
|
||||
vec4 h = max(0.6 - vec4(dot(d0, d0), dot(d1, d1), dot(d2, d2), dot(d3, d3)), 0.0);
|
||||
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)));
|
||||
|
||||
return dot(vec4(31.316), n);
|
||||
}
|
||||
|
||||
vec4 extractAlpha(vec3 colorIn)
|
||||
{
|
||||
vec4 colorOut;
|
||||
float maxValue = min(max(max(colorIn.r, colorIn.g), colorIn.b), 1.0);
|
||||
if (maxValue > 1e-5)
|
||||
{
|
||||
colorOut.rgb = colorIn.rgb * (1.0 / maxValue);
|
||||
colorOut.a = maxValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
colorOut = vec4(0.0);
|
||||
}
|
||||
return colorOut;
|
||||
}
|
||||
|
||||
#define BG_COLOR (vec3(sin(iTime)*0.5+0.5) * 0.0 + vec3(0.0))
|
||||
#define time iTime
|
||||
const vec3 color1 = vec3(0.611765, 0.262745, 0.996078);
|
||||
const vec3 color2 = vec3(0.298039, 0.760784, 0.913725);
|
||||
const vec3 color3 = vec3(0.062745, 0.078431, 0.600000);
|
||||
const float innerRadius = 0.6;
|
||||
const float noiseScale = 0.65;
|
||||
|
||||
float light1(float intensity, float attenuation, float dist)
|
||||
{
|
||||
return intensity / (1.0 + dist * attenuation);
|
||||
}
|
||||
float light2(float intensity, float attenuation, float dist)
|
||||
{
|
||||
return intensity / (1.0 + dist * dist * attenuation);
|
||||
}
|
||||
|
||||
void draw(out vec4 _FragColor, in vec2 vUv)
|
||||
{
|
||||
vec2 uv = vUv;
|
||||
float ang = atan(uv.y, uv.x);
|
||||
float len = length(uv);
|
||||
float v0, v1, v2, v3, cl;
|
||||
float r0, d0, n0;
|
||||
float r, d;
|
||||
|
||||
// ring
|
||||
n0 = snoise3(vec3(uv * noiseScale, time * 0.5)) * 0.5 + 0.5;
|
||||
r0 = mix(mix(innerRadius, 1.0, 0.4), mix(innerRadius, 1.0, 0.6), n0);
|
||||
d0 = distance(uv, r0 / len * uv);
|
||||
v0 = light1(1.0, 10.0, d0);
|
||||
v0 *= smoothstep(r0 * 1.05, r0, len);
|
||||
cl = cos(ang + time * 2.0) * 0.5 + 0.5;
|
||||
|
||||
// high light
|
||||
float a = time * -1.0;
|
||||
vec2 pos = vec2(cos(a), sin(a)) * r0;
|
||||
d = distance(uv, pos);
|
||||
v1 = light2(1.5, 5.0, d);
|
||||
v1 *= light1(1.0, 50.0, d0);
|
||||
|
||||
// back decay
|
||||
v2 = smoothstep(1.0, mix(innerRadius, 1.0, n0 * 0.5), len);
|
||||
|
||||
// hole
|
||||
v3 = smoothstep(innerRadius, mix(innerRadius, 1.0, 0.5), len);
|
||||
|
||||
// color
|
||||
vec3 c = mix(color1, color2, cl);
|
||||
vec3 col = mix(color1, color2, cl);
|
||||
col = mix(color3, col, v0);
|
||||
col = (col + v1) * v2 * v3;
|
||||
col.rgb = clamp(col.rgb, 0.0, 1.0);
|
||||
|
||||
//gl_FragColor = extractAlpha(col);
|
||||
_FragColor = extractAlpha(col);
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord)
|
||||
{
|
||||
vec2 uv = (fragCoord * 2. - iResolution.xy) / iResolution.y;
|
||||
vec4 col;
|
||||
if (abs(uv.x) < 1.0) {
|
||||
draw(col, uv);
|
||||
vec3 bg = BG_COLOR;
|
||||
col.rgb = mix(bg, col.rgb, col.a); //normal blend
|
||||
}
|
||||
else {
|
||||
col.rgb = BG_COLOR;
|
||||
}
|
||||
|
||||
vec2 termUV = fragCoord.xy / iResolution.xy;
|
||||
vec4 terminalColor = texture(iChannel0, termUV);
|
||||
|
||||
float alpha = step(length(terminalColor.rgb), BLACK_BLEND_THRESHOLD);
|
||||
vec3 blendedColor = mix(terminalColor.rgb * 1.0, col.rgb * 0.3, alpha);
|
||||
|
||||
fragColor = vec4(blendedColor, terminalColor.a);
|
||||
}
|
||||
74
ghostty-shaders/underwater.glsl
Normal file
74
ghostty-shaders/underwater.glsl
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
// adapted by Alex Sherwin for Ghostty from https://www.shadertoy.com/view/lljGDt
|
||||
|
||||
#define BLACK_BLEND_THRESHOLD .4
|
||||
|
||||
float hash21(vec2 p) {
|
||||
p = fract(p * vec2(233.34, 851.73));
|
||||
p += dot(p, p + 23.45);
|
||||
return fract(p.x * p.y);
|
||||
}
|
||||
|
||||
float rayStrength(vec2 raySource, vec2 rayRefDirection, vec2 coord, float seedA, float seedB, float speed)
|
||||
{
|
||||
vec2 sourceToCoord = coord - raySource;
|
||||
float cosAngle = dot(normalize(sourceToCoord), rayRefDirection);
|
||||
|
||||
// Add subtle dithering based on screen coordinates
|
||||
float dither = hash21(coord) * 0.015 - 0.0075;
|
||||
|
||||
float ray = clamp(
|
||||
(0.45 + 0.15 * sin(cosAngle * seedA + iTime * speed)) +
|
||||
(0.3 + 0.2 * cos(-cosAngle * seedB + iTime * speed)) + dither,
|
||||
0.0, 1.0);
|
||||
|
||||
// Smoothstep the distance falloff
|
||||
float distFade = smoothstep(0.0, iResolution.x, iResolution.x - length(sourceToCoord));
|
||||
return ray * mix(0.5, 1.0, distFade);
|
||||
}
|
||||
|
||||
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||
{
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
|
||||
uv.y = 1.0 - uv.y;
|
||||
vec2 coord = vec2(fragCoord.x, iResolution.y - fragCoord.y);
|
||||
|
||||
// Set the parameters of the sun rays
|
||||
vec2 rayPos1 = vec2(iResolution.x * 0.7, iResolution.y * 1.1);
|
||||
vec2 rayRefDir1 = normalize(vec2(1.0, 0.116));
|
||||
float raySeedA1 = 36.2214;
|
||||
float raySeedB1 = 21.11349;
|
||||
float raySpeed1 = 1.1;
|
||||
|
||||
vec2 rayPos2 = vec2(iResolution.x * 0.8, iResolution.y * 1.2);
|
||||
vec2 rayRefDir2 = normalize(vec2(1.0, -0.241));
|
||||
const float raySeedA2 = 22.39910;
|
||||
const float raySeedB2 = 18.0234;
|
||||
const float raySpeed2 = 0.9;
|
||||
|
||||
// Calculate the colour of the sun rays on the current fragment
|
||||
vec4 rays1 =
|
||||
vec4(1.0, 1.0, 1.0, 0.0) *
|
||||
rayStrength(rayPos1, rayRefDir1, coord, raySeedA1, raySeedB1, raySpeed1);
|
||||
|
||||
vec4 rays2 =
|
||||
vec4(1.0, 1.0, 1.0, 0.0) *
|
||||
rayStrength(rayPos2, rayRefDir2, coord, raySeedA2, raySeedB2, raySpeed2);
|
||||
|
||||
vec4 col = rays1 * 0.5 + rays2 * 0.4;
|
||||
|
||||
// Attenuate brightness towards the bottom, simulating light-loss due to depth.
|
||||
// Give the whole thing a blue-green tinge as well.
|
||||
float brightness = 1.0 - (coord.y / iResolution.y);
|
||||
col.r *= 0.05 + (brightness * 0.8);
|
||||
col.g *= 0.15 + (brightness * 0.6);
|
||||
col.b *= 0.3 + (brightness * 0.5);
|
||||
|
||||
vec2 termUV = fragCoord.xy / iResolution.xy;
|
||||
vec4 terminalColor = texture(iChannel0, termUV);
|
||||
|
||||
float alpha = step(length(terminalColor.rgb), BLACK_BLEND_THRESHOLD);
|
||||
vec3 blendedColor = mix(terminalColor.rgb * 1.0, col.rgb * 0.3, alpha);
|
||||
|
||||
fragColor = vec4(blendedColor, terminalColor.a);
|
||||
}
|
||||
108
ghostty-shaders/warping.glsl
Normal file
108
ghostty-shaders/warping.glsl
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
#define BLACK_BLEND_THRESHOLD .4 // This is controls the dim of the screen
|
||||
const mat2 m = mat2(0.80, 0.60, -0.60, 0.80);
|
||||
|
||||
float noise(in vec2 p)
|
||||
{
|
||||
return sin(p.x) * sin(p.y);
|
||||
}
|
||||
|
||||
float fbm4(vec2 p)
|
||||
{
|
||||
float f = 0.0;
|
||||
f += 0.5000 * noise(p);
|
||||
p = m * p * 2.02;
|
||||
f += 0.2500 * noise(p);
|
||||
p = m * p * 2.03;
|
||||
f += 0.1250 * noise(p);
|
||||
p = m * p * 2.01;
|
||||
f += 0.0625 * noise(p);
|
||||
return f / 0.9375;
|
||||
}
|
||||
|
||||
float fbm6(vec2 p)
|
||||
{
|
||||
float f = 0.0;
|
||||
f += 0.500000 * (0.5 + 0.5 * noise(p));
|
||||
p = m * p * 2.02;
|
||||
f += 0.250000 * (0.5 + 0.5 * noise(p));
|
||||
p = m * p * 2.03;
|
||||
f += 0.125000 * (0.5 + 0.5 * noise(p));
|
||||
p = m * p * 2.01;
|
||||
f += 0.062500 * (0.5 + 0.5 * noise(p));
|
||||
p = m * p * 2.04;
|
||||
f += 0.031250 * (0.5 + 0.5 * noise(p));
|
||||
p = m * p * 2.01;
|
||||
f += 0.015625 * (0.5 + 0.5 * noise(p));
|
||||
return f / 0.96875;
|
||||
}
|
||||
|
||||
vec2 fbm4_2(vec2 p)
|
||||
{
|
||||
return vec2(fbm4(p), fbm4(p + vec2(7.8)));
|
||||
}
|
||||
|
||||
vec2 fbm6_2(vec2 p)
|
||||
{
|
||||
return vec2(fbm6(p + vec2(16.8)), fbm6(p + vec2(11.5)));
|
||||
}
|
||||
|
||||
//====================================================================
|
||||
|
||||
float func(vec2 q, out vec4 ron)
|
||||
{
|
||||
q += 0.03 * sin(vec2(0.27, 0.23) * iTime + length(q) * vec2(4.1, 4.3));
|
||||
|
||||
vec2 o = fbm4_2(0.9 * q);
|
||||
|
||||
o += 0.04 * sin(vec2(0.12, 0.14) * iTime + length(o));
|
||||
|
||||
vec2 n = fbm6_2(3.0 * o);
|
||||
|
||||
ron = vec4(o, n);
|
||||
|
||||
float f = 0.5 + 0.5 * fbm4(1.8 * q + 6.0 * n);
|
||||
|
||||
return mix(f, f * f * f * 3.5, f * abs(n.x));
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord)
|
||||
{
|
||||
vec2 p = (2.0 * fragCoord - iResolution.xy) / iResolution.y;
|
||||
float e = 2.0 / iResolution.y;
|
||||
|
||||
vec4 on = vec4(0.0);
|
||||
float f = func(p, on);
|
||||
|
||||
vec3 col = vec3(0.0);
|
||||
col = mix(vec3(0.2, 0.1, 0.4), vec3(0.3, 0.05, 0.05), f);
|
||||
col = mix(col, vec3(0.9, 0.9, 0.9), dot(on.zw, on.zw));
|
||||
col = mix(col, vec3(0.4, 0.3, 0.3), 0.2 + 0.5 * on.y * on.y);
|
||||
col = mix(col, vec3(0.0, 0.2, 0.4), 0.5 * smoothstep(1.2, 1.3, abs(on.z) + abs(on.w)));
|
||||
col = clamp(col * f * 2.0, 0.0, 1.0);
|
||||
|
||||
#if 0
|
||||
// gpu derivatives - bad quality, but fast
|
||||
vec3 nor = normalize(vec3(dFdx(f) * iResolution.x, 6.0, dFdy(f) * iResolution.y));
|
||||
#else
|
||||
// manual derivatives - better quality, but slower
|
||||
vec4 kk;
|
||||
vec3 nor = normalize(vec3(func(p + vec2(e, 0.0), kk) - f,
|
||||
2.0 * e,
|
||||
func(p + vec2(0.0, e), kk) - f));
|
||||
#endif
|
||||
|
||||
vec3 lig = normalize(vec3(0.9, 0.2, -0.4));
|
||||
float dif = clamp(0.3 + 0.7 * dot(nor, lig), 0.0, 1.0);
|
||||
vec3 lin = vec3(0.70, 0.90, 0.95) * (nor.y * 0.5 + 0.5) + vec3(0.15, 0.10, 0.05) * dif;
|
||||
col *= 1.2 * lin;
|
||||
col = 1.0 - col;
|
||||
col = 1.1 * col * col;
|
||||
|
||||
vec2 termUV = fragCoord.xy / iResolution.xy;
|
||||
vec4 terminalColor = texture(iChannel0, termUV);
|
||||
//
|
||||
float alpha = step(length(terminalColor.rgb), BLACK_BLEND_THRESHOLD);
|
||||
vec3 blendedColor = mix(terminalColor.rgb * 1.0, col.rgb * 0.3, alpha);
|
||||
//
|
||||
fragColor = vec4(blendedColor, terminalColor.a);
|
||||
}
|
||||
35
ghostty-shaders/water.glsl
Normal file
35
ghostty-shaders/water.glsl
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
|
||||
#define TAU 6.28318530718
|
||||
#define MAX_ITER 6
|
||||
|
||||
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||
{
|
||||
vec3 water_color = vec3(1.0, 1.0, 1.0) * 0.5;
|
||||
float time = iTime * 0.5+23.0;
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
|
||||
vec2 p = mod(uv*TAU, TAU)-250.0;
|
||||
vec2 i = vec2(p);
|
||||
float c = 1.0;
|
||||
float inten = 0.005;
|
||||
|
||||
for (int n = 0; n < MAX_ITER; n++)
|
||||
{
|
||||
float t = time * (1.0 - (3.5 / float(n+1)));
|
||||
i = p + vec2(cos(t - i.x) + sin(t + i.y), sin(t - i.y) + cos(t + i.x));
|
||||
c += 1.0/length(vec2(p.x / (sin(i.x+t)/inten),p.y / (cos(i.y+t)/inten)));
|
||||
}
|
||||
c /= float(MAX_ITER);
|
||||
c = 1.17-pow(c, 1.4);
|
||||
vec3 color = vec3(pow(abs(c), 15.0));
|
||||
color = clamp((color + water_color)*1.2, 0.0, 1.0);
|
||||
|
||||
// perterb uv based on value of c from caustic calc above
|
||||
vec2 tc = vec2(cos(c)-0.75,sin(c)-0.75)*0.04;
|
||||
uv = clamp(uv + tc,0.0,1.0);
|
||||
|
||||
fragColor = texture(iChannel0, uv);
|
||||
// give transparent pixels a color
|
||||
if ( fragColor.a == 0.0 ) fragColor=vec4(1.0,1.0,1.0,1.0);
|
||||
fragColor *= vec4(color, 1.0);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue