赞
踩
Cesium 源码解析 Model(一)中主要介绍了数据的前期准备工作,也就是数据下载完成(解析gltf,解析json和二进制数据,查看数据是否完整,如果有使用url的资源就去下载,这个不包括纹理的下载),对于数据的处理过程,需要根据this._state === ModelState.LOADING的状态确定下面的步骤:
代码如下:
- Model.prototype.update = function (frameState) {
-
- ......
-
-
- // 正在加载
- if (this._state === ModelState.LOADING) {
- // Transition from LOADING -> LOADED once resources are downloaded and created.
- // Textures may continue to stream in while in the LOADED state.
- // 下载并创建资源后,从加载转换到加载。在加载状态下,纹理可能会继续流入。
-
- // 没有正在下载的外部buffer数据了,数据都已经下载完了
- if (loadResources.pendingBufferLoads === 0) {
- // 没有初始化
- if (!loadResources.initialized) {
- // 生成动态一张纹理brdf的纹理
- frameState.brdfLutGenerator.update(frameState);
- // 检查gltf的扩展cesium中是否都支持(不支持投递异常,日志中体现),虽然cesium支持但是浏览器不一定支持
- ModelUtility.checkSupportedExtensions(
- this.extensionsRequired,
- supportsWebP
- );
- // 更新前向轴
- ModelUtility.updateForwardAxis(this);
-
- // glTF pipeline updates, not needed if loading from cache
- // 是否定义了数据源版本
- if (!defined(this.gltf.extras.sourceVersion)) {
- var gltf = this.gltf;
- // Add the original version so it remains cached
- // 添加原始版本到缓存状态
- gltf.extras.sourceVersion = ModelUtility.getAssetVersion(gltf);
- // 定义了扩展KHR_techniques_webgl(内部包含自定义glsl等)
- gltf.extras.sourceKHRTechniquesWebGL = defined(
- ModelUtility.getUsedExtensions(gltf).KHR_techniques_webgl // 定义了KHR_techniques_webgl扩展
- );
- // 版本
- this._sourceVersion = gltf.extras.sourceVersion;
- // 扩展KHR_techniques_webgl是否定义
- this._sourceKHRTechniquesWebGL = gltf.extras.sourceKHRTechniquesWebGL;
-
- // 应该是将gltf1.0版本的数据改成2.0的数据, 为了支持1.0中的technique在2.0中使用了KHR_techniques_webgl扩展
- updateVersion(gltf);
- // 为gltf中各个属性添加默认值(buffer、material等)
- addDefaults(gltf);
-
- // glsl中是否添加批次表片段
- var options = {
- addBatchIdToGeneratedShaders: this._addBatchIdToGeneratedShaders,
- };
-
- // 处理KHR_materials_common扩展,扩展的所有的材质相信息,扩展的gltf的默认参数设置、shader片段拼接
- processModelMaterialsCommon(gltf, options);
- // 处理pbr材质
- processPbrMaterials(gltf, options);
- }
-
- // gltf版本
- this._sourceVersion = this.gltf.extras.sourceVersion;
- // 原始的glsl、uniform、attribute相关信息,与处理过的gltf.sourceKHRTechniquesWebGL信息不同
- this._sourceKHRTechniquesWebGL = this.gltf.extras.sourceKHRTechniquesWebGL;
-
- // Skip dequantizing in the shader if not encoded
- // 如果未编码,则跳过着色器中的解码
- this._dequantizeInShader =
- this._dequantizeInShader && DracoLoader.hasExtension(this);
-
- // We do this after to make sure that the ids don't change
- // 之后我们会这样做,以确保ID不会更改
-
- // 将buffer添加到gpu资源中, 存入ModelLoadResources
- addBuffersToLoadResources(this);
- // 解析骨骼动画关节
- parseArticulations(this);
- // 将gltf中的Techniques拷贝到model的成员变量中,
- parseTechniques(this);
- // 不是从缓存中加载(缓存中是已经解析过的数据,不用再处理了)
- if (!this._loadRendererResourcesFromCache) {
- // 解析bufferviewid,顶点、索引数据, 存入ModelLoadResources
- parseBufferViews(this);
- // 着色器shaderid, 存入ModelLoadResources
- parseShaders(this);
- // 着色程序programid, 存入ModelLoadResources
- parsePrograms(this);
- // 纹理id, 存入ModelLoadResources
- parseTextures(this, context, supportsWebP);
- }
- parseMaterials(this); // 解析材质(包含了真实的运行时数据存储)
- parseMeshes(this); // 解析网格(包含了真实的运行时数据存储)
- parseNodes(this); // 解析节点(包含了真实的运行时数据存储)
-
- // Start draco decoding // 解析draco编码的二进制数据
- DracoLoader.parse(this, context);
-
- // 初始化完成
- loadResources.initialized = true; // 资源部初始化完成
- }
-
- // 解码未完成
- if (!loadResources.finishedDecoding()) {
- // 解码模型
- DracoLoader.decodeModel(this, context).otherwise(
- ModelUtility.getFailedLoadFunction(this, "model", this.basePath)
- );
- }
-
- // 解码完成,资源还没解析完成
- if (loadResources.finishedDecoding() && !loadResources.resourcesParsed) {
- // 计算包围球
- this._boundingSphere = ModelUtility.computeBoundingSphere(this);
- // 包围球半径
- this._initialRadius = this._boundingSphere.radius;
-
- // 如果设置了cacheKey,缓存解码后的数据
- DracoLoader.cacheDataForModel(this);
-
- // 解析完成
- loadResources.resourcesParsed = true;
- }
-
- // 解析完成、外部链接的shader代码下载完成
- if (
- loadResources.resourcesParsed &&
- loadResources.pendingShaderLoads === 0
- ) {
- // 显示外轮廓线
- if (this.showOutline) {
- // 轮廓线是一个扩展选项,是cesium定义的,模型生成的轮廓线的数据???
- ModelOutlineLoader.outlinePrimitives(this);
- }
- // 创建gpu资源
- createResources(this, frameState);
- }
- }
-
- if (
- loadResources.finished() || // 资源加载完成或者纹理逐渐加载
- (incrementallyLoadTextures &&
- loadResources.finishedEverythingButTextureCreation()) // 除了纹理之外的所有数据都处理完了
- ) {
- // 模型装载完成(之后完成才能渲染)
- this._state = ModelState.LOADED;
- justLoaded = true;
- }
- }
-
- ......
- };
过程步骤如下:
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支持的扩展有:
- // 所有的gltf扩展内容
- ModelUtility.supportedExtensions = {
- AGI_articulations: true,
- CESIUM_RTC: true, // rtc中心
- EXT_texture_webp: true, // webp
- KHR_blend: true, // 混合
- KHR_binary_glTF: true,
- KHR_texture_basisu: true,
- KHR_draco_mesh_compression: true, // 压缩格式
- KHR_materials_common: true, // 通用材质gltf1.0版本
- KHR_techniques_webgl: true, // 自定义着色器
- KHR_materials_unlit: true, // 无灯光材质
- KHR_materials_pbrSpecularGlossiness: true, 光泽度材质模型
- KHR_texture_transform: true, // 纹理变换
- WEB3D_quantized_attributes: true,
- };
6、ModelUtility.updateForwardAxis(this); 主要是gltf1.0、2.0中定义的模型前向轴的方向不同,1.0对应的是model._gltfForwardAxis = Axis.X;
7、下面的代码是将gltf2.0之前的格式转换成一种自定义的格式,目的是能统一处理。
- // 是否定义了数据源版本
- if (!defined(this.gltf.extras.sourceVersion)) {
- var gltf = this.gltf;
- // Add the original version so it remains cached
- // 添加原始版本到缓存状态
- gltf.extras.sourceVersion = ModelUtility.getAssetVersion(gltf);
- // 定义了扩展KHR_techniques_webgl(内部包含自定义glsl等)
- gltf.extras.sourceKHRTechniquesWebGL = defined(
- ModelUtility.getUsedExtensions(gltf).KHR_techniques_webgl // 定义了KHR_techniques_webgl扩展
- );
- // 版本
- this._sourceVersion = gltf.extras.sourceVersion;
- // 扩展KHR_techniques_webgl是否定义
- this._sourceKHRTechniquesWebGL = gltf.extras.sourceKHRTechniquesWebGL;
-
- // 应该是将gltf1.0版本的数据改成2.0的数据, 为了支持1.0中的technique在2.0中使用了KHR_techniques_webgl扩展
- updateVersion(gltf);
- // 为gltf中各个属性添加默认值(buffer、material等)
- addDefaults(gltf);
-
- // glsl中是否添加批次表片段
- var options = {
- addBatchIdToGeneratedShaders: this._addBatchIdToGeneratedShaders,
- };
-
- // 处理KHR_materials_common扩展,扩展的所有的材质相信息,扩展的gltf的默认参数设置、shader片段拼接
- processModelMaterialsCommon(gltf, options);
- // 处理pbr材质
- processPbrMaterials(gltf, options);
- }
8、updateVersion(gltf);中将2.0之前的格式转换成一种兼容格式,代码如下:
- // 应该是将gltf1.0版本的数据改成2.0的数据
- function updateVersion(gltf, options) {
- options = defaultValue(options, defaultValue.EMPTY_OBJECT);
- const targetVersion = options.targetVersion;
- // 版本
- let version = gltf.version;
-
- // 如果asset存在就使用,不存在就设置1.0
- gltf.asset = defaultValue(gltf.asset, {
- version: "1.0",
- });
-
- // 设置版本
- gltf.asset.version = defaultValue(gltf.asset.version, "1.0");
- version = defaultValue(version, gltf.asset.version).toString();
-
- // Invalid version
- if (!Object.prototype.hasOwnProperty.call(updateFunctions, version)) {
- // Try truncating trailing version numbers, could be a number as well if it is 0.8
- if (defined(version)) {
- version = version.substring(0, 3);
- }
- // Default to 1.0 if it cannot be determined
- if (!Object.prototype.hasOwnProperty.call(updateFunctions, version)) {
- version = "1.0";
- }
- }
-
- // 根据gltf的版本获取更新函数(跟新1.0到2.0)
- let updateFunction = updateFunctions[version];
-
- // 需要gltf版本转换,通过函数进行转换
- while (defined(updateFunction)) {
- if (version === targetVersion) {
- break;
- }
- updateFunction(gltf, options);
- version = gltf.asset.version;
- updateFunction = updateFunctions[version];
- }
- return gltf;
- }
其中let updateFunction = updateFunctions[version];是查找转换函数:
- // gltf的版本处理函数
- const updateFunctions = {
- 0.8: glTF08to10, // 0.8转换成1.0的过程
- "1.0": glTF10to20, // 1.0转换成2.0的过程
- "2.0": undefined, // 如果默认是2.0就不用在转换了
- };
对于gltf1.0、gltf2.0的规范:
可以看出,1.0是用json对象的方式建立索引,2.0是使用json数组的方式建立索引,json字符串的大小会减少很多。
9、addDefaults(gltf);主要是对于gltf中不完整的数据(某些缺省了)进行完善(填充完整)。
- function addDefaults(gltf) {
- // 遍历访问器
- ForEach.accessor(gltf, function (accessor) {
- if (defined(accessor.bufferView)) {
- // 设置默认的访问器偏移量为0
- accessor.byteOffset = defaultValue(accessor.byteOffset, 0);
- }
- });
-
- // 遍历bufferviews
- ForEach.bufferView(gltf, function (bufferView) {
- if (defined(bufferView.buffer)) {
- // 设置默认的偏移量为0
- bufferView.byteOffset = defaultValue(bufferView.byteOffset, 0);
- }
- });
-
- // 遍历mesh
- ForEach.mesh(gltf, function (mesh) {
- // mesh的primitive
- ForEach.meshPrimitive(mesh, function (primitive) {
- // 默认绘制三角形
- primitive.mode = defaultValue(primitive.mode, WebGLConstants.TRIANGLES);
- // 材质未定义
- if (!defined(primitive.material)) {
- // 如果json中没有任何材质,材质为空数组
- if (!defined(gltf.materials)) {
- gltf.materials = [];
- }
- const defaultMaterial = {
- name: "default",
- };
- // 材质未定义,设置mesh的材质索引为“default”
- primitive.material = addToArray(gltf.materials, defaultMaterial);
- }
- });
- });
-
- // 遍历顶点属性数据
- ForEach.accessorContainingVertexAttributeData(gltf, function (accessorId) {
- // 找到属性对应的gltf中的accessor访问器
- const accessor = gltf.accessors[accessorId];
- // 获取对应bufferview的索引
- const bufferViewId = accessor.bufferView;
- // 是否归一化
- accessor.normalized = defaultValue(accessor.normalized, false);
- if (defined(bufferViewId)) {
- // 找到bufferview
- const bufferView = gltf.bufferViews[bufferViewId];
- // 填充步长大小
- bufferView.byteStride = getAccessorByteStride(gltf, accessor);
- // bufferview的目标是顶点数组
- bufferView.target = WebGLConstants.ARRAY_BUFFER;
- }
- });
-
- // 包含绘制索引
- ForEach.accessorContainingIndexData(gltf, function (accessorId) {
- // 找到索引对应的具体访问器
- const accessor = gltf.accessors[accessorId];
- // 找到索引对应的bufferView
- const bufferViewId = accessor.bufferView;
- if (defined(bufferViewId)) {
- // 设置bufferView的目标是索引缓冲
- const bufferView = gltf.bufferViews[bufferViewId];
- bufferView.target = WebGLConstants.ELEMENT_ARRAY_BUFFER;
- }
- });
-
- // 遍历材质
- ForEach.material(gltf, function (material) {
- // 材质中是否有扩展
- const extensions = defaultValue(
- material.extensions,
- defaultValue.EMPTY_OBJECT
- );
- // 材质中的KHR_materials_common扩展,定义光照模型,光照参数
- const materialsCommon = extensions.KHR_materials_common;
- if (defined(materialsCommon)) {
- // 获取自定义的光照模型,以及与光照模型相对应的values值
- const technique = materialsCommon.technique;
- const values = defined(materialsCommon.values)
- ? materialsCommon.values
- : {};
- materialsCommon.values = values;
-
- // 定义了环境光
- values.ambient = defined(values.ambient)
- ? values.ambient
- : [0.0, 0.0, 0.0, 1.0];
- // 定义了自发光
- values.emission = defined(values.emission)
- ? values.emission
- : [0.0, 0.0, 0.0, 1.0];
- // 定义了透明度
- values.transparency = defaultValue(values.transparency, 1.0);
- values.transparent = defaultValue(values.transparent, false);
- // 定义了双面渲染
- values.doubleSided = defaultValue(values.doubleSided, false);
-
- // 不是恒定的
- if (technique !== "CONSTANT") {
- values.diffuse = defined(values.diffuse)
- ? values.diffuse
- : [0.0, 0.0, 0.0, 1.0];
- // 不是兰伯特,应该是phong或者blinn,需要高光
- if (technique !== "LAMBERT") {
- // 高光
- values.specular = defined(values.specular)
- ? values.specular
- : [0.0, 0.0, 0.0, 1.0];
- // 高光强度
- values.shininess = defaultValue(values.shininess, 0.0);
- }
- }
- return;
- }
-
- // 自发光因子
- material.emissiveFactor = defaultValue(
- material.emissiveFactor,
- [0.0, 0.0, 0.0]
- );
- // 透明模式
- material.alphaMode = defaultValue(material.alphaMode, "OPAQUE");
- // 双面渲染
- material.doubleSided = defaultValue(material.doubleSided, false);
- // 遮罩
- if (material.alphaMode === "MASK") {
- material.alphaCutoff = defaultValue(material.alphaCutoff, 0.5);
- }
-
- // 如果有KHR_techniques_webgl扩展????
- const techniquesExtension = extensions.KHR_techniques_webgl;
- if (defined(techniquesExtension)) {
- // 遍历单个材质中的属性
- ForEach.materialValue(material, function (materialValue) {
- // Check if material value is a TextureInfo object
- // 是纹理就添加纹理缓存引用
- if (defined(materialValue.index)) {
- // 纹理坐标引用
- addTextureDefaults(materialValue);
- }
- });
- }
-
- // 添加纹理坐标引用(自发光贴图、法线贴图、遮蔽图)
- addTextureDefaults(material.emissiveTexture);
- addTextureDefaults(material.normalTexture);
- addTextureDefaults(material.occlusionTexture);
-
- // 金属、粗糙度
- const pbrMetallicRoughness = material.pbrMetallicRoughness;
- if (defined(pbrMetallicRoughness)) {
- // 基本颜色
- pbrMetallicRoughness.baseColorFactor = defaultValue(
- pbrMetallicRoughness.baseColorFactor,
- [1.0, 1.0, 1.0, 1.0]
- );
- // 金属都因子
- pbrMetallicRoughness.metallicFactor = defaultValue(
- pbrMetallicRoughness.metallicFactor,
- 1.0
- );
- // 粗糙度因子
- pbrMetallicRoughness.roughnessFactor = defaultValue(
- pbrMetallicRoughness.roughnessFactor,
- 1.0
- );
- // 默认纹理坐标引用
- addTextureDefaults(pbrMetallicRoughness.baseColorTexture);
- addTextureDefaults(pbrMetallicRoughness.metallicRoughnessTexture);
- }
-
- // 高光光泽度模型
- const pbrSpecularGlossiness =
- extensions.KHR_materials_pbrSpecularGlossiness;
- if (defined(pbrSpecularGlossiness)) {
- // 漫反射
- pbrSpecularGlossiness.diffuseFactor = defaultValue(
- pbrSpecularGlossiness.diffuseFactor,
- [1.0, 1.0, 1.0, 1.0]
- );
- // 镜面
- pbrSpecularGlossiness.specularFactor = defaultValue(
- pbrSpecularGlossiness.specularFactor,
- [1.0, 1.0, 1.0]
- );
- // 光泽度
- pbrSpecularGlossiness.glossinessFactor = defaultValue(
- pbrSpecularGlossiness.glossinessFactor,
- 1.0
- );
- // 光泽度纹理
- addTextureDefaults(pbrSpecularGlossiness.specularGlossinessTexture);
- }
- });
-
- // 动画
- ForEach.animation(gltf, function (animation) {
- ForEach.animationSampler(animation, function (sampler) {
- sampler.interpolation = defaultValue(sampler.interpolation, "LINEAR");
- });
- });
-
- // 动画节点
- const animatedNodes = getAnimatedNodes(gltf);
- ForEach.node(gltf, function (node, id) {
- const animated = defined(animatedNodes[id]);
- if (
- animated ||
- defined(node.translation) ||
- defined(node.rotation) ||
- defined(node.scale)
- ) {
- node.translation = defaultValue(node.translation, [0.0, 0.0, 0.0]);
- node.rotation = defaultValue(node.rotation, [0.0, 0.0, 0.0, 1.0]);
- node.scale = defaultValue(node.scale, [1.0, 1.0, 1.0]);
- } else {
- node.matrix = defaultValue(
- node.matrix,
- [
- 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,
- 0.0, 1.0,
- ]
- );
- }
- });
-
- // 采样器
- ForEach.sampler(gltf, function (sampler) {
- sampler.wrapS = defaultValue(sampler.wrapS, WebGLConstants.REPEAT); // 默认是重复
- sampler.wrapT = defaultValue(sampler.wrapT, WebGLConstants.REPEAT);
- });
-
- // 默认场景0
- if (defined(gltf.scenes) && !defined(gltf.scene)) {
- gltf.scene = 0;
- }
-
- return gltf;
- }
例如:
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);中代码如下:
- // 处KHR_materials_common扩展
- function processModelMaterialsCommon(gltf, options) {
- options = defaultValue(options, defaultValue.EMPTY_OBJECT);
-
- if (!defined(gltf)) {
- return;
- }
-
- // 没有使用扩展材质就返回
- if (!usesExtension(gltf, "KHR_materials_common")) {
- return;
- }
-
- // 使用KHR_materials_common就必须使用KHR_techniques_webgl
- if (!usesExtension(gltf, "KHR_techniques_webgl")) {
- // 没有扩展就创建扩展
- if (!defined(gltf.extensions)) {
- gltf.extensions = {};
- }
-
- // 添加默认数组
- gltf.extensions.KHR_techniques_webgl = {
- programs: [], // 程序
- shaders: [], // 着色器
- techniques: [], // glsl代码,attibute、uniform
- };
- // 将使用的扩展加入
- gltf.extensionsUsed.push("KHR_techniques_webgl");
- gltf.extensionsRequired.push("KHR_techniques_webgl");
- }
-
- // 自定义glsl、uniform、attribute等信息
- var techniquesWebgl = gltf.extensions.KHR_techniques_webgl;
-
- // 灯光默认值
- lightDefaults(gltf);
-
- // 收集灯光参数,后续uniform会使用 (灯光颜色、矩阵、衰减参数等)
- var lightParameters = generateLightParameters(gltf);
-
- // 通过mesh的材质索引封装mesh的顶点属性信息,因为这些顶点属性会影像材质(hasNormal、hasVertexColor等)
- var primitiveByMaterial = ModelUtility.splitIncompatibleMaterials(gltf);
-
- var techniques = {};
- var generatedTechniques = false;
- // 遍历材质 生成technique
- ForEach.material(gltf, function (material, materialIndex) {
- if ( // 定义了扩展
- defined(material.extensions) &&
- defined(material.extensions.KHR_materials_common)
- ) {
- // 光照模型(phong、blinn等)
- var khrMaterialsCommon = material.extensions.KHR_materials_common;
- // 材质对应的顶点属性信息
- var primitiveInfo = primitiveByMaterial[materialIndex];
- // 获取Technique相关的信息,作为一个shader的唯一key,用于缓存shader,以及区别shader
- // 将所有影像材质的信息做成一个key
- var techniqueKey = getTechniqueKey(khrMaterialsCommon, primitiveInfo);
- // 缓存避免重复处理
- var technique = techniques[techniqueKey];
-
- // 缓存中没有找到就生成
- if (!defined(technique)) {
- // 拼接成很多个glsl片段、顶点属性片段、uniform对象, 收集attribute、uniform、组成shaders、program、technique
- technique = generateTechnique(
- gltf, // 原始数据
- techniquesWebgl, // 自定义glsl、uniform、attribute等信息,生成的technique会添加到这个数组中
- primitiveInfo, // 顶点属性的一些影响材质的信息(hasNormal、hasVertexColor等)
- khrMaterialsCommon, // 光照模型(模型自身材质反射率)
- lightParameters, // 所有的灯光参数(灯光位置、颜色、衰减参数)
- options.addBatchIdToGeneratedShaders // 添加批次表id
- );
- // 缓存到techniques中,避免重复处理
- techniques[techniqueKey] = technique;
- // 生成了techniques
- generatedTechniques = true;
- }
-
- // 收集gltf中提供的uniform的值
- var materialValues = {};
- var values = khrMaterialsCommon.values;
- var uniformName;
- for (var valueName in values) {
- if (
- values.hasOwnProperty(valueName) &&
- valueName !== "transparent" && // 不是透明
- valueName !== "doubleSided" // 不是双面渲染
- ) {
- uniformName = "u_" + valueName.toLowerCase();
- materialValues[uniformName] = values[valueName]; // 添加uniform名-值
- }
- }
-
- // 添加到材质的扩展,包括technique索引和values(uniform的数值)
- material.extensions.KHR_techniques_webgl = {
- technique: technique,
- values: materialValues,
- };
-
- // 设置材质中的模式
- material.alphaMode = "OPAQUE";
- if (khrMaterialsCommon.transparent) {
- material.alphaMode = "BLEND"; // 透明模式为混合
- }
-
- // 设置材质中的双面渲染
- if (khrMaterialsCommon.doubleSided) { // 双面渲染
- material.doubleSided = true;
- }
- }
- });
-
- // 没有生成直接返回
- if (!generatedTechniques) {
- return gltf;
- }
-
- // If any primitives have semantics that aren't declared in the generated
- // shaders, we want to preserve them.
- // 确保语义存在
- ModelUtility.ensureSemanticExistence(gltf);
- return gltf;
- }
其中lightDefaults(gltf);主要是完善灯光信息(gltf中的灯光使用了默认值,这里需要完善一下)
function generateLightParameters(gltf)函数主要是收集灯光信息,这些信息主要是为后续的glsl字符串的拼接、uniform的数据的收集使用。
var primitiveByMaterial = ModelUtility.splitIncompatibleMaterials(gltf);函数会收集顶点属性等信息,这些信息为后续拼接glsl以及attibute等有帮助。
对于每一个材质var techniqueKey = getTechniqueKey(khrMaterialsCommon, primitiveInfo)会依据材质所使用的所有关键信息拼接成一个唯一值,以区别不同的材质。
- technique = generateTechnique(
- gltf, // 原始数据
- techniquesWebgl, // 自定义glsl、uniform、attribute等信息,生成的technique会添加到这个数组中
- primitiveInfo, // 顶点属性的一些影响材质的信息(hasNormal、hasVertexColor等)
- khrMaterialsCommon, // 光照模型(模型自身材质反射率)
- lightParameters, // 所有的灯光参数(灯光位置、颜色、衰减参数)
- options.addBatchIdToGeneratedShaders // 添加批次表id
- );
上述代码会根据各方面的信息生成technique,并将这个索引添加到material.extensions.KHR_techniques_webgl中,后续是由这个结构生成着色程序。
- // 生成Technique,其中包括shader、uniform、attribute所有的信息
- function generateTechnique(
- gltf,
- techniquesWebgl,
- primitiveInfo,
- khrMaterialsCommon,
- lightParameters, // 灯光参数
- addBatchIdToGeneratedShaders
- ) {
- // 未定义
- if (!defined(khrMaterialsCommon)) {
- khrMaterialsCommon = {};
- }
-
- // 批次表的id片段
- addBatchIdToGeneratedShaders = defaultValue(
- addBatchIdToGeneratedShaders,
- false
- );
-
- // gltf中自带的数据:用户自定义的(一般不会自定义,这些是在默认值中创建的)
- var techniques = techniquesWebgl.techniques; // 包括解析后的glsl的顶点属性片段、shader片段、以及uniform封装对象
- var shaders = techniquesWebgl.shaders; // 自定义的着色器片段
- var programs = techniquesWebgl.programs; // 自定义的程序片段
- var lightingModel = khrMaterialsCommon.technique.toUpperCase(); // 灯光模式(恒定、blinn、phong)
-
- var lights;
- if ( // 定义了通用材质
- defined(gltf.extensions) &&
- defined(gltf.extensions.KHR_materials_common)
- ) {
- // 获取灯光数组(环境光、点光源、聚光灯)
- lights = gltf.extensions.KHR_materials_common.lights;
- }
-
- // 与khrMaterialsCommon.technique对应的模型反射率等
- var parameterValues = khrMaterialsCommon.values;
- // 骨骼节点数
- var jointCount = defaultValue(khrMaterialsCommon.jointCount, 0);
-
- var skinningInfo;
- var hasSkinning = false;
- var hasVertexColors = false;
-
- // gltf中mesh中存储的索引信息
- if (defined(primitiveInfo)) {
- // 骨骼信息、顶点颜色
- skinningInfo = primitiveInfo.skinning;
- hasSkinning = skinningInfo.skinned;
- hasVertexColors = primitiveInfo.hasVertexColors;
- }
-
- // 拼接shader分为几部分:
- /*
- vertexShader\fragmentShader : 函数外的attribute、uniform、varing在vertexShader字符串中,
- vertexShaderMain: 函数内的处理过程在vertexShaderMain字符串中,
- techniqueUniforms: uniform相关信息,
- techniqueAttributes: attribute相关信息
- */
- // 默认高精度
- var vertexShader = "precision highp float;\n";
- var fragmentShader = "precision highp float;\n";
-
- // 光照模型不是恒定的,可能是lambert等,就需要法线参数
- var hasNormals = lightingModel !== "CONSTANT";
-
- // Add techniques 添加uniform数据矩阵信息
- var techniqueUniforms = {
- u_modelViewMatrix: { // 模型视图矩阵
- semantic: usesExtension(gltf, "CESIUM_RTC") // 如果使用了rtc,在glsl中使用CESIUM_RTC_MODELVIEW关键字,否则使用MODELVIEW
- ? "CESIUM_RTC_MODELVIEW"
- : "MODELVIEW",
- type: WebGLConstants.FLOAT_MAT4, // 类型是mat4
- },
- u_projectionMatrix: { // 定义投影矩阵,代码中的名称是u_projectionMatrix,对应glsl中的关键字是PROJECTION
- semantic: "PROJECTION",
- type: WebGLConstants.FLOAT_MAT4,
- },
- };
-
- if (hasNormals) { // 存在法线
- techniqueUniforms.u_normalMatrix = {
- semantic: "MODELVIEWINVERSETRANSPOSE", // 模型视图矩阵的逆矩阵
- type: WebGLConstants.FLOAT_MAT3, // 类型是mat3
- };
- }
-
- if (hasSkinning) { // 存在骨骼
- techniqueUniforms.u_jointMatrix = {
- count: jointCount, // 节点数
- semantic: "JOINTMATRIX", // 节点矩阵,glsl中的uniform关键字
- type: WebGLConstants.FLOAT_MAT4,
- };
- }
-
- // Add material values 添加材质值反射率信息
- var uniformName;
- var hasTexCoords = false;
- for (var name in parameterValues) { //
- //generate shader parameters for KHR_materials_common attributes
- //(including a check, because some boolean flags should not be used as shader parameters)
- if (
- parameterValues.hasOwnProperty(name) && // 本身的数据
- name !== "transparent" && // 透明
- name !== "doubleSided" // 双面渲染
- ) {
- var uniformType = getKHRMaterialsCommonValueType( // 获取值的类型
- name,
- parameterValues[name]
- );
- // 拼接uniform名称
- uniformName = "u_" + name.toLowerCase();
- // 存在纹理坐标
- if (!hasTexCoords && uniformType === WebGLConstants.SAMPLER_2D) {
- hasTexCoords = true;
- }
- // 添加uniform相关的名称与类型,一次拼接glsl中的uniform,没有语义
- techniqueUniforms[uniformName] = {
- type: uniformType,
- };
- }
- }
-
- // Give the diffuse uniform a semantic to support color replacement in 3D Tiles
- // 为漫反射均匀提供语义,以支持3D瓦片中的颜色替换
- if (defined(techniqueUniforms.u_diffuse)) {
- techniqueUniforms.u_diffuse.semantic = "_3DTILESDIFFUSE";
- }
-
- // Copy light parameters into technique parameters
- // 赋值unifrom的灯光信息
- if (defined(lightParameters)) {
- for (var lightParamName in lightParameters) {
- if (lightParameters.hasOwnProperty(lightParamName)) {
- uniformName = "u_" + lightParamName;
- techniqueUniforms[uniformName] = lightParameters[lightParamName];
- }
- }
- }
-
- // Add uniforms to shaders 将uniform添加到glsl中
- for (uniformName in techniqueUniforms) {
- if (techniqueUniforms.hasOwnProperty(uniformName)) {
- var uniform = techniqueUniforms[uniformName];
- var arraySize = defined(uniform.count) ? "[" + uniform.count + "]" : ""; // 如果uniform是数组
- if ( // 不是mat3\mat4并且是用在片段着色器中
- (uniform.type !== WebGLConstants.FLOAT_MAT3 &&
- uniform.type !== WebGLConstants.FLOAT_MAT4) ||
- uniform.useInFragment // 用在片段着色器中
- ) {
- // 拼接片段着色器中的uniform常量
- fragmentShader +=
- "uniform " +
- webGLConstantToGlslType(uniform.type) +
- " " +
- uniformName +
- arraySize +
- ";\n";
- // 使用完了就删除
- delete uniform.useInFragment;
- } else {
- // 拼接顶点着色器中的unifrom常量
- vertexShader +=
- "uniform " +
- webGLConstantToGlslType(uniform.type) +
- " " +
- uniformName +
- arraySize +
- ";\n";
- }
- }
- }
-
- // Add attributes with semantics 添加语义属性
-
- // 顶点着色器main函数
- var vertexShaderMain = "";
-
- // 存在骨骼的情况,在顶点着色器的main中拼接
- if (hasSkinning) {
- // 根据骨骼索引找到骨骼矩阵,骨骼矩阵乘以权重
- vertexShaderMain +=
- " mat4 skinMatrix =\n" +
- " a_weight.x * u_jointMatrix[int(a_joint.x)] +\n" +
- " a_weight.y * u_jointMatrix[int(a_joint.y)] +\n" +
- " a_weight.z * u_jointMatrix[int(a_joint.z)] +\n" +
- " a_weight.w * u_jointMatrix[int(a_joint.w)];\n";
- }
-
- // Add position always 添加顶点属性中的顶点
- var techniqueAttributes = {
- a_position: { //
- semantic: "POSITION", // 语义是顶点
- },
- };
- // 顶点着色器中的顶点属性位置属性、转递属性(相机空间中的坐标)
- vertexShader += "attribute vec3 a_position;\n";
- vertexShader += "varying vec3 v_positionEC;\n";
- // 存在骨骼
- if (hasSkinning) {
- // 计算骨骼变换后的相机空间坐标
- vertexShaderMain +=
- " vec4 pos = u_modelViewMatrix * skinMatrix * vec4(a_position,1.0);\n";
- } else {
- // 直接计算相机空间坐标
- vertexShaderMain +=
- " vec4 pos = u_modelViewMatrix * vec4(a_position,1.0);\n";
- }
- // 转递的相机空间坐标
- vertexShaderMain += " v_positionEC = pos.xyz;\n";
- // 投影
- vertexShaderMain += " gl_Position = u_projectionMatrix * pos;\n";
-
- // 像素着色器中接收的相机空间坐标
- fragmentShader += "varying vec3 v_positionEC;\n";
-
- // Add normal if we don't have constant lighting 如果没有恒定照明,则添加“正常”
- if (hasNormals) {
- // 存在法线
- techniqueAttributes.a_normal = {
- semantic: "NORMAL",
- };
- // 法线
- vertexShader += "attribute vec3 a_normal;\n";
- vertexShader += "varying vec3 v_normal;\n";
- if (hasSkinning) {
- // 骨骼中会计算法线
- vertexShaderMain +=
- " v_normal = u_normalMatrix * mat3(skinMatrix) * a_normal;\n";
- } else {
- vertexShaderMain += " v_normal = u_normalMatrix * a_normal;\n";
- }
- // 像素着色器中接收的法线坐标
- fragmentShader += "varying vec3 v_normal;\n";
- }
- // Add texture coordinates if the material uses them 天啊及纹理坐标
- var v_texcoord;
- if (hasTexCoords) {
- techniqueAttributes.a_texcoord_0 = { // 纹理坐标
- semantic: "TEXCOORD_0",
- };
- // 顶点着色器中的纹理坐标
- v_texcoord = "v_texcoord_0";
- vertexShader += "attribute vec2 a_texcoord_0;\n";
- vertexShader += "varying vec2 " + v_texcoord + ";\n";
- // 转递纹理坐标
- vertexShaderMain += " " + v_texcoord + " = a_texcoord_0;\n";
- // 像素着色器中接收的纹理坐标
- fragmentShader += "varying vec2 " + v_texcoord + ";\n";
- }
- if (hasSkinning) {
- // 骨骼节点属性
- techniqueAttributes.a_joint = {
- semantic: "JOINTS_0",
- };
- // 权重属性
- techniqueAttributes.a_weight = {
- semantic: "WEIGHTS_0",
- };
- // 骨骼矩阵索引,权重属性,都是vec4的
- vertexShader += "attribute vec4 a_joint;\n";
- vertexShader += "attribute vec4 a_weight;\n";
- }
- if (hasVertexColors) {
- // 颜色属性
- techniqueAttributes.a_vertexColor = {
- semantic: "COLOR_0",
- };
- // 顶点颜色、传递顶点颜色
- vertexShader += "attribute vec4 a_vertexColor;\n";
- vertexShader += "varying vec4 v_vertexColor;\n";
- vertexShaderMain += " v_vertexColor = a_vertexColor;\n";
- // 像素着色器中接收的顶点颜色
- fragmentShader += "varying vec4 v_vertexColor;\n";
- }
- // 批次id属性
- if (addBatchIdToGeneratedShaders) {
- techniqueAttributes.a_batchId = { //
- semantic: "_BATCHID", // 语义
- };
- // 顶点着色器中添加批次id
- vertexShader += "attribute float a_batchId;\n";
- }
- // 存在高光
- var hasSpecular =
- hasNormals &&
- (lightingModel === "BLINN" || lightingModel === "PHONG") && // 灯光模式为blinn或者phong
- defined(techniqueUniforms.u_specular) && // 存在高光、高光强度
- defined(techniqueUniforms.u_shininess) &&
- techniqueUniforms.u_shininess > 0.0;
- // Generate lighting code blocks 生成灯光代码块
- var hasNonAmbientLights = false;
- var hasAmbientLights = false;
- var fragmentLightingBlock = ""; // 像素着色器代码段
- for (var lightName in lights) { // 遍历灯光
- if (lights.hasOwnProperty(lightName)) {
- var light = lights[lightName];
- var lightType = light.type.toLowerCase(); // 灯光类型(环境光、点光源、聚光灯)
- var lightBaseName = light.baseName;
- fragmentLightingBlock += " {\n";
- var lightColorName = "u_" + lightBaseName + "Color"; // 灯光颜色
- var varyingDirectionName;
- var varyingPositionName;
- if (lightType === "ambient") { // 如果是换进光
- hasAmbientLights = true;
- fragmentLightingBlock += //
- " ambientLight += " + lightColorName + ";\n"; // glsl中的颜色相加
- } else if (hasNormals) { // 存在法线
- hasNonAmbientLights = true;
- varyingDirectionName = "v_" + lightBaseName + "Direction"; // 方向光
- varyingPositionName = "v_" + lightBaseName + "Position"; // 方向光的位置
- if (lightType !== "point") { // 不是点光源
- vertexShader += "varying vec3 " + varyingDirectionName + ";\n"; // v传递方向光
- fragmentShader += "varying vec3 " + varyingDirectionName + ";\n"; // f接收方向光
- vertexShaderMain +=
- " " +
- varyingDirectionName +
- " = mat3(u_" +
- lightBaseName +
- "Transform) * vec3(0.,0.,1.);\n";
- if (lightType === "directional") {
- fragmentLightingBlock +=
- " vec3 l = normalize(" + varyingDirectionName + ");\n";
- }
- }
- if (lightType !== "directional") { // 不是方向光
- vertexShader += "varying vec3 " + varyingPositionName + ";\n";
- fragmentShader += "varying vec3 " + varyingPositionName + ";\n";
- vertexShaderMain +=
- " " +
- varyingPositionName +
- " = u_" +
- lightBaseName +
- "Transform[3].xyz;\n";
- fragmentLightingBlock +=
- " vec3 VP = " + varyingPositionName + " - v_positionEC;\n";
- fragmentLightingBlock += " vec3 l = normalize(VP);\n";
- fragmentLightingBlock += " float range = length(VP);\n";
- fragmentLightingBlock +=
- " float attenuation = 1.0 / (u_" +
- lightBaseName +
- "Attenuation.x + ";
- fragmentLightingBlock +=
- "(u_" + lightBaseName + "Attenuation.y * range) + ";
- fragmentLightingBlock +=
- "(u_" + lightBaseName + "Attenuation.z * range * range));\n";
- } else {
- fragmentLightingBlock += " float attenuation = 1.0;\n";
- }
- // 聚光灯
- if (lightType === "spot") {
- fragmentLightingBlock +=
- " float spotDot = dot(l, normalize(" +
- varyingDirectionName +
- "));\n";
- fragmentLightingBlock +=
- " if (spotDot < cos(u_" + lightBaseName + "FallOff.x * 0.5))\n";
- fragmentLightingBlock += " {\n";
- fragmentLightingBlock += " attenuation = 0.0;\n";
- fragmentLightingBlock += " }\n";
- fragmentLightingBlock += " else\n";
- fragmentLightingBlock += " {\n";
- fragmentLightingBlock +=
- " attenuation *= max(0.0, pow(spotDot, u_" +
- lightBaseName +
- "FallOff.y));\n";
- fragmentLightingBlock += " }\n";
- }
- fragmentLightingBlock +=
- " diffuseLight += " +
- lightColorName +
- "* max(dot(normal,l), 0.) * attenuation;\n";
- if (hasSpecular) {
- if (lightingModel === "BLINN") {
- fragmentLightingBlock += " vec3 h = normalize(l + viewDir);\n";
- fragmentLightingBlock +=
- " float specularIntensity = max(0., pow(max(dot(normal, h), 0.), u_shininess)) * attenuation;\n";
- } else {
- // PHONG
- fragmentLightingBlock +=
- " vec3 reflectDir = reflect(-l, normal);\n";
- fragmentLightingBlock +=
- " float specularIntensity = max(0., pow(max(dot(reflectDir, viewDir), 0.), u_shininess)) * attenuation;\n";
- }
- fragmentLightingBlock +=
- " specularLight += " +
- lightColorName +
- " * specularIntensity;\n";
- }
- }
- fragmentLightingBlock += " }\n";
- }
- }
- // 不存在环境光
- if (!hasAmbientLights) {
- // Add an ambient light if we don't have one
- fragmentLightingBlock += " ambientLight += vec3(0.2, 0.2, 0.2);\n";
- }
-
- // 存在换进光
- if (!hasNonAmbientLights && lightingModel !== "CONSTANT") {
- // 自定义了灯光颜色
- fragmentShader += "#ifdef USE_CUSTOM_LIGHT_COLOR \n";
- fragmentShader += "uniform vec3 gltf_lightColor; \n";
- fragmentShader += "#endif \n";
-
- // 未定义灯光颜色
- fragmentLightingBlock += "#ifndef USE_CUSTOM_LIGHT_COLOR \n";
- fragmentLightingBlock += " vec3 lightColor = czm_lightColor;\n"; // 使用cesium灯光颜色
- fragmentLightingBlock += "#else \n";
- fragmentLightingBlock += " vec3 lightColor = gltf_lightColor;\n"; // 使用gltf灯光颜色
- fragmentLightingBlock += "#endif \n";
-
- fragmentLightingBlock += " vec3 l = normalize(czm_lightDirectionEC);\n"; // 相机空间下灯光方向
- var minimumLighting = "0.2"; // Use strings instead of values as 0.0 -> 0 when stringified
-
- // 漫反射颜色
- fragmentLightingBlock +=
- " diffuseLight += lightColor * max(dot(normal,l), " +
- minimumLighting +
- ");\n";
-
- // 存在高光
- if (hasSpecular) {
- // blinn灯光
- if (lightingModel === "BLINN") {
- fragmentLightingBlock += " vec3 h = normalize(l + viewDir);\n";
- fragmentLightingBlock +=
- " float specularIntensity = max(0., pow(max(dot(normal, h), 0.), u_shininess));\n";
- } else {
- // PHONG灯光
- fragmentLightingBlock += " vec3 reflectDir = reflect(-l, normal);\n";
- fragmentLightingBlock +=
- " float specularIntensity = max(0., pow(max(dot(reflectDir, viewDir), 0.), u_shininess));\n";
- }
-
- fragmentLightingBlock +=
- " specularLight += lightColor * specularIntensity;\n";
- }
- }
-
- // 拼接main
- vertexShader += "void main(void) {\n";
- vertexShader += vertexShaderMain;
- vertexShader += "}\n";
-
- // 处理像素着色器
- fragmentShader += "void main(void) {\n";
- var colorCreationBlock = " vec3 color = vec3(0.0, 0.0, 0.0);\n";
- // 法线
- if (hasNormals) {
- fragmentShader += " vec3 normal = normalize(v_normal);\n";
- if (khrMaterialsCommon.doubleSided) {
- fragmentShader += " if (czm_backFacing())\n";
- fragmentShader += " {\n";
- fragmentShader += " normal = -normal;\n";
- fragmentShader += " }\n";
- }
- }
-
- var finalColorComputation;
- // 不是恒定灯光
- if (lightingModel !== "CONSTANT") {
- // 漫反射
- if (defined(techniqueUniforms.u_diffuse)) {
- if (techniqueUniforms.u_diffuse.type === WebGLConstants.SAMPLER_2D) {
- fragmentShader +=
- " vec4 diffuse = texture2D(u_diffuse, " + v_texcoord + ");\n";
- } else {
- fragmentShader += " vec4 diffuse = u_diffuse;\n";
- }
- fragmentShader += " vec3 diffuseLight = vec3(0.0, 0.0, 0.0);\n";
- colorCreationBlock += " color += diffuse.rgb * diffuseLight;\n";
- }
-
- // 高光
- if (hasSpecular) {
- if (techniqueUniforms.u_specular.type === WebGLConstants.SAMPLER_2D) {
- fragmentShader +=
- " vec3 specular = texture2D(u_specular, " + v_texcoord + ").rgb;\n";
- } else {
- fragmentShader += " vec3 specular = u_specular.rgb;\n";
- }
- fragmentShader += " vec3 specularLight = vec3(0.0, 0.0, 0.0);\n";
- colorCreationBlock += " color += specular * specularLight;\n";
- }
-
- // 透明
- if (defined(techniqueUniforms.u_transparency) && false) {
- finalColorComputation =
- " gl_FragColor = vec4(color * diffuse.a * u_transparency, diffuse.a * u_transparency);\n";
- } else {
- finalColorComputation =
- //" gl_FragColor = vec4(color * diffuse.a, diffuse.a);\n";
- " gl_FragColor = vec4(diffuse.rgb * 1.5, 1.0);\n";
- }
- } else if (defined(techniqueUniforms.u_transparency)) {
- // 恒定灯光下的透明
- finalColorComputation =
- " gl_FragColor = vec4(color * u_transparency, u_transparency);\n";
- } else {
- // 最终的颜色
- finalColorComputation = " gl_FragColor = vec4(color, 1.0);\n";
- }
-
- // 顶点颜色
- if (hasVertexColors) {
- colorCreationBlock += " color *= v_vertexColor.rgb;\n";
- }
-
- // 自发光
- if (defined(techniqueUniforms.u_emission)) {
- if (techniqueUniforms.u_emission.type === WebGLConstants.SAMPLER_2D) {
- fragmentShader +=
- " vec3 emission = texture2D(u_emission, " + v_texcoord + ").rgb;\n";
- } else {
- fragmentShader += " vec3 emission = u_emission.rgb;\n";
- }
- colorCreationBlock += " color += emission;\n";
- }
-
- // 环境光
- if (defined(techniqueUniforms.u_ambient) || lightingModel !== "CONSTANT") {
- if (defined(techniqueUniforms.u_ambient)) {
- // 纹理中的环境光漫反射
- if (techniqueUniforms.u_ambient.type === WebGLConstants.SAMPLER_2D) {
- fragmentShader +=
- " vec3 ambient = texture2D(u_ambient, " + v_texcoord + ").rgb;\n";
- } else {
- fragmentShader += " vec3 ambient = u_ambient.rgb;\n";
- }
- } else {
- fragmentShader += " vec3 ambient = diffuse.rgb;\n";
- }
- // 颜色相加
- colorCreationBlock += " color += ambient * ambientLight;\n";
- }
- //
- fragmentShader += " vec3 viewDir = -normalize(v_positionEC);\n";
- fragmentShader += " vec3 ambientLight = vec3(0.0, 0.0, 0.0);\n";
-
- // Add in light computations 拼接灯光计算片段
- fragmentShader += fragmentLightingBlock;
-
- fragmentShader += colorCreationBlock;
- fragmentShader += finalColorComputation;
- fragmentShader += "}\n";
-
- // Add shaders 着色片段数组中添加一个顶点片段
- // 将新生成的片段添加到原来的gltf中,
- var vertexShaderId = addToArray(shaders, {
- type: WebGLConstants.VERTEX_SHADER, // 属于顶点着色器
- extras: { // 额外的数据
- _pipeline: { // 管线
- source: vertexShader, // 顶点着色片段
- extension: ".glsl", //glsl
- },
- },
- });
-
- // 将新生成的片段添加到原来的gltf中,
- var fragmentShaderId = addToArray(shaders, {
- type: WebGLConstants.FRAGMENT_SHADER, // 属于像素着色器
- extras: {
- _pipeline: {
- source: fragmentShader,
- extension: ".glsl",
- },
- },
- });
-
- // Add program 将新生成的片段添加到原来的gltf中索引中,添加着色程序片段
- var programId = addToArray(programs, {
- fragmentShader: fragmentShaderId,
- vertexShader: vertexShaderId,
- });
-
- // 添加到techniques数组中,返回索引位置
- var techniqueId = addToArray(techniques, {
- attributes: techniqueAttributes, // 属性片段
- program: programId, // shader片段
- uniforms: techniqueUniforms, // uniform片段
- });
-
- return techniqueId;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。