CesiumJS源码分析


这篇文章主要介绍“CesiumJS源码分析”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“CesiumJS源码分析”文章能帮助大家解决问题。CesiumJS 支持的光的类型比较少,默认场景光就一个太阳光:从上面这代码可知,CesiumJS 目前场景中只支持加入一个光源。查阅 API,可得知除了 SubLight 之外,还有一个 DirectionalLight,即方向光。官方示例代码《Lighting》中就使用了方向光来模拟手电筒效果(flashLight)、月光效果(moonLight)、自定义光效果。方向光比太阳光多出来一个必选的方向属性:这个 direction 属性是一个单位向量即可(模长是 1)。说起来归一化、规范化、标准化好像都能在网上找到与单位向量类似的意思,都是向量除以模长。可见,CesiumJS 并没有内置点光源、聚光灯,需要自己写着色过程(请参考 Primitive API 或 CustomShader API)。既然 CesiumJS 支持的光只有一个,那么调查起来就简单了。先给结论:光是作为 Uniform 值传递到着色器中的。 先查清楚光是如何从 Scene.light 转至 Renderer 中的 uniform 的。在 Scene 渲染一帧的过程中,几乎就在最顶部,Scene.js 模块内的函数 render 就每帧更新着 Context 对象的 uniformState 属性:这个 uniformState 对象就是 CesiumJS 绝大多数统一值(Uniform)的封装集合,它的更新方法就会更新来自帧状态对象(FrameState)的光参数:那么,这个挂在 Context 上的 uniformState 对象包含的光状态信息,是什么时候被使用的呢?下一小节 2.2 就会介绍。在 Scene 的更新过程中,最后 DrawCommand 对象被 Context 对象执行:就在 continueDraw 函数中,调用了 ShaderProgram 对象的 _setUniforms 方法,所有 Uniform 值在此将传入 WebGL 状态机中。而这每一个 uniforms[i],都是一个没有公开在 API 文档中的私有类,也就是接下来 2.3 小节中要介绍的 WebGL Uniform 值封装对象。进入 createUniforms.js 模块:可以说把 WebGL uniform 的类型都封装了一个私有类。以表示光方向的 UniformFloatVec3 类为例,看看它的 WebGL 调用:在 2.2 小节中有一个细节没有详细说明,即 ShaderProgram_setUniforms 方法中为什么可以直接调用每一个 uniforms[i]set()?回顾一下:Scene.jsrender 函数内,光的信息被 us.update(frameState) 更新至 UniformState 对象中;ShaderProgram_setUniforms 方法,调用 uniforms[i].set() 方法, 更新每一个私有 Uniform 对象上的值到 WebGL 状态机中是不是缺少了点什么?是的,UniformState 的值是如何赋予给 uniforms[i] 的?这就不得不提及 ShaderProgram.js 模块中为当前着色器对象的 Uniform 分类过程了,查找模块中的 reinitialize 函数:它把着色器对象上的 Uniform 全部找了出来,并分类为:_uniformsByName – 一个字典对象,键名是着色器中 uniform 的变量名,值是 Uniform 的封装对象,例如 UniformFloatVec3_uniforms – 一个数组,每个元素都是 Uniform 的封装对象,例如 UniformFloatVec3 等,若同名,则与 _uniformsByName 中的值是同一个引用_manualUniforms – 一个数组,每个元素都是 Uniform 的封装对象,例如 UniformFloatVec3 等,若同名,则与 _uniformsByName 中的值是同一个引用_automaticUniforms – 一个数组,每个元素是一个 object 对象,免费云主机域名表示要 CesiumJS 自动更新的 Uniform 的映射关联关系举例,_automaticUniforms[i] 用 TypeScript 来描述,是这么一个对象:而这个 _automaticUniforms 就拥有自动更新 CesiumJS 内部状态的 Uniform 值的功能,例如我们所需的光状态信息。来看 AutomaticUniforms.js 模块的默认导出对象:所以,在 ShaderProgram.prototype._setUniforms 执行的时候,其实是对自动统一值有一个赋值的过程,然后才到各个 uniforms[i]set() 过程:也许这个过程有些乱七八糟,那就再简单梳理一次:Scene 的 render 过程中,更新了 uniformStateContext 执行 DrawCommand 过程中,ShaderProgram 的 _setUniforms 执行所有 uniforms 的 WebGL 设置,这其中就会对 CesiumJS 内部不需要手动更新的 Uniform 状态信息进行自动刷新而在 ShaderProgram 绑定前,早就会把这个着色器中的 uniform 进行分组,一组是常规的 uniform 值,另一组则是需要根据 AutomaticUniform(自动统一值)更新的 uniform 值说到底,光状态信息也不过是一种 Uniform,在最原始的 WebGL 学习教材中也是如此,只不过 CesiumJS 是一个更复杂的状态机器,需要更多逻辑划分就是了。上面介绍完光的类型、在 CesiumJS 源码中如何转化成 Uniform 并刷入 WebGL,那么这一节就简单看看光的状态 Uniform 在着色器代码中都有哪些使用之处。PointCloud.js 使用了 czm_lightColor。找到 createShaders 函数下面这个分支:显然,这段代码在拼凑顶点着色器代码,在 1.104 版本官方并没有改变这种拼接着色器代码的模式。着色代码的含义也很简单,将漫反射强度值乘上 czm_lightColor,把结果交给 color 的 xyz 分量。漫反射强度在这里限制了最大值 0.4。漫反射强度来自内置 GLSL 函数 czm_getLambertDiffuse(参考 packages/engine/Source/Shaders/Builtin/Functions/getLambertDiffuse.glsl)Primitive API 材质对象的默认着色方法是 冯氏着色法(Phong),这个在 LearnOpenGL 网站上有详细介绍。调用链:除了 TexturedMaterialAppearanceFS 外,MaterialAppearance.js 还用了 BasicMaterialAppearanceFSAllMaterialAppearanceFS 两个片元着色器,这俩也用到了 czm_phong 函数。看看 czm_phong 函数本体:函数内前面的计算步骤是获取漫反射、高光值,走的是辅助函数,在这个文件内也能看到。最后灯光 czm_lightColor 和材质的漫反射、兰伯特漫反射、材质辉光等因子一起相乘累加,得到最终的颜色值。除了 phong.glsl 外,参与半透明计算的 czm_translucentPhong 函数(在 translucentPhong.glsl 文件中)在 OIT.js 模块中用于替换 czm_phong 函数。在 Globe.js 中使用的 GlobeFS 片元着色器代码中使用到了 czm_lightColor,主要是 main 函数中:同样是先获取兰伯特漫反射值(使用 clamp 函数钉死在 [0, 1] 区间内),然后将颜色、czm_lightColor、漫反射值和透明度一起计算出 finalColor,把最终颜色值交给下一步计算。这里区分了两个宏分支,受 TerrainProvider 影响,有兴趣可以追一下 GlobeSurfaceTileProvider.js 模块中 addDrawCommandsForTile 函数中 hasVertexNormals 参数的获取。在 1.97 大改的 Model API 中,PBR 着色法使用了 czm_lightColorHdr 变量。czm_lightColorHdr 也是自动统一值(AutomaticUniforms)的一个。在 Model 的更新过程中,有一个 buildDrawCommands 的步骤,其中有一个函数 ModelRuntimePrimitive.prototype.configurePipeline 会增减 ModelRuntimePrimitive 上的着色阶段:上面是其中一个阶段 —— LightingPipelineStage,最后在 ModelSceneGraph.prototype.buildDrawCommands 方法内会调用每一个 stage 的 process 方法,调用 shaderBuilder 构建出着色器对象所需的材料,进而构建出着色器对象。过程比较复杂,直接看其中 LightingPipelineStage.glsl 提供的阶段函数:进入 computePbrLighting 函数(同一个文件内):故,存在 USE_CUSTOM_LIGHT_COLOR 宏时才会使用 czm_lightColorHdr 变量作为灯光颜色,参与函数 czm_pbrLighting 计算出颜色值。关于“CesiumJS源码分析”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注百云主机行业资讯频道,小编每天都会为大家更新不同的知识点。

相关推荐: jquery如何根据id移除元素

本篇内容介绍了“jquery如何根据id移除元素”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! jquery根据id移除元素的方法:1、通过id属性值选中指定元…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

(0)
打赏 微信扫一扫 微信扫一扫
上一篇 07/01 11:56
下一篇 07/01 12:02

相关推荐