最简单的 MRTs(Multi Render Targets)的完整代码示例【OpenGL】
【摘要】
MRTs 允许应用程序同时渲染多个颜色缓冲区
话不多言,详细代码和注释如下:
// HelloBlitFramebuffer.cpp : 定义控制台应用程序的入口点。// #include "stdafx.h"#include <iostream>#include <GL/glew.h>#include ...
MRTs 允许应用程序同时渲染多个颜色缓冲区
话不多言,详细代码和注释如下:
-
// HelloBlitFramebuffer.cpp : 定义控制台应用程序的入口点。
-
//
-
-
#include "stdafx.h"
-
#include <iostream>
-
#include <GL/glew.h>
-
#include <gl/freeglut.h>
-
-
// -----------------------------------
-
typedef struct
-
{
-
// Handle to a program object
-
GLuint programObject;
-
-
// Handle to a framebuffer object
-
GLuint fbo;
-
-
// Texture handle
-
GLuint colorTexId[4];
-
-
// Texture size
-
GLsizei textureWidth;
-
GLsizei textureHeight;
-
-
} UserData;
-
-
UserData *userData = NULL;
-
-
const GLenum attachments[4] =
-
{
-
GL_COLOR_ATTACHMENT0,
-
GL_COLOR_ATTACHMENT1,
-
GL_COLOR_ATTACHMENT2,
-
GL_COLOR_ATTACHMENT3
-
};
-
-
#define SCREEN_W 640
-
#define SCREEN_H 640
-
-
///
-
// 初始化 FBO 和 MRTs
-
//
-
int InitFBO()
-
{
-
int i;
-
GLint defaultFramebuffer = 0;
-
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFramebuffer);
-
-
// 创建 FBO
-
glGenFramebuffers(1, &userData->fbo);
-
glBindFramebuffer(GL_FRAMEBUFFER, userData->fbo);
-
-
// 创建4个输出纹理,并绑定到 FBO
-
userData->textureHeight = userData->textureWidth = 400;
-
glGenTextures(4, &userData->colorTexId[0]);
-
for (i = 0; i < 4; ++i)
-
{
-
glBindTexture(GL_TEXTURE_2D, userData->colorTexId[i]);
-
-
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
-
userData->textureWidth, userData->textureHeight,
-
0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
-
-
// 设置过滤模式
-
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-
-
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachments[i],
-
GL_TEXTURE_2D, userData->colorTexId[i], 0);
-
}
-
// 指定待写入的 color buffers
-
glDrawBuffers(4, attachments);
-
-
if (GL_FRAMEBUFFER_COMPLETE != glCheckFramebufferStatus(GL_FRAMEBUFFER))
-
{
-
return FALSE;
-
}
-
-
// 恢复默认的 framebuffer
-
glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer);
-
-
return TRUE;
-
}
-
-
// 初始化 Shader Program,返回 Program ID
-
GLuint InitShaders(const char *vs, const char *fs)
-
{
-
GLint vertCompiled, fragCompiled, linked;
-
-
// Shaders
-
GLint v = glCreateShader(GL_VERTEX_SHADER);
-
GLint f = glCreateShader(GL_FRAGMENT_SHADER);
-
-
glShaderSource(v, 1, &vs, NULL);
-
glShaderSource(f, 1, &fs, NULL);
-
-
glCompileShader(v);
-
glGetShaderiv(v, GL_COMPILE_STATUS, &vertCompiled); // Debug
-
if (vertCompiled != GL_TRUE)
-
{
-
printf("Vertex Shader compied error! \n");
-
}
-
-
glCompileShader(f);
-
glGetShaderiv(f, GL_COMPILE_STATUS, &fragCompiled);
-
if (fragCompiled != GL_TRUE)
-
{
-
printf("Fragment Shader compied error! \n");
-
}
-
-
//Program:
-
GLuint p = glCreateProgram();
-
glAttachShader(p, v);
-
glAttachShader(p, f);
-
-
glLinkProgram(p);
-
glGetProgramiv(p, GL_LINK_STATUS, &linked); // Debug
-
if (linked != GL_TRUE)
-
{
-
printf("Program linked error! \n");
-
}
-
-
return p;
-
}
-
-
///
-
// 初始化 shader 和 program
-
//
-
int Init()
-
{
-
const char vShaderStr[] =
-
//"#version 300 es \n"
-
"#version 330 \n"
-
"layout(location = 0) in vec4 a_position; \n"
-
"void main() \n"
-
"{ \n"
-
" gl_Position = a_position; \n"
-
"} \n";
-
-
const char fShaderStr[] =
-
//"#version 300 es \n"
-
//"precision mediump float; \n"
-
"#version 330 \n"
-
"layout(location = 0) out vec4 fragData0; \n"
-
"layout(location = 1) out vec4 fragData1; \n"
-
"layout(location = 2) out vec4 fragData2; \n"
-
"layout(location = 3) out vec4 fragData3; \n"
-
"void main() \n"
-
"{ \n"
-
" // first buffer will contain red color \n"
-
" fragData0 = vec4 ( 1, 0, 0, 1 ); \n"
-
" \n"
-
" // second buffer will contain green color \n"
-
" fragData1 = vec4 ( 0, 1, 0, 1 ); \n"
-
" \n"
-
" // third buffer will contain blue color \n"
-
" fragData2 = vec4 ( 0, 0, 1, 1 ); \n"
-
" \n"
-
" // fourth buffer will contain gray color \n"
-
" fragData3 = vec4 ( 0.5, 0.5, 0.5, 1 ); \n"
-
"} \n";
-
-
userData->programObject = InitShaders(vShaderStr, fShaderStr);
-
-
InitFBO();
-
-
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
-
-
return TRUE;
-
}
-
-
///
-
// 绘制一个 Quad
-
//
-
void DrawGeometry()
-
{
-
GLfloat vVertices[] = { -1.0f, 1.0f, 0.0f,
-
-1.0f, -1.0f, 0.0f,
-
1.0f, -1.0f, 0.0f,
-
1.0f, 1.0f, 0.0f,
-
};
-
GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
-
-
glViewport(0, 0, SCREEN_W, SCREEN_H);
-
-
glClear(GL_COLOR_BUFFER_BIT);
-
-
glUseProgram(userData->programObject);
-
-
glVertexAttribPointer(0, 3, GL_FLOAT,
-
GL_FALSE, 3 * sizeof(GLfloat), vVertices);
-
glEnableVertexAttribArray(0);
-
-
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
-
}
-
-
///
-
// ☆ 拷贝 MRTs 的输出到屏幕 ☆
-
//
-
void BlitTextures()
-
{
-
// 绑定 FBO,用于读取
-
glBindFramebuffer(GL_READ_FRAMEBUFFER, userData->fbo);
-
-
// 选择一块 color buffer 作为源,拷贝输出到屏幕指定位置
-
glReadBuffer(GL_COLOR_ATTACHMENT0);
-
glBlitFramebuffer(0, 0, userData->textureWidth, userData->textureHeight,
-
0, 0,
-
SCREEN_W / 2, SCREEN_H / 2, // 左下角坐标
-
GL_COLOR_BUFFER_BIT, GL_LINEAR);
-
-
glReadBuffer(GL_COLOR_ATTACHMENT1);
-
glBlitFramebuffer(0, 0, userData->textureWidth, userData->textureHeight,
-
SCREEN_W / 2, 0,
-
SCREEN_W, SCREEN_H / 2, // 右下角坐标
-
GL_COLOR_BUFFER_BIT, GL_LINEAR);
-
-
glReadBuffer(GL_COLOR_ATTACHMENT2);
-
glBlitFramebuffer(0, 0, userData->textureWidth, userData->textureHeight,
-
0, SCREEN_H / 2,
-
SCREEN_W / 2, SCREEN_H, // 左上角坐标
-
GL_COLOR_BUFFER_BIT, GL_LINEAR);
-
-
glReadBuffer(GL_COLOR_ATTACHMENT3);
-
glBlitFramebuffer(0, 0, userData->textureWidth, userData->textureHeight,
-
SCREEN_W / 2, SCREEN_H / 2, // 右上角坐标
-
SCREEN_W, SCREEN_H,
-
GL_COLOR_BUFFER_BIT, GL_LINEAR);
-
}
-
-
///
-
// 清理善后
-
//
-
void ShutDown()
-
{
-
glDeleteTextures(4, userData->colorTexId);
-
-
glDeleteFramebuffers(1, &userData->fbo);
-
-
glDeleteProgram(userData->programObject);
-
}
-
-
// -----------------------------------
-
-
// 键盘响应事件
-
static void ProcessNormalKeys(unsigned char key, int x, int y)
-
{
-
// Esc
-
if (key == 27)
-
{
-
ShutDown();
-
exit(0);
-
}
-
}
-
-
static void Display()
-
{
-
GLint defaultFramebuffer = 0;
-
-
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFramebuffer);
-
-
// 使用 MRTs 输出4种颜色至4块缓冲区
-
glBindFramebuffer(GL_FRAMEBUFFER, userData->fbo);
-
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
glDrawBuffers(4, attachments);
-
DrawGeometry();
-
-
// 恢复默认 framebuffer
-
// 从之前的4块缓冲区中拷贝像素到屏幕指定位置
-
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, defaultFramebuffer);
-
BlitTextures();
-
-
glutSwapBuffers();
-
}
-
-
int main(int argc, char* argv[])
-
{
-
glutInit(&argc, argv);
-
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA /*| GLUT_STENCIL | GLUT_DEPTH*/);
-
glutInitWindowPosition(100, 100);
-
glutInitWindowSize(SCREEN_W, SCREEN_H);
-
glutCreateWindow("Hello BlitFramebuffer !");
-
-
GLenum err = glewInit();
-
if (err != GLEW_OK)
-
{
-
fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
-
exit(-2);
-
}
-
-
userData = new UserData;
-
-
if (!Init())
-
{
-
return GL_FALSE;
-
}
-
-
glutDisplayFunc(Display);
-
glutIdleFunc(&Display);
-
glutKeyboardFunc(ProcessNormalKeys);
-
-
glutMainLoop();
-
-
return 0;
-
}
结果:
文章来源: panda1234lee.blog.csdn.net,作者:panda1234lee,版权归原作者所有,如需转载,请联系作者。
原文链接:panda1234lee.blog.csdn.net/article/details/54287825
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)