cesium比较区别 opengl_Cesium原理篇:6 Render模块(3: Shader)

本文深入探讨Cesium中Shader模块的封装,包括ShaderSource的创建、内建变量CzmBuiltins和AutomaticUniforms的管理,以及ShaderProgram的创建和渲染状态。文章介绍了Cesium如何通过ShaderSource合并GLSL代码,利用ShaderCache实现缓存,从而提高性能。同时,文章指出ShaderSource在合并过程中的计算成本,并提到了特殊情况如多影像图层叠加的处理。
摘要由CSDN通过智能技术生成

在介绍Renderer的第一篇,我就提到WebGL1.0对应的是OpenGL ES2.0,也就是可编程渲染管线。之所以单独强调这一点,算是为本篇埋下一个伏笔。通过前两篇,我们介绍了VBO和Texture两个比较核心的WebGL概念。假设生产一辆汽车,VBO就相当于这个车的骨架,纹理相当这个车漆,但有了骨架和车漆还不够,还需要一台机器人来加工,最终才能成产出这辆汽车。而Shader模块就是负责这个生产的过程,加工参数(VBO,Texture),执行渲染任务。

这里假设大家对Shader有一个基本的了解,这一块内容也很多,不可能简单两句轻描淡写就豁然开朗,而且我也没有进行过系统的学习,所以就不班门弄斧了。进入主题,来看看Cesium对Shader的封装。

图1:ES2.0可编程渲染管线

上图是可编程渲染管线的一个大概流程,我们关注的两个橙色的圆角矩形部分,分别是顶点着色器和片源着色器。既然是可编程渲染管线,面向Shader的开发者提供了一种称为GLSL的语言,如果你懂C的话,两者语法是相当的,所以从语法层面学习成本不大。

ShaderSource创建

首先,Cesium提供了ShaderSource类来加载GLSL代码,我们来看一下它对应的拷贝构造函数:

ShaderSource.prototype.clone = function() {return newShaderSource({

sources :this.sources,

defines :this.defines,

pickColorQuantifier :this.pickColorQualifier,

includeBuiltIns :this.includeBuiltIns

});

};

sources

必须,代码本身,这里是一个数组,可以是多个代码片段的叠加

defines

非必须,执行该代码时声明的预编译宏

pickColorQualifier

非必须,当需要点击选中地物时设置此参数,值为'uniform',下面会介绍其大概

includeBuiltIns

非必须,默认为true,认为需要加载Cesium自带的GLSL变量或function,下面会详细介绍

在使用上,通常只需要指定前两个参数,就可以创建一个顶点或片元着色器,比如在Globe中创建渲染地球的着色器代码就是这么的简单:

//顶点着色器

this._surfaceShaderSet.baseVertexShaderSource = newShaderSource({

sources : [GroundAtmosphere, GlobeVS]

});//片元着色器

this._surfaceShaderSet.baseFragmentShaderSource = newShaderSource({

sources : [GlobeFS]

});

ShaderSource脚本加载

当然用起来简单,但其内部实现还是有些复杂的,在介绍ShaderSource前需要先了解两个知识点:CzmBuiltins&AutomaticUniforms。

CzmBuiltins

Cesium中提供了一些常用的GLSL文件,文件夹结构如下图:

图2:BuiltIn文件夹清单

如图所示主要分为三类(常量,方法,结构体),这些都是Cesium框架内部比较常用的基本结构和方法,属于内建类型,它们的特点是前缀均为czm_并且通过CzmBuiltins.js(打包时gulp会自动生成该文件)引用所有内建的GLSL代码:

//1 常量,例如:1 / Pi

onst float czm_oneOverPi = 0.3183098861837907;//方法,例如:八进制解码,地形数据中用于数据压缩

vec3 czm_octDecode(vec2 encoded)

{

encoded= encoded / 255.0 * 2.0 - 1.0;

vec3 v= vec3(encoded.x, encoded.y, 1.0 - abs(encoded.x) -abs(encoded.y));if (v.z < 0.0)

{

v.xy= (1.0 - abs(v.yx)) *czm_signNotZero(v.xy);

}returnnormalize(v);

}//结构体,例如:材质

structczm_material

{

vec3 diffuse;floatspecular;floatshininess;

vec3 normal;

vec3 emission;floatalpha;

};

AutomaticUniforms

然而作为参数而言,仅仅有这些Const常量还是不够的,比如在一个三维场景中,随着位置的变化,相机的状态也是需要更新的,比如ModelViewMatrix,ProjectMatrix以及ViewPort等变量通常也需要参与到GLSL的计算中,Cesium提供了AutomaticUniform类,用来封装这些内建的变量,构造函数如下:

functionAutomaticUniform(options) {this._size =options.size;this._datatype =options.datatype;this.getValue =options.getValue;

}

所有的内部变量都可以基于该构造函数创建,并添加到AutomaticUniforms数组中,并且在命名上也遵守czm_*的格式,通过命名就可以知道该变量是不是内建的,如果是,则从CzmBuiltins和AutomaticUniforms对应的列表(创建列表并维护的过程则是在ShaderSource中完成的,下面会讲)中找其对应的值就可以,这样,Cesium内部自动调用这些变量而不需要用户来处理,如果不是,则需要用户自己定义一个uniformMap的数组来自己维护。如下是AutomaticUniforms的代码片段,可以看到AutomaticUniforms中创建了czm_viewport变量,类型是vec4,并提供了getValue的方式,负责传值。

var AutomaticUniforms ={

czm_viewport :newAutomaticUniform(

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值