渲染世界的OPENGL紋理進階-紋理數組

着色器可以一次性訪問幾個紋理對象,我們可以進一步使用稱爲紋理數組的特性。
在紋理數組上,我們可以將整個數組的紋理圖像綁定到一個紋理對象上,然後在着色器當中對他們進行檢索,這樣就大大增加着色器可用紋理數據的數量。

(1)加載2D紋理數組
紋理數組添加了兩個新的紋理對象作爲大多數紋理管理函數的有效參數:GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_ARRAY。對於這些二維月亮,就像是一般紋理一樣將他們創建和綁定到紋理上,不同的只是在這裏改變了target參數。


    glGenTextures(1, &moonTexture);
    glBindTexture(GL_TEXTURE_2D_ARRAY, moonTexture);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

而且對於2D紋理數組來說,使用glTexImage3D函數:

glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, 64, 64, 30, 0,
        GL_BGRA, GL_UNSIGNED_BYTE, NULL);

參數代表2D圖像切片或數組索引。關於這個方程的使用,一個優點是可以一次性加載整個2D圖像數組。使用這個方程的一個缺點是,需要一次性加載一個2D圖項數組。但是如果我們將最後一個參數設置爲null作爲最後一個參數,OPENGL會保留紋理存儲空間,但是會將他們保持爲未初始化狀態。
然後需要加載其他圖像,每次加載一個。我們設置一個循環,用來根據循環索引爲每個文件創建文件名。並且使用glTexImage3D函數加載圖像。每次加載一個切片。

    for (int i = 0; i < 29; i++) {
        char cFile[32];
        sprintf(cFile, "moon%02d.tga", i);

        GLbyte *pBits;
        int nWidth, nHeight, nComponents;
        GLenum eFormat;

        // Read the texture bits
        pBits = gltReadTGABits(cFile, &nWidth, &nHeight, &nComponents, &eFormat);
        glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, i, nWidth, nHeight, 1, GL_BGRA, GL_UNSIGNED_BYTE, pBits);

        free(pBits);
    }

(2)紋理數組索引
再對月亮進行渲染之前綁定到這個紋理對象上,然後通過一個採樣器來訪問整個月亮圖像數組。我們需要一種方式和着色器進行通信來確定要使用哪個圖像。可以設置一個計時器,隨着秒數的變化而進行循環。再對月亮進行渲染之前,下面的代碼會在頂點着色器中設置恰當的統一值。

    // fTime goes from 0.0 to 28.0 and recycles
    float fTime = timer.GetElapsedSeconds();
    fTime = fmod(fTime, 28.0f);
    glUniform1f(locTimeStamp, fTime);

    moonBatch.Draw();

在着色器中,已經有了一個接受紋理座標的屬性,而我們只要將s和t座標複製到vec3變量的vMoonCoords中就可以了。紋理座標p來自包含經過時間(不要忘記,我們的循環實際上是從0到28)的統一值而第三個紋理座標維度值隨後在片段着色器當中使用。

#version 330
#extension GL_EXT_texture_array: require
in vec4 vVertex;
in vec4 vTexCoords;

uniform mat4 mvpMatrix;#extension GL_EXT_texture_array: require
uniform float fTime;

smooth out vec3 vMoonCoords;

void main(void) 
    { 
    vMoonCoords.st = vTexCoords.st;
    vMoonCoords.p = fTime;

    gl_Position = mvpMatrix * vVertex;
    }

頂點着色器

(3)訪問紋理數組
在片段着色器中,有一個新類型的2D紋理數組採樣器sample2Darray。使用texture2DArray函數對這個紋理進行採樣,並且傳遞一個3分量紋理座標。這個紋理座標的前兩個分量s和t用作典型的二維紋理座標。第三個分量p實際上是紋理數組的一個整形索引。

#version 330
#extension GL_EXT_texture_array: require

out vec4 vFragColor;

uniform sampler2DArray moonImage;

smooth in vec3 vMoonCoords;

void main(void)
   { 
   vFragColor = texture2DArray(moonImage, vMoonCoords);
   }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章