0.前言
做一个基于OpenGLES的项目,其中涉及到渐变宽度曲线绘制功能的开发(类似下图效果),花了一些时间学习相关的知识,这里做一下总结与整理。受限于个人能力,这里不给出具体实现时OpenGL整个工程的搭建和每个接口函数的详细说明(免得误导他人),只给出大体的使用方法和关键性的调用语句。
1.抗锯齿问题
上图中的效果除了抗锯齿外,还有颜色、宽度、透明度的变化;在OpenGL2.0及其以上版本中,颜色、透明度的变化可以通过shader渲染实现,因此主要问题只剩下抗锯齿和宽度变化,这篇文章首先讲抗锯齿部分的处理。
OpenGL中已经定义了绘制线段的相关接口函数,从OpenGL1.1中固定渲染管道操作的glBegin(GL_LINES)操作,到OPENGL2.0以上的可编程渲染管道操作的glDrawArray(GL_LINES,...)操作。但是直接调用时,一般绘制的线段在具有一定角度时(非水平、垂直状态下)会产生明显的锯齿状,那么如何消除这种锯齿?OpenGL提供了如下解决方法。
2.解决方法
2.1 glHint()
这是一个看起来十分神奇的配置,以绘制线段为例,大体调用如下:
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA);
glEnable(GL_LINE_SMOOTH);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
/* 绘制线段操作 */
效果也是出类拔萃,对比如下,左边的线段是默认设置下绘制得到,右边的线段是开启了上述设置后绘制的结果。仔细观察会发现右边的线段宽度比左边要大一些,但实际上代码中两段线段的宽度设置相同。这是一个暗示,暗示OpenGL内部抗锯齿的操作,具体原理分析见下一篇文章。。。
但我尝试在android平台上(高通8953)如上设置后,并没有产生抗锯齿效果。网上查阅相关问题时,看到一个说法,glHint()只是给硬件一个“建议”,可是否会起作用还要看硬件是否支持这样的设置“建议”,好吧。
2.2 反走样
线条的锯齿,就是走样的一种表现,相对应的可以通过设置OpenGL中的反走样来处理。OpenGL中设置反走样有如下方式。
1)设置全局环境中的反走样
OpenGL中默认开启了MSAA,要使用它还需要申请用于多重采样的缓冲区,申请方式与窗口系统有关。在glut中申请调用如下,只需增加一个GLUT_MULTISAMPLE属性
glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH |GLUT_RGBA | GLUT_MULTISAMPLE);
之后开启多重采样再进行绘制
glEnable(GL_MULTISAMPLE);
/*绘图操作*/
下图中左边为未开启MSAA的绘制结果,右边为开启MSAA之后的绘制结果。
不过在android平台中需要在EGL的初始化代码中做类似的设置,相关设置参考https://blog.csdn.net/u014248312/article/details/78027383
另外,这种设置只有在默认的绘制环境中起作用。假如你自己创建了一个FBO,在FBO中渲染时,上面的全局设置就无法发挥作用了。因此引入第二种多重采样设置—在FBO中使用多重采样。
2)FBO中的多重采样
这方面相关介绍很多,链接给出了相关的调用说明,就不再赘述了。
有两点需要注意:
a.FBO中的多重采样只作用于该FBO,譬如使用该FBO渲染,之后将渲染结果拷贝至系统默认FBO(一般是屏幕上),就具有抗锯齿作用;可若需要对该纹理做进一步的后处理,则无法直接操作,需要将该FBO的数据拷贝至一个没有开启多重采样的FBO上,再绑定这个普通FBO的纹理,做后续操作
b. 经过测试发现我的android平台中,若开启了全局MSAA,则在FBO中使用MSAA时,需要在上述操作之后增加一句 glGenerateMipmap(GL_TEXTURE_2D);调用,否则按照a中的操作得到的纹理仍然不具有抗锯齿效果
啰嗦了半天,也就只是实现了抗锯齿的设置,此时绘制得到的线段宽度无法连续变化。不得已要再进一步,下一篇文章介绍宽度连续变化线段的绘制实现。
3.参考资料
https://blog.csdn.net/wangdingqiaoit/article/details/52830310