# cesium官方案例学习
# cesium之构建viewer类
const viewer = new Cesium.Viewer("cesiumContainer", {
infoBox: false, // 信息提示框
selectionIndicator: false,// 选中实体的指示器
shadows: true,//开启阴影
shouldAnimate: true,// 动画效果
orderIndependentTranslucency:true,//顺序无关透明,默认true
terrain: Cesium.Terrain.fromWorldTerrain(),//地形
});
# orderIndependentTranslucency
orderIndependentTranslucency(顺序无关透明)是 Cesium 中一个重要的图形渲染特性,它允许在渲染半透明物体时,不受物体绘制顺序的影响,从而能够更真实地表现复杂的半透明效果。
orderIndependentTranslucency 技术通过一种称为“顺序无关透明”(OIT)的算法来解决这个问题。该算法能够在渲染半透明物体时,不考虑它们的绘制顺序,而是根据它们的深度信息和透明度信息进行正确的叠加和遮挡处理。这样,无论半透明物体的渲染顺序如何,最终得到的渲染结果都是一致的。
# trackedEntity
viewer.trackedEntity = entity;//获取或设置摄像机当前正在跟踪的Entity实例。
# cesium Scene类
Cesium.Scene是Cesium中所有3D图形对象的容器(HTML canvas),通常不是直接创建的,而是通过Viewer或CesiumWidget内部隐式创建的。
# scene.pick
它允许根据屏幕坐标(通常是鼠标点击或触摸事件的位置)来选择场景中的对象。这个方法返回一个 Cesium.Entity、Cesium.Primitive 或其他可以在场景中被拾取的对象,如果在该位置没有找到任何对象,则返回 undefined。
# scene.pickTranslucentDepth
用于控制是否允许通过半透明对象进行拾取(picking)操作。拾取操作通常涉及用户通过鼠标或其他输入设备选择场景中的对象。
当 scene.pickTranslucentDepth 设置为 true 时,CesiumJS 将允许用户通过半透明(translucent)的对象来拾取被遮挡的对象。这意味着,即使一个对象被另一个半透明对象部分或完全覆盖,用户仍然可以选中被覆盖的对象。
默认情况下,scene.pickTranslucentDepth 是 false,这意呀着拾取操作将仅限于最顶层的可见对象,即不会被半透明对象后面的对象所干扰。
# cesium Camera类
相机由位置、方向和视图截头体定义。
# flyTo 将相机从当前位置飞到新位置
viewer.camera.flyTo({
//飞行时间
duration: duration,
//摄像机在世界坐标或自顶向下视图中可见的矩形中的最终位置(必须)
destination: Cartesian3 | Rectangle ,
// 方向:两种配置方案
orientation: {
//表示相机视线的方向
direction: Cartesian3,
//一个单位向量,表示相机上方的方向
up: Cartesian3,
},
//另外一种设置偏航 俯仰 旋转角度(需要转为弧度制)
// orientation: {
// heading: Cesium.Math.toRadians(175.0),
// pitch: Cesium.Math.toRadians(-35.0),
// roll: 0.0
// },
// 控制如何在飞行持续时间内插值时间的缓动动画
easingFunction: Cesium.EasingFunction.QUADRATIC_IN_OUT,
});
# Cesium3DTileset
是Cesium中用于加载和渲染3D瓦片集的主要类
# customShader [试验属性]
应用于图块集中所有图块的自定义着色器。仅用于使用模型的内容。将自定义着色器与Cesium3DTileStyle一起使用可能会导致未定义的行为。
# modelMatrix
一个4x4转换矩阵,用于转换整个图集。这个矩阵包含平移变换,用于将瓦片集移动到新的位置
const translation = new Cesium.Cartesian3(
-1.398521324920626,
0.7823052871729486,
0.7015244410592609,
);
tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation);
# fromurl
通过给定的路径下载数据瓦片集
Cesium.Cesium3DTileset.fromUrl(url, options)
const tileset = await Cesium.Cesium3DTileset.fromUrl(
"http://localhost:8002/tilesets/Seattle/tileset.json"
);
scene.primitives.add(tileset);
# fromIonAssetId
Cesium.Cesium3DTileset.fromIonAssetId(assetId, options)
//用于流式传输大量异构3D地理空间数据集。
const terrainTileset = await Cesium.Cesium3DTileset.fromIonAssetId(
2389063
);
viewer.scene.primitives.add(terrainTileset);
# Cesium3DTileset的一些配置项
Cesium3DTileset.ConstructorOptions
- maximumScreenSpaceError:简称
MSSE定义了瓦片在屏幕上渲染时的最大允许误差。这个误差是基于屏幕像素来衡量的,它决定了瓦片被细分(即加载更高LOD级别的瓦片)的精度。当MSSE值较大时,Cesium会尝试加载较少、更粗略的瓦片来减少内存使用和渲染时间,从而可能提高性能。相反,当MSSE值较小时,Cesium会加载更多、更详细的瓦片来确保更高的视觉质量,但这可能会增加内存使用和渲染时间。
const buildingsTileset = await Cesium.Cesium3DTileset.fromIonAssetId(
2389064,
{
maximumScreenSpaceError: 12,
}
);
# cesium Cesium3DTileStyle类
应用于Cesium3DTileset的样式。
tileset.style = new Cesium.Cesium3DTileStyle({
color : {
conditions : [
['${Height} >= 100', 'color("purple", 0.5)'],
['${Height} >= 50', 'color("red")'],
['true', 'color("blue")']
]
},
show : '${Height} > 0',
meta : {
description : '"Building id ${id} has height ${Height}."'
}
});
const buildingStyle = new Cesium.Cesium3DTileStyle({
color: {
conditions: [
["${HGT} !== undefined && ${HGT} < 5", "color('#f5fd2d')"],
[
"${HGT} !== undefined && ${HGT} >= 5 && ${HGT} < 10",
"color('#d3a34a')",
],
[
"${HGT} !== undefined && ${HGT} >= 10 && ${HGT} < 15",
"color('#947e75')",
],
[
"${HGT} !== undefined && ${HGT} >= 15 && ${HGT} < 20",
"color('#565a9f')",
],
["${HGT} !== undefined && ${HGT} > 20", "color('#223bc3')"],
["true", "color('white')"],
],
},
});
# cesium Cesium3DTileFeature类
Cesium3DTileset的一个功能。
// 检测是否是Cesium3DTile
const featurePicked = feature instanceof Cesium.Cesium3DTileFeature;
const featurePicked = feature instanceof Cesium.Cesium3DTileFeature;
// 检测是否有HGT属性
const isBuildingFeature = featurePicked && feature.hasProperty("HGT");
const feature = scene.pick(movement.endPosition);
const featurePicked = feature instanceof Cesium.Cesium3DTileFeature;
const isTerrainFeature =
featurePicked && feature.hasProperty("substrates");
if(isTerrainFeature){
// 获取feature中的name属性值
feature.getProperty("name")
// 获取特征的所有属性ID
const propertyIds = feature.getPropertyIds();
}
# cesium Terrain类 地形
用于管理地形提供程序的异步操作的助手。
new Cesium.Terrain(terrainProviderPromise)
// Create
const viewer = new Cesium.Viewer("cesiumContainer", {
terrain: new Cesium.Terrain(Cesium.CesiumTerrainProvider.fromUrl("https://myTestTerrain.com"));
});
// Handle loading events
const terrain = new Cesium.Terrain(Cesium.CesiumTerrainProvider.fromUrl("https://myTestTerrain.com"));
scene.setTerrain(terrain);
terrain.readyEvent.addEventListener(provider => {
scene.globe.enableLighting = true;
terrain.provider.errorEvent.addEventListener(error => {
alert(`Encountered an error while loading terrain tiles! ${error}`);
});
});
terrain.errorEvent.addEventListener(error => {
alert(`Encountered an error while creating terrain! ${error}`);
});
# cesium Entity实体类的方法
# 添加实体
const hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
const orientation = Cesium.Transforms.headingPitchRollQuaternion(
position,
hpr
);
const entity = viewer.entities.add({
name: url,
// 定义了实体的位置。position变量是一个Cesium的Cartesian3对象,用于描述实体在三维空间中的位置。
position: position,
//定义了实体的方向。orientation变量是一个Cesium的Quaternion对象,用于描述实体的旋转。
orientation: orientation,
model: {
uri: url,
// 模型在屏幕上显示时的最小像素尺寸
minimumPixelSize: 128,
// 定义了模型可以缩放的最大比例。如果模型被缩放到超过这个比例,它将不再继续放大。
maximumScale: 20000,
// color: XXX,
// colorBlendMode: XXX,
// colorBlendAmount: XXX,
// silhouetteColor:XXX,
// silhouetteSize: XXX,
},
});
# 移除全部实体
viewer.entities.removeAll();
# 实体model的属性和方法
- entity为某个通过url添加的模型,可以修改模型的color
颜色
function getColor(colorName, alpha) {
//colorName:颜色名称如 YELLOW GREEN
const color = Cesium.Color[colorName.toUpperCase()];
return Cesium.Color.fromAlpha(color, parseFloat(alpha));
}
entity.model.color = getColor(newValue, viewModel.alpha);
- 修改模型colorBlendMode
颜色混合模式,定义用于在目标颜色和基元的源颜色之间混合的不同模式。
- HIGHLIGHT:当内部材料的透明度(alpha)小于1.0时,在其上方显示外部材料颜色(blendingColor)。这种模式通常用于高亮显示某些部分。
- MIX:对内部材料和外部材料进行平均值混合。这意味着两种颜色的RGB值将按照一定比例进行混合,生成新的颜色。
- REPLACE:用外部材料颜色完全替换内部材料颜色。这是一种简单的替换模式,不考虑内部材料的颜色。
entity.model.colorBlendMode = colorBlendMode;
- 当colorBlendMode为 MIX 时才生效的属性,用于确定颜色强度的值。0.0的值会导致模型呈现的颜色,而1.0的值会导致纯色,中间的任何值都会导致两者的混合。 ( Default Value: 0.5 )
entity.model.colorBlendAmount = parseFloat(newValue);
- 设置模型的轮廓颜色
silhouetteColor
entity.model.silhouetteColor = getColor(
newValue,
viewModel.silhouetteAlpha
);
- 设置轮廓的大小(像素)
silhouetteSize
entity.model.silhouetteSize = parseFloat(newValue);
# cesium ScreenSpaceEventHandler类
处理用户输入事件。可以添加自定义函数以在用户输入输入时执行。
const handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
# cesium Light类
光源。这种类型描述了一个接口,通常不直接实例化。颜色和强度一起产生高动态范围的光色。强度也可以单独用于在不改变色调的情况下使光变暗或变亮。
- color
- intensity:number,光的强度
const scene = viewer.scene;
// 调整光照强度
scene.light.intensity = 7.0;
# cesium LightingModel光照模型
Cesium.LightingModel 是 CesiumJS 中用于定义着色器光照模型的一个枚举类型。
Cesium.LightingModel 主要包括以下几种类型:
- Cesium.LightingModel.PBR(基于物理的渲染):
- 基于物理的光照模型,提供更真实的光照和材质效果。
- 适用于需要高度真实感的场景,如建筑、车辆、人物等复杂模型的渲染。
- Cesium.LightingModel.UNLIT(无光照):
- 不应用任何光照效果,物体的颜色完全由材质决定。
- 适用于不需要光照效果的场景,或者作为自定义光照效果的起点。
# cesium Cartesian3类
# 通过单个经纬度创建笛卡尔坐标 Cartesian3.fromDegrees
const position = Cesium.Cartesian3.fromDegrees(
-123.0744619,
44.0503706,
height
);
# 通过笛卡尔坐标直接创建一个Cartesian3对象 Cartesian3
new Cesium.Cartesian3(4397999.822774582, 4404502.67774069, 1397782.4709840622)
# 分量差 Cartesian3.subtract(left, right, result)
计算两个笛卡尔的分量差。
| 名称 | 类型 | 说明 |
|---|---|---|
| left | Cartesian3 | 第一个笛卡尔。 |
| right | Cartesian3 | 第二个笛卡尔。 |
| result | Cartesian3 | 存储结果的对象。 |
# cesium HeadingPitchRoll类
const heading = Cesium.Math.toRadians(0);//偏航角
const pitch = Cesium.Math.toRadians(0);//俯仰角
const roll = Cesium.Math.toRadians(90);//翻滚角
const hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
const orientation = Cesium.Transforms.headingPitchRollQuaternion(
position,
hpr
);
# cesium全局属性和方法
# Cesium.defined
如果定义了对象,则返回true,否则返回false。
let aa= 1;
let bb;
console.warn(Cesium.defined(aa)) //true
console.warn(Cesium.defined(bb)) //false
# Cesium.defaultValue(a, b)
第一个参数a是要检查的值,第二个参数b是当a为undefined或null时要返回的默认值。
const propertyType = Cesium.defaultValue(
property.componentType,
property.type
);
# cesium Transforms类
const orientation = Cesium.Transforms.headingPitchRollQuaternion(
position,
hpr
);
# cesium JulianDate类
表示天文儒略日期
// 将 viewer.clock.currentTime 设置为一个特定的时间点
//这个时间点是通过 ISO 8601 格式的字符串来指定的
//ISO 8601 是一种国际标准的时间表示方法,它包括了日期和时间,以及可选的时区信息。
viewer.clock.currentTime = Cesium.JulianDate.fromIso8601(
"2021-11-09T07:27:37.016064475348684937Z"
);
# cesium glsl
| 类型 | 中文 | 说明 |
|---|---|---|
| attribute | 属性 | 主要是顶点着色器用来从缓冲(Buffer)中获取数据 |
| uniform | 统一值 | 在每一次渲染中全局有效且不变的值 |
| texture | 纹理 | 一个数据序列,大多数情况下可以理解为图像数据 |
| varying | 可变量 | 顶点着色器向片元着色器传值的方式,并且会以插值的形式传递 |
| 函数名(参数) | 说明 |
|---|---|
| pow(x,y) | x的y次方。如果x小于0,结果是未定义的。同样,如果x=0并且y<=0,结果也是未定义的。 |
| sqrt(x) | 计算x的开方。如果x小于0,结果是未定义的。 |
| fract(x) | 返回x-floor(x),即返回x的小数部分 |
| step(edge, x) | 如果x < edge,返回0.0,否则返回1.0 |
| smoothstep(edge0, edge1, x) | 如果x <= edge0,返回0.0 ;如果x >= edge1 返回1.0;如果edge0 < x < edge1,则执行0~1之间的平滑埃尔米特差值。如果edge0 >= edge1,结果是未定义的。 |
| distance(a,b) | 计算a,b两点间的距离,二维三维都可以 |
cesium所需的材质shader具体来说就是需要写一个 czm_getMaterial 函数。然后这个函数返回一个czm_material类型的结构体(结构体可以类比为JS中的对象)。这个结构体最好通过 czm_getDefaultMaterial 函数获得,再在此基础上修改。
可以在这个函数上方声明一些uniform来从JS中获取一些数据,比如这个最简单的示例就从JS中获取颜色值,并赋予 czm_material 类型的结构体的diffuse属性。
czm_material czm_getMaterial(czm_materialInput materialInput)
{
return czm_getDefaultMaterial(materialInput);
}
- czm_materialInput 结构体说明
czm_materialInput 类型的结构体是 czm_getMaterial 函数的参数,cesium会在几何体的片元着色器中调用 czm_getMaterial ,并将参数传递给该函数。
| 属性名 | 类型 | 说明 |
|---|---|---|
| s | float | 一维纹理坐标 |
| st | vec2 | 二维纹理坐标 |
| str | vec3 | 三维纹理坐标 |
| normalEC | vec3 | 眼坐标系中的未扰动表面法线 |
| tangentToEyeMatrix | mat3 | 将切线空间法线转换为眼空间的矩阵 |
| positionToEyeEC | vec3 | 从片段到眼睛的向量(在眼坐标系中)。其大小为片段到眼睛的距离(以米为单位) |
czm_material结构体说明:保存可用于照明的材质信息。由所有 czm_getMaterial 函数返回。
可以了解到该结构体不仅仅保存着材质信息,并且该结构体还可以被用于光照(cesium使用的冯氏光照模型第二个参数就是该结构体)。
| 属性名 | 类型 | 说明 |
|---|---|---|
| diffuse | vec3 | 向各个方向均匀散射的入射光,默认值vec3(0.0)。(漫反射颜色) |
| specular | float | 沿单个方向反射的入射光的强度,默认值0.0。(镜面高光强度) |
| shininess | float | 镜面反射的清晰度。值越高,创建的镜面高光越小、越聚焦。默认值1.0 |
| normal | vec3 | 表面的法线在眼睛坐标中。它用于法线贴图等效果。默认值为曲面的未修改法线。(就是normalEC) |
| emission | vec3 | 材质在所有方向上均匀发射的光。默认值为 vec3(0.0),它不发光。 |
| alpha | float | 此材质的不透明度。0.0 是完全透明的;1.0 是完全不透明的。默认值1.0 |
- 渐变:渐变的产生大多需要借助纹理坐标,在webgl中,cesium纹理坐标设置大多都是完全覆盖面的。假如绘制了一个正方形,那左下角为纹理坐标的原点,右上角坐标则为(1,1)。不管实际上物体是正方形还是长方形还是什么形状,纹理坐标右上角就是(1,1)。利用好这一点就可以产生渐变效果了
const shaderSource = `
uniform vec4 color;
czm_material czm_getMaterial(czm_materialInput materialInput)
{
vec4 outColor = color;
czm_material material = czm_getDefaultMaterial(materialInput);
vec2 st = materialInput.st;
outColor.r = st.s;
// outColor.r = st.t;
material.diffuse = czm_gammaCorrect(outColor.rgb);
material.alpha = outColor.a;
return material;
}
`
因为纹理坐标都是0-1的,而rgba四个值也都是0-1之间的,如果想要在横坐标生成3个渐变效果,是不是应该需要3个0-1之间的值,这怎么得到呢。很简单,只需要将st的s乘以3,那么s就在0-3之间波动了,这时候再取其小数部分,因为小数部分就是在 [0 - 1) 之间的,这样就得到三个0-1了。可以将需要生成的数量通过uniform来传递(不要忘记在js中传递uniform值)。
const shaderSource = `
uniform vec4 color;
uniform float gradationNumber;
czm_material czm_getMaterial(czm_materialInput materialInput) {
vec4 outColor = color;
czm_material material = czm_getDefaultMaterial(materialInput);
vec2 st = materialInput.st;
// outColor.r = st.s;
// outColor.r = st.t;
// outColor.a = st.s;
// outColor.a = st.t;
outColor.a = fract(st.s * gradationNumber);
material.diffuse = czm_gammaCorrect(outColor.rgb);
material.alpha = outColor.a;
return material;
}
`
- 让线动起来:cesium中的材质动画离不开cesium的一个自动uniform,那就是czm_frameNumber,这个uniform表示当前处于cesium的第几帧绘制,从0开始,每次绘制cesium都会将其递增1。
现在假设cesium帧率为60,那么使用 czm_frameNumber / 60.0 。这样得到的结果如果只看整数部分那就是每秒钟递增1,只看小数部分那就是一直在 [0,1) 之间循环,循环时间为1秒。那假如我们将这个结果赋予alpha值,是不是就是物体透明的不断地从0-1变化,循环时间为1秒。那怎么通过这个让线动起来呢,我们知道纹理坐标的值也是0-1之间的,那如果我们将这个值赋予作为线的位置呢(我们之前线的位置为0.5),让我们试试看吧。
/**
* 流动线材质属性
*/
import { Event, Material, Property, Color, defined, createPropertyDescriptor } from "cesium";
export default class LineFlowMaterialProperty {
constructor(options) {
//。。。。。。
}
getType(time) {
return Material.LineFlowMaterialType;
}
getValue(time, result) {
if (!defined(result)) {
result = {};
}
return result;
}
}
Material.LineFlowMaterialProperty = "LineFlowMaterialProperty";
Material.LineFlowMaterialType = "LineFlowMaterialType";
Material.LineFlowMaterialSource = `
czm_material czm_getMaterial(czm_materialInput materialInput){
czm_material material = czm_getDefaultMaterial(materialInput);
//...
return material
}
`;
Material._materialCache.addMaterial(Material.LineFlowMaterialType, {
fabric: {
type: Material.LineFlowMaterialType,
uniforms: {
//......
},
source: Material.LineFlowMaterialSource,
},
});
getType和getValue方法需要定义不可缺失,否则无法呈现
# cesium CustomShader自定义着色器类
const emptyFragmentShader =
"void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {}";
const unlitShader = new Cesium.CustomShader({
lightingModel: Cesium.LightingModel.UNLIT,
fragmentShaderText: emptyFragmentShader,
});
fragmentShaderText:作为GLSL代码字符串的自定义片段着色器。它必须包含一个名为片段主的GLSL函数。有关预期签名的示例,请参阅示例。如果未指定,自定义片段着色器步骤将在计算片段着色器中跳过。FragmentInput: 这是一个结构体(或类似结构体的类型),它包含了从顶点着色器传递到片段着色器的各种数据。这些数据通常包括顶点位置、法线、纹理坐标等,以及CesiumJS自动注入的一些额外信息,如颜色、光照信息等。fsInput: 这是传递给 fragmentMain 函数的 FragmentInput 类型变量的名称。可以通过 fsInput 访问传递给片段着色器的所有数据。inout: 这是GLSL中的一个关键字,用于指定函数参数是输入-输出参数。这意味着可以在函数内部修改这个参数的值,并且修改后的值将在函数返回后保留。这对于着色器来说非常有用,可以根据计算的结果更新材质属性。czm_modelMaterial: 这是CesiumJS定义的一个结构体类型,用于表示材质的属性。它包含了多个字段,如漫反射颜色(diffuse)、镜面反射颜色(specular)、光泽度(shininess)、透明度(alpha)等。material: 这是传递给 fragmentMain 函数的 czm_modelMaterial 类型变量的名称(带有 inout 修饰符)。可以通过 material 访问和修改材质的属性。
# cesium fragmentMain函数
const customShaderColor = new Cesium.CustomShader({
fragmentShaderText:
`void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material)
{
material.diffuse = fsInput.metadata.color.rgb;
float transparency = 1.0 - fsInput.metadata.color.a;
// To mimic light scattering, use exponential decay
float thickness = fsInput.voxel.travelDistance * 16.0;
material.alpha = 1.0 - pow(transparency, thickness);
}`,
});
const customShaderWhite = new Cesium.CustomShader({
fragmentShaderText:
`void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material)
{
material.diffuse = vec3(1.0);
material.alpha = 1.0;
}`,
});
function createPrimitive(provider, customShader, modelMatrix) {
viewer.scene.primitives.removeAll();
const voxelPrimitive = viewer.scene.primitives.add(
new Cesium.VoxelPrimitive({
provider: provider,
customShader: customShader,
modelMatrix: modelMatrix,
})
);
......
}
// createPrimitive自定义函数,非官方函数
const primitive = createPrimitive(
provider,
customShaderColor,
modelMatrix
);
- normalize 函数用于归一化向量
- max 函数用于取两个值中的较大值
- dot 函数用于计算两个向量的点积(在点积运算中,第一个向量投影到第二个向量上(这里,向量的顺序是不重要的,点积运算是可交换的),然后通过除以它们的标量长度来“标准化”。这样,这个分数一定是小于等于1的,可以简单地转化成一个角度值。)
- int tileIndex = fsInput.voxel.tileIndex 和 int sampleIndex = fsInput.voxel.sampleIndex:获取体素的瓦片索引和采样索引。int 表示整数类型。
- mix(cellColor, vec3(1.0), 0.5) 函数将计算得到的体素颜色和白色进行混合
- Cesium.UniformType.INT(整数类型)
const customShader = new Cesium.CustomShader({
fragmentShaderText:
`void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material)
{
// 归一化
vec3 voxelNormal = normalize(czm_normal * fsInput.voxel.surfaceNormal);
float diffuse = max(0.0, dot(voxelNormal, czm_lightDirectionEC));
float lighting = 0.5 + 0.5 * diffuse;
int tileIndex = fsInput.voxel.tileIndex;
int sampleIndex = fsInput.voxel.sampleIndex;
//根据元数据的颜色和光照强度计算体素颜色。
vec3 cellColor = fsInput.metadata.color.rgb * lighting;
if (tileIndex == u_selectedTile && sampleIndex == u_selectedSample) {
material.diffuse = mix(cellColor, vec3(1.0), 0.5);
material.alpha = fsInput.metadata.color.a;
} else {
material.diffuse = cellColor;
material.alpha = fsInput.metadata.color.a;
}
}`,
uniforms: {
u_selectedTile: {
type: Cesium.UniformType.INT,
value: -1.0,
},
u_selectedSample: {
type: Cesium.UniformType.INT,
value: -1.0,
},
},
});
# cesium fsInput属性
// 源码中的fsInput
// FragmentInput and initializeInputStruct() are dynamically generated in JS,
// see CustomShaderPipelineStage.js
FragmentInput fsInput;
initializeInputStruct(fsInput, attributes);
fsInput.featureIds = featureIds; // 数组
fsInput.metadata = metadata; // 元数据
fsInput.metadataClass = metadataClass;
fsInput.metadataStatistics = metadataStatistics;
fragmentMain(fsInput, material);
# cesium 自定义样式材质方案
# cesium Material类
材质通过漫反射、高光、法线、发射和alpha分量的组合来定义表面外观。这些值使用名为Fabric的JSON模式指定,该模式在幕后被解析和组装成glsl着色器代码。
# cesium czm_属性
struct czm_modelMaterial {
vec4 baseColor;
vec3 diffuse;
float alpha;
vec3 specular;
float roughness;
vec3 normalEC;
float occlusion;
vec3 emissive;
#ifdef USE_SPECULAR
float specularWeight;
#endif
#ifdef USE_ANISOTROPY
vec3 anisotropicT;
vec3 anisotropicB;
float anisotropyStrength;
#endif
#ifdef USE_CLEARCOAT
float clearcoatFactor;
float clearcoatRoughness;
vec3 clearcoatNormal;
// Add clearcoatF0 when KHR_materials_ior is implemented
#endif
};
- czm_modelMaterial:结构体定义了一个用于3D模型材质的属性集合,这些属性通常用于计算机图形学中,以模拟物体表面的外观和光照效果。
- baseColor (vec4): 基础颜色,使用四维向量(vec4)表示,其中前三个分量(RGB)代表颜色,第四个分量(A)代表透明度(Alpha)。这个属性定义了材质的基本颜色。
diffuse(vec3): 漫反射颜色,使用三维向量(vec3)表示,仅包含RGB三个分量。漫反射是光线照射到粗糙表面后向各个方向散射的现象,这个属性定义了材质在漫反射作用下的颜色。alpha(float): 透明度,使用浮点数(float)表示。这个属性进一步控制材质的透明度,虽然baseColor的第四个分量也包含了透明度信息,但这里的alpha可能用于其他目的,如单独的透明度控制或特殊效果。specular(vec3): 镜面反射颜色,使用三维向量(vec3)表示。镜面反射是光线照射到光滑表面后按照特定角度反射的现象,这个属性定义了材质在镜面反射作用下的颜色。- roughness (float): 粗糙度,使用浮点数(float)表示。这个属性决定了材质表面的粗糙程度,影响镜面反射的效果。粗糙度越高,反射越分散,镜面效果越弱。
- normalEC (vec3): 切空间法线,使用三维向量(vec3)表示,并且是在眼坐标系(Eye Coordinate System)下的。这个属性用于定义材质表面的微观几何结构,影响光照和阴影的计算。
- occlusion (float): 环境光遮蔽(AO, Ambient Occlusion),使用浮点数(float)表示。这个属性模拟了由于物体表面几何形状造成的光线无法到达的区域,增强模型的深度和真实感。
- emissive (vec3): 自发光颜色,使用三维向量(vec3)表示。这个属性定义了材质自身发光的颜色,不受环境光照影响,常用于模拟光源或发光物体。
# cesium Color类
使用红色、绿色、蓝色和alpha值指定,范围从0(无强度)到1.0(全强度)。
# Color.fromAlpha基本颜色设置
Cesium.Color.GREEN //设置颜色方式
# 添加透明度设置
const color = Cesium.Color[colorName.toUpperCase()];
return Cesium.Color.fromAlpha(color, parseFloat(alpha));
# 设置自定义值
new Cesium.Color() //不传参的话默认(1,1,1,1)
# Color.clone 克隆
Cesium.Color.clone(color, result)
// 把feature的color克隆给highlighted.originalColor
Cesium.Color.clone(feature.color, highlighted.originalColor);
# cesium Math类
- Math.toRadians:角度转弧度
const heading = Cesium.Math.toRadians(135);
# cesium EasingFunction缓动动画
简化与TweenCollection一起使用的函数。
Cesium.EasingFunction.QUADRATIC_IN_OUT:开始时加速,结束时减速,形成一个平滑的过渡效果
# cesium UniformType
基本GLSL统一类型的枚举。这些可以与CustomShader一起使用来声明用户定义的Uniform。
| Name | Type | Description |
|---|---|---|
| FLOAT | string | A single floating point value. |
| VEC2 | string | A vector of 2 floating point values. |
| VEC3 | string | A vector of 3 floating point values. |
| VEC4 | string | A vector of 4 floating point values. |
| INT | string | A single integer value |
| INT_VEC2 | string | A vector of 2 integer values. |
| INT_VEC3 | string | A vector of 3 integer values. |
| INT_VEC4 | string | A vector of 4 integer values. |
| BOOL | string | A single boolean value. |
| BOOL_VEC2 | string | A vector of 2 boolean values. |
| BOOL_VEC3 | string | A vector of 3 boolean values. |
| BOOL_VEC4 | string | A vector of 4 boolean values. |
| MAT2 | string | A 2x2 matrix of floating point values. |
| MAT3 | string | A 3x3 matrix of floating point values. |
| MAT4 | string | A 3x3 matrix of floating point values. |
| SAMPLER_2D | string | A 2D sampled texture. |
| SAMPLER_CUBE | string |
const NOTHING_SELECTED = 12;
const selectFeatureShader = new Cesium.CustomShader({
uniforms: {
u_selectedFeature: {
type: Cesium.UniformType.INT,
value: NOTHING_SELECTED,
},
},
lightingModel: Cesium.LightingModel.PBR,
fragmentShaderText: `
const int NOTHING_SELECTED = 12;
void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
int featureId = fsInput.featureIds.featureId_0;
if (u_selectedFeature < NOTHING_SELECTED && featureId == u_selectedFeature) {
material.specular = vec3(1.00, 0.85, 0.57);
material.roughness = 0.1;
}
}
`,
});
tileset.customShader = selectFeatureShader;
// 可动态修改uniform
// uniform变量在着色器代码中是只读的,但可以在JavaScript代码中使用setUniform方法来修改它们的值。
selectFeatureShader.setUniform("u_selectedFeature", pickedObject.featureId);