ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

OpenGL的多重渲染目标(Multiple Render Targets)技术(Qt下实现)

2022-02-24 19:01:39  阅读:330  来源: 互联网

标签:1.0 Qt Render 0.0 TEXTURE 2D texCoord Multiple GL


一直没有找到一个Qt下的MRT的简单实例,通过查阅资料,完成如下例子。
重要参考:https://www.jianshu.com/p/da82d3616cca
欢迎学习交流:https://github.com/986247404/OpenGL-MRT-QT/tree/main
多重渲染目标允许程序同时渲染到多个颜色缓冲,向不同的颜色缓冲中送入渲染结果的不同方面(如不同RGBA 色彩通道的值、深度值等)。不少高级特效渲染时需要使用多重渲染目标技术,例如延迟着色、屏幕空间环境光遮蔽等。下面介绍使用多重渲染目标技术的基本步骤。
(1)首先需要创建一个自定义的帧缓冲,并绑定到此帧缓冲。
(2)接着可以创建并初始化一批纹理,总数量等于要输出的不同渲染结果方面的数量,并且不能超过系统的最大限制数。
(3)然后将这一批纹理一一连接到自定义帧缓冲中的不同颜色附件中。
(4)接着在绘制时正常绘制前调用glDrawBuffers 方法设置要输出的颜色附件。
(5)最后在片元着色器中定义多个输出变量一一对应到要输出的颜色附件。
给FBO添加了4个颜色附件,效果如下:
请添加图片描述
代码如下:
头文件

#ifndef GEOMETRYSHADER_H
#define GEOMETRYSHADER_H
#include <QtWidgets/QWidget>
#include <QOpenGLWidget>
#include <QOpenGLFunctions_4_5_Core>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLBuffer>
#include <QOpenGLTexture>
#include <QOpenGLShader>
#include <QOpenGLShaderProgram>
#include <QTime>
#include <QDebug>
#include <QImage>
#include <QMatrix4x4>
#include <iostream>
#include <vector>
#include <string>
constexpr int ATTACHMENT_NUM = 4;
class CGeometryShader : public QOpenGLWidget, protected QOpenGLFunctions_4_5_Core
{
	Q_OBJECT
public:
	CGeometryShader(QWidget *parent = Q_NULLPTR);
	~CGeometryShader();
	void initFBO();
protected:
	void initializeGL();
	void paintGL();
	void resizeGL(int iWidth, int iHeight);
private:
	GLuint				  VBO;
	GLuint				  VAO;
	GLuint				  EBO;
	GLuint				  m_texture[1];
	QOpenGLShaderProgram* m_pProgram;
	GLuint				  m_fVBO;
	GLuint				  m_fVAO;
	GLuint				  FBO;
	GLuint				  RBO;	
	GLuint				  m_textureFBO[ATTACHMENT_NUM];
	QOpenGLShaderProgram* m_pProgramFBO;
	int					  m_iWidth;
	int					  m_iHeight;
	const GLenum attachments[ATTACHMENT_NUM] = {
			GL_COLOR_ATTACHMENT0,
			GL_COLOR_ATTACHMENT1,
			GL_COLOR_ATTACHMENT2,
			GL_COLOR_ATTACHMENT3
	};
	QImage				  m_image;

};
#endif  //GEOMETRYSHADER_H

代码文件:

#include "GeometryShader.h"

CGeometryShader::CGeometryShader(QWidget *parent)
	: QOpenGLWidget(parent)
	, VBO(0)
	, VAO(0)
	, EBO(0)
	, m_texture{ 0 }
	, m_pProgram(new QOpenGLShaderProgram)
	, m_fVBO(0)
	, m_fVAO(0)
	, FBO(0)
	, RBO(0)
	, m_textureFBO{ 0 }
	, m_pProgramFBO(new QOpenGLShaderProgram)
	, m_iWidth(0)
	, m_iHeight(0)
{
	m_image = QImage("img/1.jpg").convertToFormat(QImage::Format_RGBA8888);
	m_iWidth = m_image.width();
	m_iHeight = m_image.height();
	this->resize(m_iWidth, m_iHeight);
}

CGeometryShader::~CGeometryShader()
{
	glDeleteVertexArrays(1, &VAO);
	glDeleteVertexArrays(1, &m_fVAO);
	glDeleteBuffers(1, &VBO);
	glDeleteBuffers(1, &EBO);
	glDeleteBuffers(1, &m_fVBO);
	glDeleteBuffers(1, &FBO);
	glDeleteBuffers(1, &RBO);
	glDeleteTextures(1, m_texture);
	glDeleteTextures(ATTACHMENT_NUM, m_textureFBO);

	if (m_pProgram)
		delete m_pProgram;
	m_pProgram = nullptr;	
	if (m_pProgramFBO)
		delete m_pProgramFBO;
	m_pProgramFBO = nullptr;
}

void CGeometryShader::initFBO()
{
	// FBO
	glGenFramebuffers(1, &FBO);
	glBindFramebuffer(GL_FRAMEBUFFER, FBO);
	// RBO
	glGenRenderbuffers(1, &RBO);
	glBindRenderbuffer(GL_RENDERBUFFER, RBO);
	glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, m_iWidth, m_iHeight);
	glBindRenderbuffer(GL_RENDERBUFFER, 0);
	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, RBO);
	// texture2D
	glGenTextures(ATTACHMENT_NUM, m_textureFBO);
	for (auto i = 0; i < ATTACHMENT_NUM; ++i)
	{
		glBindTexture(GL_TEXTURE_2D, m_textureFBO[i]);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
		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_RGBA, m_iWidth, m_iHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
		glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachments[i], GL_TEXTURE_2D, m_textureFBO[i], 0);
		glBindTexture(GL_TEXTURE_2D, 0);
	}
	//渲染到 4 个颜色附着上
	glDrawBuffers(ATTACHMENT_NUM, attachments);
	if (GL_FRAMEBUFFER_COMPLETE != glCheckFramebufferStatus(GL_FRAMEBUFFER))
		qDebug() << "GL_FRAMEBUFFER_COMPLETE ERROE !";
	glBindFramebuffer(GL_FRAMEBUFFER, 0);

	QOpenGLShader* m_vertexShader = new QOpenGLShader(QOpenGLShader::Vertex);//顶点着色器
	QOpenGLShader* m_fragmentShader = new QOpenGLShader(QOpenGLShader::Fragment);//片段着色器
	m_vertexShader->compileSourceFile("shader/1.vertex_GeometryShader_fbo.vert");
	m_fragmentShader->compileSourceFile("shader/1.fragment_GeometryShader_fbo.frag");
	m_pProgramFBO->addShader(m_vertexShader);
	m_pProgramFBO->addShader(m_fragmentShader);
	m_pProgramFBO->link();
	GLfloat vertices[] = {
		-1.0f,  1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
		-1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
		 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f,

		-1.0f,  1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
		 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
		 1.0f,  1.0f, 0.0f, 1.0f, 1.0f, 1.0f
	};

	glGenVertexArrays(1, &m_fVAO);
	glBindVertexArray(m_fVAO);
	glGenBuffers(1, &m_fVBO);
	glBindBuffer(GL_ARRAY_BUFFER, m_fVBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (void*)0);
	glEnableVertexAttribArray(1);
	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (void*)(4 * sizeof(float)));
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindVertexArray(0);

	m_pProgramFBO->bind();
	for (int i = 0; i < ATTACHMENT_NUM; ++i)
	{
		glActiveTexture(GL_TEXTURE0 + i);
		glBindTexture(GL_TEXTURE_2D, m_textureFBO[i]);
		QString texture = "s_Texture" + QString::number(i);
		QByteArray temp = texture.toLatin1(); 
		char*  index = temp.data();
		m_pProgramFBO->setUniformValue(index, i);
	}
	m_pProgramFBO->release();
}

void CGeometryShader::initializeGL()
{
	this->initializeOpenGLFunctions();

	QOpenGLShader* vertexShader = new QOpenGLShader(QOpenGLShader::Vertex);//顶点着色器
	QOpenGLShader* fragmentShader = new QOpenGLShader(QOpenGLShader::Fragment);//片段着色器
	vertexShader->compileSourceFile("shader/1.vertex_GeometryShader.vert");
	fragmentShader->compileSourceFile("shader/1.fragment_GeometryShader.frag");
	m_pProgram->addShader(vertexShader);
	m_pProgram->addShader(fragmentShader);
	m_pProgram->link();
	GLfloat vertices[] = {
		-1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
		 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
		 1.0f,  1.0f, 0.0f, 1.0f, 1.0f, 1.0f,
		-1.0f,  1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
	};
	GLuint indices[] = {
		0,1,2,
		0,2,3
	};
	glGenVertexArrays(1, &VAO);
	glBindVertexArray(VAO);
	glGenBuffers(1, &VBO);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
	glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (void*)0);
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (void*)(4 * sizeof(float)));
	glEnableVertexAttribArray(1);
	glGenBuffers(1, &EBO);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
	glBindVertexArray(0);
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

	glGenTextures(1, m_texture);
	glBindTexture(GL_TEXTURE_2D, m_texture[0]);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_iWidth, m_iHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
	glBindTexture(GL_TEXTURE_2D, 0);

	m_pProgram->bind();
	m_pProgram->setUniformValue("s_Texture", 0);
	m_pProgram->release();

	// FBO
	initFBO();
}

void CGeometryShader::paintGL()
{
	glBindFramebuffer(GL_FRAMEBUFFER, FBO);
	//glEnable(GL_DEPTH_TEST); 要关闭

	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
	glViewport(0, 0, m_iWidth, m_iHeight);
	glClear(GL_COLOR_BUFFER_BIT);
	glDrawBuffers(ATTACHMENT_NUM, attachments);
	
	m_pProgram->bind();
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, m_texture[0]);
	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_iWidth, m_iHeight, GL_RGBA, GL_UNSIGNED_BYTE, m_image.bits());
	glBindVertexArray(VAO);
	glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL);//绘制
	glBindTexture(GL_TEXTURE_2D, 0);
	glBindVertexArray(0);
	m_pProgram->release();

	auto fb = context()->defaultFramebufferObject();
	glBindFramebuffer(GL_FRAMEBUFFER, fb);
	glViewport(0, 0, m_iWidth, m_iHeight);
	glClear(GL_COLOR_BUFFER_BIT);

	m_pProgramFBO->bind();
	glBindVertexArray(m_fVAO);
	for (int i = 0; i < ATTACHMENT_NUM; ++i)
	{
		glActiveTexture(GL_TEXTURE0 + i);
		glBindTexture(GL_TEXTURE_2D, m_textureFBO[i]);
	}
	glDrawArrays(GL_TRIANGLES, 0, 6);
	glBindTexture(GL_TEXTURE_2D, 0);
	m_pProgramFBO->release();

}

void CGeometryShader::resizeGL(int iWidth, int iHeight)
{
	glViewport(0, 0, iWidth, iHeight);
}


用到的shader:
1.vertex_GeometryShader.vert和1.vertex_GeometryShader_fbo.vert相同:

#version 450 core
layout(location = 0) in vec4 a_position;
layout(location = 1) in vec2 a_texCoord;
 
out vec2 v_texCoord;

void main()
{
	v_texCoord = a_texCoord;
	gl_Position = a_position;
}

1.fragment_GeometryShader_fbo.frag:

#version 450 core

in vec2 v_texCoord;
layout(location = 0) out vec4 outColor;
uniform sampler2D s_Texture0;
uniform sampler2D s_Texture1;
uniform sampler2D s_Texture2;
uniform sampler2D s_Texture3;
void main()
{
    if(v_texCoord.x < 0.5 && v_texCoord.y < 0.5)
    {
        outColor = texture(s_Texture0, v_texCoord);
    }
    else if(v_texCoord.x > 0.5 && v_texCoord.y < 0.5)
    {
        outColor = texture(s_Texture1, v_texCoord);
    }
    else if(v_texCoord.x < 0.5 && v_texCoord.y > 0.5)
    {
        outColor = texture(s_Texture2, v_texCoord);
    }
    else
    {
        outColor = texture(s_Texture3, v_texCoord);
    }
}

1.fragment_GeometryShader.frag:

#version 450 core
 
in vec2 v_texCoord; 
layout(location = 0) out vec4 outColor0; 
layout(location = 1) out vec4 outColor1; 
layout(location = 2) out vec4 outColor2; 
layout(location = 3) out vec4 outColor3; 
uniform sampler2D s_Texture; 
void main() 
{ 
    vec4 outputColor = texture(s_Texture, v_texCoord); 
    outColor0 = outputColor; 
    outColor1 = vec4(outputColor.r, 0.0, 0.0, 1.0); 
    outColor2 = vec4(0.0, outputColor.g, 0.0, 1.0); 
    outColor3 = vec4(0.0, 0.0, outputColor.b, 1.0); 
} ;

标签:1.0,Qt,Render,0.0,TEXTURE,2D,texCoord,Multiple,GL
来源: https://blog.csdn.net/imv123/article/details/123117672

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有