@zephyr3d/scene 0.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.
Files changed (236) hide show
  1. package/dist/animation/animation.js +173 -0
  2. package/dist/animation/animation.js.map +1 -0
  3. package/dist/animation/animationset.js +95 -0
  4. package/dist/animation/animationset.js.map +1 -0
  5. package/dist/animation/animationtrack.js +38 -0
  6. package/dist/animation/animationtrack.js.map +1 -0
  7. package/dist/animation/eulerrotationtrack.js +33 -0
  8. package/dist/animation/eulerrotationtrack.js.map +1 -0
  9. package/dist/animation/rotationtrack.js +37 -0
  10. package/dist/animation/rotationtrack.js.map +1 -0
  11. package/dist/animation/scaletrack.js +36 -0
  12. package/dist/animation/scaletrack.js.map +1 -0
  13. package/dist/animation/skeleton.js +97 -0
  14. package/dist/animation/skeleton.js.map +1 -0
  15. package/dist/animation/translationtrack.js +36 -0
  16. package/dist/animation/translationtrack.js.map +1 -0
  17. package/dist/animation/usertrack.js +47 -0
  18. package/dist/animation/usertrack.js.map +1 -0
  19. package/dist/app.js +173 -0
  20. package/dist/app.js.map +1 -0
  21. package/dist/asset/assetmanager.js +476 -0
  22. package/dist/asset/assetmanager.js.map +1 -0
  23. package/dist/asset/builtin.js +373 -0
  24. package/dist/asset/builtin.js.map +1 -0
  25. package/dist/asset/loaders/dds/dds.js +472 -0
  26. package/dist/asset/loaders/dds/dds.js.map +1 -0
  27. package/dist/asset/loaders/dds/dds_loader.js +38 -0
  28. package/dist/asset/loaders/dds/dds_loader.js.map +1 -0
  29. package/dist/asset/loaders/gltf/gltf_loader.js +981 -0
  30. package/dist/asset/loaders/gltf/gltf_loader.js.map +1 -0
  31. package/dist/asset/loaders/gltf/helpers.js +314 -0
  32. package/dist/asset/loaders/gltf/helpers.js.map +1 -0
  33. package/dist/asset/loaders/hdr/hdr.js +175 -0
  34. package/dist/asset/loaders/hdr/hdr.js.map +1 -0
  35. package/dist/asset/loaders/image/tga_Loader.js +117 -0
  36. package/dist/asset/loaders/image/tga_Loader.js.map +1 -0
  37. package/dist/asset/loaders/image/webimage_loader.js +50 -0
  38. package/dist/asset/loaders/image/webimage_loader.js.map +1 -0
  39. package/dist/asset/loaders/loader.js +45 -0
  40. package/dist/asset/loaders/loader.js.map +1 -0
  41. package/dist/asset/model.js +264 -0
  42. package/dist/asset/model.js.map +1 -0
  43. package/dist/blitter/blitter.js +389 -0
  44. package/dist/blitter/blitter.js.map +1 -0
  45. package/dist/blitter/box.js +118 -0
  46. package/dist/blitter/box.js.map +1 -0
  47. package/dist/blitter/copy.js +22 -0
  48. package/dist/blitter/copy.js.map +1 -0
  49. package/dist/blitter/depthlimitedgaussion.js +166 -0
  50. package/dist/blitter/depthlimitedgaussion.js.map +1 -0
  51. package/dist/blitter/gaussianblur.js +229 -0
  52. package/dist/blitter/gaussianblur.js.map +1 -0
  53. package/dist/camera/base.js +90 -0
  54. package/dist/camera/base.js.map +1 -0
  55. package/dist/camera/camera.js +358 -0
  56. package/dist/camera/camera.js.map +1 -0
  57. package/dist/camera/fps.js +246 -0
  58. package/dist/camera/fps.js.map +1 -0
  59. package/dist/camera/orbit.js +157 -0
  60. package/dist/camera/orbit.js.map +1 -0
  61. package/dist/camera/orthocamera.js +126 -0
  62. package/dist/camera/orthocamera.js.map +1 -0
  63. package/dist/camera/perspectivecamera.js +133 -0
  64. package/dist/camera/perspectivecamera.js.map +1 -0
  65. package/dist/index.d.ts +8402 -0
  66. package/dist/index.js +87 -0
  67. package/dist/index.js.map +1 -0
  68. package/dist/input/inputmgr.js +242 -0
  69. package/dist/input/inputmgr.js.map +1 -0
  70. package/dist/material/blinn.js +75 -0
  71. package/dist/material/blinn.js.map +1 -0
  72. package/dist/material/grassmaterial.js +221 -0
  73. package/dist/material/grassmaterial.js.map +1 -0
  74. package/dist/material/lambert.js +52 -0
  75. package/dist/material/lambert.js.map +1 -0
  76. package/dist/material/lightmodel.js +2074 -0
  77. package/dist/material/lightmodel.js.map +1 -0
  78. package/dist/material/lit.js +578 -0
  79. package/dist/material/lit.js.map +1 -0
  80. package/dist/material/material.js +458 -0
  81. package/dist/material/material.js.map +1 -0
  82. package/dist/material/meshmaterial.js +311 -0
  83. package/dist/material/meshmaterial.js.map +1 -0
  84. package/dist/material/mixins/albedocolor.js +130 -0
  85. package/dist/material/mixins/albedocolor.js.map +1 -0
  86. package/dist/material/mixins/texture.js +110 -0
  87. package/dist/material/mixins/texture.js.map +1 -0
  88. package/dist/material/mixins/vertexcolor.js +45 -0
  89. package/dist/material/mixins/vertexcolor.js.map +1 -0
  90. package/dist/material/pbr.js +27 -0
  91. package/dist/material/pbr.js.map +1 -0
  92. package/dist/material/standard.js +282 -0
  93. package/dist/material/standard.js.map +1 -0
  94. package/dist/material/terrainlightmodel.js +259 -0
  95. package/dist/material/terrainlightmodel.js.map +1 -0
  96. package/dist/material/terrainmaterial.js +139 -0
  97. package/dist/material/terrainmaterial.js.map +1 -0
  98. package/dist/material/unlit.js +29 -0
  99. package/dist/material/unlit.js.map +1 -0
  100. package/dist/posteffect/bloom.js +398 -0
  101. package/dist/posteffect/bloom.js.map +1 -0
  102. package/dist/posteffect/compositor.js +264 -0
  103. package/dist/posteffect/compositor.js.map +1 -0
  104. package/dist/posteffect/fxaa.js +291 -0
  105. package/dist/posteffect/fxaa.js.map +1 -0
  106. package/dist/posteffect/grayscale.js +87 -0
  107. package/dist/posteffect/grayscale.js.map +1 -0
  108. package/dist/posteffect/posteffect.js +165 -0
  109. package/dist/posteffect/posteffect.js.map +1 -0
  110. package/dist/posteffect/sao.js +327 -0
  111. package/dist/posteffect/sao.js.map +1 -0
  112. package/dist/posteffect/tonemap.js +112 -0
  113. package/dist/posteffect/tonemap.js.map +1 -0
  114. package/dist/posteffect/water.js +535 -0
  115. package/dist/posteffect/water.js.map +1 -0
  116. package/dist/render/clipmap.js +462 -0
  117. package/dist/render/clipmap.js.map +1 -0
  118. package/dist/render/cluster_light.js +329 -0
  119. package/dist/render/cluster_light.js.map +1 -0
  120. package/dist/render/cull_visitor.js +124 -0
  121. package/dist/render/cull_visitor.js.map +1 -0
  122. package/dist/render/depth_pass.js +47 -0
  123. package/dist/render/depth_pass.js.map +1 -0
  124. package/dist/render/envlight.js +282 -0
  125. package/dist/render/envlight.js.map +1 -0
  126. package/dist/render/forward.js +186 -0
  127. package/dist/render/forward.js.map +1 -0
  128. package/dist/render/forward_pass.js +137 -0
  129. package/dist/render/forward_pass.js.map +1 -0
  130. package/dist/render/helper.js +38 -0
  131. package/dist/render/helper.js.map +1 -0
  132. package/dist/render/primitive.js +246 -0
  133. package/dist/render/primitive.js.map +1 -0
  134. package/dist/render/render_queue.js +163 -0
  135. package/dist/render/render_queue.js.map +1 -0
  136. package/dist/render/renderpass.js +151 -0
  137. package/dist/render/renderpass.js.map +1 -0
  138. package/dist/render/renderscheme.js +61 -0
  139. package/dist/render/renderscheme.js.map +1 -0
  140. package/dist/render/scatteringlut.js +634 -0
  141. package/dist/render/scatteringlut.js.map +1 -0
  142. package/dist/render/shadowmap_pass.js +70 -0
  143. package/dist/render/shadowmap_pass.js.map +1 -0
  144. package/dist/render/sky.js +881 -0
  145. package/dist/render/sky.js.map +1 -0
  146. package/dist/render/temporalcache.js +222 -0
  147. package/dist/render/temporalcache.js.map +1 -0
  148. package/dist/render/watermesh.js +835 -0
  149. package/dist/render/watermesh.js.map +1 -0
  150. package/dist/scene/environment.js +146 -0
  151. package/dist/scene/environment.js.map +1 -0
  152. package/dist/scene/graph_node.js +69 -0
  153. package/dist/scene/graph_node.js.map +1 -0
  154. package/dist/scene/light.js +436 -0
  155. package/dist/scene/light.js.map +1 -0
  156. package/dist/scene/mesh.js +215 -0
  157. package/dist/scene/mesh.js.map +1 -0
  158. package/dist/scene/model.js +111 -0
  159. package/dist/scene/model.js.map +1 -0
  160. package/dist/scene/octree.js +651 -0
  161. package/dist/scene/octree.js.map +1 -0
  162. package/dist/scene/octree_update_visitor.js +16 -0
  163. package/dist/scene/octree_update_visitor.js.map +1 -0
  164. package/dist/scene/raycast_visitor.js +72 -0
  165. package/dist/scene/raycast_visitor.js.map +1 -0
  166. package/dist/scene/scene.js +225 -0
  167. package/dist/scene/scene.js.map +1 -0
  168. package/dist/scene/scene_node.js +299 -0
  169. package/dist/scene/scene_node.js.map +1 -0
  170. package/dist/scene/terrain/grass.js +277 -0
  171. package/dist/scene/terrain/grass.js.map +1 -0
  172. package/dist/scene/terrain/heightfield.js +391 -0
  173. package/dist/scene/terrain/heightfield.js.map +1 -0
  174. package/dist/scene/terrain/patch.js +530 -0
  175. package/dist/scene/terrain/patch.js.map +1 -0
  176. package/dist/scene/terrain/quadtree.js +430 -0
  177. package/dist/scene/terrain/quadtree.js.map +1 -0
  178. package/dist/scene/terrain/terrain.js +258 -0
  179. package/dist/scene/terrain/terrain.js.map +1 -0
  180. package/dist/scene/xform.js +224 -0
  181. package/dist/scene/xform.js.map +1 -0
  182. package/dist/shaders/builtins.js +110 -0
  183. package/dist/shaders/builtins.js.map +1 -0
  184. package/dist/shaders/framework.js +709 -0
  185. package/dist/shaders/framework.js.map +1 -0
  186. package/dist/shaders/lighting.js +335 -0
  187. package/dist/shaders/lighting.js.map +1 -0
  188. package/dist/shaders/misc.js +405 -0
  189. package/dist/shaders/misc.js.map +1 -0
  190. package/dist/shaders/noise.js +157 -0
  191. package/dist/shaders/noise.js.map +1 -0
  192. package/dist/shaders/pbr.js +132 -0
  193. package/dist/shaders/pbr.js.map +1 -0
  194. package/dist/shaders/shadow.js +642 -0
  195. package/dist/shaders/shadow.js.map +1 -0
  196. package/dist/shaders/water.js +630 -0
  197. package/dist/shaders/water.js.map +1 -0
  198. package/dist/shadow/esm.js +235 -0
  199. package/dist/shadow/esm.js.map +1 -0
  200. package/dist/shadow/pcf_opt.js +182 -0
  201. package/dist/shadow/pcf_opt.js.map +1 -0
  202. package/dist/shadow/pcf_pd.js +190 -0
  203. package/dist/shadow/pcf_pd.js.map +1 -0
  204. package/dist/shadow/shadow_impl.js +15 -0
  205. package/dist/shadow/shadow_impl.js.map +1 -0
  206. package/dist/shadow/shadowmapper.js +709 -0
  207. package/dist/shadow/shadowmapper.js.map +1 -0
  208. package/dist/shadow/ssm.js +194 -0
  209. package/dist/shadow/ssm.js.map +1 -0
  210. package/dist/shadow/vsm.js +298 -0
  211. package/dist/shadow/vsm.js.map +1 -0
  212. package/dist/shapes/box.js +313 -0
  213. package/dist/shapes/box.js.map +1 -0
  214. package/dist/shapes/cylinder.js +74 -0
  215. package/dist/shapes/cylinder.js.map +1 -0
  216. package/dist/shapes/plane.js +48 -0
  217. package/dist/shapes/plane.js.map +1 -0
  218. package/dist/shapes/shape.js +33 -0
  219. package/dist/shapes/shape.js.map +1 -0
  220. package/dist/shapes/sphere.js +91 -0
  221. package/dist/shapes/sphere.js.map +1 -0
  222. package/dist/shapes/torus.js +100 -0
  223. package/dist/shapes/torus.js.map +1 -0
  224. package/dist/utility/aabbtree.js +390 -0
  225. package/dist/utility/aabbtree.js.map +1 -0
  226. package/dist/utility/bounding_volume.js +78 -0
  227. package/dist/utility/bounding_volume.js.map +1 -0
  228. package/dist/utility/panorama.js +163 -0
  229. package/dist/utility/panorama.js.map +1 -0
  230. package/dist/utility/pmrem.js +345 -0
  231. package/dist/utility/pmrem.js.map +1 -0
  232. package/dist/utility/shprojection.js +448 -0
  233. package/dist/utility/shprojection.js.map +1 -0
  234. package/dist/values.js +48 -0
  235. package/dist/values.js.map +1 -0
  236. package/package.json +70 -0
@@ -0,0 +1,329 @@
1
+ import { Vector4, Matrix4x4 } from '@zephyr3d/base';
2
+ import { Application } from '../app.js';
3
+ import { MAX_CLUSTERED_LIGHTS } from '../values.js';
4
+
5
+ class ClusteredLight {
6
+ _tileCountX;
7
+ _tileCountY;
8
+ _tileCountZ;
9
+ _lights;
10
+ _lightIndexTexture;
11
+ _lightIndexFramebuffer;
12
+ _lightIndexProgram;
13
+ _bindGroup;
14
+ _lightIndexVertexLayout;
15
+ _lightIndexRenderStates;
16
+ _lightBuffer;
17
+ _sizeParam;
18
+ _countParam;
19
+ _clusterParam;
20
+ constructor(){
21
+ this._tileCountX = 16;
22
+ this._tileCountY = 16;
23
+ this._tileCountZ = 32;
24
+ this._lights = new Float32Array(12 * (MAX_CLUSTERED_LIGHTS + 1));
25
+ this._lightIndexTexture = null;
26
+ this._lightIndexFramebuffer = null;
27
+ this._lightIndexProgram = null;
28
+ this._lightBuffer = null;
29
+ this._bindGroup = null;
30
+ this._lightIndexVertexLayout = null;
31
+ this._lightIndexRenderStates = null;
32
+ this._sizeParam = new Vector4();
33
+ this._countParam = new Int32Array(4);
34
+ this._clusterParam = new Vector4();
35
+ }
36
+ get lightBuffer() {
37
+ return this._lightBuffer;
38
+ }
39
+ get clusterParam() {
40
+ return this._clusterParam;
41
+ }
42
+ get countParam() {
43
+ return this._countParam;
44
+ }
45
+ get lightIndexTexture() {
46
+ return this._lightIndexTexture;
47
+ }
48
+ createVertexLayout(device, textureWidth, textureHeight) {
49
+ let vb;
50
+ if (device.type === 'webgl') {
51
+ const vertices = new Float32Array(this._tileCountX * this._tileCountY * this._tileCountZ * 3);
52
+ for(let i = 0; i < vertices.length; i++){
53
+ const ix = i % textureWidth;
54
+ const iy = Math.floor(i / textureWidth);
55
+ vertices[i * 3 + 0] = 2 * (ix + 0.5) / textureWidth - 1;
56
+ vertices[i * 3 + 1] = 2 * (iy + 0.5) / textureHeight - 1;
57
+ vertices[i * 3 + 2] = i;
58
+ }
59
+ vb = device.createVertexBuffer('position_f32x3', vertices);
60
+ } else {
61
+ const vertices = new Float32Array(this._tileCountX * this._tileCountY * this._tileCountZ * 2);
62
+ for(let i = 0; i < vertices.length; i++){
63
+ const ix = i % textureWidth;
64
+ const iy = Math.floor(i / textureWidth);
65
+ vertices[i * 2 + 0] = 2 * (ix + 0.5) / textureWidth - 1;
66
+ vertices[i * 2 + 1] = 2 * (iy + 0.5) / textureHeight - 1;
67
+ }
68
+ vb = device.createVertexBuffer('position_f32x2', vertices);
69
+ }
70
+ this._lightIndexVertexLayout = device.createVertexLayout({
71
+ vertexBuffers: [
72
+ {
73
+ buffer: vb
74
+ }
75
+ ]
76
+ });
77
+ }
78
+ createRenderState(device) {
79
+ this._lightIndexRenderStates = device.createRenderStateSet();
80
+ this._lightIndexRenderStates.useDepthState().enableTest(false).enableWrite(false);
81
+ this._lightIndexRenderStates.useRasterizerState().setCullMode('none');
82
+ }
83
+ createProgram(device) {
84
+ const webgl1 = device.type === 'webgl';
85
+ this._lightIndexProgram = device.buildRenderProgram({
86
+ vertex (pb) {
87
+ this.$inputs.pos = (webgl1 ? pb.vec3() : pb.vec2()).attrib('position');
88
+ this.$outputs.value = webgl1 ? pb.vec4() : pb.uvec4();
89
+ this.invProjMatrix = pb.mat4().uniform(0);
90
+ this.viewMatrix = pb.mat4().uniform(0);
91
+ this.sizeParam = pb.vec4().uniform(0);
92
+ this.countParam = pb.ivec4().uniform(0);
93
+ this.lightBuffer = pb.vec4[(MAX_CLUSTERED_LIGHTS + 1) * 3]().uniformBuffer(0);
94
+ pb.func('lineIntersectionToZPlane', [
95
+ pb.vec3('a'),
96
+ pb.vec3('b'),
97
+ pb.float('zDistance')
98
+ ], function() {
99
+ this.$l.normal = pb.vec3(0, 0, 1);
100
+ this.$l.ab = pb.sub(this.b, this.a);
101
+ this.$l.t = pb.div(pb.sub(this.zDistance, pb.dot(this.normal, this.a)), pb.dot(this.normal, this.ab));
102
+ this.$return(pb.add(this.a, pb.mul(this.t, this.ab)));
103
+ });
104
+ pb.func('clipToView', [
105
+ pb.vec4('clip')
106
+ ], function() {
107
+ this.$l.view = pb.mul(this.invProjMatrix, this.clip);
108
+ this.$return(pb.div(this.view, this.view.w));
109
+ });
110
+ pb.func('screenToView', [
111
+ pb.vec4('screen')
112
+ ], function() {
113
+ this.$l.texCoord = pb.div(this.screen.xy, this.sizeParam.xy);
114
+ this.$l.clip = pb.vec4(pb.sub(pb.mul(pb.vec2(this.texCoord.x, pb.sub(1, this.texCoord.y)), 2), pb.vec2(1)), this.screen.z, this.screen.w);
115
+ this.$return(this.clipToView(this.clip));
116
+ });
117
+ pb.func('sphereIntersectsAABB', [
118
+ pb.vec4('sphere'),
119
+ pb.vec3('aabbMin'),
120
+ pb.vec3('aabbMax')
121
+ ], function() {
122
+ this.$l.dmin = pb.float(0);
123
+ this.$if(pb.lessThanEqual(this.sphere.w, 0), function() {
124
+ this.$return(true);
125
+ });
126
+ this.$for(pb.int('i'), 0, 3, function() {
127
+ this.$if(pb.lessThan(this.sphere.at(this.i), this.aabbMin.at(this.i)), function() {
128
+ this.$l.delta = pb.sub(this.sphere.at(this.i), this.aabbMin.at(this.i));
129
+ this.dmin = pb.add(this.dmin, pb.mul(this.delta, this.delta));
130
+ }).$elseif(pb.greaterThan(this.sphere.at(this.i), this.aabbMax.at(this.i)), function() {
131
+ this.$l.delta = pb.sub(this.sphere.at(this.i), this.aabbMax.at(this.i));
132
+ this.dmin = pb.add(this.dmin, pb.mul(this.delta, this.delta));
133
+ });
134
+ });
135
+ this.$if(pb.lessThanEqual(this.dmin, pb.mul(this.sphere.w, this.sphere.w)), function() {
136
+ this.$return(true);
137
+ });
138
+ this.$return(false);
139
+ });
140
+ pb.main(function() {
141
+ if (pb.getDevice().type !== 'webgpu') {
142
+ this.$builtins.pointSize = 1;
143
+ }
144
+ this.$builtins.position = pb.vec4(this.$inputs.pos.xy, 0, 1);
145
+ if (pb.getDevice().type === 'webgpu') {
146
+ this.$builtins.position = pb.mul(this.$builtins.position, pb.vec4(1, -1, 1, 1));
147
+ }
148
+ this.$l.tileIndex = webgl1 ? pb.int(this.$inputs.pos.z) : pb.int(this.$builtins.vertexIndex);
149
+ this.$l.tileSize = pb.div(this.sizeParam.xy, pb.vec2(this.countParam.xy));
150
+ this.$l.zIndex = pb.div(this.tileIndex, pb.mul(this.countParam.x, this.countParam.y));
151
+ this.$l.yIndex = pb.div(pb.sub(this.tileIndex, pb.mul(this.zIndex, this.countParam.x, this.countParam.y)), this.countParam.x);
152
+ this.$l.xIndex = pb.sub(this.tileIndex, pb.add(pb.mul(this.zIndex, this.countParam.x, this.countParam.y), pb.mul(this.yIndex, this.countParam.x)));
153
+ this.$l.maxPoint_sS = pb.vec4(pb.mul(pb.vec2(pb.float(pb.add(this.xIndex, 1)), pb.float(pb.add(this.yIndex, 1))), this.tileSize), 0.0, 1.0);
154
+ this.$l.minPoint_sS = pb.vec4(pb.mul(pb.vec2(pb.float(this.xIndex), pb.float(this.yIndex)), this.tileSize), 0.0, 1.0);
155
+ this.$l.maxPoint_vS = this.screenToView(this.maxPoint_sS).xyz;
156
+ this.$l.minPoint_vS = this.screenToView(this.minPoint_sS).xyz;
157
+ this.$l.tileNear = pb.mul(pb.neg(this.sizeParam.z), pb.pow(pb.div(this.sizeParam.w, this.sizeParam.z), pb.div(pb.float(this.zIndex), pb.float(this.countParam.z))));
158
+ this.$l.tileFar = pb.mul(pb.neg(this.sizeParam.z), pb.pow(pb.div(this.sizeParam.w, this.sizeParam.z), pb.div(pb.add(pb.float(this.zIndex), 1), pb.float(this.countParam.z))));
159
+ this.$l.eyePos = pb.vec3(0);
160
+ this.$l.minPointNear = this.lineIntersectionToZPlane(this.eyePos, this.minPoint_vS, this.tileNear);
161
+ this.$l.minPointFar = this.lineIntersectionToZPlane(this.eyePos, this.minPoint_vS, this.tileFar);
162
+ this.$l.maxPointNear = this.lineIntersectionToZPlane(this.eyePos, this.maxPoint_vS, this.tileNear);
163
+ this.$l.maxPointFar = this.lineIntersectionToZPlane(this.eyePos, this.maxPoint_vS, this.tileFar);
164
+ this.$l.aabbMin = pb.min(pb.min(this.minPointNear, this.minPointFar), pb.min(this.maxPointNear, this.maxPointFar));
165
+ this.$l.aabbMax = pb.max(pb.max(this.minPointNear, this.minPointFar), pb.max(this.maxPointNear, this.maxPointFar));
166
+ this.$l.n = pb.int(0);
167
+ if (webgl1) {
168
+ this.$l.lightIndices = pb.float[8]();
169
+ this.$for(pb.int('i'), 0, 8, function() {
170
+ this.lightIndices.setAt(this.i, 0);
171
+ });
172
+ this.$for(pb.int('i'), 1, 256, function() {
173
+ this.$if(pb.equal(this.i, this.countParam.w), function() {
174
+ this.$break();
175
+ });
176
+ this.$l.light = this.lightBuffer.at(pb.mul(this.i, 3));
177
+ this.$l.lightPos = pb.mul(this.viewMatrix, pb.vec4(this.light.xyz, 1));
178
+ this.$l.lightPos.w = this.light.w;
179
+ this.$if(this.sphereIntersectsAABB(this.lightPos, this.aabbMin, this.aabbMax), function() {
180
+ this.$for(pb.int('j'), 0, 8, function() {
181
+ this.$if(pb.equal(this.j, this.n), function() {
182
+ this.lightIndices.setAt(this.j, pb.float(this.i));
183
+ this.n = pb.add(this.n, 1);
184
+ this.$break();
185
+ });
186
+ });
187
+ this.$if(pb.equal(this.n, 8), function() {
188
+ this.$break();
189
+ });
190
+ });
191
+ });
192
+ this.$outputs.value.r = pb.add(pb.mul(this.lightIndices[0], 256), this.lightIndices[1]);
193
+ this.$outputs.value.g = pb.add(pb.mul(this.lightIndices[2], 256), this.lightIndices[3]);
194
+ this.$outputs.value.b = pb.add(pb.mul(this.lightIndices[4], 256), this.lightIndices[5]);
195
+ this.$outputs.value.a = pb.add(pb.mul(this.lightIndices[6], 256), this.lightIndices[7]);
196
+ } else {
197
+ this.$l.lightIndex = [
198
+ pb.uint(0),
199
+ pb.uint(0),
200
+ pb.uint(0),
201
+ pb.uint(0),
202
+ pb.uint(0),
203
+ pb.uint(0),
204
+ pb.uint(0),
205
+ pb.uint(0),
206
+ pb.uint(0),
207
+ pb.uint(0),
208
+ pb.uint(0),
209
+ pb.uint(0),
210
+ pb.uint(0),
211
+ pb.uint(0),
212
+ pb.uint(0),
213
+ pb.uint(0)
214
+ ];
215
+ this.$for(pb.uint('i'), 1, pb.uint(this.countParam.w), function() {
216
+ this.$l.light = this.lightBuffer.at(pb.mul(this.i, 3));
217
+ this.$l.lightPos = pb.mul(this.viewMatrix, pb.vec4(this.light.xyz, 1));
218
+ this.$l.lightPos.w = this.light.w;
219
+ this.$if(this.sphereIntersectsAABB(this.lightPos, this.aabbMin, this.aabbMax), function() {
220
+ this.lightIndex.setAt(this.n, this.i);
221
+ this.n = pb.add(this.n, 1);
222
+ this.$if(pb.equal(this.n, 16), function() {
223
+ this.$break();
224
+ });
225
+ });
226
+ });
227
+ this.$l.r = pb.add(pb.sal(this.lightIndex[0], 24), pb.sal(this.lightIndex[1], 16), pb.sal(this.lightIndex[2], 8), this.lightIndex[3]);
228
+ this.$l.g = pb.add(pb.sal(this.lightIndex[4], 24), pb.sal(this.lightIndex[5], 16), pb.sal(this.lightIndex[6], 8), this.lightIndex[7]);
229
+ this.$l.b = pb.add(pb.sal(this.lightIndex[8], 24), pb.sal(this.lightIndex[9], 16), pb.sal(this.lightIndex[10], 8), this.lightIndex[11]);
230
+ this.$l.a = pb.add(pb.sal(this.lightIndex[12], 24), pb.sal(this.lightIndex[13], 16), pb.sal(this.lightIndex[14], 8), this.lightIndex[15]);
231
+ this.$outputs.value = pb.uvec4(this.r, this.g, this.b, this.a);
232
+ }
233
+ });
234
+ },
235
+ fragment (pb) {
236
+ this.$outputs.color = webgl1 ? pb.vec4() : pb.uvec4();
237
+ pb.main(function() {
238
+ this.$outputs.color = this.$inputs.value;
239
+ });
240
+ }
241
+ });
242
+ this._bindGroup = device.createBindGroup(this._lightIndexProgram.bindGroupLayouts[0]);
243
+ this._lightBuffer?.dispose();
244
+ const lightBufferType = this._lightIndexProgram.getBindingInfo('lightBuffer').type;
245
+ this._lightBuffer = device.createStructuredBuffer(lightBufferType, {
246
+ usage: 'uniform'
247
+ });
248
+ }
249
+ createLightIndexTexture(device) {
250
+ const exp = Math.log2(this._tileCountX * this._tileCountY * this._tileCountZ);
251
+ const a = exp + 1 >>> 1;
252
+ const b = exp - a;
253
+ const textureWidth = 2 << a - 1;
254
+ const textureHeight = 2 << b - 1;
255
+ if (textureWidth * textureHeight !== this._tileCountX * this._tileCountY * this._tileCountZ) {
256
+ throw new Error('Internal error');
257
+ }
258
+ this._lightIndexTexture = device.createTexture2D(device.type === 'webgl' ? 'rgba32f' : 'rgba32ui', textureWidth, textureHeight, {
259
+ samplerOptions: {
260
+ mipFilter: 'none'
261
+ }
262
+ });
263
+ this._lightIndexTexture.name = 'ClusterLightIndex';
264
+ this._lightIndexFramebuffer?.dispose();
265
+ this._lightIndexFramebuffer = device.createFrameBuffer([
266
+ this._lightIndexTexture
267
+ ], null);
268
+ }
269
+ calculateLightIndex(camera, renderQueue) {
270
+ const numLights = this.getVisibleLights(renderQueue, this._lights);
271
+ const device = Application.instance.device;
272
+ if (!this._lightIndexTexture) {
273
+ this.createLightIndexTexture(device);
274
+ }
275
+ if (!this._lightIndexProgram) {
276
+ this.createProgram(device);
277
+ }
278
+ if (!this._lightIndexVertexLayout) {
279
+ this.createVertexLayout(device, this._lightIndexTexture.width, this._lightIndexTexture.height);
280
+ }
281
+ if (!this._lightIndexRenderStates) {
282
+ this.createRenderState(device);
283
+ }
284
+ const viewport = device.getViewport();
285
+ const vw = device.screenToDevice(viewport.width);
286
+ const vh = device.screenToDevice(viewport.height);
287
+ const scale = this._tileCountZ / Math.log2(camera.getFarPlane() / camera.getNearPlane());
288
+ const bias = -(this._tileCountZ * Math.log2(camera.getNearPlane()) / Math.log2(camera.getFarPlane() / camera.getNearPlane()));
289
+ this._clusterParam.setXYZW(vw, vh, scale, bias);
290
+ device.pushDeviceStates();
291
+ device.setFramebuffer(this._lightIndexFramebuffer);
292
+ if (numLights > 0) {
293
+ this._lightBuffer.bufferSubData(0, this._lights);
294
+ this._sizeParam.setXYZW(vw, vh, camera.getNearPlane(), camera.getFarPlane());
295
+ this._countParam[0] = this._tileCountX;
296
+ this._countParam[1] = this._tileCountY;
297
+ this._countParam[2] = this._tileCountZ;
298
+ this._countParam[3] = numLights + 1;
299
+ this._bindGroup.setValue('invProjMatrix', Matrix4x4.invert(camera.getProjectionMatrix()));
300
+ this._bindGroup.setValue('viewMatrix', camera.viewMatrix);
301
+ this._bindGroup.setValue('sizeParam', this._sizeParam);
302
+ this._bindGroup.setValue('countParam', this._countParam);
303
+ this._bindGroup.setBuffer('lightBuffer', this._lightBuffer);
304
+ device.setProgram(this._lightIndexProgram);
305
+ device.setVertexLayout(this._lightIndexVertexLayout);
306
+ device.setBindGroup(0, this._bindGroup);
307
+ const savedRS = device.getRenderStates();
308
+ device.setRenderStates(this._lightIndexRenderStates);
309
+ device.draw('point-list', 0, this._tileCountX * this._tileCountY * this._tileCountZ);
310
+ device.setRenderStates(savedRS);
311
+ } else {
312
+ device.clearFrameBuffer(new Vector4(0, 0, 0, 0), 1, 0);
313
+ }
314
+ device.popDeviceStates();
315
+ }
316
+ getVisibleLights(renderQueue, lights) {
317
+ const numLights = Math.min(renderQueue.unshadowedLights.length, MAX_CLUSTERED_LIGHTS);
318
+ for(let i = 1; i <= numLights; i++){
319
+ const light = renderQueue.unshadowedLights[i - 1];
320
+ lights.set(light.positionAndRange, i * 12);
321
+ lights.set(light.directionAndCutoff, i * 12 + 4);
322
+ lights.set(light.diffuseAndIntensity, i * 12 + 8);
323
+ }
324
+ return numLights;
325
+ }
326
+ }
327
+
328
+ export { ClusteredLight };
329
+ //# sourceMappingURL=cluster_light.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cluster_light.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,124 @@
1
+ import { ClipState } from '@zephyr3d/base';
2
+ import { OctreeNode } from '../scene/octree.js';
3
+ import { RENDER_PASS_TYPE_SHADOWMAP } from '../values.js';
4
+ import { GraphNode } from '../scene/graph_node.js';
5
+
6
+ /**
7
+ * Node visitor for culling
8
+ * @public
9
+ */ class CullVisitor {
10
+ /** @internal */ _primaryCamera;
11
+ /** @internal */ _camera;
12
+ /** @internal */ _skipClipTest;
13
+ /** @internal */ _renderQueue;
14
+ /** @internal */ _renderPass;
15
+ /**
16
+ * Creates an instance of CullVisitor
17
+ * @param renderPass - Render pass for the culling task
18
+ * @param camera - Camera that will be used for culling
19
+ * @param rendeQueue - RenderQueue
20
+ * @param viewPoint - Camera position of the primary render pass
21
+ */ constructor(renderPass, camera, renderQueue, primaryCamera){
22
+ this._primaryCamera = primaryCamera;
23
+ this._camera = camera;
24
+ this._renderQueue = renderQueue;
25
+ this._skipClipTest = false;
26
+ this._renderPass = renderPass;
27
+ }
28
+ /** The camera that will be used for culling */ get camera() {
29
+ return this._camera;
30
+ }
31
+ set camera(camera) {
32
+ this._camera = camera || null;
33
+ }
34
+ /** The camera position of the primary render pass */ get primaryCamera() {
35
+ return this._primaryCamera;
36
+ }
37
+ /** Render pass for the culling task */ get renderPass() {
38
+ return this._renderPass;
39
+ }
40
+ /** The result of culling */ get renderQueue() {
41
+ return this._renderQueue;
42
+ }
43
+ /** Frustum for culling */ get frustum() {
44
+ return this._camera?.frustum || null;
45
+ }
46
+ /** @internal */ push(camera, drawable, renderOrder) {
47
+ this.renderQueue.push(camera, drawable, renderOrder);
48
+ }
49
+ /**
50
+ * Visits a node
51
+ * @param target - The node to be visit
52
+ */ visit(target) {
53
+ if (target instanceof OctreeNode) {
54
+ return this.visitOctreeNode(target);
55
+ } else if (target.isMesh()) {
56
+ return this.visitMesh(target);
57
+ } else if (target.isTerrain()) {
58
+ return this.visitTerrain(target);
59
+ } else if (target.isPunctualLight()) {
60
+ return this.visitPunctualLight(target);
61
+ }
62
+ }
63
+ /** @internal */ visitPunctualLight(node) {
64
+ if (!node.hidden) {
65
+ const clipState = this.getClipStateWithNode(node);
66
+ if (clipState !== ClipState.NOT_CLIPPED) {
67
+ this.renderQueue.pushLight(node);
68
+ return true;
69
+ }
70
+ }
71
+ return false;
72
+ }
73
+ /** @internal */ visitTerrain(node) {
74
+ if (!node.hidden && (node.castShadow || this._renderPass.type !== RENDER_PASS_TYPE_SHADOWMAP)) {
75
+ const clipState = this.getClipStateWithNode(node);
76
+ if (clipState !== ClipState.NOT_CLIPPED) {
77
+ return node.cull(this) > 0;
78
+ }
79
+ }
80
+ return false;
81
+ }
82
+ /** @internal */ visitMesh(node) {
83
+ if (!node.hidden && (node.castShadow || this._renderPass.type !== RENDER_PASS_TYPE_SHADOWMAP)) {
84
+ const clipState = this.getClipStateWithNode(node);
85
+ if (clipState !== ClipState.NOT_CLIPPED) {
86
+ this.push(this._camera, node, node.renderOrder);
87
+ return true;
88
+ }
89
+ }
90
+ return false;
91
+ }
92
+ /** @internal */ visitOctreeNode(node) {
93
+ const clipState = node.getLevel() > 0 ? this.getClipStateWithAABB(node.getBoxLoosed()) : ClipState.CLIPPED;
94
+ if (clipState !== ClipState.NOT_CLIPPED) {
95
+ const saveSkipFlag = this._skipClipTest;
96
+ this._skipClipTest = clipState === ClipState.A_INSIDE_B;
97
+ const nodes = node.getNodes();
98
+ for(let i = 0; i < nodes.length; i++){
99
+ this.visit(nodes[i]);
100
+ }
101
+ this._skipClipTest = saveSkipFlag;
102
+ return true;
103
+ }
104
+ return false;
105
+ }
106
+ /** @internal */ getClipStateWithNode(node) {
107
+ let clipState;
108
+ if (this._skipClipTest) {
109
+ clipState = ClipState.A_INSIDE_B;
110
+ } else if (node.computedClipMode === GraphNode.CLIP_DISABLED) {
111
+ clipState = ClipState.CLIPPED;
112
+ } else {
113
+ const bv = node.getWorldBoundingVolume();
114
+ clipState = bv ? this.getClipStateWithAABB(bv.toAABB()) : ClipState.CLIPPED;
115
+ }
116
+ return clipState;
117
+ }
118
+ /** @internal */ getClipStateWithAABB(aabb) {
119
+ return this.camera.clipMask ? aabb.getClipStateWithFrustumMask(this.frustum, this.camera.clipMask) : aabb.getClipStateWithFrustum(this.frustum);
120
+ }
121
+ }
122
+
123
+ export { CullVisitor };
124
+ //# sourceMappingURL=cull_visitor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cull_visitor.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,47 @@
1
+ import { RenderPass } from './renderpass.js';
2
+ import { RENDER_PASS_TYPE_DEPTH_ONLY } from '../values.js';
3
+ import { ShaderFramework } from '../shaders/framework.js';
4
+ import '@zephyr3d/device';
5
+ import { Application } from '../app.js';
6
+
7
+ /**
8
+ * Depth render pass
9
+ *
10
+ * Scene depth render pass
11
+ *
12
+ * @public
13
+ */ class DepthRenderPass extends RenderPass {
14
+ /**
15
+ * Creates an instance of DepthRenderPass
16
+ */ constructor(){
17
+ super(RENDER_PASS_TYPE_DEPTH_ONLY);
18
+ }
19
+ /** @internal */ _getGlobalBindGroupHash(ctx) {
20
+ return '';
21
+ }
22
+ /** @internal */ renderItems(ctx, renderQueue) {
23
+ ctx.target = null;
24
+ ctx.applyFog = false;
25
+ ctx.drawEnvLight = false;
26
+ ctx.env = null;
27
+ ctx.renderPassHash = null;
28
+ ctx.flip = this.isAutoFlip();
29
+ const device = Application.instance.device;
30
+ const bindGroup = this.getGlobalBindGroupInfo(ctx).bindGroup;
31
+ device.setBindGroup(0, bindGroup);
32
+ ShaderFramework.setCameraUniforms(bindGroup, ctx, true);
33
+ ctx.renderPassHash = this.getGlobalBindGroupHash(ctx);
34
+ const reverseWinding = ctx.camera.worldMatrixDet < 0;
35
+ for (const order of Object.keys(renderQueue.items).map((val)=>Number(val)).sort((a, b)=>a - b)){
36
+ const renderItems = renderQueue.items[order];
37
+ for (const item of renderItems.opaqueList){
38
+ ctx.instanceData = item.instanceData;
39
+ ctx.target = item.drawable;
40
+ this.drawItem(device, item, ctx, reverseWinding);
41
+ }
42
+ }
43
+ }
44
+ }
45
+
46
+ export { DepthRenderPass };
47
+ //# sourceMappingURL=depth_pass.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"depth_pass.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}