1. 程式人生 > >GLSL著色器實現多重紋理與幀緩衝物件(FBO)

GLSL著色器實現多重紋理與幀緩衝物件(FBO)

還記得我前面幾篇部落格上寫的東西都是將紋理直接渲染到螢幕上,就是產生一個和紋理尺寸大小相同的視窗進行渲染,那麼渲染完了就正好完整的顯示了紋理圖案。但是在做數值計算的時候,一般是不需要輸出到螢幕上的,這就是今天我們要用到的幀快取。有了幀快取,我們的輸出不需要是螢幕了,而是直接輸出到幀快取中去。而且幀緩衝區物件的使用還會對程式的效能有一定提升

那麼幀緩衝物件到底是個什麼東西呢?首先幀緩衝區你可以理解為就是一個概念,下面這個圖可以很形象的解釋幀緩衝區的意思。這裡對這個圖解釋一下: 

       

其實真實存放資料的快取就是紋理快取和render快取,FBO就是將紋理快取和render快取整了一個控制代碼關聯起來,對其進行處理,現在理解為啥FBO只是一個概念了。

本篇部落格主要有以下3個技術點:
1:將一個矩陣,這個矩陣儲存著我們需要的數值,有可能就是一系數矩陣或者說權值矩陣,把這個矩陣放入紋理緩衝中,當做紋理來使用。
2:這裡面用到了多重紋理,多重紋理的處理還是比單重的紋理處理的過程複雜的多的。
3:也是本文的重點,就是對幀快取(FBO)的使用。

具體的使用還是要看程式碼吧。

大家在把程式碼貼到自己電腦上會缺少一個savePicture.h這個標頭檔案,這個標頭檔案包含了loadBMP和saveBMP兩個函式,很抱歉,這兩個函式不是我寫的,不方便發到網上,但是這兩個函式都是很簡單的,大家可以自己到網上找到相關的函式來代替。有了這兩個功能,程式就可以跑起來了。

  1. #include "stdafx.h"
  2. #include<windows.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <GL/glew.h>
  6. #include <GL/glut.h>
  7. #include "savePicture.h"
  8. //紋理的編號
  9. static GLuint texture;    //lena影象作為紋理
  10. static GLuint texWeigArr1;  //自己生成的紋理1
  11. static GLuint texWeigArr2;  
    //自己生成的紋理2
  12. static GLuint texOutput;    //產生結果的紋理
  13. static GLuint fb;           //FBO編號
  14. #define printOpenGLError() printOglError(__FILE__, __LINE__)
  15. const GLint imgHeight = 512, imgWidth = 512;  
  16. const GLint imgHeight2 = 256, imgWidth2 = 256;  
  17. static GLfloat   weight_1[imgWidth][imgHeight];    //權值矩陣1
  18. static GLfloat   weight_2[imgHeight2][imgWidth2];   //權值矩陣2
  19. static  GLfloat outPutFb[imgHeight * imgWidth];   //輸出紋理緩衝
  20. static GLubyte  pData[imgHeight * imgWidth];   //儲存最終的影象資料
  21. //頂點著色器
  22. constchar *vShader = {  
  23.     //"#version 110  \n "
  24.     "void main()"
  25.     "{"
  26.         "gl_TexCoord[0] = gl_MultiTexCoord0;"
  27.         "gl_TexCoord[1] = gl_MultiTexCoord1;"
  28.         "gl_TexCoord[2] = gl_MultiTexCoord2;"
  29.         "gl_Position = ftransform();"
  30.     "}"
  31. };  
  32. //片元著色器
  33. constchar *fShader = {  
  34.     //"#version 110          \n "
  35.     "#extension GL_ARB_texture_rectangle : enable  \n"
  36.     "uniform sampler2DRect  LenaTexture;         \n"
  37.     "uniform sampler2DRect  WeightTex1;         \n"
  38.     "uniform sampler2DRect  WeightTex2;         \n"
  39.     "void main()         \n"
  40.     "{          \n"
  41.         "vec2   weig1Pos =  gl_TexCoord[1].st;                  \n "
  42.         "vec2   weig2Pos =  gl_TexCoord[0].st / 2.0;"
  43.         "vec2     pos1 = vec2(gl_TexCoord[0].s,512.0-gl_TexCoord[0].t);"
  44.         "vec4   texColor   =  texture2DRect(LenaTexture,pos1 );         \n"
  45.         "vec4   weight1    =  texture2DRect(WeightTex1, weig1Pos);          \n "
  46.         "vec4   weight2    =  texture2DRect(WeightTex2, weig2Pos);          \n"
  47.         "texColor.yzw = vec3(0.0,0.0,0.0);         \n"
  48.         "weight1.yzw = vec3(0.0,0.0,0.0);         \n"
  49.         "if ( gl_TexCoord[0].s >256.0)"
  50.         "{ gl_FragColor = texColor;     }   \n"
  51.         "else"
  52.         "{gl_FragColor =   weight1 * weight2;   }     \n"
  53.     "}        \n"
  54. };  
  55. //輸出錯誤相關資訊
  56. int printOglError(char *file, int line)  
  57. {  
  58.     GLenum glErr;  
  59.     int retCode = 0;  
  60.     glErr = glGetError();  
  61.     while (glErr != GL_NO_ERROR)  
  62.     {  
  63.         printf("glError in file %s @ line %d: %s\n", file, line, gluErrorString(glErr));  
  64.         retCode = 1;  
  65.         glErr = glGetError();  
  66.     }  
  67.     return retCode;  
  68. }  
  69. //輸出opengl錯誤
  70. void printInfoLog(GLhandleARB obj)  
  71. {  
  72.     int infologLength = 0;  
  73.     int charsWritten = 0;  
  74.     GLcharARB *infoLog;  
  75.     printOpenGLError();  
  76.     glGetObjectParameterivARB(obj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &infologLength);  
  77.     printOpenGLError();  
  78.     if(infologLength > 0)  
  79.     {  
  80.         infoLog = (GLcharARB*)malloc(infologLength);  
  81.         if(infoLog == NULL)  
  82.         {  
  83.             printf("ERROR: Could not allocate InfoLog buffer\n");  
  84.             exit(1);  
  85.         }  
  86.         glGetInfoLogARB(obj,infologLength,&charsWritten,infoLog);  
  87.         printf("InfoLog:\n%s\n\n",infoLog);  
  88.         free(infoLog);  
  89.     }  
  90.     printOpenGLError();  
  91. }  
  92. /************************************************************* 
  93. function name:   initShaders 
  94. input:   1.    const char *vShaderCode,  
  95.             2.     const char *fShaderCode, 
  96. output:  1.    -1   compile error 
  97.              2.    -2    link  error 
  98.              3.      progHandle     
  99. description: 
  100. *****************************************************************/
  101. GLhandleARB initShaders( constchar *vShaderCode, constchar *fShaderCode )     
  102. {  
  103.     GLhandleARB vertHandle, fragHandle, progHandle;   //物件控制代碼
  104.     GLint vertCompiled, fragCompiled;               //狀態值
  105.     GLint linked;  
  106.     //建立頂點著色器物件和片元著色器物件
  107.     vertHandle = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);  
  108.     fragHandle = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);  
  109.     //將原始碼字串載入到著色器中
  110.     glShaderSource( vertHandle, 1, &vShaderCode, NULL );  
  111.     glShaderSource( fragHandle, 1, &fShaderCode, NULL );  
  112.     printf("編譯碼塊頂點著色器並列印編譯器日誌檔案:\n");  
  113.     //編譯碼塊頂點著色器並列印編譯器日誌檔案
  114.     glCompileShaderARB(vertHandle);  
  115.     printOpenGLError();             //檢查opengl錯誤
  116.     glGetObjectParameterivARB(vertHandle,GL_OBJECT_COMPILE_STATUS_ARB, &vertCompiled);  
  117.     printInfoLog(vertHandle);  
  118. 相關推薦

    GLSL著色實現多重紋理緩衝物件FBO

    還記得我前面幾篇部落格上寫的東西都是將紋理直接渲染到螢幕上,就是產生一個和紋理尺寸大小相同的視窗進行渲染,那麼渲染完了就正好完整的顯示了紋理圖案。但是在做數值計算的時候,一般是不需要輸出到螢幕上的,這就是今天我們要用到的幀快取。有了幀快取,我們的輸出不需要是螢幕了,而是直

    OpenGL ES 緩衝物件FBO:Render to texture

    幀緩衝物件FBO 建立幀緩衝物件 紋理附著 渲染緩衝物件附著 渲染到紋理Render to Texture 渲染到深度紋理

    OpenGL快取物件FBO

    幀快取(Frame buffer) 幀快取是螢幕所顯示畫面的一個直接映象,又稱為位對映圖 (Bit Map) 或光柵。幀快取的每一儲存單元對應螢幕上的一個畫素,整個幀快取對應一幀影象。 圖形程式一個重要的目標,就是在螢幕上繪製圖像(或者繪製到離屏的一處快取中)。幀

    WebGL glsl fragment 著色實現紋理動畫: 神祕海洋

    glsl程式碼:this.vshdCode = "precision mediump float;" +"attribute vec3 a_vtx_pos;" +"attribute vec2 a_vtx_uv;"

    glsl著色 光照和紋理計算 有用!

    http://my.oschina.net/sweetdark/blog/214220 以下內容只針對GLSL1.20的版本進行說明的,有些內建的變數在1.20之後,已經被廢棄了。 初次實驗 每個頂點著色器都至少輸出一個裁剪空間的位置座標。光照、紋理座標的生成和其他

    FPGA實現串列埠iic控制器總結1

    在剖析了《深入淺出玩轉FPGA》的串列埠程式碼和IIC控制器程式碼、xilinx官方的xilinx的iic控制器(參見書《FPGACPLD設計工具──Xilinx ISE使用詳解》)、《片上系統設計思想與原始碼分析》一書中帶有wishbone介面的iic控制器後

    Mybatis-generator修改原始碼實現自定義方法,返回List物件

    前兩篇文章我們講了如何獲取原始碼即建立工程、修改原始碼為dao(mapper)層新增一個方法,那麼這一篇,我們來講如何在xml新增這個方法所需要sql 3、實現XML檔案新增Dao(Mapper)層的實現 前面有講過,下圖中的兩個包,分別是管理dao(M

    jsp九大內建物件四大域物件轉載

    一,什麼是內建物件? 在jsp開發中會頻繁使用到一些物件,如ServletContext HttpSession PageContext等.如果每次我們在jsp頁面中需要使用這些物件都要自己親自動手建立就會特別的繁瑣.SUN公司因此在設計jsp時,在jsp頁面載入完畢之後自

    Mybatis-generator修改原始碼實現自定義方法,返回List物件

    上一篇我們講了如何獲取Mybatis-generator的原始碼和建立工程,以及通過main方法來生成XML、實體類、mapper檔案,這一篇我們來講通過修改程式碼來為mapper新增一個方法 2、組合原始碼中的示例,實現Dao(Mapper)層新增一個

    Mybatis-generator修改原始碼實現自定義方法,返回List物件

    Mybatis-generator修改原始碼實現自定義方法,返回Lsit物件——第一篇 本文結合網上的諸多教程,詳細介紹通過修改Mybatis-generator的原始碼, 在自動生成dao層和XML檔案時,新增一個返回List的方法,資料庫使用Mysql

    【Shader特效7】磚頭牆壁紋理和排球紋理片元著色實現

    磚頭牆壁紋理片元著色器實現(Shader特效7) 最近在研究一個使用片元著色器完成牆壁紋理和排球紋理的例子,在這裡進行總結一些演算法和開發過程。我都將我的程式碼放到了我的github上https://github.com/ModestBean/ShaderSam

    GLSL實現多重紋理對映(例子取自glsl橙皮書第10章)

    要實現的是使用GLSL來模擬從太空角度觀測的地球,該例子取自GLSL橙色書第10章。這個例子寫的還是蠻有教學作用的,不過感覺把太多的重點放到了gloss map上面,這不要講的是多重紋理來著嗎。。。總之多學學沒錯。 一、要想實現對地球的模擬,我們可以畫一個球,然後直接使用一

    基於計算著色實現BlendShape三維人臉表情動畫驅動

    為什麼要用計算著色器呢? 因為人臉表情基模型頂點數實在是太多了,而且有不止一個模型,動畫越精細,表情基模型越多,這個時候僅僅用CPU計算顯然是不夠的,所以就開始上GPU了,平行計算。 直接上計算著色器的

    利用virtualbox增強實現本機kali linux的檔案共享macOS

    在Windows平臺,VMware虛擬機器,可以直接實現檔案直接拖拽十分好用。而在macOS平臺,要與virtualbox虛擬機器要實現檔案共享功能,一般要用過VBoxGuestAdditions(客戶端增強包) 總體步驟: 1在kali linux設定中

    OpenGL著色程式解析--紋理貼圖

    背景紋理貼圖意思是將任意型別的圖片貼在3d模型的一個或者多個面上。圖片可以是任意的但通常是一種通用的樣式,比如:磚塊、植物、荒蕪的土地等等,可以提高場景的真實性。比較下面兩幅圖片: 為了實現紋理貼圖我們需要做三件事:將一張貼圖載入到OpenGL中,提供紋理座標和頂點(將紋理對

    Android BLE終端通信——client服務端通信過程以及實現數據通信

    .sh 沒有 indexof 實例 解析 rip listview filter @override Android BLE與終端通信(三)——client與服務端通信過程以及實現數據通信 前面的終究僅僅是小知識點。上不了臺面,也僅僅能算是起

    Go語言實現區塊鏈加密貨幣-Part3交易優化,單機模擬多節點通訊

    交易(二) 在這個系列文章的一開始,我們就提到了,區塊鏈是一個分散式資料庫。不過在之前的文章中,我們選擇性地跳過了“分散式”這個部分,而是將注意力都放到了“資料庫”部分。到目前為止,我們幾乎已經實現了一個區塊鏈資料庫的所有元素。今天,我們將會分析之前跳過的一些機制。而在本篇文章中,我們將

    Go語言實現區塊鏈加密貨幣-Part2交易地址,餘額翻倍漏洞

    準備工作: 安裝依賴包:$ go get golang.org/x/crypto/ripemd160 安裝失敗請檢視:https://blog.csdn.net/ak47000gb/article/details/79561358 交易 交易(transaction)是比特幣

    JVM類載入雙親委派模型

    (7)URLClassLoader類 前面說到,ClassLoader這個頂級父類只是定義好了雙親委派模型的工作機制;但是ClassLoader是個抽象類,無法直接建立物件,所以需要由繼承它的子類完成建立物件的任務。子類需要自己實現findClass方法,並且在例項化時指定parent屬性的值

    JVM類載入雙親委派模型

    (1)動態載入       類載入器是 Java 語言的一個創新,也是 Java 語言流行的重要原因之一。它使得 Java 類可以被動態載入到 Java 虛擬機器中並執行。類載入器從 JDK 1.0 就出現了,最初是為了滿足 Java Applet 的需要