我有一个顶点着色器,可以移动对象的顶点,但对象投射的阴影保持静态(就像没有应用顶点着色器一样)
对象使用三个几何图形进行渲染:
BoxGeometry
、CylinderGeometry
、TetrahedronBufferGeometry
、ConeGeometry
然后对每个我应用
MeshPhongMaterial
并在 material.onBeforeCompile()
中设置我的自定义顶点着色器。
网上有人建议使用
customDepthMaterial
,可以在布料模拟示例这里中看到,但这似乎不起作用。
一个区别是该示例还在材质参数中使用了
map: clothTexture
,但我不..不知道它是否相关
代码可在 https://codepen.io/the-roman-one/pen/VwgVjdW 中找到,为了方便起见,我的材料工厂如下所示:
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
material.onBeforeCompile = (shader) =>
{
shader.uniforms = {
...shader.uniforms,
...shaderUniforms,
time: {value: 0},
}
let shaders = this.shader_maker.make(shader_type)
shader.vertexShader = shaders.vertex
shader.fragmentShader = shaders.fragment;
this.context.shaders[uuid] = shader
}
material.customDepthMaterial = new THREE.MeshDepthMaterial({
depthPacking: THREE.RGBADepthPacking,
alphaTest: 0.5
});
return material
}
没有什么比一个例子更好的了,这个例子来自@prisoner849,他已经在你的问题下留下了评论:https://codepen.io/prisoner849/pen/JjwwVWq
关键是在深度材质中复制相同的位移,以便计算正确的阴影。有多种方法可以实现此目的,具体取决于您的管道,无论您是复制整个
MeshDepthMaterial
着色器还是使用 glslify 注入新代码。
在上面的示例中,@prisoner849 使用
onBeforeCompile
来替换部分着色器:
this.customDepthMaterial = new THREE.MeshDepthMaterial({
depthPacking: THREE.RGBADepthPacking,
side: THREE.DoubleSide,
onBeforeCompile: shader => {
shader.uniforms.time = gu.time;
shader.vertexShader = `
uniform float time;
${noise}
${getHeight}
${shader.vertexShader}
`.replace(
`#include <begin_vertex>`,
`#include <begin_vertex>
${compute}
transformed = pos;
`
);
}
})
其中
noise
、getHeight
和 compute
是在代码的前面定义的,并且也在主顶点着色器中使用。