ris-framework 0.2.0-dev.13 → 0.2.0-dev.16

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 (186) hide show
  1. package/CHANGELOG.md +43 -2
  2. package/README.md +13 -5
  3. package/dist/api/IFramework.d.ts +3 -3
  4. package/dist/api/IFramework.d.ts.map +1 -1
  5. package/dist/api/_export.d.ts +3 -0
  6. package/dist/api/_export.d.ts.map +1 -1
  7. package/dist/api/camera/CameraTransformUtilities.d.ts +65 -0
  8. package/dist/api/camera/CameraTransformUtilities.d.ts.map +1 -0
  9. package/dist/api/camera/ICamera.d.ts +36 -2
  10. package/dist/api/camera/ICamera.d.ts.map +1 -1
  11. package/dist/api/camera/OrbitCamera.d.ts +22 -14
  12. package/dist/api/camera/OrbitCamera.d.ts.map +1 -1
  13. package/dist/api/camera/OrthographicCamera.d.ts +33 -11
  14. package/dist/api/camera/OrthographicCamera.d.ts.map +1 -1
  15. package/dist/api/camera/PerspectiveCamera.d.ts +32 -18
  16. package/dist/api/camera/PerspectiveCamera.d.ts.map +1 -1
  17. package/dist/api/content/ContentManager.d.ts +2 -2
  18. package/dist/api/content/ContentManager.d.ts.map +1 -1
  19. package/dist/api/content/IContentManager.d.ts +2 -2
  20. package/dist/api/content/IContentManager.d.ts.map +1 -1
  21. package/dist/api/lights/AmbientLight.d.ts +7 -2
  22. package/dist/api/lights/AmbientLight.d.ts.map +1 -1
  23. package/dist/api/lights/DirectionalLight.d.ts +18 -4
  24. package/dist/api/lights/DirectionalLight.d.ts.map +1 -1
  25. package/dist/api/lights/ILight.d.ts +18 -0
  26. package/dist/api/lights/ILight.d.ts.map +1 -0
  27. package/dist/api/lights/PointLight.d.ts +17 -4
  28. package/dist/api/lights/PointLight.d.ts.map +1 -1
  29. package/dist/api/lights/_export.d.ts +1 -0
  30. package/dist/api/lights/_export.d.ts.map +1 -1
  31. package/dist/api/material/ForwardBlinnPhongMaterial.d.ts +2 -2
  32. package/dist/api/material/ForwardBlinnPhongMaterial.d.ts.map +1 -1
  33. package/dist/api/material/IMaterial.d.ts +7 -0
  34. package/dist/api/material/IMaterial.d.ts.map +1 -1
  35. package/dist/api/material/IMaterialFactory.d.ts +3 -2
  36. package/dist/api/material/IMaterialFactory.d.ts.map +1 -1
  37. package/dist/api/material/IUnlitMaterialDescriptor.d.ts +16 -0
  38. package/dist/api/material/IUnlitMaterialDescriptor.d.ts.map +1 -0
  39. package/dist/api/material/MaterialFactory.d.ts +3 -2
  40. package/dist/api/material/MaterialFactory.d.ts.map +1 -1
  41. package/dist/api/material/SpriteMaterial.d.ts +3 -0
  42. package/dist/api/material/SpriteMaterial.d.ts.map +1 -1
  43. package/dist/api/material/UnlitMaterial.d.ts +5 -12
  44. package/dist/api/material/UnlitMaterial.d.ts.map +1 -1
  45. package/dist/api/material/_export.d.ts +1 -1
  46. package/dist/api/material/_export.d.ts.map +1 -1
  47. package/dist/api/meshes/IRenderableMesh.d.ts +3 -14
  48. package/dist/api/meshes/IRenderableMesh.d.ts.map +1 -1
  49. package/dist/api/meshes/RenderableMesh.d.ts +5 -20
  50. package/dist/api/meshes/RenderableMesh.d.ts.map +1 -1
  51. package/dist/api/rendering/IGraphicsDevice.d.ts +2 -2
  52. package/dist/api/rendering/IGraphicsDevice.d.ts.map +1 -1
  53. package/dist/api/rendering/IRenderer.d.ts +13 -6
  54. package/dist/api/rendering/IRenderer.d.ts.map +1 -1
  55. package/dist/api/rendering/_export-rendering.d.ts +1 -0
  56. package/dist/api/rendering/_export-rendering.d.ts.map +1 -1
  57. package/dist/api/rendering/enums.d.ts +5 -5
  58. package/dist/api/rendering/enums.d.ts.map +1 -1
  59. package/dist/api/rendering/primitive/IPrimitiveStateDescriptor.d.ts +24 -0
  60. package/dist/api/rendering/primitive/IPrimitiveStateDescriptor.d.ts.map +1 -0
  61. package/dist/api/rendering/primitive/_export.d.ts +1 -1
  62. package/dist/api/rendering/primitive/_export.d.ts.map +1 -1
  63. package/dist/api/rendering/render-pipelines/IMainRenderTargetRenderPipeline.d.ts +5 -0
  64. package/dist/api/rendering/render-pipelines/IMainRenderTargetRenderPipeline.d.ts.map +1 -1
  65. package/dist/api/rendering/texture/ITextureDescriptor.d.ts +53 -0
  66. package/dist/api/rendering/texture/ITextureDescriptor.d.ts.map +1 -0
  67. package/dist/api/rendering/texture/ITextureFactory.d.ts +5 -3
  68. package/dist/api/rendering/texture/ITextureFactory.d.ts.map +1 -1
  69. package/dist/api/rendering/texture/TextureUtilities.d.ts +29 -21
  70. package/dist/api/rendering/texture/TextureUtilities.d.ts.map +1 -1
  71. package/dist/api/rendering/texture/_export-texture.d.ts +1 -1
  72. package/dist/api/rendering/texture/_export-texture.d.ts.map +1 -1
  73. package/dist/api/scene/ISceneObject.d.ts +12 -0
  74. package/dist/api/scene/ISceneObject.d.ts.map +1 -0
  75. package/dist/api/scene/Scene.d.ts +17 -6
  76. package/dist/api/scene/Scene.d.ts.map +1 -1
  77. package/dist/api/scene/node/Node.d.ts +26 -0
  78. package/dist/api/scene/node/Node.d.ts.map +1 -0
  79. package/dist/api/scene/node/TransformNode.d.ts +46 -0
  80. package/dist/api/scene/node/TransformNode.d.ts.map +1 -0
  81. package/dist/core/material/UnlitMaterialDescriptorUtilities.d.ts +17 -0
  82. package/dist/core/material/UnlitMaterialDescriptorUtilities.d.ts.map +1 -0
  83. package/dist/core/rendering/AGraphicsDevice.d.ts +2 -2
  84. package/dist/core/rendering/AGraphicsDevice.d.ts.map +1 -1
  85. package/dist/core/rendering/ARenderer.d.ts +7 -1
  86. package/dist/core/rendering/ARenderer.d.ts.map +1 -1
  87. package/dist/core/rendering/primitive/PrimitiveStateDescriptorUtilities.d.ts +15 -0
  88. package/dist/core/rendering/primitive/PrimitiveStateDescriptorUtilities.d.ts.map +1 -0
  89. package/dist/core/rendering/texture/TextureDescriptorUtilities.d.ts +14 -0
  90. package/dist/core/rendering/texture/TextureDescriptorUtilities.d.ts.map +1 -0
  91. package/dist/core/rendering/texture/texture.d.ts +3 -2
  92. package/dist/core/rendering/texture/texture.d.ts.map +1 -1
  93. package/dist/index.js +959 -540
  94. package/dist/webgl/WebGlGraphicsDevice.d.ts +2 -2
  95. package/dist/webgl/WebGlGraphicsDevice.d.ts.map +1 -1
  96. package/dist/webgl/lights/WebGlLightsBuffer.d.ts.map +1 -1
  97. package/dist/webgl/primitive/WebGlPrimitiveState.d.ts +3 -3
  98. package/dist/webgl/primitive/WebGlPrimitiveState.d.ts.map +1 -1
  99. package/dist/webgl/render-pipelines/WebGlMainRenderTargetRenderPipeline.d.ts +8 -0
  100. package/dist/webgl/render-pipelines/WebGlMainRenderTargetRenderPipeline.d.ts.map +1 -1
  101. package/dist/webgl/texture/WebGlTexture2D.d.ts +3 -2
  102. package/dist/webgl/texture/WebGlTexture2D.d.ts.map +1 -1
  103. package/dist/webgl/texture/WebGlTextureFactory.d.ts +2 -9
  104. package/dist/webgl/texture/WebGlTextureFactory.d.ts.map +1 -1
  105. package/dist/webgl/utilities/WebGlErrorUtilities.d.ts.map +1 -1
  106. package/dist/webgl/utilities/WebGlTextureUtilities.d.ts.map +1 -1
  107. package/dist/webgpu/WebGpuGraphicsDevice.d.ts +2 -2
  108. package/dist/webgpu/WebGpuGraphicsDevice.d.ts.map +1 -1
  109. package/dist/webgpu/primitive/WebGpuPrimitiveState.d.ts +2 -2
  110. package/dist/webgpu/primitive/WebGpuPrimitiveState.d.ts.map +1 -1
  111. package/dist/webgpu/render-pipelines/WebGpuMainRenderTargetRenderPipeline.d.ts +5 -0
  112. package/dist/webgpu/render-pipelines/WebGpuMainRenderTargetRenderPipeline.d.ts.map +1 -1
  113. package/dist/webgpu/texture/WebGpuTexture2D.d.ts +3 -2
  114. package/dist/webgpu/texture/WebGpuTexture2D.d.ts.map +1 -1
  115. package/dist/webgpu/texture/WebGpuTextureFactory.d.ts +2 -2
  116. package/dist/webgpu/texture/WebGpuTextureFactory.d.ts.map +1 -1
  117. package/package.json +2 -2
  118. package/src/Framework.ts +2 -2
  119. package/src/api/IFramework.ts +3 -3
  120. package/src/api/_export.ts +3 -0
  121. package/src/api/camera/CameraTransformUtilities.ts +182 -0
  122. package/src/api/camera/ICamera.ts +42 -2
  123. package/src/api/camera/OrbitCamera.ts +71 -38
  124. package/src/api/camera/OrthographicCamera.ts +71 -28
  125. package/src/api/camera/PerspectiveCamera.ts +69 -33
  126. package/src/api/content/ContentManager.ts +18 -12
  127. package/src/api/content/IContentManager.ts +2 -2
  128. package/src/api/lights/AmbientLight.ts +8 -2
  129. package/src/api/lights/DirectionalLight.ts +30 -5
  130. package/src/api/lights/ILight.ts +22 -0
  131. package/src/api/lights/PointLight.ts +26 -5
  132. package/src/api/lights/_export.ts +1 -0
  133. package/src/api/material/ForwardBlinnPhongMaterial.ts +2 -2
  134. package/src/api/material/IMaterial.ts +8 -0
  135. package/src/api/material/IMaterialFactory.ts +3 -2
  136. package/src/api/material/IUnlitMaterialDescriptor.ts +18 -0
  137. package/src/api/material/MaterialFactory.ts +4 -3
  138. package/src/api/material/SpriteMaterial.ts +4 -0
  139. package/src/api/material/UnlitMaterial.ts +11 -18
  140. package/src/api/material/_export.ts +1 -1
  141. package/src/api/meshes/IRenderableMesh.ts +3 -18
  142. package/src/api/meshes/RenderableMesh.ts +15 -45
  143. package/src/api/rendering/IGraphicsDevice.ts +2 -2
  144. package/src/api/rendering/IRenderer.ts +14 -6
  145. package/src/api/rendering/_export-rendering.ts +2 -1
  146. package/src/api/rendering/enums.ts +5 -5
  147. package/src/api/rendering/primitive/IPrimitiveStateDescriptor.ts +27 -0
  148. package/src/api/rendering/primitive/_export.ts +1 -1
  149. package/src/api/rendering/render-pipelines/IMainRenderTargetRenderPipeline.ts +6 -0
  150. package/src/api/rendering/texture/ITextureDescriptor.ts +62 -0
  151. package/src/api/rendering/texture/ITextureFactory.ts +5 -3
  152. package/src/api/rendering/texture/TextureUtilities.ts +59 -61
  153. package/src/api/rendering/texture/_export-texture.ts +1 -1
  154. package/src/api/scene/ISceneObject.ts +13 -0
  155. package/src/api/scene/Scene.ts +52 -11
  156. package/src/api/scene/node/Node.ts +54 -0
  157. package/src/api/scene/node/TransformNode.ts +88 -0
  158. package/src/core/material/UnlitMaterialDescriptorUtilities.ts +21 -0
  159. package/src/core/rendering/AGraphicsDevice.ts +2 -2
  160. package/src/core/rendering/ARenderer.ts +26 -4
  161. package/src/core/rendering/primitive/PrimitiveStateDescriptorUtilities.ts +22 -0
  162. package/src/core/rendering/texture/TextureDescriptorUtilities.ts +28 -0
  163. package/src/core/rendering/texture/texture.ts +2 -2
  164. package/src/main.ts +5 -4
  165. package/src/webgl/WebGlGraphicsDevice.ts +2 -3
  166. package/src/webgl/lights/WebGlLightsBuffer.ts +21 -8
  167. package/src/webgl/primitive/WebGlPrimitiveState.ts +8 -6
  168. package/src/webgl/render-pipelines/WebGlMainRenderTargetRenderPipeline.ts +14 -0
  169. package/src/webgl/texture/WebGlTexture2D.ts +9 -8
  170. package/src/webgl/texture/WebGlTextureFactory.ts +62 -65
  171. package/src/webgl/utilities/WebGlErrorUtilities.ts +3 -2
  172. package/src/webgl/utilities/WebGlTextureUtilities.ts +10 -4
  173. package/src/webgpu/WebGpuGraphicsDevice.ts +3 -3
  174. package/src/webgpu/primitive/WebGpuPrimitiveState.ts +7 -5
  175. package/src/webgpu/render-pipelines/WebGpuMainRenderTargetRenderPipeline.ts +6 -0
  176. package/src/webgpu/texture/WebGpuTexture2D.ts +10 -9
  177. package/src/webgpu/texture/WebGpuTextureFactory.ts +20 -17
  178. package/dist/api/material/ICameraMaterial.d.ts +0 -18
  179. package/dist/api/material/ICameraMaterial.d.ts.map +0 -1
  180. package/dist/api/rendering/primitive/PrimitiveStateDescriptor.d.ts +0 -24
  181. package/dist/api/rendering/primitive/PrimitiveStateDescriptor.d.ts.map +0 -1
  182. package/dist/api/rendering/texture/TextureDescriptor.d.ts +0 -42
  183. package/dist/api/rendering/texture/TextureDescriptor.d.ts.map +0 -1
  184. package/src/api/material/ICameraMaterial.ts +0 -22
  185. package/src/api/rendering/primitive/PrimitiveStateDescriptor.ts +0 -27
  186. package/src/api/rendering/texture/TextureDescriptor.ts +0 -52
@@ -18,7 +18,7 @@ import {
18
18
  TextureFormat,
19
19
  TextureUsage
20
20
  } from "../../api/index.ts";
21
- import {TextureColorSpace} from "../../api/rendering/enums.ts";
21
+ import {ColorSpace} from "../../api/rendering/enums.ts";
22
22
 
23
23
  export abstract class ARenderer implements ITempRenderer {
24
24
 
@@ -36,6 +36,7 @@ export abstract class ARenderer implements ITempRenderer {
36
36
  private _swapChainRequiresResize: boolean = false;
37
37
  private _mainRenderPassDirty = true;
38
38
  private _clearColor: Color = Color.lightPink();
39
+ private _colorSpace: ColorSpace;
39
40
 
40
41
  protected _mainRenderTargetRequiresResize: boolean = false;
41
42
  protected _swapChain: ISwapChain = null!;
@@ -46,6 +47,7 @@ export abstract class ARenderer implements ITempRenderer {
46
47
  protected _mainRenderTargetPipeline?: IMainRenderTargetRenderPipeline;
47
48
  protected _renderConfiguration: IRendererConfiguration;
48
49
 
50
+
49
51
  /** @inheritdoc */
50
52
  public get graphicsDevice(): IGraphicsDevice {
51
53
  return this._graphicsDevice;
@@ -67,7 +69,27 @@ export abstract class ARenderer implements ITempRenderer {
67
69
  }
68
70
 
69
71
  /** @inheritdoc */
70
- public readonly preferredTextureFormat: TextureFormat;
72
+ public get preferredTextureFormat(): TextureFormat {
73
+ return this._colorSpace == ColorSpace.SRGB ? TextureFormat.RGBA_8_UNORM_SRGB : TextureFormat.RGBA_8_UNORM;
74
+ }
75
+
76
+ /** @inheritDoc */
77
+ public get colorSpace(): ColorSpace {
78
+ return this._colorSpace;
79
+ }
80
+
81
+ /** @inheritDoc */
82
+ public set colorSpace(colorSpace: ColorSpace) {
83
+ if (colorSpace == this._colorSpace) {
84
+ return;
85
+ }
86
+ this._colorSpace = colorSpace;
87
+ if (this._mainRenderTargetPipeline) {
88
+ this._mainRenderTargetPipeline.colorSpace = colorSpace;
89
+ // The main render target's format follows the color space, so recreate it on the next frame.
90
+ this._mainRenderTargetRequiresResize = true;
91
+ }
92
+ }
71
93
 
72
94
  /** @inheritdoc */
73
95
  public get preferredDepthStencilFormat(): TextureFormat {
@@ -108,8 +130,7 @@ export abstract class ARenderer implements ITempRenderer {
108
130
  this._windowManager = framework.windowManager;
109
131
  this._currentBackBufferSize[0] = this._windowManager.canvas.width;
110
132
  this._currentBackBufferSize[1] = this._windowManager.canvas.height;
111
- this.preferredTextureFormat = configuration.textureColorSpace == TextureColorSpace.SRGB
112
- ? TextureFormat.RGBA_8_UNORM_SRGB : TextureFormat.RGBA_8_UNORM;
133
+ this._colorSpace = configuration.textureColorSpace;
113
134
  }
114
135
 
115
136
  backend: RenderingBackend = RenderingBackend.WEB_GL;
@@ -188,6 +209,7 @@ export abstract class ARenderer implements ITempRenderer {
188
209
  this._mainRenderTargetPipeline = this._framework
189
210
  .renderPipelineFactory
190
211
  .createMainFrameBufferPipeline(this._mainRenderTarget);
212
+ this._mainRenderTargetPipeline.colorSpace = this._colorSpace;
191
213
 
192
214
  this._createMainRenderPass();
193
215
  this._mainRenderTargetRequiresResize = false;
@@ -0,0 +1,22 @@
1
+ import {CullMode, FrontFace, type IPrimitiveStateDescriptor, PrimitiveTopology} from "../../../api/index.ts";
2
+
3
+ /**
4
+ * A primitive state descriptor with all defaults applied.
5
+ * @internal
6
+ */
7
+ export type ResolvedPrimitiveStateDescriptor = Required<IPrimitiveStateDescriptor>;
8
+
9
+ /**
10
+ * Fills in the defaults for every missing field of a primitive state descriptor:
11
+ * TRIANGLE_LIST topology, BACK culling and CCW front face.
12
+ * @param desc The descriptor, possibly partial or missing.
13
+ * @returns A new descriptor with the defaults applied.
14
+ * @internal
15
+ */
16
+ export function resolvePrimitiveStateDescriptor(desc?: IPrimitiveStateDescriptor): ResolvedPrimitiveStateDescriptor {
17
+ return {
18
+ topology: desc?.topology ?? PrimitiveTopology.TRIANGLE_LIST,
19
+ cullFace: desc?.cullFace ?? CullMode.BACK,
20
+ frontFace: desc?.frontFace ?? FrontFace.CCW,
21
+ };
22
+ }
@@ -0,0 +1,28 @@
1
+ import {type ITextureDescriptor, TextureFormat, TextureUsage} from "../../../api/index.ts";
2
+
3
+ /**
4
+ * A texture descriptor with all defaults applied. Only `data`, `blockSize` and `preferredColorSpace` stay optional.
5
+ * @internal
6
+ */
7
+ export type ResolvedTextureDescriptor =
8
+ Required<Omit<ITextureDescriptor, "data" | "blockSize" | "preferredColorSpace">> & Pick<ITextureDescriptor, "data" | "blockSize" | "preferredColorSpace">;
9
+
10
+ /**
11
+ * Fills in the defaults for every missing field of a texture descriptor.
12
+ * @param desc The descriptor, possibly partial or missing.
13
+ * @returns A new descriptor with the defaults applied.
14
+ * @internal
15
+ */
16
+ export function resolveTextureDescriptor(desc?: ITextureDescriptor): ResolvedTextureDescriptor {
17
+ return {
18
+ width: desc?.width ?? 0,
19
+ height: desc?.height ?? 0,
20
+ textureFormat: desc?.textureFormat ?? TextureFormat.UNDEFINED,
21
+ textureUsage: desc?.textureUsage ?? (TextureUsage.TEXTURE_BINDING | TextureUsage.COPY_DST),
22
+ label: desc?.label ?? null,
23
+ data: desc?.data,
24
+ generateMipmaps: desc?.generateMipmaps ?? false,
25
+ blockSize: desc?.blockSize,
26
+ preferredColorSpace: desc?.preferredColorSpace,
27
+ };
28
+ }
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  type ITexture2D, type ITextureView,
3
3
  State,
4
- type TextureDescriptor,
5
4
  type TextureFormat,
6
5
  TextureUsage,
7
6
  TextureViewDescriptor
8
7
  } from "../../../api/index.ts";
9
8
  import {vec2} from "gl-matrix";
9
+ import type {ResolvedTextureDescriptor} from "./TextureDescriptorUtilities.ts";
10
10
 
11
11
  /**
12
12
  * The ATexture2D class is an abstract base class that implements the ITexture2D interface. It provides common properties and a constructor for initializing a 2D texture, but it does not implement the actual texture creation and management logic, which must be provided by subclasses that extend this base class.
@@ -30,7 +30,7 @@ export abstract class ATexture2D implements ITexture2D {
30
30
  * @param descriptor - The texture descriptor.
31
31
  */
32
32
  protected constructor(
33
- descriptor: TextureDescriptor,
33
+ descriptor: ResolvedTextureDescriptor,
34
34
  ) {
35
35
 
36
36
  if (!descriptor.textureFormat) {
package/src/main.ts CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  type ITexture2D,
12
12
  Rect,
13
13
  SamplerDescriptor,
14
- SamplerFilter, TextureDescriptor, TextureFormat
14
+ SamplerFilter, type ITextureDescriptor, TextureFormat
15
15
  } from "./api/index.ts";
16
16
 
17
17
  document.querySelector<HTMLDivElement>('#app')!.innerHTML = `
@@ -46,9 +46,10 @@ let sampler: ISampler;
46
46
  framework.addOnLoadContentListener(async () =>
47
47
  {
48
48
 
49
- const texDesc = new TextureDescriptor();
50
- texDesc.generateMipmaps = true;
51
- texDesc.textureFormat = TextureFormat.RGBA_8_UNORM;
49
+ const texDesc: ITextureDescriptor = {
50
+ generateMipmaps: true,
51
+ textureFormat: TextureFormat.RGBA_8_UNORM,
52
+ };
52
53
 
53
54
  tex = await framework.content.loadTexture2DAsync("/assets/test.png", texDesc);
54
55
  tex2 = await framework.content.loadTexture2DAsync("/assets/cat.jpg", texDesc);
@@ -15,7 +15,7 @@ import {
15
15
  type ISampler,
16
16
  type ISwapChain,
17
17
  type IWindowManager,
18
- PrimitiveStateDescriptor,
18
+ type IPrimitiveStateDescriptor,
19
19
  RenderPassDescriptor,
20
20
  SwapChainDescriptor
21
21
  } from "../api/index.ts";
@@ -125,8 +125,7 @@ export class WebGlGraphicsDevice extends AGraphicsDevice {
125
125
  }
126
126
 
127
127
  /** @inheritdoc */
128
- public createPrimitiveState(descriptor?: PrimitiveStateDescriptor): IPrimitiveState {
129
- descriptor = descriptor ?? new PrimitiveStateDescriptor();
128
+ public createPrimitiveState(descriptor?: IPrimitiveStateDescriptor): IPrimitiveState {
130
129
  return new WebGlPrimitiveState(this._gl, descriptor);
131
130
  }
132
131
  }
@@ -11,6 +11,9 @@ import {
11
11
  type LightsBufferDescriptor,
12
12
  DEFAULT_DIRECTIONAL_LIGHTS_COUNT,
13
13
  } from "../../api/index.ts";
14
+ import {vec3} from "gl-matrix";
15
+
16
+ const _v = vec3.create();
14
17
 
15
18
  /**
16
19
  * The WebGL lights buffer. Owns a std140 uniform buffer for the `LightsBuffer` block.
@@ -191,10 +194,15 @@ export class WebGlLightsBuffer implements LightsBuffer {
191
194
  this._writeColor(offset, light?.color, light?.intensity ?? 0);
192
195
  this._data[offset + 3] = 0;
193
196
 
194
- // vec3 direction
195
- this._data[offset + 4] = light ? light.direction[0] : 0;
196
- this._data[offset + 5] = light ? light.direction[1] : 0;
197
- this._data[offset + 6] = light ? light.direction[2] : 0;
197
+ // vec3 direction (world space, from the transform)
198
+ if (light) {
199
+ light.getDirection(_v);
200
+ } else {
201
+ vec3.zero(_v);
202
+ }
203
+ this._data[offset + 4] = _v[0];
204
+ this._data[offset + 5] = _v[1];
205
+ this._data[offset + 6] = _v[2];
198
206
  this._data[offset + 7] = 0;
199
207
  }
200
208
 
@@ -209,10 +217,15 @@ export class WebGlLightsBuffer implements LightsBuffer {
209
217
  // An empty slot keeps constant at 1 so the shader never divides by zero.
210
218
  this._data[offset + 3] = light ? light.constant : 1;
211
219
 
212
- // vec3 position, float linear
213
- this._data[offset + 4] = light ? light.position[0] : 0;
214
- this._data[offset + 5] = light ? light.position[1] : 0;
215
- this._data[offset + 6] = light ? light.position[2] : 0;
220
+ // vec3 position (world space, from the transform), float linear
221
+ if (light) {
222
+ light.getPosition(_v);
223
+ } else {
224
+ vec3.zero(_v);
225
+ }
226
+ this._data[offset + 4] = _v[0];
227
+ this._data[offset + 5] = _v[1];
228
+ this._data[offset + 6] = _v[2];
216
229
  this._data[offset + 7] = light ? light.linear : 0;
217
230
 
218
231
  // float quadratic, then padding to the 16-byte struct size
@@ -2,9 +2,10 @@ import {
2
2
  CullMode,
3
3
  type FrontFace,
4
4
  type IPrimitiveState,
5
- type PrimitiveStateDescriptor,
5
+ type IPrimitiveStateDescriptor,
6
6
  type PrimitiveTopology
7
7
  } from "../../api/index.ts";
8
+ import {resolvePrimitiveStateDescriptor} from "../../core/rendering/primitive/PrimitiveStateDescriptorUtilities.ts";
8
9
  import { WebGlConverter } from "../utilities/WebGlConverter.ts";
9
10
 
10
11
  /**
@@ -19,12 +20,13 @@ export class WebGlPrimitiveState implements IPrimitiveState {
19
20
  /**
20
21
  * The constructor.
21
22
  * @param _gl The WebGL2 Rendering Context.
22
- * @param descriptor The descriptor of the primitive state.
23
+ * @param descriptor The descriptor of the primitive state; missing fields use the defaults.
23
24
  */
24
- public constructor(_gl: WebGL2RenderingContext, descriptor: PrimitiveStateDescriptor) {
25
- this.topology = descriptor.topology;
26
- this.cullFace = descriptor.cullFace;
27
- this.frontFace = descriptor.frontFace;
25
+ public constructor(_gl: WebGL2RenderingContext, descriptor?: IPrimitiveStateDescriptor) {
26
+ const resolved = resolvePrimitiveStateDescriptor(descriptor);
27
+ this.topology = resolved.topology;
28
+ this.cullFace = resolved.cullFace;
29
+ this.frontFace = resolved.frontFace;
28
30
 
29
31
  this._cullingEnabled = this.cullFace != CullMode.NONE;
30
32
 
@@ -13,6 +13,7 @@ import {
13
13
  type ITexture2D,
14
14
  TextureFormat
15
15
  } from "../../api/index.ts";
16
+ import {ColorSpace} from "../../api/rendering/enums.ts";
16
17
 
17
18
  /**
18
19
  * The WebGL implementation of the main render target render pipeline.
@@ -24,6 +25,7 @@ export class WebGlMainRenderTargetRenderPipeline extends AWebGlRenderPipeline im
24
25
  private _mainRenderTarget: WebGlTexture2D = null!;
25
26
 
26
27
  private _colorConversionUniformLocation: WebGLUniformLocation = null!;
28
+ /** The shader's `u_colorConversion`: 1 encodes linear to sRGB on output, 0 passes through. */
27
29
  private _colorSpaceValue = 0;
28
30
 
29
31
  /**
@@ -40,6 +42,18 @@ export class WebGlMainRenderTargetRenderPipeline extends AWebGlRenderPipeline im
40
42
  }
41
43
  }
42
44
 
45
+ /**
46
+ * The color space. With SRGB the main render target is sRGB (sampled back as linear) and the shader
47
+ * encodes to sRGB for the screen; with LINEAR the values are passed through. Takes effect on the next frame.
48
+ */
49
+ public get colorSpace(): ColorSpace {
50
+ return this._colorSpaceValue == 1 ? ColorSpace.SRGB : ColorSpace.LINEAR;
51
+ }
52
+
53
+ public set colorSpace(value: ColorSpace) {
54
+ this._colorSpaceValue = value == ColorSpace.SRGB ? 1 : 0;
55
+ }
56
+
43
57
  /** @inheritDoc */
44
58
  public readonly geometryFormat = GeometryFormat.POS3_COLOR4_TEXTURECOORDS2;
45
59
 
@@ -1,6 +1,5 @@
1
1
  import {WebGlUtilities} from "../utilities/WebGlUtilities.ts";
2
2
  import {
3
- TextureDescriptor,
4
3
  type IFramework, State,
5
4
  type ITextureView,
6
5
  type TextureViewDescriptor, TextureUtilities
@@ -8,6 +7,7 @@ import {
8
7
  import type {WebGlGraphicsDevice} from "../WebGlGraphicsDevice.ts";
9
8
  import {ATexture2D} from "../../core/rendering/texture/texture.ts";
10
9
  import {vec2} from "gl-matrix";
10
+ import {type ResolvedTextureDescriptor, resolveTextureDescriptor} from "../../core/rendering/texture/TextureDescriptorUtilities.ts";
11
11
 
12
12
  /**
13
13
  * The WebGL implementation of ITexture2D.
@@ -25,7 +25,7 @@ export class WebGlTexture2D extends ATexture2D {
25
25
  */
26
26
  constructor(
27
27
  private readonly _framework: IFramework,
28
- textureDescriptor: TextureDescriptor
28
+ textureDescriptor: ResolvedTextureDescriptor
29
29
  ) {
30
30
  super(textureDescriptor);
31
31
  this._graphicsDevice = this._framework.renderer.graphicsDevice as WebGlGraphicsDevice;
@@ -121,12 +121,13 @@ export class WebGlTexture2D extends ATexture2D {
121
121
  let texture = WebGlTexture2D._defaultFilled.get(framework);
122
122
  if (!texture || texture.state === State.DISPOSED) {
123
123
 
124
- const desc = new TextureDescriptor();
125
- desc.width = 1;
126
- desc.height = 1;
127
- desc.data = [new Uint8Array([255, 255, 255, 255])];
128
- desc.textureFormat = framework.renderer.preferredTextureFormat;
129
- desc.label = "RisDefaultFilledTexture";
124
+ const desc = resolveTextureDescriptor({
125
+ width: 1,
126
+ height: 1,
127
+ data: [new Uint8Array([255, 255, 255, 255])],
128
+ textureFormat: framework.renderer.preferredTextureFormat,
129
+ label: "RisDefaultFilledTexture",
130
+ });
130
131
 
131
132
  texture = new WebGlTexture2D(framework, desc);
132
133
  texture.initialize();
@@ -2,8 +2,8 @@ import {
2
2
  Color,
3
3
  type IFramework,
4
4
  type ITexture2D,
5
+ type ITextureDescriptor,
5
6
  type ITextureFactory,
6
- TextureDescriptor,
7
7
  TextureFormat,
8
8
  TextureUsage,
9
9
  TextureUtilities
@@ -11,6 +11,8 @@ import {
11
11
  import {WebGlTexture2D} from "./WebGlTexture2D.ts";
12
12
  import {type IKtx2Texture, KtxTranscodeFlags, KtxTranscodeFormat, VkFormat} from "ris-ktx2";
13
13
  import {vec2} from "gl-matrix";
14
+ import {ColorSpace} from "../../api/rendering/enums.ts";
15
+ import {resolveTextureDescriptor} from "../../core/rendering/texture/TextureDescriptorUtilities.ts";
14
16
 
15
17
  export class WebGlTextureFactory implements ITextureFactory {
16
18
 
@@ -22,51 +24,57 @@ export class WebGlTextureFactory implements ITextureFactory {
22
24
  }
23
25
 
24
26
  /** @inheritDoc */
25
- public createFromKtx2(ktxTexture: IKtx2Texture, descriptor?: TextureDescriptor): ITexture2D {
26
- descriptor = descriptor ?? new TextureDescriptor();
27
+ public createFromKtx2(ktxTexture: IKtx2Texture, descriptor?: ITextureDescriptor): ITexture2D {
28
+ const desc = resolveTextureDescriptor(descriptor);
27
29
  const vkFormat = ktxTexture.vkFormat;
28
30
 
29
31
  // Ktx2 will have different cases, for now we consider simple 2d case.
30
32
  const numLevels = ktxTexture.numLevels;
31
33
  let transcodeFormat = KtxTranscodeFormat.NO_SELECTION;
32
- let textureFormat = descriptor.textureFormat;
34
+ let textureFormat = desc.textureFormat;
33
35
  const gpuFeatures = this._framework.graphicsDevice.features;
34
36
 
37
+ // Textures always adapt to the framework's preferred color space, unless user defined it's preferred.
38
+ const preferSrgb = (descriptor?.preferredColorSpace ?? this._framework.renderer.colorSpace) == ColorSpace.SRGB;
39
+ // An explicit texture format overrides both color space preferences.
40
+ const userSpecifiedTextureFormat = desc.textureFormat != TextureFormat.UNDEFINED;
41
+
35
42
  if (ktxTexture.needsTranscoding && vkFormat == VkFormat.UNDEFINED)
36
43
  {
37
44
  // If descriptor format is UNDEFINED, we will use format according to the GPU features.
38
- if(descriptor.textureFormat == TextureFormat.UNDEFINED)
45
+ if(desc.textureFormat == TextureFormat.UNDEFINED)
39
46
  {
40
47
  // BC7 needs BPTC (supportsTextureCompressionBC), BC3 needs S3TC.
41
48
  if(gpuFeatures.supportsTextureCompressionBC)
42
49
  {
43
50
  transcodeFormat = KtxTranscodeFormat.BC7_RGBA;
44
- textureFormat = TextureFormat.BC7_RGBA_UNORM;
51
+ textureFormat = preferSrgb ? TextureFormat.BC7_RGBA_SRGB : TextureFormat.BC7_RGBA_UNORM;
45
52
  }
46
53
  else if(gpuFeatures.supportsTextureCompressionASTC)
47
54
  {
48
55
  transcodeFormat = KtxTranscodeFormat.ASTC_4X4_RGBA;
49
- textureFormat = TextureFormat.ASTC_4X4_RGBA_UNORM
56
+ textureFormat = preferSrgb ? TextureFormat.ASTC_4X4_RGBA_SRGB : TextureFormat.ASTC_4X4_RGBA_UNORM;
50
57
  }
51
58
  else if(gpuFeatures.supportsTextureCompressionS3TC)
52
59
  {
53
60
  transcodeFormat = KtxTranscodeFormat.BC3_RGBA;
54
- textureFormat = TextureFormat.BC3_RGBA_UNORM;
61
+ textureFormat = preferSrgb ? TextureFormat.BC3_RGBA_SRGB : TextureFormat.BC3_RGBA_UNORM;
55
62
  }
56
63
  else if(gpuFeatures.supportsTextureCompressionETC2)
57
64
  {
58
65
  transcodeFormat = KtxTranscodeFormat.ETC2_RGBA;
59
- textureFormat = TextureFormat.ETC2_RGBA8_UNORM;
66
+ textureFormat = preferSrgb ? TextureFormat.ETC2_RGBA8_SRGB : TextureFormat.ETC2_RGBA8_UNORM;
60
67
  }
61
68
  else if(gpuFeatures.supportsTextureCompressionPVRTC)
62
69
  {
63
70
  transcodeFormat = KtxTranscodeFormat.PVRTC1_4_RGBA;
71
+ // Does not have SRGB equivalent.
64
72
  textureFormat = TextureFormat.PVRTC_4BPPV1_RGBA;
65
73
  }
66
74
  else
67
75
  {
68
76
  transcodeFormat = KtxTranscodeFormat.RGBA32;
69
- textureFormat = TextureFormat.RGBA_8_UNORM;
77
+ textureFormat = preferSrgb ? TextureFormat.RGBA_8_UNORM_SRGB : TextureFormat.RGBA_8_UNORM;
70
78
  }
71
79
  }
72
80
  else
@@ -75,21 +83,24 @@ export class WebGlTextureFactory implements ITextureFactory {
75
83
  }
76
84
 
77
85
  ktxTexture.transcodeBasis(transcodeFormat, KtxTranscodeFlags.HIGH_QUALITY);
78
-
79
- // After transcoding, libktx reports the sRGB vkFormat when the file's DFD transfer function is sRGB.
80
- if (descriptor.textureFormat == TextureFormat.UNDEFINED && WebGlTextureFactory._isSrgbVkFormat(ktxTexture.vkFormat))
81
- {
82
- textureFormat = TextureUtilities.toSrgbFormat(textureFormat);
83
- }
84
86
  }
85
87
  else {
86
- // No transcoding path, the vkFormat already says linear or sRGB.
88
+ // No transcoding path: map the vkFormat, then switch to the preferred color space variant.
87
89
  textureFormat = TextureUtilities.convertVkFormatToTextureFormat(vkFormat);
88
- }
89
90
 
90
- textureFormat = this._ensureSrgbSupported(textureFormat, ktxTexture.filePath);
91
+ if (userSpecifiedTextureFormat) {
92
+ // The data can only be reinterpreted as the file's format or its sRGB/linear variant.
93
+ textureFormat = TextureUtilities.resolveExplicitFormat(textureFormat, desc.textureFormat);
94
+ } else {
95
+ if (preferSrgb && !TextureUtilities.isSrgbFormat(textureFormat)) {
96
+ textureFormat = TextureUtilities.convertToSrgbVariant(textureFormat);
97
+ } else if (!preferSrgb && TextureUtilities.isSrgbFormat(textureFormat)) {
98
+ textureFormat = TextureUtilities.convertToLinearVariant(textureFormat);
99
+ }
100
+ }
101
+ }
91
102
 
92
- const blockSize = TextureUtilities.getBlockSize(textureFormat);
103
+ const blockSize = ktxTexture.getTextureFormatInfo(ktxTexture.vkFormat);
93
104
  if (!blockSize) {
94
105
  throw new Error(`Unknown block size for texture format ${textureFormat}.`);
95
106
  }
@@ -100,40 +111,20 @@ export class WebGlTextureFactory implements ITextureFactory {
100
111
  data.push(ktxTexture.getImage(i));
101
112
  }
102
113
 
103
- const textureDescriptor = new TextureDescriptor();
104
- textureDescriptor.width = ktxTexture.width;
105
- textureDescriptor.height = ktxTexture.height;
106
- textureDescriptor.data = data;
107
- textureDescriptor.textureFormat = textureFormat;
108
- textureDescriptor.generateMipmaps = descriptor.generateMipmaps;
109
- textureDescriptor.blockSize = vec2.fromValues(blockSize[0], blockSize[1]);
114
+ const textureDescriptor = resolveTextureDescriptor({
115
+ ...desc,
116
+ width: ktxTexture.width,
117
+ height: ktxTexture.height,
118
+ data,
119
+ textureFormat,
120
+ blockSize: vec2.fromValues(blockSize.blockWidth, blockSize.blockHeight),
121
+ });
110
122
 
111
123
  const texture = new WebGlTexture2D(this._framework, textureDescriptor);
112
124
  texture.initialize();
113
125
  return texture;
114
126
  }
115
127
 
116
- /** Whether the Vulkan format is an sRGB format. */
117
- private static _isSrgbVkFormat(vkFormat: VkFormat): boolean {
118
- const name = (VkFormat as unknown as Record<number, string>)[vkFormat];
119
- return typeof name === "string" && name.includes("_SRGB");
120
- }
121
-
122
- /**
123
- * Falls back to the linear variant (with a warning) when the GPU cannot sample the sRGB format.
124
- * Only S3TC sRGB (BC1/BC3) has its own WebGL extension; BC7, ETC2 and ASTC sRGB ship with their base extension.
125
- */
126
- private _ensureSrgbSupported(textureFormat: TextureFormat, source?: string): TextureFormat {
127
- const isS3tcSrgb = textureFormat === TextureFormat.BC3_RGBA_SRGB || textureFormat === TextureFormat.BC1_RGB_SRGB;
128
- if (isS3tcSrgb && !this._framework.graphicsDevice.features.supportsTextureCompressionS3TCSrgb) {
129
- const linear = TextureUtilities.toLinearFormat(textureFormat);
130
- console.warn(`sRGB S3TC is not supported (WEBGL_compressed_texture_s3tc_srgb missing); ` +
131
- `loading ${source ?? "texture"} as ${linear}. Colours will look washed out.`);
132
- return linear;
133
- }
134
- return textureFormat;
135
- }
136
-
137
128
  /** @inheritdoc */
138
129
  public create(
139
130
  width: number, height: number,
@@ -141,8 +132,12 @@ export class WebGlTextureFactory implements ITextureFactory {
141
132
  channels: number = 4,
142
133
  label: string | null | undefined = null,
143
134
  textureUsage = TextureUsage.COPY_DST | TextureUsage.TEXTURE_BINDING,
144
- textureFormat= TextureFormat.RGBA_8_UNORM,
135
+ textureFormat = TextureFormat.UNDEFINED,
145
136
  useMipMaps = false): ITexture2D {
137
+ if (textureFormat == TextureFormat.UNDEFINED) {
138
+ textureFormat = this._framework.renderer.preferredTextureFormat;
139
+ }
140
+
146
141
 
147
142
  if (!data) {
148
143
  throw new Error("Data must not be null.");
@@ -155,15 +150,16 @@ export class WebGlTextureFactory implements ITextureFactory {
155
150
  throw new Error("channels must be greater than 0.");
156
151
  }
157
152
 
158
- const desc = new TextureDescriptor();
159
- desc.width = width;
160
- desc.height = height;
161
- // @ts-ignore
162
- desc.data = data ? [data] : null;
163
- desc.textureFormat = textureFormat;
164
- desc.textureUsage = textureUsage;
165
- desc.generateMipmaps = useMipMaps;
166
- desc.label = label;
153
+ const desc = resolveTextureDescriptor({
154
+ width,
155
+ height,
156
+ // @ts-ignore HTMLImageElement is uploaded as-is by WebGlTexture2D.
157
+ data: [data],
158
+ textureFormat,
159
+ textureUsage,
160
+ generateMipmaps: useMipMaps,
161
+ label,
162
+ });
167
163
 
168
164
  const texture = new WebGlTexture2D(
169
165
  this._framework,
@@ -191,13 +187,14 @@ export class WebGlTextureFactory implements ITextureFactory {
191
187
  textureFormat = this._framework.renderer.preferredTextureFormat;
192
188
  }
193
189
 
194
- const desc = new TextureDescriptor();
195
- desc.width = width;
196
- desc.height = height;
197
- desc.textureUsage = textureUsage;
198
- desc.textureFormat = textureFormat;
199
- desc.label = label;
200
- desc.generateMipmaps = useMipmap;
190
+ const desc = resolveTextureDescriptor({
191
+ width,
192
+ height,
193
+ textureUsage,
194
+ textureFormat,
195
+ label,
196
+ generateMipmaps: useMipmap,
197
+ });
201
198
 
202
199
  // Fast path: avoid generating & uploading a big CPU-side buffer when not needed.
203
200
  if (!color || color.equals(Color.black())) {
@@ -1,7 +1,8 @@
1
1
  export class WebGlErrorUtilities {
2
2
 
3
3
  private readonly _map: Record<number, string> = {
4
- 1282: "INVALID_OPERATION"
4
+ 1281: "INVALID_VALUE",
5
+ 1282: "INVALID_OPERATION",
5
6
  }
6
7
 
7
8
  /**
@@ -9,7 +10,7 @@ export class WebGlErrorUtilities {
9
10
  * @param error The error code.
10
11
  * @return The string of error code.
11
12
  */
12
- public errorToStr(error: number) : string {
13
+ public errorToStr(error: number): string {
13
14
  return this._map[error] ?? error.toString();
14
15
  }
15
16
  }
@@ -1,5 +1,5 @@
1
1
  import {WebGlConverter} from "./WebGlConverter.ts";
2
- import {AlignUtilities, TextureFormat} from "../../api/index.ts";
2
+ import { TextureFormat} from "../../api/index.ts";
3
3
  import {vec2} from "gl-matrix";
4
4
  import {WebGlUtilities} from "./WebGlUtilities.ts";
5
5
 
@@ -127,6 +127,9 @@ export class WebGlTextureUtilities {
127
127
  gl.texStorage2D(gl.TEXTURE_2D, mipLevels, internalFormat, baseWidth, baseHeight);
128
128
  }
129
129
 
130
+ // Texture data might not be aligned to 4. So disable it.
131
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
132
+
130
133
  if (data && data.length > 0) {
131
134
 
132
135
  let width = baseWidth;
@@ -140,9 +143,9 @@ export class WebGlTextureUtilities {
140
143
  if (useTexStorage) {
141
144
  gl.compressedTexSubImage2D(gl.TEXTURE_2D, i, 0, 0, width, height, internalFormat, mipLevelData, 0);
142
145
  } else {
143
- const alignedWidth = AlignUtilities.align(width, blockSize[0]);
144
- const alignedHeight = AlignUtilities.align(height, blockSize[1]);
145
- gl.compressedTexImage2D(gl.TEXTURE_2D, i, internalFormat, alignedWidth, alignedHeight, 0, mipLevelData, 0);
146
+ // const alignedWidth = AlignUtilities.align(width, blockSize[0]);
147
+ // const alignedHeight = AlignUtilities.align(height, blockSize[1]);
148
+ gl.compressedTexImage2D(gl.TEXTURE_2D, i, internalFormat, width, height, 0, mipLevelData, 0);
146
149
  }
147
150
  } else {
148
151
  throw new Error("unsupported data type");
@@ -153,6 +156,9 @@ export class WebGlTextureUtilities {
153
156
  }
154
157
  }
155
158
 
159
+ // Restore to default.
160
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4);
161
+
156
162
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
157
163
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
158
164
 
@@ -9,7 +9,7 @@ import {
9
9
  type ISampler,
10
10
  type ISwapChain,
11
11
  type IWindowManager,
12
- PrimitiveStateDescriptor,
12
+ type IPrimitiveStateDescriptor,
13
13
  RenderPassDescriptor,
14
14
  SwapChainDescriptor,
15
15
  } from "../api/index.ts";
@@ -158,8 +158,8 @@ export class WebGpuGraphicsDevice extends AGraphicsDevice {
158
158
  }
159
159
 
160
160
  /** @inheritDoc */
161
- public createPrimitiveState(descriptor?: PrimitiveStateDescriptor): IPrimitiveState {
162
- return new WebGpuPrimitiveState(descriptor ?? new PrimitiveStateDescriptor());
161
+ public createPrimitiveState(descriptor?: IPrimitiveStateDescriptor): IPrimitiveState {
162
+ return new WebGpuPrimitiveState(descriptor);
163
163
  }
164
164
 
165
165
  /** @inheritDoc */