# Cast a shadow from a semi-transparent texture?

**URL:** <https://discourse.threejs.org/t/cast-a-shadow-from-a-semi-transparent-texture/49818>\
**Category:** Questions\
**Tags:** textures\
**Created:** [March 30, 2023, 4:16pm UTC](https://discourse.threejs.org/t/cast-a-shadow-from-a-semi-transparent-texture/49818 "2023-03-30T16:16:41Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![prismspecs](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/prismspecs/32/31954_2.png) [@prismspecs](https://discourse.threejs.org/u/prismspecs)\
**Post date:** [March 30, 2023, 4:16pm UTC](https://discourse.threejs.org/t/cast-a-shadow-from-a-semi-transparent-texture/49818/1 "2023-03-30T16:16:42Z")

</div>

Hello, if I have a texture such as this:

 ![glyph_12](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/f/c/fc7027528119c75b476cd4e7bb72bdbf0676ee6e.jpeg)

Currently I am using the black section as transparent and the white as what should be rendered to a plane. It works well, but I’m curious if I can also have that white section cast a shadow, as though it were a mesh?

Thanks

---

<div class="post-metadata">

**Author:** ![Chaser\_Code](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/chaser_code/32/20199_2.png) [@Chaser\_Code](https://discourse.threejs.org/u/Chaser_Code)\
**Post date:** [March 30, 2023, 4:29pm UTC](https://discourse.threejs.org/t/cast-a-shadow-from-a-semi-transparent-texture/49818/2 "2023-03-30T16:29:11Z")

</div>

Maybe need `material.alphaMap=texture;`

---

<div class="post-metadata">

**Author:** ![Fyrestar](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/fyrestar/32/52793_2.png) [@Fyrestar](https://discourse.threejs.org/u/Fyrestar)\
**Post date:** [March 30, 2023, 4:48pm UTC](https://discourse.threejs.org/t/cast-a-shadow-from-a-semi-transparent-texture/49818/3 "2023-03-30T16:48:00Z")

</div>

Use it as `alphaMap` and set `alphaTest` to `0.5`, you could also use it as `map` if the black parts are zero alpha.

---

<div class="post-metadata">

**Author:** ![prismspecs](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/prismspecs/32/31954_2.png) [@prismspecs](https://discourse.threejs.org/u/prismspecs)\
**Post date:** [March 31, 2023, 8:11am UTC](https://discourse.threejs.org/t/cast-a-shadow-from-a-semi-transparent-texture/49818/4 "2023-03-31T08:11:37Z")

</div>

Thank you both for your help. Unfortunately I had already set those properties. Here is my material:

```javascript
        this.material = new THREE.MeshStandardMaterial({
            map: tex,
            alphaMap: tex,
            alphaTest: .05,
            transparent: true,
        });

```

I get the following result:

 ![Screenshot from 2023-03-31 10-11-06](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/1/0/10ddd363a9a911de10e9a125407dc3dc4c47552d.jpeg)

As you can see, the cube successfully casts a shadow, while the plane+texture items do not.

---

<div class="post-metadata">

**Author:** ![Chaser\_Code](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/chaser_code/32/20199_2.png) [@Chaser\_Code](https://discourse.threejs.org/u/Chaser_Code)\
**Post date:** [March 31, 2023, 9:17am UTC](https://discourse.threejs.org/t/cast-a-shadow-from-a-semi-transparent-texture/49818/5 "2023-03-31T09:17:42Z")

</div>

```javascript
this.material=new THREE.MeshBasicMaterial({
map:tex,
alphaMap:tex,
alphaTest:0.5, // <-- not 0.05
transparent:false
});
mesh.castShadow=true;

```

 ![image](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/a/a/aa5e5e6532ee90f84c5114c6ff8a8c5513e94a6c.jpeg)

---

<div class="post-metadata">

**Author:** ![prismspecs](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/prismspecs/32/31954_2.png) [@prismspecs](https://discourse.threejs.org/u/prismspecs)\
**Post date:** [March 31, 2023, 9:34am UTC](https://discourse.threejs.org/t/cast-a-shadow-from-a-semi-transparent-texture/49818/6 "2023-03-31T09:34:40Z")

</div>

I really appreciate you taking the time to respond. I must be doing something dumb. No worries if this is too much to ask, but here is a cleaned up full version of the code…

```javascript

import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';

import { TWEEN } from 'three/examples/jsm/libs/tween.module.min'

// ----------------------- DATA
const assetsDir = "map-assets/";
const glyphDir = assetsDir + "/glyphs_jpg/";
const glyphData =
    [
        {
            "image": glyphDir + 'glyph_1.jpg',
            "position": { x: -4.0, y: 3.7, z: .5 },
        },
        {
            "image": glyphDir + 'glyph_2.jpg',
            "position": { x: 3.92, y: 4, z: .5 },
        },
        {
            "image": glyphDir + 'glyph_3.jpg',
            "position": { x: -0.35, y: 2.70, z: .4 },
        },
        
    ];

// ----------------------- SCENE
const scene = new THREE.Scene();

// ----------------------- CAMERA
const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, .1, 10000);
camera.position.set(0, 0, 5);

const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x111111);
document.body.appendChild(renderer.domElement);
renderer.setPixelRatio(window.devicePixelRatio);

// ----------------------- CONTROLS
const controls = new OrbitControls(camera, renderer.domElement);
controls.addEventListener('change', render);

// ----------------------- LIGHTING
const dirLight = new THREE.DirectionalLight(0xffffff, .5);
dirLight.position.setScalar(5); // get it away from center
dirLight.position.set(0, 0, 15);
dirLight.castShadow = true;
scene.add(dirLight);
// const helper = new THREE.CameraHelper(dirLight.shadow.camera)
// scene.add(helper)

const geometry = new THREE.BoxGeometry(11, 11, 1);
const material = new THREE.MeshStandardMaterial({ color: 0xbbccaa });
const cube = new THREE.Mesh(geometry, material);
cube.position.set(0, 0, -1);
cube.receiveShadow = true;
scene.add(cube);

const geometry2 = new THREE.BoxGeometry(3, 3, 3);
const material2 = new THREE.MeshStandardMaterial({ color: 0x555555 });
const cube2 = new THREE.Mesh(geometry2, material2);
cube2.position.set(1, 0, 5);
cube2.receiveShadow = true;
cube2.castShadow = true;
scene.add(cube2);

// ----------------------- GLYPHS

class Glyph extends THREE.Mesh {
    constructor(data) {

        super()

        this.position.set(data.position.x, data.position.y, data.position.z);

        this.geometry = new THREE.PlaneGeometry(1, 1);
        this.scale.setScalar(3);

        const tex = new THREE.TextureLoader().load(data.image);

        this.material = new THREE.MeshBasicMaterial({
            map: tex,
            alphaMap: tex,
            alphaTest: .5,
            transparent: false,

        });
        this.castShadow = true;
    }

}

let glyphs = [];
for (let i = 0; i < glyphData.length; i++) {

    glyphs[i] = new Glyph(glyphData[i]);
    scene.add(glyphs[i]);

}

renderer.shadowMap.enabled = true;

// ----------------------- RENDER
render();
function render() {

        renderer.render(scene, camera);

}

animate();
function animate() {
    // console.log("!");
    requestAnimationFrame(animate);
    TWEEN.update();
}

```

I can’t figure out why it won’t work!

 ![Screenshot from 2023-03-31 11-34-25](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/b/9/b94b9364be021a9213bee21d5c4bb5d1a49e2bd8.png)

---

<div class="post-metadata">

**Author:** ![Chaser\_Code](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/chaser_code/32/20199_2.png) [@Chaser\_Code](https://discourse.threejs.org/u/Chaser_Code)\
**Post date:** [March 31, 2023, 11:10am UTC](https://discourse.threejs.org/t/cast-a-shadow-from-a-semi-transparent-texture/49818/7 "2023-03-31T11:10:10Z")

</div>

`renderer.shadowMap.type=THREE.VSMShadowMap;`  
Another shadow types not working for me.  
 ![image](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/b/8/b8a285b35bbf12712a7a385dc74871f6d82efc46.png)

---

<div class="post-metadata">

**Author:** ![prismspecs](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/prismspecs/32/31954_2.png) [@prismspecs](https://discourse.threejs.org/u/prismspecs)\
**Post date:** [March 31, 2023, 1:10pm UTC](https://discourse.threejs.org/t/cast-a-shadow-from-a-semi-transparent-texture/49818/8 "2023-03-31T13:10:29Z")

</div>

Thank you!

It turns out that Plane geometries do not cast shadows by default, since the shadow is generated using the back face of a given mesh. The solution above works, as well as using shadowSide: THREE.DoubleSide on the Plane material.

---

<div class="post-metadata">

**Author:** ![Chaser\_Code](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/chaser_code/32/20199_2.png) [@Chaser\_Code](https://discourse.threejs.org/u/Chaser_Code)\
**Post date:** [March 31, 2023, 1:33pm UTC](https://discourse.threejs.org/t/cast-a-shadow-from-a-semi-transparent-texture/49818/9 "2023-03-31T13:33:07Z")

</div>

I used `material.side:2;`  
Added color:

```javascript
this.material = new THREE.MeshBasicMaterial({
color:data.color,
side:2,
alphaMap: tex,
alphaTest: .5,
transparent: true,
});

```

---

<div class="post-metadata">

**Author:** ![trusktr](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/trusktr/32/13726_2.png) [@trusktr](https://discourse.threejs.org/u/trusktr)\
**Post date:** [January 4, 2024, 7:21am UTC](https://discourse.threejs.org/t/cast-a-shadow-from-a-semi-transparent-texture/49818/10 "2024-01-04T07:21:03Z")

</div>

How can we make the shadow more or less depending on the amount of transparency a texture has?

For example, if part of the mesh has opacity 1, and the other part has opacity 0.5, we would want one part of the shadow to full strength (no light goes through at places with opacity 1), and part of the shadow to be half strength (some light goes through at places with opacity 0.5).
