Skip to content

Commit

Permalink
feat: createInstances
Browse files Browse the repository at this point in the history
  • Loading branch information
drcmda committed Aug 16, 2024
1 parent f4f910f commit 5cf9132
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 8 deletions.
Binary file modified .yarn/install-state.gz
Binary file not shown.
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3449,6 +3449,30 @@ You can define events on them!
<Instance onClick={...} onPointerOver={...} />
```

If you need nested, multiple instances in the same parent graph, it would normally not work because an `<Instance>` is directly paired to its nearest `<Instances>` provider. You can use the global `createInstances` helper for such cases, it creates dedicated instances-instance pairs. The first return value is the provider, the second the instance component. Both take the same properties as `<Instances>` and `<Instance>`.

```jsx
const [CubeInstances, Cube] = createInstances()
const [SphereInstances, Sphere] = createInstances()
function App() {
return (
<>
<CubeInstances>
<boxGeometry />
<meshStandardMaterial />
<SphereInstances>
<sphereGeometry />
<meshLambertMaterial />
<Cube position={[1, 2, 3]} />
<Sphere position={[4, 5, 6]} />
</SphereInstances>
</CubeInstances>
</>
)
}
```

👉 Note: While creating instances declaratively keeps all the power of components with reduced draw calls, it comes at the cost of CPU overhead. For cases like foliage where you want no CPU overhead with thousands of intances you should use THREE.InstancedMesh such as in this [example](https://codesandbox.io/s/grass-shader-5xho4?file=/src/Grass.js).

#### Merged
Expand Down
33 changes: 25 additions & 8 deletions src/core/Instances.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type Api = {
}

export type InstancesProps = JSX.IntrinsicElements['instancedMesh'] & {
context?: React.Context<Api>
range?: number
limit?: number
frames?: number
Expand Down Expand Up @@ -113,15 +114,17 @@ export const Instance = /* @__PURE__ */ React.forwardRef(({ context, children, .
)
})

export const Instances: ForwardRefComponent<InstancesProps, InstancedMesh> = /* @__PURE__ */ React.forwardRef<
InstancedMesh,
export const Instances: ForwardRefComponent<InstancesProps, THREE.InstancedMesh> = /* @__PURE__ */ React.forwardRef<
THREE.InstancedMesh,
InstancesProps
>(({ children, range, limit = 1000, frames = Infinity, ...props }, ref) => {
const [{ context, instance }] = React.useState(() => {
const context = React.createContext<Api>(null!)
>(({ context, children, range, limit = 1000, frames = Infinity, ...props }, ref) => {
const [{ localContext, instance }] = React.useState(() => {
const localContext = React.createContext<Api>(null!)
return {
context,
instance: React.forwardRef((props: InstanceProps, ref) => <Instance context={context} {...props} ref={ref} />),
localContext,
instance: React.forwardRef((props: InstanceProps, ref) => (
<Instance context={localContext} {...props} ref={ref} />
)),
}
})

Expand Down Expand Up @@ -202,7 +205,9 @@ export const Instances: ForwardRefComponent<InstancesProps, InstancedMesh> = /*
usage={THREE.DynamicDrawUsage}
/>
{isFunctionChild(children) ? (
<context.Provider value={api}>{children(instance)}</context.Provider>
<localContext.Provider value={api}>{children(instance)}</localContext.Provider>
) : context ? (
<context.Provider value={api}>{children}</context.Provider>
) : (
<globalContext.Provider value={api}>{children}</globalContext.Provider>
)}
Expand Down Expand Up @@ -241,3 +246,15 @@ export const Merged: ForwardRefComponent<any, THREE.Group> = /* @__PURE__ */ Rea
)
}
)

export function createInstances() {
const context = React.createContext<Api>(null!)
return [
React.forwardRef<THREE.InstancedMesh, InstancesProps>((props, fref) => (
<Instances ref={fref} context={context} {...props} />
)),
React.forwardRef<PositionMesh, InstanceProps>((props, fref) => (
<Instance ref={fref} context={context} {...props} />
)),
]
}

0 comments on commit 5cf9132

Please sign in to comment.