@threlte/extras
<MeshRefractionMaterial>
To use this component you need to install the seperate 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 { Group } from 'three'
import {
T,
type Props,
type Events,
type Slots,
forwardEventHandlers,
useLoader
} from '@threlte/core'
import { useGltf, MeshRefractionMaterial } from '@threlte/extras'
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js'
type $$Props = Props<THREE.Group>
type $$Events = Events<THREE.Group>
type $$Slots = Slots<THREE.Group> & { fallback: {}; error: { error: any } }
export const ref = new Group()
type GLTFResult = {
nodes: {
Diamond_1_0: THREE.Mesh
}
materials: {}
}
const gltf = useGltf<GLTFResult>('/models/diamond/dflat.glb', { useDraco: true })
const env = useLoader(RGBELoader).load('/hdr/aerodynamics_workshop_1k.hdr')
const component = forwardEventHandlers()
</script>
<T
is={ref}
dispose={false}
{...$$restProps}
bind:this={$component}
>
{#await gltf}
<slot name="fallback" />
{:then gltf}
<T.Mesh
castShadow
receiveShadow
geometry={gltf.nodes.Diamond_1_0.geometry}
>
{#await env then e}
<MeshRefractionMaterial
envMap={e}
fresnel={0.5}
ior={2.75}
aberrationStrength={0.04}
bounces={3}
color={'#ffdddd'}
/>
{/await}
</T.Mesh>
{:catch error}
<slot
name="error"
{error}
/>
{/await}
<slot {ref} />
</T>
<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}
on:create={({ ref }) => {
ref.lookAt(0, 0, 0)
}}
>
<OrbitControls
enableDamping
autoRotate
enablePan={false}
enableZoom={false}
/>
</T.PerspectiveCamera>
<Grid
cellColor={'#46536b'}
sectionThickness={0}
infiniteGrid
cellSize={5}
/>
Examples
Basic Example
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>
Component Signature
<MeshRefractionMaterial>
extends
<T.ShaderMaterial>
and supports all its props, slot props, bindings and events.