Cesium中自定义材质与外观的GLSL注入实践
引言
在三维地理可视化领域,Cesium作为一款强大的开源JavaScript库,为开发者提供了丰富的图形渲染能力。其中,Material(材质)和MaterialAppearance(材质外观)系统是Cesium实现自定义渲染效果的核心机制。本文将深入探讨如何通过这两个系统向Primitive(图元)注入自定义GLSL代码,实现独特的视觉效果。
基本概念解析
Material系统
Material系统是Cesium中定义物体表面特性的核心组件,它通过Fabric规范来描述材质属性。开发者可以通过定义uniform变量、编写GLSL片段着色器代码等方式,创建完全自定义的材质效果。
MaterialAppearance系统
MaterialAppearance则提供了更底层的控制能力,允许开发者同时自定义顶点着色器和片段着色器。这使得我们能够控制几何体的顶点变换和最终像素着色两个关键阶段。
实现步骤详解
1. 创建几何体实例
首先需要创建一个几何体实例作为渲染对象。以立方体为例:
const boxGeometry = Cesium.BoxGeometry.fromDimensions({
dimensions: new Cesium.Cartesian3(25000.0, 25000.0, 25000.0),
});
const boxInstance = new Cesium.GeometryInstance({
geometry: boxGeometry,
modelMatrix: Cesium.Transforms.eastNorthUpToFixedFrame(
Cesium.Cartesian3.fromDegrees(113, 33, 1250)
),
attributes: {
color: Cesium.ColorGeometryInstanceAttribute.fromColor(
Cesium.Color.WHITE
)
}
});
2. 定义自定义材质
创建自定义材质时,关键是在fabric.source中编写GLSL片段着色器代码:
const customMaterial = new Cesium.Material({
translucent: false,
fabric: {
type: 'CustomBoxShader',
uniforms: {
time: 0.0,
},
source:
"uniform float time;\n" +
"czm_material czm_getMaterial(czm_materialInput materialInput) {\n" +
" czm_material material = czm_getDefaultMaterial(materialInput);\n" +
" material.diffuse = vec3(1.0, 1.0, 0.0); \n" +
" material.alpha = 1.0;\n" +
" return material;\n" +
"}"
}
});
3. 创建材质外观
MaterialAppearance允许我们完全自定义顶点和片段着色器:
const appearance = new Cesium.MaterialAppearance({
material: customMaterial,
flat: false,
faceForward: true,
translucent: true,
closed: true,
vertexShaderSource:
"in vec3 position3DHigh;\n" +
"in vec3 position3DLow;\n" +
"in vec3 normal;\n" +
"in vec2 st;\n" +
"in float batchId;\n" +
"out vec3 v_positionEC;\n" +
"out vec3 v_normalEC;\n" +
"out vec2 v_st;\n" +
"uniform float testAppUniform;\n" +
"void main()\n" +
"{\n" +
" vec4 p = czm_computePosition();\n" +
" v_positionEC = (czm_modelViewRelativeToEye * p).xyz * testAppUniform; \n" +
" v_normalEC = czm_normal * normal; \n" +
" v_st = st;\n" +
" gl_Position = czm_modelViewProjectionRelativeToEye * p;\n" +
"}\n",
fragmentShaderSource:
"in vec3 v_positionEC;\n" +
"in vec3 v_normalEC;\n" +
"in vec2 v_st;\n" +
"uniform vec4 testAppColorUniform;\n"+
"void main()\n" +
"{\n" +
" vec3 positionToEyeEC = -v_positionEC;\n" +
" vec3 normalEC = normalize(v_normalEC);\n" +
"#ifdef FACE_FORWARD\n" +
" normalEC = faceforward(normalEC, vec3(0.0, 0.0, 1.0), -normalEC);\n" +
"#endif\n" +
" czm_materialInput materialInput;\n" +
" materialInput.normalEC = normalEC;\n" +
" materialInput.positionToEyeEC = positionToEyeEC;\n" +
" materialInput.st = v_st;\n" +
" czm_material material = czm_getMaterial(materialInput);\n" +
"#ifdef FLAT\n" +
" out_FragColor = vec4(material.diffuse + material.emission, material.alpha);\n" +
"#else\n" +
" out_FragColor = czm_phong(normalize(positionToEyeEC), material, czm_lightDirectionEC);\n" +
"#endif\n" +
" out_FragColor.rgb = out_FragColor.rgb * testAppColorUniform.rgb; \n" +
" out_FragColor.a = testAppColorUniform.a; \n" +
"}\n",
materialCacheKey: "my-box-material-appearance",
});
4. 设置uniform变量
为材质和外观设置uniform变量是实现动态效果的关键:
let color = new Cesium.Color(1.0, 1.0, 0.0, 1.0);
appearance.uniforms = {
testAppUniform: 1.0,
testAppColorUniform: color,
};
5. 创建图元并添加到场景
最后将配置好的几何体实例和外观组合成图元,并添加到场景中:
const primitive = new Cesium.Primitive({
geometryInstances: boxInstance,
appearance: appearance,
asynchronous: false
});
viewer.scene.primitives.add(primitive);
6. 实现动画效果
通过修改uniform变量实现动态效果:
function animate() {
customMaterial.uniforms.time++;
const t = customMaterial.uniforms.time;
appearance.uniforms.testAppColorUniform =
new Cesium.Color(t * 0.01 % 1.0, t * 0.02 % 1.0, 0.0, t * 0.03 % 1.0);
requestAnimationFrame(animate);
}
animate();
技术要点与最佳实践
-
uniform变量更新:直接创建新的Color对象赋值比单独修改属性更可靠。
-
着色器代码组织:保持GLSL代码清晰可读,合理使用Cesium内置函数(如czm_*系列)。
-
性能考虑:避免在动画循环中频繁创建新对象,尽量复用已有对象。
-
调试技巧:可以先使用简单颜色验证着色器基本功能,再逐步添加复杂效果。
常见问题解决方案
-
效果不显示:检查uniform变量是否正确定义和赋值,确保着色器编译没有错误。
-
性能问题:复杂的GLSL计算可能会影响性能,应考虑优化算法或使用更简单的近似方法。
-
光照异常:确保正确处理法线向量,必要时使用FACE_FORWARD宏。
结语
通过Cesium的Material和MaterialAppearance系统,开发者可以充分发挥WebGL的潜力,创造出丰富多样的三维可视化效果。掌握GLSL注入技术后,可以实现从简单的颜色变化到复杂的物理模拟等各种视觉效果。本文介绍的方法为Cesium高级渲染技术提供了基础,开发者可以在此基础上进一步探索更复杂的着色器编程技术。
HunyuanImage-3.0
HunyuanImage-3.0 统一多模态理解与生成,基于自回归框架,实现文本生成图像,性能媲美或超越领先闭源模型00ops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。C++043Hunyuan3D-Part
腾讯混元3D-Part00GitCode-文心大模型-智源研究院AI应用开发大赛
GitCode&文心大模型&智源研究院强强联合,发起的AI应用开发大赛;总奖池8W,单人最高可得价值3W奖励。快来参加吧~0289Hunyuan3D-Omni
腾讯混元3D-Omni:3D版ControlNet突破多模态控制,实现高精度3D资产生成00GOT-OCR-2.0-hf
阶跃星辰StepFun推出的GOT-OCR-2.0-hf是一款强大的多语言OCR开源模型,支持从普通文档到复杂场景的文字识别。它能精准处理表格、图表、数学公式、几何图形甚至乐谱等特殊内容,输出结果可通过第三方工具渲染成多种格式。模型支持1024×1024高分辨率输入,具备多页批量处理、动态分块识别和交互式区域选择等创新功能,用户可通过坐标或颜色指定识别区域。基于Apache 2.0协议开源,提供Hugging Face演示和完整代码,适用于学术研究到工业应用的广泛场景,为OCR领域带来突破性解决方案。00- HHowToCook程序员在家做饭方法指南。Programmer's guide about how to cook at home (Chinese only).Dockerfile09
- PpathwayPathway is an open framework for high-throughput and low-latency real-time data processing.Python00
热门内容推荐
最新内容推荐
项目优选









