r/shaders

▲ 269 r/shaders+2 crossposts

I free made a stylized shader pack!

Hey everyone!

link : https://phonix-cool.itch.io/ultimate-shader-pack2

I've been working on Godot Ultimate Shader Pack 2, a collection of stylized 3D shaders for Godot 4.x.

It currently includes:

  • Toon Shader
  • Outline Shader
  • Comic Shader
  • PSX Shader
  • Gradient Toon Shader
  • Sketch Shader
  • Rim Light Shader
  • Stylized Water
u/Novaleaf — 5 days ago
▲ 26 r/shaders+2 crossposts

FREE Painterly Shader for Unity

Hi, I'm a 2D/3D Artist and Game Design Enthusiast currently learning Tech Art. 

This is my first time publishing a shader, and it is still in the testing phase.
So, your feedback matters a lot to me!

It is a stylized Unlit Unity shader (unity 6+) designed to create a painterly or toon look with customizable lighting and brush-stroke effects.
It utilizes base color and maps instead of normal maps for better performance to achieve the intended look.

It is free to use just give me credit! :)

https://nomadsponge.itch.io/unity-painterlytoon-shader

u/Spongy_D — 4 days ago
▲ 83 r/shaders+2 crossposts

Legacy-console-ish Minecraft shader

Working on a small shader project very lightweight, attempts to replicate the old PS3/XBOX 360 vibe. Checking if anyone is interested, maybe ill publish it (resource pack is not made by me, PACP on modrinth).

u/Maleficent-Sort-1641 — 4 days ago

I built a web-based SKSL (Skia Shading Language) playground!

I love Shadertoy for GLSL, but lately I’ve been doing a lot of rendering work using the Skia graphics engine (specifically for Flutter and React Native).

Skia uses its own shading language called SKSL. It’s very similar to GLSL, but it has enough syntax quirks and specific uniform requirements that testing them meant constantly compiling native apps just to see if a visual effect worked.

I got tired of the slow workflow, so I built Skia Labs.

It’s a dedicated, web-based playground for writing and testing SKSL.

Under the hood:

  • It runs entirely in the browser using CanvasKit WASM (so it is rendering on the actual Skia engine, not a WebGL approximation).
  • Built-in Monaco editor with custom SKSL syntax highlighting.
  • Locks in at a buttery smooth 60fps.
  • (I also built an AI agent skill that you can download to help translate standard GLSL over to SKSL syntax automatically).

You can try the editor out for free here: https://skialabs.dev

Would love to hear what the graphics programming community thinks of it, and if there are any specific Skia features you'd want added to the editor!

u/Powerful-Sorbet6660 — 5 days ago
▲ 8 r/shaders+1 crossposts

I made a free stylized VFX pack for Godot 4.x

I've released my Godot Ultimate VFX Pack for free!

It currently includes:

  • Magic Orb
  • Fireball
  • Magic Ball
  • Fire
  • Dark Magic Circle
  • Dark Magic Orb

Everything is customizable directly in the Godot Inspector, including colors, glow, animation speed, distortion and intensity.

It's completely free to download and use in your Godot projects.

I'd love to hear what VFX I should add next!

https://phonix-cool.itch.io/godot-ultimate-vfx-pack

u/Ok_Signature8979 — 5 days ago
▲ 58 r/shaders

Wind shader for voxel forest

I'm once again amazed for what kind of things shaders can be used.

Because I use greedy meshing with T-junctions I had to make sure that the shader doesn't cause cracks between the faces. I solved this by keeping it multilinear in (y, x·y, y·z) with per tree constant coefficients, so it interpolates along axis-aligned edges.

u/calfurdev — 8 days ago
▲ 38 r/shaders+3 crossposts

Calculus on a Live Shadertoy Ocean - manic

manic is a tiny language for making animations. You write a short text file; manic renders a smooth, glowing video. No timeline scrubbing, no keyframes by hand — you describe what’s on screen and when things happen, and the engine does the rest, deterministically.

Manic Animation code

// glsl-derivative-wave — "manic meets Shadertoy": a real Shadertoy (TDM's raymarched
// Seascape) runs as a LIVE backdrop the whole time, while a Calculus-1 lesson plays on
// top of it — the DERIVATIVE as the slope of the tangent line, taught as "the slope of
// a wave". A tangent slides along y = sin x; its slope is positive climbing, ZERO at the
// crest (the water is momentarily flat - a maximum), negative descending, zero again at
// the trough. The payoff reveals f'(x) = cos x crossing zero exactly at those peaks.
// Everything is 2D over the shader, so the ocean never leaves the frame.
// Shader: https://www.shadertoy.com/view/Ms2SD1 (Alexander Alekseev, CC BY-NC-SA 3.0)
//
//   manic examples/glsl-derivative-wave.manic
title("manic meets Shadertoy - the slope of a wave");
canvas(1280, 720);
template("black");

// ================= the live Shadertoy (TDM's Seascape, raw glsl) =================
glsl(sea, `
const int NUM_STEPS = 32;
const float PI         = 3.141592;
const float EPSILON    = 1e-3;
#define EPSILON_NRM (0.1 / iResolution.x)
const int ITER_GEOMETRY = 3;
const int ITER_FRAGMENT = 5;
const float SEA_HEIGHT = 0.6;
const float SEA_CHOPPY = 4.0;
const float SEA_SPEED = 0.8;
const float SEA_FREQ = 0.16;
const vec3 SEA_BASE = vec3(0.0,0.09,0.18);
const vec3 SEA_WATER_COLOR = vec3(0.8,0.9,0.6)*0.6;
#define SEA_TIME (1.0 + iTime * SEA_SPEED)
const mat2 octave_m = mat2(1.6,1.2,-1.2,1.6);
mat3 fromEuler(vec3 ang) {
    vec2 a1 = vec2(sin(ang.x),cos(ang.x));
    vec2 a2 = vec2(sin(ang.y),cos(ang.y));
    vec2 a3 = vec2(sin(ang.z),cos(ang.z));
    mat3 m;
    m[0] = vec3(a1.y*a3.y+a1.x*a2.x*a3.x,a1.y*a2.x*a3.x+a3.y*a1.x,-a2.y*a3.x);
    m[1] = vec3(-a2.y*a1.x,a1.y*a2.y,a2.x);
    m[2] = vec3(a3.y*a1.x*a2.x+a1.y*a3.x,a1.x*a3.x-a1.y*a3.y*a2.x,a2.y*a3.y);
    return m;
}
float hash( vec2 p ) { float h = dot(p,vec2(127.1,311.7)); return fract(sin(h)*43758.5453123); }
float noise( in vec2 p ) {
    vec2 i = floor( p ); vec2 f = fract( p );
    vec2 u = f*f*(3.0-2.0*f);
    return -1.0+2.0*mix( mix( hash( i + vec2(0.0,0.0) ), hash( i + vec2(1.0,0.0) ), u.x),
                mix( hash( i + vec2(0.0,1.0) ), hash( i + vec2(1.0,1.0) ), u.x), u.y);
}
float diffuse(vec3 n,vec3 l,float p) { return pow(dot(n,l) * 0.4 + 0.6,p); }
float specular(vec3 n,vec3 l,vec3 e,float s) {
    float nrm = (s + 8.0) / (PI * 8.0);
    return pow(max(dot(reflect(e,n),l),0.0),s) * nrm;
}
vec3 getSkyColor(vec3 e) {
    e.y = (max(e.y,0.0)*0.8+0.2)*0.8;
    return vec3(pow(1.0-e.y,2.0), 1.0-e.y, 0.6+(1.0-e.y)*0.4) * 1.1;
}
float sea_octave(vec2 uv, float choppy) {
    uv += noise(uv);
    vec2 wv = 1.0-abs(sin(uv)); vec2 swv = abs(cos(uv));
    wv = mix(wv,swv,wv);
    return pow(1.0-pow(wv.x * wv.y,0.65),choppy);
}
float map(vec3 p) {
    float freq = SEA_FREQ; float amp = SEA_HEIGHT; float choppy = SEA_CHOPPY;
    vec2 uv = p.xz; uv.x *= 0.75;
    float d, h = 0.0;
    for(int i = 0; i < ITER_GEOMETRY; i++) {
        d = sea_octave((uv+SEA_TIME)*freq,choppy);
        d += sea_octave((uv-SEA_TIME)*freq,choppy);
        h += d * amp; uv *= octave_m; freq *= 1.9; amp *= 0.22;
        choppy = mix(choppy,1.0,0.2);
    }
    return p.y - h;
}
float map_detailed(vec3 p) {
    float freq = SEA_FREQ; float amp = SEA_HEIGHT; float choppy = SEA_CHOPPY;
    vec2 uv = p.xz; uv.x *= 0.75;
    float d, h = 0.0;
    for(int i = 0; i < ITER_FRAGMENT; i++) {
        d = sea_octave((uv+SEA_TIME)*freq,choppy);
        d += sea_octave((uv-SEA_TIME)*freq,choppy);
        h += d * amp; uv *= octave_m; freq *= 1.9; amp *= 0.22;
        choppy = mix(choppy,1.0,0.2);
    }
    return p.y - h;
}
vec3 getSeaColor(vec3 p, vec3 n, vec3 l, vec3 eye, vec3 dist) {
    float fresnel = clamp(1.0 - dot(n, -eye), 0.0, 1.0);
    fresnel = min(fresnel * fresnel * fresnel, 0.5);
    vec3 reflected = getSkyColor(reflect(eye, n));
    vec3 refracted = SEA_BASE + diffuse(n, l, 80.0) * SEA_WATER_COLOR * 0.12;
    vec3 color = mix(refracted, reflected, fresnel);
    float atten = max(1.0 - dot(dist, dist) * 0.001, 0.0);
    color += SEA_WATER_COLOR * (p.y - SEA_HEIGHT) * 0.18 * atten;
    color += specular(n, l, eye, 600.0 * inversesqrt(dot(dist,dist)));
    return color;
}
vec3 getNormal(vec3 p, float eps) {
    vec3 n;
    n.y = map_detailed(p);
    n.x = map_detailed(vec3(p.x+eps,p.y,p.z)) - n.y;
    n.z = map_detailed(vec3(p.x,p.y,p.z+eps)) - n.y;
    n.y = eps;
    return normalize(n);
}
float heightMapTracing(vec3 ori, vec3 dir, out vec3 p) {
    float tm = 0.0; float tx = 1000.0;
    float hx = map(ori + dir * tx);
    if(hx > 0.0) { p = ori + dir * tx; return tx; }
    float hm = map(ori);
    for(int i = 0; i < NUM_STEPS; i++) {
        float tmid = mix(tm, tx, hm / (hm - hx));
        p = ori + dir * tmid;
        float hmid = map(p);
        if(hmid < 0.0) { tx = tmid; hx = hmid; } else { tm = tmid; hm = hmid; }
        if(abs(hmid) < EPSILON) break;
    }
    return mix(tm, tx, hm / (hm - hx));
}
vec3 getPixel(in vec2 coord, float time) {
    vec2 uv = coord / iResolution.xy;
    uv = uv * 2.0 - 1.0;
    uv.x *= iResolution.x / iResolution.y;
    vec3 ang = vec3(sin(time*3.0)*0.1,sin(time)*0.2+0.3,time);
    vec3 ori = vec3(0.0,3.5,time*5.0);
    vec3 dir = normalize(vec3(uv.xy,-2.0)); dir.z += length(uv) * 0.14;
    dir = normalize(dir) * fromEuler(ang);
    vec3 p;
    heightMapTracing(ori,dir,p);
    vec3 dist = p - ori;
    vec3 n = getNormal(p, dot(dist,dist) * EPSILON_NRM);
    vec3 light = normalize(vec3(0.0,1.0,0.8));
    return mix(getSkyColor(dir), getSeaColor(p,n,light,dir,dist),
               pow(smoothstep(0.0,-0.02,dir.y),0.2));
}
void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
    float time = iTime * 0.3;
    vec3 color = getPixel(fragCoord, time);
    fragColor = vec4(pow(color,vec3(0.65)), 1.0);
}
`);
z(sea, -20);

// subdue the sea so the bright graph pops (still shimmering underneath)
rect(scrim, (640, 360), 1280, 720); color(scrim, #04070b); opacity(scrim, 0.42); z(scrim, -15);
// cinematic bands for the title & captions
rect(topband, (640, 46), 1280, 132); color(topband, #05070a); opacity(topband, 0.5); z(topband, -9);
rect(botband, (640, 684), 1280, 76);  color(botband, #05070a); opacity(botband, 0.5); z(botband, -9);

// ---- HUD ----
text(head, (640, 42), "manic meets Shadertoy"); size(head, 40); color(head, white); glow(head, 6); display(head); cursor(head);
text(sub, (640, 86), "the derivative - the slope of a wave"); size(sub, 20); color(sub, #bfe6ef); hidden(sub);
text(cap, (640, 684), ""); size(cap, 22); color(cap, white);

// worksheet chip (dark glass) — the symbolic ladder f -> f' -> f''
rect(chip, (1075, 172), 330, 224); color(chip, #081420); opacity(chip, 0.6); z(chip, -8);
equation(eqf, (1075, 112), `f(x)=\sin x`, 25); hidden(eqf);
equation(eqfp, (1075, 168), `f'(x)=\cos x`, 25); hidden(eqfp);
equation(eqfpp, (1075, 224), `f''(x)=-\sin x`, 25); hidden(eqfpp);

// ---- the wave and the tangent that reads its slope ----
let gx = 150;
let gy = 392;
arrow(xax, (gx - 30, gy), (gx + 6.3*150 + 30, gy)); untraced(xax); stroke(xax, 2); color(xax, #9fb6c4); tag(xax, g2);
plot(wave, (gx, gy), 150, 125, "sin(x)", (0, 6.3));
untraced(wave); stroke(wave, 5); color(wave, #7fe0ff); glow(wave, 5);
// the derivative curve f'(x)=cos x — revealed in Act 1
deriv(dv, wave, #ff7bd0); untraced(dv); dashed(dv, 10, 8);
// the SECOND derivative f''(x)=-sin x (derivative of the derivative) — Act 2
deriv(dv2, dv, #ffb14e); untraced(dv2); dashed(dv2, 4, 8);
// extrema (crest & trough) and inflection points (concavity flips)
extrema(ext, wave, gold); hidden(ext);
inflections(infl, wave, #74f7a0); hidden(infl);
// the tangent line + its LIVE slope readout, both riding the same x
tangent(tang, wave, 0.35, 300); color(tang, gold); stroke(tang, 4); glow(tang, 4); hidden(tang);
slope(slp, wave, 0.35); color(slp, gold); hidden(slp);

// ================= timeline =================

// ---- establish: a live Shadertoy, then calculus on it
type(head, 1.0);
show(sub, 0.5);
say(cap, "this whole sea is one real Shadertoy - now let's do calculus on it", 0.9);
wait(0.4);

// ---- the wave is a function
par { draw(xax, 0.6); show(eqf, 0.5); }
draw(wave, 1.6);
say(cap, "a wave is just a function - here y = sin x", 0.8);
par { show(tang, 0.5); show(slp, 0.4); }
say(cap, "the derivative is the SLOPE of the tangent line - how steep the water is here", 0.9);
wait(0.4);

// ---- climb to the crest: slope positive -> zero
say(cap, "climbing the front of the wave - the slope is positive", 0.8);
par { to(tang, x, 1.5708, 1.8); to(slp, x, 1.5708, 1.8); }
say(cap, "at the crest the water is momentarily FLAT - the slope is zero", 1.0);
pulse(slp, 0.8);
wait(0.5);

// ---- down to the trough: slope negative -> zero
say(cap, "over the top and down - now the slope is negative", 0.9);
par { to(tang, x, 4.7124, 2.2); to(slp, x, 4.7124, 2.2); }
say(cap, "at the trough it's flat again - slope zero, a minimum", 0.9);
pulse(slp, 0.8);
wait(0.4);

// ---- f' as a curve: zero slope marks the peaks; reveal f'(x)=cos x
show(ext, 0.6);
say(cap, "zero slope marks every peak and every trough", 0.8);
show(eqfp, 0.5);
draw(dv, 1.6);
say(cap, "and there is f'(x) = cos x - it crosses zero exactly at those points", 1.0);
wait(0.6);

// ---- Act 2: peak or valley? the SECOND derivative decides
say(cap, "but f'(x)=0 only finds the flat spots - which is a peak, which a valley?", 1.1);
say(cap, "differentiate AGAIN: f''(x) is the curvature - how the slope itself changes", 1.1);
show(eqfpp, 0.5);
draw(dv2, 1.6);
wait(0.3);

// second-derivative test at the crest
par { show(tang, 0.4); show(slp, 0.4); to(tang, x, 1.5708, 0.9); to(slp, x, 1.5708, 0.9); }
say(cap, "at the crest f'' < 0: the wave arches over - concave down - a MAXIMUM", 1.2);
pulse(dv2, 0.7);
wait(0.4);

// second-derivative test at the trough
par { to(tang, x, 4.7124, 1.3); to(slp, x, 4.7124, 1.3); }
say(cap, "at the trough f'' > 0: it cups upward - concave up - a MINIMUM", 1.2);
pulse(dv2, 0.7);
wait(0.4);

// inflection points where concavity flips (f''=0)
show(infl, 0.6);
say(cap, "and where f''=0 - the zero-crossings - the curve flips: inflection points", 1.2);
pulse(infl, 0.8);
wait(0.5);

// ---- close: the whole ladder, sin -> cos -> -sin
fade(tang, 0.5);
say(cap, "position, slope, curvature - sin, cos, minus sin - one wave, fully read", 1.2);
say(cap, "real calculus on a real shader - manic meets Shadertoy", 1.1);
wait(2.6);
u/anish2good — 14 days ago