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

来源:互联网 发布:淘宝66大促报名入口 编辑:程序博客网 时间:2024/05/17 22:55


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


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


// HelloBlitFramebuffer.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <iostream>#include <GL/glew.h>#include <gl/freeglut.h>// -----------------------------------typedef struct{// Handle to a program objectGLuint programObject;// Handle to a framebuffer objectGLuint fbo;// Texture handleGLuint colorTexId[4];// Texture sizeGLsizei 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);// 创建 FBOglGenFramebuffers(1, &userData->fbo);glBindFramebuffer(GL_FRAMEBUFFER, userData->fbo);// 创建4个输出纹理,并绑定到 FBOuserData->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 buffersglDrawBuffers(4, attachments);if (GL_FRAMEBUFFER_COMPLETE != glCheckFramebufferStatus(GL_FRAMEBUFFER)){return FALSE;}// 恢复默认的 framebufferglBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer);return TRUE;}// 初始化 Shader Program,返回 Program IDGLuint InitShaders(const char *vs, const char *fs){GLint vertCompiled, fragCompiled, linked;// ShadersGLint 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);// Debugif (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); // Debugif (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){// Escif (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;}

结果:


0 0
原创粉丝点击