ThreeJS material with shadows but no lights

自古美人都是妖i 提交于 2020-01-13 09:29:14

问题


I want a material with:

  • Textures
  • Not receiving lights
  • Receiving shadows

I tried with the following library materials:

  • MeshBasicMaterial: Does not support shadows
  • MeshLamberMaterial: If you disable lights (material.lights = false) it also disables shadows
  • ShadowMaterial: Does not support textures

Is a custom ShaderMaterial the only way to achieve it?


回答1:


In three.js, as in real life, shadows are the absence of light. So for a built-in three.js material to receive shadows, it must respond to light.

However, you can modify a built-in material's shader to achieve the effect you want with just a few lines of code. Here is an example to get you started:

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`

);

Then, to use it:

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

In spite of its name, this material will behave like MeshBasicMaterial, but will darken when it is in shadow. And furthermore, MeshLambertMaterial will still work as expected.

three.js r.88




回答2:


In a past version, maybe .72, you could cast and receive shadows with the MeshBasicMaterial. It was simple. Then the concept of ambient light changed in three.js and MeshBasicMaterial could no longer support shadows.

THREE.ShadowMaterial was introduced to compensate for the limitation. It works great! But it really only works on PlaneGeometry because by it's nature, THREE.ShadowMaterial is transparent, so the shadows cast inside and outside the object3d with ShadowMaterial are seen.

The idea is that you use two meshes, one with the MeshBasicMaterial, and the other with 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),

You can see an example of the problem, here: https://jsfiddle.net/7d47oLkh/

The shadows cast at the bottom of the box are incorrect for the use-case.

The answer is, NO. There is no easy way to support full-bright basic materials that also accept and cast a shadow in three.js.



来源:https://stackoverflow.com/questions/47367181/threejs-material-with-shadows-but-no-lights

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!