Force USE_TANGENT in three.js materials
I am using the depth texture as a depth pre-pass. It works but there is a bug with some materials that use tangents (like anisotropy). When rendering the depth using a material like MeshDepthMaterial
, the renderer, WebGLProgram ignores geometry.attributes.tangent
if it assumes tangents wont be used. This is an issue if the tangents will be used in the scene material and not the depth material, and we see z-fighting artifacts.
As of r170
, it looks like there is no way to force use of the tangents in the shaders. From WebGLProgram
- vertexTangents: !! geometry.attributes.tangent && ( HAS_NORMALMAP || HAS_ANISOTROPY )
Also, it looks like this vertexTangents
is ignored if flatShading
is false for some reason, that might be another bug.
As a workaround, in the three.js-modded fork, its possible to force it by setting geometry.userData.__forceUseTangent
to true
. With this the geometry will always use the tangents irrespective of the material.
This can be done in a custom glTF loader, or before render in a material extension.
An example of material extension snippet that requires tangents -
onObjectRender: (object, material) => {
if (!mesh.isMesh || !mesh.geometry) return
if (!mesh.geometry.attributes.tangent) {
throw new Error('No tangents on the geometry')
// mesh.geometry.computeTangents() // note - tangents must be set before onBeforeRender call, otherwise its not set in the program.
} else {
mesh.geometry.userData.__forceUseTangent = true // required for depthPrepass/gbufferDepth. Otherwise we get artifacts because depth doesn't match exactly in vertex shader...
}
// ...
}
This workaround is only available in the above fork which is used in threepipe, webgi.dev, 3dviewer.dev, ijewel3d.