Opengl - экземпляры атрибутов
Я использую oglplus - это оболочка C++ для OpenGL.
У меня проблема с определением экземпляров данных для моего рендерера частиц - позиции работают нормально, но что-то идет не так, когда я хочу скопировать целые числа из того же VBO.
Я собираюсь пропустить некоторые детали реализации, чтобы не усложнять эту проблему. Предположим, что я связываю VAO и VBO перед описанными операциями.
У меня есть массив структур (называемых "частиц"), которые я загружаю так:
glBufferData(GL_ARRAY_BUFFER, sizeof(Particle) * numInstances, newData, GL_DYNAMIC_DRAW);
Определение структуры:
struct Particle
{
float3 position;
//some more attributes, 9 floats in total
//(...)
int fluidID;
};
Я использую вспомогательную функцию для определения атрибутов OpenGL следующим образом:
void addInstancedAttrib(const InstancedAttribDescriptor& attribDesc, GLSLProgram& program, int offset=0)
{
//binding and some implementation details
//(...)
oglplus::VertexArrayAttrib attrib(program, attribDesc.getName().c_str());
attrib.Pointer(attribDesc.getPerVertVals(), attribDesc.getType(), false, sizeof(Particle), (void*)offset);
attrib.Divisor(1);
attrib.Enable();
}
Я добавляю атрибуты для позиций и флюидов, как это:
InstancedAttribDescriptor posDesc(3, "InstanceTranslation", oglplus::DataType::Float);
this->instancedData.addInstancedAttrib(posDesc, this->program);
InstancedAttribDescriptor fluidDesc(1, "FluidID", oglplus::DataType::Int);
this->instancedData.addInstancedAttrib(fluidDesc, this->program, (int)offsetof(Particle,fluidID));
Код вершинного шейдера:
uniform vec3 FluidColors[2];
in vec3 InstanceTranslation;
in vec3 VertexPosition;
in vec3 n;
in int FluidID;
out float lightIntensity;
out vec3 sphereColor;
void main()
{
//some typical MVP transformations
//(...)
sphereColor = FluidColors[FluidID];
gl_Position = projection * vertexPosEye;
}
Этот код в целом производит этот вывод:
Как вы можете видеть, частицы расположены так, как я хотел, а это значит, что свойство "InstanceTranslation" настроено правильно. Группа частиц слева имеет значение FluidID, равное 0, и число справа, равное 1. Второй набор частиц имеет правильные позиции, но неправильно указывается в массиве FluidColors.
Что я знаю:
Это не проблема с тем, как я настроил форму FluidColors. Если я жестко закодирую выделение цвета в шейдере следующим образом:
phereColor = FluidID == 0? FluidColors [0]: FluidColors 1;
Я получил:
- OpenGL возвращает GL_NO_ERROR из glGetError, поэтому нет проблем с перечислениями / значениями, которые я предоставляю
- Это не проблема с смещением макроса. Я пытался использовать жестко закодированные значения, и они тоже не работали.
- Это не проблема совместимости с GLint, я использую простые 32-битные Ints (проверил это с помощью sizeof(int))
- Мне нужно использовать FluidID в качестве экземпляра атрибута, который индексируется в массиве цветов, потому что в противном случае, если бы я установил цвет для группы частиц как простую униформу vec3, мне пришлось бы пакетировать те же типы частиц (с тем же FluidID) сначала вместе, что означает их сортировку, и это будет слишком дорогостоящей операцией.
1 ответ
Мне кажется, это вопрос того, как вы настроили fluidID
указатель атрибута. Так как вы используете тип int
в шейдере вы должны использовать glVertexAttribIPointer()
установить указатель атрибута. Атрибуты, которые вы установили с нормальным glVertexAttribPointer()
Функция работает только для типов атрибутов с плавающей точкой. Они принимают целочисленный ввод, но данные будут преобразованы в плавающие при доступе к ним шейдера.
В oglplus вы, видимо, должны использовать VertexArrayAttrib::IPointer()
вместо VertexArrayAttrib::Pointer()
если вы хотите работать с целочисленными атрибутами.