Я использую контекст OpenGL 3.2 с GLSL 1.5, и по некоторым причинам целочисленные атрибуты (типа int, uint, ivecX или uvecX) всегда читаются как 0 в вершинном шейдере.Я объявляю их, используя:
in int name;
, и я связываю атрибуты, используя glVertexAttribIPointer (обратите внимание на I), а не glVertexAttribPointer (но это тоже не работает).Если я изменю их на плавающие, они будут работать отлично - единственное отличие кода - это тип в структуре вершин, тип в GLSL и вызов функции IPointer вместо просто Pointer.Я не получаю никаких ошибок или чего-то подобного, они просто равны 0. Если я жестко кодирую целочисленные значения, это работает нормально, а целочисленные формы работают нормально.Кроме того, встроенные целые числа, такие как gl_VertexID, работают отлично, просто пользовательские - нет.Я использую ATI Mobility Radeon HD 5870. Я попробовал на другом компьютере с другим графическим процессором (к сожалению, я не уверен, какой графический процессор, но он отличался от моего) с теми же результатами.Любые идеи, почему это может иметь место?Спасибо.
РЕДАКТИРОВАТЬ: На самом деле похоже, что они не равны 0, скорее всего, они случайные большие неинициализированные значения ... трудно сказать, так как я не могу найти какие-либо способы отладки шейдеров GLSL.Во всяком случае, еще немного информации.Вот моя структура вершин:
struct TileVertex {
float pos[2];
float uv[2];
float width;
float pad;
int animFrames;
int animFrameLength;
};
animFrames и animFrameLength - это два целочисленных значения, которые я пытаюсь отправить в шейдер.Мой призыв к glVertexAttribIPointer for animFrames следующий:
glVertexAttribIPointer( attribute.location, attribute.typeSize, attribute.baseType, (GLsizei)stride, bufferOffset( bufOffset + attribOffset ) );
где:
attribute.location = 1 (as determined by OpenGL)
attribute.typeSize = 1 (since it's a single int, not a vector)
attribute.baseType = 5124, which is GL_INT
stride = 32, which is sizeof( TileVertex )
bufferOffset() converts to a void pointer relative to NULL
bufOffset = 0 (my vertices start at the beginning of the VBO), and
attribOffset = 24, which is the offset of animFrames in the TileVertex struct
РЕДАКТИРОВАТЬ: Спасибо за помощь, ребята.Поэтому я попытался использовать обратную связь с преобразованием, и теперь все становится более понятным.Если я установлю значение int attrib равным 1, в шейдере это будет:
1065353216 = 0x3F800000 = 1.0 in floating point
Если я установлю его на 10, в шейдере я получу:
1092616192 = 0x41200000 = 10.0 in floating point
Так оно и появляетсячто int attrib преобразуется в float, тогда эти биты интерпретируются как int в шейдере, хотя я указываю GL_INT и использую IPointer вместо Pointer!Насколько я понимаю, IPointer должен просто оставлять данные в целочисленной форме, а не преобразовывать их в число с плавающей точкой.
РЕДАКТИРОВАТЬ:
Вот еще несколько тестов.Для каждого теста я пытаюсь передать целочисленное значение 1 на целочисленный ввод в шейдере:
glVertexAttribIPointer with GL_INT: shader values are 0x3F800000, which is 1.0 in floating point
, кажется, указывает, что целое число 1 преобразуется в число с плавающей запятой 1.0, а затем интерпретируется как целое число.Это означает, что OpenGL либо думает, что исходные данные находятся в форме с плавающей запятой (когда они на самом деле находятся в целочисленной форме), либо думает, что входные данные шейдера являются плавающей запятой (когда они на самом деле являются целыми числами).
glVertexAttribIPointer with GL_FLOAT: shader values are valid but weird floating point values, such as 0.0, 1.0, 4.0, 36.0... what the hell!?
понятия не имею, что это значит.Единственное значение, которое я передаю, это целое число 1, поэтому я не могу понять, почему каждое из этих значений будет разным или почему они будут действительными числами с плавающей запятой!Моя логика заключается в том, что если OpenGL конвертирует целые числа в числа с плавающей точкой, возможно, сообщая, что они уже являются числами с плавающей точкой, этого можно избежать, но, очевидно, нет.
glVertexAttribPointer with GL_INT: same result as glVertexAttribIPointer with GL_INT
- это ожидаемый результат.OpenGL преобразует целые числа в плавающие, а затем передает их шейдеру.Это то, что должно произойти, так как я не использовал версию I.
glVertexAttribPointer with GL_FLOAT: integer values 1 (the correct result)
это работает, потому что OpenGL 1) думает, что исходные данные находятся в форме с плавающей запятой, и 2) думает, что входы шейдеров такжев форме с плавающей точкой (на самом деле это int и int), поэтому не применяет никакого преобразования, оставляя int как int (или float как float, как он думает).Это работает, но кажется очень хакерским и ненадежным, поскольку я не думаю, что есть гарантия того, что процесс с плавающей запятой процессора не будет нуждаться в преобразовании (разве некоторые графические процессоры не используют 16-битные операции с плавающей запятой? Может быть, это всего лишь pre-OpenGL 3, новсе еще) - это просто не на моем GPU.