
Shader Fundamentals
- 158 installs
- 8 repo stars
- Updated August 4, 2026
- bbeierle12/skill-mcp-claude
Author vertex and fragment shaders for lighting, textures, and effects when building WebGL games, creative coding sketches, or GPU-accelerated UI visuals.
About
Shader-fundamentals covers GPU shader basics—vertex and fragment stages, uniforms, textures, and lighting—for WebGL and similar clients so developers and agents can author correct, performant visual effects in games and interactive experiences.
- Explains vertex vs fragment shader roles and data flow
- Covers uniforms, varyings, textures, and basic lighting
- Foundation for games, creative coding, and visual demos
- Complements particles-physics for full graphics stacks
- Helps agents avoid common GLSL compilation and precision pitfalls
Shader Fundamentals by the numbers
- 158 all-time installs (skills.sh)
- Ranked #107 of 247 Game Development skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/bbeierle12/skill-mcp-claude --skill shader-fundamentalsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 158 |
|---|---|
| repo stars | ★ 8 |
| Last updated | August 4, 2026 |
| Repository | bbeierle12/skill-mcp-claude ↗ |
What it does
Author vertex and fragment shaders for lighting, textures, and effects when building WebGL games, creative coding sketches, or GPU-accelerated UI visuals.
Files
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 2Samplers
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 colorCoordinate 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 positionStandard 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 interpolationVector
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 neededCommon 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 linearSmooth 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 shaderReference
references/glsl-types.md— Complete data type referencereferences/builtin-functions.md— All GLSL built-in functionsreferences/coordinate-spaces.md— Transform pipeline deep-dive
{
"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.",
"tags": [
"shaders",
"glsl",
"code-generation"
],
"sub_skills": [],
"source": "claude-user",
"type": "template",
"depends_on": [],
"enhances": [
"shader-noise",
"shader-sdf",
"shader-effects"
],
"last_reviewed_at": null,
"review_score": null,
"relevance_tier": null
}
GLSL Types Reference
Complete reference for GLSL data types and operations.
Scalar Types
| Type | Description | Range/Notes |
|---|---|---|
bool | Boolean | true or false |
int | Signed integer | At least 16-bit |
uint | Unsigned integer | GLSL 1.3+ |
float | Floating point | IEEE 754 single precision |
bool b = true;
int i = 42;
uint u = 42u;
float f = 3.14;
float f2 = 3.; // Shorthand
float f3 = .5; // ShorthandVector Types
| Type | Components | Description |
|---|---|---|
vec2, vec3, vec4 | 2, 3, 4 | Float vectors |
ivec2, ivec3, ivec4 | 2, 3, 4 | Integer vectors |
uvec2, uvec3, uvec4 | 2, 3, 4 | Unsigned integer vectors |
bvec2, bvec3, bvec4 | 2, 3, 4 | Boolean vectors |
Construction
// Direct
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);
// Scalar broadcast
vec3 gray = vec3(0.5); // (0.5, 0.5, 0.5)
// From smaller vectors
vec4 v = vec4(v2, 0.0, 1.0); // (v2.x, v2.y, 0.0, 1.0)
vec4 v = vec4(v3, 1.0); // (v3.x, v3.y, v3.z, 1.0)
vec4 v = vec4(v2.x, v3); // Error! Can't mix like this
// From larger vectors
vec2 v2 = v4.xy;
vec3 v3 = v4.xyz;Swizzling
Access components with .xyzw, .rgba, or .stpq:
vec4 v = vec4(1.0, 2.0, 3.0, 4.0);
// Single component
float x = v.x; // 1.0
float r = v.r; // 1.0 (same as .x)
float s = v.s; // 1.0 (same as .x)
// Multiple components
vec2 xy = v.xy; // (1.0, 2.0)
vec3 rgb = v.rgb; // (1.0, 2.0, 3.0)
// Reorder
vec2 yx = v.yx; // (2.0, 1.0)
vec4 wzyx = v.wzyx; // (4.0, 3.0, 2.0, 1.0)
// Repeat
vec3 xxx = v.xxx; // (1.0, 1.0, 1.0)
vec4 rrrr = v.rrrr; // (1.0, 1.0, 1.0, 1.0)
// Write swizzle
v.xy = vec2(5.0, 6.0);
v.zw = v.xy;Rules:
- Cannot mix swizzle sets:
v.xgis invalid - Cannot repeat in write:
v.xx = ...is invalid
Matrix Types
| Type | Size | Description |
|---|---|---|
mat2, mat2x2 | 2×2 | 2 columns, 2 rows |
mat3, mat3x3 | 3×3 | 3 columns, 3 rows |
mat4, mat4x4 | 4×4 | 4 columns, 4 rows |
mat2x3 | 2×3 | 2 columns, 3 rows |
mat2x4 | 2×4 | 2 columns, 4 rows |
mat3x2 | 3×2 | 3 columns, 2 rows |
mat3x4 | 3×4 | 3 columns, 4 rows |
mat4x2 | 4×2 | 4 columns, 2 rows |
mat4x3 | 4×3 | 4 columns, 3 rows |
Construction
// From scalars (column-major order!)
mat2 m = mat2(
1.0, 2.0, // Column 0
3.0, 4.0 // Column 1
);
// Results in:
// | 1 3 |
// | 2 4 |
// Identity
mat3 identity = mat3(1.0);
// From vectors (columns)
vec2 col0 = vec2(1.0, 2.0);
vec2 col1 = vec2(3.0, 4.0);
mat2 m = mat2(col0, col1);
// From larger matrix (truncate)
mat3 m3 = mat3(m4);Access
mat4 m;
// Column access (returns vector)
vec4 col0 = m[0];
vec4 col2 = m[2];
// Element access
float val = m[1][2]; // Column 1, Row 2
float val = m[1].z; // Same thingSampler Types
| Type | Description |
|---|---|
sampler2D | 2D texture |
sampler3D | 3D texture |
samplerCube | Cube map |
sampler2DShadow | 2D depth texture |
samplerCubeShadow | Cube depth texture |
sampler2DArray | 2D texture array |
uniform sampler2D uTexture;
// Sampling
vec4 color = texture2D(uTexture, uv);
vec4 color = texture(uTexture, uv); // GLSL 1.3+Type Conversion
Implicit Conversion
Limited in GLSL:
int→float(sometimes)int→uint
Explicit Conversion (Constructors)
float f = float(i);
int i = int(f); // Truncates
vec3 v = vec3(ivec3(1, 2, 3));Operators
Arithmetic
// Scalar
float a = 1.0 + 2.0;
float b = 3.0 - 1.0;
float c = 2.0 * 3.0;
float d = 6.0 / 2.0;
// Vector (component-wise)
vec3 v = vec3(1.0) + vec3(2.0); // (3.0, 3.0, 3.0)
vec3 v = vec3(1.0, 2.0, 3.0) * vec3(2.0, 2.0, 2.0); // (2.0, 4.0, 6.0)
// Scalar * Vector
vec3 v = 2.0 * vec3(1.0, 2.0, 3.0); // (2.0, 4.0, 6.0)
// Matrix * Vector
vec4 v = mat4(...) * vec4(...); // Transform
// Matrix * Matrix
mat4 m = mat4(...) * mat4(...); // Combine transformsComparison
// Scalar (returns bool)
bool b = a < b;
bool b = a <= b;
bool b = a > b;
bool b = a >= b;
bool b = a == b;
bool b = a != b;
// Vector (returns bvec, component-wise)
bvec3 b = lessThan(v1, v2);
bvec3 b = lessThanEqual(v1, v2);
bvec3 b = greaterThan(v1, v2);
bvec3 b = greaterThanEqual(v1, v2);
bvec3 b = equal(v1, v2);
bvec3 b = notEqual(v1, v2);
// Aggregate
bool anyTrue = any(bvec);
bool allTrue = all(bvec);
bvec not = not(bvec);Logical
bool b = a && b; // AND
bool b = a || b; // OR
bool b = !a; // NOT
bool b = a ^^ b; // XORBitwise (GLSL 1.3+)
int a = i & j; // AND
int a = i | j; // OR
int a = i ^ j; // XOR
int a = ~i; // NOT
int a = i << 2; // Left shift
int a = i >> 2; // Right shiftPrecision Qualifiers
// Fragment shader (required in ES)
precision highp float;
precision mediump float;
precision lowp float;
// Per-variable
highp float f;
mediump vec3 v;
lowp int i;| Qualifier | Float Range | Float Precision | Int Range |
|---|---|---|---|
highp | ±2^62 | 2^-16 relative | ±2^16 |
mediump | ±2^14 | 2^-10 relative | ±2^10 |
lowp | ±2 | 2^-8 absolute | ±2^8 |
Arrays
// Fixed size
float arr[4];
vec3 positions[10];
// Access
float val = arr[0];
arr[2] = 3.14;
// Initialize
float arr[3] = float[3](1.0, 2.0, 3.0);
float arr[] = float[](1.0, 2.0, 3.0); // Size inferred
// Length
int len = arr.length(); // GLSL 1.2+Structs
struct Light {
vec3 position;
vec3 color;
float intensity;
};
Light light;
light.position = vec3(1.0, 2.0, 3.0);
light.color = vec3(1.0);
light.intensity = 1.0;
// Initialize
Light light = Light(vec3(0.0), vec3(1.0), 1.0);
// Arrays of structs
Light lights[4];