shader-fundamentals

shader-fundamentals

GLSL shader fundamentals—vertex and fragment shaders, uniforms, varyings, attributes, coordinate systems, built-in variables, and data types. Use when writing custom shaders, understanding the graphics pipeline, or debugging shader code. The foundational skill for all shader work.

3estrellas
0forks
Actualizado 1/9/2026
SKILL.md
readonlyread-only
name
shader-fundamentals
description

GLSL shader fundamentals—vertex and fragment shaders, uniforms, varyings, attributes, coordinate systems, built-in variables, and data types. Use when writing custom shaders, understanding the graphics pipeline, or debugging shader code. The foundational skill for all shader work.

Shader Fundamentals

GLSL (OpenGL Shading Language) runs on the GPU. Vertex shaders transform geometry; fragment shaders color pixels.

Quick Start

// Vertex Shader
uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;

attribute vec3 position;
attribute vec2 uv;

varying vec2 vUv;

void main() {
  vUv = uv;
  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

// Fragment Shader
uniform float uTime;
varying vec2 vUv;

void main() {
  vec3 color = vec3(vUv, sin(uTime) * 0.5 + 0.5);
  gl_FragColor = vec4(color, 1.0);
}

Graphics Pipeline

Vertex Data → [Vertex Shader] → Primitives → Rasterization → [Fragment Shader] → Pixels
     ↑              ↑                                              ↑
 attributes    transforms                                    per-pixel color
Stage Runs Per Purpose
Vertex Shader Vertex Transform positions, pass data to fragment
Fragment Shader Pixel Calculate final color

Data Types

Scalars

bool b = true;
int i = 42;
float f = 3.14;

Vectors

vec2 v2 = vec2(1.0, 2.0);
vec3 v3 = vec3(1.0, 2.0, 3.0);
vec4 v4 = vec4(1.0, 2.0, 3.0, 4.0);

// Integer vectors
ivec2 iv2 = ivec2(1, 2);
ivec3 iv3 = ivec3(1, 2, 3);

// Boolean vectors
bvec2 bv2 = bvec2(true, false);

Swizzling

vec4 color = vec4(1.0, 0.5, 0.2, 1.0);

vec3 rgb = color.rgb;      // (1.0, 0.5, 0.2)
vec2 rg = color.rg;        // (1.0, 0.5)
float r = color.r;         // 1.0

// Reorder
vec3 bgr = color.bgr;      // (0.2, 0.5, 1.0)

// Duplicate
vec3 rrr = color.rrr;      // (1.0, 1.0, 1.0)

// Position aliases (xyzw = rgba = stpq)
vec3 pos = v4.xyz;
vec2 uv = v4.st;

Matrices

mat2 m2;  // 2x2
mat3 m3;  // 3x3
mat4 m4;  // 4x4

// Access columns
vec4 col0 = m4[0];

// Access element
float val = m4[1][2];  // column 1, row 2

Samplers

uniform sampler2D uTexture;      // 2D texture
uniform samplerCube uCubemap;    // Cube map

// Sample texture
vec4 texColor = texture2D(uTexture, vUv);
vec4 cubeColor = textureCube(uCubemap, direction);

Variable Qualifiers

Uniforms (CPU → GPU, constant per draw)

// Set from JavaScript, same for all vertices/fragments
uniform float uTime;
uniform vec3 uColor;
uniform mat4 uModelMatrix;
uniform sampler2D uTexture;

Attributes (Per-vertex data)

// Only in vertex shader
attribute vec3 position;    // Built-in: vertex position
attribute vec3 normal;      // Built-in: vertex normal
attribute vec2 uv;          // Built-in: texture coordinates
attribute vec3 color;       // Built-in: vertex color

// Custom attributes
attribute float aScale;
attribute vec3 aOffset;

Varyings (Vertex → Fragment, interpolated)

// Vertex shader: write
varying vec2 vUv;
varying vec3 vNormal;

void main() {
  vUv = uv;
  vNormal = normal;
}

// Fragment shader: read (interpolated across triangle)
varying vec2 vUv;
varying vec3 vNormal;

void main() {
  // vUv is interpolated between triangle vertices
}

Built-in Variables

Vertex Shader

// Output (must write)
vec4 gl_Position;       // Clip-space position

// Output (optional)
float gl_PointSize;     // Point sprite size (for gl.POINTS)

Fragment Shader

// Input
vec4 gl_FragCoord;      // Window-space position (pixel coordinates)
bool gl_FrontFacing;    // True if front face
vec2 gl_PointCoord;     // Point sprite coordinates [0,1]

// Output
vec4 gl_FragColor;      // Final pixel color

Coordinate Spaces

Local/Object Space
      ↓ modelMatrix
World Space
      ↓ viewMatrix
View/Eye/Camera Space
      ↓ projectionMatrix
Clip Space (-1 to 1)
      ↓ perspective divide
NDC (Normalized Device Coordinates)
      ↓ viewport transform
Screen Space (pixels)

Common Matrices (Three.js/R3F)

uniform mat4 modelMatrix;       // Local → World
uniform mat4 viewMatrix;        // World → View
uniform mat4 projectionMatrix;  // View → Clip
uniform mat4 modelViewMatrix;   // Local → View (modelMatrix * viewMatrix)
uniform mat3 normalMatrix;      // For transforming normals

uniform vec3 cameraPosition;    // Camera world position

Standard Vertex Transform

void main() {
  // Full transform chain
  vec4 worldPosition = modelMatrix * vec4(position, 1.0);
  vec4 viewPosition = viewMatrix * worldPosition;
  vec4 clipPosition = projectionMatrix * viewPosition;
  gl_Position = clipPosition;
  
  // Or combined (more efficient)
  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

Built-in Functions

Math

// Trigonometry
sin(x), cos(x), tan(x)
asin(x), acos(x), atan(x)
atan(y, x)  // atan2

// Exponential
pow(x, y)   // x^y
exp(x)      // e^x
log(x)      // ln(x)
sqrt(x)     // √x
inversesqrt(x)  // 1/√x

// Common
abs(x)
sign(x)     // -1, 0, or 1
floor(x)
ceil(x)
fract(x)    // x - floor(x)
mod(x, y)   // x % y (floating point)
min(x, y)
max(x, y)
clamp(x, min, max)
mix(a, b, t)  // Linear interpolation: a*(1-t) + b*t
step(edge, x) // 0 if x < edge, else 1
smoothstep(e0, e1, x)  // Smooth Hermite interpolation

Vector

length(v)        // Vector magnitude
distance(a, b)   // length(a - b)
dot(a, b)        // Dot product
cross(a, b)      // Cross product (vec3 only)
normalize(v)     // Unit vector
reflect(I, N)    // Reflection vector
refract(I, N, eta)  // Refraction vector
faceforward(N, I, Nref)  // Flip normal if needed

Common Patterns

UV Coordinates

// vUv ranges from (0,0) at bottom-left to (1,1) at top-right
varying vec2 vUv;

void main() {
  // Center UVs: -0.5 to 0.5
  vec2 centered = vUv - 0.5;
  
  // Aspect-corrected (assuming you pass uResolution)
  vec2 uv = vUv;
  uv.x *= uResolution.x / uResolution.y;
  
  // Tiling
  vec2 tiled = fract(vUv * 4.0);  // 4x4 tiles
  
  // Polar coordinates
  float angle = atan(centered.y, centered.x);
  float radius = length(centered);
}

Color Operations

// Grayscale (perceptual weights)
float gray = dot(color.rgb, vec3(0.299, 0.587, 0.114));

// Contrast
color = (color - 0.5) * contrast + 0.5;

// Brightness
color += brightness;

// Saturation
float gray = dot(color, vec3(0.299, 0.587, 0.114));
color = mix(vec3(gray), color, saturation);

// Gamma correction
color = pow(color, vec3(1.0 / 2.2));  // Linear to sRGB
color = pow(color, vec3(2.2));         // sRGB to linear

Smooth Transitions

// Hard edge
float mask = step(0.5, value);

// Soft edge
float mask = smoothstep(0.4, 0.6, value);

// Anti-aliased edge (screen-space)
float mask = smoothstep(-fwidth(value), fwidth(value), value);

Debugging

Visualize Values

// Show UVs as color
gl_FragColor = vec4(vUv, 0.0, 1.0);

// Show normals
gl_FragColor = vec4(vNormal * 0.5 + 0.5, 1.0);

// Show depth
float depth = gl_FragCoord.z;
gl_FragColor = vec4(vec3(depth), 1.0);

// Show value range (red=negative, green=positive)
gl_FragColor = vec4(max(0.0, value), max(0.0, -value), 0.0, 1.0);

Common Errors

Issue Likely Cause
Black screen gl_Position not set, or NaN values
Uniform not updating Wrong name or type mismatch
Texture black Texture not loaded, wrong UV
Flickering Z-fighting, precision issues
Faceted look Normals not interpolated

Precision

// Declare precision (required in fragment shader for WebGL 1)
precision highp float;
precision mediump float;
precision lowp float;
Precision Range Use Case
highp ~10^38 Positions, matrices
mediump ~10^14 UVs, colors
lowp ~2 Simple flags

File Structure

shader-fundamentals/
├── SKILL.md
├── references/
│   ├── glsl-types.md         # Complete type reference
│   ├── builtin-functions.md  # All built-in functions
│   └── coordinate-spaces.md  # Transform pipeline
└── scripts/
    └── templates/
        ├── basic.glsl        # Starter template
        └── fullscreen.glsl   # Fullscreen quad shader

Reference

  • references/glsl-types.md — Complete data type reference
  • references/builtin-functions.md — All GLSL built-in functions
  • references/coordinate-spaces.md — Transform pipeline deep-dive

You Might Also Like

Related Skills

coding-agent

coding-agent

179Kdev-codegen

Run Codex CLI, Claude Code, OpenCode, or Pi Coding Agent via background process for programmatic control.

openclaw avataropenclaw
Obtener
add-uint-support

add-uint-support

97Kdev-codegen

Add unsigned integer (uint) type support to PyTorch operators by updating AT_DISPATCH macros. Use when adding support for uint16, uint32, uint64 types to operators, kernels, or when user mentions enabling unsigned types, barebones unsigned types, or uint support.

pytorch avatarpytorch
Obtener
at-dispatch-v2

at-dispatch-v2

97Kdev-codegen

Convert PyTorch AT_DISPATCH macros to AT_DISPATCH_V2 format in ATen C++ code. Use when porting AT_DISPATCH_ALL_TYPES_AND*, AT_DISPATCH_FLOATING_TYPES*, or other dispatch macros to the new v2 API. For ATen kernel files, CUDA kernels, and native operator implementations.

pytorch avatarpytorch
Obtener
skill-writer

skill-writer

97Kdev-codegen

Guide users through creating Agent Skills for Claude Code. Use when the user wants to create, write, author, or design a new Skill, or needs help with SKILL.md files, frontmatter, or skill structure.

pytorch avatarpytorch
Obtener

Implements JavaScript classes in C++ using JavaScriptCore. Use when creating new JS classes with C++ bindings, prototypes, or constructors.

oven-sh avataroven-sh
Obtener

Creates JavaScript classes using Bun's Zig bindings generator (.classes.ts). Use when implementing new JS APIs in Zig with JSC integration.

oven-sh avataroven-sh
Obtener