#version 330 core out vec4 FragColor; in vec3 ourColor; in vec2 TexCoord; uniform sampler2D ourTexture; void main() { FragColor = texture(ourTexture, TexCoord); }
在剛才的程序中,關於片段着色器的中我們聲明了一個采樣器(Sampler),一般來講我們需要用glUniform1i()函數進行將紋理對象(數據),從CPU中傳入顯存中的着色器這樣一個過程。但是現實是我們沒有這么做,我們只是在主函數里綁定了目標,就自動傳入到片段着色器里面了。這就是我們忽視的一個概念——紋理單元。
一個紋理的位置值通常稱為一個紋理單元(Texture Unit)。之所以我們沒有去用glUniform1i()函數,是因為一個紋理的默認紋理單元是0,它是默認的激活紋理單元。
如果我們只傳入一個紋理對象,那么倒是不用擔心紋理單元的問題,反正自動傳入,你綁定就好了。但是當有多個紋理對象要傳入的時候,我們必須指定紋理對象,然后再主函數用glUniform1i()函數一個一個對接到着色器內部完畢,否則一切就亂套了。
紋理單元的主要目的是讓我們在着色器中可以使用多於一個的紋理。
使用glUniform1i設置采樣器:
使用glUniform1i()函數作為着色器內部和程序溝通的橋梁需要知道兩件事情,一個是在着色器內部接受信息的對象為位置 (layout)。一個是外界的數據對象。嚴格來講傳入數據本身也不是這個函數做的,這個函數是告訴着色器那個紋理對象對應哪個采樣 器對象。至於傳入這個是沒有函數對應的,就是激活紋理對象,綁定紋理對象,激活下一個紋理對象,綁定下一個對象。就可以告訴計算 機全部了。 glActiveTexture(GL_TEXTURE0); // 在綁定紋理之前先激活紋理單元 glBindTexture(GL_TEXTURE_2D, texture);
渲染之前設置:
ourShader.use(); // 別忘記在激活着色器前先設置uniform! glUniform1i(glGetUniformLocation(ourShader.ID, "texture1"), 0); // 手動設置 ourShader.setInt("texture2", 1); // 或者使用着色器類設置 while(...) { [...] }
渲染過程中:
glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture1); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, texture2); glBindVertexArray(VAO); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); //glBindTexture函數調用會綁定這個紋理到當前激活的紋理單元,紋理單元GL_TEXTURE0默認總是被激活,所以我們在前面的例子 里當我們使用glBindTexture的時候,無需激活任何紋理單元。