yzt
2023-05-26 de4278af2fd46705a40bac58ec01122db6b7f3d7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
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:
 * <ul>
 *  <li>generates dequantization function and adds it to the shader</li>
 *  <li>adds any uniforms needed for dequantization to the shader and uniform map</li>
 * </ul>
 *
 * @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;