Skip to content

@typegpu/react

Setting up and managing TypeGPU resources in React components is not a trivial task, which is why we provide a set of hooks and utilities to help with it.

Refer to TypeGPU’s installation guide for setting up TypeGPU if you haven’t already. After that, install React and @typegpu/react using the package manager of your choice.

npm install @typegpu/react

We first get a reference to a TypeGPU root via the useRoot hook.

import {
function useRoot(): TgpuRoot

Returns the TypeGPU root shared between all components under the nearest provider. (equivalent to calling await tgpu.init()) It's not necessary to use a <Root> provider; if none is found, the global context is used.

If the root hasn't been initialized yet, it will suspend the component until it is. This hook will throw if there is an error initializing the root (like no WebGPU support). If you'd like to handle these cases yourself, you can use

useRootOrError

or

useRootWithStatus

instead.

useRoot
} from '@typegpu/react';
function
function MyEffect(): void
MyEffect
() {
const
const root: TgpuRoot
root
=
function useRoot(): TgpuRoot

Returns the TypeGPU root shared between all components under the nearest provider. (equivalent to calling await tgpu.init()) It's not necessary to use a <Root> provider; if none is found, the global context is used.

If the root hasn't been initialized yet, it will suspend the component until it is. This hook will throw if there is an error initializing the root (like no WebGPU support). If you'd like to handle these cases yourself, you can use

useRootOrError

or

useRootWithStatus

instead.

useRoot
();
// the rest of our code will be here
}

Then we create a Render Pipeline that emits a red color over the whole canvas, and we memoize it.

const
const renderPipeline: TgpuRenderPipeline<d.Vec4f>
renderPipeline
=
useMemo<TgpuRenderPipeline<d.Vec4f>>(factory: () => TgpuRenderPipeline<d.Vec4f>, deps: React.DependencyList): TgpuRenderPipeline<d.Vec4f>

useMemo will only recompute the memoized value when one of the deps has changed.

@version16.8.0

@seehttps://react.dev/reference/react/useMemo

useMemo
(
() =>
const root: TgpuRoot
root
.
WithBinding.createRenderPipeline<{}, {}, {
uv: d.Vec2f;
}, d.v4f>(descriptor: TgpuRenderPipeline<in Targets = never>.DescriptorBase & {
attribs?: {};
vertex: TgpuVertexFn<{}, {
uv: d.Vec2f;
}> | ((input: AutoVertexIn<InferGPURecord<AttribRecordToDefaultDataTypes<{}>>>) => AutoVertexOut<AnyAutoCustoms>);
fragment: TgpuFragmentFn<{
uv: d.Vec2f;
} & Record<string, AnyFragmentInputBuiltin>, TgpuFragmentFn<in Varying extends TgpuFragmentFn.In = Record<...>, out Output extends TgpuFragmentFn.Out = TgpuFragmentFn.Out>.Out> | ((input: AutoFragmentIn<...>) => d.v4f);
targets?: TgpuColorTargetState;
}): TgpuRenderPipeline<...> (+2 overloads)
createRenderPipeline
({
vertex: TgpuVertexFn<{}, {
uv: d.Vec2f;
}> | ((input: AutoVertexIn<InferGPURecord<AttribRecordToDefaultDataTypes<{}>>>) => AutoVertexOut<AnyAutoCustoms>)
vertex
:
import common
common
.
const fullScreenTriangle: TgpuVertexFn<{}, {
uv: d.Vec2f;
}>
export fullScreenTriangle

A vertex function that defines a single full-screen triangle out of three points.

@example

import { common } from 'typegpu';
const pipeline = root.createRenderPipeline({
vertex: common.fullScreenTriangle,
fragment: yourFragmentShader,
});
pipeline.draw(3);

fullScreenTriangle
,
fragment: TgpuFragmentFn<{
uv: d.Vec2f;
} & Record<string, AnyFragmentInputBuiltin>, TgpuFragmentFn.Out> | ((input: AutoFragmentIn<InferGPURecord<{
uv: d.Vec2f;
}>>) => d.v4f)
fragment
: () => {
'use gpu';
// r g b a
return
import d
d
.
function vec4f(x: number, y: number, z: number, w: number): d.v4f (+9 overloads)
export vec4f

Schema representing vec4f - a vector with 4 elements of type f32. Also a constructor function for this vector value.

@example const vector = d.vec4f(); // (0.0, 0.0, 0.0, 0.0) const vector = d.vec4f(1); // (1.0, 1.0, 1.0, 1.0) const vector = d.vec4f(1, 2, 3, 4.5); // (1.0, 2.0, 3.0, 4.5)

@example const buffer = root.createBuffer(d.vec4f, d.vec4f(0, 1, 2, 3)); // buffer holding a d.vec4f value, with an initial value of vec4f(0, 1, 2, 3);

vec4f
(1, 0, 0, 1);
},
}),
[
const root: TgpuRoot
root
],
);

We need to update our imports to get access to both d and common from typegpu:

import { d, common } from 'typegpu';

Then we call the useConfigureContext hook, which will give us a ref to pass into a <canvas> element, as well as access to the WebGPU context via ctxRef.

// ...
const { ref, ctxRef } = useConfigureContext();
return <canvas ref={ref} className="absolute inset-0" />;
}

We’ll draw to the canvas each frame using useFrame:

useFrame(() => {
if (!ctxRef.current) return;
renderPipeline
.withColorAttachment({ view: ctxRef.current })
.draw(3); // 3 vertices of the full-screen triangle
});

After these changes, you should see a blank red canvas on your webpage. Let’s make the effect more interesting.

Right now, each pixel is calculating exactly the same value, which is why we get a single color output. The fragment function received contextual information as an argument, and can use it to vary the output along the image.

const renderPipeline = useMemo(
() =>
root.createRenderPipeline({
vertex: common.fullScreenTriangle,
fragment: () => {
fragment: ({ uv }) => {
'use gpu';
// r g b a
return d.vec4f(1, 0, 0, 1);
return d.vec4f(uv, 0, 1);
},
}),
[root],
);

The uv value is a 2d vector provided by the vertex shader common.fullScreenTriangle, and ranges from 0 to 1 in both axes. Since it consists of x and y components, it can be placed inside the d.vec4f() constructor and fills up the red and green channels.

a red-green gradient

To pass dynamic values to your shader without having to recompile it (compilation takes significant time), you can use useUniform or useMirroredUniform, depending on the situation.

  • useUniform - allocates a uniform that can be updated outside of the React lifecycle.
  • useMirroredUniform - allocates a uniform and keeps it synchronized with the latest value.

We’re going to define a time variable to use in our shader. Since it’s a value that will get updated each frame, we want it to be done outside of the React lifecycle to not trigger deadly re-renders. Let’s choose useUniform:

const root = useRoot();
const time = useUniform(d.f32);
const renderPipeline = useMemo(
() =>
root.createRenderPipeline({
vertex: common.fullScreenTriangle,
fragment: ({ uv }) => {
'use gpu';
return d.vec4f(uv, 0, 1);
return d.vec4f((uv * 5 + time.$) % 1, 0, 1);
},
}),
[root, time],
);

We have just tiled the pattern with multiplication and modulo, but since we’re not updating time, it’s a still image.

a static gradient repeated 5 times

We can update time each frame to get the desired result:

useFrame(() => {
useFrame(({ elapsedSeconds }) => {
if (!ctxRef.current) return;
time.write(elapsedSeconds);
renderPipeline.withColorAttachment({ view: ctxRef.current }).draw(3);
});
import {
function useMemo<T>(factory: () => T, deps: React.DependencyList): T

useMemo will only recompute the memoized value when one of the deps has changed.

@version16.8.0

@seehttps://react.dev/reference/react/useMemo

useMemo
} from 'react';
import {
import d
d
,
import common
common
} from 'typegpu';
import {
const useConfigureContext: (options?: UseConfigureContextOptions) => UseConfigureContextResult
useConfigureContext
,
function useFrame(cb: (ctx: FrameCtx) => void): void
useFrame
,
function useRoot(): TgpuRoot

Returns the TypeGPU root shared between all components under the nearest provider. (equivalent to calling await tgpu.init()) It's not necessary to use a <Root> provider; if none is found, the global context is used.

If the root hasn't been initialized yet, it will suspend the component until it is. This hook will throw if there is an error initializing the root (like no WebGPU support). If you'd like to handle these cases yourself, you can use

useRootOrError

or

useRootWithStatus

instead.

useRoot
,
function useUniform<TSchema extends d.AnyWgslData>(_schema: ValidateUniformSchema<TSchema>, options?: UseUniformOptions<TSchema>): TgpuUniform<TSchema>
useUniform
} from '@typegpu/react';
function
function MyEffect(): React.JSX.Element
MyEffect
() {
const
const root: TgpuRoot
root
=
function useRoot(): TgpuRoot

Returns the TypeGPU root shared between all components under the nearest provider. (equivalent to calling await tgpu.init()) It's not necessary to use a <Root> provider; if none is found, the global context is used.

If the root hasn't been initialized yet, it will suspend the component until it is. This hook will throw if there is an error initializing the root (like no WebGPU support). If you'd like to handle these cases yourself, you can use

useRootOrError

or

useRootWithStatus

instead.

useRoot
();
const
const time: TgpuUniform<d.F32>
time
=
useUniform<d.F32>(_schema: d.F32, options?: UseUniformOptions<d.F32> | undefined): TgpuUniform<d.F32>
useUniform
(
import d
d
.
const f32: d.F32
export f32

A schema that represents a 32-bit float value. (equivalent to f32 in WGSL)

Can also be called to cast a value to an f32.

@example const value = f32(); // 0

@example const value = f32(1.23); // 1.23

@example const value = f32(true); // 1

f32
);
const
const renderPipeline: TgpuRenderPipeline<d.Vec4f>
renderPipeline
=
useMemo<TgpuRenderPipeline<d.Vec4f>>(factory: () => TgpuRenderPipeline<d.Vec4f>, deps: React.DependencyList): TgpuRenderPipeline<d.Vec4f>

useMemo will only recompute the memoized value when one of the deps has changed.

@version16.8.0

@seehttps://react.dev/reference/react/useMemo

useMemo
(
() =>
const root: TgpuRoot
root
.
WithBinding.createRenderPipeline<{}, {}, {
uv: d.Vec2f;
}, d.v4f>(descriptor: TgpuRenderPipeline<in Targets = never>.DescriptorBase & {
attribs?: {};
vertex: TgpuVertexFn<{}, {
uv: d.Vec2f;
}> | ((input: AutoVertexIn<InferGPURecord<AttribRecordToDefaultDataTypes<{}>>>) => AutoVertexOut<AnyAutoCustoms>);
fragment: TgpuFragmentFn<{
uv: d.Vec2f;
} & Record<string, AnyFragmentInputBuiltin>, TgpuFragmentFn<in Varying extends TgpuFragmentFn.In = Record<...>, out Output extends TgpuFragmentFn.Out = TgpuFragmentFn.Out>.Out> | ((input: AutoFragmentIn<...>) => d.v4f);
targets?: TgpuColorTargetState;
}): TgpuRenderPipeline<...> (+2 overloads)
createRenderPipeline
({
vertex: TgpuVertexFn<{}, {
uv: d.Vec2f;
}> | ((input: AutoVertexIn<InferGPURecord<AttribRecordToDefaultDataTypes<{}>>>) => AutoVertexOut<AnyAutoCustoms>)
vertex
:
import common
common
.
const fullScreenTriangle: TgpuVertexFn<{}, {
uv: d.Vec2f;
}>
export fullScreenTriangle

A vertex function that defines a single full-screen triangle out of three points.

@example

import { common } from 'typegpu';
const pipeline = root.createRenderPipeline({
vertex: common.fullScreenTriangle,
fragment: yourFragmentShader,
});
pipeline.draw(3);

fullScreenTriangle
,
fragment: TgpuFragmentFn<{
uv: d.Vec2f;
} & Record<string, AnyFragmentInputBuiltin>, TgpuFragmentFn.Out> | ((input: AutoFragmentIn<InferGPURecord<{
uv: d.Vec2f;
}>>) => d.v4f)
fragment
: ({
uv: d.v2f
uv
}) => {
'use gpu';
return
import d
d
.
function vec4f(v0: AnyNumericVec2Instance, z: number, w: number): d.v4f (+9 overloads)
export vec4f

Schema representing vec4f - a vector with 4 elements of type f32. Also a constructor function for this vector value.

@example const vector = d.vec4f(); // (0.0, 0.0, 0.0, 0.0) const vector = d.vec4f(1); // (1.0, 1.0, 1.0, 1.0) const vector = d.vec4f(1, 2, 3, 4.5); // (1.0, 2.0, 3.0, 4.5)

@example const buffer = root.createBuffer(d.vec4f, d.vec4f(0, 1, 2, 3)); // buffer holding a d.vec4f value, with an initial value of vec4f(0, 1, 2, 3);

vec4f
((
uv: d.v2f
uv
* 5 +
const time: TgpuUniform<d.F32>
time
.
TgpuUniform<F32>.$: number
$
) % 1, 0, 1);
},
}),
[
const root: TgpuRoot
root
,
const time: TgpuUniform<d.F32>
time
],
);
const {
const ref: (instance: CanvasRef | null) => void | (() => VoidOrUndefinedOnly) | React.DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES[keyof React.DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES]
ref
,
const ctxRef: React.RefObject<CanvasContext | null>
ctxRef
} =
function useConfigureContext(options?: UseConfigureContextOptions): UseConfigureContextResult
useConfigureContext
();
function useFrame(cb: (ctx: FrameCtx) => void): void
useFrame
(({
elapsedSeconds: number

Time elapsed since the mounting of this hook

elapsedSeconds
}) => {
if (!
const ctxRef: React.RefObject<CanvasContext | null>
ctxRef
.
RefObject<CanvasContext | null>.current: CanvasContext | null

The current value of the ref.

current
) return;
const time: TgpuUniform<d.F32>
time
.
TgpuBufferShorthandBase<F32>.write(data: number, options?: BufferWriteOptions): void
write
(
elapsedSeconds: number

Time elapsed since the mounting of this hook

elapsedSeconds
);
const renderPipeline: TgpuRenderPipeline<d.Vec4f>
renderPipeline
.
TgpuRenderPipeline<Vec4f>.withColorAttachment(attachment: ColorAttachment): TgpuRenderPipeline<d.Vec4f>

Attaches texture views to the pipeline's targets (outputs).

@example // Draw 3 vertices onto the context's canvas pipeline .withColorAttachment({ view: context }) .draw(3)

@paramattachment The object should match the shape returned by the fragment shader, with values matching the ColorAttachment type.

withColorAttachment
({
ColorAttachment.view: GPUCanvasContext | (ColorTextureConstraint & RenderFlag) | GPUTextureView | TgpuTextureView<d.WgslTexture<WgslTextureProps>> | TgpuTextureRenderView

A

GPUTextureView

describing the texture subresource that will be output to for this color attachment.

view
:
const ctxRef: React.RefObject<CanvasContext | null>
ctxRef
.
RefObject<CanvasContext | null>.current: CanvasContext

The current value of the ref.

current
}).
TgpuRenderPipeline<Vec4f>.draw(vertexCount: number, instanceCount?: number, firstVertex?: number, firstInstance?: number): void
draw
(3);
});
return <
JSX.IntrinsicElements.canvas: React.DetailedHTMLProps<React.CanvasHTMLAttributes<HTMLCanvasElement>, HTMLCanvasElement>
canvas
RefAttributes<HTMLCanvasElement>.ref?: React.Ref<HTMLCanvasElement> | undefined

Allows getting a ref to the component instance. Once the component unmounts, React will set ref.current to null (or call the ref with null if you passed a callback ref).

ref
={
const ref: (instance: CanvasRef | null) => void | (() => VoidOrUndefinedOnly) | React.DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES[keyof React.DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES]
ref
}
HTMLAttributes<HTMLCanvasElement>.className?: string | undefined
className
="absolute inset-0" />;
}

Returns the TypeGPU root shared between all components under the nearest <Root> provider. (equivalent to calling await tgpu.init()).

It’s not necessary to use a <Root> provider; if none is found, the global root is used instead.

import {
function useRoot(): TgpuRoot

Returns the TypeGPU root shared between all components under the nearest provider. (equivalent to calling await tgpu.init()) It's not necessary to use a <Root> provider; if none is found, the global context is used.

If the root hasn't been initialized yet, it will suspend the component until it is. This hook will throw if there is an error initializing the root (like no WebGPU support). If you'd like to handle these cases yourself, you can use

useRootOrError

or

useRootWithStatus

instead.

useRoot
} from '@typegpu/react';
function
function MyEffect(): void
MyEffect
() {
const
const root: TgpuRoot
root
=
function useRoot(): TgpuRoot

Returns the TypeGPU root shared between all components under the nearest provider. (equivalent to calling await tgpu.init()) It's not necessary to use a <Root> provider; if none is found, the global context is used.

If the root hasn't been initialized yet, it will suspend the component until it is. This hook will throw if there is an error initializing the root (like no WebGPU support). If you'd like to handle these cases yourself, you can use

useRootOrError

or

useRootWithStatus

instead.

useRoot
();
// ...
}

If the root hasn’t been initialized yet, it will suspend the component until it is. This hook will also throw if there is an error initializing the root (like no WebGPU support). If you’d like to handle these cases yourself, you can use useRootOrError or useRootWithStatus instead.

const foo = useUniform(schema, { /* options */ });
OptionDescription
initialAn initial value given to the uniform buffer on component mount. Alternatively, a function can be passed in to imperatively write to the buffer while its still mapped to CPU memory.
onInitA function that will be called after the buffer is initialized. An example of where this is useful is populating the buffer with a compute shader.
// creating a resource to be updated outside of the React lifecycle
const
const time: TgpuUniform<d.F32>
time
=
useUniform<d.F32>(_schema: d.F32, options?: UseUniformOptions<d.F32> | undefined): TgpuUniform<d.F32>
useUniform
(
import d
d
.
const f32: d.F32
export f32

A schema that represents a 32-bit float value. (equivalent to f32 in WGSL)

Can also be called to cast a value to an f32.

@example const value = f32(); // 0

@example const value = f32(1.23); // 1.23

@example const value = f32(true); // 1

f32
);
const
const updateTime: (value: number) => void
updateTime
=
useCallback<(value: number) => void>(callback: (value: number) => void, deps: React.DependencyList): (value: number) => void

useCallback will return a memoized version of the callback that only changes if one of the inputs has changed.

useCallback
((
value: number
value
: number) => {
const time: TgpuUniform<d.F32>
time
.
TgpuBufferShorthandBase<F32>.write(data: number, options?: BufferWriteOptions): void
write
(
value: number
value
);
}, [
const time: TgpuUniform<d.F32>
time
]);
const foo = useMutable(schema, { /* options */ });
OptionDescription
initialAn initial value given to the mutable buffer on component mount. Alternatively, a function can be passed in to imperatively write to the buffer while its still mapped to CPU memory.
onInitA function that will be called after the buffer is initialized. An example of where this is useful is populating the buffer with a compute shader.
// creating a mutable resource to be updated outside of the React lifecycle
const
const counter: TgpuMutable<d.F32>
counter
=
useMutable<d.F32>(_schema: d.F32, options?: UseMutableOptions<d.F32> | undefined): TgpuMutable<d.F32>
useMutable
(
import d
d
.
const f32: d.F32
export f32

A schema that represents a 32-bit float value. (equivalent to f32 in WGSL)

Can also be called to cast a value to an f32.

@example const value = f32(); // 0

@example const value = f32(1.23); // 1.23

@example const value = f32(true); // 1

f32
);
// a compute shader that increments the counter in-place
const
const incrementPipeline: TgpuGuardedComputePipeline<[]>
incrementPipeline
=
useMemo<TgpuGuardedComputePipeline<[]>>(factory: () => TgpuGuardedComputePipeline<[]>, deps: React.DependencyList): TgpuGuardedComputePipeline<[]>

useMemo will only recompute the memoized value when one of the deps has changed.

@version16.8.0

@seehttps://react.dev/reference/react/useMemo

useMemo
(() => {
return
const root: TgpuRoot
root
.
WithBinding.createGuardedComputePipeline<[]>(callback: () => void): TgpuGuardedComputePipeline<[]>

Creates a compute pipeline that executes the given callback in an exact number of threads. This is different from createComputePipeline() in that it does a bounds check on the thread id, where as regular pipelines do not and work in units of workgroups.

@paramcallback A function converted to WGSL and executed on the GPU. It can accept up to 3 parameters (x, y, z) which correspond to the global invocation ID of the executing thread.

@example

If no parameters are provided, the callback will be executed once, in a single thread.

const fooPipeline = root
.createGuardedComputePipeline(() => {
'use gpu';
console.log('Hello, GPU!');
});
fooPipeline.dispatchThreads();
// [GPU] Hello, GPU!

@example

One parameter means n-threads will be executed in parallel.

const fooPipeline = root
.createGuardedComputePipeline((x) => {
'use gpu';
if (x % 16 === 0) {
// Logging every 16th thread
console.log('I am the', x, 'thread');
}
});
// executing 512 threads
fooPipeline.dispatchThreads(512);
// [GPU] I am the 256 thread
// [GPU] I am the 272 thread
// ... (30 hidden logs)
// [GPU] I am the 16 thread
// [GPU] I am the 240 thread

createGuardedComputePipeline
(() => {
'use gpu';
// Direct memory access through .$
const counter: TgpuMutable<d.F32>
counter
.
TgpuMutable<F32>.$: number
$
+= 1;
});
}, [
const root: TgpuRoot
root
,
const counter: TgpuMutable<d.F32>
counter
]);
// a function that dispatches the shader and reads the result asynchronously
const
const increment: (value: number) => Promise<number>
increment
=
useEffectEvent<(value: number) => Promise<number>>(callback: (value: number) => Promise<number>): (value: number) => Promise<number>

@seehttps://react.dev/reference/react/useEffectEvent useEffectEvent() documentation

@version19.2.0

useEffectEvent
(async (
value: number
value
: number) => {
const incrementPipeline: TgpuGuardedComputePipeline<[]>
incrementPipeline
.
TgpuGuardedComputePipeline<[]>.dispatchThreads(): void

Dispatches the pipeline. Unlike TgpuComputePipeline.dispatchWorkgroups(), this method takes in the number of threads to run in each dimension.

Under the hood, the number of expected threads is sent as a uniform, and "guarded" by a bounds check.

dispatchThreads
();
return await
const counter: TgpuMutable<d.F32>
counter
.
TgpuBufferShorthandBase<F32>.read(): Promise<number>
read
();
});
const foo = useReadonly(schema, { /* options */ });
OptionDescription
initialAn initial value given to the readonly buffer on component mount. Alternatively, a function can be passed in to imperatively write to the buffer while its still mapped to CPU memory.
onInitA function that will be called after the buffer is initialized. An example of where this is useful is populating the buffer with a compute shader.
const foo = useMirroredUniform(schema, valueToMirror);

On each React re-render, the uniform will be updated with the latest value of valueToMirror.

// a value accessible in the React lifecycle
const
const theme: {
primaryColor: [number, number, number];
}
theme
=
const useTheme: () => {
primaryColor: [number, number, number];
}
useTheme
();
// making it accessible in a shader
const
const primaryColor: MirroredValue<d.Vec3f>
primaryColor
=
useMirroredUniform<d.Vec3f, d.v3f>(_schema: d.Vec3f, value: d.v3f): MirroredValue<d.Vec3f>
useMirroredUniform
(
import d
d
.
const vec3f: d.Vec3f
export vec3f

Schema representing vec3f - a vector with 3 elements of type f32. Also a constructor function for this vector value.

@example const vector = d.vec3f(); // (0.0, 0.0, 0.0) const vector = d.vec3f(1); // (1.0, 1.0, 1.0) const vector = d.vec3f(1, 2, 3.5); // (1.0, 2.0, 3.5)

@example const buffer = root.createBuffer(d.vec3f, d.vec3f(0, 1, 2)); // buffer holding a d.vec3f value, with an initial value of vec3f(0, 1, 2);

vec3f
,
import d
d
.
function vec3f(x: number, y: number, z: number): d.v3f (+5 overloads)
export vec3f

Schema representing vec3f - a vector with 3 elements of type f32. Also a constructor function for this vector value.

@example const vector = d.vec3f(); // (0.0, 0.0, 0.0) const vector = d.vec3f(1); // (1.0, 1.0, 1.0) const vector = d.vec3f(1, 2, 3.5); // (1.0, 2.0, 3.5)

@example const buffer = root.createBuffer(d.vec3f, d.vec3f(0, 1, 2)); // buffer holding a d.vec3f value, with an initial value of vec3f(0, 1, 2);

vec3f
(...
const theme: {
primaryColor: [number, number, number];
}
theme
.
primaryColor: [number, number, number]
primaryColor
));
// ...
const group = useBindGroup(layout, { /* entries */ });

Creates a bind group out of the given resources. The API matches root.createBindGroup.

The <Root> component is a context provider for all of its descendants. All useRoot calls made by components beneath this wrapper will return the same TgpuRoot object.

PropertyTypeDescription
rootTgpuRoot|undefinedA custom root to provide for all descendants. If not provided, one will be created on demand.
import {
const Root: ({ children, root }: RootProps) => React.JSX.Element
Root
} from '@typegpu/react';
function
function App(): React.JSX.Element
App
() {
return (
<
const Root: ({ children, root }: RootProps) => React.JSX.Element
Root
>
{/* ... other components ... */}
</
const Root: ({ children, root }: RootProps) => React.JSX.Element
Root
>
);
}