最簡單的 MRTs(Multi Render Targets)的完整代碼示例【OpenGL】

      網友投稿 791 2025-04-02

      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)

      {

      最簡單的 MRTs(Multi Render Targets)的完整代碼示例【OpenGL】

      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;

      }

      結果:

      OpenGL

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:excel表格排序功能使用的教程(excel表格排序操作方法)
      下一篇:IMLOG10(imlog10是什么函數)
      相關文章
      亚洲欧洲精品无码AV| 国产亚洲美女精品久久久久| 亚洲最大av资源站无码av网址| 久久青草亚洲AV无码麻豆| 亚洲国产aⅴ综合网| 国产精品亚洲精品久久精品| 亚洲欧洲无码AV不卡在线| 中国china体内裑精亚洲日本| 亚洲精品国产精品国自产网站| 精品无码一区二区三区亚洲桃色| 亚洲成a人片在线观看中文动漫| 国产l精品国产亚洲区在线观看| 久久亚洲综合色一区二区三区| 亚洲欧洲日产国码无码网站| 亚洲人成色7777在线观看| 亚洲一级片内射网站在线观看| 亚洲一级片内射网站在线观看| 中文字幕一精品亚洲无线一区| 亚洲人成色77777| 亚洲第一精品福利| 亚洲卡一卡2卡三卡4卡无卡三| 亚洲综合久久综合激情久久| 亚洲视频手机在线| 亚洲国产精品一区二区久| 久久亚洲精品专区蓝色区| 亚洲日韩精品无码专区加勒比| 亚洲精品乱码久久久久久蜜桃图片 | 亚洲色欲久久久久综合网| 久久久久亚洲AV成人网| 亚洲色婷婷综合久久| 久久精品国产亚洲av四虎| 亚洲蜜芽在线精品一区| 亚洲精品国产精品国自产网站 | 国产偷v国产偷v亚洲高清| 亚洲国产高清人在线| 亚洲第一永久在线观看| 亚洲狠狠成人综合网| 亚洲AV无码AV日韩AV网站| 亚洲日韩国产成网在线观看| 亚洲国产另类久久久精品小说 | 久久亚洲私人国产精品|