Cesium 1.02.0 及以上版本下自定义材质报错:[Cesium WebGL] ERROR_ 0_1_ ‘varying‘ _ Illegal use of reserved wor

2,430 阅读2分钟

在 Cesium 1.102.0 及以上版本中,对 WebGL 支持做了调整,默认使用 WebGL2,对应 OpenGL3,因此一些语法已经不支持,需要使用最新语法进行调整。

前两天解决了 墙体动态效果报错,今天又遇到雨雪天气报错,这里记录一下。

本文包括,报错原因、解决方法、在线示例三部分。


报错原因

==为了阅读方便,这里在把错误原因贴一下:==

报错原因:Cesium 自 1.102.0 开始,为了更好支持跨平台,尤其是移动端,Cesium 默认使用 WebGL2 上下文,如果想使用 WebGL1 上下文,需要在地球初始化的时候设置相应的参数。

为了在 WebGL2 上下文中工作,任何自定义材质、自定义图元和自定义着色器都需要升级到使用 GLSL 300

详见解释:

openGL之API学习(三十五)texture和texture2D

The OpenGL® Shading Language

以及:解决着色器运行报错: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);
}


在线示例

示例中展示了, ==三维地图下雪天气效果==

Cesium 沙盒测试

三维地图下雪天气效果

在这里插入图片描述