【OpenGL】FBO中多重采样抗锯齿.doc_第1页
【OpenGL】FBO中多重采样抗锯齿.doc_第2页
【OpenGL】FBO中多重采样抗锯齿.doc_第3页
【OpenGL】FBO中多重采样抗锯齿.doc_第4页
【OpenGL】FBO中多重采样抗锯齿.doc_第5页
免费预览已结束,剩余1页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

【OpenGL】FBO中多重采样抗锯齿(MSAA:MultiSampling Anti-Aliasing) 今天在写这样一个程序,就是导入一个OBJ模型然后显示出来的时候,遇到了一个问题。我在程序中开启了多重采样,在屏幕上显示出来的效果确实有抗锯齿。但是当我用FBO离屏渲染,然后保存为BMP图像的时候,发现保存出来的BMP图像并没有抗锯齿效果。问题产生原因及解决方案:在默认帧缓冲中启用多重采样并不会导致FBO里也会启用多重采样。因此要在FBO里达到多重采样的效果,必须创建适用多重采样的FBO,而不是普通的FBO。关于FBO介绍及使用可参考:FBO下面分别介绍多重采样抗锯齿以及怎样在FBO中使用这一技术。一、多重采样抗锯齿技术(multisampling anti-aliasing)1、抗锯齿技术种类分类全屏反锯齿全屏反锯齿(full scene Anti-aliasing,简称FSAA),也称全屏抗锯齿,它指的是利用反锯齿技术对输出到显示器的满屏画面信号进行放大与采样分析并重新制作满屏画面信号输出至显示器,而不是对画面某一部分使用反锯齿技术。全屏反锯齿对于3D游戏画面有着很大的影响,它能使整个3D游戏画面变得细腻、清晰与逼真,这是是一种重要的技术应用。全屏抗锯齿反锯齿技术,有以下方法:超级采样抗锯齿超级采样抗锯齿(Super-Sampling Anti-aliasing,简称SSAA)此是早期抗锯齿方法,比较消耗资源,但简单直接,先把图像映射到缓存并把它放大,再用超级采样把放大后的图像像素进行采样,一般选取2个或4个邻近像素,把这些采样混合起来后,生成的最终像素,令每个像素拥有邻近像素的特征,像素与像素之间的过渡色彩,就变得近似,令图形的边缘色彩过渡趋于平滑。再把最终像素还原回原来大小的图像,并保存到帧缓存也就是显存中,替代原图像存储起来,最后输出到显示器,显示出一帧画面。这样就等于把一幅模糊的大图,通过细腻化后再缩小成清晰的小图。如果每帧都进行抗锯齿处理,游戏或视频中的所有画面都带有抗锯齿效果。2而将图像映射到缓存并把它放大时,放大的倍数被用于分别抗锯齿的效果,如:图1,AA后面的x2、x4、x8就是原图放大的倍数。 超级采样抗锯齿中使用的采样法一般有两种:顺序栅格超级采样(Ordered Grid Super-Sampling,简称OGSS),采样时选取2个邻近像素。旋转栅格超级采样(Rotated Grid Super-Sampling,简称RGSS),采样时选取4个邻近像素。多重采样抗锯齿多重采样抗锯齿(MultiSampling Anti-Aliasing,简称MSAA)是一种特殊的超级采样抗锯齿(SSAA)。MSAA首先来自于OpenGl。具体是MSAA只对Z缓存(Z-Buffer)和模板缓存(Stencil Buffer)中的数据进行超级采样抗锯齿的处理。可以简单理解为只对多边形的边缘进行抗锯齿处理。这样的话,相比SSAA对画面中所有数据进行处理,MSAA对资源的消耗需求大大减弱,不过在画质上可能稍有不如SSAA。覆盖采样抗锯齿覆盖采样抗锯齿(CoverageSampling Anti-Aliasing,简称CSAA)可编程过滤抗锯齿可编程过滤抗锯齿(Custom Filter Anti-Aliasing)2、多重采样抗锯齿技术详解首先看下面这幅图,左右对比了采样多重采样抗锯齿技术和不采用的效果对比:图一 采样多重采样抗锯齿技术前后对比可以看出,左图边缘有很明显的锯齿状。导致这一现象的原因是:每个像素的绘制是由它是否完全位于多边形内部所决定的。如果它在多边形内部,则渲染它;否则不渲染。很显然,这是不准确的。一些像素恰好位于边缘上面。如果我们依据一个像素它位于多边形内部的区域的大小来决定它的渲染,那么获得的效果要好很多。最终像素的颜色就是多边形颜色和其外部的颜色的混合。你也许会认为这样会导致性能上的消耗,事实却是如此。但是我们可以针对每个像素使用多个采样来近似估计最终结果。MSAA技术包括针对每个像素实施多个采样,然后对这些采样的结果进行混合来决定这个像素的最终值。采样点位于像素内部的不同位置。很显然,大多数的采样点会位于多边形内部,但是对于那些位于多边形边缘的像素,一些采样点会位于多边形外部。如果对每个像素进行4次采样,那么光栅化的频率将是不进行多重采样的4倍。对于每个像素,片断着色器执行一次,输出结果由4个采样点中位于多边形内部的数量决定。3、在OpenGL中实现MSAA技术在OpenGL中实施这一技术非常简单,不需要过多的操作。它是通过使用额外的缓冲区来存储子像素样本来实现的。然后这些样本被合成以生成片断的最终颜色。下面以在Qt中为例来进行说明,它和使用GLUT等API很相似。(1)在创建OpenGL窗口的时候,需要选择支持MSAA的OpenGL上下文:Cpp代码 1 QGLFormat format; 2 format.setVersion(4,0); 3 format.setProfile(QGLFormat:CoreProfile); 4 format.setSampleBuffers(true); 5 format.setSamples(4); 6 QGLWidget *glView = new QGLWidget(format); (2)判断多重采样缓冲区是否存在,以及对每个像素使用几个采样:Cpp代码 7 GLint bufs, samples; 8 glGetIntegerv(GL_SAMPLE_BUFFERS, &bufs); 9 glGetIntegerv(GL_SAMPLES, &samples); 10 printf(MSAA: buffers = %d samples = %dn, bufs, samples); (3)启用MSAA:Cpp代码 11 glEnable(GL_MULTISAMPLE); (4)如果要禁用MSAA,使用以下代码:Cpp代码 12 glDisable(GL_MULTISAMPLE); 如果使用GLUT,则使用以下代码:Cpp代码 13 /申请一个采用了双重缓存,包含颜色,深度的帧缓存和多重采样。 14 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_MULTISAMPLE); 15 glEnable(GL_MULTISAMPLE);/开启多重缓存 16 glDisable(GL_MULTISAMPLE);/关闭多重缓存 二、在FBO中使用多重采样抗锯齿技术首先我们需要创建1个适用于多重采样的FBO:Cpp代码 17 /创建FBO:multisampling 18 glGenFramebuffers(1,&m_frameBufferMS); 19 glBindFramebuffer(GL_FRAMEBUFFER,m_frameBufferMS); 20 21 glGenRenderbuffers(1,&m_renderBufferColorMS); 22 glBindRenderbuffer(GL_RENDERBUFFER,m_renderBufferColorMS); 23 glRenderbufferStorageMultisample(GL_RENDERBUFFER,4, 24 GL_RGB,m_subImageWidth,m_subImageHeight); 25 glBindRenderbuffer(GL_RENDERBUFFER,0); 26 glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0, 27 GL_RENDERBUFFER,m_renderBufferColorMS); 28 29 glGenRenderbuffers(1,&m_renderBufferDepthMS); 30 glBindRenderbuffer(GL_RENDERBUFFER,m_renderBufferDepthMS); 31 glRenderbufferStorageMultisample(GL_RENDERBUFFER,4, 32 GL_DEPTH_COMPONENT24,m_subImageWidth,m_subImageHeight); 33 glBindRenderbuffer(GL_RENDERBUFFER,0); 34 glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT, 35 GL_RENDERBUFFER,m_renderBufferDepthMS); 36 37 glBindFramebuffer(GL_FRAMEBUFFER,0); 记住需要在应用程序后面进行清除操作:Cpp代码 38 glDeleteRenderbuffers(1,&m_renderBufferColorMS); 39 glDeleteRenderbuffers(1,&m_renderBufferDepthMS); 40 glDeleteFramebuffers(1,&m_frameBufferMS); 然后在绘制物体的时候进行绑定:Cpp代码 41 glBindFramebuffer(GL_FRAMEBUFFER,m_frameBuffer); 42 GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); 43 if (status != GL_FRAMEBUFFER_COMPLETE) 44 45 cout The frame buffer status is not complete! endl; 46 return; 47 48 49 drawing();/draw something 50 glBindFramebuffer(GL_FRAMEBUFFER,0); 接下来我要用函数glReadPixels读取数据,然后保存为BMP图像。在这里我使用了PBO(像素缓冲区对象)。在这里需要注意的是:不能用glReadPixels直接读取多重采样缓冲区里面的数据,否则会出现GL_INVALID_OPERATION错误。那么应该怎么做呢?一个常用的方法是创建另外一个FBO。它是一个普通的FBO,用于进行传图操作(Blit).创建用于Blit的普通FBO:Cpp代码 51 /创建普通FBO 52 glGenFramebuffers(1,&m_frameBuffer); 53 glBindFramebuffer(GL_FRAMEBUFFER,m_frameBuffer); 54 55 glGenRenderbuffers(1,&m_renderBufferColor); 56 glBindRenderbuffer(GL_RENDERBUFFER,m_renderBufferColor); 57 glRenderbufferStorage(GL_RENDERBUFFER,GL_RGB, 58 m_subImageWidth,m_subImageHeight); 59 glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0, 60 GL_RENDERBUFFER,m_renderBufferColor); 61 62 glGenRenderbuffers(1,&m_renderBufferDepth); 63 glBindRenderbuffer(GL_RENDERBUFFER,m_renderBufferDepth); 64 glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH_COMPONENT, 65 m_subImageWidth,m_subImageHeight); 66 glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT, 67 GL_RENDERBUFFER,m_renderBufferDepth); 68 69 glBindFramebuffer(GL_FRAMEBUFFER,0);/解除绑定 记住也要进行清除操作:Cpp代码 70 glDeleteRenderbuffers(1,&m_renderBufferColor); 71 glDeleteRenderbuffers(1,&m_renderBufferDepth); 72 glDeleteFramebuffers(1,&m_frameBuffer); 然后绑定两个FBO,一个用于读,一个进行写入,进行blit操作:Cpp代码 73 glBindFramebuffer(GL_FRAMEBUFFER,0); 74 75 glBindFramebuffer(GL_READ_FRAMEBUFFER,m_frameBufferMS); 76 status = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER); 77 if (status != GL_FRAMEBUFFER_COMPLETE) 78 79 cout The frame buffer status is not complete! endl; 80 return; 81 82 glBindFramebuffer(GL_DRAW_FRAMEBUFFER,m_frameBuffer); 83 status = glCheckFramebufferStatus(GL_DRAW_FRAM

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论