Instanced Attributes

The GPU Instancing feature allows for GPU instancing of render objects with the same mesh and material. If we want to modify the visual effect for one of the instanced objects without breaking this feature, we need to add instanced attributes.

Let’s take adding a color property as an example.

Add Attribute

GPU Instancing need to add new attributes and they should be placed within the USE_INSTANCING macro to avoid compilation errors.

  1. #if USE_INSTANCING // when instancing is enabled
  2. #pragma format(RGBA8) // normalized unsigned byte
  3. in vec4 a_instanced_color;
  4. #endif

Passing to FS

The instanced attributes are vertex attributes and can only be accessed in the vertex shader, and the a_instanced_color is only used to modify the object’s color in the fragment shader. Therefore, we need to declare an out variable in the vertex shader that will be used to pass attributes to the fragment shader. Here’s an example of the code.

  1. CCProgram vs %{
  2. #if USE_INSTANCING
  3. out vec4 instancedColor;
  4. #endif
  5. vec4 vert(){
  6. ...
  7. #if USE_INSTANCING
  8. instancedColor = a_instanced_color;
  9. #endif
  10. ...
  11. }
  12. }%

Access in FS

To achieve the desired functionality, declare the corresponding in variable in the fragment shader to retrieve the value passed from the vertex shader.

  1. CCProgram fs %{
  2. #if USE_INSTANCING
  3. in vec4 instancedColor;
  4. #endif
  5. vec4 frag(){
  6. ...
  7. vec4 o = mainColor;
  8. #if USE_INSTANCING
  9. o *= instancedColor;
  10. #endif
  11. ...
  12. }
  13. }%

Set Instanced Attribute in Script

Instanced Attributes belong to specific instances of render objects and cannot be set through the material panel. Instead, they can be set using the setInstancedAttribute method on the MeshRenderer component. Here’s an example of the code.

  1. const comp = node.getComponent(MeshRenderer);
  2. comp.setInstancedAttribute('a_instanced_color', [100, 150, 200, 255]);

Notes

Here are a few points to keep in mind.

  1. #pragma format(RGBA8) is use to specify the specific data format of the property. The parameter can be any enumeration name from the engine’s GFXFormat1. If not specified, it defaults to the RGBA32F type.

  2. All instanced attributes are input through the vertex attributes. If you want to use them in the fragment shader, you need to pass them to the fragment shader from vertex shader using the varying variables(in,out).

  3. Ensure that your code can execute correctly in all branches, regardless of whether the USE_INSTANCING is enabled.

  4. The values of instanced attributes are initialized to 0 when engine starts.

  5. If the material has been changed on MeshRenderer, all values of instanced attributes will be reset and need to be set again.

  1. Integer attributes are not supported on WebGL-1.0-only platforms. If your project needs to be published on these platforms, always use the floating-point type.