<AsciiRenderer>
A wrapper around Three’s AsciiEffect addon. It replaces the main render function with a function that renders the scene to an HTML table and overlays it on top of the canvas. Areas with a higher “brightness” are mapped to characters that appear “fuller”.
<script lang="ts"> import Scene from './Scene.svelte' import type { AsciiEffectOptions } from 'three/examples/jsm/Addons.js' import { AsciiRenderer } from '@threlte/extras' import { Button, Checkbox, Color, Folder, Pane, Slider, Text } from 'svelte-tweakpane-ui' import { Canvas } from '@threlte/core'
let fgColor = $state('#ff2400') let bgColor = $state('#000000')
const defaultCharacters = ' .:-+*=%@#' let characters = $state(defaultCharacters)
let alpha = $state(true) let block = $state(false) let color = $state(false) let invert = $state(true) let resolution = $state(0.1) let scale = $state(1)
const options = $derived<AsciiEffectOptions>({ alpha, block, color, invert, resolution, scale })
let autoRotate = $state(true)</script>
<div> <Pane position="fixed" title="AsciiRenderer" > <Folder title="scene"> <Checkbox bind:value={autoRotate} label="auto rotate" /> </Folder> <Folder title="options"> <Slider bind:value={scale} label="scale" min={1} max={3} step={1} /> <Slider bind:value={resolution} label="resolution" min={0.05} max={0.2} step={0.05} /> <Checkbox bind:value={invert} label="invert" /> <Checkbox bind:value={color} label="color" /> {#if color} <Checkbox bind:value={block} label="block" /> {/if} </Folder> <Folder title="props"> <Text bind:value={characters} label="characters" /> <Button on:click={() => { characters = defaultCharacters }} title="reset characters" /> {#if !color} <Color bind:value={fgColor} label="text color" /> <Color bind:value={bgColor} label="background color" /> {/if} </Folder> </Pane> <Canvas> <AsciiRenderer {bgColor} {characters} {fgColor} {options} /> <Scene {autoRotate} /> </Canvas></div>
<style> div { height: 100%; }</style><script lang="ts"> import { OrbitControls } from '@threlte/extras' import { T } from '@threlte/core'
type SceneProps = { autoRotate: boolean }
let { autoRotate = true }: SceneProps = $props()</script>
<T.DirectionalLight position={5} />
<T.PerspectiveCamera makeDefault position.z={5}> <OrbitControls {autoRotate} /></T.PerspectiveCamera>
<T.Mesh> <T.MeshNormalMaterial /> <T.TorusKnotGeometry /></T.Mesh>Typically you’d use <AsciiRenderer> alongside your main Scene component. <AsciiRenderer> creates an absolutely postioned table element that is appended to the dom element of the <Canvas>. You may need to set the wrapping element’s position to relative
<div> <Canvas> <AsciiRenderer /> <Scene /> </Canvas></div>
<style> div { position: relative; }</style>Characters
Section titled “Characters”The characters prop should be sorted by ascending “opaqueness”.
<AsciiRenderer characters=" #" />The example above uses a character set with two characters - and #.
Colors
Section titled “Colors”By default the renderer sets options.color to false and will only use the colors given by the fgColor and bgColor props. fgColor and bgColor can be any acceptable CSS color string. If your colors contain an alpha component, make sure to set options.alpha to true.
If options.color is set to true, fgColor and bgColor will be ignored and the corresponding color of the scene will be used for each character.
<AsciiRenderer options={{ color: true }} />Setting options.color to true slows down performance. Using a static scene or manually
rendering can help.
Other Options Props
Section titled “Other Options Props”Because the effect doesn’t support dynamically updating options, any time an options property changes, a new AsciiEffect is created inside <AsciiRenderer. For this reason, options is passed as an object to <AsciiRenderer>
options.blockmakes the characters into color blocks. It is only applied ifoptions.coloristrue.options.invertinverts thefgColorandbgColorcolors.options.resolutioncontrols how detailed the render is.options.scalecontrols the scale of the characters. Note that zooming the camera does not control the size of the characters.
A new AsciiEffect instance must be created anytime options changes because an effect can not
have it options changed after it has been created. This is a limitation of the AsciiEffect addon
from Three.js.
Disabling the Render Task
Section titled “Disabling the Render Task”If at some point your scene doesn’t need to be rendered because it will no longer update or nothing will change between frames, you can turn off the rendering task by setting the autoRender prop to false. This will stop the render task from running which can improve performance. This is especially useful when using options.color which is known to slow down the renderer.
AsciiRenderer passes its AsciiEffect instance to its children snippet. This allows you to opt out of AsciiEffect’s renderering task but still use the effect it creates. It can also be used for on-demand rendering.
<script lang="ts"> import Scene from './Scene.svelte' import type { AsciiEffectOptions } from 'three/examples/jsm/Addons.js' import { AsciiRenderer } from '@threlte/extras' import { Canvas } from '@threlte/core' import { Checkbox, Pane } from 'svelte-tweakpane-ui'
let color = $state(false)
const options: AsciiEffectOptions = $derived({ color })</script>
<Pane title="render on update" position="fixed"> <Checkbox bind:value={color} label="color" /></Pane>
<div> <Canvas> <AsciiRenderer autoRender={false} {options} > {#snippet children({ asciiEffect })} <Scene {asciiEffect} /> {/snippet} </AsciiRenderer> </Canvas></div>
<style> div { height: 100%; }</style><script lang="ts"> import { T, useThrelte } from '@threlte/core' import type { AsciiEffect } from 'three/examples/jsm/Addons.js'
let { asciiEffect }: { asciiEffect: AsciiEffect } = $props()
const { autoRender, camera, scene } = useThrelte()
$effect(() => { const lastAutoRender = autoRender.current autoRender.set(false) return () => { autoRender.set(lastAutoRender) } })
// render once $effect(() => { asciiEffect.render(scene, camera.current) })</script>
<T.DirectionalLight position={5} />
<T.PerspectiveCamera makeDefault position.z={5}/>
<T.Mesh> <T.MeshNormalMaterial /> <T.TorusKnotGeometry /></T.Mesh>The example above demonstrates how to render on demand. The scene is only rendered when the color checkbox changes. The change causes the options object to update which triggers a new AsciiEffect to be created. The effect is passed into the <Scene> component and an $effect is used to rerender the scene.