@threlte/core
useRender
This hook allows you to execute code on every invalidated frame and after all useFrame
hooks have been executed.
You receive the state (the same as useThrelte
) and a clock delta in seconds.
Typically this hook is used to implement advanced rendering techniques such as post processing or custom render passes.
As soon as this hook is used anywhere in the component tree, the default render loop is disabled. You need to take care of rendering yourself.
You may pass additional options to this hook. The property order
is useful if you need to order the sequence of useRender
callbacks across the component tree where callbacks are ordered from low to high.
type ThrelteUseRenderOptions = {
order?: number
}
Basic Rendering
<script>
import { useRender } from '@threlte/core'
useRender(({ camera, renderer, scene }, delta) => {
renderer.render(scene, camera.current)
})
</script>
The state available in the callback is the same as the one available with useThrelte
.
Some properties (such as the property camera
) use a CurrentWritable
store. which is a custom
Threlte store. It’s a regular writable store that also has a current
property which is the
current value of the store. It’s useful for accessing the value of a store in a non-reactive
context, such as in loops.
Post Processing
This example demonstrates how to use useRender
to implement post processing effects using the library postprocessing
.
When using SvelteKit (or more broadly, SSR) be sure to add ssr: { noExternal: [ 'postprocessing' ] }
to your vite.config.js
.
<script>
import { useThrelte, useRender } from '@threlte/core'
import {
EffectComposer,
EffectPass,
RenderPass,
SMAAEffect,
SMAAPreset,
BloomEffect,
KernelSize
} from 'postprocessing'
const { scene, renderer, camera, size } = useThrelte()
// To use the EffectComposer we need to pass arguments to the
// default WebGLRenderer: https://github.com/pmndrs/postprocessing#usage
const composer = new EffectComposer(renderer)
const setupEffectComposer = (camera) => {
composer.removeAllPasses()
composer.addPass(new RenderPass(scene, camera))
composer.addPass(
new EffectPass(
camera,
new BloomEffect({
intensity: 1,
luminanceThreshold: 0.15,
height: 512,
width: 512,
luminanceSmoothing: 0.08,
mipmapBlur: true,
kernelSize: KernelSize.MEDIUM
})
)
)
composer.addPass(
new EffectPass(
camera,
new SMAAEffect({
preset: SMAAPreset.LOW
})
)
)
}
// We need to set up the passes according to the camera in use
$: setupEffectComposer($camera)
$: composer.setSize($size.width, $size.height)
useRender((_, delta) => {
composer.render(delta)
})
</script>