Изменение цвета вершин после их загрузки с помощью VBO

РЕДАКТИРОВАТЬ: Рабочий код Apple, найденный по этой ссылке: http://developer.apple.com/ библиотека/ИОС/# документация/3DDrawing/Концептуальное/OpenGLES_ProgrammingGuide/TechniquesforWorkingwithVertexData/TechniquesforWorkingwithVertexData.html

После создания вершин для фиксированной сетки 200 x 200 квадратов я визуализирую его, отправив вершины на GPU с помощью VBO. Как я могу обновить цвет вершин? Цвет сотен вершин будет меняться часто - каждые несколько кадров.

Я ранее рассматривал проблему, не используя VBO. Я создал массивы вершин и цветов и использовал следующий код для рендеринга вершин. Я изменил цвет вершин, обновив массив triangleColours :

-(void)render {

    glClearColor(clearColor.r, clearColor.g, clearColor.b, clearColor.a);
    glClear(GL_COLOR_BUFFER_BIT);

    [effect prepareToDraw];

    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition, 2,
                          GL_FLOAT, GL_FALSE, 0, triangleVertices);

    glEnableVertexAttribArray(GLKVertexAttribColor);
    glVertexAttribPointer(GLKVertexAttribColor, 4,
                          GL_FLOAT, GL_FALSE, 0, triangleColours);


    glDrawArrays(GL_TRIANGLES, 0, numTriangleVertices);

    glDisableVertexAttribArray(GLKVertexAttribPosition);
    glDisableVertexAttribArray(GLKVertexAttribColor);
}

Хотя приведенный выше код работал, он съел много батареи, поэтому теперь я пытаюсь сделать это с VBOs. Вершины не меняют позиции, поэтому я понимаю, что VBO - хороший выбор для использования, но как насчет изменения цвета вершин?

Это мой текущий код, упрощенный, чтобы нарисовать только один квадрат:

EDIT: How would I update the code below so it uploads only the vertex colours when they change? How should the VBO setup code and the draw code change? How about updating my verticesColours colours array then calling glBufferSubData()?

   //Setup vertices and VBO

   //Vertices for a single square

    const Vertex Vertices[] = {

       //position and colour
        {{-20, -20}, {1, 1, 1, 1}},
        {{-20, -20}, {1, 1, 1, 1}},
        {{-20, -20}, {1, 1, 1, 1}},
        {{-20, -20}, {1, 1, 1, 1}},
    };

    const GLubyte Indices[] = {

        0, 1, 2,
        2, 3, 0,
    };

    numIndices = sizeof(Indices)/sizeof(Indices[0]);

    [EAGLContext setCurrentContext:self.context];

    glEnable(GL_CULL_FACE);

    self.effect = [[GLKBaseEffect alloc] init];

    self.effect.transform.projectionMatrix = GLKMatrix4MakeOrtho(-50.0, 50.0,
                                                                 -50.0, 50.0,
                                                                  0.0, 1.0);


    glGenVertexArraysOES(1, &_vertexArray);
    glBindVertexArrayOES(_vertexArray);

    glGenBuffers(1, &_vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);

    glGenBuffers(1, &_indexBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);

    glEnableVertexAttribArray(GLKVertexAttribPosition);        
    glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *) offsetof(Vertex, Position));
    glEnableVertexAttribArray(GLKVertexAttribColor);
    glVertexAttribPointer(GLKVertexAttribColor, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *) offsetof(Vertex, Color));

    glBindVertexArrayOES(0);


// Render

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {

    glClearColor(0.0, 0.0, 0.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);

    [self.effect prepareToDraw];    

    glBindVertexArrayOES(_vertexArray);   
    glDrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_BYTE, 0);
}
2
nl ja de

1 ответы

Зависит. (Отличное слово, не так ли? Хорошо для всех ситуаций.)

If you truly need to mutate the colors of each vertex in unpredictable ways, every time you draw them, then yes you will need to upload the vertex colors each frame. Putting the vertex positions in their own (static) VBO is a good choice, since that allows you to reuse without uploading every time (system memory <-> GPU memory bandwidth always being a precious commodity), but anything that will have to change, well, will have to change.

Если вы можете вычислить цвет каждой вершины программно, тем не менее, здесь вершинные шейдеры пригодится. (Действительно, для чего они были сделаны!) Надеюсь, цвет каждой вершины является некоторой функцией некоторой комбинации:

  1. Статические данные для вершин. Вы можете загрузить его один раз в VBO и повторное использование.
  2. Переменные данные, глобальные по всему массиву. Вы используете шейдерную форму для этого и просто загружаете их один раз для каждой ничьей.
  3. Возможно, текстуры вершин , если ваша платформа поддерживает это?

Затем вы можете написать вершинный шейдер, который вычисляет цвет с этих входов, и каждый кадр вам нужно будет только обработать шейдерную форму, которая обычно составляет порядка дюжины плавающих чисел.

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

6
добавлено
Лично я пойду за вершинными текстурами. Чтобы выполнять поиск текстур в вершинных шейдерах, вы должны использовать texture2DLod() . См. Раздел 8.7 Функции поиска текстуры спецификаций GLSL ES 2.0: khronos .org/файлы/opengles_shading_language.pdf
добавлено автор keaukraine, источник
Никогда не слышал о вершинных текстурах ; получение текстуры в программе вершин? Кажется, он был добавлен в SM3.
добавлено автор Stefan Hanke, источник
Скажем, я не использую шейдеры и reupload цвета каждого кадра. Нужно ли загружать весь массив цветов сетки, или я могу отправить только цвета вершин, которые изменились?
добавлено автор freeform, источник
Но, возможно, я могу использовать шейдер. Каждая ячейка в сетке может находиться в одном из двух состояний: вкл. И выкл. (Черно-белое). Я поддерживаю эти состояния в массиве. Клетка включена, если включено 2 или 3 соседних ячейки, иначе она выключена. Может ли эта логика обрабатываться в шейдере?
добавлено автор freeform, источник
@sheu Учитывая подход, который вы упомянули, используя шейдер для установки вершинных цветов. Как насчет того, имеет ли вершинный шейдер единый массив цветов возможных цветов и атрибут colorIndex. Можно ли установить colorIndex вне шейдера, когда конкретная вершина должна изменить цвет?
добавлено автор freeform, источник
@dene: вам нужно будет повторно загрузить весь массив цветов; нет выбора и выбора. Ваша конкретная логика будет трудно инкапсулировать в шейдер, хотя, поскольку вызовы шейдера независимы и не обмениваются информацией. Возможно, для этого стоит задать другой вопрос?
добавлено автор sheu, источник
pro.graphon (and gamedev)
pro.graphon (and gamedev)
389 участник(ов)

Обсуждаем стандарты консорциума Khronos: OpenGL, OpenCL и пр., предлагаем различные работы, туторы, интересные материалы по этим стандартам (и помечаем их тегами). Правила чата и инфо по системе тегов – /rules. Реклама только по согласованию с @AlexFails.