CesiumJS PrimitiveAPI 高级着色入门-使用 GLSL 着色器
CesiumJS 是一个非常强大的开源 JavaScript 库,用于在 web 浏览器中创建 3D 地球仪和 2D 地图。它提供了丰富的API,允许开发者构建复杂的地理空间可视化应用。在 CesiumJS 中,PrimitiveAPI 允许你以较低级别的方式渲染几何体,如点、线和多边形等,这为自定义着色和渲染效果提供了可能。
明确一个定义,在 Primitive API
中应用着色器,实际上是给 Appearance
的 vertexShaderSource
、fragmentShaderSource
或 Material
中的 fabric.source
设置着色器代码,它们所能控制的层级不太一样。但是他们的共同目的都是为了 Geometry 服务的,它们会随着 CesiumJS 的每帧 update 过程,创建 ShaderProgram,创建 DrawCommand,最终去到 WebGL 的底层渲染中。
3D模型在线预览提供多种低代码平台3D模型在线预览解决方案,实现了将多种3D模型格式无缝集成到低代码业务表单中。这意味着用户可以在不离开低代码平台的情况下,直接查看和操作3D模型,极大地提升了数据可视化的效果和用户交互体验。
使用 GLSL 着色器
为 Fabric 材质添加自定义着色代码 - Fabric 材质的本质
有了之前的 fabric.uniforms
、fabric.materials
、fabric.components
基础,你可能迫不及待想写自定义着色器代码了。需要知道的一点是,有了 fabric.source
,就不兼容 fabric.components
了,只能二选一。
关于 fabric.uniforms
,它的所有键名都可以在着色器代码中作为 GLSL Uniform 变量使用;关于 fabric.materials
,它的所有键名都可以在着色器代码中作为 GLSL 变量使用,也就是一个计算完成的 czm_material
结构体变量。
编写 fabric.source
,实际上就是写一个函数,它必须返回一个 czm_material
结构体,且输入一些特定的、当前片元的信息:
czm_material
已经在之前提及过了,它包含了实时渲染所需的一些基本材质参数。而 materialInput
这个变量,它是 czm_materialInput
类型的结构体,定义如下:
其中:
s
- 一维纹理坐标st
- 二维纹理坐标str
- 三维纹理坐标。注意,materialInput.str.st
不一定就是materialInput.st
,也不能保证materialInput.st.s == materialInput.s
,例如对于椭球体而言,s
是底部到顶部的纹理坐标,st
是经纬度,str
可能是范围框的轴向值,这要参考源代码tangentToEyeMatrix
- 片元切线空间到眼坐标系的转换矩阵,用于法线计算等positionToEyeEC
- 片元坐标到观察坐标系(眼坐标系)原点的向量,模长为片元到原点的距离,单位是米,可以用于反射或者折射计算normalEC
- 可用于凹凸映射、反射、折射计算中的眼睛坐标系下的标准化法线
那个 czm_getDefaultMaterial
函数就是获取默认的材质结构,这个函数很简单:
有了上面这些基础,你就可以在这个 czm_getMaterial()
函数体里写你想要的片元着色内容了,注意任意 CesiumJS 的内置变量、自动 Uniform、结构体、内置函数都可以用。
社区实现案例 - 泛光墙体和流动线材质
有了上一节的基础,我们直接参考网上的一些案例。
其用到的渐变纹理可以是任意的一个横向颜色至透明的渐变 png:
效果:
文中还介绍了 Entity
使用自定义 MaterialProperty
的方法,实际上底层也是 Material
:
详细的完整封装调用就不列举了,需要有 Entity API
的使用经验,不在本篇范围。想知道 Property 是如何调用底层的,也需要自己研究 EntityAPI 的底层。
直接定义外观对象的两个着色器
fabric.source
只能作用于材质的片元着色,当然也可以通过编写外观对象的两个着色器实现更大自由。
默认情况下,MaterialAppearance
的顶点着色器与片元着色器是这样的:
顶点着色器调用 czm_computePosition()
函数将 position3DHigh
和 position3DLow
合成为 vec4
的模型坐标,然后乘以 czm_modelViewProjectionRelativeToEye
这个内置的矩阵,得到裁剪坐标。然后是片元着色器:
如果想完全定制 Primitive 的着色行为,需要十分熟悉你所定制的 Geometry 的 VertexBuffer,也要控制好两大着色器之间相互传递的值。
源码中如何合并着色器
这段要讲讲源码,定位到 Primitive.prototype.update()
方法:
使用 createShaderProgram
函数会用到外观对象。
总之,外观的两个着色器也仅仅是 CesiumJS 这个庞大的着色器系统中的一部分,仍有非常多的状态需要添加到着色器对象(ShaderProgram
)上。
CesiumJS PrimitiveAPI 高级着色入门-索引
CesiumJS PrimitiveAPI 高级着色入门-参数化几何
CesiumJS PrimitiveAPI 高级着色入门-外观材质