firtoz / react-three-renderer

Render into a three.js canvas using React.
https://toxicfork.github.com/react-three-renderer-example/
MIT License
1.49k stars 155 forks source link

How to update <bufferGeometry> positions? #210

Closed johnmarinelli closed 6 years ago

johnmarinelli commented 6 years ago

I'm writing a particle system that uses a buffer geometry for performance.

here is my current render() function, which works fine, but as you can see I'm creating a new THREE.Float32BufferAttribute object on every render (which I would like to avoid):

      const { position, rotation } = this.props;                                     

      return (                                                                       
        <points                                                                      
          position={position}                                                        
          rotation={rotation}>                                                       
          <bufferGeometry                                                                                                                                                            
            index={null}                                                             
            position={new THREE.Float32BufferAttribute(this.positions.slice(), 3)} 
            color={new THREE.Float32BufferAttribute(this.colors.slice(), 3)} />   
          <materialResource                                                          
            resourceId="particleMaterial" />                                         
        </points> 
    )

I would like to replace: position={new THREE.Float32BufferAttribute(this.positions.slice(), 3)} with position={this.positionsBuffer}. Similarly for color.

this.positionsBuffer is a THREE.Float32BufferAttribute defined in the constructor and is updated in componentWillUpdate. I also set this.positionsBuffer.dynamic = true, but it still doesn't work.

However, when I do this, the <bufferGeometry> appears to only get updated once. The values in this.positionsBuffer get updated correctly, but the new positions aren't reflected in the renderer and the particle system looks "frozen".

I have a suspicion this has something to do with setting the needsUpdate property of the bufferGeometry object but as far as I can tell, r3r doesn't offer that in the api. Do you have any suggestions?

Update: adding .clone() - position={this.positionsBuffer.clone()} seems to work, but it's basically the same thing because there's object creation going on. ideally I'd like to have a single channel for cpu -> gpu communication, which (I think?) breaks when a new buffer attribute is created.

toxicFork commented 6 years ago

You can get a ref to the geometry object and then call any function on it freely :) All the other solutions I can think of are potentially hacks... You could also have 2 different float32bufferattributes and alternate between them (double buffering muahahah), which should be cheaper than reconstructing still

johnmarinelli commented 6 years ago

Ahh! Of course, I even came across the ref idea from one of your examples but completely forgot about it. Thanks :)