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

InstancedMesh: Add support for async color definitions. #26430

Merged
merged 2 commits into from
Jul 17, 2023

Conversation

CodyJasonBennett
Copy link
Contributor

@CodyJasonBennett CodyJasonBennett commented Jul 14, 2023

Fixed #21786

Description

Flags the current instanced material for update on render whenever instanceColor is (un)set. This tracks async effects without explicitly managing them in InstancedMesh.

Show Example:

The following renders a red cube whenever instanceColor is properly in sync with the mesh (~1s).

import * as THREE from 'three';

let renderer, scene, camera;

init();
animate();

function init() {

    renderer = new THREE.WebGLRenderer();
    renderer.setSize( window.innerWidth, window.innerHeight );
    renderer.setPixelRatio( window.devicePixelRatio );
    document.body.appendChild( renderer.domElement );

    scene = new THREE.Scene();
    
    camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight );
    camera.position.z = 5;

    const geometry = new THREE.BoxGeometry();

    const material = new THREE.ShaderMaterial({
      vertexShader: /* glsl */ `

        varying vec3 vColor;

        void main() {

          #ifdef USE_INSTANCING_COLOR

            vColor = instanceColor;

          #endif

          gl_Position = projectionMatrix * modelViewMatrix * instanceMatrix * vec4( position, 1.0 );

        }

      `,
      fragmentShader: /* glsl */ `

        varying vec3 vColor;

        void main() {

          gl_FragColor = vec4( vColor, 1.0 );

        }

      `,
    });

    const mesh = new THREE.InstancedMesh( geometry, material, 1 );
    scene.add( mesh );

    setTimeout(() => {

      mesh.setColorAt( 0, new THREE.Color( 'red' ) );
      mesh.instanceColor.needsUpdate = true;

    }, 1000 );

}

function animate() {

  requestAnimationFrame( animate );
  renderer.render( scene, camera );

}

@github-actions
Copy link

github-actions bot commented Jul 14, 2023

📦 Bundle size

Full ESM build, minified and gzipped.

Filesize dev Filesize PR Diff
643.8 kB (159.6 kB) 644 kB (159.7 kB) +170 B

🌳 Bundle size after tree-shaking

Minimal build including a renderer, camera, empty scene, and dependencies.

Filesize dev Filesize PR Diff
437 kB (105.8 kB) 437.2 kB (105.8 kB) +170 B

@Mugen87
Copy link
Collaborator

Mugen87 commented Jul 15, 2023

We have to decide first if we want to support setting instanceColor asynchronously or if the data setup has to be done before the first render.

The problem is that every additional check in setProgram() increases the per-frame overhead for all scenes. So my personal preference is to not add these checks but update the docs instead.

@Mugen87
Copy link
Collaborator

Mugen87 commented Jul 15, 2023

On the other hand setting up the instanced mesh before the first render does not fix the use case described in #21786 (comment).

Um, this is indeed a tricky one. I guess I'm okay with accepting the changes to the renderer then.

@Mugen87 Mugen87 added this to the r155 milestone Jul 16, 2023
@Mugen87 Mugen87 merged commit b8a2003 into mrdoob:dev Jul 17, 2023
@CodyJasonBennett CodyJasonBennett deleted the async-instancecolor branch July 17, 2023 13:00
@Mugen87 Mugen87 changed the title WebGLRenderer: invalidate materials on async instanceColor set InstancedMesh: Add support for async color definitions. Jul 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

instanceColor attribute is not defined when InstancedMesh is populated asynchronously
2 participants