Cesium 1.02.0 及以上版本下自定义材质报错:[Cesium WebGL] Fragment shader compile log: ERROR: 0:8: 'texture2D'
2023年4月19日更新—搞了一个 Cesium
镜像,欢迎使用:沙盒示例 和 API
在看到 Cesium 官方更新的日志,最新版(1.103.0)
支持平滑缩放,于是升级尝试一下。
结果偶然发现,之前写的墙体动态效果报错,经过调试,找到原因,Cesium 新版对 WebGL2
支持有变化,这里记录一下。
本文包括,报错原因、解决方法、在线示例
三部分。
报错原因
报错原因:Cesium 自 1.102.0
开始,为了更好支持跨平台,尤其是移动端,Cesium 默认使用 WebGL2
上下文,如果想使用 WebGL1
上下文,需要在地球初始化的时候设置相应的参数。
为了在 WebGL2 上下文中工作,任何自定义材质、自定义图元和自定义着色器都需要升级到使用 GLSL 300
。
详见解释:
openGL之API学习(三十五)texture和texture2D
而笔者写的自定义材质,使用的语法应该是低于 GLSL 300,因此不支持,将语法更新即可。
涉及语法:
vec4 colorImage = texture2D(image, vec2(fract(st.t - time), st.t));
完整错误:
[Cesium WebGL] Fragment shader compile log: ERROR: 0:8: 'texture2D' : no matching overloaded function found
ERROR: 0:8: '=' : dimension mismatch
ERROR: 0:8: '=' : cannot convert from 'const mediump float' to 'highp 4-component vector of float'
[Cesium WebGL] Fragment shader source:
#version 300 es
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
precision highp int;
#else
precision mediump float;
precision mediump int;
#define highp mediump
#endif
#define OES_texture_float_linear
#define OES_texture_float
#line 0
layout(location = 0) out vec4 out_FragColor;
CesiumWidget.js:703 An error occurred while rendering. Rendering has stopped.
RuntimeError: Fragment shader failed to compile. Compile log: ERROR: 0:8: 'texture2D' : no matching overloaded function found
ERROR: 0:8: '=' : dimension mismatch
ERROR: 0:8: '=' : cannot convert from 'const mediump float' to 'highp 4-component vector of float'
解决方法
以下是两种方法解决问题,推荐第二种
。
1. 初始化地球时(不推荐),传入参数,使用 WebGL1 上下文
const viewer = new Viewer("cesiumContainer", {
// 指定上下文
contextOptions: {
requestWebgl1: true,
},
});
2. 修正 GLSL 代码(推荐)
错误代码(texture2D
):
vec4 colorImage = texture2D(image, vec2(fract(st.t - time), st.t));
修正为:
vec4 colorImage = texture(image, vec2(fract(st.t - time), st.t));
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Use correct character set. -->
<meta charset="utf-8"/>
<!-- Tell IE to use the latest, best version. -->
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<!-- Make the application on mobile take up the full browser screen and disable user scaling. -->
<meta
name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"
/>
<title>Cesium model adjust</title>
<script src="./Cesium.js"></script>
<script src="./cesium_init.js"></script>
<script src="http://www.openlayers.vip/examples/resources/jquery-3.5.1.min.js"></script>
<style>
@import url(./Widgets/widgets.css);
html,
body,
#cesiumContainer {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
</style>
<script>
var _hmt = _hmt || [];
(function () {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?f80a36f14f8a73bb0f82e0fdbcee3058";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
<script>
var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?f80a36f14f8a73bb0f82e0fdbcee3058";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script></head>
<body>
<div id="cesiumContainer"></div>
<script>
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJhMzVlZmUzZi0xMWRmLTQxZGEtYWQyMS1iMDhmYWM3NDkyZjMiLCJpZCI6MTIzMTAsInNjb3BlcyI6WyJhc3IiLCJnYyJdLCJpYXQiOjE1NjA4MzkzNTZ9.ORdbpPmws56kqB_GOcdYo-v38ezBkYUVqjPJiZ73JvA';
// 创建三维球
const viewer = init();
viewer.scene.debugShowFramesPerSecond = true;
/**
* @description:立体墙效果
* @date:2022-02-12
* @param:viewer
* @positions: 墙体底部位置坐标
*/
function drawWall(positionsTemp) {
// 绘制墙体
viewer.entities.add({
name: "立体墙效果",
wall: {
positions: Cesium.Cartesian3.fromDegreesArrayHeights([
118.286419,31.864436,20000.0,
119.386419,31.864436,20000.0,
119.386419,32.864436,20000.0,
118.286419,32.864436,20000.0,
118.286419,31.864436,20000.0,
]),
// 设置高度
maximumHeights: new Array(5).fill(10000),
minimumHeights: new Array(5).fill(1000),
material: new DynamicWallMaterialProperty({
color: new Cesium.Color(1.0, 0.0, 0.0, 0.5),
duration: 1000
}),
}
});
}
/**
* @description:动态立体墙材质
* @date: 2022-02-11
*/
//动态墙材质
function DynamicWallMaterialProperty(options) {
// 默认参数设置
this._definitionChanged = new Cesium.Event();
this._color = undefined;
this._colorSubscription = undefined;
this.color = options.color;
this.duration = options.duration;
this.trailImage = options.trailImage;
this._time = (new Date()).getTime();
}
Object.defineProperties(DynamicWallMaterialProperty.prototype, {
isConstant: {
get: function() {
return false;
}
},
definitionChanged: {
get: function() {
return this._definitionChanged;
}
},
color: Cesium.createPropertyDescriptor('color')
});
DynamicWallMaterialProperty.prototype.getType = function(time) {
return 'DynamicWall';
};
DynamicWallMaterialProperty.prototype.getValue = function(time, result) {
if (!Cesium.defined(result)) {
result = {};
}
result.color = Cesium.Property.getValueOrClonedDefault(this._color, time, Cesium.Color.WHITE, result.color);
if (this.trailImage) {
result.image = this.trailImage;
} else {
result.image = Cesium.Material.DynamicWallImage;
}
if (this.duration) {
result.time = (((new Date()).getTime() - this._time) % this.duration) / this.duration;
}
viewer.scene.requestRender();
return result;
};
DynamicWallMaterialProperty.prototype.equals = function(other) {
return this === other ||
(other instanceof DynamicWallMaterialProperty &&
Cesium.Property.equals(this._color, other._color));
};
Cesium.DynamicWallMaterialProperty = DynamicWallMaterialProperty;
Cesium.Material.DynamicWallType = 'DynamicWall';
Cesium.Material.DynamicWallImage = "http://openlayers.vip/resources/polylineTrailLinkMaterial.png";
Cesium.Material.DynamicWallSource = "czm_material czm_getMaterial(czm_materialInput materialInput)\n\
{\n\
czm_material material = czm_getDefaultMaterial(materialInput);\n\
vec2 st = materialInput.st;\n\
vec4 colorImage = texture(image, vec2(fract(st.t - time), st.t));\n\
vec4 fragColor;\n\
fragColor.rgb = color.rgb / 1.0;\n\
fragColor = czm_gammaCorrect(fragColor);\n\
material.alpha = colorImage.a * color.a;\n\
material.diffuse = color.rgb;\n\
material.emission = fragColor.rgb;\n\
return material;\n\
}";
Cesium.Material._materialCache.addMaterial(Cesium.Material.DynamicWallType, {
fabric: {
type: Cesium.Material.DynamicWallType,
uniforms: {
color: new Cesium.Color(1.0, 1.0, 1.0, 1),
image: Cesium.Material.DynamicWallImage,
time: 0
},
source: Cesium.Material.DynamicWallSource
},
translucent: function(material) {
return true;
}
});
drawWall();
viewer.zoomTo(viewer.entities);
</script>
</body>
</html>
在线示例
示例中展示了, 三维地图动态墙效果。