diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index cd0ca280ec4..00000000000 --- a/.eslintignore +++ /dev/null @@ -1,23 +0,0 @@ -Apps/HelloWorld.html -Apps/Sandcastle/ThirdParty/** -Build/** -Documentation/** -Source/** -Specs/jasmine/** -ThirdParty/** -Tools/** -Apps/Sandcastle/jsHintOptions.js -Apps/Sandcastle/gallery/gallery-index.js -index.html -index.release.html - - -# packages/engine -packages/engine/Build/** -packages/engine/Source/Scene/GltfPipeline/** -packages/engine/Source/Shaders/** -packages/engine/Source/ThirdParty/** - -# packages/widgets -packages/widgets/Build/** -packages/widgets/Source/ThirdParty/** \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 1468218cac6..00000000000 --- a/.eslintrc.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "extends": [ - "cesium/node" - ] -} diff --git a/.github/actions/check-for-CLA/.gitignore b/.github/actions/check-for-CLA/.gitignore new file mode 100644 index 00000000000..25c8fdbaba6 --- /dev/null +++ b/.github/actions/check-for-CLA/.gitignore @@ -0,0 +1,2 @@ +node_modules +package-lock.json \ No newline at end of file diff --git a/.github/actions/check-for-CLA/index.js b/.github/actions/check-for-CLA/index.js index e1ee29e17d2..56ece7b8e03 100644 --- a/.github/actions/check-for-CLA/index.js +++ b/.github/actions/check-for-CLA/index.js @@ -2,6 +2,8 @@ import { Octokit } from "@octokit/core"; import { google } from "googleapis"; import Handlebars from "handlebars"; import fs from "fs-extra"; +import { dirname, join } from "path"; +import { fileURLToPath } from "url"; const PULL_REQUST_INFO = { id: process.env.PULL_REQUEST_ID, @@ -20,30 +22,26 @@ const GOOGLE_SHEETS_INFO = { const CONTRIBUTORS_URL = "https://github.com/CesiumGS/cesium/blob/main/CONTRIBUTORS.md"; -const main = async () => { - let hasSignedCLA; - let errorFoundOnCLACheck; +const getGoogleSheetsApiClient = async () => { + const googleConfigFilePath = "GoogleConfig.json"; + fs.writeFileSync(googleConfigFilePath, GOOGLE_SHEETS_INFO.APIKeys); - try { - hasSignedCLA = await checkIfUserHasSignedAnyCLA(); - } catch (error) { - errorFoundOnCLACheck = error.toString(); - } + const auth = new google.auth.GoogleAuth({ + keyFile: googleConfigFilePath, + scopes: ["https://www.googleapis.com/auth/spreadsheets"], + }); + const googleAuthClient = await auth.getClient(); - const response = await postCommentOnPullRequest( - hasSignedCLA, - errorFoundOnCLACheck - ); + return google.sheets({ version: "v4", auth: googleAuthClient }); }; -const checkIfUserHasSignedAnyCLA = async () => { - let foundIndividualCLA = await checkIfIndividualCLAFound(); - if (foundIndividualCLA) { - return true; - } +const getValuesFromGoogleSheet = async (sheetId, cellRanges) => { + const googleSheetsApi = await getGoogleSheetsApiClient(); - let foundCorporateCLA = await checkIfCorporateCLAFound(); - return foundCorporateCLA; + return googleSheetsApi.spreadsheets.values.get({ + spreadsheetId: sheetId, + range: cellRanges, + }); }; const checkIfIndividualCLAFound = async () => { @@ -95,26 +93,34 @@ const checkIfCorporateCLAFound = async () => { return false; }; -const getValuesFromGoogleSheet = async (sheetId, cellRanges) => { - const googleSheetsApi = await getGoogleSheetsApiClient(); +const checkIfUserHasSignedAnyCLA = async () => { + const foundIndividualCLA = await checkIfIndividualCLAFound(); + if (foundIndividualCLA) { + return true; + } - return googleSheetsApi.spreadsheets.values.get({ - spreadsheetId: sheetId, - range: cellRanges, - }); + const foundCorporateCLA = await checkIfCorporateCLAFound(); + return foundCorporateCLA; }; -const getGoogleSheetsApiClient = async () => { - const googleConfigFilePath = "GoogleConfig.json"; - fs.writeFileSync(googleConfigFilePath, GOOGLE_SHEETS_INFO.APIKeys); +const getCommentBody = (hasSignedCLA, errorFoundOnCLACheck) => { + const commentTemplate = fs.readFileSync( + join( + dirname(fileURLToPath(import.meta.url)), + "templates/pullRequestComment.hbs" + ), + "utf-8" + ); - const auth = new google.auth.GoogleAuth({ - keyFile: googleConfigFilePath, - scopes: ["https://www.googleapis.com/auth/spreadsheets"], + const getCommentFromTemplate = Handlebars.compile(commentTemplate); + const commentBody = getCommentFromTemplate({ + errorCla: errorFoundOnCLACheck, + hasCla: hasSignedCLA, + username: PULL_REQUST_INFO.username, + contributorsUrl: CONTRIBUTORS_URL, }); - const googleAuthClient = await auth.getClient(); - return google.sheets({ version: "v4", auth: googleAuthClient }); + return commentBody; }; const postCommentOnPullRequest = async (hasSignedCLA, errorFoundOnCLACheck) => { @@ -136,21 +142,17 @@ const postCommentOnPullRequest = async (hasSignedCLA, errorFoundOnCLACheck) => { ); }; -const getCommentBody = (hasSignedCLA, errorFoundOnCLACheck) => { - const commentTemplate = fs.readFileSync( - "./.github/actions/check-for-CLA/templates/pullRequestComment.hbs", - "utf-8" - ); +const main = async () => { + let hasSignedCLA; + let errorFoundOnCLACheck; - const getCommentFromTemplate = Handlebars.compile(commentTemplate); - const commentBody = getCommentFromTemplate({ - errorCla: errorFoundOnCLACheck, - hasCla: hasSignedCLA, - username: PULL_REQUST_INFO.username, - contributorsUrl: CONTRIBUTORS_URL, - }); + try { + hasSignedCLA = await checkIfUserHasSignedAnyCLA(); + } catch (error) { + errorFoundOnCLACheck = error.toString(); + } - return commentBody; + await postCommentOnPullRequest(hasSignedCLA, errorFoundOnCLACheck); }; main(); diff --git a/.github/actions/check-for-CLA/package.json b/.github/actions/check-for-CLA/package.json new file mode 100644 index 00000000000..d04d9c10a6d --- /dev/null +++ b/.github/actions/check-for-CLA/package.json @@ -0,0 +1,21 @@ +{ + "name": "@cesium/check-for-cla", + "version": "0.1.0", + "main": "index.js", + "dependencies": { + "@octokit/core": "^6.1.2", + "fs-extra": "^11.2.0", + "googleapis": "^137.1.0", + "handlebars": "^4.7.8" + }, + "type": "module", + "repository": { + "type": "git", + "url": "git+https://github.com/CesiumGS/cesium.git" + }, + "license": "Apache-2.0", + "author": { + "name": "Cesium GS, Inc.", + "url": "https://cesium.com" + } +} diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml index 79a23b3a1a2..60ffd52516e 100644 --- a/.github/workflows/cla.yml +++ b/.github/workflows/cla.yml @@ -16,9 +16,11 @@ jobs: with: node-version: '20' - name: install npm packages - run: npm install googleapis @octokit/core handlebars fs-extra + working-directory: ./.github/actions/check-for-CLA + run: npm install - name: run script - run: node .github/actions/check-for-CLA/index.js + working-directory: ./.github/actions/check-for-CLA + run: node index.js env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} PULL_REQUEST_ID: ${{ github.event.number }} diff --git a/.slackbot.yml b/.slackbot.yml index d7ef941fcb8..a5496634288 100644 --- a/.slackbot.yml +++ b/.slackbot.yml @@ -1,11 +1,11 @@ releaseSchedule: - jjspace, 4/1/2024 - - jjhembd, 5/1/2024 - - ggetz, 6/1/2024 + - ggetz, 5/1/2024 + - jjhembd, 6/1/2024 - jjspace, 7/1/2024 - - jjhembd, 8/1/2024 - - ggetz, 9/1/2024 + - ggetz, 8/1/2024 + - jjhembd, 9/1/2024 - jjspace, 10/1/2024 - - jjhembd, 11/1/2024 - - ggetz, 12/1/2024 + - ggetz, 11/1/2024 + - jjhembd, 12/1/2024 diff --git a/Apps/.eslintrc.json b/Apps/.eslintrc.json deleted file mode 100644 index e646ee82716..00000000000 --- a/Apps/.eslintrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "../packages/.eslintrc.json" -} diff --git a/Apps/Sandcastle/.eslintrc.json b/Apps/Sandcastle/.eslintrc.json deleted file mode 100644 index daf23f0bdcd..00000000000 --- a/Apps/Sandcastle/.eslintrc.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "extends": "../.eslintrc.json", - "env": { - "amd": true - }, - "globals": { - "JSON": true, - "require": true, - "console": true, - "Sandcastle": true, - "Cesium": true - }, - "parserOptions": { - "sourceType": "script" - }, - "rules": { - "no-alert": ["off"], - "no-unused-vars": ["off"] - }, - "overrides": [ - { - "files": [ - "load-cesium-es6.js" - ], - "parserOptions": { - "sourceType": "module" - } - } - ] -} diff --git a/Apps/Sandcastle/gallery/Japan Buildings.html b/Apps/Sandcastle/gallery/Japan Buildings.html new file mode 100644 index 00000000000..5534dd276bd --- /dev/null +++ b/Apps/Sandcastle/gallery/Japan Buildings.html @@ -0,0 +1,284 @@ + + +
+ + + + + +value
.
*/
-// eslint-disable-next-line es/no-math-sinh
CesiumMath.sinh = defaultValue(Math.sinh, function sinh(value) {
return (Math.exp(value) - Math.exp(-value)) / 2.0;
});
@@ -317,7 +315,6 @@ CesiumMath.sinh = defaultValue(Math.sinh, function sinh(value) {
* @param {number} value The number whose hyperbolic cosine is to be returned.
* @returns {number} The hyperbolic cosine of value
.
*/
-// eslint-disable-next-line es/no-math-cosh
CesiumMath.cosh = defaultValue(Math.cosh, function cosh(value) {
return (Math.exp(value) + Math.exp(-value)) / 2.0;
});
@@ -1034,7 +1031,6 @@ CesiumMath.logBase = function (number, base) {
* @param {number} [number] The number.
* @returns {number} The result.
*/
-// eslint-disable-next-line es/no-math-cbrt
CesiumMath.cbrt = defaultValue(Math.cbrt, function cbrt(number) {
const result = Math.pow(Math.abs(number), 1.0 / 3.0);
return number < 0.0 ? -result : result;
@@ -1047,7 +1043,6 @@ CesiumMath.cbrt = defaultValue(Math.cbrt, function cbrt(number) {
* @param {number} number The number.
* @returns {number} The result.
*/
-// eslint-disable-next-line es/no-math-log2
CesiumMath.log2 = defaultValue(Math.log2, function log2(number) {
return Math.log(number) * Math.LOG2E;
});
diff --git a/packages/engine/Source/Core/TaskProcessor.js b/packages/engine/Source/Core/TaskProcessor.js
index b69011c6817..9eca8d863e1 100644
--- a/packages/engine/Source/Core/TaskProcessor.js
+++ b/packages/engine/Source/Core/TaskProcessor.js
@@ -81,18 +81,34 @@ function urlFromScript(script) {
function createWorker(url) {
const uri = new Uri(url);
const isUri = uri.scheme().length !== 0 && uri.fragment().length === 0;
+ const moduleID = url.replace(/\.js$/, "");
const options = {};
let workerPath;
+ let crossOriginUrl;
+
+ // If we are provided a fully resolved URL, check it is cross-origin
+ // Or if provided a module ID, check the full absolute URL instead.
if (isCrossOriginUrl(url)) {
+ crossOriginUrl = url;
+ } else if (!isUri) {
+ const moduleAbsoluteUrl = buildModuleUrl(
+ `${TaskProcessor._workerModulePrefix}/${moduleID}.js`
+ );
+
+ if (isCrossOriginUrl(moduleAbsoluteUrl)) {
+ crossOriginUrl = moduleAbsoluteUrl;
+ }
+ }
+
+ if (crossOriginUrl) {
// To load cross-origin, create a shim worker from a blob URL
- const script = `importScripts("${url}");`;
+ const script = `import "${crossOriginUrl}";`;
workerPath = urlFromScript(script);
+ options.type = "module";
return new Worker(workerPath, options);
}
- const moduleID = url.replace(/\.js$/, "");
-
/* global CESIUM_WORKERS */
if (!isUri && typeof CESIUM_WORKERS !== "undefined") {
// If the workers are embedded, create a shim worker from the embedded script data
diff --git a/packages/engine/Source/Core/sampleTerrain.js b/packages/engine/Source/Core/sampleTerrain.js
index f2804b431e2..cd2f2dee82f 100644
--- a/packages/engine/Source/Core/sampleTerrain.js
+++ b/packages/engine/Source/Core/sampleTerrain.js
@@ -20,7 +20,7 @@ import defined from "./defined.js";
* @param {TerrainProvider} terrainProvider The terrain provider from which to query heights.
* @param {number} level The terrain level-of-detail from which to query terrain heights.
* @param {Cartographic[]} positions The positions to update with terrain heights.
- * @param {boolean} [rejectOnTileFail=false] If true, for a failed terrain tile request the promise will be rejected. If false, returned heights will be undefined.
+ * @param {boolean} [rejectOnTileFail=false] If true, for any failed terrain tile requests, the promise will be rejected. If false, returned heights will be undefined.
* @returns {Promise.materials
array in the glTF JSON
+ * @param {FrameState} frameState
+ * @returns {ModelComponents.Material}
+ * @private
+ */
+function loadMaterial(loader, gltfMaterial, frameState) {
const material = new Material();
const extensions = defaultValue(
@@ -1505,82 +1642,43 @@ function loadMaterial(
defaultValue.EMPTY_OBJECT
);
const pbrSpecularGlossiness = extensions.KHR_materials_pbrSpecularGlossiness;
+ const pbrSpecular = extensions.KHR_materials_specular;
+ const pbrAnisotropy = extensions.KHR_materials_anisotropy;
+ const pbrClearcoat = extensions.KHR_materials_clearcoat;
const pbrMetallicRoughness = gltfMaterial.pbrMetallicRoughness;
material.unlit = defined(extensions.KHR_materials_unlit);
if (defined(pbrSpecularGlossiness)) {
- const specularGlossiness = new SpecularGlossiness();
- material.specularGlossiness = specularGlossiness;
-
- if (defined(pbrSpecularGlossiness.diffuseTexture)) {
- specularGlossiness.diffuseTexture = loadTexture(
+ material.specularGlossiness = loadSpecularGlossiness(
+ loader,
+ pbrSpecularGlossiness,
+ frameState
+ );
+ } else {
+ if (defined(pbrMetallicRoughness)) {
+ material.metallicRoughness = loadMetallicRoughness(
loader,
- gltf,
- pbrSpecularGlossiness.diffuseTexture,
- supportedImageFormats,
+ pbrMetallicRoughness,
frameState
);
}
- if (defined(pbrSpecularGlossiness.specularGlossinessTexture)) {
- if (defined(pbrSpecularGlossiness.specularGlossinessTexture)) {
- specularGlossiness.specularGlossinessTexture = loadTexture(
- loader,
- gltf,
- pbrSpecularGlossiness.specularGlossinessTexture,
- supportedImageFormats,
- frameState
- );
- }
+ if (defined(pbrSpecular) && !material.unlit) {
+ material.specular = loadSpecular(loader, pbrSpecular, frameState);
}
- specularGlossiness.diffuseFactor = fromArray(
- Cartesian4,
- pbrSpecularGlossiness.diffuseFactor
- );
- specularGlossiness.specularFactor = fromArray(
- Cartesian3,
- pbrSpecularGlossiness.specularFactor
- );
- specularGlossiness.glossinessFactor =
- pbrSpecularGlossiness.glossinessFactor;
- material.pbrSpecularGlossiness = pbrSpecularGlossiness;
- } else if (defined(pbrMetallicRoughness)) {
- const metallicRoughness = new MetallicRoughness();
-
- if (defined(pbrMetallicRoughness.baseColorTexture)) {
- metallicRoughness.baseColorTexture = loadTexture(
- loader,
- gltf,
- pbrMetallicRoughness.baseColorTexture,
- supportedImageFormats,
- frameState
- );
+ if (defined(pbrAnisotropy) && !material.unlit) {
+ material.anisotropy = loadAnisotropy(loader, pbrAnisotropy, frameState);
}
- if (defined(pbrMetallicRoughness.metallicRoughnessTexture)) {
- metallicRoughness.metallicRoughnessTexture = loadTexture(
- loader,
- gltf,
- pbrMetallicRoughness.metallicRoughnessTexture,
- supportedImageFormats,
- frameState
- );
+ if (defined(pbrClearcoat) && !material.unlit) {
+ material.clearcoat = loadClearcoat(loader, pbrClearcoat, frameState);
}
- metallicRoughness.baseColorFactor = fromArray(
- Cartesian4,
- pbrMetallicRoughness.baseColorFactor
- );
- metallicRoughness.metallicFactor = pbrMetallicRoughness.metallicFactor;
- metallicRoughness.roughnessFactor = pbrMetallicRoughness.roughnessFactor;
- material.metallicRoughness = metallicRoughness;
}
// Top level textures
if (defined(gltfMaterial.emissiveTexture)) {
material.emissiveTexture = loadTexture(
loader,
- gltf,
gltfMaterial.emissiveTexture,
- supportedImageFormats,
frameState
);
}
@@ -1588,18 +1686,14 @@ function loadMaterial(
if (defined(gltfMaterial.normalTexture) && !loader._loadForClassification) {
material.normalTexture = loadTexture(
loader,
- gltf,
gltfMaterial.normalTexture,
- supportedImageFormats,
frameState
);
}
if (defined(gltfMaterial.occlusionTexture)) {
material.occlusionTexture = loadTexture(
loader,
- gltf,
gltfMaterial.occlusionTexture,
- supportedImageFormats,
frameState
);
}
@@ -1679,9 +1773,7 @@ function loadFeatureIdImplicitRangeLegacy(
// for EXT_mesh_features
function loadFeatureIdTexture(
loader,
- gltf,
gltfFeatureIdTexture,
- supportedImageFormats,
frameState,
positionalLabel
) {
@@ -1696,9 +1788,7 @@ function loadFeatureIdTexture(
const textureInfo = gltfFeatureIdTexture.texture;
featureIdTexture.textureReader = loadTexture(
loader,
- gltf,
textureInfo,
- supportedImageFormats,
frameState,
Sampler.NEAREST // Feature ID textures require nearest sampling
);
@@ -1720,10 +1810,8 @@ function loadFeatureIdTexture(
// for backwards compatibility with EXT_feature_metadata
function loadFeatureIdTextureLegacy(
loader,
- gltf,
gltfFeatureIdTexture,
featureTableId,
- supportedImageFormats,
frameState,
featureCount,
positionalLabel
@@ -1735,9 +1823,7 @@ function loadFeatureIdTextureLegacy(
featureIdTexture.propertyTableId = featureTableId;
featureIdTexture.textureReader = loadTexture(
loader,
- gltf,
textureInfo,
- supportedImageFormats,
frameState,
Sampler.NEAREST // Feature ID textures require nearest sampling
);
@@ -1750,7 +1836,6 @@ function loadFeatureIdTextureLegacy(
function loadMorphTarget(
loader,
- gltf,
target,
needsPostProcessing,
primitiveLoadPlan,
@@ -1763,44 +1848,46 @@ function loadMorphTarget(
const hasInstances = false;
for (const semantic in target) {
- if (target.hasOwnProperty(semantic)) {
- const accessorId = target[semantic];
+ if (!target.hasOwnProperty(semantic)) {
+ continue;
+ }
+ const accessorId = target[semantic];
- const semanticInfo = getSemanticInfo(
- loader,
- VertexAttributeSemantic,
- semantic
- );
+ const semanticInfo = getSemanticInfo(
+ loader,
+ VertexAttributeSemantic,
+ semantic
+ );
- const attributePlan = loadVertexAttribute(
- loader,
- gltf,
- accessorId,
- semanticInfo,
- draco,
- hasInstances,
- needsPostProcessing,
- frameState
- );
- morphTarget.attributes.push(attributePlan.attribute);
+ const attributePlan = loadVertexAttribute(
+ loader,
+ accessorId,
+ semanticInfo,
+ draco,
+ hasInstances,
+ needsPostProcessing,
+ frameState
+ );
+ morphTarget.attributes.push(attributePlan.attribute);
- // The load plan doesn't need to distinguish morph target attributes from
- // regular attributes
- primitiveLoadPlan.attributePlans.push(attributePlan);
- }
+ // The load plan doesn't need to distinguish morph target attributes from
+ // regular attributes
+ primitiveLoadPlan.attributePlans.push(attributePlan);
}
return morphTarget;
}
-function loadPrimitive(
- loader,
- gltf,
- gltfPrimitive,
- hasInstances,
- supportedImageFormats,
- frameState
-) {
+/**
+ * Load resources associated with a mesh primitive for a glTF node
+ * @param {GltfLoader} loader
+ * @param {object} gltfPrimitive One of the primitives in a mesh
+ * @param {boolean} hasInstances True if the node using this mesh has instances
+ * @param {FrameState} frameState
+ * @returns {ModelComponents.Primitive}
+ * @private
+ */
+function loadPrimitive(loader, gltfPrimitive, hasInstances, frameState) {
const primitive = new Primitive();
const primitivePlan = new PrimitiveLoadPlan(primitive);
loader._primitiveLoadPlans.push(primitivePlan);
@@ -1809,9 +1896,7 @@ function loadPrimitive(
if (defined(materialId)) {
primitive.material = loadMaterial(
loader,
- gltf,
- gltf.materials[materialId],
- supportedImageFormats,
+ loader.gltfJson.materials[materialId],
frameState
);
}
@@ -1828,7 +1913,6 @@ function loadPrimitive(
primitivePlan.needsOutlines = true;
primitivePlan.outlineIndices = loadPrimitiveOutline(
loader,
- gltf,
outlineExtension,
primitivePlan
);
@@ -1841,52 +1925,47 @@ function loadPrimitive(
const attributes = gltfPrimitive.attributes;
if (defined(attributes)) {
for (const semantic in attributes) {
- if (attributes.hasOwnProperty(semantic)) {
- const accessorId = attributes[semantic];
- const semanticInfo = getSemanticInfo(
- loader,
- VertexAttributeSemantic,
- semantic
- );
+ if (!attributes.hasOwnProperty(semantic)) {
+ continue;
+ }
+ const accessorId = attributes[semantic];
+ const semanticInfo = getSemanticInfo(
+ loader,
+ VertexAttributeSemantic,
+ semantic
+ );
- const modelSemantic = semanticInfo.modelSemantic;
- if (
- loadForClassification &&
- !isClassificationAttribute(modelSemantic)
- ) {
- continue;
- }
+ const modelSemantic = semanticInfo.modelSemantic;
+ if (loadForClassification && !isClassificationAttribute(modelSemantic)) {
+ continue;
+ }
- if (modelSemantic === VertexAttributeSemantic.FEATURE_ID) {
- hasFeatureIds = true;
- }
+ if (modelSemantic === VertexAttributeSemantic.FEATURE_ID) {
+ hasFeatureIds = true;
+ }
- const attributePlan = loadVertexAttribute(
- loader,
- gltf,
- accessorId,
- semanticInfo,
- draco,
- hasInstances,
- needsPostProcessing,
- frameState
- );
+ const attributePlan = loadVertexAttribute(
+ loader,
+ accessorId,
+ semanticInfo,
+ draco,
+ hasInstances,
+ needsPostProcessing,
+ frameState
+ );
- primitivePlan.attributePlans.push(attributePlan);
- primitive.attributes.push(attributePlan.attribute);
- }
+ primitivePlan.attributePlans.push(attributePlan);
+ primitive.attributes.push(attributePlan.attribute);
}
}
const targets = gltfPrimitive.targets;
// Morph targets are disabled for classification models.
if (defined(targets) && !loadForClassification) {
- const targetsLength = targets.length;
- for (let i = 0; i < targetsLength; ++i) {
+ for (let i = 0; i < targets.length; ++i) {
primitive.morphTargets.push(
loadMorphTarget(
loader,
- gltf,
targets[i],
needsPostProcessing,
primitivePlan,
@@ -1900,7 +1979,6 @@ function loadPrimitive(
if (defined(indices)) {
const indicesPlan = loadIndices(
loader,
- gltf,
indices,
draco,
hasFeatureIds,
@@ -1925,21 +2003,12 @@ function loadPrimitive(
// Load feature Ids
if (defined(meshFeatures)) {
- loadPrimitiveFeatures(
- loader,
- gltf,
- primitive,
- meshFeatures,
- supportedImageFormats,
- frameState
- );
+ loadPrimitiveFeatures(loader, primitive, meshFeatures, frameState);
} else if (hasFeatureMetadataLegacy) {
loadPrimitiveFeaturesLegacy(
loader,
- gltf,
primitive,
featureMetadataLegacy,
- supportedImageFormats,
frameState
);
}
@@ -1962,19 +2031,18 @@ function loadPrimitive(
return primitive;
}
-function loadPrimitiveOutline(loader, gltf, outlineExtension) {
+function loadPrimitiveOutline(loader, outlineExtension) {
const accessorId = outlineExtension.indices;
+ const accessor = loader.gltfJson.accessors[accessorId];
const useQuaternion = false;
- return loadAccessor(loader, gltf, accessorId, useQuaternion);
+ return loadAccessor(loader, accessor, useQuaternion);
}
// For EXT_mesh_features
function loadPrimitiveFeatures(
loader,
- gltf,
primitive,
meshFeaturesExtension,
- supportedImageFormats,
frameState
) {
let featureIdsArray;
@@ -1995,9 +2063,7 @@ function loadPrimitiveFeatures(
if (defined(featureIds.texture)) {
featureIdComponent = loadFeatureIdTexture(
loader,
- gltf,
featureIds,
- supportedImageFormats,
frameState,
label
);
@@ -2016,22 +2082,19 @@ function loadPrimitiveFeatures(
// For EXT_feature_metadata
function loadPrimitiveFeaturesLegacy(
loader,
- gltf,
primitive,
metadataExtension,
- supportedImageFormats,
frameState
) {
// For looking up the featureCount for each set of feature IDs
- const featureTables = gltf.extensions.EXT_feature_metadata.featureTables;
+ const { featureTables } = loader.gltfJson.extensions.EXT_feature_metadata;
let nextFeatureIdIndex = 0;
// Feature ID Attributes
const featureIdAttributes = metadataExtension.featureIdAttributes;
if (defined(featureIdAttributes)) {
- const featureIdAttributesLength = featureIdAttributes.length;
- for (let i = 0; i < featureIdAttributesLength; ++i) {
+ for (let i = 0; i < featureIdAttributes.length; ++i) {
const featureIdAttribute = featureIdAttributes[i];
const featureTableId = featureIdAttribute.featureTable;
const propertyTableId = loader._sortedPropertyTableIds.indexOf(
@@ -2064,8 +2127,7 @@ function loadPrimitiveFeaturesLegacy(
// Feature ID Textures
const featureIdTextures = metadataExtension.featureIdTextures;
if (defined(featureIdTextures)) {
- const featureIdTexturesLength = featureIdTextures.length;
- for (let i = 0; i < featureIdTexturesLength; ++i) {
+ for (let i = 0; i < featureIdTextures.length; ++i) {
const featureIdTexture = featureIdTextures[i];
const featureTableId = featureIdTexture.featureTable;
const propertyTableId = loader._sortedPropertyTableIds.indexOf(
@@ -2077,10 +2139,8 @@ function loadPrimitiveFeaturesLegacy(
const featureIdComponent = loadFeatureIdTextureLegacy(
loader,
- gltf,
featureIdTexture,
propertyTableId,
- supportedImageFormats,
frameState,
featureCount,
featureIdLabel
@@ -2124,26 +2184,26 @@ function loadPrimitiveMetadataLegacy(loader, primitive, metadataExtension) {
}
}
-function loadInstances(loader, gltf, nodeExtensions, frameState) {
+function loadInstances(loader, nodeExtensions, frameState) {
const instancingExtension = nodeExtensions.EXT_mesh_gpu_instancing;
const instances = new Instances();
const attributes = instancingExtension.attributes;
if (defined(attributes)) {
for (const semantic in attributes) {
- if (attributes.hasOwnProperty(semantic)) {
- const accessorId = attributes[semantic];
- instances.attributes.push(
- loadInstancedAttribute(
- loader,
- gltf,
- accessorId,
- attributes,
- semantic,
- frameState
- )
- );
+ if (!attributes.hasOwnProperty(semantic)) {
+ continue;
}
+ const accessorId = attributes[semantic];
+ instances.attributes.push(
+ loadInstancedAttribute(
+ loader,
+ accessorId,
+ attributes,
+ semantic,
+ frameState
+ )
+ );
}
}
@@ -2158,7 +2218,7 @@ function loadInstances(loader, gltf, nodeExtensions, frameState) {
loadInstanceFeatures(instances, instanceFeatures);
} else if (defined(featureMetadataLegacy)) {
loadInstanceFeaturesLegacy(
- gltf,
+ loader.gltfJson,
instances,
featureMetadataLegacy,
loader._sortedPropertyTableIds
@@ -2202,8 +2262,7 @@ function loadInstanceFeaturesLegacy(
const featureIdAttributes = metadataExtension.featureIdAttributes;
if (defined(featureIdAttributes)) {
- const featureIdAttributesLength = featureIdAttributes.length;
- for (let i = 0; i < featureIdAttributesLength; ++i) {
+ for (let i = 0; i < featureIdAttributes.length; ++i) {
const featureIdAttribute = featureIdAttributes[i];
const featureTableId = featureIdAttribute.featureTable;
const propertyTableId = sortedPropertyTableIds.indexOf(featureTableId);
@@ -2231,7 +2290,15 @@ function loadInstanceFeaturesLegacy(
}
}
-function loadNode(loader, gltf, gltfNode, supportedImageFormats, frameState) {
+/**
+ * Load resources associated with one node from a glTF JSON
+ * @param {GltfLoader} loader
+ * @param {object} gltfNode An entry from the .nodes
array in the glTF JSON
+ * @param {FrameState} frameState
+ * @returns {ModelComponents.Node}
+ * @private
+ */
+function loadNode(loader, gltfNode, frameState) {
const node = new Node();
node.name = gltfNode.name;
@@ -2254,7 +2321,7 @@ function loadNode(loader, gltf, gltfNode, supportedImageFormats, frameState) {
"Models with the EXT_mesh_gpu_instancing extension cannot be used for classification."
);
}
- node.instances = loadInstances(loader, gltf, nodeExtensions, frameState);
+ node.instances = loadInstances(loader, nodeExtensions, frameState);
}
if (defined(articulationsExtension)) {
@@ -2263,17 +2330,14 @@ function loadNode(loader, gltf, gltfNode, supportedImageFormats, frameState) {
const meshId = gltfNode.mesh;
if (defined(meshId)) {
- const mesh = gltf.meshes[meshId];
+ const mesh = loader.gltfJson.meshes[meshId];
const primitives = mesh.primitives;
- const primitivesLength = primitives.length;
- for (let i = 0; i < primitivesLength; ++i) {
+ for (let i = 0; i < primitives.length; ++i) {
node.primitives.push(
loadPrimitive(
loader,
- gltf,
primitives[i],
defined(node.instances),
- supportedImageFormats,
frameState
)
);
@@ -2283,120 +2347,105 @@ function loadNode(loader, gltf, gltfNode, supportedImageFormats, frameState) {
// by the mesh. If both are undefined, it will default to an array of zero weights.
const morphWeights = defaultValue(gltfNode.weights, mesh.weights);
const targets = node.primitives[0].morphTargets;
- const targetsLength = targets.length;
// Since meshes are not stored as separate components, the mesh weights will still
// be stored at the node level.
node.morphWeights = defined(morphWeights)
? morphWeights.slice()
- : new Array(targetsLength).fill(0.0);
+ : new Array(targets.length).fill(0.0);
}
return node;
}
-function loadNodes(loader, gltf, supportedImageFormats, frameState) {
- if (!defined(gltf.nodes)) {
+/**
+ * Load resources associated with the nodes in a glTF JSON
+ * @param {GltfLoader} loader
+ * @param {FrameState} frameState
+ * @returns {ModelComponents.Node[]}
+ * @private
+ */
+function loadNodes(loader, frameState) {
+ const nodeJsons = loader.gltfJson.nodes;
+ if (!defined(nodeJsons)) {
return [];
}
- let i;
- let j;
-
- const nodesLength = gltf.nodes.length;
- const nodes = new Array(nodesLength);
- for (i = 0; i < nodesLength; ++i) {
- const node = loadNode(
- loader,
- gltf,
- gltf.nodes[i],
- supportedImageFormats,
- frameState
- );
+ const loadedNodes = nodeJsons.map(function (nodeJson, i) {
+ const node = loadNode(loader, nodeJson, frameState);
node.index = i;
- nodes[i] = node;
- }
+ return node;
+ });
- for (i = 0; i < nodesLength; ++i) {
- const childrenNodeIds = gltf.nodes[i].children;
+ for (let i = 0; i < loadedNodes.length; ++i) {
+ const childrenNodeIds = nodeJsons[i].children;
if (defined(childrenNodeIds)) {
- const childrenLength = childrenNodeIds.length;
- for (j = 0; j < childrenLength; ++j) {
- nodes[i].children.push(nodes[childrenNodeIds[j]]);
+ for (let j = 0; j < childrenNodeIds.length; ++j) {
+ loadedNodes[i].children.push(loadedNodes[childrenNodeIds[j]]);
}
}
}
- return nodes;
+ return loadedNodes;
}
-function loadSkin(loader, gltf, gltfSkin, nodes) {
+function loadSkin(loader, gltfSkin, nodes) {
const skin = new Skin();
const jointIds = gltfSkin.joints;
- const jointsLength = jointIds.length;
- const joints = new Array(jointsLength);
- for (let i = 0; i < jointsLength; ++i) {
- joints[i] = nodes[jointIds[i]];
- }
- skin.joints = joints;
+ skin.joints = jointIds.map((jointId) => nodes[jointId]);
const inverseBindMatricesAccessorId = gltfSkin.inverseBindMatrices;
if (defined(inverseBindMatricesAccessorId)) {
- skin.inverseBindMatrices = loadAccessor(
- loader,
- gltf,
- inverseBindMatricesAccessorId
- );
+ const accessor = loader.gltfJson.accessors[inverseBindMatricesAccessorId];
+ skin.inverseBindMatrices = loadAccessor(loader, accessor);
} else {
- skin.inverseBindMatrices = new Array(jointsLength).fill(Matrix4.IDENTITY);
+ skin.inverseBindMatrices = new Array(jointIds.length).fill(
+ Matrix4.IDENTITY
+ );
}
return skin;
}
-function loadSkins(loader, gltf, nodes) {
- const gltfSkins = gltf.skins;
+function loadSkins(loader, nodes) {
+ const skinJsons = loader.gltfJson.skins;
// Skins are disabled for classification models.
- if (loader._loadForClassification || !defined(gltfSkins)) {
+ if (loader._loadForClassification || !defined(skinJsons)) {
return [];
}
- const skinsLength = gltf.skins.length;
- const skins = new Array(skinsLength);
- for (let i = 0; i < skinsLength; ++i) {
- const skin = loadSkin(loader, gltf, gltf.skins[i], nodes);
+ const loadedSkins = skinJsons.map(function (skinJson, i) {
+ const skin = loadSkin(loader, skinJson, nodes);
skin.index = i;
- skins[i] = skin;
- }
+ return skin;
+ });
- const nodesLength = nodes.length;
- for (let i = 0; i < nodesLength; ++i) {
- const skinId = gltf.nodes[i].skin;
+ const nodeJsons = loader.gltfJson.nodes;
+ for (let i = 0; i < nodes.length; ++i) {
+ const skinId = nodeJsons[i].skin;
if (defined(skinId)) {
- nodes[i].skin = skins[skinId];
+ nodes[i].skin = loadedSkins[skinId];
}
}
- return skins;
+ return loadedSkins;
}
async function loadStructuralMetadata(
loader,
- gltf,
extension,
extensionLegacy,
- supportedImageFormats,
frameState
) {
const structuralMetadataLoader = new GltfStructuralMetadataLoader({
- gltf: gltf,
+ gltf: loader.gltfJson,
extension: extension,
extensionLegacy: extensionLegacy,
gltfResource: loader._gltfResource,
baseResource: loader._baseResource,
- supportedImageFormats: supportedImageFormats,
+ supportedImageFormats: loader._supportedImageFormats,
frameState: frameState,
asynchronous: loader._asynchronous,
});
@@ -2404,11 +2453,12 @@ async function loadStructuralMetadata(
return structuralMetadataLoader.load();
}
-function loadAnimationSampler(loader, gltf, gltfSampler) {
+function loadAnimationSampler(loader, gltfSampler) {
const animationSampler = new AnimationSampler();
+ const accessors = loader.gltfJson.accessors;
- const inputAccessorId = gltfSampler.input;
- animationSampler.input = loadAccessor(loader, gltf, inputAccessorId);
+ const inputAccessor = accessors[gltfSampler.input];
+ animationSampler.input = loadAccessor(loader, inputAccessor);
const gltfInterpolation = gltfSampler.interpolation;
animationSampler.interpolation = defaultValue(
@@ -2416,8 +2466,8 @@ function loadAnimationSampler(loader, gltf, gltfSampler) {
InterpolationType.LINEAR
);
- const outputAccessorId = gltfSampler.output;
- animationSampler.output = loadAccessor(loader, gltf, outputAccessorId, true);
+ const outputAccessor = accessors[gltfSampler.output];
+ animationSampler.output = loadAccessor(loader, outputAccessor, true);
return animationSampler;
}
@@ -2450,29 +2500,19 @@ function loadAnimationChannel(gltfChannel, samplers, nodes) {
return animationChannel;
}
-function loadAnimation(loader, gltf, gltfAnimation, nodes) {
- let i;
-
+function loadAnimation(loader, animationJson, nodes) {
const animation = new Animation();
- animation.name = gltfAnimation.name;
+ animation.name = animationJson.name;
- const gltfSamplers = gltfAnimation.samplers;
- const samplersLength = gltfSamplers.length;
-
- const samplers = new Array(samplersLength);
- for (i = 0; i < samplersLength; i++) {
- const sampler = loadAnimationSampler(loader, gltf, gltfSamplers[i]);
+ const samplers = animationJson.samplers.map(function (samplerJson, i) {
+ const sampler = loadAnimationSampler(loader, samplerJson);
sampler.index = i;
- samplers[i] = sampler;
- }
-
- const gltfChannels = gltfAnimation.channels;
- const channelsLength = gltfChannels.length;
+ return sampler;
+ });
- const channels = new Array(channelsLength);
- for (i = 0; i < channelsLength; i++) {
- channels[i] = loadAnimationChannel(gltfChannels[i], samplers, nodes);
- }
+ const channels = animationJson.channels.map(function (channelJson) {
+ return loadAnimationChannel(channelJson, samplers, nodes);
+ });
animation.samplers = samplers;
animation.channels = channels;
@@ -2480,21 +2520,19 @@ function loadAnimation(loader, gltf, gltfAnimation, nodes) {
return animation;
}
-function loadAnimations(loader, gltf, nodes) {
- const gltfAnimations = gltf.animations;
+function loadAnimations(loader, nodes) {
+ const animationJsons = loader.gltfJson.animations;
// Animations are disabled for classification models.
- if (loader._loadForClassification || !defined(gltfAnimations)) {
+ if (loader._loadForClassification || !defined(animationJsons)) {
return [];
}
- const animationsLength = gltf.animations.length;
- const animations = new Array(animationsLength);
- for (let i = 0; i < animationsLength; ++i) {
- const animation = loadAnimation(loader, gltf, gltf.animations[i], nodes);
+ const animations = animationJsons.map(function (animationJson, i) {
+ const animation = loadAnimation(loader, animationJson, nodes);
animation.index = i;
- animations[i] = animation;
- }
+ return animation;
+ });
return animations;
}
@@ -2513,45 +2551,20 @@ function loadArticulationStage(gltfStage) {
return stage;
}
-function loadArticulation(gltfArticulation) {
+function loadArticulation(articulationJson) {
const articulation = new Articulation();
- articulation.name = gltfArticulation.name;
-
- const gltfStages = gltfArticulation.stages;
- const gltfStagesLength = gltfStages.length;
-
- const stages = new Array(gltfStagesLength);
- for (let i = 0; i < gltfStagesLength; i++) {
- const stage = loadArticulationStage(gltfStages[i]);
- stages[i] = stage;
- }
-
- articulation.stages = stages;
-
+ articulation.name = articulationJson.name;
+ articulation.stages = articulationJson.stages.map(loadArticulationStage);
return articulation;
}
function loadArticulations(gltf) {
const extensions = defaultValue(gltf.extensions, defaultValue.EMPTY_OBJECT);
- const articulationsExtension = extensions.AGI_articulations;
-
- if (!defined(articulationsExtension)) {
+ const articulationJsons = extensions.AGI_articulations?.articulations;
+ if (!defined(articulationJsons)) {
return [];
}
-
- const gltfArticulations = articulationsExtension.articulations;
- if (!defined(gltfArticulations)) {
- return [];
- }
-
- const gltfArticulationsLength = gltfArticulations.length;
- const articulations = new Array(gltfArticulationsLength);
- for (let i = 0; i < gltfArticulationsLength; i++) {
- const articulation = loadArticulation(gltfArticulations[i]);
- articulations[i] = articulation;
- }
-
- return articulations;
+ return articulationJsons.map(loadArticulation);
}
function getSceneNodeIds(gltf) {
@@ -2575,7 +2588,23 @@ function loadScene(gltf, nodes) {
const scratchCenter = new Cartesian3();
-function parse(loader, gltf, supportedImageFormats, frameState) {
+/**
+ * Parse the glTF which populates the loaders arrays. Loading promises will be created, and will
+ * resolve once the loaders are ready (i.e. all external resources
+ * have been fetched and all GPU resources have been created). Loaders that
+ * create GPU resources need to be processed every frame until they become
+ * ready since the JobScheduler is not able to execute all jobs in a single
+ * frame. Any promise failures are collected, and will be handled synchronously in process().
+ * Also note that it's fine to call process before a loader is ready to process or
+ * after it has failed; nothing will happen.
+ *
+ * @param {GltfLoader} loader
+ * @param {FrameState} frameState
+ * @returns {Promise} A Promise that resolves when all loaders are ready
+ * @private
+ */
+function parse(loader, frameState) {
+ const gltf = loader.gltfJson;
const extensions = defaultValue(gltf.extensions, defaultValue.EMPTY_OBJECT);
const structuralMetadataExtension = extensions.EXT_structural_metadata;
const featureMetadataExtensionLegacy = extensions.EXT_feature_metadata;
@@ -2598,9 +2627,9 @@ function parse(loader, gltf, supportedImageFormats, frameState) {
loader._sortedFeatureTextureIds = Object.keys(allFeatureTextureIds).sort();
}
- const nodes = loadNodes(loader, gltf, supportedImageFormats, frameState);
- const skins = loadSkins(loader, gltf, nodes);
- const animations = loadAnimations(loader, gltf, nodes);
+ const nodes = loadNodes(loader, frameState);
+ const skins = loadSkins(loader, nodes);
+ const animations = loadAnimations(loader, nodes);
const articulations = loadArticulations(gltf);
const scene = loadScene(gltf, nodes);
@@ -2645,10 +2674,8 @@ function parse(loader, gltf, supportedImageFormats, frameState) {
) {
const promise = loadStructuralMetadata(
loader,
- gltf,
structuralMetadataExtension,
featureMetadataExtensionLegacy,
- supportedImageFormats,
frameState
);
loader._loaderPromises.push(promise);
@@ -2669,8 +2696,7 @@ function parse(loader, gltf, supportedImageFormats, frameState) {
function unloadTextures(loader) {
const textureLoaders = loader._textureLoaders;
- const textureLoadersLength = textureLoaders.length;
- for (let i = 0; i < textureLoadersLength; ++i) {
+ for (let i = 0; i < textureLoaders.length; ++i) {
textureLoaders[i] =
!textureLoaders[i].isDestroyed() &&
ResourceCache.unload(textureLoaders[i]);
@@ -2680,8 +2706,7 @@ function unloadTextures(loader) {
function unloadBufferViewLoaders(loader) {
const bufferViewLoaders = loader._bufferViewLoaders;
- const bufferViewLoadersLength = bufferViewLoaders.length;
- for (let i = 0; i < bufferViewLoadersLength; ++i) {
+ for (let i = 0; i < bufferViewLoaders.length; ++i) {
bufferViewLoaders[i] =
!bufferViewLoaders[i].isDestroyed() &&
ResourceCache.unload(bufferViewLoaders[i]);
@@ -2691,8 +2716,7 @@ function unloadBufferViewLoaders(loader) {
function unloadGeometry(loader) {
const geometryLoaders = loader._geometryLoaders;
- const geometryLoadersLength = geometryLoaders.length;
- for (let i = 0; i < geometryLoadersLength; ++i) {
+ for (let i = 0; i < geometryLoaders.length; ++i) {
geometryLoaders[i] =
!geometryLoaders[i].isDestroyed() &&
ResourceCache.unload(geometryLoaders[i]);
@@ -2702,8 +2726,7 @@ function unloadGeometry(loader) {
function unloadGeneratedAttributes(loader) {
const buffers = loader._postProcessBuffers;
- const length = buffers.length;
- for (let i = 0; i < length; i++) {
+ for (let i = 0; i < buffers.length; i++) {
const buffer = buffers[i];
if (!buffer.isDestroyed()) {
buffer.destroy();
diff --git a/packages/engine/Source/Scene/GltfLoaderUtil.js b/packages/engine/Source/Scene/GltfLoaderUtil.js
index ac24f378a55..76f0a5c3b17 100644
--- a/packages/engine/Source/Scene/GltfLoaderUtil.js
+++ b/packages/engine/Source/Scene/GltfLoaderUtil.js
@@ -35,9 +35,7 @@ const GltfLoaderUtil = {};
*/
GltfLoaderUtil.getImageIdFromTexture = function (options) {
options = defaultValue(options, defaultValue.EMPTY_OBJECT);
- const gltf = options.gltf;
- const textureId = options.textureId;
- const supportedImageFormats = options.supportedImageFormats;
+ const { gltf, textureId, supportedImageFormats } = options;
//>>includeStart('debug', pragmas.debug);
Check.typeOf.object("options.gltf", gltf);
@@ -73,12 +71,7 @@ GltfLoaderUtil.getImageIdFromTexture = function (options) {
*/
GltfLoaderUtil.createSampler = function (options) {
options = defaultValue(options, defaultValue.EMPTY_OBJECT);
- const gltf = options.gltf;
- const textureInfo = options.textureInfo;
- const compressedTextureNoMipmap = defaultValue(
- options.compressedTextureNoMipmap,
- false
- );
+ const { gltf, textureInfo, compressedTextureNoMipmap = false } = options;
//>>includeStart('debug', pragmas.debug);
Check.typeOf.object("options.gltf", gltf);
@@ -140,9 +133,7 @@ const defaultScale = new Cartesian2(1.0, 1.0);
*/
GltfLoaderUtil.createModelTextureReader = function (options) {
options = defaultValue(options, defaultValue.EMPTY_OBJECT);
- const textureInfo = options.textureInfo;
- const channels = options.channels;
- const texture = options.texture;
+ const { textureInfo, channels, texture } = options;
//>>includeStart('debug', pragmas.debug);
Check.typeOf.object("options.textureInfo", textureInfo);
diff --git a/packages/engine/Source/Scene/GltfPipeline/forEachTextureInMaterial.js b/packages/engine/Source/Scene/GltfPipeline/forEachTextureInMaterial.js
index 047d4883de1..09ef6ceb2d0 100644
--- a/packages/engine/Source/Scene/GltfPipeline/forEachTextureInMaterial.js
+++ b/packages/engine/Source/Scene/GltfPipeline/forEachTextureInMaterial.js
@@ -33,10 +33,11 @@ function forEachTextureInMaterial(material, handler) {
}
}
- if (defined(material.extensions)) {
+ const { extensions } = material;
+ if (defined(extensions)) {
// Spec gloss extension
const pbrSpecularGlossiness =
- material.extensions.KHR_materials_pbrSpecularGlossiness;
+ extensions.KHR_materials_pbrSpecularGlossiness;
if (defined(pbrSpecularGlossiness)) {
if (defined(pbrSpecularGlossiness.diffuseTexture)) {
const textureInfo = pbrSpecularGlossiness.diffuseTexture;
@@ -54,13 +55,28 @@ function forEachTextureInMaterial(material, handler) {
}
}
+ // Specular extension
+ const specular = extensions.KHR_materials_specular;
+ if (defined(specular)) {
+ const { specularTexture, specularColorTexture } = specular;
+ if (defined(specularTexture)) {
+ const value = handler(specularTexture.index, specularTexture);
+ if (defined(value)) {
+ return value;
+ }
+ }
+ if (defined(specularColorTexture)) {
+ const value = handler(specularColorTexture.index, specularColorTexture);
+ if (defined(value)) {
+ return value;
+ }
+ }
+ }
+
// Materials common extension (may be present in models converted from glTF 1.0)
- const materialsCommon = material.extensions.KHR_materials_common;
+ const materialsCommon = extensions.KHR_materials_common;
if (defined(materialsCommon) && defined(materialsCommon.values)) {
- const diffuse = materialsCommon.values.diffuse;
- const ambient = materialsCommon.values.ambient;
- const emission = materialsCommon.values.emission;
- const specular = materialsCommon.values.specular;
+ const { diffuse, ambient, emission, specular } = materialsCommon.values;
if (defined(diffuse) && defined(diffuse.index)) {
const value = handler(diffuse.index, diffuse);
if (defined(value)) {
diff --git a/packages/engine/Source/Scene/GltfStructuralMetadataLoader.js b/packages/engine/Source/Scene/GltfStructuralMetadataLoader.js
index 7bd6129a086..b8b2d0b0b45 100644
--- a/packages/engine/Source/Scene/GltfStructuralMetadataLoader.js
+++ b/packages/engine/Source/Scene/GltfStructuralMetadataLoader.js
@@ -34,15 +34,17 @@ import ResourceLoaderState from "./ResourceLoaderState.js";
*/
function GltfStructuralMetadataLoader(options) {
options = defaultValue(options, defaultValue.EMPTY_OBJECT);
- const gltf = options.gltf;
- const extension = options.extension;
- const extensionLegacy = options.extensionLegacy;
- const gltfResource = options.gltfResource;
- const baseResource = options.baseResource;
- const supportedImageFormats = options.supportedImageFormats;
- const frameState = options.frameState;
- const cacheKey = options.cacheKey;
- const asynchronous = defaultValue(options.asynchronous, true);
+ const {
+ gltf,
+ extension,
+ extensionLegacy,
+ gltfResource,
+ baseResource,
+ supportedImageFormats,
+ frameState,
+ cacheKey,
+ asynchronous = true,
+ } = options;
//>>includeStart('debug', pragmas.debug);
Check.typeOf.object("options.gltf", gltf);
diff --git a/packages/engine/Source/Scene/Label.js b/packages/engine/Source/Scene/Label.js
index 7949cef4d80..bc10b50510f 100644
--- a/packages/engine/Source/Scene/Label.js
+++ b/packages/engine/Source/Scene/Label.js
@@ -91,7 +91,7 @@ function parseFont(label) {
* Initialization options for the Label constructor
*
* @property {Cartesian3} position The cartesian position of the label.
- * @property {string} [id] A user-defined object to return when the label is picked with {@link Scene#pick}.
+ * @property {*} [id] A user-defined object to return when the label is picked with {@link Scene#pick}.
* @property {boolean} [show=true] Determines if this label will be shown.
* @property {string} [text] A string specifying the text of the label.
* @property {string} [font='30px sans-serif'] A string specifying the font used to draw this label. Fonts are specified using the same syntax as the CSS 'font' property.
diff --git a/packages/engine/Source/Scene/Model/AlphaPipelineStage.js b/packages/engine/Source/Scene/Model/AlphaPipelineStage.js
index 1cb1f3f1cc4..2f1d542f6d6 100644
--- a/packages/engine/Source/Scene/Model/AlphaPipelineStage.js
+++ b/packages/engine/Source/Scene/Model/AlphaPipelineStage.js
@@ -7,7 +7,7 @@ import Pass from "../../Renderer/Pass.js";
/**
* A pipeline stage for configuring the alpha options for handling translucency.
*
- * @namespace MaterialPipelineStage
+ * @namespace AlphaPipelineStage
*
* @private
*/
diff --git a/packages/engine/Source/Scene/Model/GeometryPipelineStage.js b/packages/engine/Source/Scene/Model/GeometryPipelineStage.js
index ca753b6a01e..28b769a07c9 100644
--- a/packages/engine/Source/Scene/Model/GeometryPipelineStage.js
+++ b/packages/engine/Source/Scene/Model/GeometryPipelineStage.js
@@ -63,8 +63,7 @@ GeometryPipelineStage.process = function (
primitive,
frameState
) {
- const shaderBuilder = renderResources.shaderBuilder;
- const model = renderResources.model;
+ const { shaderBuilder, model } = renderResources;
// These structs are similar, though the fragment shader version has a couple
// additional fields.
@@ -125,8 +124,7 @@ GeometryPipelineStage.process = function (
);
// .pnts point clouds store sRGB color rather than linear color
- const modelType = model.type;
- if (modelType === ModelType.TILE_PNTS) {
+ if (model.type === ModelType.TILE_PNTS) {
shaderBuilder.addDefine(
"HAS_SRGB_COLOR",
undefined,
@@ -246,8 +244,7 @@ function processAttribute(
}
function addSemanticDefine(shaderBuilder, attribute) {
- const semantic = attribute.semantic;
- const setIndex = attribute.setIndex;
+ const { semantic, setIndex } = attribute;
switch (semantic) {
case VertexAttributeSemantic.NORMAL:
shaderBuilder.addDefine("HAS_NORMALS");
@@ -272,19 +269,11 @@ function addAttributeToRenderResources(
attributeIndex,
modifyFor2D
) {
- const quantization = attribute.quantization;
- let type;
- let componentDatatype;
- if (defined(quantization)) {
- type = quantization.type;
- componentDatatype = quantization.componentDatatype;
- } else {
- type = attribute.type;
- componentDatatype = attribute.componentDatatype;
- }
+ const { quantization, semantic, setIndex } = attribute;
+ const { type, componentDatatype } = defined(quantization)
+ ? quantization
+ : attribute;
- const semantic = attribute.semantic;
- const setIndex = attribute.setIndex;
if (
semantic === VertexAttributeSemantic.FEATURE_ID &&
setIndex >= renderResources.featureIdVertexAttributeSetIndex
@@ -337,18 +326,10 @@ function addMatrixAttributeToRenderResources(
attributeIndex,
columnCount
) {
- const quantization = attribute.quantization;
- let type;
- let componentDatatype;
- if (defined(quantization)) {
- type = quantization.type;
- componentDatatype = quantization.componentDatatype;
- } else {
- type = attribute.type;
- componentDatatype = attribute.componentDatatype;
- }
-
- const normalized = attribute.normalized;
+ const { quantization, normalized } = attribute;
+ const { type, componentDatatype } = defined(quantization)
+ ? quantization
+ : attribute;
// componentCount is either 4, 9 or 16
const componentCount = AttributeType.getNumberOfComponents(type);
@@ -435,7 +416,7 @@ function addAttributeDeclaration(shaderBuilder, attributeInfo, modifyFor2D) {
function updateAttributesStruct(shaderBuilder, attributeInfo, use2D) {
const vsStructId = GeometryPipelineStage.STRUCT_ID_PROCESSED_ATTRIBUTES_VS;
const fsStructId = GeometryPipelineStage.STRUCT_ID_PROCESSED_ATTRIBUTES_FS;
- const variableName = attributeInfo.variableName;
+ const { variableName, glslType } = attributeInfo;
if (variableName === "tangentMC") {
// The w component of the tangent is only used for computing the bitangent,
@@ -451,16 +432,8 @@ function updateAttributesStruct(shaderBuilder, attributeInfo, use2D) {
shaderBuilder.addStructField(vsStructId, "vec3", "normalMC");
shaderBuilder.addStructField(fsStructId, "vec3", "normalEC");
} else {
- shaderBuilder.addStructField(
- vsStructId,
- attributeInfo.glslType,
- variableName
- );
- shaderBuilder.addStructField(
- fsStructId,
- attributeInfo.glslType,
- variableName
- );
+ shaderBuilder.addStructField(vsStructId, glslType, variableName);
+ shaderBuilder.addStructField(fsStructId, glslType, variableName);
}
if (variableName === "positionMC" && use2D) {
@@ -501,8 +474,7 @@ function updateInitializeAttributesFunction(
}
function updateSetDynamicVaryingsFunction(shaderBuilder, attributeInfo) {
- const semantic = attributeInfo.attribute.semantic;
- const setIndex = attributeInfo.attribute.setIndex;
+ const { semantic, setIndex } = attributeInfo.attribute;
if (defined(semantic) && !defined(setIndex)) {
// positions, normals, and tangents are handled statically in
// GeometryStageVS
diff --git a/packages/engine/Source/Scene/Model/ImageBasedLightingPipelineStage.js b/packages/engine/Source/Scene/Model/ImageBasedLightingPipelineStage.js
index 48ebcf81ff4..d347e141100 100644
--- a/packages/engine/Source/Scene/Model/ImageBasedLightingPipelineStage.js
+++ b/packages/engine/Source/Scene/Model/ImageBasedLightingPipelineStage.js
@@ -8,6 +8,13 @@ const ImageBasedLightingPipelineStage = {
name: "ImageBasedLightingPipelineStage", // Helps with debugging
};
+/**
+ * Add shader code, uniforms, and defines related to image based lighting
+ * @param {ModelRenderResources} renderResources
+ * @param {Model} model
+ * @param {FrameState} frameState
+ * @private
+ */
ImageBasedLightingPipelineStage.process = function (
renderResources,
model,
diff --git a/packages/engine/Source/Scene/Model/LightingPipelineStage.js b/packages/engine/Source/Scene/Model/LightingPipelineStage.js
index 6ed8f4aad1a..a2f466484ee 100644
--- a/packages/engine/Source/Scene/Model/LightingPipelineStage.js
+++ b/packages/engine/Source/Scene/Model/LightingPipelineStage.js
@@ -28,9 +28,7 @@ const LightingPipelineStage = {
* @private
*/
LightingPipelineStage.process = function (renderResources, primitive) {
- const model = renderResources.model;
- const lightingOptions = renderResources.lightingOptions;
- const shaderBuilder = renderResources.shaderBuilder;
+ const { model, lightingOptions, shaderBuilder } = renderResources;
if (defined(model.lightColor)) {
shaderBuilder.addDefine(
@@ -53,7 +51,7 @@ LightingPipelineStage.process = function (renderResources, primitive) {
// The lighting model is always set by the material. However, custom shaders
// can override this.
- const lightingModel = lightingOptions.lightingModel;
+ const { lightingModel } = lightingOptions;
if (lightingModel === LightingModel.PBR) {
shaderBuilder.addDefine(
diff --git a/packages/engine/Source/Scene/Model/MaterialPipelineStage.js b/packages/engine/Source/Scene/Model/MaterialPipelineStage.js
index 0d2f200d53b..99f630f990d 100644
--- a/packages/engine/Source/Scene/Model/MaterialPipelineStage.js
+++ b/packages/engine/Source/Scene/Model/MaterialPipelineStage.js
@@ -12,15 +12,20 @@ import VertexAttributeSemantic from "../VertexAttributeSemantic.js";
import LightingModel from "./LightingModel.js";
import ModelUtility from "./ModelUtility.js";
-const Material = ModelComponents.Material;
-const MetallicRoughness = ModelComponents.MetallicRoughness;
-const SpecularGlossiness = ModelComponents.SpecularGlossiness;
+const {
+ Material,
+ MetallicRoughness,
+ SpecularGlossiness,
+ Specular,
+ Clearcoat,
+} = ModelComponents;
/**
* The material pipeline stage processes textures and other uniforms needed
* to render a primitive. This handles the following material types:
* * This function only handles the lighting calculations. Metallic/roughness - * and specular/glossy must be handled separately. See {@czm_pbrMetallicRoughnessMaterial}, {@czm_pbrSpecularGlossinessMaterial} and {@czm_defaultPbrMaterial} + * and specular/glossy must be handled separately. See {@MaterialStageFS} *
* - * @name czm_pbrlighting + * @name czm_pbrLighting * @glslFunction * - * @param {vec3} positionEC The position of the fragment in eye coordinates + * @param {vec3} viewDirectionEC Unit vector pointing from the fragment to the eye position * @param {vec3} normalEC The surface normal in eye coordinates * @param {vec3} lightDirectionEC Unit vector pointing to the light source in eye coordinates. - * @param {vec3} lightColorHdr radiance of the light source. This is a HDR value. - * @param {czm_pbrParameters} The computed PBR parameters. + * @param {czm_modelMaterial} The material properties. * @return {vec3} The computed HDR color - * - * @example - * czm_pbrParameters pbrParameters = czm_pbrMetallicRoughnessMaterial( - * baseColor, - * metallic, - * roughness - * ); - * vec3 color = czm_pbrlighting( - * positionEC, - * normalEC, - * lightDirectionEC, - * lightColorHdr, - * pbrParameters); */ -vec3 czm_pbrLighting( - vec3 positionEC, - vec3 normalEC, - vec3 lightDirectionEC, - vec3 lightColorHdr, - czm_pbrParameters pbrParameters -) +vec3 czm_pbrLighting(vec3 viewDirectionEC, vec3 normalEC, vec3 lightDirectionEC, czm_modelMaterial material) { - vec3 v = -normalize(positionEC); - vec3 l = normalize(lightDirectionEC); - vec3 h = normalize(v + l); - vec3 n = normalEC; - float NdotL = clamp(dot(n, l), 0.001, 1.0); - float NdotV = abs(dot(n, v)) + 0.001; - float NdotH = clamp(dot(n, h), 0.0, 1.0); - float LdotH = clamp(dot(l, h), 0.0, 1.0); - float VdotH = clamp(dot(v, h), 0.0, 1.0); + vec3 halfwayDirectionEC = normalize(viewDirectionEC + lightDirectionEC); + float VdotH = clamp(dot(viewDirectionEC, halfwayDirectionEC), 0.0, 1.0); + float NdotL = clamp(dot(normalEC, lightDirectionEC), 0.001, 1.0); - vec3 f0 = pbrParameters.f0; - float reflectance = max(max(f0.r, f0.g), f0.b); + vec3 f0 = material.specular; + float reflectance = czm_maximumComponent(f0); + // Typical dielectrics will have reflectance 0.04, so f90 will be 1.0. + // In this case, at grazing angle, all incident energy is reflected. vec3 f90 = vec3(clamp(reflectance * 25.0, 0.0, 1.0)); vec3 F = fresnelSchlick2(f0, f90, VdotH); - float alpha = pbrParameters.roughness; - float G = smithVisibilityGGX(alpha, NdotL, NdotV); - float D = GGX(alpha, NdotH); - vec3 specularContribution = F * G * D / (4.0 * NdotL * NdotV); + #if defined(USE_SPECULAR) + F *= material.specularWeight; + #endif + + float alpha = material.roughness; + #ifdef USE_ANISOTROPY + mat3 tbn = mat3(material.anisotropicT, material.anisotropicB, normalEC); + vec3 lightDirection = lightDirectionEC * tbn; + vec3 viewDirection = viewDirectionEC * tbn; + vec3 halfwayDirection = halfwayDirectionEC * tbn; + float anisotropyStrength = material.anisotropyStrength; + float tangentialRoughness = mix(alpha, 1.0, anisotropyStrength * anisotropyStrength); + float G = smithVisibilityGGX_anisotropic(alpha, tangentialRoughness, lightDirection, viewDirection); + float D = GGX_anisotropic(alpha, tangentialRoughness, halfwayDirection); + vec3 specularContribution = F * G * D; + #else + float specularStrength = computeDirectSpecularStrength(normalEC, lightDirectionEC, viewDirectionEC, halfwayDirectionEC, alpha); + vec3 specularContribution = F * specularStrength; + #endif - vec3 diffuseColor = pbrParameters.diffuseColor; + vec3 diffuseColor = material.diffuse; // F here represents the specular contribution vec3 diffuseContribution = (1.0 - F) * lambertianDiffuse(diffuseColor); // Lo = (diffuse + specular) * Li * NdotL - return (diffuseContribution + specularContribution) * NdotL * lightColorHdr; + return (diffuseContribution + specularContribution) * NdotL; } diff --git a/packages/engine/Source/Shaders/Builtin/Functions/pbrMetallicRoughnessMaterial.glsl b/packages/engine/Source/Shaders/Builtin/Functions/pbrMetallicRoughnessMaterial.glsl deleted file mode 100644 index 4ae262e867c..00000000000 --- a/packages/engine/Source/Shaders/Builtin/Functions/pbrMetallicRoughnessMaterial.glsl +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Compute parameters for physically based rendering using the - * metallic/roughness workflow. All inputs are linear; sRGB texture values must - * be decoded beforehand - * - * @name czm_pbrMetallicRoughnessMaterial - * @glslFunction - * - * @param {vec3} baseColor For dielectrics, this is the base color. For metals, this is the f0 value (reflectance at normal incidence) - * @param {float} metallic 0.0 indicates dielectric. 1.0 indicates metal. Values in between are allowed (e.g. to model rust or dirt); - * @param {float} roughness A value between 0.0 and 1.0 - * @return {czm_pbrParameters} parameters to pass into {@link czm_pbrLighting} - */ -czm_pbrParameters czm_pbrMetallicRoughnessMaterial( - vec3 baseColor, - float metallic, - float roughness -) -{ - czm_pbrParameters results; - - // roughness is authored as perceptual roughness - // square it to get material roughness - roughness = clamp(roughness, 0.0, 1.0); - results.roughness = roughness * roughness; - - // dielectrics use f0 = 0.04, metals use albedo as f0 - metallic = clamp(metallic, 0.0, 1.0); - const vec3 REFLECTANCE_DIELECTRIC = vec3(0.04); - vec3 f0 = mix(REFLECTANCE_DIELECTRIC, baseColor, metallic); - results.f0 = f0; - - // diffuse only applies to dielectrics. - results.diffuseColor = baseColor * (1.0 - f0) * (1.0 - metallic); - - return results; -} diff --git a/packages/engine/Source/Shaders/Builtin/Functions/pbrSpecularGlossinessMaterial.glsl b/packages/engine/Source/Shaders/Builtin/Functions/pbrSpecularGlossinessMaterial.glsl deleted file mode 100644 index 01dc7a5102a..00000000000 --- a/packages/engine/Source/Shaders/Builtin/Functions/pbrSpecularGlossinessMaterial.glsl +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Compute parameters for physically based rendering using the - * specular/glossy workflow. All inputs are linear; sRGB texture values must - * be decoded beforehand - * - * @name czm_pbrSpecularGlossinessMaterial - * @glslFunction - * - * @param {vec3} diffuse The diffuse color for dielectrics (non-metals) - * @param {vec3} specular The reflectance at normal incidence (f0) - * @param {float} glossiness A number from 0.0 to 1.0 indicating how smooth the surface is. - * @return {czm_pbrParameters} parameters to pass into {@link czm_pbrLighting} - */ -czm_pbrParameters czm_pbrSpecularGlossinessMaterial( - vec3 diffuse, - vec3 specular, - float glossiness -) -{ - czm_pbrParameters results; - - // glossiness is the opposite of roughness, but easier for artists to use. - float roughness = 1.0 - glossiness; - results.roughness = roughness * roughness; - - results.diffuseColor = diffuse * (1.0 - max(max(specular.r, specular.g), specular.b)); - results.f0 = specular; - - return results; -} diff --git a/packages/engine/Source/Shaders/Builtin/Structs/modelMaterial.glsl b/packages/engine/Source/Shaders/Builtin/Structs/modelMaterial.glsl index ff21e666cd2..3802a9a9a06 100644 --- a/packages/engine/Source/Shaders/Builtin/Structs/modelMaterial.glsl +++ b/packages/engine/Source/Shaders/Builtin/Structs/modelMaterial.glsl @@ -26,4 +26,18 @@ struct czm_modelMaterial { vec3 normalEC; float occlusion; vec3 emissive; +#ifdef USE_SPECULAR + float specularWeight; +#endif +#ifdef USE_ANISOTROPY + vec3 anisotropicT; + vec3 anisotropicB; + float anisotropyStrength; +#endif +#ifdef USE_CLEARCOAT + float clearcoatFactor; + float clearcoatRoughness; + vec3 clearcoatNormal; + // Add clearcoatF0 when KHR_materials_ior is implemented +#endif }; diff --git a/packages/engine/Source/Shaders/Builtin/Structs/pbrParameters.glsl b/packages/engine/Source/Shaders/Builtin/Structs/pbrParameters.glsl deleted file mode 100644 index e1d33418d83..00000000000 --- a/packages/engine/Source/Shaders/Builtin/Structs/pbrParameters.glsl +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Parameters for {@link czm_pbrLighting} - * - * @name czm_material - * @glslStruct - * - * @property {vec3} diffuseColor the diffuse color of the material for the lambert term of the rendering equation - * @property {float} roughness a value from 0.0 to 1.0 that indicates how rough the surface of the material is. - * @property {vec3} f0 The reflectance of the material at normal incidence - */ -struct czm_pbrParameters -{ - vec3 diffuseColor; - float roughness; - vec3 f0; -}; diff --git a/packages/engine/Source/Shaders/GlobeFS.glsl b/packages/engine/Source/Shaders/GlobeFS.glsl index 11072943caf..74ad34d886e 100644 --- a/packages/engine/Source/Shaders/GlobeFS.glsl +++ b/packages/engine/Source/Shaders/GlobeFS.glsl @@ -207,7 +207,7 @@ vec4 sampleAndBlend( #ifdef APPLY_COLOR_TO_ALPHA vec3 colorDiff = abs(color.rgb - colorToAlpha.rgb); - colorDiff.r = max(max(colorDiff.r, colorDiff.g), colorDiff.b); + colorDiff.r = czm_maximumComponent(colorDiff); alpha = czm_branchFreeTernary(colorDiff.r < colorToAlpha.a, 0.0, alpha); #endif diff --git a/packages/engine/Source/Shaders/Model/ImageBasedLightingStageFS.glsl b/packages/engine/Source/Shaders/Model/ImageBasedLightingStageFS.glsl index 22fda5197e4..e94ffd0a0dc 100644 --- a/packages/engine/Source/Shaders/Model/ImageBasedLightingStageFS.glsl +++ b/packages/engine/Source/Shaders/Model/ImageBasedLightingStageFS.glsl @@ -1,165 +1,243 @@ -vec3 proceduralIBL( - vec3 positionEC, - vec3 normalEC, - vec3 lightDirectionEC, - vec3 lightColorHdr, - czm_pbrParameters pbrParameters -) { - vec3 v = -positionEC; - vec3 positionWC = vec3(czm_inverseView * vec4(positionEC, 1.0)); - vec3 vWC = -normalize(positionWC); - vec3 l = normalize(lightDirectionEC); - vec3 n = normalEC; - vec3 r = normalize(czm_inverseViewRotation * normalize(reflect(v, n))); +/** + * Compute some metrics for a procedural sky lighting model + * + * @param {vec3} positionWC The position of the fragment in world coordinates. + * @param {vec3} reflectionWC A unit vector in the direction of the reflection, in world coordinates. + * @return {vec3} The dot products of the horizon and reflection directions with the nadir, and an atmosphere boundary distance. + */ +vec3 getProceduralSkyMetrics(vec3 positionWC, vec3 reflectionWC) +{ + // Figure out if the reflection vector hits the ellipsoid + float horizonDotNadir = 1.0 - min(1.0, czm_ellipsoidRadii.x / length(positionWC)); + float reflectionDotNadir = dot(reflectionWC, normalize(positionWC)); + float atmosphereHeight = 0.05; + float smoothstepHeight = smoothstep(0.0, atmosphereHeight, horizonDotNadir); + return vec3(horizonDotNadir, reflectionDotNadir, smoothstepHeight); +} - float NdotL = clamp(dot(n, l), 0.001, 1.0); - float NdotV = abs(dot(n, v)) + 0.001; +/** + * Compute the diffuse irradiance for a procedural sky lighting model + * + * @param {vec3} skyMetrics The dot products of the horizon and reflection directions with the nadir, and an atmosphere boundary distance. + * @return {vec3} The computed diffuse irradiance + */ +vec3 getProceduralDiffuseIrradiance(vec3 skyMetrics) +{ + vec3 blueSkyDiffuseColor = vec3(0.7, 0.85, 0.9); + float diffuseIrradianceFromEarth = (1.0 - skyMetrics.x) * (skyMetrics.y * 0.25 + 0.75) * skyMetrics.z; + float diffuseIrradianceFromSky = (1.0 - skyMetrics.z) * (1.0 - (skyMetrics.y * 0.25 + 0.25)); + return blueSkyDiffuseColor * clamp(diffuseIrradianceFromEarth + diffuseIrradianceFromSky, 0.0, 1.0); +} - // Figure out if the reflection vector hits the ellipsoid - float vertexRadius = length(positionWC); - float horizonDotNadir = 1.0 - min(1.0, czm_ellipsoidRadii.x / vertexRadius); - float reflectionDotNadir = dot(r, normalize(positionWC)); +/** + * Compute the specular irradiance for a procedural sky lighting model + * + * @param {vec3} skyMetrics The dot products of the horizon and reflection directions with the nadir, and an atmosphere boundary distance. + * @return {vec3} The computed specular irradiance + */ +vec3 getProceduralSpecularIrradiance(vec3 reflectionWC, vec3 skyMetrics, float roughness) +{ // Flipping the X vector is a cheap way to get the inverse of czm_temeToPseudoFixed, since that's a rotation about Z. - r.x = -r.x; - r = -normalize(czm_temeToPseudoFixed * r); - r.x = -r.x; - - vec3 diffuseColor = pbrParameters.diffuseColor; - float roughness = pbrParameters.roughness; - vec3 specularColor = pbrParameters.f0; + reflectionWC.x = -reflectionWC.x; + reflectionWC = -normalize(czm_temeToPseudoFixed * reflectionWC); + reflectionWC.x = -reflectionWC.x; float inverseRoughness = 1.04 - roughness; inverseRoughness *= inverseRoughness; - vec3 sceneSkyBox = czm_textureCube(czm_environmentMap, r).rgb * inverseRoughness; + vec3 sceneSkyBox = czm_textureCube(czm_environmentMap, reflectionWC).rgb * inverseRoughness; - float atmosphereHeight = 0.05; - float blendRegionSize = 0.1 * ((1.0 - inverseRoughness) * 8.0 + 1.1 - horizonDotNadir); - float blendRegionOffset = roughness * -1.0; - float farAboveHorizon = clamp(horizonDotNadir - blendRegionSize * 0.5 + blendRegionOffset, 1.0e-10 - blendRegionSize, 0.99999); - float aroundHorizon = clamp(horizonDotNadir + blendRegionSize * 0.5, 1.0e-10 - blendRegionSize, 0.99999); - float farBelowHorizon = clamp(horizonDotNadir + blendRegionSize * 1.5, 1.0e-10 - blendRegionSize, 0.99999); - float smoothstepHeight = smoothstep(0.0, atmosphereHeight, horizonDotNadir); - vec3 belowHorizonColor = mix(vec3(0.1, 0.15, 0.25), vec3(0.4, 0.7, 0.9), smoothstepHeight); + // Compute colors at different angles relative to the horizon + vec3 belowHorizonColor = mix(vec3(0.1, 0.15, 0.25), vec3(0.4, 0.7, 0.9), skyMetrics.z); vec3 nadirColor = belowHorizonColor * 0.5; vec3 aboveHorizonColor = mix(vec3(0.9, 1.0, 1.2), belowHorizonColor, roughness * 0.5); - vec3 blueSkyColor = mix(vec3(0.18, 0.26, 0.48), aboveHorizonColor, reflectionDotNadir * inverseRoughness * 0.5 + 0.75); - vec3 zenithColor = mix(blueSkyColor, sceneSkyBox, smoothstepHeight); - vec3 blueSkyDiffuseColor = vec3(0.7, 0.85, 0.9); - float diffuseIrradianceFromEarth = (1.0 - horizonDotNadir) * (reflectionDotNadir * 0.25 + 0.75) * smoothstepHeight; - float diffuseIrradianceFromSky = (1.0 - smoothstepHeight) * (1.0 - (reflectionDotNadir * 0.25 + 0.25)); - vec3 diffuseIrradiance = blueSkyDiffuseColor * clamp(diffuseIrradianceFromEarth + diffuseIrradianceFromSky, 0.0, 1.0); - float notDistantRough = (1.0 - horizonDotNadir * roughness * 0.8); - vec3 specularIrradiance = mix(zenithColor, aboveHorizonColor, smoothstep(farAboveHorizon, aroundHorizon, reflectionDotNadir) * notDistantRough); - specularIrradiance = mix(specularIrradiance, belowHorizonColor, smoothstep(aroundHorizon, farBelowHorizon, reflectionDotNadir) * inverseRoughness); - specularIrradiance = mix(specularIrradiance, nadirColor, smoothstep(farBelowHorizon, 1.0, reflectionDotNadir) * inverseRoughness); - - // Luminance model from page 40 of http://silviojemma.com/public/papers/lighting/spherical-harmonic-lighting.pdf - #ifdef USE_SUN_LUMINANCE - // Angle between sun and zenith - float LdotZenith = clamp(dot(normalize(czm_inverseViewRotation * l), vWC), 0.001, 1.0); + vec3 blueSkyColor = mix(vec3(0.18, 0.26, 0.48), aboveHorizonColor, skyMetrics.y * inverseRoughness * 0.5 + 0.75); + vec3 zenithColor = mix(blueSkyColor, sceneSkyBox, skyMetrics.z); + + // Compute blend zones + float blendRegionSize = 0.1 * ((1.0 - inverseRoughness) * 8.0 + 1.1 - skyMetrics.x); + float blendRegionOffset = roughness * -1.0; + float farAboveHorizon = clamp(skyMetrics.x - blendRegionSize * 0.5 + blendRegionOffset, 1.0e-10 - blendRegionSize, 0.99999); + float aroundHorizon = clamp(skyMetrics.x + blendRegionSize * 0.5, 1.0e-10 - blendRegionSize, 0.99999); + float farBelowHorizon = clamp(skyMetrics.x + blendRegionSize * 1.5, 1.0e-10 - blendRegionSize, 0.99999); + + // Blend colors + float notDistantRough = (1.0 - skyMetrics.x * roughness * 0.8); + vec3 specularIrradiance = mix(zenithColor, aboveHorizonColor, smoothstep(farAboveHorizon, aroundHorizon, skyMetrics.y) * notDistantRough); + specularIrradiance = mix(specularIrradiance, belowHorizonColor, smoothstep(aroundHorizon, farBelowHorizon, skyMetrics.y) * inverseRoughness); + specularIrradiance = mix(specularIrradiance, nadirColor, smoothstep(farBelowHorizon, 1.0, skyMetrics.y) * inverseRoughness); + + return specularIrradiance; +} + +#ifdef USE_SUN_LUMINANCE +float clampedDot(vec3 x, vec3 y) +{ + return clamp(dot(x, y), 0.001, 1.0); +} +/** + * Sun luminance following the "CIE Clear Sky Model" + * See page 40 of https://3dvar.com/Green2003Spherical.pdf + * + * @param {vec3} positionWC The position of the fragment in world coordinates. + * @param {vec3} normalEC The surface normal in eye coordinates. + * @param {vec3} lightDirectionEC Unit vector pointing to the light source in eye coordinates. + * @return {float} The computed sun luminance. + */ +float getSunLuminance(vec3 positionWC, vec3 normalEC, vec3 lightDirectionEC) +{ + vec3 normalWC = normalize(czm_inverseViewRotation * normalEC); + vec3 lightDirectionWC = normalize(czm_inverseViewRotation * lightDirectionEC); + vec3 vWC = -normalize(positionWC); + + // Angle between sun and zenith. + float LdotZenith = clampedDot(lightDirectionWC, vWC); float S = acos(LdotZenith); // Angle between zenith and current pixel - float NdotZenith = clamp(dot(normalize(czm_inverseViewRotation * n), vWC), 0.001, 1.0); + float NdotZenith = clampedDot(normalWC, vWC); // Angle between sun and current pixel + float NdotL = clampedDot(normalEC, lightDirectionEC); float gamma = acos(NdotL); - float numerator = ((0.91 + 10.0 * exp(-3.0 * gamma) + 0.45 * pow(NdotL, 2.0)) * (1.0 - exp(-0.32 / NdotZenith))); - float denominator = (0.91 + 10.0 * exp(-3.0 * S) + 0.45 * pow(LdotZenith,2.0)) * (1.0 - exp(-0.32)); - float luminance = model_luminanceAtZenith * (numerator / denominator); - #endif + float numerator = ((0.91 + 10.0 * exp(-3.0 * gamma) + 0.45 * NdotL * NdotL) * (1.0 - exp(-0.32 / NdotZenith))); + float denominator = (0.91 + 10.0 * exp(-3.0 * S) + 0.45 * LdotZenith * LdotZenith) * (1.0 - exp(-0.32)); + return model_luminanceAtZenith * (numerator / denominator); +} +#endif + +/** + * Compute the light contribution from a procedural sky model + * + * @param {vec3} positionEC The position of the fragment in eye coordinates. + * @param {vec3} normalEC The surface normal in eye coordinates. + * @param {vec3} lightDirectionEC Unit vector pointing to the light source in eye coordinates. + * @param {czm_modelMaterial} The material properties. + * @return {vec3} The computed HDR color + */ + vec3 proceduralIBL( + vec3 positionEC, + vec3 normalEC, + vec3 lightDirectionEC, + czm_modelMaterial material +) { + vec3 viewDirectionEC = -normalize(positionEC); + vec3 positionWC = vec3(czm_inverseView * vec4(positionEC, 1.0)); + vec3 reflectionWC = normalize(czm_inverseViewRotation * normalize(reflect(viewDirectionEC, normalEC))); + vec3 skyMetrics = getProceduralSkyMetrics(positionWC, reflectionWC); + + float roughness = material.roughness; + vec3 f0 = material.specular; + + vec3 specularIrradiance = getProceduralSpecularIrradiance(reflectionWC, skyMetrics, roughness); + float NdotV = abs(dot(normalEC, viewDirectionEC)) + 0.001; vec2 brdfLut = texture(czm_brdfLut, vec2(NdotV, roughness)).rg; - vec3 iblColor = (diffuseIrradiance * diffuseColor * model_iblFactor.x) + (specularIrradiance * czm_srgbToLinear(specularColor * brdfLut.x + brdfLut.y) * model_iblFactor.y); - float maximumComponent = max(max(lightColorHdr.x, lightColorHdr.y), lightColorHdr.z); - vec3 lightColor = lightColorHdr / max(maximumComponent, 1.0); - iblColor *= lightColor; + vec3 specularColor = czm_srgbToLinear(f0 * brdfLut.x + brdfLut.y); + vec3 specularContribution = specularIrradiance * specularColor * model_iblFactor.y; + #ifdef USE_SPECULAR + specularContribution *= material.specularWeight; + #endif + + vec3 diffuseIrradiance = getProceduralDiffuseIrradiance(skyMetrics); + vec3 diffuseColor = material.diffuse; + vec3 diffuseContribution = diffuseIrradiance * diffuseColor * model_iblFactor.x; - #ifdef USE_SUN_LUMINANCE - iblColor *= luminance; + vec3 iblColor = specularContribution + diffuseContribution; + + #ifdef USE_SUN_LUMINANCE + iblColor *= getSunLuminance(positionWC, normalEC, lightDirectionEC); #endif return iblColor; } +#ifdef DIFFUSE_IBL +vec3 computeDiffuseIBL(vec3 cubeDir) +{ + #ifdef CUSTOM_SPHERICAL_HARMONICS + return czm_sphericalHarmonics(cubeDir, model_sphericalHarmonicCoefficients); + #else + return czm_sphericalHarmonics(cubeDir, czm_sphericalHarmonicCoefficients); + #endif +} +#endif + +#ifdef SPECULAR_IBL +vec3 sampleSpecularEnvironment(vec3 cubeDir, float roughness) +{ + #ifdef CUSTOM_SPECULAR_IBL + float maxLod = model_specularEnvironmentMapsMaximumLOD; + float lod = roughness * maxLod; + return czm_sampleOctahedralProjection(model_specularEnvironmentMaps, model_specularEnvironmentMapsSize, cubeDir, lod, maxLod); + #else + float maxLod = czm_specularEnvironmentMapsMaximumLOD; + float lod = roughness * maxLod; + return czm_sampleOctahedralProjection(czm_specularEnvironmentMaps, czm_specularEnvironmentMapSize, cubeDir, lod, maxLod); + #endif +} +vec3 computeSpecularIBL(vec3 cubeDir, float NdotV, float VdotH, vec3 f0, float roughness) +{ + float reflectance = czm_maximumComponent(f0); + vec3 f90 = vec3(clamp(reflectance * 25.0, 0.0, 1.0)); + vec3 F = fresnelSchlick2(f0, f90, VdotH); + + vec2 brdfLut = texture(czm_brdfLut, vec2(NdotV, roughness)).rg; + vec3 specularSample = sampleSpecularEnvironment(cubeDir, roughness); + + return specularSample * (F * brdfLut.x + brdfLut.y); +} +#endif + #if defined(DIFFUSE_IBL) || defined(SPECULAR_IBL) +/** + * Compute the light contributions from environment maps and spherical harmonic coefficients + * + * @param {vec3} viewDirectionEC Unit vector pointing from the fragment to the eye position + * @param {vec3} normalEC The surface normal in eye coordinates + * @param {vec3} lightDirectionEC Unit vector pointing to the light source in eye coordinates. + * @param {czm_modelMaterial} The material properties. + * @return {vec3} The computed HDR color + */ vec3 textureIBL( - vec3 positionEC, + vec3 viewDirectionEC, vec3 normalEC, vec3 lightDirectionEC, - czm_pbrParameters pbrParameters + czm_modelMaterial material ) { - vec3 diffuseColor = pbrParameters.diffuseColor; - float roughness = pbrParameters.roughness; - vec3 specularColor = pbrParameters.f0; - - vec3 v = -positionEC; - vec3 n = normalEC; - vec3 l = normalize(lightDirectionEC); - vec3 h = normalize(v + l); - - float NdotV = abs(dot(n, v)) + 0.001; - float VdotH = clamp(dot(v, h), 0.0, 1.0); - - const mat3 yUpToZUp = mat3( - -1.0, 0.0, 0.0, - 0.0, 0.0, -1.0, - 0.0, 1.0, 0.0 - ); - vec3 cubeDir = normalize(yUpToZUp * model_iblReferenceFrameMatrix * normalize(reflect(-v, n))); - - #ifdef DIFFUSE_IBL - #ifdef CUSTOM_SPHERICAL_HARMONICS - vec3 diffuseIrradiance = czm_sphericalHarmonics(cubeDir, model_sphericalHarmonicCoefficients); - #else - vec3 diffuseIrradiance = czm_sphericalHarmonics(cubeDir, czm_sphericalHarmonicCoefficients); - #endif - #else - vec3 diffuseIrradiance = vec3(0.0); - #endif + // Find the direction in which to sample the environment map + vec3 cubeDir = normalize(model_iblReferenceFrameMatrix * normalize(reflect(-viewDirectionEC, normalEC))); + + #ifdef DIFFUSE_IBL + vec3 diffuseContribution = computeDiffuseIBL(cubeDir) * material.diffuse; + #else + vec3 diffuseContribution = vec3(0.0); + #endif + + float roughness = material.roughness; + + #ifdef USE_ANISOTROPY + // Update environment map sampling direction to account for anisotropic distortion of specular reflection + vec3 anisotropyDirection = material.anisotropicB; + vec3 anisotropicTangent = cross(anisotropyDirection, viewDirectionEC); + vec3 anisotropicNormal = cross(anisotropicTangent, anisotropyDirection); + float bendFactor = 1.0 - material.anisotropyStrength * (1.0 - roughness); + float bendFactorPow4 = bendFactor * bendFactor * bendFactor * bendFactor; + vec3 bentNormal = normalize(mix(anisotropicNormal, normalEC, bendFactorPow4)); + cubeDir = normalize(model_iblReferenceFrameMatrix * normalize(reflect(-viewDirectionEC, bentNormal))); + #endif #ifdef SPECULAR_IBL - vec3 r0 = specularColor.rgb; - float reflectance = max(max(r0.r, r0.g), r0.b); - vec3 r90 = vec3(clamp(reflectance * 25.0, 0.0, 1.0)); - vec3 F = fresnelSchlick2(r0, r90, VdotH); - - vec2 brdfLut = texture(czm_brdfLut, vec2(NdotV, roughness)).rg; - #ifdef CUSTOM_SPECULAR_IBL - vec3 specularIBL = czm_sampleOctahedralProjection(model_specularEnvironmentMaps, model_specularEnvironmentMapsSize, cubeDir, roughness * model_specularEnvironmentMapsMaximumLOD, model_specularEnvironmentMapsMaximumLOD); - #else - vec3 specularIBL = czm_sampleOctahedralProjection(czm_specularEnvironmentMaps, czm_specularEnvironmentMapSize, cubeDir, roughness * czm_specularEnvironmentMapsMaximumLOD, czm_specularEnvironmentMapsMaximumLOD); - #endif - specularIBL *= F * brdfLut.x + brdfLut.y; - #else - vec3 specularIBL = vec3(0.0); + float NdotV = abs(dot(normalEC, viewDirectionEC)) + 0.001; + vec3 halfwayDirectionEC = normalize(viewDirectionEC + lightDirectionEC); + float VdotH = clamp(dot(viewDirectionEC, halfwayDirectionEC), 0.0, 1.0); + vec3 f0 = material.specular; + vec3 specularContribution = computeSpecularIBL(cubeDir, NdotV, VdotH, f0, roughness); + #else + vec3 specularContribution = vec3(0.0); + #endif + + #ifdef USE_SPECULAR + specularContribution *= material.specularWeight; #endif - return diffuseColor * diffuseIrradiance + specularColor * specularIBL; + return diffuseContribution + specularContribution; } #endif - -vec3 imageBasedLightingStage( - vec3 positionEC, - vec3 normalEC, - vec3 lightDirectionEC, - vec3 lightColorHdr, - czm_pbrParameters pbrParameters -) { - #if defined(DIFFUSE_IBL) || defined(SPECULAR_IBL) - // Environment maps were provided, use them for IBL - return textureIBL( - positionEC, - normalEC, - lightDirectionEC, - pbrParameters - ); - #else - // Use the procedural IBL if there are no environment maps - return proceduralIBL( - positionEC, - normalEC, - lightDirectionEC, - lightColorHdr, - pbrParameters - ); - #endif -} \ No newline at end of file diff --git a/packages/engine/Source/Shaders/Model/LightingStageFS.glsl b/packages/engine/Source/Shaders/Model/LightingStageFS.glsl index 77965e25f69..2b04c170871 100644 --- a/packages/engine/Source/Shaders/Model/LightingStageFS.glsl +++ b/packages/engine/Source/Shaders/Model/LightingStageFS.glsl @@ -1,72 +1,137 @@ -#ifdef LIGHTING_PBR -vec3 computePbrLighting(czm_modelMaterial inputMaterial, ProcessedAttributes attributes) +#ifdef USE_IBL_LIGHTING +vec3 computeIBL(vec3 position, vec3 normal, vec3 lightDirection, vec3 lightColorHdr, czm_modelMaterial material) { - czm_pbrParameters pbrParameters; - pbrParameters.diffuseColor = inputMaterial.diffuse; - pbrParameters.f0 = inputMaterial.specular; - pbrParameters.roughness = inputMaterial.roughness; - - #ifdef USE_CUSTOM_LIGHT_COLOR - vec3 lightColorHdr = model_lightColorHdr; + #if defined(DIFFUSE_IBL) || defined(SPECULAR_IBL) + // Environment maps were provided, use them for IBL + vec3 viewDirection = -normalize(position); + vec3 iblColor = textureIBL(viewDirection, normal, lightDirection, material); #else - vec3 lightColorHdr = czm_lightColorHdr; + // Use procedural IBL if there are no environment maps + vec3 imageBasedLighting = proceduralIBL(position, normal, lightDirection, material); + float maximumComponent = czm_maximumComponent(lightColorHdr); + vec3 clampedLightColor = lightColorHdr / max(maximumComponent, 1.0); + vec3 iblColor = clampedLightColor * imageBasedLighting; #endif + return iblColor * material.occlusion; +} +#endif + +#ifdef USE_CLEARCOAT +vec3 addClearcoatReflection(vec3 baseLayerColor, vec3 position, vec3 lightDirection, vec3 lightColorHdr, czm_modelMaterial material) +{ + vec3 viewDirection = -normalize(position); + vec3 halfwayDirection = normalize(viewDirection + lightDirection); + vec3 normal = material.clearcoatNormal; + float NdotL = clamp(dot(normal, lightDirection), 0.001, 1.0); + + // clearcoatF0 = vec3(pow((ior - 1.0) / (ior + 1.0), 2.0)), but without KHR_materials_ior, ior is a constant 1.5. + vec3 f0 = vec3(0.04); + vec3 f90 = vec3(1.0); + // Note: clearcoat Fresnel computed with dot(n, v) instead of dot(v, h). + // This is to make it energy conserving with a simple layering function. + float NdotV = clamp(dot(normal, viewDirection), 0.0, 1.0); + vec3 F = fresnelSchlick2(f0, f90, NdotV); - vec3 color = inputMaterial.diffuse; - #ifdef HAS_NORMALS - color = czm_pbrLighting( - attributes.positionEC, - inputMaterial.normalEC, - czm_lightDirectionEC, - lightColorHdr, - pbrParameters - ); - - #ifdef USE_IBL_LIGHTING - color += imageBasedLightingStage( - attributes.positionEC, - inputMaterial.normalEC, - czm_lightDirectionEC, - lightColorHdr, - pbrParameters - ); + // compute specular reflection from direct lighting + float roughness = material.clearcoatRoughness; + float directStrength = computeDirectSpecularStrength(normal, lightDirection, viewDirection, halfwayDirection, roughness); + vec3 directReflection = F * directStrength * NdotL; + vec3 color = lightColorHdr * directReflection; + + #ifdef SPECULAR_IBL + // Find the direction in which to sample the environment map + vec3 cubeDir = normalize(model_iblReferenceFrameMatrix * normalize(reflect(-viewDirection, normal))); + vec3 iblColor = computeSpecularIBL(cubeDir, NdotV, NdotV, f0, roughness); + color += iblColor * material.occlusion; + #elif defined(USE_IBL_LIGHTING) + vec3 positionWC = vec3(czm_inverseView * vec4(position, 1.0)); + vec3 reflectionWC = normalize(czm_inverseViewRotation * normalize(reflect(viewDirection, normal))); + vec3 skyMetrics = getProceduralSkyMetrics(positionWC, reflectionWC); + + vec3 specularIrradiance = getProceduralSpecularIrradiance(reflectionWC, skyMetrics, roughness); + vec2 brdfLut = texture(czm_brdfLut, vec2(NdotV, roughness)).rg; + vec3 specularColor = czm_srgbToLinear(f0 * brdfLut.x + brdfLut.y); + vec3 iblColor = specularIrradiance * specularColor * model_iblFactor.y; + #ifdef USE_SUN_LUMINANCE + iblColor *= getSunLuminance(positionWC, normal, lightDirection); #endif + float maximumComponent = czm_maximumComponent(lightColorHdr); + vec3 clampedLightColor = lightColorHdr / max(maximumComponent, 1.0); + color += clampedLightColor* iblColor * material.occlusion; + #endif + + float clearcoatFactor = material.clearcoatFactor; + vec3 clearcoatColor = color * clearcoatFactor; + + // Dim base layer based on transmission loss through clearcoat + return baseLayerColor * (1.0 - clearcoatFactor * F) + clearcoatColor; +} +#endif + +#if defined(LIGHTING_PBR) && defined(HAS_NORMALS) +vec3 computePbrLighting(in czm_modelMaterial material, in vec3 position) +{ + #ifdef USE_CUSTOM_LIGHT_COLOR + vec3 lightColorHdr = model_lightColorHdr; + #else + vec3 lightColorHdr = czm_lightColorHdr; #endif - color *= inputMaterial.occlusion; - color += inputMaterial.emissive; + vec3 viewDirection = -normalize(position); + vec3 normal = material.normalEC; + vec3 lightDirection = normalize(czm_lightDirectionEC); + + vec3 directLighting = czm_pbrLighting(viewDirection, normal, lightDirection, material); + vec3 directColor = lightColorHdr * directLighting; - // In HDR mode, the frame buffer is in linear color space. The - // post-processing stages (see PostProcessStageCollection) will handle - // tonemapping. However, if HDR is not enabled, we must tonemap else large - // values may be clamped to 1.0 - #ifndef HDR - color = czm_acesTonemapping(color); - #endif + // Accumulate colors from base layer + vec3 color = directColor + material.emissive; + #ifdef USE_IBL_LIGHTING + color += computeIBL(position, normal, lightDirection, lightColorHdr, material); + #endif + + #ifdef USE_CLEARCOAT + color = addClearcoatReflection(color, position, lightDirection, lightColorHdr, material); + #endif return color; } #endif +/** + * Compute the material color under the current lighting conditions. + * All other material properties are passed through so further stages + * have access to them. + * + * @param {czm_modelMaterial} material The material properties from {@MaterialStageFS} + * @param {ProcessedAttributes} attributes + */ void lightingStage(inout czm_modelMaterial material, ProcessedAttributes attributes) { - // Even though the lighting will only set the diffuse color, - // pass all other properties so further stages have access to them. - vec3 color = vec3(0.0); - #ifdef LIGHTING_PBR - color = computePbrLighting(material, attributes); + #ifdef HAS_NORMALS + vec3 color = computePbrLighting(material, attributes.positionEC); + #else + vec3 color = material.diffuse * material.occlusion + material.emissive; + #endif + // In HDR mode, the frame buffer is in linear color space. The + // post-processing stages (see PostProcessStageCollection) will handle + // tonemapping. However, if HDR is not enabled, we must tonemap else large + // values may be clamped to 1.0 + #ifndef HDR + color = czm_acesTonemapping(color); + #endif #else // unlit - color = material.diffuse; + vec3 color = material.diffuse; #endif #ifdef HAS_POINT_CLOUD_COLOR_STYLE - // The colors resulting from point cloud styles are adjusted differently. - color = czm_gammaCorrect(color); + // The colors resulting from point cloud styles are adjusted differently. + color = czm_gammaCorrect(color); #elif !defined(HDR) - // If HDR is not enabled, the frame buffer stores sRGB colors rather than - // linear colors so the linear value must be converted. - color = czm_linearToSrgb(color); + // If HDR is not enabled, the frame buffer stores sRGB colors rather than + // linear colors so the linear value must be converted. + color = czm_linearToSrgb(color); #endif material.diffuse = color; diff --git a/packages/engine/Source/Shaders/Model/MaterialStageFS.glsl b/packages/engine/Source/Shaders/Model/MaterialStageFS.glsl index 784c9274b97..b4326757bd3 100644 --- a/packages/engine/Source/Shaders/Model/MaterialStageFS.glsl +++ b/packages/engine/Source/Shaders/Model/MaterialStageFS.glsl @@ -16,211 +16,473 @@ vec2 computeTextureTransform(vec2 texCoord, mat3 textureTransform) return vec2(textureTransform * vec3(texCoord, 1.0)); } -#ifdef HAS_NORMALS -vec3 computeNormal(ProcessedAttributes attributes) +#ifdef HAS_NORMAL_TEXTURE +vec2 getNormalTexCoords() { - // Geometry normal. This is already normalized - vec3 ng = attributes.normalEC; + vec2 texCoord = TEXCOORD_NORMAL; + #ifdef HAS_NORMAL_TEXTURE_TRANSFORM + texCoord = vec2(u_normalTextureTransform * vec3(texCoord, 1.0)); + #endif + return texCoord; +} +#endif - vec3 normal = ng; - #if defined(HAS_NORMAL_TEXTURE) && !defined(HAS_WIREFRAME) - vec2 normalTexCoords = TEXCOORD_NORMAL; - #ifdef HAS_NORMAL_TEXTURE_TRANSFORM - normalTexCoords = computeTextureTransform(normalTexCoords, u_normalTextureTransform); - #endif +#if defined(HAS_NORMAL_TEXTURE) || defined(HAS_CLEARCOAT_NORMAL_TEXTURE) +vec3 computeTangent(in vec3 position, in vec2 normalTexCoords) +{ + vec2 tex_dx = dFdx(normalTexCoords); + vec2 tex_dy = dFdy(normalTexCoords); + float determinant = tex_dx.x * tex_dy.y - tex_dy.x * tex_dx.y; + vec3 tangent = tex_dy.t * dFdx(position) - tex_dx.t * dFdy(position); + return tangent / determinant; +} +#endif - // If HAS_BITANGENTS is set, then HAS_TANGENTS is also set - #ifdef HAS_BITANGENTS - vec3 t = attributes.tangentEC; - vec3 b = attributes.bitangentEC; - mat3 tbn = mat3(t, b, ng); - vec3 n = texture(u_normalTexture, normalTexCoords).rgb; - normal = normalize(tbn * (2.0 * n - 1.0)); - #elif (__VERSION__ == 300 || defined(GL_OES_standard_derivatives)) - // If derivatives are available (not IE 10), compute tangents - vec3 positionEC = attributes.positionEC; - vec3 pos_dx = dFdx(positionEC); - vec3 pos_dy = dFdy(positionEC); - vec3 tex_dx = dFdx(vec3(normalTexCoords,0.0)); - vec3 tex_dy = dFdy(vec3(normalTexCoords,0.0)); - vec3 t = (tex_dy.t * pos_dx - tex_dx.t * pos_dy) / (tex_dx.s * tex_dy.t - tex_dy.s * tex_dx.t); - t = normalize(t - ng * dot(ng, t)); - vec3 b = normalize(cross(ng, t)); - mat3 tbn = mat3(t, b, ng); - vec3 n = texture(u_normalTexture, normalTexCoords).rgb; - normal = normalize(tbn * (2.0 * n - 1.0)); - #endif +#ifdef USE_ANISOTROPY +struct NormalInfo { + vec3 tangent; + vec3 bitangent; + vec3 normal; + vec3 geometryNormal; +}; + +NormalInfo getNormalInfo(ProcessedAttributes attributes) +{ + vec3 geometryNormal = attributes.normalEC; + #ifdef HAS_NORMAL_TEXTURE + vec2 normalTexCoords = getNormalTexCoords(); + #endif + + #ifdef HAS_BITANGENTS + vec3 tangent = attributes.tangentEC; + vec3 bitangent = attributes.bitangentEC; + #else // Assume HAS_NORMAL_TEXTURE + vec3 tangent = computeTangent(attributes.positionEC, normalTexCoords); + tangent = normalize(tangent - geometryNormal * dot(geometryNormal, tangent)); + vec3 bitangent = normalize(cross(geometryNormal, tangent)); + #endif + + #ifdef HAS_NORMAL_TEXTURE + mat3 tbn = mat3(tangent, bitangent, geometryNormal); + vec3 normalSample = texture(u_normalTexture, normalTexCoords).rgb; + vec3 normal = normalize(tbn * (2.0 * normalSample - 1.0)); + #else + vec3 normal = geometryNormal; #endif #ifdef HAS_DOUBLE_SIDED_MATERIAL - if (czm_backFacing()) { - normal = -normal; - } + if (czm_backFacing()) { + tangent *= -1.0; + bitangent *= -1.0; + normal *= -1.0; + geometryNormal *= -1.0; + } #endif - return normal; + NormalInfo normalInfo; + normalInfo.tangent = tangent; + normalInfo.bitangent = bitangent; + normalInfo.normal = normal; + normalInfo.geometryNormal = geometryNormal; + + return normalInfo; } #endif -void materialStage(inout czm_modelMaterial material, ProcessedAttributes attributes, SelectedFeature feature) +#if defined(HAS_NORMAL_TEXTURE) && !defined(HAS_WIREFRAME) +vec3 getNormalFromTexture(ProcessedAttributes attributes, vec3 geometryNormal) { - #ifdef HAS_NORMALS - material.normalEC = computeNormal(attributes); + vec2 normalTexCoords = getNormalTexCoords(); + + // If HAS_BITANGENTS is set, then HAS_TANGENTS is also set + #ifdef HAS_BITANGENTS + vec3 t = attributes.tangentEC; + vec3 b = attributes.bitangentEC; + #else + vec3 t = computeTangent(attributes.positionEC, normalTexCoords); + t = normalize(t - geometryNormal * dot(geometryNormal, t)); + vec3 b = normalize(cross(geometryNormal, t)); #endif - vec4 baseColorWithAlpha = vec4(1.0); - // Regardless of whether we use PBR, set a base color - #ifdef HAS_BASE_COLOR_TEXTURE - vec2 baseColorTexCoords = TEXCOORD_BASE_COLOR; + mat3 tbn = mat3(t, b, geometryNormal); + vec3 n = texture(u_normalTexture, normalTexCoords).rgb; + vec3 textureNormal = normalize(tbn * (2.0 * n - 1.0)); - #ifdef HAS_BASE_COLOR_TEXTURE_TRANSFORM - baseColorTexCoords = computeTextureTransform(baseColorTexCoords, u_baseColorTextureTransform); - #endif + return textureNormal; +} +#endif - baseColorWithAlpha = czm_srgbToLinear(texture(u_baseColorTexture, baseColorTexCoords)); +#ifdef HAS_CLEARCOAT_NORMAL_TEXTURE +vec3 getClearcoatNormalFromTexture(ProcessedAttributes attributes, vec3 geometryNormal) +{ + vec2 normalTexCoords = TEXCOORD_CLEARCOAT_NORMAL; + #ifdef HAS_CLEARCOAT_NORMAL_TEXTURE_TRANSFORM + normalTexCoords = vec2(u_clearcoatNormalTextureTransform * vec3(normalTexCoords, 1.0)); + #endif - #ifdef HAS_BASE_COLOR_FACTOR - baseColorWithAlpha *= u_baseColorFactor; - #endif - #elif defined(HAS_BASE_COLOR_FACTOR) - baseColorWithAlpha = u_baseColorFactor; + // If HAS_BITANGENTS is set, then HAS_TANGENTS is also set + #ifdef HAS_BITANGENTS + vec3 t = attributes.tangentEC; + vec3 b = attributes.bitangentEC; + #else + vec3 t = computeTangent(attributes.positionEC, normalTexCoords); + t = normalize(t - geometryNormal * dot(geometryNormal, t)); + vec3 b = normalize(cross(geometryNormal, t)); #endif - #ifdef HAS_POINT_CLOUD_COLOR_STYLE - baseColorWithAlpha = v_pointCloudColor; - #elif defined(HAS_COLOR_0) - vec4 color = attributes.color_0; - // .pnts files store colors in the sRGB color space - #ifdef HAS_SRGB_COLOR - color = czm_srgbToLinear(color); - #endif - baseColorWithAlpha *= color; + mat3 tbn = mat3(t, b, geometryNormal); + vec3 n = texture(u_clearcoatNormalTexture, normalTexCoords).rgb; + vec3 textureNormal = normalize(tbn * (2.0 * n - 1.0)); + + return textureNormal; +} +#endif + +#ifdef HAS_NORMALS +vec3 computeNormal(ProcessedAttributes attributes) +{ + // Geometry normal. This is already normalized + vec3 normal = attributes.normalEC; + + #if defined(HAS_NORMAL_TEXTURE) && !defined(HAS_WIREFRAME) + normal = getNormalFromTexture(attributes, normal); #endif - material.diffuse = baseColorWithAlpha.rgb; - material.alpha = baseColorWithAlpha.a; + #ifdef HAS_DOUBLE_SIDED_MATERIAL + if (czm_backFacing()) { + normal = -normal; + } + #endif - #ifdef USE_CPU_STYLING - material.diffuse = blend(material.diffuse, feature.color.rgb, model_colorBlend); + return normal; +} +#endif + +#ifdef HAS_BASE_COLOR_TEXTURE +vec4 getBaseColorFromTexture() +{ + vec2 baseColorTexCoords = TEXCOORD_BASE_COLOR; + #ifdef HAS_BASE_COLOR_TEXTURE_TRANSFORM + baseColorTexCoords = computeTextureTransform(baseColorTexCoords, u_baseColorTextureTransform); #endif - #ifdef HAS_OCCLUSION_TEXTURE - vec2 occlusionTexCoords = TEXCOORD_OCCLUSION; - #ifdef HAS_OCCLUSION_TEXTURE_TRANSFORM - occlusionTexCoords = computeTextureTransform(occlusionTexCoords, u_occlusionTextureTransform); - #endif - material.occlusion = texture(u_occlusionTexture, occlusionTexCoords).r; + vec4 baseColorWithAlpha = czm_srgbToLinear(texture(u_baseColorTexture, baseColorTexCoords)); + + #ifdef HAS_BASE_COLOR_FACTOR + baseColorWithAlpha *= u_baseColorFactor; #endif - #ifdef HAS_EMISSIVE_TEXTURE + return baseColorWithAlpha; +} +#endif + +#ifdef HAS_EMISSIVE_TEXTURE +vec3 getEmissiveFromTexture() +{ vec2 emissiveTexCoords = TEXCOORD_EMISSIVE; - #ifdef HAS_EMISSIVE_TEXTURE_TRANSFORM + #ifdef HAS_EMISSIVE_TEXTURE_TRANSFORM emissiveTexCoords = computeTextureTransform(emissiveTexCoords, u_emissiveTextureTransform); - #endif + #endif vec3 emissive = czm_srgbToLinear(texture(u_emissiveTexture, emissiveTexCoords).rgb); - #ifdef HAS_EMISSIVE_FACTOR + #ifdef HAS_EMISSIVE_FACTOR emissive *= u_emissiveFactor; - #endif - material.emissive = emissive; - #elif defined(HAS_EMISSIVE_FACTOR) - material.emissive = u_emissiveFactor; #endif - #if defined(LIGHTING_PBR) && defined(USE_SPECULAR_GLOSSINESS) - #ifdef HAS_SPECULAR_GLOSSINESS_TEXTURE + return emissive; +} +#endif + +#if defined(LIGHTING_PBR) && defined(USE_SPECULAR_GLOSSINESS) +void setSpecularGlossiness(inout czm_modelMaterial material) +{ + #ifdef HAS_SPECULAR_GLOSSINESS_TEXTURE vec2 specularGlossinessTexCoords = TEXCOORD_SPECULAR_GLOSSINESS; - #ifdef HAS_SPECULAR_GLOSSINESS_TEXTURE_TRANSFORM - specularGlossinessTexCoords = computeTextureTransform(specularGlossinessTexCoords, u_specularGlossinessTextureTransform); - #endif + #ifdef HAS_SPECULAR_GLOSSINESS_TEXTURE_TRANSFORM + specularGlossinessTexCoords = computeTextureTransform(specularGlossinessTexCoords, u_specularGlossinessTextureTransform); + #endif vec4 specularGlossiness = czm_srgbToLinear(texture(u_specularGlossinessTexture, specularGlossinessTexCoords)); vec3 specular = specularGlossiness.rgb; float glossiness = specularGlossiness.a; - #ifdef HAS_SPECULAR_FACTOR - specular *= u_specularFactor; - #endif + #ifdef HAS_LEGACY_SPECULAR_FACTOR + specular *= u_legacySpecularFactor; + #endif - #ifdef HAS_GLOSSINESS_FACTOR + #ifdef HAS_GLOSSINESS_FACTOR glossiness *= u_glossinessFactor; - #endif + #endif + #else + #ifdef HAS_LEGACY_SPECULAR_FACTOR + vec3 specular = clamp(u_legacySpecularFactor, vec3(0.0), vec3(1.0)); #else - #ifdef HAS_SPECULAR_FACTOR - vec3 specular = clamp(u_specularFactor, vec3(0.0), vec3(1.0)); - #else vec3 specular = vec3(1.0); - #endif + #endif - #ifdef HAS_GLOSSINESS_FACTOR + #ifdef HAS_GLOSSINESS_FACTOR float glossiness = clamp(u_glossinessFactor, 0.0, 1.0); - #else + #else float glossiness = 1.0; - #endif #endif + #endif - #ifdef HAS_DIFFUSE_TEXTURE + #ifdef HAS_DIFFUSE_TEXTURE vec2 diffuseTexCoords = TEXCOORD_DIFFUSE; - #ifdef HAS_DIFFUSE_TEXTURE_TRANSFORM + #ifdef HAS_DIFFUSE_TEXTURE_TRANSFORM diffuseTexCoords = computeTextureTransform(diffuseTexCoords, u_diffuseTextureTransform); - #endif + #endif vec4 diffuse = czm_srgbToLinear(texture(u_diffuseTexture, diffuseTexCoords)); - #ifdef HAS_DIFFUSE_FACTOR + #ifdef HAS_DIFFUSE_FACTOR diffuse *= u_diffuseFactor; - #endif - #elif defined(HAS_DIFFUSE_FACTOR) + #endif + #elif defined(HAS_DIFFUSE_FACTOR) vec4 diffuse = clamp(u_diffuseFactor, vec4(0.0), vec4(1.0)); - #else + #else vec4 diffuse = vec4(1.0); - #endif - czm_pbrParameters parameters = czm_pbrSpecularGlossinessMaterial( - diffuse.rgb, - specular, - glossiness - ); - material.diffuse = parameters.diffuseColor; + #endif + + material.diffuse = diffuse.rgb * (1.0 - czm_maximumComponent(specular)); // the specular glossiness extension's alpha overrides anything set // by the base material. material.alpha = diffuse.a; - material.specular = parameters.f0; - material.roughness = parameters.roughness; - #elif defined(LIGHTING_PBR) - #ifdef HAS_METALLIC_ROUGHNESS_TEXTURE + + material.specular = specular; + + // glossiness is the opposite of roughness, but easier for artists to use. + float roughness = 1.0 - glossiness; + material.roughness = roughness * roughness; +} +#elif defined(LIGHTING_PBR) +float setMetallicRoughness(inout czm_modelMaterial material) +{ + #ifdef HAS_METALLIC_ROUGHNESS_TEXTURE vec2 metallicRoughnessTexCoords = TEXCOORD_METALLIC_ROUGHNESS; - #ifdef HAS_METALLIC_ROUGHNESS_TEXTURE_TRANSFORM + #ifdef HAS_METALLIC_ROUGHNESS_TEXTURE_TRANSFORM metallicRoughnessTexCoords = computeTextureTransform(metallicRoughnessTexCoords, u_metallicRoughnessTextureTransform); - #endif + #endif vec3 metallicRoughness = texture(u_metallicRoughnessTexture, metallicRoughnessTexCoords).rgb; float metalness = clamp(metallicRoughness.b, 0.0, 1.0); float roughness = clamp(metallicRoughness.g, 0.04, 1.0); - #ifdef HAS_METALLIC_FACTOR - metalness *= u_metallicFactor; - #endif + #ifdef HAS_METALLIC_FACTOR + metalness = clamp(metalness * u_metallicFactor, 0.0, 1.0); + #endif - #ifdef HAS_ROUGHNESS_FACTOR - roughness *= u_roughnessFactor; - #endif - #else - #ifdef HAS_METALLIC_FACTOR + #ifdef HAS_ROUGHNESS_FACTOR + roughness = clamp(roughness * u_roughnessFactor, 0.0, 1.0); + #endif + #else + #ifdef HAS_METALLIC_FACTOR float metalness = clamp(u_metallicFactor, 0.0, 1.0); - #else + #else float metalness = 1.0; - #endif + #endif - #ifdef HAS_ROUGHNESS_FACTOR + #ifdef HAS_ROUGHNESS_FACTOR float roughness = clamp(u_roughnessFactor, 0.04, 1.0); - #else + #else float roughness = 1.0; - #endif - #endif - czm_pbrParameters parameters = czm_pbrMetallicRoughnessMaterial( - material.diffuse, - metalness, - roughness - ); - material.diffuse = parameters.diffuseColor; - material.specular = parameters.f0; - material.roughness = parameters.roughness; + #endif + #endif + + // dielectrics use f0 = 0.04, metals use albedo as f0 + const vec3 REFLECTANCE_DIELECTRIC = vec3(0.04); + vec3 f0 = mix(REFLECTANCE_DIELECTRIC, material.diffuse, metalness); + + material.specular = f0; + + // diffuse only applies to dielectrics. + material.diffuse = material.diffuse * (1.0 - f0) * (1.0 - metalness); + + // roughness is authored as perceptual roughness + // square it to get material roughness + material.roughness = roughness * roughness; + + return metalness; +} +#ifdef USE_SPECULAR +void setSpecular(inout czm_modelMaterial material, in float metalness) +{ + #ifdef HAS_SPECULAR_TEXTURE + vec2 specularTexCoords = TEXCOORD_SPECULAR; + #ifdef HAS_SPECULAR_TEXTURE_TRANSFORM + specularTexCoords = computeTextureTransform(specularTexCoords, u_specularTextureTransform); + #endif + float specularWeight = texture(u_specularTexture, specularTexCoords).a; + #ifdef HAS_SPECULAR_FACTOR + specularWeight *= u_specularFactor; + #endif + #else + #ifdef HAS_SPECULAR_FACTOR + float specularWeight = u_specularFactor; + #else + float specularWeight = 1.0; + #endif + #endif + + #ifdef HAS_SPECULAR_COLOR_TEXTURE + vec2 specularColorTexCoords = TEXCOORD_SPECULAR_COLOR; + #ifdef HAS_SPECULAR_COLOR_TEXTURE_TRANSFORM + specularColorTexCoords = computeTextureTransform(specularColorTexCoords, u_specularColorTextureTransform); + #endif + vec3 specularColorSample = texture(u_specularColorTexture, specularColorTexCoords).rgb; + vec3 specularColorFactor = czm_srgbToLinear(specularColorSample); + #ifdef HAS_SPECULAR_COLOR_FACTOR + specularColorFactor *= u_specularColorFactor; + #endif + #else + #ifdef HAS_SPECULAR_COLOR_FACTOR + vec3 specularColorFactor = u_specularColorFactor; + #else + vec3 specularColorFactor = vec3(1.0); + #endif + #endif + material.specularWeight = specularWeight; + vec3 f0 = material.specular; + vec3 dielectricSpecularF0 = min(f0 * specularColorFactor, vec3(1.0)); + material.specular = mix(dielectricSpecularF0, material.diffuse, metalness); +} +#endif +#ifdef USE_ANISOTROPY +void setAnisotropy(inout czm_modelMaterial material, in NormalInfo normalInfo) +{ + mat2 rotation = mat2(u_anisotropy.xy, -u_anisotropy.y, u_anisotropy.x); + float anisotropyStrength = u_anisotropy.z; + + vec2 direction = vec2(1.0, 0.0); + #ifdef HAS_ANISOTROPY_TEXTURE + vec2 anisotropyTexCoords = TEXCOORD_ANISOTROPY; + #ifdef HAS_ANISOTROPY_TEXTURE_TRANSFORM + anisotropyTexCoords = computeTextureTransform(anisotropyTexCoords, u_anisotropyTextureTransform); + #endif + vec3 anisotropySample = texture(u_anisotropyTexture, anisotropyTexCoords).rgb; + direction = anisotropySample.rg * 2.0 - vec2(1.0); + anisotropyStrength *= anisotropySample.b; + #endif + + direction = rotation * direction; + mat3 tbn = mat3(normalInfo.tangent, normalInfo.bitangent, normalInfo.normal); + vec3 anisotropicT = tbn * normalize(vec3(direction, 0.0)); + vec3 anisotropicB = cross(normalInfo.geometryNormal, anisotropicT); + + material.anisotropicT = anisotropicT; + material.anisotropicB = anisotropicB; + material.anisotropyStrength = anisotropyStrength; +} +#endif +#ifdef USE_CLEARCOAT +void setClearcoat(inout czm_modelMaterial material, in ProcessedAttributes attributes) +{ + #ifdef HAS_CLEARCOAT_TEXTURE + vec2 clearcoatTexCoords = TEXCOORD_CLEARCOAT; + #ifdef HAS_CLEARCOAT_TEXTURE_TRANSFORM + clearcoatTexCoords = computeTextureTransform(clearcoatTexCoords, u_clearcoatTextureTransform); + #endif + float clearcoatFactor = texture(u_clearcoatTexture, clearcoatTexCoords).r; + #ifdef HAS_CLEARCOAT_FACTOR + clearcoatFactor *= u_clearcoatFactor; + #endif + #else + #ifdef HAS_CLEARCOAT_FACTOR + float clearcoatFactor = u_clearcoatFactor; + #else + // PERFORMANCE_IDEA: this case should turn the whole extension off + float clearcoatFactor = 0.0; + #endif + #endif + + #ifdef HAS_CLEARCOAT_ROUGHNESS_TEXTURE + vec2 clearcoatRoughnessTexCoords = TEXCOORD_CLEARCOAT_ROUGHNESS; + #ifdef HAS_CLEARCOAT_ROUGHNESS_TEXTURE_TRANSFORM + clearcoatRoughnessTexCoords = computeTextureTransform(clearcoatRoughnessTexCoords, u_clearcoatRoughnessTextureTransform); + #endif + float clearcoatRoughness = texture(u_clearcoatRoughnessTexture, clearcoatRoughnessTexCoords).g; + #ifdef HAS_CLEARCOAT_ROUGHNESS_FACTOR + clearcoatRoughness *= u_clearcoatRoughnessFactor; + #endif + #else + #ifdef HAS_CLEARCOAT_ROUGHNESS_FACTOR + float clearcoatRoughness = u_clearcoatRoughnessFactor; + #else + float clearcoatRoughness = 0.0; + #endif + #endif + + material.clearcoatFactor = clearcoatFactor; + // roughness is authored as perceptual roughness + // square it to get material roughness + material.clearcoatRoughness = clearcoatRoughness * clearcoatRoughness; + #ifdef HAS_CLEARCOAT_NORMAL_TEXTURE + material.clearcoatNormal = getClearcoatNormalFromTexture(attributes, attributes.normalEC); + #else + material.clearcoatNormal = attributes.normalEC; + #endif +} +#endif +#endif + +void materialStage(inout czm_modelMaterial material, ProcessedAttributes attributes, SelectedFeature feature) +{ + #ifdef USE_ANISOTROPY + NormalInfo normalInfo = getNormalInfo(attributes); + material.normalEC = normalInfo.normal; + #elif defined(HAS_NORMALS) + material.normalEC = computeNormal(attributes); + #endif + + vec4 baseColorWithAlpha = vec4(1.0); + // Regardless of whether we use PBR, set a base color + #ifdef HAS_BASE_COLOR_TEXTURE + baseColorWithAlpha = getBaseColorFromTexture(); + #elif defined(HAS_BASE_COLOR_FACTOR) + baseColorWithAlpha = u_baseColorFactor; + #endif + + #ifdef HAS_POINT_CLOUD_COLOR_STYLE + baseColorWithAlpha = v_pointCloudColor; + #elif defined(HAS_COLOR_0) + vec4 color = attributes.color_0; + // .pnts files store colors in the sRGB color space + #ifdef HAS_SRGB_COLOR + color = czm_srgbToLinear(color); + #endif + baseColorWithAlpha *= color; + #endif + + material.diffuse = baseColorWithAlpha.rgb; + material.alpha = baseColorWithAlpha.a; + + #ifdef USE_CPU_STYLING + material.diffuse = blend(material.diffuse, feature.color.rgb, model_colorBlend); + #endif + + #ifdef HAS_OCCLUSION_TEXTURE + vec2 occlusionTexCoords = TEXCOORD_OCCLUSION; + #ifdef HAS_OCCLUSION_TEXTURE_TRANSFORM + occlusionTexCoords = computeTextureTransform(occlusionTexCoords, u_occlusionTextureTransform); + #endif + material.occlusion = texture(u_occlusionTexture, occlusionTexCoords).r; + #endif + + #ifdef HAS_EMISSIVE_TEXTURE + material.emissive = getEmissiveFromTexture(); + #elif defined(HAS_EMISSIVE_FACTOR) + material.emissive = u_emissiveFactor; + #endif + + #if defined(LIGHTING_PBR) && defined(USE_SPECULAR_GLOSSINESS) + setSpecularGlossiness(material); + #elif defined(LIGHTING_PBR) + float metalness = setMetallicRoughness(material); + #ifdef USE_SPECULAR + setSpecular(material, metalness); + #endif + #ifdef USE_ANISOTROPY + setAnisotropy(material, normalInfo); + #endif + #ifdef USE_CLEARCOAT + setClearcoat(material, attributes); + #endif #endif } diff --git a/packages/engine/Specs/.eslintrc.json b/packages/engine/Specs/.eslintrc.json deleted file mode 100644 index 5b6725648bf..00000000000 --- a/packages/engine/Specs/.eslintrc.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "../../.eslintrc.json", - "env": { - "jasmine": true - }, - "rules": { - "no-self-assign": "off", - "no-duplicate-imports": "off" - } -} \ No newline at end of file diff --git a/packages/engine/Specs/Core/Cartesian3Spec.js b/packages/engine/Specs/Core/Cartesian3Spec.js index 73e89bcf3e5..463be5cfc4b 100644 --- a/packages/engine/Specs/Core/Cartesian3Spec.js +++ b/packages/engine/Specs/Core/Cartesian3Spec.js @@ -1,6 +1,10 @@ -import { Cartesian3, Cartographic, Ellipsoid } from "../../index.js"; +import { + Cartesian3, + Cartographic, + Ellipsoid, + Math as CesiumMath, +} from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; import createPackableArraySpecs from "../../../../Specs/createPackableArraySpecs.js"; import createPackableSpecs from "../../../../Specs/createPackableSpecs.js"; diff --git a/packages/engine/Specs/Core/Cartesian4Spec.js b/packages/engine/Specs/Core/Cartesian4Spec.js index 478ec96fdf3..b9146991493 100644 --- a/packages/engine/Specs/Core/Cartesian4Spec.js +++ b/packages/engine/Specs/Core/Cartesian4Spec.js @@ -1,6 +1,5 @@ -import { Cartesian4, Color } from "../../index.js"; +import { Cartesian4, Color, Math as CesiumMath } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; import createPackableArraySpecs from "../../../../Specs/createPackableArraySpecs.js"; import createPackableSpecs from "../../../../Specs/createPackableSpecs.js"; diff --git a/packages/engine/Specs/Core/CartographicSpec.js b/packages/engine/Specs/Core/CartographicSpec.js index 9aaf8bc8a03..98cabba7053 100644 --- a/packages/engine/Specs/Core/CartographicSpec.js +++ b/packages/engine/Specs/Core/CartographicSpec.js @@ -1,6 +1,9 @@ -import { Cartesian3, Cartographic, Ellipsoid } from "../../index.js"; - -import { Math as CesiumMath } from "../../index.js"; +import { + Cartesian3, + Cartographic, + Ellipsoid, + Math as CesiumMath, +} from "../../index.js"; describe("Core/Cartographic", function () { const surfaceCartesian = new Cartesian3( diff --git a/packages/engine/Specs/Core/CatmullRomSplineSpec.js b/packages/engine/Specs/Core/CatmullRomSplineSpec.js index 8db028f94cb..4dd08e164df 100644 --- a/packages/engine/Specs/Core/CatmullRomSplineSpec.js +++ b/packages/engine/Specs/Core/CatmullRomSplineSpec.js @@ -1,6 +1,9 @@ -import { Cartesian3, CatmullRomSpline, HermiteSpline } from "../../index.js"; - -import { Math as CesiumMath } from "../../index.js"; +import { + Cartesian3, + CatmullRomSpline, + HermiteSpline, + Math as CesiumMath, +} from "../../index.js"; describe("Core/CatmullRomSpline", function () { let points; diff --git a/packages/engine/Specs/Core/CircleGeometrySpec.js b/packages/engine/Specs/Core/CircleGeometrySpec.js index dee09cac9f5..78cc3929c4d 100644 --- a/packages/engine/Specs/Core/CircleGeometrySpec.js +++ b/packages/engine/Specs/Core/CircleGeometrySpec.js @@ -2,11 +2,10 @@ import { Cartesian3, CircleGeometry, Ellipsoid, + Math as CesiumMath, VertexFormat, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createPackableSpecs from "../../../../Specs/createPackableSpecs.js"; describe("Core/CircleGeometry", function () { diff --git a/packages/engine/Specs/Core/ColorSpec.js b/packages/engine/Specs/Core/ColorSpec.js index 11cb942a722..96ab7d12417 100644 --- a/packages/engine/Specs/Core/ColorSpec.js +++ b/packages/engine/Specs/Core/ColorSpec.js @@ -1,6 +1,5 @@ -import { Cartesian4, Color } from "../../index.js"; +import { Cartesian4, Color, Math as CesiumMath } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; import createPackableSpecs from "../../../../Specs/createPackableSpecs.js"; describe("Core/Color", function () { diff --git a/packages/engine/Specs/Core/CoplanarPolygonGeometrySpec.js b/packages/engine/Specs/Core/CoplanarPolygonGeometrySpec.js index 820b4b33b8a..11e767ab508 100644 --- a/packages/engine/Specs/Core/CoplanarPolygonGeometrySpec.js +++ b/packages/engine/Specs/Core/CoplanarPolygonGeometrySpec.js @@ -2,12 +2,11 @@ import { Cartesian3, Cartesian2, CoplanarPolygonGeometry, + Math as CesiumMath, Ellipsoid, VertexFormat, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createPackableSpecs from "../../../../Specs/createPackableSpecs.js"; describe("Core/CoplanarPolygonGeometry", function () { diff --git a/packages/engine/Specs/Core/CorridorGeometrySpec.js b/packages/engine/Specs/Core/CorridorGeometrySpec.js index f11f558cd7f..c8d4c6efd2d 100644 --- a/packages/engine/Specs/Core/CorridorGeometrySpec.js +++ b/packages/engine/Specs/Core/CorridorGeometrySpec.js @@ -4,12 +4,11 @@ import { CorridorGeometry, Ellipsoid, GeometryOffsetAttribute, + Math as CesiumMath, Rectangle, VertexFormat, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createPackableSpecs from "../../../../Specs/createPackableSpecs.js"; describe("Core/CorridorGeometry", function () { diff --git a/packages/engine/Specs/Core/CubicRealPolynomialSpec.js b/packages/engine/Specs/Core/CubicRealPolynomialSpec.js index 3ee4bca475b..5673df7ff91 100644 --- a/packages/engine/Specs/Core/CubicRealPolynomialSpec.js +++ b/packages/engine/Specs/Core/CubicRealPolynomialSpec.js @@ -1,6 +1,4 @@ -import { CubicRealPolynomial } from "../../index.js"; - -import { Math as CesiumMath } from "../../index.js"; +import { CubicRealPolynomial, Math as CesiumMath } from "../../index.js"; describe("Core/CubicRealPolynomial", function () { it("discriminant throws without a", function () { diff --git a/packages/engine/Specs/Core/EllipseGeometrySpec.js b/packages/engine/Specs/Core/EllipseGeometrySpec.js index 6aecd97936c..06a1463fb84 100644 --- a/packages/engine/Specs/Core/EllipseGeometrySpec.js +++ b/packages/engine/Specs/Core/EllipseGeometrySpec.js @@ -3,12 +3,11 @@ import { EllipseGeometry, Ellipsoid, GeometryOffsetAttribute, + Math as CesiumMath, Rectangle, VertexFormat, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createPackableSpecs from "../../../../Specs/createPackableSpecs.js"; describe("Core/EllipseGeometry", function () { diff --git a/packages/engine/Specs/Core/EllipsoidGeodesicSpec.js b/packages/engine/Specs/Core/EllipsoidGeodesicSpec.js index e3a52f862aa..3b7c1edb274 100644 --- a/packages/engine/Specs/Core/EllipsoidGeodesicSpec.js +++ b/packages/engine/Specs/Core/EllipsoidGeodesicSpec.js @@ -1,6 +1,9 @@ -import { Cartographic, Ellipsoid, EllipsoidGeodesic } from "../../index.js"; - -import { Math as CesiumMath } from "../../index.js"; +import { + Cartographic, + Ellipsoid, + EllipsoidGeodesic, + Math as CesiumMath, +} from "../../index.js"; describe("Core/EllipsoidGeodesic", function () { it("throws without start", function () { diff --git a/packages/engine/Specs/Core/EllipsoidGeometrySpec.js b/packages/engine/Specs/Core/EllipsoidGeometrySpec.js index 1e175fe763a..7800e7afbba 100644 --- a/packages/engine/Specs/Core/EllipsoidGeometrySpec.js +++ b/packages/engine/Specs/Core/EllipsoidGeometrySpec.js @@ -2,11 +2,10 @@ import { Cartesian3, EllipsoidGeometry, GeometryOffsetAttribute, + Math as CesiumMath, VertexFormat, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createPackableSpecs from "../../../../Specs/createPackableSpecs.js"; describe("Core/EllipsoidGeometry", function () { diff --git a/packages/engine/Specs/Core/EllipsoidOutlineGeometrySpec.js b/packages/engine/Specs/Core/EllipsoidOutlineGeometrySpec.js index 691d16402b5..e24be1fefa9 100644 --- a/packages/engine/Specs/Core/EllipsoidOutlineGeometrySpec.js +++ b/packages/engine/Specs/Core/EllipsoidOutlineGeometrySpec.js @@ -2,9 +2,9 @@ import { Cartesian3, EllipsoidOutlineGeometry, GeometryOffsetAttribute, + Math as CesiumMath, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; import createPackableSpecs from "../../../../Specs/createPackableSpecs.js"; describe("Core/EllipsoidOutlineGeometry", function () { diff --git a/packages/engine/Specs/Core/EllipsoidRhumbLineSpec.js b/packages/engine/Specs/Core/EllipsoidRhumbLineSpec.js index 87157adea73..afc652627b0 100644 --- a/packages/engine/Specs/Core/EllipsoidRhumbLineSpec.js +++ b/packages/engine/Specs/Core/EllipsoidRhumbLineSpec.js @@ -4,10 +4,9 @@ import { Ellipsoid, EllipsoidGeodesic, EllipsoidRhumbLine, + Math as CesiumMath, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - describe("Core/EllipsoidRhumbLine", function () { const oneDegree = CesiumMath.RADIANS_PER_DEGREE; const fifteenDegrees = Math.PI / 12; diff --git a/packages/engine/Specs/Core/EllipsoidalOccluderSpec.js b/packages/engine/Specs/Core/EllipsoidalOccluderSpec.js index 6992603a74b..154d4c502b5 100644 --- a/packages/engine/Specs/Core/EllipsoidalOccluderSpec.js +++ b/packages/engine/Specs/Core/EllipsoidalOccluderSpec.js @@ -4,12 +4,11 @@ import { Ellipsoid, EllipsoidalOccluder, IntersectionTests, + Math as CesiumMath, Ray, Rectangle, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - describe("Core/EllipsoidalOccluder", function () { it("uses ellipsoid", function () { const ellipsoid = new Ellipsoid(2.0, 3.0, 4.0); diff --git a/packages/engine/Specs/Core/FrustumGeometrySpec.js b/packages/engine/Specs/Core/FrustumGeometrySpec.js index b0073b16784..24af379c258 100644 --- a/packages/engine/Specs/Core/FrustumGeometrySpec.js +++ b/packages/engine/Specs/Core/FrustumGeometrySpec.js @@ -1,13 +1,12 @@ import { Cartesian3, FrustumGeometry, + Math as CesiumMath, PerspectiveFrustum, Quaternion, VertexFormat, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createPackableSpecs from "../../../../Specs/createPackableSpecs.js"; describe("Core/FrustumGeometry", function () { diff --git a/packages/engine/Specs/Core/FrustumOutlineGeometrySpec.js b/packages/engine/Specs/Core/FrustumOutlineGeometrySpec.js index bb4d2643d63..e5435ea98dd 100644 --- a/packages/engine/Specs/Core/FrustumOutlineGeometrySpec.js +++ b/packages/engine/Specs/Core/FrustumOutlineGeometrySpec.js @@ -1,13 +1,12 @@ import { Cartesian3, FrustumOutlineGeometry, + Math as CesiumMath, PerspectiveFrustum, Quaternion, VertexFormat, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createPackableSpecs from "../../../../Specs/createPackableSpecs.js"; describe("Core/FrustumOutlineGeometry", function () { diff --git a/packages/engine/Specs/Core/GeographicProjectionSpec.js b/packages/engine/Specs/Core/GeographicProjectionSpec.js index ba405515f81..19f890867cb 100644 --- a/packages/engine/Specs/Core/GeographicProjectionSpec.js +++ b/packages/engine/Specs/Core/GeographicProjectionSpec.js @@ -3,10 +3,9 @@ import { Cartographic, Ellipsoid, GeographicProjection, + Math as CesiumMath, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - describe("Core/GeographicProjection", function () { it("construct0", function () { const projection = new GeographicProjection(); diff --git a/packages/engine/Specs/Core/GeographicTilingSchemeSpec.js b/packages/engine/Specs/Core/GeographicTilingSchemeSpec.js index 53ba59db214..e08cc000e89 100644 --- a/packages/engine/Specs/Core/GeographicTilingSchemeSpec.js +++ b/packages/engine/Specs/Core/GeographicTilingSchemeSpec.js @@ -3,12 +3,11 @@ import { Cartographic, GeographicProjection, GeographicTilingScheme, + Math as CesiumMath, Rectangle, TilingScheme, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - describe("Core/GeographicTilingScheme", function () { it("conforms to TilingScheme interface.", function () { expect(GeographicTilingScheme).toConformToInterface(TilingScheme); diff --git a/packages/engine/Specs/Core/GeometryPipelineSpec.js b/packages/engine/Specs/Core/GeometryPipelineSpec.js index 10ccf984273..4cba2dd3c47 100644 --- a/packages/engine/Specs/Core/GeometryPipelineSpec.js +++ b/packages/engine/Specs/Core/GeometryPipelineSpec.js @@ -14,6 +14,7 @@ import { GeometryInstance, GeometryPipeline, GeometryType, + Math as CesiumMath, Matrix4, PolygonGeometry, PrimitiveType, @@ -21,8 +22,6 @@ import { VertexFormat, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - describe("Core/GeometryPipeline", function () { it("converts triangles to wireframe in place", function () { const geometry = GeometryPipeline.toWireframe( diff --git a/packages/engine/Specs/Core/GeometrySpec.js b/packages/engine/Specs/Core/GeometrySpec.js index 2c80342e238..c07668cb52e 100644 --- a/packages/engine/Specs/Core/GeometrySpec.js +++ b/packages/engine/Specs/Core/GeometrySpec.js @@ -6,12 +6,11 @@ import { Geometry, GeometryAttribute, GeometryType, + Math as CesiumMath, PrimitiveType, Rectangle, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - describe("Core/Geometry", function () { it("constructor", function () { const attributes = { diff --git a/packages/engine/Specs/Core/GoogleEarthEnterpriseTerrainDataSpec.js b/packages/engine/Specs/Core/GoogleEarthEnterpriseTerrainDataSpec.js index 5ddf66bbdf0..25bc601ff70 100644 --- a/packages/engine/Specs/Core/GoogleEarthEnterpriseTerrainDataSpec.js +++ b/packages/engine/Specs/Core/GoogleEarthEnterpriseTerrainDataSpec.js @@ -4,13 +4,12 @@ import { Ellipsoid, GeographicTilingScheme, GoogleEarthEnterpriseTerrainData, + Math as CesiumMath, Rectangle, TerrainData, TerrainMesh, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - describe("Core/GoogleEarthEnterpriseTerrainData", function () { const sizeOfUint8 = Uint8Array.BYTES_PER_ELEMENT; const sizeOfUint16 = Uint16Array.BYTES_PER_ELEMENT; diff --git a/packages/engine/Specs/Core/GroundPolylineGeometrySpec.js b/packages/engine/Specs/Core/GroundPolylineGeometrySpec.js index d308b26210c..84af45fa9cb 100644 --- a/packages/engine/Specs/Core/GroundPolylineGeometrySpec.js +++ b/packages/engine/Specs/Core/GroundPolylineGeometrySpec.js @@ -6,11 +6,10 @@ import { Ellipsoid, GeographicProjection, GroundPolylineGeometry, + Math as CesiumMath, WebMercatorProjection, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createPackableSpecs from "../../../../Specs/createPackableSpecs.js"; describe("Core/GroundPolylineGeometry", function () { diff --git a/packages/engine/Specs/Core/HeadingPitchRollSpec.js b/packages/engine/Specs/Core/HeadingPitchRollSpec.js index 9cb6dbf4fb3..a65df32d563 100644 --- a/packages/engine/Specs/Core/HeadingPitchRollSpec.js +++ b/packages/engine/Specs/Core/HeadingPitchRollSpec.js @@ -1,6 +1,8 @@ -import { HeadingPitchRoll, Quaternion } from "../../index.js"; - -import { Math as CesiumMath } from "../../index.js"; +import { + HeadingPitchRoll, + Math as CesiumMath, + Quaternion, +} from "../../index.js"; describe("Core/HeadingPitchRoll", function () { const deg2rad = CesiumMath.RADIANS_PER_DEGREE; diff --git a/packages/engine/Specs/Core/HermiteSplineSpec.js b/packages/engine/Specs/Core/HermiteSplineSpec.js index 28307fad357..3b04ea68238 100644 --- a/packages/engine/Specs/Core/HermiteSplineSpec.js +++ b/packages/engine/Specs/Core/HermiteSplineSpec.js @@ -1,6 +1,9 @@ -import { Cartesian3, HermiteSpline, Quaternion } from "../../index.js"; - -import { Math as CesiumMath } from "../../index.js"; +import { + Cartesian3, + HermiteSpline, + Math as CesiumMath, + Quaternion, +} from "../../index.js"; describe("Core/HermiteSpline", function () { let points; diff --git a/packages/engine/Specs/Core/IauOrientationAxesSpec.js b/packages/engine/Specs/Core/IauOrientationAxesSpec.js index c43d5c5e424..8d220d4f1a1 100644 --- a/packages/engine/Specs/Core/IauOrientationAxesSpec.js +++ b/packages/engine/Specs/Core/IauOrientationAxesSpec.js @@ -3,11 +3,10 @@ import { IauOrientationAxes, JulianDate, Matrix3, + Math as CesiumMath, TimeStandard, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - describe("Core/IauOrientationAxes", function () { it("compute ICRF to Moon Fixed", function () { const date = new JulianDate(2451545.0, -32.184, TimeStandard.TAI); diff --git a/packages/engine/Specs/Core/IndexDatatypeSpec.js b/packages/engine/Specs/Core/IndexDatatypeSpec.js index 636b59e44da..a3a8132643b 100644 --- a/packages/engine/Specs/Core/IndexDatatypeSpec.js +++ b/packages/engine/Specs/Core/IndexDatatypeSpec.js @@ -1,6 +1,4 @@ -import { IndexDatatype } from "../../index.js"; - -import { Math as CesiumMath } from "../../index.js"; +import { IndexDatatype, Math as CesiumMath } from "../../index.js"; describe("Core/IndexDatatype", function () { it("validate validates input", function () { diff --git a/packages/engine/Specs/Core/IntersectionTestsSpec.js b/packages/engine/Specs/Core/IntersectionTestsSpec.js index 8e884ace515..8b1a1eb776f 100644 --- a/packages/engine/Specs/Core/IntersectionTestsSpec.js +++ b/packages/engine/Specs/Core/IntersectionTestsSpec.js @@ -3,12 +3,11 @@ import { Cartesian3, Ellipsoid, IntersectionTests, + Math as CesiumMath, Plane, Ray, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - describe("Core/IntersectionTests", function () { it("rayPlane intersects", function () { const ray = new Ray( diff --git a/packages/engine/Specs/Core/JulianDateSpec.js b/packages/engine/Specs/Core/JulianDateSpec.js index 751cb95e68e..4a034a29365 100644 --- a/packages/engine/Specs/Core/JulianDateSpec.js +++ b/packages/engine/Specs/Core/JulianDateSpec.js @@ -1,12 +1,11 @@ import { Iso8601, JulianDate, + Math as CesiumMath, TimeConstants, TimeStandard, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - describe("Core/JulianDate", function () { // All exact Julian Dates found using NASA's Time Conversion Tool: http://ssd.jpl.nasa.gov/tc.cgi it("Construct a default date", function () { diff --git a/packages/engine/Specs/Core/Matrix2Spec.js b/packages/engine/Specs/Core/Matrix2Spec.js index 839b54df2fd..540b550d0c2 100644 --- a/packages/engine/Specs/Core/Matrix2Spec.js +++ b/packages/engine/Specs/Core/Matrix2Spec.js @@ -1,6 +1,4 @@ -import { Cartesian2, Matrix2 } from "../../index.js"; - -import { Math as CesiumMath } from "../../index.js"; +import { Cartesian2, Math as CesiumMath, Matrix2 } from "../../index.js"; import createPackableSpecs from "../../../../Specs/createPackableSpecs.js"; import createPackableArraySpecs from "../../../../Specs/createPackableArraySpecs.js"; diff --git a/packages/engine/Specs/Core/Matrix3Spec.js b/packages/engine/Specs/Core/Matrix3Spec.js index ff05dd3e084..e0ada12c175 100644 --- a/packages/engine/Specs/Core/Matrix3Spec.js +++ b/packages/engine/Specs/Core/Matrix3Spec.js @@ -1,12 +1,11 @@ import { Cartesian3, HeadingPitchRoll, + Math as CesiumMath, Matrix3, Quaternion, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createPackableSpecs from "../../../../Specs/createPackableSpecs.js"; import createPackableArraySpecs from "../../../../Specs/createPackableArraySpecs.js"; diff --git a/packages/engine/Specs/Core/Matrix4Spec.js b/packages/engine/Specs/Core/Matrix4Spec.js index 3109a8220d9..ae2c6fa15a8 100644 --- a/packages/engine/Specs/Core/Matrix4Spec.js +++ b/packages/engine/Specs/Core/Matrix4Spec.js @@ -1,6 +1,7 @@ import { Cartesian3, Cartesian4, + Math as CesiumMath, Matrix3, Matrix4, Quaternion, @@ -8,8 +9,6 @@ import { RuntimeError, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createPackableSpecs from "../../../../Specs/createPackableSpecs.js"; import createPackableArraySpecs from "../../../../Specs/createPackableArraySpecs.js"; diff --git a/packages/engine/Specs/Core/OccluderSpec.js b/packages/engine/Specs/Core/OccluderSpec.js index 798f850ea84..d4e18ff9b12 100644 --- a/packages/engine/Specs/Core/OccluderSpec.js +++ b/packages/engine/Specs/Core/OccluderSpec.js @@ -2,13 +2,12 @@ import { BoundingSphere, Cartesian3, Ellipsoid, + Math as CesiumMath, Occluder, Rectangle, Visibility, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - describe("Core/Occluder", function () { it("throws an exception during construction (1 of 3)", function () { expect(function () { diff --git a/packages/engine/Specs/Core/OrientedBoundingBoxSpec.js b/packages/engine/Specs/Core/OrientedBoundingBoxSpec.js index 37d506dfc38..a424c6561c3 100644 --- a/packages/engine/Specs/Core/OrientedBoundingBoxSpec.js +++ b/packages/engine/Specs/Core/OrientedBoundingBoxSpec.js @@ -4,6 +4,7 @@ import { Cartesian4, Ellipsoid, Intersect, + Math as CesiumMath, Matrix3, Matrix4, Occluder, @@ -13,8 +14,6 @@ import { Rectangle, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createPackableSpecs from "../../../../Specs/createPackableSpecs.js"; describe("Core/OrientedBoundingBox", function () { diff --git a/packages/engine/Specs/Core/OrthographicFrustumSpec.js b/packages/engine/Specs/Core/OrthographicFrustumSpec.js index 1a65cbaba34..fa90747bbd1 100644 --- a/packages/engine/Specs/Core/OrthographicFrustumSpec.js +++ b/packages/engine/Specs/Core/OrthographicFrustumSpec.js @@ -2,12 +2,11 @@ import { Cartesian2, Cartesian3, Cartesian4, + Math as CesiumMath, Matrix4, OrthographicFrustum, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createPackableSpecs from "../../../../Specs/createPackableSpecs.js"; describe("Core/OrthographicFrustum", function () { diff --git a/packages/engine/Specs/Core/OrthographicOffCenterFrustumSpec.js b/packages/engine/Specs/Core/OrthographicOffCenterFrustumSpec.js index 9f87f5f5ad0..4040ffc5df3 100644 --- a/packages/engine/Specs/Core/OrthographicOffCenterFrustumSpec.js +++ b/packages/engine/Specs/Core/OrthographicOffCenterFrustumSpec.js @@ -2,12 +2,11 @@ import { Cartesian2, Cartesian3, Cartesian4, + Math as CesiumMath, Matrix4, OrthographicOffCenterFrustum, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - describe("Core/OrthographicOffCenterFrustum", function () { let frustum, planes; diff --git a/packages/engine/Specs/Core/PerspectiveFrustumSpec.js b/packages/engine/Specs/Core/PerspectiveFrustumSpec.js index afea2402bfd..3e3c16fdcf1 100644 --- a/packages/engine/Specs/Core/PerspectiveFrustumSpec.js +++ b/packages/engine/Specs/Core/PerspectiveFrustumSpec.js @@ -2,12 +2,11 @@ import { Cartesian2, Cartesian3, Cartesian4, + Math as CesiumMath, Matrix4, PerspectiveFrustum, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createPackableSpecs from "../../../../Specs/createPackableSpecs.js"; describe("Core/PerspectiveFrustum", function () { diff --git a/packages/engine/Specs/Core/PerspectiveOffCenterFrustumSpec.js b/packages/engine/Specs/Core/PerspectiveOffCenterFrustumSpec.js index 7da3ff6afac..3d4201bff5c 100644 --- a/packages/engine/Specs/Core/PerspectiveOffCenterFrustumSpec.js +++ b/packages/engine/Specs/Core/PerspectiveOffCenterFrustumSpec.js @@ -2,12 +2,11 @@ import { Cartesian2, Cartesian3, Cartesian4, + Math as CesiumMath, Matrix4, PerspectiveOffCenterFrustum, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - describe("Core/PerspectiveOffCenterFrustum", function () { let frustum, planes; diff --git a/packages/engine/Specs/Core/PlaneSpec.js b/packages/engine/Specs/Core/PlaneSpec.js index 0d573a0f0b2..cd41d22d07b 100644 --- a/packages/engine/Specs/Core/PlaneSpec.js +++ b/packages/engine/Specs/Core/PlaneSpec.js @@ -1,13 +1,12 @@ import { Cartesian3, Cartesian4, + Math as CesiumMath, Matrix3, Matrix4, Plane, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - describe("Core/Plane", function () { it("constructs", function () { const normal = Cartesian3.UNIT_X; diff --git a/packages/engine/Specs/Core/PolygonGeometrySpec.js b/packages/engine/Specs/Core/PolygonGeometrySpec.js index 33c92d35032..14d51ec7191 100644 --- a/packages/engine/Specs/Core/PolygonGeometrySpec.js +++ b/packages/engine/Specs/Core/PolygonGeometrySpec.js @@ -7,13 +7,12 @@ import { Ellipsoid, GeometryOffsetAttribute, GeometryPipeline, + Math as CesiumMath, PolygonGeometry, Rectangle, VertexFormat, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createPackableSpecs from "../../../../Specs/createPackableSpecs.js"; describe("Core/PolygonGeometry", function () { diff --git a/packages/engine/Specs/Core/PolygonOutlineGeometrySpec.js b/packages/engine/Specs/Core/PolygonOutlineGeometrySpec.js index 582fbbd8c07..92838d833a1 100644 --- a/packages/engine/Specs/Core/PolygonOutlineGeometrySpec.js +++ b/packages/engine/Specs/Core/PolygonOutlineGeometrySpec.js @@ -4,11 +4,10 @@ import { Cartesian3, Ellipsoid, GeometryOffsetAttribute, + Math as CesiumMath, PolygonOutlineGeometry, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createPackableSpecs from "../../../../Specs/createPackableSpecs.js"; describe("Core/PolygonOutlineGeometry", function () { diff --git a/packages/engine/Specs/Core/PolygonPipelineSpec.js b/packages/engine/Specs/Core/PolygonPipelineSpec.js index 77823cb0f24..b39594523ec 100644 --- a/packages/engine/Specs/Core/PolygonPipelineSpec.js +++ b/packages/engine/Specs/Core/PolygonPipelineSpec.js @@ -2,12 +2,11 @@ import { Cartesian2, Cartesian3, Ellipsoid, + Math as CesiumMath, PolygonPipeline, WindingOrder, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - describe("Core/PolygonPipeline", function () { beforeEach(function () { CesiumMath.setRandomNumberSeed(0.0); diff --git a/packages/engine/Specs/Core/PolylineGeometrySpec.js b/packages/engine/Specs/Core/PolylineGeometrySpec.js index 3ac021c212c..46f0bf04b4d 100644 --- a/packages/engine/Specs/Core/PolylineGeometrySpec.js +++ b/packages/engine/Specs/Core/PolylineGeometrySpec.js @@ -1,14 +1,15 @@ import { + ArcType, Cartesian3, Color, + defaultValue, Ellipsoid, + Math as CesiumMath, PolylineGeometry, VertexFormat, } from "../../index.js"; -import { ArcType, defaultValue } from "../../index.js"; import createPackableSpecs from "../../../../Specs/createPackableSpecs.js"; -import CesiumMath from "../../Source/Core/Math.js"; describe("Core/PolylineGeometry", function () { it("constructor throws with no positions", function () { diff --git a/packages/engine/Specs/Core/PolylinePipelineSpec.js b/packages/engine/Specs/Core/PolylinePipelineSpec.js index cd1e1ca6089..2c8d62b014e 100644 --- a/packages/engine/Specs/Core/PolylinePipelineSpec.js +++ b/packages/engine/Specs/Core/PolylinePipelineSpec.js @@ -1,12 +1,11 @@ import { Cartesian3, Ellipsoid, + Math as CesiumMath, PolylinePipeline, Transforms, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - describe("Core/PolylinePipeline", function () { it("wrapLongitude", function () { const positions = Cartesian3.fromDegreesArray([ diff --git a/packages/engine/Specs/Core/QuadraticRealPolynomialSpec.js b/packages/engine/Specs/Core/QuadraticRealPolynomialSpec.js index e3956505a9a..283e769fab9 100644 --- a/packages/engine/Specs/Core/QuadraticRealPolynomialSpec.js +++ b/packages/engine/Specs/Core/QuadraticRealPolynomialSpec.js @@ -1,5 +1,4 @@ -import { QuadraticRealPolynomial } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; +import { Math as CesiumMath, QuadraticRealPolynomial } from "../../index.js"; describe("Core/QuadraticRealPolynomial", function () { it("discriminant throws without a", function () { diff --git a/packages/engine/Specs/Core/QuantizedMeshTerrainDataSpec.js b/packages/engine/Specs/Core/QuantizedMeshTerrainDataSpec.js index 10357fdad70..11097df0680 100644 --- a/packages/engine/Specs/Core/QuantizedMeshTerrainDataSpec.js +++ b/packages/engine/Specs/Core/QuantizedMeshTerrainDataSpec.js @@ -3,13 +3,12 @@ import { Cartesian3, defined, GeographicTilingScheme, + Math as CesiumMath, QuantizedMeshTerrainData, TerrainData, TerrainMesh, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - describe("Core/QuantizedMeshTerrainData", function () { it("conforms to TerrainData interface", function () { expect(QuantizedMeshTerrainData).toConformToInterface(TerrainData); diff --git a/packages/engine/Specs/Core/QuarticRealPolynomialSpec.js b/packages/engine/Specs/Core/QuarticRealPolynomialSpec.js index 82fcc76e15a..ff3259814cf 100644 --- a/packages/engine/Specs/Core/QuarticRealPolynomialSpec.js +++ b/packages/engine/Specs/Core/QuarticRealPolynomialSpec.js @@ -1,5 +1,4 @@ -import { QuarticRealPolynomial } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; +import { Math as CesiumMath, QuarticRealPolynomial } from "../../index.js"; describe("Core/QuarticRealPolynomial", function () { it("discriminant throws without a", function () { diff --git a/packages/engine/Specs/Core/QuaternionSpec.js b/packages/engine/Specs/Core/QuaternionSpec.js index 8bfc1730513..b5186d4e1ee 100644 --- a/packages/engine/Specs/Core/QuaternionSpec.js +++ b/packages/engine/Specs/Core/QuaternionSpec.js @@ -1,12 +1,11 @@ import { Cartesian3, HeadingPitchRoll, + Math as CesiumMath, Matrix3, Quaternion, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createPackableSpecs from "../../../../Specs/createPackableSpecs.js"; describe("Core/Quaternion", function () { diff --git a/packages/engine/Specs/Core/QuaternionSplineSpec.js b/packages/engine/Specs/Core/QuaternionSplineSpec.js index 300ea367ab5..e8c953433e6 100644 --- a/packages/engine/Specs/Core/QuaternionSplineSpec.js +++ b/packages/engine/Specs/Core/QuaternionSplineSpec.js @@ -1,6 +1,9 @@ -import { Cartesian3, Quaternion, QuaternionSpline } from "../../index.js"; - -import { Math as CesiumMath } from "../../index.js"; +import { + Cartesian3, + Math as CesiumMath, + Quaternion, + QuaternionSpline, +} from "../../index.js"; describe("Core/QuaternionSpline", function () { let points; diff --git a/packages/engine/Specs/Core/RectangleGeometrySpec.js b/packages/engine/Specs/Core/RectangleGeometrySpec.js index 9a4feb0e0d7..2c2451a1835 100644 --- a/packages/engine/Specs/Core/RectangleGeometrySpec.js +++ b/packages/engine/Specs/Core/RectangleGeometrySpec.js @@ -4,14 +4,13 @@ import { Ellipsoid, GeographicProjection, GeometryOffsetAttribute, + Math as CesiumMath, Matrix2, Rectangle, RectangleGeometry, VertexFormat, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createPackableSpecs from "../../../../Specs/createPackableSpecs.js"; describe("Core/RectangleGeometry", function () { diff --git a/packages/engine/Specs/Core/RectangleOutlineGeometrySpec.js b/packages/engine/Specs/Core/RectangleOutlineGeometrySpec.js index ff095efbab0..47def1381cc 100644 --- a/packages/engine/Specs/Core/RectangleOutlineGeometrySpec.js +++ b/packages/engine/Specs/Core/RectangleOutlineGeometrySpec.js @@ -4,13 +4,12 @@ import { Ellipsoid, GeographicProjection, GeometryOffsetAttribute, + Math as CesiumMath, Matrix2, Rectangle, RectangleOutlineGeometry, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createPackableSpecs from "../../../../Specs/createPackableSpecs.js"; describe("Core/RectangleOutlineGeometry", function () { diff --git a/packages/engine/Specs/Core/S2CellSpec.js b/packages/engine/Specs/Core/S2CellSpec.js index ae41af33367..57a4f7ef264 100644 --- a/packages/engine/Specs/Core/S2CellSpec.js +++ b/packages/engine/Specs/Core/S2CellSpec.js @@ -1,8 +1,9 @@ -import { Cartesian3, FeatureDetection, S2Cell } from "../../index.js"; -/* eslint-disable new-cap */ -/* eslint-disable no-undef */ - -import { Math as CesiumMath } from "../../index.js"; +import { + Cartesian3, + FeatureDetection, + Math as CesiumMath, + S2Cell, +} from "../../index.js"; describe("Core/S2Cell", function () { if (!FeatureDetection.supportsBigInt()) { @@ -15,16 +16,16 @@ describe("Core/S2Cell", function () { }); it("throws for invalid cell ID in constructor", function () { - // eslint-disable-next-line new-cap expect(function () { - S2Cell(BigInt(-1)); + // eslint-disable-next-line no-unused-vars + const cell = new S2Cell(BigInt(-1)); }).toThrowDeveloperError(); }); it("throws for missing cell ID in constructor", function () { - // eslint-disable-next-line new-cap expect(function () { - S2Cell(); + // eslint-disable-next-line no-unused-vars + const cell = new S2Cell(); }).toThrowDeveloperError(); }); diff --git a/packages/engine/Specs/Core/SimplePolylineGeometrySpec.js b/packages/engine/Specs/Core/SimplePolylineGeometrySpec.js index d1d3da5a043..1375664dfda 100644 --- a/packages/engine/Specs/Core/SimplePolylineGeometrySpec.js +++ b/packages/engine/Specs/Core/SimplePolylineGeometrySpec.js @@ -4,12 +4,11 @@ import { Cartesian3, Color, Ellipsoid, + Math as CesiumMath, PrimitiveType, SimplePolylineGeometry, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createPackableSpecs from "../../../../Specs/createPackableSpecs.js"; describe("Core/SimplePolylineGeometry", function () { diff --git a/packages/engine/Specs/Core/SphereGeometrySpec.js b/packages/engine/Specs/Core/SphereGeometrySpec.js index a19991ff77d..d4aa38e45c5 100644 --- a/packages/engine/Specs/Core/SphereGeometrySpec.js +++ b/packages/engine/Specs/Core/SphereGeometrySpec.js @@ -1,6 +1,9 @@ -import { Cartesian3, SphereGeometry, VertexFormat } from "../../index.js"; - -import { Math as CesiumMath } from "../../index.js"; +import { + Cartesian3, + Math as CesiumMath, + SphereGeometry, + VertexFormat, +} from "../../index.js"; import createPackableSpecs from "../../../../Specs/createPackableSpecs.js"; diff --git a/packages/engine/Specs/Core/SphereOutlineGeometrySpec.js b/packages/engine/Specs/Core/SphereOutlineGeometrySpec.js index 97e4f78023e..fe20690fb5b 100644 --- a/packages/engine/Specs/Core/SphereOutlineGeometrySpec.js +++ b/packages/engine/Specs/Core/SphereOutlineGeometrySpec.js @@ -1,7 +1,6 @@ -import { SphereOutlineGeometry } from "../../index.js"; +import { Math as CesiumMath, SphereOutlineGeometry } from "../../index.js"; import createPackableSpecs from "../../../../Specs/createPackableSpecs.js"; -import { Math as CesiumMath } from "../../index.js"; describe("Core/SphereOutlineGeometry", function () { it("constructor throws if stackPartitions less than 1", function () { diff --git a/packages/engine/Specs/Core/SphericalSpec.js b/packages/engine/Specs/Core/SphericalSpec.js index 6b174fdd276..c5515a14f86 100644 --- a/packages/engine/Specs/Core/SphericalSpec.js +++ b/packages/engine/Specs/Core/SphericalSpec.js @@ -1,6 +1,4 @@ -import { Cartesian3, Spherical } from "../../index.js"; - -import { Math as CesiumMath } from "../../index.js"; +import { Cartesian3, Math as CesiumMath, Spherical } from "../../index.js"; describe("Core/Spherical", function () { //Mock object to make sure methods take non-sphericals. diff --git a/packages/engine/Specs/Core/TaskProcessorSpec.js b/packages/engine/Specs/Core/TaskProcessorSpec.js index 449209df579..80c541b8776 100644 --- a/packages/engine/Specs/Core/TaskProcessorSpec.js +++ b/packages/engine/Specs/Core/TaskProcessorSpec.js @@ -1,4 +1,9 @@ -import { FeatureDetection, RuntimeError, TaskProcessor } from "../../index.js"; +import { + buildModuleUrl, + FeatureDetection, + RuntimeError, + TaskProcessor, +} from "../../index.js"; import absolutize from "../../../../Specs/absolutize.js"; @@ -60,6 +65,46 @@ describe("Core/TaskProcessor", function () { ); }); + it("when workers loaded via module ID and it is cross-origin, loads worker with appropriate shim", async function () { + // Setup a cross origin BASE_URL + const oldCESIUM_BASE_URL = window.CESIUM_BASE_URL; + window.CESIUM_BASE_URL = "http://test.com/source/"; + buildModuleUrl._clearBaseResource(); + + const blobSpy = spyOn(window, "Blob").and.callThrough(); + + // Provide just the module ID, as is prevalent in the codebase + taskProcessor = new TaskProcessor("transferTypedArrayTest"); + // Create the worker, but don't execute the task this frame + taskProcessor._activeTasks = taskProcessor._maximumActiveTasks; + + await taskProcessor.scheduleTask(); + + expect(blobSpy).toHaveBeenCalledWith( + [`import "http://test.com/source/Workers/transferTypedArrayTest.js";`], + { type: "application/javascript" } + ); + + // Reset old values for BASE_URL + window.CESIUM_BASE_URL = oldCESIUM_BASE_URL; + buildModuleUrl._clearBaseResource(); + }); + + it("when provided a cross-origin URI, loads worker with appropriate shim", async function () { + const blobSpy = spyOn(window, "Blob").and.callThrough(); + + taskProcessor = new TaskProcessor("http://test.com/Workers/testing.js"); + // Create the worker, but don't execute the task this frame + taskProcessor._activeTasks = taskProcessor._maximumActiveTasks; + + await taskProcessor.scheduleTask(); + + expect(blobSpy).toHaveBeenCalledWith( + [`import "http://test.com/Workers/testing.js";`], + { type: "application/javascript" } + ); + }); + it("can be destroyed", function () { taskProcessor = new TaskProcessor( absolutize("../Specs/Build/TestWorkers/returnParameters.js") diff --git a/packages/engine/Specs/Core/TerrainEncodingSpec.js b/packages/engine/Specs/Core/TerrainEncodingSpec.js index 2407ed32fff..3856b6a5952 100644 --- a/packages/engine/Specs/Core/TerrainEncodingSpec.js +++ b/packages/engine/Specs/Core/TerrainEncodingSpec.js @@ -4,6 +4,7 @@ import { Cartesian2, Cartesian3, Ellipsoid, + Math as CesiumMath, Matrix4, TerrainEncoding, VerticalExaggeration, @@ -11,8 +12,6 @@ import { Transforms, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - describe("Core/TerrainEncoding", function () { let center; let maximum; diff --git a/packages/engine/Specs/Core/TransformsSpec.js b/packages/engine/Specs/Core/TransformsSpec.js index f1cd9b75b5b..30306adc419 100644 --- a/packages/engine/Specs/Core/TransformsSpec.js +++ b/packages/engine/Specs/Core/TransformsSpec.js @@ -9,6 +9,7 @@ import { HeadingPitchRoll, Iau2006XysData, JulianDate, + Math as CesiumMath, Matrix3, Matrix4, Quaternion, @@ -18,8 +19,6 @@ import { Transforms, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - describe("Core/Transforms", function () { const negativeX = new Cartesian4(-1, 0, 0, 0); const negativeY = new Cartesian4(0, -1, 0, 0); diff --git a/packages/engine/Specs/Core/TridiagonalSystemSolverSpec.js b/packages/engine/Specs/Core/TridiagonalSystemSolverSpec.js index 39c55821936..b96c8720ab3 100644 --- a/packages/engine/Specs/Core/TridiagonalSystemSolverSpec.js +++ b/packages/engine/Specs/Core/TridiagonalSystemSolverSpec.js @@ -1,6 +1,8 @@ -import { Cartesian3, TridiagonalSystemSolver } from "../../index.js"; - -import { Math as CesiumMath } from "../../index.js"; +import { + Cartesian3, + Math as CesiumMath, + TridiagonalSystemSolver, +} from "../../index.js"; describe("Core/TridiagonalSystemSolver", function () { it("solve throws exception without lower diagonal", function () { diff --git a/packages/engine/Specs/Core/VideoSynchronizerSpec.js b/packages/engine/Specs/Core/VideoSynchronizerSpec.js index 4993cb4c9c1..2b7e578238d 100644 --- a/packages/engine/Specs/Core/VideoSynchronizerSpec.js +++ b/packages/engine/Specs/Core/VideoSynchronizerSpec.js @@ -3,11 +3,10 @@ import { FeatureDetection, Iso8601, JulianDate, + Math as CesiumMath, VideoSynchronizer, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import pollToPromise from "../../../../Specs/pollToPromise.js"; describe("Core/VideoSynchronizer", function () { diff --git a/packages/engine/Specs/Core/WallGeometrySpec.js b/packages/engine/Specs/Core/WallGeometrySpec.js index 98af438006c..d8f430d9f0a 100644 --- a/packages/engine/Specs/Core/WallGeometrySpec.js +++ b/packages/engine/Specs/Core/WallGeometrySpec.js @@ -1,12 +1,11 @@ import { Cartesian3, Ellipsoid, + Math as CesiumMath, VertexFormat, WallGeometry, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createPackableSpecs from "../../../../Specs/createPackableSpecs.js"; describe("Core/WallGeometry", function () { diff --git a/packages/engine/Specs/Core/WallOutlineGeometrySpec.js b/packages/engine/Specs/Core/WallOutlineGeometrySpec.js index 28236e4fb74..42435f0eb47 100644 --- a/packages/engine/Specs/Core/WallOutlineGeometrySpec.js +++ b/packages/engine/Specs/Core/WallOutlineGeometrySpec.js @@ -1,6 +1,9 @@ -import { Cartesian3, Ellipsoid, WallOutlineGeometry } from "../../index.js"; - -import { Math as CesiumMath } from "../../index.js"; +import { + Cartesian3, + Ellipsoid, + Math as CesiumMath, + WallOutlineGeometry, +} from "../../index.js"; import createPackableSpecs from "../../../../Specs/createPackableSpecs.js"; diff --git a/packages/engine/Specs/Core/WebMercatorProjectionSpec.js b/packages/engine/Specs/Core/WebMercatorProjectionSpec.js index 67d1af2fda8..e8c8d0eee17 100644 --- a/packages/engine/Specs/Core/WebMercatorProjectionSpec.js +++ b/packages/engine/Specs/Core/WebMercatorProjectionSpec.js @@ -3,11 +3,10 @@ import { Cartesian3, Cartographic, Ellipsoid, + Math as CesiumMath, WebMercatorProjection, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - describe("Core/WebMercatorProjection", function () { it("construct0", function () { const projection = new WebMercatorProjection(); diff --git a/packages/engine/Specs/Core/WebMercatorTilingSchemeSpec.js b/packages/engine/Specs/Core/WebMercatorTilingSchemeSpec.js index 71aead9eb65..8c1b325fbea 100644 --- a/packages/engine/Specs/Core/WebMercatorTilingSchemeSpec.js +++ b/packages/engine/Specs/Core/WebMercatorTilingSchemeSpec.js @@ -2,14 +2,13 @@ import { Cartesian2, Cartographic, Ellipsoid, + Math as CesiumMath, Rectangle, TilingScheme, WebMercatorProjection, WebMercatorTilingScheme, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - describe("Core/WebMercatorTilingScheme", function () { let tilingScheme; beforeEach(function () { diff --git a/packages/engine/Specs/Core/arrayRemoveDuplicatesSpec.js b/packages/engine/Specs/Core/arrayRemoveDuplicatesSpec.js index b787cba4f47..fa7bd7714a7 100644 --- a/packages/engine/Specs/Core/arrayRemoveDuplicatesSpec.js +++ b/packages/engine/Specs/Core/arrayRemoveDuplicatesSpec.js @@ -1,6 +1,9 @@ -import { arrayRemoveDuplicates, Cartesian3, Spherical } from "../../index.js"; - -import { Math as CesiumMath } from "../../index.js"; +import { + arrayRemoveDuplicates, + Cartesian3, + Math as CesiumMath, + Spherical, +} from "../../index.js"; describe("Core/arrayRemoveDuplicates", function () { it("removeDuplicates returns positions if none removed - length === 1", function () { diff --git a/packages/engine/Specs/Core/barycentricCoordinatesSpec.js b/packages/engine/Specs/Core/barycentricCoordinatesSpec.js index 59af6f8c5ed..3b8f81d4638 100644 --- a/packages/engine/Specs/Core/barycentricCoordinatesSpec.js +++ b/packages/engine/Specs/Core/barycentricCoordinatesSpec.js @@ -1,6 +1,8 @@ -import { barycentricCoordinates, Cartesian3 } from "../../index.js"; - -import { Math as CesiumMath } from "../../index.js"; +import { + barycentricCoordinates, + Cartesian3, + Math as CesiumMath, +} from "../../index.js"; describe("Core/barycentricCoordinates", function () { const p0 = new Cartesian3(-1.0, 0.0, 0.0); diff --git a/packages/engine/Specs/Core/sampleTerrainSpec.js b/packages/engine/Specs/Core/sampleTerrainSpec.js index c88c1a5ddff..ce265ee5ca5 100644 --- a/packages/engine/Specs/Core/sampleTerrainSpec.js +++ b/packages/engine/Specs/Core/sampleTerrainSpec.js @@ -104,6 +104,16 @@ describe("Core/sampleTerrain", function () { ).toBeRejected(); }); + it("rejects if terrain data is not available for the second position and rejectOnTileFail is true", function () { + const positionWithData = Cartographic.fromDegrees(86.925145, 27.988257); + const positionWithoutData = Cartographic.fromDegrees(0.0, 0.0, 0.0); + + const positions = [positionWithData, positionWithoutData]; + return expectAsync( + sampleTerrain(worldTerrain, 12, positions, true) + ).toBeRejected(); + }); + it("fills in what it can when given a mix of positions with and without valid tiles", function () { const positions = [ Cartographic.fromDegrees(86.925145, 27.988257), diff --git a/packages/engine/Specs/DataSources/CorridorGeometryUpdaterSpec.js b/packages/engine/Specs/DataSources/CorridorGeometryUpdaterSpec.js index 9f25bedf82e..6f455e96ce6 100644 --- a/packages/engine/Specs/DataSources/CorridorGeometryUpdaterSpec.js +++ b/packages/engine/Specs/DataSources/CorridorGeometryUpdaterSpec.js @@ -3,6 +3,7 @@ import { Cartesian3, CornerType, JulianDate, + Math as CesiumMath, TimeInterval, TimeIntervalCollection, ConstantProperty, @@ -16,8 +17,6 @@ import { PrimitiveCollection, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createDynamicGeometryUpdaterSpecs from "../../../../Specs/createDynamicGeometryUpdaterSpecs.js"; import createDynamicProperty from "../../../../Specs/createDynamicProperty.js"; import createGeometryUpdaterGroundGeometrySpecs from "../../../../Specs/createGeometryUpdaterGroundGeometrySpecs.js"; diff --git a/packages/engine/Specs/DataSources/EllipsoidGeometryUpdaterSpec.js b/packages/engine/Specs/DataSources/EllipsoidGeometryUpdaterSpec.js index 8d3e910ee5b..15429632c91 100644 --- a/packages/engine/Specs/DataSources/EllipsoidGeometryUpdaterSpec.js +++ b/packages/engine/Specs/DataSources/EllipsoidGeometryUpdaterSpec.js @@ -4,6 +4,7 @@ import { ColorGeometryInstanceAttribute, GeometryOffsetAttribute, JulianDate, + Math as CesiumMath, Quaternion, TimeIntervalCollection, ColorMaterialProperty, @@ -18,8 +19,6 @@ import { PrimitiveCollection, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createDynamicGeometryUpdaterSpecs from "../../../../Specs/createDynamicGeometryUpdaterSpecs.js"; import createDynamicProperty from "../../../../Specs/createDynamicProperty.js"; import createGeometryUpdaterSpecs from "../../../../Specs/createGeometryUpdaterSpecs.js"; diff --git a/packages/engine/Specs/DataSources/KmlDataSourceSpec.js b/packages/engine/Specs/DataSources/KmlDataSourceSpec.js index 15f9bfd6c5f..0fe44e005c4 100644 --- a/packages/engine/Specs/DataSources/KmlDataSourceSpec.js +++ b/packages/engine/Specs/DataSources/KmlDataSourceSpec.js @@ -16,6 +16,7 @@ import { isDataUri, Iso8601, JulianDate, + Math as CesiumMath, NearFarScalar, PerspectiveFrustum, Rectangle, @@ -38,8 +39,6 @@ import { SceneMode, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createCamera from "../../../../Specs/createCamera.js"; import pollToPromise from "../../../../Specs/pollToPromise.js"; diff --git a/packages/engine/Specs/DataSources/KmlTourFlyToSpec.js b/packages/engine/Specs/DataSources/KmlTourFlyToSpec.js index 6430da63c06..da982b9920a 100644 --- a/packages/engine/Specs/DataSources/KmlTourFlyToSpec.js +++ b/packages/engine/Specs/DataSources/KmlTourFlyToSpec.js @@ -5,10 +5,9 @@ import { KmlCamera, KmlLookAt, KmlTourFlyTo, + Math as CesiumMath, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import pollToPromise from "../../../../Specs/pollToPromise.js"; describe("DataSources/KmlTourFlyTo", function () { diff --git a/packages/engine/Specs/DataSources/PolygonGeometryUpdaterSpec.js b/packages/engine/Specs/DataSources/PolygonGeometryUpdaterSpec.js index 8d1fdea0b76..7e01741214f 100644 --- a/packages/engine/Specs/DataSources/PolygonGeometryUpdaterSpec.js +++ b/packages/engine/Specs/DataSources/PolygonGeometryUpdaterSpec.js @@ -8,6 +8,7 @@ import { CoplanarPolygonOutlineGeometry, Ellipsoid, JulianDate, + Math as CesiumMath, PolygonGeometry, PolygonHierarchy, PolygonOutlineGeometry, @@ -24,8 +25,6 @@ import { PrimitiveCollection, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createDynamicGeometryUpdaterSpecs from "../../../../Specs/createDynamicGeometryUpdaterSpecs.js"; import createDynamicProperty from "../../../../Specs/createDynamicProperty.js"; import createGeometryUpdaterGroundGeometrySpecs from "../../../../Specs/createGeometryUpdaterGroundGeometrySpecs.js"; diff --git a/packages/engine/Specs/DataSources/RectangleGeometryUpdaterSpec.js b/packages/engine/Specs/DataSources/RectangleGeometryUpdaterSpec.js index 8d376e20dfb..551b4e52397 100644 --- a/packages/engine/Specs/DataSources/RectangleGeometryUpdaterSpec.js +++ b/packages/engine/Specs/DataSources/RectangleGeometryUpdaterSpec.js @@ -2,6 +2,7 @@ import { ApproximateTerrainHeights, Cartesian3, JulianDate, + Math as CesiumMath, Rectangle, TimeIntervalCollection, ConstantProperty, @@ -12,8 +13,6 @@ import { PrimitiveCollection, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createDynamicGeometryUpdaterSpecs from "../../../../Specs/createDynamicGeometryUpdaterSpecs.js"; import createDynamicProperty from "../../../../Specs/createDynamicProperty.js"; import createGeometryUpdaterGroundGeometrySpecs from "../../../../Specs/createGeometryUpdaterGroundGeometrySpecs.js"; diff --git a/packages/engine/Specs/DataSources/RotationSpec.js b/packages/engine/Specs/DataSources/RotationSpec.js index 7603863f99d..97a5d09b5cd 100644 --- a/packages/engine/Specs/DataSources/RotationSpec.js +++ b/packages/engine/Specs/DataSources/RotationSpec.js @@ -1,6 +1,9 @@ -import { JulianDate, Rotation, SampledProperty } from "../../index.js"; - -import { Math as CesiumMath } from "../../index.js"; +import { + JulianDate, + Math as CesiumMath, + Rotation, + SampledProperty, +} from "../../index.js"; import createPackableSpecs from "../../../../Specs/createPackableSpecs.js"; diff --git a/packages/engine/Specs/DataSources/SampledPropertySpec.js b/packages/engine/Specs/DataSources/SampledPropertySpec.js index 1eb6a80aaa6..8f98ee27507 100644 --- a/packages/engine/Specs/DataSources/SampledPropertySpec.js +++ b/packages/engine/Specs/DataSources/SampledPropertySpec.js @@ -6,13 +6,12 @@ import { JulianDate, LagrangePolynomialApproximation, LinearApproximation, + Math as CesiumMath, Quaternion, TimeInterval, SampledProperty, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - describe("DataSources/SampledProperty", function () { it("constructor sets expected defaults", function () { let property = new SampledProperty(Cartesian3); diff --git a/packages/engine/Specs/DataSources/StaticGeometryColorBatchSpec.js b/packages/engine/Specs/DataSources/StaticGeometryColorBatchSpec.js index 4f032c5563c..379410a2a3b 100644 --- a/packages/engine/Specs/DataSources/StaticGeometryColorBatchSpec.js +++ b/packages/engine/Specs/DataSources/StaticGeometryColorBatchSpec.js @@ -3,6 +3,7 @@ import { Color, DistanceDisplayCondition, JulianDate, + Math as CesiumMath, TimeInterval, TimeIntervalCollection, CallbackProperty, @@ -17,8 +18,6 @@ import { ShadowMode, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createScene from "../../../../Specs/createScene.js"; import pollToPromise from "../../../../Specs/pollToPromise.js"; diff --git a/packages/engine/Specs/DataSources/StaticGeometryPerMaterialBatchSpec.js b/packages/engine/Specs/DataSources/StaticGeometryPerMaterialBatchSpec.js index d47aefd4491..ea0933a13df 100644 --- a/packages/engine/Specs/DataSources/StaticGeometryPerMaterialBatchSpec.js +++ b/packages/engine/Specs/DataSources/StaticGeometryPerMaterialBatchSpec.js @@ -4,6 +4,7 @@ import { Color, DistanceDisplayCondition, JulianDate, + Math as CesiumMath, TimeInterval, TimeIntervalCollection, BoxGeometryUpdater, @@ -27,8 +28,6 @@ import { ShadowMode, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createScene from "../../../../Specs/createScene.js"; import pollToPromise from "../../../../Specs/pollToPromise.js"; diff --git a/packages/engine/Specs/DataSources/StaticGroundGeometryColorBatchSpec.js b/packages/engine/Specs/DataSources/StaticGroundGeometryColorBatchSpec.js index ed74bebc081..24711775a35 100644 --- a/packages/engine/Specs/DataSources/StaticGroundGeometryColorBatchSpec.js +++ b/packages/engine/Specs/DataSources/StaticGroundGeometryColorBatchSpec.js @@ -4,6 +4,7 @@ import { Color, DistanceDisplayCondition, JulianDate, + Math as CesiumMath, TimeInterval, TimeIntervalCollection, CallbackProperty, @@ -15,8 +16,6 @@ import { GroundPrimitive, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createScene from "../../../../Specs/createScene.js"; import pollToPromise from "../../../../Specs/pollToPromise.js"; diff --git a/packages/engine/Specs/DataSources/StaticGroundGeometryPerMaterialBatchSpec.js b/packages/engine/Specs/DataSources/StaticGroundGeometryPerMaterialBatchSpec.js index 26bb7fd8ba8..6f7ceb39ab5 100644 --- a/packages/engine/Specs/DataSources/StaticGroundGeometryPerMaterialBatchSpec.js +++ b/packages/engine/Specs/DataSources/StaticGroundGeometryPerMaterialBatchSpec.js @@ -5,6 +5,7 @@ import { Color, DistanceDisplayCondition, JulianDate, + Math as CesiumMath, TimeInterval, TimeIntervalCollection, ConstantProperty, @@ -19,8 +20,6 @@ import { MaterialAppearance, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createScene from "../../../../Specs/createScene.js"; import pollToPromise from "../../../../Specs/pollToPromise.js"; diff --git a/packages/engine/Specs/DataSources/StaticGroundPolylinePerMaterialBatchSpec.js b/packages/engine/Specs/DataSources/StaticGroundPolylinePerMaterialBatchSpec.js index 028ed7db0de..32ade306d4f 100644 --- a/packages/engine/Specs/DataSources/StaticGroundPolylinePerMaterialBatchSpec.js +++ b/packages/engine/Specs/DataSources/StaticGroundPolylinePerMaterialBatchSpec.js @@ -6,6 +6,7 @@ import { defined, DistanceDisplayCondition, JulianDate, + Math as CesiumMath, TimeInterval, TimeIntervalCollection, BoundingSphereState, @@ -21,8 +22,6 @@ import { GroundPolylinePrimitive, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createScene from "../../../../Specs/createScene.js"; import pollToPromise from "../../../../Specs/pollToPromise.js"; diff --git a/packages/engine/Specs/DataSources/StaticOutlineGeometryBatchSpec.js b/packages/engine/Specs/DataSources/StaticOutlineGeometryBatchSpec.js index f468076338a..3af4d26484a 100644 --- a/packages/engine/Specs/DataSources/StaticOutlineGeometryBatchSpec.js +++ b/packages/engine/Specs/DataSources/StaticOutlineGeometryBatchSpec.js @@ -3,6 +3,7 @@ import { Color, DistanceDisplayCondition, JulianDate, + Math as CesiumMath, TimeInterval, TimeIntervalCollection, CallbackProperty, @@ -13,8 +14,6 @@ import { ShadowMode, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createScene from "../../../../Specs/createScene.js"; import pollToPromise from "../../../../Specs/pollToPromise.js"; diff --git a/packages/engine/Specs/DataSources/VelocityVectorPropertySpec.js b/packages/engine/Specs/DataSources/VelocityVectorPropertySpec.js index 0ee09930845..7a65f3b3b3a 100644 --- a/packages/engine/Specs/DataSources/VelocityVectorPropertySpec.js +++ b/packages/engine/Specs/DataSources/VelocityVectorPropertySpec.js @@ -3,14 +3,13 @@ import { Event, ExtrapolationType, JulianDate, + Math as CesiumMath, CallbackProperty, ConstantPositionProperty, SampledPositionProperty, VelocityVectorProperty, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - describe("DataSources/VelocityVectorProperty", function () { const time = JulianDate.now(); diff --git a/packages/engine/Specs/DataSources/exportKmlSpec.js b/packages/engine/Specs/DataSources/exportKmlSpec.js index 542a2edcc33..61c40af5615 100644 --- a/packages/engine/Specs/DataSources/exportKmlSpec.js +++ b/packages/engine/Specs/DataSources/exportKmlSpec.js @@ -8,6 +8,7 @@ import { defined, Iso8601, JulianDate, + Math as CesiumMath, PolygonHierarchy, Rectangle, TimeInterval, @@ -24,8 +25,6 @@ import { VerticalOrigin, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - describe("DataSources/exportKml", function () { let kmlDoc; function checkKmlDoc(entities, properties, options) { diff --git a/packages/engine/Specs/Scene/AxisSpec.js b/packages/engine/Specs/Scene/AxisSpec.js index 5478e5e413b..f01d807ed0f 100644 --- a/packages/engine/Specs/Scene/AxisSpec.js +++ b/packages/engine/Specs/Scene/AxisSpec.js @@ -1,6 +1,4 @@ -import { Cartesian4, Matrix4, Axis } from "../../index.js"; - -import { Math as CesiumMath } from "../../index.js"; +import { Cartesian4, Math as CesiumMath, Matrix4, Axis } from "../../index.js"; describe("Scene/Axis", function () { function convertUpAxis(upAxis, transformation, expected) { diff --git a/packages/engine/Specs/Scene/BatchTableSpec.js b/packages/engine/Specs/Scene/BatchTableSpec.js index feb3c823c6c..ea765487e13 100644 --- a/packages/engine/Specs/Scene/BatchTableSpec.js +++ b/packages/engine/Specs/Scene/BatchTableSpec.js @@ -1,13 +1,12 @@ import { Cartesian4, ComponentDatatype, + Math as CesiumMath, PixelDatatype, Texture, BatchTable, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createScene from "../../../../Specs/createScene.js"; describe( diff --git a/packages/engine/Specs/Scene/BillboardCollectionSpec.js b/packages/engine/Specs/Scene/BillboardCollectionSpec.js index 58b341e8fc7..a47d5246846 100644 --- a/packages/engine/Specs/Scene/BillboardCollectionSpec.js +++ b/packages/engine/Specs/Scene/BillboardCollectionSpec.js @@ -9,6 +9,7 @@ import { createGuid, DistanceDisplayCondition, Globe, + Math as CesiumMath, NearFarScalar, OrthographicOffCenterFrustum, PerspectiveFrustum, @@ -23,8 +24,6 @@ import { VerticalOrigin, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createScene from "../../../../Specs/createScene.js"; import pollToPromise from "../../../../Specs/pollToPromise.js"; diff --git a/packages/engine/Specs/Scene/CameraFlightPathSpec.js b/packages/engine/Specs/Scene/CameraFlightPathSpec.js index 795c7bc0255..a4573e7688e 100644 --- a/packages/engine/Specs/Scene/CameraFlightPathSpec.js +++ b/packages/engine/Specs/Scene/CameraFlightPathSpec.js @@ -4,13 +4,12 @@ import { Ellipsoid, GeographicProjection, Globe, + Math as CesiumMath, OrthographicOffCenterFrustum, CameraFlightPath, SceneMode, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createScene from "../../../../Specs/createScene.js"; describe( diff --git a/packages/engine/Specs/Scene/CameraSpec.js b/packages/engine/Specs/Scene/CameraSpec.js index c6340f832ab..6f90f345f17 100644 --- a/packages/engine/Specs/Scene/CameraSpec.js +++ b/packages/engine/Specs/Scene/CameraSpec.js @@ -8,6 +8,7 @@ import { Ellipsoid, GeographicProjection, HeadingPitchRange, + Math as CesiumMath, Matrix3, Matrix4, OrthographicFrustum, @@ -23,8 +24,6 @@ import { TweenCollection, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - describe("Scene/Camera", function () { let scene; let camera; diff --git a/packages/engine/Specs/Scene/CloudCollectionSpec.js b/packages/engine/Specs/Scene/CloudCollectionSpec.js index fae53214550..a8283482baa 100644 --- a/packages/engine/Specs/Scene/CloudCollectionSpec.js +++ b/packages/engine/Specs/Scene/CloudCollectionSpec.js @@ -7,13 +7,11 @@ import { ComputeCommand, DrawCommand, defined, + Math as CesiumMath, PerspectiveFrustum, } from "../../index.js"; import createScene from "../../../../Specs/createScene.js"; - -import { Math as CesiumMath } from "../../index.js"; - import pollToPromise from "../../../../Specs/pollToPromise.js"; describe( diff --git a/packages/engine/Specs/Scene/ConeEmitterSpec.js b/packages/engine/Specs/Scene/ConeEmitterSpec.js index 54e62f1ce1e..f3f94dd75ad 100644 --- a/packages/engine/Specs/Scene/ConeEmitterSpec.js +++ b/packages/engine/Specs/Scene/ConeEmitterSpec.js @@ -1,6 +1,9 @@ -import { Cartesian3, ConeEmitter, Particle } from "../../index.js"; - -import { Math as CesiumMath } from "../../index.js"; +import { + Cartesian3, + ConeEmitter, + Math as CesiumMath, + Particle, +} from "../../index.js"; describe("Scene/ConeEmitter", function () { it("default constructor", function () { diff --git a/packages/engine/Specs/Scene/DeviceOrientationCameraControllerSpec.js b/packages/engine/Specs/Scene/DeviceOrientationCameraControllerSpec.js index 245d90f9639..af76fa49b6d 100644 --- a/packages/engine/Specs/Scene/DeviceOrientationCameraControllerSpec.js +++ b/packages/engine/Specs/Scene/DeviceOrientationCameraControllerSpec.js @@ -1,6 +1,8 @@ -import { Cartesian3, DeviceOrientationCameraController } from "../../index.js"; - -import { Math as CesiumMath } from "../../index.js"; +import { + Cartesian3, + DeviceOrientationCameraController, + Math as CesiumMath, +} from "../../index.js"; import createCamera from "../../../../Specs/createCamera.js"; import createCanvas from "../../../../Specs/createCanvas.js"; diff --git a/packages/engine/Specs/Scene/ExpressionSpec.js b/packages/engine/Specs/Scene/ExpressionSpec.js index a5a5c7f3942..c1f1d8c9d7b 100644 --- a/packages/engine/Specs/Scene/ExpressionSpec.js +++ b/packages/engine/Specs/Scene/ExpressionSpec.js @@ -5,11 +5,10 @@ import { Color, Expression, ExpressionNodeType, + Math as CesiumMath, RuntimeError, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - describe("Scene/Expression", function () { function MockFeature() { this._properties = {}; diff --git a/packages/engine/Specs/Scene/GeometryRenderingSpec.js b/packages/engine/Specs/Scene/GeometryRenderingSpec.js index 46ebb2e0348..316131be6ef 100644 --- a/packages/engine/Specs/Scene/GeometryRenderingSpec.js +++ b/packages/engine/Specs/Scene/GeometryRenderingSpec.js @@ -19,6 +19,7 @@ import { Geometry, GeometryAttribute, GeometryInstance, + Math as CesiumMath, Matrix4, PerspectiveFrustum, PlaneGeometry, @@ -40,8 +41,6 @@ import { SceneMode, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createScene from "../../../../Specs/createScene.js"; import pollToPromise from "../../../../Specs/pollToPromise.js"; diff --git a/packages/engine/Specs/Scene/GltfLoaderSpec.js b/packages/engine/Specs/Scene/GltfLoaderSpec.js index 24a7f780784..cfcab67f19d 100644 --- a/packages/engine/Specs/Scene/GltfLoaderSpec.js +++ b/packages/engine/Specs/Scene/GltfLoaderSpec.js @@ -122,6 +122,12 @@ describe( "./Data/Models/glTF-2.0/TorusQuantized/glTF/TorusQuantized.gltf"; const boxWeb3dQuantizedAttributes = "./Data/Models/glTF-2.0/BoxWeb3dQuantizedAttributes/glTF/BoxWeb3dQuantizedAttributes.gltf"; + const specularTestData = + "./Data/Models/glTF-2.0/BoxSpecular/glTF/BoxSpecular.gltf"; + const anisotropyTestData = + "./Data/Models/glTF-2.0/BoxAnisotropy/glTF/BoxAnisotropy.gltf"; + const clearcoatTestData = + "./Data/Models/glTF-2.0/BoxClearcoat/glTF/BoxClearcoat.gltf"; let scene; const gltfLoaders = []; @@ -4138,6 +4144,53 @@ describe( }); }); + it("loads model with KHR_materials_specular extension", async function () { + const gltfLoader = await loadGltf(specularTestData); + + const { material } = gltfLoader.components.nodes[1].primitives[0]; + + expect(material.specular.specularFactor).toEqual(0.7); + expect(material.specular.specularTexture.texture.width).toBe(256); + expect(material.specular.specularColorFactor).toEqual( + Cartesian3.fromElements(50, 0, 0) + ); + expect(material.specular.specularTexture.texture.width).toBe(256); + }); + + it("loads model with KHR_materials_anisotropy extension", async function () { + const gltfLoader = await loadGltf(anisotropyTestData); + + const { material } = gltfLoader.components.nodes[1].primitives[0]; + const { + anisotropyStrength, + anisotropyRotation, + anisotropyTexture, + } = material.anisotropy; + + expect(anisotropyStrength).toBe(0.5); + expect(anisotropyRotation).toBe(0.349065850398866); + expect(anisotropyTexture.texture.width).toBe(256); + }); + + it("loads model with KHR_materials_clearcoat extension", async function () { + const gltfLoader = await loadGltf(clearcoatTestData); + + const { material } = gltfLoader.components.nodes[1].primitives[0]; + const { + clearcoatFactor, + clearcoatTexture, + clearcoatRoughnessFactor, + clearcoatRoughnessTexture, + clearcoatNormalTexture, + } = material.clearcoat; + + expect(clearcoatFactor).toBe(0.5); + expect(clearcoatTexture.texture.width).toBe(256); + expect(clearcoatRoughnessFactor).toBe(0.2); + expect(clearcoatRoughnessTexture.texture.width).toBe(256); + expect(clearcoatNormalTexture.texture.width).toBe(256); + }); + it("parses copyright field", function () { return loadGltf(boxWithCredits).then(function (gltfLoader) { const components = gltfLoader.components; diff --git a/packages/engine/Specs/Scene/GroundPolylinePrimitiveSpec.js b/packages/engine/Specs/Scene/GroundPolylinePrimitiveSpec.js index 3e394c60955..fd9f8eeb639 100644 --- a/packages/engine/Specs/Scene/GroundPolylinePrimitiveSpec.js +++ b/packages/engine/Specs/Scene/GroundPolylinePrimitiveSpec.js @@ -10,6 +10,7 @@ import { GeometryInstance, GroundPolylineGeometry, HeadingPitchRange, + Math as CesiumMath, Rectangle, RectangleGeometry, ShowGeometryInstanceAttribute, @@ -21,8 +22,6 @@ import { Primitive, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createCanvas from "../../../../Specs/createCanvas.js"; import createScene from "../../../../Specs/createScene.js"; import pollToPromise from "../../../../Specs/pollToPromise.js"; diff --git a/packages/engine/Specs/Scene/GroundPrimitiveSpec.js b/packages/engine/Specs/Scene/GroundPrimitiveSpec.js index 20a453354b2..1fffa328d6f 100644 --- a/packages/engine/Specs/Scene/GroundPrimitiveSpec.js +++ b/packages/engine/Specs/Scene/GroundPrimitiveSpec.js @@ -7,6 +7,7 @@ import { Ellipsoid, GeometryInstance, HeadingPitchRange, + Math as CesiumMath, PolygonGeometry, Rectangle, RectangleGeometry, @@ -23,8 +24,6 @@ import { StencilConstants, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createCanvas from "../../../../Specs/createCanvas.js"; import createScene from "../../../../Specs/createScene.js"; import pollToPromise from "../../../../Specs/pollToPromise.js"; diff --git a/packages/engine/Specs/Scene/HeightmapTessellatorSpec.js b/packages/engine/Specs/Scene/HeightmapTessellatorSpec.js index 9505296676e..06835f4d42a 100644 --- a/packages/engine/Specs/Scene/HeightmapTessellatorSpec.js +++ b/packages/engine/Specs/Scene/HeightmapTessellatorSpec.js @@ -3,12 +3,11 @@ import { Cartesian3, Ellipsoid, HeightmapTessellator, + Math as CesiumMath, Rectangle, WebMercatorProjection, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - describe("Scene/HeightmapTessellator", function () { it("throws when heightmap is not provided", function () { expect(function () { diff --git a/packages/engine/Specs/Scene/LabelCollectionSpec.js b/packages/engine/Specs/Scene/LabelCollectionSpec.js index 70d96c24404..352e8fcfd82 100644 --- a/packages/engine/Specs/Scene/LabelCollectionSpec.js +++ b/packages/engine/Specs/Scene/LabelCollectionSpec.js @@ -7,6 +7,7 @@ import { Color, defined, DistanceDisplayCondition, + Math as CesiumMath, NearFarScalar, Rectangle, BlendOption, @@ -19,7 +20,6 @@ import { VerticalOrigin, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; import createScene from "../../../../Specs/createScene.js"; import pollToPromise from "../../../../Specs/pollToPromise.js"; diff --git a/packages/engine/Specs/Scene/MapboxImageryProviderSpec.js b/packages/engine/Specs/Scene/MapboxImageryProviderSpec.js index e2f3374f26a..201da71b3e6 100644 --- a/packages/engine/Specs/Scene/MapboxImageryProviderSpec.js +++ b/packages/engine/Specs/Scene/MapboxImageryProviderSpec.js @@ -1,4 +1,5 @@ import { + Math as CesiumMath, Rectangle, Request, RequestScheduler, @@ -10,7 +11,6 @@ import { ImageryState, MapboxImageryProvider, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; import pollToPromise from "../../../../Specs/pollToPromise.js"; diff --git a/packages/engine/Specs/Scene/MapboxStyleImageryProviderSpec.js b/packages/engine/Specs/Scene/MapboxStyleImageryProviderSpec.js index 16fa51193a1..a44d3c25c3e 100644 --- a/packages/engine/Specs/Scene/MapboxStyleImageryProviderSpec.js +++ b/packages/engine/Specs/Scene/MapboxStyleImageryProviderSpec.js @@ -1,4 +1,5 @@ import { + Math as CesiumMath, Rectangle, Request, RequestScheduler, @@ -10,7 +11,6 @@ import { ImageryState, MapboxStyleImageryProvider, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; import pollToPromise from "../../../../Specs/pollToPromise.js"; diff --git a/packages/engine/Specs/Scene/Model/MaterialPipelineStageSpec.js b/packages/engine/Specs/Scene/Model/MaterialPipelineStageSpec.js index 9c6f090d70a..389be73969a 100644 --- a/packages/engine/Specs/Scene/Model/MaterialPipelineStageSpec.js +++ b/packages/engine/Specs/Scene/Model/MaterialPipelineStageSpec.js @@ -85,6 +85,12 @@ describe( const triangle = "./Data/Models/glTF-2.0/Triangle/glTF/Triangle.gltf"; const twoSidedPlane = "./Data/Models/glTF-2.0/TwoSidedPlane/glTF/TwoSidedPlane.gltf"; + const specularTestData = + "./Data/Models/glTF-2.0/BoxSpecular/glTF/BoxSpecular.gltf"; + const anisotropyTestData = + "./Data/Models/glTF-2.0/BoxAnisotropy/glTF/BoxAnisotropy.gltf"; + const clearcoatTestData = + "./Data/Models/glTF-2.0/BoxClearcoat/glTF/BoxClearcoat.gltf"; function expectUniformMap(uniformMap, expected) { for (const key in expected) { @@ -111,656 +117,671 @@ describe( }; } - it("processes default material", function () { - return loadGltf(triangle).then(function (gltfLoader) { - const components = gltfLoader.components; - const primitive = components.nodes[0].primitives[0]; + it("processes default material", async function () { + const gltfLoader = await loadGltf(triangle); + const primitive = gltfLoader.components.nodes[0].primitives[0]; - const renderResources = mockRenderResources(); - const shaderBuilder = renderResources.shaderBuilder; - const uniformMap = renderResources.uniformMap; + const renderResources = mockRenderResources(); + const { shaderBuilder, uniformMap } = renderResources; - MaterialPipelineStage.process( - renderResources, - primitive, - mockFrameState - ); + MaterialPipelineStage.process(renderResources, primitive, mockFrameState); - ShaderBuilderTester.expectHasVertexUniforms(shaderBuilder, []); - ShaderBuilderTester.expectHasFragmentUniforms(shaderBuilder, []); + ShaderBuilderTester.expectHasVertexUniforms(shaderBuilder, []); + ShaderBuilderTester.expectHasFragmentUniforms(shaderBuilder, []); - ShaderBuilderTester.expectHasVertexDefines(shaderBuilder, []); - ShaderBuilderTester.expectHasFragmentDefines(shaderBuilder, [ - "USE_METALLIC_ROUGHNESS", - ]); + ShaderBuilderTester.expectHasVertexDefines(shaderBuilder, []); + ShaderBuilderTester.expectHasFragmentDefines(shaderBuilder, [ + "USE_METALLIC_ROUGHNESS", + ]); - const expectedUniforms = {}; - expectUniformMap(uniformMap, expectedUniforms); - }); + const expectedUniforms = {}; + expectUniformMap(uniformMap, expectedUniforms); }); - it("adds material and metallic roughness uniforms", function () { - return loadGltf(boomBox).then(function (gltfLoader) { - const components = gltfLoader.components; - const primitive = components.nodes[0].primitives[0]; - const renderResources = mockRenderResources(); - const shaderBuilder = renderResources.shaderBuilder; - const uniformMap = renderResources.uniformMap; - - MaterialPipelineStage.process( - renderResources, - primitive, - mockFrameState - ); - - ShaderBuilderTester.expectHasVertexUniforms(shaderBuilder, []); - ShaderBuilderTester.expectHasFragmentUniforms(shaderBuilder, [ - "uniform sampler2D u_baseColorTexture;", - "uniform sampler2D u_emissiveTexture;", - "uniform sampler2D u_metallicRoughnessTexture;", - "uniform sampler2D u_normalTexture;", - "uniform sampler2D u_occlusionTexture;", - "uniform vec3 u_emissiveFactor;", - ]); - - ShaderBuilderTester.expectHasVertexDefines(shaderBuilder, []); - ShaderBuilderTester.expectHasFragmentDefines(shaderBuilder, [ - "HAS_BASE_COLOR_TEXTURE", - "HAS_EMISSIVE_FACTOR", - "HAS_EMISSIVE_TEXTURE", - "HAS_METALLIC_ROUGHNESS_TEXTURE", - "HAS_NORMAL_TEXTURE", - "HAS_OCCLUSION_TEXTURE", - "TEXCOORD_BASE_COLOR v_texCoord_0", - "TEXCOORD_EMISSIVE v_texCoord_0", - "TEXCOORD_METALLIC_ROUGHNESS v_texCoord_0", - "TEXCOORD_NORMAL v_texCoord_0", - "TEXCOORD_OCCLUSION v_texCoord_0", - "USE_METALLIC_ROUGHNESS", - ]); - - const metallicRoughness = primitive.material.metallicRoughness; - const material = primitive.material; - const expectedUniforms = { - u_emissiveTexture: material.emissiveTexture.texture, - u_emissiveFactor: material.emissiveFactor, - u_normalTexture: material.normalTexture.texture, - u_occlusionTexture: material.occlusionTexture.texture, - u_baseColorTexture: metallicRoughness.baseColorTexture.texture, - u_metallicRoughnessTexture: - metallicRoughness.metallicRoughnessTexture.texture, - }; - expectUniformMap(uniformMap, expectedUniforms); - }); + it("adds material and metallic roughness uniforms", async function () { + const gltfLoader = await loadGltf(boomBox); + const primitive = gltfLoader.components.nodes[0].primitives[0]; + const renderResources = mockRenderResources(); + const { shaderBuilder, uniformMap } = renderResources; + + MaterialPipelineStage.process(renderResources, primitive, mockFrameState); + + ShaderBuilderTester.expectHasVertexUniforms(shaderBuilder, []); + ShaderBuilderTester.expectHasFragmentUniforms(shaderBuilder, [ + "uniform sampler2D u_baseColorTexture;", + "uniform sampler2D u_emissiveTexture;", + "uniform sampler2D u_metallicRoughnessTexture;", + "uniform sampler2D u_normalTexture;", + "uniform sampler2D u_occlusionTexture;", + "uniform vec3 u_emissiveFactor;", + ]); + + ShaderBuilderTester.expectHasVertexDefines(shaderBuilder, []); + ShaderBuilderTester.expectHasFragmentDefines(shaderBuilder, [ + "HAS_BASE_COLOR_TEXTURE", + "HAS_EMISSIVE_FACTOR", + "HAS_EMISSIVE_TEXTURE", + "HAS_METALLIC_ROUGHNESS_TEXTURE", + "HAS_NORMAL_TEXTURE", + "HAS_OCCLUSION_TEXTURE", + "TEXCOORD_BASE_COLOR v_texCoord_0", + "TEXCOORD_EMISSIVE v_texCoord_0", + "TEXCOORD_METALLIC_ROUGHNESS v_texCoord_0", + "TEXCOORD_NORMAL v_texCoord_0", + "TEXCOORD_OCCLUSION v_texCoord_0", + "USE_METALLIC_ROUGHNESS", + ]); + + const metallicRoughness = primitive.material.metallicRoughness; + const material = primitive.material; + const expectedUniforms = { + u_emissiveTexture: material.emissiveTexture.texture, + u_emissiveFactor: material.emissiveFactor, + u_normalTexture: material.normalTexture.texture, + u_occlusionTexture: material.occlusionTexture.texture, + u_baseColorTexture: metallicRoughness.baseColorTexture.texture, + u_metallicRoughnessTexture: + metallicRoughness.metallicRoughnessTexture.texture, + }; + expectUniformMap(uniformMap, expectedUniforms); }); - it("adds metallic roughness uniforms without defaults", function () { - return loadGltf(boomBox).then(function (gltfLoader) { - const components = gltfLoader.components; - const primitive = components.nodes[0].primitives[0]; - - const metallicRoughness = primitive.material.metallicRoughness; - metallicRoughness.baseColorFactor = new Cartesian4(0.5, 0.5, 0.5, 0.5); - metallicRoughness.metallicFactor = 0.5; - metallicRoughness.roughnessFactor = 0.5; - - const renderResources = mockRenderResources(); - const shaderBuilder = renderResources.shaderBuilder; - const uniformMap = renderResources.uniformMap; - - MaterialPipelineStage.process( - renderResources, - primitive, - mockFrameState - ); - - ShaderBuilderTester.expectHasVertexUniforms(shaderBuilder, []); - ShaderBuilderTester.expectHasFragmentUniforms(shaderBuilder, [ - "uniform float u_metallicFactor;", - "uniform float u_roughnessFactor;", - "uniform sampler2D u_baseColorTexture;", - "uniform sampler2D u_emissiveTexture;", - "uniform sampler2D u_metallicRoughnessTexture;", - "uniform sampler2D u_normalTexture;", - "uniform sampler2D u_occlusionTexture;", - "uniform vec3 u_emissiveFactor;", - "uniform vec4 u_baseColorFactor;", - ]); - - ShaderBuilderTester.expectHasVertexDefines(shaderBuilder, []); - ShaderBuilderTester.expectHasFragmentDefines(shaderBuilder, [ - "HAS_BASE_COLOR_FACTOR", - "HAS_BASE_COLOR_TEXTURE", - "HAS_EMISSIVE_FACTOR", - "HAS_EMISSIVE_TEXTURE", - "HAS_METALLIC_FACTOR", - "HAS_METALLIC_ROUGHNESS_TEXTURE", - "HAS_NORMAL_TEXTURE", - "HAS_OCCLUSION_TEXTURE", - "HAS_ROUGHNESS_FACTOR", - "TEXCOORD_BASE_COLOR v_texCoord_0", - "TEXCOORD_EMISSIVE v_texCoord_0", - "TEXCOORD_METALLIC_ROUGHNESS v_texCoord_0", - "TEXCOORD_NORMAL v_texCoord_0", - "TEXCOORD_OCCLUSION v_texCoord_0", - "USE_METALLIC_ROUGHNESS", - ]); - - const expectedUniforms = { - u_baseColorTexture: metallicRoughness.baseColorTexture.texture, - u_baseColorFactor: metallicRoughness.baseColorFactor, - u_metallicRoughnessTexture: - metallicRoughness.metallicRoughnessTexture.texture, - u_metallicFactor: metallicRoughness.metallicFactor, - u_roughnessFactor: metallicRoughness.roughnessFactor, - }; - expectUniformMap(uniformMap, expectedUniforms); - }); + it("adds metallic roughness uniforms without defaults", async function () { + const gltfLoader = await loadGltf(boomBox); + const primitive = gltfLoader.components.nodes[0].primitives[0]; + + const metallicRoughness = primitive.material.metallicRoughness; + metallicRoughness.baseColorFactor = new Cartesian4(0.5, 0.5, 0.5, 0.5); + metallicRoughness.metallicFactor = 0.5; + metallicRoughness.roughnessFactor = 0.5; + + const renderResources = mockRenderResources(); + const { shaderBuilder, uniformMap } = renderResources; + + MaterialPipelineStage.process(renderResources, primitive, mockFrameState); + + ShaderBuilderTester.expectHasVertexUniforms(shaderBuilder, []); + ShaderBuilderTester.expectHasFragmentUniforms(shaderBuilder, [ + "uniform float u_metallicFactor;", + "uniform float u_roughnessFactor;", + "uniform sampler2D u_baseColorTexture;", + "uniform sampler2D u_emissiveTexture;", + "uniform sampler2D u_metallicRoughnessTexture;", + "uniform sampler2D u_normalTexture;", + "uniform sampler2D u_occlusionTexture;", + "uniform vec3 u_emissiveFactor;", + "uniform vec4 u_baseColorFactor;", + ]); + + ShaderBuilderTester.expectHasVertexDefines(shaderBuilder, []); + ShaderBuilderTester.expectHasFragmentDefines(shaderBuilder, [ + "HAS_BASE_COLOR_FACTOR", + "HAS_BASE_COLOR_TEXTURE", + "HAS_EMISSIVE_FACTOR", + "HAS_EMISSIVE_TEXTURE", + "HAS_METALLIC_FACTOR", + "HAS_METALLIC_ROUGHNESS_TEXTURE", + "HAS_NORMAL_TEXTURE", + "HAS_OCCLUSION_TEXTURE", + "HAS_ROUGHNESS_FACTOR", + "TEXCOORD_BASE_COLOR v_texCoord_0", + "TEXCOORD_EMISSIVE v_texCoord_0", + "TEXCOORD_METALLIC_ROUGHNESS v_texCoord_0", + "TEXCOORD_NORMAL v_texCoord_0", + "TEXCOORD_OCCLUSION v_texCoord_0", + "USE_METALLIC_ROUGHNESS", + ]); + + const expectedUniforms = { + u_baseColorTexture: metallicRoughness.baseColorTexture.texture, + u_baseColorFactor: metallicRoughness.baseColorFactor, + u_metallicRoughnessTexture: + metallicRoughness.metallicRoughnessTexture.texture, + u_metallicFactor: metallicRoughness.metallicFactor, + u_roughnessFactor: metallicRoughness.roughnessFactor, + }; + expectUniformMap(uniformMap, expectedUniforms); }); - it("doesn't add emissive uniforms when emissive factor is default", function () { - return loadGltf(boomBox).then(function (gltfLoader) { - const components = gltfLoader.components; - const primitive = components.nodes[0].primitives[0]; - - const material = primitive.material; - material.emissiveFactor = Cartesian3.clone( - ModelComponents.Material.DEFAULT_EMISSIVE_FACTOR - ); - const metallicRoughness = material.metallicRoughness; - - const renderResources = mockRenderResources(); - const shaderBuilder = renderResources.shaderBuilder; - const uniformMap = renderResources.uniformMap; - - MaterialPipelineStage.process( - renderResources, - primitive, - mockFrameState - ); - - ShaderBuilderTester.expectHasVertexUniforms(shaderBuilder, []); - ShaderBuilderTester.expectHasFragmentUniforms(shaderBuilder, [ - "uniform sampler2D u_baseColorTexture;", - "uniform sampler2D u_metallicRoughnessTexture;", - "uniform sampler2D u_normalTexture;", - "uniform sampler2D u_occlusionTexture;", - ]); - - ShaderBuilderTester.expectHasVertexDefines(shaderBuilder, []); - ShaderBuilderTester.expectHasFragmentDefines(shaderBuilder, [ - "HAS_BASE_COLOR_TEXTURE", - "HAS_METALLIC_ROUGHNESS_TEXTURE", - "HAS_NORMAL_TEXTURE", - "HAS_OCCLUSION_TEXTURE", - "TEXCOORD_BASE_COLOR v_texCoord_0", - "TEXCOORD_METALLIC_ROUGHNESS v_texCoord_0", - "TEXCOORD_NORMAL v_texCoord_0", - "TEXCOORD_OCCLUSION v_texCoord_0", - "USE_METALLIC_ROUGHNESS", - ]); - - const expectedUniforms = { - u_normalTexture: material.normalTexture.texture, - u_occlusionTexture: material.occlusionTexture.texture, - u_baseColorTexture: metallicRoughness.baseColorTexture.texture, - u_metallicRoughnessTexture: - metallicRoughness.metallicRoughnessTexture.texture, - }; - expectUniformMap(uniformMap, expectedUniforms); - }); + it("doesn't add emissive uniforms when emissive factor is default", async function () { + const gltfLoader = await loadGltf(boomBox); + const primitive = gltfLoader.components.nodes[0].primitives[0]; + + const material = primitive.material; + material.emissiveFactor = Cartesian3.clone( + ModelComponents.Material.DEFAULT_EMISSIVE_FACTOR + ); + const metallicRoughness = material.metallicRoughness; + + const renderResources = mockRenderResources(); + const { shaderBuilder, uniformMap } = renderResources; + + MaterialPipelineStage.process(renderResources, primitive, mockFrameState); + + ShaderBuilderTester.expectHasVertexUniforms(shaderBuilder, []); + ShaderBuilderTester.expectHasFragmentUniforms(shaderBuilder, [ + "uniform sampler2D u_baseColorTexture;", + "uniform sampler2D u_metallicRoughnessTexture;", + "uniform sampler2D u_normalTexture;", + "uniform sampler2D u_occlusionTexture;", + ]); + + ShaderBuilderTester.expectHasVertexDefines(shaderBuilder, []); + ShaderBuilderTester.expectHasFragmentDefines(shaderBuilder, [ + "HAS_BASE_COLOR_TEXTURE", + "HAS_METALLIC_ROUGHNESS_TEXTURE", + "HAS_NORMAL_TEXTURE", + "HAS_OCCLUSION_TEXTURE", + "TEXCOORD_BASE_COLOR v_texCoord_0", + "TEXCOORD_METALLIC_ROUGHNESS v_texCoord_0", + "TEXCOORD_NORMAL v_texCoord_0", + "TEXCOORD_OCCLUSION v_texCoord_0", + "USE_METALLIC_ROUGHNESS", + ]); + + const expectedUniforms = { + u_normalTexture: material.normalTexture.texture, + u_occlusionTexture: material.occlusionTexture.texture, + u_baseColorTexture: metallicRoughness.baseColorTexture.texture, + u_metallicRoughnessTexture: + metallicRoughness.metallicRoughnessTexture.texture, + }; + expectUniformMap(uniformMap, expectedUniforms); }); - it("adds specular glossiness uniforms", function () { - return loadGltf(boomBoxSpecularGlossiness).then(function (gltfLoader) { - const components = gltfLoader.components; - const primitive = components.nodes[0].primitives[0]; - const renderResources = mockRenderResources(); - const shaderBuilder = renderResources.shaderBuilder; - const uniformMap = renderResources.uniformMap; - - MaterialPipelineStage.process( - renderResources, - primitive, - mockFrameState - ); - ShaderBuilderTester.expectHasVertexUniforms(shaderBuilder, []); - ShaderBuilderTester.expectHasFragmentUniforms(shaderBuilder, [ - "uniform float u_glossinessFactor;", - "uniform sampler2D u_diffuseTexture;", - "uniform sampler2D u_emissiveTexture;", - "uniform sampler2D u_normalTexture;", - "uniform sampler2D u_occlusionTexture;", - "uniform sampler2D u_specularGlossinessTexture;", - "uniform vec3 u_emissiveFactor;", - ]); - - ShaderBuilderTester.expectHasVertexDefines(shaderBuilder, []); - ShaderBuilderTester.expectHasFragmentDefines(shaderBuilder, [ - "HAS_DIFFUSE_TEXTURE", - "HAS_EMISSIVE_FACTOR", - "HAS_EMISSIVE_TEXTURE", - "HAS_GLOSSINESS_FACTOR", - "HAS_NORMAL_TEXTURE", - "HAS_OCCLUSION_TEXTURE", - "HAS_SPECULAR_GLOSSINESS_TEXTURE", - "TEXCOORD_DIFFUSE v_texCoord_0", - "TEXCOORD_EMISSIVE v_texCoord_0", - "TEXCOORD_NORMAL v_texCoord_0", - "TEXCOORD_OCCLUSION v_texCoord_0", - "TEXCOORD_SPECULAR_GLOSSINESS v_texCoord_0", - "USE_SPECULAR_GLOSSINESS", - ]); - - const specularGlossiness = primitive.material.specularGlossiness; - const expectedUniforms = { - u_diffuseTexture: specularGlossiness.diffuseTexture.texture, - u_specularGlossinessTexture: - specularGlossiness.specularGlossinessTexture.texture, - u_glossinessFactor: specularGlossiness.glossinessFactor, - }; - expectUniformMap(uniformMap, expectedUniforms); - }); + it("adds specular glossiness uniforms", async function () { + const gltfLoader = await loadGltf(boomBoxSpecularGlossiness); + const primitive = gltfLoader.components.nodes[0].primitives[0]; + const renderResources = mockRenderResources(); + const { shaderBuilder, uniformMap } = renderResources; + + MaterialPipelineStage.process(renderResources, primitive, mockFrameState); + ShaderBuilderTester.expectHasVertexUniforms(shaderBuilder, []); + ShaderBuilderTester.expectHasFragmentUniforms(shaderBuilder, [ + "uniform float u_glossinessFactor;", + "uniform sampler2D u_diffuseTexture;", + "uniform sampler2D u_emissiveTexture;", + "uniform sampler2D u_normalTexture;", + "uniform sampler2D u_occlusionTexture;", + "uniform sampler2D u_specularGlossinessTexture;", + "uniform vec3 u_emissiveFactor;", + ]); + + ShaderBuilderTester.expectHasVertexDefines(shaderBuilder, []); + ShaderBuilderTester.expectHasFragmentDefines(shaderBuilder, [ + "HAS_DIFFUSE_TEXTURE", + "HAS_EMISSIVE_FACTOR", + "HAS_EMISSIVE_TEXTURE", + "HAS_GLOSSINESS_FACTOR", + "HAS_NORMAL_TEXTURE", + "HAS_OCCLUSION_TEXTURE", + "HAS_SPECULAR_GLOSSINESS_TEXTURE", + "TEXCOORD_DIFFUSE v_texCoord_0", + "TEXCOORD_EMISSIVE v_texCoord_0", + "TEXCOORD_NORMAL v_texCoord_0", + "TEXCOORD_OCCLUSION v_texCoord_0", + "TEXCOORD_SPECULAR_GLOSSINESS v_texCoord_0", + "USE_SPECULAR_GLOSSINESS", + ]); + + const specularGlossiness = primitive.material.specularGlossiness; + const expectedUniforms = { + u_diffuseTexture: specularGlossiness.diffuseTexture.texture, + u_specularGlossinessTexture: + specularGlossiness.specularGlossinessTexture.texture, + u_glossinessFactor: specularGlossiness.glossinessFactor, + }; + expectUniformMap(uniformMap, expectedUniforms); }); - it("adds specular glossiness uniforms without defaults", function () { - return loadGltf(boomBoxSpecularGlossiness).then(function (gltfLoader) { - const components = gltfLoader.components; - const primitive = components.nodes[0].primitives[0]; - - const specularGlossiness = primitive.material.specularGlossiness; - specularGlossiness.diffuseFactor = new Cartesian4(0.5, 0.5, 0.5, 0.5); - specularGlossiness.specularFactor = new Cartesian3(0.5, 0.5, 0.5); - - const renderResources = mockRenderResources(); - const shaderBuilder = renderResources.shaderBuilder; - const uniformMap = renderResources.uniformMap; - - MaterialPipelineStage.process( - renderResources, - primitive, - mockFrameState - ); - - ShaderBuilderTester.expectHasVertexUniforms(shaderBuilder, []); - ShaderBuilderTester.expectHasFragmentUniforms(shaderBuilder, [ - "uniform float u_glossinessFactor;", - "uniform sampler2D u_diffuseTexture;", - "uniform sampler2D u_emissiveTexture;", - "uniform sampler2D u_normalTexture;", - "uniform sampler2D u_occlusionTexture;", - "uniform sampler2D u_specularGlossinessTexture;", - "uniform vec3 u_emissiveFactor;", - "uniform vec3 u_specularFactor;", - "uniform vec4 u_diffuseFactor;", - ]); - - ShaderBuilderTester.expectHasVertexDefines(shaderBuilder, []); - ShaderBuilderTester.expectHasFragmentDefines(shaderBuilder, [ - "HAS_DIFFUSE_FACTOR", - "HAS_DIFFUSE_TEXTURE", - "HAS_EMISSIVE_FACTOR", - "HAS_EMISSIVE_TEXTURE", - "HAS_GLOSSINESS_FACTOR", - "HAS_NORMAL_TEXTURE", - "HAS_OCCLUSION_TEXTURE", - "HAS_SPECULAR_FACTOR", - "HAS_SPECULAR_GLOSSINESS_TEXTURE", - "TEXCOORD_DIFFUSE v_texCoord_0", - "TEXCOORD_EMISSIVE v_texCoord_0", - "TEXCOORD_NORMAL v_texCoord_0", - "TEXCOORD_OCCLUSION v_texCoord_0", - "TEXCOORD_SPECULAR_GLOSSINESS v_texCoord_0", - "USE_SPECULAR_GLOSSINESS", - ]); - - const expectedUniforms = { - u_diffuseTexture: specularGlossiness.diffuseTexture.texture, - u_diffuseFactor: specularGlossiness.diffuseFactor, - u_specularGlossinessTexture: - specularGlossiness.specularGlossinessTexture.texture, - u_specularFactor: specularGlossiness.specularFactor, - u_glossinessFactor: specularGlossiness.glossinessFactor, - }; - expectUniformMap(uniformMap, expectedUniforms); - }); + it("adds specular glossiness uniforms without defaults", async function () { + const gltfLoader = await loadGltf(boomBoxSpecularGlossiness); + const primitive = gltfLoader.components.nodes[0].primitives[0]; + + const specularGlossiness = primitive.material.specularGlossiness; + specularGlossiness.diffuseFactor = new Cartesian4(0.5, 0.5, 0.5, 0.5); + specularGlossiness.specularFactor = new Cartesian3(0.5, 0.5, 0.5); + + const renderResources = mockRenderResources(); + const { shaderBuilder, uniformMap } = renderResources; + + MaterialPipelineStage.process(renderResources, primitive, mockFrameState); + + ShaderBuilderTester.expectHasVertexUniforms(shaderBuilder, []); + ShaderBuilderTester.expectHasFragmentUniforms(shaderBuilder, [ + "uniform float u_glossinessFactor;", + "uniform sampler2D u_diffuseTexture;", + "uniform sampler2D u_emissiveTexture;", + "uniform sampler2D u_normalTexture;", + "uniform sampler2D u_occlusionTexture;", + "uniform sampler2D u_specularGlossinessTexture;", + "uniform vec3 u_emissiveFactor;", + "uniform vec3 u_legacySpecularFactor;", + "uniform vec4 u_diffuseFactor;", + ]); + + ShaderBuilderTester.expectHasVertexDefines(shaderBuilder, []); + ShaderBuilderTester.expectHasFragmentDefines(shaderBuilder, [ + "HAS_DIFFUSE_FACTOR", + "HAS_DIFFUSE_TEXTURE", + "HAS_EMISSIVE_FACTOR", + "HAS_EMISSIVE_TEXTURE", + "HAS_GLOSSINESS_FACTOR", + "HAS_NORMAL_TEXTURE", + "HAS_OCCLUSION_TEXTURE", + "HAS_LEGACY_SPECULAR_FACTOR", + "HAS_SPECULAR_GLOSSINESS_TEXTURE", + "TEXCOORD_DIFFUSE v_texCoord_0", + "TEXCOORD_EMISSIVE v_texCoord_0", + "TEXCOORD_NORMAL v_texCoord_0", + "TEXCOORD_OCCLUSION v_texCoord_0", + "TEXCOORD_SPECULAR_GLOSSINESS v_texCoord_0", + "USE_SPECULAR_GLOSSINESS", + ]); + + const expectedUniforms = { + u_diffuseTexture: specularGlossiness.diffuseTexture.texture, + u_diffuseFactor: specularGlossiness.diffuseFactor, + u_specularGlossinessTexture: + specularGlossiness.specularGlossinessTexture.texture, + u_legacySpecularFactor: specularGlossiness.specularFactor, + u_glossinessFactor: specularGlossiness.glossinessFactor, + }; + expectUniformMap(uniformMap, expectedUniforms); }); - it("doesn't add texture uniforms for classification models", function () { - return loadGltf(boomBox).then(function (gltfLoader) { - const components = gltfLoader.components; - const primitive = components.nodes[0].primitives[0]; - const renderResources = mockRenderResources(ClassificationType.BOTH); - const shaderBuilder = renderResources.shaderBuilder; - const uniformMap = renderResources.uniformMap; - - MaterialPipelineStage.process( - renderResources, - primitive, - mockFrameState - ); - - ShaderBuilderTester.expectHasVertexUniforms(shaderBuilder, []); - ShaderBuilderTester.expectHasFragmentUniforms(shaderBuilder, [ - "uniform vec3 u_emissiveFactor;", - ]); - - ShaderBuilderTester.expectHasVertexDefines(shaderBuilder, []); - ShaderBuilderTester.expectHasFragmentDefines(shaderBuilder, [ - "HAS_EMISSIVE_FACTOR", - "USE_METALLIC_ROUGHNESS", - ]); - const material = primitive.material; - const expectedUniforms = { - u_emissiveFactor: material.emissiveFactor, - }; - expectUniformMap(uniformMap, expectedUniforms); - }); + it("adds uniforms and defines for KHR_materials_specular", async function () { + const gltfLoader = await loadGltf(specularTestData); + + const primitive = gltfLoader.components.nodes[1].primitives[0]; + + const renderResources = mockRenderResources(); + const { shaderBuilder, uniformMap } = renderResources; + + MaterialPipelineStage.process(renderResources, primitive, mockFrameState); + ShaderBuilderTester.expectHasVertexUniforms(shaderBuilder, []); + ShaderBuilderTester.expectHasFragmentUniforms(shaderBuilder, [ + "uniform float u_metallicFactor;", + "uniform float u_specularFactor;", + "uniform sampler2D u_baseColorTexture;", + "uniform sampler2D u_specularColorTexture;", + "uniform sampler2D u_specularTexture;", + "uniform vec3 u_specularColorFactor;", + ]); + + ShaderBuilderTester.expectHasVertexDefines(shaderBuilder, []); + ShaderBuilderTester.expectHasFragmentDefines(shaderBuilder, [ + "HAS_BASE_COLOR_TEXTURE", + "HAS_METALLIC_FACTOR", + "HAS_SPECULAR_COLOR_FACTOR", + "HAS_SPECULAR_COLOR_TEXTURE", + "HAS_SPECULAR_FACTOR", + "HAS_SPECULAR_TEXTURE", + "TEXCOORD_BASE_COLOR v_texCoord_0", + "TEXCOORD_SPECULAR v_texCoord_0", + "TEXCOORD_SPECULAR_COLOR v_texCoord_0", + "USE_METALLIC_ROUGHNESS", + "USE_SPECULAR", + ]); + + const { + specularFactor, + specularTexture, + specularColorFactor, + specularColorTexture, + } = primitive.material.specular; + const expectedUniforms = { + u_specularFactor: specularFactor, + u_specularColorFactor: specularColorFactor, + u_specularTexture: specularTexture.texture, + u_specularColorTexture: specularColorTexture.texture, + }; + expectUniformMap(uniformMap, expectedUniforms); }); - it("doesn't add metallic roughness textures for classification models", function () { - return loadGltf(boomBox).then(function (gltfLoader) { - const components = gltfLoader.components; - const primitive = components.nodes[0].primitives[0]; - - const metallicRoughness = primitive.material.metallicRoughness; - metallicRoughness.baseColorFactor = new Cartesian4(0.5, 0.5, 0.5, 0.5); - metallicRoughness.metallicFactor = 0.5; - metallicRoughness.roughnessFactor = 0.5; - - const renderResources = mockRenderResources(); - const shaderBuilder = renderResources.shaderBuilder; - const uniformMap = renderResources.uniformMap; - - MaterialPipelineStage.process( - renderResources, - primitive, - mockFrameState - ); - - ShaderBuilderTester.expectHasVertexUniforms(shaderBuilder, []); - ShaderBuilderTester.expectHasFragmentUniforms(shaderBuilder, [ - "uniform float u_metallicFactor;", - "uniform float u_roughnessFactor;", - "uniform sampler2D u_baseColorTexture;", - "uniform sampler2D u_emissiveTexture;", - "uniform sampler2D u_metallicRoughnessTexture;", - "uniform sampler2D u_normalTexture;", - "uniform sampler2D u_occlusionTexture;", - "uniform vec3 u_emissiveFactor;", - "uniform vec4 u_baseColorFactor;", - ]); - - ShaderBuilderTester.expectHasVertexDefines(shaderBuilder, []); - ShaderBuilderTester.expectHasFragmentDefines(shaderBuilder, [ - "HAS_BASE_COLOR_FACTOR", - "HAS_BASE_COLOR_TEXTURE", - "HAS_EMISSIVE_FACTOR", - "HAS_EMISSIVE_TEXTURE", - "HAS_METALLIC_FACTOR", - "HAS_METALLIC_ROUGHNESS_TEXTURE", - "HAS_NORMAL_TEXTURE", - "HAS_OCCLUSION_TEXTURE", - "HAS_ROUGHNESS_FACTOR", - "TEXCOORD_BASE_COLOR v_texCoord_0", - "TEXCOORD_EMISSIVE v_texCoord_0", - "TEXCOORD_METALLIC_ROUGHNESS v_texCoord_0", - "TEXCOORD_NORMAL v_texCoord_0", - "TEXCOORD_OCCLUSION v_texCoord_0", - "USE_METALLIC_ROUGHNESS", - ]); - - const expectedUniforms = { - u_baseColorFactor: metallicRoughness.baseColorFactor, - u_metallicFactor: metallicRoughness.metallicFactor, - u_roughnessFactor: metallicRoughness.roughnessFactor, - }; - expectUniformMap(uniformMap, expectedUniforms); - }); + it("adds uniforms and defines for KHR_materials_anisotropy", async function () { + const gltfLoader = await loadGltf(anisotropyTestData); + + const primitive = gltfLoader.components.nodes[1].primitives[0]; + const renderResources = mockRenderResources(); + MaterialPipelineStage.process(renderResources, primitive, mockFrameState); + const { shaderBuilder, uniformMap } = renderResources; + + ShaderBuilderTester.expectHasVertexUniforms(shaderBuilder, []); + ShaderBuilderTester.expectHasFragmentUniforms(shaderBuilder, [ + "uniform float u_metallicFactor;", + "uniform sampler2D u_anisotropyTexture;", + "uniform sampler2D u_baseColorTexture;", + "uniform sampler2D u_normalTexture;", + "uniform vec3 u_anisotropy;", + ]); + + ShaderBuilderTester.expectHasVertexDefines(shaderBuilder, []); + ShaderBuilderTester.expectHasFragmentDefines(shaderBuilder, [ + "HAS_ANISOTROPY_TEXTURE", + "HAS_BASE_COLOR_TEXTURE", + "HAS_METALLIC_FACTOR", + "HAS_NORMAL_TEXTURE", + "TEXCOORD_ANISOTROPY v_texCoord_0", + "TEXCOORD_BASE_COLOR v_texCoord_0", + "TEXCOORD_NORMAL v_texCoord_0", + "USE_ANISOTROPY", + "USE_METALLIC_ROUGHNESS", + ]); + + const { + anisotropyStrength, + anisotropyRotation, + anisotropyTexture, + } = primitive.material.anisotropy; + const expectedAnisotropy = Cartesian3.fromElements( + Math.cos(anisotropyRotation), + Math.sin(anisotropyRotation), + anisotropyStrength + ); + const expectedUniforms = { + u_anisotropy: expectedAnisotropy, + u_anisotropyTexture: anisotropyTexture.texture, + }; + expectUniformMap(uniformMap, expectedUniforms); }); - it("enables PBR lighting for metallic roughness materials", function () { - return loadGltf(boomBox).then(function (gltfLoader) { - const components = gltfLoader.components; - const primitive = components.nodes[0].primitives[0]; - const renderResources = mockRenderResources(); - const lightingOptions = renderResources.lightingOptions; - - MaterialPipelineStage.process( - renderResources, - primitive, - mockFrameState - ); - expect(lightingOptions.lightingModel).toBe(LightingModel.PBR); - }); + it("adds uniforms and defines for KHR_materials_clearcoat", async function () { + const gltfLoader = await loadGltf(clearcoatTestData); + + const primitive = gltfLoader.components.nodes[1].primitives[0]; + const renderResources = mockRenderResources(); + MaterialPipelineStage.process(renderResources, primitive, mockFrameState); + const { shaderBuilder, uniformMap } = renderResources; + + ShaderBuilderTester.expectHasVertexUniforms(shaderBuilder, []); + ShaderBuilderTester.expectHasFragmentUniforms(shaderBuilder, [ + "uniform float u_metallicFactor;", + "uniform float u_clearcoatFactor;", + "uniform float u_clearcoatRoughnessFactor;", + "uniform sampler2D u_baseColorTexture;", + "uniform sampler2D u_clearcoatTexture;", + "uniform sampler2D u_clearcoatRoughnessTexture;", + "uniform sampler2D u_clearcoatNormalTexture;", + ]); + + ShaderBuilderTester.expectHasVertexDefines(shaderBuilder, []); + ShaderBuilderTester.expectHasFragmentDefines(shaderBuilder, [ + "HAS_BASE_COLOR_TEXTURE", + "HAS_CLEARCOAT_FACTOR", + "HAS_CLEARCOAT_NORMAL_TEXTURE", + "HAS_CLEARCOAT_ROUGHNESS_FACTOR", + "HAS_CLEARCOAT_ROUGHNESS_TEXTURE", + "HAS_CLEARCOAT_TEXTURE", + "HAS_METALLIC_FACTOR", + "TEXCOORD_CLEARCOAT v_texCoord_0", + "TEXCOORD_CLEARCOAT_ROUGHNESS v_texCoord_0", + "TEXCOORD_CLEARCOAT_NORMAL v_texCoord_0", + "TEXCOORD_BASE_COLOR v_texCoord_0", + "USE_CLEARCOAT", + "USE_METALLIC_ROUGHNESS", + ]); + + const { + clearcoatFactor, + clearcoatRoughnessFactor, + clearcoatTexture, + clearcoatRoughnessTexture, + clearcoatNormalTexture, + } = primitive.material.clearcoat; + const expectedUniforms = { + u_clearcoatFactor: clearcoatFactor, + u_clearcoatRoughnessFactor: clearcoatRoughnessFactor, + u_clearcoatTexture: clearcoatTexture.texture, + u_clearcoatRoughnessTexture: clearcoatRoughnessTexture.texture, + u_clearcoatNormalTexture: clearcoatNormalTexture.texture, + }; + expectUniformMap(uniformMap, expectedUniforms); }); - it("enables PBR lighting for specular glossiness materials", function () { - return loadGltf(boomBoxSpecularGlossiness).then(function (gltfLoader) { - const components = gltfLoader.components; - const primitive = components.nodes[0].primitives[0]; - const renderResources = mockRenderResources(); - const lightingOptions = renderResources.lightingOptions; - - MaterialPipelineStage.process( - renderResources, - primitive, - mockFrameState - ); - expect(lightingOptions.lightingModel).toBe(LightingModel.PBR); - }); + it("doesn't add texture uniforms for classification models", async function () { + const gltfLoader = await loadGltf(boomBox); + const primitive = gltfLoader.components.nodes[0].primitives[0]; + const renderResources = mockRenderResources(ClassificationType.BOTH); + const { shaderBuilder, uniformMap } = renderResources; + + MaterialPipelineStage.process(renderResources, primitive, mockFrameState); + + ShaderBuilderTester.expectHasVertexUniforms(shaderBuilder, []); + ShaderBuilderTester.expectHasFragmentUniforms(shaderBuilder, [ + "uniform vec3 u_emissiveFactor;", + ]); + + ShaderBuilderTester.expectHasVertexDefines(shaderBuilder, []); + ShaderBuilderTester.expectHasFragmentDefines(shaderBuilder, [ + "HAS_EMISSIVE_FACTOR", + "USE_METALLIC_ROUGHNESS", + ]); + const material = primitive.material; + const expectedUniforms = { + u_emissiveFactor: material.emissiveFactor, + }; + expectUniformMap(uniformMap, expectedUniforms); }); - it("enables unlit lighting when KHR_materials_unlit is present", function () { - return loadGltf(boxUnlit).then(function (gltfLoader) { - const components = gltfLoader.components; - const primitive = components.nodes[1].primitives[0]; - const renderResources = mockRenderResources(); - const lightingOptions = renderResources.lightingOptions; - - MaterialPipelineStage.process( - renderResources, - primitive, - mockFrameState - ); - expect(lightingOptions.lightingModel).toBe(LightingModel.UNLIT); - }); + it("doesn't add metallic roughness textures for classification models", async function () { + const gltfLoader = await loadGltf(boomBox); + const primitive = gltfLoader.components.nodes[0].primitives[0]; + + const metallicRoughness = primitive.material.metallicRoughness; + metallicRoughness.baseColorFactor = new Cartesian4(0.5, 0.5, 0.5, 0.5); + metallicRoughness.metallicFactor = 0.5; + metallicRoughness.roughnessFactor = 0.5; + + const renderResources = mockRenderResources(); + const { shaderBuilder, uniformMap } = renderResources; + + MaterialPipelineStage.process(renderResources, primitive, mockFrameState); + + ShaderBuilderTester.expectHasVertexUniforms(shaderBuilder, []); + ShaderBuilderTester.expectHasFragmentUniforms(shaderBuilder, [ + "uniform float u_metallicFactor;", + "uniform float u_roughnessFactor;", + "uniform sampler2D u_baseColorTexture;", + "uniform sampler2D u_emissiveTexture;", + "uniform sampler2D u_metallicRoughnessTexture;", + "uniform sampler2D u_normalTexture;", + "uniform sampler2D u_occlusionTexture;", + "uniform vec3 u_emissiveFactor;", + "uniform vec4 u_baseColorFactor;", + ]); + + ShaderBuilderTester.expectHasVertexDefines(shaderBuilder, []); + ShaderBuilderTester.expectHasFragmentDefines(shaderBuilder, [ + "HAS_BASE_COLOR_FACTOR", + "HAS_BASE_COLOR_TEXTURE", + "HAS_EMISSIVE_FACTOR", + "HAS_EMISSIVE_TEXTURE", + "HAS_METALLIC_FACTOR", + "HAS_METALLIC_ROUGHNESS_TEXTURE", + "HAS_NORMAL_TEXTURE", + "HAS_OCCLUSION_TEXTURE", + "HAS_ROUGHNESS_FACTOR", + "TEXCOORD_BASE_COLOR v_texCoord_0", + "TEXCOORD_EMISSIVE v_texCoord_0", + "TEXCOORD_METALLIC_ROUGHNESS v_texCoord_0", + "TEXCOORD_NORMAL v_texCoord_0", + "TEXCOORD_OCCLUSION v_texCoord_0", + "USE_METALLIC_ROUGHNESS", + ]); + + const expectedUniforms = { + u_baseColorFactor: metallicRoughness.baseColorFactor, + u_metallicFactor: metallicRoughness.metallicFactor, + u_roughnessFactor: metallicRoughness.roughnessFactor, + }; + expectUniformMap(uniformMap, expectedUniforms); }); - it("enables unlit lighting for classification models", function () { - return loadGltf(boxUnlit).then(function (gltfLoader) { - const components = gltfLoader.components; - const primitive = components.nodes[1].primitives[0]; - const renderResources = mockRenderResources(ClassificationType.BOTH); - const lightingOptions = renderResources.lightingOptions; - - MaterialPipelineStage.process( - renderResources, - primitive, - mockFrameState - ); - expect(lightingOptions.lightingModel).toBe(LightingModel.UNLIT); - }); + it("enables PBR lighting for metallic roughness materials", async function () { + const gltfLoader = await loadGltf(boomBox); + const primitive = gltfLoader.components.nodes[0].primitives[0]; + const renderResources = mockRenderResources(); + const lightingOptions = renderResources.lightingOptions; + + MaterialPipelineStage.process(renderResources, primitive, mockFrameState); + expect(lightingOptions.lightingModel).toBe(LightingModel.PBR); }); - it("gracefully falls back to unlit shading for models without normals", function () { - return loadGltf(boxNoNormals).then(function (gltfLoader) { - const components = gltfLoader.components; - const primitive = components.nodes[1].primitives[0]; - const renderResources = mockRenderResources(); - const lightingOptions = renderResources.lightingOptions; - - MaterialPipelineStage.process( - renderResources, - primitive, - mockFrameState - ); - expect(lightingOptions.lightingModel).toBe(LightingModel.UNLIT); - }); + it("enables PBR lighting for specular glossiness materials", async function () { + const gltfLoader = await loadGltf(boomBox); + const primitive = gltfLoader.components.nodes[0].primitives[0]; + const renderResources = mockRenderResources(); + const lightingOptions = renderResources.lightingOptions; + + MaterialPipelineStage.process(renderResources, primitive, mockFrameState); + expect(lightingOptions.lightingModel).toBe(LightingModel.PBR); }); - it("handles opaque material", function () { - return loadGltf(boomBox).then(function (gltfLoader) { - const components = gltfLoader.components; - const primitive = components.nodes[0].primitives[0]; - const renderResources = mockRenderResources(); + it("enables unlit lighting when KHR_materials_unlit is present", async function () { + const gltfLoader = await loadGltf(boxUnlit); + const primitive = gltfLoader.components.nodes[1].primitives[0]; + const renderResources = mockRenderResources(); + const lightingOptions = renderResources.lightingOptions; - MaterialPipelineStage.process( - renderResources, - primitive, - mockFrameState - ); + MaterialPipelineStage.process(renderResources, primitive, mockFrameState); + expect(lightingOptions.lightingModel).toBe(LightingModel.UNLIT); + }); - expect(renderResources.alphaOptions.pass).not.toBeDefined(); - expect(renderResources.alphaOptions.alphaCutoff).not.toBeDefined(); - }); + it("enables unlit lighting for classification models", async function () { + const gltfLoader = await loadGltf(boxUnlit); + const primitive = gltfLoader.components.nodes[1].primitives[0]; + const renderResources = mockRenderResources(ClassificationType.BOTH); + const lightingOptions = renderResources.lightingOptions; + + MaterialPipelineStage.process(renderResources, primitive, mockFrameState); + expect(lightingOptions.lightingModel).toBe(LightingModel.UNLIT); }); - it("handles alpha mask material", function () { - return loadGltf(boomBox).then(function (gltfLoader) { - const cutoff = 0.6; - const components = gltfLoader.components; - const primitive = components.nodes[0].primitives[0]; - primitive.material.alphaMode = AlphaMode.MASK; - primitive.material.alphaCutoff = cutoff; - - const renderResources = mockRenderResources(); - MaterialPipelineStage.process( - renderResources, - primitive, - mockFrameState - ); - - expect(renderResources.alphaOptions.pass).not.toBeDefined(); - expect(renderResources.alphaOptions.alphaCutoff).toBe(cutoff); - }); + it("gracefully falls back to unlit shading for models without normals", async function () { + const gltfLoader = await loadGltf(boxNoNormals); + const primitive = gltfLoader.components.nodes[1].primitives[0]; + const renderResources = mockRenderResources(); + const lightingOptions = renderResources.lightingOptions; + + MaterialPipelineStage.process(renderResources, primitive, mockFrameState); + expect(lightingOptions.lightingModel).toBe(LightingModel.UNLIT); }); - it("handles translucent material", function () { - return loadGltf(boomBox).then(function (gltfLoader) { - const components = gltfLoader.components; - const primitive = components.nodes[0].primitives[0]; - primitive.material.alphaMode = AlphaMode.BLEND; + it("handles opaque material", async function () { + const gltfLoader = await loadGltf(boomBox); + const primitive = gltfLoader.components.nodes[0].primitives[0]; + const renderResources = mockRenderResources(); - const renderResources = mockRenderResources(); - renderResources.pass = Pass.OPAQUE; + MaterialPipelineStage.process(renderResources, primitive, mockFrameState); - MaterialPipelineStage.process( - renderResources, - primitive, - mockFrameState - ); + expect(renderResources.alphaOptions.pass).not.toBeDefined(); + expect(renderResources.alphaOptions.alphaCutoff).not.toBeDefined(); + }); - expect(renderResources.alphaOptions.pass).toBe(Pass.TRANSLUCENT); - expect(renderResources.alphaOptions.alphaCutoff).not.toBeDefined(); - }); + it("handles alpha mask material", async function () { + const gltfLoader = await loadGltf(boomBox); + const cutoff = 0.6; + const primitive = gltfLoader.components.nodes[0].primitives[0]; + primitive.material.alphaMode = AlphaMode.MASK; + primitive.material.alphaCutoff = cutoff; + + const renderResources = mockRenderResources(); + MaterialPipelineStage.process(renderResources, primitive, mockFrameState); + + expect(renderResources.alphaOptions.pass).not.toBeDefined(); + expect(renderResources.alphaOptions.alphaCutoff).toBe(cutoff); }); - it("disables back-face culling if model.backFaceCulling is false", function () { - return loadGltf(boxUnlit).then(function (gltfLoader) { - const components = gltfLoader.components; - const primitive = components.nodes[1].primitives[0]; - - const renderResources = mockRenderResources(); - const renderStateOptions = renderResources.renderStateOptions; - renderResources.model.backFaceCulling = false; - renderResources.cull = true; - - MaterialPipelineStage.process( - renderResources, - primitive, - mockFrameState - ); - expect(renderStateOptions.cull.enabled).toBe(false); - }); + it("handles translucent material", async function () { + const gltfLoader = await loadGltf(boomBox); + const primitive = gltfLoader.components.nodes[0].primitives[0]; + primitive.material.alphaMode = AlphaMode.BLEND; + + const renderResources = mockRenderResources(); + renderResources.pass = Pass.OPAQUE; + + MaterialPipelineStage.process(renderResources, primitive, mockFrameState); + + expect(renderResources.alphaOptions.pass).toBe(Pass.TRANSLUCENT); + expect(renderResources.alphaOptions.alphaCutoff).not.toBeDefined(); }); - it("enables back-face culling if material is not double-sided", function () { - return loadGltf(boxUnlit).then(function (gltfLoader) { - const components = gltfLoader.components; - const primitive = components.nodes[1].primitives[0]; - const renderResources = mockRenderResources(); - const renderStateOptions = renderResources.renderStateOptions; - renderResources.model.backFaceCulling = true; - renderResources.cull = true; - - MaterialPipelineStage.process( - renderResources, - primitive, - mockFrameState - ); - expect(renderStateOptions.cull.enabled).toBe(true); - }); + it("disables back-face culling if model.backFaceCulling is false", async function () { + const gltfLoader = await loadGltf(boxUnlit); + const primitive = gltfLoader.components.nodes[1].primitives[0]; + + const renderResources = mockRenderResources(); + const renderStateOptions = renderResources.renderStateOptions; + renderResources.model.backFaceCulling = false; + renderResources.cull = true; + + MaterialPipelineStage.process(renderResources, primitive, mockFrameState); + expect(renderStateOptions.cull.enabled).toBe(false); }); - it("disables back-face culling if material is double-sided", function () { - return loadGltf(boxUnlit).then(function (gltfLoader) { - const components = gltfLoader.components; - const primitive = components.nodes[1].primitives[0]; - const renderResources = mockRenderResources(); - renderResources.model.backFaceCulling = true; - const renderStateOptions = renderResources.renderStateOptions; - - primitive.material.doubleSided = true; - MaterialPipelineStage.process( - renderResources, - primitive, - mockFrameState - ); - - expect(renderStateOptions.cull.enabled).toBe(false); - }); + it("enables back-face culling if material is not double-sided", async function () { + const gltfLoader = await loadGltf(boxUnlit); + const primitive = gltfLoader.components.nodes[1].primitives[0]; + const renderResources = mockRenderResources(); + const renderStateOptions = renderResources.renderStateOptions; + renderResources.model.backFaceCulling = true; + renderResources.cull = true; + + MaterialPipelineStage.process(renderResources, primitive, mockFrameState); + expect(renderStateOptions.cull.enabled).toBe(true); }); - it("adds material stage functions to the fragment shader", function () { - return loadGltf(boxUnlit).then(function (gltfLoader) { - const components = gltfLoader.components; - const primitive = components.nodes[1].primitives[0]; - primitive.material.doubleSided = true; - - const renderResources = mockRenderResources(); - const shaderBuilder = renderResources.shaderBuilder; - - MaterialPipelineStage.process( - renderResources, - primitive, - mockFrameState - ); - - ShaderBuilderTester.expectVertexLinesEqual(shaderBuilder, []); - ShaderBuilderTester.expectFragmentLinesEqual(shaderBuilder, [ - _shadersMaterialStageFS, - ]); - }); + it("disables back-face culling if material is double-sided", async function () { + const gltfLoader = await loadGltf(boxUnlit); + const primitive = gltfLoader.components.nodes[1].primitives[0]; + const renderResources = mockRenderResources(); + renderResources.model.backFaceCulling = true; + const renderStateOptions = renderResources.renderStateOptions; + + primitive.material.doubleSided = true; + MaterialPipelineStage.process(renderResources, primitive, mockFrameState); + + expect(renderStateOptions.cull.enabled).toBe(false); }); - it("adds define to shader if material is double-sided", function () { - return loadGltf(twoSidedPlane).then(function (gltfLoader) { - const components = gltfLoader.components; - const primitive = components.nodes[0].primitives[0]; - const renderResources = mockRenderResources(); - const shaderBuilder = renderResources.shaderBuilder; - - MaterialPipelineStage.process( - renderResources, - primitive, - mockFrameState - ); - - ShaderBuilderTester.expectHasVertexDefines(shaderBuilder, [ - "HAS_DOUBLE_SIDED_MATERIAL", - ]); - ShaderBuilderTester.expectHasFragmentDefines(shaderBuilder, [ - "HAS_BASE_COLOR_TEXTURE", - "HAS_DOUBLE_SIDED_MATERIAL", - "HAS_METALLIC_ROUGHNESS_TEXTURE", - "HAS_NORMAL_TEXTURE", - "TEXCOORD_BASE_COLOR v_texCoord_0", - "TEXCOORD_METALLIC_ROUGHNESS v_texCoord_0", - "TEXCOORD_NORMAL v_texCoord_0", - "USE_METALLIC_ROUGHNESS", - ]); - }); + it("adds material stage functions to the fragment shader", async function () { + const gltfLoader = await loadGltf(boxUnlit); + const primitive = gltfLoader.components.nodes[1].primitives[0]; + primitive.material.doubleSided = true; + + const renderResources = mockRenderResources(); + const shaderBuilder = renderResources.shaderBuilder; + + MaterialPipelineStage.process(renderResources, primitive, mockFrameState); + + ShaderBuilderTester.expectVertexLinesEqual(shaderBuilder, []); + ShaderBuilderTester.expectFragmentLinesEqual(shaderBuilder, [ + _shadersMaterialStageFS, + ]); + }); + + it("adds define to shader if material is double-sided", async function () { + const gltfLoader = await loadGltf(twoSidedPlane); + const primitive = gltfLoader.components.nodes[0].primitives[0]; + const renderResources = mockRenderResources(); + const shaderBuilder = renderResources.shaderBuilder; + + MaterialPipelineStage.process(renderResources, primitive, mockFrameState); + + ShaderBuilderTester.expectHasVertexDefines(shaderBuilder, [ + "HAS_DOUBLE_SIDED_MATERIAL", + ]); + ShaderBuilderTester.expectHasFragmentDefines(shaderBuilder, [ + "HAS_BASE_COLOR_TEXTURE", + "HAS_DOUBLE_SIDED_MATERIAL", + "HAS_METALLIC_ROUGHNESS_TEXTURE", + "HAS_NORMAL_TEXTURE", + "TEXCOORD_BASE_COLOR v_texCoord_0", + "TEXCOORD_METALLIC_ROUGHNESS v_texCoord_0", + "TEXCOORD_NORMAL v_texCoord_0", + "USE_METALLIC_ROUGHNESS", + ]); }); it("_processTextureTransform updates the shader and uniform map", function () { diff --git a/packages/engine/Specs/Scene/Model/ModelSpec.js b/packages/engine/Specs/Scene/Model/ModelSpec.js index 767b78df552..7fc682127e0 100644 --- a/packages/engine/Specs/Scene/Model/ModelSpec.js +++ b/packages/engine/Specs/Scene/Model/ModelSpec.js @@ -106,6 +106,12 @@ describe( "./Data/Models/glTF-2.0/BoxEmissive/glTF/BoxEmissive.gltf"; const boomBoxUrl = "./Data/Models/glTF-2.0/BoomBox/glTF-pbrSpecularGlossiness/BoomBox.gltf"; + const boxSpecularUrl = + "./Data/Models/glTF-2.0/BoxSpecular/glTF/BoxSpecular.gltf"; + const boxAnisotropyUrl = + "./Data/Models/glTF-2.0/BoxAnisotropy/glTF/BoxAnisotropy.gltf"; + const boxClearcoatUrl = + "./Data/Models/glTF-2.0/BoxClearcoat/glTF/BoxClearcoat.gltf"; const riggedFigureUrl = "./Data/Models/glTF-2.0/RiggedFigureTest/glTF/RiggedFigureTest.gltf"; const dracoCesiumManUrl = @@ -267,75 +273,67 @@ describe( ).toBeRejectedWithDeveloperError(); }); - it("initializes and renders from Uint8Array", function () { + it("initializes and renders from Uint8Array", async function () { const resource = Resource.createIfNeeded(boxTexturedGlbUrl); - const loadPromise = resource.fetchArrayBuffer(); - return loadPromise.then(function (buffer) { - return loadAndZoomToModelAsync( - { gltf: new Uint8Array(buffer) }, - scene - ).then(function (model) { - expect(model.ready).toEqual(true); - expect(model._sceneGraph).toBeDefined(); - expect(model._resourcesLoaded).toEqual(true); - verifyRender(model, true); - }); - }); + const buffer = await resource.fetchArrayBuffer(); + const model = await loadAndZoomToModelAsync( + { gltf: new Uint8Array(buffer) }, + scene + ); + expect(model.ready).toEqual(true); + expect(model._sceneGraph).toBeDefined(); + expect(model._resourcesLoaded).toEqual(true); + verifyRender(model, true); }); - it("initializes and renders from JSON object", function () { + it("initializes and renders from JSON object", async function () { const resource = Resource.createIfNeeded(boxTexturedGltfUrl); - return resource.fetchJson().then(function (gltf) { - return loadAndZoomToModelAsync( - { - gltf: gltf, - basePath: boxTexturedGltfUrl, - }, - scene - ).then(function (model) { - expect(model.ready).toEqual(true); - expect(model._sceneGraph).toBeDefined(); - expect(model._resourcesLoaded).toEqual(true); - verifyRender(model, true); - }); - }); + const gltf = await resource.fetchJson(); + const model = await loadAndZoomToModelAsync( + { + gltf: gltf, + basePath: boxTexturedGltfUrl, + }, + scene + ); + expect(model.ready).toEqual(true); + expect(model._sceneGraph).toBeDefined(); + expect(model._resourcesLoaded).toEqual(true); + verifyRender(model, true); }); - it("initializes and renders from JSON object with external buffers", function () { + it("initializes and renders from JSON object with external buffers", async function () { const resource = Resource.createIfNeeded(microcosm); - return resource.fetchJson().then(function (gltf) { - return loadAndZoomToModelAsync( - { - gltf: gltf, - basePath: microcosm, - }, - scene - ).then(function (model) { - expect(model.ready).toEqual(true); - expect(model._sceneGraph).toBeDefined(); - expect(model._resourcesLoaded).toEqual(true); - verifyRender(model, true); - }); - }); + const gltf = await resource.fetchJson(); + const model = await loadAndZoomToModelAsync( + { + gltf: gltf, + basePath: microcosm, + }, + scene + ); + expect(model.ready).toEqual(true); + expect(model._sceneGraph).toBeDefined(); + expect(model._resourcesLoaded).toEqual(true); + verifyRender(model, true); }); - it("initializes and renders with url", function () { - return loadAndZoomToModelAsync( + it("initializes and renders with url", async function () { + const model = await loadAndZoomToModelAsync( { url: boxTexturedGltfUrl, }, scene - ).then(function (model) { - expect(model.ready).toEqual(true); - expect(model._sceneGraph).toBeDefined(); - expect(model._resourcesLoaded).toEqual(true); - verifyRender(model, true); - }); + ); + expect(model.ready).toEqual(true); + expect(model._sceneGraph).toBeDefined(); + expect(model._resourcesLoaded).toEqual(true); + verifyRender(model, true); }); - it("calls gltfCallback", function () { + it("calls gltfCallback", async function () { let wasCalled = false; - return loadAndZoomToModelAsync( + const model = await loadAndZoomToModelAsync( { url: boxTexturedGltfUrl, gltfCallback: (gltf) => { @@ -348,13 +346,12 @@ describe( }, }, scene - ).then(function (model) { - expect(model.ready).toEqual(true); - expect(model._sceneGraph).toBeDefined(); - expect(model._resourcesLoaded).toEqual(true); - expect(wasCalled).toBeTrue(); - verifyRender(model, true); - }); + ); + expect(model.ready).toEqual(true); + expect(model._sceneGraph).toBeDefined(); + expect(model._resourcesLoaded).toEqual(true); + expect(wasCalled).toBeTrue(); + verifyRender(model, true); }); it("raises errorEvent when a texture fails to load and incrementallyLoadTextures is true", async function () { @@ -438,294 +435,320 @@ describe( }); }); - it("loads with asynchronous set to true", function () { + it("loads with asynchronous set to true", async function () { const jobSchedulerExecute = spyOn( JobScheduler.prototype, "execute" ).and.callThrough(); - return loadAndZoomToModelAsync( + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl, asynchronous: true, }, scene - ).then(function (model) { - const loader = model.loader; - expect(loader._asynchronous).toBe(true); + ); + const loader = model.loader; + expect(loader._asynchronous).toBe(true); - expect(jobSchedulerExecute).toHaveBeenCalled(); - }); + expect(jobSchedulerExecute).toHaveBeenCalled(); }); - it("loads with asynchronous set to false", function () { + it("loads with asynchronous set to false", async function () { const jobSchedulerExecute = spyOn( JobScheduler.prototype, "execute" ).and.callThrough(); - return loadAndZoomToModelAsync( + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl, asynchronous: false, }, scene - ).then(function (model) { - const loader = model.loader; - expect(loader._asynchronous).toBe(false); + ); + const loader = model.loader; + expect(loader._asynchronous).toBe(false); - expect(jobSchedulerExecute).not.toHaveBeenCalled(); - }); + expect(jobSchedulerExecute).not.toHaveBeenCalled(); }); - it("initializes feature table", function () { - return loadAndZoomToModelAsync({ gltf: buildingsMetadata }, scene).then( - function (model) { - expect(model.ready).toEqual(true); - expect(model.featureTables).toBeDefined(); - - const featureTable = model.featureTables[0]; - expect(featureTable).toBeDefined(); - - const featuresLength = featureTable.featuresLength; - expect(featuresLength).toEqual(10); - expect(featureTable.batchTexture).toBeDefined(); - expect(featureTable.batchTexture._featuresLength).toEqual(10); - - for (let i = 0; i < featuresLength; i++) { - const modelFeature = featureTable.getFeature(i); - expect(modelFeature instanceof ModelFeature).toEqual(true); - expect(modelFeature._featureId).toEqual(i); - expect(modelFeature.primitive).toEqual(model); - expect(modelFeature.featureTable).toEqual(featureTable); - } - - expect(model._resourcesLoaded).toEqual(true); - } + it("initializes feature table", async function () { + const model = await loadAndZoomToModelAsync( + { gltf: buildingsMetadata }, + scene ); + expect(model.ready).toEqual(true); + expect(model.featureTables).toBeDefined(); + + const featureTable = model.featureTables[0]; + expect(featureTable).toBeDefined(); + + const featuresLength = featureTable.featuresLength; + expect(featuresLength).toEqual(10); + expect(featureTable.batchTexture).toBeDefined(); + expect(featureTable.batchTexture._featuresLength).toEqual(10); + + for (let i = 0; i < featuresLength; i++) { + const modelFeature = featureTable.getFeature(i); + expect(modelFeature instanceof ModelFeature).toEqual(true); + expect(modelFeature._featureId).toEqual(i); + expect(modelFeature.primitive).toEqual(model); + expect(modelFeature.featureTable).toEqual(featureTable); + } + + expect(model._resourcesLoaded).toEqual(true); }); - it("sets default properties", function () { - return loadAndZoomToModelAsync( + it("sets default properties", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGlbUrl, }, scene - ).then(function (model) { - expect(model.show).toEqual(true); - expect(model.modelMatrix).toEqual(Matrix4.IDENTITY); - expect(model.scale).toEqual(1.0); - expect(model.minimumPixelSize).toEqual(0.0); - expect(model.maximumScale).toBeUndefined(); - - expect(model.id).toBeUndefined(); - expect(model.allowPicking).toEqual(true); - - expect(model.activeAnimations).toBeDefined(); - expect(model.clampAnimations).toEqual(true); - - expect(model.shadows).toEqual(ShadowMode.ENABLED); - expect(model.debugShowBoundingVolume).toEqual(false); - expect(model._enableDebugWireframe).toEqual(false); - expect(model.debugWireframe).toEqual(false); - - expect(model.cull).toEqual(true); - expect(model.backFaceCulling).toEqual(true); - expect(model.opaquePass).toEqual(Pass.OPAQUE); - expect(model.customShader).toBeUndefined(); - - expect(model.heightReference).toEqual(HeightReference.NONE); - expect(model.scene).toBeUndefined(); - expect(model.distanceDisplayCondition).toBeUndefined(); - - expect(model.color).toBeUndefined(); - expect(model.colorBlendMode).toEqual(ColorBlendMode.HIGHLIGHT); - expect(model.colorBlendAmount).toEqual(0.5); - expect(model.silhouetteColor).toEqual(Color.RED); - expect(model.silhouetteSize).toEqual(0.0); - - expect(model._enableShowOutline).toEqual(true); - expect(model.showOutline).toEqual(true); - expect(model.outlineColor).toEqual(Color.BLACK); - - expect(model.clippingPlanes).toBeUndefined(); - expect(model.lightColor).toBeUndefined(); - expect(model.imageBasedLighting).toBeDefined(); - - expect(model.credit).toBeUndefined(); - expect(model.showCreditsOnScreen).toEqual(false); - expect(model.splitDirection).toEqual(SplitDirection.NONE); - expect(model._projectTo2D).toEqual(false); - }); + ); + expect(model.show).toEqual(true); + expect(model.modelMatrix).toEqual(Matrix4.IDENTITY); + expect(model.scale).toEqual(1.0); + expect(model.minimumPixelSize).toEqual(0.0); + expect(model.maximumScale).toBeUndefined(); + + expect(model.id).toBeUndefined(); + expect(model.allowPicking).toEqual(true); + + expect(model.activeAnimations).toBeDefined(); + expect(model.clampAnimations).toEqual(true); + + expect(model.shadows).toEqual(ShadowMode.ENABLED); + expect(model.debugShowBoundingVolume).toEqual(false); + expect(model._enableDebugWireframe).toEqual(false); + expect(model.debugWireframe).toEqual(false); + + expect(model.cull).toEqual(true); + expect(model.backFaceCulling).toEqual(true); + expect(model.opaquePass).toEqual(Pass.OPAQUE); + expect(model.customShader).toBeUndefined(); + + expect(model.heightReference).toEqual(HeightReference.NONE); + expect(model.scene).toBeUndefined(); + expect(model.distanceDisplayCondition).toBeUndefined(); + + expect(model.color).toBeUndefined(); + expect(model.colorBlendMode).toEqual(ColorBlendMode.HIGHLIGHT); + expect(model.colorBlendAmount).toEqual(0.5); + expect(model.silhouetteColor).toEqual(Color.RED); + expect(model.silhouetteSize).toEqual(0.0); + + expect(model._enableShowOutline).toEqual(true); + expect(model.showOutline).toEqual(true); + expect(model.outlineColor).toEqual(Color.BLACK); + + expect(model.clippingPlanes).toBeUndefined(); + expect(model.lightColor).toBeUndefined(); + expect(model.imageBasedLighting).toBeDefined(); + + expect(model.credit).toBeUndefined(); + expect(model.showCreditsOnScreen).toEqual(false); + expect(model.splitDirection).toEqual(SplitDirection.NONE); + expect(model._projectTo2D).toEqual(false); }); - it("renders model without indices", function () { + it("renders model without indices", async function () { const resource = Resource.createIfNeeded(triangleWithoutIndicesUrl); - return resource.fetchJson().then(function (gltf) { - return loadAndZoomToModelAsync( - { - gltf: gltf, - basePath: triangleWithoutIndicesUrl, - modelMatrix: Transforms.eastNorthUpToFixedFrame( - Cartesian3.fromDegrees(0.0, 0.0, 100.0) - ), - }, - scene - ).then(function (model) { - // Orient the camera so it doesn't back-face cull the triangle. - const center = model.boundingSphere.center; - const range = 4.0 * model.boundingSphere.radius; - scene.camera.lookAt( - center, - new HeadingPitchRange(-CesiumMath.PI_OVER_TWO, 0, range) - ); + const gltf = await resource.fetchJson(); + const model = await loadAndZoomToModelAsync( + { + gltf: gltf, + basePath: triangleWithoutIndicesUrl, + modelMatrix: Transforms.eastNorthUpToFixedFrame( + Cartesian3.fromDegrees(0.0, 0.0, 100.0) + ), + }, + scene + ); + // Orient the camera so it doesn't back-face cull the triangle. + const center = model.boundingSphere.center; + const range = 4.0 * model.boundingSphere.radius; + scene.camera.lookAt( + center, + new HeadingPitchRange(-CesiumMath.PI_OVER_TWO, 0, range) + ); - // The triangle's diagonal edge is slightly out of frame. - scene.camera.moveDown(0.1); + // The triangle's diagonal edge is slightly out of frame. + scene.camera.moveDown(0.1); - verifyRender(model, true, { - zoomToModel: false, - }); - }); + verifyRender(model, true, { + zoomToModel: false, }); }); - it("renders model with vertex colors", function () { + it("renders model with vertex colors", async function () { const resource = Resource.createIfNeeded(vertexColorTestUrl); - return resource.fetchJson().then(function (gltf) { - return loadAndZoomToModelAsync( - { - gltf: gltf, - basePath: vertexColorTestUrl, - }, - scene - ).then(function (model) { - const renderOptions = { - scene: scene, - time: defaultDate, - }; - // Move the camera to the blue plane. - scene.camera.moveLeft(0.5); - - expect(renderOptions).toRenderAndCall(function (rgba) { - expect(rgba[0]).toEqual(0); - expect(rgba[1]).toEqual(0); - expect(rgba[2]).toEqual(255); - expect(rgba[3]).toEqual(255); - }); - - // Move the camera to the red plane. - scene.camera.moveRight(1.0); - expect(renderOptions).toRenderAndCall(function (rgba) { - expect(rgba[0]).toEqual(255); - expect(rgba[1]).toEqual(0); - expect(rgba[2]).toEqual(0); - expect(rgba[3]).toEqual(255); - }); - }); + const gltf = await resource.fetchJson(); + await loadAndZoomToModelAsync( + { + gltf: gltf, + basePath: vertexColorTestUrl, + }, + scene + ); + const renderOptions = { + scene: scene, + time: defaultDate, + }; + // Move the camera to the blue plane. + scene.camera.moveLeft(0.5); + + expect(renderOptions).toRenderAndCall(function (rgba) { + expect(rgba[0]).toEqual(0); + expect(rgba[1]).toEqual(0); + expect(rgba[2]).toEqual(255); + expect(rgba[3]).toEqual(255); + }); + + // Move the camera to the red plane. + scene.camera.moveRight(1.0); + expect(renderOptions).toRenderAndCall(function (rgba) { + expect(rgba[0]).toEqual(255); + expect(rgba[1]).toEqual(0); + expect(rgba[2]).toEqual(0); + expect(rgba[3]).toEqual(255); }); }); - it("renders model with double-sided material", function () { + it("renders model with double-sided material", async function () { const resource = Resource.createIfNeeded(twoSidedPlaneUrl); - return resource.fetchJson().then(function (gltf) { - return loadAndZoomToModelAsync( - { - gltf: gltf, - basePath: twoSidedPlaneUrl, - modelMatrix: Transforms.eastNorthUpToFixedFrame( - Cartesian3.fromDegrees(0.0, 0.0, 100.0) - ), - }, - scene - ).then(function (model) { - const renderOptions = { - scene: scene, - time: defaultDate, - }; - - const center = model.boundingSphere.center; - const range = 4.0 * model.boundingSphere.radius; - scene.camera.lookAt( - center, - new HeadingPitchRange(0, -CesiumMath.PI_OVER_TWO, range) - ); + const gltf = await resource.fetchJson(); + const model = await loadAndZoomToModelAsync( + { + gltf: gltf, + basePath: twoSidedPlaneUrl, + modelMatrix: Transforms.eastNorthUpToFixedFrame( + Cartesian3.fromDegrees(0.0, 0.0, 100.0) + ), + }, + scene + ); + const renderOptions = { + scene: scene, + time: defaultDate, + }; - // The top of the double-sided plane should render brightly, since - // its normal is pointing towards the light - let result; - expect(renderOptions).toRenderAndCall(function (rgba) { - expect(rgba).not.toEqual([0, 0, 0, 255]); - result = rgba; - }); - - scene.camera.lookAt( - center, - new HeadingPitchRange(0, CesiumMath.PI_OVER_TWO, range) - ); + const center = model.boundingSphere.center; + const range = 4.0 * model.boundingSphere.radius; + scene.camera.lookAt( + center, + new HeadingPitchRange(0, -CesiumMath.PI_OVER_TWO, range) + ); + + // The top of the double-sided plane should render brightly, since + // its normal is pointing towards the light + let result; + expect(renderOptions).toRenderAndCall(function (rgba) { + expect(rgba).not.toEqual([0, 0, 0, 255]); + result = rgba; + }); - // The bottom of the plane should render darker than the top, since - // its normal is pointing away from the light. - expect(renderOptions).toRenderAndCall(function (rgba) { - expect(rgba).not.toEqual([0, 0, 0, 255]); + scene.camera.lookAt( + center, + new HeadingPitchRange(0, CesiumMath.PI_OVER_TWO, range) + ); - expect(rgba[0]).toBeLessThan(result[0]); - expect(rgba[1]).toBeLessThan(result[1]); - expect(rgba[2]).toBeLessThan(result[2]); - expect(rgba[3]).toEqual(result[3]); - }); - }); + // The bottom of the plane should render darker than the top, since + // its normal is pointing away from the light. + expect(renderOptions).toRenderAndCall(function (rgba) { + expect(rgba).not.toEqual([0, 0, 0, 255]); + + expect(rgba[0]).toBeLessThan(result[0]); + expect(rgba[1]).toBeLessThan(result[1]); + expect(rgba[2]).toBeLessThan(result[2]); + expect(rgba[3]).toEqual(result[3]); }); }); // This test does not yet work since models without normals are // rendered as unlit. See https://github.com/CesiumGS/cesium/issues/6506 - xit("renders model with emissive texture", function () { + xit("renders model with emissive texture", async function () { const resource = Resource.createIfNeeded(emissiveTextureUrl); - return resource.fetchJson().then(function (gltf) { - return loadAndZoomToModelAsync( - { - gltf: gltf, - basePath: emissiveTextureUrl, - }, - scene - ).then(function (model) { - const renderOptions = { - scene: scene, - time: defaultDate, - }; - - expect(renderOptions).toRenderAndCall(function (rgba) { - // Emissive texture is red - expect(rgba[0]).toBeGreaterThan(20); - expect(rgba[1]).toBeLessThan(20); - expect(rgba[2]).toBeLessThan(20); - expect(rgba[3]).toEqual(255); - }); - }); + const gltf = await resource.fetchJson(); + await loadAndZoomToModelAsync( + { + gltf: gltf, + basePath: emissiveTextureUrl, + }, + scene + ); + const renderOptions = { + scene: scene, + time: defaultDate, + }; + + expect(renderOptions).toRenderAndCall(function (rgba) { + // Emissive texture is red + expect(rgba[0]).toBeGreaterThan(20); + expect(rgba[1]).toBeLessThan(20); + expect(rgba[2]).toBeLessThan(20); + expect(rgba[3]).toEqual(255); }); }); - it("renders model with the KHR_materials_pbrSpecularGlossiness extension", function () { + it("renders model with the KHR_materials_pbrSpecularGlossiness extension", async function () { // This model gets clipped if log depth is disabled, so zoom out // the camera just a little const offset = new HeadingPitchRange(0, -CesiumMath.PI_OVER_FOUR, 2); const resource = Resource.createIfNeeded(boomBoxUrl); - return resource.fetchJson().then(function (gltf) { - return loadAndZoomToModelAsync( - { - gltf: gltf, - basePath: boomBoxUrl, - // This model is tiny, so scale it up so it's visible. - scale: 10.0, - offset: offset, - }, - scene - ).then(function (model) { - verifyRender(model, true); - }); - }); + const gltf = await resource.fetchJson(); + const model = await loadAndZoomToModelAsync( + { + gltf: gltf, + basePath: boomBoxUrl, + // This model is tiny, so scale it up so it's visible. + scale: 10.0, + offset: offset, + }, + scene + ); + verifyRender(model, true); + }); + + it("renders model with the KHR_materials_specular extension", async function () { + const resource = Resource.createIfNeeded(boxSpecularUrl); + const gltf = await resource.fetchJson(); + const model = await loadAndZoomToModelAsync( + { + gltf: gltf, + basePath: boxSpecularUrl, + }, + scene + ); + verifyRender(model, true); + }); + + it("renders model with the KHR_materials_anisotropy extension", async function () { + const resource = Resource.createIfNeeded(boxAnisotropyUrl); + const gltf = await resource.fetchJson(); + const model = await loadAndZoomToModelAsync( + { + gltf: gltf, + basePath: boxAnisotropyUrl, + }, + scene + ); + verifyRender(model, true); + }); + + it("renders model with the KHR_materials_clearcoat extension", async function () { + const resource = Resource.createIfNeeded(boxClearcoatUrl); + const gltf = await resource.fetchJson(); + const model = await loadAndZoomToModelAsync( + { + gltf: gltf, + basePath: boxClearcoatUrl, + }, + scene + ); + verifyRender(model, true); }); it("transforms property textures with KHR_texture_transform", async function () { @@ -863,44 +886,42 @@ describe( }); }); - it("renders model with morph targets", function () { + it("renders model with morph targets", async function () { // This model gets clipped if log depth is disabled, so zoom out // the camera just a little const offset = new HeadingPitchRange(0, -CesiumMath.PI_OVER_FOUR, 2); const resource = Resource.createIfNeeded(morphPrimitivesTestUrl); - return resource.fetchJson().then(function (gltf) { - return loadAndZoomToModelAsync( - { - gltf: gltf, - basePath: morphPrimitivesTestUrl, - offset: offset, - }, - scene - ).then(function (model) { - // The background color must be changed because the model's texture - // contains black, which can confuse the test. - const renderOptions = { - backgroundColor: Color.BLUE, - zoomToModel: false, - }; + const gltf = await resource.fetchJson(); + const model = await loadAndZoomToModelAsync( + { + gltf: gltf, + basePath: morphPrimitivesTestUrl, + offset: offset, + }, + scene + ); + // The background color must be changed because the model's texture + // contains black, which can confuse the test. + const renderOptions = { + backgroundColor: Color.BLUE, + zoomToModel: false, + }; - // Move the camera down slightly so the morphed part is in view. - scene.camera.moveDown(0.25); + // Move the camera down slightly so the morphed part is in view. + scene.camera.moveDown(0.25); - // The model is a plane made three-dimensional by morph targets. - // If morph targets aren't supported, the model won't appear in the camera. - verifyRender(model, true, renderOptions); - }); - }); + // The model is a plane made three-dimensional by morph targets. + // If morph targets aren't supported, the model won't appear in the camera. + verifyRender(model, true, renderOptions); }); - it("renders Draco-compressed model", function () { - return loadAndZoomToModelAsync({ gltf: dracoCesiumManUrl }, scene).then( - function (model) { - verifyRender(model, true); - } + it("renders Draco-compressed model", async function () { + const model = await loadAndZoomToModelAsync( + { gltf: dracoCesiumManUrl }, + scene ); + verifyRender(model, true); }); it("fails to load with Draco decoding error", async function () { @@ -940,86 +961,83 @@ describe( ); }); - it("renders model without animations added", function () { - return loadAndZoomToModelAsync( + it("renders model without animations added", async function () { + const model = await loadAndZoomToModelAsync( { gltf: animatedTriangleUrl, offset: animatedTriangleOffset, }, scene - ).then(function (model) { - const animationCollection = model.activeAnimations; - expect(animationCollection).toBeDefined(); - expect(animationCollection.length).toBe(0); + ); + const animationCollection = model.activeAnimations; + expect(animationCollection).toBeDefined(); + expect(animationCollection.length).toBe(0); - // Move camera so that the triangle is in view. - scene.camera.moveDown(0.5); - verifyRender(model, true, { - zoomToModel: false, - }); + // Move camera so that the triangle is in view. + scene.camera.moveDown(0.5); + verifyRender(model, true, { + zoomToModel: false, }); }); - it("renders model with animations added", function () { - return loadAndZoomToModelAsync( + it("renders model with animations added", async function () { + const model = await loadAndZoomToModelAsync( { gltf: animatedTriangleUrl, offset: animatedTriangleOffset, }, scene - ).then(function (model) { - // Move camera so that the triangle is in view. - scene.camera.moveDown(0.5); - - // The model rotates such that it leaves the view of the camera - // halfway into its animation. - const startTime = defaultDate; - const animationCollection = model.activeAnimations; - animationCollection.add({ - index: 0, - startTime: startTime, - }); - expect(animationCollection.length).toBe(1); - verifyRender(model, true, { - zoomToModel: false, - time: startTime, - }); - - const time = JulianDate.addSeconds(startTime, 0.5, new JulianDate()); - verifyRender(model, false, { - zoomToModel: false, - time: time, - }); + ); + // Move camera so that the triangle is in view. + scene.camera.moveDown(0.5); + + // The model rotates such that it leaves the view of the camera + // halfway into its animation. + const startTime = defaultDate; + const animationCollection = model.activeAnimations; + animationCollection.add({ + index: 0, + startTime: startTime, + }); + expect(animationCollection.length).toBe(1); + verifyRender(model, true, { + zoomToModel: false, + time: startTime, + }); + + const time = JulianDate.addSeconds(startTime, 0.5, new JulianDate()); + verifyRender(model, false, { + zoomToModel: false, + time: time, }); }); - it("renders model with CESIUM_RTC extension", function () { - return loadAndZoomToModelAsync( + it("renders model with CESIUM_RTC extension", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxCesiumRtcUrl, }, scene - ).then(function (model) { - verifyRender(model, true); - }); + ); + verifyRender(model, true); }); - it("adds animation to draco-compressed model", function () { - return loadAndZoomToModelAsync({ gltf: dracoCesiumManUrl }, scene).then( - function (model) { - verifyRender(model, true); - - const animationCollection = model.activeAnimations; - const animation = animationCollection.add({ - index: 0, - }); - expect(animation).toBeDefined(); - expect(animationCollection.length).toBe(1); - } + it("adds animation to draco-compressed model", async function () { + const model = await loadAndZoomToModelAsync( + { gltf: dracoCesiumManUrl }, + scene ); + verifyRender(model, true); + + const animationCollection = model.activeAnimations; + const animation = animationCollection.add({ + index: 0, + }); + expect(animation).toBeDefined(); + expect(animationCollection.length).toBe(1); }); - it("renders model with instancing but no normals", function () { + it("renders model with instancing but no normals", async function () { // None of the 4 instanced cubes are in the center of the model's bounding // sphere, so set up a camera view that focuses in on one of them. const offset = new HeadingPitchRange( @@ -1029,61 +1047,55 @@ describe( ); const resource = Resource.createIfNeeded(boxInstancedNoNormalsUrl); - return resource.fetchJson().then(function (gltf) { - return loadAndZoomToModelAsync( - { - gltf: gltf, - basePath: boxInstancedNoNormalsUrl, - offset: offset, - }, - scene - ).then(function (model) { - const renderOptions = { - zoomToModel: false, - }; - - verifyRender(model, true, renderOptions); - }); - }); + const gltf = await resource.fetchJson(); + const model = await loadAndZoomToModelAsync( + { + gltf: gltf, + basePath: boxInstancedNoNormalsUrl, + offset: offset, + }, + scene + ); + const renderOptions = { + zoomToModel: false, + }; + + verifyRender(model, true, renderOptions); }); - it("show works", function () { + it("show works", async function () { const resource = Resource.createIfNeeded(boxTexturedGlbUrl); - const loadPromise = resource.fetchArrayBuffer(); - return loadPromise.then(function (buffer) { - return loadAndZoomToModelAsync( - { gltf: new Uint8Array(buffer), show: false }, - scene - ).then(function (model) { - expect(model.ready).toEqual(true); - expect(model.show).toEqual(false); - verifyRender(model, false); - - model.show = true; - expect(model.show).toEqual(true); - verifyRender(model, true); - }); - }); + const buffer = await resource.fetchArrayBuffer(); + const model = await loadAndZoomToModelAsync( + { gltf: new Uint8Array(buffer), show: false }, + scene + ); + expect(model.ready).toEqual(true); + expect(model.show).toEqual(false); + verifyRender(model, false); + + model.show = true; + expect(model.show).toEqual(true); + verifyRender(model, true); }); - it("renders in 2D", function () { - return loadAndZoomToModelAsync( + it("renders in 2D", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGlbUrl, modelMatrix: modelMatrix, }, scene2D - ).then(function (model) { - expect(model.ready).toEqual(true); - verifyRender(model, true, { - zoomToModel: false, - scene: scene2D, - }); + ); + expect(model.ready).toEqual(true); + verifyRender(model, true, { + zoomToModel: false, + scene: scene2D, }); }); - it("renders in 2D over the IDL", function () { - return loadAndZoomToModelAsync( + it("renders in 2D over the IDL", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGlbUrl, modelMatrix: Transforms.eastNorthUpToFixedFrame( @@ -1091,65 +1103,62 @@ describe( ), }, scene2D - ).then(function (model) { - expect(model.ready).toEqual(true); - verifyRender(model, true, { - zoomToModel: false, - scene: scene2D, - }); + ); + expect(model.ready).toEqual(true); + verifyRender(model, true, { + zoomToModel: false, + scene: scene2D, + }); - model.modelMatrix = Transforms.eastNorthUpToFixedFrame( - Cartesian3.fromDegrees(-180.0, 0.0) - ); - verifyRender(model, true, { - zoomToModel: false, - scene: scene2D, - }); + model.modelMatrix = Transforms.eastNorthUpToFixedFrame( + Cartesian3.fromDegrees(-180.0, 0.0) + ); + verifyRender(model, true, { + zoomToModel: false, + scene: scene2D, }); }); - it("renders in CV", function () { - return loadAndZoomToModelAsync( + it("renders in CV", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGlbUrl, modelMatrix: modelMatrix, }, sceneCV - ).then(function (model) { - expect(model.ready).toEqual(true); - scene.camera.moveBackward(1.0); - verifyRender(model, true, { - zoomToModel: false, - scene: sceneCV, - }); + ); + expect(model.ready).toEqual(true); + scene.camera.moveBackward(1.0); + verifyRender(model, true, { + zoomToModel: false, + scene: sceneCV, }); }); - it("renders in CV after draw commands are reset", function () { - return loadAndZoomToModelAsync( + it("renders in CV after draw commands are reset", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGlbUrl, modelMatrix: modelMatrix, }, sceneCV - ).then(function (model) { - expect(model.ready).toEqual(true); - scene.camera.moveBackward(1.0); - verifyRender(model, true, { - zoomToModel: false, - scene: sceneCV, - }); + ); + expect(model.ready).toEqual(true); + scene.camera.moveBackward(1.0); + verifyRender(model, true, { + zoomToModel: false, + scene: sceneCV, + }); - model._drawCommandsBuilt = false; - verifyRender(model, true, { - zoomToModel: false, - scene: sceneCV, - }); + model._drawCommandsBuilt = false; + verifyRender(model, true, { + zoomToModel: false, + scene: sceneCV, }); }); - it("projectTo2D works for 2D", function () { - return loadAndZoomToModelAsync( + it("projectTo2D works for 2D", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGlbUrl, modelMatrix: modelMatrix, @@ -1157,17 +1166,16 @@ describe( incrementallyLoadTextures: false, }, scene2D - ).then(function (model) { - expect(model.ready).toEqual(true); - verifyRender(model, true, { - zoomToModel: false, - scene: scene2D, - }); + ); + expect(model.ready).toEqual(true); + verifyRender(model, true, { + zoomToModel: false, + scene: scene2D, }); }); - it("projectTo2D works for CV", function () { - return loadAndZoomToModelAsync( + it("projectTo2D works for CV", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGlbUrl, modelMatrix: modelMatrix, @@ -1175,174 +1183,153 @@ describe( incrementallyLoadTextures: false, }, sceneCV - ).then(function (model) { - expect(model.ready).toEqual(true); - sceneCV.camera.moveBackward(1.0); - verifyRender(model, true, { - zoomToModel: false, - scene: sceneCV, - }); + ); + expect(model.ready).toEqual(true); + sceneCV.camera.moveBackward(1.0); + verifyRender(model, true, { + zoomToModel: false, + scene: sceneCV, }); }); - it("does not render during morph", function () { - return loadAndZoomToModelAsync( + it("does not render during morph", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGlbUrl, modelMatrix: modelMatrix, projectTo2D: true, }, scene - ).then(function (model) { - const commandList = scene.frameState.commandList; - expect(model.ready).toEqual(true); + ); + const commandList = scene.frameState.commandList; + expect(model.ready).toEqual(true); - scene.renderForSpecs(); - expect(commandList.length).toBeGreaterThan(0); + scene.renderForSpecs(); + expect(commandList.length).toBeGreaterThan(0); - scene.morphTo2D(1.0); - scene.renderForSpecs(); - expect(commandList.length).toBe(0); + scene.morphTo2D(1.0); + scene.renderForSpecs(); + expect(commandList.length).toBe(0); - scene.completeMorph(); - scene.morphTo3D(0.0); - scene.renderForSpecs(); - expect(commandList.length).toBeGreaterThan(0); - }); + scene.completeMorph(); + scene.morphTo3D(0.0); + scene.renderForSpecs(); + expect(commandList.length).toBeGreaterThan(0); }); describe("style", function () { - it("applies style to model with feature table", function () { - let model; - let style; - return loadAndZoomToModelAsync({ gltf: buildingsMetadata }, scene).then( - function (result) { - model = result; - // Renders without style. - verifyRender(model, true); - - // Renders with opaque style. - style = new Cesium3DTileStyle({ - color: { - conditions: [["${height} > 1", "color('red')"]], - }, - }); - - model.style = style; - verifyRender(model, true); - expect(model._styleCommandsNeeded).toBe( - StyleCommandsNeeded.ALL_OPAQUE - ); + it("applies style to model with feature table", async function () { + const model = await loadAndZoomToModelAsync( + { gltf: buildingsMetadata }, + scene + ); - // Renders with translucent style. - style = new Cesium3DTileStyle({ - color: { - conditions: [["${height} > 1", "color('red', 0.5)"]], - }, - }); - - model.style = style; - verifyRender(model, true); - expect(model._styleCommandsNeeded).toBe( - StyleCommandsNeeded.ALL_TRANSLUCENT - ); + // Renders without style. + verifyRender(model, true); - // Does not render with invisible color. - style = new Cesium3DTileStyle({ - color: { - conditions: [["${height} > 1", "color('red', 0.0)"]], - }, - }); - - // Does not render when style disables show. - style = new Cesium3DTileStyle({ - show: { - conditions: [["${height} > 1", "false"]], - }, - }); - - model.style = style; - verifyRender(model, false); - - // Render when style is removed. - model.style = undefined; - verifyRender(model, true); - } + // Renders with opaque style. + model.style = new Cesium3DTileStyle({ + color: { + conditions: [["${height} > 1", "color('red')"]], + }, + }); + verifyRender(model, true); + expect(model._styleCommandsNeeded).toBe(StyleCommandsNeeded.ALL_OPAQUE); + + // Renders with translucent style. + model.style = new Cesium3DTileStyle({ + color: { + conditions: [["${height} > 1", "color('red', 0.5)"]], + }, + }); + verifyRender(model, true); + expect(model._styleCommandsNeeded).toBe( + StyleCommandsNeeded.ALL_TRANSLUCENT ); + + // Does not render with invisible color. + model.style = new Cesium3DTileStyle({ + color: { + conditions: [["${height} > 1", "color('red', 0.0)"]], + }, + }); + verifyRender(model, false); + + // Does not render when style disables show. + model.style = new Cesium3DTileStyle({ + show: { + conditions: [["${height} > 1", "false"]], + }, + }); + verifyRender(model, false); + + // Render when style is removed. + model.style = undefined; + verifyRender(model, true); }); - it("applies style to model without feature table", function () { - let model; - let style; - return loadAndZoomToModelAsync({ gltf: boxTexturedGlbUrl }, scene).then( - function (result) { - const renderOptions = { - scene: scene, - time: defaultDate, - }; - model = result; - - // Renders without style. - let original; - verifyRender(model, true); - expect(renderOptions).toRenderAndCall(function (rgba) { - original = rgba; - }); - - // Renders with opaque style. - style = new Cesium3DTileStyle({ - color: "color('red')", - }); - - model.style = style; - verifyRender(model, true); - expect(renderOptions).toRenderAndCall(function (rgba) { - expect(rgba[0]).toEqual(original[0]); - expect(rgba[1]).toBeLessThan(original[1]); - expect(rgba[2]).toBeLessThan(original[2]); - expect(rgba[3]).toEqual(original[3]); - }); - - // Renders with translucent style. - style = new Cesium3DTileStyle({ - color: "color('red', 0.5)", - }); - - model.style = style; - verifyRender(model, true); - expect(renderOptions).toRenderAndCall(function (rgba) { - expect(rgba[0]).toBeLessThan(original[0]); - expect(rgba[1]).toBeLessThan(original[1]); - expect(rgba[2]).toBeLessThan(original[2]); - expect(rgba[3]).toEqual(original[3]); - }); - - // Does not render with invisible color. - style = new Cesium3DTileStyle({ - color: "color('red', 0.0)", - }); - - model.style = style; - verifyRender(model, false, { zoomToModel: false }); - - // Does not render when style disables show. - style = new Cesium3DTileStyle({ - show: "false", - }); - - model.style = style; - verifyRender(model, false, { zoomToModel: false }); - - // Render when style is removed. - model.style = undefined; - expect(renderOptions).toRenderAndCall(function (rgba) { - expect(rgba[0]).toEqual(original[0]); - expect(rgba[1]).toEqual(original[1]); - expect(rgba[2]).toEqual(original[2]); - expect(rgba[3]).toEqual(original[3]); - }); - } + it("applies style to model without feature table", async function () { + const model = await loadAndZoomToModelAsync( + { gltf: boxTexturedGlbUrl }, + scene ); + + const renderOptions = { + scene: scene, + time: defaultDate, + }; + + // Renders without style. + let original; + verifyRender(model, true); + expect(renderOptions).toRenderAndCall(function (rgba) { + original = rgba; + }); + + // Renders with opaque style. + model.style = new Cesium3DTileStyle({ + color: "color('red')", + }); + verifyRender(model, true); + expect(renderOptions).toRenderAndCall(function (rgba) { + expect(rgba[0]).toEqual(original[0]); + expect(rgba[1]).toBeLessThan(original[1]); + expect(rgba[2]).toBeLessThan(original[2]); + expect(rgba[3]).toEqual(original[3]); + }); + + // Renders with translucent style. + model.style = new Cesium3DTileStyle({ + color: "color('red', 0.5)", + }); + verifyRender(model, true); + expect(renderOptions).toRenderAndCall(function (rgba) { + expect(rgba[0]).toBeLessThan(original[0]); + expect(rgba[1]).toBeLessThan(original[1]); + expect(rgba[2]).toBeLessThan(original[2]); + expect(rgba[3]).toEqual(original[3]); + }); + + // Does not render with invisible color. + model.style = new Cesium3DTileStyle({ + color: "color('red', 0.0)", + }); + verifyRender(model, false, { zoomToModel: false }); + + // Does not render when style disables show. + model.style = new Cesium3DTileStyle({ + show: "false", + }); + verifyRender(model, false, { zoomToModel: false }); + + // Render when style is removed. + model.style = undefined; + expect(renderOptions).toRenderAndCall(function (rgba) { + expect(rgba[0]).toEqual(original[0]); + expect(rgba[1]).toEqual(original[1]); + expect(rgba[2]).toEqual(original[2]); + expect(rgba[3]).toEqual(original[3]); + }); }); }); @@ -1350,227 +1337,198 @@ describe( const boxWithCreditsUrl = "./Data/Models/glTF-2.0/BoxWithCopyright/glTF/Box.gltf"; - it("initializes with credit", function () { + it("initializes with credit", async function () { const credit = new Credit("User Credit"); const resource = Resource.createIfNeeded(boxTexturedGltfUrl); - return resource.fetchJson().then(function (gltf) { - return loadAndZoomToModelAsync( - { - gltf: gltf, - basePath: boxTexturedGltfUrl, - credit: credit, - }, - scene - ).then(function (model) { - scene.renderForSpecs(); - const creditDisplay = scene.frameState.creditDisplay; - const credits = - creditDisplay._currentFrameCredits.lightboxCredits.values; - const length = credits.length; - expect(length).toEqual(1); - expect(credits[0].credit.html).toEqual("User Credit"); - }); - }); + const gltf = await resource.fetchJson(); + await loadAndZoomToModelAsync( + { + gltf: gltf, + basePath: boxTexturedGltfUrl, + credit: credit, + }, + scene + ); + scene.renderForSpecs(); + const creditDisplay = scene.frameState.creditDisplay; + const credits = + creditDisplay._currentFrameCredits.lightboxCredits.values; + expect(credits.length).toEqual(1); + expect(credits[0].credit.html).toEqual("User Credit"); }); - it("initializes with credit string", function () { + it("initializes with credit string", async function () { const creditString = "User Credit"; const resource = Resource.createIfNeeded(boxTexturedGltfUrl); - return resource.fetchJson().then(function (gltf) { - return loadAndZoomToModelAsync( - { - gltf: gltf, - basePath: boxTexturedGltfUrl, - credit: creditString, - }, - scene - ).then(function (model) { - scene.renderForSpecs(); - const creditDisplay = scene.frameState.creditDisplay; - const credits = - creditDisplay._currentFrameCredits.lightboxCredits.values; - const length = credits.length; - expect(length).toEqual(1); - expect(credits[0].credit.html).toEqual(creditString); - }); - }); + const gltf = await resource.fetchJson(); + await loadAndZoomToModelAsync( + { + gltf: gltf, + basePath: boxTexturedGltfUrl, + credit: creditString, + }, + scene + ); + scene.renderForSpecs(); + const creditDisplay = scene.frameState.creditDisplay; + const credits = + creditDisplay._currentFrameCredits.lightboxCredits.values; + expect(credits.length).toEqual(1); + expect(credits[0].credit.html).toEqual(creditString); }); - it("gets copyrights from gltf", function () { + it("gets copyrights from gltf", async function () { const resource = Resource.createIfNeeded(boxWithCreditsUrl); - return resource.fetchJson().then(function (gltf) { - return loadAndZoomToModelAsync( - { - gltf: gltf, - basePath: boxWithCreditsUrl, - }, - scene - ).then(function (model) { - const expectedCredits = [ - "First Source", - "Second Source", - "Third Source", - ]; - - scene.renderForSpecs(); - const creditDisplay = scene.frameState.creditDisplay; - const credits = - creditDisplay._currentFrameCredits.lightboxCredits.values; - const length = credits.length; - expect(length).toEqual(expectedCredits.length); - for (let i = 0; i < length; i++) { - expect(credits[i].credit.html).toEqual(expectedCredits[i]); - } - }); - }); + const gltf = await resource.fetchJson(); + await loadAndZoomToModelAsync( + { + gltf: gltf, + basePath: boxWithCreditsUrl, + }, + scene + ); + const expectedCredits = [ + "First Source", + "Second Source", + "Third Source", + ]; + + scene.renderForSpecs(); + const creditDisplay = scene.frameState.creditDisplay; + const credits = + creditDisplay._currentFrameCredits.lightboxCredits.values; + expect(credits.length).toEqual(expectedCredits.length); + for (let i = 0; i < credits.length; i++) { + expect(credits[i].credit.html).toEqual(expectedCredits[i]); + } }); - it("displays all types of credits", function () { + it("displays all types of credits", async function () { const resource = Resource.createIfNeeded(boxWithCreditsUrl); - return resource.fetchJson().then(function (gltf) { - return loadAndZoomToModelAsync( - { - gltf: gltf, - basePath: boxWithCreditsUrl, - credit: "User Credit", - }, - scene - ).then(function (model) { - model._resourceCredits = [new Credit("Resource Credit")]; - const expectedCredits = [ - "User Credit", - "Resource Credit", - "First Source", - "Second Source", - "Third Source", - ]; - - scene.renderForSpecs(); - const creditDisplay = scene.frameState.creditDisplay; - const credits = - creditDisplay._currentFrameCredits.lightboxCredits.values; - const length = credits.length; - expect(length).toEqual(expectedCredits.length); - for (let i = 0; i < length; i++) { - expect(credits[i].credit.html).toEqual(expectedCredits[i]); - } - }); - }); + const gltf = await resource.fetchJson(); + const model = await loadAndZoomToModelAsync( + { + gltf: gltf, + basePath: boxWithCreditsUrl, + credit: "User Credit", + }, + scene + ); + model._resourceCredits = [new Credit("Resource Credit")]; + const expectedCredits = [ + "User Credit", + "Resource Credit", + "First Source", + "Second Source", + "Third Source", + ]; + + scene.renderForSpecs(); + const creditDisplay = scene.frameState.creditDisplay; + const credits = + creditDisplay._currentFrameCredits.lightboxCredits.values; + expect(credits.length).toEqual(expectedCredits.length); + for (let i = 0; i < credits.length; i++) { + expect(credits[i].credit.html).toEqual(expectedCredits[i]); + } }); - it("initializes with showCreditsOnScreen", function () { + it("initializes with showCreditsOnScreen", async function () { const resource = Resource.createIfNeeded(boxWithCreditsUrl); - return resource.fetchJson().then(function (gltf) { - return loadAndZoomToModelAsync( - { - gltf: gltf, - basePath: boxWithCreditsUrl, - credit: "User Credit", - showCreditsOnScreen: true, - }, - scene - ).then(function (model) { - const expectedCredits = [ - "User Credit", - "First Source", - "Second Source", - "Third Source", - ]; - - scene.renderForSpecs(); - const creditDisplay = scene.frameState.creditDisplay; - const credits = - creditDisplay._currentFrameCredits.screenCredits.values; - const length = credits.length; - expect(length).toEqual(expectedCredits.length); - for (let i = 0; i < length; i++) { - expect(credits[i].credit.html).toEqual(expectedCredits[i]); - } - }); - }); + const gltf = await resource.fetchJson(); + await loadAndZoomToModelAsync( + { + gltf: gltf, + basePath: boxWithCreditsUrl, + credit: "User Credit", + showCreditsOnScreen: true, + }, + scene + ); + const expectedCredits = [ + "User Credit", + "First Source", + "Second Source", + "Third Source", + ]; + + scene.renderForSpecs(); + const creditDisplay = scene.frameState.creditDisplay; + const credits = creditDisplay._currentFrameCredits.screenCredits.values; + expect(credits.length).toEqual(expectedCredits.length); + for (let i = 0; i < credits.length; i++) { + expect(credits[i].credit.html).toEqual(expectedCredits[i]); + } }); - it("changing showCreditsOnScreen works", function () { + it("changing showCreditsOnScreen works", async function () { const resource = Resource.createIfNeeded(boxWithCreditsUrl); - return resource.fetchJson().then(function (gltf) { - return loadAndZoomToModelAsync( - { - gltf: gltf, - basePath: boxWithCreditsUrl, - credit: "User Credit", - showCreditsOnScreen: false, - }, - scene - ).then(function (model) { - const expectedCredits = [ - "User Credit", - "First Source", - "Second Source", - "Third Source", - ]; - - scene.renderForSpecs(); - const creditDisplay = scene.frameState.creditDisplay; - const lightboxCredits = - creditDisplay._currentFrameCredits.lightboxCredits.values; - const screenCredits = - creditDisplay._currentFrameCredits.screenCredits.values; - - let length = lightboxCredits.length; - expect(length).toEqual(expectedCredits.length); - for (let i = 0; i < length; i++) { - expect(lightboxCredits[i].credit.html).toEqual( - expectedCredits[i] - ); - } - expect(screenCredits.length).toEqual(0); - - model.showCreditsOnScreen = true; - scene.renderForSpecs(); - length = screenCredits.length; - expect(length).toEqual(expectedCredits.length); - for (let i = 0; i < length; i++) { - expect(screenCredits[i].credit.html).toEqual(expectedCredits[i]); - } - expect(lightboxCredits.length).toEqual(0); - - model.showCreditsOnScreen = false; - scene.renderForSpecs(); - length = lightboxCredits.length; - expect(length).toEqual(expectedCredits.length); - for (let i = 0; i < length; i++) { - expect(lightboxCredits[i].credit.html).toEqual( - expectedCredits[i] - ); - } - expect(screenCredits.length).toEqual(0); - }); - }); + const gltf = await resource.fetchJson(); + const model = await loadAndZoomToModelAsync( + { + gltf: gltf, + basePath: boxWithCreditsUrl, + credit: "User Credit", + showCreditsOnScreen: false, + }, + scene + ); + const expectedCredits = [ + "User Credit", + "First Source", + "Second Source", + "Third Source", + ]; + + scene.renderForSpecs(); + const creditDisplay = scene.frameState.creditDisplay; + const lightboxCredits = + creditDisplay._currentFrameCredits.lightboxCredits.values; + const screenCredits = + creditDisplay._currentFrameCredits.screenCredits.values; + + expect(lightboxCredits.length).toEqual(expectedCredits.length); + for (let i = 0; i < lightboxCredits.length; i++) { + expect(lightboxCredits[i].credit.html).toEqual(expectedCredits[i]); + } + expect(screenCredits.length).toEqual(0); + + model.showCreditsOnScreen = true; + scene.renderForSpecs(); + expect(screenCredits.length).toEqual(expectedCredits.length); + for (let i = 0; i < screenCredits.length; i++) { + expect(screenCredits[i].credit.html).toEqual(expectedCredits[i]); + } + expect(lightboxCredits.length).toEqual(0); + + model.showCreditsOnScreen = false; + scene.renderForSpecs(); + expect(lightboxCredits.length).toEqual(expectedCredits.length); + for (let i = 0; i < lightboxCredits.length; i++) { + expect(lightboxCredits[i].credit.html).toEqual(expectedCredits[i]); + } + expect(screenCredits.length).toEqual(0); }); - it("showCreditsOnScreen overrides existing credit setting", function () { + it("showCreditsOnScreen overrides existing credit setting", async function () { const resource = Resource.createIfNeeded(boxTexturedGltfUrl); - return resource.fetchJson().then(function (gltf) { - return loadAndZoomToModelAsync( - { - gltf: gltf, - basePath: boxTexturedGltfUrl, - credit: new Credit("User Credit", false), - showCreditsOnScreen: true, - }, - scene - ).then(function (model) { - scene.renderForSpecs(); - const creditDisplay = scene.frameState.creditDisplay; - const credits = - creditDisplay._currentFrameCredits.screenCredits.values; - const length = credits.length; - expect(length).toEqual(1); - for (let i = 0; i < length; i++) { - expect(credits[i].credit.html).toEqual("User Credit"); - } - }); - }); + const gltf = await resource.fetchJson(); + await loadAndZoomToModelAsync( + { + gltf: gltf, + basePath: boxTexturedGltfUrl, + credit: new Credit("User Credit", false), + showCreditsOnScreen: true, + }, + scene + ); + scene.renderForSpecs(); + const creditDisplay = scene.frameState.creditDisplay; + const credits = creditDisplay._currentFrameCredits.screenCredits.values; + expect(credits.length).toEqual(1); + for (let i = 0; i < credits.length; i++) { + expect(credits[i].credit.html).toEqual("User Credit"); + } }); }); @@ -1598,143 +1556,124 @@ describe( sceneWithWebgl1.destroyForSpecs(); }); - it("debugWireframe works for WebGL1 if enableDebugWireframe is true", function () { + it("debugWireframe works for WebGL1 if enableDebugWireframe is true", async function () { const resource = Resource.createIfNeeded(boxTexturedGlbUrl); - const loadPromise = resource.fetchArrayBuffer(); - return loadPromise.then(function (buffer) { - return loadAndZoomToModelAsync( - { gltf: new Uint8Array(buffer), enableDebugWireframe: true }, - sceneWithWebgl1 - ).then(function (model) { - verifyDebugWireframe(model, PrimitiveType.TRIANGLES); - }); - }); + const buffer = await resource.fetchArrayBuffer(); + const model = await loadAndZoomToModelAsync( + { gltf: new Uint8Array(buffer), enableDebugWireframe: true }, + sceneWithWebgl1 + ); + verifyDebugWireframe(model, PrimitiveType.TRIANGLES); }); - it("debugWireframe does nothing in WebGL1 if enableDebugWireframe is false", function () { + it("debugWireframe does nothing in WebGL1 if enableDebugWireframe is false", async function () { const resource = Resource.createIfNeeded(boxTexturedGlbUrl); - const loadPromise = resource.fetchArrayBuffer(); - return loadPromise.then(function (buffer) { - return loadAndZoomToModelAsync( - { gltf: new Uint8Array(buffer), enableDebugWireframe: false }, - sceneWithWebgl1 - ).then(function (model) { - const commandList = scene.frameState.commandList; - const commandCounts = []; - let i, command; - sceneWithWebgl1.renderForSpecs(); - for (i = 0; i < commandList.length; i++) { - command = commandList[i]; - expect(command.primitiveType).toBe(PrimitiveType.TRIANGLES); - commandCounts.push(command.count); - } + const buffer = await resource.fetchArrayBuffer(); + const model = await loadAndZoomToModelAsync( + { gltf: new Uint8Array(buffer), enableDebugWireframe: false }, + sceneWithWebgl1 + ); + const commandList = scene.frameState.commandList; + const commandCounts = []; + sceneWithWebgl1.renderForSpecs(); + for (let i = 0; i < commandList.length; i++) { + const command = commandList[i]; + expect(command.primitiveType).toBe(PrimitiveType.TRIANGLES); + commandCounts.push(command.count); + } - model.debugWireframe = true; - expect(model._drawCommandsBuilt).toBe(false); + model.debugWireframe = true; + expect(model._drawCommandsBuilt).toBe(false); - sceneWithWebgl1.renderForSpecs(); - for (i = 0; i < commandList.length; i++) { - command = commandList[i]; - expect(command.primitiveType).toBe(PrimitiveType.TRIANGLES); - expect(command.count).toEqual(commandCounts[i]); - } - }); - }); + sceneWithWebgl1.renderForSpecs(); + for (let i = 0; i < commandList.length; i++) { + const command = commandList[i]; + expect(command.primitiveType).toBe(PrimitiveType.TRIANGLES); + expect(command.count).toEqual(commandCounts[i]); + } }); - it("debugWireframe works for WebGL2", function () { + it("debugWireframe works for WebGL2", async function () { if (!scene.context.webgl2) { return; } const resource = Resource.createIfNeeded(boxTexturedGlbUrl); - const loadPromise = resource.fetchArrayBuffer(); - return loadPromise.then(function (buffer) { - return loadAndZoomToModelAsync( - { gltf: new Uint8Array(buffer) }, - scene - ).then(function (model) { - verifyDebugWireframe(model, PrimitiveType.TRIANGLES, { - scene: scene, - }); - }); + const buffer = await resource.fetchArrayBuffer(); + const model = await loadAndZoomToModelAsync( + { gltf: new Uint8Array(buffer) }, + scene + ); + verifyDebugWireframe(model, PrimitiveType.TRIANGLES, { + scene: scene, }); }); - it("debugWireframe works for model without indices", function () { - return loadAndZoomToModelAsync( + it("debugWireframe works for model without indices", async function () { + const model = await loadAndZoomToModelAsync( { gltf: triangleWithoutIndicesUrl, enableDebugWireframe: true }, scene - ).then(function (model) { - verifyDebugWireframe(model, PrimitiveType.TRIANGLES, { - hasIndices: false, - }); + ); + verifyDebugWireframe(model, PrimitiveType.TRIANGLES, { + hasIndices: false, }); }); - it("debugWireframe works for model with triangle strip", function () { - return loadAndZoomToModelAsync( + it("debugWireframe works for model with triangle strip", async function () { + const model = await loadAndZoomToModelAsync( { gltf: triangleStripUrl, enableDebugWireframe: true }, scene - ).then(function (model) { - verifyDebugWireframe(model, PrimitiveType.TRIANGLE_STRIP); - }); + ); + verifyDebugWireframe(model, PrimitiveType.TRIANGLE_STRIP); }); - it("debugWireframe works for model with triangle fan", function () { - return loadAndZoomToModelAsync( + it("debugWireframe works for model with triangle fan", async function () { + const model = await loadAndZoomToModelAsync( { gltf: triangleFanUrl, enableDebugWireframe: true }, scene - ).then(function (model) { - verifyDebugWireframe(model, PrimitiveType.TRIANGLE_FAN); - }); + ); + verifyDebugWireframe(model, PrimitiveType.TRIANGLE_FAN); }); - it("debugWireframe ignores points", function () { - return loadAndZoomToModelAsync( + it("debugWireframe ignores points", async function () { + const model = await loadAndZoomToModelAsync( { gltf: pointCloudUrl, enableDebugWireframe: true }, scene - ).then(function (model) { - let i; - scene.renderForSpecs(); - const commandList = scene.frameState.commandList; - for (i = 0; i < commandList.length; i++) { - const command = commandList[i]; - expect(command.primitiveType).toBe(PrimitiveType.POINTS); - expect(command.vertexArray.indexBuffer).toBeUndefined(); - } + ); + scene.renderForSpecs(); + const commandList = scene.frameState.commandList; + for (let i = 0; i < commandList.length; i++) { + const command = commandList[i]; + expect(command.primitiveType).toBe(PrimitiveType.POINTS); + expect(command.vertexArray.indexBuffer).toBeUndefined(); + } - model.debugWireframe = true; - for (i = 0; i < commandList.length; i++) { - const command = commandList[i]; - expect(command.primitiveType).toBe(PrimitiveType.POINTS); - expect(command.vertexArray.indexBuffer).toBeUndefined(); - } - }); + model.debugWireframe = true; + for (let i = 0; i < commandList.length; i++) { + const command = commandList[i]; + expect(command.primitiveType).toBe(PrimitiveType.POINTS); + expect(command.vertexArray.indexBuffer).toBeUndefined(); + } }); }); - it("debugShowBoundingVolume works", function () { + it("debugShowBoundingVolume works", async function () { const resource = Resource.createIfNeeded(boxTexturedGlbUrl); - const loadPromise = resource.fetchArrayBuffer(); - return loadPromise.then(function (buffer) { - return loadAndZoomToModelAsync( - { gltf: new Uint8Array(buffer), debugShowBoundingVolume: true }, - scene - ).then(function (model) { - let i; - scene.renderForSpecs(); - const commandList = scene.frameState.commandList; - for (i = 0; i < commandList.length; i++) { - expect(commandList[i].debugShowBoundingVolume).toBe(true); - } - model.debugShowBoundingVolume = false; - expect(model._debugShowBoundingVolumeDirty).toBe(true); - scene.renderForSpecs(); - for (i = 0; i < commandList.length; i++) { - expect(commandList[i].debugShowBoundingVolume).toBe(false); - } - }); - }); + const buffer = await resource.fetchArrayBuffer(); + const model = await loadAndZoomToModelAsync( + { gltf: new Uint8Array(buffer), debugShowBoundingVolume: true }, + scene + ); + scene.renderForSpecs(); + const commandList = scene.frameState.commandList; + for (let i = 0; i < commandList.length; i++) { + expect(commandList[i].debugShowBoundingVolume).toBe(true); + } + model.debugShowBoundingVolume = false; + expect(model._debugShowBoundingVolumeDirty).toBe(true); + scene.renderForSpecs(); + for (let i = 0; i < commandList.length; i++) { + expect(commandList[i].debugShowBoundingVolume).toBe(false); + } }); describe("boundingSphere", function () { @@ -1747,133 +1686,123 @@ describe( }).toThrowDeveloperError(); }); - it("boundingSphere works", function () { + it("boundingSphere works", async function () { const resource = Resource.createIfNeeded(boxTexturedGlbUrl); - const loadPromise = resource.fetchArrayBuffer(); - return loadPromise.then(function (buffer) { - return loadAndZoomToModelAsync( - { gltf: new Uint8Array(buffer) }, - scene - ).then(function (model) { - const boundingSphere = model.boundingSphere; - expect(boundingSphere).toBeDefined(); - expect(boundingSphere.center).toEqual(new Cartesian3()); - expect(boundingSphere.radius).toEqualEpsilon( - 0.8660254037844386, - CesiumMath.EPSILON8 - ); - }); - }); + const buffer = await resource.fetchArrayBuffer(); + const model = await loadAndZoomToModelAsync( + { gltf: new Uint8Array(buffer) }, + scene + ); + const boundingSphere = model.boundingSphere; + expect(boundingSphere).toBeDefined(); + expect(boundingSphere.center).toEqual(new Cartesian3()); + expect(boundingSphere.radius).toEqualEpsilon( + 0.8660254037844386, + CesiumMath.EPSILON8 + ); }); - it("boundingSphere accounts for axis correction", function () { + it("boundingSphere accounts for axis correction", async function () { const resource = Resource.createIfNeeded(riggedFigureUrl); - return resource.fetchJson().then(function (gltf) { - return loadAndZoomToModelAsync({ gltf: gltf }, scene).then(function ( - model - ) { - // The bounding sphere should transform from z-forward - // to x-forward. - const boundingSphere = model.boundingSphere; - expect(boundingSphere).toBeDefined(); - expect(boundingSphere.center).toEqualEpsilon( - new Cartesian3(0.0320296511054039, 0, 0.7249599695205688), - CesiumMath.EPSILON3 - ); - expect(boundingSphere.radius).toEqualEpsilon( - 0.9484635280120018, - CesiumMath.EPSILON3 - ); - }); - }); + const gltf = await resource.fetchJson(); + const model = await loadAndZoomToModelAsync({ gltf: gltf }, scene); + // The bounding sphere should transform from z-forward + // to x-forward. + const boundingSphere = model.boundingSphere; + expect(boundingSphere).toBeDefined(); + expect(boundingSphere.center).toEqualEpsilon( + new Cartesian3(0.0320296511054039, 0, 0.7249599695205688), + CesiumMath.EPSILON3 + ); + expect(boundingSphere.radius).toEqualEpsilon( + 0.9484635280120018, + CesiumMath.EPSILON3 + ); }); - it("boundingSphere accounts for transform from CESIUM_RTC extension", function () { - return loadAndZoomToModelAsync( + it("boundingSphere accounts for transform from CESIUM_RTC extension", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxCesiumRtcUrl, }, scene - ).then(function (model) { - const boundingSphere = model.boundingSphere; - expect(boundingSphere).toBeDefined(); - expect(boundingSphere.center).toEqual(new Cartesian3(6378137, 0, 0)); - }); + ); + const boundingSphere = model.boundingSphere; + expect(boundingSphere).toBeDefined(); + expect(boundingSphere.center).toEqual(new Cartesian3(6378137, 0, 0)); }); - it("boundingSphere updates bounding sphere when invoked", function () { - return loadAndZoomToModelAsync({ gltf: boxTexturedGlbUrl }, scene).then( - function (model) { - const expectedRadius = 0.8660254037844386; - const translation = new Cartesian3(10, 0, 0); - const modelMatrix = Matrix4.fromTranslation(translation); - model.modelMatrix = modelMatrix; - model.scale = 2.0; - - // boundingSphere should still account for the model matrix - // even though the scene has not yet updated. - const boundingSphere = model.boundingSphere; - expect(boundingSphere.center).toEqual(translation); - expect(boundingSphere.radius).toEqualEpsilon( - 2.0 * expectedRadius, - CesiumMath.EPSILON8 - ); - } + it("boundingSphere updates bounding sphere when invoked", async function () { + const model = await loadAndZoomToModelAsync( + { gltf: boxTexturedGlbUrl }, + scene + ); + const expectedRadius = 0.8660254037844386; + const translation = new Cartesian3(10, 0, 0); + const modelMatrix = Matrix4.fromTranslation(translation); + model.modelMatrix = modelMatrix; + model.scale = 2.0; + + // boundingSphere should still account for the model matrix + // even though the scene has not yet updated. + const boundingSphere = model.boundingSphere; + expect(boundingSphere.center).toEqual(translation); + expect(boundingSphere.radius).toEqualEpsilon( + 2.0 * expectedRadius, + CesiumMath.EPSILON8 ); }); }); describe("picking and id", function () { - it("initializes with id", function () { + it("initializes with id", async function () { // This model gets clipped if log depth is disabled, so zoom out // the camera just a little const offset = new HeadingPitchRange(0, -CesiumMath.PI_OVER_FOUR, 2); - return loadAndZoomToModelAsync( + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGlbUrl, offset: offset, id: boxTexturedGlbUrl, }, scene - ).then(function (model) { - expect(model.id).toBe(boxTexturedGlbUrl); + ); + expect(model.id).toBe(boxTexturedGlbUrl); - const pickIds = model._pickIds; - expect(pickIds.length).toEqual(1); - expect(pickIds[0].object.id).toEqual(boxTexturedGlbUrl); - }); + const pickIds = model._pickIds; + expect(pickIds.length).toEqual(1); + expect(pickIds[0].object.id).toEqual(boxTexturedGlbUrl); }); - it("changing id works", function () { + it("changing id works", async function () { // This model gets clipped if log depth is disabled, so zoom out // the camera just a little const offset = new HeadingPitchRange(0, -CesiumMath.PI_OVER_FOUR, 2); - return loadAndZoomToModelAsync( + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGlbUrl, offset: offset, }, scene - ).then(function (model) { - expect(model.id).toBeUndefined(); + ); + expect(model.id).toBeUndefined(); - const pickIds = model._pickIds; - expect(pickIds.length).toEqual(1); - expect(pickIds[0].object.id).toBeUndefined(); + const pickIds = model._pickIds; + expect(pickIds.length).toEqual(1); + expect(pickIds[0].object.id).toBeUndefined(); - model.id = boxTexturedGlbUrl; - scene.renderForSpecs(); - expect(pickIds[0].object.id).toBe(boxTexturedGlbUrl); + model.id = boxTexturedGlbUrl; + scene.renderForSpecs(); + expect(pickIds[0].object.id).toBe(boxTexturedGlbUrl); - model.id = undefined; - scene.renderForSpecs(); - expect(pickIds[0].object.id).toBeUndefined(); - }); + model.id = undefined; + scene.renderForSpecs(); + expect(pickIds[0].object.id).toBeUndefined(); }); - it("picks box textured", function () { + it("picks box textured", async function () { if (FeatureDetection.isInternetExplorer()) { // Workaround IE 11.0.9. This test fails when all tests are ran without a breakpoint here. return; @@ -1883,21 +1812,20 @@ describe( // the camera just a little const offset = new HeadingPitchRange(0, -CesiumMath.PI_OVER_FOUR, 2); - return loadAndZoomToModelAsync( + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGlbUrl, offset: offset, }, scene - ).then(function (model) { - expect(scene).toPickAndCall(function (result) { - expect(result.primitive).toBeInstanceOf(Model); - expect(result.primitive).toEqual(model); - }); + ); + expect(scene).toPickAndCall(function (result) { + expect(result.primitive).toBeInstanceOf(Model); + expect(result.primitive).toEqual(model); }); }); - it("picks box textured with id", function () { + it("picks box textured with id", async function () { if (FeatureDetection.isInternetExplorer()) { // Workaround IE 11.0.9. This test fails when all tests are ran without a breakpoint here. return; @@ -1907,23 +1835,22 @@ describe( // the camera just a little const offset = new HeadingPitchRange(0, -CesiumMath.PI_OVER_FOUR, 2); - return loadAndZoomToModelAsync( + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGlbUrl, offset: offset, id: boxTexturedGlbUrl, }, scene - ).then(function (model) { - expect(scene).toPickAndCall(function (result) { - expect(result.primitive).toBeInstanceOf(Model); - expect(result.primitive).toEqual(model); - expect(result.id).toEqual(boxTexturedGlbUrl); - }); + ); + expect(scene).toPickAndCall(function (result) { + expect(result.primitive).toBeInstanceOf(Model); + expect(result.primitive).toEqual(model); + expect(result.id).toEqual(boxTexturedGlbUrl); }); }); - it("picks box textured with a new id", function () { + it("picks box textured with a new id", async function () { if (FeatureDetection.isInternetExplorer()) { // Workaround IE 11.0.9. This test fails when all tests are ran without a breakpoint here. return; @@ -1933,30 +1860,29 @@ describe( // the camera just a little const offset = new HeadingPitchRange(0, -CesiumMath.PI_OVER_FOUR, 2); - return loadAndZoomToModelAsync( + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGlbUrl, offset: offset, id: boxTexturedGlbUrl, }, scene - ).then(function (model) { - expect(scene).toPickAndCall(function (result) { - expect(result.primitive).toBeInstanceOf(Model); - expect(result.primitive).toEqual(model); - expect(result.id).toEqual(boxTexturedGlbUrl); - }); - - model.id = "new id"; - expect(scene).toPickAndCall(function (result) { - expect(result.primitive).toBeInstanceOf(Model); - expect(result.primitive).toEqual(model); - expect(result.id).toEqual("new id"); - }); + ); + expect(scene).toPickAndCall(function (result) { + expect(result.primitive).toBeInstanceOf(Model); + expect(result.primitive).toEqual(model); + expect(result.id).toEqual(boxTexturedGlbUrl); + }); + + model.id = "new id"; + expect(scene).toPickAndCall(function (result) { + expect(result.primitive).toBeInstanceOf(Model); + expect(result.primitive).toEqual(model); + expect(result.id).toEqual("new id"); }); }); - it("doesn't pick when allowPicking is false", function () { + it("doesn't pick when allowPicking is false", async function () { if (FeatureDetection.isInternetExplorer()) { // Workaround IE 11.0.9. This test fails when all tests are ran without a breakpoint here. return; @@ -1966,21 +1892,20 @@ describe( // the camera just a little const offset = new HeadingPitchRange(0, -CesiumMath.PI_OVER_FOUR, 2); - return loadAndZoomToModelAsync( + await loadAndZoomToModelAsync( { gltf: boxTexturedGlbUrl, allowPicking: false, offset: offset, }, scene - ).then(function () { - expect(scene).toPickAndCall(function (result) { - expect(result).toBeUndefined(); - }); + ); + expect(scene).toPickAndCall(function (result) { + expect(result).toBeUndefined(); }); }); - it("doesn't pick when model is hidden", function () { + it("doesn't pick when model is hidden", async function () { if (FeatureDetection.isInternetExplorer()) { // Workaround IE 11.0.9. This test fails when all tests are ran without a breakpoint here. return; @@ -1990,17 +1915,16 @@ describe( // the camera just a little const offset = new HeadingPitchRange(0, -CesiumMath.PI_OVER_FOUR, 2); - return loadAndZoomToModelAsync( + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGlbUrl, offset: offset, }, scene - ).then(function (model) { - model.show = false; - expect(scene).toPickAndCall(function (result) { - expect(result).toBeUndefined(); - }); + ); + model.show = false; + expect(scene).toPickAndCall(function (result) { + expect(result).toBeUndefined(); }); }); }); @@ -2011,141 +1935,134 @@ describe( opaqueFeaturesLength, translucentFeaturesLength ) { - let i, feature; - for (i = 0; i < opaqueFeaturesLength; i++) { - feature = featureTable.getFeature(i); + for (let i = 0; i < opaqueFeaturesLength; i++) { + const feature = featureTable.getFeature(i); feature.color = Color.RED; } for ( - i = opaqueFeaturesLength; + let i = opaqueFeaturesLength; i < opaqueFeaturesLength + translucentFeaturesLength; i++ ) { - feature = featureTable.getFeature(i); + const feature = featureTable.getFeature(i); feature.color = Color.RED.withAlpha(0.5); } } - it("resets draw commands when the style commands needed are changed", function () { - return loadAndZoomToModelAsync( + it("resets draw commands when the style commands needed are changed", async function () { + const model = await loadAndZoomToModelAsync( { gltf: buildingsMetadata, }, scene - ).then(function (model) { - const featureTable = model.featureTables[model.featureTableId]; - - // Set all features to opaque. - setFeaturesWithOpacity(featureTable, 10, 0); - scene.renderForSpecs(); - expect(featureTable.styleCommandsNeededDirty).toEqual(false); - expect(featureTable._styleCommandsNeeded).toEqual( - StyleCommandsNeeded.ALL_OPAQUE - ); + ); + const featureTable = model.featureTables[model.featureTableId]; - // Set some features to translucent. - setFeaturesWithOpacity(featureTable, 8, 2); - scene.renderForSpecs(); - expect(featureTable.styleCommandsNeededDirty).toEqual(true); - expect(featureTable._styleCommandsNeeded).toEqual( - StyleCommandsNeeded.OPAQUE_AND_TRANSLUCENT - ); + // Set all features to opaque. + setFeaturesWithOpacity(featureTable, 10, 0); + scene.renderForSpecs(); + expect(featureTable.styleCommandsNeededDirty).toEqual(false); + expect(featureTable._styleCommandsNeeded).toEqual( + StyleCommandsNeeded.ALL_OPAQUE + ); - // Set some more features to translucent. - setFeaturesWithOpacity(featureTable, 2, 8); - scene.renderForSpecs(); - expect(featureTable.styleCommandsNeededDirty).toEqual(false); - expect(featureTable._styleCommandsNeeded).toEqual( - StyleCommandsNeeded.OPAQUE_AND_TRANSLUCENT - ); + // Set some features to translucent. + setFeaturesWithOpacity(featureTable, 8, 2); + scene.renderForSpecs(); + expect(featureTable.styleCommandsNeededDirty).toEqual(true); + expect(featureTable._styleCommandsNeeded).toEqual( + StyleCommandsNeeded.OPAQUE_AND_TRANSLUCENT + ); - // Set all features to translucent. - setFeaturesWithOpacity(featureTable, 0, 10); - scene.renderForSpecs(); - expect(featureTable.styleCommandsNeededDirty).toEqual(true); - expect(featureTable._styleCommandsNeeded).toEqual( - StyleCommandsNeeded.ALL_TRANSLUCENT - ); - }); + // Set some more features to translucent. + setFeaturesWithOpacity(featureTable, 2, 8); + scene.renderForSpecs(); + expect(featureTable.styleCommandsNeededDirty).toEqual(false); + expect(featureTable._styleCommandsNeeded).toEqual( + StyleCommandsNeeded.OPAQUE_AND_TRANSLUCENT + ); + + // Set all features to translucent. + setFeaturesWithOpacity(featureTable, 0, 10); + scene.renderForSpecs(); + expect(featureTable.styleCommandsNeededDirty).toEqual(true); + expect(featureTable._styleCommandsNeeded).toEqual( + StyleCommandsNeeded.ALL_TRANSLUCENT + ); }); - it("selects feature table for instanced feature ID attributes", function () { + it("selects feature table for instanced feature ID attributes", async function () { if (webglStub) { return; } - return loadAndZoomToModelAsync( + const model = await loadAndZoomToModelAsync( { gltf: boxInstanced, instanceFeatureIdLabel: "section", }, scene - ).then(function (model) { - expect(model.featureTableId).toEqual(1); - }); + ); + expect(model.featureTableId).toEqual(1); }); - it("selects feature table for feature ID textures", function () { - return loadAndZoomToModelAsync( + it("selects feature table for feature ID textures", async function () { + const model = await loadAndZoomToModelAsync( { gltf: microcosm, }, scene - ).then(function (model) { - expect(model.featureTableId).toEqual(0); - }); + ); + expect(model.featureTableId).toEqual(0); }); - it("selects feature table for feature ID attributes", function () { - return loadAndZoomToModelAsync( + it("selects feature table for feature ID attributes", async function () { + const model = await loadAndZoomToModelAsync( { gltf: buildingsMetadata, }, scene - ).then(function (model) { - expect(model.featureTableId).toEqual(0); - }); + ); + expect(model.featureTableId).toEqual(0); }); - it("featureIdLabel setter works", function () { - return loadAndZoomToModelAsync( + it("featureIdLabel setter works", async function () { + const model = await loadAndZoomToModelAsync( { gltf: buildingsMetadata, }, scene - ).then(function (model) { - expect(model.featureIdLabel).toBe("featureId_0"); - model.featureIdLabel = "buildings"; - expect(model.featureIdLabel).toBe("buildings"); - model.featureIdLabel = 1; - expect(model.featureIdLabel).toBe("featureId_1"); - }); + ); + expect(model.featureIdLabel).toBe("featureId_0"); + model.featureIdLabel = "buildings"; + expect(model.featureIdLabel).toBe("buildings"); + model.featureIdLabel = 1; + expect(model.featureIdLabel).toBe("featureId_1"); }); - it("instanceFeatureIdLabel setter works", function () { + it("instanceFeatureIdLabel setter works", async function () { if (webglStub) { return; } - return loadAndZoomToModelAsync( + const model = await loadAndZoomToModelAsync( { gltf: boxInstanced, }, scene - ).then(function (model) { - expect(model.instanceFeatureIdLabel).toBe("instanceFeatureId_0"); - model.instanceFeatureIdLabel = "section"; - expect(model.instanceFeatureIdLabel).toBe("section"); - model.instanceFeatureIdLabel = 1; - expect(model.instanceFeatureIdLabel).toBe("instanceFeatureId_1"); - }); + ); + expect(model.instanceFeatureIdLabel).toBe("instanceFeatureId_0"); + model.instanceFeatureIdLabel = "section"; + expect(model.instanceFeatureIdLabel).toBe("section"); + model.instanceFeatureIdLabel = 1; + expect(model.instanceFeatureIdLabel).toBe("instanceFeatureId_1"); }); }); describe("model matrix", function () { - it("initializes with model matrix", function () { + it("initializes with model matrix", async function () { const translation = new Cartesian3(10, 0, 0); const transform = Matrix4.fromTranslation(translation); - return loadAndZoomToModelAsync( + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGlbUrl, upAxis: Axis.Z, @@ -2153,106 +2070,99 @@ describe( modelMatrix: transform, }, scene - ).then(function (model) { - const sceneGraph = model.sceneGraph; - scene.renderForSpecs(); - expect(sceneGraph.computedModelMatrix).toEqual(transform); - expect(model.boundingSphere.center).toEqual(translation); - verifyRender(model, true); + ); + const sceneGraph = model.sceneGraph; + scene.renderForSpecs(); + expect(sceneGraph.computedModelMatrix).toEqual(transform); + expect(model.boundingSphere.center).toEqual(translation); + verifyRender(model, true); - expect(sceneGraph.computedModelMatrix).not.toBe(transform); - expect(model.modelMatrix).not.toBe(transform); - }); + expect(sceneGraph.computedModelMatrix).not.toBe(transform); + expect(model.modelMatrix).not.toBe(transform); }); - it("changing model matrix works", function () { + it("changing model matrix works", async function () { const translation = new Cartesian3(10, 0, 0); const updateModelMatrix = spyOn( ModelSceneGraph.prototype, "updateModelMatrix" ).and.callThrough(); - return loadAndZoomToModelAsync( + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGlbUrl, upAxis: Axis.Z, forwardAxis: Axis.X }, scene - ).then(function (model) { - verifyRender(model, true); - const sceneGraph = model.sceneGraph; + ); + verifyRender(model, true); + const sceneGraph = model.sceneGraph; - const transform = Matrix4.fromTranslation(translation); - Matrix4.multiplyTransformation( - model.modelMatrix, - transform, - model.modelMatrix - ); - scene.renderForSpecs(); + const transform = Matrix4.fromTranslation(translation); + Matrix4.multiplyTransformation( + model.modelMatrix, + transform, + model.modelMatrix + ); + scene.renderForSpecs(); - expect(updateModelMatrix).toHaveBeenCalled(); - expect(sceneGraph.computedModelMatrix).toEqual(transform); + expect(updateModelMatrix).toHaveBeenCalled(); + expect(sceneGraph.computedModelMatrix).toEqual(transform); - // Keep the camera in-place to confirm that the model matrix moves the model out of view. - verifyRender(model, false, { - zoomToModel: false, - }); + // Keep the camera in-place to confirm that the model matrix moves the model out of view. + verifyRender(model, false, { + zoomToModel: false, }); }); - it("changing model matrix affects bounding sphere", function () { + it("changing model matrix affects bounding sphere", async function () { const translation = new Cartesian3(10, 0, 0); - return loadAndZoomToModelAsync( + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGlbUrl, upAxis: Axis.Z, forwardAxis: Axis.X }, scene - ).then(function (model) { - const transform = Matrix4.fromTranslation(translation); - expect(model.boundingSphere.center).toEqual(Cartesian3.ZERO); + ); + const transform = Matrix4.fromTranslation(translation); + expect(model.boundingSphere.center).toEqual(Cartesian3.ZERO); - Matrix4.multiplyTransformation( - model.modelMatrix, - transform, - model.modelMatrix - ); - scene.renderForSpecs(); + Matrix4.multiplyTransformation( + model.modelMatrix, + transform, + model.modelMatrix + ); + scene.renderForSpecs(); - expect(model.boundingSphere.center).toEqual(translation); - }); + expect(model.boundingSphere.center).toEqual(translation); }); - it("changing model matrix in 2D mode works if projectTo2D is false", function () { - return loadAndZoomToModelAsync( + it("changing model matrix in 2D mode works if projectTo2D is false", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGlbUrl, modelMatrix: modelMatrix, }, scene2D - ).then(function (model) { - verifyRender(model, true, { - zoomToModel: false, - scene: scene2D, - }); - - model.modelMatrix = Matrix4.fromTranslation( - new Cartesian3(10, 10, 10) - ); - verifyRender(model, false, { - zoomToModel: false, - scene: scene2D, - }); + ); + verifyRender(model, true, { + zoomToModel: false, + scene: scene2D, + }); + + model.modelMatrix = Matrix4.fromTranslation(new Cartesian3(10, 10, 10)); + verifyRender(model, false, { + zoomToModel: false, + scene: scene2D, }); }); - it("changing model matrix in 2D mode throws if projectTo2D is true", function () { - return loadAndZoomToModelAsync( + it("changing model matrix in 2D mode throws if projectTo2D is true", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGlbUrl, modelMatrix: modelMatrix, projectTo2D: true, }, scene2D - ).then(function (model) { - expect(function () { - model.modelMatrix = Matrix4.IDENTITY; - scene2D.renderForSpecs(); - }).toThrowDeveloperError(); - }); + ); + expect(function () { + model.modelMatrix = Matrix4.IDENTITY; + scene2D.renderForSpecs(); + }).toThrowDeveloperError(); }); }); @@ -2605,175 +2515,167 @@ describe( }); describe("distance display condition", function () { - it("initializes with distance display condition", function () { + it("initializes with distance display condition", async function () { const near = 10.0; const far = 100.0; const condition = new DistanceDisplayCondition(near, far); - return loadAndZoomToModelAsync( + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl, distanceDisplayCondition: condition, }, scene - ).then(function (model) { - verifyRender(model, false); - }); + ); + verifyRender(model, false); }); - it("changing distance display condition works", function () { + it("changing distance display condition works", async function () { const near = 10.0; const far = 100.0; const condition = new DistanceDisplayCondition(near, far); - return loadAndZoomToModelAsync( + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl, }, scene - ).then(function (model) { - verifyRender(model, true); + ); + verifyRender(model, true); - model.distanceDisplayCondition = condition; - verifyRender(model, false); + model.distanceDisplayCondition = condition; + verifyRender(model, false); - model.distanceDisplayCondition = undefined; - verifyRender(model, true); - }); + model.distanceDisplayCondition = undefined; + verifyRender(model, true); }); - it("distanceDisplayCondition works with camera movement", function () { + it("distanceDisplayCondition works with camera movement", async function () { const near = 10.0; const far = 100.0; const condition = new DistanceDisplayCondition(near, far); - return loadAndZoomToModelAsync( + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl, }, scene - ).then(function (model) { - verifyRender(model, true); + ); + verifyRender(model, true); - // Model distance is smaller than near value, should not render - model.distanceDisplayCondition = condition; - verifyRender(model, false); + // Model distance is smaller than near value, should not render + model.distanceDisplayCondition = condition; + verifyRender(model, false); - const frameState = scene.frameState; + const frameState = scene.frameState; - // Model distance is between near and far values, should render - frameState.camera.lookAt( - Cartesian3.ZERO, - new HeadingPitchRange(0.0, 0.0, (far + near) * 0.5) - ); - verifyRender(model, true, { - zoomToModel: false, - }); - - // Model distance is greater than far value, should not render - frameState.camera.lookAt( - Cartesian3.ZERO, - new HeadingPitchRange(0.0, 0.0, far + 10.0) - ); - verifyRender(model, false, { - zoomToModel: false, - }); + // Model distance is between near and far values, should render + frameState.camera.lookAt( + Cartesian3.ZERO, + new HeadingPitchRange(0.0, 0.0, (far + near) * 0.5) + ); + verifyRender(model, true, { + zoomToModel: false, + }); + + // Model distance is greater than far value, should not render + frameState.camera.lookAt( + Cartesian3.ZERO, + new HeadingPitchRange(0.0, 0.0, far + 10.0) + ); + verifyRender(model, false, { + zoomToModel: false, }); }); - it("distanceDisplayCondition throws when near >= far", function () { + it("distanceDisplayCondition throws when near >= far", async function () { const near = 101.0; const far = 100.0; const condition = new DistanceDisplayCondition(near, far); - return loadAndZoomToModelAsync( + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl, }, scene - ).then(function (model) { - expect(function () { - model.distanceDisplayCondition = condition; - }).toThrowDeveloperError(); - }); + ); + expect(function () { + model.distanceDisplayCondition = condition; + }).toThrowDeveloperError(); }); }); describe("model color", function () { - it("initializes with model color", function () { - return loadAndZoomToModelAsync( + it("initializes with model color", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl, color: Color.BLACK }, scene - ).then(function (model) { - verifyRender(model, false); - }); + ); + verifyRender(model, false); }); - it("changing model color works", function () { - return loadAndZoomToModelAsync( + it("changing model color works", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl }, scene - ).then(function (model) { - verifyRender(model, true); + ); + verifyRender(model, true); - model.color = Color.BLACK; - verifyRender(model, false); + model.color = Color.BLACK; + verifyRender(model, false); - model.color = Color.RED; - verifyRender(model, true); + model.color = Color.RED; + verifyRender(model, true); - model.color = undefined; - verifyRender(model, true); - }); + model.color = undefined; + verifyRender(model, true); }); - it("renders with translucent color", function () { + it("renders with translucent color", async function () { // This model gets clipped if log depth is disabled, so zoom out // the camera just a little const offset = new HeadingPitchRange(0, -CesiumMath.PI_OVER_FOUR, 2); - return loadAndZoomToModelAsync( + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl, offset: offset, }, scene - ).then(function (model) { - const renderOptions = { - scene: scene, - time: defaultDate, - }; - - let result; - expect(renderOptions).toRenderAndCall(function (rgba) { - result = rgba; - }); - - model.color = Color.fromAlpha(Color.WHITE, 0.5); - expect(renderOptions).toRenderAndCall(function (rgba) { - expect(rgba[0]).toBeLessThan(result[0]); - expect(rgba[1]).toBeLessThan(result[1]); - expect(rgba[2]).toBeLessThan(result[2]); - expect(rgba[3]).toBe(255); - }); + ); + const renderOptions = { + scene: scene, + time: defaultDate, + }; + + let result; + expect(renderOptions).toRenderAndCall(function (rgba) { + result = rgba; + }); + + model.color = Color.fromAlpha(Color.WHITE, 0.5); + expect(renderOptions).toRenderAndCall(function (rgba) { + expect(rgba[0]).toBeLessThan(result[0]); + expect(rgba[1]).toBeLessThan(result[1]); + expect(rgba[2]).toBeLessThan(result[2]); + expect(rgba[3]).toBe(255); }); }); - it("doesn't render invisible model", function () { + it("doesn't render invisible model", async function () { // This model gets clipped if log depth is disabled, so zoom out // the camera just a little const offset = new HeadingPitchRange(0, -CesiumMath.PI_OVER_FOUR, 2); - return loadAndZoomToModelAsync( + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl, color: Color.fromAlpha(Color.BLACK, 0.0), offset: offset, }, scene - ).then(function (model) { - verifyRender(model, false); + ); + verifyRender(model, false); - // No commands should have been submitted - const commands = scene.frameState.commandList; - expect(commands.length).toBe(0); - }); + // No commands should have been submitted + const commands = scene.frameState.commandList; + expect(commands.length).toBe(0); }); }); @@ -2809,8 +2711,8 @@ describe( // the camera just a little const offset = new HeadingPitchRange(0, -CesiumMath.PI_OVER_FOUR, 2); - it("initializes with ColorBlendMode.HIGHLIGHT", function () { - return loadAndZoomToModelAsync( + it("initializes with ColorBlendMode.HIGHLIGHT", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl, offset: offset, @@ -2818,21 +2720,20 @@ describe( colorBlendMode: ColorBlendMode.HIGHLIGHT, }, scene - ).then(function (model) { - expect(model.colorBlendMode).toEqual(ColorBlendMode.HIGHLIGHT); + ); + expect(model.colorBlendMode).toEqual(ColorBlendMode.HIGHLIGHT); - const renderOptions = { - scene: scene, - time: defaultDate, - }; - expect(renderOptions).toRenderAndCall(function (rgba) { - verifyHighlightColor(rgba); - }); + const renderOptions = { + scene: scene, + time: defaultDate, + }; + expect(renderOptions).toRenderAndCall(function (rgba) { + verifyHighlightColor(rgba); }); }); - it("initializes with ColorBlendMode.REPLACE", function () { - return loadAndZoomToModelAsync( + it("initializes with ColorBlendMode.REPLACE", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl, offset: offset, @@ -2840,21 +2741,20 @@ describe( colorBlendMode: ColorBlendMode.REPLACE, }, scene - ).then(function (model) { - expect(model.colorBlendMode).toEqual(ColorBlendMode.REPLACE); + ); + expect(model.colorBlendMode).toEqual(ColorBlendMode.REPLACE); - const renderOptions = { - scene: scene, - time: defaultDate, - }; - expect(renderOptions).toRenderAndCall(function (rgba) { - verifyReplaceColor(rgba); - }); + const renderOptions = { + scene: scene, + time: defaultDate, + }; + expect(renderOptions).toRenderAndCall(function (rgba) { + verifyReplaceColor(rgba); }); }); - it("initializes with ColorBlendMode.MIX", function () { - return loadAndZoomToModelAsync( + it("initializes with ColorBlendMode.MIX", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl, offset: offset, @@ -2862,21 +2762,20 @@ describe( colorBlendMode: ColorBlendMode.MIX, }, scene - ).then(function (model) { - expect(model.colorBlendMode).toEqual(ColorBlendMode.MIX); + ); + expect(model.colorBlendMode).toEqual(ColorBlendMode.MIX); - const renderOptions = { - scene: scene, - time: defaultDate, - }; - expect(renderOptions).toRenderAndCall(function (rgba) { - verifyMixColor(rgba); - }); + const renderOptions = { + scene: scene, + time: defaultDate, + }; + expect(renderOptions).toRenderAndCall(function (rgba) { + verifyMixColor(rgba); }); }); - it("toggles colorBlendMode", function () { - return loadAndZoomToModelAsync( + it("toggles colorBlendMode", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl, offset: offset, @@ -2884,30 +2783,29 @@ describe( colorBlendMode: ColorBlendMode.REPLACE, }, scene - ).then(function (model) { - expect(model.colorBlendMode).toEqual(ColorBlendMode.REPLACE); + ); + expect(model.colorBlendMode).toEqual(ColorBlendMode.REPLACE); - const renderOptions = { - scene: scene, - time: defaultDate, - }; - expect(renderOptions).toRenderAndCall(function (rgba) { - verifyReplaceColor(rgba); - }); + const renderOptions = { + scene: scene, + time: defaultDate, + }; + expect(renderOptions).toRenderAndCall(function (rgba) { + verifyReplaceColor(rgba); + }); - model.colorBlendMode = ColorBlendMode.HIGHLIGHT; - expect(model.colorBlendMode).toEqual(ColorBlendMode.HIGHLIGHT); + model.colorBlendMode = ColorBlendMode.HIGHLIGHT; + expect(model.colorBlendMode).toEqual(ColorBlendMode.HIGHLIGHT); - expect(renderOptions).toRenderAndCall(function (rgba) { - verifyHighlightColor(rgba); - }); + expect(renderOptions).toRenderAndCall(function (rgba) { + verifyHighlightColor(rgba); + }); - model.colorBlendMode = ColorBlendMode.MIX; - expect(model.colorBlendMode).toEqual(ColorBlendMode.MIX); + model.colorBlendMode = ColorBlendMode.MIX; + expect(model.colorBlendMode).toEqual(ColorBlendMode.MIX); - expect(renderOptions).toRenderAndCall(function (rgba) { - verifyMixColor(rgba); - }); + expect(renderOptions).toRenderAndCall(function (rgba) { + verifyMixColor(rgba); }); }); }); @@ -2917,8 +2815,8 @@ describe( // the camera just a little const offset = new HeadingPitchRange(0, -CesiumMath.PI_OVER_FOUR, 2); - it("initializes with colorBlendAmount", function () { - return loadAndZoomToModelAsync( + it("initializes with colorBlendAmount", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl, offset: offset, @@ -2927,203 +2825,195 @@ describe( colorBlendAmount: 1.0, }, scene - ).then(function (model) { - expect(model.colorBlendAmount).toEqual(1.0); + ); + expect(model.colorBlendAmount).toEqual(1.0); - const renderOptions = { - scene: scene, - time: defaultDate, - }; - // colorBlendAmount = 1.0 is visually equivalent to - // ColorBlendMode.REPLACE - expect(renderOptions).toRenderAndCall(function (rgba) { - verifyReplaceColor(rgba); - }); + const renderOptions = { + scene: scene, + time: defaultDate, + }; + // colorBlendAmount = 1.0 is visually equivalent to + // ColorBlendMode.REPLACE + expect(renderOptions).toRenderAndCall(function (rgba) { + verifyReplaceColor(rgba); }); }); - it("changing colorBlendAmount works", function () { - return loadAndZoomToModelAsync( + it("changing colorBlendAmount works", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl, offset: offset, }, scene - ).then(function (model) { - const renderOptions = { - scene: scene, - time: defaultDate, - }; - - let originalColor; - expect(renderOptions).toRenderAndCall(function (rgba) { - originalColor = rgba; - }); - - model.color = Color.RED; - model.colorBlendMode = ColorBlendMode.MIX; - model.colorBlendAmount = 1.0; - expect(model.colorBlendAmount).toEqual(1.0); - - // colorBlendAmount = 1.0 is visually equivalent to - // ColorBlendMode.REPLACE - expect(renderOptions).toRenderAndCall(function (rgba) { - verifyReplaceColor(rgba); - }); - - model.colorBlendAmount = 0.5; - expect(model.colorBlendAmount).toEqual(0.5); - expect(renderOptions).toRenderAndCall(function (rgba) { - verifyMixColor(rgba); - }); - - model.colorBlendAmount = 0.0; - expect(model.colorBlendAmount).toEqual(0.0); - // colorBlendAmount = 0.0 is visually equivalent to - // having no color applied to the model. - expect(renderOptions).toRenderAndCall(function (rgba) { - expect(rgba[0]).toEqual(originalColor[0]); - expect(rgba[1]).toEqual(originalColor[1]); - expect(rgba[2]).toEqual(originalColor[2]); - expect(rgba[3]).toEqual(originalColor[3]); - }); + ); + const renderOptions = { + scene: scene, + time: defaultDate, + }; + + let originalColor; + expect(renderOptions).toRenderAndCall(function (rgba) { + originalColor = rgba; + }); + + model.color = Color.RED; + model.colorBlendMode = ColorBlendMode.MIX; + model.colorBlendAmount = 1.0; + expect(model.colorBlendAmount).toEqual(1.0); + + // colorBlendAmount = 1.0 is visually equivalent to + // ColorBlendMode.REPLACE + expect(renderOptions).toRenderAndCall(function (rgba) { + verifyReplaceColor(rgba); + }); + + model.colorBlendAmount = 0.5; + expect(model.colorBlendAmount).toEqual(0.5); + expect(renderOptions).toRenderAndCall(function (rgba) { + verifyMixColor(rgba); + }); + + model.colorBlendAmount = 0.0; + expect(model.colorBlendAmount).toEqual(0.0); + // colorBlendAmount = 0.0 is visually equivalent to + // having no color applied to the model. + expect(renderOptions).toRenderAndCall(function (rgba) { + expect(rgba[0]).toEqual(originalColor[0]); + expect(rgba[1]).toEqual(originalColor[1]); + expect(rgba[2]).toEqual(originalColor[2]); + expect(rgba[3]).toEqual(originalColor[3]); }); }); }); describe("silhouette", function () { - it("initializes with silhouette size", function () { - return loadAndZoomToModelAsync( + it("initializes with silhouette size", async function () { + await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl, silhouetteSize: 1.0 }, scene - ).then(function (model) { - const commands = scene.frameState.commandList; - scene.renderForSpecs(); - expect(commands.length).toBe(2); - expect(commands[0].renderState.stencilTest.enabled).toBe(true); - expect(commands[0].pass).toBe(Pass.OPAQUE); - expect(commands[1].renderState.stencilTest.enabled).toBe(true); - expect(commands[1].pass).toBe(Pass.OPAQUE); - }); + ); + const commands = scene.frameState.commandList; + scene.renderForSpecs(); + expect(commands.length).toBe(2); + expect(commands[0].renderState.stencilTest.enabled).toBe(true); + expect(commands[0].pass).toBe(Pass.OPAQUE); + expect(commands[1].renderState.stencilTest.enabled).toBe(true); + expect(commands[1].pass).toBe(Pass.OPAQUE); }); - it("changing silhouette size works", function () { - return loadAndZoomToModelAsync( + it("changing silhouette size works", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl }, scene - ).then(function (model) { - const commands = scene.frameState.commandList; - scene.renderForSpecs(); - expect(commands.length).toBe(1); - expect(commands[0].renderState.stencilTest.enabled).toBe(false); - expect(commands[0].pass).toBe(Pass.OPAQUE); + ); + const commands = scene.frameState.commandList; + scene.renderForSpecs(); + expect(commands.length).toBe(1); + expect(commands[0].renderState.stencilTest.enabled).toBe(false); + expect(commands[0].pass).toBe(Pass.OPAQUE); - model.silhouetteSize = 1.0; - scene.renderForSpecs(); - expect(commands.length).toBe(2); - expect(commands[0].renderState.stencilTest.enabled).toBe(true); - expect(commands[0].pass).toBe(Pass.OPAQUE); - expect(commands[1].renderState.stencilTest.enabled).toBe(true); - expect(commands[1].pass).toBe(Pass.OPAQUE); + model.silhouetteSize = 1.0; + scene.renderForSpecs(); + expect(commands.length).toBe(2); + expect(commands[0].renderState.stencilTest.enabled).toBe(true); + expect(commands[0].pass).toBe(Pass.OPAQUE); + expect(commands[1].renderState.stencilTest.enabled).toBe(true); + expect(commands[1].pass).toBe(Pass.OPAQUE); - model.silhouetteSize = 0.0; - scene.renderForSpecs(); - expect(commands.length).toBe(1); - expect(commands[0].renderState.stencilTest.enabled).toBe(false); - expect(commands[0].pass).toBe(Pass.OPAQUE); - }); + model.silhouetteSize = 0.0; + scene.renderForSpecs(); + expect(commands.length).toBe(1); + expect(commands[0].renderState.stencilTest.enabled).toBe(false); + expect(commands[0].pass).toBe(Pass.OPAQUE); }); - it("silhouette works with translucent color", function () { - return loadAndZoomToModelAsync( + it("silhouette works with translucent color", async function () { + await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl, silhouetteSize: 1.0, silhouetteColor: Color.fromAlpha(Color.GREEN, 0.5), }, scene - ).then(function (model) { - const commands = scene.frameState.commandList; - scene.renderForSpecs(); - expect(commands.length).toBe(2); - expect(commands[0].renderState.stencilTest.enabled).toBe(true); - expect(commands[0].pass).toBe(Pass.OPAQUE); - expect(commands[1].renderState.stencilTest.enabled).toBe(true); - expect(commands[1].pass).toBe(Pass.TRANSLUCENT); - }); + ); + const commands = scene.frameState.commandList; + scene.renderForSpecs(); + expect(commands.length).toBe(2); + expect(commands[0].renderState.stencilTest.enabled).toBe(true); + expect(commands[0].pass).toBe(Pass.OPAQUE); + expect(commands[1].renderState.stencilTest.enabled).toBe(true); + expect(commands[1].pass).toBe(Pass.TRANSLUCENT); }); - it("silhouette is disabled by invisible color", function () { - return loadAndZoomToModelAsync( + it("silhouette is disabled by invisible color", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl, silhouetteSize: 1.0 }, scene - ).then(function (model) { - const commands = scene.frameState.commandList; - scene.renderForSpecs(); - expect(commands.length).toBe(2); - expect(commands[0].renderState.stencilTest.enabled).toBe(true); - expect(commands[0].pass).toBe(Pass.OPAQUE); - expect(commands[1].renderState.stencilTest.enabled).toBe(true); - expect(commands[1].pass).toBe(Pass.OPAQUE); + ); + const commands = scene.frameState.commandList; + scene.renderForSpecs(); + expect(commands.length).toBe(2); + expect(commands[0].renderState.stencilTest.enabled).toBe(true); + expect(commands[0].pass).toBe(Pass.OPAQUE); + expect(commands[1].renderState.stencilTest.enabled).toBe(true); + expect(commands[1].pass).toBe(Pass.OPAQUE); - model.silhouetteColor = Color.fromAlpha(Color.GREEN, 0.0); - scene.renderForSpecs(); - expect(commands.length).toBe(1); - expect(commands[0].renderState.stencilTest.enabled).toBe(false); - expect(commands[0].pass).toBe(Pass.OPAQUE); - }); + model.silhouetteColor = Color.fromAlpha(Color.GREEN, 0.0); + scene.renderForSpecs(); + expect(commands.length).toBe(1); + expect(commands[0].renderState.stencilTest.enabled).toBe(false); + expect(commands[0].pass).toBe(Pass.OPAQUE); }); - it("silhouette works for invisible model", function () { - return loadAndZoomToModelAsync( + it("silhouette works for invisible model", async function () { + await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl, silhouetteSize: 1.0, color: Color.fromAlpha(Color.WHITE, 0.0), }, scene - ).then(function (model) { - const commands = scene.frameState.commandList; - scene.renderForSpecs(); - expect(commands.length).toBe(2); - expect(commands[0].renderState.colorMask).toEqual({ - red: false, - green: false, - blue: false, - alpha: false, - }); - expect(commands[0].renderState.depthMask).toEqual(false); - expect(commands[0].renderState.stencilTest.enabled).toBe(true); - expect(commands[0].pass).toBe(Pass.TRANSLUCENT); - expect(commands[1].renderState.stencilTest.enabled).toBe(true); - expect(commands[1].pass).toBe(Pass.TRANSLUCENT); - }); - }); - - it("silhouette works for translucent model", function () { - return loadAndZoomToModelAsync( + ); + const commands = scene.frameState.commandList; + scene.renderForSpecs(); + expect(commands.length).toBe(2); + expect(commands[0].renderState.colorMask).toEqual({ + red: false, + green: false, + blue: false, + alpha: false, + }); + expect(commands[0].renderState.depthMask).toEqual(false); + expect(commands[0].renderState.stencilTest.enabled).toBe(true); + expect(commands[0].pass).toBe(Pass.TRANSLUCENT); + expect(commands[1].renderState.stencilTest.enabled).toBe(true); + expect(commands[1].pass).toBe(Pass.TRANSLUCENT); + }); + + it("silhouette works for translucent model", async function () { + await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl, silhouetteSize: 1.0, color: Color.fromAlpha(Color.WHITE, 0.5), }, scene - ).then(function (model) { - const commands = scene.frameState.commandList; - scene.renderForSpecs(); - expect(commands.length).toBe(2); - - // Even though the silhouette color is opaque, the silhouette - // needs to be placed in the translucent pass. - expect(commands[0].renderState.stencilTest.enabled).toBe(true); - expect(commands[0].pass).toBe(Pass.TRANSLUCENT); - expect(commands[1].renderState.stencilTest.enabled).toBe(true); - expect(commands[1].pass).toBe(Pass.TRANSLUCENT); - }); + ); + const commands = scene.frameState.commandList; + scene.renderForSpecs(); + expect(commands.length).toBe(2); + + // Even though the silhouette color is opaque, the silhouette + // needs to be placed in the translucent pass. + expect(commands[0].renderState.stencilTest.enabled).toBe(true); + expect(commands[0].pass).toBe(Pass.TRANSLUCENT); + expect(commands[1].renderState.stencilTest.enabled).toBe(true); + expect(commands[1].pass).toBe(Pass.TRANSLUCENT); }); - it("silhouette works for translucent model and translucent silhouette color", function () { - return loadAndZoomToModelAsync( + it("silhouette works for translucent model and translucent silhouette color", async function () { + await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl, silhouetteSize: 1.0, @@ -3131,91 +3021,85 @@ describe( silhouetteColor: Color.fromAlpha(Color.RED, 0.5), }, scene - ).then(function (model) { - const commands = scene.frameState.commandList; - scene.renderForSpecs(); - expect(commands.length).toBe(2); + ); + const commands = scene.frameState.commandList; + scene.renderForSpecs(); + expect(commands.length).toBe(2); - expect(commands[0].renderState.stencilTest.enabled).toBe(true); - expect(commands[0].pass).toBe(Pass.TRANSLUCENT); - expect(commands[1].renderState.stencilTest.enabled).toBe(true); - expect(commands[1].pass).toBe(Pass.TRANSLUCENT); - }); + expect(commands[0].renderState.stencilTest.enabled).toBe(true); + expect(commands[0].pass).toBe(Pass.TRANSLUCENT); + expect(commands[1].renderState.stencilTest.enabled).toBe(true); + expect(commands[1].pass).toBe(Pass.TRANSLUCENT); }); - it("silhouette works for multiple models", function () { - return loadAndZoomToModelAsync( + it("silhouette works for multiple models", async function () { + await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl, silhouetteSize: 1.0, }, scene - ).then(function (model) { - return loadAndZoomToModelAsync( - { - gltf: boxTexturedGltfUrl, - silhouetteSize: 1.0, - }, - scene - ).then(function (model2) { - const commands = scene.frameState.commandList; - scene.renderForSpecs(); - const length = commands.length; - expect(length).toBe(4); - for (let i = 0; i < length; i++) { - const command = commands[i]; - expect(command.renderState.stencilTest.enabled).toBe(true); - expect(command.pass).toBe(Pass.OPAQUE); - } + ); + await loadAndZoomToModelAsync( + { + gltf: boxTexturedGltfUrl, + silhouetteSize: 1.0, + }, + scene + ); + const commands = scene.frameState.commandList; + scene.renderForSpecs(); + expect(commands.length).toBe(4); + for (let i = 0; i < commands.length; i++) { + const command = commands[i]; + expect(command.renderState.stencilTest.enabled).toBe(true); + expect(command.pass).toBe(Pass.OPAQUE); + } - const reference1 = commands[0].renderState.stencilTest.reference; - const reference2 = commands[2].renderState.stencilTest.reference; - expect(reference2).toEqual(reference1 + 1); - }); - }); + const reference1 = commands[0].renderState.stencilTest.reference; + const reference2 = commands[2].renderState.stencilTest.reference; + expect(reference2).toEqual(reference1 + 1); }); }); describe("light color", function () { - it("initializes with light color", function () { - return loadAndZoomToModelAsync( + it("initializes with light color", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl, lightColor: Cartesian3.ZERO }, scene - ).then(function (model) { - verifyRender(model, false); - }); + ); + verifyRender(model, false); }); - it("changing light color works", function () { - return loadAndZoomToModelAsync( + it("changing light color works", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl }, scene - ).then(function (model) { - model.lightColor = Cartesian3.ZERO; - verifyRender(model, false); + ); + model.lightColor = Cartesian3.ZERO; + verifyRender(model, false); - model.lightColor = new Cartesian3(1.0, 0.0, 0.0); - verifyRender(model, true); + model.lightColor = new Cartesian3(1.0, 0.0, 0.0); + verifyRender(model, true); - model.lightColor = undefined; - verifyRender(model, true); - }); + model.lightColor = undefined; + verifyRender(model, true); }); - it("light color doesn't affect unlit models", function () { - return loadAndZoomToModelAsync({ gltf: boxUnlitUrl }, scene).then( - function (model) { - const options = { - zoomToModel: false, - }; - // Move the camera to face one of the two boxes. - scene.camera.moveRight(1.0); - verifyRender(model, true, options); + it("light color doesn't affect unlit models", async function () { + const model = await loadAndZoomToModelAsync( + { gltf: boxUnlitUrl }, + scene + ); + const options = { + zoomToModel: false, + }; + // Move the camera to face one of the two boxes. + scene.camera.moveRight(1.0); + verifyRender(model, true, options); - model.lightColor = Cartesian3.ZERO; - verifyRender(model, true, options); - } - ); + model.lightColor = Cartesian3.ZERO; + verifyRender(model, true, options); }); }); @@ -3224,68 +3108,65 @@ describe( scene.highDynamicRange = false; }); - it("initializes with imageBasedLighting", function () { + it("initializes with imageBasedLighting", async function () { const ibl = new ImageBasedLighting({ imageBasedLightingFactor: Cartesian2.ZERO, luminanceAtZenith: 0.5, }); - return loadAndZoomToModelAsync( + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl, imageBasedLighting: ibl }, scene - ).then(function (model) { - expect(model.imageBasedLighting).toBe(ibl); - }); + ); + expect(model.imageBasedLighting).toBe(ibl); }); - it("creates default imageBasedLighting", function () { - return loadAndZoomToModelAsync( + it("creates default imageBasedLighting", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl }, scene - ).then(function (model) { - const imageBasedLighting = model.imageBasedLighting; - expect(imageBasedLighting).toBeDefined(); - expect( - Cartesian2.equals( - imageBasedLighting.imageBasedLightingFactor, - new Cartesian2(1, 1) - ) - ).toBe(true); - expect(imageBasedLighting.luminanceAtZenith).toBe(0.2); - expect( - imageBasedLighting.sphericalHarmonicCoefficients - ).toBeUndefined(); - expect(imageBasedLighting.specularEnvironmentMaps).toBeUndefined(); - }); + ); + const imageBasedLighting = model.imageBasedLighting; + expect(imageBasedLighting).toBeDefined(); + expect( + Cartesian2.equals( + imageBasedLighting.imageBasedLightingFactor, + new Cartesian2(1, 1) + ) + ).toBe(true); + expect(imageBasedLighting.luminanceAtZenith).toBe(0.2); + expect( + imageBasedLighting.sphericalHarmonicCoefficients + ).toBeUndefined(); + expect(imageBasedLighting.specularEnvironmentMaps).toBeUndefined(); }); - it("changing imageBasedLighting works", function () { + it("changing imageBasedLighting works", async function () { const imageBasedLighting = new ImageBasedLighting({ imageBasedLightingFactor: Cartesian2.ZERO, }); - return loadAndZoomToModelAsync( + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl }, scene - ).then(function (model) { - const renderOptions = { - scene: scene, - time: defaultDate, - }; - - let result; - verifyRender(model, true); - expect(renderOptions).toRenderAndCall(function (rgba) { - result = rgba; - }); - - model.imageBasedLighting = imageBasedLighting; - expect(renderOptions).toRenderAndCall(function (rgba) { - expect(rgba).not.toEqual(result); - }); + ); + const renderOptions = { + scene: scene, + time: defaultDate, + }; + + let result; + verifyRender(model, true); + expect(renderOptions).toRenderAndCall(function (rgba) { + result = rgba; + }); + + model.imageBasedLighting = imageBasedLighting; + expect(renderOptions).toRenderAndCall(function (rgba) { + expect(rgba).not.toEqual(result); }); }); - it("changing imageBasedLightingFactor works", function () { - return loadAndZoomToModelAsync( + it("changing imageBasedLightingFactor works", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl, imageBasedLighting: new ImageBasedLighting({ @@ -3293,28 +3174,27 @@ describe( }), }, scene - ).then(function (model) { - const renderOptions = { - scene: scene, - time: defaultDate, - }; - - let result; - verifyRender(model, true); - expect(renderOptions).toRenderAndCall(function (rgba) { - result = rgba; - }); - - const ibl = model.imageBasedLighting; - ibl.imageBasedLightingFactor = new Cartesian2(1, 1); - expect(renderOptions).toRenderAndCall(function (rgba) { - expect(rgba).not.toEqual(result); - }); + ); + const renderOptions = { + scene: scene, + time: defaultDate, + }; + + let result; + verifyRender(model, true); + expect(renderOptions).toRenderAndCall(function (rgba) { + result = rgba; + }); + + const ibl = model.imageBasedLighting; + ibl.imageBasedLightingFactor = new Cartesian2(1, 1); + expect(renderOptions).toRenderAndCall(function (rgba) { + expect(rgba).not.toEqual(result); }); }); - it("changing luminanceAtZenith works", function () { - return loadAndZoomToModelAsync( + it("changing luminanceAtZenith works", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl, imageBasedLighting: new ImageBasedLighting({ @@ -3322,27 +3202,26 @@ describe( }), }, scene - ).then(function (model) { - const renderOptions = { - scene: scene, - time: defaultDate, - }; - - let result; - verifyRender(model, true); - expect(renderOptions).toRenderAndCall(function (rgba) { - result = rgba; - }); - - const ibl = model.imageBasedLighting; - ibl.luminanceAtZenith = 0.2; - expect(renderOptions).toRenderAndCall(function (rgba) { - expect(rgba).not.toEqual(result); - }); + ); + const renderOptions = { + scene: scene, + time: defaultDate, + }; + + let result; + verifyRender(model, true); + expect(renderOptions).toRenderAndCall(function (rgba) { + result = rgba; + }); + + const ibl = model.imageBasedLighting; + ibl.luminanceAtZenith = 0.2; + expect(renderOptions).toRenderAndCall(function (rgba) { + expect(rgba).not.toEqual(result); }); }); - it("changing sphericalHarmonicCoefficients works", function () { + it("changing sphericalHarmonicCoefficients works", async function () { if (!scene.highDynamicRangeSupported) { return; } @@ -3392,7 +3271,7 @@ describe( 0.121102528320197 ); // L22, irradiance, pre-scaled base const coefficients = [L00, L1_1, L10, L11, L2_2, L2_1, L20, L21, L22]; - return loadAndZoomToModelAsync( + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl, imageBasedLighting: new ImageBasedLighting({ @@ -3400,34 +3279,33 @@ describe( }), }, scene - ).then(function (model) { - scene.highDynamicRange = true; + ); + scene.highDynamicRange = true; - const renderOptions = { - scene: scene, - time: defaultDate, - }; - - let result; - verifyRender(model, true); - expect(renderOptions).toRenderAndCall(function (rgba) { - result = rgba; - }); - - const ibl = model.imageBasedLighting; - ibl.sphericalHarmonicCoefficients = undefined; - expect(renderOptions).toRenderAndCall(function (rgba) { - expect(rgba).not.toEqual(result); - }); + const renderOptions = { + scene: scene, + time: defaultDate, + }; + + let result; + verifyRender(model, true); + expect(renderOptions).toRenderAndCall(function (rgba) { + result = rgba; + }); + + const ibl = model.imageBasedLighting; + ibl.sphericalHarmonicCoefficients = undefined; + expect(renderOptions).toRenderAndCall(function (rgba) { + expect(rgba).not.toEqual(result); }); }); - it("changing specularEnvironmentMaps works", function () { + it("changing specularEnvironmentMaps works", async function () { if (!scene.highDynamicRangeSupported) { return; } const url = "./Data/EnvironmentMap/kiara_6_afternoon_2k_ibl.ktx2"; - return loadAndZoomToModelAsync( + const model = await loadAndZoomToModelAsync( { gltf: boomBoxUrl, scale: 10.0, @@ -3436,56 +3314,53 @@ describe( }), }, scene - ).then(function (model) { - const ibl = model.imageBasedLighting; + ); + const ibl = model.imageBasedLighting; - return pollToPromise(function () { - scene.render(); - return ( - defined(ibl.specularEnvironmentMapAtlas) && - ibl.specularEnvironmentMapAtlas.ready - ); - }).then(function () { - scene.highDynamicRange = true; + await pollToPromise(function () { + scene.render(); + return ( + defined(ibl.specularEnvironmentMapAtlas) && + ibl.specularEnvironmentMapAtlas.ready + ); + }); + scene.highDynamicRange = true; - const renderOptions = { - scene: scene, - time: defaultDate, - }; + const renderOptions = { + scene: scene, + time: defaultDate, + }; - let result; - verifyRender(model, true); - expect(renderOptions).toRenderAndCall(function (rgba) { - result = rgba; - }); - - ibl.specularEnvironmentMaps = undefined; - expect(renderOptions).toRenderAndCall(function (rgba) { - expect(rgba).not.toEqual(result); - }); - }); + let result; + verifyRender(model, true); + expect(renderOptions).toRenderAndCall(function (rgba) { + result = rgba; + }); + + ibl.specularEnvironmentMaps = undefined; + expect(renderOptions).toRenderAndCall(function (rgba) { + expect(rgba).not.toEqual(result); }); }); - it("renders when specularEnvironmentMaps aren't supported", function () { + it("renders when specularEnvironmentMaps aren't supported", async function () { spyOn(OctahedralProjectedCubeMap, "isSupported").and.returnValue(false); - return loadAndZoomToModelAsync( + const model = await loadAndZoomToModelAsync( { gltf: boomBoxUrl, scale: 10.0, }, scene - ).then(function (model) { - expect(scene.specularEnvironmentMapsSupported).toBe(false); - verifyRender(model, true); - }); + ); + expect(scene.specularEnvironmentMapsSupported).toBe(false); + verifyRender(model, true); }); }); describe("scale", function () { - it("initializes with scale", function () { - return loadAndZoomToModelAsync( + it("initializes with scale", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGlbUrl, upAxis: Axis.Z, @@ -3493,173 +3368,158 @@ describe( scale: 0.0, }, scene - ).then(function (model) { - scene.renderForSpecs(); + ); + scene.renderForSpecs(); - verifyRender(model, false); - expect(model.boundingSphere.center).toEqual(Cartesian3.ZERO); - expect(model.boundingSphere.radius).toEqual(0.0); - }); + verifyRender(model, false); + expect(model.boundingSphere.center).toEqual(Cartesian3.ZERO); + expect(model.boundingSphere.radius).toEqual(0.0); }); - it("changing scale works", function () { + it("changing scale works", async function () { const updateModelMatrix = spyOn( ModelSceneGraph.prototype, "updateModelMatrix" ).and.callThrough(); - return loadAndZoomToModelAsync( + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGlbUrl, upAxis: Axis.Z, forwardAxis: Axis.X, }, scene - ).then(function (model) { - verifyRender(model, true); - model.scale = 0.0; - scene.renderForSpecs(); - expect(updateModelMatrix).toHaveBeenCalled(); - verifyRender(model, false); + ); + verifyRender(model, true); + model.scale = 0.0; + scene.renderForSpecs(); + expect(updateModelMatrix).toHaveBeenCalled(); + verifyRender(model, false); - model.scale = 1.0; - scene.renderForSpecs(); - expect(updateModelMatrix).toHaveBeenCalled(); - verifyRender(model, true); - }); + model.scale = 1.0; + scene.renderForSpecs(); + expect(updateModelMatrix).toHaveBeenCalled(); + verifyRender(model, true); }); - it("changing scale affects bounding sphere", function () { + it("changing scale affects bounding sphere", async function () { const resource = Resource.createIfNeeded(boxTexturedGlbUrl); - const loadPromise = resource.fetchArrayBuffer(); - return loadPromise.then(function (buffer) { - return loadAndZoomToModelAsync( - { - gltf: new Uint8Array(buffer), - scale: 10, - }, - scene - ).then(function (model) { - scene.renderForSpecs(); - - const expectedRadius = 0.866; - const boundingSphere = model.boundingSphere; - expect(boundingSphere.center).toEqual(Cartesian3.ZERO); - expect(boundingSphere.radius).toEqualEpsilon( - expectedRadius * 10.0, - CesiumMath.EPSILON3 - ); + const buffer = await resource.fetchArrayBuffer(); + const model = await loadAndZoomToModelAsync( + { + gltf: new Uint8Array(buffer), + scale: 10, + }, + scene + ); + scene.renderForSpecs(); - model.scale = 0.0; - scene.renderForSpecs(); - expect(boundingSphere.center).toEqual(Cartesian3.ZERO); - expect(boundingSphere.radius).toEqual(0.0); - - model.scale = 1.0; - scene.renderForSpecs(); - expect(boundingSphere.center).toEqual(Cartesian3.ZERO); - expect(boundingSphere.radius).toEqualEpsilon( - expectedRadius, - CesiumMath.EPSILON3 - ); - }); - }); + const expectedRadius = 0.866; + const boundingSphere = model.boundingSphere; + expect(boundingSphere.center).toEqual(Cartesian3.ZERO); + expect(boundingSphere.radius).toEqualEpsilon( + expectedRadius * 10.0, + CesiumMath.EPSILON3 + ); + + model.scale = 0.0; + scene.renderForSpecs(); + expect(boundingSphere.center).toEqual(Cartesian3.ZERO); + expect(boundingSphere.radius).toEqual(0.0); + + model.scale = 1.0; + scene.renderForSpecs(); + expect(boundingSphere.center).toEqual(Cartesian3.ZERO); + expect(boundingSphere.radius).toEqualEpsilon( + expectedRadius, + CesiumMath.EPSILON3 + ); }); - it("changing scale affects bounding sphere for uncentered models", function () { + it("changing scale affects bounding sphere for uncentered models", async function () { const resource = Resource.createIfNeeded(boxWithOffsetUrl); - const loadPromise = resource.fetchArrayBuffer(); - return loadPromise.then(function (buffer) { - return loadAndZoomToModelAsync( - { - gltf: new Uint8Array(buffer), - scale: 10, - }, - scene - ).then(function (model) { - const expectedRadius = 0.866; - const expectedCenter = new Cartesian3(5.0, 0.0, 0.0); - const expectedTranslation = Matrix4.fromTranslation(expectedCenter); - const axisCorrectionMatrix = ModelUtility.getAxisCorrectionMatrix( - Axis.Y, - Axis.Z, - new Matrix4() - ); - Matrix4.multiplyTransformation( - axisCorrectionMatrix, - expectedTranslation, - expectedTranslation - ); - Matrix4.getTranslation(expectedTranslation, expectedCenter); - - const boundingSphere = model.boundingSphere; - expect(boundingSphere.center).toEqual( - Cartesian3.multiplyByScalar( - expectedCenter, - 10.0, - new Cartesian3() - ) - ); - expect(boundingSphere.radius).toEqualEpsilon( - expectedRadius * 10.0, - CesiumMath.EPSILON3 - ); + const buffer = await resource.fetchArrayBuffer(); + const model = await loadAndZoomToModelAsync( + { + gltf: new Uint8Array(buffer), + scale: 10, + }, + scene + ); + const expectedRadius = 0.866; + const expectedCenter = new Cartesian3(5.0, 0.0, 0.0); + const expectedTranslation = Matrix4.fromTranslation(expectedCenter); + const axisCorrectionMatrix = ModelUtility.getAxisCorrectionMatrix( + Axis.Y, + Axis.Z, + new Matrix4() + ); + Matrix4.multiplyTransformation( + axisCorrectionMatrix, + expectedTranslation, + expectedTranslation + ); + Matrix4.getTranslation(expectedTranslation, expectedCenter); - model.scale = 0.0; - scene.renderForSpecs(); - expect(boundingSphere.center).toEqual(Cartesian3.ZERO); - expect(boundingSphere.radius).toEqual(0.0); - - model.scale = 1.0; - scene.renderForSpecs(); - expect(boundingSphere.center).toEqual(expectedCenter); - expect(boundingSphere.radius).toEqualEpsilon( - expectedRadius, - CesiumMath.EPSILON3 - ); - }); - }); + const boundingSphere = model.boundingSphere; + expect(boundingSphere.center).toEqual( + Cartesian3.multiplyByScalar(expectedCenter, 10.0, new Cartesian3()) + ); + expect(boundingSphere.radius).toEqualEpsilon( + expectedRadius * 10.0, + CesiumMath.EPSILON3 + ); + + model.scale = 0.0; + scene.renderForSpecs(); + expect(boundingSphere.center).toEqual(Cartesian3.ZERO); + expect(boundingSphere.radius).toEqual(0.0); + + model.scale = 1.0; + scene.renderForSpecs(); + expect(boundingSphere.center).toEqual(expectedCenter); + expect(boundingSphere.radius).toEqualEpsilon( + expectedRadius, + CesiumMath.EPSILON3 + ); }); }); describe("minimumPixelSize", function () { - it("initializes with minimumPixelSize", function () { + it("initializes with minimumPixelSize", async function () { const resource = Resource.createIfNeeded(boxTexturedGlbUrl); - const loadPromise = resource.fetchArrayBuffer(); - return loadPromise.then(function (buffer) { - return loadAndZoomToModelAsync( - { - gltf: new Uint8Array(buffer), - upAxis: Axis.Z, - forwardAxis: Axis.X, - minimumPixelSize: 1, - offset: new HeadingPitchRange(0, 0, 500), - }, - scene - ).then(function (model) { - const renderOptions = { - zoomToModel: false, - }; + const buffer = await resource.fetchArrayBuffer(); + const model = await loadAndZoomToModelAsync( + { + gltf: new Uint8Array(buffer), + upAxis: Axis.Z, + forwardAxis: Axis.X, + minimumPixelSize: 1, + offset: new HeadingPitchRange(0, 0, 500), + }, + scene + ); + const renderOptions = { + zoomToModel: false, + }; - const expectedRadius = 0.866; - scene.renderForSpecs(); - verifyRender(model, true, renderOptions); + const expectedRadius = 0.866; + scene.renderForSpecs(); + verifyRender(model, true, renderOptions); - // Verify that minimumPixelSize didn't affect other parameters - expect(model.scale).toEqual(1.0); - expect(model.boundingSphere.radius).toEqualEpsilon( - expectedRadius, - CesiumMath.EPSILON3 - ); - }); - }); + // Verify that minimumPixelSize didn't affect other parameters + expect(model.scale).toEqual(1.0); + expect(model.boundingSphere.radius).toEqualEpsilon( + expectedRadius, + CesiumMath.EPSILON3 + ); }); - it("changing minimumPixelSize works", function () { + it("changing minimumPixelSize works", async function () { const updateModelMatrix = spyOn( ModelSceneGraph.prototype, "updateModelMatrix" ).and.callThrough(); - return loadAndZoomToModelAsync( + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGlbUrl, upAxis: Axis.Z, @@ -3668,33 +3528,32 @@ describe( offset: new HeadingPitchRange(0, 0, 500), }, scene - ).then(function (model) { - const renderOptions = { - zoomToModel: false, - }; + ); + const renderOptions = { + zoomToModel: false, + }; - scene.renderForSpecs(); - expect(updateModelMatrix).toHaveBeenCalled(); - verifyRender(model, true, renderOptions); + scene.renderForSpecs(); + expect(updateModelMatrix).toHaveBeenCalled(); + verifyRender(model, true, renderOptions); - model.minimumPixelSize = 0.0; - scene.renderForSpecs(); - expect(updateModelMatrix).toHaveBeenCalled(); - verifyRender(model, false, renderOptions); + model.minimumPixelSize = 0.0; + scene.renderForSpecs(); + expect(updateModelMatrix).toHaveBeenCalled(); + verifyRender(model, false, renderOptions); - model.minimumPixelSize = 1; - scene.renderForSpecs(); - expect(updateModelMatrix).toHaveBeenCalled(); - verifyRender(model, true, renderOptions); - }); + model.minimumPixelSize = 1; + scene.renderForSpecs(); + expect(updateModelMatrix).toHaveBeenCalled(); + verifyRender(model, true, renderOptions); }); - it("changing minimumPixelSize doesn't affect bounding sphere or scale", function () { + it("changing minimumPixelSize doesn't affect bounding sphere or scale", async function () { const updateModelMatrix = spyOn( ModelSceneGraph.prototype, "updateModelMatrix" ).and.callThrough(); - return loadAndZoomToModelAsync( + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGlbUrl, upAxis: Axis.Z, @@ -3703,65 +3562,61 @@ describe( offset: new HeadingPitchRange(0, 0, 500), }, scene - ).then(function (model) { - const expectedRadius = 0.866; - scene.renderForSpecs(); - expect(updateModelMatrix).toHaveBeenCalled(); - expect(model.scale).toEqual(1.0); - expect(model.boundingSphere.radius).toEqualEpsilon( - expectedRadius, - CesiumMath.EPSILON3 - ); + ); + const expectedRadius = 0.866; + scene.renderForSpecs(); + expect(updateModelMatrix).toHaveBeenCalled(); + expect(model.scale).toEqual(1.0); + expect(model.boundingSphere.radius).toEqualEpsilon( + expectedRadius, + CesiumMath.EPSILON3 + ); - model.minimumPixelSize = 0.0; - scene.renderForSpecs(); - expect(updateModelMatrix).toHaveBeenCalled(); - expect(model.scale).toEqual(1.0); - expect(model.boundingSphere.radius).toEqualEpsilon( - expectedRadius, - CesiumMath.EPSILON3 - ); + model.minimumPixelSize = 0.0; + scene.renderForSpecs(); + expect(updateModelMatrix).toHaveBeenCalled(); + expect(model.scale).toEqual(1.0); + expect(model.boundingSphere.radius).toEqualEpsilon( + expectedRadius, + CesiumMath.EPSILON3 + ); - model.minimumPixelSize = 1; - scene.renderForSpecs(); - expect(updateModelMatrix).toHaveBeenCalled(); - expect(model.scale).toEqual(1.0); - expect(model.boundingSphere.radius).toEqualEpsilon( - expectedRadius, - CesiumMath.EPSILON3 - ); - }); + model.minimumPixelSize = 1; + scene.renderForSpecs(); + expect(updateModelMatrix).toHaveBeenCalled(); + expect(model.scale).toEqual(1.0); + expect(model.boundingSphere.radius).toEqualEpsilon( + expectedRadius, + CesiumMath.EPSILON3 + ); }); }); describe("maximumScale", function () { - it("initializes with maximumScale", function () { + it("initializes with maximumScale", async function () { const resource = Resource.createIfNeeded(boxTexturedGlbUrl); - const loadPromise = resource.fetchArrayBuffer(); - return loadPromise.then(function (buffer) { - return loadAndZoomToModelAsync( - { - gltf: new Uint8Array(buffer), - upAxis: Axis.Z, - forwardAxis: Axis.X, - maximumScale: 0.0, - }, - scene - ).then(function (model) { - scene.renderForSpecs(); - verifyRender(model, false); - expect(model.boundingSphere.center).toEqual(Cartesian3.ZERO); - expect(model.boundingSphere.radius).toEqual(0.0); - }); - }); + const buffer = await resource.fetchArrayBuffer(); + const model = await loadAndZoomToModelAsync( + { + gltf: new Uint8Array(buffer), + upAxis: Axis.Z, + forwardAxis: Axis.X, + maximumScale: 0.0, + }, + scene + ); + scene.renderForSpecs(); + verifyRender(model, false); + expect(model.boundingSphere.center).toEqual(Cartesian3.ZERO); + expect(model.boundingSphere.radius).toEqual(0.0); }); - it("changing maximumScale works", function () { + it("changing maximumScale works", async function () { const updateModelMatrix = spyOn( ModelSceneGraph.prototype, "updateModelMatrix" ).and.callThrough(); - return loadAndZoomToModelAsync( + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGlbUrl, upAxis: Axis.Z, @@ -3769,180 +3624,169 @@ describe( scale: 2.0, }, scene - ).then(function (model) { - scene.renderForSpecs(); - verifyRender(model, true); + ); + scene.renderForSpecs(); + verifyRender(model, true); - model.maximumScale = 0.0; - scene.renderForSpecs(); - expect(updateModelMatrix).toHaveBeenCalled(); - verifyRender(model, false); + model.maximumScale = 0.0; + scene.renderForSpecs(); + expect(updateModelMatrix).toHaveBeenCalled(); + verifyRender(model, false); - model.maximumScale = 1.0; - scene.renderForSpecs(); - expect(updateModelMatrix).toHaveBeenCalled(); - verifyRender(model, true); - }); + model.maximumScale = 1.0; + scene.renderForSpecs(); + expect(updateModelMatrix).toHaveBeenCalled(); + verifyRender(model, true); }); - it("changing maximumScale affects bounding sphere", function () { + it("changing maximumScale affects bounding sphere", async function () { const resource = Resource.createIfNeeded(boxTexturedGlbUrl); - const loadPromise = resource.fetchArrayBuffer(); - return loadPromise.then(function (buffer) { - return loadAndZoomToModelAsync( - { - gltf: new Uint8Array(buffer), - scale: 20, - maximumScale: 10, - }, - scene - ).then(function (model) { - scene.renderForSpecs(); - - const expectedRadius = 0.866; - const boundingSphere = model.boundingSphere; - expect(boundingSphere.center).toEqual(Cartesian3.ZERO); - expect(boundingSphere.radius).toEqualEpsilon( - expectedRadius * 10.0, - CesiumMath.EPSILON3 - ); + const buffer = await resource.fetchArrayBuffer(); + const model = await loadAndZoomToModelAsync( + { + gltf: new Uint8Array(buffer), + scale: 20, + maximumScale: 10, + }, + scene + ); + scene.renderForSpecs(); - model.maximumScale = 0.0; - scene.renderForSpecs(); - expect(boundingSphere.center).toEqual(Cartesian3.ZERO); - expect(boundingSphere.radius).toEqual(0.0); - - model.maximumScale = 1.0; - scene.renderForSpecs(); - expect(boundingSphere.center).toEqual(Cartesian3.ZERO); - expect(boundingSphere.radius).toEqualEpsilon( - expectedRadius, - CesiumMath.EPSILON3 - ); - }); - }); + const expectedRadius = 0.866; + const boundingSphere = model.boundingSphere; + expect(boundingSphere.center).toEqual(Cartesian3.ZERO); + expect(boundingSphere.radius).toEqualEpsilon( + expectedRadius * 10.0, + CesiumMath.EPSILON3 + ); + + model.maximumScale = 0.0; + scene.renderForSpecs(); + expect(boundingSphere.center).toEqual(Cartesian3.ZERO); + expect(boundingSphere.radius).toEqual(0.0); + + model.maximumScale = 1.0; + scene.renderForSpecs(); + expect(boundingSphere.center).toEqual(Cartesian3.ZERO); + expect(boundingSphere.radius).toEqualEpsilon( + expectedRadius, + CesiumMath.EPSILON3 + ); }); - it("changing maximumScale affects minimumPixelSize", function () { + it("changing maximumScale affects minimumPixelSize", async function () { const resource = Resource.createIfNeeded(boxTexturedGlbUrl); - const loadPromise = resource.fetchArrayBuffer(); - return loadPromise.then(function (buffer) { - return loadAndZoomToModelAsync( - { - gltf: new Uint8Array(buffer), - minimumPixelSize: 1, - maximumScale: 10, - }, - scene - ).then(function (model) { - scene.renderForSpecs(); - - const expectedRadius = 0.866; - const boundingSphere = model.boundingSphere; - expect(boundingSphere.center).toEqual(Cartesian3.ZERO); - expect(boundingSphere.radius).toEqualEpsilon( - expectedRadius, - CesiumMath.EPSILON3 - ); + const buffer = await resource.fetchArrayBuffer(); + const model = await loadAndZoomToModelAsync( + { + gltf: new Uint8Array(buffer), + minimumPixelSize: 1, + maximumScale: 10, + }, + scene + ); + scene.renderForSpecs(); - model.maximumScale = 0.0; - scene.renderForSpecs(); - expect(boundingSphere.center).toEqual(Cartesian3.ZERO); - expect(boundingSphere.radius).toEqual(0.0); - - model.maximumScale = 10.0; - scene.renderForSpecs(); - expect(boundingSphere.center).toEqual(Cartesian3.ZERO); - expect(boundingSphere.radius).toEqualEpsilon( - expectedRadius, - CesiumMath.EPSILON3 - ); - }); - }); + const expectedRadius = 0.866; + const boundingSphere = model.boundingSphere; + expect(boundingSphere.center).toEqual(Cartesian3.ZERO); + expect(boundingSphere.radius).toEqualEpsilon( + expectedRadius, + CesiumMath.EPSILON3 + ); + + model.maximumScale = 0.0; + scene.renderForSpecs(); + expect(boundingSphere.center).toEqual(Cartesian3.ZERO); + expect(boundingSphere.radius).toEqual(0.0); + + model.maximumScale = 10.0; + scene.renderForSpecs(); + expect(boundingSphere.center).toEqual(Cartesian3.ZERO); + expect(boundingSphere.radius).toEqualEpsilon( + expectedRadius, + CesiumMath.EPSILON3 + ); }); }); - it("resets draw commands when vertical exaggeration changes", function () { - return loadAndZoomToModelAsync( + it("resets draw commands when vertical exaggeration changes", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl, }, scene - ).then(function (model) { - const resetDrawCommands = spyOn( - model, - "resetDrawCommands" - ).and.callThrough(); - expect(model.ready).toBe(true); + ); + const resetDrawCommands = spyOn( + model, + "resetDrawCommands" + ).and.callThrough(); + expect(model.ready).toBe(true); - scene.verticalExaggeration = 2.0; - scene.renderForSpecs(); - expect(resetDrawCommands).toHaveBeenCalled(); - scene.verticalExaggeration = 1.0; - }); + scene.verticalExaggeration = 2.0; + scene.renderForSpecs(); + expect(resetDrawCommands).toHaveBeenCalled(); + scene.verticalExaggeration = 1.0; }); - it("does not issue draw commands when ignoreCommands is true", function () { - return loadAndZoomToModelAsync( + it("does not issue draw commands when ignoreCommands is true", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl, }, scene - ).then(function (model) { - expect(model.ready).toBe(true); - model._ignoreCommands = true; + ); + expect(model.ready).toBe(true); + model._ignoreCommands = true; - scene.renderForSpecs(); - expect(scene.frameState.commandList.length).toEqual(0); - }); + scene.renderForSpecs(); + expect(scene.frameState.commandList.length).toEqual(0); }); describe("frustum culling ", function () { - it("enables frustum culling", function () { - return loadAndZoomToModelAsync( + it("enables frustum culling", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl, cull: true, }, scene - ).then(function (model) { - expect(model.cull).toEqual(true); + ); + expect(model.cull).toEqual(true); - // Commands should be submitted while viewing the model. - scene.renderForSpecs(); - expect(scene.frustumCommandsList.length).toBeGreaterThan(0); + // Commands should be submitted while viewing the model. + scene.renderForSpecs(); + expect(scene.frustumCommandsList.length).toBeGreaterThan(0); - // Commands should not be submitted when model is out of view. - model.modelMatrix = Matrix4.fromTranslation( - new Cartesian3(100.0, 0.0, 0.0) - ); - scene.renderForSpecs(); - expect(scene.frustumCommandsList.length).toEqual(0); - }); + // Commands should not be submitted when model is out of view. + model.modelMatrix = Matrix4.fromTranslation( + new Cartesian3(100.0, 0.0, 0.0) + ); + scene.renderForSpecs(); + expect(scene.frustumCommandsList.length).toEqual(0); }); - it("disables frustum culling", function () { - return loadAndZoomToModelAsync( + it("disables frustum culling", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl, cull: false, }, scene - ).then(function (model) { - expect(model.cull).toEqual(false); + ); + expect(model.cull).toEqual(false); - // Commands should be submitted while viewing the model. - scene.renderForSpecs(); - const length = scene.frustumCommandsList.length; - expect(length).toBeGreaterThan(0); + // Commands should be submitted while viewing the model. + scene.renderForSpecs(); + const length = scene.frustumCommandsList.length; + expect(length).toBeGreaterThan(0); - // Commands should still be submitted when model is out of view. - model.modelMatrix = Matrix4.fromTranslation( - new Cartesian3(0.0, 100.0, 0.0) - ); - scene.renderForSpecs(); - expect(scene.frustumCommandsList.length).toEqual(length); - }); + // Commands should still be submitted when model is out of view. + model.modelMatrix = Matrix4.fromTranslation( + new Cartesian3(0.0, 100.0, 0.0) + ); + scene.renderForSpecs(); + expect(scene.frustumCommandsList.length).toEqual(length); }); }); @@ -3955,80 +3799,76 @@ describe( 2.0 ); - it("enables back-face culling", function () { - return loadAndZoomToModelAsync( + it("enables back-face culling", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxBackFaceCullingUrl, backFaceCulling: true, offset: boxBackFaceCullingOffset, }, scene - ).then(function (model) { - verifyRender(model, false, { - zoomToModel: false, - }); + ); + verifyRender(model, false, { + zoomToModel: false, }); }); - it("disables back-face culling", function () { - return loadAndZoomToModelAsync( + it("disables back-face culling", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxBackFaceCullingUrl, backFaceCulling: false, offset: boxBackFaceCullingOffset, }, scene - ).then(function (model) { - verifyRender(model, true, { - zoomToModel: false, - }); + ); + verifyRender(model, true, { + zoomToModel: false, }); }); - it("ignores back-face culling when translucent", function () { - return loadAndZoomToModelAsync( + it("ignores back-face culling when translucent", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxBackFaceCullingUrl, backFaceCulling: true, offset: boxBackFaceCullingOffset, }, scene - ).then(function (model) { - verifyRender(model, false, { - zoomToModel: false, - }); + ); + verifyRender(model, false, { + zoomToModel: false, + }); - model.color = new Color(0, 0, 1.0, 0.5); + model.color = new Color(0, 0, 1.0, 0.5); - verifyRender(model, true, { - zoomToModel: false, - }); + verifyRender(model, true, { + zoomToModel: false, }); }); - it("toggles back-face culling at runtime", function () { - return loadAndZoomToModelAsync( + it("toggles back-face culling at runtime", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxBackFaceCullingUrl, backFaceCulling: false, offset: boxBackFaceCullingOffset, }, scene - ).then(function (model) { - verifyRender(model, true, { - zoomToModel: false, - }); + ); + verifyRender(model, true, { + zoomToModel: false, + }); - model.backFaceCulling = true; + model.backFaceCulling = true; - verifyRender(model, false, { - zoomToModel: false, - }); + verifyRender(model, false, { + zoomToModel: false, }); }); - it("ignores back-face culling toggles when translucent", function () { - return loadAndZoomToModelAsync( + it("ignores back-face culling toggles when translucent", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxBackFaceCullingUrl, backFaceCulling: false, @@ -4036,123 +3876,117 @@ describe( color: new Color(0, 0, 1.0, 0.5), }, scene - ).then(function (model) { - verifyRender(model, true, { - zoomToModel: false, - }); + ); + verifyRender(model, true, { + zoomToModel: false, + }); - model.backFaceCulling = true; + model.backFaceCulling = true; - verifyRender(model, true, { - zoomToModel: false, - }); + verifyRender(model, true, { + zoomToModel: false, + }); - model.backFaceCulling = false; + model.backFaceCulling = false; - verifyRender(model, true, { - zoomToModel: false, - }); + verifyRender(model, true, { + zoomToModel: false, }); }); }); - it("reverses winding order for negatively scaled models", function () { - return loadAndZoomToModelAsync( + it("reverses winding order for negatively scaled models", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGlbUrl, modelMatrix: Matrix4.fromUniformScale(-1.0), }, scene - ).then(function (model) { - const renderOptions = { - scene: scene, - time: defaultDate, - }; + ); + const renderOptions = { + scene: scene, + time: defaultDate, + }; - // The model should look the same whether it has -1.0 scale or 1.0 scale. - // The initial scale is -1.0. Test switching this at runtime. - let initialRgba; - expect(renderOptions).toRenderAndCall(function (rgba) { - initialRgba = rgba; - }); + // The model should look the same whether it has -1.0 scale or 1.0 scale. + // The initial scale is -1.0. Test switching this at runtime. + let initialRgba; + expect(renderOptions).toRenderAndCall(function (rgba) { + initialRgba = rgba; + }); - model.modelMatrix = Matrix4.IDENTITY; + model.modelMatrix = Matrix4.IDENTITY; - expect(renderOptions).toRenderAndCall(function (rgba) { - expect(rgba).toEqual(initialRgba); - }); + expect(renderOptions).toRenderAndCall(function (rgba) { + expect(rgba).toEqual(initialRgba); + }); - model.modelMatrix = Matrix4.fromUniformScale(-1.0); + model.modelMatrix = Matrix4.fromUniformScale(-1.0); - expect(renderOptions).toRenderAndCall(function (rgba) { - expect(rgba).toEqual(initialRgba); - }); + expect(renderOptions).toRenderAndCall(function (rgba) { + expect(rgba).toEqual(initialRgba); }); }); describe("clipping planes", function () { - it("throws when given clipping planes attached to another model", function () { + it("throws when given clipping planes attached to another model", async function () { const plane = new ClippingPlane(Cartesian3.UNIT_X, 0.0); const clippingPlanes = new ClippingPlaneCollection({ planes: [plane], }); - return loadAndZoomToModelAsync( + await loadAndZoomToModelAsync( { gltf: boxTexturedGlbUrl, clippingPlanes: clippingPlanes }, scene - ) - .then(function (model) { - return loadAndZoomToModelAsync({ gltf: boxTexturedGlbUrl }, scene); - }) - .then(function (model2) { - expect(function () { - model2.clippingPlanes = clippingPlanes; - }).toThrowDeveloperError(); - }); + ); + const model = await loadAndZoomToModelAsync( + { gltf: boxTexturedGlbUrl }, + scene + ); + expect(function () { + model.clippingPlanes = clippingPlanes; + }).toThrowDeveloperError(); }); - it("updates clipping planes when clipping planes are enabled", function () { + it("updates clipping planes when clipping planes are enabled", async function () { const plane = new ClippingPlane(Cartesian3.UNIT_X, 0.0); const clippingPlanes = new ClippingPlaneCollection({ planes: [plane], }); - return loadAndZoomToModelAsync({ gltf: boxTexturedGlbUrl }, scene).then( - function (model) { - const gl = scene.frameState.context._gl; - spyOn(gl, "texImage2D").and.callThrough(); - - scene.renderForSpecs(); - const callsBeforeClipping = gl.texImage2D.calls.count(); - - model.clippingPlanes = clippingPlanes; - scene.renderForSpecs(); - scene.renderForSpecs(); - // When clipping planes are created, we expect two calls to texImage2D - // (one for initial creation, and one for copying the data in) - // because clipping planes is stored inside a texture. - expect(gl.texImage2D.calls.count() - callsBeforeClipping).toEqual( - 2 - ); - } + const model = await loadAndZoomToModelAsync( + { gltf: boxTexturedGlbUrl }, + scene ); + const gl = scene.frameState.context._gl; + spyOn(gl, "texImage2D").and.callThrough(); + + scene.renderForSpecs(); + const callsBeforeClipping = gl.texImage2D.calls.count(); + + model.clippingPlanes = clippingPlanes; + scene.renderForSpecs(); + scene.renderForSpecs(); + // When clipping planes are created, we expect two calls to texImage2D + // (one for initial creation, and one for copying the data in) + // because clipping planes is stored inside a texture. + expect(gl.texImage2D.calls.count() - callsBeforeClipping).toEqual(2); }); - it("initializes and updates with clipping planes", function () { + it("initializes and updates with clipping planes", async function () { const plane = new ClippingPlane(Cartesian3.UNIT_X, -2.5); const clippingPlanes = new ClippingPlaneCollection({ planes: [plane], }); - return loadAndZoomToModelAsync( + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGlbUrl, clippingPlanes: clippingPlanes }, scene - ).then(function (model) { - verifyRender(model, false); + ); + verifyRender(model, false); - model.clippingPlanes = undefined; - verifyRender(model, true); - }); + model.clippingPlanes = undefined; + verifyRender(model, true); }); - it("updating clipping planes properties works", function () { + it("updating clipping planes properties works", async function () { const direction = Cartesian3.multiplyByScalar( Cartesian3.UNIT_X, -1, @@ -4162,62 +3996,60 @@ describe( const clippingPlanes = new ClippingPlaneCollection({ planes: [plane], }); - return loadAndZoomToModelAsync({ gltf: boxTexturedGlbUrl }, scene).then( - function (model) { - let modelColor; - verifyRender(model, true); - expect(scene).toRenderAndCall(function (rgba) { - modelColor = rgba; - }); - - // The clipping plane should cut the model in half such that - // we see the back faces. - model.clippingPlanes = clippingPlanes; - expect(scene).toRenderAndCall(function (rgba) { - expect(rgba).not.toEqual(modelColor); - }); - - plane.distance = 10.0; // Move the plane away from the model - expect(scene).toRenderAndCall(function (rgba) { - expect(rgba).toEqual(modelColor); - }); - } + const model = await loadAndZoomToModelAsync( + { gltf: boxTexturedGlbUrl }, + scene ); + let modelColor; + verifyRender(model, true); + expect(scene).toRenderAndCall(function (rgba) { + modelColor = rgba; + }); + + // The clipping plane should cut the model in half such that + // we see the back faces. + model.clippingPlanes = clippingPlanes; + expect(scene).toRenderAndCall(function (rgba) { + expect(rgba).not.toEqual(modelColor); + }); + + plane.distance = 10.0; // Move the plane away from the model + expect(scene).toRenderAndCall(function (rgba) { + expect(rgba).toEqual(modelColor); + }); }); - it("removing clipping plane from collection works", function () { + it("removing clipping plane from collection works", async function () { const plane = new ClippingPlane(Cartesian3.UNIT_X, -2.5); const clippingPlanes = new ClippingPlaneCollection({ planes: [plane], }); - return loadAndZoomToModelAsync( + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGlbUrl, clippingPlanes: clippingPlanes }, scene - ).then(function (model) { - verifyRender(model, false); + ); + verifyRender(model, false); - clippingPlanes.removeAll(); - verifyRender(model, true); - }); + clippingPlanes.removeAll(); + verifyRender(model, true); }); - it("removing clipping planes collection works", function () { + it("removing clipping planes collection works", async function () { const plane = new ClippingPlane(Cartesian3.UNIT_X, -2.5); const clippingPlanes = new ClippingPlaneCollection({ planes: [plane], }); - return loadAndZoomToModelAsync( + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGlbUrl, clippingPlanes: clippingPlanes }, scene - ).then(function (model) { - verifyRender(model, false); + ); + verifyRender(model, false); - model.clippingPlanes = undefined; - verifyRender(model, true); - }); + model.clippingPlanes = undefined; + verifyRender(model, true); }); - it("replacing clipping planes with another collection works", function () { + it("replacing clipping planes with another collection works", async function () { const modelClippedPlane = new ClippingPlane(Cartesian3.UNIT_X, -2.5); const modelVisiblePlane = new ClippingPlane(Cartesian3.UNIT_X, 2.5); @@ -4225,27 +4057,26 @@ describe( planes: [modelClippedPlane], }); - return loadAndZoomToModelAsync( + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGlbUrl, clippingPlanes: clippingPlanes }, scene - ).then(function (model) { - verifyRender(model, false); + ); + verifyRender(model, false); - // Replace the clipping plane collection with one that makes the model visible. - model.clippingPlanes = new ClippingPlaneCollection({ - planes: [modelVisiblePlane], - }); - verifyRender(model, true); + // Replace the clipping plane collection with one that makes the model visible. + model.clippingPlanes = new ClippingPlaneCollection({ + planes: [modelVisiblePlane], + }); + verifyRender(model, true); - // Replace the clipping plane collection with one that clips the model. - model.clippingPlanes = new ClippingPlaneCollection({ - planes: [modelClippedPlane], - }); - verifyRender(model, false); + // Replace the clipping plane collection with one that clips the model. + model.clippingPlanes = new ClippingPlaneCollection({ + planes: [modelClippedPlane], }); + verifyRender(model, false); }); - it("clipping planes apply edge styling", function () { + it("clipping planes apply edge styling", async function () { const plane = new ClippingPlane(Cartesian3.UNIT_X, 0); const clippingPlanes = new ClippingPlaneCollection({ planes: [plane], @@ -4253,29 +4084,29 @@ describe( edgeColor: Color.BLUE, }); - return loadAndZoomToModelAsync({ gltf: boxTexturedGlbUrl }, scene).then( - function (model) { - let modelColor; - verifyRender(model, true); - expect(scene).toRenderAndCall(function (rgba) { - modelColor = rgba; - }); + const model = await loadAndZoomToModelAsync( + { gltf: boxTexturedGlbUrl }, + scene + ); + let modelColor; + verifyRender(model, true); + expect(scene).toRenderAndCall(function (rgba) { + modelColor = rgba; + }); - model.clippingPlanes = clippingPlanes; + model.clippingPlanes = clippingPlanes; - expect(scene).toRenderAndCall(function (rgba) { - expect(rgba).toEqual([0, 0, 255, 255]); - }); + expect(scene).toRenderAndCall(function (rgba) { + expect(rgba).toEqual([0, 0, 255, 255]); + }); - clippingPlanes.edgeWidth = 0.0; - expect(scene).toRenderAndCall(function (rgba) { - expect(rgba).toEqual(modelColor); - }); - } - ); + clippingPlanes.edgeWidth = 0.0; + expect(scene).toRenderAndCall(function (rgba) { + expect(rgba).toEqual(modelColor); + }); }); - it("clipping planes union regions", function () { + it("clipping planes union regions", async function () { const clippingPlanes = new ClippingPlaneCollection({ planes: [ new ClippingPlane(Cartesian3.UNIT_Z, 5.0), @@ -4283,58 +4114,55 @@ describe( ], unionClippingRegions: true, }); - return loadAndZoomToModelAsync({ gltf: boxTexturedGlbUrl }, scene).then( - function (model) { - verifyRender(model, true); + const model = await loadAndZoomToModelAsync( + { gltf: boxTexturedGlbUrl }, + scene + ); + verifyRender(model, true); - // These planes are defined such that the model is outside their union. - model.clippingPlanes = clippingPlanes; - verifyRender(model, false); + // These planes are defined such that the model is outside their union. + model.clippingPlanes = clippingPlanes; + verifyRender(model, false); - model.clippingPlanes.unionClippingRegions = false; - verifyRender(model, true); - } - ); + model.clippingPlanes.unionClippingRegions = false; + verifyRender(model, true); }); - it("destroys attached ClippingPlaneCollections", function () { - return loadAndZoomToModelAsync( + it("destroys attached ClippingPlaneCollections", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGlbUrl, }, scene - ).then(function (model) { - const clippingPlanes = new ClippingPlaneCollection({ - planes: [new ClippingPlane(Cartesian3.UNIT_X, 0.0)], - }); + ); + const clippingPlanes = new ClippingPlaneCollection({ + planes: [new ClippingPlane(Cartesian3.UNIT_X, 0.0)], + }); - model.clippingPlanes = clippingPlanes; - expect(model.isDestroyed()).toEqual(false); - expect(clippingPlanes.isDestroyed()).toEqual(false); + model.clippingPlanes = clippingPlanes; + expect(model.isDestroyed()).toEqual(false); + expect(clippingPlanes.isDestroyed()).toEqual(false); - scene.primitives.remove(model); - expect(model.isDestroyed()).toEqual(true); - expect(clippingPlanes.isDestroyed()).toEqual(true); - }); + scene.primitives.remove(model); + expect(model.isDestroyed()).toEqual(true); + expect(clippingPlanes.isDestroyed()).toEqual(true); }); - it("destroys ClippingPlaneCollections that are detached", function () { - let clippingPlanes; - return loadAndZoomToModelAsync( + it("destroys ClippingPlaneCollections that are detached", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGlbUrl, }, scene - ).then(function (model) { - clippingPlanes = new ClippingPlaneCollection({ - planes: [new ClippingPlane(Cartesian3.UNIT_X, 0.0)], - }); - model.clippingPlanes = clippingPlanes; - expect(clippingPlanes.isDestroyed()).toBe(false); - - model.clippingPlanes = undefined; - expect(clippingPlanes.isDestroyed()).toBe(true); + ); + const clippingPlanes = new ClippingPlaneCollection({ + planes: [new ClippingPlane(Cartesian3.UNIT_X, 0.0)], }); + model.clippingPlanes = clippingPlanes; + expect(clippingPlanes.isDestroyed()).toBe(false); + + model.clippingPlanes = undefined; + expect(clippingPlanes.isDestroyed()).toBe(true); }); }); @@ -4504,68 +4332,63 @@ describe( }); }); - it("renders with classificationType", function () { - return loadAndZoomToModelAsync( + it("renders with classificationType", async function () { + const model = await loadAndZoomToModelAsync( { url: boxTexturedGltfUrl, classificationType: ClassificationType.CESIUM_3D_TILE, }, scene - ).then(function (model) { - expect(model.classificationType).toBe( - ClassificationType.CESIUM_3D_TILE - ); + ); + expect(model.classificationType).toBe(ClassificationType.CESIUM_3D_TILE); - // There's nothing to classify, so the model won't render. - verifyRender(model, false); - }); + // There's nothing to classify, so the model won't render. + verifyRender(model, false); }); describe("statistics", function () { - it("gets triangle count", function () { - return loadAndZoomToModelAsync( + it("gets triangle count", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl }, scene - ).then(function (model) { - const statistics = model.statistics; - expect(statistics.trianglesLength).toEqual(12); - }); + ); + const statistics = model.statistics; + expect(statistics.trianglesLength).toEqual(12); }); - it("gets point count", function () { - return loadAndZoomToModelAsync({ gltf: pointCloudUrl }, scene).then( - function (model) { - const statistics = model.statistics; - expect(statistics.pointsLength).toEqual(2500); - } + it("gets point count", async function () { + const model = await loadAndZoomToModelAsync( + { gltf: pointCloudUrl }, + scene ); + const statistics = model.statistics; + expect(statistics.pointsLength).toEqual(2500); }); - it("gets memory usage for geometry and textures", function () { - return loadAndZoomToModelAsync( + it("gets memory usage for geometry and textures", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxTexturedGltfUrl, incrementallyLoadTextures: false }, scene - ).then(function (model) { - const expectedGeometryMemory = 840; - // Texture is 256*256 and then is mipmapped - const expectedTextureMemory = Math.floor(256 * 256 * 4 * (4 / 3)); + ); + const expectedGeometryMemory = 840; + // Texture is 256*256 and then is mipmapped + const expectedTextureMemory = Math.floor(256 * 256 * 4 * (4 / 3)); - const statistics = model.statistics; - expect(statistics.geometryByteLength).toEqual(expectedGeometryMemory); - expect(statistics.texturesByteLength).toEqual(expectedTextureMemory); - }); + const statistics = model.statistics; + expect(statistics.geometryByteLength).toEqual(expectedGeometryMemory); + expect(statistics.texturesByteLength).toEqual(expectedTextureMemory); }); - it("gets memory usage for property tables", function () { - return loadAndZoomToModelAsync({ gltf: buildingsMetadata }, scene).then( - function (model) { - const expectedPropertyTableMemory = 110; + it("gets memory usage for property tables", async function () { + const model = await loadAndZoomToModelAsync( + { gltf: buildingsMetadata }, + scene + ); + const expectedPropertyTableMemory = 110; - const statistics = model.statistics; - expect(statistics.propertyTablesByteLength).toEqual( - expectedPropertyTableMemory - ); - } + const statistics = model.statistics; + expect(statistics.propertyTablesByteLength).toEqual( + expectedPropertyTableMemory ); }); }); @@ -4581,17 +4404,16 @@ describe( }).toThrowDeveloperError(); }); - it("setArticulationStage throws with invalid value", function () { - return loadAndZoomToModelAsync( + it("setArticulationStage throws with invalid value", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxArticulationsUrl, }, scene - ).then(function (model) { - expect(function () { - model.setArticulationStage("SampleArticulation MoveX", "bad"); - }).toThrowDeveloperError(); - }); + ); + expect(function () { + model.setArticulationStage("SampleArticulation MoveX", "bad"); + }).toThrowDeveloperError(); }); it("applyArticulations throws when model is not ready", async function () { @@ -4604,31 +4426,30 @@ describe( }).toThrowDeveloperError(); }); - it("applies articulations", function () { - return loadAndZoomToModelAsync( + it("applies articulations", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxArticulationsUrl, }, scene - ).then(function (model) { - verifyRender(model, true); + ); + verifyRender(model, true); - model.setArticulationStage("SampleArticulation MoveX", 10.0); - model.applyArticulations(); - verifyRender(model, false); + model.setArticulationStage("SampleArticulation MoveX", 10.0); + model.applyArticulations(); + verifyRender(model, false); - model.setArticulationStage("SampleArticulation MoveX", 0.0); - model.applyArticulations(); - verifyRender(model, true); + model.setArticulationStage("SampleArticulation MoveX", 0.0); + model.applyArticulations(); + verifyRender(model, true); - model.setArticulationStage("SampleArticulation Size", 0.0); - model.applyArticulations(); - verifyRender(model, false); + model.setArticulationStage("SampleArticulation Size", 0.0); + model.applyArticulations(); + verifyRender(model, false); - model.setArticulationStage("SampleArticulation Size", 1.0); - model.applyArticulations(); - verifyRender(model, true); - }); + model.setArticulationStage("SampleArticulation Size", 1.0); + model.applyArticulations(); + verifyRender(model, true); }); }); @@ -4643,82 +4464,77 @@ describe( }).toThrowDeveloperError(); }); - it("getNode throws when name is undefined", function () { - return loadAndZoomToModelAsync( + it("getNode throws when name is undefined", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxArticulationsUrl, }, scene - ).then(function (model) { - expect(function () { - model.getNode(); - }).toThrowDeveloperError(); - }); + ); + expect(function () { + model.getNode(); + }).toThrowDeveloperError(); }); - it("getNode returns undefined for nonexistent node", function () { - return loadAndZoomToModelAsync( + it("getNode returns undefined for nonexistent node", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxArticulationsUrl, }, scene - ).then(function (model) { - const node = model.getNode("I don't exist"); - expect(node).toBeUndefined(); - }); + ); + const node = model.getNode("I don't exist"); + expect(node).toBeUndefined(); }); - it("getNode returns a node", function () { - return loadAndZoomToModelAsync( + it("getNode returns a node", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxArticulationsUrl, }, scene - ).then(function (model) { - const node = model.getNode("Root"); + ); + const node = model.getNode("Root"); - expect(node).toBeDefined(); - expect(node.name).toEqual("Root"); - expect(node.id).toEqual(0); - expect(node.show).toEqual(true); - expect(node.matrix).toEqual(boxArticulationsMatrix); - expect(node.originalMatrix).toEqual(boxArticulationsMatrix); - }); + expect(node).toBeDefined(); + expect(node.name).toEqual("Root"); + expect(node.id).toEqual(0); + expect(node.show).toEqual(true); + expect(node.matrix).toEqual(boxArticulationsMatrix); + expect(node.originalMatrix).toEqual(boxArticulationsMatrix); }); - it("changing node.show works", function () { - return loadAndZoomToModelAsync( + it("changing node.show works", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxArticulationsUrl, }, scene - ).then(function (model) { - verifyRender(model, true); - const node = model.getNode("Root"); - expect(node.show).toEqual(true); + ); + verifyRender(model, true); + const node = model.getNode("Root"); + expect(node.show).toEqual(true); - node.show = false; - verifyRender(model, false); - }); + node.show = false; + verifyRender(model, false); }); - it("changing node.matrix works", function () { - return loadAndZoomToModelAsync( + it("changing node.matrix works", async function () { + const model = await loadAndZoomToModelAsync( { gltf: boxArticulationsUrl, }, scene - ).then(function (model) { - verifyRender(model, true); - const node = model.getNode("Root"); - expect(node.matrix).toEqual(boxArticulationsMatrix); - expect(node.originalMatrix).toEqual(boxArticulationsMatrix); + ); + verifyRender(model, true); + const node = model.getNode("Root"); + expect(node.matrix).toEqual(boxArticulationsMatrix); + expect(node.originalMatrix).toEqual(boxArticulationsMatrix); - node.matrix = Matrix4.fromTranslation(new Cartesian3(10, 0, 0)); - // The model's bounding sphere doesn't account for animations, - // so the camera will not account for the node's new transform. - verifyRender(model, false); - }); + node.matrix = Matrix4.fromTranslation(new Cartesian3(10, 0, 0)); + // The model's bounding sphere doesn't account for animations, + // so the camera will not account for the node's new transform. + verifyRender(model, false); }); }); @@ -5178,66 +4994,63 @@ describe( ); }); - it("destroy works", function () { + it("destroy works", async function () { spyOn(ShaderProgram.prototype, "destroy").and.callThrough(); - return loadAndZoomToModelAsync({ gltf: boxTexturedGlbUrl }, scene).then( - function (model) { - const resources = model._pipelineResources; - const loader = model._loader; - let resource; - - let i; - for (i = 0; i < resources.length; i++) { - resource = resources[i]; - if (defined(resource.isDestroyed)) { - expect(resource.isDestroyed()).toEqual(false); - } - } - expect(loader.isDestroyed()).toEqual(false); - expect(model.isDestroyed()).toEqual(false); - scene.primitives.remove(model); - if (!webglStub) { - expect(ShaderProgram.prototype.destroy).toHaveBeenCalled(); - } - for (i = 0; i < resources.length - 1; i++) { - resource = resources[i]; - if (defined(resource.isDestroyed)) { - expect(resource.isDestroyed()).toEqual(true); - } - } - expect(loader.isDestroyed()).toEqual(true); - expect(model.isDestroyed()).toEqual(true); - } + const model = await loadAndZoomToModelAsync( + { gltf: boxTexturedGlbUrl }, + scene ); + const resources = model._pipelineResources; + const loader = model._loader; + + for (let i = 0; i < resources.length; i++) { + const resource = resources[i]; + if (defined(resource.isDestroyed)) { + expect(resource.isDestroyed()).toEqual(false); + } + } + expect(loader.isDestroyed()).toEqual(false); + expect(model.isDestroyed()).toEqual(false); + scene.primitives.remove(model); + if (!webglStub) { + expect(ShaderProgram.prototype.destroy).toHaveBeenCalled(); + } + for (let i = 0; i < resources.length - 1; i++) { + const resource = resources[i]; + if (defined(resource.isDestroyed)) { + expect(resource.isDestroyed()).toEqual(true); + } + } + expect(loader.isDestroyed()).toEqual(true); + expect(model.isDestroyed()).toEqual(true); }); - it("destroy doesn't destroy resources when they're in use", function () { - return Promise.all([ + it("destroy doesn't destroy resources when they're in use", async function () { + const models = await Promise.all([ loadAndZoomToModelAsync({ gltf: boxTexturedGlbUrl }, scene), loadAndZoomToModelAsync({ gltf: boxTexturedGlbUrl }, scene), - ]).then(function (models) { - const cacheEntries = ResourceCache.cacheEntries; - let cacheKey; - let cacheEntry; + ]); + const cacheEntries = ResourceCache.cacheEntries; + let cacheKey; + let cacheEntry; - scene.primitives.remove(models[0]); + scene.primitives.remove(models[0]); - for (cacheKey in cacheEntries) { - if (cacheEntries.hasOwnProperty(cacheKey)) { - cacheEntry = cacheEntries[cacheKey]; - expect(cacheEntry.referenceCount).toBeGreaterThan(0); - } + for (cacheKey in cacheEntries) { + if (cacheEntries.hasOwnProperty(cacheKey)) { + cacheEntry = cacheEntries[cacheKey]; + expect(cacheEntry.referenceCount).toBeGreaterThan(0); } + } - scene.primitives.remove(models[1]); + scene.primitives.remove(models[1]); - for (cacheKey in cacheEntries) { - if (cacheEntries.hasOwnProperty(cacheKey)) { - cacheEntry = cacheEntries[cacheKey]; - expect(cacheEntry.referenceCount).toBe(0); - } + for (cacheKey in cacheEntries) { + if (cacheEntries.hasOwnProperty(cacheKey)) { + cacheEntry = cacheEntries[cacheKey]; + expect(cacheEntry.referenceCount).toBe(0); } - }); + } }); }, "WebGL" diff --git a/packages/engine/Specs/Scene/MultifrustumSpec.js b/packages/engine/Specs/Scene/MultifrustumSpec.js index aa9917256f0..5c417c6f4a7 100644 --- a/packages/engine/Specs/Scene/MultifrustumSpec.js +++ b/packages/engine/Specs/Scene/MultifrustumSpec.js @@ -8,6 +8,7 @@ import { defined, destroyObject, GeometryPipeline, + Math as CesiumMath, Matrix4, Resource, BufferUsage, @@ -22,8 +23,6 @@ import { TextureAtlas, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createScene from "../../../../Specs/createScene.js"; import pollToPromise from "../../../../Specs/pollToPromise.js"; diff --git a/packages/engine/Specs/Scene/OctahedralProjectedCubeMapSpec.js b/packages/engine/Specs/Scene/OctahedralProjectedCubeMapSpec.js index 2d13eba58fb..ac9efc89fb9 100644 --- a/packages/engine/Specs/Scene/OctahedralProjectedCubeMapSpec.js +++ b/packages/engine/Specs/Scene/OctahedralProjectedCubeMapSpec.js @@ -1,9 +1,10 @@ import { + Cartesian3, + defined, ComputeEngine, Pass, OctahedralProjectedCubeMap, } from "../../index.js"; -import { Cartesian3, defined } from "../../index.js"; import createContext from "../../../../Specs/createContext.js"; import createFrameState from "../../../../Specs/createFrameState.js"; diff --git a/packages/engine/Specs/Scene/OpenStreetMapImageryProviderSpec.js b/packages/engine/Specs/Scene/OpenStreetMapImageryProviderSpec.js index 4300e9d8d37..b097f2c020e 100644 --- a/packages/engine/Specs/Scene/OpenStreetMapImageryProviderSpec.js +++ b/packages/engine/Specs/Scene/OpenStreetMapImageryProviderSpec.js @@ -1,4 +1,5 @@ import { + Math as CesiumMath, Rectangle, Request, RequestScheduler, @@ -10,7 +11,6 @@ import { ImageryState, UrlTemplateImageryProvider, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; import pollToPromise from "../../../../Specs/pollToPromise.js"; diff --git a/packages/engine/Specs/Scene/PickingSpec.js b/packages/engine/Specs/Scene/PickingSpec.js index bbf53c690f6..362fb4ca53b 100644 --- a/packages/engine/Specs/Scene/PickingSpec.js +++ b/packages/engine/Specs/Scene/PickingSpec.js @@ -6,6 +6,7 @@ import { Color, Ellipsoid, GeometryInstance, + Math as CesiumMath, Matrix4, OrthographicFrustum, PerspectiveFrustum, @@ -23,8 +24,6 @@ import { VoxelPrimitive, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import Cesium3DTilesTester from "../../../../Specs/Cesium3DTilesTester.js"; import createCanvas from "../../../../Specs/createCanvas.js"; import createScene from "../../../../Specs/createScene.js"; diff --git a/packages/engine/Specs/Scene/PointCloudEyeDomeLightingSpec.js b/packages/engine/Specs/Scene/PointCloudEyeDomeLightingSpec.js index 2b502bb8ddd..7668c5c4d02 100644 --- a/packages/engine/Specs/Scene/PointCloudEyeDomeLightingSpec.js +++ b/packages/engine/Specs/Scene/PointCloudEyeDomeLightingSpec.js @@ -2,12 +2,11 @@ import { Cartesian3, Cesium3DTileStyle, HeadingPitchRange, + Math as CesiumMath, PerspectiveFrustum, PointCloudEyeDomeLighting, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import Cesium3DTilesTester from "../../../../Specs/Cesium3DTilesTester.js"; import createScene from "../../../../Specs/createScene.js"; diff --git a/packages/engine/Specs/Scene/PointPrimitiveCollectionSpec.js b/packages/engine/Specs/Scene/PointPrimitiveCollectionSpec.js index fc5844f0bdf..bbe04eebdd3 100644 --- a/packages/engine/Specs/Scene/PointPrimitiveCollectionSpec.js +++ b/packages/engine/Specs/Scene/PointPrimitiveCollectionSpec.js @@ -5,6 +5,7 @@ import { Cartesian3, Color, DistanceDisplayCondition, + Math as CesiumMath, NearFarScalar, Rectangle, BlendOption, @@ -12,8 +13,6 @@ import { PointPrimitiveCollection, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createScene from "../../../../Specs/createScene.js"; describe( diff --git a/packages/engine/Specs/Scene/PolylineCollectionSpec.js b/packages/engine/Specs/Scene/PolylineCollectionSpec.js index d931227c045..f237f0a4aef 100644 --- a/packages/engine/Specs/Scene/PolylineCollectionSpec.js +++ b/packages/engine/Specs/Scene/PolylineCollectionSpec.js @@ -4,6 +4,7 @@ import { Color, DistanceDisplayCondition, HeadingPitchRange, + Math as CesiumMath, Matrix4, Camera, Material, @@ -11,8 +12,6 @@ import { SceneMode, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createScene from "../../../../Specs/createScene.js"; describe( diff --git a/packages/engine/Specs/Scene/PrimitiveCullingSpec.js b/packages/engine/Specs/Scene/PrimitiveCullingSpec.js index 7fd59d356f3..e9f311e4b55 100644 --- a/packages/engine/Specs/Scene/PrimitiveCullingSpec.js +++ b/packages/engine/Specs/Scene/PrimitiveCullingSpec.js @@ -5,6 +5,7 @@ import { defaultValue, defined, GeometryInstance, + Math as CesiumMath, PerspectiveFrustum, Rectangle, RectangleGeometry, @@ -22,8 +23,6 @@ import { VerticalOrigin, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createScene from "../../../../Specs/createScene.js"; import pollToPromise from "../../../../Specs/pollToPromise.js"; diff --git a/packages/engine/Specs/Scene/PrimitiveSpec.js b/packages/engine/Specs/Scene/PrimitiveSpec.js index 4c229a09a1e..c218d444315 100644 --- a/packages/engine/Specs/Scene/PrimitiveSpec.js +++ b/packages/engine/Specs/Scene/PrimitiveSpec.js @@ -13,6 +13,7 @@ import { GeometryInstance, GeometryInstanceAttribute, HeadingPitchRange, + Math as CesiumMath, Matrix4, PerspectiveFrustum, PolygonGeometry, @@ -28,8 +29,6 @@ import { SceneMode, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import BadGeometry from "../../../../Specs/BadGeometry.js"; import createContext from "../../../../Specs/createContext.js"; import createFrameState from "../../../../Specs/createFrameState.js"; diff --git a/packages/engine/Specs/Scene/QuadtreeTileSpec.js b/packages/engine/Specs/Scene/QuadtreeTileSpec.js index 350e5ca4816..2e6d6c7edcb 100644 --- a/packages/engine/Specs/Scene/QuadtreeTileSpec.js +++ b/packages/engine/Specs/Scene/QuadtreeTileSpec.js @@ -1,12 +1,11 @@ import { GeographicTilingScheme, Rectangle, + Math as CesiumMath, WebMercatorTilingScheme, QuadtreeTile, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - describe("Scene/QuadtreeTile", function () { it("throws without a options", function () { expect(function () { diff --git a/packages/engine/Specs/Scene/SceneSpec.js b/packages/engine/Specs/Scene/SceneSpec.js index 99f09001915..7e3fc5fdaa6 100644 --- a/packages/engine/Specs/Scene/SceneSpec.js +++ b/packages/engine/Specs/Scene/SceneSpec.js @@ -11,6 +11,7 @@ import { GeometryInstance, HeadingPitchRoll, JulianDate, + Math as CesiumMath, PixelFormat, Rectangle, RectangleGeometry, @@ -48,8 +49,6 @@ import { Resource, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createCanvas from "../../../../Specs/createCanvas.js"; import createScene from "../../../../Specs/createScene.js"; import pollToPromise from "../../../../Specs/pollToPromise.js"; diff --git a/packages/engine/Specs/Scene/SceneTransformsSpec.js b/packages/engine/Specs/Scene/SceneTransformsSpec.js index adaad81640a..0839423d89e 100644 --- a/packages/engine/Specs/Scene/SceneTransformsSpec.js +++ b/packages/engine/Specs/Scene/SceneTransformsSpec.js @@ -2,6 +2,7 @@ import { Cartesian2, Cartesian3, Ellipsoid, + Math as CesiumMath, OrthographicFrustum, Rectangle, Camera, @@ -9,8 +10,6 @@ import { SceneTransforms, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createScene from "../../../../Specs/createScene.js"; describe( diff --git a/packages/engine/Specs/Scene/ScreenSpaceCameraControllerSpec.js b/packages/engine/Specs/Scene/ScreenSpaceCameraControllerSpec.js index 5da26e0c64a..9611aac90c4 100644 --- a/packages/engine/Specs/Scene/ScreenSpaceCameraControllerSpec.js +++ b/packages/engine/Specs/Scene/ScreenSpaceCameraControllerSpec.js @@ -7,6 +7,7 @@ import { GeographicProjection, IntersectionTests, KeyboardEventModifier, + Math as CesiumMath, OrthographicFrustum, OrthographicOffCenterFrustum, Ray, @@ -18,8 +19,6 @@ import { ScreenSpaceCameraController, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createCamera from "../../../../Specs/createCamera.js"; import createCanvas from "../../../../Specs/createCanvas.js"; import DomEventSimulator from "../../../../Specs/DomEventSimulator.js"; diff --git a/packages/engine/Specs/Scene/ShadowMapSpec.js b/packages/engine/Specs/Scene/ShadowMapSpec.js index 231ea6088e7..762791743a0 100644 --- a/packages/engine/Specs/Scene/ShadowMapSpec.js +++ b/packages/engine/Specs/Scene/ShadowMapSpec.js @@ -12,6 +12,7 @@ import { HeadingPitchRoll, HeightmapTerrainData, JulianDate, + Math as CesiumMath, Matrix4, OrthographicOffCenterFrustum, PixelFormat, @@ -31,8 +32,6 @@ import { ShadowMode, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createScene from "../../../../Specs/createScene.js"; import pollToPromise from "../../../../Specs/pollToPromise.js"; diff --git a/packages/engine/Specs/Scene/ShadowVolumeAppearanceSpec.js b/packages/engine/Specs/Scene/ShadowVolumeAppearanceSpec.js index a24bad1fcbb..8eba7af6b61 100644 --- a/packages/engine/Specs/Scene/ShadowVolumeAppearanceSpec.js +++ b/packages/engine/Specs/Scene/ShadowVolumeAppearanceSpec.js @@ -4,6 +4,7 @@ import { ComponentDatatype, Ellipsoid, EncodedCartesian3, + Math as CesiumMath, Matrix4, Rectangle, Transforms, @@ -14,8 +15,6 @@ import { ShadowVolumeAppearance, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - describe("Scene/ShadowVolumeAppearance", function () { // using ShadowVolumeAppearanceVS directly fails on CI with the --release test const testVs = diff --git a/packages/engine/Specs/Scene/SkyAtmosphereSpec.js b/packages/engine/Specs/Scene/SkyAtmosphereSpec.js index b7be045cfd3..71a215cff6c 100644 --- a/packages/engine/Specs/Scene/SkyAtmosphereSpec.js +++ b/packages/engine/Specs/Scene/SkyAtmosphereSpec.js @@ -2,12 +2,11 @@ import { Cartesian3, DynamicAtmosphereLightingType, Ellipsoid, + Math as CesiumMath, SceneMode, SkyAtmosphere, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createScene from "../../../../Specs/createScene.js"; describe( diff --git a/packages/engine/Specs/Scene/SunSpec.js b/packages/engine/Specs/Scene/SunSpec.js index f892f6e0a37..caa9fd39793 100644 --- a/packages/engine/Specs/Scene/SunSpec.js +++ b/packages/engine/Specs/Scene/SunSpec.js @@ -1,6 +1,10 @@ -import { BoundingSphere, Color, SceneMode, Sun } from "../../index.js"; - -import { Math as CesiumMath } from "../../index.js"; +import { + BoundingSphere, + Color, + Math as CesiumMath, + SceneMode, + Sun, +} from "../../index.js"; import createScene from "../../../../Specs/createScene.js"; diff --git a/packages/engine/Specs/Scene/TerrainFillMeshSpec.js b/packages/engine/Specs/Scene/TerrainFillMeshSpec.js index 0d604f43b21..cf3589dd19a 100644 --- a/packages/engine/Specs/Scene/TerrainFillMeshSpec.js +++ b/packages/engine/Specs/Scene/TerrainFillMeshSpec.js @@ -4,6 +4,7 @@ import { GeographicProjection, HeightmapTerrainData, Intersect, + Math as CesiumMath, Camera, GlobeSurfaceTileProvider, ImageryLayerCollection, @@ -16,8 +17,6 @@ import { import MockTerrainProvider from "../../../../Specs/MockTerrainProvider.js"; import TerrainTileProcessor from "../../../../Specs/TerrainTileProcessor.js"; -import { Math as CesiumMath } from "../../index.js"; - describe("Scene/TerrainFillMesh", function () { let processor; let scene; diff --git a/packages/engine/Specs/Scene/TileBoundingRegionSpec.js b/packages/engine/Specs/Scene/TileBoundingRegionSpec.js index eda4730996d..92beba6e486 100644 --- a/packages/engine/Specs/Scene/TileBoundingRegionSpec.js +++ b/packages/engine/Specs/Scene/TileBoundingRegionSpec.js @@ -6,14 +6,13 @@ import { Ellipsoid, GeographicTilingScheme, Intersect, + Math as CesiumMath, Plane, Rectangle, SceneMode, TileBoundingRegion, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createFrameState from "../../../../Specs/createFrameState.js"; describe("Scene/TileBoundingRegion", function () { diff --git a/packages/engine/Specs/Scene/TileBoundingS2CellSpec.js b/packages/engine/Specs/Scene/TileBoundingS2CellSpec.js index 4777629003c..61f0d8f20f1 100644 --- a/packages/engine/Specs/Scene/TileBoundingS2CellSpec.js +++ b/packages/engine/Specs/Scene/TileBoundingS2CellSpec.js @@ -3,13 +3,12 @@ import { Color, Ellipsoid, Intersect, + Math as CesiumMath, Plane, S2Cell, TileBoundingS2Cell, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createFrameState from "../../../../Specs/createFrameState.js"; describe("Scene/TileBoundingS2Cell", function () { diff --git a/packages/engine/Specs/Scene/TileBoundingSphereSpec.js b/packages/engine/Specs/Scene/TileBoundingSphereSpec.js index 05164ba32e6..32c87cb0078 100644 --- a/packages/engine/Specs/Scene/TileBoundingSphereSpec.js +++ b/packages/engine/Specs/Scene/TileBoundingSphereSpec.js @@ -2,12 +2,11 @@ import { Cartesian3, Color, Intersect, + Math as CesiumMath, Plane, TileBoundingSphere, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createFrameState from "../../../../Specs/createFrameState.js"; describe("Scene/TileBoundingSphere", function () { diff --git a/packages/engine/Specs/Scene/TileMapServiceImageryProviderSpec.js b/packages/engine/Specs/Scene/TileMapServiceImageryProviderSpec.js index 293813ecca8..72494dceb68 100644 --- a/packages/engine/Specs/Scene/TileMapServiceImageryProviderSpec.js +++ b/packages/engine/Specs/Scene/TileMapServiceImageryProviderSpec.js @@ -4,6 +4,7 @@ import { GeographicProjection, GeographicTilingScheme, getAbsoluteUri, + Math as CesiumMath, Rectangle, Request, RequestErrorEvent, @@ -19,8 +20,6 @@ import { UrlTemplateImageryProvider, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import pollToPromise from "../../../../Specs/pollToPromise.js"; describe("Scene/TileMapServiceImageryProvider", function () { diff --git a/packages/engine/Specs/Scene/TileOrientedBoundingBoxSpec.js b/packages/engine/Specs/Scene/TileOrientedBoundingBoxSpec.js index 9748bfd03c3..91ad1dbfc72 100644 --- a/packages/engine/Specs/Scene/TileOrientedBoundingBoxSpec.js +++ b/packages/engine/Specs/Scene/TileOrientedBoundingBoxSpec.js @@ -2,13 +2,12 @@ import { Cartesian3, Color, Intersect, + Math as CesiumMath, Matrix3, Plane, TileOrientedBoundingBox, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createFrameState from "../../../../Specs/createFrameState.js"; describe("Scene/TileOrientedBoundingBox", function () { diff --git a/packages/engine/Specs/Scene/UrlTemplateImageryProviderSpec.js b/packages/engine/Specs/Scene/UrlTemplateImageryProviderSpec.js index eabc3f55f44..a7e6e2a3761 100644 --- a/packages/engine/Specs/Scene/UrlTemplateImageryProviderSpec.js +++ b/packages/engine/Specs/Scene/UrlTemplateImageryProviderSpec.js @@ -1,6 +1,7 @@ import { Ellipsoid, GeographicTilingScheme, + Math as CesiumMath, Rectangle, Request, RequestScheduler, @@ -15,8 +16,6 @@ import { UrlTemplateImageryProvider, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import pollToPromise from "../../../../Specs/pollToPromise.js"; describe("Scene/UrlTemplateImageryProvider", function () { diff --git a/packages/engine/Specs/Scene/Vector3DTilePointsSpec.js b/packages/engine/Specs/Scene/Vector3DTilePointsSpec.js index c1a22dfedf6..eb701fc8236 100644 --- a/packages/engine/Specs/Scene/Vector3DTilePointsSpec.js +++ b/packages/engine/Specs/Scene/Vector3DTilePointsSpec.js @@ -8,6 +8,7 @@ import { defined, DistanceDisplayCondition, Ellipsoid, + Math as CesiumMath, NearFarScalar, Rectangle, Cesium3DTileBatchTable, @@ -19,8 +20,6 @@ import { VerticalOrigin, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createScene from "../../../../Specs/createScene.js"; import pollToPromise from "../../../../Specs/pollToPromise.js"; diff --git a/packages/engine/Specs/Scene/Vector3DTilePolylinesSpec.js b/packages/engine/Specs/Scene/Vector3DTilePolylinesSpec.js index 7a82e8db713..1ca2cffad46 100644 --- a/packages/engine/Specs/Scene/Vector3DTilePolylinesSpec.js +++ b/packages/engine/Specs/Scene/Vector3DTilePolylinesSpec.js @@ -3,14 +3,13 @@ import { Cartesian3, Cartographic, Ellipsoid, + Math as CesiumMath, Rectangle, Cesium3DTileBatchTable, ColorBlendMode, Vector3DTilePolylines, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createScene from "../../../../Specs/createScene.js"; import pollToPromise from "../../../../Specs/pollToPromise.js"; diff --git a/packages/engine/Specs/Scene/WebMapServiceImageryProviderSpec.js b/packages/engine/Specs/Scene/WebMapServiceImageryProviderSpec.js index 320052224e0..fe750f3c434 100644 --- a/packages/engine/Specs/Scene/WebMapServiceImageryProviderSpec.js +++ b/packages/engine/Specs/Scene/WebMapServiceImageryProviderSpec.js @@ -12,6 +12,7 @@ import { ImageryProvider, ImageryState, JulianDate, + Math as CesiumMath, queryToObject, Rectangle, Request, @@ -23,8 +24,6 @@ import { WebMercatorTilingScheme, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import pollToPromise from "../../../../Specs/pollToPromise.js"; describe("Scene/WebMapServiceImageryProvider", function () { diff --git a/packages/engine/Specs/Scene/createElevationBandMaterialSpec.js b/packages/engine/Specs/Scene/createElevationBandMaterialSpec.js index b0bb626bf89..1b1ee0ee4a7 100644 --- a/packages/engine/Specs/Scene/createElevationBandMaterialSpec.js +++ b/packages/engine/Specs/Scene/createElevationBandMaterialSpec.js @@ -2,13 +2,12 @@ import { Cartesian4, Color, createElevationBandMaterial, + Math as CesiumMath, PixelFormat, Texture, TextureMinificationFilter, } from "../../index.js"; -import { Math as CesiumMath } from "../../index.js"; - import createScene from "../../../../Specs/createScene.js"; describe("Scene/createElevationBandMaterial", function () { diff --git a/packages/engine/package.json b/packages/engine/package.json index 46ac0a1772d..91727f56299 100644 --- a/packages/engine/package.json +++ b/packages/engine/package.json @@ -1,6 +1,6 @@ { "name": "@cesium/engine", - "version": "9.1.0", + "version": "9.2.0", "description": "CesiumJS is a JavaScript library for creating 3D globes and 2D maps in a web browser without a plugin.", "keywords": [ "3D", diff --git a/packages/widgets/Specs/.eslintrc.json b/packages/widgets/Specs/.eslintrc.json deleted file mode 100644 index 5b6725648bf..00000000000 --- a/packages/widgets/Specs/.eslintrc.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "../../.eslintrc.json", - "env": { - "jasmine": true - }, - "rules": { - "no-self-assign": "off", - "no-duplicate-imports": "off" - } -} \ No newline at end of file diff --git a/packages/widgets/Specs/I3SBSLExplorer/I3SBSLExplorerViewModelSpec.js b/packages/widgets/Specs/I3SBSLExplorer/I3SBSLExplorerViewModelSpec.js index 94ecb6361b2..8d8c22af3c4 100644 --- a/packages/widgets/Specs/I3SBSLExplorer/I3SBSLExplorerViewModelSpec.js +++ b/packages/widgets/Specs/I3SBSLExplorer/I3SBSLExplorerViewModelSpec.js @@ -1,6 +1,7 @@ -import { I3SBuildingSceneLayerExplorerViewModel } from "../../index.js"; - -import { knockout } from "../../index.js"; +import { + I3SBuildingSceneLayerExplorerViewModel, + knockout, +} from "../../index.js"; describe("Widgets/I3SBuildingSceneLayerExplorer/I3SBuildingSceneLayerExplorerViewModel", function () { const i3sProvider = { diff --git a/packages/widgets/package.json b/packages/widgets/package.json index 0832b3e0536..7e157710951 100644 --- a/packages/widgets/package.json +++ b/packages/widgets/package.json @@ -28,7 +28,7 @@ "node": ">=14.0.0" }, "dependencies": { - "@cesium/engine": "^9.1.0", + "@cesium/engine": "^9.2.0", "nosleep.js": "^0.12.0" }, "type": "module", @@ -52,4 +52,4 @@ "bugs": { "url": "https://github.com/CesiumGS/cesium/issues" } -} +} \ No newline at end of file diff --git a/scripts/build.js b/scripts/build.js index 4a35e6a3eb0..a28de85995a 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -1,17 +1,16 @@ -/*eslint-env node*/ import child_process from "child_process"; import { existsSync, readFileSync, statSync } from "fs"; import { readFile, writeFile } from "fs/promises"; import { EOL } from "os"; import path from "path"; import { createRequire } from "module"; +import { finished } from 'stream/promises'; import esbuild from "esbuild"; import { globby } from "globby"; import glslStripComments from "glsl-strip-comments"; import gulp from "gulp"; import { rimraf } from "rimraf"; -import streamToPromise from "stream-to-promise"; import { mkdirp } from "mkdirp"; @@ -640,7 +639,7 @@ export async function createGalleryList(noDevelopmentGallery) { .toString() .trim() .split("\n"); - } catch (e) { + } catch { // On a Cesium fork, tags don't exist so we can't generate the list. } @@ -715,10 +714,11 @@ const has_new_gallery_demos = ${newDemos.length > 0 ? "true;" : "false;"}\n`; */ export async function copyFiles(globs, destination, base) { const stream = gulp - .src(globs, { nodir: true, base: base ?? "" }) + .src(globs, { nodir: true, base: base ?? "", encoding: false }) .pipe(gulp.dest(destination)); - return streamToPromise(stream); + await finished(stream); + return stream; } /** diff --git a/server.js b/server.js index 590470ef1ba..057beb0f0d9 100644 --- a/server.js +++ b/server.js @@ -1,4 +1,3 @@ -/*eslint-env node*/ import fs from "fs"; import path from "path"; import { performance } from "perf_hooks";