• Cesium 源码解析 Model(二)


            Cesium 源码解析 Model(一)中主要介绍了数据的前期准备工作,也就是数据下载完成(解析gltf,解析json和二进制数据,查看数据是否完整,如果有使用url的资源就去下载,这个不包括纹理的下载),对于数据的处理过程,需要根据this._state === ModelState.LOADING的状态确定下面的步骤:

            代码如下:

    1. Model.prototype.update = function (frameState) {
    2. ......
    3. // 正在加载
    4. if (this._state === ModelState.LOADING) {
    5. // Transition from LOADING -> LOADED once resources are downloaded and created.
    6. // Textures may continue to stream in while in the LOADED state.
    7. // 下载并创建资源后,从加载转换到加载。在加载状态下,纹理可能会继续流入。
    8. // 没有正在下载的外部buffer数据了,数据都已经下载完了
    9. if (loadResources.pendingBufferLoads === 0) {
    10. // 没有初始化
    11. if (!loadResources.initialized) {
    12. // 生成动态一张纹理brdf的纹理
    13. frameState.brdfLutGenerator.update(frameState);
    14. // 检查gltf的扩展cesium中是否都支持(不支持投递异常,日志中体现),虽然cesium支持但是浏览器不一定支持
    15. ModelUtility.checkSupportedExtensions(
    16. this.extensionsRequired,
    17. supportsWebP
    18. );
    19. // 更新前向轴
    20. ModelUtility.updateForwardAxis(this);
    21. // glTF pipeline updates, not needed if loading from cache
    22. // 是否定义了数据源版本
    23. if (!defined(this.gltf.extras.sourceVersion)) {
    24. var gltf = this.gltf;
    25. // Add the original version so it remains cached
    26. // 添加原始版本到缓存状态
    27. gltf.extras.sourceVersion = ModelUtility.getAssetVersion(gltf);
    28. // 定义了扩展KHR_techniques_webgl(内部包含自定义glsl等)
    29. gltf.extras.sourceKHRTechniquesWebGL = defined(
    30. ModelUtility.getUsedExtensions(gltf).KHR_techniques_webgl // 定义了KHR_techniques_webgl扩展
    31. );
    32. // 版本
    33. this._sourceVersion = gltf.extras.sourceVersion;
    34. // 扩展KHR_techniques_webgl是否定义
    35. this._sourceKHRTechniquesWebGL = gltf.extras.sourceKHRTechniquesWebGL;
    36. // 应该是将gltf1.0版本的数据改成2.0的数据, 为了支持1.0中的technique在2.0中使用了KHR_techniques_webgl扩展
    37. updateVersion(gltf);
    38. // 为gltf中各个属性添加默认值(buffer、material等)
    39. addDefaults(gltf);
    40. // glsl中是否添加批次表片段
    41. var options = {
    42. addBatchIdToGeneratedShaders: this._addBatchIdToGeneratedShaders,
    43. };
    44. // 处理KHR_materials_common扩展,扩展的所有的材质相信息,扩展的gltf的默认参数设置、shader片段拼接
    45. processModelMaterialsCommon(gltf, options);
    46. // 处理pbr材质
    47. processPbrMaterials(gltf, options);
    48. }
    49. // gltf版本
    50. this._sourceVersion = this.gltf.extras.sourceVersion;
    51. // 原始的glsl、uniform、attribute相关信息,与处理过的gltf.sourceKHRTechniquesWebGL信息不同
    52. this._sourceKHRTechniquesWebGL = this.gltf.extras.sourceKHRTechniquesWebGL;
    53. // Skip dequantizing in the shader if not encoded
    54. // 如果未编码,则跳过着色器中的解码
    55. this._dequantizeInShader =
    56. this._dequantizeInShader && DracoLoader.hasExtension(this);
    57. // We do this after to make sure that the ids don't change
    58. // 之后我们会这样做,以确保ID不会更改
    59. // 将buffer添加到gpu资源中, 存入ModelLoadResources
    60. addBuffersToLoadResources(this);
    61. // 解析骨骼动画关节
    62. parseArticulations(this);
    63. // 将gltf中的Techniques拷贝到model的成员变量中,
    64. parseTechniques(this);
    65. // 不是从缓存中加载(缓存中是已经解析过的数据,不用再处理了)
    66. if (!this._loadRendererResourcesFromCache) {
    67. // 解析bufferviewid,顶点、索引数据, 存入ModelLoadResources
    68. parseBufferViews(this);
    69. // 着色器shaderid, 存入ModelLoadResources
    70. parseShaders(this);
    71. // 着色程序programid, 存入ModelLoadResources
    72. parsePrograms(this);
    73. // 纹理id, 存入ModelLoadResources
    74. parseTextures(this, context, supportsWebP);
    75. }
    76. parseMaterials(this); // 解析材质(包含了真实的运行时数据存储)
    77. parseMeshes(this); // 解析网格(包含了真实的运行时数据存储)
    78. parseNodes(this); // 解析节点(包含了真实的运行时数据存储)
    79. // Start draco decoding // 解析draco编码的二进制数据
    80. DracoLoader.parse(this, context);
    81. // 初始化完成
    82. loadResources.initialized = true; // 资源部初始化完成
    83. }
    84. // 解码未完成
    85. if (!loadResources.finishedDecoding()) {
    86. // 解码模型
    87. DracoLoader.decodeModel(this, context).otherwise(
    88. ModelUtility.getFailedLoadFunction(this, "model", this.basePath)
    89. );
    90. }
    91. // 解码完成,资源还没解析完成
    92. if (loadResources.finishedDecoding() && !loadResources.resourcesParsed) {
    93. // 计算包围球
    94. this._boundingSphere = ModelUtility.computeBoundingSphere(this);
    95. // 包围球半径
    96. this._initialRadius = this._boundingSphere.radius;
    97. // 如果设置了cacheKey,缓存解码后的数据
    98. DracoLoader.cacheDataForModel(this);
    99. // 解析完成
    100. loadResources.resourcesParsed = true;
    101. }
    102. // 解析完成、外部链接的shader代码下载完成
    103. if (
    104. loadResources.resourcesParsed &&
    105. loadResources.pendingShaderLoads === 0
    106. ) {
    107. // 显示外轮廓线
    108. if (this.showOutline) {
    109. // 轮廓线是一个扩展选项,是cesium定义的,模型生成的轮廓线的数据???
    110. ModelOutlineLoader.outlinePrimitives(this);
    111. }
    112. // 创建gpu资源
    113. createResources(this, frameState);
    114. }
    115. }
    116. if (
    117. loadResources.finished() || // 资源加载完成或者纹理逐渐加载
    118. (incrementallyLoadTextures &&
    119. loadResources.finishedEverythingButTextureCreation()) // 除了纹理之外的所有数据都处理完了
    120. ) {
    121. // 模型装载完成(之后完成才能渲染)
    122. this._state = ModelState.LOADED;
    123. justLoaded = true;
    124. }
    125. }
    126. ......
    127. };

            过程步骤如下:

            1、this._state === ModelState.LOADING指明当前的数据除了纹理都已下载完成。

            2、loadResources.pendingBufferLoads === 0 说明二进制数据下载完成。

            3、!loadResources.initialized 说明资源还没有初始化完成,即还没将资源存储到ModelLoadResources结构中。

            4、frameState.brdfLutGenerator.update(frameState); 因为pbr需要brdf的使用的相关纹理。

            5、ModelUtility.checkSupportedExtensions 用来检查cesium是否支持所有模型正在使用的扩展。当前cesium支持的扩展有:

    1. // 所有的gltf扩展内容
    2. ModelUtility.supportedExtensions = {
    3. AGI_articulations: true,
    4. CESIUM_RTC: true, // rtc中心
    5. EXT_texture_webp: true, // webp
    6. KHR_blend: true, // 混合
    7. KHR_binary_glTF: true,
    8. KHR_texture_basisu: true,
    9. KHR_draco_mesh_compression: true, // 压缩格式
    10. KHR_materials_common: true, // 通用材质gltf1.0版本
    11. KHR_techniques_webgl: true, // 自定义着色器
    12. KHR_materials_unlit: true, // 无灯光材质
    13. KHR_materials_pbrSpecularGlossiness: true, 光泽度材质模型
    14. KHR_texture_transform: true, // 纹理变换
    15. WEB3D_quantized_attributes: true,
    16. };

    6、ModelUtility.updateForwardAxis(this);  主要是gltf1.0、2.0中定义的模型前向轴的方向不同,1.0对应的是model._gltfForwardAxis = Axis.X;

    7、下面的代码是将gltf2.0之前的格式转换成一种自定义的格式,目的是能统一处理。

    1. // 是否定义了数据源版本
    2. if (!defined(this.gltf.extras.sourceVersion)) {
    3. var gltf = this.gltf;
    4. // Add the original version so it remains cached
    5. // 添加原始版本到缓存状态
    6. gltf.extras.sourceVersion = ModelUtility.getAssetVersion(gltf);
    7. // 定义了扩展KHR_techniques_webgl(内部包含自定义glsl等)
    8. gltf.extras.sourceKHRTechniquesWebGL = defined(
    9. ModelUtility.getUsedExtensions(gltf).KHR_techniques_webgl // 定义了KHR_techniques_webgl扩展
    10. );
    11. // 版本
    12. this._sourceVersion = gltf.extras.sourceVersion;
    13. // 扩展KHR_techniques_webgl是否定义
    14. this._sourceKHRTechniquesWebGL = gltf.extras.sourceKHRTechniquesWebGL;
    15. // 应该是将gltf1.0版本的数据改成2.0的数据, 为了支持1.0中的technique在2.0中使用了KHR_techniques_webgl扩展
    16. updateVersion(gltf);
    17. // 为gltf中各个属性添加默认值(buffer、material等)
    18. addDefaults(gltf);
    19. // glsl中是否添加批次表片段
    20. var options = {
    21. addBatchIdToGeneratedShaders: this._addBatchIdToGeneratedShaders,
    22. };
    23. // 处理KHR_materials_common扩展,扩展的所有的材质相信息,扩展的gltf的默认参数设置、shader片段拼接
    24. processModelMaterialsCommon(gltf, options);
    25. // 处理pbr材质
    26. processPbrMaterials(gltf, options);
    27. }

    8、updateVersion(gltf);中将2.0之前的格式转换成一种兼容格式,代码如下:

    1. // 应该是将gltf1.0版本的数据改成2.0的数据
    2. function updateVersion(gltf, options) {
    3. options = defaultValue(options, defaultValue.EMPTY_OBJECT);
    4. const targetVersion = options.targetVersion;
    5. // 版本
    6. let version = gltf.version;
    7. // 如果asset存在就使用,不存在就设置1.0
    8. gltf.asset = defaultValue(gltf.asset, {
    9. version: "1.0",
    10. });
    11. // 设置版本
    12. gltf.asset.version = defaultValue(gltf.asset.version, "1.0");
    13. version = defaultValue(version, gltf.asset.version).toString();
    14. // Invalid version
    15. if (!Object.prototype.hasOwnProperty.call(updateFunctions, version)) {
    16. // Try truncating trailing version numbers, could be a number as well if it is 0.8
    17. if (defined(version)) {
    18. version = version.substring(0, 3);
    19. }
    20. // Default to 1.0 if it cannot be determined
    21. if (!Object.prototype.hasOwnProperty.call(updateFunctions, version)) {
    22. version = "1.0";
    23. }
    24. }
    25. // 根据gltf的版本获取更新函数(跟新1.02.0
    26. let updateFunction = updateFunctions[version];
    27. // 需要gltf版本转换,通过函数进行转换
    28. while (defined(updateFunction)) {
    29. if (version === targetVersion) {
    30. break;
    31. }
    32. updateFunction(gltf, options);
    33. version = gltf.asset.version;
    34. updateFunction = updateFunctions[version];
    35. }
    36. return gltf;
    37. }

    其中let updateFunction = updateFunctions[version];是查找转换函数:

    1. // gltf的版本处理函数
    2. const updateFunctions = {
    3. 0.8: glTF08to10, // 0.8转换成1.0的过程
    4. "1.0": glTF10to20, // 1.0转换成2.0的过程
    5. "2.0": undefined, // 如果默认是2.0就不用在转换了
    6. };

     对于gltf1.0、gltf2.0的规范:

    可以看出,1.0是用json对象的方式建立索引,2.0是使用json数组的方式建立索引,json字符串的大小会减少很多。

    9、addDefaults(gltf);主要是对于gltf中不完整的数据(某些缺省了)进行完善(填充完整)。

    1. function addDefaults(gltf) {
    2. // 遍历访问器
    3. ForEach.accessor(gltf, function (accessor) {
    4. if (defined(accessor.bufferView)) {
    5. // 设置默认的访问器偏移量为0
    6. accessor.byteOffset = defaultValue(accessor.byteOffset, 0);
    7. }
    8. });
    9. // 遍历bufferviews
    10. ForEach.bufferView(gltf, function (bufferView) {
    11. if (defined(bufferView.buffer)) {
    12. // 设置默认的偏移量为0
    13. bufferView.byteOffset = defaultValue(bufferView.byteOffset, 0);
    14. }
    15. });
    16. // 遍历mesh
    17. ForEach.mesh(gltf, function (mesh) {
    18. // mesh的primitive
    19. ForEach.meshPrimitive(mesh, function (primitive) {
    20. // 默认绘制三角形
    21. primitive.mode = defaultValue(primitive.mode, WebGLConstants.TRIANGLES);
    22. // 材质未定义
    23. if (!defined(primitive.material)) {
    24. // 如果json中没有任何材质,材质为空数组
    25. if (!defined(gltf.materials)) {
    26. gltf.materials = [];
    27. }
    28. const defaultMaterial = {
    29. name: "default",
    30. };
    31. // 材质未定义,设置mesh的材质索引为“default
    32. primitive.material = addToArray(gltf.materials, defaultMaterial);
    33. }
    34. });
    35. });
    36. // 遍历顶点属性数据
    37. ForEach.accessorContainingVertexAttributeData(gltf, function (accessorId) {
    38. // 找到属性对应的gltf中的accessor访问器
    39. const accessor = gltf.accessors[accessorId];
    40. // 获取对应bufferview的索引
    41. const bufferViewId = accessor.bufferView;
    42. // 是否归一化
    43. accessor.normalized = defaultValue(accessor.normalized, false);
    44. if (defined(bufferViewId)) {
    45. // 找到bufferview
    46. const bufferView = gltf.bufferViews[bufferViewId];
    47. // 填充步长大小
    48. bufferView.byteStride = getAccessorByteStride(gltf, accessor);
    49. // bufferview的目标是顶点数组
    50. bufferView.target = WebGLConstants.ARRAY_BUFFER;
    51. }
    52. });
    53. // 包含绘制索引
    54. ForEach.accessorContainingIndexData(gltf, function (accessorId) {
    55. // 找到索引对应的具体访问器
    56. const accessor = gltf.accessors[accessorId];
    57. // 找到索引对应的bufferView
    58. const bufferViewId = accessor.bufferView;
    59. if (defined(bufferViewId)) {
    60. // 设置bufferView的目标是索引缓冲
    61. const bufferView = gltf.bufferViews[bufferViewId];
    62. bufferView.target = WebGLConstants.ELEMENT_ARRAY_BUFFER;
    63. }
    64. });
    65. // 遍历材质
    66. ForEach.material(gltf, function (material) {
    67. // 材质中是否有扩展
    68. const extensions = defaultValue(
    69. material.extensions,
    70. defaultValue.EMPTY_OBJECT
    71. );
    72. // 材质中的KHR_materials_common扩展,定义光照模型,光照参数
    73. const materialsCommon = extensions.KHR_materials_common;
    74. if (defined(materialsCommon)) {
    75. // 获取自定义的光照模型,以及与光照模型相对应的values
    76. const technique = materialsCommon.technique;
    77. const values = defined(materialsCommon.values)
    78. ? materialsCommon.values
    79. : {};
    80. materialsCommon.values = values;
    81. // 定义了环境光
    82. values.ambient = defined(values.ambient)
    83. ? values.ambient
    84. : [0.0, 0.0, 0.0, 1.0];
    85. // 定义了自发光
    86. values.emission = defined(values.emission)
    87. ? values.emission
    88. : [0.0, 0.0, 0.0, 1.0];
    89. // 定义了透明度
    90. values.transparency = defaultValue(values.transparency, 1.0);
    91. values.transparent = defaultValue(values.transparent, false);
    92. // 定义了双面渲染
    93. values.doubleSided = defaultValue(values.doubleSided, false);
    94. // 不是恒定的
    95. if (technique !== "CONSTANT") {
    96. values.diffuse = defined(values.diffuse)
    97. ? values.diffuse
    98. : [0.0, 0.0, 0.0, 1.0];
    99. // 不是兰伯特,应该是phong或者blinn,需要高光
    100. if (technique !== "LAMBERT") {
    101. // 高光
    102. values.specular = defined(values.specular)
    103. ? values.specular
    104. : [0.0, 0.0, 0.0, 1.0];
    105. // 高光强度
    106. values.shininess = defaultValue(values.shininess, 0.0);
    107. }
    108. }
    109. return;
    110. }
    111. // 自发光因子
    112. material.emissiveFactor = defaultValue(
    113. material.emissiveFactor,
    114. [0.0, 0.0, 0.0]
    115. );
    116. // 透明模式
    117. material.alphaMode = defaultValue(material.alphaMode, "OPAQUE");
    118. // 双面渲染
    119. material.doubleSided = defaultValue(material.doubleSided, false);
    120. // 遮罩
    121. if (material.alphaMode === "MASK") {
    122. material.alphaCutoff = defaultValue(material.alphaCutoff, 0.5);
    123. }
    124. // 如果有KHR_techniques_webgl扩展????
    125. const techniquesExtension = extensions.KHR_techniques_webgl;
    126. if (defined(techniquesExtension)) {
    127. // 遍历单个材质中的属性
    128. ForEach.materialValue(material, function (materialValue) {
    129. // Check if material value is a TextureInfo object
    130. // 是纹理就添加纹理缓存引用
    131. if (defined(materialValue.index)) {
    132. // 纹理坐标引用
    133. addTextureDefaults(materialValue);
    134. }
    135. });
    136. }
    137. // 添加纹理坐标引用(自发光贴图、法线贴图、遮蔽图)
    138. addTextureDefaults(material.emissiveTexture);
    139. addTextureDefaults(material.normalTexture);
    140. addTextureDefaults(material.occlusionTexture);
    141. // 金属、粗糙度
    142. const pbrMetallicRoughness = material.pbrMetallicRoughness;
    143. if (defined(pbrMetallicRoughness)) {
    144. // 基本颜色
    145. pbrMetallicRoughness.baseColorFactor = defaultValue(
    146. pbrMetallicRoughness.baseColorFactor,
    147. [1.0, 1.0, 1.0, 1.0]
    148. );
    149. // 金属都因子
    150. pbrMetallicRoughness.metallicFactor = defaultValue(
    151. pbrMetallicRoughness.metallicFactor,
    152. 1.0
    153. );
    154. // 粗糙度因子
    155. pbrMetallicRoughness.roughnessFactor = defaultValue(
    156. pbrMetallicRoughness.roughnessFactor,
    157. 1.0
    158. );
    159. // 默认纹理坐标引用
    160. addTextureDefaults(pbrMetallicRoughness.baseColorTexture);
    161. addTextureDefaults(pbrMetallicRoughness.metallicRoughnessTexture);
    162. }
    163. // 高光光泽度模型
    164. const pbrSpecularGlossiness =
    165. extensions.KHR_materials_pbrSpecularGlossiness;
    166. if (defined(pbrSpecularGlossiness)) {
    167. // 漫反射
    168. pbrSpecularGlossiness.diffuseFactor = defaultValue(
    169. pbrSpecularGlossiness.diffuseFactor,
    170. [1.0, 1.0, 1.0, 1.0]
    171. );
    172. // 镜面
    173. pbrSpecularGlossiness.specularFactor = defaultValue(
    174. pbrSpecularGlossiness.specularFactor,
    175. [1.0, 1.0, 1.0]
    176. );
    177. // 光泽度
    178. pbrSpecularGlossiness.glossinessFactor = defaultValue(
    179. pbrSpecularGlossiness.glossinessFactor,
    180. 1.0
    181. );
    182. // 光泽度纹理
    183. addTextureDefaults(pbrSpecularGlossiness.specularGlossinessTexture);
    184. }
    185. });
    186. // 动画
    187. ForEach.animation(gltf, function (animation) {
    188. ForEach.animationSampler(animation, function (sampler) {
    189. sampler.interpolation = defaultValue(sampler.interpolation, "LINEAR");
    190. });
    191. });
    192. // 动画节点
    193. const animatedNodes = getAnimatedNodes(gltf);
    194. ForEach.node(gltf, function (node, id) {
    195. const animated = defined(animatedNodes[id]);
    196. if (
    197. animated ||
    198. defined(node.translation) ||
    199. defined(node.rotation) ||
    200. defined(node.scale)
    201. ) {
    202. node.translation = defaultValue(node.translation, [0.0, 0.0, 0.0]);
    203. node.rotation = defaultValue(node.rotation, [0.0, 0.0, 0.0, 1.0]);
    204. node.scale = defaultValue(node.scale, [1.0, 1.0, 1.0]);
    205. } else {
    206. node.matrix = defaultValue(
    207. node.matrix,
    208. [
    209. 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0,
    210. 0.0, 1.0,
    211. ]
    212. );
    213. }
    214. });
    215. // 采样器
    216. ForEach.sampler(gltf, function (sampler) {
    217. sampler.wrapS = defaultValue(sampler.wrapS, WebGLConstants.REPEAT); // 默认是重复
    218. sampler.wrapT = defaultValue(sampler.wrapT, WebGLConstants.REPEAT);
    219. });
    220. // 默认场景0
    221. if (defined(gltf.scenes) && !defined(gltf.scene)) {
    222. gltf.scene = 0;
    223. }
    224. return gltf;
    225. }

     例如:

    accessor.byteOffset   访问器的偏移量

    bufferView.byteOffset  二进制数据的偏移量

    primitive.material  如果某个mesh没有材质,则使用一个默认的材质

    accessor.normalized    数据是否归一化

    bufferView.byteStride    数据的步长   

    bufferView.target = WebGLConstants.ARRAY_BUFFER;  顶点数组缓存类型的二进制数据

    bufferView.target = WebGLConstants.ELEMENT_ARRAY_BUFFER;  索引数组缓存类型的二进制数据

     technique !== "CONSTANT"或"LAMBERT"指明材质所使用的光照模型,以及使用这个光照模型需要哪些对应的参数(材质的各种反射率),

    材质的自发光、是否透明、是否双面渲染、透明剔除discard

    自发光贴图、法线贴图、环境光遮蔽图的uv坐标索引

    金属粗糙度模型的默认参数、光泽度模型的默认参数

    动画的插值方式、骨骼矩阵

    采样器的默认值

    默认场景

    10、processModelMaterialsCommon(gltf, options);是对于gltf的“KHR_materials_common”扩展的处理过程,与processPbrMaterials(gltf, options);对pbr的处理过程是互斥的。

            processModelMaterialsCommon(gltf, options);中代码如下:

    1. // 处KHR_materials_common扩展
    2. function processModelMaterialsCommon(gltf, options) {
    3. options = defaultValue(options, defaultValue.EMPTY_OBJECT);
    4. if (!defined(gltf)) {
    5. return;
    6. }
    7. // 没有使用扩展材质就返回
    8. if (!usesExtension(gltf, "KHR_materials_common")) {
    9. return;
    10. }
    11. // 使用KHR_materials_common就必须使用KHR_techniques_webgl
    12. if (!usesExtension(gltf, "KHR_techniques_webgl")) {
    13. // 没有扩展就创建扩展
    14. if (!defined(gltf.extensions)) {
    15. gltf.extensions = {};
    16. }
    17. // 添加默认数组
    18. gltf.extensions.KHR_techniques_webgl = {
    19. programs: [], // 程序
    20. shaders: [], // 着色器
    21. techniques: [], // glsl代码,attibute、uniform
    22. };
    23. // 将使用的扩展加入
    24. gltf.extensionsUsed.push("KHR_techniques_webgl");
    25. gltf.extensionsRequired.push("KHR_techniques_webgl");
    26. }
    27. // 自定义glsl、uniform、attribute等信息
    28. var techniquesWebgl = gltf.extensions.KHR_techniques_webgl;
    29. // 灯光默认值
    30. lightDefaults(gltf);
    31. // 收集灯光参数,后续uniform会使用 (灯光颜色、矩阵、衰减参数等)
    32. var lightParameters = generateLightParameters(gltf);
    33. // 通过mesh的材质索引封装mesh的顶点属性信息,因为这些顶点属性会影像材质(hasNormal、hasVertexColor等)
    34. var primitiveByMaterial = ModelUtility.splitIncompatibleMaterials(gltf);
    35. var techniques = {};
    36. var generatedTechniques = false;
    37. // 遍历材质 生成technique
    38. ForEach.material(gltf, function (material, materialIndex) {
    39. if ( // 定义了扩展
    40. defined(material.extensions) &&
    41. defined(material.extensions.KHR_materials_common)
    42. ) {
    43. // 光照模型(phong、blinn等)
    44. var khrMaterialsCommon = material.extensions.KHR_materials_common;
    45. // 材质对应的顶点属性信息
    46. var primitiveInfo = primitiveByMaterial[materialIndex];
    47. // 获取Technique相关的信息,作为一个shader的唯一key,用于缓存shader,以及区别shader
    48. // 将所有影像材质的信息做成一个key
    49. var techniqueKey = getTechniqueKey(khrMaterialsCommon, primitiveInfo);
    50. // 缓存避免重复处理
    51. var technique = techniques[techniqueKey];
    52. // 缓存中没有找到就生成
    53. if (!defined(technique)) {
    54. // 拼接成很多个glsl片段、顶点属性片段、uniform对象, 收集attribute、uniform、组成shaders、program、technique
    55. technique = generateTechnique(
    56. gltf, // 原始数据
    57. techniquesWebgl, // 自定义glsl、uniform、attribute等信息,生成的technique会添加到这个数组中
    58. primitiveInfo, // 顶点属性的一些影响材质的信息(hasNormal、hasVertexColor等)
    59. khrMaterialsCommon, // 光照模型(模型自身材质反射率)
    60. lightParameters, // 所有的灯光参数(灯光位置、颜色、衰减参数)
    61. options.addBatchIdToGeneratedShaders // 添加批次表id
    62. );
    63. // 缓存到techniques中,避免重复处理
    64. techniques[techniqueKey] = technique;
    65. // 生成了techniques
    66. generatedTechniques = true;
    67. }
    68. // 收集gltf中提供的uniform的值
    69. var materialValues = {};
    70. var values = khrMaterialsCommon.values;
    71. var uniformName;
    72. for (var valueName in values) {
    73. if (
    74. values.hasOwnProperty(valueName) &&
    75. valueName !== "transparent" && // 不是透明
    76. valueName !== "doubleSided" // 不是双面渲染
    77. ) {
    78. uniformName = "u_" + valueName.toLowerCase();
    79. materialValues[uniformName] = values[valueName]; // 添加uniform名-值
    80. }
    81. }
    82. // 添加到材质的扩展,包括technique索引和values(uniform的数值)
    83. material.extensions.KHR_techniques_webgl = {
    84. technique: technique,
    85. values: materialValues,
    86. };
    87. // 设置材质中的模式
    88. material.alphaMode = "OPAQUE";
    89. if (khrMaterialsCommon.transparent) {
    90. material.alphaMode = "BLEND"; // 透明模式为混合
    91. }
    92. // 设置材质中的双面渲染
    93. if (khrMaterialsCommon.doubleSided) { // 双面渲染
    94. material.doubleSided = true;
    95. }
    96. }
    97. });
    98. // 没有生成直接返回
    99. if (!generatedTechniques) {
    100. return gltf;
    101. }
    102. // If any primitives have semantics that aren't declared in the generated
    103. // shaders, we want to preserve them.
    104. // 确保语义存在
    105. ModelUtility.ensureSemanticExistence(gltf);
    106. return gltf;
    107. }

    其中lightDefaults(gltf);主要是完善灯光信息(gltf中的灯光使用了默认值,这里需要完善一下)

    function generateLightParameters(gltf)函数主要是收集灯光信息,这些信息主要是为后续的glsl字符串的拼接、uniform的数据的收集使用。

     

     var primitiveByMaterial = ModelUtility.splitIncompatibleMaterials(gltf);函数会收集顶点属性等信息,这些信息为后续拼接glsl以及attibute等有帮助。

    对于每一个材质var techniqueKey = getTechniqueKey(khrMaterialsCommon, primitiveInfo)会依据材质所使用的所有关键信息拼接成一个唯一值,以区别不同的材质。

    1. technique = generateTechnique(
    2. gltf, // 原始数据
    3. techniquesWebgl, // 自定义glsl、uniform、attribute等信息,生成的technique会添加到这个数组中
    4. primitiveInfo, // 顶点属性的一些影响材质的信息(hasNormal、hasVertexColor等)
    5. khrMaterialsCommon, // 光照模型(模型自身材质反射率)
    6. lightParameters, // 所有的灯光参数(灯光位置、颜色、衰减参数)
    7. options.addBatchIdToGeneratedShaders // 添加批次表id
    8. );

    上述代码会根据各方面的信息生成technique,并将这个索引添加到material.extensions.KHR_techniques_webgl中,后续是由这个结构生成着色程序。

    1. // 生成Technique,其中包括shader、uniform、attribute所有的信息
    2. function generateTechnique(
    3. gltf,
    4. techniquesWebgl,
    5. primitiveInfo,
    6. khrMaterialsCommon,
    7. lightParameters, // 灯光参数
    8. addBatchIdToGeneratedShaders
    9. ) {
    10. // 未定义
    11. if (!defined(khrMaterialsCommon)) {
    12. khrMaterialsCommon = {};
    13. }
    14. // 批次表的id片段
    15. addBatchIdToGeneratedShaders = defaultValue(
    16. addBatchIdToGeneratedShaders,
    17. false
    18. );
    19. // gltf中自带的数据:用户自定义的(一般不会自定义,这些是在默认值中创建的)
    20. var techniques = techniquesWebgl.techniques; // 包括解析后的glsl的顶点属性片段、shader片段、以及uniform封装对象
    21. var shaders = techniquesWebgl.shaders; // 自定义的着色器片段
    22. var programs = techniquesWebgl.programs; // 自定义的程序片段
    23. var lightingModel = khrMaterialsCommon.technique.toUpperCase(); // 灯光模式(恒定、blinn、phong)
    24. var lights;
    25. if ( // 定义了通用材质
    26. defined(gltf.extensions) &&
    27. defined(gltf.extensions.KHR_materials_common)
    28. ) {
    29. // 获取灯光数组(环境光、点光源、聚光灯)
    30. lights = gltf.extensions.KHR_materials_common.lights;
    31. }
    32. // 与khrMaterialsCommon.technique对应的模型反射率等
    33. var parameterValues = khrMaterialsCommon.values;
    34. // 骨骼节点数
    35. var jointCount = defaultValue(khrMaterialsCommon.jointCount, 0);
    36. var skinningInfo;
    37. var hasSkinning = false;
    38. var hasVertexColors = false;
    39. // gltf中mesh中存储的索引信息
    40. if (defined(primitiveInfo)) {
    41. // 骨骼信息、顶点颜色
    42. skinningInfo = primitiveInfo.skinning;
    43. hasSkinning = skinningInfo.skinned;
    44. hasVertexColors = primitiveInfo.hasVertexColors;
    45. }
    46. // 拼接shader分为几部分:
    47. /*
    48. vertexShader\fragmentShader : 函数外的attribute、uniform、varing在vertexShader字符串中,
    49. vertexShaderMain: 函数内的处理过程在vertexShaderMain字符串中,
    50. techniqueUniforms: uniform相关信息,
    51. techniqueAttributes: attribute相关信息
    52. */
    53. // 默认高精度
    54. var vertexShader = "precision highp float;\n";
    55. var fragmentShader = "precision highp float;\n";
    56. // 光照模型不是恒定的,可能是lambert等,就需要法线参数
    57. var hasNormals = lightingModel !== "CONSTANT";
    58. // Add techniques 添加uniform数据矩阵信息
    59. var techniqueUniforms = {
    60. u_modelViewMatrix: { // 模型视图矩阵
    61. semantic: usesExtension(gltf, "CESIUM_RTC") // 如果使用了rtc,在glsl中使用CESIUM_RTC_MODELVIEW关键字,否则使用MODELVIEW
    62. ? "CESIUM_RTC_MODELVIEW"
    63. : "MODELVIEW",
    64. type: WebGLConstants.FLOAT_MAT4, // 类型是mat4
    65. },
    66. u_projectionMatrix: { // 定义投影矩阵,代码中的名称是u_projectionMatrix,对应glsl中的关键字是PROJECTION
    67. semantic: "PROJECTION",
    68. type: WebGLConstants.FLOAT_MAT4,
    69. },
    70. };
    71. if (hasNormals) { // 存在法线
    72. techniqueUniforms.u_normalMatrix = {
    73. semantic: "MODELVIEWINVERSETRANSPOSE", // 模型视图矩阵的逆矩阵
    74. type: WebGLConstants.FLOAT_MAT3, // 类型是mat3
    75. };
    76. }
    77. if (hasSkinning) { // 存在骨骼
    78. techniqueUniforms.u_jointMatrix = {
    79. count: jointCount, // 节点数
    80. semantic: "JOINTMATRIX", // 节点矩阵,glsl中的uniform关键字
    81. type: WebGLConstants.FLOAT_MAT4,
    82. };
    83. }
    84. // Add material values 添加材质值反射率信息
    85. var uniformName;
    86. var hasTexCoords = false;
    87. for (var name in parameterValues) { //
    88. //generate shader parameters for KHR_materials_common attributes
    89. //(including a check, because some boolean flags should not be used as shader parameters)
    90. if (
    91. parameterValues.hasOwnProperty(name) && // 本身的数据
    92. name !== "transparent" && // 透明
    93. name !== "doubleSided" // 双面渲染
    94. ) {
    95. var uniformType = getKHRMaterialsCommonValueType( // 获取值的类型
    96. name,
    97. parameterValues[name]
    98. );
    99. // 拼接uniform名称
    100. uniformName = "u_" + name.toLowerCase();
    101. // 存在纹理坐标
    102. if (!hasTexCoords && uniformType === WebGLConstants.SAMPLER_2D) {
    103. hasTexCoords = true;
    104. }
    105. // 添加uniform相关的名称与类型,一次拼接glsl中的uniform,没有语义
    106. techniqueUniforms[uniformName] = {
    107. type: uniformType,
    108. };
    109. }
    110. }
    111. // Give the diffuse uniform a semantic to support color replacement in 3D Tiles
    112. // 为漫反射均匀提供语义,以支持3D瓦片中的颜色替换
    113. if (defined(techniqueUniforms.u_diffuse)) {
    114. techniqueUniforms.u_diffuse.semantic = "_3DTILESDIFFUSE";
    115. }
    116. // Copy light parameters into technique parameters
    117. // 赋值unifrom的灯光信息
    118. if (defined(lightParameters)) {
    119. for (var lightParamName in lightParameters) {
    120. if (lightParameters.hasOwnProperty(lightParamName)) {
    121. uniformName = "u_" + lightParamName;
    122. techniqueUniforms[uniformName] = lightParameters[lightParamName];
    123. }
    124. }
    125. }
    126. // Add uniforms to shaders 将uniform添加到glsl中
    127. for (uniformName in techniqueUniforms) {
    128. if (techniqueUniforms.hasOwnProperty(uniformName)) {
    129. var uniform = techniqueUniforms[uniformName];
    130. var arraySize = defined(uniform.count) ? "[" + uniform.count + "]" : ""; // 如果uniform是数组
    131. if ( // 不是mat3\mat4并且是用在片段着色器中
    132. (uniform.type !== WebGLConstants.FLOAT_MAT3 &&
    133. uniform.type !== WebGLConstants.FLOAT_MAT4) ||
    134. uniform.useInFragment // 用在片段着色器中
    135. ) {
    136. // 拼接片段着色器中的uniform常量
    137. fragmentShader +=
    138. "uniform " +
    139. webGLConstantToGlslType(uniform.type) +
    140. " " +
    141. uniformName +
    142. arraySize +
    143. ";\n";
    144. // 使用完了就删除
    145. delete uniform.useInFragment;
    146. } else {
    147. // 拼接顶点着色器中的unifrom常量
    148. vertexShader +=
    149. "uniform " +
    150. webGLConstantToGlslType(uniform.type) +
    151. " " +
    152. uniformName +
    153. arraySize +
    154. ";\n";
    155. }
    156. }
    157. }
    158. // Add attributes with semantics 添加语义属性
    159. // 顶点着色器main函数
    160. var vertexShaderMain = "";
    161. // 存在骨骼的情况,在顶点着色器的main中拼接
    162. if (hasSkinning) {
    163. // 根据骨骼索引找到骨骼矩阵,骨骼矩阵乘以权重
    164. vertexShaderMain +=
    165. " mat4 skinMatrix =\n" +
    166. " a_weight.x * u_jointMatrix[int(a_joint.x)] +\n" +
    167. " a_weight.y * u_jointMatrix[int(a_joint.y)] +\n" +
    168. " a_weight.z * u_jointMatrix[int(a_joint.z)] +\n" +
    169. " a_weight.w * u_jointMatrix[int(a_joint.w)];\n";
    170. }
    171. // Add position always 添加顶点属性中的顶点
    172. var techniqueAttributes = {
    173. a_position: { //
    174. semantic: "POSITION", // 语义是顶点
    175. },
    176. };
    177. // 顶点着色器中的顶点属性位置属性、转递属性(相机空间中的坐标)
    178. vertexShader += "attribute vec3 a_position;\n";
    179. vertexShader += "varying vec3 v_positionEC;\n";
    180. // 存在骨骼
    181. if (hasSkinning) {
    182. // 计算骨骼变换后的相机空间坐标
    183. vertexShaderMain +=
    184. " vec4 pos = u_modelViewMatrix * skinMatrix * vec4(a_position,1.0);\n";
    185. } else {
    186. // 直接计算相机空间坐标
    187. vertexShaderMain +=
    188. " vec4 pos = u_modelViewMatrix * vec4(a_position,1.0);\n";
    189. }
    190. // 转递的相机空间坐标
    191. vertexShaderMain += " v_positionEC = pos.xyz;\n";
    192. // 投影
    193. vertexShaderMain += " gl_Position = u_projectionMatrix * pos;\n";
    194. // 像素着色器中接收的相机空间坐标
    195. fragmentShader += "varying vec3 v_positionEC;\n";
    196. // Add normal if we don't have constant lighting 如果没有恒定照明,则添加“正常”
    197. if (hasNormals) {
    198. // 存在法线
    199. techniqueAttributes.a_normal = {
    200. semantic: "NORMAL",
    201. };
    202. // 法线
    203. vertexShader += "attribute vec3 a_normal;\n";
    204. vertexShader += "varying vec3 v_normal;\n";
    205. if (hasSkinning) {
    206. // 骨骼中会计算法线
    207. vertexShaderMain +=
    208. " v_normal = u_normalMatrix * mat3(skinMatrix) * a_normal;\n";
    209. } else {
    210. vertexShaderMain += " v_normal = u_normalMatrix * a_normal;\n";
    211. }
    212. // 像素着色器中接收的法线坐标
    213. fragmentShader += "varying vec3 v_normal;\n";
    214. }
    215. // Add texture coordinates if the material uses them 天啊及纹理坐标
    216. var v_texcoord;
    217. if (hasTexCoords) {
    218. techniqueAttributes.a_texcoord_0 = { // 纹理坐标
    219. semantic: "TEXCOORD_0",
    220. };
    221. // 顶点着色器中的纹理坐标
    222. v_texcoord = "v_texcoord_0";
    223. vertexShader += "attribute vec2 a_texcoord_0;\n";
    224. vertexShader += "varying vec2 " + v_texcoord + ";\n";
    225. // 转递纹理坐标
    226. vertexShaderMain += " " + v_texcoord + " = a_texcoord_0;\n";
    227. // 像素着色器中接收的纹理坐标
    228. fragmentShader += "varying vec2 " + v_texcoord + ";\n";
    229. }
    230. if (hasSkinning) {
    231. // 骨骼节点属性
    232. techniqueAttributes.a_joint = {
    233. semantic: "JOINTS_0",
    234. };
    235. // 权重属性
    236. techniqueAttributes.a_weight = {
    237. semantic: "WEIGHTS_0",
    238. };
    239. // 骨骼矩阵索引,权重属性,都是vec4的
    240. vertexShader += "attribute vec4 a_joint;\n";
    241. vertexShader += "attribute vec4 a_weight;\n";
    242. }
    243. if (hasVertexColors) {
    244. // 颜色属性
    245. techniqueAttributes.a_vertexColor = {
    246. semantic: "COLOR_0",
    247. };
    248. // 顶点颜色、传递顶点颜色
    249. vertexShader += "attribute vec4 a_vertexColor;\n";
    250. vertexShader += "varying vec4 v_vertexColor;\n";
    251. vertexShaderMain += " v_vertexColor = a_vertexColor;\n";
    252. // 像素着色器中接收的顶点颜色
    253. fragmentShader += "varying vec4 v_vertexColor;\n";
    254. }
    255. // 批次id属性
    256. if (addBatchIdToGeneratedShaders) {
    257. techniqueAttributes.a_batchId = { //
    258. semantic: "_BATCHID", // 语义
    259. };
    260. // 顶点着色器中添加批次id
    261. vertexShader += "attribute float a_batchId;\n";
    262. }
    263. // 存在高光
    264. var hasSpecular =
    265. hasNormals &&
    266. (lightingModel === "BLINN" || lightingModel === "PHONG") && // 灯光模式为blinn或者phong
    267. defined(techniqueUniforms.u_specular) && // 存在高光、高光强度
    268. defined(techniqueUniforms.u_shininess) &&
    269. techniqueUniforms.u_shininess > 0.0;
    270. // Generate lighting code blocks 生成灯光代码块
    271. var hasNonAmbientLights = false;
    272. var hasAmbientLights = false;
    273. var fragmentLightingBlock = ""; // 像素着色器代码段
    274. for (var lightName in lights) { // 遍历灯光
    275. if (lights.hasOwnProperty(lightName)) {
    276. var light = lights[lightName];
    277. var lightType = light.type.toLowerCase(); // 灯光类型(环境光、点光源、聚光灯)
    278. var lightBaseName = light.baseName;
    279. fragmentLightingBlock += " {\n";
    280. var lightColorName = "u_" + lightBaseName + "Color"; // 灯光颜色
    281. var varyingDirectionName;
    282. var varyingPositionName;
    283. if (lightType === "ambient") { // 如果是换进光
    284. hasAmbientLights = true;
    285. fragmentLightingBlock += //
    286. " ambientLight += " + lightColorName + ";\n"; // glsl中的颜色相加
    287. } else if (hasNormals) { // 存在法线
    288. hasNonAmbientLights = true;
    289. varyingDirectionName = "v_" + lightBaseName + "Direction"; // 方向光
    290. varyingPositionName = "v_" + lightBaseName + "Position"; // 方向光的位置
    291. if (lightType !== "point") { // 不是点光源
    292. vertexShader += "varying vec3 " + varyingDirectionName + ";\n"; // v传递方向光
    293. fragmentShader += "varying vec3 " + varyingDirectionName + ";\n"; // f接收方向光
    294. vertexShaderMain +=
    295. " " +
    296. varyingDirectionName +
    297. " = mat3(u_" +
    298. lightBaseName +
    299. "Transform) * vec3(0.,0.,1.);\n";
    300. if (lightType === "directional") {
    301. fragmentLightingBlock +=
    302. " vec3 l = normalize(" + varyingDirectionName + ");\n";
    303. }
    304. }
    305. if (lightType !== "directional") { // 不是方向光
    306. vertexShader += "varying vec3 " + varyingPositionName + ";\n";
    307. fragmentShader += "varying vec3 " + varyingPositionName + ";\n";
    308. vertexShaderMain +=
    309. " " +
    310. varyingPositionName +
    311. " = u_" +
    312. lightBaseName +
    313. "Transform[3].xyz;\n";
    314. fragmentLightingBlock +=
    315. " vec3 VP = " + varyingPositionName + " - v_positionEC;\n";
    316. fragmentLightingBlock += " vec3 l = normalize(VP);\n";
    317. fragmentLightingBlock += " float range = length(VP);\n";
    318. fragmentLightingBlock +=
    319. " float attenuation = 1.0 / (u_" +
    320. lightBaseName +
    321. "Attenuation.x + ";
    322. fragmentLightingBlock +=
    323. "(u_" + lightBaseName + "Attenuation.y * range) + ";
    324. fragmentLightingBlock +=
    325. "(u_" + lightBaseName + "Attenuation.z * range * range));\n";
    326. } else {
    327. fragmentLightingBlock += " float attenuation = 1.0;\n";
    328. }
    329. // 聚光灯
    330. if (lightType === "spot") {
    331. fragmentLightingBlock +=
    332. " float spotDot = dot(l, normalize(" +
    333. varyingDirectionName +
    334. "));\n";
    335. fragmentLightingBlock +=
    336. " if (spotDot < cos(u_" + lightBaseName + "FallOff.x * 0.5))\n";
    337. fragmentLightingBlock += " {\n";
    338. fragmentLightingBlock += " attenuation = 0.0;\n";
    339. fragmentLightingBlock += " }\n";
    340. fragmentLightingBlock += " else\n";
    341. fragmentLightingBlock += " {\n";
    342. fragmentLightingBlock +=
    343. " attenuation *= max(0.0, pow(spotDot, u_" +
    344. lightBaseName +
    345. "FallOff.y));\n";
    346. fragmentLightingBlock += " }\n";
    347. }
    348. fragmentLightingBlock +=
    349. " diffuseLight += " +
    350. lightColorName +
    351. "* max(dot(normal,l), 0.) * attenuation;\n";
    352. if (hasSpecular) {
    353. if (lightingModel === "BLINN") {
    354. fragmentLightingBlock += " vec3 h = normalize(l + viewDir);\n";
    355. fragmentLightingBlock +=
    356. " float specularIntensity = max(0., pow(max(dot(normal, h), 0.), u_shininess)) * attenuation;\n";
    357. } else {
    358. // PHONG
    359. fragmentLightingBlock +=
    360. " vec3 reflectDir = reflect(-l, normal);\n";
    361. fragmentLightingBlock +=
    362. " float specularIntensity = max(0., pow(max(dot(reflectDir, viewDir), 0.), u_shininess)) * attenuation;\n";
    363. }
    364. fragmentLightingBlock +=
    365. " specularLight += " +
    366. lightColorName +
    367. " * specularIntensity;\n";
    368. }
    369. }
    370. fragmentLightingBlock += " }\n";
    371. }
    372. }
    373. // 不存在环境光
    374. if (!hasAmbientLights) {
    375. // Add an ambient light if we don't have one
    376. fragmentLightingBlock += " ambientLight += vec3(0.2, 0.2, 0.2);\n";
    377. }
    378. // 存在换进光
    379. if (!hasNonAmbientLights && lightingModel !== "CONSTANT") {
    380. // 自定义了灯光颜色
    381. fragmentShader += "#ifdef USE_CUSTOM_LIGHT_COLOR \n";
    382. fragmentShader += "uniform vec3 gltf_lightColor; \n";
    383. fragmentShader += "#endif \n";
    384. // 未定义灯光颜色
    385. fragmentLightingBlock += "#ifndef USE_CUSTOM_LIGHT_COLOR \n";
    386. fragmentLightingBlock += " vec3 lightColor = czm_lightColor;\n"; // 使用cesium灯光颜色
    387. fragmentLightingBlock += "#else \n";
    388. fragmentLightingBlock += " vec3 lightColor = gltf_lightColor;\n"; // 使用gltf灯光颜色
    389. fragmentLightingBlock += "#endif \n";
    390. fragmentLightingBlock += " vec3 l = normalize(czm_lightDirectionEC);\n"; // 相机空间下灯光方向
    391. var minimumLighting = "0.2"; // Use strings instead of values as 0.0 -> 0 when stringified
    392. // 漫反射颜色
    393. fragmentLightingBlock +=
    394. " diffuseLight += lightColor * max(dot(normal,l), " +
    395. minimumLighting +
    396. ");\n";
    397. // 存在高光
    398. if (hasSpecular) {
    399. // blinn灯光
    400. if (lightingModel === "BLINN") {
    401. fragmentLightingBlock += " vec3 h = normalize(l + viewDir);\n";
    402. fragmentLightingBlock +=
    403. " float specularIntensity = max(0., pow(max(dot(normal, h), 0.), u_shininess));\n";
    404. } else {
    405. // PHONG灯光
    406. fragmentLightingBlock += " vec3 reflectDir = reflect(-l, normal);\n";
    407. fragmentLightingBlock +=
    408. " float specularIntensity = max(0., pow(max(dot(reflectDir, viewDir), 0.), u_shininess));\n";
    409. }
    410. fragmentLightingBlock +=
    411. " specularLight += lightColor * specularIntensity;\n";
    412. }
    413. }
    414. // 拼接main
    415. vertexShader += "void main(void) {\n";
    416. vertexShader += vertexShaderMain;
    417. vertexShader += "}\n";
    418. // 处理像素着色器
    419. fragmentShader += "void main(void) {\n";
    420. var colorCreationBlock = " vec3 color = vec3(0.0, 0.0, 0.0);\n";
    421. // 法线
    422. if (hasNormals) {
    423. fragmentShader += " vec3 normal = normalize(v_normal);\n";
    424. if (khrMaterialsCommon.doubleSided) {
    425. fragmentShader += " if (czm_backFacing())\n";
    426. fragmentShader += " {\n";
    427. fragmentShader += " normal = -normal;\n";
    428. fragmentShader += " }\n";
    429. }
    430. }
    431. var finalColorComputation;
    432. // 不是恒定灯光
    433. if (lightingModel !== "CONSTANT") {
    434. // 漫反射
    435. if (defined(techniqueUniforms.u_diffuse)) {
    436. if (techniqueUniforms.u_diffuse.type === WebGLConstants.SAMPLER_2D) {
    437. fragmentShader +=
    438. " vec4 diffuse = texture2D(u_diffuse, " + v_texcoord + ");\n";
    439. } else {
    440. fragmentShader += " vec4 diffuse = u_diffuse;\n";
    441. }
    442. fragmentShader += " vec3 diffuseLight = vec3(0.0, 0.0, 0.0);\n";
    443. colorCreationBlock += " color += diffuse.rgb * diffuseLight;\n";
    444. }
    445. // 高光
    446. if (hasSpecular) {
    447. if (techniqueUniforms.u_specular.type === WebGLConstants.SAMPLER_2D) {
    448. fragmentShader +=
    449. " vec3 specular = texture2D(u_specular, " + v_texcoord + ").rgb;\n";
    450. } else {
    451. fragmentShader += " vec3 specular = u_specular.rgb;\n";
    452. }
    453. fragmentShader += " vec3 specularLight = vec3(0.0, 0.0, 0.0);\n";
    454. colorCreationBlock += " color += specular * specularLight;\n";
    455. }
    456. // 透明
    457. if (defined(techniqueUniforms.u_transparency) && false) {
    458. finalColorComputation =
    459. " gl_FragColor = vec4(color * diffuse.a * u_transparency, diffuse.a * u_transparency);\n";
    460. } else {
    461. finalColorComputation =
    462. //" gl_FragColor = vec4(color * diffuse.a, diffuse.a);\n";
    463. " gl_FragColor = vec4(diffuse.rgb * 1.5, 1.0);\n";
    464. }
    465. } else if (defined(techniqueUniforms.u_transparency)) {
    466. // 恒定灯光下的透明
    467. finalColorComputation =
    468. " gl_FragColor = vec4(color * u_transparency, u_transparency);\n";
    469. } else {
    470. // 最终的颜色
    471. finalColorComputation = " gl_FragColor = vec4(color, 1.0);\n";
    472. }
    473. // 顶点颜色
    474. if (hasVertexColors) {
    475. colorCreationBlock += " color *= v_vertexColor.rgb;\n";
    476. }
    477. // 自发光
    478. if (defined(techniqueUniforms.u_emission)) {
    479. if (techniqueUniforms.u_emission.type === WebGLConstants.SAMPLER_2D) {
    480. fragmentShader +=
    481. " vec3 emission = texture2D(u_emission, " + v_texcoord + ").rgb;\n";
    482. } else {
    483. fragmentShader += " vec3 emission = u_emission.rgb;\n";
    484. }
    485. colorCreationBlock += " color += emission;\n";
    486. }
    487. // 环境光
    488. if (defined(techniqueUniforms.u_ambient) || lightingModel !== "CONSTANT") {
    489. if (defined(techniqueUniforms.u_ambient)) {
    490. // 纹理中的环境光漫反射
    491. if (techniqueUniforms.u_ambient.type === WebGLConstants.SAMPLER_2D) {
    492. fragmentShader +=
    493. " vec3 ambient = texture2D(u_ambient, " + v_texcoord + ").rgb;\n";
    494. } else {
    495. fragmentShader += " vec3 ambient = u_ambient.rgb;\n";
    496. }
    497. } else {
    498. fragmentShader += " vec3 ambient = diffuse.rgb;\n";
    499. }
    500. // 颜色相加
    501. colorCreationBlock += " color += ambient * ambientLight;\n";
    502. }
    503. //
    504. fragmentShader += " vec3 viewDir = -normalize(v_positionEC);\n";
    505. fragmentShader += " vec3 ambientLight = vec3(0.0, 0.0, 0.0);\n";
    506. // Add in light computations 拼接灯光计算片段
    507. fragmentShader += fragmentLightingBlock;
    508. fragmentShader += colorCreationBlock;
    509. fragmentShader += finalColorComputation;
    510. fragmentShader += "}\n";
    511. // Add shaders 着色片段数组中添加一个顶点片段
    512. // 将新生成的片段添加到原来的gltf中,
    513. var vertexShaderId = addToArray(shaders, {
    514. type: WebGLConstants.VERTEX_SHADER, // 属于顶点着色器
    515. extras: { // 额外的数据
    516. _pipeline: { // 管线
    517. source: vertexShader, // 顶点着色片段
    518. extension: ".glsl", //glsl
    519. },
    520. },
    521. });
    522. // 将新生成的片段添加到原来的gltf中,
    523. var fragmentShaderId = addToArray(shaders, {
    524. type: WebGLConstants.FRAGMENT_SHADER, // 属于像素着色器
    525. extras: {
    526. _pipeline: {
    527. source: fragmentShader,
    528. extension: ".glsl",
    529. },
    530. },
    531. });
    532. // Add program 将新生成的片段添加到原来的gltf中索引中,添加着色程序片段
    533. var programId = addToArray(programs, {
    534. fragmentShader: fragmentShaderId,
    535. vertexShader: vertexShaderId,
    536. });
    537. // 添加到techniques数组中,返回索引位置
    538. var techniqueId = addToArray(techniques, {
    539. attributes: techniqueAttributes, // 属性片段
    540. program: programId, // shader片段
    541. uniforms: techniqueUniforms, // uniform片段
    542. });
    543. return techniqueId;
    544. }

  • 相关阅读:
    JavaSE学习--数据类型和运算符
    【学习笔记】ARC11123
    C语言经典算法实例1:求二维数组最大最小值
    分享Arduino环境下加速下载 第三方库或芯片包
    DIFM网络详解及复现
    计算机网络
    自动化办公02 用openpyxl库操作excel.xlsx文件(新版本)
    数据结构之详解【Map和Set】
    ITIL-4关键词汇总
    【TensorFlow深度学习】张量Broadcasting机制与数学运算实践
  • 原文地址:https://blog.csdn.net/tianyapai/article/details/126728460