簡體   English   中英

OpenGL:關於使用多個紋理或紋理單元的一些說明

[英]OpenGL: Some clarification on using multiple textures or texture units

我需要在着色器中使用兩個紋理,一個在頂點着色器中,另一個在片段着色器中。 在這兩種情況下,它們在着色器中引用,如uniform sampler2D tex1; uniform sampler2D tex2; 但是,我不確定如何正確使用相關的GL調用。

初始化

首先,我如何創建兩個紋理? 我是否需要使用多個紋理單元

GLuint texIdx[2] = {0, 1};
GLuint texName[2];
Grint  texUniformID[2];

// Initialize first texture
glActiveTexture (GL_TEXTURE0 + texIdx[0]);
glGenTextures   (1, &texName[0]);
glBindTexture   (GL_TEXTURE_2D, texName[0]);
glTexImage2D    (GL_TEXTURE_2D, 0, GL_R32F, xDim0, yDim0, 0, GL_RED, GL_FLOAT, someTextureData);

// Initialize second texture
glActiveTexture (GL_TEXTURE0 + texIdx[1]);
glGenTextures   (1, &texName[1]);
glBindTexture   (GL_TEXTURE_2D, texName[1]);
glTexImage2D    (GL_TEXTURE_2D, 0, GL_RGB, xDim1, yDim1, 0, GL_RGB, GL_FLOAT, someOther1TextureData);

// Set the uniforms to refer to the textures
texUniformID[0] = glGetUniformLocation (myShaderProgram, "tex1");
texUniformID[1] = glGetUniformLocation (myShaderProgram, "tex2");
glUniform1i (texUniformID[0], texIdx[0]);
glUniform1i (texUniformID[1], texIdx[1]);

或者我可以使用單個紋理單元,因為glGenTextures允許我創建多個紋理,有點像:

GLuint texName[2];
Grint  texUniformID[2];

// Activate some texture unit
glActiveTexture (GL_TEXTURE0);

// Generate two textures
glGenTextures (2, texName);

// Initialize first texture
glBindTexture   (GL_TEXTURE_2D, texName[0]);
glTexImage2D    (GL_TEXTURE_2D, 0, GL_R32F, xDim0, yDim0, 0, GL_RED, GL_FLOAT, someTextureData);

// Initialize second texture
glBindTexture   (GL_TEXTURE_2D, texName[1]);
glTexImage2D    (GL_TEXTURE_2D, 0, GL_RGB, xDim1, yDim1, 0, GL_RGB, GL_FLOAT, someOther1TextureData);

// Set the uniforms to refer to the textures
texUniformID[0] = glGetUniformLocation (myShaderProgram, "tex1");
texUniformID[1] = glGetUniformLocation (myShaderProgram, "tex2");
glUniform1i (texUniformID[0], /* what parameter here? */);
glUniform1i (texUniformID[1], /* what parameter here? */);

總而言之,我不明白一方面有多個紋理單元的意義,另一方面是通過調用glGenTextures創建多個紋理的能力,如果我需要多個紋理,那么正確的方法是什么在着色器程序中。

渲染時的用法

作為一個后續問題,如果我用正確的方式初始化了我的多個紋理,那么在調用glDrawElements期間激活兩個紋理以調用活動的調用的正確順序是什么,以及成功更新紋理的調用的正確順序是什么在運行時glTexSubImage2D

跟進問題

現在更進一步,如果我在渲染調用中使用多個不同的着色器程序並且所有這些程序都使用紋理,那么應該如何處理? 每個着色器程序的每個紋理是否應使用唯一的紋理單元?

如果要在一個着色器程序中使用多個二維紋理,則需要將不同的紋理對象綁定到不同的紋理單元。
生成紋理名稱(值)( glGenTextures )或指定紋理圖像( glTexImage2D )時,沒有必要選擇合適的紋理單元( glActiveTexture ),但是紋理必須先綁定到適當的紋理單元通過使用着色器程序繪制對象(網格)。

通過將紋理綁定到紋理單元並將紋理單元的數量設置為均勻變量,實現着色器程序中的紋理采樣器均勻與紋理對象之間的綁定。

制服的值可以由glUniform1i設置

texUniformID[0] = glGetUniformLocation(myShaderProgram, "tex1");
texUniformID[1] = glGetUniformLocation(myShaderProgram, "tex2");
glUniform1i(texUniformID[0], 0);
glUniform1i(texUniformID[1], 1);

或者通過綁定點布局限定符進行着色器:

layout(binding = 0) uniform sampler2D tex1;
layout(binding = 1) uniform sampler2D tex2;

由於綁定點為0和1,因此在使用着色器程序繪制幾何體之前,紋理對象必須綁定到紋理單元0( GL_TEXTURE0 )和1( GL_TEXTURE1 ):

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texName[0]);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texName[1]);

glDrawElements(...);

但是當紋理被“創建”時,沒有必要分別選擇紋理單元0 1:

glGenTextures(2, texName);

// Initialize first texture
glBindTexture(GL_TEXTURE_2D, texName[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, xDim0, yDim0, 0, GL_RED, GL_FLOAT, data1);

// Initialize second texture
glBindTexture(GL_TEXTURE_2D, texName[1]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, xDim1, yDim1, 0, GL_RGB, GL_FLOAT, data2);

當然,您可以在創建紋理之前選擇紋理單元,然后在以后綁定它們是多余的。 但請注意, glGenTextures不會創建紋理對象,它只保留可用於紋理對象的名稱(值)。 glBindTexture第一次將名稱(值)綁定到紋理目標時,將創建紋理。 這意味着如果glBindTexture不存在或者使用現有紋理, glBindTexture創建紋理。 glTexImage2D指定,創建和初始化綁定到當前紋理單元的指定目標的現有紋理對象的圖像:

glGenTextures(2, texName);

// Initialize first texture
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texName[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, xDim0, yDim0, 0, GL_RED, GL_FLOAT, data1);

// Initialize second texture
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texName[1]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, xDim1, yDim1, 0, GL_RGB, GL_FLOAT, data2);

glTexSubImage2D更新當前綁定到當前紋理單元的指定目標的紋理對象的紋理圖像的內容。 你要做的就是綁定紋理對象。

glBindTexture(GL_TEXTURE_2D, texName[0]);
glTexSubImage2D(GL_TEXTURE_2D, ...);

但請注意, glBindTexture將紋理綁定到當前選定的紋理單元,因此如果當前選擇了“錯誤”紋理單元(當前紋理單元是全局狀態),它可能會弄亂紋理對象和紋理單元的組合。 因此選擇合適的紋理單元可能是有意義的。 如果紋理對象仍然綁定到紋理單元,則無需將其綁定到agian:

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texName[0]); // <-- this is possibly unnecessary
glTexSubImage2D(GL_TEXTURE_2D, ...);

當然,不同的着色器程序可以使用相同的綁定點。 但請注意,紋理單元的數量是有限的。 如果你有很多紋理,就不可能將每個紋理對象綁定到不同的紋理單元。 但是,如果你有2個紋理對象和不同的着色器程序,將2個紋理對象綁定到不同的紋理對象並在每個着色器程序中(重新)使用相同的綁定點是很方便的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM