我怎样才能写这个普通的着色器,这样它就可以绕过 controlnet 的预处理器 https://jsfiddle.net/lunchie/mpuanxL3/4/
skinnedMesh.material = new THREE.ShaderMaterial( {
vertexShader: [
'#include <skinning_pars_vertex>',
'varying vec3 vNormal;',
'void main() {',
'#include <skinbase_vertex>',
'#include <begin_vertex>',
'#include <skinning_vertex>',
'#include <project_vertex>',
'mat4 skinMatrix = boneMatX * skinWeight.x + boneMatY * skinWeight.y + boneMatZ * skinWeight.z + boneMatW * skinWeight.w;',
'vNormal = (skinMatrix * vec4(normal, 0.0)).xyz;',
'}'
].join( '\n' ),
fragmentShader: [
'varying vec3 vNormal;',
'void main() {',
' gl_FragColor = vec4(abs(vNormal), 1.0);',
'}'
].join( '\n' ),
skinning: true
} );
Three.js 和大多数 3D 渲染器显示其法线的方式是将范围从
[-1, 1]
移动到 [0, 1]
的可见颜色范围。这是一个简单的等式:
gl_FragColor = vec4(vNormal * 0.5 + 0.5, 1.0);
或者有时你的 skinnnedMesh 可能会拉伸法线,所以你想将它们缩小到 1 的长度:
gl_FragColor = vec4(normalize( vNormal ) * 0.5 + 0.5, 1.0);
这应该是你的结果,就像
MeshNormalMaterial
:
要绕过 THREE.js 材质的顶点着色器中的预处理器,您可以将 #include 指令替换为相应的代码片段。以下是您可以在小提琴中修改着色器的方法:
skinnedMesh.material = new THREE.ShaderMaterial({
vertexShader: `
attribute vec4 skinIndex;
attribute vec4 skinWeight;
uniform mat4 bindMatrix;
uniform mat4 bindMatrixInverse;
uniform mat4 boneMatX;
uniform mat4 boneMatY;
uniform mat4 boneMatZ;
uniform mat4 boneMatW;
varying vec3 vNormal;
void main() {
vec4 skinVertex = bindMatrix * vec4(position, 1.0);
mat4 skinMatrix = boneMatX * skinWeight.x + boneMatY * skinWeight.y + boneMatZ * skinWeight.z + boneMatW * skinWeight.w;
skinVertex = skinMatrix * skinVertex;
skinVertex = bindMatrixInverse * skinVertex;
vNormal = (skinMatrix * vec4(normal, 0.0)).xyz;
gl_Position = projectionMatrix * modelViewMatrix * skinVertex;
}
`,
fragmentShader: `
varying vec3 vNormal;
void main() {
gl_FragColor = vec4(abs(vNormal), 1.0);
}
`,
skinning: true
});
在这个修改过的着色器中,我用它们引用的代码片段替换了#include 指令。我还将顶点着色器转换为模板字符串,以便它可以跨越多行。