import defined from "../../Core/defined.js"; import ShaderDestination from "../../Renderer/ShaderDestination.js"; import ModelExperimentalUtility from "./ModelExperimentalUtility.js"; /** * The dequantization stage generates shader code to dequantize attributes * in the vertex shader * * @namespace DequantizationPipelineStage * * @private */ var DequantizationPipelineStage = {}; DequantizationPipelineStage.name = "DequantizationPipelineStage"; // Helps with debugging DequantizationPipelineStage.FUNCTION_ID_DEQUANTIZATION_STAGE_VS = "dequantizationStage"; DequantizationPipelineStage.FUNCTION_SIGNATURE_DEQUANTIZATION_STAGE_VS = "void dequantizationStage(inout ProcessedAttributes attributes)"; /** * Process a primitive with quantized attributes. This stage modifies the * following parts of the render resources: * * * @param {PrimitiveRenderResources} renderResources The render resources for this primitive. * @param {ModelComponents.Primitive} primitive The primitive * * @private */ DequantizationPipelineStage.process = function (renderResources, primitive) { var shaderBuilder = renderResources.shaderBuilder; shaderBuilder.addFunction( DequantizationPipelineStage.FUNCTION_ID_DEQUANTIZATION_STAGE_VS, DequantizationPipelineStage.FUNCTION_SIGNATURE_DEQUANTIZATION_STAGE_VS, ShaderDestination.VERTEX ); shaderBuilder.addDefine( "USE_DEQUANTIZATION", undefined, ShaderDestination.VERTEX ); var attributes = primitive.attributes; for (var i = 0; i < attributes.length; i++) { var attribute = attributes[i]; var quantization = attribute.quantization; if (!defined(quantization)) { // non-quantized attributes were already handled in GeometryPipelineStage continue; } var attributeInfo = ModelExperimentalUtility.getAttributeInfo(attribute); updateDequantizationFunction(shaderBuilder, attributeInfo); addDequantizationUniforms(renderResources, attributeInfo); } }; function addDequantizationUniforms(renderResources, attributeInfo) { var shaderBuilder = renderResources.shaderBuilder; var uniformMap = renderResources.uniformMap; var variableName = attributeInfo.variableName; var quantization = attributeInfo.attribute.quantization; if (quantization.octEncoded) { var normalizationRange = "model_normalizationRange_" + variableName; shaderBuilder.addUniform( "float", normalizationRange, ShaderDestination.VERTEX ); uniformMap[normalizationRange] = function () { return quantization.normalizationRange; }; } else { var offset = "model_quantizedVolumeOffset_" + variableName; var stepSize = "model_quantizedVolumeStepSize_" + variableName; var glslType = attributeInfo.glslType; shaderBuilder.addUniform(glslType, offset, ShaderDestination.VERTEX); shaderBuilder.addUniform(glslType, stepSize, ShaderDestination.VERTEX); uniformMap[offset] = function () { return quantization.quantizedVolumeOffset; }; uniformMap[stepSize] = function () { return quantization.quantizedVolumeStepSize; }; } } function updateDequantizationFunction(shaderBuilder, attributeInfo) { var variableName = attributeInfo.variableName; var quantization = attributeInfo.attribute.quantization; var line; if (quantization.octEncoded) { line = generateOctDecodeLine(variableName, quantization); } else { line = generateDequantizeLine(variableName); } shaderBuilder.addFunctionLines( DequantizationPipelineStage.FUNCTION_ID_DEQUANTIZATION_STAGE_VS, [line] ); } function generateOctDecodeLine(variableName, quantization) { var structField = "attributes." + variableName; var quantizedAttribute = "a_quantized_" + variableName; var normalizationRange = "model_normalizationRange_" + variableName; // Draco stores things as .zxy instead of xyz, so be explicit about the // swizzle to avoid confusion var swizzle = quantization.octEncodedZXY ? ".zxy" : ".xyz"; // This generates lines such as: // attributes.normal = czm_octDecode(a_quantized_normal, model_normalizationRange_normal).zxy; return ( structField + " = czm_octDecode(" + quantizedAttribute + ", " + normalizationRange + ")" + swizzle + ";" ); } function generateDequantizeLine(variableName) { var structField = "attributes." + variableName; var quantizedAttribute = "a_quantized_" + variableName; var offset = "model_quantizedVolumeOffset_" + variableName; var stepSize = "model_quantizedVolumeStepSize_" + variableName; // This generates lines such as: // attributes.texCoord_0 = model_quantizedVolumeOffset_texCoord_0 + a_quantized_texCoord_0 * model_quantizedVolumeStepSize; return ( structField + " = " + offset + " + " + quantizedAttribute + " * " + stepSize + ";" ); } export default DequantizationPipelineStage;