Skip to content

Instantly share code, notes, and snippets.

@mrange
Last active September 6, 2026 09:08
Show Gist options
  • Select an option

  • Save mrange/2dff1cfe69ecda11a9c061d6dcfc9e18 to your computer and use it in GitHub Desktop.

Select an option

Save mrange/2dff1cfe69ecda11a9c061d6dcfc9e18 to your computer and use it in GitHub Desktop.
Snippets for shader devs

Snippets for shader devs

⚠️ All text content on this blog is licensed under CC BY-SA 4.0. All code is licensed under CC0. ⚠️

All code assumes shadertoy environment:

// O - output color
// C - pixel coordinate
// iResolution - vec3 uniform containing the resolution, .z is 1 when generating 2D fragments.
void mainImage(out vec4 O, vec2 C) {
}

Resources

  1. ShaderToy
  2. IQ's 3D SDFs
  3. IQ's smooth minimum
  4. Mercury's GLSL lib

General

Ray direction

float 
  fov = 2.
;
vec2
  r = iResolution.xy
, p = (2.*C-r)/r.y
;

vec3
  ray_origin   = vec(0,0,3)
, look_at      = vec3(0,0,0)
, up           = vec3(0,1,0)
, Z            = normalize(look_at-ray_origin)
, X            = normalize(cross(Z,up))
, Y            = cross(X,Z)
, ray_direction= normalize(mat3(X,Y,Z)*vec3(p,fov))
;

Code golfing

Ray direction with resolution as vec2

vec2
  r = iResolution.xy
;

vec3
  ray_direction=normalize(vec3(C-.5*r,r.y))
;

Ray direction with resolution as vec3

vec3
  r = iResolution
;

vec3
  ray_direction=normalize(vec3(C,r.y)-.5*r)
;

Ray direction with no variable for resolution

// Note negative z component of ray direction
vec3
  ray_direction=normalize(vec3(C+C,0)-iResolution.xyy)
;

Rotation matrix approximation

float
  angle=1.
;
mat2 
  R=mat2(cos(angle+vec4(0,11,33,0)))
;

Rotation using rotation vector

float
  angle=1.
;
vec3
  p=vec3(0) // Current position of ray
, R=normalize(sin(angle+vec3(0,1,2)))
;
// Rotate
p=R*dot(R,p)+cross(R,p);

Palette generator

float
  off=0.
;
vec3
  color=.5+.5*sin(off+vec3(0,1,2))
;

Rounded cube distance field

vec3
  p=vec3(0) // Current position of ray
;
float
  d=sqrt(length(p*p))-1.
;

Domain repetition (infinite)

vec3
  p=vec3(0) // Current position of ray
;
// Repeats what's inside unit cube at center of universe
p-=round(p);

Domain repetition (constrained)

vec3
  p=vec3(0) // Current position of ray
, lower=vec3(-1,-2,-3)
, upper=vec3(4,5,6)
;
// Repeats what's inside unit cube at center of universe
p-=clamp(round(p),lower,upper);

Simple raymarcher

void mainImage(out vec4 O, vec2 C) {
  // While code golfing variables are assumed to be initialized to 0
  float 
    i
  , z
  , d=1e3
  ;
  vec3 
    // Accumulated color
    o
  , p
  , r=iResolution
    // Ray direction
  , D=normalize(vec3(C,r.y)-.5*r)
    // Rotation vector
  , R=normalize(sin(iTime+vec3(0,1,2)))
  ;
  // Raymarching
  for (
      // Abort if out of iterations, near the surface or we went too far
    ; ++i<77.&&d>=1e-3&&z<9.
      // Increment with distance to "cube"
    ; z+=d
    )
    // Current ray position
    p=z*D
    // Move scene 3 units in front of camera
  , p.z-=3.
    // Apply rotation
  , p=R*dot(R,p)+cross(R,p)
    // Rounded cube
  , d=sqrt(length(p*p))-1.
  ;
  // Did we hit the "cube"?
  if(d<1e-3)
    o+=1.-i/77.;
    
  O=vec4(o,1);
}

Simple glowmarcher

void mainImage(out vec4 O, vec2 C) {
  // While code golfing variables are assumed to be initialized to 0
  vec3 
    // Current ray position
    p
    // Ray position after rotation
  , P
  , r=iResolution
    // Sweeps a tilted axis over time, used for rotation
  , R=normalize(sin(iTime+vec3(0,1,2)))
  ;
  vec4
    // Accumulated color
    o
  ;
  // Glowmarching loop, no hard surface hit, accumulates glow along full ray
  for (
      float i,z,d
    ; ++i<77.&&z<9.
      // Accumulate: weight color by alpha and inverse distance each step
    ; o+=O.w/d*O
    )
    // Ray position at depth z, centered on screen
    p=z*normalize(vec3(C,r.y)-.5*r)
    // Move camera back 3 units
  , p.z-=3.
    // Apply rotation
  , P=R*dot(R,p)+cross(R,p)
    // SDF for a rounded cube shell; step size halved for glow accumulation
  , z+=d=.5*(abs(sqrt(length(P*P))-1.)+2e-3)
    // Animated color, channel-offset for hue cycling
  , O=1.1+sin(length(p-P)+iTime+C.y/r.y+vec4(0,1,2,0))
    // Accumulate color weight by alpha and proximity
  ;
  // Tonemap accumulated color into [0,1]
  O=tanh(o/3e4);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment