Can you use Alpha Map shadows with ranges of transparency?

I want to use a grayscale image as the alphaMap and have variable amount of transparency on the shadow cast.

The problem is that the alphaMap is binary, the section either casts shadows or does not. Nothing inbetween. As an example I want a 50% gray pixel to cast a 50% strong shadow.

Here is a image of the issue I am having (taken from demo website):

Mock code from demo of current implementation

    const canvas = document.getElementById('myCanvas')
    const ctx = canvas.getContext('2d');

    // blur alphaMap texture
    const blurRadius = 5;
    blurCanvas(ctx, blurRadius);

    // load texture from canvas
    const texture = new THREE.CanvasTexture(ctx.canvas);

    const material = new THREE.MeshBasicMaterial({
        alphaMap: texture
    });

    cube = new THREE.Mesh(geometry, material);

Solutions that won’t work

Here are a couple things I have in mind:

  • It is important that the solution works with normal maps, so it can’t just be a image overlay with transparancy.

  • Shadows need to be of really high quality, so the normal three.js shadow implementation wouldn’t cut it.

  • The alphaMap should be customizable so can therefore not be pre-baked into the texture.

For the final product I only need a top down, locked, 2D perspective so am happy to take shortcuts if there are easier ways to implement this within those limitations.

Still very new to Three.js. Tried to look online and didn’t find anything that has solved my issue. Feel free to ask if there are any questions or things that need clearing up.

You can’t expect the blurry part of alphaMap to be the same for shadow, it’s not how shadows in general work.

You can only have shadows on transparency with “alpha cut”, “alpha test”, it has many names and is literally just as you figured: shadow or no shadow

You might look into different shadow techniques, or ultimately into baking shadows which won’t allow dynamic lighting.

You will get higher quality/more realistic with other techniques such as contact shadows as far as there are implementations, however they usually come with a massive performance cost and/or other limitations.

The cheapest higher quality approach is switching to variance shadow maps, which is technically like post shadowing having a wider penumbra range than PCF shadows, but you can’t use alphaMap to control the penumbra range.

VSM you can activate in THREE

Keep in mind this technique also has limitations and cases where you’ll get glitches/errors due to it being processes like a post-effect.

1 Like

Thanks for the reply!

Here is a better example of the complex result’s I want the shadow to achieve:

Maybe a camera projected shadow texture in a custom fragment shader could do the trick?

I see now that attempting to use 3D traditional shadows doesn’t fit for my use case.

Then you would need to avoid the object from receiving it and the light source moving, and it would be only semi-dynamic as you’re projecting a fixed silhouette. And in general this wouldn’t work beyond a single object scene.

With a extreme high res VSM you can get somewhere close but not like in the image with varying penumbras. So yes if you only have a single item and need the shadow to be semi-dynamic then working out some silhouette projecting would give the desired quality result/look, but it’s not the original purpose of the light texture projection and you also won’t be able to move the light source around as there will be just one true direction the shadow (like a tree) will stem from the stem.

So yeah for 99% of circumstances this wouldn’t work for a bunch of reasons, but for exactly all the particular requirements of my use case it’s a sorta functional solution.

Well good to know I’m not going crazy. Thanks for the help!