Я новичок в современных 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 для визуализации графического интерфейса (нестатический графический интерфейс). Может быть, будет хорошей идеей объединить все прямоугольники в одном VBO и VAO (и воссоздать его всякий раз, когда UIElement добавляется / удаляется)?
Любые советы, изучающие лучшие практики с OpenGL, приветствуются.
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, и вам не нужно ничего объединять.