最简单的 MRTs(Multi Render Targets)的完整代码示例【OpenGL】

网友投稿 649 2022-05-29

MRTs 允许应用程序同时渲染多个颜色缓冲区

话不多言,详细代码和注释如下:

// HelloBlitFramebuffer.cpp : 定义控制台应用程序的入口点。

//

#include "stdafx.h"

#include

#include

#include

// -----------------------------------

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();

}

最简单的 MRTs(Multi Render Targets)的完整代码示例【OpenGL】

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;

}

结果:

OpenGL

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:厦门理工学院2019年数据结构与算法考研初试大纲
下一篇:springboot +nginx +freemarker 模板的简单集成
相关文章