# 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的属性和方法

  1. 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);
  1. 修改模型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);
  1. 设置模型的轮廓颜色silhouetteColor
entity.model.silhouetteColor = getColor(
  newValue,
  viewModel.silhouetteAlpha
);
  1. 设置轮廓的大小(像素)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 主要包括以下几种类型:

  1. Cesium.LightingModel.PBR(基于物理的渲染):
    • 基于物理的光照模型,提供更真实的光照和材质效果。
    • 适用于需要高度真实感的场景,如建筑、车辆、人物等复杂模型的渲染。
  2. 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
};
  1. 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类

  1. 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);
最后更新: 11/19/2024, 6:29:46 PM