具有阴影但没有灯光的ThreeJS材质

时间:2017-11-18 14:32:01

标签: three.js

我想要一个材料:

  • 纹理
  • 没有接收灯光
  • 接收阴影

我尝试使用以下库材料:

  • MeshBasicMaterial:不支持阴影
  • MeshLamberMaterial:如果禁用灯光(material.lights = false),它也会禁用阴影
  • ShadowMaterial:不支持纹理

自定义ShaderMaterial是实现它的唯一方法吗?

2 个答案:

答案 0 :(得分:5)

在三个世界中,就像在现实生活中一样,阴影是没有光的。因此,对于内置的three.js材质来接收阴影,它必须响应光线。

但是,您可以使用几行代码修改内置素材的着色器以达到您想要的效果。这是一个让你入门的例子:

THREE.ShaderLib[ 'lambert' ].fragmentShader = THREE.ShaderLib[ 'lambert' ].fragmentShader.replace(

    `vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;`,

    `#ifndef CUSTOM
        vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;
    #else
        vec3 outgoingLight = diffuseColor.rgb * ( 1.0 - 0.5 * ( 1.0 - getShadowMask() ) ); // shadow intensity hardwired to 0.5 here
    #endif`

);

然后,使用它:

var material = new THREE.MeshLambertMaterial( { map: texture } );
material.defines = material.defines || {};
material.defines.CUSTOM = "";

尽管名称不同,但此材质的行为与MeshBasicMaterial相似,但在阴影中会变暗。此外,MeshLambertMaterial仍将按预期工作。

three.js r.88

答案 1 :(得分:2)

在过去的版本中,也许.72,您可以使用MeshBasicMaterial投射和接收阴影。这很简单。然后环境光的概念在three.js中变化,MeshBasicMaterial不再支持阴影。

THREE.ShadowMaterial是为了弥补这个限制而引入的。它很棒!但它实际上只适用于PlaneGeometry,因为它的性质,THREE.ShadowMaterial是透明的,因此可以看到使用ShadowMaterial在object3d内部和外部投射的阴影。

这个想法是你使用两个网格,一个是MeshBasicMaterial,另一个是ShadowMaterial。

shape = new THREE.BoxGeometry(1,1,1),

basicMaterial = new THREE.MeshBasicMaterial({
  color: 0xff0000
}),
mesh = new THREE.Mesh(shape, basicMaterial),

shadowMaterial = new THREE.ShadowMaterial({opacity:.2}),
mesh2 = new THREE.Mesh(shape, shadowMaterial),

您可以在此处查看问题的示例:https://jsfiddle.net/7d47oLkh/

盒子底部的阴影对于用例来说是不正确的。

答案是,不。没有简单的方法来支持全亮的基本材料,这些材料也接受并在three.js中投下阴影。