前言
人生一迹,谨以此记录Cesium相关系列知识
问题发现,使用cesium加载GLTF模型,会比其他平台加载的模型变的很暗?
(重点在于发现问题解决问题的思路与方法)
一、cesium加载GLTF模型
首先,不管怎么说,第一步加载gltf数据。Cesium对于模型的加载有两种方法,分别对应大模型和小模型。大数据模型建议用Primitive API进行加载,而小场景模型建议用Entity API加载。在此仅提供小场景模型即Entity API加载代码。
let viewer = new Cesium.Viewer("cesiumdiv");
var position = Cesium.Cartesian3.fromDegrees(113, 33, 0);
var hpr = new Cesium.HeadingPitchRoll(180, 0, 0);
var model_entity = viewer.entities.add({
name: "gltf模型",
position: position,
// 通过 Quaternion 为 Entity.orientation 属性指定值来控制模型的方向,控制模型的航向,俯仰和横滚。
orientation: Cesium.Transforms.headingPitchRollQuaternion(
position,
hpr
),
model: {
show: true,
uri: "./data/gltf/youcar.gltf",
scale: 1.0, // 缩放比例
minimumPixelSize: 128, // 最小像素大小
maximumScale: 20000, // 模型的最大比例尺大小。minimumPixelSize的上限
incrementallyLoadTextures: true, // 加载模型后纹理是否可以继续流入
runAnimations: true, // 是否应启动模型中指定的glTF动画
clampAnimations: true, // 指定glTF动画是否应在没有关键帧的持续时间内保持最后一个姿势
// 指定模型是否投射或接收来自光源的阴影 type:ShadowMode
// DISABLED 对象不投射或接收阴影;ENABLED 对象投射并接收阴影;CAST_ONLY 对象仅投射阴影;RECEIVE_ONLY 对象仅接收阴影
shadows: Cesium.ShadowMode.ENABLED,
// 参考高度
heightReference: Cesium.HeightReference.NONE,
// silhouetteColor:Cesium.Color.RED 模型轮廓颜色
// silhouetteSize 模型轮廓大小
// color 模型颜色:指定与模型混色的颜色
// colorBlendMode 混色方式
// colorBlendAmount 混色强度(1是纯色,0是模型原色)
// imageBasedLightingFactor 镜面光照强度【一般不修改,修改了没见颜色变化,或者是针对有水面反射才有效果)
},
});
viewer.trackedEntity = model_entity; // 聚焦模型
viewer.zoomTo(model_entity); //定位到模型
二、研究cesium加载模型中,对应函数参数
第二步呢,正式进入研究分析问题阶段。最容易想到的方法呢就是看加载函数中有无相关参数,那就先研究entity API的相关参数。通过上一节加载gltf的函数可以知道,里面最重要的参数设置属于model里面的参数,那么我们去官网查找[Model的相关参数](ModelGraphics - Cesium Documentation)
属性 | 默认值 | 描述 |
---|---|---|
show | true | 控制模型显隐 |
uri | 模型路径 | |
scale | 1.0 | 模型缩放比例 |
minimumPixelSize | 0.0 | 控制模型最小像素大小 |
maximumScale | 20000 | 模型的最大缩放比例,minimumPixelSize的上限 |
incrementallyLoadTextures | true | 加载模型后是否还继续传入纹理 |
runAnimations | ture | 是否启动模型gltf的动画 |
clampAnimations | true | 模型动画结束后展现最后一帧 |
shadows | ShadowMode.ENABLED | 模型接受阴影方式,DISABLED 对象不投射或接收阴影;ENABLED 对象投射并接收阴影;CAST_ONLY 对象仅投射阴影;RECEIVE_ONLY 对象仅接收阴影 |
heightReference | HeightReference.NONE | 高程参考系 |
silhouetteColor | Color.RED | 轮廓线颜色 |
silhouetteSize | 0.0 | 轮廓线大小宽度 |
color | Color.WHITE | 模型混合颜色 |
colorBlendMode | ColorBlendMode.HIGHLIGHT | 混色方式 |
colorBlendAmount | 0.5 | 混色颜色强度 |
imageBasedLightingFactor | new Cartesian2(1.0, 1.0) | 指定漫反射和镜面图像照明的贡献因子 |
lightColor | 指定模型着色时对应光线的颜色,默认使用场景光线颜色 | |
distanceDisplayCondition | 模型将在相机距离多远时显示 | |
nodeTransformations | ||
articulations | ||
clippingPlanes | 模型路径 | |
customShader | 自定义模型渲染 |
经过一个参数一个参数的去对比、分析、侦查,结果这些个参数均不能满足要求,即都不能提高加载gltf模型的亮度。
三、研究gltf同类型加载网站
gltf在线浏览网站一
gltf在线浏览网站二
gltf在线模型转换网站
3.1 修改cesium源码 toneMap参数
首先打开两个浏览网站,查看修改参数界面,发现修改toneMap可以改变模型的亮和暗,好嘞,那么去查找Cesium源码里面的渲染gltf的ToneMap方式。
接下来就,借助WebGL Inspector浏览器插件,逐帧分析Cesium加载源码
3.2 修改cesium源码 lightColorHdr参数
更改Cesium源码后,发现toneMapping发现无效。改变策略:更改模型加载的初识亮度,源码找到变量lightColorHdr,增加系数比重,可以成功!
3.3 修改gltf模型 metallicFactor金属材质参数
但是由于牵扯源码,牵一发动全身,直接更改源码对其他模型不太友好 因此需要另一个角度,从模型本身查找问题,尝试更改模型参数,gltf模型可利用vscode打开,里面为json文件,因此可以进行修改,那么我们现在需要知道参数的意义,然后还需要找到一个工具可以即时查看修改结果。
- 花开两朵,各表一枝。先说实时修改模型工具(VScode中gltfTools)
- 再说下,gltf模型的参数意义。gltf构造及参数含义
一级 | 二级 | 三级 |
---|---|---|
materials(材质) | pbrMetallicRoughness | baseColorFactor属性包含了红,绿,蓝和alpha成分,构成了材质的基本颜色 |
metallicFactor属性用于指定材质的反射情况与金属的相似度 | ||
roughnessFactor属性用于指定材质粗糙度 |
主要是更改material材质里面的metallicFactor金属感强度,更改为0即可 "metallicFactor": 0,
有金属质感,即metallicFactor不为0
无金属质感,即metallicFactor为0
2024年03月29日补充
- cesium读取gltf文件逻辑:如果gltf文件中包含metallicRoughnessTexture属性,则不读取metallicFactor属性。cesium源码中,processPbrMaterials.js文件部分逻辑代码:
else if (defined(generatedMaterialValues.u_metallicRoughnessTexture)) {
fragmentShader +=
" vec3 metallicRoughness = texture2D(u_metallicRoughnessTexture, " +
metallicRoughnessTexCoord +
").rgb;\n";
fragmentShader +=
" float metalness = clamp(metallicRoughness.b, 0.0, 1.0);\n";
fragmentShader +=
" float roughness = clamp(metallicRoughness.g, 0.04, 1.0);\n";
if (defined(generatedMaterialValues.u_metallicFactor)) {
fragmentShader += " metalness *= u_metallicFactor;\n";
}
if (defined(generatedMaterialValues.u_roughnessFactor)) {
fragmentShader += " roughness *= u_roughnessFactor;\n";
}
} else {
if (defined(generatedMaterialValues.u_metallicFactor)) {
fragmentShader +=
" float metalness = clamp(u_metallicFactor, 0.0, 1.0);\n";
} else {
fragmentShader += " float metalness = 1.0;\n";
}