为什么我必须切换纹理单元才能让我的片段着色器识别出要使用的纹理?

时间:2011-12-22 16:26:40

标签: c++ glsl textures fragment-shader multitexturing

我有这个程序用于简单的测试目的。该程序创建两个1-D纹理并将它们传递给着色器。片段着色器非常简单。它只是在第一个纹理的索引4处拉出纹素,并使该纹理像素成为颜色片段:

 #extension GL_EXT_gpu_shader4 : enable

 uniform sampler1D firstTexture;
 uniform sampler1D secondTexture;

 uniform int max_index;

 void main()
 {
     vec4 texel = texture1D( firstTexture, float(4.0) / float(max_index));

     gl_FragColor = texel;
 }

我正在绘制一个正方形,并且在第一个纹理中索引4的纹素包含< 1.0,0.0,0.0,1.0>,其为红色。因此,上面着色器的结果是红色方块。当我创建第二个1-D纹理并将其传递给着色器时,会出现问题。由于某些未知原因,着色器不喜欢它,并且它不再起作用,并且绘制黑色方块而不是红色方块。这是C ++代码:(函数“makeGLTexture”中的代码如下所示)。

// =========================================
// Set up the first 1-D texture.
// =========================================
firstTexture.allocateTexels(10);
firstTexture.fullyPopulateTexture();
glActiveTexture(GL_TEXTURE0);
firstTextureID = firstTexture.makeGLTexture();



// =========================================
// Set up the second 1-D texture.
// =========================================
secondTexture.allocateTexels(10);
secondTexture.fullyPopulateTexture();
glActiveTexture(GL_TEXTURE1);
secondTextureID = secondTexture.makeGLTexture();



// Set up some parameters.
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);



// ========================================
// Create the Shaders and Get Them Running.
// ========================================
#if defined (_WIN32)
const char* vertexShaderSource = textFileRead("Vertex.vs");
const char* fragmentShaderSource = textFileRead("Fragment.fs");
#else
const char* vertexShaderSource = textFileRead("../../Vertex.vs");
const char* fragmentShaderSource = textFileRead("../../Fragment.fs");
#endif

GLuint vertexShader = createShader(vertexShaderSource, GL_VERTEX_SHADER);
GLuint fragmentShader = createShader(fragmentShaderSource, GL_FRAGMENT_SHADER);

GLuint shaderProgram = createProgram(vertexShader, fragmentShader);

if (shaderProgram != 0) glUseProgram(shaderProgram);

delete vertexShaderSource;
delete fragmentShaderSource;



// ===================================================
// Pass the information of the textures to the shader.
// ===================================================

// Pass the texture unit of the first texture to the shaders.
GLuint location = glGetUniformLocation(shaderProgram,"firstTexture");
glUniform1i ( location, 0 );

// Pass the texture unit of the second texture to the shaders.
location = glGetUniformLocation(shaderProgram,"secondTexture");
glUniform1i ( location, 1 );

// Pass the maximum number of texels in the 1D texture.
location = glGetUniformLocation(shaderProgram,"max_index");
glUniform1i ( location, 9 );

纹理绑定完成的是函数“makeGLTexture”。这是里面的代码。

// Define an array that stores the texture's information.
Texel* const texelArray = new Texel[texels.size()];

// Copy information from the vector of texels into the array of texels.
for (unsigned int index = 0; index < texels.size(); index++)
    texelArray[index] = texels[index];



/* ====================
 * Generate the texture.
 * ====================*/

// ID of the texture.
GLuint textureID;

// Generate a texture object ID for this texture.
glGenTextures( 1, &textureID );

// Bind the texture object to the texture identifier.
glBindTexture( GL_TEXTURE_1D, textureID );

// Define the texture image.
glTexImage1D( GL_TEXTURE_1D, 0, GL_RGBA, texels.size(), 0, GL_RGBA, GL_FLOAT, texelArray );

// ===================== //



// Free the memory allocated for the texture array (array of texels).
delete[] texelArray;

// Return the texture ID.
return textureID;

奇特的是,如果我在第二个纹理创建到第一个纹理的纹理单元后立即切换活动纹理单元,则程序再次工作,并绘制一个红色正方形。

/* =========================================
 * Set up the second one-dimensional texture.
 * =========================================*/

...

**glActiveTexture(GL_TEXTURE0);**

然后,程序将再次运行。

我的问题是为什么会发生这种情况?着色器不是独立于纹理单元吗?难道我们不需要将纹理单元传递给sampler变量,就是这样吗?在这种情况下,为什么我必须将纹理单元更改回纹理单元零以使着色器再次运行?发生了什么事?

1 个答案:

答案 0 :(得分:0)

我有点担心你的索引代码。 IIRC如果你想要纹理元素的确切值,你必须在中心而不是左边缘上击中它。你基本上是在像素边界上采样。你想做更像

的事情
 vec4 texel = texture1D( firstTexture, float(4.0 + 0.5) / float(max_index + 1));

我假设max_index是纹理中最高的有效索引,而不是计数。

您正在使用GL_NEAREST,但您现在正在texel 3和texel 4的边界上进行采样。所以它可能会取而代之的是texel 3.