<LinearGradientTexture>
A reactive linear gradient texture. 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 { Color, Folder, List, Pane, Slider } from 'svelte-tweakpane-ui' import { ClampToEdgeWrapping, MirroredRepeatWrapping, RepeatWrapping, ACESFilmicToneMapping, AgXToneMapping, CineonToneMapping, LinearToneMapping, NeutralToneMapping, NoToneMapping, ReinhardToneMapping } from 'three'
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
let sceneClearColor = $state('#000000') let sceneToneMapping = $state(AgXToneMapping)
let gradientStartColor = $state('#ff00ff') let gradientEndColor = $state('#ffff00') let gradientStartX = $state(0) let gradientStartY = $state(0) let gradientEndX = $state(0) let gradientEndY = $state(canvasSize)
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)</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={gradientStartX} label="start x" min={0} max={canvasSize} step={1} /> <Slider bind:value={gradientStartY} label="start y" min={0} max={canvasSize} step={1} /> <Slider bind:value={gradientEndX} label="end x" min={0} max={canvasSize} step={1} /> <Slider bind:value={gradientEndY} label="end y" min={0} max={canvasSize} step={1} /> </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} {gradientEndX} {gradientEndY} {gradientStartColor} {gradientStartX} {gradientStartY} {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 { LinearGradientTexture, OrbitControls } from '@threlte/extras' import { T, useThrelte } from '@threlte/core'
type SceneProps = { canvasSize: number gradientEndColor: string gradientEndX: number gradientEndY: number gradientStartColor: string gradientStartX: number gradientStartY: number sceneClearColor: ColorRepresentation sceneToneMapping: ToneMapping textureCenterX: number textureCenterY: number textureOffsetX: number textureOffsetY: number textureRepeatX: number textureRepeatY: number textureRotation: number textureWrapS: Wrapping textureWrapT: Wrapping }
let { canvasSize, gradientEndColor, gradientEndX, gradientEndY, gradientStartColor, gradientStartX, gradientStartY, 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}> <LinearGradientTexture width={canvasSize} height={canvasSize} startX={gradientStartX} startY={gradientStartY} endX={gradientEndX} endY={gradientEndY} 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>
<LinearGradientTexture attach={false} bind:ref={texture}/>
<SomeComponent {texture} />Gradient Stops
Section titled “Gradient Stops”<LinearGradientTexture> 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 CanvasRenderingContext2D, notably the offset should be a number between 0 and 1 inclusive. Stop colors can be any valid color representation in Three.js. Here are a couple examples of valid stops.
<LinearGradientTexture stops={[ { color: 'black', offset: 0 }, { color: 'white', offset: 1 } ]}/>
<LinearGradientTexture stops={[ { color: '#00ffff', offset: 0 }, { color: '#ff00ff', offset: 0.5 }, { color: '#ffff00', offset: 1 } ]}/>You can even mix and match color representations
<LinearGradientTexture stops={[ { color: 'red', offset: 0 }, { color: 0xff_00_00, 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 } ]}/>All of the colors above are valid representations of the color red.
Gradient Start Point and End Point
Section titled “Gradient Start Point and End Point”You can control the gradient start point and end point with the startX, startY, endX, and endY props. For example, the props for a gradient that starts at the bottom left corner of the texture and ends at the top right corner would be:
<LinearGradientTexture startX={0} startY={height} endX={width} endY={0}/>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”
<LinearGradientTexture> extends
<
T
.
CanvasTexture
>
and supports all its props, snippets, bindings and events.