Невозможно получить целочисленные атрибуты вершин, работающие в GLSL 1.5

Я использую контекст OpenGL 3.2 с GLSL 1.5, и по какой-то причине целочисленные атрибуты (типа int, uint, ivecX или uvecX) всегда читаются как 0 в вершинный шейдер. Я объявляю их с помощью:

in int name;

и связываю атрибуты с помощью glVertexAttribIPointer (обратите внимание на I), а не glVertexAttribPointer (но он тоже не работает). Если я заменю их на числа с плавающей запятой, они будут работать отлично - единственное отличие кода - это тип в структуре вершины, тип в GLSL и вызов функции IPointer, а не просто указатель. Я не получаю никаких ошибок или чего-то подобного, они просто все 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 для 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

EDIT: Спасибо за помощь, ребята. Поэтому я попробовал использовать обратную связь с преобразованием, и теперь все обретает смысл. Если я установил значение 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 должен просто оставлять данные в целочисленной форме, а не преобразовывать их в число с плавающей запятой.

EDIT:

Вот еще несколько тестов. Для каждого теста я пытаюсь передать целочисленное значение 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, как он думает). Это работает, но кажется очень хакерским и ненадежным, поскольку я не думаю, что есть гарантия, что преобразование CPU с плавающей запятой в GPU с плавающей запятой не потребует преобразования (разве некоторые графические процессоры не используют 16-битные с плавающей запятой? Может быть, это просто до OpenGL 3, но все еще) - этого просто нет на моем GPU.

16
задан Gumgo 6 July 2011 в 01:45
поделиться