-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactored GPUParticleSystem. Improved FP Texture detection
- Loading branch information
1 parent
7b70127
commit 648bfaa
Showing
10 changed files
with
213 additions
and
84 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
v7.0.1 | ||
v7.1.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,87 +1,109 @@ | ||
import { Object3D } from 'three'; | ||
import { BufferAttribute } from 'three'; | ||
import { PlaneGeometry } from 'three'; | ||
import { Mesh } from 'three'; | ||
import { BufferGeometry } from 'three'; | ||
import { Scene } from 'three'; | ||
import { Points } from 'three'; | ||
import { InstancedBufferGeometry } from 'three'; | ||
import { InstancedBufferAttribute } from 'three'; | ||
import ParticleAttribute from './ParticleAttribute'; | ||
|
||
export default class GPUParticleSystem extends Object3D | ||
{ | ||
constructor() | ||
constructor(particle_count, material) | ||
{ | ||
super(); | ||
this.attributes = []; | ||
|
||
this.particles = undefined; | ||
} | ||
|
||
set_from_geometry(geometry, material, init_attribute_uvs) | ||
{ | ||
// let position = new ParticlePositionAttribute("_Position"); | ||
if (init_attribute_uvs && geometry.getAttribute('storage_uv') === undefined) | ||
{ | ||
const uv_storage_attr = this.build_uv_storage_attribute(geometry.getAttribute('position').count); | ||
geometry.setAttribute('storage_uv', uv_storage_attr); | ||
} | ||
// position.init_from_geometry(geometry); | ||
// this.attributes.push(position); | ||
this.mesh = this.build_point_mesh(particle_count, material); | ||
this.add(this.mesh); | ||
|
||
// material.uniforms._Position.value = position.read.texture; | ||
|
||
const points = new Points(geometry, material); | ||
points.frustumCulled = false; | ||
this.particles = points; | ||
|
||
this.add(points); | ||
this.attribute_writter_mesh = this.build_attribute_writter_mesh(particle_count); | ||
this.attribute_writter_scene = new Scene(); | ||
this.attribute_writter_scene.add(this.attribute_writter_mesh); | ||
} | ||
|
||
add_texture_attribute(buffer_attribute) | ||
{ | ||
|
||
this.attributes.push(buffer_attribute); | ||
} | ||
|
||
add_attribute(name, buffer_attribute) | ||
add_update_attribute_array(name, array, item_size) | ||
{ | ||
this.attribute_writter_mesh.geometry.setAttribute(name, new BufferAttribute(array, item_size, false)); | ||
} | ||
|
||
add_attribute_array(name, array, item_size) | ||
{ | ||
this.mesh.geometry.setAttribute(name, new InstancedBufferAttribute(array, item_size, false)); | ||
} | ||
|
||
build_uv_storage_attribute(particle_count) | ||
update() | ||
{ | ||
const resolution = this.calculate_resolution(particle_count); | ||
const uvs = new Float32Array(particle_count * 2); | ||
for (let i = 0, j = 0; i < particle_count * 2; i += 2, j++) | ||
this.mesh.material.update(); | ||
for (let i = 0; i < this.attributes.length; i++) | ||
{ | ||
uvs[i] = ((j % resolution) / resolution) + (0.5 / resolution); | ||
uvs[i + 1] = (Math.floor(j / resolution) / resolution) + (0.5 / resolution); | ||
this.attributes[i].update(this.attribute_writter_scene); | ||
} | ||
|
||
return new BufferAttribute(uvs, 2); | ||
} | ||
|
||
calculate_resolution(particle_count) | ||
dispose() | ||
{ | ||
return Math.ceil(Math.sqrt(particle_count)); | ||
this.mesh.geometry.dispose(); | ||
this.mesh.material.dispose(); | ||
} | ||
|
||
update() | ||
build_point_mesh(instance_count = 1, material) | ||
{ | ||
for (let i = 0; i < this.attributes.length; i++) | ||
{ | ||
this.attributes[i].update(); | ||
} | ||
const geo = new PlaneGeometry(); | ||
|
||
const instanced_geo = new InstancedBufferGeometry(); | ||
instanced_geo.setAttribute('position', geo.getAttribute('position')); | ||
instanced_geo.index = geo.index; | ||
|
||
instanced_geo.setAttribute('storage_uv', this.build_uv_storage_attribute(instance_count)); | ||
instanced_geo.instanceCount = instance_count; | ||
const mesh = new Mesh(instanced_geo, material); | ||
mesh.frustumCulled = false; | ||
return mesh; | ||
} | ||
|
||
set_attribute_update_material(attribute_name, mat) | ||
build_attribute_writter_mesh(particle_count) | ||
{ | ||
for (let i = 0; i < this.attributes.length; i++) | ||
const { width, height } = ParticleAttribute.calculate_resolution(particle_count); | ||
|
||
const uvs = new Float32Array(particle_count * 3); | ||
|
||
for (let i = 0; i < particle_count; i++) | ||
{ | ||
if (this.attributes[i].name === attribute_name) | ||
{ | ||
this.attributes[i].update_material = mat; | ||
} | ||
const x = i % width; | ||
const y = Math.floor(i / width); | ||
uvs[i * 3 + 0] = (x + 0.5) / width; | ||
uvs[i * 3 + 1] = (y + 0.5) / height; | ||
uvs[i * 3 + 2] = i; | ||
} | ||
const geo = new BufferGeometry(); | ||
geo.setAttribute('position', new BufferAttribute(uvs, 3, false)); | ||
|
||
const points = new Points(geo); | ||
points.frustumCulled = false; | ||
return points; | ||
} | ||
|
||
dispose() | ||
build_uv_storage_attribute(particle_count) | ||
{ | ||
this.particles.geometry.dispose(); | ||
this.particles.material.dispose(); | ||
const { width, height } = ParticleAttribute.calculate_resolution(particle_count); | ||
|
||
const uvs = new Float32Array(particle_count * 2); | ||
|
||
for (let i = 0; i < particle_count; i++) | ||
{ | ||
const x = i % width; | ||
const y = Math.floor(i / width); | ||
uvs[i * 2 + 0] = (x + 0.5) / width; | ||
uvs[i * 2 + 1] = (y + 0.5) / height; | ||
} | ||
return new InstancedBufferAttribute(uvs, 2, false); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,40 @@ | ||
import { BufferAttribute } from 'three'; | ||
|
||
import ParticleAttribute from '../gpu_particles/ParticleAttribute'; | ||
import PositionStorageMaterial from '../materials/gpu_particles/PositionStorageMaterial'; | ||
import ParticleStorageMaterial from '../materials/gpu_particles/ParticleStorageMaterial'; | ||
|
||
export default class ParticlePositionAttribute extends ParticleAttribute | ||
{ | ||
constructor() | ||
constructor(update_material) | ||
{ | ||
super('_Position'); | ||
super('_Position', update_material); | ||
} | ||
|
||
init_from_geometry(geometry) | ||
store_geometry(geometry, attribute_writter_scene) | ||
{ | ||
const pos_attr = geometry.getAttribute('position'); | ||
this.read = this.build_RT(pos_attr.count); | ||
this.write = this.build_RT(pos_attr.count); | ||
|
||
const mat = new PositionStorageMaterial(); | ||
this.render_geometry_to_RT(geometry, mat, this.read); | ||
const mat = new ParticleStorageMaterial(); | ||
this.store_geometry_attribute_in_RT(geometry.getAttribute('position'), this.read, mat, attribute_writter_scene); | ||
} | ||
|
||
store_positions(positions, attribute_writter_scene) | ||
{ | ||
this.read = this.build_RT(positions.length); | ||
this.write = this.build_RT(positions.length); | ||
|
||
const arr = new Float32Array(positions.length * 4); | ||
|
||
for (let i = 0; i < positions.length; i++) | ||
{ | ||
arr[i * 4 + 0] = positions[i].x; | ||
arr[i * 4 + 1] = positions[i].y; | ||
arr[i * 4 + 2] = positions[i].z; | ||
arr[i * 4 + 3] = (Math.random() * 2 - 1) * 10; | ||
} | ||
const mat = new ParticleStorageMaterial(); | ||
this.store_geometry_attribute_in_RT(new BufferAttribute(arr, 4), this.read, mat, attribute_writter_scene); | ||
} | ||
} |
Oops, something went wrong.