Cesium中实现体渲染

体渲染 Volume Rendering

传统意义上我们构建模型都是通过构建物体的外表面去实现的,例如通过三角面构建模型,或者通过方程的形式构建隐式的表面模型。

而体渲染则是通过 3d 数据集渲染物体的一种方式,典型的 3d 数据集是医学领域上的 CT,CT 是一组 2d 的切片图像(例如,每毫米深度进行一次切片),因此 3d 数据集也可以理解成一组存放 2d 贴图的数组。

通过 3d 数据集可以渲染出具有内部信息的模型。

Threejs 中的体渲染示例

Threejs 中有一些非常优秀的体渲染示例,这次的目的就是在 cesium 中复现这些示例。

体积云

在这里插入图片描述

柏林噪声

在这里插入图片描述

在 Cesium 中复现

翻看 Threejs 的相关源码,可以很轻松的获取到 3D 贴图数据的计算方式,以及相关的着色器代码。

但是比较麻烦的一点是,Cesium 目前并不支持 sampler3D,并且在默认使用 WebGL1 情况下不支持 glsl 3.0 的语法。

不支持 sampler3D 和 glsl 3.0 的语法的解决办法

对于支持 glsl 3.0 语法的问题,只需要在构建 Viewer 时传入参数,利用 WebGL2 渲染即可。


contextOptions: {
  requestWebgl2: true, // 开启webgl2
}

而对于 sampler3D 的支持,我的做法是对 Cesium 的源码进行一点改造,仿照 Cesium 原有的 Texture 类,再构建一个 Texture3 类用于传入 sampler3D 纹理。

着色器代码适配

在 Threejs 的顶点着色器中,计算 vOrigin 的方式是传入相机的世界坐标 cameraPos, 再乘以模型矩阵的逆矩阵获得的。

而在 Cesium 中,则可以直接利用内部变量计算得到

vOrigin=czm_encodedCameraPositionMCHigh+czm_encodedCameraPositionMCLow;

片元着色器基本照搬即可,需要注意的是,Threejs 的片元着色器是利用 color 的变量输出最终结果的,因此移植到 Cesium 中还需要将其输出到 gl_FragColor 中

实现效果

在这里插入图片描述

实际体验

由于csdn无法放置自定义的html,因此如果想体验实际效果,请移步Cesium中实现体渲染

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Cesium,您可以使用`CustomDataSource`和`CustomRenderPrimitive`来自定义渲染代码。 `CustomDataSource`是一种特殊类型的`DataSource`,它允许您在场景添加自定义的实和几何图形。您可以使用`CustomRenderPrimitive`在场景添加自定义的渲染图元,每个渲染图元都可以实现自己的渲染逻辑。 以下是一个简单的示例,演示如何使用`CustomDataSource`和`CustomRenderPrimitive`来自定义渲染代码: ```javascript // 创建Cesium Viewer var viewer = new Cesium.Viewer('cesiumContainer'); // 创建自定义数据源 var customDataSource = new Cesium.CustomDataSource('custom'); // 添加自定义实 var entity = customDataSource.entities.add({ position: Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883), billboard: { image: 'path/to/image.png', scale: 2.0 } }); viewer.dataSources.add(customDataSource); // 创建自定义渲染图元 var customPrimitive = new Cesium.CustomRenderPrimitive({ geometryInstances: new Cesium.GeometryInstance({ geometry: new Cesium.RectangleGeometry({ rectangle: Cesium.Rectangle.fromDegrees(-75.0, 35.0, -125.0, 45.0) }), attributes: { color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED) } }), fragmentShaderSource: 'void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); }', vertexShaderSource: 'attribute vec3 position3DHigh;\ attribute vec3 position3DLow;\ attribute vec4 color;\ varying vec4 v_color;\ void main() {\ vec4 position = czm_computePosition();\ gl_Position = czm_viewProjection * position;\ v_color = color;\ }', renderState: { blending: Cesium.BlendingState.DISABLED, depthTest: { enabled: true, func: Cesium.DepthFunction.LESS }, depthMask: true, polygonOffset: { enabled: false, factor: 0.0, units: 0.0 } } }); viewer.scene.primitives.add(customPrimitive); ``` 在上面的代码,我们首先创建了一个Cesium Viewer,并创建了一个自定义数据源。然后,我们向自定义数据源添加了一个自定义实,并将其添加到场景。接下来,我们创建了一个自定义渲染图元,并将其添加到场景。在自定义渲染图元,我们使用了自定义的顶点着色器和片段着色器,并设置了渲染状态。 请注意,上面的示例仅用于演示目的。实际应用,您可能需要更复杂的渲染逻辑和着色器代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值