Почему мне нужно переключить текстурный блок, чтобы мой фрагментный шейдер распознал, какую текстуру использовать? - PullRequest
0 голосов
/ 22 декабря 2011

У меня есть эта программа для простого тестирования.Программа создает две 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);**

Затем программа снова будет работать.

Мой вопрос: почему это происходит?Разве шейдер не зависит от текстурного блока?Разве нам не нужно только передавать текстурный блок в переменную-сэмплер, и все?В этом случае, почему я должен изменить текстурный блок обратно на нулевой блок текстуры, чтобы шейдер снова запустился?Что происходит?

1 Ответ

0 голосов
/ 22 декабря 2011

Я немного беспокоюсь о вашем коде индексации. IIRC, если вы хотите получить точное значение текселя, вы должны ударить его по центру, а не по левому краю. Вы в основном делаете выборку на границах пикселей. Вы хотите сделать что-то более похожее на

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

Я предполагаю, что max_index - это самый высокий действительный индекс в текстуре, а не количество.

Вы используете GL_NEAREST, но сейчас вы производите выборку прямо на границе текселей 3 и 4. Так что вместо этого можно получить тексель 3.

...