【Question】about points

Hi guys!
I m trying to write a smoke effect,an explosive smoke for example.
I only set like 1k+ vertexs ,but the FPS goes down to 1~5 per sceond

code here


this._geometry = new THREE.BufferGeometry()

this._geometry.setAttribute('position', new THREE.Float32BufferAttribute([], 3))  

this._geometry.setAttribute('size', new THREE.Float32BufferAttribute([], 1)) 

this._geometry.setAttribute('opacity',new THREE.Float32BufferAttribute([],1)) 

this._geometry.setAttribute('lifeTime',new THREE.Float32BufferAttribute([],1))

this._geometry.setAttribute('rotation',new THREE.Float32BufferAttribute([],1))


this._material = new THREE.PointsMaterial( {
			size: 1, 
			transparent: true ,
			map : new THREE.TextureLoader().load('./resources/textures/smoke.png'),
			blending: THREE.CustomBlending,
            blendEquation: THREE.AddEquation,
            blendSrc: THREE.OneFactor,
            blendDst: THREE.OneMinusSrcAlphaFactor,
            depthTest: true,
            depthWrite: false,
            transparent: true,
            vertexColors: true
		} )
this._points = new THREE.Points(this._geometry,this._material)

const vertexs = []
		const sizes = []
		const opacities = []
		const lifeTimes = []
		const rotation = []

		let lastTime = 0
		let timeInterval,vertexX,vertexY,vertexZ,x,y,z
               
                // the last batch added to the scene when the first batch runs out lifetime 
		const activity = new TWEEN.Tween({
			time : 0
		},this._group).to({
			time :5
		},5*2*1000).onUpdate(object=>{
			timeInterval = object.time - lastTime
			lastTime = object.time

			// update by a movement pattern( its just a scratch)
			for(let i = 0;i<sizes.length;i++){

				if(lifeTimes[i]>0){
					let index = i*3

					lifeTimes[i]-=timeInterval
					x = 2*(this._lifeTime-lifeTimes[i])
					y = vertexX/Math.tan(1/6*Math.PI)
					vertexX = x*Math.random()
					vertexY = y*(Math.random()-0.5)*2

					z = Math.sqrt(y*y-vertexY*vertexY)

					vertexZ = y*(Math.random()-0.5)*2

					vertexs[i] = vertexX
                                        // another question vertexY maybe negative but it appears positive in the position.array
					vertexs[i+1] = vertexY
					vertexs[i+2] = vertexZ>z?vertexZ-z:vertexZ

				}

			}

			this._points.geometry.attributes.position.needsUpdate = true
			this._points.geometry.attributes.size.needsUpdate = true
			this._points.geometry.attributes.opacity.needsUpdate = true
			this._points.geometry.attributes.lifeTime.needsUpdate = true
			this._points.geometry.attributes.rotation.needsUpdate = true

			// add 50 particles everytime in the first 5 seconds
			if(object.time<5){
				for(let i = 0;i<this.50;i++){
					vertexs.push(0)
					vertexs.push(0)
					vertexs.push(0)

					sizes.push(this._size*Math.random())
					opacities.push(1)
					lifeTimes.push(this._lifeTime)

					rotation.push(Math.random())
					rotation.push(Math.random())
					rotation.push(Math.random())
				}
			}else{
				this._isProducing = false
			}

			this._points.geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertexs, 3))
		  this._points.geometry.setAttribute('size', new THREE.Float32BufferAttribute(sizes, 1))
		  this._points.geometry.setAttribute('opacity',new THREE.Float32BufferAttribute(opacities,1))
		  this._points.geometry.setAttribute('lifeTime',new THREE.Float32BufferAttribute(lifeTimes,1))
		  this._points.geometry.setAttribute('rotation',new THREE.Float32BufferAttribute(rotation,3))
		})
		
		activity.start()

I saw the example they got like 10k more vertexs but the FPS looks fine.
Their vertexs are scattered while mine concentrated.
And i noteiced their particles moves as one which is a little bit simple while mine are much complicated
Can someone elighten me on this question?Maybe some advises about the sctructure or how it should be done?
Any help would be great!

Your indentation is all over the map, but are you creating 5 new BufferAttributes per frame on each update? If so, then that’s your problem. You should create the BufferAttribute just once, and then update its values. For example, take a look at this example of a dynamic geometry, the position.y attribute changes on each frame, but it’s only constructed once:

geometry = new THREE.PlaneGeometry( 20000, 20000, worldWidth - 1, worldDepth - 1 );
geometry.rotateX( - Math.PI / 2 );

const position = geometry.attributes.position;
position.usage = THREE.DynamicDrawUsage;

function render() {
	for ( let i = 0; i < position.count; i ++ ) {
		const y = 35 * Math.sin( i / 5 + ( time + i ) / 7 );
		position.setY( i, y );
	}
	position.needsUpdate = true;
}

Thanks man,i do create 5 new BufferAtrribute on per frame each update.I’ll try this!much apperciate

is there a way to put new element into BufferAttribute?I saw the document seems dont has a method to add new element.

Add new point or new attribute ?

I constructed one THREE.Points add vertexs to BufferAttribute

See the BufferGeometry section in “how to update things”.

1 Like