前端开发
在 Three.js 中需要自定义 GLSL 视觉效果…
适用于 Three.js 项目中创建自定义视觉特效、编写顶点/片元着色器、传递 uniforms/varyings、扩展内置材质的场景。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 59/100 ×0.15
适用场景
在 Three.js 中需要自定义 GL特定
解决思路
- Quick Start:用 import * as THREE from 'three'; 创建 THREE.ShaderMaterial,提供 uniforms(如 time: { value: 0 }、color: { value: new THREE.Color(0xff0000) })、vertexShader 与 fragmentShader;顶点着色器中写 gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);,片元着色器中声明 uniform vec3 color; 并写 gl_FragColor = vec4(color, 1.0);。
- Quick Start:在动画循环中更新 material.uniforms.time.value = clock.getElapsedTime();。
- ShaderMaterial:Three.js 提供内置 uniforms 和 attributes,可直接使用 modelMatrix、modelViewMatrix、projectionMatrix、viewMatrix、normalMatrix、cameraPosition,以及 position、normal、uv。
- RawShaderMaterial:完全自己定义一切;在 vertexShader 与 fragmentShader 中都写 precision highp float;,显式声明 attribute vec3 position; uniform mat4 projectionMatrix; uniform mat4 modelViewMatrix;,并在 uniforms 中传入 projectionMatrix: { value: camera.projectionMatrix }、modelViewMatrix: { value: new THREE.Matrix4() } 等。
- Uniform Types:支持 Numbers:floatValue: { value: 1.5 }、intValue: { value: 1 }。
- Uniform Types:支持 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) }。
- Uniform Types:支持 Colors:colorValue: { value: new THREE.Color(0xff0000) },在 shader 中转为 vec3。
- Uniform Types:支持 Matrices:mat3Value: { value: new THREE.Matrix3() }、mat4Value: { value: new THREE.Matrix4() }。
- Uniform Types:支持 Textures:textureValue: { value: texture }、cubeTextureValue: { value: cubeTexture }。
- Uniform Types:支持 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:在 shader 中写 uniform float floatValue; uniform int intValue; uniform vec2 vec2Value; uniform vec3 vec3Value; uniform vec3 colorValue; 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:直接赋值,如 material.uniforms.time.value = clock.getElapsedTime();。
- Updating Uniforms:Vector/Color 更新用 material.uniforms.position.value.set(x, y, z); 和 material.uniforms.color.value.setHSL(hue, 1, 0.5);。
- Updating Uniforms:Matrix 更新用 material.uniforms.matrix.value.copy(mesh.matrixWorld);。
- Varyings:在 vertexShader 中声明 varying vec2 vUv; varying vec3 vNormal; varying vec3 vPosition;,赋值 vUv = uv; vNormal = normalize(normalMatrix * normal); vPosition = (modelViewMatrix * vec4(position, 1.0)).xyz;,再设置 gl_Position;在 fragmentShader 中声明相同 varying 并使用插值值。
- Texture Sampling:uniforms 中 map: { value: texture };vertexShader 中 varying vec2 vUv; vUv = uv;;fragmentShader 中 uniform sampler2D map; varying vec2 vUv;,用 vec4 texColor = texture2D(map, vUv); gl_FragColor = texColor;。
- Vertex Displacement:uniforms 中 time: { value: 0 }、amplitude: { value: 0.5 };vertexShader 中 vec3 pos = position; pos.z += sin(pos.x * 5.0 + time) * amplitude; pos.z += sin(pos.y * 5.0 + time) * amplitude;,然后用 pos 计算 gl_Position;fragmentShader 输出颜色。
- Fresnel Effect:vertexShader 中计算 vNormal = normalize(normalMatrix * normal); vWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz;;fragmentShader 中用 cameraPosition(ShaderMaterial 自动提供)计算 viewDirection = normalize(cameraPosition - vWorldPosition); fresnel = pow(1.0 - dot(viewDirection, vNormal), 3.0);,再用 mix(baseColor, fresnelColor, fresnel) 输出。
- Noise-Based Effects:定义 random(vec2 st) { return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453); }。
- Noise-Based Effects:定义 value noise(vec2 st):vec2 i = floor(st); vec2 f = fract(st);,取四角 random(i)、random(i + vec2(1.0, 0.0))、random(i + vec2(0.0, 1.0))、random(i + vec2(1.0, 1.0)),用 vec2 u = f * f * (3.0 - 2.0 * f); 与 mix 插值返回。
- Noise-Based Effects:使用 float n = noise(vUv * 10.0 + time);。
- Gradient:线性渐变用 vec3 color = mix(colorA, colorB, vUv.y);。
- Gradient:径向渐变用 float dist = distance(vUv, vec2(0.5)); vec3 color = mix(centerColor, edgeColor, dist * 2.0);。
- Gradient:平滑曲线渐变用 float t = smoothstep(0.0, 1.0, vUv.y); vec3 color = mix(colorA, colorB, t);。
- Rim Lighting:vertexShader 中计算 vNormal = normalize(normalMatrix * normal); vec4 mvPosition = modelViewMatrix * vec4(position, 1.0); vViewPosition = mvPosition.xyz; gl_Position = projectionMatrix * mvPosition;;fragmentShader 中计算 vec3 viewDir = normalize(-vViewPosition); float rim = 1.0 - max(0.0, dot(viewDir, vNormal)); rim = pow(rim, 4.0);,输出 baseColor + rimColor * rim。
- Dissolve Effect:uniform float progress; uniform sampler2D noiseMap;;fragmentShader 中 float noise = texture2D(noiseMap, vUv).r;,若 noise < progress 则 discard;,计算 float edge = smoothstep(progress, progress + 0.1, noise);,用 mix(edgeColor, baseColor, edge) 输出。
- Extending Built-in Materials 的 onBeforeCompile:创建 THREE.MeshStandardMaterial,设置 material.onBeforeCompile = (shader) => { ... };在其中添加 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;'); 修改顶点,并在 shader.vertexShader 前加 'uniform float time;'。
- Extending Built-in Materials 的更新:在动画循环中判断 if (material.userData.shader) { material.userData.shader.uniforms.time.value = clock.getElapsedTime(); }。
- 常用注入点:vertex shader chunks 包括 '#include <begin_vertex>'(position 计算后)、'#include <project_vertex>'(gl_Position 后)、'#include <beginnormal_vertex>'(法线计算开始)。
- 常用注入点:fragment shader chunks 包括 '#include <color_fragment>'(diffuse color 后)、'#include <output_fragment>'(最终输出)、'#include <fog_fragment>'(雾应用后)。
- GLSL Math Functions: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)。
- GLSL Math Functions:Trigonometry 包括 sin(x), cos(x), tan(x), asin(x), acos(x), atan(y, x), atan(x), radians(degrees), degrees(radians)。
- GLSL Math Functions:Exponential 包括 pow(x, y), exp(x), log(x), exp2(x), log2(x), sqrt(x), inversesqrt(x)。
- GLSL Vector Functions: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)。
- GLSL Texture Functions:GLSL 1.0(默认)使用 texture2D(sampler, coord)、texture2D(sampler, coord, bias)、textureCube(sampler, coord)。
- GLSL Texture Functions:GLSL 3.0 使用 glslVersion: THREE.GLSL3 时,用 texture(sampler, coord) 替代 texture2D/textureCube,并用 out vec4 fragColor 替代 gl_FragColor。
- GLSL Texture Functions:GLSL 1.30+ 可用 textureSize(sampler, lod)。
- Common Material Properties:渲染相关设置包括 transparent: true、opacity: 1.0、side: THREE.DoubleSide、depthTest: true、depthWrite: true。
- Common Material Properties:混合设置包括 blending: THREE.NormalBlending,也可用 AdditiveBlending、SubtractiveBlending、MultiplyBlending。
- Common Material Properties:线框设置包括 wireframe: false、wireframeLinewidth: 1;注意 wireframeLinewidth > 1 在多数平台无效(WebGL 限制)。
- Common Material Properties:extensions 设置包括 derivatives: true(用于 fwidth、dFdx、dFdy)、fragDepth: true(gl_FragDepth)、drawBuffers: true(多重渲染目标)、shaderTextureLOD: true(texture2DLod)。
- Common Material Properties:glslVersion: THREE.GLSL3 可启用 WebGL2 特性。
- Shader Includes:用 import { ShaderChunk } from 'three';,在 fragmentShader 中嵌入 ${ShaderChunk.common} 和 ${ShaderChunk.packing},再用 perspectiveDepthToViewZ(depth, 0.1, 1000.0) 等函数。
- External Shader Files:用 vite/webpack 时写 import vertexShader from './shaders/vertex.glsl'; import fragmentShader from './shaders/fragment.glsl';,将 vertexShader、fragmentShader 传入 THREE.ShaderMaterial。
- Instanced Shaders:创建 const offsets = new Float32Array(instanceCount * 3); 并填充;用 geometry.setAttribute('offset', new THREE.InstancedBufferAttribute(offsets, 3));;vertexShader 中声明 attribute vec3 offset;,写 vec3 pos = position + offset;,再计算 gl_Position。
- Debugging Shaders:在 material.onBeforeCompile = (shader) => { console.log('Vertex Shader:', shader.vertexShader); console.log('Fragment Shader:', shader.fragmentShader); }; 中打印着色器检查编译错误。
- Debugging Shaders:可视化调试时,在 fragmentShader 输出 vec4(vUv, 0.0, 1.0) 调试 UV、vec4(vNormal * 0.5 + 0.5, 1.0) 调试法线、vec4(vPosition * 0.1 + 0.5, 1.0) 调试位置。
- Debugging Shaders:设置 renderer.debug.checkShaderErrors = true; 检查 WebGL 错误。
- Performance Tips:最小化 uniforms,将相关值分组成向量。
- Performance Tips:避免条件分支,用 mix/step 代替 if/else。
- Performance Tips:预计算,尽可能把计算移到 JS。
- Performance Tips:对复杂函数使用纹理查找表。
- Performance Tips:限制 overdraw,尽可能避免透明对象。
- Performance Tips 示例:用 color = mix(colorB, colorA, step(0.5, value)); 替代 if (value > 0.5) { color = colorA; } else { color = colorB; }。
适用边界 · 注意事项
- 只需要标准材质/光照时,不要写自定义 shader,优先用 Three.js 内置材质。
- 目标环境不支持 WebGL/GLSL,或缺少所需扩展(derivatives、fragDepth、drawBuffers、shaderTextureLOD)时不适用。
- 依赖 wireframeLinewidth > 1 实现粗线框时不适用,因为多数 WebGL 平台无效。