在 Cesium 1.102.0 及以上版本中,对 WebGL 支持做了调整,默认使用 WebGL2,对应 OpenGL3,因此一些语法已经不支持,需要使用最新语法进行调整。
前两天解决了 墙体动态效果报错,今天又遇到雨雪天气报错,这里记录一下。
本文包括,报错原因、解决方法、在线示例三部分。
报错原因
==为了阅读方便,这里在把错误原因贴一下:==
报错原因:Cesium 自 1.102.0 开始,为了更好支持跨平台,尤其是移动端,Cesium 默认使用 WebGL2 上下文,如果想使用 WebGL1 上下文,需要在地球初始化的时候设置相应的参数。
为了在 WebGL2 上下文中工作,任何自定义材质、自定义图元和自定义着色器都需要升级到使用 GLSL 300。
详见解释:
openGL之API学习(三十五)texture和texture2D
以及:解决着色器运行报错:ERROR: 0:32: ‘texture2D‘ : type is for Vulkan api only
而笔者写的自定义材质,使用的语法应该是低于 GLSL 300,因此不支持,将语法更新即可。
涉及语法:
// 主要是 varying
varying vec2 v_textureCoordinates;
// 主要是 gl_FragColor 和 texture2D
gl_FragColor=mix(texture2D(colorTexture,v_textureCoordinates),vec4(finalColor,1),.5);
完整错误:
[Cesium WebGL] Fragment shader compile log: ERROR: 0:1: 'varying' : Illegal use of reserved word
Sandcastle-client.js:42 [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 LOG_DEPTH
#define OES_texture_float_linear
#define OES_texture_float
#line 0
uniform vec4 czm_viewport;
uniform float czm_frameNumber;
#line 0
uniform sampler2D colorTexture;
varying vec2 v_textureCoordinates;
uniform float snowSpeed;
uniform float snowSize;
float snow(vec2 uv,float scale)
{
float time=czm_frameNumber/snowSpeed;
float w=smoothstep(1.,0.,-uv.y*(scale/10.));if(w<.1)return 0.;
uv+=time/scale;uv.y+=time*2./scale;uv.x+=sin(uv.y+time*.5)/scale;
uv*=scale;vec2 s=floor(uv),f=fract(uv),p;float k=3.,d;
p=.5+.35*sin(11.*fract(sin((s+p+scale)*mat2(7,3,6,5))*5.))-f;d=length(p);k=min(d,k);
k=smoothstep(0.,k,sin(f.x+f.y)*snowSize);
return k*w;
}
void main(void){
vec2 resolution=czm_viewport.zw;
vec2 uv=(gl_FragCoord.xy*2.-resolution.xy)/min(resolution.x,resolution.y);
vec3 finalColor=vec3(0);
float c=0.;
c+=snow(uv,30.)*.0;
c+=snow(uv,20.)*.0;
c+=snow(uv,15.)*.0;
c+=snow(uv,10.);
c+=snow(uv,8.);
c+=snow(uv,6.);
c+=snow(uv,5.);
finalColor=(vec3(c));
gl_FragColor=mix(texture2D(colorTexture,v_textureCoordinates),vec4(finalColor,1),.5);
}
An error occurred while rendering. Rendering has stopped.
RuntimeError: Fragment shader failed to compile. Compile log: ERROR: 0:1: 'varying' : Illegal use of reserved word
解决方法
以下是两种方法解决问题,推荐第二种。
1. 初始化地球时(不推荐),传入参数,使用 WebGL1 上下文
const viewer = new Viewer("cesiumContainer", {
// 指定上下文
contextOptions: {
requestWebgl1: true,
},
});
2. 修正 GLSL 代码(推荐)
错误代码(texture2D):
// 主要是 varying
varying vec2 v_textureCoordinates;
// 主要是 gl_FragColor 和 texture2D
gl_FragColor=mix(texture2D(colorTexture,v_textureCoordinates),vec4(finalColor,1),.5);
修正为:
// 注意:这里用 in 或者 out 替换 varying
in vec2 v_textureCoordinates;
// 注意:这里将 vFragColor 定义在 main 之外,在 main 内赋值
// texture2D 替换为 texture
out vec4 vFragColor;
void main(void){
vFragColor=mix(texture(colorTexture,v_textureCoordinates),vec4(finalColor,1),.5);
}
在线示例
示例中展示了, ==三维地图下雪天气效果==。