Я изучаю OpenGL прямо сейчас, и я хотел бы нарисовать некоторые спрайты на экране из листа спрайтов. Я уверен, если я делаю это правильно, хотя.
Что я хочу сделать, так это построить мир из плиток а-ля Terraria. Это означает, что все плитки, которые строят мой мир, имеют размер 1×1, но мне могут понадобиться такие вещи, как объекты 2×1, 1×2, 2×2 и т. Д.
Что я делаю сейчас, так это то, что у меня есть класс с именем «Tile», который содержит матрицу преобразования плитки и указатель на ее буфер. Очень просто:
Tile::Tile(glm::vec2 position, GLuint* vbo)
{
transformMatrix = glm::translate(transformMatrix, glm::vec3(position, 0.0f));
buffer = vbo;
}
Затем, когда я рисую плитку, я просто связываю буфер и обновляю UV-координаты шейдера и положение вершины. После этого я передаю матрицу преобразования тайла в шейдер и рисую ее, используя glDrawElements:
glEnableVertexAttribArray(positionAttrib);
glEnableVertexAttribArray(textureAttrib);
for(int i = 0; i < 5; i++)
{
glBindBuffer(GL_ARRAY_BUFFER, *tiles[i].buffer);
glVertexAttribPointer(positionAttrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0);
glVertexAttribPointer(textureAttrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (void*)(2 * sizeof(GLfloat)));
glUniformMatrix4fv(transformMatrixLoc, 1, GL_FALSE, value_ptr(tiles[i].transformMatrix));
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0);
}
glDisableVertexAttribArray(positionAttrib);
glDisableVertexAttribArray(textureAttrib);
Могу ли я сделать это более эффективно? Я думал, что мог бы иметь один буфер для тайлов 1×1, один буфер для тайлов 2×1 и т. Д. И т. Д., А затем просто иметь класс Tile, содержащий UVpos и UVsize, а затем просто отправить их в шейдер, но я не уверен, как сделал бы это
Я думаю, что то, что я описал с одним буфером для 1×1 и одним для 2×1, звучит так, как будто это будет намного быстрее.
Могу ли я сделать это более эффективно?
Я не думаю, что вы могли бы сделать это Меньше эффективно. Вы связываете целый буферный объект для каждого четырехугольника. Затем вы загружаете матрицу. За каждый квад.
Способ рисования тайла карты (и только карта, не сущности) обычно работает так, что вы строите буферный объект, который содержит некоторую часть плиток видимого экрана. Пустое пространство отображается как прозрачная плитка. Затем вы оказываете все плитки для этой области экрана, все в одном вызове рисования. Вы предоставляете одну матрицу для всех плиток в этом регионе.
Обычно у вас будет некоторое количество таких видимых областей, чтобы было проще обновлять плитки для этого региона при их изменении. Области, которые выходят за пределы экрана, повторно используются для областей, которые появляются на экране, поэтому вы заполняете их новыми данными плитки.
Других решений пока нет …