import BlendingState from "../BlendingState.js"; import clone from "../../Core/clone.js"; import defined from "../../Core/defined.js"; import DrawCommand from "../../Renderer/DrawCommand.js"; import ModelExperimentalFS from "../../Shaders/ModelExperimental/ModelExperimentalFS.js"; import ModelExperimentalVS from "../../Shaders/ModelExperimental/ModelExperimentalVS.js"; import Pass from "../../Renderer/Pass.js"; import RenderState from "../../Renderer/RenderState.js"; import RuntimeError from "../../Core/RuntimeError.js"; import StyleCommandsNeeded from "./StyleCommandsNeeded.js"; import VertexArray from "../../Renderer/VertexArray.js"; /** * Builds the DrawCommands for a {@link ModelExperimentalPrimitive} using its render resources. * * @param {PrimitiveRenderResources} primitiveRenderResources The render resources for a primitive. * @param {FrameState} frameState The frame state for creating GPU resources. * * @returns {DrawCommand[]} The generated DrawCommands. * * @private */ export default function buildDrawCommands( primitiveRenderResources, frameState ) { var shaderBuilder = primitiveRenderResources.shaderBuilder; shaderBuilder.addVertexLines([ModelExperimentalVS]); shaderBuilder.addFragmentLines([ModelExperimentalFS]); var indexBuffer = defined(primitiveRenderResources.indices) ? primitiveRenderResources.indices.buffer : undefined; var vertexArray = new VertexArray({ context: frameState.context, indexBuffer: indexBuffer, attributes: primitiveRenderResources.attributes, }); var model = primitiveRenderResources.model; model._resources.push(vertexArray); var renderState = RenderState.fromCache( primitiveRenderResources.renderStateOptions ); var shaderProgram = shaderBuilder.buildShaderProgram(frameState.context); model._resources.push(shaderProgram); var pass = primitiveRenderResources.alphaOptions.pass; var command = new DrawCommand({ boundingVolume: primitiveRenderResources.boundingSphere, modelMatrix: primitiveRenderResources.modelMatrix, uniformMap: primitiveRenderResources.uniformMap, renderState: renderState, vertexArray: vertexArray, shaderProgram: shaderProgram, cull: model.cull, pass: pass, count: primitiveRenderResources.count, pickId: primitiveRenderResources.pickId, instanceCount: primitiveRenderResources.instanceCount, primitiveType: primitiveRenderResources.primitiveType, debugShowBoundingVolume: model.debugShowBoundingVolume, }); var styleCommandsNeeded = primitiveRenderResources.styleCommandsNeeded; var commandList = []; if (defined(styleCommandsNeeded)) { var derivedCommands = createDerivedCommands(command); if (pass !== Pass.TRANSLUCENT) { switch (styleCommandsNeeded) { case StyleCommandsNeeded.ALL_OPAQUE: commandList.push(command); break; case StyleCommandsNeeded.ALL_TRANSLUCENT: commandList.push(derivedCommands.translucent); break; case StyleCommandsNeeded.OPAQUE_AND_TRANSLUCENT: // Push both opaque and translucent commands. The rendering of features based on opacity is handled in the shaders. commandList.push(command, derivedCommands.translucent); break; //>>includeStart('debug', pragmas.debug); default: throw new RuntimeError("styleCommandsNeeded is not a valid value."); //>>includeEnd('debug'); } } else { // Command was originally translucent so no need to derive new commands; // as of now, a style can't change an originally translucent feature to // opaque since the style's alpha is modulated, not a replacement. When // this changes, we need to derive new opaque commands here. commandList.push(command); } } else { commandList.push(command); } return commandList; } /** * @private */ function createDerivedCommands(command) { var derivedCommands = {}; derivedCommands.translucent = deriveTranslucentCommand(command); return derivedCommands; } /** * @private */ function deriveTranslucentCommand(command) { var derivedCommand = DrawCommand.shallowClone(command); derivedCommand.pass = Pass.TRANSLUCENT; var rs = clone(command.renderState, true); rs.cull.enabled = false; rs.depthTest.enabled = true; rs.depthMask = false; rs.blending = BlendingState.ALPHA_BLEND; derivedCommand.renderState = RenderState.fromCache(rs); return derivedCommand; }