Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance tile skirts light occlusion #11460

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
- Implemented sharper rendering and lighting on voxels with CYLINDER and ELLIPSOID shape. [#11875](https://github.com/CesiumGS/cesium/pull/11875)
- Implemented vertical exaggeration for voxels with BOX shape. [#11887](https://github.com/CesiumGS/cesium/pull/11887)
- Added the `Check` object of validators to the public api and types. [#11901](https://github.com/CesiumGS/cesium/pull/11901)
- Added an optional property 'extendedSkirts' to `CesiumTerrainProvider`to enable extended skirts on tiles, improving light occlusion when shadows are enabled. [#11459][https://github.com/cesiumgs/cesium/issues/11459]

##### Fixes :wrench:

Expand Down
24 changes: 24 additions & 0 deletions packages/engine/Source/Core/CesiumTerrainProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ function LayerInformation(layer) {
* @property {boolean} [requestVertexNormals=false] Flag that indicates if the client should request additional lighting information from the server, in the form of per vertex normals if available.
* @property {boolean} [requestWaterMask=false] Flag that indicates if the client should request per tile water masks from the server, if available.
* @property {boolean} [requestMetadata=true] Flag that indicates if the client should request per tile metadata from the server, if available.
* @property {boolean} [extendedSkirts=false] Flag that indicates if the tile should have extended skirts for better light occlusion when shadows are enabled.
* @property {Ellipsoid} [ellipsoid] The ellipsoid. If not specified, the WGS84 ellipsoid is used.
* @property {Credit|string} [credit] A credit for the data source, which is displayed on the canvas.
*/
Expand Down Expand Up @@ -503,6 +504,15 @@ function CesiumTerrainProvider(options) {
*/
this._requestWaterMask = defaultValue(options.requestWaterMask, false);

/**
* Boolean flag that indicates if the tile should have extended skirts for better light occlusion
* when shadows are enabled.
* @type {boolean}
* @default false
* @private
*/
this._extendedSkirts = defaultValue(options.extendedSkirts, false);

/**
* Boolean flag that indicates if the client should request tile metadata from the server.
* @type {boolean}
Expand Down Expand Up @@ -834,6 +844,7 @@ function createQuantizedMeshTerrainData(provider, buffer, level, x, y, layer) {
childTileMask: provider.availability.computeChildMaskForTile(level, x, y),
waterMask: waterMaskBuffer,
credits: provider._tileCredits,
extendedSkirts: provider._extendedSkirts,
});
}

Expand Down Expand Up @@ -1140,6 +1151,19 @@ Object.defineProperties(CesiumTerrainProvider.prototype, {
return this._availability;
},
},

/**
* Gets a value indicating whether or not the requested tiles include extended skirts.
* Extended skirts are used for better light occlusion when shadows are enabled.
* @memberof CesiumTerrainProvider.prototype
* @type {boolean}
* @readonly
*/
extendedSkirts: {
get: function () {
return this._extendedSkirts;
},
},
});

/**
Expand Down
6 changes: 6 additions & 0 deletions packages/engine/Source/Core/QuantizedMeshTerrainData.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ import TerrainMesh from "./TerrainMesh.js";
* @param {Uint8Array} [options.encodedNormals] The buffer containing per vertex normals, encoded using 'oct' encoding
* @param {Uint8Array} [options.waterMask] The buffer containing the watermask.
* @param {Credit[]} [options.credits] Array of credits for this tile.
* @param {boolean} [options.extendedSkirts=false] True if the tile has extended skirts for better light occlusion when shadows are enabled.
*
*
* @example
Expand Down Expand Up @@ -203,6 +204,7 @@ function QuantizedMeshTerrainData(options) {

this._createdByUpsampling = defaultValue(options.createdByUpsampling, false);
this._waterMask = options.waterMask;
this._extendedSkirts = defaultValue(options.extendedSkirts, false);

this._mesh = undefined;
}
Expand Down Expand Up @@ -335,6 +337,8 @@ QuantizedMeshTerrainData.prototype.createMesh = function (options) {
ellipsoid: ellipsoid,
exaggeration: exaggeration,
exaggerationRelativeHeight: exaggerationRelativeHeight,
level: level,
extendedSkirts: this._extendedSkirts,
});

if (!defined(verticesPromise)) {
Expand Down Expand Up @@ -518,6 +522,7 @@ QuantizedMeshTerrainData.prototype.upsample = function (
? this._northSkirtHeight
: shortestSkirt * 0.5;
const credits = this._credits;
const extendedSkirts = this._extendedSkirts;

return Promise.resolve(upsamplePromise).then(function (result) {
const quantizedVertices = new Uint16Array(result.vertices);
Expand Down Expand Up @@ -552,6 +557,7 @@ QuantizedMeshTerrainData.prototype.upsample = function (
childTileMask: 0,
credits: credits,
createdByUpsampling: true,
extendedSkirts: extendedSkirts,
});
});
};
Expand Down
26 changes: 25 additions & 1 deletion packages/engine/Source/Core/TerrainProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,31 @@ TerrainProvider.addSkirtIndices = function (
offset
);
vertexIndex += eastIndicesNorthToSouth.length;
addSkirtIndices(northIndicesWestToEast, vertexIndex, indices, offset);
offset = addSkirtIndices(
northIndicesWestToEast,
vertexIndex,
indices,
offset
);
return offset;
};

TerrainProvider.addSkirtsBottomPlane = function (
WSVertexIndex,
WNVertexIndex,
ENVertexIndex,
ESVertexIndex,
indices,
offset
) {
// add triangles for bottom plane
indices[offset++] = WSVertexIndex;
indices[offset++] = WNVertexIndex;
indices[offset++] = ENVertexIndex;

indices[offset++] = WSVertexIndex;
indices[offset++] = ENVertexIndex;
indices[offset++] = ESVertexIndex;
};

function getEdgeIndices(width, height) {
Expand Down
2 changes: 2 additions & 0 deletions packages/engine/Source/Core/createWorldTerrainAsync.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import defaultValue from "./defaultValue.js";
* @param {Object} [options] Object with the following properties:
* @param {Boolean} [options.requestVertexNormals=false] Flag that indicates if the client should request additional lighting information from the server if available.
* @param {Boolean} [options.requestWaterMask=false] Flag that indicates if the client should request per tile water masks from the server if available.
* @param {Boolean} [options.extendedSkirts=false] Flag that indicates if the tiles should have extended skirts for better light occlusion when shadows are enabled.
* @returns {Promise<CesiumTerrainProvider>} A promise that resolves to the created CesiumTerrainProvider
*
* @see Ion
Expand Down Expand Up @@ -43,6 +44,7 @@ function createWorldTerrainAsync(options) {
return CesiumTerrainProvider.fromIonAssetId(1, {
requestVertexNormals: defaultValue(options.requestVertexNormals, false),
requestWaterMask: defaultValue(options.requestWaterMask, false),
extendedSkirts: defaultValue(options.extendedSkirts, false),
});
}
export default createWorldTerrainAsync;
17 changes: 16 additions & 1 deletion packages/engine/Source/Scene/GlobeSurfaceTile.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,22 @@ GlobeSurfaceTile.prototype.pick = function (
const vertices = mesh.vertices;
const indices = mesh.indices;
const encoding = mesh.encoding;
const indicesLength = indices.length;
let indicesLength = indices.length;

// do not consider skirts pixels for finding terrain interceptions
const edgeVertexCount =
mesh.westIndicesSouthToNorth.length +
mesh.eastIndicesNorthToSouth.length +
mesh.southIndicesEastToWest.length +
mesh.northIndicesWestToEast.length;
const edgeTriangleCount = Math.max(0, (edgeVertexCount - 4) * 2);
let skirtsIndexBufferLength = edgeTriangleCount * 3;
if (this.level >= 3) {
// 2 more triangles for bottom skirts plane
skirtsIndexBufferLength += 2 * 3;
}

indicesLength -= skirtsIndexBufferLength;

let minT = Number.MAX_VALUE;

Expand Down
1 change: 1 addition & 0 deletions packages/engine/Source/Scene/Terrain.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ Object.defineProperties(Terrain.prototype, {
* @param {Object} [options] Object with the following properties:
* @param {Boolean} [options.requestVertexNormals=false] Flag that indicates if the client should request additional lighting information from the server if available.
* @param {Boolean} [options.requestWaterMask=false] Flag that indicates if the client should request per tile water masks from the server if available.
* @param {Boolean} [options.extendedSkirts=false] Flag that indicates if the tiles should have extended skirts for better light occlusion when shadows are enabled.
* @returns {Terrain} An asynchronous helper object for a CesiumTerrainProvider
*
* @see Ion
Expand Down