threlte logo
@threlte/extras

<Outlines>

A port of the drei <Outlines> component.

An ornamental component that extracts the geometry from its parent and displays an inverted-hull outline. Supported parents are Mesh, SkinnedMesh and InstancedMesh.

<script lang="ts">
  import { Canvas } from '@threlte/core'
  import Scene from './Scene.svelte'
</script>

<div>
  <Canvas>
    <Scene />
  </Canvas>
</div>

<style>
  div {
    height: 100%;
  }
</style>
<script lang="ts">
  import { T, useTask } from '@threlte/core'
  import { Edges, Outlines, useDraco, useGltf } from '@threlte/extras'
  import { BufferGeometry, Mesh, MeshStandardMaterial } from 'three'
  import { MathUtils } from 'three'

  let rotation = 0
  useTask((delta) => {
    rotation += delta
  })

  const helmetGltf = useGltf<{
    nodes: {
      'node_damagedHelmet_-6514': Mesh
    }
    materials: {
      Material_MR: MeshStandardMaterial
    }
  }>('/models/helmet/DamagedHelmet.gltf')

  let helmetGeometry: BufferGeometry | undefined
  $: if ($helmetGltf) {
    const mesh = $helmetGltf.nodes['node_damagedHelmet_-6514'] as Mesh
    helmetGeometry = mesh.geometry
  }

  const dracoLoader = useDraco()
  const suziGltf = useGltf<{
    nodes: {
      Suzanne: Mesh
    }
    materials: {
      Material_MR: MeshStandardMaterial
    }
  }>(
    'https://vazxmixjsiawhamofees.supabase.co/storage/v1/object/public/models/suzanne-high-poly/model.gltf',
    { dracoLoader }
  )
</script>

<T.PerspectiveCamera
  makeDefault
  position.z={30}
  fov={20}
/>

<T.DirectionalLight position={[5, 5, 5]} />

<T.Group
  rotation.y={rotation}
  position.x={-3}
>
  <T.Mesh>
    <T.TorusKnotGeometry args={[0.5, 0.15, 128, 64]} />
    <T.MeshToonMaterial color="#ff3e00" />
    <Outlines color="white" />
    <Outlines
      color="hotpink"
      thickness={0.05}
    />
    <Outlines
      color="yellow"
      thickness={0.1}
    />
  </T.Mesh>
</T.Group>

<T.Group rotation.y={rotation}>
  {#if helmetGeometry}
    <T.Mesh
      rotation.x={90 * MathUtils.DEG2RAD}
      geometry={helmetGeometry}
    >
      <T.MeshBasicMaterial
        color="#ff3e00"
        toneMapped={false}
      />
      <Edges
        thresholdAngle={20}
        color="white"
        scale={1.01}
      />
      <Outlines
        color="white"
        thickness={0.02}
      />
    </T.Mesh>
  {/if}
</T.Group>

{#if $suziGltf}
  <T.Group
    rotation.y={rotation}
    position.x={3}
    position.y={-1}
  >
    <T.Mesh
      geometry={$suziGltf.nodes['Suzanne'].geometry}
      scale={1.2}
    >
      <T.MeshStandardMaterial color="turquoise" />
      <Outlines
        color="white"
        screenspace
        thickness={2}
        angle={0.001}
      />
    </T.Mesh>
  </T.Group>
{/if}

Model: Battle Damaged Sci-fi Helmet by theblueturtle_

Example

<script lang="ts">
  import { BoxBufferGeometry, MeshBasicMaterial } from 'three'
  import { T } from '@threlte/core'
  import { Outlines } from '@threlte/extras'
</script>

<T.Mesh
  geometry={new BoxBufferGeometry(1, 1, 1)}
  material={new MeshBasicMaterial()}
>
  <Outlines color="black" />
</T.Mesh>

Component Signature

Props

name
type
required
default
description

angle
number
no
Math.PI

color
THREE.ColorRepresentation
no
black
Outline color

opacity
boolean
no
1
Outline transparency

polygonOffset
boolean
no
false

polygonOffsetFactor
number
no
0

renderOrder
number
no
0

screenspace
boolean
no
false
Line thickness is independent of zoom

thickness
number
no
0.05
Outline thickness

toneMapped
boolean
no
true