Я использую контекст OpenGL 3.2 с GLSL 1.5 и по какой-то причине целочисленные атрибуты (типа int, uint, ivecX или uvecX) всегда читаются как 0 в вершинном шейдере. Я объявляю, что они используют:
in int name;
и я связываю атрибуты с помощью glVertexAttribIPointer (обратите внимание на I), а не glVertexAttribPointer (но это тоже не работает). Если я поменяю их на float, они работают отлично - единственное различие в тексте - это тип в структуре вершин, тип в GLSL и вызов функции IPointer вместо простого указателя. Я не получаю никаких ошибок или чего-то еще, они всего лишь 0. Если я нажимаю только целые значения, то отлично работает, а целочисленные униформы работают нормально. Кроме того, встроенные целые числа, такие как gl_VertexID, работают отлично, а обычные пользовательские - нет. Я запускаю ATI Mobility Radeon HD 5870. Я пробовал на другом компьютере с другим графическим процессором (к сожалению, я не уверен, какой графический процессор, но он отличается от моего) с теми же результатами. Любые идеи, почему это может быть так? Спасибо.
EDIT: На самом деле, похоже, что они не 0, скорее, это случайные большие неинициализированные значения... это трудно сказать, поскольку я не могу найти способы отладки шейдеров GLSL. Во всяком случае, еще немного информации. Вот моя структура вершин:
struct TileVertex {
float pos[2];
float uv[2];
float width;
float pad;
int animFrames;
int animFrameLength;
};
animFrames и animFrameLength - это два целочисленных значения, которые я пытаюсь отправить в шейдер. Мой вызов glVertexAttribIPointer для 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 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
EDIT: Спасибо за помощь до сих пор ребята. Поэтому я попытался использовать обратную связь с преобразованием, и теперь все становится понятным. Если я установил значение присваивания int равным 1, в шейдере это будет:
1065353216 = 0x3F800000 = 1.0 in floating point
Если я устанавливаю его в 10, в шейдере я получаю:
1092616192 = 0x41200000 = 10.0 in floating point
Итак, кажется, что атрибут int преобразуется в float, тогда эти биты интерпретируются как int в шейдере, хотя я указываю GL_INT и использую IPointer вместо Pointer! Насколько я понимаю, IPointer должен просто оставить данные в целочисленной форме и не преобразовать их в float.
EDIT:
Вот еще несколько тестов. Для каждого теста я пытаюсь передать целочисленное значение 1 на целочисленный ввод в шейдере:
glVertexAttribIPointer with GL_INT: shader values are 0x3F800000, which is 1.0 in floating point
кажется, указывает, что целое число 1 преобразуется в плавающую точку 1.0, а затем интерпретируется как целое число. Это означает, что OpenGL либо думает, что исходные данные находятся в форме с плавающей точкой (когда она фактически находится в целочисленной форме), либо думает, что входы шейдера являются плавающей точкой (когда они фактически являются ints).
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 конвертировал целые числа в float, возможно, это говорит о том, что они уже были float, чтобы избежать этого, но, по-видимому, нет.
glVertexAttribPointer with GL_INT: same result as glVertexAttribIPointer with GL_INT
это ожидаемый результат. OpenGL преобразует ints в float, а затем передает их в шейдер. Это то, что должно произойти, поскольку я не использовал версию I.
glVertexAttribPointer with GL_FLOAT: integer values 1 (the correct result)
это работает, потому что OpenGL 1) считает исходные данные в форме с плавающей точкой и 2) считает, что входы с шейдером также находятся в форме с плавающей точкой (они на самом деле являются int и int), поэтому поэтому не применяет никакого преобразования, оставляя int как int (или плавать как float, как он думает). Это работает, но кажется очень хакированным и ненадежным, так как я не думаю, что есть гарантия того, что CPU float to GPU float не потребует конверсии (не используют ли некоторые GPU 16-битные поплавки? Возможно, это только предварительный OpenGL 3, но все же) - это просто не на моем GPU.