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,3 @@
1
+ export * from './texture.js'
2
+ export * from './obj.js'
3
+ export * from './gltf.js'
@@ -0,0 +1,174 @@
1
+ /**
2
+ * @enum {number}
3
+ */
4
+ export const OnAssetLoadedStrategy = /**@type {const}*/({
5
+ Original: 0,
6
+ Clone: 1
7
+ })
8
+
9
+ /**
10
+ * @template {Clonable<Asset> & Copyable<Asset>} Asset
11
+ * @template {LoadSettings} [Settings = LoadSettings]
12
+ */
13
+ export class Loader {
14
+ /**
15
+ * @readonly
16
+ * @type {Constructor<Asset>}
17
+ */
18
+ asset
19
+
20
+ /**
21
+ * @protected
22
+ * @type {OnAssetLoadedStrategy}
23
+ */
24
+ strategy = OnAssetLoadedStrategy.Clone
25
+
26
+ /**
27
+ * @private
28
+ * @readonly
29
+ * @type {Map<string,Asset>}
30
+ */
31
+ assets = new Map()
32
+
33
+ /**
34
+ * @private
35
+ * @readonly
36
+ * @type {Map<string,[Asset,((asset:Asset)=>void) | undefined][]>}
37
+ */
38
+ toLoad = new Map()
39
+ /**
40
+ * @param {Constructor<Asset>} asset
41
+ */
42
+ constructor(asset) {
43
+ this.asset = asset
44
+ }
45
+
46
+ /**
47
+ * @param {Settings & {postprocessor?:(asset:Asset)=>void}} settings
48
+ */
49
+ load(settings) {
50
+ const root = this.default(settings)
51
+
52
+ if (this.strategy === OnAssetLoadedStrategy.Clone) {
53
+ const clone = root.clone()
54
+ this.addToLoad(settings.paths.join('/'), clone, settings.postprocessor)
55
+ this.asyncLoad(settings, root)
56
+ return clone
57
+ }
58
+
59
+ this.asyncLoad(settings, root)
60
+ return root
61
+ }
62
+
63
+
64
+ /**
65
+ * @param {Settings} settings
66
+ * @param {Asset} [original]
67
+ */
68
+ async asyncLoad(settings, original) {
69
+ const cachedAsset = original || this.default(settings)
70
+ const response = await this.fetch(settings.paths)
71
+
72
+ await this.parse(response, cachedAsset, settings)
73
+ this.assets.set(settings.paths.join("/"), cachedAsset)
74
+
75
+ const loads = this.toLoad.get(settings.paths.join('/'))
76
+
77
+ if (loads) {
78
+ for (let i = 0; i < loads.length; i++) {
79
+ const [clone, postprocessor] = /**@type {[Asset, ((asset: Asset) => void) | undefined]} */ (loads[i]);
80
+
81
+ clone.copy(cachedAsset)
82
+ if (postprocessor) {
83
+ postprocessor(clone)
84
+ }
85
+ }
86
+
87
+ loads.length = 0
88
+ }
89
+ return cachedAsset
90
+ }
91
+
92
+ /**
93
+ * @private
94
+ * @param {string} url
95
+ * @param {Asset} asset
96
+ * @param {((asset: Asset)=> void) | undefined} postprocessor
97
+ */
98
+ addToLoad(url, asset, postprocessor) {
99
+ const assets = this.toLoad.get(url)
100
+
101
+ if (assets) {
102
+ assets.push([asset, postprocessor])
103
+ } else {
104
+ this.toLoad.set(url, [[asset, postprocessor]])
105
+ }
106
+ }
107
+ /**
108
+ * @private
109
+ * @param {string[]} paths
110
+ * @returns {Promise<ArrayBuffer[]>}
111
+ */
112
+ async fetch(paths) {
113
+ const data = paths.map(async (path) => {
114
+ const response = await fetch(path)
115
+ return response.arrayBuffer()
116
+ })
117
+ const buffers = await Promise.all(data)
118
+
119
+ return buffers
120
+ }
121
+
122
+ /**
123
+ * @protected
124
+ * @param {ArrayBuffer[]} _buffers
125
+ * @param {Asset} _destination
126
+ * @param {Settings} _settings
127
+ * @returns {Promise<void>}
128
+ */
129
+ async parse(_buffers, _destination, _settings) {
130
+ if (this.constructor === this.constructor) {
131
+ throw `\`${this.constructor.name}\` cannot be used directly.`
132
+ }
133
+ throw `Implement \`${this.constructor.name}.parse()\``
134
+ }
135
+ /**
136
+ * @protected
137
+ * @param {Settings} _settings
138
+ * @returns {Asset}
139
+ */
140
+ default(_settings) {
141
+ if (this.constructor === this.constructor) {
142
+ throw `\`${this.constructor.name}\` cannot be used directly.`
143
+ }
144
+ throw `Implement \`${this.constructor.name}.parse()\``
145
+ }
146
+ }
147
+
148
+ /**
149
+ * @typedef LoadSettings
150
+ * @property {string[]} paths
151
+ */
152
+
153
+ /**
154
+ * @template T
155
+ * @typedef Defaultable
156
+ * @property {()=>T} default
157
+ */
158
+
159
+ /**
160
+ * @template T
161
+ * @typedef Clonable
162
+ * @property {()=>T} clone
163
+ */
164
+
165
+ /**
166
+ * @template T
167
+ * @typedef Copyable
168
+ * @property {(other:T)=>T} copy
169
+ */
170
+
171
+ /**
172
+ * @template [T = unknown]
173
+ * @typedef {new (...args:any[])=>T} Constructor
174
+ */
@@ -0,0 +1,188 @@
1
+ import { Mesh, Attribute } from '../mesh/index.js';
2
+ import { BasicMaterial } from '../material/index.js';
3
+ import { MeshMaterial3D, Object3D } from '../objects/index.js';
4
+ import { Loader } from './loader.js';
5
+ import { arrayBufferToText } from './utils.js';
6
+ import { SeparateAttributeData } from '../mesh/attributedata/separate.js';
7
+
8
+ /**
9
+ * @extends {Loader<Object3D, ObjLoadSettings>}
10
+ */
11
+ export class OBJLoader extends Loader {
12
+
13
+ constructor() {
14
+ super(Object3D)
15
+ }
16
+
17
+ /**
18
+ * @override
19
+ * @param {ArrayBuffer[]} buffers
20
+ * @param {Object3D} destination
21
+ * @param {ObjLoadSettings} _settings
22
+ */
23
+ async parse(buffers, destination, _settings) {
24
+ const buffer = buffers[0]
25
+ if (!buffer) {
26
+ return
27
+ }
28
+ const raw = arrayBufferToText(buffer)
29
+ const obj = await loadOBJ(raw)
30
+ const attributes = new SeparateAttributeData()
31
+ const position = obj.attributes.get(Attribute.Position.name)
32
+ const normals = obj.attributes.get(Attribute.Normal.name)
33
+ const uvs = obj.attributes.get(Attribute.UV.name)
34
+
35
+ if (position) {
36
+ attributes.set(Attribute.Position.name, position)
37
+ }
38
+
39
+ if (normals) {
40
+ attributes.set(Attribute.Normal.name, normals)
41
+ }
42
+
43
+ if (uvs) {
44
+ attributes.set(Attribute.UV.name, uvs)
45
+ }
46
+ const mesh = new Mesh(attributes)
47
+ const root = new MeshMaterial3D(mesh, new BasicMaterial())
48
+
49
+ destination.add(root)
50
+ }
51
+
52
+ /**
53
+ * @override
54
+ */
55
+ default() {
56
+ return new Object3D()
57
+ }
58
+ }
59
+
60
+ /**
61
+ * @param {string} data
62
+ */
63
+ async function loadOBJ(data) {
64
+ const positions = []
65
+ const uvs = []
66
+ const normals = []
67
+ const faces = []
68
+ let includeUVs = true
69
+ let includeNormals = true
70
+
71
+ const lines = data.split("\n")
72
+
73
+ for (let line of lines) {
74
+ line = line.trim();
75
+
76
+ // skip empty & comments
77
+ if (line === "" || line.startsWith("#")) continue;
78
+
79
+ const parts = line.split(/\s+/);
80
+ const keyword = parts[0];
81
+ const data = parts.slice(1);
82
+
83
+ switch (keyword) {
84
+ case "v": // vertex position
85
+ positions.push(data.map(Number));
86
+ break;
87
+ case "vt": // uv
88
+ uvs.push(data.map(Number));
89
+ break;
90
+ case "vn": // normal
91
+ normals.push(data.map(Number));
92
+ break;
93
+ case "f": { // face
94
+ const face = data.map(ref => {
95
+ const [v, vt, vn] = ref
96
+ .split("/")
97
+ .map(x => x ? parseInt(x) : undefined);
98
+
99
+ if (v === undefined) {
100
+ throw new Error("OBJ faces must always reference a position index.")
101
+ }
102
+
103
+ return {
104
+ v: v !== undefined ? v - 1 : undefined, // OBJ is 1-based → shift to 0-based
105
+ vt: vt !== undefined ? vt - 1 : undefined,
106
+ vn: vn !== undefined ? vn - 1 : undefined
107
+ };
108
+ });
109
+ includeUVs &&= face.every(vertex => vertex.vt !== undefined)
110
+ includeNormals &&= face.every(vertex => vertex.vn !== undefined)
111
+ faces.push(face);
112
+ break;
113
+ }
114
+ }
115
+ }
116
+
117
+ return buildBuffers({
118
+ positions,
119
+ uvs,
120
+ normals,
121
+ triangles: faces,
122
+ includeUVs,
123
+ includeNormals
124
+ })
125
+ }
126
+
127
+ /**
128
+ * @param {{ positions: any; uvs: any; normals: any; triangles: any; includeUVs: boolean; includeNormals: boolean; }} data
129
+ */
130
+ function buildBuffers(data) {
131
+ const positions = [];
132
+ const uvs = [];
133
+ const normals = [];
134
+
135
+ for (const triangle of data.triangles) {
136
+ for (let i = 1; i < triangle.length - 1; i++) {
137
+ const vertex1 = triangle[0]
138
+ const vertex2 = triangle[i]
139
+ const vertex3 = triangle[i + 1]
140
+
141
+ positions.push(...data.positions[vertex1.v])
142
+ if (data.includeNormals && vertex1.vn !== undefined) {
143
+ normals.push(...data.normals[vertex1.vn])
144
+ }
145
+ if (data.includeUVs && vertex1.vt !== undefined) {
146
+ uvs.push(...data.uvs[vertex1.vt])
147
+ }
148
+
149
+ positions.push(...data.positions[vertex2.v])
150
+ if (data.includeNormals && vertex2.vn !== undefined) {
151
+ normals.push(...data.normals[vertex2.vn])
152
+ }
153
+ if (data.includeUVs && vertex2.vt !== undefined) {
154
+ uvs.push(...data.uvs[vertex2.vt])
155
+ }
156
+
157
+ positions.push(...data.positions[vertex3.v])
158
+ if (data.includeNormals && vertex3.vn !== undefined) {
159
+ normals.push(...data.normals[vertex3.vn])
160
+ }
161
+ if (data.includeUVs && vertex3.vt !== undefined) {
162
+ uvs.push(...data.uvs[vertex3.vt])
163
+ }
164
+ }
165
+ }
166
+
167
+ const attributes = new Map([
168
+ [Attribute.Position.name, new DataView(new Float32Array(positions).buffer)]
169
+ ])
170
+
171
+ if (data.includeUVs && uvs.length > 0) {
172
+ attributes.set(Attribute.UV.name, new DataView(new Float32Array(uvs).buffer))
173
+ }
174
+
175
+ if (data.includeNormals && normals.length > 0) {
176
+ attributes.set(Attribute.Normal.name, new DataView(new Float32Array(normals).buffer))
177
+ }
178
+
179
+ return {
180
+ attributes,
181
+ count: positions.length / 3
182
+ };
183
+ }
184
+
185
+
186
+ /**
187
+ * @typedef {import('./loader.js').LoadSettings} ObjLoadSettings
188
+ */
@@ -0,0 +1,85 @@
1
+ /** @import { TextureSettings } from '../texture/index.js' */
2
+
3
+ import { TextureFormat, TextureType, getTextureFormatSize } from '../constants/index.js';
4
+ import { Texture } from '../texture/index.js';
5
+ import { assert } from '../utils/index.js';
6
+ import { Loader, OnAssetLoadedStrategy } from './loader.js';
7
+
8
+ /**
9
+ * @extends {Loader<Texture,TextureLoadSettings>}
10
+ */
11
+ export class TextureLoader extends Loader {
12
+
13
+ constructor() {
14
+ super(Texture)
15
+ this.strategy = OnAssetLoadedStrategy.Original
16
+ }
17
+
18
+ /**
19
+ * @override
20
+ * @param {ArrayBuffer[]} buffers
21
+ * @param {Texture} destination
22
+ */
23
+ async parse(buffers, destination) {
24
+ let width = 0, height = 0
25
+ const data = buffers.map(async (buffer) => {
26
+ const blob = await new Blob([buffer])
27
+ const bitmap = await createImageBitmap(blob)
28
+ const canvas = new OffscreenCanvas(bitmap.width, bitmap.height)
29
+ const ctx = canvas.getContext('2d')
30
+
31
+ assert(ctx, "Could not sreate context to load image.")
32
+ ctx.drawImage(bitmap, 0, 0)
33
+ width = bitmap.width
34
+ height = bitmap.height
35
+
36
+ return ctx.getImageData(0, 0, bitmap.width, bitmap.height, {
37
+ colorSpace: "srgb"
38
+ }).data.buffer
39
+ })
40
+ const textureFormat = TextureFormat.RGBA8Unorm
41
+ const images = await Promise.all(data)
42
+ const depth = images.length
43
+ const sliceSize = getTextureFormatSize(textureFormat) * width * height
44
+ const buffer = new ArrayBuffer(
45
+ sliceSize * depth
46
+ )
47
+ images.forEach((image, i) => {
48
+ const sourceView = new Uint8Array(image)
49
+ const destView = new Uint8Array(buffer, sliceSize * i, sliceSize)
50
+ destView.set(sourceView)
51
+ })
52
+ destination.data = buffer
53
+ destination.format = textureFormat,
54
+ destination.width = width
55
+ destination.height = height
56
+ destination.depth = depth
57
+ }
58
+
59
+ /**
60
+ * @override
61
+ * @param {TextureLoadSettings} settings
62
+ */
63
+ default(settings) {
64
+ const pixel = new Uint8Array(
65
+ settings.paths.flatMap(()=>[255, 0, 255, 255])
66
+ )
67
+ const texture = new Texture({
68
+ ...(settings.textureSettings || {}),
69
+ data: pixel.buffer,
70
+ type: settings.type || TextureType.Texture2D,
71
+ width: 1,
72
+ height: 1,
73
+ depth: settings.paths.length
74
+ })
75
+
76
+ return texture
77
+ }
78
+ }
79
+
80
+ /**
81
+ * @typedef TextureLoadSettings
82
+ * @property {string[]} paths
83
+ * @property {TextureType} [type]
84
+ * @property {TextureSettings} [textureSettings]
85
+ */
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @param {AllowSharedBufferSource} buffer
3
+ */
4
+ export function arrayBufferToJSON(buffer) {
5
+ const decoder = new TextDecoder('utf-8');
6
+ const jsonString = decoder.decode(buffer);
7
+ return JSON.parse(jsonString);
8
+ }
9
+
10
+ /**
11
+ * @param {AllowSharedBufferSource} buffer
12
+ */
13
+ export function arrayBufferToText(buffer) {
14
+ const decoder = new TextDecoder('utf-8')
15
+ return decoder.decode(buffer);
16
+ }
@@ -0,0 +1,75 @@
1
+ import { Material } from "./material.js"
2
+ import { Color } from "../math/index.js"
3
+ import { basicVertex, basicFragment } from "../shader/index.js"
4
+ import { Texture } from "../texture/index.js"
5
+ import { Sampler } from "../texture/sampler.js"
6
+
7
+ export class BasicMaterial extends Material {
8
+
9
+ /**
10
+ * @type {Color}
11
+ */
12
+ color
13
+
14
+ /**
15
+ * @type {Texture | undefined}
16
+ */
17
+ mainTexture
18
+
19
+ /**
20
+ * @type {Sampler | undefined}
21
+ */
22
+ mainSampler
23
+
24
+ /**
25
+ * @param {BasicMaterialOptions} param0
26
+ */
27
+ constructor({
28
+ color = new Color(1, 1, 1),
29
+ mainTexture = undefined,
30
+ mainSampler = undefined
31
+ } = {}) {
32
+ super()
33
+ this.color = color
34
+ this.mainTexture = mainTexture
35
+ this.mainSampler = mainSampler
36
+ }
37
+
38
+ /**
39
+ * @override
40
+ */
41
+ vertex() {
42
+ return basicVertex
43
+ }
44
+
45
+ /**
46
+ * @override
47
+ */
48
+ fragment() {
49
+ return basicFragment
50
+ }
51
+
52
+ /**
53
+ * @override
54
+ */
55
+ getData() {
56
+ const { color } = this
57
+
58
+ return new Float32Array([...color]).buffer
59
+ }
60
+
61
+ /**
62
+ * @override
63
+ * @returns {[string, number, Texture | undefined, Sampler | undefined][]}
64
+ */
65
+ getTextures() {
66
+ return [['mainTexture', 0, this.mainTexture, this.mainSampler]]
67
+ }
68
+ }
69
+
70
+ /**
71
+ * @typedef BasicMaterialOptions
72
+ * @property {Color} [color]
73
+ * @property {Texture | undefined} [mainTexture]
74
+ * @property {Sampler | undefined} [mainSampler]
75
+ */
@@ -0,0 +1,73 @@
1
+ import { Material } from "./material.js"
2
+ import { basicVertex, depthFragment } from "../shader/index.js"
3
+ import { Texture } from "../texture/index.js"
4
+ import { Sampler } from "../texture/sampler.js"
5
+ import { TextureFilter } from "../constants/texture.js"
6
+
7
+ // This should be a post processing effect as it renders the entire scene.
8
+ export class DepthMaterial extends Material {
9
+
10
+ /**
11
+ * @type {Texture | undefined}
12
+ */
13
+ depth
14
+
15
+ near = 0.1
16
+
17
+ far = 1000
18
+ /**
19
+ * @type {Sampler | undefined}
20
+ */
21
+ mainSampler
22
+
23
+ /**
24
+ * @param {DepthMaterialOptions} options
25
+ */
26
+ constructor({
27
+ depth
28
+ }) {
29
+ super()
30
+ this.depth = depth
31
+ this.mainSampler = new Sampler({
32
+ minificationFilter: TextureFilter.Nearest,
33
+ magnificationFilter: TextureFilter.Nearest
34
+ })
35
+ }
36
+
37
+ /**
38
+ * @override
39
+ */
40
+ vertex() {
41
+ return basicVertex
42
+ }
43
+
44
+ /**
45
+ * @override
46
+ */
47
+ fragment() {
48
+ return depthFragment
49
+ }
50
+
51
+ /**
52
+ * @override
53
+ */
54
+ getData() {
55
+ return new Float32Array([
56
+ this.near,
57
+ this.far
58
+ ]).buffer
59
+ }
60
+
61
+ /**
62
+ * @override
63
+ * @returns {[string, number, Texture | undefined, Sampler | undefined][]}
64
+ */
65
+ getTextures() {
66
+ return [['depth_texture', 0, this.depth, this.mainSampler]]
67
+ }
68
+ }
69
+
70
+ /**
71
+ * @typedef DepthMaterialOptions
72
+ * @property {Texture} depth
73
+ */
@@ -0,0 +1,8 @@
1
+ export * from "./material.js"
2
+ export * from "./basic.js"
3
+ export * from "./normal.js"
4
+ export * from "./lambert.js"
5
+ export * from "./phong.js"
6
+ export * from "./standard.js"
7
+ export * from "./depth.js"
8
+ export * from "./raw.js"
@@ -0,0 +1,73 @@
1
+ import { Material } from "./material.js"
2
+ import { Color } from "../math/index.js"
3
+ import { basicVertex, lambertFragment } from "../shader/index.js"
4
+ import { Texture, Sampler } from "../texture/index.js"
5
+
6
+ export class LambertMaterial extends Material {
7
+ /**
8
+ * @type {Color}
9
+ */
10
+ color
11
+
12
+ /**
13
+ * @type {Texture | undefined}
14
+ */
15
+ mainTexture
16
+
17
+ /**
18
+ * @type {Sampler | undefined}
19
+ */
20
+ mainSampler
21
+
22
+ /**
23
+ * @param {LambertMaterialOptions} param0
24
+ */
25
+ constructor({
26
+ mainTexture = undefined,
27
+ mainSampler = undefined,
28
+ color = new Color(1, 1, 1)
29
+ } = {}) {
30
+ super()
31
+ this.color = color
32
+ this.mainTexture = mainTexture
33
+ this.mainSampler = mainSampler
34
+ }
35
+
36
+ /**
37
+ * @override
38
+ */
39
+ vertex() {
40
+ return basicVertex
41
+ }
42
+
43
+ /**
44
+ * @override
45
+ */
46
+ fragment() {
47
+ return lambertFragment
48
+ }
49
+
50
+ /**
51
+ * @override
52
+ */
53
+ getData() {
54
+ const { color } = this
55
+
56
+ return new Float32Array([...color]).buffer
57
+ }
58
+
59
+ /**
60
+ * @returns {[string, number, Texture | undefined, Sampler | undefined][]}
61
+ * @override
62
+ */
63
+ getTextures() {
64
+ return [['mainTexture', 0, this.mainTexture, this.mainSampler]]
65
+ }
66
+ }
67
+
68
+ /**
69
+ * @typedef LambertMaterialOptions
70
+ * @property {Color} [color]
71
+ * @property {Texture} [mainTexture]
72
+ * @property {Sampler} [mainSampler]
73
+ */