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,127 @@
1
+ import { Object3D } from "../../../objects/index.js"
2
+ import { AmbientLight, PointLight, SpotLight,DirectionalLight } from "../../../objects/index.js"
3
+ import { ShadowMap } from "../../shadow/index.js"
4
+
5
+ export class LightNode {
6
+ subgraph() {
7
+ return undefined
8
+ }
9
+
10
+ /**
11
+ * @param {import("../../../renderer/graph/index.js").RenderGraphContext} context
12
+ */
13
+ execute(context) {
14
+ updateLights(context.objects, context.renderDevice, context.renderer)
15
+ }
16
+ }
17
+
18
+ /**
19
+ * @param {import("../../../objects/index.js").Object3D[]} objects
20
+ * @param {import("../../../core/index.js").WebGLRenderDevice} device
21
+ * @param {import("../../../renderer/index.js").WebGLRenderer} renderer
22
+ */
23
+ function updateLights(objects, device, renderer) {
24
+ const shadowMap = renderer.getResource(ShadowMap)
25
+ const directionalLights = new LightQueue()
26
+ const pointLights = new LightQueue()
27
+ const spotLights = new LightQueue()
28
+
29
+ for (let i = 0; i < objects.length; i++) {
30
+ const object = /**@type {Object3D}*/(objects[i])
31
+
32
+ object.traverseDFS((object) => {
33
+ if (object instanceof DirectionalLight) {
34
+ directionalLights.add(object)
35
+ } else if (object instanceof PointLight) {
36
+ pointLights.add(object)
37
+ } else if (object instanceof SpotLight) {
38
+ spotLights.add(object)
39
+ } else if (object instanceof AmbientLight) {
40
+ renderer.updateUBO(device.context, object.getData())
41
+ }
42
+ return true
43
+ })
44
+ }
45
+
46
+ const directionalLightData = directionalLights.getData()
47
+ const spotLightData = spotLights.getData()
48
+ const pointLightData = pointLights.getData()
49
+ const directionalItems = new Int32Array(directionalLightData.buffer)
50
+ const spotItems = new Int32Array(spotLightData.buffer)
51
+ const pointItems = new Int32Array(pointLightData.buffer)
52
+
53
+ for (let i = 0; i < directionalLights.lights.length; i++) {
54
+ const offset = (i * 12) + 8 + 4
55
+ const item = shadowMap?.inner.get(/**@type {DirectionalLight}*/(directionalLights.lights[i]))
56
+
57
+ if (item?.enabled) {
58
+ directionalItems[offset] = item.spaceIndex
59
+ } else {
60
+ directionalItems[offset] = -1
61
+ }
62
+ }
63
+
64
+ for (let i = 0; i < spotLights.lights.length; i++) {
65
+ const offset = (i * 16) + 7 + 4
66
+ const item = shadowMap?.inner.get(/**@type {SpotLight}*/(spotLights.lights[i]))
67
+ if (item?.enabled) {
68
+ spotItems[offset] = item.spaceIndex
69
+ } else {
70
+ spotItems[offset] = -1
71
+ }
72
+ }
73
+
74
+ for (let i = 0; i < pointLights.lights.length; i++) {
75
+ const offset = (i * 12) + 10 + 4
76
+ const item = shadowMap?.inner.get(/**@type {PointLight}*/(pointLights.lights[i]))
77
+ if (item?.enabled) {
78
+ pointItems[offset] = item.spaceIndex
79
+ } else {
80
+ pointItems[offset] = -1
81
+ }
82
+ }
83
+
84
+ renderer.updateUBO(device.context, {
85
+ name: "DirectionalLightBlock",
86
+ data: directionalLightData
87
+ })
88
+
89
+ renderer.updateUBO(device.context, {
90
+ name: "PointLightBlock",
91
+ data: pointLightData
92
+ })
93
+
94
+ renderer.updateUBO(device.context, {
95
+ name: "SpotLightBlock",
96
+ data: spotLightData
97
+ })
98
+ }
99
+
100
+ /**
101
+ * @template {{pack:()=>number[]}} T
102
+ */
103
+ class LightQueue {
104
+ /**
105
+ * @type {T[]}
106
+ */
107
+ lights = []
108
+
109
+ /**
110
+ * @param {T} light
111
+ */
112
+ add(light) {
113
+ this.lights.push(light)
114
+ }
115
+
116
+ getData() {
117
+ const buffer = new Float32Array([
118
+ 0, 0, 0, 0,
119
+ ...this.lights.flatMap(light => light.pack())
120
+ ])
121
+ const dataView = new Uint32Array(buffer.buffer)
122
+
123
+ dataView[0] = this.lights.length
124
+
125
+ return buffer
126
+ }
127
+ }
@@ -0,0 +1,3 @@
1
+ export * from './meshmaterial.js'
2
+ export * from './nodes/index.js'
3
+ export * from './resources/index.js'
@@ -0,0 +1,381 @@
1
+ /**@import { Brand } from '../../utils/index.js' */
2
+ /**@import { Defaults } from '../../renderer/index.js' */
3
+ /**@import { GPUTexture, WebGLRenderPipeline, WebGLRenderPipelineDescriptor } from '../../core/index.js' */
4
+ import { assert } from '../../utils/index.js'
5
+ import { MeshVertexLayout, Shader, Uniform, WebGLRenderDevice } from "../../core/index.js";
6
+ import { Mesh, Attribute } from "../../mesh/index.js";
7
+ import { MeshMaterial3D, Object3D } from "../../objects/index.js";
8
+ import { Plugin, RenderItem, SortViewsNode, WebGLRenderer } from "../../renderer/index.js";
9
+ import { Sampler, Texture } from "../../texture/index.js";
10
+ import { PrimitiveTopology, TextureFilter, TextureFormat } from '../../constants/index.js';
11
+ import { Caches } from '../../caches/index.js';
12
+ import { ShadowMap } from '../shadow/index.js';
13
+ import { CameraViewNode } from '../camera/index.js';
14
+ import { MeshMaterialNode } from './nodes/index.js';
15
+ import { MeshMaterialPipelines } from './resources/index.js';
16
+
17
+ export class MeshMaterialPlugin extends Plugin {
18
+ /**
19
+ * @override
20
+ * @param {WebGLRenderer} renderer
21
+ */
22
+ init(renderer) {
23
+ renderer.setResource(new MeshMaterialPipelines())
24
+ renderer.uniformBinders.set(MeshMaterial3D.name, uploadUniforms)
25
+ renderer.renderGraph.addNode(MeshMaterialNode.name, new MeshMaterialNode())
26
+ renderer.renderGraph.addDependency(CameraViewNode.name, MeshMaterialNode.name)
27
+ renderer.renderGraph.addDependency(MeshMaterialNode.name, SortViewsNode.name)
28
+ }
29
+
30
+ /**
31
+ * @override
32
+ */
33
+ preprocess() { }
34
+ }
35
+
36
+ /**
37
+ * @param {Object3D} object
38
+ * @param {WebGLRenderDevice} device
39
+ * @param {WebGLRenderer} renderer
40
+ * @param {MeshMaterialPipelines} pipelines
41
+ * @returns {RenderItem | undefined}
42
+ */
43
+ export function createMeshMaterialRenderItem(object, device, renderer, pipelines) {
44
+ if (!(object instanceof MeshMaterial3D)) {
45
+ return
46
+ }
47
+
48
+ const { caches, attributes } = renderer
49
+ const { material, mesh, transform } = object
50
+ const gpuMesh = caches.getMesh(device, mesh, attributes)
51
+ const meshBits = createPipelineBitsFromMesh(mesh, object)
52
+ const materialBits = material.getPipelineBits()
53
+ const pipelineKey = createPipelineKey(gpuMesh.layoutHash, meshBits, materialBits)
54
+ const materialName = material.constructor.name
55
+ const pipelineId = pipelines.getOrSetCompute(materialName, pipelineKey, () => {
56
+ const keyMeshBits = pipelineKey >> GeneralPipelineKeyShiftBits.MeshBits
57
+ const meshLayout = caches.getMeshVertexLayout(gpuMesh.layoutHash)
58
+ const { defines, includes } = renderer
59
+ assert(meshLayout, "Mesh layout not available")
60
+ const shaderdefs = getShaderDefs(meshLayout, keyMeshBits, defines)
61
+ /**
62
+ * @type {WebGLRenderPipelineDescriptor}
63
+ */
64
+ const descriptor = {
65
+ topology: mesh.topology,
66
+ vertexLayout: meshLayout,
67
+ vertex: new Shader({
68
+ source: material.vertex()
69
+ }),
70
+ fragment: {
71
+ source: new Shader({
72
+ source: material.fragment()
73
+ }),
74
+ targets: [{
75
+ format: TextureFormat.RGBA8Unorm
76
+ }]
77
+ }
78
+ }
79
+
80
+ for (const shaderdef of shaderdefs) {
81
+ descriptor.vertex.defines.set(shaderdef[0], shaderdef[1])
82
+ descriptor.fragment?.source?.defines?.set(shaderdef[0], shaderdef[1])
83
+ }
84
+ for (const [name, value] of includes) {
85
+ descriptor.vertex.includes.set(name, value)
86
+ descriptor.fragment?.source?.includes?.set(name, value)
87
+ }
88
+
89
+ material.specialize(descriptor)
90
+
91
+ const [_, newId] = caches.createRenderPipeline(device, descriptor)
92
+
93
+ return newId
94
+ })
95
+
96
+ const uniforms = new MaterialBindGroup({
97
+ textures: object.material.getTextures(),
98
+ data: material.getData(),
99
+ })
100
+
101
+ if (object.skin) {
102
+ object.skin.bindMatrix.copy(object.transform.world)
103
+ object.skin.inverseBindMatrix.copy(object.skin.bindMatrix).invert()
104
+ object.skin.updateTexture()
105
+ const texture = caches.getTexture(device, object.skin.boneTexture)
106
+
107
+ uniforms.boneTransforms = texture
108
+ }
109
+ const item = new RenderItem({
110
+ uniforms,
111
+ mesh: gpuMesh,
112
+ pipelineId,
113
+ tag: MeshMaterial3D.name,
114
+ transform: transform.world
115
+ })
116
+
117
+ return item
118
+ }
119
+
120
+ class MaterialBindGroup {
121
+ /**
122
+ * @type {GPUTexture | undefined}
123
+ */
124
+ boneTransforms
125
+
126
+ /**
127
+ * @type {[string, number, Texture | undefined, Sampler | undefined][]}
128
+ */
129
+ textures
130
+ /**
131
+ * @type {ArrayBuffer}
132
+ */
133
+ data
134
+ /**
135
+ * @param {MaterialBindGroupOptions} options
136
+ */
137
+ constructor({
138
+ textures,
139
+ data,
140
+ boneTransforms
141
+ }) {
142
+ this.boneTransforms = boneTransforms
143
+ this.data = data
144
+ this.textures = textures
145
+ }
146
+ }
147
+
148
+ /**
149
+ * @typedef MaterialBindGroupOptions
150
+ * @property {[string, number, Texture | undefined, Sampler | undefined][]} textures
151
+ * @property {ArrayBuffer} data
152
+ * @property {GPUTexture} [boneTransforms]
153
+ */
154
+
155
+ /**
156
+ * @param {WebGLRenderDevice} device
157
+ * @param {WebGLRenderer} renderer
158
+ * @param {WebGLRenderPipeline} pipeline
159
+ * @param {MaterialBindGroup} bindGroup
160
+ */
161
+ function uploadUniforms(device, renderer, pipeline, bindGroup) {
162
+ const { caches, defaults } = renderer
163
+ const shadowmap = renderer.getResource(ShadowMap)
164
+ const shadowInfo = pipeline.uniforms.get('shadow_atlas')
165
+ const boneMatricesInfo = pipeline.uniforms.get("bone_transforms")
166
+ const materialBuffer = caches.uniformBuffers.get('MaterialBlock')
167
+
168
+ if (shadowmap && shadowInfo && shadowInfo.texture_unit !== undefined) {
169
+ device.context.activeTexture(WebGL2RenderingContext.TEXTURE0 + shadowInfo.texture_unit)
170
+
171
+ const texture = caches.getTexture(device, shadowmap.shadowAtlas)
172
+ device.context.bindTexture(shadowmap.shadowAtlas.type, texture.inner)
173
+ updateTextureSampler(device.context, shadowmap.shadowAtlas, shadowmap.sampler)
174
+ }
175
+
176
+ if (boneMatricesInfo && boneMatricesInfo.texture_unit !== undefined && bindGroup.boneTransforms) {
177
+ device.context.activeTexture(WebGL2RenderingContext.TEXTURE0 + boneMatricesInfo.texture_unit)
178
+
179
+ device.context.bindTexture(bindGroup.boneTransforms.type, bindGroup.boneTransforms.inner)
180
+ device.context.texParameteri(bindGroup.boneTransforms.type, WebGL2RenderingContext.TEXTURE_MIN_FILTER, WebGL2RenderingContext.LINEAR)
181
+ }
182
+
183
+ if (materialBuffer) {
184
+ materialBuffer.update(device.context, bindGroup.data)
185
+ }
186
+
187
+ uploadTextures(device, bindGroup.textures, pipeline.uniforms, caches, defaults)
188
+ }
189
+ /**
190
+ * @enum {bigint}
191
+ */
192
+ export const MeshKey = /**@type {const}*/({
193
+ TopologyBits: 0b1111111n,
194
+ None: 0n,
195
+ Points: 1n << 0n,
196
+ Lines: 1n << 1n,
197
+ LineLoop: 1n << 2n,
198
+ LineStrip: 1n << 3n,
199
+ Triangles: 1n << 4n,
200
+ TriangleStrip: 1n << 5n,
201
+ TriangleFan: 1n << 6n,
202
+ Skinned: 1n << 7n
203
+ })
204
+
205
+ /**
206
+ * @param {Mesh} mesh
207
+ * @returns {bigint}
208
+ */
209
+ function keyFromTopology(mesh) {
210
+ if (mesh.topology === PrimitiveTopology.Points) {
211
+ return MeshKey.Points
212
+ }
213
+ if (mesh.topology === PrimitiveTopology.Lines) {
214
+ return MeshKey.Lines
215
+ }
216
+ if (mesh.topology === PrimitiveTopology.LineLoop) {
217
+ return MeshKey.LineLoop
218
+ }
219
+ if (mesh.topology === PrimitiveTopology.LineStrip) {
220
+ return MeshKey.LineStrip
221
+ }
222
+ if (mesh.topology === PrimitiveTopology.Triangles) {
223
+ return MeshKey.Triangles
224
+ }
225
+ if (mesh.topology === PrimitiveTopology.TriangleStrip) {
226
+ return MeshKey.TriangleStrip
227
+ }
228
+ if (mesh.topology === PrimitiveTopology.TriangleFan) {
229
+ return MeshKey.TriangleFan
230
+ }
231
+
232
+ return MeshKey.Triangles
233
+ }
234
+
235
+ /**
236
+ * @param {Mesh} mesh
237
+ * @param {MeshMaterial3D} object
238
+ * @returns {bigint}
239
+ */
240
+ function createPipelineBitsFromMesh(mesh, object) {
241
+ let key = keyFromTopology(mesh)
242
+
243
+ if (
244
+ mesh.attributes.has(Attribute.JointIndex.name) &&
245
+ mesh.attributes.has(Attribute.JointWeight.name) &&
246
+ object.skin
247
+ ) {
248
+ key |= MeshKey.Skinned
249
+ }
250
+ return key
251
+ }
252
+
253
+ /**
254
+ * @param {WebGL2RenderingContext} context
255
+ * @param {Texture} texture
256
+ * @param {Sampler} sampler
257
+ */
258
+ function updateTextureSampler(context, texture, sampler) {
259
+ const lod = sampler.lod
260
+ const anisotropyExtenstion = context.getExtension("EXT_texture_filter_anisotropic")
261
+
262
+ context.texParameteri(texture.type, context.TEXTURE_MAG_FILTER, sampler.magnificationFilter)
263
+ context.texParameteri(texture.type, context.TEXTURE_WRAP_S, sampler.wrapS)
264
+ context.texParameteri(texture.type, context.TEXTURE_WRAP_T, sampler.wrapT)
265
+ context.texParameteri(texture.type, context.TEXTURE_WRAP_R, sampler.wrapR)
266
+
267
+ if (lod) {
268
+ context.texParameteri(texture.type, context.TEXTURE_MIN_LOD, lod.min)
269
+ context.texParameteri(texture.type, context.TEXTURE_MAX_LOD, lod.max)
270
+ }
271
+
272
+ if (sampler.mipmapFilter !== undefined) {
273
+ if (sampler.minificationFilter === TextureFilter.Linear) {
274
+ if (sampler.mipmapFilter === TextureFilter.Linear) {
275
+ context.texParameteri(texture.type, context.TEXTURE_MIN_FILTER, context.LINEAR_MIPMAP_LINEAR);
276
+ } else if (sampler.mipmapFilter === TextureFilter.Nearest) {
277
+ context.texParameteri(texture.type, context.TEXTURE_MIN_FILTER, context.LINEAR_MIPMAP_NEAREST);
278
+ }
279
+ } else if (sampler.minificationFilter === TextureFilter.Nearest) {
280
+ if (sampler.mipmapFilter === TextureFilter.Linear) {
281
+ context.texParameteri(texture.type, context.TEXTURE_MIN_FILTER, context.NEAREST_MIPMAP_LINEAR);
282
+ } else if (sampler.mipmapFilter === TextureFilter.Nearest) {
283
+ context.texParameteri(texture.type, context.TEXTURE_MIN_FILTER, context.NEAREST_MIPMAP_NEAREST);
284
+ }
285
+ }
286
+ } else {
287
+ if (sampler.minificationFilter === TextureFilter.Nearest) {
288
+ context.texParameteri(texture.type, context.TEXTURE_MIN_FILTER, context.NEAREST)
289
+ } else if (sampler.minificationFilter === TextureFilter.Linear) {
290
+ context.texParameteri(texture.type, context.TEXTURE_MIN_FILTER, context.LINEAR)
291
+ }
292
+ }
293
+ if (anisotropyExtenstion) {
294
+ context.texParameterf(texture.type, anisotropyExtenstion.TEXTURE_MAX_ANISOTROPY_EXT, sampler.anisotropy)
295
+ }
296
+
297
+ if (sampler.compare !== undefined) {
298
+ context.texParameteri(texture.type, context.TEXTURE_COMPARE_MODE, context.COMPARE_REF_TO_TEXTURE);
299
+ context.texParameteri(texture.type, context.TEXTURE_COMPARE_FUNC, sampler.compare)
300
+ } else {
301
+ context.texParameteri(texture.type, context.TEXTURE_COMPARE_MODE, context.NONE);
302
+ }
303
+ }
304
+
305
+ /**
306
+ * @param {WebGLRenderDevice} device
307
+ * @param {[string, number, Texture | undefined, Sampler | undefined][]} textures
308
+ * @param {ReadonlyMap<string, Uniform>} uniforms
309
+ * @param {Caches} caches
310
+ * @param {Defaults} defaults
311
+ */
312
+ function uploadTextures(device, textures, uniforms, caches, defaults) {
313
+ for (let i = 0; i < textures.length; i++) {
314
+ const [name, _, texture = defaults.texture2D, sampler = defaults.textureSampler] =
315
+ /**@type {[string, number, Texture | undefined, Sampler | undefined]}*/(textures[i])
316
+ const textureInfo = uniforms.get(name)
317
+
318
+ if (textureInfo && textureInfo.texture_unit !== undefined) {
319
+ const gpuTexture = caches.getTexture(device, texture)
320
+ device.context.activeTexture(WebGL2RenderingContext.TEXTURE0 + textureInfo.texture_unit)
321
+ device.context.bindTexture(texture.type, gpuTexture.inner)
322
+ updateTextureSampler(device.context, texture, sampler)
323
+ }
324
+ }
325
+ }
326
+ /**
327
+ * @param {MeshVertexLayout} meshLayout
328
+ * @param {bigint} meshBits
329
+ * @param {ReadonlyMap<string, string>} globalDefines
330
+ */
331
+ function getShaderDefs(meshLayout, meshBits, globalDefines) {
332
+ /**@type {[string,string][]} */
333
+ const shaderdefs = []
334
+ if (meshBits & MeshKey.Skinned) {
335
+ shaderdefs.push(["SKINNED", ""])
336
+ }
337
+
338
+ if (meshLayout.hasAttribute(Attribute.UV)) {
339
+ shaderdefs.push(['VERTEX_UVS', ''])
340
+ }
341
+
342
+ if (meshLayout.hasAttribute(Attribute.Normal)) {
343
+ shaderdefs.push(['VERTEX_NORMALS', ''])
344
+ }
345
+
346
+ if (meshLayout.hasAttribute(Attribute.Tangent)) {
347
+ shaderdefs.push(['VERTEX_TANGENTS', ''])
348
+ }
349
+
350
+ for (const [name, value] of globalDefines) {
351
+ shaderdefs.push([name, value])
352
+ }
353
+
354
+ return shaderdefs
355
+ }
356
+
357
+ /**
358
+ * @enum {bigint}
359
+ */
360
+ export const GeneralPipelineKeyShiftBits = /**@type {const}*/({
361
+ LayoutHashBits: 0n,
362
+ MeshBits: 15n,
363
+ MaterialBits: 47n
364
+ })
365
+ /**
366
+ * @param {number} layoutHash
367
+ * @param {bigint} meshBits
368
+ * @param {bigint} materialBits
369
+ */
370
+ function createPipelineKey(layoutHash, meshBits, materialBits) {
371
+ const layoutHashBits = BigInt(layoutHash)
372
+ return /**@type {PipelineKey}*/(
373
+ layoutHashBits << GeneralPipelineKeyShiftBits.LayoutHashBits |
374
+ meshBits << GeneralPipelineKeyShiftBits.MeshBits |
375
+ (materialBits << GeneralPipelineKeyShiftBits.MaterialBits)
376
+ )
377
+ }
378
+
379
+ /**
380
+ * @typedef {Brand<bigint,"PipelineKey">} PipelineKey
381
+ */
@@ -0,0 +1 @@
1
+ export * from "./meshmaterial.js"
@@ -0,0 +1,50 @@
1
+ import { assert } from "../../../utils/index.js"
2
+ import { Camera, Object3D } from "../../../objects/index.js"
3
+ import { Views } from "../../../renderer/index.js"
4
+ import { MeshMaterialPipelines } from "../resources/index.js"
5
+ import { createMeshMaterialRenderItem } from "../meshmaterial.js"
6
+
7
+ export class MeshMaterialNode {
8
+ subgraph() {
9
+ return undefined
10
+ }
11
+
12
+ /**
13
+ * @param {import("../../../renderer/graph/index.js").RenderGraphContext} context
14
+ */
15
+ execute(context) {
16
+ const { renderer, renderDevice, objects } = context
17
+ const views = renderer.getResource(Views)
18
+ const pipelines = renderer.getResource(MeshMaterialPipelines)
19
+
20
+ assert(views, "Views resource missing")
21
+ assert(pipelines, "MeshMaterialPipelines resource missing")
22
+
23
+ for (const view of views.items()) {
24
+ if (view.tag !== Camera.name) {
25
+ continue
26
+ }
27
+
28
+ const opaqueStage = view.renderStage.opaque || []
29
+ view.renderStage.opaque = opaqueStage
30
+
31
+ for (let i = 0; i < objects.length; i++) {
32
+ // SAFETY: Asssume the list is dense
33
+ const object = /**@type {Object3D}*/(objects[i])
34
+
35
+ object.traverseDFS((child) => {
36
+ if (!child.renderMask.test(view.renderMask)) {
37
+ return true
38
+ }
39
+
40
+ const item = createMeshMaterialRenderItem(child, renderDevice, renderer, pipelines)
41
+
42
+ if (item) {
43
+ opaqueStage.push(item)
44
+ }
45
+ return true
46
+ })
47
+ }
48
+ }
49
+ }
50
+ }
@@ -0,0 +1 @@
1
+ export * from "./meshmaterialpipelines.js"
@@ -0,0 +1,50 @@
1
+ export class MeshMaterialPipelines {
2
+ /**
3
+ * @private
4
+ * @type {Map<string, Map<bigint, number>>}
5
+ */
6
+ pipelines = new Map()
7
+
8
+ /**
9
+ * @param {string} materialName
10
+ * @param {bigint} key
11
+ * @returns {number | undefined}
12
+ */
13
+ get(materialName, key) {
14
+ return this.pipelines.get(materialName)?.get(key)
15
+ }
16
+
17
+ /**
18
+ * @param {string} materialName
19
+ * @param {bigint} key
20
+ * @param {number} pipelineId
21
+ */
22
+ set(materialName, key, pipelineId) {
23
+ let materialPipelines = this.pipelines.get(materialName)
24
+
25
+ if (!materialPipelines) {
26
+ materialPipelines = new Map()
27
+ this.pipelines.set(materialName, materialPipelines)
28
+ }
29
+
30
+ materialPipelines.set(key, pipelineId)
31
+ }
32
+
33
+ /**
34
+ * @param {string} materialName
35
+ * @param {bigint} key
36
+ * @param {() => number} compute
37
+ * @returns {number}
38
+ */
39
+ getOrSetCompute(materialName, key, compute) {
40
+ const pipelineId = this.get(materialName, key)
41
+
42
+ if (pipelineId !== undefined) {
43
+ return pipelineId
44
+ }
45
+
46
+ const newPipelineId = compute()
47
+ this.set(materialName, key, newPipelineId)
48
+ return newPipelineId
49
+ }
50
+ }
@@ -0,0 +1,3 @@
1
+ export * from './shadow.js'
2
+ export * from './nodes/index.js'
3
+ export * from './resources/index.js'
@@ -0,0 +1,3 @@
1
+ export * from './shadow.js'
2
+ export * from './shadowOccluder.js'
3
+ export * from './shadowOpaquePass.js'