Cesium的着色器是一个很庞大的技术体系,我们使用起来相对还是比较容易的。Cesium内置了很多以CZM_开头的函数和Uniform。这些着色器是如何关联,又是如何调用的呢?
为了方便表示,我们可以做一个想象。一堆货物需要经过码头,放到货轮上,运往远处。
1、货物(JS代码生成的对象)
为啥需要走这个流程呢?这是因为WebGL跟OpenGL、DirectX不一样。在WebGL中并没有Camera、View这种实例类,你需要在GLSL中编写相关脚本。也就是说,离开着色器是写不了WebGL的,一个最简单的WebGL程序都需要定义顶点着色器和片元着色器。
2、UniformState(码头)
这个玩意相当于码头。在这个类中,积累了大量运行参数,包括摄像头、View信息,比如_view3D、_viewRotation、_lightColor等等。UniformState提供setView()等函数,可以将JS计算得到的投影矩阵存储到本类的属性中。
3、AutomaticUniforms(货轮)
这玩意相当于货轮。在这个类中,它会把UniformState的_view3D等对象转化为Cesium着色器对应的名词,通俗一点就是包装。比如uniformState.viewportCartesian4被包装成czm_viewport。看到这里,你应该差不多想到后面的操作了。
4、ShaderProgram(远方)
这玩意相当于远方的消费市场。当然,你也清楚,不同的Shader使用的CZM_的数量是不一样的,因此在这里,还会调用partitionUniforms方法找出哪些名词需要映射到Cesium着色器中。而不是把AutomaticUniforms所有的对象都映射过去。最后这个映射方法是_setUniforms。
5、GLSL的绑定Shader的方法
下面我以表的方式,把WebGL绑定Shader的方法列出来。
序号 | 类型 | 方法 | 函数 |
1A | 顶点着色器 | 创建流水线对象 | const vertexShader = gl.createShader(gl.VERTEX_SHADER); |
1B | 片元着色器 | const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); | |
2A | 顶点着色器 | 设定脚本语言 | gl.shaderSource(vertexShader, vsSource); |
2B | 片元着色器 | gl.shaderSource(fragmentShader, fsSource); | |
3A | 顶点着色器 | 编译脚本 | gl.compileShader(vertexShader); |
3B | 片元着色器 | gl.compileShader(fragmentShader); | |
4 | 创建流水线管道 | const program = gl.createProgram(); | |
5A | 顶点着色器 | 绑定脚本语言 | gl.attachShader(program, vertexShader); |
5B | 片元着色器 | gl.attachShader(program, fragmentShader); | |
6 | 绑定属性(数组) | gl.bindAttribLocation( program, attributeLocations[attribute], attribute); | |
7 | 链接流水线管道 | gl.linkProgram(program); | |
8 | 如果不做异常判断,则上述流程结束,否则需要下面流程 | ||
9 | 获得流水线管道链接状态(对应7 ) | gl.getProgramParameter(program, gl.LINK_STATUS),返回boolean | |
10A | 顶点着色器 | 获得编译日志 | log = gl.getShaderInfoLog(vertexShader) |
10B | 片元着色器 | log = gl.getShaderInfoLog(fragmentShader); | |
10C | 获得链接日志(对应7) | log = gl.getProgramInfoLog(program) | |
11 | 获得流水线管道编译状态(对应7) | gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS),返回boolean | |
12A | 顶点着色器 | 删除Shader | gl.deleteShader(vertexShader); |
12B | 片元着色器 | gl.deleteShader(fragmentShader); | |
12C | 流水线管道 | gl.deleteProgram(program); |