diff --git a/apps/typegpu-docs/src/content/examples/react/triangle/index.html b/apps/typegpu-docs/src/content/examples/react/triangle/index.html index 2efc24ac5..974ed97c0 100644 --- a/apps/typegpu-docs/src/content/examples/react/triangle/index.html +++ b/apps/typegpu-docs/src/content/examples/react/triangle/index.html @@ -1 +1 @@ -
+
diff --git a/apps/typegpu-docs/src/content/examples/react/triangle/index.tsx b/apps/typegpu-docs/src/content/examples/react/triangle/index.tsx index ab1a8c6e8..8401cea97 100644 --- a/apps/typegpu-docs/src/content/examples/react/triangle/index.tsx +++ b/apps/typegpu-docs/src/content/examples/react/triangle/index.tsx @@ -1,17 +1,23 @@ -import { vec4f } from 'typegpu/data'; -import { useRender } from '@typegpu/react'; +import * as d from 'typegpu/data'; +import { useFrame, useRender, useUniformValue } from '@typegpu/react'; +import { hsvToRgb } from '@typegpu/color'; function App() { + const time = useUniformValue(d.f32, 0); + + useFrame(() => { + time.value = performance.now() / 1000; + }); + const { ref } = useRender({ - fragment: ({ uv }) => { + fragment: () => { 'kernel'; - return vec4f(uv.x, uv.y, 1, 1); + const t = time.$; + const rgb = hsvToRgb(d.vec3f(t * 0.5, 1, 1)); + return d.vec4f(rgb, 1); }, }); - // TODO: Provide a time variable to the shader with useUniformValue - // TODO: Make the gradient shift colors over time using hsvToRgb from @typegpu/color - return (
@@ -28,7 +34,7 @@ const reactRoot = createRoot( reactRoot.render(); export function onCleanup() { - reactRoot.unmount(); + setTimeout(() => reactRoot.unmount(), 0); } // #endregion diff --git a/apps/typegpu-docs/vitest.config.mts b/apps/typegpu-docs/vitest.config.mts index f8fe6776e..bd7dc9541 100644 --- a/apps/typegpu-docs/vitest.config.mts +++ b/apps/typegpu-docs/vitest.config.mts @@ -1,5 +1,5 @@ import { createJiti } from 'jiti'; -import { defineConfig } from 'vitest/config'; +import { defineConfig, type Plugin } from 'vitest/config'; import { imagetools } from 'vite-imagetools'; import type TypeGPUPlugin from 'unplugin-typegpu/vite'; @@ -13,7 +13,7 @@ export default defineConfig({ plugins: [ typegpu({ include: [/\.m?[jt]sx?/] }), /** @type {any} */ imagetools(), - ], + ] as Plugin[], server: { proxy: { '/TypeGPU': { diff --git a/packages/typegpu-react/src/use-uniform-value.ts b/packages/typegpu-react/src/use-uniform-value.ts index 6d4c4bcc7..752d86690 100644 --- a/packages/typegpu-react/src/use-uniform-value.ts +++ b/packages/typegpu-react/src/use-uniform-value.ts @@ -1,13 +1,62 @@ import type * as d from 'typegpu/data'; +import { useRoot } from './root-context.tsx'; +import { useEffect, useMemo, useRef, useState } from 'react'; +import type { ValidateUniformSchema } from 'typegpu'; interface UniformValue> { schema: TSchema; - value: TValue; + value: TValue | undefined; + readonly $: d.InferGPU; } -export function useUniformValue>( - schema: d.AnyWgslData, +export function useUniformValue< + TSchema extends d.AnyWgslData, + TValue extends d.Infer, +>( + schema: ValidateUniformSchema, initialValue?: TValue | undefined, ): UniformValue { - // TODO: Implement + const root = useRoot(); + + const [uniformBuffer] = useState(() => { + return root.createUniform( + schema, + initialValue, + ); + }); + + const cleanupRef = useRef | null>(null); + useEffect(() => { + if (cleanupRef.current) { + clearTimeout(cleanupRef.current); + } + + return () => { + cleanupRef.current = setTimeout(() => { + uniformBuffer.buffer.destroy(); + }, 200); + }; + }, [uniformBuffer]); + + // biome-ignore lint/correctness/useExhaustiveDependencies: This value needs to be stable + const uniformValue = useMemo(() => { + let currentValue = initialValue; + return { + schema, + get value() { + return currentValue; + }, + set value(newValue: TValue | undefined) { + currentValue = newValue; + if (newValue !== undefined) { + uniformBuffer.write(newValue); + } + }, + get $() { + return uniformBuffer.$; + }, + }; + }, []); + + return uniformValue as UniformValue; } diff --git a/packages/typegpu/src/index.ts b/packages/typegpu/src/index.ts index e45cdb6b9..c1f3770c1 100644 --- a/packages/typegpu/src/index.ts +++ b/packages/typegpu/src/index.ts @@ -94,6 +94,8 @@ export type { Configurable, TgpuRoot, ValidateBufferSchema, + ValidateStorageSchema, + ValidateUniformSchema, WithBinding, WithCompute, WithFragment,