Skip to content
Snippets Groups Projects
useInstancedVertex.ts 1.62 KiB
Newer Older
Steven Wittens's avatar
Steven Wittens committed
import type { Lazy } from '@use-gpu/core';
Steven Wittens's avatar
Steven Wittens committed
import type { ShaderModule, ShaderSource } from '@use-gpu/shader';
Steven Wittens's avatar
Steven Wittens committed
import { resolve } from '@use-gpu/core';
Steven Wittens's avatar
Steven Wittens committed
import { useMemo, useNoMemo } from '@use-gpu/live';
Steven Wittens's avatar
Steven Wittens committed
import { useShaderRef, useNoShaderRef } from '../hooks/useShaderRef';
Steven Wittens's avatar
Steven Wittens committed
import { getShader } from '../hooks/useShader';
Steven Wittens's avatar
Steven Wittens committed

Steven Wittens's avatar
Steven Wittens committed
import { getInstanceRepeatIndex } from '@use-gpu/wgsl/instance/index/repeat.wgsl';
Steven Wittens's avatar
Steven Wittens committed
import { getInstancedVertex } from '@use-gpu/wgsl/instance/vertex/instanced.wgsl';

const INSTANCES = {HAS_INSTANCES: true};
const NO_INSTANCES = {HAS_INSTANCES: false};

/** Instanced draw, repeated) or random access */
export const useInstancedVertex = (
Steven Wittens's avatar
15  
Steven Wittens committed
  getVertex: ShaderModule,
Steven Wittens's avatar
Steven Wittens committed
  instance?: Lazy<number>,
  instances?: ShaderSource,
  elementCount?: Lazy<number>,
Steven Wittens's avatar
Steven Wittens committed
  mapIndex?: ShaderSource,
Steven Wittens's avatar
Steven Wittens committed
): [ShaderModule, Lazy<number>, Record<string, boolean>] => {
Steven Wittens's avatar
Steven Wittens committed

  if (!(instance != null || instances)) {
    useNoInstancedVertex();
Steven Wittens's avatar
9  
Steven Wittens committed
    return [getVertex, elementCount || 0, NO_INSTANCES];
Steven Wittens's avatar
Steven Wittens committed
  }

Steven Wittens's avatar
Steven Wittens committed
  const instanceSize = instance == null ? useNoShaderRef() : useShaderRef(elementCount);
Steven Wittens's avatar
Steven Wittens committed

  return useMemo(() => {

    const mappedIndex = instanceSize
Steven Wittens's avatar
Steven Wittens committed
      ? getShader(getInstanceRepeatIndex, [instanceSize])
      : mapIndex;
Steven Wittens's avatar
Steven Wittens committed

Steven Wittens's avatar
Steven Wittens committed
    const boundInstance = getShader(getInstancedVertex, [getVertex, instances, mappedIndex]);
Steven Wittens's avatar
Steven Wittens committed

    const totalCount = () => {
      const l = resolve(elementCount) || 0;
Steven Wittens's avatar
Steven Wittens committed
      return instance != null ? l * resolve(instance) : l;
Steven Wittens's avatar
Steven Wittens committed
    };

    return [boundInstance, totalCount, INSTANCES];

  }, [instance, instances, elementCount, instanceSize]);
}

export const useNoInstancedVertex = () => {
  useNoShaderRef();
  useNoMemo();
};