<RadialGradientTexture>
A reactive radial gradient texture that attaches to the “map” property of its parent. The underlying texture uses an OffscreenCanvas and a CanvasTexture and is assigned the same colorspace as the renderer.
<script lang="ts"> import Scene from './Scene.svelte' import type { ToneMapping, Wrapping } from 'three' import { Canvas } from '@threlte/core' import { ClampToEdgeWrapping, MirroredRepeatWrapping, RepeatWrapping, ACESFilmicToneMapping, AgXToneMapping, CineonToneMapping, LinearToneMapping, NeutralToneMapping, NoToneMapping, ReinhardToneMapping } from 'three' import { Checkbox, Color, Folder, List, Pane, Slider } from 'svelte-tweakpane-ui'
const toneMappingOptions: Record<PropertyKey, ToneMapping> = { ACESFilmic: ACESFilmicToneMapping, AgX: AgXToneMapping, Cineon: CineonToneMapping, Linear: LinearToneMapping, NeutralToneMapping, None: NoToneMapping, Reinhard: ReinhardToneMapping }
const wrappingOptions: Record<PropertyKey, Wrapping> = { ClampToEdge: ClampToEdgeWrapping, MirroredRepeat: MirroredRepeatWrapping, Repeat: RepeatWrapping }
const canvasSize = 1024 const halfCanvasSize = 0.5 * 1024
// from center to one of the corners const diagonal = Math.floor(Math.hypot(halfCanvasSize, halfCanvasSize))
let sceneClearColor = $state('#000000') let sceneToneMapping = $state(AgXToneMapping)
let gradientStartColor = $state('#ffff00') let gradientEndColor = $state('#ff00ff') let gradientInnerRadius = $state(0) let gradientOuterRadiusNumber = $state(diagonal) let gradientUseOuterRadiusAuto = $state(true)
let textureCenterX = $state(0) let textureCenterY = $state(0) let textureOffsetX = $state(0) let textureOffsetY = $state(0) let textureRepeatX = $state(1) let textureRepeatY = $state(1) let textureRotationDegrees = $state(0) let textureWrapS = $state<Wrapping>(ClampToEdgeWrapping) let textureWrapT = $state<Wrapping>(ClampToEdgeWrapping)
let textureRotation = $derived((Math.PI / 180) * textureRotationDegrees) let gradientOuterRadius = $derived<number | 'auto'>( gradientUseOuterRadiusAuto ? 'auto' : gradientOuterRadiusNumber )</script>
<Pane position="fixed"> <List bind:value={sceneToneMapping} options={toneMappingOptions} label="tone mapping" /> <Color bind:value={sceneClearColor} label="clear color" /> <Folder title="gradient props"> <Color bind:value={gradientStartColor} label="start color" /> <Color bind:value={gradientEndColor} label="end color" /> <Slider bind:value={gradientInnerRadius} label="inner radius" min={0} max={gradientUseOuterRadiusAuto ? diagonal : gradientOuterRadiusNumber} step={1} /> <Checkbox bind:value={gradientUseOuterRadiusAuto} label="use 'auto' outer radius" /> {#if !gradientUseOuterRadiusAuto} <Slider bind:value={gradientOuterRadiusNumber} label="outer radius" min={0} max={canvasSize} step={1} on:change={({ detail }) => { gradientInnerRadius = Math.min(detail.value, gradientInnerRadius) }} /> {/if} </Folder> <Folder title="texture props"> <List bind:value={textureWrapS} label="wrapS" options={wrappingOptions} /> <List bind:value={textureWrapT} label="wrapT" options={wrappingOptions} /> <Slider label="centerX" bind:value={textureCenterX} min={-0.5} max={1.5} step={0.5} /> <Slider label="centerY" bind:value={textureCenterY} min={-0.5} max={1.5} step={0.5} /> <Slider label="offsetX" bind:value={textureOffsetX} min={-2} max={2} step={1} /> <Slider label="offsetY" bind:value={textureOffsetY} min={-2} max={2} step={1} /> <Slider label="repeatX" bind:value={textureRepeatX} min={0} max={5} step={1} /> <Slider label="repeatY" bind:value={textureRepeatY} min={0} max={5} step={1} /> <Slider label="rotation (degrees)" bind:value={textureRotationDegrees} min={-360} max={360} step={1} /> </Folder></Pane>
<div> <Canvas> <Scene {gradientEndColor} {gradientInnerRadius} {gradientOuterRadius} {gradientStartColor} {sceneClearColor} {sceneToneMapping} {textureCenterX} {textureCenterY} {textureOffsetX} {textureOffsetY} {textureRepeatX} {textureRepeatY} {textureRotation} {textureWrapS} {textureWrapT} {canvasSize} /> </Canvas></div>
<style> div { height: 100%; }</style><script lang="ts"> import type { ColorRepresentation, ToneMapping, Wrapping } from 'three' import type { ColorStop } from '@threlte/extras' import { DoubleSide } from 'three' import { RadialGradientTexture, OrbitControls } from '@threlte/extras' import { T, useThrelte } from '@threlte/core'
type SceneProps = { canvasSize: number gradientEndColor: string gradientInnerRadius: number gradientOuterRadius: number | 'auto' gradientStartColor: string sceneClearColor: ColorRepresentation sceneToneMapping: ToneMapping textureCenterX: number textureCenterY: number textureOffsetX: number textureOffsetY: number textureRepeatX: number textureRepeatY: number textureRotation: number textureWrapS: Wrapping textureWrapT: Wrapping }
let { canvasSize, gradientInnerRadius, gradientOuterRadius, gradientEndColor, gradientStartColor, sceneClearColor, sceneToneMapping, textureCenterX, textureCenterY, textureOffsetX, textureOffsetY, textureRepeatX, textureRepeatY, textureRotation, textureWrapS, textureWrapT }: SceneProps = $props()
let stops = $derived<ColorStop[]>([ { color: gradientStartColor, offset: 0 }, { color: gradientEndColor, offset: 1 } ])
const { invalidate, renderer, toneMapping } = useThrelte()
$effect(() => { toneMapping.set(sceneToneMapping) invalidate() })
$effect(() => { renderer.setClearColor(sceneClearColor) invalidate() })</script>
<T.PerspectiveCamera makeDefault position.z={5}> <OrbitControls /></T.PerspectiveCamera>
<T.Mesh scale={2}> <T.PlaneGeometry /> <T.MeshBasicMaterial side={DoubleSide}> <RadialGradientTexture width={canvasSize} height={canvasSize} innerRadius={gradientInnerRadius} outerRadius={gradientOuterRadius} center.x={textureCenterX} center.y={textureCenterY} offset.x={textureOffsetX} offset.y={textureOffsetY} repeat.x={textureRepeatX} repeat.y={textureRepeatY} rotation={textureRotation} wrapS={textureWrapS} wrapT={textureWrapT} {stops} /> </T.MeshBasicMaterial></T.Mesh>Attaching the Texture
Section titled “Attaching the Texture”The texture is automatically attached to the map property of its parent. You can disable this behaviour by setting the attach prop to false. This may be useful if you want to create the texture but use it somewhere else.
<script> let texture = $state()</script>
<RadialGradientTexture attach={false} bind:ref={texture}/>
<SomeComponent {texture} />Radius Props
Section titled “Radius Props”The innerRadius and outerRadius props control the size of the gradient. The innerRadius prop should be less than the outerRadius prop but it is not enforced. If outerRadius is set to 'auto' the outerRadius is effectively set to the radius of the circle that circumscribes the canvas. For example, if the canvas’s width and height are 1024, and outerRadius is set to 'auto', the radius that will be used is sqrt(1024**2 + 1024**2) or roughly 724.
It is also not enforced that innerRadius and outerRadius are both positive.
Gradient Stops
Section titled “Gradient Stops”<RadialGradientTexture> accepts a stops prop which is an array of color stops that define the gradient. A stop is defined by two things; an offset and a color. Gradient stops are identical to how you would use them with a 2D context, notably the offset should be a number between 0 and 1 inclusive. Stop colors must be any acceptable CSS string. Here are a couple examples of valid stops.
<RadialGradientTexture stops={[ { color: 'black', offset: 0 }, { color: 'white', offset: 1 } ]}/>Three.js’s Color class conveniently has a getHexString method which you can use to convert a color to a css color string.
<RadialGradientTexture stops={[ { color: 'red', offset: 0 }, { color: new Color(0xff_00_00).getHexString(), offset: 0.25 }, { color: 'rgb(255, 0, 0)', offset: 0.5 }, { color: '#ff0000', offset: 0.75 }, { color: new Color(new Color(new Color())).set(1, 0, 0), offset: 1 } ]}/>Adjusting Scene Colors
Section titled “Adjusting Scene Colors”If the colors in your scene do not match the color in your stops, you may need to adjust the tone mapping of the scene. ToneMapping constants are imported from the three library.
<script> import { useThrelte } from '@threlte/core' import { LinearToneMapping } from 'three'
const { toneMapping } = useThrelte()
toneMapping.set(LinearToneMapping)</script>Component Signature
Section titled “Component Signature”
<RadialGradientTexture> extends
<
T
.
CanvasTexture
>
and supports all its props, snippets, bindings and events.