<Wireframe>
<Wireframe> patches the material of its parent to render an antialiased, shader based wireframe on a geometry.
<script lang="ts"> import { Color } from 'three' import { Pane, Checkbox, Slider, Color as ColorInput, Separator } from 'svelte-tweakpane-ui' import { Canvas } from '@threlte/core' import Scene from './Scene.svelte'
let wireframeProps = $state({ thickness: 0.7,
squeeze: true, squeezeMin: 0.2, squeezeMax: -0.13,
dash: false, dashInvert: true, dashRepeats: 4, dashLength: 0.1,
fill: new Color('lightgreen'), fillOpacity: 1, fillMix: 0,
stroke: new Color('red'), strokeOpacity: 1, colorBackfaces: false, backfaceStroke: new Color('lightred') })</script>
<Pane title="Wireframe" position="fixed"> <Slider label="thickness" bind:value={wireframeProps.thickness} /> <Separator />
<Checkbox label="squeeze" bind:value={wireframeProps.squeeze} /> <Slider label="squeezeMin" bind:value={wireframeProps.squeezeMin} /> <Slider label="squeezeMax" bind:value={wireframeProps.squeezeMax} /> <Separator />
<Checkbox label="dash" bind:value={wireframeProps.dash} /> <Checkbox label="dashInvert" bind:value={wireframeProps.dashInvert} /> <Slider label="dashLength" bind:value={wireframeProps.dashLength} /> <Slider label="dashRepeats" step={1} bind:value={wireframeProps.dashRepeats} /> <Separator />
<ColorInput label="fill" type="float" bind:value={wireframeProps.fill} /> <Slider label="fillOpacity" bind:value={wireframeProps.fillOpacity} /> <Slider label="fillMix" step={0.01} bind:value={wireframeProps.fillMix} /> <Separator />
<ColorInput label="stroke" type="float" bind:value={wireframeProps.stroke} /> <Slider label="fillOpacity" bind:value={wireframeProps.strokeOpacity} /> <ColorInput label="backfaceStroke" type="float" bind:value={wireframeProps.backfaceStroke} /></Pane>
<div> <Canvas> <Scene {wireframeProps} /> </Canvas></div>
<style> div { position: relative; height: 100%; width: 100%; }</style><script lang="ts"> import { T } from '@threlte/core' import { useGltf, useGltfAnimations, Wireframe } from '@threlte/extras'
let { wireframeProps } = $props()
const gltf = useGltf('https://threejs.org/examples/models/gltf/Xbot.glb') let { actions } = useGltfAnimations(gltf)
$effect(() => { // This effect acts like an init default pose $actions?.['idle']?.play() })</script>
<T.Group dispose={false}> {#await gltf then { nodes, materials }} <T is={nodes.Scene}> <T is={nodes.Armature} name="Armature" scale={0.01} > <T is={nodes.mixamorigHips} /> <T.SkinnedMesh name="Beta_Joints" geometry={nodes.Beta_Joints.geometry} material={materials.Beta_Joints_MAT} skeleton={nodes.Beta_Joints.skeleton} castShadow /> <T.SkinnedMesh name="Beta_Surface" geometry={nodes.Beta_Surface.geometry} material={materials['asdf1:Beta_HighLimbsGeoSG2']} skeleton={nodes.Beta_Surface.skeleton} castShadow > <Wireframe {...wireframeProps} /> </T.SkinnedMesh> </T> </T> {/await}</T.Group><script lang="ts"> import type { InstancedMesh as ThreeInstancedMesh } from 'three' import { T, useTask } from '@threlte/core' import Character from './Character.svelte' import { InstancedMesh, Instance, Wireframe, Outlines, Float } from '@threlte/extras' import { Vector3, Quaternion, type QuaternionTuple, type Vector3Tuple } from 'three'
let { wireframeProps } = $props()
let boxes = $state.raw<ThreeInstancedMesh>()
let poses: { position: Vector3Tuple quaternion: QuaternionTuple }[] = []
const numCubes = 70 for (let i = 0; i < numCubes; i += 1) { const position = new Vector3().randomDirection().multiplyScalar(1).toArray() position[1] += 1.2 poses.push({ position, quaternion: new Quaternion().random().toArray() }) }
useTask((delta) => { if (boxes) boxes.rotation.y += delta / 60 })</script>
<T.PerspectiveCamera makeDefault position={[-0.8, 1.2, 1.7]} oncreate={(ref) => { ref.lookAt(0, 1, 0) }}/>
<T.AmbientLight /><T.DirectionalLight position={[10, 5, 5]} castShadow/>
<Character {wireframeProps} />
<T.Mesh rotation.x={-90 * (Math.PI / 180)} receiveShadow> <T.CircleGeometry args={[3, 72]} /> <T.MeshStandardMaterial color={'white'} />
<Outlines color="red" thickness={10} /></T.Mesh>
<InstancedMesh bind:ref={boxes} castShadow> <T.BoxGeometry args={[0.07, 0.07, 0.07]} /> <T.MeshStandardMaterial />
<Wireframe {...wireframeProps} /> {#each poses as { position, quaternion }, index} <Float seed={Math.random() * index}> <Instance {position} {quaternion} /> </Float> {/each}</InstancedMesh><Wireframe> uses barycentric coordinates to generate the wireframe, which requires a non-indexed geometry to create.
This means that any geometry with a <Wireframe> that has indices will be converted to a non-indexed version.
Basic Example
Section titled “Basic Example”<script> import { T } from '@threlte/core' import { Wireframe } from '@threlte/extras'</script>
<T.Mesh> <T.BoxGeometry /> <T.MeshStandardMaterial /> <Wireframe /></T.Mesh>