Управление VAO/VBO - изменить все данные VBO

У меня есть VAO с 3 VBO, содержащими модель с вершинами, нормалями и текстурными координатами.

Я намерен довольно часто менять все данные в этих VBO, примерно с частоты обновления от 500 мс до 20 мс. Новая модель, загруженная в VBO, может иметь меньше или больше треугольников, чем предыдущая. Таким образом, размер буфера также изменится.

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

glBindVertexArray(*vao);

if (mesh->HasPositions()) {
    glBindBuffer(GL_ARRAY_BUFFER, vbo_pos);
    glBufferData(
        GL_ARRAY_BUFFER,
        3 * *point_count * sizeof (GLfloat),
        points,
        GL_DYNAMIC_DRAW
        );
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
    glEnableVertexAttribArray(0);
    free(points); // free our temporary memory
}
if (mesh->HasNormals()) {
    glBindBuffer(GL_ARRAY_BUFFER, vbo_norm);
    glBufferData(
        GL_ARRAY_BUFFER,
        3 * *point_count * sizeof (GLfloat),
        normals,
        GL_DYNAMIC_DRAW
        );
    glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, NULL);
    glEnableVertexAttribArray(2);
    free(normals); // free our temporary memory
}
if (mesh->HasTextureCoords(0)) {
    glBindBuffer(GL_ARRAY_BUFFER, vbo_tex);
    glBufferData(
        GL_ARRAY_BUFFER,
        2 * *point_count * sizeof (GLfloat),
        texcoords,
        GL_DYNAMIC_DRAW
        );
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, NULL);
    glEnableVertexAttribArray(1);
    free(texcoords); // free our temporary memory
}

РЕДАКТИРОВАТЬ:

Это текущее решение имеет проблему, заключающуюся в том, что рисунок не такой, каким должен быть.

Если моя первая модель большая (50 Мб), а я загружаю другую, немного меньшего размера (25 Мб), то часть предыдущей модели все еще нарисована.

Если первая модель маленькая (25Мб), а потом я поменял ее на большую (50Мб), то рисунок не меняется (или по крайней мере кажется, что не меняется). Если заряжаю после еще меньшего (216кб) рисунок меняется (но часть еще остается).

Я полагаю, что-то не так с моим управлением VBO?


person user3544665    schedule 18.06.2014    source источник
comment
20 мс на самом деле не так быстро, если только вы не выполняете дисковый ввод-вывод, тогда это может быть неразумно. 20 мс — это 50 Гц (это означает, что это может происходить чуть реже одного раза в каждом кадре, если вы рисуете со скоростью 60 кадров в секунду); 500 мс — это 2 Гц, легко управляемые при любой частоте кадров. В любом случае, в этом решении нет ничего плохого — на самом деле обычной практикой является выделение нового хранилища для вашего буфера каждый раз, когда вы меняете данные, чтобы избежать конвейерной синхронизации для команд, которые все еще используют старые данные; концепция, именуемая отключением буфера. Есть ли что-то конкретное, что вам не нравится в этом дизайне?   -  person Andon M. Coleman    schedule 18.06.2014
comment
Возможно, мне следует на секунду отступить и спросить: вы когда-нибудь повторно использовали старые данные модели? Если да, то вместо повторного использования старого VBO вы можете просто создать несколько VBO, по одному для каждой модели.   -  person Andon M. Coleman    schedule 18.06.2014
comment
@Андон М. Коулман: Разве ему не нужно использовать glBufferData с указателем NULL перед реальным вызовом glBufferData для правильного выполнения осиротения? Что вообще происходит со старыми буферными данными, когда он просто выделяет их снова и снова, никогда не освобождая. Есть ли в OpenGL какой-нибудь волшебный способ справиться с этим?   -  person Elvithari    schedule 18.06.2014
comment
Учитывая, что вы не можете фактически освободить буферную память объекта (используя специальную команду) в OpenGL, это не проблема. Когда вы вызываете glBufferData (...), он выделяет новое хранилище, а также эффективно помещает старое хранилище в список памяти, которую нужно освободить (то же самое относится к таким вещам, как glTexImage2D (...) и т. д.). После того, как ожидающие команды не используют эту старую память, OpenGL может освободить ее. Причина, по которой вы хотели бы передать NULL при потере буфера, заключается в том, что вы собираетесь вызывать glBufferSubData (...) один или несколько раз позже. В этом случае данные настраиваются одновременно с их выделением.   -  person Andon M. Coleman    schedule 18.06.2014
comment
20 мс - это потому, что модель занесена другим компьютером по tcp. но на самом деле с моим текущим решением у меня есть проблема с тем, что тонет, я отредактирую сообщение, чтобы описать эту проблему   -  person user3544665    schedule 18.06.2014
comment
*Я не использую старые данные   -  person user3544665    schedule 18.06.2014


Ответы (1)


хорошо, я нашел проблему

Я обновлял данные vbo в потоке. Я не знал, что это не работает :/

person user3544665    schedule 19.06.2014
comment
На самом деле вы можете, но в зависимости от платформы вам понадобится еще один контекст, а затем используйте flush. - person Volodymyr B.; 19.06.2014