[GLES] glClear的限制

函数原型

/**
 * 清除指定缓冲区
 * @param mask 以位指定的形式来指定需要被清除内容的缓冲区
 *     可用的参数有:
 *      - GL_COLOR_BUFFER_BIT 颜色缓冲区
 *      - GL_DEPTH_BUFFER_BIT 深度缓冲区
 *      - GL_ACCUM_BUFFER_BIT 累积缓冲区
 *      - GL_STENCIL_BUFFER_BIT 模板缓冲区
 */
void glClear(
    GLbitfield mask // Parameters
);

执行此方法可以将指定的缓冲区被赋值为默认的值,
mask中有指定GL_COLOR_BUFFER_BIT时,颜色缓冲区将被全部重置为glClearColor(float red, float green, float blue, float alpha)指定的颜色;
mask中有指定GL_DEPTH_BUFFER_BIT时,深度缓冲区将被全部重置为glClearDepthf(float depth)指定的深度值。

问题现象

问题截图

上面截图中,屏幕顶部出现了花屏。
此问题发生的场景:

  1. 窗口尺寸发生变化时,窗口的显存被重新分配

此问题发生的条件:

  1. 开启了剪裁测试:glEnable(GL_SCISSOR_TEST)
  2. 设定了剪裁区域:glScissor(0, 0, window_width, window_height - 300)

完整问题代码:

fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
    glEnable(GL_SCISSOR_TEST)
    glClearColor(0.5f, 0.0f, 0.5f, 0.0f) // 紫色
}

fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
    glViewport(0, 0, width, height)
    glScissor(0, 0, width, height - 300)
}

fun onDrawFrame(gl: GL10?) {
    glClear(GL_COLOR_BUFFER_BIT)

    // TODO render.......
}

问题原因

glClear能够清理的缓冲区是有范围限制的,它会因为glViewport剪裁测试等操作被限制可清除的范围。所以想要清除整个缓冲区时,记得重置Viewport、关闭剪裁测试(现在还不清楚模板测试、Alpha测试等操作是不是也会同理影响glClear的清理范围,不过涉及到这些操作的同学可以自行验证一下)。

解决方案

针对此问题,可以有以下两种解决方案:

  1. onSurfaceChanged时,针对全屏做清屏,代码如下:
    fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
       // TODO ..........
    
      val isScissorEnabled = glIsEnable(GL_SCISSOR_TEST)
      if (isScissorEnabled) glDisable(GL_SCISSOR_TEST)
      glClear(GL_COLOR_BUFFER_BIT) // 根据自己的需要清除指定的缓冲区
      if (isScissorEnabled) glEnable(GL_SCISSOR_TEST)     
    
       // TODO ..........
    }
    
  2. onDrawFrame里清屏时,关闭剪裁测试,代码如下:
    fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
        val isScissorEnabled = glIsEnable(GL_SCISSOR_TEST)
        if (isScissorEnabled) glDisable(GL_SCISSOR_TEST)
        glClear(GL_COLOR_BUFFER_BIT) // 根据自己的需要清除指定的缓冲区
        if (isScissorEnabled) glEnable(GL_SCISSOR_TEST)
    
        // TODO rendering......
    }
    

不过考虑到drawcall的开销,条件允许时,还是选择方法1比较好。

你可能感兴趣的:([GLES] glClear的限制)