美文网首页my-QT专栏
QT+OPenGL十七帧缓冲区(离屏渲染)

QT+OPenGL十七帧缓冲区(离屏渲染)

作者: c之气三段 | 来源:发表于2021-05-01 12:59 被阅读0次

    帧缓冲区((Framebuffer)

    OpenGL允许我们自定义一个可渲染的缓冲区,我们之前渲染的场景是默认的缓冲区,而自定义是另外的缓冲区。这种缓冲区包含自己的颜色缓冲、深度和模板缓冲,也就是我们自己可以定义。在这个缓冲区绘制的场景可以认为是预渲染的,也就是不会看到效果。我们需要进行纹理采样,把场景采样成纹理,然会绘制出纹理达到离屏渲染的目的。

    创建帧缓冲区

    OpenGL原生中

    GLuint fbo;
    glGenFramebuffers(1, &fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    if(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE)
      //绑定成功执行渲染
    glBindFramebuffer(GL_FRAMEBUFFER, 0);//解绑也就是激活默认的缓冲区
    glDeleteFramebuffers(1, &fbo);//删除缓冲对象
    
    GLuint texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 800, 600, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
    
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    //缓冲区和纹理绑定在一起
    glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, 800, 600, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL );
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, texture, 0);
    
    我们用的是qt的封装缓冲区来模拟一个反光镜效果

    我们先绘制一面镜子
    Mirror.h

    #pragma once
    #include "Camera.h"
    class Mirror : protected QOpenGLFunctions_4_3_Core
    {
    public:
        Mirror();
        ~Mirror();
        void init(QOpenGLShaderProgram* shaderProgram);
        void draw(Camera camera,GLuint colorSreen);
    private:
        QOpenGLVertexArrayObject vao;
        QOpenGLBuffer vbo, uvVbo;
        QOpenGLShaderProgram* shaderProgram;
        QMatrix4x4 mvMat;
    };
    

    Mirror.cpp

    #include "stdafx.h"
    #include "Image.h"
    #include "Mirror.h"
    Mirror::Mirror() {}
    Mirror::~Mirror(){}
    void Mirror::init(QOpenGLShaderProgram* shaderProgram) {
        initializeOpenGLFunctions();
        this->shaderProgram = shaderProgram;
        this->shaderProgram->bind();
        GLfloat vertexs[] = {
            -0.5,-0.5,-5.0,
            0.5,-0.5,-5.0,
            0.5,0.5,-5.0,
            -0.5,0.5,-5.0
        };
        GLfloat UV[] = {
            0.0f, 0.0f,
            1.0f, 0.0f,
            1.0f, 1.0f,
            0.0f,1.0f,
        };
        vao.create();
        vbo.create();
        uvVbo.create();
        vao.bind();
        vbo.bind();
        vbo.setUsagePattern(QOpenGLBuffer::StaticDraw);
        vbo.allocate(vertexs,sizeof(vertexs));
        GLuint position = this->shaderProgram->attributeLocation("vPosition");
        this->shaderProgram->setAttributeBuffer(position, GL_FLOAT,0,3,0);
        glEnableVertexAttribArray(position);
        uvVbo.bind();
        uvVbo.setUsagePattern(QOpenGLBuffer::StaticDraw);
        uvVbo.allocate(UV,sizeof(UV));
        GLuint inuv = this->shaderProgram->attributeLocation("inuv");
        this->shaderProgram->setAttributeBuffer(inuv, GL_FLOAT, 0, 2, 0);
        glEnableVertexAttribArray(inuv);
        this->shaderProgram->release();
        vbo.release();
        uvVbo.release();
        vao.release();
    }
    void Mirror::draw(Camera camera, GLuint colorSreen) {
        shaderProgram->bind();
        QMatrix4x4 mMat;
        mMat.translate(camera.viewPoint.x, camera.viewPoint.y, camera.viewPoint.z);
        QMatrix4x4 v;
        v.lookAt(QVector3D(camera.location.x, camera.location.y, camera.location.z),
            QVector3D(camera.viewPoint.x, camera.viewPoint.y, camera.viewPoint.z),
            QVector3D(camera.worldY.x, camera.worldY.y, camera.worldY.z));
        mvMat = v * mMat;
        shaderProgram->setUniformValue("mv_matrix", mvMat);
        glActiveTexture(GL_TEXTURE0 + colorSreen);
        glBindTexture(GL_TEXTURE_2D, colorSreen);
        shaderProgram->setUniformValue("imgTexture", colorSreen);
        vao.bind();
        glDrawArrays(GL_QUADS,0,4);
        vao.release();
        shaderProgram->release();
    }
    

    shader.vs

    #version 430 
    uniform mat4 mv_matrix;
    uniform mat4 proj_matrix;
    out vec2 uv;
    in vec3 vPosition;
    in vec2 inuv;
    void main(void)
    {
    gl_Position=proj_matrix*mv_matrix*vec4(vPosition,1.0);
    uv=inuv;
    }
    

    shader.vs

    #version 430 
    out vec4 color;
    uniform mat4 mv_matrix;
    uniform mat4 proj_matrix;
    in vec2 uv;
    uniform sampler2D imgTexture;
    void main(void) 
    {
    color =texture(imgTexture,uv) ;
    }
    

    使用:
    .h

    QOpenGLFramebufferObject* fbo;
    

    init函数中:

    mirror.init(shader.getShader());
    fbo= new QOpenGLFramebufferObject(width(), height(), QOpenGLFramebufferObject::Depth);
    

    draw函数

      bool result = fbo->bind();
        if (result) {
            glClearColor(1.0, 0.0, 1.0, 1.0);
           glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
           camera.viewPoint.x=-camera.viewPoint.x;//摄像机反向,模拟镜像的效果
           camera.viewPoint.y = -camera.viewPoint.y;
           camera.viewPoint.z = -camera.viewPoint.z;
           sky.draw(camera);//当前缓冲区渲染场景
           ground.draw(camera);
           model.draw(camera);
          GLuint  m_ColorBuffer = fbo->texture();//获取缓冲区的纹理ID
            fbo->release();
            camera.viewPoint.x = -camera.viewPoint.x;//摄像机复原
            camera.viewPoint.y = -camera.viewPoint.y;
            camera.viewPoint.z = -camera.viewPoint.z;
            mirror.draw(camera, m_ColorBuffer);//绘制镜子
        }
    

    因为qt给我们把缓冲区需要的操作都封装在QOpenGLFramebufferObject中了,因此我们可以直接获取绑定的纹理,并且把他贴在矩形上。当然我们为了看到效果是将镜子的位置跟着摄像机的位置一起移动的。而且rbo渲染缓冲区的概念也被封装好了的。

    动态图效果:

    image.gif

    目录

    VSC++2019+QT+OpenGL
    QT+OpenGL一之绘制立方体(三角形图元)
    QT+OpenGL二之纹理贴图
    QT+OpenGL三之矩阵简解
    QT+OpenGL四之相机的移动和旋转
    QT+OpenGL五之绘制不同的模型(vao,vbo机制)
    QT+OpenGL六之天空盒
    QT+OpenGL七之使用EBO
    QT+OPenGL八之模型准备
    QT+OPenGL九之模型解码
    QT+OPenGL十之光照模型
    QT+OPenGL十一之漫反射和镜面反射贴图
    QT+OPenGL十二之定向光
    QT+OPenGL十三之真正的点光源和聚光灯
    QT+OPenGL十四之多光源混合的问题
    QT+OPenGL十五之深度缓冲区
    QT+OPenGL十六之模板缓冲区
    QT+OPenGL十七帧缓冲区(离屏渲染)
    QT+OPenGL十八抗锯齿
    QT+OPenGL十九镜面反射效率调整
    QT+OPenGL二十Gamma校正

    相关文章

      网友评论

        本文标题:QT+OPenGL十七帧缓冲区(离屏渲染)

        本文链接:https://www.haomeiwen.com/subject/amparltx.html