Экземпляры прямоугольника с различными текстурами UV
Я новичок в современных OpenGL VBO/VAO, и я борюсь с одной вещью: я кодировал RectangleAsset на основе этого урока, но я не уверен, как перенести информацию о текстурных UV в RactangleAssetInstance (мои прямоугольники могут иметь разные текстуры).
Нужно ли создавать для него новую VAO, или я могу просто пропустить ультрафиолет? Или добавить второй VBO для ультрафиолетовых лучей? И самое важное: что будет лучшим решением для решения этой проблемы?
struct RectangleAsset {
GLuint VBO;
GLuint VAO;
};
struct RectangleAssetInstance { //this is actually more complex class in my code
RectangleAsset rect; //but tried to extract the most imporatant code
glm::mat4 transform;
Texture * texture;
void UpdateTransform(int,int,int,int);
private:
int x,y,width,height;
};
и функция загрузки RectangleAsset:
void GUIRenderer::init()
{
image = new Program ("vs.glsl", "fs.glsl");
glGenVertexArrays(1, &rect.VAO);
glBindVertexArray(rect.VAO);
glGenBuffers(1, &rect.VBO);
glBindBuffer(GL_ARRAY_BUFFER, rect.VAO);
GLfloat vertexData[] = {
// X Y Z U V
0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
};
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);
glEnableVertexAttribArray(image->attrib("vert"));
glVertexAttribPointer(image->attrib("vert"), 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), NULL);
glEnableVertexAttribArray(image->attrib("vertTexCoord"));
glVertexAttribPointer(image->attrib("vertTexCoord"), 2, GL_FLOAT, GL_TRUE, 5*sizeof(GLfloat), (const GLvoid*)(3 * sizeof(GLfloat)));
glBindVertexArray(0);
}
ПРИМЕЧАНИЕ: я планирую использовать RectangleAssetInstances только в одном месте, в одном std::vector для визуализации GUI (нестатический графический интерфейс). Может быть, будет хорошей идеей объединить все прямоугольники в одном VBO и VAO (и воссоздать его всякий раз, когда UIElement добавляется / удаляется)?
Любые советы, изучающие лучшие практики с OpenGL, приветствуются.
1 ответ
VAO хранят как формат входных данных, так и местоположение, из которого эти входные данные получены. На самом деле это две разные концепции. Если вы хотите изменить источник ультрафиолетовых лучей, вы должны снова вызвать glVertexAttribPointer. Этот вызов будет выглядеть примерно так glVertexAttribPointer(uvLoc, GL_FLOAT, false, sizeof(float) * 5, (const GLvoid*)(sizeof(float) * 3))
Обратите внимание, что это НЕ изменит VBO, из которого поступает информация о вашей позиции.
Теперь вы упомянули, что хотите сделать это, потому что ваши экземпляры прямоугольника могут иметь разные текстуры. Вам не нужно менять UV, чтобы это произошло. В общих положениях, UV и нормали являются частью сетки, и вам нужна только одна их копия. Чтобы изменить текстуру просто позвоните glActiveTexture(GL_TEXTURE0 + i)
с последующим glBindTexture(GL_TEXTURE_2D, tex)
а затем установите единицу сэмплера в своем шейдере, чтобы использовать правильную единицу изображения с glUniform1i(samplerLoc, i)
Существует также расширение ARB_vertex_attrib_binding, которое стало основным в OpenGL 4.3. Это позволяет отделить макет атрибута от местоположения данных. Статья на вики OpenGL содержит информацию о том, как это сделать, но, опять же, вероятно, лучше написать все текстуры для данного меша, используя те же UV.
Что касается вашего вопроса о слиянии всего в одно VAO и VBO: если вам нужны только прямоугольники, то в этом нет необходимости, поскольку вы можете получить любой вид прямоугольника, который вы хотели бы использовать с помощью аффинного преобразования с неоднородным компонентом масштабирования. Таким образом, вам нужен только один VAO и один VBO, и вам не нужно ничего объединять.