Allow hot-swapping CustomShaders for models and tilesets

This commit is contained in:
Peter Gagliardi 2021-10-28 16:31:18 -04:00
parent 3d7a7fb14b
commit 557ca328b0
4 changed files with 66 additions and 14 deletions

View File

@ -951,15 +951,7 @@ function Cesium3DTileset(options) {
*/
this.metadata = undefined;
/**
* A custom shader to apply to the tileset. Only used for contents that use
* {@link ModelExperimental}
*
* @type {CustomShader}
* @private
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*/
this.customShader = options.customShader;
this._customShader = options.customShader;
this._schemaLoader = undefined;
@ -1331,6 +1323,36 @@ Object.defineProperties(Cesium3DTileset.prototype, {
},
},
/**
* A custom shader to apply to the tileset. Only used for contents that use
* {@link ModelExperimental}
*
* @memberof Cesium3DTileset.prototype
*
* @type {CustomShader|undefined}
*
* @default undefined
*
* @private
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*/
customShader: {
get: function () {
return this._customShader;
},
set: function (value) {
//>>includeStart('debug', pragmas.debug);
if (defined(this.style) && defined(value)) {
throw new DeveloperError(
"Custom shaders and style cannot be applied at the same time."
);
}
//>>includeEnd('debug');
this._customShader = value;
},
},
/**
* The maximum screen space error used to drive level of detail refinement. This value helps determine when a tile
* refines to its descendants, and therefore plays a major role in balancing performance with visual quality.

View File

@ -295,6 +295,20 @@ Object.defineProperties(ModelExperimental.prototype, {
get: function () {
return this._customShader;
},
set: function (value) {
//>>includeStart('debug', pragmas.debug);
if (defined(this._style) && defined(value)) {
throw new DeveloperError(
"Custom shaders and style cannot be applied at the same time."
);
}
//>>includeEnd('debug');
if (value !== this._customShader) {
this.resetDrawCommands();
}
this._customShader = value;
},
},
/**
@ -622,6 +636,13 @@ ModelExperimental.prototype.update = function (frameState) {
this._loader.process(frameState);
}
// Update the custom shader. if the value changed, this will recreate
// the primitive pipeline.
if (defined(this._content)) {
var tileset = this._content.tileset;
this.customShader = tileset.customShader;
}
// A custom shader may have to load texture uniforms.
if (defined(this._customShader)) {
this._customShader.update(frameState);

View File

@ -5,7 +5,6 @@ import CustomShaderMode from "./CustomShaderMode.js";
import defaultValue from "../../Core/defaultValue.js";
import defined from "../../Core/defined.js";
import FeatureIdPipelineStage from "./FeatureIdPipelineStage.js";
import CustomShaderPipelineStage from "./CustomShaderPipelineStage.js";
import DequantizationPipelineStage from "./DequantizationPipelineStage.js";
import GeometryPipelineStage from "./GeometryPipelineStage.js";
import LightingPipelineStage from "./LightingPipelineStage.js";
@ -105,10 +104,6 @@ function initialize(runtimePrimitive) {
pipelineStages.push(MaterialPipelineStage);
}
if (hasCustomShader) {
pipelineStages.push(CustomShaderPipelineStage);
}
pipelineStages.push(LightingPipelineStage);
// Add the FeatureIdPipelineStage and BatchTexturePipelineStage when the primitive has features, i.e. when at least one of the following conditions exists:

View File

@ -5,6 +5,8 @@ import CPUStylingPipelineStage from "./CPUStylingPipelineStage.js";
import defaultValue from "../../Core/defaultValue.js";
import defined from "../../Core/defined.js";
import Matrix4 from "../../Core/Matrix4.js";
import CustomShaderPipelineStage from "./CustomShaderPipelineStage.js";
import LightingPipelineStage from "./LightingPipelineStage.js";
import ModelColorPipelineStage from "./ModelColorPipelineStage.js";
import ModelExperimentalPrimitive from "./ModelExperimentalPrimitive.js";
import ModelExperimentalNode from "./ModelExperimentalNode.js";
@ -239,6 +241,18 @@ ModelExperimentalSceneGraph.prototype.buildDrawCommands = function (
);
}
if (defined(model.customShader) && !defined(model.style)) {
// The custom shader stage needs to go before the lighting stage.
var lightingStageIndex = primitivePipelineStages.indexOf(
LightingPipelineStage
);
primitivePipelineStages.splice(
lightingStageIndex,
0,
CustomShaderPipelineStage
);
}
var primitiveRenderResources = new PrimitiveRenderResources(
nodeRenderResources,
runtimePrimitive