从Blender

时间:2016-06-09 00:28:42

标签: three.js

我试图让一个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着色器的文档的指针。 ShaderChunkShaderLibUniformsLib的官方文档并非您所说的详尽无遗。

1 个答案:

答案 0 :(得分:1)

您的Blender导出模型的法线不正确。

vnh1 = new THREE.VertexNormalsHelper( mesh1, 1, 0xff0000, 1 );
scene.add( vnh1 );

小提琴:https://jsfiddle.net/5j0axcgz/1/

three.js r.77