# Shadow artifacts with WebGPURenderer VSMShadowMap

**URL:** <https://discourse.threejs.org/t/shadow-artifacts-with-webgpurenderer-vsmshadowmap/89017>\
**Category:** Questions\
**Tags:** shadows, lights, webgpu\
**Created:** [January 8, 2026, 8:22am UTC](https://discourse.threejs.org/t/shadow-artifacts-with-webgpurenderer-vsmshadowmap/89017 "2026-01-08T08:22:47Z")\
**Posts on this page:** 6\
**Page:** 1

<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 8, 2026, 8:22am UTC](https://discourse.threejs.org/t/shadow-artifacts-with-webgpurenderer-vsmshadowmap/89017/1 "2026-01-08T08:22:47Z")

</div>

I can’t get `VSMShadowMap` to work right (using `WebGPURenderer`).

When I use `PCFSoftShadowMap` the scene looks like the following (white line is a light helper):

 ![Screenshot 2026-01-08 at 12.14.51 AM](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/0/1/011ea7bc0a47bd1e307294d8d8f0c25058ff23b3.jpeg)

Changes to `light.shadow.radius` and `light.shadow.blurSamples` seem to have no effect on the shadow.

I would like softer/blurrier/fuzzier shadows. When I switch to `VSMShadowMap`, I get something like the following:

 ![Screenshot 2026-01-08 at 12.17.54 AM](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/9/b/9bfa0830ccd493a910940fa056ff71dad722cd21.jpeg)

That’s with shadow.radius 30 and shadow.blurSamples 16, size 1024x1024. The wall does not cast shadows, only receives shadows, so it can’t be acne.

When I change radius to 10 and samples to 8, I get:

 ![Screenshot 2026-01-08 at 12.18.58 AM](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/4/2/422b8a81178f25fd27b48f5740faf31a5fee1917.jpeg)

Radius 4 samples 2:

 ![Screenshot 2026-01-08 at 12.20.04 AM](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/7/f/7f94ce57107ccc6da15d8995879adc866e0af0a4.jpeg)

The shadow isn’t looking right. But also regardless of the radius/samples, there’s this gradient banding.

Any ideas why this is? I still need to make a standalone reproduction.

---

<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 8, 2026, 9:02am UTC](https://discourse.threejs.org/t/shadow-artifacts-with-webgpurenderer-vsmshadowmap/89017/2 "2026-01-08T09:02:18Z")

</div>

Oh, the [VSMShadowMap docs](https://threejs.org/docs/?q=shadowmap#Global.VSMShadowMap) state:

> When using VSMShadowMap all shadow receivers will also cast shadows.

So `castShadow` not being `true` doesn’t matter then. I wonder if this has anything to do with it. Why does PCFSoftShadowMap look drastically better?

EDIT: Ah! That banding _was_ shadow acne. I didn’t realize enabling VSM shadows forced shadow receivers to also cast shadow even if `castShadow` is `false`, so I had assumed the wall was not casting shadows on itself, leading me to believe it was some other issue!

To fix the banding, I had to adjust the `light.shadow.camera.near/far` values to tighten up the shadow camera frustum, then I could remove tiny amounts of acne with small `shadow.bias` values. The frustum near/far distance was previously way too large, which happened to work fine with PCFSoft shadows.

---

<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 8, 2026, 9:42am UTC](https://discourse.threejs.org/t/shadow-artifacts-with-webgpurenderer-vsmshadowmap/89017/3 "2026-01-08T09:42:18Z")

</div>

However there’s still a “shadow” at the edge to the shadow map that I’m not sure how to get rid of:

 ![Screenshot 2026-01-08 at 1.38.11 AM](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/b/f/bf204bb0c82bf4f28b01167293dcab7514c5788b.jpeg)

(other lines are light/camera helpers)

How do we get rid of that edge-of-shadow-map artifact?

Turning down the resolution from 1024 to 512 (and adjusting blur/samples to get a desired shadow), I can now see three edges of the shadow map:

 ![Screenshot 2026-01-08 at 1.53.52 AM](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/a/3/a347be1dddccf2c1d4ff65c8a844d8ad54dabcc7.jpeg)

How do we get rid of those?

EDIT: same problem here: [Hide line from Shadow - #10 by Chaser\_Code](https://discourse.threejs.org/t/hide-line-from-shadow/53656/10)

If I increase shadow.bias to a fairly larger number like -0.1, I get less shadow-map-edge-lines, but the whole shadow is almost gone, so that isn’t working:

 ![Screenshot 2026-01-08 at 2.29.44 AM](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/9/8/985d6b2a05a9488aac5057d281fec4141d4d9f00.jpeg)

It’s like there is a massive depth delta at the shadow map edges.

Is there some way to hook up TSL, re-using VSM nodes, but adding some logic to fade out the edges of the shadow map?

---

<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 10, 2026, 10:53am UTC](https://discourse.threejs.org/t/shadow-artifacts-with-webgpurenderer-vsmshadowmap/89017/4 "2026-01-10T10:53:09Z")

</div>

A solution for the shadow outline artifact is to patch `ShadowNode.prototype.setupShadowFilter` to fade out shadows around the edges of the shadow map area, like so:

```js
			const originalSetupShadowFilter = THREE.ShadowNode.prototype.setupShadowFilter;

			THREE.ShadowNode.prototype.setupShadowFilter = function ( builder, inputs ) {

				// portion of shadow map UV space along edges to fade
				const fadePortion = 0.05;

				const base = originalSetupShadowFilter.call( this, builder, inputs );
				const uv = inputs.shadowCoord.xy;

				// Distance to nearest edge of the shadow UV box
				const edgeDist = min( min( uv.x, uv.x.oneMinus() ), min( uv.y, uv.y.oneMinus() ) );

				// Fade: 1 at the very edge, 0 inside (only if in a shadow)
				const fade = sub( 1, smoothstep( 0, fadePortion, edgeDist ) );
				return mix( base, 1, fade );

			};

```

 ![Screenshot 2026-01-10 at 2.52.29 AM](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/a/f/afc449535cc51dfd1bcfbc9b57b71b2355fb5aaa.jpeg)

---

<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 10, 2026, 11:04pm UTC](https://discourse.threejs.org/t/shadow-artifacts-with-webgpurenderer-vsmshadowmap/89017/5 "2026-01-10T23:04:56Z")

</div>

There was also a bug, that just got fixed today, that was coincidentally causing excessive banding compared to WebGLRenderer:

> <https://github.com/mrdoob/three.js/issues/32698>
>
> \### Description
> 
> For the same scene \`WebGPURenderer\` shows severe shadow acne ar…tifacts compared to \`WebGLRenderer\`:
> 
> Both have identical settings regarding:
> \- Shadow map resolution (1024)
> \- Shadow map camera near / far
> \- Render camera near / far
> \- Shadow bias (0)
> \- Normal bias (0)
> 
> 
> \### Reproduction steps
> 
> 1. Open the two attached live examples
> 
> \### Code
> 
> See fiddles
> 
> 
> \### Live example
> 
> \* \[jsfiddle-latest-release WebGPURenderer\](https://jsfiddle.net/TobiasNoell/jprxayeb/23/)
> \* \[jsfiddle-latest-release WebGLRenderer\](https://jsfiddle.net/TobiasNoell/6hj3ear9/)
> 
> 
> 
> \### Screenshots
> 
> \`WebGPURenderer\`:
> \<img width="690" height="451" alt="Image" src="https://github.com/user-attachments/assets/8444521f-9f85-4870-bcf2-9e3487b87523" /\>
> 
> \`WebGLRenderer\`:
> \<img width="690" height="451" alt="Image" src="https://github.com/user-attachments/assets/0f4485e0-82b8-4ccb-b62d-7e119de486d3" /\>
> 
> \### Version
> 
> r182
> 
> \### Device
> 
> Desktop
> 
> \### Browser
> 
> Chrome
> 
> \### OS
> 
> Windows

---

<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 12, 2026, 7:50am UTC](https://discourse.threejs.org/t/shadow-artifacts-with-webgpurenderer-vsmshadowmap/89017/6 "2026-01-12T07:50:39Z")

</div>

It turns out the outline artifact is a bug in Safari only!

> <https://github.com/mrdoob/three.js/issues/32708>
>
> \### Description
> 
> A couple examples:
> 
> \- https://discourse.threejs.org/t/shadow-ba…nding-with-webgpurenderer-vsmshadowmap/89017/3
> \- https://discourse.threejs.org/t/hide-line-from-shadow/53656
> 
> \### Reproduction steps
> 
> 
> 1. Here's the webgpu VSM example with some debug helpers enabled, and also the spotlight frustum is tighter to more closely encompass the example: https://jsfiddle.net/s79ack12
> No issue so yet:
> \<img height="250" alt="Image" src="https://github.com/user-attachments/assets/a46705f8-792b-4566-b75b-a9a0a5d0e901" /\>
> 3. When we tighten up the spotlight's \`shadow.focus\`, we can see a line at the edge of the spotlight's shadow map area: https://jsfiddle.net/zm53Ladu (line 87)
> This is not typical shadow acne, as it happens exclusively along the edge of the shadow map area:
> \<img height="250" alt="Image" src="https://github.com/user-attachments/assets/1605b679-2613-4391-a414-f5c3848beba7" /\>
> 3. A workaround is to patch \`THREE.ShadowNode.prototype.setupShadowFilter\` to set shadow pixels to \`1\` inside of a border around the shadow map area. In this example, fading the shadow out (or more technically, fading the light back in): https://jsfiddle.net/4675h9j8
> No more map edge artifact:
> \<img height="250" alt="Image" src="https://github.com/user-attachments/assets/8254c7e0-85da-46ec-a429-21ff98c955dd" /\>
> (it doesn't need to be a fade, it could be a hard drop off around the edges, but I also wanted a configurable fade in my case).
> 
> \### Code
> 
> The problem becomes apparent (at least in this scnenario) with this particular line:
> 
> \`\`\`js
> spotLight.shadow.focus = 0.3
> \`\`\`
> 
> \### Live example
> 
> above
> 
> \### Screenshots
> 
> above
> 
> \### Version
> 
> r182, macOS 26 Safari 26
> 
> \### Device
> 
> Desktop
> 
> \### Browser
> 
> Safari
> 
> \### OS
> 
> MacOS
