threejs-shaders
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseThree.js Shaders
Three.js着色器
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();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);
}
`,
});
// 在动画循环中更新
material.uniforms.time.value = clock.getElapsedTime();ShaderMaterial vs RawShaderMaterial
ShaderMaterial 与 RawShaderMaterial
ShaderMaterial
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);
}
`,
});Three.js 提供内置的uniform和属性。
javascript
const material = new THREE.ShaderMaterial({
vertexShader: `
// 可用的内置uniform:
// uniform mat4 modelMatrix;
// uniform mat4 modelViewMatrix;
// uniform mat4 projectionMatrix;
// uniform mat4 viewMatrix;
// uniform mat3 normalMatrix;
// uniform vec3 cameraPosition;
// 可用的内置属性:
// 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
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);
}
`,
});完全可控 - 所有内容都由你定义。
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
Uniforms
Uniform Types
Uniform类型
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)],
},
},
});javascript
const material = new THREE.ShaderMaterial({
uniforms: {
// 数值类型
floatValue: { value: 1.5 },
intValue: { value: 1 },
// 向量类型
vec2Value: { value: new THREE.Vector2(1, 2) },
vec3Value: { value: new THREE.Vector3(1, 2, 3) },
vec4Value: { value: new THREE.Vector4(1, 2, 3, 4) },
// 颜色类型(会转换为vec3)
colorValue: { value: new THREE.Color(0xff0000) },
// 矩阵类型
mat3Value: { value: new THREE.Matrix3() },
mat4Value: { value: new THREE.Matrix4() },
// 纹理类型
textureValue: { value: texture },
cubeTextureValue: { value: cubeTexture },
// 数组类型
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声明
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];glsl
// 在着色器中
uniform float floatValue;
uniform int intValue;
uniform vec2 vec2Value;
uniform vec3 vec3Value;
uniform vec3 colorValue; // 颜色会转为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
更新Uniform
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);javascript
// 直接赋值
material.uniforms.time.value = clock.getElapsedTime();
// 向量/颜色更新
material.uniforms.position.value.set(x, y, z);
material.uniforms.color.value.setHSL(hue, 1, 0.5);
// 矩阵更新
material.uniforms.matrix.value.copy(mesh.matrixWorld);Varyings
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);
}
`,
});在顶点着色器和片元着色器之间传递数据。
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() {
// 使用插值后的值
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;
}
`,
});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);
}
`,
});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;
// 波浪位移
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);
}
`,
});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 由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);glsl
// 简单噪声函数
float random(vec2 st) {
return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453);
}
// 价值噪声
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;
}
// 使用示例
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);glsl
// 线性渐变
vec3 color = mix(colorA, colorB, vUv.y);
// 径向渐变
float dist = distance(vUv, vec2(0.5));
vec3 color = mix(centerColor, edgeColor, dist * 2.0);
// 带自定义曲线的平滑渐变
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);
}
`,
});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);
}glsl
uniform float progress;
uniform sampler2D noiseMap;
void main() {
float noise = texture2D(noiseMap, vUv).r;
if (noise < progress) {
discard;
}
// 边缘发光
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
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();
}修改现有材质的着色器。
javascript
const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
material.onBeforeCompile = (shader) => {
// 添加自定义uniform
shader.uniforms.time = { value: 0 };
// 存储引用以便后续更新
material.userData.shader = shader;
// 修改顶点着色器
shader.vertexShader = shader.vertexShader.replace(
"#include <begin_vertex>",
`
#include <begin_vertex>
transformed.y += sin(position.x * 10.0 + time) * 0.1;
`,
);
// 添加uniform声明
shader.vertexShader = "uniform float time;\n" + shader.vertexShader;
};
// 在动画循环中更新
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 appliedjavascript
// 顶点着色器代码块
"#include <begin_vertex>"; // 位置计算完成后
"#include <project_vertex>"; // gl_Position计算完成后
"#include <beginnormal_vertex>"; // 法线计算开始处
// 片元着色器代码块
"#include <color_fragment>"; // 漫反射颜色计算完成后
"#include <output_fragment>"; // 最终输出前
"#include <fog_fragment>"; // 雾效应用完成后GLSL Built-in Functions
GLSL内置函数
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)glsl
// 基础函数
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)
// 三角函数
sin(x), cos(x), tan(x)
asin(x), acos(x), atan(y, x), atan(x)
radians(degrees), degrees(radians)
// 指数函数
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)glsl
// 长度与距离
length(v), distance(p0, p1), dot(x, y), cross(x, y)
// 归一化
normalize(v)
// 反射与折射
reflect(I, N), refract(I, N, eta)
// 分量级操作
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)glsl
// GLSL 1.0(默认)- 使用texture2D/textureCube
texture2D(sampler, coord)
texture2D(sampler, coord, bias)
textureCube(sampler, coord)
// GLSL 3.0(glslVersion: THREE.GLSL3)- 使用texture()
// texture(sampler, coord) 替代 texture2D/textureCube
// 同时使用:out vec4 fragColor 替代 gl_FragColor
// 纹理尺寸(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
});javascript
const material = new THREE.ShaderMaterial({
uniforms: {
/* ... */
},
vertexShader: "/* ... */",
fragmentShader: "/* ... */",
// 渲染设置
transparent: true,
opacity: 1.0,
side: THREE.DoubleSide,
depthTest: true,
depthWrite: true,
// 混合模式
blending: THREE.NormalBlending,
// AdditiveBlending, SubtractiveBlending, MultiplyBlending
// 线框模式
wireframe: false,
wireframeLinewidth: 1, // 注意:大多数平台上线宽>1无效(WebGL限制)
// 扩展功能
extensions: {
derivatives: true, // 用于fwidth, dFdx, dFdy
fragDepth: true, // gl_FragDepth
drawBuffers: true, // 多渲染目标
shaderTextureLOD: true, // texture2DLod
},
// GLSL版本
glslVersion: THREE.GLSL3, // 用于WebGL2特性
});Shader Includes
着色器引用
Using Three.js Shader Chunks
使用Three.js着色器代码块
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);
}
`;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,
});javascript
// 配合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);
}
`,
});javascript
// 实例化属性
const offsets = new Float32Array(instanceCount * 3);
// 填充偏移数据...
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;javascript
// 检查编译错误
material.onBeforeCompile = (shader) => {
console.log("顶点着色器:", shader.vertexShader);
console.log("片元着色器:", shader.fragmentShader);
};
// 可视化调试
fragmentShader: `
void main() {
// 调试UV
gl_FragColor = vec4(vUv, 0.0, 1.0);
// 调试法线
gl_FragColor = vec4(vNormal * 0.5 + 0.5, 1.0);
// 调试位置
gl_FragColor = vec4(vPosition * 0.1 + 0.5, 1.0);
}
`;
// 检查WebGL错误
renderer.debug.checkShaderErrors = true;Performance Tips
性能优化技巧
- Minimize uniforms: Group related values into vectors
- Avoid conditionals: Use mix/step instead of if/else
- Precalculate: Move calculations to JS when possible
- Use textures: For complex functions, use lookup tables
- 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));- 减少uniform数量:将相关值分组到向量中
- 避免条件判断:使用mix/step替代if/else
- 预计算:尽可能将计算逻辑移到JS中
- 使用纹理:对于复杂函数,使用查找表
- 限制过度绘制:尽可能避免使用透明对象
glsl
// 替代:
if (value > 0.5) {
color = colorA;
} else {
color = colorB;
}
// 使用:
color = mix(colorB, colorA, step(0.5, value));See Also
相关链接
- - Built-in material types
threejs-materials - - Full-screen shader effects
threejs-postprocessing - - Texture sampling in shaders
threejs-textures
- - 内置材质类型
threejs-materials - - 全屏着色器特效
threejs-postprocessing - - 着色器中的纹理采样
threejs-textures