我试图让一个ShaderMaterial的灯工作在three.js r77。当应用于具有简单BoxGeometry的网格时,它可以正常工作,但在应用于从Blender导入的网格时,它的行为不正确。
说明问题的简单方法是here。左侧的网格是从Blender导出创建的。右侧的网格是从简单的BoxGeometry创建的。两者都使用相同的ShaderMaterial。指示灯的位置由DirectionalLightHelper指示。
右侧的网格正确点亮,而左侧的网格则没有。显然问题出在我的着色器代码中。我最初假设问题出在导入网格上的UV贴图中,但这似乎不是真的。在jsfiddle示例中,UV贴图从导入的几何体直接复制到BoxGeometry网格 - 由于Blender和three.js之间的坐标差异,它们相对于彼此旋转,但照明仍然正常工作使用导入的UV在右侧的网格上。
着色器代码为:
THREE.TestShader = {
uniforms: {
"uDirLightPos": {
type: "v3",
value: new THREE.Vector3(20, 20, 20)
},
"uDirLightColor": {
type: "c",
value: new THREE.Color(0xffffff)
},
"uTexture": {
type: "t",
value: null
},
},
vertexShader: [
"varying vec3 vNormal;",
"varying vec3 vViewPosition;",
"varying vec2 vUv;",
"void main() {",
"vUv = uv;",
"vNormal = normalize(normalMatrix * normal);",
"vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);",
"vViewPosition = -mvPosition.xyz;",
"gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);",
"}"
].join("\n"),
fragmentShader: [
"uniform vec3 uDirLightPos;",
"uniform vec3 uDirLightColor;",
"varying vec2 vUv;",
"varying vec3 vNormal;",
"varying vec3 vViewPosition;",
"varying vec4 mvPosition;",
"uniform sampler2D uTexture;",
"void main() {",
"vec4 lDirection = viewMatrix * vec4(uDirLightPos, 0.0);",
"vec3 lVector = normalize(lDirection.xyz);",
"vec3 normal = normalize(vNormal);",
"float diffuse = dot(normal, lVector);",
"vec4 texel = texture2D( uTexture, vUv );",
"gl_FragColor = vec4(uDirLightColor * diffuse, 1.0) * texel;",
"}"
].join("\n")
};
除了这个特定问题的解决方案之外,还可以理解指向更好的关于three.js着色器的文档的指针。 ShaderChunk,ShaderLib和UniformsLib的官方文档并非您所说的详尽无遗。
答案 0 :(得分:1)
您的Blender导出模型的法线不正确。
vnh1 = new THREE.VertexNormalsHelper( mesh1, 1, 0xff0000, 1 );
scene.add( vnh1 );
小提琴:https://jsfiddle.net/5j0axcgz/1/
three.js r.77