大家好,我是程序员kenney,今天给大家分析一下OpenGL的黑屏常见原因。
做OpenGL开发的同学,想必一定碰到过黑屏的问题,特别是刚接触OpenGL的同学,可能会觉得黑屏问题让人相当头疼,因为OpenGL的查错没有一般编程时那么简单,我们通常是利用glGetError()这个API来获取错误码,但这个方法获取的错误是调用这个方法时,已经产生的错误,它有可能是很久之前产生的,这样查越来还是比较不方便的,而且,有些黑屏的情况下,glGetError()也不会报任何错。
在给大家总结常见的黑屏原因之前,我们先来了解一下我们看到的黑屏究竟是什么?其实屏幕也是一块frame buffer,但它比较特殊,是0号frame buffer,我们如果自己申请frame buffer的话,得到的id是大于0的。那么frame buffer它就会有自己的颜色,如果不特意设置的话,它就是黑色的,因此如果我们渲染操作未正确执行,什么也没渲染出来,自然看到了底色的黑色。
我们也可以通过glClearColor()+glClear()来设置消除颜色及执行消除操作,来将一个frame buffer清成某种颜色。因此,如果你将frame buffer清成了别的颜色,但其它渲染操作未正确执行,你有可能也不是黑屏,而是你设置的消除颜色,这里也一并总结了,统成为黑屏,同时也包括其它一些不正确的情形。
下面给大家总结一下:
• 调用线程不正确
OpenGL的API在调用时需要有正确的上下文,在Android中称为EGL Context,其它平台有其它平台的叫法,但原理类似。一个线程需要跟EGL Context绑定才能正确使用OpenGL的API,否则调用不会有任何效果,具体可参考我的一篇文章:《OpenGL ES 高级进阶:EGL及GL线程》。
• GL Program不正确
OpenGL渲染需要通过GL Program,它就是一个程序,和我们的普通程序是一个道理,只不过它是运行在GPU上的,如果它不正确了,那自然就渲染不出正确的结果,常见的不正确原因为shader编译失败,通常是因为语法错误,可以用glGetShaderInfoLog()来在编译之后查看相关shader信息,以及在Link后用glGetProgramInfoLog()查看相关program信息,如果得到的信息为空,则说明没有错。
• 未调用glDrawXXX()
要渲染出来东西,必须调用glDrawXXX(),一般很少出现没调的情况,一般都是低级失误,最好也排查一下。
• 顶点attribute值设置错误
顶点关系到渲染到什么位置,如果设置错误导致渲染的位置在可视范围之外,那么就看不到了,等于没做渲染。
• attribute未启用
我们通过想要设置一个attribute的值,需要获取这个attribute的location,并通过glVertexAttribPointer()给它设置值,但别忘了需要使用glGetAttribLocation()来启用这个location,不然设置了也没有用,默认是不启用的。
• View Port设置错误
View Port即视口,可以理解成我们通过一个窗口去看见OpenGL世界坐标系里渲染的景物,就像我们通过窗口看到室外的景物一样,如果这个窗口没设置或者设置不正确,也会导致看不到东西,一般情况下,我们会将它设置为surface的大小,这样渲染出来的东西就刚好填满这个surface。
• 没有渲染到0号frame buffer
有时候渲染操作有很多步,想做完这些步骤后,再将做好的结果显示的屏幕上,这时就会用一些frame buffer来做离屏渲染,但在最后一步渲染到屏幕上时,需要将frame buffer绑定回0号,才能上屏。
• 渲染了一个不正确的纹理
例如我们希望对一个纹理做一些处理然后渲染出来,但如果这个纹理本身是不正确的,例如前面的步骤出了一些错,导致给过来的纹理id不正确,比如是0,或者纹理id是正确的,但这个纹理是全黑的或者空的,也会导致黑屏。
• glDrawXXX()方法传递的顶点数不正确
我们在调用glDrawXXX(),会设置顶点数组的开始位置和数量,如果设置不正确,导致传递的顶点是0个,也会导致渲染不出来任何东西。
• 顶点buffer的position不正确
这一点主要是针对java及kotlin,glVertexAttribPointer()接受数据时是通过一个buffer,而我们往buffer是put数据后,buffer的position会相应地往后移动,因此在调用glVertexAttribPointer()之前,记得将position设回到0,否则它将从末尾开始取数据,当然就取不到了。
• 未开启颜色混合渲染了有透明度的纹理
OpenGL默认是不开启颜色混合的,这会导致透明的部分通常会被渲染成黑色,而不是透出下面的颜色,具体可以参数我的一篇文章:《OpenGL ES 高级进阶:颜色混合》。
好了,先总结到这,这些是比较常见的,也欢迎大家给我留意补充讨论~
感谢阅读!
来源:掘金,作者:程序员kenney
链接:https://juejin.im/post/5d5038ef6fb9a06b130f15b9
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。