Я пытаюсь передать массив int в фрагментный шейдер с помощью 1D текстуры. Хотя код компилируется и запускается, когда я смотрю на значения текстуры в шейдере, все они равны нулю!
Это код C ++, который я имею после следующих руководств:
GLuint texture;
glGenTextures(1, &texture);
glActiveTexture(GL_TEXTURE0 + 5); // use the 5th since first 4 may be taken
glBindTexture (GL_TEXTURE_1D, texture);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage1D(GL_TEXTURE_1D, 0, GL_RED_INTEGER, myVec.size(), 0,
GL_RED_INTEGER, GL_INT, &myVec[0]);
GLint textureLoc = glGetUniformLocation( program, "myTexture" );
glUniform1i(textureLoc, 5);
И вот как я пытаюсь получить доступ к текстуре в шейдере:
uniform sampler1D myTexture;
int dat = int(texture1D(myTexture, 0.0).r); // 0.0 is just an example
if (dat == 0) { // always true!
Я уверен, что это какая-то тривиальная ошибка с моей стороны, но я просто не могу понять это. К сожалению, я ограничен в использовании GLSL 1.20, поэтому этот синтаксис может показаться устаревшим для некоторых.
Так почему же значения текстуры в шейдере всегда равны нулю?
РЕДАКТИРОВАТЬ:
Если я заменю int на float, у меня все еще будет проблема:
std::vector <float> temp;
// fill temp...
glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage1D(GL_TEXTURE_1D, 0, GL_R32F, temp.size(), 0, GL_R32F, GL_FLOAT, &temp[0]);
// ...
glUniform1f(textureLoc, 5);
На этот раз, просто читая из sampler
кажется, испортить другие текстуры ..
Начать с, GL_RED_INTEGER
неверно для внутреннего формата. я хотел бы использовать GL_R32I
(32-разрядное целое число со знаком), вы также можете использовать GL_R8I
или же GL_R16I
в зависимости от ваших реальных требований к хранению — меньшие типы, как правило, лучше. Кроме того, не используйте sampler1D
для целочисленной текстуры используйте isampler1D
,
Поскольку OpenGL ES не поддерживает преобразование типов данных, когда вы используете функцию передачи пикселей (например, glTexture2D (...)
), вы обычно можете найти оптимальное сочетание формата, внутреннего формата и типа в таблице, если вы просматриваете OpenGL ES документы.
Вы не можете использовать целочисленные текстуры в OpenGL 2.1, если мы вернемся к той же проблеме, что у вас была вчера с UBO. Если вы не можете получить контекст основного профиля в OS X, вы ограничены GLSL 1.2 (OpenGL 2.1). Константы для GL_R32I
, GL_RED_INTEGER
и т. д. будут определены, но они должны создавать GL_INVALID_ENUM
ошибки во время выполнения в реализации OpenGL 2.1 OS X.
Это не означает, что вы не можете упаковать целочисленное значение в стандартную текстуру с фиксированной запятой и вернуть целочисленное значение обратно в шейдер. Если вы используете 8-битный формат для каждого компонента (например, GL_R8
) вы можете хранить значения в диапазоне 0 — 255. В вашем шейдере после поиска текстур (я бы использовал GL_NEAREST
для фильтра текстуры, фильтрация действительно испортит все) вы можете умножить результат с плавающей запятой на 255,0 и бросить в int
, Это далеко не идеально, но мы прекрасно обходились без целочисленных текстур в течение многих лет.
#version 120
uniform sampler1D myTexture;
int dat = (int)(texture1D (myTexture, (idx + 0.5)/(float)textureWidth).r * 255.0);
if (dat == 0) { // not always true!
Предполагает GL_R8
для внутреннего формата используйте 65535.0
за GL_R16
Других решений пока нет …