函数原型
/**
* 清除指定缓冲区
* @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)
指定的深度值。
问题现象
上面截图中,屏幕顶部出现了花屏。
此问题发生的场景:
- 窗口尺寸发生变化时,窗口的显存被重新分配
此问题发生的条件:
- 开启了剪裁测试:
glEnable(GL_SCISSOR_TEST)
- 设定了剪裁区域:
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
的清理范围,不过涉及到这些操作的同学可以自行验证一下)。
解决方案
针对此问题,可以有以下两种解决方案:
- 在
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 .......... }
- 在
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比较好。