Add 260+ Claude Code skills from skills.sh
Complete collection of AI agent skills including: - Frontend Development (Vue, React, Next.js, Three.js) - Backend Development (NestJS, FastAPI, Node.js) - Mobile Development (React Native, Expo) - Testing (E2E, frontend, webapp) - DevOps (GitHub Actions, CI/CD) - Marketing (SEO, copywriting, analytics) - Security (binary analysis, vulnerability scanning) - And many more... Synchronized from: https://skills.sh/ Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
642
threejs-shaders/skill.md
Normal file
642
threejs-shaders/skill.md
Normal file
@@ -0,0 +1,642 @@
|
||||
---
|
||||
name: threejs-shaders
|
||||
description: Three.js shaders - GLSL, ShaderMaterial, uniforms, custom effects. Use when creating custom visual effects, modifying vertices, writing fragment shaders, or extending built-in materials.
|
||||
---
|
||||
|
||||
# Three.js Shaders
|
||||
|
||||
## Quick Start
|
||||
|
||||
```javascript
|
||||
import * as THREE from "three";
|
||||
|
||||
const material = new THREE.ShaderMaterial({
|
||||
uniforms: {
|
||||
time: { value: 0 },
|
||||
color: { value: new THREE.Color(0xff0000) },
|
||||
},
|
||||
vertexShader: `
|
||||
void main() {
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
||||
}
|
||||
`,
|
||||
fragmentShader: `
|
||||
uniform vec3 color;
|
||||
|
||||
void main() {
|
||||
gl_FragColor = vec4(color, 1.0);
|
||||
}
|
||||
`,
|
||||
});
|
||||
|
||||
// Update in animation loop
|
||||
material.uniforms.time.value = clock.getElapsedTime();
|
||||
```
|
||||
|
||||
## ShaderMaterial vs RawShaderMaterial
|
||||
|
||||
### ShaderMaterial
|
||||
|
||||
Three.js provides built-in uniforms and attributes.
|
||||
|
||||
```javascript
|
||||
const material = new THREE.ShaderMaterial({
|
||||
vertexShader: `
|
||||
// Built-in uniforms available:
|
||||
// uniform mat4 modelMatrix;
|
||||
// uniform mat4 modelViewMatrix;
|
||||
// uniform mat4 projectionMatrix;
|
||||
// uniform mat4 viewMatrix;
|
||||
// uniform mat3 normalMatrix;
|
||||
// uniform vec3 cameraPosition;
|
||||
|
||||
// Built-in attributes available:
|
||||
// attribute vec3 position;
|
||||
// attribute vec3 normal;
|
||||
// attribute vec2 uv;
|
||||
|
||||
void main() {
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
||||
}
|
||||
`,
|
||||
fragmentShader: `
|
||||
void main() {
|
||||
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
`,
|
||||
});
|
||||
```
|
||||
|
||||
### RawShaderMaterial
|
||||
|
||||
Full control - you define everything.
|
||||
|
||||
```javascript
|
||||
const material = new THREE.RawShaderMaterial({
|
||||
uniforms: {
|
||||
projectionMatrix: { value: camera.projectionMatrix },
|
||||
modelViewMatrix: { value: new THREE.Matrix4() },
|
||||
},
|
||||
vertexShader: `
|
||||
precision highp float;
|
||||
|
||||
attribute vec3 position;
|
||||
uniform mat4 projectionMatrix;
|
||||
uniform mat4 modelViewMatrix;
|
||||
|
||||
void main() {
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
||||
}
|
||||
`,
|
||||
fragmentShader: `
|
||||
precision highp float;
|
||||
|
||||
void main() {
|
||||
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
`,
|
||||
});
|
||||
```
|
||||
|
||||
## Uniforms
|
||||
|
||||
### Uniform Types
|
||||
|
||||
```javascript
|
||||
const material = new THREE.ShaderMaterial({
|
||||
uniforms: {
|
||||
// Numbers
|
||||
floatValue: { value: 1.5 },
|
||||
intValue: { value: 1 },
|
||||
|
||||
// Vectors
|
||||
vec2Value: { value: new THREE.Vector2(1, 2) },
|
||||
vec3Value: { value: new THREE.Vector3(1, 2, 3) },
|
||||
vec4Value: { value: new THREE.Vector4(1, 2, 3, 4) },
|
||||
|
||||
// Colors (converted to vec3)
|
||||
colorValue: { value: new THREE.Color(0xff0000) },
|
||||
|
||||
// Matrices
|
||||
mat3Value: { value: new THREE.Matrix3() },
|
||||
mat4Value: { value: new THREE.Matrix4() },
|
||||
|
||||
// Textures
|
||||
textureValue: { value: texture },
|
||||
cubeTextureValue: { value: cubeTexture },
|
||||
|
||||
// Arrays
|
||||
floatArray: { value: [1.0, 2.0, 3.0] },
|
||||
vec3Array: {
|
||||
value: [new THREE.Vector3(1, 0, 0), new THREE.Vector3(0, 1, 0)],
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### GLSL Declarations
|
||||
|
||||
```glsl
|
||||
// In shader
|
||||
uniform float floatValue;
|
||||
uniform int intValue;
|
||||
uniform vec2 vec2Value;
|
||||
uniform vec3 vec3Value;
|
||||
uniform vec3 colorValue; // Color becomes vec3
|
||||
uniform vec4 vec4Value;
|
||||
uniform mat3 mat3Value;
|
||||
uniform mat4 mat4Value;
|
||||
uniform sampler2D textureValue;
|
||||
uniform samplerCube cubeTextureValue;
|
||||
uniform float floatArray[3];
|
||||
uniform vec3 vec3Array[2];
|
||||
```
|
||||
|
||||
### Updating Uniforms
|
||||
|
||||
```javascript
|
||||
// Direct assignment
|
||||
material.uniforms.time.value = clock.getElapsedTime();
|
||||
|
||||
// Vector/Color updates
|
||||
material.uniforms.position.value.set(x, y, z);
|
||||
material.uniforms.color.value.setHSL(hue, 1, 0.5);
|
||||
|
||||
// Matrix updates
|
||||
material.uniforms.matrix.value.copy(mesh.matrixWorld);
|
||||
```
|
||||
|
||||
## Varyings
|
||||
|
||||
Pass data from vertex to fragment shader.
|
||||
|
||||
```javascript
|
||||
const material = new THREE.ShaderMaterial({
|
||||
vertexShader: `
|
||||
varying vec2 vUv;
|
||||
varying vec3 vNormal;
|
||||
varying vec3 vPosition;
|
||||
|
||||
void main() {
|
||||
vUv = uv;
|
||||
vNormal = normalize(normalMatrix * normal);
|
||||
vPosition = (modelViewMatrix * vec4(position, 1.0)).xyz;
|
||||
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
||||
}
|
||||
`,
|
||||
fragmentShader: `
|
||||
varying vec2 vUv;
|
||||
varying vec3 vNormal;
|
||||
varying vec3 vPosition;
|
||||
|
||||
void main() {
|
||||
// Use interpolated values
|
||||
gl_FragColor = vec4(vNormal * 0.5 + 0.5, 1.0);
|
||||
}
|
||||
`,
|
||||
});
|
||||
```
|
||||
|
||||
## Common Shader Patterns
|
||||
|
||||
### Texture Sampling
|
||||
|
||||
```javascript
|
||||
const material = new THREE.ShaderMaterial({
|
||||
uniforms: {
|
||||
map: { value: texture },
|
||||
},
|
||||
vertexShader: `
|
||||
varying vec2 vUv;
|
||||
|
||||
void main() {
|
||||
vUv = uv;
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
||||
}
|
||||
`,
|
||||
fragmentShader: `
|
||||
uniform sampler2D map;
|
||||
varying vec2 vUv;
|
||||
|
||||
void main() {
|
||||
vec4 texColor = texture2D(map, vUv);
|
||||
gl_FragColor = texColor;
|
||||
}
|
||||
`,
|
||||
});
|
||||
```
|
||||
|
||||
### Vertex Displacement
|
||||
|
||||
```javascript
|
||||
const material = new THREE.ShaderMaterial({
|
||||
uniforms: {
|
||||
time: { value: 0 },
|
||||
amplitude: { value: 0.5 },
|
||||
},
|
||||
vertexShader: `
|
||||
uniform float time;
|
||||
uniform float amplitude;
|
||||
|
||||
void main() {
|
||||
vec3 pos = position;
|
||||
|
||||
// Wave displacement
|
||||
pos.z += sin(pos.x * 5.0 + time) * amplitude;
|
||||
pos.z += sin(pos.y * 5.0 + time) * amplitude;
|
||||
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
|
||||
}
|
||||
`,
|
||||
fragmentShader: `
|
||||
void main() {
|
||||
gl_FragColor = vec4(0.5, 0.8, 1.0, 1.0);
|
||||
}
|
||||
`,
|
||||
});
|
||||
```
|
||||
|
||||
### Fresnel Effect
|
||||
|
||||
```javascript
|
||||
const material = new THREE.ShaderMaterial({
|
||||
vertexShader: `
|
||||
varying vec3 vNormal;
|
||||
varying vec3 vWorldPosition;
|
||||
|
||||
void main() {
|
||||
vNormal = normalize(normalMatrix * normal);
|
||||
vWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz;
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
||||
}
|
||||
`,
|
||||
fragmentShader: `
|
||||
varying vec3 vNormal;
|
||||
varying vec3 vWorldPosition;
|
||||
|
||||
void main() {
|
||||
// cameraPosition is auto-provided by ShaderMaterial
|
||||
vec3 viewDirection = normalize(cameraPosition - vWorldPosition);
|
||||
float fresnel = pow(1.0 - dot(viewDirection, vNormal), 3.0);
|
||||
|
||||
vec3 baseColor = vec3(0.0, 0.0, 0.5);
|
||||
vec3 fresnelColor = vec3(0.5, 0.8, 1.0);
|
||||
|
||||
gl_FragColor = vec4(mix(baseColor, fresnelColor, fresnel), 1.0);
|
||||
}
|
||||
`,
|
||||
});
|
||||
```
|
||||
|
||||
### Noise-Based Effects
|
||||
|
||||
```glsl
|
||||
// Simple noise function
|
||||
float random(vec2 st) {
|
||||
return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453);
|
||||
}
|
||||
|
||||
// Value noise
|
||||
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;
|
||||
}
|
||||
|
||||
// Usage
|
||||
float n = noise(vUv * 10.0 + time);
|
||||
```
|
||||
|
||||
### Gradient
|
||||
|
||||
```glsl
|
||||
// Linear gradient
|
||||
vec3 color = mix(colorA, colorB, vUv.y);
|
||||
|
||||
// Radial gradient
|
||||
float dist = distance(vUv, vec2(0.5));
|
||||
vec3 color = mix(centerColor, edgeColor, dist * 2.0);
|
||||
|
||||
// Smooth gradient with custom curve
|
||||
float t = smoothstep(0.0, 1.0, vUv.y);
|
||||
vec3 color = mix(colorA, colorB, t);
|
||||
```
|
||||
|
||||
### Rim Lighting
|
||||
|
||||
```javascript
|
||||
const material = new THREE.ShaderMaterial({
|
||||
vertexShader: `
|
||||
varying vec3 vNormal;
|
||||
varying vec3 vViewPosition;
|
||||
|
||||
void main() {
|
||||
vNormal = normalize(normalMatrix * normal);
|
||||
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
|
||||
vViewPosition = mvPosition.xyz;
|
||||
gl_Position = projectionMatrix * mvPosition;
|
||||
}
|
||||
`,
|
||||
fragmentShader: `
|
||||
varying vec3 vNormal;
|
||||
varying vec3 vViewPosition;
|
||||
|
||||
void main() {
|
||||
vec3 viewDir = normalize(-vViewPosition);
|
||||
float rim = 1.0 - max(0.0, dot(viewDir, vNormal));
|
||||
rim = pow(rim, 4.0);
|
||||
|
||||
vec3 baseColor = vec3(0.2, 0.2, 0.8);
|
||||
vec3 rimColor = vec3(1.0, 0.5, 0.0);
|
||||
|
||||
gl_FragColor = vec4(baseColor + rimColor * rim, 1.0);
|
||||
}
|
||||
`,
|
||||
});
|
||||
```
|
||||
|
||||
### Dissolve Effect
|
||||
|
||||
```glsl
|
||||
uniform float progress;
|
||||
uniform sampler2D noiseMap;
|
||||
|
||||
void main() {
|
||||
float noise = texture2D(noiseMap, vUv).r;
|
||||
|
||||
if (noise < progress) {
|
||||
discard;
|
||||
}
|
||||
|
||||
// Edge glow
|
||||
float edge = smoothstep(progress, progress + 0.1, noise);
|
||||
vec3 edgeColor = vec3(1.0, 0.5, 0.0);
|
||||
vec3 baseColor = vec3(0.5);
|
||||
|
||||
gl_FragColor = vec4(mix(edgeColor, baseColor, edge), 1.0);
|
||||
}
|
||||
```
|
||||
|
||||
## Extending Built-in Materials
|
||||
|
||||
### onBeforeCompile
|
||||
|
||||
Modify existing material shaders.
|
||||
|
||||
```javascript
|
||||
const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
|
||||
|
||||
material.onBeforeCompile = (shader) => {
|
||||
// Add custom uniform
|
||||
shader.uniforms.time = { value: 0 };
|
||||
|
||||
// Store reference for updates
|
||||
material.userData.shader = shader;
|
||||
|
||||
// Modify vertex shader
|
||||
shader.vertexShader = shader.vertexShader.replace(
|
||||
"#include <begin_vertex>",
|
||||
`
|
||||
#include <begin_vertex>
|
||||
transformed.y += sin(position.x * 10.0 + time) * 0.1;
|
||||
`,
|
||||
);
|
||||
|
||||
// Add uniform declaration
|
||||
shader.vertexShader = "uniform float time;\n" + shader.vertexShader;
|
||||
};
|
||||
|
||||
// Update in animation loop
|
||||
if (material.userData.shader) {
|
||||
material.userData.shader.uniforms.time.value = clock.getElapsedTime();
|
||||
}
|
||||
```
|
||||
|
||||
### Common Injection Points
|
||||
|
||||
```javascript
|
||||
// Vertex shader chunks
|
||||
"#include <begin_vertex>"; // After position is calculated
|
||||
"#include <project_vertex>"; // After gl_Position
|
||||
"#include <beginnormal_vertex>"; // Normal calculation start
|
||||
|
||||
// Fragment shader chunks
|
||||
"#include <color_fragment>"; // After diffuse color
|
||||
"#include <output_fragment>"; // Final output
|
||||
"#include <fog_fragment>"; // After fog applied
|
||||
```
|
||||
|
||||
## GLSL Built-in Functions
|
||||
|
||||
### Math Functions
|
||||
|
||||
```glsl
|
||||
// Basic
|
||||
abs(x), sign(x), floor(x), ceil(x), fract(x)
|
||||
mod(x, y), min(x, y), max(x, y), clamp(x, min, max)
|
||||
mix(a, b, t), step(edge, x), smoothstep(edge0, edge1, x)
|
||||
|
||||
// Trigonometry
|
||||
sin(x), cos(x), tan(x)
|
||||
asin(x), acos(x), atan(y, x), atan(x)
|
||||
radians(degrees), degrees(radians)
|
||||
|
||||
// Exponential
|
||||
pow(x, y), exp(x), log(x), exp2(x), log2(x)
|
||||
sqrt(x), inversesqrt(x)
|
||||
```
|
||||
|
||||
### Vector Functions
|
||||
|
||||
```glsl
|
||||
// Length and distance
|
||||
length(v), distance(p0, p1), dot(x, y), cross(x, y)
|
||||
|
||||
// Normalization
|
||||
normalize(v)
|
||||
|
||||
// Reflection and refraction
|
||||
reflect(I, N), refract(I, N, eta)
|
||||
|
||||
// Component-wise
|
||||
lessThan(x, y), lessThanEqual(x, y)
|
||||
greaterThan(x, y), greaterThanEqual(x, y)
|
||||
equal(x, y), notEqual(x, y)
|
||||
any(bvec), all(bvec)
|
||||
```
|
||||
|
||||
### Texture Functions
|
||||
|
||||
```glsl
|
||||
// GLSL 1.0 (default) - use texture2D/textureCube
|
||||
texture2D(sampler, coord)
|
||||
texture2D(sampler, coord, bias)
|
||||
textureCube(sampler, coord)
|
||||
|
||||
// GLSL 3.0 (glslVersion: THREE.GLSL3) - use texture()
|
||||
// texture(sampler, coord) replaces texture2D/textureCube
|
||||
// Also use: out vec4 fragColor instead of gl_FragColor
|
||||
|
||||
// Texture size (GLSL 1.30+)
|
||||
textureSize(sampler, lod)
|
||||
```
|
||||
|
||||
## Common Material Properties
|
||||
|
||||
```javascript
|
||||
const material = new THREE.ShaderMaterial({
|
||||
uniforms: {
|
||||
/* ... */
|
||||
},
|
||||
vertexShader: "/* ... */",
|
||||
fragmentShader: "/* ... */",
|
||||
|
||||
// Rendering
|
||||
transparent: true,
|
||||
opacity: 1.0,
|
||||
side: THREE.DoubleSide,
|
||||
depthTest: true,
|
||||
depthWrite: true,
|
||||
|
||||
// Blending
|
||||
blending: THREE.NormalBlending,
|
||||
// AdditiveBlending, SubtractiveBlending, MultiplyBlending
|
||||
|
||||
// Wireframe
|
||||
wireframe: false,
|
||||
wireframeLinewidth: 1, // Note: >1 has no effect on most platforms (WebGL limitation)
|
||||
|
||||
// Extensions
|
||||
extensions: {
|
||||
derivatives: true, // For fwidth, dFdx, dFdy
|
||||
fragDepth: true, // gl_FragDepth
|
||||
drawBuffers: true, // Multiple render targets
|
||||
shaderTextureLOD: true, // texture2DLod
|
||||
},
|
||||
|
||||
// GLSL version
|
||||
glslVersion: THREE.GLSL3, // For WebGL2 features
|
||||
});
|
||||
```
|
||||
|
||||
## Shader Includes
|
||||
|
||||
### Using Three.js Shader Chunks
|
||||
|
||||
```javascript
|
||||
import { ShaderChunk } from "three";
|
||||
|
||||
const fragmentShader = `
|
||||
${ShaderChunk.common}
|
||||
${ShaderChunk.packing}
|
||||
|
||||
uniform sampler2D depthTexture;
|
||||
varying vec2 vUv;
|
||||
|
||||
void main() {
|
||||
float depth = texture2D(depthTexture, vUv).r;
|
||||
float linearDepth = perspectiveDepthToViewZ(depth, 0.1, 1000.0);
|
||||
gl_FragColor = vec4(vec3(-linearDepth / 100.0), 1.0);
|
||||
}
|
||||
`;
|
||||
```
|
||||
|
||||
### External Shader Files
|
||||
|
||||
```javascript
|
||||
// With vite/webpack
|
||||
import vertexShader from "./shaders/vertex.glsl";
|
||||
import fragmentShader from "./shaders/fragment.glsl";
|
||||
|
||||
const material = new THREE.ShaderMaterial({
|
||||
vertexShader,
|
||||
fragmentShader,
|
||||
});
|
||||
```
|
||||
|
||||
## Instanced Shaders
|
||||
|
||||
```javascript
|
||||
// Instanced attribute
|
||||
const offsets = new Float32Array(instanceCount * 3);
|
||||
// Fill offsets...
|
||||
geometry.setAttribute("offset", new THREE.InstancedBufferAttribute(offsets, 3));
|
||||
|
||||
const material = new THREE.ShaderMaterial({
|
||||
vertexShader: `
|
||||
attribute vec3 offset;
|
||||
|
||||
void main() {
|
||||
vec3 pos = position + offset;
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
|
||||
}
|
||||
`,
|
||||
fragmentShader: `
|
||||
void main() {
|
||||
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
`,
|
||||
});
|
||||
```
|
||||
|
||||
## Debugging Shaders
|
||||
|
||||
```javascript
|
||||
// Check for compile errors
|
||||
material.onBeforeCompile = (shader) => {
|
||||
console.log("Vertex Shader:", shader.vertexShader);
|
||||
console.log("Fragment Shader:", shader.fragmentShader);
|
||||
};
|
||||
|
||||
// Visual debugging
|
||||
fragmentShader: `
|
||||
void main() {
|
||||
// Debug UV
|
||||
gl_FragColor = vec4(vUv, 0.0, 1.0);
|
||||
|
||||
// Debug normals
|
||||
gl_FragColor = vec4(vNormal * 0.5 + 0.5, 1.0);
|
||||
|
||||
// Debug position
|
||||
gl_FragColor = vec4(vPosition * 0.1 + 0.5, 1.0);
|
||||
}
|
||||
`;
|
||||
|
||||
// Check WebGL errors
|
||||
renderer.debug.checkShaderErrors = true;
|
||||
```
|
||||
|
||||
## Performance Tips
|
||||
|
||||
1. **Minimize uniforms**: Group related values into vectors
|
||||
2. **Avoid conditionals**: Use mix/step instead of if/else
|
||||
3. **Precalculate**: Move calculations to JS when possible
|
||||
4. **Use textures**: For complex functions, use lookup tables
|
||||
5. **Limit overdraw**: Avoid transparent objects when possible
|
||||
|
||||
```glsl
|
||||
// Instead of:
|
||||
if (value > 0.5) {
|
||||
color = colorA;
|
||||
} else {
|
||||
color = colorB;
|
||||
}
|
||||
|
||||
// Use:
|
||||
color = mix(colorB, colorA, step(0.5, value));
|
||||
```
|
||||
|
||||
## See Also
|
||||
|
||||
- `threejs-materials` - Built-in material types
|
||||
- `threejs-postprocessing` - Full-screen shader effects
|
||||
- `threejs-textures` - Texture sampling in shaders
|
||||
Reference in New Issue
Block a user