2015-04-19 3 views
0

Я смущен о VBO и современном openGL. В конце этого поста есть прямой вопрос, затем на пути есть пучок. Если у вас есть какой-либо смысл в этом, я был бы благодарен за ответ. И если вы ответите, пожалуйста, рассматривайте меня как завершающего идиота, без какого бы то ни было знания.OpenGl> v3, 2d эффективный рендеринг игры

Итак, моя история такова:

У меня есть игра, которая сверху вниз 2d игры. Я использовал режим immideate для рендеринга 2d спрайтов. Фактические координаты текстуры моих атласов текстуры были статичными и предопределены в отдельном классе. Квадратные координаты были определены в каждом объекте и обновлены по мере продвижения игры. Когда я создавал, я просто привязывал определенную текстуру, называемую glBegin (треугольники), а затем вызывал каждый метод визуализации видимых объектов. Это, в свою очередь, отправило координаты quad и texure в мой класс Renderer, что вызвало вызовы openGl. Затем я очистил текстуру, которая вызывает только glEnd().

Я сделал это для всех разных атласов и в порядке, чтобы получить необходимую глубину.

Но времена действительно меняются. Я хочу перейти к использованию VBO и шейдеров. Я несколько раз пробовал в прошлом, но провалился с ошибкой. Есть всего несколько вещей, которые я не могу найти в google, чтобы дать мне полное представление об этом, и как я могу использовать его для ускорения моей игры.

Я знаю основы. Вместо того, чтобы отправлять всю информацию по шине в gpu каждый вызов рендеринга, я могу просто сохранить все, что мне нужно на этапе инициализации, а затем использовать шейдеры для вычисления конечного результата. Но ...

У меня есть идея для координат текстуры. Они будут статичными, поскольку они никогда не изменятся. Это обеспечило бы сохранение их на графическом процессоре. Но как узнать, какие координаты соответствуют каждому QUAD/TRIANGLE. Я думаю, что вместо четырех поплавков каждый рендерируемый объект в игре может иметь какой-то индекс, который он передает как атрибут вершинному шейдеру. вершинный шейдер использует индекс для поиска четырех координат текстуры в VBO. Является ли это приемлемым решением? Как бы вы реализовали что-то подобное?

Но что касается четырех вершин, я потерян. Они будут постоянно перемещаться. Они будут видимыми, затем исчезнут и т. Д. Это означает, что мой квадратный VBO изменится при каждом вызове рендеринга, а код, который я видел, обновляет VBO довольно уродливо. Я видел что-то вроде:

  • хранить 4 квадратных координаты в массиве.
  • создать флоатбуфер, положить их туда
  • управлять буфером.
  • отправить буфер в VBO

Выглядит довольно дорого для меня. И я не понимаю, как я могу удалить определенную запись (если объект выходит из экрана и т. Д.), И как я могу манипулировать определенной записью (объект перемещается). И если мне нужно обновить VBO таким образом, что каждый вызов рендеринга, какой прирост производительности? Выглядит больше как потеря для меня ...

Также, как я могу отслеживать «глубину» полученного изображения. Я делаю 2d, но с «глубиной» я подразумеваю порядок рендеринга, например. убедившись, что object2 отображается поверх объекта1. Возможно, другой VBO для каждой глубины? Или я должен использовать z-координату для этого и энтузиастов глубины. Неужели последний не даст ударный удар?

Также есть 2-й коэффициент.Я очень уважаю 3d, но я хочу использовать 2d и воспользоваться тем, что теоретически это должно обеспечить лучшую производительность. Однако, из того, что я собрал, это, похоже, не так. В opengl 3+ Кажется, что для того, чтобы я мог сделать 2d, мне нужно сначала перенести его в 3d, так как это то, что происходит в harware. Кажется странным для меня, так как конечный результат на экране 2d. Есть ли способ обойти это, и сохранить GPU работу 2d -> 3d -> 2d?

Другими словами, как я могу изменить эффективности оборудования:

class main{ 

void main(){ 
while(true){ 
Renderer.bind(); 
//call render in all gameObjects 
Renderer.flush(); 
} 
} 
} 

class GameObject{ 

private float X1, X2, Y1, Y2; 
private TexureCoordinate tex; 

render(float dt){ 
//update X1, X2... 
Renderer.render(tex.getX1(), tex.getX2()... X1, X2 ...); 
} 

} 

class Renderer{ 

//called once 
void bind(Texture texture){ 
    texture.bind(); 
    glBegin(GL_TRIANGLES) 

} 

//called "nr of visable objects" times 
void render(texX1, texX2, texY1, texY2, quadX1, quadX2, quadY1, quadY2){ 

glTexCoo2d(texX1, texY1) 
.... 
etc. 
.... 
} 

void flush(){ 
glEnd(); 
} 
} 

В то, что использует современный OpenGL?

ответ

3

Первым и главным важным ключом к пониманию является то, что вершины - это не только позиция. Вершина - это весь набор атрибутов, которые были предварительно заданы в режиме немедленного рисования вызовов перед вызовом glVertex. Если вы измените только один из атрибутов, вы получите совсем другую вершину.

Давайте вернемся из VBOs на мгновение, чтобы получить все данные glBuffer [Sub] и взглянуть на обычные старые вершинные массивы клиентской стороны (примерно до тех пор, пока существует немедленный режим).

Допустим, у вас два массива позиции, которые имеют точно такой же формат, но с разными значениями:

GLfloat quad_pos_a[2][4] = { 
    {1,2}, {2,2}, {2,3}, {1,3} 
}; 

GLfloat quad_pos_b[2][4] = { 
    {5,5}, {10,5}, {10,20}, {5,20} 
}; 

Другие, чем их значения их расположение идентично: Четыре 2-атрибуты элемента в последовательности. Это тривиальное позволяет использовать общую структуру массива координат, соответствие расположения этих двух каре:

GLfloat quad_texc[2][4] = { 
    {0,0},{1,0},{1,1},{0,1} 
}; 

Я думаю, что это должно быть очевидны для вас, как использовать непосредственный режим требует привлечь quad_pos_a и quad_pos_bquad_texc обмена. Если это не очевидно, пришло время его разгадать. Этот ответ пациента и будет ждать, пока вы не сделали ...


Антракт


... с момента ввода геометрических данных в массивах такая очевидная вещь не легкая задача, OpenGL довольно скоро вводит понятие под названием vertex arrays: вы можете указать OpenGL, откуда получить данные вершин, а затем просто указать ему, сколько вершин есть для рисования, или какие вершины чередуются с массивами, учитывая список индексов.

Использование VAs выглядит следующим образом:

glEnableClientState(GL_VERTEX_ARRAY); 
glEnableClientState(GL_TEXTURE_COORD_ARRAY); 

glVertexPointer(
    2 /* = number of elements per attribute */, 
    GL_FLOAT /* type of attribute elements */, 
    0 /* = the byte distance between attributes OR zero if tightly packed */, 
    quad_pos_a); 
glTexCoordPointer(
    2 /* = number of elements per attribute */, 
    GL_FLOAT /* type of attribute elements */, 
    0 /* = the byte distance between attributes OR zero if tightly packed */, 
    quad_texc); 

glDrawArrays(
    GL_QUADS /* what to draw */, 
    0 /* which index to start with */, 
    4 /* how many vertices to process*/); 

или если вы просто хотите, чтобы нарисовать треугольник 0-й, 1-й и 3-й вершины:

GLushort indices[] = {0,1,3}; 
glDrawElements(
    GL_TRIANGLES /* what */, 
    3 /* how many */, 
    GL_UNSIGNED_SHORT /* type of index elements */, 
    indices); 

Теперь основное различие между обычной старой вершиной массивы и VBOs - это то, что VBOs помещают данные в хранилище OpenGL - вот и все. Если вы поняли VA, вы подделываете VBOs. Однако, в отличие от VA, вы не можете легко изменять содержимое VBOs. Разница с шейдерами заключается в том, что уже не определенный тип атрибута предопределен. Вместо этого существуют общие атрибуты вершин, заданные с glEnableVertexAttribArray (вместо glEnableClientState) и glVertexAttribPointer.

Итак, как сохранить накладные расходы на загрузку обновленных данных? Ну, это зависит от того, что вы считаете дорогостоящим: в конечном итоге данные должны перейти на GPU. Таким образом, упаковка его в объединенную передачу данных с буфером данных, вероятно, выгодна, поскольку она экономит накладные расходы для каждого вызова, чтобы разбить каждый вызов glVertex.

+0

Это очень хорошее разъяснение, спасибо. Просто некоторые последующие вопросы: – Jake

+0

Как эффективно изменить свой VBO. Полагаю, мне следует использовать GL_STREAM_DRAW? Если я использую glBufferSubData, как узнать, какие Vertecies заменены, а какие нет? Как стереть весь shabang и загрузить совершенно новый контент? – Jake

+0

И, как насчет глубины. Будут ли рисовать четвероны в том же порядке, что и я, помещаю их в VBO? – Jake

Смежные вопросы