当前位置: 首页 > news >正文

Cesium进阶教程——自定义图形、外观、绘图基础、现有着色器移植至Cesium、ShadowMapping、视频GIS、模型压平、卷帘

基础必看

WEBGL基础(从渲染管线角度解读)

参考路线

http://www.xt3d.online/tutorial/further/article.html

自定义图形

在这里插入图片描述

https://blog.csdn.net/m0_55049655/article/details/138908327
https://blog.csdn.net/m0_55049655/article/details/140306837
https://blog.51cto.com/u_15080020/4200536
https://blog.csdn.net/xietao20/article/details/142913781

在Cesium中,绘制带颜色的三角形可以使用 PrimitiveGeometry,结合 Material 来实现。以下是一个详细的步骤和代码示例:

必要的输入

  • 三角形节点的坐标(以数组形式提供,例如 [x1, y1, z1, x2, y2, z2, ...])。
  • 三角形的节点颜色(对应每个节点的颜色,例如 [color1, color2, color3],每个颜色是 Cesium.Color 对象)。
  • 三角形的索引值(定义每个三角形的三个顶点索引)。

实现步骤

  1. 创建顶点数组:根据节点的坐标创建一个 Float32Array,代表所有的顶点坐标。
  2. 创建颜色数组:将颜色信息转换为 Uint8Array,每个颜色包含 RGBA 四个分量。
  3. 定义索引:根据提供的索引值定义三角形顶点的连接关系。
  4. 生成 Geometry 对象:使用 Cesium 的 Geometry 来存储顶点、颜色和索引信息。
  5. 创建 Primitive:将 Geometry 包裹在一个 Primitive 中,添加到 Cesium 场景中。

代码示例

以下是完整的代码实现:

// 三角形节点的坐标数组 [x1, y1, z1, x2, y2, z2, ...]
const positions = new Float32Array([0.0, 0.0, 0.0,   // 节点11.0, 0.0, 0.0,   // 节点20.0, 1.0, 0.0    // 节点3
]);// 每个节点对应的颜色数组 [r, g, b, a, r, g, b, a, ...]
const colors = new Uint8Array([255, 0, 0, 255,   // 红色 (节点1)0, 255, 0, 255,   // 绿色 (节点2)0, 0, 255, 255    // 蓝色 (节点3)
]);// 三角形的索引数组(定义三角形的顶点关系)
const indices = new Uint16Array([0, 1, 2  // 一个三角形,由节点1, 2, 3组成
]);// 创建几何体
const geometry = new Cesium.Geometry({attributes: {position: new Cesium.GeometryAttribute({componentDatatype: Cesium.ComponentDatatype.FLOAT,componentsPerAttribute: 3,values: positions}),color: new Cesium.GeometryAttribute({componentDatatype: Cesium.ComponentDatatype.UNSIGNED_BYTE,componentsPerAttribute: 4,values: colors,normalize: true // 归一化到 [0, 1]})},indices: indices,primitiveType: Cesium.PrimitiveType.TRIANGLES // 指定绘制三角形
});// 创建材质
const appearance = new Cesium.PerInstanceColorAppearance({flat: true, // 关闭光照影响translucent: false // 不透明
});// 创建 Primitive
const primitive = new Cesium.Primitive({geometryInstances: new Cesium.GeometryInstance({geometry: geometry}),appearance: appearance
});// 添加到场景
viewer.scene.primitives.add(primitive);

代码解读

  1. 顶点和颜色的绑定
    • GeometryAttribute 用于绑定顶点坐标和颜色信息。
    • 颜色数组的 normalize: true 参数确保颜色范围从 [0, 255] 映射到 [0.0, 1.0]
  2. 索引的作用
    • 索引定义了顶点的连接顺序,减少重复存储顶点的开销。
  3. 材质和外观
    • PerInstanceColorAppearance 直接使用颜色属性,无需纹理。
    • 设置 flat: truetranslucent: false 可以提升渲染效率。

注意事项

  • 如果需要动态更新顶点或颜色,可以重新创建 Geometry 或使用 CustomShader 实现更灵活的渲染。
  • 确保坐标和颜色的数组长度对应,否则会引发错误。

尝试运行这段代码,你应该能看到一个由三角形组成的彩色几何体!

外观

Cesium 中,Material 是一个强大的工具,用于定义几何体外观。它允许开发者通过 顶点着色器(Vertex Shader)和 片段着色器(Fragment Shader)实现自定义效果。以下将从 Material 架构着色器编程、以及 GPU 与 CPU 数据传递 等方面进行详解。


1. Cesium 的 Material 架构

在 Cesium 中,Material 是通过 GLSL 代码(WebGL 的着色器语言)实现的。Cesium 提供了一些预定义的 Material 类型(例如 ColorMaterialProperty),也允许用户定义自定义着色器。

Material 的构成
  1. 顶点着色器(Vertex Shader):处理每个顶点的逻辑,计算顶点的变换(位置、法线等)。
  2. 片段着色器(Fragment Shader):处理每个片元的逻辑,定义像素的颜色、纹理等属性。
  3. Uniforms:从 CPU 向 GPU 传递的全局数据,通常是不变的值(如时间、模型矩阵)。
  4. Varyings:从顶点着色器传递到片段着色器的中间数据,用于共享信息。
  5. Attributes:每个顶点的数据(如位置、法线、颜色等)。

2. 自定义 Material 示例

以下是创建一个动态颜色渐变 Material 的示例。

// 创建自定义材质
const customMaterial = new Cesium.Material({fabric: {type: 'CustomMaterial', // 自定义类型名uniforms: {u_time: 0.0, // 时间参数(Uniform)u_color1: new Cesium.Color(1.0, 0.0, 0.0, 1.0), // 起始颜色u_color2: new Cesium.Color(0.0, 0.0, 1.0, 1.0), // 结束颜色},source: `// 顶点着色器代码czm_material czm_getMaterial(czm_materialInput materialInput) {czm_material material = czm_getDefaultMaterial(materialInput);float mixRatio = abs(sin(u_time)); // 动态变化的混合因子material.diffuse = mix(u_color1.rgb, u_color2.rgb, mixRatio); // 颜色渐变material.alpha = 1.0; // 不透明return material;}`,},
});// 创建带自定义材质的实体
viewer.entities.add({position: Cesium.Cartesian3.fromDegrees(0, 0, 0),ellipsoid: {radii: new Cesium.Cartesian3(500000.0, 500000.0, 500000.0),material: customMaterial, // 应用自定义材质},
});// 更新时间参数
viewer.clock.onTick.addEventListener(() => {customMaterial.uniforms.u_time += viewer.clock.deltaTime;
});
代码说明
  1. fabric 定义了材质结构。
  2. uniforms 是从 CPU 传递到 GPU 的参数,支持动态更新。
  3. source 是 GLSL 着色器代码,定义了颜色渐变逻辑。

3. 顶点着色器详解

顶点着色器的主要作用是处理顶点数据并计算最终的顶点位置。

关键点
  1. 输入
    • attributes:顶点属性,如位置、法线、纹理坐标。
    • uniforms:全局常量参数。
  2. 输出
    • gl_Position:顶点在屏幕上的位置。
    • varyings:传递给片段着色器的数据。
示例
attribute vec3 position;
attribute vec3 normal;uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;varying vec3 vNormal;void main() {gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);vNormal = normal;
}

4. 片段着色器详解

片段着色器负责计算每个像素的颜色。

关键点
  1. 输入
    • varyings:从顶点着色器传递的数据。
    • uniforms:全局参数。
  2. 输出
    • gl_FragColor:最终片元颜色。
示例
varying vec3 vNormal;uniform vec3 lightDirection;void main() {float brightness = max(dot(normalize(vNormal), normalize(lightDirection)), 0.0);gl_FragColor = vec4(vec3(brightness), 1.0);
}

5. GPU 和 CPU 之间的数据传递

Cesium 提供了友好的接口来传递数据:

  1. Uniforms

    • 用于传递全局数据,如时间、颜色、纹理等。
    • Material 中通过 uniforms 字段定义。
    • 动态更新方法:
      customMaterial.uniforms.u_time = newValue;
      
  2. Attributes

    • 每个顶点的数据,如位置、法线。
    • Cesium 自动处理基本的顶点数据,但你也可以通过 Geometry 自定义。
  3. Textures

    • Cesium 支持将纹理传递给 GPU,通常通过 Uniform 实现。
    • 示例:
      const texture = new Cesium.Texture({context: viewer.scene.context,source: imageElement,
      });
      customMaterial.uniforms.u_texture = texture;
      

6. 着色器编程中的关键概念

1. 模型-视图-投影矩阵
  • 用于将世界坐标系的顶点转换到屏幕坐标系。
  • Cesium 自动为大多数几何体处理这些矩阵。
2. 法线和光照
  • 在顶点着色器中计算法线,并传递给片段着色器以实现光照效果。
3. 颜色混合
  • 使用 GLSL 的 mix 函数,可以实现颜色渐变或插值。
4. 动态效果
  • 利用时间参数(u_time)可以实现波浪、脉冲等动态视觉效果。

7. 实现复杂效果的技巧

1. 多纹理混合

将多个纹理通过自定义逻辑混合,创建复杂的表面外观。

uniform sampler2D texture1;
uniform sampler2D texture2;
uniform float mixRatio;void main() {vec4 color1 = texture2D(texture1, gl_TexCoord[0].st);vec4 color2 = texture2D(texture2, gl_TexCoord[0].st);gl_FragColor = mix(color1, color2, mixRatio);
}
2. 法线贴图

使用法线贴图来模拟复杂的表面细节。


总结

  • 顶点着色器:处理顶点位置,计算中间数据。
  • 片段着色器:处理像素颜色,定义最终的视觉效果。
  • GPU-CPU 数据传递:通过 Uniforms 和 Attributes 实现,Cesium 提供了友好的接口。

通过以上知识,可以在 Cesium 中实现丰富的自定义渲染效果!

3D热力图绘制

在这里插入图片描述

在Cesium中绘制3D热力图可以为数据可视化提供强大的展示能力。以下是关于如何在Cesium中实现3D热力图绘制的详细说明。


1. 了解热力图和3D热力图

  • 热力图是通过颜色来表达数据强度的一种可视化手段,通常用于显示某一地理区域的数据分布。
  • 3D热力图不仅通过颜色显示数据,还结合高度或体积的变化来体现数据的三维分布。

2. 实现3D热力图的关键步骤

2.1 数据准备

热力图的数据通常包括以下内容:

  • 地理坐标(经纬度)。
  • 数据值(如温度、密度或强度)。

确保数据经过适当的预处理,比如去除异常值或归一化处理。


2.2 热力图生成技术

在Cesium中,可以使用以下几种方式实现3D热力图:

方法 1:使用 Cesium 的 Primitive 和 Polygon
  1. 计算数据范围
    根据数据的值生成颜色和高度的映射关系。

  2. 生成网格
    将目标区域划分为多个小网格,每个网格代表一个采样点。

  3. 动态绘制高度柱(Extruded Height)
    为每个网格创建一个 Polygon,其高度(extrudedHeight)由数据值决定,颜色根据数据值映射至色谱(例如从蓝到红)。

viewer.entities.add({name: "Heatmap Column",polygon: {hierarchy: Cesium.Cartesian3.fromDegreesArray([lon1, lat1, lon2, lat2, lon3, lat3]),extrudedHeight: dataValue * heightFactor, // 数据值映射为高度material: Cesium.Color.fromCssColorString(colorMapping(dataValue)) // 数据值映射为颜色}
});
方法 2:借助第三方库

使用开源库(如 heatmap.js 或其他热力图生成工具)来生成2D热力图纹理,再将其投影到Cesium地图上,甚至可以结合3D高度。

  1. 生成热力图纹理
    使用 heatmap.js 创建热力图图片(PNG)。

  2. 投影到 Cesium 地图上
    将生成的图片作为材质贴到平面或地形上。

const heatmapImageryProvider = new Cesium.SingleTileImageryProvider({url: 'path/to/heatmap-image.png',rectangle: Cesium.Rectangle.fromDegrees(west, south, east, north)
});
viewer.imageryLayers.addImageryProvider(heatmapImageryProvider);
  1. 叠加 3D 高度
    如果需要3D效果,可以为热力图纹理增加基于值的高程。

2.3 使用 Shader 实现

通过 WebGL 着色器(Shader)实现更加复杂的3D热力图效果:

  1. 传递数据到 Shader
    使用 Cesium.Material 或自定义 Primitive,将热力图数据以纹理或属性形式传递到 GPU。

  2. 编写 Fragment Shader

    • 使用颜色梯度映射值。
    • 控制每个像素的高度和透明度。
Cesium.Material.fromType('Heatmap3D', {fabric: {type: 'Heatmap3D',uniforms: {colorGradient: gradientTexture,dataTexture: dataTexture},source: `czm_material czm_getMaterial(czm_materialInput materialInput) {// 核心逻辑:颜色和高度映射}`}
});

3. 优化和交互

3.1 性能优化
  • 数据网格的分辨率控制:根据视图范围动态调整网格大小。
  • 着色器优化:尽量减少复杂计算。
3.2 提供交互功能
  • 鼠标悬停:显示特定区域的数据值。
  • 动态更新:响应实时数据变化,更新热力图显示。

4. 示例代码

以下是完整的代码片段示例:

// 创建 Cesium Viewer
const viewer = new Cesium.Viewer('cesiumContainer');// 示例数据
const data = [{ lon: 120.1, lat: 30.2, value: 10 },{ lon: 120.2, lat: 30.3, value: 20 },// ...
];// 绘制 3D 热力柱
data.forEach(d => {viewer.entities.add({position: Cesium.Cartesian3.fromDegrees(d.lon, d.lat),cylinder: {length: d.value * 100, // 高度topRadius: 0,bottomRadius: 500, // 半径material: Cesium.Color.fromCssColorString(colorMapping(d.value)) // 颜色}});
});// 映射函数示例
function colorMapping(value) {if (value < 10) return '#00FF00';if (value < 20) return '#FFFF00';return '#FF0000';
}

5. 总结

通过以上方法,您可以在Cesium中实现丰富的3D热力图效果。根据需求选择合适的技术,结合性能优化和交互功能,能够为用户提供更直观的地理数据可视化体验。

绘图基础

https://www.cnblogs.com/jiujiubashiyi/p/17124717.html
https://blog.csdn.net/m0_55049655/article/details/139720401

在这里插入图片描述

Cesium中的顶点着色器和片段着色器使用详解

Cesium 是一个基于 WebGL 的 3D 地图渲染框架,它支持通过自定义着色器(Shader)控制图形渲染的细节。WebGL 渲染管线包括顶点着色器和片段着色器两个主要阶段,Cesium 同样可以自定义和扩展这些功能。


1. 着色器基础

  1. 顶点着色器(Vertex Shader)

    • 主要任务是处理几何数据,如顶点的位置、法向量等。
    • 输入:顶点属性(如位置、法线、纹理坐标等)。
    • 输出:每个顶点的变换结果(如屏幕空间位置)。
  2. 片段着色器(Fragment Shader)

    • 主要任务是为每个像素(片段)计算颜色。
    • 输入:顶点着色器输出的插值数据。
    • 输出:像素颜色(以及透明度)。

2. Cesium 渲染管线概述

Cesium 的渲染管线是 WebGL 管线的封装,涉及以下步骤:

  1. 顶点数据:Cesium 使用缓冲区(Buffer)存储顶点数据。
  2. 自定义材质:通过 MaterialAppearance 配置 GLSL 着色器。
  3. 渲染对象:通过 Primitive 实例化对象,将着色器与几何结合。

3. 使用顶点和片段着色器的关键模块

  1. 创建顶点着色器和片段着色器
    在 Cesium 中,顶点和片段着色器是通过 GLSL 编写的,可以嵌入到自定义材质或 Primitive 中。例如:

    • 顶点着色器负责将地理坐标转换为屏幕空间。
    • 片段着色器控制每个像素的颜色或透明度。
  2. 绑定着色器到 Cesium 的渲染对象
    使用 Cesium 的 Primitive,结合自定义的 Appearance,将着色器与几何对象绑定。


4. Cesium 着色器示例:自定义渲染一片三角形网格

4.1 顶点着色器(Vertex Shader)
attribute vec3 position; // 顶点位置
attribute vec3 color;    // 每个顶点的颜色
varying vec3 vColor;     // 传递到片段着色器的颜色void main() {// 世界空间位置转换为裁剪空间gl_Position = czm_modelViewProjection * vec4(position, 1.0);// 将顶点颜色传递到片段着色器vColor = color;
}
4.2 片段着色器(Fragment Shader)
precision mediump float;
varying vec3 vColor; // 从顶点着色器传递过来的颜色void main() {// 设置片段颜色gl_FragColor = vec4(vColor, 1.0); // RGB + Alpha
}

4.3 构建 Cesium 渲染对象

在 Cesium 中,需要将顶点数据、着色器和渲染管线连接起来。

  1. 定义顶点数据
    包括三角形的顶点位置和颜色。
const positions = new Float32Array([0.0, 0.0, 0.0, // 第一个顶点1.0, 0.0, 0.0, // 第二个顶点0.0, 1.0, 0.0  // 第三个顶点
]);const colors = new Float32Array([1.0, 0.0, 0.0, // 红色0.0, 1.0, 0.0, // 绿色0.0, 0.0, 1.0  // 蓝色
]);
  1. 创建顶点属性缓冲区
    将数据绑定到 WebGL 缓冲区。
const geometry = new Cesium.Geometry({attributes: {position: new Cesium.GeometryAttribute({componentDatatype: Cesium.ComponentDatatype.FLOAT,componentsPerAttribute: 3,values: positions}),color: new Cesium.GeometryAttribute({componentDatatype: Cesium.ComponentDatatype.FLOAT,componentsPerAttribute: 3,values: colors})},// 指定为三角形几何indices: new Uint16Array([0, 1, 2]),primitiveType: Cesium.PrimitiveType.TRIANGLES
});
  1. 编写自定义 Appearance
    使用自定义的顶点和片段着色器。
const appearance = new Cesium.Appearance({materialSupport: Cesium.MaterialAppearance.MaterialSupport.BASIC,vertexShaderSource: `attribute vec3 position;attribute vec3 color;varying vec3 vColor;void main() {gl_Position = czm_modelViewProjection * vec4(position, 1.0);vColor = color;}`,fragmentShaderSource: `precision mediump float;varying vec3 vColor;void main() {gl_FragColor = vec4(vColor, 1.0);}`
});
  1. 创建 Primitive 对象并添加到场景
    将顶点数据和外观结合,渲染到 Cesium 场景中。
const primitive = new Cesium.Primitive({geometryInstances: new Cesium.GeometryInstance({geometry: geometry}),appearance: appearance,asynchronous: false
});viewer.scene.primitives.add(primitive);

5. 完整示例代码

以下是完整的 Cesium 程序,用于渲染带颜色的三角形:

const viewer = new Cesium.Viewer('cesiumContainer');// 顶点数据
const positions = new Float32Array([0.0, 0.0, 0.0,1.0, 0.0, 0.0,0.0, 1.0, 0.0
]);const colors = new Float32Array([1.0, 0.0, 0.0,0.0, 1.0, 0.0,0.0, 0.0, 1.0
]);// 创建几何
const geometry = new Cesium.Geometry({attributes: {position: new Cesium.GeometryAttribute({componentDatatype: Cesium.ComponentDatatype.FLOAT,componentsPerAttribute: 3,values: positions}),color: new Cesium.GeometryAttribute({componentDatatype: Cesium.ComponentDatatype.FLOAT,componentsPerAttribute: 3,values: colors})},indices: new Uint16Array([0, 1, 2]),primitiveType: Cesium.PrimitiveType.TRIANGLES
});// 创建着色器外观
const appearance = new Cesium.Appearance({materialSupport: Cesium.MaterialAppearance.MaterialSupport.BASIC,vertexShaderSource: `attribute vec3 position;attribute vec3 color;varying vec3 vColor;void main() {gl_Position = czm_modelViewProjection * vec4(position, 1.0);vColor = color;}`,fragmentShaderSource: `precision mediump float;varying vec3 vColor;void main() {gl_FragColor = vec4(vColor, 1.0);}`
});// 创建 Primitive
const primitive = new Cesium.Primitive({geometryInstances: new Cesium.GeometryInstance({geometry: geometry}),appearance: appearance,asynchronous: false
});// 添加到 Cesium 场景
viewer.scene.primitives.add(primitive);

6. 总结

通过以上步骤,您可以在 Cesium 中自定义顶点和片段着色器,实现对渲染管线的全面控制。本例中我们展示了如何绘制一个简单的三角形,并用每个顶点的颜色实现平滑的渐变效果。这种能力可以扩展到更复杂的渲染任务,比如动态纹理、光照计算或基于高度的数据可视化。

ShaderToy以及代码移植至Cesium

ShaderToy 详解与移植到 Cesium 的方法

1. 什么是 ShaderToy?

ShaderToy 是一个在线平台,用于创建和分享基于 GLSL(OpenGL Shading Language)的着色器。它允许开发者实时编写、调试和查看 GPU 着色器的效果,广泛用于学习图形编程、生成视觉效果和艺术创作。


2. ShaderToy 的核心组件

ShaderToy 着色器通常运行在 WebGL 环境,具有以下关键部分:

  1. 片段着色器(Fragment Shader)

    • 主函数为 mainImage(out vec4 fragColor, in vec2 fragCoord)
    • 使用 fragCoord 定位像素并计算输出颜色。
  2. 全局 Uniforms
    ShaderToy 提供了一些预定义的全局变量,便于开发者创建动态效果。

    • iResolution:画布的分辨率(像素)。
    • iTime:运行时间(秒)。
    • iMouse:鼠标位置。
    • iChannel0 - iChannel3:纹理通道,用于输入纹理或音频数据。
  3. 纹理采样和噪声生成
    ShaderToy 支持使用噪声函数、渐变和纹理来实现复杂效果。


3. 将 ShaderToy 着色器移植至 Cesium 的步骤

Cesium 支持 WebGL 和 GLSL 着色器,因此可以将 ShaderToy 的着色器逻辑移植到 Cesium 的材质系统中,例如通过 Cesium.MaterialPrimitive 实现。


3.1 准备 ShaderToy 着色器

在 ShaderToy 上找到目标着色器代码,并确认其主要逻辑。以一个简单的着色器为例:

void mainImage(out vec4 fragColor, in vec2 fragCoord) {vec2 uv = fragCoord / iResolution.xy;fragColor = vec4(uv, 0.5 + 0.5 * sin(iTime), 1.0);
}

这段代码生成了一个动态颜色随时间变化的效果。


3.2 移植到 Cesium 的材质系统

步骤 1:创建自定义材质
Cesium 的 Material 支持自定义 GLSL 代码,可以直接移植 ShaderToy 的片段着色器。

Cesium.Material._materialCache.addMaterial('ShaderToyMaterial', {fabric: {type: 'ShaderToyMaterial',uniforms: {iResolution: new Cesium.Cartesian2(1920, 1080),iTime: 0.0},source: `czm_material czm_getMaterial(czm_materialInput materialInput) {czm_material material = czm_getDefaultMaterial(materialInput);vec2 fragCoord = materialInput.st * iResolution;vec2 uv = fragCoord / iResolution;material.diffuse = vec3(uv, 0.5 + 0.5 * sin(iTime));material.alpha = 1.0;return material;}`},translucent: false
});
  • czm_materialInput.st:Cesium 的纹理坐标(对应 fragCoord 的归一化版本)。
  • czm_material:Cesium 的材质结构,包括 diffuse(颜色)和 alpha(透明度)。

步骤 2:应用材质
将材质应用到 Cesium 的对象上,如地形、实体或 Primitive

viewer.entities.add({rectangle: {coordinates: Cesium.Rectangle.fromDegrees(-180, -90, 180, 90),material: new Cesium.Material({fabric: {type: 'ShaderToyMaterial'}})}
});

3.3 将 ShaderToy 的 Uniforms 转换为 Cesium Uniforms

ShaderToy 的一些 Uniforms 需要用 Cesium 的方法进行动态更新:

  1. iTime:通过 Cesium 的动画循环更新时间。
viewer.clock.onTick.addEventListener(() => {const material = viewer.entities.values[0].rectangle.material;material.uniforms.iTime += viewer.clock.tickDeltaSeconds;
});
  1. iResolution:可以设置为 Cesium 画布的大小。
material.uniforms.iResolution = new Cesium.Cartesian2(viewer.canvas.clientWidth,viewer.canvas.clientHeight
);
  1. iMouse:通过事件监听鼠标位置。
viewer.canvas.addEventListener('mousemove', (event) => {const rect = viewer.canvas.getBoundingClientRect();material.uniforms.iMouse = new Cesium.Cartesian2(event.clientX - rect.left,event.clientY - rect.top);
});

3.4 使用纹理通道(iChannel)

Cesium 支持加载和绑定纹理,可用于 ShaderToy 的纹理采样需求。

  1. 加载纹理
Cesium.Material._materialCache.addMaterial('ShaderToyWithTexture', {fabric: {type: 'ShaderToyWithTexture',uniforms: {iChannel0: Cesium.buildImageMaterialProperty({image: 'path/to/texture.png'}),iResolution: new Cesium.Cartesian2(1920, 1080),iTime: 0.0},source: `czm_material czm_getMaterial(czm_materialInput materialInput) {czm_material material = czm_getDefaultMaterial(materialInput);vec2 uv = materialInput.st;vec4 textureColor = texture2D(iChannel0, uv);material.diffuse = textureColor.rgb;material.alpha = textureColor.a;return material;}`},translucent: false
});

4. 注意事项
  1. 坐标系统:ShaderToy 使用屏幕空间坐标,而 Cesium 在地理坐标和屏幕坐标之间转换时,需要确保纹理映射正确。
  2. 性能优化:复杂着色器可能导致 Cesium 场景帧率下降,建议优化 ShaderToy 着色器逻辑。
  3. 兼容性:某些 GLSL 函数在 WebGL 中可能不可用,需要调整代码。

5. 示例完整代码

以下是一个 ShaderToy 着色器移植到 Cesium 的完整示例:

const viewer = new Cesium.Viewer('cesiumContainer');// 添加自定义材质
Cesium.Material._materialCache.addMaterial('DynamicShaderToy', {fabric: {type: 'DynamicShaderToy',uniforms: {iResolution: new Cesium.Cartesian2(window.innerWidth, window.innerHeight),iTime: 0.0},source: `czm_material czm_getMaterial(czm_materialInput materialInput) {czm_material material = czm_getDefaultMaterial(materialInput);vec2 uv = materialInput.st;material.diffuse = vec3(uv.x, uv.y, 0.5 + 0.5 * sin(iTime));material.alpha = 1.0;return material;}`},translucent: false
});// 应用材质到实体
viewer.entities.add({rectangle: {coordinates: Cesium.Rectangle.fromDegrees(-180, -90, 180, 90),material: new Cesium.Material({fabric: {type: 'DynamicShaderToy'}})}
});// 动态更新 iTime
viewer.clock.onTick.addEventListener(() => {const material = viewer.entities.values[0].rectangle.material;material.uniforms.iTime += viewer.clock.tickDeltaSeconds;
});

通过这些步骤,您可以将 ShaderToy 的 GLSL 代码高效移植到 Cesium 场景中,用于实现炫酷的动态效果。

后处理

https://blog.csdn.net/m0_55049655/article/details/140263921
https://blog.csdn.net/m0_55049655/article/details/144428500

WebGL 中的后处理阶段

在 WebGL 中,后处理(Post-Processing)阶段是渲染管线的一部分,指的是在渲染场景或帧缓冲区内容之后,对整个帧进行额外的处理,以实现某些全屏效果或优化。后处理阶段通常会将场景的渲染结果作为输入纹理,使用额外的着色器(通常是片段着色器)来实现。


后处理的主要功能

  1. 视觉特效

    • 增强画面表现力,为场景增加特殊的视觉效果。
    • 例如:
      • 景深(Depth of Field):模拟摄像机对焦的模糊效果。
      • 运动模糊(Motion Blur):模拟物体快速移动时的模糊。
      • 泛光效果(Bloom):增强亮部区域的光晕效果。
      • 色调映射(Tone Mapping):处理高动态范围(HDR)图像以适配屏幕显示。
  2. 屏幕空间效果

    • 基于屏幕空间的后处理效果,使用屏幕上的深度或法线信息。
    • 例如:
      • 屏幕空间环境光遮蔽(SSAO):模拟物体之间遮挡的阴影效果。
      • 屏幕空间反射(SSR):实现镜面反射的效果。
      • 光晕(Lens Flare):模拟摄像机中的光斑。
  3. 图像优化

    • 调整画面亮度、对比度、饱和度等,优化整体画质。
    • 例如:
      • 伽马校正(Gamma Correction):修正亮度与色彩分布。
      • 色彩校正:调整色调和饱和度,统一画面风格。
      • 降噪:减少高频纹理中的噪点。
  4. 模拟屏幕或摄像机特性

    • 模拟现实中镜头、屏幕、胶片的特性。
    • 例如:
      • 失真(Distortion):模拟透镜的变形效果。
      • 伪像(Chromatic Aberration):模拟镜头中的色彩分散。
      • 颗粒(Film Grain):模拟老电影的颗粒感。
  5. 调试与辅助

    • 后处理阶段也常用于渲染调试和开发辅助。
    • 例如:
      • 深度可视化:将深度信息以灰度图显示。
      • 法线可视化:显示每个像素的法线方向。

后处理的工作流程

后处理的基本工作流程通常如下:

  1. 渲染到帧缓冲区(Frame Buffer Object, FBO)

    • 场景渲染的结果会被绘制到一个帧缓冲区,而不是直接输出到屏幕。
    • 帧缓冲区包含颜色纹理、深度纹理等。
  2. 使用全屏四边形进行处理

    • 创建一个覆盖整个屏幕的矩形(通常为两个三角形组成)。
    • 将帧缓冲区的内容作为纹理,传递给片段着色器。
  3. 后处理效果的实现

    • 在片段着色器中读取纹理信息,并根据需要实现特定效果。
  4. 输出最终结果

    • 将处理后的结果绘制到默认帧缓冲区(屏幕)上。

实现后处理的关键技术

  1. 帧缓冲区(Framebuffer Object, FBO)

    • WebGL 中后处理需要使用帧缓冲区将场景渲染结果保存为纹理,供后续处理。
  2. 纹理采样

    • 通过纹理采样操作,从帧缓冲区纹理中读取像素信息。
  3. 多通道渲染

    • 某些复杂效果需要多次渲染,生成多个中间纹理(例如 SSAO、HDR)。
  4. 片段着色器

    • 后处理的核心逻辑大部分在片段着色器中实现,通过操作像素级数据完成各种效果。

常见后处理效果实现原理

1. 模糊(Blur)
  • 原理
    • 读取周围像素的颜色值并求平均,生成模糊效果。
  • 实现
    • 高斯模糊(Gaussian Blur)通过二维卷积核实现逐渐变化的模糊。
uniform sampler2D uTexture;
uniform vec2 uResolution;void main() {vec2 texelSize = 1.0 / uResolution;vec4 color = vec4(0.0);// 简单高斯核float kernel[9];kernel[0] = 1.0; kernel[1] = 2.0; kernel[2] = 1.0;kernel[3] = 2.0; kernel[4] = 4.0; kernel[5] = 2.0;kernel[6] = 1.0; kernel[7] = 2.0; kernel[8] = 1.0;// 相邻像素偏移vec2 offset[9];offset[0] = vec2(-1, -1) * texelSize;offset[1] = vec2( 0, -1) * texelSize;offset[2] = vec2( 1, -1) * texelSize;offset[3] = vec2(-1,  0) * texelSize;offset[4] = vec2( 0,  0) * texelSize;offset[5] = vec2( 1,  0) * texelSize;offset[6] = vec2(-1,  1) * texelSize;offset[7] = vec2( 0,  1) * texelSize;offset[8] = vec2( 1,  1) * texelSize;// 加权采样for (int i = 0; i < 9; i++) {color += texture2D(uTexture, gl_FragCoord.xy / uResolution + offset[i]) * kernel[i];}color /= 16.0;gl_FragColor = color;
}
2. 景深(Depth of Field, DOF)
  • 原理
    • 利用深度值决定是否对某些区域模糊。
  • 实现
    • 使用深度纹理,计算每个像素到焦点的模糊程度。

后处理的优点和挑战

优点
  1. 灵活性:允许在一个统一的阶段对整个场景进行全局调整和特效应用。
  2. 多样性:通过组合不同效果,能够快速实现复杂的渲染目标。
  3. 性能优化:某些全屏效果(如抗锯齿)在后处理阶段比逐像素计算更高效。
挑战
  1. 性能消耗:后处理需要额外的帧缓冲区和纹理采样,可能带来性能开销。
  2. 复杂性:实现高质量后处理效果(如 SSAO、体积光)可能涉及复杂的数学和算法。
  3. 纹理分辨率限制:后处理效果依赖于帧缓冲区分辨率,低分辨率可能导致效果不够清晰。

总结

WebGL 中的后处理阶段主要用于对渲染结果进行全局调整和特效应用。通过利用帧缓冲区、纹理采样和片段着色器,可以实现如模糊、景深、环境光遮蔽等丰富的效果。后处理为场景渲染提供了强大的扩展能力,是现代图形渲染中的重要组成部分。

Cesium中PostProcessStage

在这里插入图片描述

// Simple stage to change the color
const fs =`uniform sampler2D colorTexture;in vec2 v_textureCoordinates;uniform float scale;uniform vec3 offset;void main() {vec4 color = texture(colorTexture, v_textureCoordinates);out_FragColor = vec4(color.rgb * scale + offset, 1.0);}`;
scene.postProcessStages.add(new Cesium.PostProcessStage({fragmentShader : fs,uniforms : {scale : 1.1,offset : function() {return new Cesium.Cartesian3(0.1, 0.2, 0.3);}}
}));// Simple stage to change the color of what is selected.
// If czm_selected returns true, the current fragment belongs to geometry in the selected array.
const fs =`uniform sampler2D colorTexture;in vec2 v_textureCoordinates;uniform vec4 highlight;void main() {vec4 color = texture(colorTexture, v_textureCoordinates);if (czm_selected()) {vec3 highlighted = highlight.a * highlight.rgb + (1.0 - highlight.a) * color.rgb;out_FragColor = vec4(highlighted, 1.0);} else {out_FragColor = color;}}`;
const stage = scene.postProcessStages.add(new Cesium.PostProcessStage({fragmentShader : fs,uniforms : {highlight : function() {return new Cesium.Color(1.0, 0.0, 0.0, 0.5);}}
}));
stage.selected = [cesium3DTileFeature]

Cesium获取深度图

屏幕坐标反算世界坐标

https://blog.csdn.net/qq_52254412/article/details/139982116?spm=1001.2014.3001.5502
在这里插入图片描述
[1]巨博 城市雨洪模型配置式集成与三维可视化研究.[D].南京师范大学,2024.

阴影贴图

ShadowMap

在这里插入图片描述

https://blog.csdn.net/m0_55049655/article/details/140423323
https://blog.csdn.net/m0_55049655/article/details/140423480
在Cesium中,阴影贴图(Shadow Map)是实现场景中逼真阴影效果的主要技术之一。以下是对阴影贴图的详细解析及其在Cesium中使用的指导,并进一步探讨如何利用此技术实现场景视频融合。


阴影贴图基本原理

阴影贴图是一种基于图像的算法,用于模拟光源投射的阴影。其主要步骤如下:

  1. 从光源视角渲染深度图
    • 渲染场景,记录每个像素到光源的距离(深度值)。
  2. 场景渲染时检测阴影
    • 从场景相机的视角渲染场景,计算每个像素在光源视角下的深度值。
    • 将此值与阴影贴图中的深度值比较。如果像素的深度值大于阴影贴图记录值,则该像素被认为在阴影中。

Cesium中的阴影实现

Cesium中的阴影效果基于WebGL实现,并支持对地形、模型和几何体的阴影渲染。以下是关键点:

  1. 启用阴影

    • Cesium的阴影功能默认是关闭的,需要手动开启:
      viewer.shadows = true;
      
  2. 光源设置
    Cesium目前支持两种主要光源:

    • 太阳光:通过viewer.scene.sun自动计算太阳位置和方向。
    • 定制光源:通过编写自定义的着色器实现。
  3. ShadowMap配置
    Cesium使用ShadowMap类来管理阴影贴图的生成与应用。其主要参数包括:

    • enabled:是否启用阴影。
    • size:阴影贴图的分辨率,值越高阴影效果越细腻,但性能开销也更大。
    • softShadows:是否启用软阴影。
    • maximumDistance:阴影影响的最大距离。

    示例代码:

    viewer.scene.shadowMap.enabled = true;
    viewer.scene.shadowMap.size = 2048; // 提高分辨率
    viewer.scene.shadowMap.softShadows = true; // 开启软阴影
    
  4. 为特定对象启用阴影

    • castShadows:是否投射阴影。
    • receiveShadows:是否接收阴影。
      示例:
    model.castShadows = true;
    model.receiveShadows = true;
    

场景视频融合的实现

在视频融合场景中,目标是将真实视频的内容与虚拟3D场景无缝融合,这可以通过阴影贴图和视频纹理技术实现。

1. 加载视频纹理

使用Cesium的材质系统,将视频作为纹理映射到平面几何体上:

const videoElement = document.createElement('video');
videoElement.src = 'path_to_video.mp4';
videoElement.loop = true;
videoElement.play();const videoMaterial = new Cesium.Material({fabric: {type: 'Image',uniforms: {image: videoElement}}
});const videoPlane = viewer.entities.add({rectangle: {coordinates: Cesium.Rectangle.fromDegrees(minLon, minLat, maxLon, maxLat),material: videoMaterial}
});
2. 与阴影贴图结合
  • 确保视频平面可以接收3D物体投射的阴影。
  • 通过配置receiveShadows,使视频纹理表面接收来自虚拟场景的阴影。
3. 校准视频与场景

为了实现无缝融合,需要对视频与3D场景进行视角、位置和光照校准:

  • 位置校准:确保视频平面在3D场景中的地理位置与视频内容一致。
  • 光照一致性:调整Cesium中的光源方向,使其与视频中的光影方向匹配。
  • 投影匹配:使用Cesium的ShadowMap功能,将3D物体的阴影精确投射到视频平面上。
示例代码:
const shadowMap = viewer.scene.shadowMap;
shadowMap.enabled = true;
shadowMap.size = 2048;const boxEntity = viewer.entities.add({position: Cesium.Cartesian3.fromDegrees(lon, lat, height),box: {dimensions: new Cesium.Cartesian3(10, 10, 10),material: Cesium.Color.RED,castShadows: true}
});videoPlane.receiveShadows = true;

优化与注意事项

  1. 性能优化

    • 阴影贴图分辨率:在视觉效果与性能之间找到平衡。
    • 裁剪范围:限制阴影贴图的作用范围,减少多余计算。
  2. 融合效果

    • 视频中的动态光影与虚拟场景光影可能不一致,这需要通过后期调试微调光源位置与方向。
  3. 多光源支持
    如果场景需要多个光源(例如多个虚拟灯光),需要自行扩展Cesium的着色器代码。


通过以上方法,Cesium的阴影贴图与视频纹理技术可实现高质量的场景视频融合,为虚拟与现实的结合提供了丰富的可能性。

  • 视频融合 视频纹理 视频贴图
  • 水文模型模拟过程可视化[二三维,输入+中间+输出数据] All in Cesium?

模型分析

模型压平

在Cesium中,CustomShader 类提供了一个强大的方式来定制模型的渲染行为。通过自定义着色器,可以对模型进行特定的操作,例如模型压平(将部分区域的高度调整为指定值)。以下是实现模型压平的详细步骤。


步骤详解

1. 创建 CustomShader

创建一个 CustomShader 对象,用于在渲染过程中修改模型的顶点或片段数据。

const customShader = new Cesium.CustomShader({vertexShaderText: `void main() {czm_modelViewPosition = czm_modelView * vec4(position, 1.0);}`,fragmentShaderText: `void main() {gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);}`
});

此时,vertexShaderTextfragmentShaderText 定义了基本的顶点着色器和片段着色器结构。后续会逐步完善顶点处理逻辑以实现压平效果。


2. 修改顶点输出

在顶点着色器中,修改顶点位置以实现压平效果。

示例代码:

const customShader = new Cesium.CustomShader({vertexShaderText: `void main() {vec4 positionInModel = czm_modelView * vec4(position, 1.0);// 自定义逻辑:修改顶点高度if (positionInModel.z > 50.0) { // 假设压平的高度为50positionInModel.z = 50.0;}gl_Position = czm_projection * positionInModel;}`
});

这段代码中:

  • positionInModel.z 表示顶点的高度。
  • 根据条件判断是否将顶点高度设置为指定值。

3. 创建范围数据

创建一个描述压平范围的数据,例如一个地理边界框或者特定区域的坐标集合。

const flattenBounds = {minLon: 100.0,maxLon: 101.0,minLat: 30.0,maxLat: 31.0,flattenHeight: 50.0
};

通过这种方式,可以明确指定需要压平的区域范围以及压平后的高度。


4. 判断坐标关系

在顶点着色器中,加入对顶点坐标与范围数据的判断逻辑。

示例代码:

const customShader = new Cesium.CustomShader({vertexShaderText: `uniform vec4 flattenBounds; // (minLon, minLat, maxLon, maxLat)uniform float flattenHeight;void main() {vec4 positionInModel = czm_modelView * vec4(position, 1.0);// 将模型坐标转换为经纬度坐标vec3 positionInWGS84 = czm_modelToWGS84Matrix * positionInModel.xyz;// 判断是否在范围内if (positionInWGS84.x > flattenBounds.x && positionInWGS84.x < flattenBounds.z &&positionInWGS84.y > flattenBounds.y && positionInWGS84.y < flattenBounds.w) {// 设置压平高度positionInModel.z = flattenHeight;}gl_Position = czm_projection * positionInModel;}`,uniforms: {flattenBounds: new Cesium.Cartesian4(flattenBounds.minLon, flattenBounds.minLat, flattenBounds.maxLon, flattenBounds.maxLat),flattenHeight: flattenBounds.flattenHeight}
});

说明:

  • 使用 uniform 变量将范围数据传递到着色器中。
  • 使用 czm_modelToWGS84Matrix 将模型坐标转换为地理坐标。

5. 设置压平高度

压平的核心操作是将符合条件的顶点高度设置为指定值。通过控制变量 flattenHeight,可以动态调整压平的高度。

例如:

const flattenHeight = 50.0; // 压平后的高度// 更新 customShader 的 uniform
customShader.setUniform('flattenHeight', flattenHeight);

将 CustomShader 应用于模型

CustomShader 对象绑定到模型上,使其生效。

示例:

const model = viewer.scene.primitives.add(Cesium.Model.fromGltf({url: 'path/to/model.gltf',})
);// 将自定义着色器应用于模型
model.customShader = customShader;

最终完整代码

以下代码整合了上述步骤,展示了完整实现:

const flattenBounds = {minLon: 100.0,maxLon: 101.0,minLat: 30.0,maxLat: 31.0,flattenHeight: 50.0
};const customShader = new Cesium.CustomShader({vertexShaderText: `uniform vec4 flattenBounds; // (minLon, minLat, maxLon, maxLat)uniform float flattenHeight;void main() {vec4 positionInModel = czm_modelView * vec4(position, 1.0);// 将模型坐标转换为经纬度坐标vec3 positionInWGS84 = czm_modelToWGS84Matrix * positionInModel.xyz;// 判断是否在范围内if (positionInWGS84.x > flattenBounds.x && positionInWGS84.x < flattenBounds.z &&positionInWGS84.y > flattenBounds.y && positionInWGS84.y < flattenBounds.w) {// 设置压平高度positionInModel.z = flattenHeight;}gl_Position = czm_projection * positionInModel;}`,uniforms: {flattenBounds: new Cesium.Cartesian4(flattenBounds.minLon, flattenBounds.minLat, flattenBounds.maxLon, flattenBounds.maxLat),flattenHeight: flattenBounds.flattenHeight}
});const model = viewer.scene.primitives.add(Cesium.Model.fromGltf({url: 'path/to/model.gltf',})
);model.customShader = customShader;

注意事项

  1. 性能优化

    • 压平范围较小时,可以减少对所有顶点的判断逻辑。
    • 使用更低分辨率的模型可能减少计算量。
  2. 准确性校准

    • 如果范围数据不准确,可能导致压平效果偏差。
  3. 动态交互

    • 通过监听用户交互(如鼠标点击),可以动态修改压平区域和高度。

这样实现的模型压平在场景中可以很好地适应各种地形修改需求,特别适用于建筑物基底调整或地形分析场景。

卷帘

在 Cesium 中实现卷帘效果需要结合自定义着色器(CustomShader)、屏幕空间计算(Screen Space)以及 Cesium 提供的模型显示与隐藏控制功能。以下是分步实现自定义卷帘效果的具体方法,包括屏幕区域卷帘、模型隐藏、上下卷帘、对角线卷帘。


1. 自定义卷帘的实现思路

卷帘效果是通过动态调整模型或地形的可见区域来实现的。常见方法包括:

  • 利用屏幕坐标(Screen Space)进行遮罩计算。
  • 使用 CustomShader 修改顶点或片段渲染逻辑。
  • 动态更新遮罩参数(如卷帘位置、方向等)。

2. 实现屏幕区域卷帘

屏幕区域卷帘控制场景中某一部分可见,其余部分被遮挡。

实现步骤:
  1. 计算屏幕坐标遮罩区域
    使用屏幕坐标定义卷帘范围,利用 gl_FragCoord 获取当前片段的屏幕位置。

  2. 定义遮罩逻辑
    CustomShader 的片段着色器中,将超出卷帘范围的像素隐藏(例如通过设置透明度为 0)。

示例代码:
const customShader = new Cesium.CustomShader({fragmentShaderText: `uniform vec2 screenBounds; // 卷帘边界 (x = 左/右界限, y = 上/下界限)void main() {// 获取屏幕坐标vec2 screenPosition = gl_FragCoord.xy;// 检查是否在卷帘范围内if (screenPosition.x > screenBounds.x || screenPosition.y > screenBounds.y) {discard; // 丢弃像素}gl_FragColor = vec4(1.0); // 保留像素}`,uniforms: {screenBounds: new Cesium.Cartesian2(500.0, 300.0) // 自定义屏幕区域}
});const model = viewer.scene.primitives.add(Cesium.Model.fromGltf({url: 'path/to/model.gltf',})
);model.customShader = customShader;

3. 模型隐藏

通过动态调整模型的可见性,可以实现对模型的隐藏或显示。

实现步骤:
  1. 设置模型显示状态
    Cesium 提供 show 属性控制模型是否可见。

  2. 基于条件隐藏模型
    使用场景中的时间、位置或事件控制模型隐藏。

示例代码:
const model = viewer.scene.primitives.add(Cesium.Model.fromGltf({url: 'path/to/model.gltf',})
);// 隐藏模型
model.show = false;// 显示模型
model.show = true;

4. 上下卷帘

上下卷帘控制场景从上向下或从下向上依次显示。

实现步骤:
  1. 动态控制屏幕 Y 坐标的可见性
    在片段着色器中,根据屏幕的 Y 坐标动态调整遮罩范围。

  2. 实现动画效果
    动态更新卷帘参数,形成卷帘移动的动画。

示例代码:
const customShader = new Cesium.CustomShader({fragmentShaderText: `uniform float curtainY; // 当前卷帘 Y 坐标void main() {// 获取屏幕 Y 坐标float screenY = gl_FragCoord.y;// 判断是否在卷帘范围内if (screenY > curtainY) {discard; // 丢弃像素}gl_FragColor = vec4(1.0); // 保留像素}`,uniforms: {curtainY: 300.0 // 初始卷帘位置}
});// 动画更新
viewer.scene.preRender.addEventListener(() => {const time = Date.now() * 0.001;customShader.setUniform('curtainY', 300.0 + Math.sin(time) * 200.0);
});model.customShader = customShader;

5. 对角线卷帘

对角线卷帘根据屏幕对角线范围动态调整场景显示。

实现步骤:
  1. 计算对角线方向的屏幕坐标
    使用 gl_FragCoord 和对角线公式计算片段的对角线位置。

  2. 动态控制对角线遮罩范围
    通过条件判断,逐步扩大或缩小对角线遮罩范围。

示例代码:
const customShader = new Cesium.CustomShader({fragmentShaderText: `uniform float diagonalPosition; // 当前对角线卷帘位置void main() {// 计算屏幕坐标和对角线位置float screenX = gl_FragCoord.x;float screenY = gl_FragCoord.y;float diagonal = screenX + screenY;// 判断是否在对角线卷帘范围内if (diagonal > diagonalPosition) {discard; // 丢弃像素}gl_FragColor = vec4(1.0); // 保留像素}`,uniforms: {diagonalPosition: 600.0 // 初始对角线位置}
});// 动态更新对角线位置
viewer.scene.preRender.addEventListener(() => {const time = Date.now() * 0.001;customShader.setUniform('diagonalPosition', 600.0 + Math.sin(time) * 300.0);
});model.customShader = customShader;

6. 整合控制与动画

通过事件和动画逻辑,整合各类卷帘效果。

示例:
  • 使用 GUI 或交互事件切换不同卷帘模式。
  • 动态调整 CustomShader 的参数。
动态控制代码:
let currentEffect = 'vertical'; // 当前卷帘模式// 监听用户交互
viewer.scene.canvas.addEventListener('click', () => {if (currentEffect === 'vertical') {currentEffect = 'diagonal';} else {currentEffect = 'vertical';}
});// 根据模式切换卷帘逻辑
viewer.scene.preRender.addEventListener(() => {const time = Date.now() * 0.001;if (currentEffect === 'vertical') {customShader.setUniform('curtainY', 300.0 + Math.sin(time) * 200.0);} else if (currentEffect === 'diagonal') {customShader.setUniform('diagonalPosition', 600.0 + Math.sin(time) * 300.0);}
});

总结

通过上述步骤,可以实现 Cesium 中自定义卷帘效果,包括:

  1. 屏幕区域卷帘:限制特定屏幕区域的显示。
  2. 模型隐藏:动态控制模型的可见性。
  3. 上下卷帘:从上到下或从下到上显示场景。
  4. 对角线卷帘:沿屏幕对角线显示场景内容。

卷帘效果的核心是通过自定义着色器和 Cesium 的 CustomShader 功能动态调整模型的渲染行为,再结合事件监听和动画逻辑实现更灵活的交互。

相关文章:

Cesium进阶教程——自定义图形、外观、绘图基础、现有着色器移植至Cesium、ShadowMapping、视频GIS、模型压平、卷帘

基础必看 WEBGL基础&#xff08;从渲染管线角度解读&#xff09; 参考路线 http://www.xt3d.online/tutorial/further/article.html 自定义图形 https://blog.csdn.net/m0_55049655/article/details/138908327 https://blog.csdn.net/m0_55049655/article/details/140306837 …...

搭建Tomcat(一)---SocketServerSocket

目录 引入1 引入2--socket 流程 Socket&#xff08;应用程序之间的通讯保障&#xff09; 网卡(计算机之间的通讯保障) 端口 端口号 实例 client端 解析 server端 解析 相关方法 问题1&#xff1a;ServerSocket和Socket有什么关系&#xff1f; ServerSocket Soc…...

Sublime Text 64位:前端及全栈开发利器

本文还有配套的精品资源&#xff0c;点击获取 简介&#xff1a;Sublime Text作为一款高效的文本编辑器&#xff0c;在前端网页开发领域受到广泛青睐&#xff0c;特别是其64位版本在处理大型项目和高内存需求的场景下表现出色。编辑器内置Emmet插件&#xff0c;提供代码高亮、…...

CNCF云原生生态版图-分类指南(一)- 观测和分析

CNCF云原生生态版图-分类指南&#xff08;一&#xff09;- 观测和分析 CNCF云原生生态版图-分类指南一、观测和分析&#xff08;Observability and Analysis&#xff09;&#xff08;一&#xff09;可观测性&#xff08;Observablility&#xff09;1. 是什么&#xff1f;2. 解决…...

Ubuntu本地快速搭建web小游戏网站,公网用户远程访问【内网穿透】

文章目录 前言1. 本地环境服务搭建2. 局域网测试访问3. 内网穿透3.1 ubuntu本地安装cpolar内网穿透3.2 创建隧道3.3 测试公网访问4. 配置固定二级子域名4.1 保留一个二级子域名4.2 配置二级子域名4.3 测试访问公网固定二级子域名前言 网:我们通常说的是互联网;站:可以理解成…...

VMware ubuntu12.04怎么设置静态IP联网

记得刚开始学习嵌入式就是从ubuntu12.04的环境开始学习的C语言&#xff0c;当时没有弄清楚怎么设置静态IP联网&#xff0c;现在写一篇文章。 1.首先&#xff0c;关闭ubuntu的网络&#xff1b; 2.电脑使用的是wifi,将VMware桥接到该网卡上&#xff1b; 3.在虚拟机设置里面选择桥…...

Qt WORD/PDF(一)使用 QtPdfium库实现 PDF 预览

文章目录 一、简介二、下载 QtPdfium三、加载 QtPdfium 动态库四、Demo 使用 关于QT Widget 其它文章请点击这里: QT Widget 姊妹篇: Qt WORD/PDF&#xff08;一&#xff09;使用 QtPdfium库实现 PDF 操作 Qt WORD/PDF&#xff08;二&#xff09;使用 QtPdfium库实现…...

UE5 C++ Subsystem 和 多线程

一.Subsystem先做一个简单的介绍&#xff0c;其实可以去看大钊的文章有一篇专门讲这个的。 GamePlay框架基础上的一个增强功能&#xff0c;属于GamePlay架构的范围。Subsystems是一套可以定义自动实例化和释放的类的框架。这个框架允许你从5类里选择一个来定义子类(只能在C定义…...

23.DDD与微服务

学习视频来源&#xff1a;DDD独家秘籍视频合集 https://space.bilibili.com/24690212/channel/collectiondetail?sid1940048&ctype0 文章目录 DDD与微服务的关系1. DDD可以用微服务实现&#xff0c;也可以不用微服务实现2. DDD是微服务拆分的必须参考项之一3. 微服务架构…...

vue3+ant design vue实现日期选择器不展示清除按钮

1、代码&#xff1a;只需设置:allowClear"false"即可 <a-date-pickerv-model:value"value1":disabledDate"disabledDate"change"queryRate":allowClear"false" />const disabledDate (current: Dayjs) > {// 获取…...

Amazon Bedrock与AWS服务的无缝集成,如何打造智能化应用

在AI和大数据飞速发展的今天&#xff0c;Amazon Bedrock作为AWS的一项新兴服务&#xff0c;正逐渐成为开发者和企业拥抱生成式AI的核心工具。那么&#xff0c;Amazon Bedrock与AWS其他服务结合&#xff0c;究竟能够带来哪些强大的应用场景呢&#xff1f;今天九河云就来和大家探…...

Rust之抽空学习系列(四)—— 编程通用概念(下)

Rust之抽空学习系列&#xff08;四&#xff09;—— 编程通用概念&#xff08;下&#xff09; 1、函数 函数用来对功能逻辑进行封装&#xff0c;能够增强复用、提高代码的可读 以下是函数的主要组成部分&#xff1a; 名称参数返回类型函数体 1.1、函数名称 在Rust中&…...

【Apache paimon】-- 集成 hive3.1.3 异常

目录 1、场景再现 Step1:在 hive cli beeline 执行创建 hive paimon 表 Step2:使用 insert into 写入数据 Step3:抛出异常 2、原因分析 Step1:在 yarn resource manager 作业界面查询 hive sql mr job 的 yarn log Step2:搜索job 使用的 zstd jar 版本 Step3:定…...

SpringCloud微服务实战系列:01让SpringCloud项目在你机器上运行起来

目录 项目选型 项目安装-本地运行起来 软件安装&#xff1a; 项目启动&#xff1a; 总结&答疑 项目选型 软件开发&#xff0c;基本上都不会从0开始&#xff0c;一般都是在其他项目或者组件的基础上进行整合优化迭代&#xff0c;站在巨人肩膀上才能看得更远&#xff0c…...

分布式锁【Redis场景分布式锁篇】

文章目录 1.Redis分布式锁2.分布式锁其它方案1.主动轮询型1.MySQL分布式锁2.Redis分布式锁 2.监听回调型1.Etcd2.Zookeeper 总结 1.Redis分布式锁 锁通常用来控制共享资源&#xff0c;比如一个进程内有多个线程竞争一个数据的使用权限&#xff0c;解决方式之一就是加锁。分布式…...

BGP协议

BGP&#xff08;Border Gateway Protocol&#xff0c;边界网关协议&#xff09;是一种用于在不同网络之间传输可达性信息的路由协议。它是互联网上使用的主要协议之一&#xff0c;用于连接不同的自治系统&#xff08;AS&#xff09;&#xff0c;即由单个实体控。边界网关协议_百…...

iframe webview打开外链内嵌video标签导致视频无法全屏展示

iframe webview打开外链内嵌video标签导致视频无法全屏展示 解决方法iframe 添加属性webview 添加属性 解决方法 iframe 添加属性 <iframe style"width: 100%;height: 100vh;" src"http://xxx.xxx........" allowfullscreen"true" w…...

学习日志024--opencv中处理轮廓的函数

目录 前言​​​​​​​ 一、 梯度处理的sobel算子函数 功能 参数 返回值 代码演示 二、梯度处理拉普拉斯算子 功能 参数 返回值 代码演示 三、Canny算子 功能 参数 返回值 代码演示 四、findContours函数与drawContours函数 功能 参数 返回值 代码演示 …...

【从零开始入门unity游戏开发之——C#篇05】转义字符、@处理多行文本或者不使用转义字符、随机数

文章目录 一、转义字符1、什么是转义字符&#xff1f;2、常见的转义字符3、总结 二、使用处理多行文本或者不使用转义字符1、多行字符串2、不使用转义字符 三、随机数1、Random.Next()生成随机整数示例&#xff1a;生成一个随机整数生成指定范围内的随机整数 2、Random.NextSin…...

PHP获取指定日期的下周日至下周六的日期(下周几的日期)

PHP获取指定日期的下周日至下周六的日期&#xff08;下周几的日期&#xff09; 在PHP中&#xff0c;可以使用strtotime()函数来获取指定日期的下周日至下周六的日期。 // 周天 sunday // 周一 monday // 周二 tuesday // 周三 wednesday // 周四 thursday // 周五 friday // …...

超越飞书钉钉:探索高效内部知识库平替方案与应用

在团队协作日益频繁的今天&#xff0c;飞书与钉钉作为两大主流的企业沟通与协作平台&#xff0c;广受企业青睐。然而&#xff0c;随着企业规模的扩大和知识的累积&#xff0c;单纯的沟通与协作已难以满足企业对知识管理与传承的需求。因此&#xff0c;寻找一款能够高效整合内部…...

3D相框案例讲解(详细)

前言 通过现阶段的学习&#xff0c;我们已经掌握了HTML&#xff0c;CSS和JS部分的相关知识点&#xff0c;现在让我们通过一篇案例&#xff0c;来巩固我们近期所学的知识点。 详细视频讲解戳这里 任务一 了解目标案例样式 1.1了解案例 3D相框 1.2 分析案例 首先我们看到一个…...

一、基于langchain使用Qwen搭建金融RAG问答机器人--技术准备

一,LangChain框架介绍 LangChain 框架是一个开源工具&#xff0c;通过为各种 LLM 提供通用接口来简化应用程序的开发流程&#xff0c;帮助开发者自由构建 LLM应用。 LangChain封装了很多组件&#xff0c;通过这些组件的组合可以构建多种类型的RAG应用。开发者可以直接将私有数…...

2024年全球安全光幕装置行业总体规模、主要企业国内外市场占有率及排名

根据研究团队调研统计&#xff0c;2023年全球安全光幕装置市场销售额达到了46亿元&#xff0c;预计2030年将达到70亿元&#xff0c;年复合增长率&#xff08;CAGR&#xff09;为6.4%&#xff08;2024-2030&#xff09;。中国市场在过去几年变化较快&#xff0c;2023年市场规模为…...

uniapp跨端适配—条件编译

在uniapp中&#xff0c;跨端适配是通过条件编译实现的。条件编译允许开发者根据不同的平台&#xff08;如iOS、Android、微信小程序、百度小程序等&#xff09;编写不同的代码。这样可以确保每个平台上的应用都能得到最优的性能和用户体验。 以下是uniapp中条件编译的基本语法…...

HTML、CSS表格的斜表头样式设置title 画对角线

我里面有用到layui框架的影响&#xff0c;实际根据你自己的框架来小调下就可以 效果如下 上代码 <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-wi…...

自动驾驶控制与规划——Project 2: 车辆横向控制

目录 零、任务介绍一、环境配置二、算法三、代码实现四、效果展示 零、任务介绍 补全src/ros-bridge/carla_shenlan_projects/carla_shenlan_stanley_pid_controller/src/stanley_controller.cpp中的TODO部分。 一、环境配置 上一次作业中没有配置docker使用gpu&#xff0c;…...

Docker的初识

目录 1. 容器技术发展史1.1 Jail 时代1.2 云时代1.3 云原生时代1.3.1 Google & Docker 竞争1.3.2 k8s 成为云原生事实标准 2. 虚拟化和容器化的概念2.1 什么是虚拟化、容器化2.2 为什么要虚拟化、容器化&#xff1f;2.3 虚拟化实现方式2.3.1 应用程序执行环境分层2.3.2 虚拟…...

R-Studio Technician,无网络负担地进行远程数据分析和数据恢复任务

对于数据恢复技术人员和技术支持团队来说&#xff0c;时间就是金钱。这不仅包括您在客户机器上花费的时间 - 还包括您往返公司办公室的时间&#xff0c;这可能会带来巨大的不便&#xff0c;特别是如果客户位于其他省市。电话支持通常不适用于需要数小时才能完成的复杂任务&…...

Couchbase的OLAP支持情况

Couchbase 是一个高性能的 NoSQL 数据库&#xff0c;主要用于在线事务处理&#xff08;OLTP&#xff09;场景&#xff0c;但它也提供了一些功能来支持在线分析处理&#xff08;OLAP&#xff09;需求。以下是 Couchbase 对 OLAP 支持的几个方面&#xff1a; 1. N1QL 查询语言 …...

路径规划之启发式算法之十六:和声搜索算法(Harmony Search, HS)

和声搜索算法(Harmony Search, HS)是一种新兴的启发式全局搜索算法,是一种模拟音乐家即兴演奏过程的群体智能优化算法。这种算法由Zong Woo Geem等人在2001年提出,灵感来源于音乐家在寻找和声时的创造性思维过程。HS算法通过模拟音乐家演奏音乐时的选择过程来寻找问题的最优…...

服务器---centos上安装docker并使用docker配置jenkins

要在 Docker 中安装 Jenkins 并进行管理,可以按照以下步骤操作: 1. 安装 Docker 首先,确保你的系统已经安装了 Docker。如果尚未安装,可以使用以下命令进行安装: 在 CentOS 上安装 Docker sudo yum install -y yum-utils sudo yum-config-manager --add-repo https://…...

面试题整理1---正向代理和反向代理的含义及异同

面试题整理1---正向代理和反向代理的含义及异同 1. 正向代理 (Forward Proxy)1.1 正向代理定义&#xff1a;1.2 正向代理的工作流程&#xff1a;1.3 正向代理的应用场景&#xff1a; 2. 反向代理 (Reverse Proxy)2.1 反向代理的定义&#xff1a;2.2 反向代理的工作流程&#xf…...

记录学习《手动学习深度学习》这本书的笔记(五)

这一章是循环神经网络&#xff0c;太难了太难了&#xff0c;有很多卡壳的地方理解了好久&#xff0c;比如隐藏层和隐状态的区别、代码的含义&#xff08;为此专门另写了一篇【笔记】记录对自主实现一个神经网络的步骤的理解&#xff09;、梯度计算相关&#xff08;【笔记】记录…...

鸿蒙调试打包(非正式打包)

文章目录 前言第一步&#xff1a;生成.p12和.csr文件第二步&#xff1a;申请证书的前置步骤第三步&#xff1a;申请证书 前言 HarmonyOS 应用打包后的文件为.app 格式&#xff0c; android 打包后的文件为.apk&#xff0c;IOS 打包后的文件为.apa HarmonyOS通过数字证书&#…...

Python中的容器化服务监控:结合Prometheus和Grafana实现高效监控与可视化

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 在现代的DevOps和微服务架构中,容器化技术(如Docker)已成为主流的部署方式。然而,容器环境的动态特性使得服务监控和性能分析变得更加复…...

【大数据】-- 读放大和写放大

目录 一、定义 1. 读放大(Read Amplification) 定义 原因 优化方法 2. 写放大(Write Amplification) 定义 原因 优化方法 对比与联系 二、举例 1. Hadoop(HDFS) 读放大 写放大 2. Flink 读放大 写放大 3. Hive 读放大 写放大 4. Presto 读放大 写放…...

[工具升级问题] 钉钉(linux版)升级带来的小麻烦

本文由Markdown语法编辑器编辑完成。 1. 背景: 今日钉钉又发布了新的升级版本。由于我工作时使用的是Ubuntu 20.04版本&#xff0c;收到的升级推送信息是&#xff0c;可以升级到最新的7.6.25-Release版本。根据钉钉官方给出的历次更新版说明&#xff0c;这个新的版本&#xf…...

Maven学习(Maven项目模块化。模块间“继承“机制。父(工程),子项目(模块)间聚合)

目录 一、Maven项目模块化&#xff1f; &#xff08;1&#xff09;基本介绍。 &#xff08;2&#xff09;汽车模块化生产再聚合组装。 &#xff08;3&#xff09;Maven项目模块化图解。 1、maven_parent。 2、maven_pojo。 3、maven_dao。 4、maven_service。 5、maven_web。 6…...

Opencv之图像添加水印

一、实验原理 在图片处理领域&#xff0c;添加水印是一种常见的操作。通过叠加图像的方式&#xff0c;可以将水印无缝嵌入目标图像的指定位置。其基本原理包括以下步骤&#xff1a; 1、模板输入&#xff08;掩膜生成&#xff09;&#xff1a; 将水印图片转换为灰度图&#xf…...

在线预约陪诊小程序

一、前言 随着社会老龄化加剧以及人们健康意识的提高&#xff0c;就医过程中的陪伴需求日益增长。许多患者在面对复杂的医院环境、繁琐的就医流程时&#xff0c;需要有人协助挂号、候诊、取药等&#xff0c;而家属可能因工作繁忙无法全程陪同。同时&#xff0c;异地就医的患者更…...

2024年9月CCF GESP Scratch图形化编程等级考试四级真题试卷

GESP 图形化四级试卷&#xff08;A&#xff09; &#xff08;满分&#xff1a;100 分 考试时间&#xff1a;120 分钟&#xff09; 一、单选题&#xff08;共 10 题&#xff0c;每题 2 分&#xff0c;共 30 分&#xff09; 1、2024 年 10 月 8 日&#xff0c;诺贝尔物理学奖“意…...

[免费]SpringBoot+Vue校园社团管理系统(优质版)【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的SpringBootVue校园社团管理系统(优质版)&#xff0c;分享下哈。 项目视频演示 【免费】SpringBootVue校园社团管理系统(优质版) Java毕业设计_哔哩哔哩_bilibili 项目介绍 随着信息技术的迅速发展&#x…...

NX系列-使用 `nmcli` 命令创建 Wi-Fi 热点并设置固定 IP 地址

使用 nmcli 命令创建 Wi-Fi 热点并设置固定 IP 地址 一、前言 在一些场景下&#xff0c;我们需要将计算机或嵌入式设备&#xff08;例如 NVIDIA Orin NX&#xff09;转换为 Wi-Fi 热点&#xff0c;以便其他设备&#xff08;如手机、笔记本等&#xff09;能够连接并使用该设备…...

Qt控件的盒子模型,了解边距边线和内容区

这篇专门讲讲一个控件在绘制时的视觉样式。我们平常在对控件设置样式时&#xff0c;需要设置控件的一些外边距&#xff0c;内边距&#xff0c;边线&#xff0c;还有文字内容&#xff0c;贴上图片等。那么对于一个控件&#xff0c;到底怎么实现这些设置的呢&#xff1f; 先看下面…...

深度学习基础--将yolov5的backbone模块用于目标识别会出现怎么效果呢??

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 前言 yolov5网络结构比较复杂&#xff0c;上次我们简要介绍了yolov5网络模块&#xff0c;并且复现了C3模块&#xff0c;深度学习基础–yolov5网络结构简介&a…...

MySQL 根据 字段包含关键词进行分类

为了解决动态关键词匹配的需求&#xff0c;我们需要创建一个关键词表&#xff08;keywords_table&#xff09;&#xff0c;其中存储关键词和对应的类别。以下是具体的步骤&#xff1a; 1. 创建关键词表 可以用以下 SQL 创建一个简单的关键词表&#xff1a; CREATE TABLE keyw…...

ssm-day04 mybatis

mybatis是一个持久层框架&#xff0c;针对的是JDBC的优化 简化数据库操作&#xff0c;能进行单表、多表操作&#xff0c;在这个框架下&#xff0c;需要我们自己写SQL语句 Mapper接口和MapperXML文件就相当于Dao和Dao层的实现 通常将xml文件放在resources包下 &#xff0c;放在…...

soul大数据面试题及参考答案

如何看待数据仓库? 数据仓库是一个面向主题的、集成的、相对稳定的、反映历史变化的数据集合,用于支持管理决策。 从数据存储角度看,它整合了来自多个数据源的数据。这些数据源可能包括业务系统数据库、日志文件等各种结构化和非结构化数据。例如,在电商企业中,它会整合订…...

【SpringBoot中MySQL生成唯一ID的常见方法】

SpringBoot中MySQL生成唯一ID的常见方法 在Spring Boot中&#xff0c;为MySQL生成唯一ID有多种方式&#xff0c;每种方式都有其特定的概念、优越点和使用场景。以下是详细的说明和代码示例&#xff1a; UUID 概念: UUID&#xff08;Universally Unique Identifier&#xff0…...