Light shine through transparent png texture map

I have a THREE.PlaneBufferGeometry() with a map that is part wise transparent. When this object cast shadow, the shadow is a rectangle. I want the shadow to be the same as displayed mesh. Can someone help me with this?
Thanks in advance!

I use a shader I found years ago that fixes this. I will find it and post a bit later today…

<script type='x-shader/x-fragment' id='fragmentShaderDepth'>
	uniform sampler2D texture;
	varying vec2 vUV;

	vec4 pack_depth( const in float depth ) {

		const vec4 bit_shift = vec4( 256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0 );
		const vec4 bit_mask  = vec4( 0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0 );
		vec4 res = fract( depth * bit_shift );
		res -= res.xxyz * bit_mask;
		return res;

	}

	void main() {

		vec4 pixel = texture2D( texture, vUV );

		if ( pixel.a < 0.5 ) discard;

		gl_FragData[ 0 ] = pack_depth( gl_FragCoord.z );

	}
</script>

<script type='x-shader/x-vertex' id='vertexShaderDepth'>
	varying vec2 vUV;
	void main() {

		vUV = 0.99 * uv;
		vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
		gl_Position = projectionMatrix * mvPosition;
	}

</script>

To use this add those to your html then call it like this

Texture = new THREE.TextureLoader().load(“picture.png”);
Geometry = new THREE.PlaneGeometry(10,6 );//or whatever size
Material= new THREE.MeshBasicMaterial( {side:THREE.DoubleSide, transparent : true, opacity: 1, map: Texture } );

MyMesh = new THREE.Mesh(Geometry, Material);
var uniforms = { texture: { type: “t”, value: Texture } };
var vertexShader = document.getElementById( ‘vertexShaderDepth’ ).textContent;
var fragmentShader = document.getElementById( ‘fragmentShaderDepth’ ).textContent;
MyMesh.customDepthMaterial = new THREE.ShaderMaterial( { uniforms: uniforms, vertexShader: vertexShader, fragmentShader: fragmentShader } );

This is what it will look like

3 Likes

Thank you! :smiley:

You bet, glad I was able to help. Others have been so kind here answering all my stupid questions, it feels good to be on the other end :sunglasses:

Another option is to use MeshDepthMaterial. Something like this:

let texture = _your_texture_ ;
let mesh = new THREE.Mesh( 
  _your_geometry_, 
  new THREE.MeshBasicMaterial({
    map: texture, 
    alphaTest: 0.5, 
    side: THREE.DoubleSide
  })
);
mesh.customDepthMaterial = new THREE.MeshDepthMaterial({
  depthPacking: THREE.RGBADepthPacking,
  map: texture,
  alphaTest: 0.5
});

Sweet, I may change mine to that if I get the same results