UNPKG

@cesium/engine

Version:

CesiumJS is a JavaScript library for creating 3D globes and 2D maps in a web browser without a plugin.

110 lines (98 loc) 3.69 kB
import combine from "../../Core/combine.js"; import defined from "../../Core/defined.js"; import ShaderDestination from "../../Renderer/ShaderDestination.js"; import ModelSilhouetteStageFS from "../../Shaders/Model/ModelSilhouetteStageFS.js"; import ModelSilhouetteStageVS from "../../Shaders/Model/ModelSilhouetteStageVS.js"; /** * The model silhouette pipeline stage is responsible applying silhouettes to the model. * * @namespace ModelSilhouettePipelineStage * * @private */ const ModelSilhouettePipelineStage = { name: "ModelSilhouettePipelineStage", // Helps with debugging }; /** * Tracks how many silhouettes have been created. This value is used to * assign a reference number to the stencil. * * @type {number} * @private */ ModelSilhouettePipelineStage.silhouettesLength = 0; /** * Process a model. This modifies the following parts of the render resources: * * <ul> * <li>defines the silhouette ID for the model, if it doesn't yet exist * <li>adds a define to the shaders to indicate that the model uses silhouettes</li> * <li>adds a function to the vertex shader to create the silhouette around the model</li> * <li>adds a function to the fragment shader to apply color to the silhouette</li> * <li>adds the uniforms to the shaders for the corresponding silhouette properties</li> * <li>adds a uniform to distinguish which draw command is used to render the silhouette</li> * <li>sets a variable in the render resources denoting whether the model has a silhouette</li> * </ul> * * <p> * Note that the model must have a normal attribute in order to use silhouettes. The flag for this is * added to the shader in GeometryPipelineStage. * </p> * * @param {ModelRenderResources} renderResources The render resources for this model. * @param {Model} model The model. * @param {FrameState} frameState The frameState. * * @private */ ModelSilhouettePipelineStage.process = function ( renderResources, model, frameState, ) { if (!defined(model._silhouetteId)) { model._silhouetteId = ++ModelSilhouettePipelineStage.silhouettesLength; } const shaderBuilder = renderResources.shaderBuilder; shaderBuilder.addDefine("HAS_SILHOUETTE", undefined, ShaderDestination.BOTH); shaderBuilder.addVertexLines(ModelSilhouetteStageVS); shaderBuilder.addFragmentLines(ModelSilhouetteStageFS); shaderBuilder.addUniform( "vec4", "model_silhouetteColor", ShaderDestination.FRAGMENT, ); shaderBuilder.addUniform( "float", "model_silhouetteSize", ShaderDestination.VERTEX, ); // Rendering silhouettes requires two draw commands: // - First, the model is rendered as normal, writing to the stencil buffer. // - Second, the silhouette is drawn, and the stencil buffer is used to cutout // the part that overlaps the regular model. // // To avoid creating a second shader program to handle silhouettes, a uniform // is used to distinguish between the two draw commands. The second command will set // this uniform true, such that only it applies the silhouette stage. shaderBuilder.addUniform( "bool", "model_silhouettePass", ShaderDestination.BOTH, ); const uniformMap = { model_silhouetteColor: function () { return model.silhouetteColor; }, model_silhouetteSize: function () { return model.silhouetteSize; }, model_silhouettePass: function () { // This will be set to true by the draw command that draws the silhouette. return false; }, }; renderResources.uniformMap = combine(uniformMap, renderResources.uniformMap); renderResources.hasSilhouette = true; }; export default ModelSilhouettePipelineStage;