美文网首页
[GLES] glClear的限制

[GLES] glClear的限制

作者: Cocoonshu | 来源:发表于2021-07-28 17:07 被阅读0次

    函数原型

    /**
     * 清除指定缓冲区
     * @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的限制

          本文链接:https://www.haomeiwen.com/subject/zuizmltx.html