Skip to content

<MeshRefractionMaterial>

To use this component you need to install the separate library three-mesh-bvh, please run npm install three-mesh-bvh before adding this component to your project.

This material may not work reliably on some devices or browsers. We’re investigating possible fixes.

This component is a port of drei’s <MeshRefractionMaterial> component, a convincing Glass/Diamond refraction material.

<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 { Mesh } from 'three'
import { T, useLoader } from '@threlte/core'
import { useGltf, MeshRefractionMaterial, useDraco } from '@threlte/extras'
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js'
let { ...props } = $props()
type GLTFResult = {
nodes: {
Diamond_1_0: Mesh
}
materials: {}
}
const dracoLoader = useDraco()
const gltf = useGltf<GLTFResult>('/models/diamond/dflat.glb', { dracoLoader })
const env = useLoader(RGBELoader).load(
'/textures/equirectangular/hdr/aerodynamics_workshop_1k.hdr'
)
</script>
{#await gltf then { nodes }}
<T.Mesh
castShadow
receiveShadow
geometry={nodes.Diamond_1_0.geometry}
{...props}
>
{#await env then e}
<MeshRefractionMaterial
envMap={e}
fresnel={0.5}
ior={2.75}
aberrationStrength={0.04}
bounces={3}
color={'#ffdddd'}
/>
{/await}
</T.Mesh>
{/await}
<script lang="ts">
import { T } from '@threlte/core'
import { OrbitControls, Grid, Float } from '@threlte/extras'
import Diamond from './Diamond.svelte'
</script>
<Float
floatIntensity={5}
rotationIntensity={1}
rotationSpeed={[0, 0, 0]}
>
<Diamond
scale={3}
position.y={2}
/>
</Float>
<T.PerspectiveCamera
makeDefault
position.y={7}
position.z={-8}
fov={90}
>
<OrbitControls
enableDamping
autoRotate
enablePan={false}
enableZoom={false}
/>
</T.PerspectiveCamera>
<Grid
cellColor={'#46536b'}
sectionThickness={0}
infiniteGrid
cellSize={5}
/>

You can either pass in a texture to use as the environment:

RefractionWithTexture.svelte
<script lang="ts">
import { T, useLoader } from '@threlte/core'
import { MeshRefractionMaterial } from '@threlte/extras'
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js'
const env = useLoader(RGBELoader).load('/hdr/aerodynamics_workshop_1k.hdr')
</script>
{#await env then texture}
<T.Mesh>
<MeshRefractionMaterial envMap={texture} />
<T.IcosahedronGeometry args={[4, 0]} />
</T.Mesh>
{/await}

or you can use a cube camera to generate the environment:

RefractionWithCubeCamera.svelte
<script lang="ts">
import { T, useThrelte, useTask } from '@threlte/core'
import { MeshRefractionMaterial } from '@threlte/extras'
import { WebGLCubeRenderTarget, CubeCamera } from 'three'
let renderTarget: WebGLCubeRenderTarget = new WebGLCubeRenderTarget(128)
let cubeCamera: CubeCamera = new CubeCamera(0.1, 100, renderTarget)
const { scene, renderer } = useThrelte()
useTask(() => {
if (cubeCamera) {
cubeCamera.update(renderer, scene)
}
})
</script>
<T.Mesh>
<MeshRefractionMaterial envMap={renderTarget.texture} />
<T.IcosahedronGeometry args={[4, 0]} />
</T.Mesh>

<MeshRefractionMaterial> extends < T . ShaderMaterial > and supports all its props, snippets, bindings and events.

Props

name
type
required
default
description

envMap
CubeTexture | Texture
yes

aberrationStrength
number
no
0.0
RGB shift intensity, can be expensive

bounces
number
no
2
Number of ray-cast bounces, it can be expensive to have too many

color
ColorRepresentation
no
white

fastChrome
boolean
no
true
If this is on it uses fewer ray casts for the RGB shift sacrificing physical accuracy

fresnel
number
no
0.0
Fresnel (strip light)

ior
number
no
2.4
Refraction index