Can't seem to make a basic instancedMesh work with instancedBuffers + declarative babylonjs

Hello,

I’m currently blocked on a specific issue: Adjusting the color and alpha channel of an instancedMesh.

I’ve been reading through the documentation, also following instructions from react-babylonjs instanced hex example.

The sample code is quite simple. If you run it (check it out here on codesandbox), neither the mesh nor the instancedMesh are displayed.

What have I obviously missed here?

Note: I have reused the useCallback() construct from react-babylonjs example, as it seems to allow a call to registerInstancedBuffer() at the right time.

Note2: I must implement this behaviour in a wider project written in declarative style.

Thanks in advance for the support.

import { Color3, Color4, Vector3 } from '@babylonjs/core'
import React, { FC, ReactNode, useCallback, useState } from 'react'
import { Engine, Scene } from 'react-babylonjs'

type BabylonAppProps = {
  children?: ReactNode
}

let instanceColor = new Color4(
  Math.random(),
  Math.random(),
  Math.random(),
  Math.random()
)

const BabylonApp: FC<BabylonAppProps> = ({ children }) => {
  const [boxMesh, setBoxMesh] = useState(null)
  const boxRef = useCallback((node: any) => {
    if (node) {
      const mesh = node
      mesh.registerInstancedBuffer('color', 4)
      setBoxMesh(mesh)
    }
  }, [])
  return (
    <div style={{ flex: 1, display: 'flex' }}>
      <Engine antialias adaptToDeviceRatio canvasId="babylon-canvas">
        <Scene>
          <freeCamera
            name="camera1"
            position={new Vector3(0, 5, -10)}
            setTarget={[Vector3.Zero()]}
          />

          <hemisphericLight
            name="light1"
            intensity={0.7}
            direction={new Vector3(0, 1, 0)}
          />

          <ground name="ground" width={6} height={6} />

          <box
            ref={boxRef}
            name="box"
            size={2}
            position={new Vector3(0, 1, 0)}
            rotation={Vector3.Zero()}
            hasVertexAlpha={true}
            isVisible={true}
          >
            <standardMaterial
              name="mat"
              emissiveColor={Color3.White()}
              disableLighting={true}
            />
          </box>
          {boxMesh && (
            <instancedMesh
              source={boxMesh}
              name="box-instanced"
              position={new Vector3(1, 1, 0)}
              rotation={Vector3.Zero()}
              hasVertexAlpha={true}
              instancedBuffers={{ color: instanceColor }}
              isVisible={true}
            />
          )}
        </Scene>
      </Engine>
    </div>
  )
}

export default BabylonApp

Welcome aboard!

cc @brianzinn who is the creator of react-babylonjs.

hi @keldonin - welcome to the forum!

I think you just need to add “instancedBuffers” to your root mesh where your registered instance buffer can be found. It’s of type Record<string, any>.

const boxRef = useCallback((node: Mesh) => {
    if (node) {
      const mesh = node
      mesh.registerInstancedBuffer('color', 4)
      mesh.instancedBuffers.color = new Color4(
        Math.random(),
        Math.random(),
        Math.random(),
        1
      )
  
      setBoxMesh(mesh)
    }
  }, [])

I’m seeing an instance with just that change.

2 Likes

Thank you so much @brianzinn. It was not obvious to me that the root mesh would need that bufferedInstance as well. It might be useful to add to your otherwise awesome documentation on your github project!