ohzi-core 7.0.1 → 7.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ohzi-core",
3
- "version": "7.0.1",
3
+ "version": "7.1.0",
4
4
  "description": "OHZI Core Library",
5
5
  "source": "src/index.js",
6
6
  "module": "build/index.module.js",
package/src/Graphics.js CHANGED
@@ -7,6 +7,17 @@ import Capabilities from './Capabilities';
7
7
  import DepthAndNormalsRenderer from './render_utilities/DepthAndNormalsRenderer';
8
8
  import Blitter from './render_utilities/Blitter';
9
9
 
10
+ import {
11
+ NearestFilter,
12
+ RGBAFormat,
13
+ LinearEncoding,
14
+ FloatType,
15
+ WebGLRenderTarget,
16
+ ShaderMaterial,
17
+ NoBlending,
18
+ AlwaysDepth
19
+ } from 'three';
20
+
10
21
  import { WebGLRenderer } from 'three';
11
22
 
12
23
  class Graphics
@@ -87,7 +98,7 @@ class Graphics
87
98
  this.current_render_mode = this.no_render;
88
99
  Capabilities.max_anisotropy = this._renderer.capabilities.getMaxAnisotropy();
89
100
  Capabilities.vertex_texture_sampler_available = this._renderer.capabilities.maxVertexTextures > 0;
90
- Capabilities.fp_textures_available = this._renderer.capabilities.floatVertexTextures;
101
+ Capabilities.fp_textures_available = this.is_floating_point_texture_available();
91
102
 
92
103
  this.generateDepthNormalTexture = false;
93
104
 
@@ -332,6 +343,48 @@ class Graphics
332
343
  this.current_render_mode.dispose();
333
344
  this.blitter.dispose();
334
345
  }
346
+
347
+ is_floating_point_texture_available()
348
+ {
349
+ const RT = new WebGLRenderTarget(1, 1, {
350
+ minFilter: NearestFilter,
351
+ magFilter: NearestFilter,
352
+ format: RGBAFormat,
353
+ encoding: LinearEncoding,
354
+ type: FloatType,
355
+ stencilBuffer: false,
356
+ depthBuffer: false
357
+ });
358
+
359
+ const vert = `
360
+ void main()
361
+ {
362
+ gl_Position = vec4(uv * 2.0 - 1.0, 1.0, 1.0);
363
+ }
364
+ `;
365
+ const frag = `
366
+ void main()
367
+ {
368
+ gl_FragColor = vec4(0.0, 4865.35, 0.0, 1.0);
369
+ }
370
+ `;
371
+
372
+ const mat = new ShaderMaterial({
373
+ vertexShader: vert,
374
+ fragmentShader: frag,
375
+ depthWrite: false,
376
+ blending: NoBlending,
377
+ depthTest: false,
378
+ depthFunc: AlwaysDepth
379
+ });
380
+
381
+ this.material_pass(mat, RT);
382
+
383
+ const output = new Float32Array(4);
384
+ this._renderer.readRenderTargetPixels(RT, 0, 0, 1, 1, output);
385
+
386
+ return Math.abs(output[1] - 4865.35) < 0.001;
387
+ }
335
388
  }
336
389
 
337
390
  export default new Graphics();
@@ -1,87 +1,109 @@
1
1
  import { Object3D } from 'three';
2
2
  import { BufferAttribute } from 'three';
3
+ import { PlaneGeometry } from 'three';
4
+ import { Mesh } from 'three';
5
+ import { BufferGeometry } from 'three';
6
+ import { Scene } from 'three';
3
7
  import { Points } from 'three';
8
+ import { InstancedBufferGeometry } from 'three';
9
+ import { InstancedBufferAttribute } from 'three';
10
+ import ParticleAttribute from './ParticleAttribute';
4
11
 
5
12
  export default class GPUParticleSystem extends Object3D
6
13
  {
7
- constructor()
14
+ constructor(particle_count, material)
8
15
  {
9
16
  super();
10
17
  this.attributes = [];
11
18
 
12
- this.particles = undefined;
13
- }
14
-
15
- set_from_geometry(geometry, material, init_attribute_uvs)
16
- {
17
- // let position = new ParticlePositionAttribute("_Position");
18
- if (init_attribute_uvs && geometry.getAttribute('storage_uv') === undefined)
19
- {
20
- const uv_storage_attr = this.build_uv_storage_attribute(geometry.getAttribute('position').count);
21
- geometry.setAttribute('storage_uv', uv_storage_attr);
22
- }
23
- // position.init_from_geometry(geometry);
24
- // this.attributes.push(position);
19
+ this.mesh = this.build_point_mesh(particle_count, material);
20
+ this.add(this.mesh);
25
21
 
26
- // material.uniforms._Position.value = position.read.texture;
27
-
28
- const points = new Points(geometry, material);
29
- points.frustumCulled = false;
30
- this.particles = points;
31
-
32
- this.add(points);
22
+ this.attribute_writter_mesh = this.build_attribute_writter_mesh(particle_count);
23
+ this.attribute_writter_scene = new Scene();
24
+ this.attribute_writter_scene.add(this.attribute_writter_mesh);
33
25
  }
34
26
 
35
27
  add_texture_attribute(buffer_attribute)
36
28
  {
37
-
29
+ this.attributes.push(buffer_attribute);
38
30
  }
39
31
 
40
- add_attribute(name, buffer_attribute)
32
+ add_update_attribute_array(name, array, item_size)
41
33
  {
34
+ this.attribute_writter_mesh.geometry.setAttribute(name, new BufferAttribute(array, item_size, false));
35
+ }
42
36
 
37
+ add_attribute_array(name, array, item_size)
38
+ {
39
+ this.mesh.geometry.setAttribute(name, new InstancedBufferAttribute(array, item_size, false));
43
40
  }
44
41
 
45
- build_uv_storage_attribute(particle_count)
42
+ update()
46
43
  {
47
- const resolution = this.calculate_resolution(particle_count);
48
- const uvs = new Float32Array(particle_count * 2);
49
- for (let i = 0, j = 0; i < particle_count * 2; i += 2, j++)
44
+ this.mesh.material.update();
45
+ for (let i = 0; i < this.attributes.length; i++)
50
46
  {
51
- uvs[i] = ((j % resolution) / resolution) + (0.5 / resolution);
52
- uvs[i + 1] = (Math.floor(j / resolution) / resolution) + (0.5 / resolution);
47
+ this.attributes[i].update(this.attribute_writter_scene);
53
48
  }
54
-
55
- return new BufferAttribute(uvs, 2);
56
49
  }
57
50
 
58
- calculate_resolution(particle_count)
51
+ dispose()
59
52
  {
60
- return Math.ceil(Math.sqrt(particle_count));
53
+ this.mesh.geometry.dispose();
54
+ this.mesh.material.dispose();
61
55
  }
62
56
 
63
- update()
57
+ build_point_mesh(instance_count = 1, material)
64
58
  {
65
- for (let i = 0; i < this.attributes.length; i++)
66
- {
67
- this.attributes[i].update();
68
- }
59
+ const geo = new PlaneGeometry();
60
+
61
+ const instanced_geo = new InstancedBufferGeometry();
62
+ instanced_geo.setAttribute('position', geo.getAttribute('position'));
63
+ instanced_geo.index = geo.index;
64
+
65
+ instanced_geo.setAttribute('storage_uv', this.build_uv_storage_attribute(instance_count));
66
+ instanced_geo.instanceCount = instance_count;
67
+ const mesh = new Mesh(instanced_geo, material);
68
+ mesh.frustumCulled = false;
69
+ return mesh;
69
70
  }
70
71
 
71
- set_attribute_update_material(attribute_name, mat)
72
+ build_attribute_writter_mesh(particle_count)
72
73
  {
73
- for (let i = 0; i < this.attributes.length; i++)
74
+ const { width, height } = ParticleAttribute.calculate_resolution(particle_count);
75
+
76
+ const uvs = new Float32Array(particle_count * 3);
77
+
78
+ for (let i = 0; i < particle_count; i++)
74
79
  {
75
- if (this.attributes[i].name === attribute_name)
76
- {
77
- this.attributes[i].update_material = mat;
78
- }
80
+ const x = i % width;
81
+ const y = Math.floor(i / width);
82
+ uvs[i * 3 + 0] = (x + 0.5) / width;
83
+ uvs[i * 3 + 1] = (y + 0.5) / height;
84
+ uvs[i * 3 + 2] = i;
79
85
  }
86
+ const geo = new BufferGeometry();
87
+ geo.setAttribute('position', new BufferAttribute(uvs, 3, false));
88
+
89
+ const points = new Points(geo);
90
+ points.frustumCulled = false;
91
+ return points;
80
92
  }
81
93
 
82
- dispose()
94
+ build_uv_storage_attribute(particle_count)
83
95
  {
84
- this.particles.geometry.dispose();
85
- this.particles.material.dispose();
96
+ const { width, height } = ParticleAttribute.calculate_resolution(particle_count);
97
+
98
+ const uvs = new Float32Array(particle_count * 2);
99
+
100
+ for (let i = 0; i < particle_count; i++)
101
+ {
102
+ const x = i % width;
103
+ const y = Math.floor(i / width);
104
+ uvs[i * 2 + 0] = (x + 0.5) / width;
105
+ uvs[i * 2 + 1] = (y + 0.5) / height;
106
+ }
107
+ return new InstancedBufferAttribute(uvs, 2, false);
86
108
  }
87
109
  }
@@ -1,26 +1,23 @@
1
1
  import Graphics from '../Graphics';
2
2
 
3
- import { Scene } from 'three';
4
3
  import { NearestFilter } from 'three';
5
4
  import { RGBAFormat } from 'three';
6
5
  import { LinearEncoding } from 'three';
7
6
  import { HalfFloatType } from 'three';
8
7
  import { FloatType } from 'three';
9
8
  import { WebGLRenderTarget } from 'three';
10
- import { Points } from 'three';
9
+ import Capabilities from '../Capabilities';
11
10
 
12
11
  export default class ParticleAttribute
13
12
  {
14
- constructor(attr_name)
13
+ constructor(attr_name, update_material)
15
14
  {
16
15
  this.read = undefined;
17
16
  this.write = undefined;
18
17
 
19
18
  this.name = attr_name;
20
19
 
21
- this.update_material = undefined;
22
-
23
- this.update_scene = new Scene();
20
+ this.update_material = update_material;
24
21
  }
25
22
 
26
23
  init_from_geometry(geometry)
@@ -35,23 +32,25 @@ export default class ParticleAttribute
35
32
 
36
33
  build_RT(particle_count)
37
34
  {
38
- const resolution = this.calculate_resolution(particle_count);
35
+ const resolution = ParticleAttribute.calculate_resolution(particle_count);
39
36
  const options = {
40
37
  minFilter: NearestFilter,
41
38
  magFilter: NearestFilter,
42
39
  format: RGBAFormat,
43
40
  encoding: LinearEncoding,
44
- type: (/(iPad|iPhone|iPod)/g.test(navigator.userAgent)) ? HalfFloatType : FloatType,
41
+ type: Capabilities.fp_textures_available ? FloatType : HalfFloatType,
45
42
  stencilBuffer: false,
46
43
  depthBuffer: false
47
44
  };
48
45
 
49
- return new WebGLRenderTarget(resolution, resolution, options);
46
+ return new WebGLRenderTarget(resolution.width, resolution.height, options);
50
47
  }
51
48
 
52
- calculate_resolution(particle_count)
49
+ static calculate_resolution(particle_count)
53
50
  {
54
- return Math.ceil(Math.sqrt(particle_count));
51
+ const width = Math.min(particle_count, 512);
52
+ const height = Math.max(1, Math.ceil(particle_count / width));
53
+ return { width, height };
55
54
  }
56
55
 
57
56
  swap_RT()
@@ -61,23 +60,33 @@ export default class ParticleAttribute
61
60
  this.write = tmp;
62
61
  }
63
62
 
64
- update()
63
+ update(attribute_writter_scene)
65
64
  {
66
65
  if (this.update_material)
67
66
  {
68
- Graphics.blit(this.read, this.write, this.update_material);
67
+ this.update_material.update();
68
+ attribute_writter_scene.children[0].material = this.update_material;
69
+ this.update_material.uniforms._MainTex.value = this.read.texture;
70
+ Graphics.render(attribute_writter_scene, undefined, this.write);
71
+ attribute_writter_scene.children[0].material = undefined;
72
+
69
73
  this.swap_RT();
70
74
  }
71
75
  }
72
76
 
73
- render_geometry_to_RT(geometry, material, RT)
77
+ store_geometry_attribute_in_RT(attribute, RT, storage_material, attribute_writter_scene)
78
+ {
79
+ attribute_writter_scene.children[0].geometry.setAttribute('data', attribute);
80
+ attribute_writter_scene.children[0].material = storage_material;
81
+
82
+ Graphics.render(attribute_writter_scene, undefined, RT);
83
+
84
+ attribute_writter_scene.children[0].geometry.deleteAttribute('data');
85
+ attribute_writter_scene.children[0].material = undefined;
86
+ }
87
+
88
+ get_texture()
74
89
  {
75
- const points = new Points(geometry, material);
76
- points.frustumCulled = false;
77
- // let scene = new Scene();
78
- // scene.add( points );
79
- this.update_scene.add(points);
80
- Graphics.render(this.update_scene, undefined, RT);
81
- // Graphics.render(scene, undefined, RT);
90
+ return this.read.texture;
82
91
  }
83
92
  }
@@ -1,20 +1,40 @@
1
+ import { BufferAttribute } from 'three';
2
+
1
3
  import ParticleAttribute from '../gpu_particles/ParticleAttribute';
2
- import PositionStorageMaterial from '../materials/gpu_particles/PositionStorageMaterial';
4
+ import ParticleStorageMaterial from '../materials/gpu_particles/ParticleStorageMaterial';
3
5
 
4
6
  export default class ParticlePositionAttribute extends ParticleAttribute
5
7
  {
6
- constructor()
8
+ constructor(update_material)
7
9
  {
8
- super('_Position');
10
+ super('_Position', update_material);
9
11
  }
10
12
 
11
- init_from_geometry(geometry)
13
+ store_geometry(geometry, attribute_writter_scene)
12
14
  {
13
15
  const pos_attr = geometry.getAttribute('position');
14
16
  this.read = this.build_RT(pos_attr.count);
15
17
  this.write = this.build_RT(pos_attr.count);
16
18
 
17
- const mat = new PositionStorageMaterial();
18
- this.render_geometry_to_RT(geometry, mat, this.read);
19
+ const mat = new ParticleStorageMaterial();
20
+ this.store_geometry_attribute_in_RT(geometry.getAttribute('position'), this.read, mat, attribute_writter_scene);
21
+ }
22
+
23
+ store_positions(positions, attribute_writter_scene)
24
+ {
25
+ this.read = this.build_RT(positions.length);
26
+ this.write = this.build_RT(positions.length);
27
+
28
+ const arr = new Float32Array(positions.length * 4);
29
+
30
+ for (let i = 0; i < positions.length; i++)
31
+ {
32
+ arr[i * 4 + 0] = positions[i].x;
33
+ arr[i * 4 + 1] = positions[i].y;
34
+ arr[i * 4 + 2] = positions[i].z;
35
+ arr[i * 4 + 3] = (Math.random() * 2 - 1) * 10;
36
+ }
37
+ const mat = new ParticleStorageMaterial();
38
+ this.store_geometry_attribute_in_RT(new BufferAttribute(arr, 4), this.read, mat, attribute_writter_scene);
19
39
  }
20
40
  }
package/src/index.js CHANGED
@@ -82,6 +82,8 @@ import DualFilteringBlurrer from './render_utilities/DualFilteringBlurrer';
82
82
  import Blurrer from './render_utilities/Blurrer';
83
83
 
84
84
  import GPUParticleSystem from './gpu_particles/GPUParticleSystem';
85
+ import ParticleAttribute from './gpu_particles/ParticleAttribute';
86
+ import ParticlePositionAttribute from './gpu_particles/ParticlePositionAttribute';
85
87
 
86
88
  import DualFilteringBlurMaterial from './materials/DualFilteringBlurMaterial';
87
89
  import * as BufferGeometryUtils from 'three/examples/jsm/utils/BufferGeometryUtils.js';
@@ -187,6 +189,8 @@ export {
187
189
  DualFilteringBlurrer,
188
190
 
189
191
  GPUParticleSystem,
192
+ ParticleAttribute,
193
+ ParticlePositionAttribute,
190
194
  PerspectiveFrustumPointFitter,
191
195
  OrthographicFrustumPointFitter,
192
196
 
@@ -1,17 +1,24 @@
1
1
  import frag from '../../shaders/gpu_particles/generic_storage.frag';
2
- import common_utils from '../../shaders/gpu_particles/common_utils.glsl';
3
-
4
2
  import { ShaderMaterial } from 'three';
5
- import { ShaderChunk } from 'three';
6
3
  import { NoBlending } from 'three';
7
4
  import { AlwaysDepth } from 'three';
8
5
 
9
6
  export default class ParticleStorageMaterial extends ShaderMaterial
10
7
  {
11
- constructor(vert)
8
+ constructor()
12
9
  {
13
- ShaderChunk.gpu_particles_utils = common_utils;
10
+ const vert = `
11
+ varying vec4 value;
12
+ attribute vec4 data;
13
+
14
+ void main()
15
+ {
16
+ gl_Position = vec4(position.xy * 2.0 - 1.0, 1.0,1.0);
17
+ gl_PointSize = 1.0;
14
18
 
19
+ value = data;
20
+ }
21
+ `;
15
22
  super({
16
23
  uniforms: {
17
24
 
@@ -1,10 +1,25 @@
1
1
  import ParticleStorageMaterial from '../../materials/gpu_particles/ParticleStorageMaterial';
2
- import vert from '../../shaders/gpu_particles/store/store_position.vert';
3
2
 
4
3
  export default class PositionStorageMaterial extends ParticleStorageMaterial
5
4
  {
6
5
  constructor()
7
6
  {
7
+ const vert = `
8
+
9
+ varying vec4 value;
10
+
11
+ attribute vec2 storage_uv;
12
+
13
+
14
+ void main()
15
+ {
16
+ gl_Position = vec4(storage_uv * 2.0 - 1.0, 1.0,1.0);
17
+ gl_PointSize = 1.0;
18
+
19
+ value = vec4(position.xyz, 1.0);
20
+ }
21
+
22
+ `;
8
23
  super(vert);
9
24
  }
10
25
  }
@@ -2,6 +2,5 @@ varying vec4 value;
2
2
 
3
3
  void main()
4
4
  {
5
- //gl_FragColor = vec4(5.0, 0.0, 0.0, 1.0);
6
5
  gl_FragColor = value;
7
6
  }