欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

基于 QT 的 OpenGL 教程 18 - 反锯齿

最编程 2024-04-29 14:27:16
...
【直播预告】大模型会取代程序员吗?”

对应教程地址:教程

这一节主要讲的是抗锯齿,主要分三种来讲述,教程中已经讲了MSAA的原理这里就不说了。教程中一共提到三种:

第一种是使用框架自带的抗锯齿方法;

第二种是离屏MSAA

第三种是自定义抗锯齿函数;

这里我主要实现前面两种;

第一种在QT中也有对应的方式:

在我们的主窗体函数:MainWindow(继承自QMainWindow)中,直接实例化QSurfaceFormat并直接设置像素的样本个数即可:

代码段如下:

centreimgwidget=new MyGLWidget(centralWidget);
 centreimgwidget->setGeometry(QRect(0, 0, 351, 251));
 QSurfaceFormat format;
 //设置像素采样的样本个数,用于抗锯齿
 format.setSamples(8);//16
 centreimgwidget->setFormat(format);

可见十分简单,调整setSamples函数中的值可以看到不同的渲染效果;

第二种:离屏MSAA,我觉得这里可以简单复述下教程中的内容:

想要实现离屏的MSAA,我们需要添加两个QOpenGLFrameBufferObject实例;其中一个用于多重采样, 一个多重采样的图像包含比普通图像更多的信息 ,所以此时我们的另外一个QOpenGLFrameBufferObject 实例就需要实现降采样;

那么首先我们创建两个FBO,并分别设置其采样值:

   //MultiSampling set to 4 now
        QOpenGLFramebufferObjectFormat muliSampleFormat;
        muliSampleFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
        muliSampleFormat.setMipmap(true);
        muliSampleFormat.setSamples(4);
        muliSampleFormat.setTextureTarget(GL_TEXTURE_2D);
        muliSampleFormat.setInternalTextureFormat(GL_RGBA32F_ARB);

        //fbo=new QOpenGLFramebufferObject(this->width(),this->height(),QOpenGLFramebufferObject::Depth);
        fbo=new QOpenGLFramebufferObject(this->width(),this->height(),muliSampleFormat);

        QOpenGLFramebufferObjectFormat downSampledFormat;
        downSampledFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
        downSampledFormat.setMipmap(true);
        downSampledFormat.setTextureTarget(GL_TEXTURE_2D);
        downSampledFormat.setInternalTextureFormat(GL_RGBA32F_ARB);

        renderfbo=new QOpenGLFramebufferObject(this->width(),this->height(),downSampledFormat);

然后在执行渲染操作的时候,首先绑定多重采样FBO,将内容绘制到多重采样FBO中,然后解绑多重采样FBO。接着绑定降采样FBO,然后使用    QOpenGLFramebufferObject::blitFramebuffer方法,实现位块传送,此时解绑降采样FBo。然后从降采样的FBO中获取textureid,并进行渲染;

具体代码如下:

void MyGLWidget::paintGL()
{
    if(fbo!=nullptr)
    {
        bool result = fbo->bind();
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
      
        //在此进行物体的渲染



        if(result)
        {
            fbo->release();
            renderfbo->bind();
            QOpenGLFramebufferObject::blitFramebuffer(renderfbo,fbo,GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT| GL_STENCIL_BUFFER_BIT,GL_NEAREST);
            renderfbo->release();
            GLuint textureid=renderfbo->texture();

            m_program->bind();
            {
                glActiveTexture(GL_TEXTURE0);
                glBindTexture(GL_TEXTURE_2D, textureid);
                glUniform1i(m_program->uniformLocation("screenTexture"), 0);
                m_vao->bind();
                glDrawArrays(GL_TRIANGLES, 0, 6);
                m_vao->release();

            }
            m_program->release();
        }

    }
   
}

以上,模拟了一次基本流程;

我今天稍微翻看了自己以前的博客,发现其实有不少漏掉或者出错的地方,太惭愧了;

而且本身我写这个博客的初衷是记录下自己的学习过程,因为好多知识平时不用的话,太容易忘记了;当时准备写的时候发现也有别人写类似的博客,

所以我就想着采取现在这种尽量非过程式的方式去组织代码;但是每次教程内容并不一致,导致现在的整个代码,既不像教程中那样,单个知识点看的明明白白,又不是十分的面向对象;o(╥﹏╥)o

博客写到现在已经过去一大半了,其实,后续的有点不想写了,起码不想频繁的更新了,因为我日常用到的集中在前面的章节中,高级光照这些用到的比较少了;所以我想把前面的知识点混合起来做个小项目分支,来展开写;后面的章节,或快或慢的更吧;

最后贴一下源码地址:

提交信息:anti aliasing

推荐阅读