Since r132, I can't replicate MeshPhongMaterial’s new displacementMap-based self-shadowing using ShaderMaterial (with ShaderLib.phong)
See original GitHub issueDescribe the bug
Since r132, it seems to be possible to have self-shadowing in geometry that has a displacementMap
applied (see DisplacementMap with Shadow - Three.js Tutorials 1).
Using MeshPhongMaterial
in r132, I get the following (correct) result: the shadow casts from the grid structures – please ignore the block structures in the front):
Up to r131, I had a custom depth material that enabled the same functionality (customized to an RGBA elevation texture that I’m decoding in the shader – which is why I can’t work with out-of-the-box MeshPhongMaterial
), which now stopped working since r132. In one of many attempts to fix this, I tried to get a custom ShaderMaterial
up and running, based on ShaderLib.phong
. While the displacement mapping happens (displaced geometry can be seen in the following screenshot’s grid lines), there is no shadowing:
Up to now, I tried out various defines
, I’m setting the textures at “material level”, etc. – but I can’t get self-shadowing to work. It seems that there’s some define missing or some other flag off. I feel like I’m almost there but I’m not.
To Reproduce
In Three.js >= 132, create a ShaderMaterial
with ShaderLib.phong
. Set a displacementMap
. While the mesh geometry gets distorted accordingly, there is no self-shadowing.
Code
this.mesh.receiveShadow = true;
this.mesh.castShadow = true;
const terrainMaterial = new THREE.ShaderMaterial(THREE.ShaderLib.phong);
//I maxed out on defines in an attempt to get this to work:
terrainMaterial.defines = {
USE_UV: "",
USE_MAP: "",
USE_BUMPMAP: "",
USE_DISPLACEMENTMAP: "",
VERTEX_TEXTURES: "",
};
terrainMaterial.lights = true;
terrainMaterial.fog = true;
terrainMaterial.extensions.derivatives = true;
terrainMaterial.extensions.fragDepth = true;
terrainMaterial.map = TerrainTile.TextureLoader.load("img/grid512.png");
terrainMaterial.uniforms.map.value = TerrainTile.TextureLoader.load("img/grid512.png");
terrainMaterial.displacementMap = TerrainTile.TextureLoader.load("img/grid512.png");
terrainMaterial.uniforms.displacementMap.value = TerrainTile.TextureLoader.load("img/grid512.png");
this.mesh.material = terrainMaterial;
this.mesh.material.needsUpdate = true;
Expected behavior
As self-shadowing got integrated into displacement mapped materials in r132, this should work with ShaderMaterial as well.
Platform:
- Device: Desktop, Mobile
- OS: MacOS
- Browser: Chrome, Firefox, Safari
- Three.js version: since r132
Issue Analytics
- State:
- Created 2 years ago
- Comments:7
Top GitHub Comments
The renderer works with both material properties and uniform values.
I’m not sure but I don’t think the approach of the fiddle is the recommended way of the project to enhance built-in materials. IMO, the OP should use
onBeforeCompile()
instead.Thankfully, this will become more clean with a node material…
Thank you @Mugen87 for the general advice and making this work! 🙏
To my defense 😅, it started as a help request (https://discourse.threejs.org/t/cannot-replicate-meshphongmaterials-new-displacementmap-based-self-shadowing-using-custom-shadermaterial-with-shaderlib-phong/32027) and the boss asked me to create an issue here.
I want to emphasize that the change that made the difference was to set all displacement properties – beside the displacementMap – explicitly (i.e., my laymen intuition was, that that’s not required since these are default values – but they are required to toggle defines, I assume?):
Anyways, hallelujah!