Three.js自定义顶点着色器后阴影静态问题求助
解决Three.js自定义顶点着色器阴影静态问题
问题根源
Three.js中物体的阴影是通过渲染深度材质生成的深度缓冲计算而来的。你当前只给主材质应用了自定义顶点着色器,但customDepthMaterial仍使用默认的顶点逻辑,没有同步顶点变换,导致深度缓冲里的物体位置还是原始状态,阴影自然不会跟随物体变形。
解决方案
需要给customDepthMaterial也应用相同的顶点变换逻辑,并同步所有动态uniforms(比如time),具体修改如下:
1. 复用顶点变换逻辑,给深度材质添加onBeforeCompile
修改你的材质工厂函数,将顶点变换逻辑提取为可复用的函数,同时给customDepthMaterial设置相同的着色器处理:
make = (shaderUniforms, shader_type) => { let material switch(shader_type) { case SHADER_TYPES.GRASS: material = this.raw_material; break; default: material = this.phong_material } material = material.clone() material.needsUpdate = true; let {uuid} = material // 提取顶点变换逻辑,主材质和深度材质共用 const setupShader = (shader) => { // 合并uniforms,包括动态变量 shader.uniforms = { ...shader.uniforms, ...shaderUniforms, time: {value: 0}, } // 应用自定义顶点着色器 shader.vertexShader = this.shader_maker.make(shader_type).vertex; } // 处理主材质 material.onBeforeCompile = (shader) => { setupShader(shader); // 主材质需要自定义片元着色器 shader.fragmentShader = this.shader_maker.make(shader_type).fragment; this.context.shaders[uuid] = shader } // 创建并配置自定义深度材质 material.customDepthMaterial = new THREE.MeshDepthMaterial({ depthPacking: THREE.RGBADepthPacking, alphaTest: 0.5 }); // 深度材质应用相同的顶点变换 material.customDepthMaterial.onBeforeCompile = setupShader; return material }
2. 同步动态Uniforms的更新
在你的动画循环中,需要同时更新主材质和深度材质的动态uniforms(比如time),确保两者的顶点变换同步:
// 示例动画循环 function animate() { requestAnimationFrame(animate); const currentTime = performance.now() * 0.001; // 更新主材质的uniforms Object.values(this.context.shaders).forEach(shader => { shader.uniforms.time.value = currentTime; }); // 更新深度材质的uniforms scene.traverse(obj => { if (obj.material?.customDepthMaterial?.uniforms) { obj.material.customDepthMaterial.uniforms.time.value = currentTime; // 其他需要同步的uniforms也在这里更新 } }); renderer.render(scene, camera); }
关键注意点
- 自定义顶点着色器必须正确输出
gl_Position:确保顶点变换后,通过projectionMatrix * modelViewMatrix * vec4(transformed, 1.0)计算最终位置,深度材质依赖这个值生成正确的深度缓冲。 - 如果你的自定义顶点着色器依赖其他属性(如UV、法线),深度材质的顶点着色器也要确保这些属性被正确传递(MeshDepthMaterial默认已处理基础属性,一般无需额外修改)。
内容的提问来源于stack exchange,提问作者Roman
相关产品推荐
相关产品推荐

