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:
*
* - generates dequantization function and adds it to the shader
* - adds any uniforms needed for dequantization to the shader and uniform map
*
*
* @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;