Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BREAKING] More general instancing #6867

Merged
merged 7 commits into from
Aug 2, 2024
Merged

[BREAKING] More general instancing #6867

merged 7 commits into from
Aug 2, 2024

Conversation

mvaligursky
Copy link
Contributor

@mvaligursky mvaligursky commented Aug 1, 2024

Fixes #4878

Marked as BREAKING, as in case the user modified transformVS chunk, this needs to be updated to the new format. But no public API has been changed otherwise, and the default instancing works exactly as before.

https://x.com/ValigurskyM/status/1819367152614260934

This PR adds a user exposed and more generic version of hardware instancing. Details:

  • an instancing part of the transformVS chunk has been moved to transformInstancingVS chunk. This implements the existing instancing, where 4 x Vec4 are passed in by the vertex buffer, representing a world matrix.
  • this chunk is available as an include to ShaderMaterial, allowing instancing support by it
  • this chunk can be overwritten allowing custom attributes and implementation - user can also pass in any attributes like non related to transform, say per instance color or texture offset or anything else.

Example of custom instancing for StandardMaterial:

const material = new pc.StandardMaterial();

// set up additional attributes needed for instancing
material.setAttribute('aInstPosition', pc.SEMANTIC_ATTR12);
material.setAttribute('aInstScale', pc.SEMANTIC_ATTR13);

 material.chunks.transformInstancingVS = `
    // instancing attributes
    attribute vec3 aInstPosition;
    attribute float aInstScale;

    // function to generate world matrix
    mat4 getModelMatrix() {
        return mat4(
            vec4(aInstScale, 0.0, 0.0, 0.0),
            vec4(0.0, aInstScale, 0.0, 0.0),
            vec4(0.0, 0.0, aInstScale, 0.0),
            vec4(aInstPosition, 1.0)
        );
    }
`;

Example of custom instancing for ShaderMaterial. Shader variations for instancing are created automatically if instancing is set up on the mesh instance using this material.

const material = new ShaderMaterial({
    uniqueName: 'GoochShader',
    vertexCode: /* glsl */ `
    
    #include "transformCore"
    
    #if INSTANCING
        // add instancing attributes we need for our case - here we have position and scale
        attribute vec3 aInstPosition;
        attribute float aInstScale;
        // instancing needs to provide a model matrix, the rest is handled by the engine when using transformCore
        mat4 getModelMatrix() {
            return mat4(
                vec4(aInstScale, 0.0, 0.0, 0.0),
                vec4(0.0, aInstScale, 0.0, 0.0),
                vec4(0.0, 0.0, aInstScale, 0.0),
                vec4(aInstPosition, 1.0)
            );
        }
    #endif
        
    // the rest is the same as without instancing
    void main() {
        mat4 modelMatrix = getModelMatrix();
        vec3 localPos = getLocalPosition(vertex_position.xyz);
        vec4 worldPos = modelMatrix * vec4(localPos, 1.0);
        gl_Position = matrix_viewProjection * worldPos;
    },
    fragmentCode: // whatever,
    attributes: {
        vertex_position: SEMANTIC_POSITION,
        vertex_normal: SEMANTIC_NORMAL,
        aUv0: SEMANTIC_TEXCOORD0,

        // instancing attributes
        aInstPosition: SEMANTIC_ATTR12,
        aInstScale: SEMANTIC_ATTR13
    }
});

New examples

ShaderMaterial using instancing:
image

Custom StandardMaterial instancing:
image

@mvaligursky mvaligursky added feature area: graphics Graphics related issue labels Aug 1, 2024
@mvaligursky mvaligursky self-assigned this Aug 1, 2024
@mvaligursky mvaligursky marked this pull request as draft August 1, 2024 11:27
@mvaligursky mvaligursky changed the base branch from main to mv-shader-defines August 1, 2024 11:37
@mvaligursky mvaligursky changed the title More general instancing [BREAKING] More general instancing Aug 1, 2024
Martin Valigursky added 2 commits August 1, 2024 12:52
@mvaligursky mvaligursky marked this pull request as ready for review August 1, 2024 11:58
@mvaligursky mvaligursky requested a review from a team August 1, 2024 11:58
Base automatically changed from mv-shader-defines to main August 2, 2024 12:21
# Conflicts:
#	src/scene/materials/material.js
#	src/scene/shader-lib/programs/lit-shader.js
#	src/scene/shader-lib/programs/shader-generator-shader.js
#	src/scene/shader-lib/programs/shader-generator.js
@mvaligursky mvaligursky merged commit 6ab7df0 into main Aug 2, 2024
8 checks passed
@mvaligursky mvaligursky deleted the mv-instancing branch August 2, 2024 13:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: graphics Graphics related issue feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Hardware instancing improvements
2 participants