ris-framework 0.1.0-dev.9 → 0.2.0-dev.11

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 (217) hide show
  1. package/CHANGELOG.md +49 -1
  2. package/README.md +15 -4
  3. package/dist/Framework.d.ts +9 -3
  4. package/dist/Framework.d.ts.map +1 -1
  5. package/dist/api/IFramework.d.ts +7 -6
  6. package/dist/api/IFramework.d.ts.map +1 -1
  7. package/dist/api/_export.d.ts +2 -0
  8. package/dist/api/_export.d.ts.map +1 -1
  9. package/dist/api/camera/CameraFactory.d.ts +3 -2
  10. package/dist/api/camera/CameraFactory.d.ts.map +1 -1
  11. package/dist/api/camera/ICamera.d.ts +5 -0
  12. package/dist/api/camera/ICamera.d.ts.map +1 -1
  13. package/dist/api/camera/ICameraFactory.d.ts +5 -6
  14. package/dist/api/camera/ICameraFactory.d.ts.map +1 -1
  15. package/dist/api/camera/OrthographicCamera.d.ts +7 -0
  16. package/dist/api/camera/OrthographicCamera.d.ts.map +1 -1
  17. package/dist/api/camera/PerspectiveCamera.d.ts +30 -6
  18. package/dist/api/camera/PerspectiveCamera.d.ts.map +1 -1
  19. package/dist/api/content/ContentManager.d.ts +67 -2
  20. package/dist/api/content/ContentManager.d.ts.map +1 -1
  21. package/dist/api/content/IContentManager.d.ts +32 -1
  22. package/dist/api/content/IContentManager.d.ts.map +1 -1
  23. package/dist/api/content/ShaderModuleContent.d.ts.map +1 -1
  24. package/dist/api/data/Color.d.ts +5 -0
  25. package/dist/api/data/Color.d.ts.map +1 -1
  26. package/dist/api/geometry/BaseGeometry.d.ts +9 -0
  27. package/dist/api/geometry/BaseGeometry.d.ts.map +1 -1
  28. package/dist/api/geometry/GeometryBuilder.d.ts +3 -1
  29. package/dist/api/geometry/GeometryBuilder.d.ts.map +1 -1
  30. package/dist/api/geometry/IGeometryBuilder.d.ts +24 -0
  31. package/dist/api/geometry/IGeometryBuilder.d.ts.map +1 -1
  32. package/dist/api/geometry/_export-geometry.d.ts +1 -0
  33. package/dist/api/geometry/_export-geometry.d.ts.map +1 -1
  34. package/dist/api/input/InputManager.d.ts +4 -0
  35. package/dist/api/input/InputManager.d.ts.map +1 -1
  36. package/dist/api/lights/AmbientLight.d.ts +35 -0
  37. package/dist/api/lights/AmbientLight.d.ts.map +1 -0
  38. package/dist/api/lights/DirectionalLight.d.ts +40 -0
  39. package/dist/api/lights/DirectionalLight.d.ts.map +1 -0
  40. package/dist/api/lights/LightFactory.d.ts +18 -0
  41. package/dist/api/lights/LightFactory.d.ts.map +1 -0
  42. package/dist/api/lights/LightId.d.ts +6 -0
  43. package/dist/api/lights/LightId.d.ts.map +1 -0
  44. package/dist/api/lights/LightsBuffer.d.ts +70 -0
  45. package/dist/api/lights/LightsBuffer.d.ts.map +1 -0
  46. package/dist/api/lights/PointLight.d.ts +59 -0
  47. package/dist/api/lights/PointLight.d.ts.map +1 -0
  48. package/dist/api/lights/_export.d.ts +6 -0
  49. package/dist/api/lights/_export.d.ts.map +1 -0
  50. package/dist/api/loaders/ObjGeometryMapper.d.ts +19 -0
  51. package/dist/api/loaders/ObjGeometryMapper.d.ts.map +1 -0
  52. package/dist/api/loaders/_export.d.ts +1 -0
  53. package/dist/api/loaders/_export.d.ts.map +1 -1
  54. package/dist/api/loaders/obj/ObjLoader.d.ts +29 -0
  55. package/dist/api/loaders/obj/ObjLoader.d.ts.map +1 -0
  56. package/dist/api/loaders/obj/ObjTypes.d.ts +103 -0
  57. package/dist/api/loaders/obj/ObjTypes.d.ts.map +1 -0
  58. package/dist/api/loaders/obj/index.d.ts +3 -0
  59. package/dist/api/loaders/obj/index.d.ts.map +1 -0
  60. package/dist/api/material/ForwardBlinnPhongMaterial.d.ts +127 -0
  61. package/dist/api/material/ForwardBlinnPhongMaterial.d.ts.map +1 -0
  62. package/dist/api/material/IMaterial.d.ts +15 -6
  63. package/dist/api/material/IMaterial.d.ts.map +1 -1
  64. package/dist/api/material/IMaterialFactory.d.ts +17 -2
  65. package/dist/api/material/IMaterialFactory.d.ts.map +1 -1
  66. package/dist/api/material/InspectTextureMipsMaterial.d.ts +16 -7
  67. package/dist/api/material/InspectTextureMipsMaterial.d.ts.map +1 -1
  68. package/dist/api/material/MaterialFactory.d.ts +6 -0
  69. package/dist/api/material/MaterialFactory.d.ts.map +1 -1
  70. package/dist/api/material/SpriteMaterial.d.ts +51 -0
  71. package/dist/api/material/SpriteMaterial.d.ts.map +1 -0
  72. package/dist/api/material/UnlitMaterial.d.ts +28 -10
  73. package/dist/api/material/UnlitMaterial.d.ts.map +1 -1
  74. package/dist/api/material/_export.d.ts +2 -0
  75. package/dist/api/material/_export.d.ts.map +1 -1
  76. package/dist/api/meshes/IMesh.d.ts +35 -5
  77. package/dist/api/meshes/IMesh.d.ts.map +1 -1
  78. package/dist/api/meshes/IMeshFactory.d.ts +25 -4
  79. package/dist/api/meshes/IMeshFactory.d.ts.map +1 -1
  80. package/dist/api/meshes/Mesh.d.ts +58 -6
  81. package/dist/api/meshes/Mesh.d.ts.map +1 -1
  82. package/dist/api/meshes/MeshFactory.d.ts +7 -3
  83. package/dist/api/meshes/MeshFactory.d.ts.map +1 -1
  84. package/dist/api/meshes/QuadMesh.d.ts +5 -1
  85. package/dist/api/meshes/QuadMesh.d.ts.map +1 -1
  86. package/dist/api/meshes/SubMesh.d.ts +47 -0
  87. package/dist/api/meshes/SubMesh.d.ts.map +1 -0
  88. package/dist/api/meshes/_export.d.ts +1 -0
  89. package/dist/api/meshes/_export.d.ts.map +1 -1
  90. package/dist/api/rendering/render-pipelines/IForwardBlinnPhongRenderPipeline.d.ts +56 -0
  91. package/dist/api/rendering/render-pipelines/IForwardBlinnPhongRenderPipeline.d.ts.map +1 -0
  92. package/dist/api/rendering/render-pipelines/IRenderPipeline.d.ts +3 -0
  93. package/dist/api/rendering/render-pipelines/IRenderPipeline.d.ts.map +1 -1
  94. package/dist/api/rendering/render-pipelines/IRenderPipelineFactory.d.ts +29 -0
  95. package/dist/api/rendering/render-pipelines/IRenderPipelineFactory.d.ts.map +1 -1
  96. package/dist/api/rendering/render-pipelines/_export-render-pipelines.d.ts +1 -0
  97. package/dist/api/rendering/render-pipelines/_export-render-pipelines.d.ts.map +1 -1
  98. package/dist/api/scene/Scene.d.ts +104 -0
  99. package/dist/api/scene/Scene.d.ts.map +1 -0
  100. package/dist/api/shader/IShaderModuleLoader.d.ts +4 -1
  101. package/dist/api/shader/IShaderModuleLoader.d.ts.map +1 -1
  102. package/dist/api/shader/{shader-loader.d.ts → ShaderLoader.d.ts} +1 -1
  103. package/dist/api/shader/ShaderLoader.d.ts.map +1 -0
  104. package/dist/api/sprites/SpriteBatchDrawable.d.ts +1 -1
  105. package/dist/api/sprites/SpriteBatchDrawable.d.ts.map +1 -1
  106. package/dist/api/sprites/SpriteBatchMesh.d.ts +14 -1
  107. package/dist/api/sprites/SpriteBatchMesh.d.ts.map +1 -1
  108. package/dist/api/utilities/GeometryUtilities.d.ts.map +1 -1
  109. package/dist/api/window/WindowManager.d.ts +4 -0
  110. package/dist/api/window/WindowManager.d.ts.map +1 -1
  111. package/dist/core/rendering/vertex-buffer-layout.d.ts +1 -0
  112. package/dist/core/rendering/vertex-buffer-layout.d.ts.map +1 -1
  113. package/dist/index.js +2252 -260
  114. package/dist/webgl/WebGlGraphicsDevice.d.ts.map +1 -1
  115. package/dist/webgl/lights/WebGlAmbientLightFactory.d.ts +17 -0
  116. package/dist/webgl/lights/WebGlAmbientLightFactory.d.ts.map +1 -0
  117. package/dist/webgl/lights/WebGlLightsBuffer.d.ts +55 -0
  118. package/dist/webgl/lights/WebGlLightsBuffer.d.ts.map +1 -0
  119. package/dist/webgl/render-pipelines/AWebGlRenderPipeline.d.ts +3 -1
  120. package/dist/webgl/render-pipelines/AWebGlRenderPipeline.d.ts.map +1 -1
  121. package/dist/webgl/render-pipelines/WebGlMainRenderTargetRenderPipeline.d.ts +3 -0
  122. package/dist/webgl/render-pipelines/WebGlMainRenderTargetRenderPipeline.d.ts.map +1 -1
  123. package/dist/webgl/render-pipelines/WebGlRenderPipelineFactory.d.ts +3 -1
  124. package/dist/webgl/render-pipelines/WebGlRenderPipelineFactory.d.ts.map +1 -1
  125. package/dist/webgl/render-pipelines/inspect/WebGlInspectTextureMipsRenderPipeline.d.ts +3 -1
  126. package/dist/webgl/render-pipelines/inspect/WebGlInspectTextureMipsRenderPipeline.d.ts.map +1 -1
  127. package/dist/webgl/render-pipelines/material/WebGlBlinnPhongRenderPipeline.d.ts +88 -0
  128. package/dist/webgl/render-pipelines/material/WebGlBlinnPhongRenderPipeline.d.ts.map +1 -0
  129. package/dist/webgl/render-pipelines/material/WebGlUnlitRenderPipeline.d.ts +3 -1
  130. package/dist/webgl/render-pipelines/material/WebGlUnlitRenderPipeline.d.ts.map +1 -1
  131. package/dist/webgl/render-pipelines/sprite/WebGlSpriteRenderPipeline.d.ts +3 -1
  132. package/dist/webgl/render-pipelines/sprite/WebGlSpriteRenderPipeline.d.ts.map +1 -1
  133. package/dist/webgl/shader/WebGlShaderModule.d.ts +4 -1
  134. package/dist/webgl/shader/WebGlShaderModule.d.ts.map +1 -1
  135. package/dist/webgl/shader/WebGlShaderModuleLoader.d.ts +16 -5
  136. package/dist/webgl/shader/WebGlShaderModuleLoader.d.ts.map +1 -1
  137. package/dist/webgl/texture/WebGlTexture2D.d.ts +8 -1
  138. package/dist/webgl/texture/WebGlTexture2D.d.ts.map +1 -1
  139. package/dist/webgl/utilities/webgl-filter-anisotropic-utilities.d.ts +0 -1
  140. package/dist/webgl/utilities/webgl-filter-anisotropic-utilities.d.ts.map +1 -1
  141. package/package.json +4 -4
  142. package/shaders/glsl/forward_blinn_phong_material_fs.glsl +110 -0
  143. package/shaders/glsl/forward_blinn_phong_material_vs.glsl +32 -0
  144. package/shaders/glsl/sprite_fs.glsl +1 -1
  145. package/shaders/glsl/unlit_material_fs.glsl +1 -1
  146. package/src/Framework.ts +37 -13
  147. package/src/api/IFramework.ts +8 -6
  148. package/src/api/_export.ts +2 -0
  149. package/src/api/camera/CameraFactory.ts +6 -6
  150. package/src/api/camera/ICamera.ts +6 -0
  151. package/src/api/camera/ICameraFactory.ts +5 -10
  152. package/src/api/camera/OrthographicCamera.ts +23 -1
  153. package/src/api/camera/PerspectiveCamera.ts +60 -15
  154. package/src/api/content/ContentManager.ts +201 -5
  155. package/src/api/content/IContentManager.ts +33 -1
  156. package/src/api/content/ShaderModuleContent.ts +9 -0
  157. package/src/api/data/Color.ts +7 -1
  158. package/src/api/geometry/BaseGeometry.ts +23 -0
  159. package/src/api/geometry/GeometryBuilder.ts +14 -2
  160. package/src/api/geometry/IGeometryBuilder.ts +31 -1
  161. package/src/api/geometry/_export-geometry.ts +2 -1
  162. package/src/api/input/InputManager.ts +14 -5
  163. package/src/api/lights/AmbientLight.ts +53 -0
  164. package/src/api/lights/DirectionalLight.ts +60 -0
  165. package/src/api/lights/LightFactory.ts +21 -0
  166. package/src/api/lights/LightId.ts +9 -0
  167. package/src/api/lights/LightsBuffer.ts +87 -0
  168. package/src/api/lights/PointLight.ts +91 -0
  169. package/src/api/lights/_export.ts +5 -0
  170. package/src/api/loaders/ObjGeometryMapper.ts +28 -0
  171. package/src/api/loaders/_export.ts +2 -1
  172. package/src/api/loaders/obj/ObjLoader.ts +270 -0
  173. package/src/api/loaders/obj/ObjTypes.ts +124 -0
  174. package/src/api/loaders/obj/index.ts +5 -0
  175. package/src/api/material/ForwardBlinnPhongMaterial.ts +302 -0
  176. package/src/api/material/IMaterial.ts +16 -6
  177. package/src/api/material/IMaterialFactory.ts +19 -2
  178. package/src/api/material/InspectTextureMipsMaterial.ts +63 -24
  179. package/src/api/material/MaterialFactory.ts +12 -0
  180. package/src/api/material/SpriteMaterial.ts +83 -0
  181. package/src/api/material/UnlitMaterial.ts +101 -29
  182. package/src/api/material/_export.ts +3 -1
  183. package/src/api/meshes/IMesh.ts +45 -6
  184. package/src/api/meshes/IMeshFactory.ts +27 -4
  185. package/src/api/meshes/Mesh.ts +163 -41
  186. package/src/api/meshes/MeshFactory.ts +30 -6
  187. package/src/api/meshes/QuadMesh.ts +6 -2
  188. package/src/api/meshes/SubMesh.ts +71 -0
  189. package/src/api/meshes/_export.ts +1 -0
  190. package/src/api/rendering/render-pipelines/IForwardBlinnPhongRenderPipeline.ts +66 -0
  191. package/src/api/rendering/render-pipelines/IRenderPipeline.ts +4 -0
  192. package/src/api/rendering/render-pipelines/IRenderPipelineFactory.ts +39 -0
  193. package/src/api/rendering/render-pipelines/_export-render-pipelines.ts +2 -1
  194. package/src/api/scene/Scene.ts +264 -0
  195. package/src/api/shader/IShaderModuleLoader.ts +2 -1
  196. package/src/api/sprites/SpriteBatchDrawable.ts +12 -16
  197. package/src/api/sprites/SpriteBatchMesh.ts +23 -4
  198. package/src/api/utilities/GeometryUtilities.ts +2 -0
  199. package/src/api/window/WindowManager.ts +22 -2
  200. package/src/core/rendering/vertex-buffer-layout.ts +32 -1
  201. package/src/main.ts +0 -1
  202. package/src/webgl/WebGlGraphicsDevice.ts +0 -1
  203. package/src/webgl/lights/WebGlAmbientLightFactory.ts +35 -0
  204. package/src/webgl/lights/WebGlLightsBuffer.ts +215 -0
  205. package/src/webgl/render-pipelines/AWebGlRenderPipeline.ts +7 -1
  206. package/src/webgl/render-pipelines/WebGlMainRenderTargetRenderPipeline.ts +3 -0
  207. package/src/webgl/render-pipelines/WebGlRenderPipelineFactory.ts +24 -2
  208. package/src/webgl/render-pipelines/inspect/WebGlInspectTextureMipsRenderPipeline.ts +16 -6
  209. package/src/webgl/render-pipelines/material/WebGlBlinnPhongRenderPipeline.ts +300 -0
  210. package/src/webgl/render-pipelines/material/WebGlUnlitRenderPipeline.ts +16 -6
  211. package/src/webgl/render-pipelines/sprite/WebGlSpriteRenderPipeline.ts +11 -7
  212. package/src/webgl/shader/WebGlShaderModule.ts +11 -4
  213. package/src/webgl/shader/WebGlShaderModuleLoader.ts +29 -10
  214. package/src/webgl/texture/WebGlTexture2D.ts +19 -5
  215. package/src/webgl/utilities/webgl-filter-anisotropic-utilities.ts +9 -6
  216. package/dist/api/shader/shader-loader.d.ts.map +0 -1
  217. /package/src/api/shader/{shader-loader.ts → ShaderLoader.ts} +0 -0
@@ -3,12 +3,29 @@ import {
3
3
  type IContentManager,
4
4
  type IShaderModuleLoader,
5
5
  type ITexture2D,
6
- type IFramework, TextureDescriptor, TextureFormat, ContentConfig, TextureUsage
6
+ type IFramework,
7
+ TextureDescriptor,
8
+ TextureFormat,
9
+ ContentConfig,
10
+ TextureUsage,
11
+ type IMesh,
12
+ ObjLoader,
13
+ Color,
14
+ type ICamera,
15
+ type IMaterial,
16
+ type ObjMaterialDefinition,
17
+ type SubMeshDescriptor,
18
+ type ObjLoadResult,
19
+ type ObjGeometryDefinition,
20
+ type IGeometry,
21
+ type LightsBuffer,
22
+ type Scene,
23
+ type IDisposable,
7
24
  } from "../index.ts";
25
+ import {ObjGeometryMapper} from "../loaders/ObjGeometryMapper.ts";
8
26
  import {Ktx2Factory} from "ris-ktx2";
9
27
  import type {IKtx2Texture} from "ris-ktx2";
10
28
 
11
-
12
29
  /**
13
30
  * The content manager.
14
31
  * The content manager is responsible for managing the content modules and loading the content with the given asset file path or identifier.
@@ -17,6 +34,7 @@ export class ContentManager implements IContentManager {
17
34
 
18
35
  private readonly _ktx2Factory = new Ktx2Factory();
19
36
  private readonly _ktx2TextureCache: {[key: string]: IKtx2Texture} = {};
37
+ private readonly _objLoader = new ObjLoader();
20
38
 
21
39
  /**
22
40
  * The constructor.
@@ -41,9 +59,20 @@ export class ContentManager implements IContentManager {
41
59
  return ktx2Texture;
42
60
  }
43
61
 
62
+ /**
63
+ * Disposes the cached shader modules (their GL programs) and forgets cached KTX2 data.
64
+ * Called from `Framework.dispose()`.
65
+ */
66
+ public dispose(): void {
67
+ (this.shaderModuleLoader as Partial<IDisposable>).dispose?.();
68
+ for (const key of Object.keys(this._ktx2TextureCache)) {
69
+ delete this._ktx2TextureCache[key];
70
+ }
71
+ }
72
+
44
73
  /** @inheritDoc */
45
- public loadShaderModule(shaderModuleId: string): IShaderModule {
46
- return this.shaderModuleLoader.load(shaderModuleId);
74
+ public loadShaderModule(shaderModuleId: string, keyValueDictionary?: { [id:string]: number}): IShaderModule {
75
+ return this.shaderModuleLoader.load(shaderModuleId, keyValueDictionary);
47
76
  }
48
77
 
49
78
  /** @inheritDoc */
@@ -84,4 +113,171 @@ export class ContentManager implements IContentManager {
84
113
  return this._framework.textureFactory.create(width, height, view);
85
114
  }
86
115
 
87
- }
116
+ /** @inheritDoc */
117
+ public async loadMeshAsync(path: string, scene: Scene): Promise<IMesh> {
118
+
119
+ const objResult = await this._loadObj(path);
120
+ const geometry = this._createGeometry(objResult.geometry);
121
+ const subMeshes = this._createSubMeshDescriptors(objResult,
122
+ definition => this._createUnlitMaterial(definition, scene.camera));
123
+
124
+ return this._framework.meshFactory.createWithSubMeshes(scene, geometry, subMeshes);
125
+ }
126
+
127
+ /** @inheritDoc */
128
+ public async loadBlinnPhongMeshAsync(path: string, scene: Scene): Promise<IMesh> {
129
+ // Checked before loading, so a missing camera fails fast.
130
+ const camera = scene.camera;
131
+ if (!camera) {
132
+ throw new Error(`loadBlinnPhongMeshAsync("${path}"): the scene has no camera. Set scene.camera (or pass the scene to createPerspectiveCamera) before loading a Blinn-Phong mesh.`);
133
+ }
134
+ if (!camera.positionBuffer || !camera.projectionViewBuffer) {
135
+ const what = [camera.projectionViewBuffer ? undefined : "projectionViewBuffer", camera.positionBuffer ? undefined : "positionBuffer"]
136
+ .filter(x => x !== undefined).join(" and ");
137
+ throw new Error(`loadBlinnPhongMeshAsync("${path}"): the scene camera has no ${what}. Call camera.initialize() first (the camera factory does).`);
138
+ }
139
+ const objResult = await this._loadObj(path);
140
+ const geometry = this._createGeometry(objResult.geometry);
141
+ const subMeshes = this._createSubMeshDescriptors(objResult,
142
+ definition => this._createBlinnPhongMaterial(definition, camera, scene.__forwardLightsBuffer));
143
+
144
+ return this._framework.meshFactory.createWithSubMeshes(scene, geometry, subMeshes);
145
+ }
146
+
147
+ /**
148
+ * Loads the OBJ file and its .mtl material libraries.
149
+ * @param path The path or url to the .obj file.
150
+ * @returns The plain OBJ data.
151
+ */
152
+ private _loadObj(path: string): Promise<ObjLoadResult> {
153
+ return this._objLoader.loadAsync(path);
154
+ }
155
+
156
+ /**
157
+ * Creates framework geometry from the OBJ geometry.
158
+ * Vertex colours stay white, because each submesh's material carries the colour.
159
+ * @param definition The OBJ geometry definition.
160
+ * @returns The geometry.
161
+ */
162
+ private _createGeometry(definition: ObjGeometryDefinition): IGeometry {
163
+ const descriptor = ObjGeometryMapper.toDescriptor(definition);
164
+ return this._framework.geometryBuilder.create(descriptor);
165
+ }
166
+
167
+
168
+ /**
169
+ * Creates one submesh descriptor per material range.
170
+ * Ranges that use the same material name share one material instance.
171
+ * @param objResult The loaded OBJ data.
172
+ * @param createMaterial Creates the material for a definition (undefined without `usemtl` or .mtl entry).
173
+ * @returns The submesh descriptors, in file order.
174
+ */
175
+ private _createSubMeshDescriptors(
176
+ objResult: ObjLoadResult,
177
+ createMaterial: (definition: ObjMaterialDefinition | undefined) => IMaterial): SubMeshDescriptor[] {
178
+
179
+ const definitionsByName = this._indexMaterialDefinitions(objResult.materials);
180
+ const materialsByName = new Map<string | undefined, IMaterial>();
181
+ const subMeshes: SubMeshDescriptor[] = [];
182
+
183
+ for (const range of objResult.geometry.materialRanges) {
184
+ let material = materialsByName.get(range.materialName);
185
+ if (material === undefined) {
186
+ const definition = this._findMaterialDefinition(definitionsByName, range.materialName);
187
+ material = createMaterial(definition);
188
+ materialsByName.set(range.materialName, material);
189
+ }
190
+
191
+ subMeshes.push({
192
+ material: material,
193
+ indexStart: range.indexStart,
194
+ indexCount: range.indexCount,
195
+ });
196
+ }
197
+
198
+ return subMeshes;
199
+ }
200
+
201
+ /**
202
+ * Indexes material definitions by name.
203
+ * @param definitions The material definitions from the .mtl files.
204
+ * @returns A map from material name to definition.
205
+ */
206
+ private _indexMaterialDefinitions(definitions: ObjMaterialDefinition[]): Map<string, ObjMaterialDefinition> {
207
+ const definitionsByName = new Map<string, ObjMaterialDefinition>();
208
+ for (const definition of definitions) {
209
+ definitionsByName.set(definition.name, definition);
210
+ }
211
+ return definitionsByName;
212
+ }
213
+
214
+ /**
215
+ * Finds the definition for a `usemtl` name.
216
+ * @param definitionsByName The definitions by name.
217
+ * @param materialName The material name, or undefined for faces without `usemtl`.
218
+ * @returns The definition, or undefined when there is none.
219
+ */
220
+ private _findMaterialDefinition(
221
+ definitionsByName: Map<string, ObjMaterialDefinition>,
222
+ materialName: string | undefined): ObjMaterialDefinition | undefined {
223
+ if (materialName === undefined) {
224
+ return undefined;
225
+ }
226
+ return definitionsByName.get(materialName);
227
+ }
228
+
229
+ /**
230
+ * Creates the default unlit material for an OBJ material definition.
231
+ * The diffuse colour is the definition's `Kd` with `d` as alpha; white when there is no definition.
232
+ * @param definition The material definition, or undefined.
233
+ * @param camera The scene's current camera, or undefined; the scene assigns it on update.
234
+ * @returns The unlit material.
235
+ */
236
+ private _createUnlitMaterial(definition: ObjMaterialDefinition | undefined, camera: ICamera | undefined): IMaterial {
237
+ const material = this._framework.materialFactory.createUnlitMaterial({
238
+ camera: camera,
239
+ });
240
+
241
+ const diffuse = definition?.diffuseColor ?? [1, 1, 1];
242
+ const opacity = definition?.opacity ?? 1;
243
+ material.diffuseColor = new Color(diffuse[0], diffuse[1], diffuse[2], opacity);
244
+ return material;
245
+ }
246
+
247
+ /**
248
+ * Creates a Blinn-Phong material for an OBJ material definition.
249
+ * `Kd` (with `d` as alpha) becomes the diffuse colour, white when missing.
250
+ * `Ka` becomes the ambient colour; when missing the diffuse colour is used, so ambient light tints by the surface colour.
251
+ * `Ks` and `Ns` become specular colour and shininess; when missing the material defaults stay (0.5 grey, 32).
252
+ * @param definition The material definition, or undefined.
253
+ * @param camera The scene's camera; its projection view and position buffers are bound.
254
+ * @param lightsBuffer The optional lights buffer; the shader is compiled for its light counts.
255
+ * @returns The Blinn-Phong material.
256
+ */
257
+ private _createBlinnPhongMaterial(
258
+ definition: ObjMaterialDefinition | undefined,
259
+ camera: ICamera,
260
+ lightsBuffer: LightsBuffer | undefined): IMaterial {
261
+
262
+ const material = this._framework.materialFactory.createForwardBlinnPhongMaterial({
263
+ projectionViewBuffer: camera.projectionViewBuffer,
264
+ cameraPositionBuffer: camera.positionBuffer,
265
+ lightsBuffer: lightsBuffer,
266
+ });
267
+ // Matches the scene camera, so Scene.update() does not rebind.
268
+ material.camera = camera;
269
+
270
+ const diffuse = definition?.diffuseColor ?? [1, 1, 1];
271
+ const ambient = definition?.ambientColor ?? diffuse;
272
+ material.diffuseColor = new Color(diffuse[0], diffuse[1], diffuse[2], definition?.opacity ?? 1);
273
+ material.ambientColor = new Color(ambient[0], ambient[1], ambient[2]);
274
+ if (definition?.specularColor) {
275
+ const specular = definition.specularColor;
276
+ material.specularColor = new Color(specular[0], specular[1], specular[2]);
277
+ }
278
+ if (definition?.specularExponent !== undefined) {
279
+ material.shininess = definition.specularExponent;
280
+ }
281
+ return material;
282
+ }
283
+ }
@@ -1,9 +1,11 @@
1
+ import type { Scene } from "../scene/Scene.ts";
1
2
  import type { IShaderModuleLoader } from "../shader/IShaderModuleLoader.ts";
2
3
  import type { IShaderModule } from "../shader/IShaderModule.ts";
3
4
  import type { ITexture2D } from "../rendering/texture/ITexture2D.ts";
4
5
  import {TextureDescriptor} from "../rendering/texture/TextureDescriptor.ts";
5
6
  import {ContentConfig} from "./ContentConfig.ts";
6
7
  import type { IKtx2Texture } from "ris-ktx2";
8
+ import type {IMesh} from "../meshes/IMesh.ts";
7
9
 
8
10
  /**
9
11
  * The content manager.
@@ -26,9 +28,10 @@ export interface IContentManager {
26
28
  /**
27
29
  * Loads a shader module.
28
30
  * @param shaderAssetId - The id of a shader asset.
31
+ * @param keyValueDictionary - If present, tries to find key in shader such that it replaced ##DIRECTIONAL_LIGHT_COUNT## by given value for key DIRECTIONAL_LIGHST_COUNT.
29
32
  * @returns The shader module.
30
33
  */
31
- loadShaderModule(shaderAssetId: string): IShaderModule;
34
+ loadShaderModule(shaderAssetId: string, keyValueDictionary?: { [id:string]: number}): IShaderModule;
32
35
 
33
36
  /**
34
37
  * Loads a texture2D.
@@ -38,4 +41,33 @@ export interface IContentManager {
38
41
  * @returns The Texture2D.
39
42
  */
40
43
  loadTexture2DAsync(path: string, desc?: TextureDescriptor, contentConfig?: ContentConfig): Promise<ITexture2D>;
44
+
45
+ /**
46
+ * Loads a mesh from a model, typically.
47
+ * Currently, OBJ(WAVEFRONT) is supported.
48
+ * The mesh has one submesh per `usemtl` range, all sharing one vertex and index buffer.
49
+ * By default, each submesh gets an unlit material with the .mtl `Kd` as diffuse colour and `d` as alpha.
50
+ * @param path The path or url to the model.
51
+ * @param scene The scene the mesh adds itself to; `scene.render()` draws it. The materials use `scene.camera`
52
+ * (assigned on `scene.update()` when it is set later).
53
+ * @return The mesh.
54
+ */
55
+ loadMeshAsync(path: string, scene: Scene): Promise<IMesh>;
56
+
57
+ /**
58
+ * Loads an OBJ (Wavefront) mesh with lit Blinn-Phong materials.
59
+ * Like {@link loadMeshAsync}, the mesh has one submesh per `usemtl` range sharing one vertex and index buffer,
60
+ * and ranges with the same material name share one material. `scene.render()` draws it.
61
+ * The .mtl values map onto `ForwardBlinnPhongMaterial`:
62
+ * - `Kd` → `diffuseColor` (with `d` as alpha), white when missing.
63
+ * - `Ka` → `ambientColor`, the diffuse colour when missing.
64
+ * - `Ks` → `specularColor` and `Ns` → `shininess`, the material defaults (0.5 grey, 32) when missing.
65
+ * Without an .mtl file every submesh gets a white material with those defaults.
66
+ * @param path The path or url to the .obj file. A relative `mtllib` is resolved against it.
67
+ * @param scene The scene the mesh adds itself to. Every material uses the scene's lights and `scene.camera`
68
+ * (assigned on `scene.update()` when it is set later).
69
+ * @return The mesh.
70
+ */
71
+ loadBlinnPhongMeshAsync(path: string, scene: Scene): Promise<IMesh>;
72
+
41
73
  }
@@ -6,6 +6,9 @@ import inspectTextureMipsVS from "../../../shaders/glsl/inspect_texture_mips_vs.
6
6
  import inspectTextureMipsFS from "../../../shaders/glsl/inspect_texture_mips_fs.glsl?raw";
7
7
  import unlitMaterialVS from "../../../shaders/glsl/unlit_material_vs.glsl?raw";
8
8
  import unlitMaterialFS from "../../../shaders/glsl/unlit_material_fs.glsl?raw";
9
+ import forwardBlinnPhongVS from "../../../shaders/glsl/forward_blinn_phong_material_vs.glsl?raw";
10
+ import forwardBlinnPhongFS from "../../../shaders/glsl/forward_blinn_phong_material_fs.glsl?raw";
11
+
9
12
 
10
13
  /**
11
14
  * The api should look something like this for internal ones.
@@ -43,5 +46,11 @@ export const ShaderModuleContent : {[id: string]: any} = {
43
46
  "vertex": unlitMaterialVS,
44
47
  "fragment": unlitMaterialFS,
45
48
  "reflection": {}
49
+ },
50
+
51
+ "forward_blinn_phong_material": {
52
+ "vertex": forwardBlinnPhongVS,
53
+ "fragment": forwardBlinnPhongFS,
54
+ "reflection": {}
46
55
  }
47
56
  }
@@ -222,7 +222,13 @@ export class Color implements Iterable<number>{
222
222
  o
223
223
  }
224
224
 
225
-
225
+ /**
226
+ * Copy self and return new instance with same values.
227
+ * @return Color
228
+ * */
229
+ public copy(): Color {
230
+ return new Color(this.r, this.g, this.b, this.a);
231
+ }
226
232
  }
227
233
 
228
234
 
@@ -2,11 +2,34 @@ import { GeometryFormat } from "./GeometryFormat.ts";
2
2
  import {VertexFormat} from "./VertexFormat.ts";
3
3
  import type {IGeometry} from "../index.ts";
4
4
 
5
+
5
6
  /**
6
7
  * The default IGeometry implementation. GeometryBuilder fills it with vertex data.
7
8
  */
8
9
  export class BaseGeometry implements IGeometry {
9
10
 
11
+ /**
12
+ * Initializes a new instance of the BaseGeometry class.
13
+ * @param positions The optional positions of the geometry.
14
+ * @param indices The optional indices of the geometry.
15
+ * @param normals The optional normals of the geometry.
16
+ * @param textureCoords The optional texture coordinates of the geometry.
17
+ * @param colors The optional colors of the geometry.
18
+ */
19
+ constructor(positions?: number[], indices?: number[], normals?: number[], textureCoords?: number[], colors?: number[]) {
20
+ this.positions = positions;
21
+ this.indices = indices;
22
+ this.normals = normals;
23
+ this.textureCoords = textureCoords;
24
+ this.colors = colors;
25
+
26
+ if(this.indices && this.indices.length > 0) {
27
+ this.vertexCount = this.indices.length / 3;
28
+ } else if(this.positions && this.positions.length > 0) {
29
+ this.vertexCount = this.positions.length / 3;
30
+ }
31
+ }
32
+
10
33
  /** @inheritdoc */
11
34
  public vertexCount: number = 0;
12
35
 
@@ -1,6 +1,6 @@
1
1
  import { vec2 } from "gl-matrix"
2
2
  import { BaseGeometry } from "./BaseGeometry.ts";
3
- import type {IGeometry, IGeometryBuilder} from "../index.ts";
3
+ import type {IGeometry, IGeometryBuilder, GeometryDescriptor} from "../index.ts";
4
4
 
5
5
  /**
6
6
  * The GeometryBuilder class provides methods for creating various types of geometries, such as quads, with specified parameters like scale and winding order.
@@ -55,4 +55,16 @@ export class GeometryBuilder implements IGeometryBuilder {
55
55
 
56
56
  return geometry;
57
57
  }
58
- }
58
+
59
+ /** @inheritdoc */
60
+ public create(descriptor: GeometryDescriptor): IGeometry {
61
+ const vertexCount = descriptor.positions.length / 3;
62
+ return new BaseGeometry(
63
+ [...descriptor.positions],
64
+ descriptor.indices ? [...descriptor.indices] : undefined,
65
+ descriptor.normals ? [...descriptor.normals] : new Array(vertexCount * 3).fill(0),
66
+ descriptor.textureCoords ? [...descriptor.textureCoords] : new Array(vertexCount * 2).fill(0),
67
+ descriptor.colors ? [...descriptor.colors] : new Array(vertexCount * 4).fill(1),
68
+ );
69
+ }
70
+ }
@@ -1,6 +1,28 @@
1
1
  import type { IGeometry } from "./IGeometry.ts";
2
2
  import {vec2} from "gl-matrix";
3
3
 
4
+ /**
5
+ * The geometry descriptor.
6
+ * @public
7
+ */
8
+ export interface GeometryDescriptor {
9
+
10
+ /** Positions, 3 per vertex. */
11
+ readonly positions: number[];
12
+
13
+ /** Triangle indices, 3 per triangle. Optional for non-indexed geometry. */
14
+ readonly indices?: number[];
15
+
16
+ /** Normals, 3 per vertex. */
17
+ readonly normals?: number[];
18
+
19
+ /** Texture coordinates, 2 per vertex. */
20
+ readonly textureCoords?: number[];
21
+
22
+ /** RGBA colours, 4 per vertex. */
23
+ readonly colors?: number[];
24
+ }
25
+
4
26
  /**
5
27
  * The geometry builder.
6
28
  */
@@ -13,5 +35,13 @@ export interface IGeometryBuilder {
13
35
  * @returns The geometry.
14
36
  */
15
37
  quadGeometry(scale?: vec2, counterClockwise?: boolean): IGeometry;
16
-
38
+
39
+ /**
40
+ * Creates geometry from a plain descriptor.
41
+ * Attributes a material's geometry format needs but the descriptor lacks are filled with defaults:
42
+ * white colours, zero texture coordinates and zero normals.
43
+ * @param descriptor - The geometry descriptor. Its arrays are copied.
44
+ * @returns The geometry.
45
+ */
46
+ create(descriptor: GeometryDescriptor): IGeometry;
17
47
  }
@@ -1,4 +1,5 @@
1
1
  export * from "./IGeometryBuilder.ts";
2
2
  export * from "./IGeometry.ts";
3
3
  export * from "./VertexFormat.ts";
4
- export * from "./GeometryFormat.ts";
4
+ export * from "./GeometryFormat.ts";
5
+ export * from "./BaseGeometry.ts";
@@ -63,6 +63,8 @@ export class InputManager implements IInputManager {
63
63
  private readonly _touchCapabilities: TouchPanelCapabilities;
64
64
  private readonly _contacts: TouchContact[];
65
65
  private _touchListening = false;
66
+ /** Aborting it removes every canvas listener added in initialize(). */
67
+ private _listeners = new AbortController();
66
68
  /** Set in update, consumed in afterUpdate. Ageing before a publish would hide the press. */
67
69
  private _touchPublished = false;
68
70
 
@@ -120,6 +122,13 @@ export class InputManager implements IInputManager {
120
122
  return this._touchCapabilities;
121
123
  }
122
124
 
125
+ /** Removes the canvas listeners. Called from `Framework.dispose()`. */
126
+ public dispose(): void {
127
+ this._listeners.abort();
128
+ this._listeners = new AbortController();
129
+ this._touchListening = false;
130
+ }
131
+
123
132
  /** @inheritDoc */
124
133
  public initialize(): void {
125
134
 
@@ -133,20 +142,20 @@ export class InputManager implements IInputManager {
133
142
  canvas.addEventListener("mousemove", (e: MouseEvent) => {
134
143
  this._mousePosition[0] = e.clientX;
135
144
  this._mousePosition[1] = e.clientY;
136
- });
145
+ }, {signal: this._listeners.signal});
137
146
 
138
147
  canvas.addEventListener("mousedown", (e: MouseEvent) => {
139
148
  const idx = e.button;
140
149
  const btn = this._mouseButtonMap[idx] ?? MouseButton.NONE;
141
150
  this._mouseButtonDown[btn] = true;
142
- })
151
+ }, {signal: this._listeners.signal})
143
152
 
144
153
  canvas.addEventListener("mouseup", (e: MouseEvent) => {
145
154
  const idx = e.button;
146
155
  const btn = this._mouseButtonMap[idx] ?? MouseButton.NONE;
147
156
  this._mouseButtonDown[btn] = false;
148
157
  this._mouseButtonReleased[btn] = true;
149
- });
158
+ }, {signal: this._listeners.signal});
150
159
 
151
160
  canvas.addEventListener("wheel", (e: WheelEvent) => {
152
161
 
@@ -167,7 +176,7 @@ export class InputManager implements IInputManager {
167
176
  vec2.set(this._scrollWheelPosition, x, y);
168
177
 
169
178
  e.preventDefault();
170
- })
179
+ }, {signal: this._listeners.signal})
171
180
  }
172
181
 
173
182
  private _handleTouchEvents(canvas: HTMLCanvasElement): void {
@@ -179,7 +188,7 @@ export class InputManager implements IInputManager {
179
188
  // Pan and pinch-zoom start on this canvas only. The rest of the page is left alone.
180
189
  canvas.style.touchAction = "none";
181
190
 
182
- const options = InputManager._touchListenerOptions;
191
+ const options: AddEventListenerOptions = {...InputManager._touchListenerOptions, signal: this._listeners.signal};
183
192
  canvas.addEventListener("touchstart", this._onTouchStart, options);
184
193
  canvas.addEventListener("touchmove", this._onTouchMove, options);
185
194
  canvas.addEventListener("touchend", this._onTouchEnd, options);
@@ -0,0 +1,53 @@
1
+ import {Color} from "../data/Color.ts";
2
+ import {createLightId} from "./LightId.ts";
3
+ import type {Scene} from "../scene/Scene.ts";
4
+
5
+ /** The descriptor for an ambient light. All fields are optional. */
6
+ export interface AmbientLightDescriptor {
7
+ /** The unique id. Assigned automatically when omitted. */
8
+ id?: number;
9
+
10
+ /** The optional name for a light. */
11
+ name?: string;
12
+
13
+ /** The light colour. Alpha is ignored. Defaults to black. */
14
+ color?: Color;
15
+
16
+ /** Multiplies the colour. Defaults to 1. */
17
+ intensity?: number;
18
+ }
19
+
20
+ /**
21
+ * The ambient light. Plain data: it has no GPU resources.
22
+ * Put it into a {@link LightsBuffer} to use it in shaders.
23
+ * @public
24
+ */
25
+ export class AmbientLight {
26
+
27
+ /**
28
+ * The constructor.
29
+ * @param descriptor The optional descriptor. The colour is copied.
30
+ * @param scene The optional scene to register with.
31
+ */
32
+ public constructor(descriptor?: AmbientLightDescriptor, scene?: Scene) {
33
+
34
+ this.id = descriptor?.id ?? createLightId();
35
+ this.name = descriptor?.name;
36
+ this.color = descriptor?.color?.copy() ?? Color.black();
37
+ this.intensity = descriptor?.intensity ?? 1;
38
+
39
+ scene?.add(this);
40
+ }
41
+
42
+ /** The unique id of this light. */
43
+ public readonly id: number;
44
+
45
+ /** The optional name for a light. */
46
+ public name?: string;
47
+
48
+ /** The light color. Alpha is ignored. */
49
+ public color: Color;
50
+
51
+ /** Multiplies {@link color} when written to the lights buffer. */
52
+ public intensity: number;
53
+ }
@@ -0,0 +1,60 @@
1
+ import {vec3} from "gl-matrix";
2
+ import {Color} from "../data/Color.ts";
3
+ import {createLightId} from "./LightId.ts";
4
+ import type {Scene} from "../scene/Scene.ts";
5
+
6
+ /** The descriptor for a directional light. All fields are optional. */
7
+ export interface DirectionalLightDescriptor {
8
+ /** The unique id. Assigned automatically when omitted. */
9
+ id?: number;
10
+
11
+ /** The optional name for a light. */
12
+ name?: string;
13
+
14
+ /** The light colour. Alpha is ignored. Defaults to white. */
15
+ color?: Color;
16
+
17
+ /** Multiplies the colour. Defaults to 1. */
18
+ intensity?: number;
19
+
20
+ /** The direction in which the light travels. Defaults to straight down, (0, -1, 0). */
21
+ direction?: vec3;
22
+ }
23
+
24
+ /**
25
+ * The directional light. Plain data: it has no GPU resources.
26
+ * @public
27
+ */
28
+ export class DirectionalLight {
29
+
30
+ /**
31
+ * The constructor.
32
+ * @param descriptor The optional descriptor. Colour and direction are copied.
33
+ * @param scene The optional scene; the light adds itself via {@link Scene.add}.
34
+ * @throws Error when the scene has no free directional light slot left (the light is then not in the scene).
35
+ */
36
+ public constructor(descriptor?: DirectionalLightDescriptor, scene?: Scene) {
37
+ this.id = descriptor?.id ?? createLightId();
38
+ this.name = descriptor?.name;
39
+ this.color = descriptor?.color?.copy() ?? Color.white();
40
+ this.intensity = descriptor?.intensity ?? 1;
41
+ this.direction = descriptor?.direction ? vec3.clone(descriptor.direction) : vec3.fromValues(0, -1, 0);
42
+
43
+ scene?.add(this);
44
+ }
45
+
46
+ /** The unique id of this light. */
47
+ public readonly id: number;
48
+
49
+ /** The optional name for a light. */
50
+ public name?: string;
51
+
52
+ /** The light colour. Alpha is ignored. */
53
+ public color: Color;
54
+
55
+ /** Multiplies {@link color} when written to the lights buffer. */
56
+ public intensity: number;
57
+
58
+ /** The direction in which the light travels. */
59
+ public direction: vec3;
60
+ }
@@ -0,0 +1,21 @@
1
+ import type {AmbientLight, AmbientLightDescriptor} from "./AmbientLight.ts";
2
+ import type {Scene} from "../scene/Scene.ts";
3
+ import type {LightsBuffer, LightsBufferDescriptor} from "./LightsBuffer.ts";
4
+
5
+ /** The light factory */
6
+ export interface AmbientLightFactory {
7
+
8
+ /**
9
+ * Creates the ambient light.
10
+ * @param desc The descriptor for ambient light. The colour defaults to a dim grey; the id is assigned automatically.
11
+ * @param scene The optional scene to register the light with.
12
+ */
13
+ createAmbientLight(desc?: AmbientLightDescriptor, scene?: Scene): AmbientLight;
14
+
15
+ /**
16
+ * Creates a lights buffer, which owns the uniform buffer with all lights for shaders.
17
+ * @param desc The optional descriptor with the initial lights and directional light count.
18
+ */
19
+ __createLightsBuffer(desc?: LightsBufferDescriptor): LightsBuffer;
20
+
21
+ }
@@ -0,0 +1,9 @@
1
+ let nextLightId = 1;
2
+
3
+ /**
4
+ * Returns a new unique light id. Light constructors call this when no id is given.
5
+ * @internal
6
+ */
7
+ export function createLightId(): number {
8
+ return nextLightId++;
9
+ }