ris-framework 0.2.0-dev.14 → 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.
- package/CHANGELOG.md +39 -2
- package/README.md +8 -6
- package/dist/api/IFramework.d.ts +1 -1
- package/dist/api/IFramework.d.ts.map +1 -1
- package/dist/api/_export.d.ts +3 -0
- package/dist/api/_export.d.ts.map +1 -1
- package/dist/api/camera/CameraTransformUtilities.d.ts +65 -0
- package/dist/api/camera/CameraTransformUtilities.d.ts.map +1 -0
- package/dist/api/camera/ICamera.d.ts +36 -2
- package/dist/api/camera/ICamera.d.ts.map +1 -1
- package/dist/api/camera/OrbitCamera.d.ts +22 -14
- package/dist/api/camera/OrbitCamera.d.ts.map +1 -1
- package/dist/api/camera/OrthographicCamera.d.ts +33 -11
- package/dist/api/camera/OrthographicCamera.d.ts.map +1 -1
- package/dist/api/camera/PerspectiveCamera.d.ts +32 -18
- package/dist/api/camera/PerspectiveCamera.d.ts.map +1 -1
- package/dist/api/content/ContentManager.d.ts.map +1 -1
- package/dist/api/lights/AmbientLight.d.ts +7 -2
- package/dist/api/lights/AmbientLight.d.ts.map +1 -1
- package/dist/api/lights/DirectionalLight.d.ts +18 -4
- package/dist/api/lights/DirectionalLight.d.ts.map +1 -1
- package/dist/api/lights/ILight.d.ts +18 -0
- package/dist/api/lights/ILight.d.ts.map +1 -0
- package/dist/api/lights/PointLight.d.ts +17 -4
- package/dist/api/lights/PointLight.d.ts.map +1 -1
- package/dist/api/lights/_export.d.ts +1 -0
- package/dist/api/lights/_export.d.ts.map +1 -1
- package/dist/api/material/ForwardBlinnPhongMaterial.d.ts +2 -2
- package/dist/api/material/ForwardBlinnPhongMaterial.d.ts.map +1 -1
- package/dist/api/material/IMaterial.d.ts +7 -0
- package/dist/api/material/IMaterial.d.ts.map +1 -1
- package/dist/api/material/IMaterialFactory.d.ts +3 -2
- package/dist/api/material/IMaterialFactory.d.ts.map +1 -1
- package/dist/api/material/IUnlitMaterialDescriptor.d.ts +16 -0
- package/dist/api/material/IUnlitMaterialDescriptor.d.ts.map +1 -0
- package/dist/api/material/MaterialFactory.d.ts +3 -2
- package/dist/api/material/MaterialFactory.d.ts.map +1 -1
- package/dist/api/material/SpriteMaterial.d.ts +3 -0
- package/dist/api/material/SpriteMaterial.d.ts.map +1 -1
- package/dist/api/material/UnlitMaterial.d.ts +5 -12
- package/dist/api/material/UnlitMaterial.d.ts.map +1 -1
- package/dist/api/material/_export.d.ts +1 -1
- package/dist/api/material/_export.d.ts.map +1 -1
- package/dist/api/meshes/IRenderableMesh.d.ts +3 -14
- package/dist/api/meshes/IRenderableMesh.d.ts.map +1 -1
- package/dist/api/meshes/RenderableMesh.d.ts +5 -20
- package/dist/api/meshes/RenderableMesh.d.ts.map +1 -1
- package/dist/api/rendering/IGraphicsDevice.d.ts +2 -2
- package/dist/api/rendering/IGraphicsDevice.d.ts.map +1 -1
- package/dist/api/rendering/IRenderer.d.ts +6 -4
- package/dist/api/rendering/IRenderer.d.ts.map +1 -1
- package/dist/api/rendering/_export-rendering.d.ts +1 -0
- package/dist/api/rendering/_export-rendering.d.ts.map +1 -1
- package/dist/api/rendering/primitive/IPrimitiveStateDescriptor.d.ts +24 -0
- package/dist/api/rendering/primitive/IPrimitiveStateDescriptor.d.ts.map +1 -0
- package/dist/api/rendering/primitive/_export.d.ts +1 -1
- package/dist/api/rendering/primitive/_export.d.ts.map +1 -1
- package/dist/api/rendering/render-pipelines/IMainRenderTargetRenderPipeline.d.ts +5 -0
- package/dist/api/rendering/render-pipelines/IMainRenderTargetRenderPipeline.d.ts.map +1 -1
- package/dist/api/rendering/texture/ITextureDescriptor.d.ts +5 -1
- package/dist/api/rendering/texture/ITextureDescriptor.d.ts.map +1 -1
- package/dist/api/rendering/texture/ITextureFactory.d.ts +3 -1
- package/dist/api/rendering/texture/ITextureFactory.d.ts.map +1 -1
- package/dist/api/rendering/texture/TextureUtilities.d.ts +7 -0
- package/dist/api/rendering/texture/TextureUtilities.d.ts.map +1 -1
- package/dist/api/scene/ISceneObject.d.ts +12 -0
- package/dist/api/scene/ISceneObject.d.ts.map +1 -0
- package/dist/api/scene/Scene.d.ts +17 -6
- package/dist/api/scene/Scene.d.ts.map +1 -1
- package/dist/api/scene/node/Node.d.ts +26 -0
- package/dist/api/scene/node/Node.d.ts.map +1 -0
- package/dist/api/scene/node/TransformNode.d.ts +46 -0
- package/dist/api/scene/node/TransformNode.d.ts.map +1 -0
- package/dist/core/material/UnlitMaterialDescriptorUtilities.d.ts +17 -0
- package/dist/core/material/UnlitMaterialDescriptorUtilities.d.ts.map +1 -0
- package/dist/core/rendering/AGraphicsDevice.d.ts +2 -2
- package/dist/core/rendering/AGraphicsDevice.d.ts.map +1 -1
- package/dist/core/rendering/ARenderer.d.ts +5 -2
- package/dist/core/rendering/ARenderer.d.ts.map +1 -1
- package/dist/core/rendering/primitive/PrimitiveStateDescriptorUtilities.d.ts +15 -0
- package/dist/core/rendering/primitive/PrimitiveStateDescriptorUtilities.d.ts.map +1 -0
- package/dist/core/rendering/texture/TextureDescriptorUtilities.d.ts +2 -2
- package/dist/core/rendering/texture/TextureDescriptorUtilities.d.ts.map +1 -1
- package/dist/index.js +704 -272
- package/dist/webgl/WebGlGraphicsDevice.d.ts +2 -2
- package/dist/webgl/WebGlGraphicsDevice.d.ts.map +1 -1
- package/dist/webgl/lights/WebGlLightsBuffer.d.ts.map +1 -1
- package/dist/webgl/primitive/WebGlPrimitiveState.d.ts +3 -3
- package/dist/webgl/primitive/WebGlPrimitiveState.d.ts.map +1 -1
- package/dist/webgl/render-pipelines/WebGlMainRenderTargetRenderPipeline.d.ts +8 -0
- package/dist/webgl/render-pipelines/WebGlMainRenderTargetRenderPipeline.d.ts.map +1 -1
- package/dist/webgl/texture/WebGlTextureFactory.d.ts +1 -1
- package/dist/webgl/texture/WebGlTextureFactory.d.ts.map +1 -1
- package/dist/webgl/utilities/WebGlTextureUtilities.d.ts.map +1 -1
- package/dist/webgpu/WebGpuGraphicsDevice.d.ts +2 -2
- package/dist/webgpu/WebGpuGraphicsDevice.d.ts.map +1 -1
- package/dist/webgpu/primitive/WebGpuPrimitiveState.d.ts +2 -2
- package/dist/webgpu/primitive/WebGpuPrimitiveState.d.ts.map +1 -1
- package/dist/webgpu/render-pipelines/WebGpuMainRenderTargetRenderPipeline.d.ts +5 -0
- package/dist/webgpu/render-pipelines/WebGpuMainRenderTargetRenderPipeline.d.ts.map +1 -1
- package/dist/webgpu/texture/WebGpuTextureFactory.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/Framework.ts +1 -1
- package/src/api/IFramework.ts +1 -1
- package/src/api/_export.ts +3 -0
- package/src/api/camera/CameraTransformUtilities.ts +182 -0
- package/src/api/camera/ICamera.ts +42 -2
- package/src/api/camera/OrbitCamera.ts +71 -38
- package/src/api/camera/OrthographicCamera.ts +71 -28
- package/src/api/camera/PerspectiveCamera.ts +69 -33
- package/src/api/content/ContentManager.ts +9 -5
- package/src/api/lights/AmbientLight.ts +8 -2
- package/src/api/lights/DirectionalLight.ts +30 -5
- package/src/api/lights/ILight.ts +22 -0
- package/src/api/lights/PointLight.ts +26 -5
- package/src/api/lights/_export.ts +1 -0
- package/src/api/material/ForwardBlinnPhongMaterial.ts +2 -2
- package/src/api/material/IMaterial.ts +8 -0
- package/src/api/material/IMaterialFactory.ts +3 -2
- package/src/api/material/IUnlitMaterialDescriptor.ts +18 -0
- package/src/api/material/MaterialFactory.ts +4 -3
- package/src/api/material/SpriteMaterial.ts +4 -0
- package/src/api/material/UnlitMaterial.ts +11 -18
- package/src/api/material/_export.ts +1 -1
- package/src/api/meshes/IRenderableMesh.ts +3 -18
- package/src/api/meshes/RenderableMesh.ts +15 -45
- package/src/api/rendering/IGraphicsDevice.ts +2 -2
- package/src/api/rendering/IRenderer.ts +6 -4
- package/src/api/rendering/_export-rendering.ts +2 -1
- package/src/api/rendering/primitive/IPrimitiveStateDescriptor.ts +27 -0
- package/src/api/rendering/primitive/_export.ts +1 -1
- package/src/api/rendering/render-pipelines/IMainRenderTargetRenderPipeline.ts +6 -0
- package/src/api/rendering/texture/ITextureDescriptor.ts +6 -1
- package/src/api/rendering/texture/ITextureFactory.ts +3 -1
- package/src/api/rendering/texture/TextureUtilities.ts +16 -0
- package/src/api/scene/ISceneObject.ts +13 -0
- package/src/api/scene/Scene.ts +52 -11
- package/src/api/scene/node/Node.ts +54 -0
- package/src/api/scene/node/TransformNode.ts +88 -0
- package/src/core/material/UnlitMaterialDescriptorUtilities.ts +21 -0
- package/src/core/rendering/AGraphicsDevice.ts +2 -2
- package/src/core/rendering/ARenderer.ts +23 -5
- package/src/core/rendering/primitive/PrimitiveStateDescriptorUtilities.ts +22 -0
- package/src/core/rendering/texture/TextureDescriptorUtilities.ts +3 -2
- package/src/webgl/WebGlGraphicsDevice.ts +2 -3
- package/src/webgl/lights/WebGlLightsBuffer.ts +21 -8
- package/src/webgl/primitive/WebGlPrimitiveState.ts +8 -6
- package/src/webgl/render-pipelines/WebGlMainRenderTargetRenderPipeline.ts +14 -0
- package/src/webgl/texture/WebGlTextureFactory.ts +27 -16
- package/src/webgl/utilities/WebGlTextureUtilities.ts +10 -4
- package/src/webgpu/WebGpuGraphicsDevice.ts +3 -3
- package/src/webgpu/primitive/WebGpuPrimitiveState.ts +7 -5
- package/src/webgpu/render-pipelines/WebGpuMainRenderTargetRenderPipeline.ts +6 -0
- package/src/webgpu/texture/WebGpuTextureFactory.ts +1 -1
- package/dist/api/material/ICameraMaterial.d.ts +0 -18
- package/dist/api/material/ICameraMaterial.d.ts.map +0 -1
- package/dist/api/rendering/primitive/PrimitiveStateDescriptor.d.ts +0 -24
- package/dist/api/rendering/primitive/PrimitiveStateDescriptor.d.ts.map +0 -1
- package/src/api/material/ICameraMaterial.ts +0 -22
- package/src/api/rendering/primitive/PrimitiveStateDescriptor.ts +0 -27
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { vec4, vec3, mat4,
|
|
1
|
+
import { vec4, vec3, quat, mat4, mat3, vec2 } from "gl-matrix";
|
|
2
2
|
var RenderingBackend = /* @__PURE__ */ ((RenderingBackend2) => {
|
|
3
3
|
RenderingBackend2[RenderingBackend2["DEFAULT"] = 0] = "DEFAULT";
|
|
4
4
|
RenderingBackend2[RenderingBackend2["WEB_GPU"] = 1] = "WEB_GPU";
|
|
@@ -35,7 +35,7 @@ class IFrameworkConfiguration {
|
|
|
35
35
|
backBufferSize;
|
|
36
36
|
/** The texture filtering to configure */
|
|
37
37
|
textureFiltering;
|
|
38
|
-
/** The texture color space to use by default. By default, it is {@link ColorSpace.
|
|
38
|
+
/** The texture color space to use by default. By default, it is {@link ColorSpace.LINEAR}. */
|
|
39
39
|
textureColorSpace;
|
|
40
40
|
/**
|
|
41
41
|
* The HTMLCanvasElement to use for rendering.
|
|
@@ -1052,6 +1052,7 @@ class TextureUtilities {
|
|
|
1052
1052
|
[TextureFormat.BC7_RGBA_UNORM]: m.BC7_RGBA,
|
|
1053
1053
|
[TextureFormat.ETC2_RGBA8_UNORM]: m.ETC2_RGBA,
|
|
1054
1054
|
[TextureFormat.PVRTC_4BPPV1_RGBA]: m.PVRTC1_4_RGBA,
|
|
1055
|
+
[TextureFormat.PVRTC_4BPPV1_RGB]: m.PVRTC1_4_RGB,
|
|
1055
1056
|
// Basis transcodes to the same blocks for sRGB; only the GPU format differs.
|
|
1056
1057
|
[TextureFormat.RGBA_8_UNORM_SRGB]: m.RGBA32,
|
|
1057
1058
|
[TextureFormat.ASTC_4X4_RGBA_SRGB]: m.ASTC_4X4_RGBA,
|
|
@@ -1185,6 +1186,18 @@ class TextureUtilities {
|
|
|
1185
1186
|
static isSrgbFormat(textureFormat) {
|
|
1186
1187
|
return this._srgbFormats.includes(textureFormat);
|
|
1187
1188
|
}
|
|
1189
|
+
/**
|
|
1190
|
+
* Returns the requested format if it is the file's format or its sRGB/linear variant.
|
|
1191
|
+
* @param fileFormat The format the data is stored in.
|
|
1192
|
+
* @param requested The explicitly requested format.
|
|
1193
|
+
* @throws If the requested format cannot reinterpret the data.
|
|
1194
|
+
*/
|
|
1195
|
+
static resolveExplicitFormat(fileFormat, requested) {
|
|
1196
|
+
if (requested == fileFormat || requested == TextureUtilities.convertToSrgbVariant(fileFormat) || requested == TextureUtilities.convertToLinearVariant(fileFormat)) {
|
|
1197
|
+
return requested;
|
|
1198
|
+
}
|
|
1199
|
+
throw new Error(`Texture format ${requested} is not compatible with the file's format ${fileFormat}; only its sRGB or linear variant can be used.`);
|
|
1200
|
+
}
|
|
1188
1201
|
}
|
|
1189
1202
|
var BufferUsage = /* @__PURE__ */ ((BufferUsage2) => {
|
|
1190
1203
|
BufferUsage2[BufferUsage2["NONE"] = 0] = "NONE";
|
|
@@ -1643,48 +1656,23 @@ let SamplerDescriptor$1 = class SamplerDescriptor {
|
|
|
1643
1656
|
*/
|
|
1644
1657
|
mipMapFilter = MipMapSamplerFilter.NONE;
|
|
1645
1658
|
};
|
|
1646
|
-
var PrimitiveTopology = /* @__PURE__ */ ((PrimitiveTopology2) => {
|
|
1647
|
-
PrimitiveTopology2[PrimitiveTopology2["LINE_LIST"] = 0] = "LINE_LIST";
|
|
1648
|
-
PrimitiveTopology2[PrimitiveTopology2["LINE_STRIP"] = 1] = "LINE_STRIP";
|
|
1649
|
-
PrimitiveTopology2[PrimitiveTopology2["POINT_LIST"] = 2] = "POINT_LIST";
|
|
1650
|
-
PrimitiveTopology2[PrimitiveTopology2["TRIANGLE_LIST"] = 3] = "TRIANGLE_LIST";
|
|
1651
|
-
PrimitiveTopology2[PrimitiveTopology2["TRIANGLE_STRIP"] = 4] = "TRIANGLE_STRIP";
|
|
1652
|
-
return PrimitiveTopology2;
|
|
1653
|
-
})(PrimitiveTopology || {});
|
|
1654
|
-
var CullMode = /* @__PURE__ */ ((CullMode2) => {
|
|
1655
|
-
CullMode2[CullMode2["NONE"] = 0] = "NONE";
|
|
1656
|
-
CullMode2[CullMode2["BACK"] = 1] = "BACK";
|
|
1657
|
-
CullMode2[CullMode2["FRONT"] = 2] = "FRONT";
|
|
1658
|
-
return CullMode2;
|
|
1659
|
-
})(CullMode || {});
|
|
1660
|
-
var FrontFace = /* @__PURE__ */ ((FrontFace2) => {
|
|
1661
|
-
FrontFace2[FrontFace2["CW"] = 0] = "CW";
|
|
1662
|
-
FrontFace2[FrontFace2["CCW"] = 1] = "CCW";
|
|
1663
|
-
return FrontFace2;
|
|
1664
|
-
})(FrontFace || {});
|
|
1665
|
-
class PrimitiveStateDescriptor {
|
|
1666
|
-
/**
|
|
1667
|
-
* The topology of the primitive.
|
|
1668
|
-
* By default, it is set to TRIANGLE_LIST.
|
|
1669
|
-
*/
|
|
1670
|
-
topology = PrimitiveTopology.TRIANGLE_LIST;
|
|
1671
|
-
/**
|
|
1672
|
-
* The culling mode.
|
|
1673
|
-
* By default, it is set to BACK.
|
|
1674
|
-
*/
|
|
1675
|
-
cullFace = CullMode.BACK;
|
|
1676
|
-
/**
|
|
1677
|
-
* The front face.
|
|
1678
|
-
* By default, it is set to CCW(counter clock-wise).
|
|
1679
|
-
*/
|
|
1680
|
-
frontFace = FrontFace.CCW;
|
|
1681
|
-
}
|
|
1682
1659
|
var PowerPreferenceType = /* @__PURE__ */ ((PowerPreferenceType2) => {
|
|
1683
1660
|
PowerPreferenceType2["DEFAULT"] = "default";
|
|
1684
1661
|
PowerPreferenceType2["LOW_POWER"] = "low-power";
|
|
1685
1662
|
PowerPreferenceType2["HIGH_PERFORMANCE"] = "high-performance";
|
|
1686
1663
|
return PowerPreferenceType2;
|
|
1687
1664
|
})(PowerPreferenceType || {});
|
|
1665
|
+
var Culling = /* @__PURE__ */ ((Culling2) => {
|
|
1666
|
+
Culling2[Culling2["None"] = 0] = "None";
|
|
1667
|
+
Culling2[Culling2["Back"] = 1] = "Back";
|
|
1668
|
+
Culling2[Culling2["Front"] = 2] = "Front";
|
|
1669
|
+
return Culling2;
|
|
1670
|
+
})(Culling || {});
|
|
1671
|
+
var ColorSpace = /* @__PURE__ */ ((ColorSpace2) => {
|
|
1672
|
+
ColorSpace2["LINEAR"] = "LINEAR";
|
|
1673
|
+
ColorSpace2["SRGB"] = "SRGB";
|
|
1674
|
+
return ColorSpace2;
|
|
1675
|
+
})(ColorSpace || {});
|
|
1688
1676
|
class MathHelper {
|
|
1689
1677
|
/**
|
|
1690
1678
|
* The value of half PI.
|
|
@@ -1887,9 +1875,272 @@ class MathHelper {
|
|
|
1887
1875
|
throw new Error("Not implemented");
|
|
1888
1876
|
}
|
|
1889
1877
|
}
|
|
1878
|
+
class Node {
|
|
1879
|
+
_children = [];
|
|
1880
|
+
_parent;
|
|
1881
|
+
/** The child nodes of this node. */
|
|
1882
|
+
get children() {
|
|
1883
|
+
return this._children;
|
|
1884
|
+
}
|
|
1885
|
+
/** The parent node of this node, if any. */
|
|
1886
|
+
get parent() {
|
|
1887
|
+
return this._parent;
|
|
1888
|
+
}
|
|
1889
|
+
/**
|
|
1890
|
+
* Adds a child. It is removed from its previous parent first. Adding an existing child does nothing.
|
|
1891
|
+
* @param child The child to add.
|
|
1892
|
+
* @throws Error when adding the node to itself or to one of its descendants.
|
|
1893
|
+
*/
|
|
1894
|
+
addChild(child) {
|
|
1895
|
+
if (child._parent === this) {
|
|
1896
|
+
return;
|
|
1897
|
+
}
|
|
1898
|
+
for (let n2 = this; n2; n2 = n2._parent) {
|
|
1899
|
+
if (n2 === child) {
|
|
1900
|
+
throw new Error("Node.addChild: a node cannot be added to itself or to one of its descendants.");
|
|
1901
|
+
}
|
|
1902
|
+
}
|
|
1903
|
+
child._parent?.removeChild(child);
|
|
1904
|
+
child._parent = this;
|
|
1905
|
+
this._children.push(child);
|
|
1906
|
+
}
|
|
1907
|
+
/**
|
|
1908
|
+
* Removes a child.
|
|
1909
|
+
* @param child The child to remove.
|
|
1910
|
+
* @returns True when it was a child of this node.
|
|
1911
|
+
*/
|
|
1912
|
+
removeChild(child) {
|
|
1913
|
+
const index = this._children.indexOf(child);
|
|
1914
|
+
if (index < 0) {
|
|
1915
|
+
return false;
|
|
1916
|
+
}
|
|
1917
|
+
this._children.splice(index, 1);
|
|
1918
|
+
child._parent = void 0;
|
|
1919
|
+
return true;
|
|
1920
|
+
}
|
|
1921
|
+
}
|
|
1922
|
+
class TransformNode extends Node {
|
|
1923
|
+
_rotationQuat = quat.create();
|
|
1924
|
+
_localMatrix = mat4.create();
|
|
1925
|
+
_worldMatrix = mat4.create();
|
|
1926
|
+
// Cached copies to detect in-place edits; NaN forces the first computation.
|
|
1927
|
+
_lastPosition = vec3.fromValues(NaN, NaN, NaN);
|
|
1928
|
+
_lastRotation = vec3.create();
|
|
1929
|
+
_lastScale = vec3.create();
|
|
1930
|
+
/**
|
|
1931
|
+
* The constructor.
|
|
1932
|
+
*/
|
|
1933
|
+
constructor() {
|
|
1934
|
+
super();
|
|
1935
|
+
this.position = vec3.fromValues(0, 0, 0);
|
|
1936
|
+
this.rotation = vec3.fromValues(0, 0, 0);
|
|
1937
|
+
this.scale = vec3.fromValues(1, 1, 1);
|
|
1938
|
+
}
|
|
1939
|
+
/** Position relative to the parent (the world, without one). Defaults to the origin. In-place edits are detected. */
|
|
1940
|
+
position;
|
|
1941
|
+
/**
|
|
1942
|
+
* Euler rotation in radians, applied in Y, X, Z order (yaw, pitch, roll): `R = Ry * Rx * Rz`.
|
|
1943
|
+
* Defaults to (0, 0, 0). In-place edits are detected.
|
|
1944
|
+
*/
|
|
1945
|
+
rotation;
|
|
1946
|
+
/** Scale. Defaults to (1, 1, 1). In-place edits are detected. */
|
|
1947
|
+
scale;
|
|
1948
|
+
/** The local matrix `T * R * S`, recomputed only when position, rotation or scale changed. */
|
|
1949
|
+
get localMatrix() {
|
|
1950
|
+
if (!vec3.exactEquals(this._lastPosition, this.position) || !vec3.exactEquals(this._lastRotation, this.rotation) || !vec3.exactEquals(this._lastScale, this.scale)) {
|
|
1951
|
+
vec3.copy(this._lastPosition, this.position);
|
|
1952
|
+
vec3.copy(this._lastRotation, this.rotation);
|
|
1953
|
+
vec3.copy(this._lastScale, this.scale);
|
|
1954
|
+
const q = quat.identity(this._rotationQuat);
|
|
1955
|
+
quat.rotateY(q, q, this.rotation[1]);
|
|
1956
|
+
quat.rotateX(q, q, this.rotation[0]);
|
|
1957
|
+
quat.rotateZ(q, q, this.rotation[2]);
|
|
1958
|
+
mat4.fromRotationTranslationScale(this._localMatrix, q, this.position, this.scale);
|
|
1959
|
+
}
|
|
1960
|
+
return this._localMatrix;
|
|
1961
|
+
}
|
|
1962
|
+
/**
|
|
1963
|
+
* The model (world) matrix: {@link localMatrix}, or `parent.modelMatrix * localMatrix` when the parent is a
|
|
1964
|
+
* `TransformNode`. Always the same matrix object for a node without a parent transform.
|
|
1965
|
+
*/
|
|
1966
|
+
get modelMatrix() {
|
|
1967
|
+
const parent = this.parent;
|
|
1968
|
+
if (parent instanceof TransformNode) {
|
|
1969
|
+
return mat4.multiply(this._worldMatrix, parent.modelMatrix, this.localMatrix);
|
|
1970
|
+
}
|
|
1971
|
+
return this.localMatrix;
|
|
1972
|
+
}
|
|
1973
|
+
/**
|
|
1974
|
+
* Updates the node and its transform children, recomputing the matrices if needed.
|
|
1975
|
+
* Called by `Scene.update` for scene nodes; optional otherwise.
|
|
1976
|
+
* @param gameTime The {@link GameTime}
|
|
1977
|
+
*/
|
|
1978
|
+
update(gameTime) {
|
|
1979
|
+
void this.modelMatrix;
|
|
1980
|
+
for (const child of this.children) {
|
|
1981
|
+
if (child instanceof TransformNode) {
|
|
1982
|
+
child.update(gameTime);
|
|
1983
|
+
}
|
|
1984
|
+
}
|
|
1985
|
+
}
|
|
1986
|
+
}
|
|
1987
|
+
const _f = vec3.create();
|
|
1988
|
+
const _x = vec3.create();
|
|
1989
|
+
const _y = vec3.create();
|
|
1990
|
+
const _z = vec3.create();
|
|
1991
|
+
const _u = vec3.create();
|
|
1992
|
+
const _m = mat4.create();
|
|
1993
|
+
const _n = mat3.create();
|
|
1994
|
+
const _p = vec3.create();
|
|
1995
|
+
const _t = vec3.create();
|
|
1996
|
+
class CameraTransformUtilities {
|
|
1997
|
+
/**
|
|
1998
|
+
* Writes the view matrix `inverse(T * R)` from a world matrix, ignoring scale.
|
|
1999
|
+
* @param out The view matrix.
|
|
2000
|
+
* @param world The camera's world matrix (`transform.modelMatrix`).
|
|
2001
|
+
*/
|
|
2002
|
+
static viewFromWorld(out, world) {
|
|
2003
|
+
mat4.copy(out, world);
|
|
2004
|
+
for (let c2 = 0; c2 < 3; c2++) {
|
|
2005
|
+
const i2 = c2 * 4;
|
|
2006
|
+
const length = Math.hypot(out[i2], out[i2 + 1], out[i2 + 2]) || 1;
|
|
2007
|
+
out[i2] /= length;
|
|
2008
|
+
out[i2 + 1] /= length;
|
|
2009
|
+
out[i2 + 2] /= length;
|
|
2010
|
+
}
|
|
2011
|
+
return mat4.invert(out, out) ?? mat4.identity(out);
|
|
2012
|
+
}
|
|
2013
|
+
/**
|
|
2014
|
+
* Writes the Euler rotation (the transform's Y-X-Z order) that makes a camera at `position` look at `target`
|
|
2015
|
+
* with `up` as the up hint (a non-vertical up rolls the camera). When `up` is parallel to the view direction,
|
|
2016
|
+
* the world axis least aligned with the view direction is used instead. Leaves `out` unchanged when the points are equal.
|
|
2017
|
+
* @param out The rotation.
|
|
2018
|
+
* @param position The camera position.
|
|
2019
|
+
* @param target The point to look at.
|
|
2020
|
+
* @param up The up hint. By default, world +Y.
|
|
2021
|
+
*/
|
|
2022
|
+
static lookAtRotation(out, position, target, up = [0, 1, 0]) {
|
|
2023
|
+
vec3.sub(_f, target, position);
|
|
2024
|
+
if (vec3.sqrLen(_f) === 0) {
|
|
2025
|
+
return out;
|
|
2026
|
+
}
|
|
2027
|
+
vec3.normalize(_f, _f);
|
|
2028
|
+
vec3.negate(_z, _f);
|
|
2029
|
+
vec3.cross(_x, up, _z);
|
|
2030
|
+
if (vec3.sqrLen(_x) < 1e-12) {
|
|
2031
|
+
const ax = Math.abs(_f[0]), ay = Math.abs(_f[1]), az = Math.abs(_f[2]);
|
|
2032
|
+
vec3.set(_u, 0, 0, 0);
|
|
2033
|
+
_u[ay <= ax && ay <= az ? 1 : az <= ax ? 2 : 0] = 1;
|
|
2034
|
+
vec3.cross(_x, _u, _z);
|
|
2035
|
+
}
|
|
2036
|
+
vec3.normalize(_x, _x);
|
|
2037
|
+
vec3.cross(_y, _z, _x);
|
|
2038
|
+
const m23 = _z[1];
|
|
2039
|
+
out[0] = Math.asin(Math.max(-1, Math.min(1, -m23)));
|
|
2040
|
+
if (Math.abs(m23) < 0.9999999) {
|
|
2041
|
+
out[1] = Math.atan2(_z[0], _z[2]);
|
|
2042
|
+
out[2] = Math.atan2(_x[1], _y[1]);
|
|
2043
|
+
} else {
|
|
2044
|
+
out[1] = Math.atan2(-_x[2], _x[0]);
|
|
2045
|
+
out[2] = 0;
|
|
2046
|
+
}
|
|
2047
|
+
return out;
|
|
2048
|
+
}
|
|
2049
|
+
/**
|
|
2050
|
+
* Writes the camera's forward direction (unit length) from a world matrix.
|
|
2051
|
+
* @param out The direction.
|
|
2052
|
+
* @param world The camera's world matrix.
|
|
2053
|
+
*/
|
|
2054
|
+
static forwardFromWorld(out, world) {
|
|
2055
|
+
vec3.set(out, -world[8], -world[9], -world[10]);
|
|
2056
|
+
return vec3.normalize(out, out);
|
|
2057
|
+
}
|
|
2058
|
+
/**
|
|
2059
|
+
* Rotates a camera transform to look at a world-space point with a world-space up hint.
|
|
2060
|
+
* When the transform has a `TransformNode` parent, the target and up are converted into the parent's space.
|
|
2061
|
+
* @param transform The camera transform.
|
|
2062
|
+
* @param target The world point.
|
|
2063
|
+
* @param up The world up hint.
|
|
2064
|
+
*/
|
|
2065
|
+
static aimTransform(transform, target, up) {
|
|
2066
|
+
const parent = transform.parent;
|
|
2067
|
+
if (parent instanceof TransformNode) {
|
|
2068
|
+
mat4.invert(_m, parent.modelMatrix);
|
|
2069
|
+
vec3.transformMat4(_t, target, _m);
|
|
2070
|
+
mat3.fromMat4(_n, _m);
|
|
2071
|
+
vec3.transformMat3(_p, up, _n);
|
|
2072
|
+
CameraTransformUtilities.lookAtRotation(transform.rotation, transform.position, _t, _p);
|
|
2073
|
+
} else {
|
|
2074
|
+
CameraTransformUtilities.lookAtRotation(transform.rotation, transform.position, target, up);
|
|
2075
|
+
}
|
|
2076
|
+
}
|
|
2077
|
+
/**
|
|
2078
|
+
* Writes a world position into `transform.position`, converting into the parent's space when it has a `TransformNode` parent.
|
|
2079
|
+
*/
|
|
2080
|
+
static setWorldPosition(transform, world) {
|
|
2081
|
+
const parent = transform.parent;
|
|
2082
|
+
if (parent instanceof TransformNode) {
|
|
2083
|
+
mat4.invert(_m, parent.modelMatrix);
|
|
2084
|
+
vec3.transformMat4(transform.position, world, _m);
|
|
2085
|
+
} else {
|
|
2086
|
+
vec3.copy(transform.position, world);
|
|
2087
|
+
}
|
|
2088
|
+
}
|
|
2089
|
+
}
|
|
2090
|
+
class CameraAim {
|
|
2091
|
+
constructor(_transform) {
|
|
2092
|
+
this._transform = _transform;
|
|
2093
|
+
}
|
|
2094
|
+
_transform;
|
|
2095
|
+
_target = vec3.create();
|
|
2096
|
+
_hasTarget = false;
|
|
2097
|
+
_up = vec3.fromValues(0, 1, 0);
|
|
2098
|
+
setEye(eye) {
|
|
2099
|
+
CameraTransformUtilities.setWorldPosition(this._transform(), eye);
|
|
2100
|
+
if (this._hasTarget) {
|
|
2101
|
+
this.aim();
|
|
2102
|
+
}
|
|
2103
|
+
}
|
|
2104
|
+
getEye(out = vec3.create()) {
|
|
2105
|
+
const m2 = this._transform().modelMatrix;
|
|
2106
|
+
return vec3.set(out, m2[12], m2[13], m2[14]);
|
|
2107
|
+
}
|
|
2108
|
+
setTarget(target) {
|
|
2109
|
+
vec3.copy(this._target, target);
|
|
2110
|
+
this._hasTarget = true;
|
|
2111
|
+
this.aim();
|
|
2112
|
+
}
|
|
2113
|
+
getTarget(out = vec3.create()) {
|
|
2114
|
+
if (this._hasTarget) {
|
|
2115
|
+
return vec3.copy(out, this._target);
|
|
2116
|
+
}
|
|
2117
|
+
const m2 = this._transform().modelMatrix;
|
|
2118
|
+
CameraTransformUtilities.forwardFromWorld(_f, m2);
|
|
2119
|
+
return vec3.set(out, m2[12] + _f[0], m2[13] + _f[1], m2[14] + _f[2]);
|
|
2120
|
+
}
|
|
2121
|
+
setUp(up) {
|
|
2122
|
+
vec3.copy(this._up, up);
|
|
2123
|
+
if (this._hasTarget) {
|
|
2124
|
+
this.aim();
|
|
2125
|
+
}
|
|
2126
|
+
}
|
|
2127
|
+
getUp(out = vec3.create()) {
|
|
2128
|
+
return vec3.copy(out, this._up);
|
|
2129
|
+
}
|
|
2130
|
+
/** One-shot look-at with the current up; forgets the stored target. */
|
|
2131
|
+
lookAt(target) {
|
|
2132
|
+
this._hasTarget = false;
|
|
2133
|
+
CameraTransformUtilities.aimTransform(this._transform(), target, this._up);
|
|
2134
|
+
}
|
|
2135
|
+
/** Re-aims at the stored target. */
|
|
2136
|
+
aim() {
|
|
2137
|
+
CameraTransformUtilities.aimTransform(this._transform(), this._target, this._up);
|
|
2138
|
+
}
|
|
2139
|
+
}
|
|
1890
2140
|
class PerspectiveCamera {
|
|
1891
2141
|
_framework;
|
|
1892
|
-
|
|
2142
|
+
_lastWorld = mat4.fromValues(NaN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
|
2143
|
+
_positionData = [0, 0, 0, 0];
|
|
1893
2144
|
_projectionMatrix = mat4.create();
|
|
1894
2145
|
_viewMatrix = mat4.create();
|
|
1895
2146
|
_projectionViewMatrix = mat4.create();
|
|
@@ -1911,15 +2162,11 @@ class PerspectiveCamera {
|
|
|
1911
2162
|
this.aspectRatio = descriptor?.aspectRatio ?? 1;
|
|
1912
2163
|
this.nearPlane = descriptor?.near ?? 0.01;
|
|
1913
2164
|
this.farPlane = descriptor?.far ?? 100;
|
|
1914
|
-
|
|
1915
|
-
vec3.copy(this.eye, descriptor.eye);
|
|
1916
|
-
}
|
|
1917
|
-
if (descriptor?.target) {
|
|
1918
|
-
vec3.copy(this.target, descriptor.target);
|
|
1919
|
-
}
|
|
2165
|
+
vec3.copy(this.transform.position, descriptor?.position ?? descriptor?.eye ?? [0, 0, -3]);
|
|
1920
2166
|
if (descriptor?.up) {
|
|
1921
|
-
|
|
2167
|
+
this.setUp(descriptor.up);
|
|
1922
2168
|
}
|
|
2169
|
+
this.setTarget(descriptor?.target ?? [0, 0, 0]);
|
|
1923
2170
|
if (scene) {
|
|
1924
2171
|
scene.add(this);
|
|
1925
2172
|
}
|
|
@@ -1978,21 +2225,47 @@ class PerspectiveCamera {
|
|
|
1978
2225
|
return this._positionBuffer;
|
|
1979
2226
|
}
|
|
1980
2227
|
/**
|
|
1981
|
-
* The
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
/**
|
|
1985
|
-
* The target position of the camera.
|
|
2228
|
+
* The camera transform: the single source of the view. The camera looks down its local -Z axis;
|
|
2229
|
+
* the view matrix is `inverse(T * R)` of `transform.modelMatrix` (scale is ignored).
|
|
2230
|
+
* By default, at (0, 0, -3) looking at the origin.
|
|
1986
2231
|
*/
|
|
1987
|
-
|
|
2232
|
+
transform = new TransformNode();
|
|
2233
|
+
/** The unit direction the camera looks in, from the transform. */
|
|
2234
|
+
get direction() {
|
|
2235
|
+
return CameraTransformUtilities.forwardFromWorld(this._direction, this.transform.modelMatrix);
|
|
2236
|
+
}
|
|
2237
|
+
_aim = new CameraAim(() => this.transform);
|
|
1988
2238
|
/**
|
|
1989
|
-
*
|
|
2239
|
+
* Rotates the transform once so the camera looks at a world point, using the current up ({@link getUp}).
|
|
2240
|
+
* Forgets the target stored by {@link setTarget}, so a later {@link setEye} does not re-aim.
|
|
2241
|
+
* @param target The point to look at.
|
|
1990
2242
|
*/
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
2243
|
+
lookAt(target) {
|
|
2244
|
+
this._aim.lookAt(target);
|
|
2245
|
+
}
|
|
2246
|
+
/** @inheritDoc */
|
|
2247
|
+
setEye(eye) {
|
|
2248
|
+
this._aim.setEye(eye);
|
|
2249
|
+
}
|
|
2250
|
+
/** @inheritDoc */
|
|
2251
|
+
getEye(out) {
|
|
2252
|
+
return this._aim.getEye(out);
|
|
2253
|
+
}
|
|
2254
|
+
/** @inheritDoc */
|
|
2255
|
+
setTarget(target) {
|
|
2256
|
+
this._aim.setTarget(target);
|
|
2257
|
+
}
|
|
2258
|
+
/** @inheritDoc */
|
|
2259
|
+
getTarget(out) {
|
|
2260
|
+
return this._aim.getTarget(out);
|
|
2261
|
+
}
|
|
2262
|
+
/** @inheritDoc */
|
|
2263
|
+
setUp(up) {
|
|
2264
|
+
this._aim.setUp(up);
|
|
2265
|
+
}
|
|
2266
|
+
/** @inheritDoc */
|
|
2267
|
+
getUp(out) {
|
|
2268
|
+
return this._aim.getUp(out);
|
|
1996
2269
|
}
|
|
1997
2270
|
/**
|
|
1998
2271
|
* The field of view of the camera.
|
|
@@ -2022,22 +2295,24 @@ class PerspectiveCamera {
|
|
|
2022
2295
|
this._projectionBuffer = this._framework.bufferFactory.createUniformBuffer(this.projectionMatrix, bufferUsage);
|
|
2023
2296
|
this._viewBuffer = this._framework.bufferFactory.createUniformBuffer(this.viewMatrix, bufferUsage);
|
|
2024
2297
|
}
|
|
2025
|
-
/**
|
|
2026
|
-
* The eye in world space, as used by the view matrix: z is flipped for the right-handed look-at.
|
|
2027
|
-
* This is what {@link positionBuffer} holds, std140 `vec3` (padded to 16 bytes).
|
|
2028
|
-
*/
|
|
2298
|
+
/** The world position, std140 `vec3` (padded to 16 bytes). This is what {@link positionBuffer} holds. */
|
|
2029
2299
|
_worldEye() {
|
|
2030
|
-
|
|
2300
|
+
const m2 = this.transform.modelMatrix;
|
|
2301
|
+
this._positionData[0] = m2[12];
|
|
2302
|
+
this._positionData[1] = m2[13];
|
|
2303
|
+
this._positionData[2] = m2[14];
|
|
2304
|
+
return this._positionData;
|
|
2031
2305
|
}
|
|
2032
2306
|
/**
|
|
2033
2307
|
* Updates the camera matrices.
|
|
2034
2308
|
*/
|
|
2035
2309
|
_updateMatrices() {
|
|
2036
2310
|
mat4.perspectiveNO(this._projectionMatrix, this.fieldOfView, this.aspectRatio, this.nearPlane, this.farPlane);
|
|
2037
|
-
|
|
2038
|
-
this.
|
|
2039
|
-
|
|
2040
|
-
|
|
2311
|
+
const world = this.transform.modelMatrix;
|
|
2312
|
+
if (!mat4.exactEquals(this._lastWorld, world)) {
|
|
2313
|
+
mat4.copy(this._lastWorld, world);
|
|
2314
|
+
CameraTransformUtilities.viewFromWorld(this.viewMatrix, world);
|
|
2315
|
+
}
|
|
2041
2316
|
mat4.multiply(this.projectionViewMatrix, this.projectionMatrix, this.viewMatrix);
|
|
2042
2317
|
}
|
|
2043
2318
|
/** @inheritDoc */
|
|
@@ -2414,8 +2689,8 @@ class OrbitCamera {
|
|
|
2414
2689
|
this.supportedInputTypes = supportedInputTypes;
|
|
2415
2690
|
this._coreCamera = coreCamera;
|
|
2416
2691
|
this._inputManager = inputManager;
|
|
2417
|
-
this.
|
|
2418
|
-
this.
|
|
2692
|
+
vec3.set(this._coreCamera.transform.position, 0, 0, 3);
|
|
2693
|
+
this._syncFromTransform();
|
|
2419
2694
|
void this.POSITIVE_179_DEG;
|
|
2420
2695
|
void this.findTarget;
|
|
2421
2696
|
}
|
|
@@ -2431,6 +2706,7 @@ class OrbitCamera {
|
|
|
2431
2706
|
_coreCamera;
|
|
2432
2707
|
_inputManager;
|
|
2433
2708
|
/** The rotation around the vertical axis. */
|
|
2709
|
+
_target = vec3.create();
|
|
2434
2710
|
_yaw = 0;
|
|
2435
2711
|
/** The tilt of the camera.*/
|
|
2436
2712
|
_pitch = 0;
|
|
@@ -2443,7 +2719,6 @@ class OrbitCamera {
|
|
|
2443
2719
|
/** The speed of pinch.*/
|
|
2444
2720
|
pinchSpeed = 1;
|
|
2445
2721
|
/** The up vector. */
|
|
2446
|
-
up = vec3.fromValues(0, 1, 0);
|
|
2447
2722
|
/** The clamp values of pitch axis */
|
|
2448
2723
|
pitchClamp = vec2.fromValues(-this.POSITIVE_89_DEG, this.POSITIVE_89_DEG);
|
|
2449
2724
|
/** @inheritDoc */
|
|
@@ -2484,33 +2759,56 @@ class OrbitCamera {
|
|
|
2484
2759
|
}
|
|
2485
2760
|
/** Orbit controls can be used if this button is pressed. */
|
|
2486
2761
|
orbitButton = MouseButton.LEFT;
|
|
2487
|
-
/**
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
get eye() {
|
|
2491
|
-
return this._coreCamera.eye;
|
|
2762
|
+
/** The orbit camera's transform: the core camera's transform. Its position is the eye; the rotation is set each update to look at {@link target}. */
|
|
2763
|
+
get transform() {
|
|
2764
|
+
return this._coreCamera.transform;
|
|
2492
2765
|
}
|
|
2493
2766
|
/**
|
|
2494
|
-
*
|
|
2767
|
+
* Sets the point the camera orbits around and looks at (the core camera's target). By default, the origin.
|
|
2768
|
+
* @param target The world point.
|
|
2495
2769
|
*/
|
|
2496
|
-
|
|
2497
|
-
this.
|
|
2498
|
-
this.
|
|
2770
|
+
setTarget(target) {
|
|
2771
|
+
vec3.copy(this._target, target);
|
|
2772
|
+
this._syncFromTransform();
|
|
2499
2773
|
}
|
|
2500
|
-
/**
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
get target() {
|
|
2504
|
-
return this._coreCamera.target;
|
|
2774
|
+
/** @inheritDoc */
|
|
2775
|
+
getTarget(out = vec3.create()) {
|
|
2776
|
+
return vec3.copy(out, this._target);
|
|
2505
2777
|
}
|
|
2506
2778
|
/**
|
|
2507
|
-
*
|
|
2779
|
+
* Moves the camera to a world position and re-derives the orbit (pitch, yaw, distance) around the target.
|
|
2780
|
+
* @param eye The world position.
|
|
2508
2781
|
*/
|
|
2509
|
-
|
|
2510
|
-
this._coreCamera.
|
|
2511
|
-
this.
|
|
2782
|
+
setEye(eye) {
|
|
2783
|
+
CameraTransformUtilities.setWorldPosition(this._coreCamera.transform, eye);
|
|
2784
|
+
this._syncFromTransform();
|
|
2785
|
+
}
|
|
2786
|
+
/** @inheritDoc */
|
|
2787
|
+
getEye(out) {
|
|
2788
|
+
return this._coreCamera.getEye(out);
|
|
2789
|
+
}
|
|
2790
|
+
/** Sets the up vector the core camera aims with (the orbit angles stay around world +Y, so this rolls the view). */
|
|
2791
|
+
setUp(up) {
|
|
2792
|
+
this._coreCamera.setUp(up);
|
|
2793
|
+
this._coreCamera.setTarget(this._target);
|
|
2794
|
+
}
|
|
2795
|
+
/** @inheritDoc */
|
|
2796
|
+
getUp(out) {
|
|
2797
|
+
return this._coreCamera.getUp(out);
|
|
2798
|
+
}
|
|
2799
|
+
/** The eye: `transform.position` (world space). */
|
|
2800
|
+
get _eye() {
|
|
2801
|
+
return this._coreCamera.transform.position;
|
|
2802
|
+
}
|
|
2803
|
+
/** Re-derives pitch and yaw from the eye and target, and aims the core camera at the target. */
|
|
2804
|
+
_syncFromTransform() {
|
|
2805
|
+
vec3.sub(this._tempDirection, this._target, this._eye);
|
|
2806
|
+
if (vec3.sqrLen(this._tempDirection) === 0) {
|
|
2807
|
+
return;
|
|
2808
|
+
}
|
|
2809
|
+
this._setPitchAndYawFromDirection(this._tempDirection);
|
|
2810
|
+
this._coreCamera.setTarget(this._target);
|
|
2512
2811
|
}
|
|
2513
|
-
/** Gets the core camera.*/
|
|
2514
2812
|
get coreCamera() {
|
|
2515
2813
|
return this._coreCamera;
|
|
2516
2814
|
}
|
|
@@ -2539,11 +2837,11 @@ class OrbitCamera {
|
|
|
2539
2837
|
vec3.normalize(lookDirection, lookDirection);
|
|
2540
2838
|
const y2 = MathHelper.clamp(lookDirection[1], -1, 1);
|
|
2541
2839
|
this._pitch = -this._pitchClamp(Math.asin(y2));
|
|
2542
|
-
this._yaw = -Math.atan2(lookDirection[0], lookDirection[2]);
|
|
2840
|
+
this._yaw = -Math.atan2(lookDirection[0], 0 - lookDirection[2]);
|
|
2543
2841
|
}
|
|
2544
2842
|
_calculateOrbitMovement() {
|
|
2545
2843
|
this._pitch = this._pitchClamp(this._pitch);
|
|
2546
|
-
vec3.sub(this._tempVec3, this.
|
|
2844
|
+
vec3.sub(this._tempVec3, this._target, this._eye);
|
|
2547
2845
|
const radius = vec3.len(this._tempVec3);
|
|
2548
2846
|
const sinPitch = Math.sin(this._pitch);
|
|
2549
2847
|
const cosPitch = Math.cos(this._pitch);
|
|
@@ -2552,8 +2850,9 @@ class OrbitCamera {
|
|
|
2552
2850
|
const z = radius * cosPitch * Math.cos(this._yaw);
|
|
2553
2851
|
this._tempVec3[0] = x2;
|
|
2554
2852
|
this._tempVec3[1] = y2;
|
|
2555
|
-
this._tempVec3[2] =
|
|
2556
|
-
vec3.add(this.
|
|
2853
|
+
this._tempVec3[2] = z;
|
|
2854
|
+
vec3.add(this._eye, this._target, this._tempVec3);
|
|
2855
|
+
this._coreCamera.setTarget(this._target);
|
|
2557
2856
|
}
|
|
2558
2857
|
/**
|
|
2559
2858
|
* Handles the mouse movement for orbit camera.
|
|
@@ -2605,9 +2904,9 @@ class OrbitCamera {
|
|
|
2605
2904
|
if (diff == 0) {
|
|
2606
2905
|
return;
|
|
2607
2906
|
}
|
|
2608
|
-
vec3.
|
|
2907
|
+
vec3.sub(this._tempDirection, this._target, this._eye);
|
|
2609
2908
|
vec3.normalize(this._tempDirection, this._tempDirection);
|
|
2610
|
-
vec3.copy(this._tempNextEye, this.
|
|
2909
|
+
vec3.copy(this._tempNextEye, this._eye);
|
|
2611
2910
|
if (diff < 0) {
|
|
2612
2911
|
vec3.scale(this._tempVec3, this._tempDirection, this.pinchSpeed * deltaTime);
|
|
2613
2912
|
vec3.sub(this._tempNextEye, this._tempNextEye, this._tempVec3);
|
|
@@ -2615,16 +2914,16 @@ class OrbitCamera {
|
|
|
2615
2914
|
vec3.scale(this._tempVec3, this._tempDirection, this.pinchSpeed * deltaTime);
|
|
2616
2915
|
vec3.add(this._tempNextEye, this._tempNextEye, this._tempVec3);
|
|
2617
2916
|
}
|
|
2618
|
-
vec3.sub(this._tempNextDirection, this.
|
|
2619
|
-
const nextLength = this._tempNextDirection
|
|
2917
|
+
vec3.sub(this._tempNextDirection, this._target, this._tempNextEye);
|
|
2918
|
+
const nextLength = vec3.len(this._tempNextDirection);
|
|
2620
2919
|
vec3.normalize(this._tempNextDirection, this._tempNextDirection);
|
|
2621
2920
|
vec3.sub(this._tempVec3, this._tempNextDirection, this._tempDirection);
|
|
2622
2921
|
const lenSq = vec3.sqrLen(this._tempVec3);
|
|
2623
2922
|
if (nextLength < this._coreCamera.nearPlane || nextLength > this._coreCamera.farPlane || lenSq > 0.1) {
|
|
2624
2923
|
return;
|
|
2625
2924
|
}
|
|
2626
|
-
vec3.copy(this.
|
|
2627
|
-
this.
|
|
2925
|
+
vec3.copy(this._eye, this._tempNextEye);
|
|
2926
|
+
this._syncFromTransform();
|
|
2628
2927
|
}
|
|
2629
2928
|
/** Handles forward/backward movement */
|
|
2630
2929
|
_handleMouseForwardBackwardMovement(mouseState, deltaTime) {
|
|
@@ -2632,7 +2931,7 @@ class OrbitCamera {
|
|
|
2632
2931
|
if (mouseScrollPos == 0) {
|
|
2633
2932
|
return;
|
|
2634
2933
|
}
|
|
2635
|
-
vec3.
|
|
2934
|
+
vec3.sub(this._tempDirection, this._target, this._eye);
|
|
2636
2935
|
const distance = vec3.len(this._tempDirection);
|
|
2637
2936
|
const step = MathHelper.map(
|
|
2638
2937
|
distance,
|
|
@@ -2646,7 +2945,7 @@ class OrbitCamera {
|
|
|
2646
2945
|
trueScrollSpeed = this.maxScrollSpeed;
|
|
2647
2946
|
}
|
|
2648
2947
|
vec3.normalize(this._tempDirection, this._tempDirection);
|
|
2649
|
-
vec3.copy(this._tempNextEye, this.
|
|
2948
|
+
vec3.copy(this._tempNextEye, this._eye);
|
|
2650
2949
|
if (mouseScrollPos > 0) {
|
|
2651
2950
|
vec3.scale(this._tempVec3, this._tempDirection, trueScrollSpeed * deltaTime);
|
|
2652
2951
|
vec3.sub(this._tempNextEye, this._tempNextEye, this._tempVec3);
|
|
@@ -2654,16 +2953,16 @@ class OrbitCamera {
|
|
|
2654
2953
|
vec3.scale(this._tempVec3, this._tempDirection, trueScrollSpeed * deltaTime);
|
|
2655
2954
|
vec3.add(this._tempNextEye, this._tempNextEye, this._tempVec3);
|
|
2656
2955
|
}
|
|
2657
|
-
vec3.sub(this._tempNextDirection, this.
|
|
2658
|
-
const nextLength = this._tempNextDirection
|
|
2956
|
+
vec3.sub(this._tempNextDirection, this._target, this._tempNextEye);
|
|
2957
|
+
const nextLength = vec3.len(this._tempNextDirection);
|
|
2659
2958
|
vec3.normalize(this._tempNextDirection, this._tempNextDirection);
|
|
2660
2959
|
vec3.sub(this._tempVec3, this._tempNextDirection, this._tempDirection);
|
|
2661
2960
|
const lenSq = vec3.sqrLen(this._tempVec3);
|
|
2662
2961
|
if (nextLength < this._coreCamera.nearPlane || nextLength > this._coreCamera.farPlane || lenSq > 0.01) {
|
|
2663
2962
|
return;
|
|
2664
2963
|
}
|
|
2665
|
-
vec3.copy(this.
|
|
2666
|
-
this.
|
|
2964
|
+
vec3.copy(this._eye, this._tempNextEye);
|
|
2965
|
+
this._syncFromTransform();
|
|
2667
2966
|
}
|
|
2668
2967
|
/** @inheritDoc */
|
|
2669
2968
|
update(time) {
|
|
@@ -2681,6 +2980,7 @@ class OrbitCamera {
|
|
|
2681
2980
|
this._handleMouseForwardBackwardMovement(mouseState, deltaTime);
|
|
2682
2981
|
}
|
|
2683
2982
|
}
|
|
2983
|
+
this._coreCamera.setTarget(this._target);
|
|
2684
2984
|
this._coreCamera.update(time);
|
|
2685
2985
|
}
|
|
2686
2986
|
/** @inheritDoc */
|
|
@@ -2689,12 +2989,11 @@ class OrbitCamera {
|
|
|
2689
2989
|
}
|
|
2690
2990
|
}
|
|
2691
2991
|
class OrthographicCamera {
|
|
2692
|
-
static UP_VECTOR = vec3.fromValues(0, 1, 0);
|
|
2693
2992
|
_framework;
|
|
2694
2993
|
/** @ts-ignore */
|
|
2695
2994
|
_zSpaceLength;
|
|
2696
|
-
|
|
2697
|
-
|
|
2995
|
+
_lastWorld = mat4.fromValues(NaN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
|
2996
|
+
_direction = vec3.create();
|
|
2698
2997
|
_left;
|
|
2699
2998
|
_right;
|
|
2700
2999
|
_top;
|
|
@@ -2705,9 +3004,49 @@ class OrthographicCamera {
|
|
|
2705
3004
|
_projectionMatrix = mat4.create();
|
|
2706
3005
|
_viewMatrix = mat4.create();
|
|
2707
3006
|
_projectionViewMatrix = mat4.create();
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
3007
|
+
/**
|
|
3008
|
+
* The camera transform: the single source of the view. The camera looks down its local -Z axis;
|
|
3009
|
+
* the view matrix is `inverse(T * R)` of `transform.modelMatrix` (scale is ignored).
|
|
3010
|
+
* By default, at (0, 0, 1) looking down -Z at the origin.
|
|
3011
|
+
*/
|
|
3012
|
+
transform = new TransformNode();
|
|
3013
|
+
/** The unit direction the camera looks in, from the transform. */
|
|
3014
|
+
get direction() {
|
|
3015
|
+
return CameraTransformUtilities.forwardFromWorld(this._direction, this.transform.modelMatrix);
|
|
3016
|
+
}
|
|
3017
|
+
_aim = new CameraAim(() => this.transform);
|
|
3018
|
+
/**
|
|
3019
|
+
* Rotates the transform once so the camera looks at a world point, using the current up ({@link getUp}).
|
|
3020
|
+
* Forgets the target stored by {@link setTarget}, so a later {@link setEye} does not re-aim.
|
|
3021
|
+
* @param target The point to look at.
|
|
3022
|
+
*/
|
|
3023
|
+
lookAt(target) {
|
|
3024
|
+
this._aim.lookAt(target);
|
|
3025
|
+
}
|
|
3026
|
+
/** @inheritDoc */
|
|
3027
|
+
setEye(eye) {
|
|
3028
|
+
this._aim.setEye(eye);
|
|
3029
|
+
}
|
|
3030
|
+
/** @inheritDoc */
|
|
3031
|
+
getEye(out) {
|
|
3032
|
+
return this._aim.getEye(out);
|
|
3033
|
+
}
|
|
3034
|
+
/** @inheritDoc */
|
|
3035
|
+
setTarget(target) {
|
|
3036
|
+
this._aim.setTarget(target);
|
|
3037
|
+
}
|
|
3038
|
+
/** @inheritDoc */
|
|
3039
|
+
getTarget(out) {
|
|
3040
|
+
return this._aim.getTarget(out);
|
|
3041
|
+
}
|
|
3042
|
+
/** @inheritDoc */
|
|
3043
|
+
setUp(up) {
|
|
3044
|
+
this._aim.setUp(up);
|
|
3045
|
+
}
|
|
3046
|
+
/** @inheritDoc */
|
|
3047
|
+
getUp(out) {
|
|
3048
|
+
return this._aim.getUp(out);
|
|
3049
|
+
}
|
|
2711
3050
|
_projectionBuffer = null;
|
|
2712
3051
|
_viewBuffer = null;
|
|
2713
3052
|
_projectionViewBuffer = null;
|
|
@@ -2732,8 +3071,7 @@ class OrthographicCamera {
|
|
|
2732
3071
|
this._bottom = bottom;
|
|
2733
3072
|
this._near = near;
|
|
2734
3073
|
this._far = far;
|
|
2735
|
-
this.
|
|
2736
|
-
this._target = vec3.fromValues(0, 0, 0);
|
|
3074
|
+
vec3.set(this.transform.position, 0, 0, 1);
|
|
2737
3075
|
this._zSpaceLength = 2;
|
|
2738
3076
|
this._updateMatrices();
|
|
2739
3077
|
}
|
|
@@ -2804,17 +3142,6 @@ class OrthographicCamera {
|
|
|
2804
3142
|
this._isDirty = true;
|
|
2805
3143
|
}
|
|
2806
3144
|
/** @inheritDoc */
|
|
2807
|
-
get eye() {
|
|
2808
|
-
return this._eye;
|
|
2809
|
-
}
|
|
2810
|
-
/** @inheritDoc */
|
|
2811
|
-
set eye(value) {
|
|
2812
|
-
if (this._eye === value)
|
|
2813
|
-
return;
|
|
2814
|
-
this._eye = value;
|
|
2815
|
-
this._isDirty = true;
|
|
2816
|
-
}
|
|
2817
|
-
/** @inheritDoc */
|
|
2818
3145
|
get projectionMatrix() {
|
|
2819
3146
|
return this._projectionMatrix;
|
|
2820
3147
|
}
|
|
@@ -2842,18 +3169,25 @@ class OrthographicCamera {
|
|
|
2842
3169
|
get positionBuffer() {
|
|
2843
3170
|
return this._positionBuffer;
|
|
2844
3171
|
}
|
|
2845
|
-
/** Writes the world
|
|
3172
|
+
/** Writes the transform's world position into the std140 position data. */
|
|
2846
3173
|
_updatePositionData() {
|
|
2847
|
-
|
|
2848
|
-
this._positionData[
|
|
2849
|
-
this._positionData[
|
|
3174
|
+
const m2 = this.transform.modelMatrix;
|
|
3175
|
+
this._positionData[0] = m2[12];
|
|
3176
|
+
this._positionData[1] = m2[13];
|
|
3177
|
+
this._positionData[2] = m2[14];
|
|
2850
3178
|
return this._positionData;
|
|
2851
3179
|
}
|
|
3180
|
+
/** True when the transform's world matrix changed since the view was last built. */
|
|
3181
|
+
_transformChanged() {
|
|
3182
|
+
return !mat4.exactEquals(this._lastWorld, this.transform.modelMatrix);
|
|
3183
|
+
}
|
|
2852
3184
|
/**
|
|
2853
3185
|
* Updates the camera matrices.
|
|
2854
3186
|
*/
|
|
2855
3187
|
_updateMatrices() {
|
|
2856
|
-
|
|
3188
|
+
const world = this.transform.modelMatrix;
|
|
3189
|
+
mat4.copy(this._lastWorld, world);
|
|
3190
|
+
CameraTransformUtilities.viewFromWorld(this._viewMatrix, world);
|
|
2857
3191
|
mat4.orthoNO(this._projectionMatrix, this._left, this._right, this._bottom, this._top, this._near, this._far);
|
|
2858
3192
|
mat4.multiply(this._projectionViewMatrix, this._projectionMatrix, this._viewMatrix);
|
|
2859
3193
|
}
|
|
@@ -2890,7 +3224,7 @@ class OrthographicCamera {
|
|
|
2890
3224
|
}
|
|
2891
3225
|
/** @inheritDoc */
|
|
2892
3226
|
update(_2) {
|
|
2893
|
-
if (!this._isDirty)
|
|
3227
|
+
if (!this._isDirty && !this._transformChanged())
|
|
2894
3228
|
return;
|
|
2895
3229
|
this.updateBuffers();
|
|
2896
3230
|
this._isDirty = false;
|
|
@@ -2975,6 +3309,25 @@ class ContentConfig {
|
|
|
2975
3309
|
*/
|
|
2976
3310
|
keepDataCached = false;
|
|
2977
3311
|
}
|
|
3312
|
+
var CullMode = /* @__PURE__ */ ((CullMode2) => {
|
|
3313
|
+
CullMode2[CullMode2["NONE"] = 0] = "NONE";
|
|
3314
|
+
CullMode2[CullMode2["BACK"] = 1] = "BACK";
|
|
3315
|
+
CullMode2[CullMode2["FRONT"] = 2] = "FRONT";
|
|
3316
|
+
return CullMode2;
|
|
3317
|
+
})(CullMode || {});
|
|
3318
|
+
var FrontFace = /* @__PURE__ */ ((FrontFace2) => {
|
|
3319
|
+
FrontFace2[FrontFace2["CW"] = 0] = "CW";
|
|
3320
|
+
FrontFace2[FrontFace2["CCW"] = 1] = "CCW";
|
|
3321
|
+
return FrontFace2;
|
|
3322
|
+
})(FrontFace || {});
|
|
3323
|
+
var PrimitiveTopology = /* @__PURE__ */ ((PrimitiveTopology2) => {
|
|
3324
|
+
PrimitiveTopology2[PrimitiveTopology2["LINE_LIST"] = 0] = "LINE_LIST";
|
|
3325
|
+
PrimitiveTopology2[PrimitiveTopology2["LINE_STRIP"] = 1] = "LINE_STRIP";
|
|
3326
|
+
PrimitiveTopology2[PrimitiveTopology2["POINT_LIST"] = 2] = "POINT_LIST";
|
|
3327
|
+
PrimitiveTopology2[PrimitiveTopology2["TRIANGLE_LIST"] = 3] = "TRIANGLE_LIST";
|
|
3328
|
+
PrimitiveTopology2[PrimitiveTopology2["TRIANGLE_STRIP"] = 4] = "TRIANGLE_STRIP";
|
|
3329
|
+
return PrimitiveTopology2;
|
|
3330
|
+
})(PrimitiveTopology || {});
|
|
2978
3331
|
class RawImageData {
|
|
2979
3332
|
/**
|
|
2980
3333
|
* The constructor.
|
|
@@ -3603,16 +3956,6 @@ class Mesh {
|
|
|
3603
3956
|
class RenderableMesh extends Mesh {
|
|
3604
3957
|
_subMeshes = [];
|
|
3605
3958
|
_parent;
|
|
3606
|
-
// Transform; only used on the root.
|
|
3607
|
-
_position = vec3.create();
|
|
3608
|
-
_rotation = vec3.create();
|
|
3609
|
-
_scale = vec3.fromValues(1, 1, 1);
|
|
3610
|
-
_modelMatrix = mat4.create();
|
|
3611
|
-
_rotationQuat = quat.create();
|
|
3612
|
-
// Cached copies to detect in-place edits; NaN forces the first computation.
|
|
3613
|
-
_lastPosition = vec3.fromValues(NaN, NaN, NaN);
|
|
3614
|
-
_lastRotation = vec3.create();
|
|
3615
|
-
_lastScale = vec3.create();
|
|
3616
3959
|
_modelBuffer;
|
|
3617
3960
|
/** The matrix last uploaded to the model buffer. */
|
|
3618
3961
|
_uploadedMatrix = mat4.create();
|
|
@@ -3622,6 +3965,14 @@ class RenderableMesh extends Mesh {
|
|
|
3622
3965
|
indexStart;
|
|
3623
3966
|
/** @inheritDoc */
|
|
3624
3967
|
indexCount;
|
|
3968
|
+
_transform = new TransformNode();
|
|
3969
|
+
/** @inheritDoc A sub mesh returns (and sets) the root's transform. */
|
|
3970
|
+
get transform() {
|
|
3971
|
+
return this._root._transform;
|
|
3972
|
+
}
|
|
3973
|
+
set transform(value) {
|
|
3974
|
+
this._root._transform = value;
|
|
3975
|
+
}
|
|
3625
3976
|
/**
|
|
3626
3977
|
* The constructor.
|
|
3627
3978
|
* @param framework The framework.
|
|
@@ -3672,45 +4023,6 @@ class RenderableMesh extends Mesh {
|
|
|
3672
4023
|
get _defaultGeometryFormat() {
|
|
3673
4024
|
return this.material?.geometryFormat;
|
|
3674
4025
|
}
|
|
3675
|
-
/** @inheritDoc */
|
|
3676
|
-
get position() {
|
|
3677
|
-
return this._root._position;
|
|
3678
|
-
}
|
|
3679
|
-
set position(value) {
|
|
3680
|
-
this._root._position = value;
|
|
3681
|
-
}
|
|
3682
|
-
/** @inheritDoc */
|
|
3683
|
-
get rotation() {
|
|
3684
|
-
return this._root._rotation;
|
|
3685
|
-
}
|
|
3686
|
-
set rotation(value) {
|
|
3687
|
-
this._root._rotation = value;
|
|
3688
|
-
}
|
|
3689
|
-
/** @inheritDoc */
|
|
3690
|
-
get scale() {
|
|
3691
|
-
return this._root._scale;
|
|
3692
|
-
}
|
|
3693
|
-
set scale(value) {
|
|
3694
|
-
this._root._scale = value;
|
|
3695
|
-
}
|
|
3696
|
-
/** @inheritDoc */
|
|
3697
|
-
get modelMatrix() {
|
|
3698
|
-
const root = this._root;
|
|
3699
|
-
if (root !== this) {
|
|
3700
|
-
return root.modelMatrix;
|
|
3701
|
-
}
|
|
3702
|
-
if (!vec3.exactEquals(this._lastPosition, this._position) || !vec3.exactEquals(this._lastRotation, this._rotation) || !vec3.exactEquals(this._lastScale, this._scale)) {
|
|
3703
|
-
vec3.copy(this._lastPosition, this._position);
|
|
3704
|
-
vec3.copy(this._lastRotation, this._rotation);
|
|
3705
|
-
vec3.copy(this._lastScale, this._scale);
|
|
3706
|
-
const q = quat.identity(this._rotationQuat);
|
|
3707
|
-
quat.rotateY(q, q, this._rotation[1]);
|
|
3708
|
-
quat.rotateX(q, q, this._rotation[0]);
|
|
3709
|
-
quat.rotateZ(q, q, this._rotation[2]);
|
|
3710
|
-
mat4.fromRotationTranslationScale(this._modelMatrix, q, this._position, this._scale);
|
|
3711
|
-
}
|
|
3712
|
-
return this._modelMatrix;
|
|
3713
|
-
}
|
|
3714
4026
|
/** @inheritDoc Created on first access and disposed with the root mesh. */
|
|
3715
4027
|
get modelBuffer() {
|
|
3716
4028
|
const root = this._root;
|
|
@@ -3718,7 +4030,7 @@ class RenderableMesh extends Mesh {
|
|
|
3718
4030
|
return root.modelBuffer;
|
|
3719
4031
|
}
|
|
3720
4032
|
if (!this._modelBuffer) {
|
|
3721
|
-
mat4.copy(this._uploadedMatrix, this.modelMatrix);
|
|
4033
|
+
mat4.copy(this._uploadedMatrix, this.transform.modelMatrix);
|
|
3722
4034
|
this._modelBuffer = this._framework.bufferFactory.createUniformBuffer(
|
|
3723
4035
|
this._uploadedMatrix,
|
|
3724
4036
|
BufferUsage.UNIFORM | BufferUsage.COPY_DST,
|
|
@@ -3731,7 +4043,7 @@ class RenderableMesh extends Mesh {
|
|
|
3731
4043
|
_updateModelBuffer() {
|
|
3732
4044
|
const root = this._root;
|
|
3733
4045
|
const buffer = root.modelBuffer;
|
|
3734
|
-
const matrix = root.modelMatrix;
|
|
4046
|
+
const matrix = root.transform.modelMatrix;
|
|
3735
4047
|
if (!mat4.exactEquals(root._uploadedMatrix, matrix)) {
|
|
3736
4048
|
mat4.copy(root._uploadedMatrix, matrix);
|
|
3737
4049
|
buffer.update(root._uploadedMatrix);
|
|
@@ -4422,11 +4734,11 @@ class InspectTextureMipsMaterial {
|
|
|
4422
4734
|
this._fragmentDataBuffer.dispose();
|
|
4423
4735
|
}
|
|
4424
4736
|
}
|
|
4425
|
-
|
|
4426
|
-
|
|
4427
|
-
|
|
4428
|
-
|
|
4429
|
-
|
|
4737
|
+
function resolveUnlitMaterialDescriptor(desc) {
|
|
4738
|
+
return {
|
|
4739
|
+
primitiveState: desc?.primitiveState,
|
|
4740
|
+
camera: desc?.camera
|
|
4741
|
+
};
|
|
4430
4742
|
}
|
|
4431
4743
|
class UnlitMaterial {
|
|
4432
4744
|
_framework;
|
|
@@ -4448,16 +4760,17 @@ class UnlitMaterial {
|
|
|
4448
4760
|
/**
|
|
4449
4761
|
* The constructor.
|
|
4450
4762
|
* @param framework The framework.
|
|
4451
|
-
* @param
|
|
4763
|
+
* @param descriptor The optional material descriptor. A projection view buffer passed here is shared and is not disposed by this material.
|
|
4452
4764
|
*/
|
|
4453
|
-
constructor(framework,
|
|
4765
|
+
constructor(framework, descriptor) {
|
|
4766
|
+
const config = resolveUnlitMaterialDescriptor(descriptor);
|
|
4454
4767
|
this._framework = framework;
|
|
4455
4768
|
const usage = BufferUsage.UNIFORM | BufferUsage.COPY_DST;
|
|
4456
|
-
this._camera = config
|
|
4457
|
-
this._ownsProjectionViewBuffer = !config
|
|
4458
|
-
this._projectionViewBuffer = config
|
|
4769
|
+
this._camera = config.camera;
|
|
4770
|
+
this._ownsProjectionViewBuffer = !config.camera?.projectionViewBuffer;
|
|
4771
|
+
this._projectionViewBuffer = config.camera?.projectionViewBuffer ?? framework.bufferFactory.createUniformBuffer(mat4.create(), usage);
|
|
4459
4772
|
this._materialBuffer = framework.bufferFactory.createUniformBuffer(this._materialData, usage);
|
|
4460
|
-
this._primitiveState = config
|
|
4773
|
+
this._primitiveState = config.primitiveState;
|
|
4461
4774
|
}
|
|
4462
4775
|
/** Creates the pipeline with the current bindings. */
|
|
4463
4776
|
_createPipeline(modelBuffer) {
|
|
@@ -4595,6 +4908,8 @@ class UnlitMaterial {
|
|
|
4595
4908
|
}
|
|
4596
4909
|
}
|
|
4597
4910
|
class SpriteMaterial {
|
|
4911
|
+
/** The camera. Stored only: sprites render in screen space and use no camera buffers. */
|
|
4912
|
+
camera;
|
|
4598
4913
|
_renderPipeline;
|
|
4599
4914
|
/**
|
|
4600
4915
|
* The constructor.
|
|
@@ -4666,9 +4981,6 @@ class MaterialFactory {
|
|
|
4666
4981
|
return new ForwardBlinnPhongMaterial(this._framework, descriptor);
|
|
4667
4982
|
}
|
|
4668
4983
|
}
|
|
4669
|
-
function isCameraMaterial(material) {
|
|
4670
|
-
return !!material && "camera" in material;
|
|
4671
|
-
}
|
|
4672
4984
|
function isLightsMaterial(material) {
|
|
4673
4985
|
return !!material && "directionalLights" in material && "pointLights" in material && "ambientLight" in material;
|
|
4674
4986
|
}
|
|
@@ -4689,6 +5001,8 @@ class AmbientLight {
|
|
|
4689
5001
|
this.intensity = descriptor?.intensity ?? 1;
|
|
4690
5002
|
scene?.add(this);
|
|
4691
5003
|
}
|
|
5004
|
+
/** The transform. It has no effect on an ambient light. */
|
|
5005
|
+
transform = new TransformNode();
|
|
4692
5006
|
/** The unique id of this light. */
|
|
4693
5007
|
id;
|
|
4694
5008
|
/** The optional name for a light. */
|
|
@@ -4698,6 +5012,7 @@ class AmbientLight {
|
|
|
4698
5012
|
/** Multiplies {@link color} when written to the lights buffer. */
|
|
4699
5013
|
intensity;
|
|
4700
5014
|
}
|
|
5015
|
+
const _target = vec3.create();
|
|
4701
5016
|
class DirectionalLight {
|
|
4702
5017
|
/**
|
|
4703
5018
|
* The constructor.
|
|
@@ -4710,7 +5025,7 @@ class DirectionalLight {
|
|
|
4710
5025
|
this.name = descriptor?.name;
|
|
4711
5026
|
this.color = descriptor?.color?.copy() ?? Color.white();
|
|
4712
5027
|
this.intensity = descriptor?.intensity ?? 1;
|
|
4713
|
-
this.
|
|
5028
|
+
this.setDirection(descriptor?.direction ?? [0, -1, 0]);
|
|
4714
5029
|
scene?.add(this);
|
|
4715
5030
|
}
|
|
4716
5031
|
/** The unique id of this light. */
|
|
@@ -4721,8 +5036,25 @@ class DirectionalLight {
|
|
|
4721
5036
|
color;
|
|
4722
5037
|
/** Multiplies {@link color} when written to the lights buffer. */
|
|
4723
5038
|
intensity;
|
|
4724
|
-
/** The
|
|
4725
|
-
|
|
5039
|
+
/** The transform. Its world rotation sets the direction (forward is -Z). */
|
|
5040
|
+
transform = new TransformNode();
|
|
5041
|
+
/**
|
|
5042
|
+
* Rotates the transform so the light travels along a world-space direction (converted into the parent's space
|
|
5043
|
+
* when parented). A zero vector leaves the rotation unchanged.
|
|
5044
|
+
* @param direction The world direction; it does not need to be normalized.
|
|
5045
|
+
*/
|
|
5046
|
+
setDirection(direction) {
|
|
5047
|
+
const m2 = this.transform.modelMatrix;
|
|
5048
|
+
vec3.set(_target, m2[12] + direction[0], m2[13] + direction[1], m2[14] + direction[2]);
|
|
5049
|
+
CameraTransformUtilities.aimTransform(this.transform, _target, [0, 1, 0]);
|
|
5050
|
+
}
|
|
5051
|
+
/**
|
|
5052
|
+
* Gets the world-space direction in which the light travels (unit length), derived from the transform.
|
|
5053
|
+
* @param out The optional output vector.
|
|
5054
|
+
*/
|
|
5055
|
+
getDirection(out = vec3.create()) {
|
|
5056
|
+
return CameraTransformUtilities.forwardFromWorld(out, this.transform.modelMatrix);
|
|
5057
|
+
}
|
|
4726
5058
|
}
|
|
4727
5059
|
class PointLight {
|
|
4728
5060
|
/** The default constant attenuation. */
|
|
@@ -4742,7 +5074,7 @@ class PointLight {
|
|
|
4742
5074
|
this.name = descriptor?.name;
|
|
4743
5075
|
this.color = descriptor?.color?.copy() ?? Color.white();
|
|
4744
5076
|
this.intensity = descriptor?.intensity ?? 1;
|
|
4745
|
-
this.position
|
|
5077
|
+
vec3.copy(this.transform.position, descriptor?.position ?? [0, 0, 0]);
|
|
4746
5078
|
this.constant = descriptor?.constant ?? PointLight.DEFAULT_CONSTANT;
|
|
4747
5079
|
this.linear = descriptor?.linear ?? PointLight.DEFAULT_LINEAR;
|
|
4748
5080
|
this.quadratic = descriptor?.quadratic ?? PointLight.DEFAULT_QUADRATIC;
|
|
@@ -4756,8 +5088,23 @@ class PointLight {
|
|
|
4756
5088
|
color;
|
|
4757
5089
|
/** Multiplies {@link color} when written to the lights buffer. */
|
|
4758
5090
|
intensity;
|
|
4759
|
-
/**
|
|
4760
|
-
|
|
5091
|
+
/** The transform. Its world position is the light position. */
|
|
5092
|
+
transform = new TransformNode();
|
|
5093
|
+
/**
|
|
5094
|
+
* Moves the light to a world position (converted into the parent's space when parented).
|
|
5095
|
+
* @param position The world position.
|
|
5096
|
+
*/
|
|
5097
|
+
setPosition(position) {
|
|
5098
|
+
CameraTransformUtilities.setWorldPosition(this.transform, position);
|
|
5099
|
+
}
|
|
5100
|
+
/**
|
|
5101
|
+
* Gets the world position of the light, read from the transform.
|
|
5102
|
+
* @param out The optional output vector.
|
|
5103
|
+
*/
|
|
5104
|
+
getPosition(out = vec3.create()) {
|
|
5105
|
+
const m2 = this.transform.modelMatrix;
|
|
5106
|
+
return vec3.set(out, m2[12], m2[13], m2[14]);
|
|
5107
|
+
}
|
|
4761
5108
|
/** Constant attenuation term. */
|
|
4762
5109
|
constant;
|
|
4763
5110
|
/** Linear attenuation term. */
|
|
@@ -4816,6 +5163,7 @@ class SceneMesh {
|
|
|
4816
5163
|
}
|
|
4817
5164
|
class Scene {
|
|
4818
5165
|
_sceneMeshes = [];
|
|
5166
|
+
_nodes = [];
|
|
4819
5167
|
_directionalLights = [];
|
|
4820
5168
|
_pointLights = [];
|
|
4821
5169
|
/** The directional light slots (matches the Blinn-Phong material). */
|
|
@@ -4855,6 +5203,10 @@ class Scene {
|
|
|
4855
5203
|
get sceneMeshes() {
|
|
4856
5204
|
return this._sceneMeshes;
|
|
4857
5205
|
}
|
|
5206
|
+
/** The scene objects (anything with a transform, including root meshes), in the order they were added. */
|
|
5207
|
+
get nodes() {
|
|
5208
|
+
return this._nodes;
|
|
5209
|
+
}
|
|
4858
5210
|
/** The root meshes in this scene, in the order they were added. */
|
|
4859
5211
|
get meshes() {
|
|
4860
5212
|
return this._sceneMeshes.map((s2) => s2.mesh);
|
|
@@ -4879,23 +5231,32 @@ class Scene {
|
|
|
4879
5231
|
this._activeAmbientLight = value;
|
|
4880
5232
|
}
|
|
4881
5233
|
/**
|
|
4882
|
-
|
|
4883
|
-
|
|
4884
|
-
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
|
|
4890
|
-
|
|
4891
|
-
|
|
5234
|
+
* Adds a mesh, a light or a camera. Adding an item that is already in the scene does nothing.
|
|
5235
|
+
* - Renderable mesh or {@link SceneMesh}: drawn by {@link render}; its materials get the scene camera and lights.
|
|
5236
|
+
* A mesh is wrapped in a `SceneMesh`, so {@link dispose} also disposes its materials.
|
|
5237
|
+
* The mesh is also added to {@link nodes}.
|
|
5238
|
+
* - {@link ISceneObject} (anything with a `transform`): added to {@link nodes}; {@link update} updates its transform.
|
|
5239
|
+
* - Lights are also added to {@link nodes} (they are scene objects).
|
|
5240
|
+
* - Ambient light: added to {@link ambientLights} (use {@link activeAmbientLight} to make it the lit one).
|
|
5241
|
+
* - Directional / point light: added to {@link directionalLights} / {@link pointLights}.
|
|
5242
|
+
* - Camera: becomes the scene {@link camera} and is added to {@link nodes} (cameras are scene objects).
|
|
5243
|
+
* Checked before the generic scene object case.
|
|
5244
|
+
* Constructors given a scene (lights, the perspective camera) call this themselves.
|
|
5245
|
+
* @param item The item to add.
|
|
5246
|
+
* @throws Error when all slots for a light kind are in use (3 directional, 5 point), or for an unsupported item.
|
|
5247
|
+
*/
|
|
4892
5248
|
add(item) {
|
|
4893
5249
|
if (item instanceof AmbientLight) {
|
|
4894
5250
|
this._addAmbientLight(item);
|
|
5251
|
+
this._addNode(item);
|
|
4895
5252
|
} else if (item instanceof DirectionalLight || item instanceof PointLight) {
|
|
4896
5253
|
this._addLight(item);
|
|
5254
|
+
this._addNode(item);
|
|
4897
5255
|
} else if (Scene._isCamera(item)) {
|
|
4898
5256
|
this.camera = item;
|
|
5257
|
+
if (Scene._isSceneObject(item)) {
|
|
5258
|
+
this._addNode(item);
|
|
5259
|
+
}
|
|
4899
5260
|
} else if (item instanceof SceneMesh || Scene._isMesh(item)) {
|
|
4900
5261
|
const mesh = item instanceof SceneMesh ? item.mesh : item;
|
|
4901
5262
|
if (!this._sceneMeshes.some((s2) => s2.mesh === mesh)) {
|
|
@@ -4903,15 +5264,18 @@ class Scene {
|
|
|
4903
5264
|
this._sceneMeshes.push(sceneMesh);
|
|
4904
5265
|
this._bind(sceneMesh);
|
|
4905
5266
|
}
|
|
5267
|
+
this._addNode(mesh);
|
|
5268
|
+
} else if (Scene._isSceneObject(item)) {
|
|
5269
|
+
this._addNode(item);
|
|
4906
5270
|
} else {
|
|
4907
|
-
throw new Error("Scene.add: expected a mesh, an AmbientLight, DirectionalLight, PointLight or a camera.");
|
|
5271
|
+
throw new Error("Scene.add: expected a mesh, a scene object, an AmbientLight, DirectionalLight, PointLight or a camera.");
|
|
4908
5272
|
}
|
|
4909
5273
|
}
|
|
4910
5274
|
/**
|
|
4911
5275
|
* Removes a mesh (or scene mesh), a light or a camera. The mesh and its materials are not disposed.
|
|
4912
5276
|
* Removing the active camera clears {@link camera}.
|
|
4913
5277
|
* @param item The item to remove.
|
|
4914
|
-
* @returns True when the item was in the scene
|
|
5278
|
+
* @returns True when the item was in the scene.
|
|
4915
5279
|
* @throws Error when removing the active ambient light (set another {@link activeAmbientLight} first), or for an unsupported item.
|
|
4916
5280
|
*/
|
|
4917
5281
|
remove(item) {
|
|
@@ -4919,14 +5283,17 @@ class Scene {
|
|
|
4919
5283
|
if (item === this._activeAmbientLight) {
|
|
4920
5284
|
throw new Error("Scene.remove: cannot remove the active ambient light; set scene.activeAmbientLight to another light first.");
|
|
4921
5285
|
}
|
|
5286
|
+
Scene._removeFrom(this._nodes, item);
|
|
4922
5287
|
return Scene._removeFrom(this.ambientLights, item);
|
|
4923
5288
|
}
|
|
4924
5289
|
if (item instanceof DirectionalLight || item instanceof PointLight) {
|
|
5290
|
+
Scene._removeFrom(this._nodes, item);
|
|
4925
5291
|
return item instanceof DirectionalLight ? Scene._removeFrom(this._directionalLights, item) : Scene._removeFrom(this._pointLights, item);
|
|
4926
5292
|
}
|
|
4927
5293
|
if (Scene._isCamera(item)) {
|
|
5294
|
+
const wasNode = Scene._removeFrom(this._nodes, item);
|
|
4928
5295
|
if (item !== this._activeCamera) {
|
|
4929
|
-
return
|
|
5296
|
+
return wasNode;
|
|
4930
5297
|
}
|
|
4931
5298
|
this._activeCamera = void 0;
|
|
4932
5299
|
return true;
|
|
@@ -4934,13 +5301,17 @@ class Scene {
|
|
|
4934
5301
|
if (item instanceof SceneMesh || Scene._isMesh(item)) {
|
|
4935
5302
|
const mesh = item instanceof SceneMesh ? item.mesh : item;
|
|
4936
5303
|
const index = this._sceneMeshes.findIndex((s2) => s2.mesh === mesh);
|
|
5304
|
+
Scene._removeFrom(this._nodes, mesh);
|
|
4937
5305
|
if (index < 0) {
|
|
4938
5306
|
return false;
|
|
4939
5307
|
}
|
|
4940
5308
|
this._sceneMeshes.splice(index, 1);
|
|
4941
5309
|
return true;
|
|
4942
5310
|
}
|
|
4943
|
-
|
|
5311
|
+
if (Scene._isSceneObject(item)) {
|
|
5312
|
+
return Scene._removeFrom(this._nodes, item);
|
|
5313
|
+
}
|
|
5314
|
+
throw new Error("Scene.remove: expected a mesh, a scene object, an AmbientLight, DirectionalLight, PointLight or a camera.");
|
|
4944
5315
|
}
|
|
4945
5316
|
/**
|
|
4946
5317
|
* Adds a directional or point light.
|
|
@@ -4986,18 +5357,30 @@ class Scene {
|
|
|
4986
5357
|
const camera = item;
|
|
4987
5358
|
return typeof camera === "object" && camera !== null && "projectionViewBuffer" in camera && "viewMatrix" in camera && typeof camera.updateBuffers === "function";
|
|
4988
5359
|
}
|
|
5360
|
+
/** Scene objects have a TransformNode as transform. */
|
|
5361
|
+
static _isSceneObject(item) {
|
|
5362
|
+
return typeof item === "object" && item !== null && item.transform instanceof TransformNode;
|
|
5363
|
+
}
|
|
5364
|
+
_addNode(node) {
|
|
5365
|
+
if (!this._nodes.includes(node)) {
|
|
5366
|
+
this._nodes.push(node);
|
|
5367
|
+
}
|
|
5368
|
+
}
|
|
4989
5369
|
/** Renderable meshes have render() and sub meshes. */
|
|
4990
5370
|
static _isMesh(item) {
|
|
4991
5371
|
const mesh = item;
|
|
4992
5372
|
return typeof mesh === "object" && mesh !== null && typeof mesh.render === "function" && "subMeshes" in mesh;
|
|
4993
5373
|
}
|
|
4994
5374
|
/**
|
|
4995
|
-
* Updates the scene: assigns {@link camera}, the active ambient light and the light lists to the mesh materials.
|
|
5375
|
+
* Updates the scene: updates the transforms of {@link nodes}, assigns {@link camera}, the active ambient light and the light lists to the mesh materials.
|
|
4996
5376
|
* Each lights material uploads its lights buffer when drawn, only if the lights changed.
|
|
4997
5377
|
* @param _time The game time.
|
|
4998
5378
|
* @public
|
|
4999
5379
|
*/
|
|
5000
5380
|
update(_time) {
|
|
5381
|
+
for (const node of this._nodes) {
|
|
5382
|
+
node.transform.update(_time);
|
|
5383
|
+
}
|
|
5001
5384
|
for (const sceneMesh of this._sceneMeshes) {
|
|
5002
5385
|
this._bind(sceneMesh);
|
|
5003
5386
|
}
|
|
@@ -5026,7 +5409,7 @@ class Scene {
|
|
|
5026
5409
|
return;
|
|
5027
5410
|
}
|
|
5028
5411
|
for (const material of sceneMesh.materials) {
|
|
5029
|
-
if (
|
|
5412
|
+
if (material.camera !== camera) {
|
|
5030
5413
|
material.camera = camera;
|
|
5031
5414
|
}
|
|
5032
5415
|
}
|
|
@@ -5049,6 +5432,7 @@ class Scene {
|
|
|
5049
5432
|
sceneMesh.dispose();
|
|
5050
5433
|
}
|
|
5051
5434
|
this._sceneMeshes.length = 0;
|
|
5435
|
+
this._nodes.length = 0;
|
|
5052
5436
|
}
|
|
5053
5437
|
}
|
|
5054
5438
|
var Key = /* @__PURE__ */ ((Key2) => {
|
|
@@ -5324,6 +5708,7 @@ class CpuImageProcessor {
|
|
|
5324
5708
|
return promise;
|
|
5325
5709
|
}
|
|
5326
5710
|
}
|
|
5711
|
+
const _v = vec3.create();
|
|
5327
5712
|
class WebGlLightsBuffer {
|
|
5328
5713
|
/** Floats for the ambient light: vec3 padded to 16 bytes. */
|
|
5329
5714
|
static AMBIENT_FLOAT_COUNT = 4;
|
|
@@ -5465,9 +5850,14 @@ class WebGlLightsBuffer {
|
|
|
5465
5850
|
const light = this._directionalLights[i2];
|
|
5466
5851
|
this._writeColor(offset, light?.color, light?.intensity ?? 0);
|
|
5467
5852
|
this._data[offset + 3] = 0;
|
|
5468
|
-
|
|
5469
|
-
|
|
5470
|
-
|
|
5853
|
+
if (light) {
|
|
5854
|
+
light.getDirection(_v);
|
|
5855
|
+
} else {
|
|
5856
|
+
vec3.zero(_v);
|
|
5857
|
+
}
|
|
5858
|
+
this._data[offset + 4] = _v[0];
|
|
5859
|
+
this._data[offset + 5] = _v[1];
|
|
5860
|
+
this._data[offset + 6] = _v[2];
|
|
5471
5861
|
this._data[offset + 7] = 0;
|
|
5472
5862
|
}
|
|
5473
5863
|
const pointLightsStart = WebGlLightsBuffer.AMBIENT_FLOAT_COUNT + this.maxDirectionalLights * WebGlLightsBuffer.DIRECTIONAL_LIGHT_FLOAT_COUNT;
|
|
@@ -5476,9 +5866,14 @@ class WebGlLightsBuffer {
|
|
|
5476
5866
|
const light = this._pointLights[i2];
|
|
5477
5867
|
this._writeColor(offset, light?.color, light?.intensity ?? 0);
|
|
5478
5868
|
this._data[offset + 3] = light ? light.constant : 1;
|
|
5479
|
-
|
|
5480
|
-
|
|
5481
|
-
|
|
5869
|
+
if (light) {
|
|
5870
|
+
light.getPosition(_v);
|
|
5871
|
+
} else {
|
|
5872
|
+
vec3.zero(_v);
|
|
5873
|
+
}
|
|
5874
|
+
this._data[offset + 4] = _v[0];
|
|
5875
|
+
this._data[offset + 5] = _v[1];
|
|
5876
|
+
this._data[offset + 6] = _v[2];
|
|
5482
5877
|
this._data[offset + 7] = light ? light.linear : 0;
|
|
5483
5878
|
this._data[offset + 8] = light ? light.quadratic : 0;
|
|
5484
5879
|
this._data[offset + 9] = 0;
|
|
@@ -5709,7 +6104,8 @@ function resolveTextureDescriptor(desc) {
|
|
|
5709
6104
|
label: desc?.label ?? null,
|
|
5710
6105
|
data: desc?.data,
|
|
5711
6106
|
generateMipmaps: desc?.generateMipmaps ?? false,
|
|
5712
|
-
blockSize: desc?.blockSize
|
|
6107
|
+
blockSize: desc?.blockSize,
|
|
6108
|
+
preferredColorSpace: desc?.preferredColorSpace
|
|
5713
6109
|
};
|
|
5714
6110
|
}
|
|
5715
6111
|
const KTX2_EXTENSION = ".ktx2";
|
|
@@ -5766,7 +6162,7 @@ class ContentManager {
|
|
|
5766
6162
|
}
|
|
5767
6163
|
return tex;
|
|
5768
6164
|
}
|
|
5769
|
-
let format = this._framework.renderer.preferredTextureFormat;
|
|
6165
|
+
let format = desc.preferredColorSpace ? desc.preferredColorSpace == ColorSpace.SRGB ? TextureFormat.RGBA_8_UNORM_SRGB : TextureFormat.RGBA_8_UNORM : this._framework.renderer.preferredTextureFormat;
|
|
5770
6166
|
if (desc.textureFormat != TextureFormat.UNDEFINED) {
|
|
5771
6167
|
format = desc.textureFormat;
|
|
5772
6168
|
}
|
|
@@ -5777,8 +6173,8 @@ class ContentManager {
|
|
|
5777
6173
|
data.baseHeight,
|
|
5778
6174
|
data.getData(0),
|
|
5779
6175
|
data.channels,
|
|
5780
|
-
path,
|
|
5781
|
-
TextureUsage.TEXTURE_BINDING | TextureUsage.COPY_SRC,
|
|
6176
|
+
desc.label ?? path,
|
|
6177
|
+
textureDescriptor?.textureUsage ?? TextureUsage.TEXTURE_BINDING | TextureUsage.COPY_SRC,
|
|
5782
6178
|
format,
|
|
5783
6179
|
desc.generateMipmaps
|
|
5784
6180
|
);
|
|
@@ -5786,7 +6182,7 @@ class ContentManager {
|
|
|
5786
6182
|
/** @inheritDoc */
|
|
5787
6183
|
loadTexture2DFromPixels(width, height, pixels) {
|
|
5788
6184
|
const view = new Uint8Array(pixels);
|
|
5789
|
-
return this._framework.textureFactory.create(width, height, view);
|
|
6185
|
+
return this._framework.textureFactory.create(width, height, view, 4, void 0, void 0, TextureFormat.RGBA_8_UNORM);
|
|
5790
6186
|
}
|
|
5791
6187
|
/** @inheritDoc */
|
|
5792
6188
|
async loadMeshAsync(path, geometryFormat) {
|
|
@@ -5814,17 +6210,6 @@ class ContentManager {
|
|
|
5814
6210
|
});
|
|
5815
6211
|
}
|
|
5816
6212
|
}
|
|
5817
|
-
var Culling = /* @__PURE__ */ ((Culling2) => {
|
|
5818
|
-
Culling2[Culling2["None"] = 0] = "None";
|
|
5819
|
-
Culling2[Culling2["Back"] = 1] = "Back";
|
|
5820
|
-
Culling2[Culling2["Front"] = 2] = "Front";
|
|
5821
|
-
return Culling2;
|
|
5822
|
-
})(Culling || {});
|
|
5823
|
-
var ColorSpace = /* @__PURE__ */ ((ColorSpace2) => {
|
|
5824
|
-
ColorSpace2["LINEAR"] = "LINEAR";
|
|
5825
|
-
ColorSpace2["SRGB"] = "SRGB";
|
|
5826
|
-
return ColorSpace2;
|
|
5827
|
-
})(ColorSpace || {});
|
|
5828
6213
|
class ARenderer {
|
|
5829
6214
|
_framework;
|
|
5830
6215
|
/**
|
|
@@ -5838,6 +6223,7 @@ class ARenderer {
|
|
|
5838
6223
|
_swapChainRequiresResize = false;
|
|
5839
6224
|
_mainRenderPassDirty = true;
|
|
5840
6225
|
_clearColor = Color.lightPink();
|
|
6226
|
+
_colorSpace;
|
|
5841
6227
|
_mainRenderTargetRequiresResize = false;
|
|
5842
6228
|
_swapChain = null;
|
|
5843
6229
|
_mainRenderTarget = null;
|
|
@@ -5863,9 +6249,24 @@ class ARenderer {
|
|
|
5863
6249
|
throw new Error("Method not implemented.");
|
|
5864
6250
|
}
|
|
5865
6251
|
/** @inheritdoc */
|
|
5866
|
-
preferredTextureFormat
|
|
6252
|
+
get preferredTextureFormat() {
|
|
6253
|
+
return this._colorSpace == ColorSpace.SRGB ? TextureFormat.RGBA_8_UNORM_SRGB : TextureFormat.RGBA_8_UNORM;
|
|
6254
|
+
}
|
|
6255
|
+
/** @inheritDoc */
|
|
6256
|
+
get colorSpace() {
|
|
6257
|
+
return this._colorSpace;
|
|
6258
|
+
}
|
|
5867
6259
|
/** @inheritDoc */
|
|
5868
|
-
|
|
6260
|
+
set colorSpace(colorSpace) {
|
|
6261
|
+
if (colorSpace == this._colorSpace) {
|
|
6262
|
+
return;
|
|
6263
|
+
}
|
|
6264
|
+
this._colorSpace = colorSpace;
|
|
6265
|
+
if (this._mainRenderTargetPipeline) {
|
|
6266
|
+
this._mainRenderTargetPipeline.colorSpace = colorSpace;
|
|
6267
|
+
this._mainRenderTargetRequiresResize = true;
|
|
6268
|
+
}
|
|
6269
|
+
}
|
|
5869
6270
|
/** @inheritdoc */
|
|
5870
6271
|
get preferredDepthStencilFormat() {
|
|
5871
6272
|
return this._preferredDepthStencilFormat;
|
|
@@ -5899,8 +6300,7 @@ class ARenderer {
|
|
|
5899
6300
|
this._windowManager = framework.windowManager;
|
|
5900
6301
|
this._currentBackBufferSize[0] = this._windowManager.canvas.width;
|
|
5901
6302
|
this._currentBackBufferSize[1] = this._windowManager.canvas.height;
|
|
5902
|
-
this.
|
|
5903
|
-
this.preferredTextureFormat = configuration.textureColorSpace == ColorSpace.SRGB ? TextureFormat.RGBA_8_UNORM_SRGB : TextureFormat.RGBA_8_UNORM;
|
|
6303
|
+
this._colorSpace = configuration.textureColorSpace;
|
|
5904
6304
|
}
|
|
5905
6305
|
backend = RenderingBackend.WEB_GL;
|
|
5906
6306
|
/** @inheritDoc */
|
|
@@ -5958,6 +6358,7 @@ class ARenderer {
|
|
|
5958
6358
|
this.preferredDepthStencilFormat
|
|
5959
6359
|
);
|
|
5960
6360
|
this._mainRenderTargetPipeline = this._framework.renderPipelineFactory.createMainFrameBufferPipeline(this._mainRenderTarget);
|
|
6361
|
+
this._mainRenderTargetPipeline.colorSpace = this._colorSpace;
|
|
5961
6362
|
this._createMainRenderPass();
|
|
5962
6363
|
this._mainRenderTargetRequiresResize = false;
|
|
5963
6364
|
}
|
|
@@ -7113,6 +7514,7 @@ class WebGlTextureUtilities {
|
|
|
7113
7514
|
if (useTexStorage) {
|
|
7114
7515
|
gl.texStorage2D(gl.TEXTURE_2D, mipLevels, internalFormat, baseWidth, baseHeight);
|
|
7115
7516
|
}
|
|
7517
|
+
gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
|
|
7116
7518
|
if (data && data.length > 0) {
|
|
7117
7519
|
let width = baseWidth;
|
|
7118
7520
|
let height = baseHeight;
|
|
@@ -7122,9 +7524,7 @@ class WebGlTextureUtilities {
|
|
|
7122
7524
|
if (useTexStorage) {
|
|
7123
7525
|
gl.compressedTexSubImage2D(gl.TEXTURE_2D, i2, 0, 0, width, height, internalFormat, mipLevelData, 0);
|
|
7124
7526
|
} else {
|
|
7125
|
-
|
|
7126
|
-
const alignedHeight = AlignUtilities.align(height, blockSize[1]);
|
|
7127
|
-
gl.compressedTexImage2D(gl.TEXTURE_2D, i2, internalFormat, alignedWidth, alignedHeight, 0, mipLevelData, 0);
|
|
7527
|
+
gl.compressedTexImage2D(gl.TEXTURE_2D, i2, internalFormat, width, height, 0, mipLevelData, 0);
|
|
7128
7528
|
}
|
|
7129
7529
|
} else {
|
|
7130
7530
|
throw new Error("unsupported data type");
|
|
@@ -7133,6 +7533,7 @@ class WebGlTextureUtilities {
|
|
|
7133
7533
|
height = Math.max(1, Math.floor(height / 2));
|
|
7134
7534
|
}
|
|
7135
7535
|
}
|
|
7536
|
+
gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4);
|
|
7136
7537
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
7137
7538
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
7138
7539
|
if (anisotropy > 1) {
|
|
@@ -8034,6 +8435,13 @@ class AGraphicsDevice {
|
|
|
8034
8435
|
this._defaultBlendState.dispose();
|
|
8035
8436
|
}
|
|
8036
8437
|
}
|
|
8438
|
+
function resolvePrimitiveStateDescriptor(desc) {
|
|
8439
|
+
return {
|
|
8440
|
+
topology: desc?.topology ?? PrimitiveTopology.TRIANGLE_LIST,
|
|
8441
|
+
cullFace: desc?.cullFace ?? CullMode.BACK,
|
|
8442
|
+
frontFace: desc?.frontFace ?? FrontFace.CCW
|
|
8443
|
+
};
|
|
8444
|
+
}
|
|
8037
8445
|
class WebGlPrimitiveState {
|
|
8038
8446
|
_cullingEnabled;
|
|
8039
8447
|
_glPrimitiveType;
|
|
@@ -8042,12 +8450,13 @@ class WebGlPrimitiveState {
|
|
|
8042
8450
|
/**
|
|
8043
8451
|
* The constructor.
|
|
8044
8452
|
* @param _gl The WebGL2 Rendering Context.
|
|
8045
|
-
* @param descriptor The descriptor of the primitive state.
|
|
8453
|
+
* @param descriptor The descriptor of the primitive state; missing fields use the defaults.
|
|
8046
8454
|
*/
|
|
8047
8455
|
constructor(_gl, descriptor) {
|
|
8048
|
-
|
|
8049
|
-
this.
|
|
8050
|
-
this.
|
|
8456
|
+
const resolved = resolvePrimitiveStateDescriptor(descriptor);
|
|
8457
|
+
this.topology = resolved.topology;
|
|
8458
|
+
this.cullFace = resolved.cullFace;
|
|
8459
|
+
this.frontFace = resolved.frontFace;
|
|
8051
8460
|
this._cullingEnabled = this.cullFace != CullMode.NONE;
|
|
8052
8461
|
this._glPrimitiveType = WebGlConverter.convertPrimitiveType(this.topology);
|
|
8053
8462
|
this._glCullFace = WebGlConverter.convertCullFace(this.cullFace);
|
|
@@ -8281,7 +8690,6 @@ class WebGlGraphicsDevice extends AGraphicsDevice {
|
|
|
8281
8690
|
}
|
|
8282
8691
|
/** @inheritdoc */
|
|
8283
8692
|
createPrimitiveState(descriptor) {
|
|
8284
|
-
descriptor = descriptor ?? new PrimitiveStateDescriptor();
|
|
8285
8693
|
return new WebGlPrimitiveState(this._gl, descriptor);
|
|
8286
8694
|
}
|
|
8287
8695
|
}
|
|
@@ -8986,28 +9394,28 @@ class WebGlTextureFactory {
|
|
|
8986
9394
|
let transcodeFormat = m.NO_SELECTION;
|
|
8987
9395
|
let textureFormat = desc.textureFormat;
|
|
8988
9396
|
const gpuFeatures = this._framework.graphicsDevice.features;
|
|
8989
|
-
const
|
|
8990
|
-
const
|
|
9397
|
+
const preferSrgb = (descriptor?.preferredColorSpace ?? this._framework.renderer.colorSpace) == ColorSpace.SRGB;
|
|
9398
|
+
const userSpecifiedTextureFormat = desc.textureFormat != TextureFormat.UNDEFINED;
|
|
8991
9399
|
if (ktxTexture.needsTranscoding && vkFormat == n.UNDEFINED) {
|
|
8992
9400
|
if (desc.textureFormat == TextureFormat.UNDEFINED) {
|
|
8993
9401
|
if (gpuFeatures.supportsTextureCompressionBC) {
|
|
8994
9402
|
transcodeFormat = m.BC7_RGBA;
|
|
8995
|
-
textureFormat =
|
|
9403
|
+
textureFormat = preferSrgb ? TextureFormat.BC7_RGBA_SRGB : TextureFormat.BC7_RGBA_UNORM;
|
|
8996
9404
|
} else if (gpuFeatures.supportsTextureCompressionASTC) {
|
|
8997
9405
|
transcodeFormat = m.ASTC_4X4_RGBA;
|
|
8998
|
-
textureFormat =
|
|
9406
|
+
textureFormat = preferSrgb ? TextureFormat.ASTC_4X4_RGBA_SRGB : TextureFormat.ASTC_4X4_RGBA_UNORM;
|
|
8999
9407
|
} else if (gpuFeatures.supportsTextureCompressionS3TC) {
|
|
9000
9408
|
transcodeFormat = m.BC3_RGBA;
|
|
9001
|
-
textureFormat =
|
|
9409
|
+
textureFormat = preferSrgb ? TextureFormat.BC3_RGBA_SRGB : TextureFormat.BC3_RGBA_UNORM;
|
|
9002
9410
|
} else if (gpuFeatures.supportsTextureCompressionETC2) {
|
|
9003
9411
|
transcodeFormat = m.ETC2_RGBA;
|
|
9004
|
-
textureFormat =
|
|
9412
|
+
textureFormat = preferSrgb ? TextureFormat.ETC2_RGBA8_SRGB : TextureFormat.ETC2_RGBA8_UNORM;
|
|
9005
9413
|
} else if (gpuFeatures.supportsTextureCompressionPVRTC) {
|
|
9006
9414
|
transcodeFormat = m.PVRTC1_4_RGBA;
|
|
9007
9415
|
textureFormat = TextureFormat.PVRTC_4BPPV1_RGBA;
|
|
9008
9416
|
} else {
|
|
9009
9417
|
transcodeFormat = m.RGBA32;
|
|
9010
|
-
textureFormat =
|
|
9418
|
+
textureFormat = preferSrgb ? TextureFormat.RGBA_8_UNORM_SRGB : TextureFormat.RGBA_8_UNORM;
|
|
9011
9419
|
}
|
|
9012
9420
|
} else {
|
|
9013
9421
|
transcodeFormat = TextureUtilities.convertTextureFormatToKtxTranscodeFormat(textureFormat);
|
|
@@ -9015,10 +9423,14 @@ class WebGlTextureFactory {
|
|
|
9015
9423
|
ktxTexture.transcodeBasis(transcodeFormat, i.HIGH_QUALITY);
|
|
9016
9424
|
} else {
|
|
9017
9425
|
textureFormat = TextureUtilities.convertVkFormatToTextureFormat(vkFormat);
|
|
9018
|
-
if (
|
|
9019
|
-
textureFormat = TextureUtilities.
|
|
9020
|
-
} else
|
|
9021
|
-
|
|
9426
|
+
if (userSpecifiedTextureFormat) {
|
|
9427
|
+
textureFormat = TextureUtilities.resolveExplicitFormat(textureFormat, desc.textureFormat);
|
|
9428
|
+
} else {
|
|
9429
|
+
if (preferSrgb && !TextureUtilities.isSrgbFormat(textureFormat)) {
|
|
9430
|
+
textureFormat = TextureUtilities.convertToSrgbVariant(textureFormat);
|
|
9431
|
+
} else if (!preferSrgb && TextureUtilities.isSrgbFormat(textureFormat)) {
|
|
9432
|
+
textureFormat = TextureUtilities.convertToLinearVariant(textureFormat);
|
|
9433
|
+
}
|
|
9022
9434
|
}
|
|
9023
9435
|
}
|
|
9024
9436
|
const blockSize = ktxTexture.getTextureFormatInfo(ktxTexture.vkFormat);
|
|
@@ -9042,7 +9454,10 @@ class WebGlTextureFactory {
|
|
|
9042
9454
|
return texture;
|
|
9043
9455
|
}
|
|
9044
9456
|
/** @inheritdoc */
|
|
9045
|
-
create(width, height, data, channels = 4, label = null, textureUsage = TextureUsage.COPY_DST | TextureUsage.TEXTURE_BINDING, textureFormat = TextureFormat.
|
|
9457
|
+
create(width, height, data, channels = 4, label = null, textureUsage = TextureUsage.COPY_DST | TextureUsage.TEXTURE_BINDING, textureFormat = TextureFormat.UNDEFINED, useMipMaps = false) {
|
|
9458
|
+
if (textureFormat == TextureFormat.UNDEFINED) {
|
|
9459
|
+
textureFormat = this._framework.renderer.preferredTextureFormat;
|
|
9460
|
+
}
|
|
9046
9461
|
if (!data) {
|
|
9047
9462
|
throw new Error("Data must not be null.");
|
|
9048
9463
|
}
|
|
@@ -9282,6 +9697,7 @@ class WebGlMainRenderTargetRenderPipeline extends AWebGlRenderPipeline {
|
|
|
9282
9697
|
_indexBuffer = null;
|
|
9283
9698
|
_mainRenderTarget = null;
|
|
9284
9699
|
_colorConversionUniformLocation = null;
|
|
9700
|
+
/** The shader's `u_colorConversion`: 1 encodes linear to sRGB on output, 0 passes through. */
|
|
9285
9701
|
_colorSpaceValue = 0;
|
|
9286
9702
|
/**
|
|
9287
9703
|
* The constructor.
|
|
@@ -9295,6 +9711,16 @@ class WebGlMainRenderTargetRenderPipeline extends AWebGlRenderPipeline {
|
|
|
9295
9711
|
this._colorSpaceValue = 1;
|
|
9296
9712
|
}
|
|
9297
9713
|
}
|
|
9714
|
+
/**
|
|
9715
|
+
* The color space. With SRGB the main render target is sRGB (sampled back as linear) and the shader
|
|
9716
|
+
* encodes to sRGB for the screen; with LINEAR the values are passed through. Takes effect on the next frame.
|
|
9717
|
+
*/
|
|
9718
|
+
get colorSpace() {
|
|
9719
|
+
return this._colorSpaceValue == 1 ? ColorSpace.SRGB : ColorSpace.LINEAR;
|
|
9720
|
+
}
|
|
9721
|
+
set colorSpace(value) {
|
|
9722
|
+
this._colorSpaceValue = value == ColorSpace.SRGB ? 1 : 0;
|
|
9723
|
+
}
|
|
9298
9724
|
/** @inheritDoc */
|
|
9299
9725
|
geometryFormat = GeometryFormat.POS3_COLOR4_TEXTURECOORDS2;
|
|
9300
9726
|
/** @inheritdoc */
|
|
@@ -11238,9 +11664,10 @@ class WebGpuPrimitiveState {
|
|
|
11238
11664
|
* @param descriptor The primitive state descriptor.
|
|
11239
11665
|
*/
|
|
11240
11666
|
constructor(descriptor) {
|
|
11241
|
-
|
|
11242
|
-
this.
|
|
11243
|
-
this.
|
|
11667
|
+
const resolved = resolvePrimitiveStateDescriptor(descriptor);
|
|
11668
|
+
this.topology = resolved.topology;
|
|
11669
|
+
this.cullFace = resolved.cullFace;
|
|
11670
|
+
this.frontFace = resolved.frontFace;
|
|
11244
11671
|
this.gpuTopology = WebGpuConverter.convertTopology(this.topology);
|
|
11245
11672
|
this.gpuCullMode = WebGpuConverter.convertCullMode(this.cullFace);
|
|
11246
11673
|
this.gpuFrontFace = WebGpuConverter.convertFrontFace(this.frontFace);
|
|
@@ -11372,7 +11799,7 @@ class WebGpuGraphicsDevice extends AGraphicsDevice {
|
|
|
11372
11799
|
}
|
|
11373
11800
|
/** @inheritDoc */
|
|
11374
11801
|
createPrimitiveState(descriptor) {
|
|
11375
|
-
return new WebGpuPrimitiveState(descriptor
|
|
11802
|
+
return new WebGpuPrimitiveState(descriptor);
|
|
11376
11803
|
}
|
|
11377
11804
|
/** @inheritDoc */
|
|
11378
11805
|
setupDebugCallback() {
|
|
@@ -11453,7 +11880,7 @@ class WebGpuTextureFactory {
|
|
|
11453
11880
|
throw new Error("createFromKtx2 is not implemented for WebGPU.");
|
|
11454
11881
|
}
|
|
11455
11882
|
/** @inheritDoc */
|
|
11456
|
-
create(width, height, data, channels = 4, label = null, textureUsage = TextureUsage.COPY_DST | TextureUsage.TEXTURE_BINDING, textureFormat = TextureFormat.
|
|
11883
|
+
create(width, height, data, channels = 4, label = null, textureUsage = TextureUsage.COPY_DST | TextureUsage.TEXTURE_BINDING, textureFormat = TextureFormat.UNDEFINED, useMipMaps = false) {
|
|
11457
11884
|
if (!data) {
|
|
11458
11885
|
throw new Error("Data must not be null.");
|
|
11459
11886
|
}
|
|
@@ -11647,6 +12074,10 @@ class WebGpuMainRenderTargetRenderPipeline extends AWebGpuRenderPipeline {
|
|
|
11647
12074
|
this._graphicsDevice.swapChain?.textureFormat ?? this._framework.renderer.preferredTextureFormat
|
|
11648
12075
|
);
|
|
11649
12076
|
}
|
|
12077
|
+
/**
|
|
12078
|
+
* The color space. Stored only; it has no effect on WebGPU yet.
|
|
12079
|
+
*/
|
|
12080
|
+
colorSpace = ColorSpace.LINEAR;
|
|
11650
12081
|
_getBindGroup() {
|
|
11651
12082
|
if (!this._bindGroup) {
|
|
11652
12083
|
this._bindGroup = this._graphicsDevice.device.createBindGroup({
|
|
@@ -12371,7 +12802,7 @@ class Framework {
|
|
|
12371
12802
|
textureFiltering: this._configuration.textureFiltering ?? TextureSamplerFilteringPreset.BILINEAR,
|
|
12372
12803
|
alpha: this._configuration.alpha ?? false,
|
|
12373
12804
|
powerPreference: this._configuration.powerPreference ?? PowerPreferenceType.DEFAULT,
|
|
12374
|
-
textureColorSpace: this._configuration.textureColorSpace ?? ColorSpace.
|
|
12805
|
+
textureColorSpace: this._configuration.textureColorSpace ?? ColorSpace.LINEAR
|
|
12375
12806
|
};
|
|
12376
12807
|
let backend = this._configuration.renderingBackend ?? RenderingBackend.WEB_GL;
|
|
12377
12808
|
if (backend === RenderingBackend.DEFAULT) {
|
|
@@ -12602,9 +13033,11 @@ export {
|
|
|
12602
13033
|
Button,
|
|
12603
13034
|
CameraFactory,
|
|
12604
13035
|
Color,
|
|
13036
|
+
ColorSpace,
|
|
12605
13037
|
ContentConfig,
|
|
12606
13038
|
CpuImageProcessor,
|
|
12607
13039
|
CullMode,
|
|
13040
|
+
Culling,
|
|
12608
13041
|
DEFAULT_DIRECTIONAL_LIGHTS_COUNT,
|
|
12609
13042
|
DEFAULT_POINT_LIGHTS_COUNT,
|
|
12610
13043
|
DirectionalLight,
|
|
@@ -12633,6 +13066,7 @@ export {
|
|
|
12633
13066
|
MipMapSamplerFilter,
|
|
12634
13067
|
MouseButton,
|
|
12635
13068
|
MouseState,
|
|
13069
|
+
Node,
|
|
12636
13070
|
ObjLoader,
|
|
12637
13071
|
ObjMaterialDefinition,
|
|
12638
13072
|
ObjParser,
|
|
@@ -12641,7 +13075,6 @@ export {
|
|
|
12641
13075
|
PerspectiveCamera,
|
|
12642
13076
|
PointLight,
|
|
12643
13077
|
PowerPreferenceType,
|
|
12644
|
-
PrimitiveStateDescriptor,
|
|
12645
13078
|
PrimitiveTopology,
|
|
12646
13079
|
QuadMesh,
|
|
12647
13080
|
RawImageData,
|
|
@@ -12673,12 +13106,11 @@ export {
|
|
|
12673
13106
|
TouchLocation,
|
|
12674
13107
|
TouchLocationState,
|
|
12675
13108
|
TouchPanelCapabilities,
|
|
13109
|
+
TransformNode,
|
|
12676
13110
|
UnlitMaterial,
|
|
12677
|
-
UnlitMaterialDescriptor,
|
|
12678
13111
|
VertexAttribute,
|
|
12679
13112
|
VertexFormat,
|
|
12680
13113
|
VertexStepMode,
|
|
12681
13114
|
WindowBounds,
|
|
12682
|
-
isCameraMaterial,
|
|
12683
13115
|
isLightsMaterial
|
|
12684
13116
|
};
|