threlte logo
@threlte/extras

<ShadowMaterial>

webgl <ShadowMaterial> works with WebGL and is available from the @threlte/extras export. webgpu <ShadowMaterial> works with WebGPU and is available from the @threlte/extras/webgpu export.

A cheap CanvasTexture-based material meant to look like a shadow without the need for any lights in the scene.

<script lang="ts">
  import { Canvas } from '@threlte/core'
  import Scene from './Scene.svelte'
  import { Color, Pane } from 'svelte-tweakpane-ui'

  let color = $state('#000000')
</script>

<Canvas>
  <Scene {color} />
</Canvas>
<Pane
  title="shadow material"
  position="fixed"
>
  <Color
    bind:value={color}
    label="shadow color"
  />
</Pane>
<script lang="ts">
  import { Mesh } from 'three'
  import { OrbitControls, ShadowMaterial } from '@threlte/extras'
  import { T, useTask } from '@threlte/core'

  let { color = '#000000' } = $props()

  const plane = new Mesh()

  const sphere = new Mesh()

  const radius = 1

  const diameter = 2 * radius
  const planeScale = 2 * diameter
  plane.scale.x = planeScale
  plane.scale.y = planeScale

  let time = 0

  const shadowMesh = new Mesh()

  useTask((dt) => {
    time += dt
    const s = Math.sin(time)
    sphere.position.y = 2.5 + s
    shadowMesh.scale.setScalar(3 + s)
  })
</script>

<T.PerspectiveCamera
  makeDefault
  position.x={5}
  position.y={5}
  position.z={5}
  oncreate={(ref) => {
    ref.lookAt(plane.position)
  }}
>
  <OrbitControls />
</T.PerspectiveCamera>

<T is={sphere}>
  <T.IcosahedronGeometry args={[radius, 2]} />
  <T.MeshBasicMaterial
    color="orangered"
    wireframe
  />
</T>

<T.Group rotation.x={-1 * 0.5 * Math.PI}>
  <T is={plane}>
    <T.PlaneGeometry />
  </T>
  <T
    is={shadowMesh}
    position.z={0.01}
  >
    <T.PlaneGeometry />
    <ShadowMaterial {color} />
  </T>
</T.Group>

Transparency

Because the canvas texture uses an alpha channel, <ShadowMaterial> uses transparency by default. This means it will be sorted into a “transparent objects” render list by the renderer. In three.js, transparent objects are rendered after opaque objects. This may be something to keep in mind when using <ShadowMaterial>.

Component Signature

<ShadowMaterial> extends < T . MeshBasicMaterial > and supports all its props, snippets, bindings and events.

Props

name
type
required
default
description

color
string
no
'black'
The color at the center of the shadow, which fades out to transparent at the edges.

depthWrite
boolean
no
false
Whether the shadow writes to the depth buffer.

fog
boolean
no
false
Whether the scene's fog affects the shadow.

opacity
number
no
0.5
The opacity of the shadow.

side
Side
no
DoubleSide
Which side of the faces is rendered.

transparent
boolean
no
true
Whether the material is transparent.