chorama 0.0.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 (256) hide show
  1. package/.configs/tsconfig.lib.json +43 -0
  2. package/.configs/tsconfig.website.json +34 -0
  3. package/.github/workflows/static.yml +88 -0
  4. package/.vscode/launch.json +29 -0
  5. package/.vscode/tasks.json +19 -0
  6. package/README.md +127 -0
  7. package/assets/images/disappointed.jpg +0 -0
  8. package/assets/images/skybox/grimmnight_back.png +0 -0
  9. package/assets/images/skybox/grimmnight_bottom.png +0 -0
  10. package/assets/images/skybox/grimmnight_front.png +0 -0
  11. package/assets/images/skybox/grimmnight_left.png +0 -0
  12. package/assets/images/skybox/grimmnight_right.png +0 -0
  13. package/assets/images/skybox/grimmnight_top.png +0 -0
  14. package/assets/images/skybox/miramar_back.png +0 -0
  15. package/assets/images/skybox/miramar_bottom.png +0 -0
  16. package/assets/images/skybox/miramar_front.png +0 -0
  17. package/assets/images/skybox/miramar_left.png +0 -0
  18. package/assets/images/skybox/miramar_right.png +0 -0
  19. package/assets/images/skybox/miramar_top.png +0 -0
  20. package/assets/images/uv.jpg +0 -0
  21. package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_GlassPlasticMat_BaseColor.png +0 -0
  22. package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_GlassPlasticMat_Normal.png +0 -0
  23. package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_GlassPlasticMat_OcclusionRoughMetal.png +0 -0
  24. package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_LeatherPartsMat_BaseColor.png +0 -0
  25. package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_LeatherPartsMat_Normal.png +0 -0
  26. package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_LeatherPartsMat_OcclusionRoughMetal.png +0 -0
  27. package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_LensesMat_BaseColor.png +0 -0
  28. package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_LensesMat_Normal.png +0 -0
  29. package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_LensesMat_OcclusionRoughMetal.png +0 -0
  30. package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_MetalPartsMat_BaseColor.png +0 -0
  31. package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_MetalPartsMat_Normal.png +0 -0
  32. package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_MetalPartsMat_OcclusionRoughMetal.png +0 -0
  33. package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_RubberWoodMat_BaseColor.png +0 -0
  34. package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_RubberWoodMat_Normal.png +0 -0
  35. package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_RubberWoodMat_OcclusionRoughMetal.png +0 -0
  36. package/assets/models/gltf/flight_helmet/index.bin +0 -0
  37. package/assets/models/gltf/flight_helmet/index.gltf +705 -0
  38. package/assets/models/gltf/object.gltf +23 -0
  39. package/assets/models/gltf/pirate_girl/index.bin +0 -0
  40. package/assets/models/gltf/pirate_girl/index.gltf +2082 -0
  41. package/assets/models/obj/pirate_girl/pirate_girl.obj +18459 -0
  42. package/assets/models/obj/pirate_girl/pirate_girl.png +0 -0
  43. package/astro.config.mjs +45 -0
  44. package/content/guide/api-map.md +89 -0
  45. package/content/guide/camera-and-controls.md +98 -0
  46. package/content/guide/first-scene.md +176 -0
  47. package/content/guide/index.md +72 -0
  48. package/content/guide/installation.md +179 -0
  49. package/content/guide/materials-and-lighting.md +138 -0
  50. package/content/guide/plugins-and-render-pipeline.md +124 -0
  51. package/content/guide/render-targets-and-views.md +147 -0
  52. package/content/guide/scene-graph-and-transforms.md +113 -0
  53. package/content/guide/textures-and-assets.md +120 -0
  54. package/content/guide/troubleshooting.md +49 -0
  55. package/env.d.ts +19 -0
  56. package/examples/addons/rendergraph_gui.js +580 -0
  57. package/examples/camera/orthographic.js +120 -0
  58. package/examples/camera/perspective.js +138 -0
  59. package/examples/lights/directional.js +397 -0
  60. package/examples/lights/multiple_spot_lights.js +304 -0
  61. package/examples/lights/point.js +337 -0
  62. package/examples/lights/spot.js +366 -0
  63. package/examples/loader/gltf_material.js +111 -0
  64. package/examples/loader/gltfloader.js +78 -0
  65. package/examples/loader/objloader.js +95 -0
  66. package/examples/material/cullface.js +111 -0
  67. package/examples/material/materials.js +126 -0
  68. package/examples/material/standard/basic.js +164 -0
  69. package/examples/mesh/circle.js +117 -0
  70. package/examples/mesh/cuboid.js +151 -0
  71. package/examples/mesh/cylinder.js +139 -0
  72. package/examples/mesh/geometries.js +108 -0
  73. package/examples/mesh/meshTopology.js +103 -0
  74. package/examples/mesh/plane.js +117 -0
  75. package/examples/mesh/skinning.js +136 -0
  76. package/examples/mesh/uvsphere.js +113 -0
  77. package/examples/other/rotatingCube.js +93 -0
  78. package/examples/other/rotatingSphere.js +96 -0
  79. package/examples/rendertarget/basic_canvas.js +130 -0
  80. package/examples/rendertarget/depth_texture.js +130 -0
  81. package/examples/rendertarget/image_target.js +140 -0
  82. package/examples/rendertarget/multiple_views.js +158 -0
  83. package/examples/rendertarget/render_masks.js +173 -0
  84. package/examples/rendertarget/split_screen.js +123 -0
  85. package/examples/rendertarget/split_view.js +137 -0
  86. package/examples/skybox/skybox.js +111 -0
  87. package/examples/texture/arrays.js +156 -0
  88. package/examples/texture/textureWrap.js +118 -0
  89. package/examples/transform/propagation.js +92 -0
  90. package/package.json +55 -0
  91. package/rollup.config.js +66 -0
  92. package/scripts/stage-chorama.mjs +29 -0
  93. package/src/caches/cache.js +420 -0
  94. package/src/caches/index.js +2 -0
  95. package/src/caches/uniformbuffers.js +104 -0
  96. package/src/cameracontrols/index.js +258 -0
  97. package/src/constants/index.js +3 -0
  98. package/src/constants/mesh.js +197 -0
  99. package/src/constants/others.js +218 -0
  100. package/src/constants/texture.js +183 -0
  101. package/src/core/constants.js +14 -0
  102. package/src/core/extensions.js +42 -0
  103. package/src/core/index.js +7 -0
  104. package/src/core/layouts/index.js +4 -0
  105. package/src/core/layouts/meshvertex.js +60 -0
  106. package/src/core/layouts/uniform.js +21 -0
  107. package/src/core/layouts/uniformbuffer.js +15 -0
  108. package/src/core/layouts/vertexbuffer.js +43 -0
  109. package/src/core/limits.js +247 -0
  110. package/src/core/resources/blendparams.js +89 -0
  111. package/src/core/resources/framebuffer.js +127 -0
  112. package/src/core/resources/gpubuffer.js +32 -0
  113. package/src/core/resources/gpumesh.js +43 -0
  114. package/src/core/resources/gputexture.js +73 -0
  115. package/src/core/resources/index.js +5 -0
  116. package/src/core/shader.js +62 -0
  117. package/src/core/webgl/bindgroup.js +89 -0
  118. package/src/core/webgl/descriptors.js +104 -0
  119. package/src/core/webgl/index.js +5 -0
  120. package/src/core/webgl/renderpassencoder.js +96 -0
  121. package/src/core/webgl/renderpipeline.js +54 -0
  122. package/src/core/webgl/utils.js +371 -0
  123. package/src/core/webgl/webglrenderdevice.js +235 -0
  124. package/src/function.js +358 -0
  125. package/src/index.js +15 -0
  126. package/src/loader/gltf.js +2172 -0
  127. package/src/loader/index.js +3 -0
  128. package/src/loader/loader.js +174 -0
  129. package/src/loader/obj.js +188 -0
  130. package/src/loader/texture.js +85 -0
  131. package/src/loader/utils.js +16 -0
  132. package/src/material/basic.js +75 -0
  133. package/src/material/depth.js +73 -0
  134. package/src/material/index.js +8 -0
  135. package/src/material/lambert.js +73 -0
  136. package/src/material/material.js +106 -0
  137. package/src/material/normal.js +30 -0
  138. package/src/material/phong.js +86 -0
  139. package/src/material/raw.js +52 -0
  140. package/src/material/standard.js +221 -0
  141. package/src/math/index.js +3 -0
  142. package/src/math/transform.js +38 -0
  143. package/src/mesh/attribute/attribute.js +79 -0
  144. package/src/mesh/attribute/index.js +1 -0
  145. package/src/mesh/attributedata/index.js +1 -0
  146. package/src/mesh/attributedata/separate.js +180 -0
  147. package/src/mesh/builders/base.js +41 -0
  148. package/src/mesh/builders/circle.js +63 -0
  149. package/src/mesh/builders/cuboid.js +135 -0
  150. package/src/mesh/builders/cylinder.js +131 -0
  151. package/src/mesh/builders/index.js +7 -0
  152. package/src/mesh/builders/plane.js +73 -0
  153. package/src/mesh/builders/utils.js +20 -0
  154. package/src/mesh/builders/uvsphere.js +80 -0
  155. package/src/mesh/builders/wireframe.js +62 -0
  156. package/src/mesh/index.js +4 -0
  157. package/src/mesh/mesh.js +149 -0
  158. package/src/objects/bone.js +17 -0
  159. package/src/objects/camera/camera.js +56 -0
  160. package/src/objects/camera/index.js +2 -0
  161. package/src/objects/camera/projection.js +203 -0
  162. package/src/objects/debug/index.js +1 -0
  163. package/src/objects/debug/skeleton.js +28 -0
  164. package/src/objects/index.js +7 -0
  165. package/src/objects/light/ambient.js +20 -0
  166. package/src/objects/light/directional.js +29 -0
  167. package/src/objects/light/index.js +5 -0
  168. package/src/objects/light/point.js +32 -0
  169. package/src/objects/light/shadow/index.js +1 -0
  170. package/src/objects/light/shadow/shadow.js +67 -0
  171. package/src/objects/light/spot.js +56 -0
  172. package/src/objects/mesh.js +141 -0
  173. package/src/objects/object3d.js +167 -0
  174. package/src/objects/skybox.js +38 -0
  175. package/src/plugins/camera/camera.js +19 -0
  176. package/src/plugins/camera/index.js +2 -0
  177. package/src/plugins/camera/nodes/cameraview.js +46 -0
  178. package/src/plugins/camera/nodes/index.js +2 -0
  179. package/src/plugins/camera/nodes/opaquepass.js +79 -0
  180. package/src/plugins/index.js +6 -0
  181. package/src/plugins/light/index.js +2 -0
  182. package/src/plugins/light/light.js +23 -0
  183. package/src/plugins/light/nodes/index.js +1 -0
  184. package/src/plugins/light/nodes/light.js +127 -0
  185. package/src/plugins/meshmaterial/index.js +3 -0
  186. package/src/plugins/meshmaterial/meshmaterial.js +381 -0
  187. package/src/plugins/meshmaterial/nodes/index.js +1 -0
  188. package/src/plugins/meshmaterial/nodes/meshmaterial.js +50 -0
  189. package/src/plugins/meshmaterial/resources/index.js +1 -0
  190. package/src/plugins/meshmaterial/resources/meshmaterialpipelines.js +50 -0
  191. package/src/plugins/shadow/index.js +3 -0
  192. package/src/plugins/shadow/nodes/index.js +3 -0
  193. package/src/plugins/shadow/nodes/shadow.js +272 -0
  194. package/src/plugins/shadow/nodes/shadowOccluder.js +112 -0
  195. package/src/plugins/shadow/nodes/shadowOpaquePass.js +73 -0
  196. package/src/plugins/shadow/resources/ShadowMap.js +99 -0
  197. package/src/plugins/shadow/resources/index.js +2 -0
  198. package/src/plugins/shadow/resources/shadowpipelines.js +25 -0
  199. package/src/plugins/shadow/shadow.js +31 -0
  200. package/src/plugins/skeletonhelper/index.js +1 -0
  201. package/src/plugins/skeletonhelper/skeletonhelper.js +160 -0
  202. package/src/plugins/skybox/index.js +3 -0
  203. package/src/plugins/skybox/nodes/index.js +1 -0
  204. package/src/plugins/skybox/nodes/skybox.js +143 -0
  205. package/src/plugins/skybox/resources/index.js +2 -0
  206. package/src/plugins/skybox/resources/skyboxmesh.js +14 -0
  207. package/src/plugins/skybox/resources/skyboxpipeline.js +6 -0
  208. package/src/plugins/skybox/skybox.js +137 -0
  209. package/src/renderer/core/index.js +179 -0
  210. package/src/renderer/graph/index.js +3 -0
  211. package/src/renderer/graph/nodes.js +34 -0
  212. package/src/renderer/graph/rendergraph.js +182 -0
  213. package/src/renderer/index.js +5 -0
  214. package/src/renderer/plugin.js +36 -0
  215. package/src/renderer/renderer.js +179 -0
  216. package/src/renderer/views.js +28 -0
  217. package/src/rendertarget/canvastarget.js +30 -0
  218. package/src/rendertarget/image.js +132 -0
  219. package/src/rendertarget/index.js +3 -0
  220. package/src/rendertarget/rendertarget.js +89 -0
  221. package/src/shader/basicFragment.glsl +30 -0
  222. package/src/shader/basicVertex.glsl +87 -0
  223. package/src/shader/common/color.glsl +7 -0
  224. package/src/shader/common/common.glsl +25 -0
  225. package/src/shader/common/index.js +4 -0
  226. package/src/shader/common/light.glsl +437 -0
  227. package/src/shader/common/math.glsl +12 -0
  228. package/src/shader/debug/index.js +2 -0
  229. package/src/shader/debug/skeletonFragment.glsl +8 -0
  230. package/src/shader/debug/skeletonVertex.glsl +27 -0
  231. package/src/shader/depthFragment.glsl +37 -0
  232. package/src/shader/index.js +11 -0
  233. package/src/shader/lambertFragment.glsl +126 -0
  234. package/src/shader/normalFragment.glsl +25 -0
  235. package/src/shader/phongFragment.glsl +140 -0
  236. package/src/shader/skyboxFragment.glsl +16 -0
  237. package/src/shader/skyboxVertex.glsl +20 -0
  238. package/src/shader/standardFragment.glsl +274 -0
  239. package/src/texture/index.js +2 -0
  240. package/src/texture/sampler.js +111 -0
  241. package/src/texture/texture.js +234 -0
  242. package/src/utils/index.js +115 -0
  243. package/tsconfig.json +11 -0
  244. package/website/config/index.ts +1 -0
  245. package/website/config/navigation.ts +53 -0
  246. package/website/content.config.ts +92 -0
  247. package/website/layouts/DocLayout.astro +501 -0
  248. package/website/layouts/Example.astro +91 -0
  249. package/website/pages/examples/[...slug].astro +77 -0
  250. package/website/pages/examples/index.astro +98 -0
  251. package/website/pages/examples/samples/[...slug].astro +17 -0
  252. package/website/pages/guide/[slug].astro +30 -0
  253. package/website/pages/guide/index.astro +21 -0
  254. package/website/pages/index.astro +9 -0
  255. package/website/plugins/remark-link-base.js +23 -0
  256. package/website/utils/url.ts +30 -0
@@ -0,0 +1,272 @@
1
+ import { Affine3, Matrix4, Vector3 } from "hisabati"
2
+ import { DirectionalLight, SpotLight, PointLight, PCFShadowFilter, PCSSShadowFilter } from "../../../objects"
3
+ import { Object3D, PerspectiveProjection } from "../../../objects"
4
+ import { Views, View } from "../../../renderer"
5
+ import { ShadowMap } from "../resources/ShadowMap"
6
+ import { assert } from "../../../utils"
7
+
8
+ const SHADOW_ITEM_BYTE_SIZE = 96
9
+
10
+ export class ShadowViewNode {
11
+ subgraph() {
12
+ return undefined
13
+ }
14
+
15
+ /**
16
+ * @param {import("src/renderer").RenderGraphContext} graphcontext
17
+ */
18
+ execute(graphcontext){
19
+ const {renderDevice: device, renderer, objects } = graphcontext
20
+ const { context } = device
21
+ const shadowMap = renderer.getResource(ShadowMap)
22
+ const views = renderer.getResource(Views)
23
+ /** @type {ShadowItem[]}*/
24
+ const blocks = []
25
+
26
+ assert(shadowMap, "Shadow map not set up.")
27
+ assert(views, "Views resource missing")
28
+
29
+ shadowMap.reset()
30
+ for (let i = 0; i < objects.length; i++) {
31
+ const object = /**@type {Object3D} */ (objects[i]);
32
+
33
+ object.traverseDFS((object) => {
34
+ const area = shadowMap.getOrSet(object)
35
+ const items = object instanceof DirectionalLight ?
36
+ buildDirectionalShadowPass(object, shadowMap) :
37
+ object instanceof SpotLight ?
38
+ buildSpotShadowPass(object, shadowMap) :
39
+ object instanceof PointLight ?
40
+ buildPointShadowPass(object, shadowMap) :
41
+ undefined
42
+
43
+ if (!items) {
44
+ return true
45
+ }
46
+
47
+ area.enabled = true
48
+ area.spaceIndex = blocks.length
49
+ blocks.push(items[0])
50
+ items[1].forEach(e => e.order = -100)
51
+ views.push(...items[1])
52
+
53
+ return true
54
+ })
55
+ }
56
+
57
+ const data = new ArrayBuffer(blocks.length * SHADOW_ITEM_BYTE_SIZE)
58
+ const view = new DataView(data)
59
+
60
+ for (let i = 0; i < blocks.length; i++) {
61
+ // SAFETY: The array is dense
62
+ /**@type {ShadowItem}*/(blocks[i]).write(view, i * SHADOW_ITEM_BYTE_SIZE)
63
+ }
64
+
65
+ renderer.updateUBO(context, {
66
+ name: "ShadowCasterBlock",
67
+ data
68
+ })
69
+ }
70
+ }
71
+
72
+ /**
73
+ * @param {DirectionalLight} light
74
+ * @param {ShadowMap} shadowMap
75
+ * @returns {[ShadowItem, View[]] | undefined}
76
+ */
77
+ function buildDirectionalShadowPass(light, shadowMap) {
78
+ const shadow = light.shadow
79
+
80
+ if (!shadow) return
81
+
82
+ const [renderTarget, layer] = shadowMap.getTarget()
83
+ const shadowItem = new ShadowItem()
84
+ const projectionMatrix = shadow.projection.asProjectionMatrix(shadow.near, shadow.far)
85
+ const viewMatrix = Affine3.toMatrix4(light.transform.world).invert()
86
+ const view = new View({
87
+ renderTarget,
88
+ position: light.transform.position,
89
+ projection: projectionMatrix,
90
+ view: viewMatrix,
91
+ near: shadow.near,
92
+ far: shadow.far,
93
+ tag: DirectionalLight.name,
94
+ object: light,
95
+ renderMask: light.renderMask
96
+ })
97
+
98
+
99
+ shadowItem.layer = layer
100
+ shadowItem.bias = shadow.bias
101
+ shadowItem.normalBias = shadow.normalBias
102
+ packShadowMode(shadowItem,shadow.filterMode)
103
+ Matrix4.multiply(projectionMatrix, viewMatrix, shadowItem.matrix)
104
+
105
+ return [shadowItem, [view]]
106
+ }
107
+
108
+ /**
109
+ * @param {SpotLight} light
110
+ * @param {ShadowMap} shadowMap
111
+ * @returns {[ShadowItem, View[]] | undefined}
112
+ */
113
+ function buildSpotShadowPass(light, shadowMap) {
114
+ const shadow = light.shadow
115
+
116
+ if (!shadow) {
117
+ return
118
+ }
119
+ const [renderTarget, layer] = shadowMap.getTarget()
120
+ const shadowItem = new ShadowItem()
121
+ const viewMatrix = Affine3.toMatrix4(light.transform.world).invert()
122
+ const projectionMatrix = new PerspectiveProjection(light.outerAngle, 1).asProjectionMatrix(
123
+ shadow.near,
124
+ light.range
125
+ )
126
+ const view = new View({
127
+ renderTarget,
128
+ position: light.transform.position,
129
+ projection: projectionMatrix,
130
+ view: viewMatrix,
131
+ near: shadow.near,
132
+ far: light.range,
133
+ tag: SpotLight.name,
134
+ object: light,
135
+ renderMask: light.renderMask
136
+ })
137
+
138
+ shadowItem.layer = layer
139
+ shadowItem.bias = shadow.bias
140
+ shadowItem.normalBias = shadow.normalBias
141
+ packShadowMode(shadowItem, shadow.filterMode)
142
+ Matrix4.multiply(projectionMatrix, viewMatrix, shadowItem.matrix)
143
+
144
+ return [shadowItem, [view]]
145
+ }
146
+
147
+ /**
148
+ * @param {PointLight} light
149
+ * @param {ShadowMap} shadowMap
150
+ * @returns {[ShadowItem, View[]] | undefined}
151
+ *
152
+ */
153
+ function buildPointShadowPass(light, shadowMap) {
154
+ const shadow = light.shadow
155
+
156
+ if (!shadow) {
157
+ return
158
+ }
159
+ const shadowItem = new ShadowItem()
160
+ const sides = [
161
+ [Vector3.X, Vector3.NegY],
162
+ [Vector3.NegX, Vector3.NegY],
163
+ [Vector3.Y, Vector3.Z],
164
+ [Vector3.NegY, Vector3.NegZ],
165
+ [Vector3.Z, Vector3.NegY],
166
+ [Vector3.NegZ, Vector3.NegY]
167
+ ]
168
+ const projectionMatrix = new PerspectiveProjection(Math.PI / 2, 1).asProjectionMatrix(
169
+ shadow.near,
170
+ light.radius
171
+ )
172
+ const views = []
173
+ let layerId = 0
174
+
175
+ for (let i = 0; i < sides.length; i++) {
176
+ const side = /**@type {[Vector3, Vector3]} */ (sides[i])
177
+ const [renderTarget, layer] = shadowMap.getTarget()
178
+
179
+ const worldMatrix = light.transform.world
180
+ const viewMatrix = Affine3.toMatrix4(new Affine3()
181
+ .lookAt(side[0], side[1])
182
+ .translate(new Vector3(
183
+ worldMatrix.x,
184
+ worldMatrix.y,
185
+ worldMatrix.z
186
+ )))
187
+ .invert()
188
+
189
+ layerId = layer
190
+ views.push(new View({
191
+ renderTarget,
192
+ view: viewMatrix,
193
+ projection: projectionMatrix,
194
+ position: light.transform.position,
195
+ near: shadow.near,
196
+ far: light.radius,
197
+ tag: PointLight.name,
198
+ object: light,
199
+ renderMask: light.renderMask
200
+ }))
201
+ }
202
+
203
+ // Encode clipping planes as they are neccessary for point light shadows
204
+ // Will be unpacked in the corresponding shader
205
+ shadowItem.matrix.a = shadow.near;
206
+ shadowItem.matrix.b = light.radius;
207
+
208
+ // We only need the light position for point lights
209
+ shadowItem.matrix.m = light.transform.world.x
210
+ shadowItem.matrix.n = light.transform.world.y
211
+ shadowItem.matrix.o = light.transform.world.z
212
+ shadowItem.bias = shadow.bias
213
+ shadowItem.normalBias = shadow.normalBias
214
+ packShadowMode(shadowItem, shadow.filterMode)
215
+ shadowItem.layer = layerId - 5
216
+
217
+ return [shadowItem, views]
218
+ }
219
+
220
+ /**
221
+ * @param {ShadowItem} item
222
+ * @param {import("../../../objects/light/index.js").ShadowFilteringModes} mode
223
+ */
224
+ function packShadowMode(item, mode) {
225
+ if (typeof mode === "undefined") {
226
+ item.mode = 0
227
+ } else if (mode instanceof PCFShadowFilter) {
228
+ item.mode = 1
229
+ item.pcfRadius = mode.radius
230
+ } else if (mode instanceof PCSSShadowFilter) {
231
+ item.mode = 2
232
+ item.pcfRadius = mode.radius
233
+ item.pcssSearchRadius = mode.searchRadius
234
+ item.pcssPenumbra = mode.penumbra
235
+ }else {
236
+ throw new Error("Invalid shadow filtering mode")
237
+ }
238
+ }
239
+
240
+ export class ShadowItem {
241
+ matrix = new Matrix4()
242
+ bias = 0.001
243
+ normalBias = 0
244
+ /**
245
+ * 0 = hard compare, 1 = PCF, 2 = PCSS.
246
+ * @type {number}
247
+ */
248
+ mode = 0
249
+ pcfRadius = 0
250
+ pcssSearchRadius = 0
251
+ pcssPenumbra = 0
252
+ layer = 0
253
+ /**
254
+ * @param {DataView} view
255
+ * @param {number} offset
256
+ */
257
+ write(view, offset) {
258
+ let i = 0
259
+ for (const value of this.matrix) {
260
+ view.setFloat32(offset + (i * 4), value, true)
261
+ i++
262
+ }
263
+ view.setFloat32(offset + 64, this.bias, true)
264
+ view.setFloat32(offset + 68, this.normalBias, true)
265
+ view.setFloat32(offset + 72, this.layer, true)
266
+ view.setUint32(offset + 76, this.mode >>> 0, true)
267
+ view.setFloat32(offset + 80, this.pcfRadius, true)
268
+ view.setFloat32(offset + 84, this.pcssSearchRadius, true)
269
+ view.setFloat32(offset + 88, this.pcssPenumbra, true)
270
+ view.setFloat32(offset + 92, 0, true)
271
+ }
272
+ }
@@ -0,0 +1,112 @@
1
+ import { assert } from "../../../utils"
2
+ import { PrimitiveTopology } from "../../../constants"
3
+ import { WebGLRenderDevice, GPUMesh, Shader } from "../../../core"
4
+ import { DirectionalLight, PointLight, SpotLight } from "../../../objects"
5
+ import { MeshMaterial3D, Object3D } from "../../../objects"
6
+ import { RenderItem, Views } from "../../../renderer/index.js"
7
+ import { WebGLRenderer } from "../../../renderer/index"
8
+ import { basicVertex } from "../../../shader/index.js"
9
+ import { ShadowPipelines } from "../resources"
10
+
11
+ export class ShadowOccluderNode {
12
+ subgraph() {
13
+ return undefined
14
+ }
15
+
16
+ /**
17
+ * @param {import("../../../renderer/graph/index.js").RenderGraphContext} context
18
+ */
19
+ execute(context) {
20
+ const { renderer, renderDevice, objects } = context
21
+ const views = renderer.getResource(Views)
22
+ const shadowPipelines = renderer.getResource(ShadowPipelines)
23
+
24
+ assert(views, "Views resource missing")
25
+ assert(shadowPipelines, "ShadowPipelines resource missing")
26
+
27
+ for (const view of views.items()) {
28
+ if (
29
+ view.tag !== DirectionalLight.name &&
30
+ view.tag !== PointLight.name &&
31
+ view.tag !== SpotLight.name
32
+ ) {
33
+ continue
34
+ }
35
+
36
+ /**@type {RenderItem[]} */
37
+ const opaqueStage = []
38
+
39
+ for (let i = 0; i < objects.length; i++) {
40
+ const object = /**@type {Object3D} */ (objects[i])
41
+ object.traverseDFS((child) => {
42
+ if (!child.renderMask.test(view.renderMask)) {
43
+ return true
44
+ }
45
+
46
+ if (!(child instanceof MeshMaterial3D)) {
47
+ return true
48
+ }
49
+ const gpuMesh = renderer.caches.getMesh(renderDevice, child.mesh, renderer.attributes)
50
+ const item = new RenderItem({
51
+ pipelineId: getRenderPipelineId(renderDevice, renderer, gpuMesh, shadowPipelines),
52
+ transform: child.transform.world,
53
+ mesh: gpuMesh,
54
+ uniforms: {},
55
+ tag: ""
56
+ })
57
+
58
+ opaqueStage.push(item)
59
+ return true
60
+ })
61
+ }
62
+
63
+ view.renderStage.opaque = opaqueStage
64
+ }
65
+ }
66
+ }
67
+
68
+ /**
69
+ * @param {WebGLRenderDevice} device
70
+ * @param {WebGLRenderer} renderer
71
+ * @param {GPUMesh} mesh
72
+ * @param {ShadowPipelines} pipelines
73
+ * @returns {number}
74
+ */
75
+ function getRenderPipelineId(device, renderer, mesh, pipelines) {
76
+ const { caches, includes, defines: globalDefines } = renderer
77
+ const pipelineid = pipelines.get(mesh.layoutHash)
78
+
79
+ if (pipelineid !== undefined) {
80
+ return pipelineid
81
+ }
82
+
83
+ const layout = caches.getMeshVertexLayout(mesh.layoutHash)
84
+
85
+ assert(layout, "Invalid mesh layout")
86
+ /**
87
+ * @type {import("src/core").WebGLRenderPipelineDescriptor}
88
+ */
89
+ const descriptor = {
90
+ //cullFace:CullFace.None,
91
+ depthWrite: true,
92
+ topology: PrimitiveTopology.Triangles,
93
+ vertexLayout: layout,
94
+ vertex: new Shader({
95
+ source: basicVertex
96
+ })
97
+ }
98
+
99
+
100
+ for (const [name, value] of globalDefines) {
101
+ descriptor.vertex.defines.set(name, value)
102
+ descriptor.fragment?.source?.defines?.set(name, value)
103
+ }
104
+ for (const [name, value] of includes) {
105
+ descriptor.vertex.includes.set(name, value)
106
+ descriptor.fragment?.source?.includes?.set(name, value)
107
+ }
108
+ const [_, newId] = caches.createRenderPipeline(device, descriptor)
109
+
110
+ pipelines.set(mesh.layoutHash, newId)
111
+ return newId
112
+ }
@@ -0,0 +1,73 @@
1
+ import { Camera } from "../../../objects/index.js"
2
+ import { RenderItem, Views } from "../../../renderer/index.js"
3
+ import { assert } from "../../../utils/index.js"
4
+ import { Affine3 } from "../../../math/index.js"
5
+
6
+ /**
7
+ * @param {import("../../../renderer/index.js").View} view
8
+ * @param {import("../../../core/index.js").WebGLRenderDevice} device
9
+ * @param {import("../../../renderer/renderer.js").WebGLRenderer} renderer
10
+ */
11
+ function renderItems(view, device, renderer) {
12
+ const { renderStage, renderTarget } = view
13
+ const opaquePhase = renderStage.opaque
14
+
15
+ const context = device.context
16
+ const caches = renderer.caches
17
+ const { clearColor, clearDepth, clearStencil, viewport, scissor } = renderTarget
18
+
19
+ const framebuffer = caches.getFrameBuffer(device, renderTarget)
20
+ framebuffer.setViewport(context, viewport, scissor || viewport)
21
+ framebuffer.clear(context, clearColor, clearDepth, clearStencil)
22
+
23
+ if (!opaquePhase) {
24
+ return
25
+ }
26
+
27
+ const pass = device.beginRenderPass()
28
+ for (let i = 0; i < opaquePhase.length; i++) {
29
+ // SAFETY: List is dense
30
+ const { pipelineId, mesh, transform } = /**@type {RenderItem}*/(opaquePhase[i])
31
+ const pipeline = caches.getRenderPipeline(pipelineId)
32
+
33
+ if (!pipeline) {
34
+ continue
35
+ }
36
+
37
+ const modelInfo = pipeline.uniforms.get("model")
38
+ const transformMatrix = Affine3.toMatrix4(transform)
39
+
40
+ pass.setPipeline(pipeline)
41
+
42
+ if (modelInfo) {
43
+ context.uniformMatrix4fv(modelInfo.location, false, new Float32Array(transformMatrix))
44
+ }
45
+ pass.draw(mesh)
46
+ }
47
+ pass.end()
48
+ }
49
+
50
+ export class ShadowOpaquePassNode {
51
+ subgraph() {
52
+ return undefined
53
+ }
54
+
55
+ /**
56
+ * @param {import("../../../renderer/graph/index.js").RenderGraphContext} context
57
+ */
58
+ execute(context) {
59
+ const { renderer, renderDevice } = context
60
+ const views = renderer.getResource(Views)
61
+
62
+ assert(views, "Views resource missing")
63
+
64
+ for (const view of views.items()) {
65
+ if (view.tag === Camera.name) {
66
+ continue
67
+ }
68
+
69
+ renderer.updateUBO(renderDevice.context, view.getData())
70
+ renderItems(view, renderDevice, renderer)
71
+ }
72
+ }
73
+ }
@@ -0,0 +1,99 @@
1
+ import { Object3D } from "../../../objects";
2
+ import { TextureType, TextureFormat, TextureWrap, TextureFilter } from "../../../constants";
3
+ import { ImageRenderTarget } from "../../../rendertarget";
4
+ import { Texture, Sampler } from "../../../texture";
5
+
6
+
7
+ export class ShadowMap {
8
+
9
+ /**
10
+ * @private
11
+ */
12
+ counter = 0;
13
+ /**
14
+ * @type {ImageRenderTarget[]}
15
+ */
16
+ targets = [];
17
+
18
+ shadowAtlas = new Texture({
19
+ type: TextureType.Texture2DArray,
20
+ format: TextureFormat.Depth32Float
21
+ });
22
+
23
+ sampler = new Sampler({
24
+ wrapR: TextureWrap.Clamp,
25
+ wrapS: TextureWrap.Clamp,
26
+ wrapT: TextureWrap.Clamp,
27
+ minificationFilter: TextureFilter.Nearest,
28
+ magnificationFilter: TextureFilter.Nearest,
29
+ mipmapFilter: undefined
30
+ });
31
+
32
+ maxDepth = 10;
33
+
34
+ /**
35
+ * @param {number} maxShadows
36
+ */
37
+ constructor(maxShadows) {
38
+ this.maxDepth = maxShadows;
39
+ }
40
+
41
+ /**
42
+ * @type {Map<Object3D, ShadowArea>}
43
+ */
44
+ inner = new Map();
45
+
46
+ reset() {
47
+ this.counter = 0;
48
+ this.inner.forEach((area) => {
49
+ area.enabled = false;
50
+ });
51
+ }
52
+ /**
53
+ * @return {[ImageRenderTarget, number]}
54
+ */
55
+ getTarget() {
56
+ const layer = this.counter;
57
+ const target = this.targets[layer];
58
+
59
+ if (this.counter > this.maxDepth) {
60
+ console.error('Maximum shadows reached, some shadows will be ignored');
61
+ }
62
+
63
+ this.counter++;
64
+ if (target) {
65
+ return [target, layer];
66
+ }
67
+
68
+ const newTarget = new ImageRenderTarget({
69
+ depthTexture: this.shadowAtlas,
70
+ width: 2048,
71
+ height: 2048,
72
+ depth: this.maxDepth,
73
+ layer: layer
74
+ });
75
+ this.targets[layer] = newTarget;
76
+
77
+ return [newTarget, layer];
78
+ }
79
+ /**
80
+ * @param {Object3D} object
81
+ */
82
+ getOrSet(object) {
83
+ const item = this.inner.get(object);
84
+
85
+ if (item) {
86
+ return item;
87
+ }
88
+
89
+ const newItem = new ShadowArea();
90
+
91
+ this.inner.set(object, newItem);
92
+ return newItem;
93
+ }
94
+ }
95
+
96
+ export class ShadowArea {
97
+ enabled = false;
98
+ spaceIndex = -1;
99
+ }
@@ -0,0 +1,2 @@
1
+ export * from './ShadowMap.js'
2
+ export * from './shadowpipelines.js'
@@ -0,0 +1,25 @@
1
+ export class ShadowPipelines {
2
+
3
+ /**
4
+ * Layout hash is the key, pipeline id the value.
5
+ * @private
6
+ * @type {Map<number, number>}
7
+ */
8
+ pipelines = new Map()
9
+
10
+ /**
11
+ * @param {number} layoutHash
12
+ * @returns {number | undefined}
13
+ */
14
+ get(layoutHash) {
15
+ return this.pipelines.get(layoutHash)
16
+ }
17
+
18
+ /**
19
+ * @param {number} layoutHash
20
+ * @param {number} pipelineId
21
+ */
22
+ set(layoutHash, pipelineId) {
23
+ this.pipelines.set(layoutHash, pipelineId)
24
+ }
25
+ }
@@ -0,0 +1,31 @@
1
+ import { Plugin, SortViewsNode, WebGLRenderer } from "../../renderer/index.js";
2
+ import { ShadowMap, ShadowPipelines } from "./resources/index.js";
3
+ import { ShadowOccluderNode, ShadowOpaquePassNode, ShadowViewNode } from "./nodes/index.js";
4
+ import { CameraOpaquePassNode } from "../camera/index.js";
5
+
6
+ export class ShadowPlugin extends Plugin {
7
+ /**
8
+ * @override
9
+ * @param {WebGLRenderer} renderer
10
+ */
11
+ init(renderer) {
12
+ const maxShadows = 10
13
+ renderer.setResource(new ShadowMap(maxShadows))
14
+ renderer.setResource(new ShadowPipelines())
15
+ renderer.defines.set('MAX_SHADOW_CASTERS', maxShadows.toString())
16
+
17
+ renderer.renderGraph.addNode(ShadowViewNode.name, new ShadowViewNode())
18
+ renderer.renderGraph.addNode(ShadowOccluderNode.name, new ShadowOccluderNode())
19
+ renderer.renderGraph.addNode(ShadowOpaquePassNode.name, new ShadowOpaquePassNode())
20
+ renderer.renderGraph.addDependency(ShadowViewNode.name, ShadowOccluderNode.name)
21
+ renderer.renderGraph.addDependency(ShadowOccluderNode.name, SortViewsNode.name)
22
+ renderer.renderGraph.addDependency(SortViewsNode.name, ShadowOpaquePassNode.name)
23
+ renderer.renderGraph.addDependency(ShadowOpaquePassNode.name, CameraOpaquePassNode.name)
24
+
25
+ }
26
+
27
+ /**
28
+ * @override
29
+ */
30
+ preprocess() {}
31
+ }
@@ -0,0 +1 @@
1
+ export * from './skeletonhelper.js'