OpenGL: многократное использование буферов обратной связи преобразования перезаписывает уже созданные текстуры

У меня есть рабочая реализация этой методики для отбора усеченного вида геометрии. Суть этой техники в том, что мы используем вершинный шейдер, чтобы проверить, лежат ли границы объекта в пределах усеченного вида, и если они это сделают, мы выводим положение этого объекта, используя буфер обратной связи преобразования и геометрический шейдер, в текстура. Затем мы можем во время фактического прохода рендеринга использовать эту текстуру вместе с запросом о том, сколько позиций мы испустили, чтобы получить релевантные данные о положении для объекта, который мы рендерим, и количество рисований, которое нужно указать в нашем вызове glDrawElementsInstanced., Одно из различий между тем, что я делаю, и тем, что делает статья, состоит в том, что я излучаю текстуру, а не простой вектор позиции, но я сомневаюсь, что это как-то влияет на мою проблему.

Актуальная проблема: в настоящее время у меня есть эта настройка, так что для каждого отображаемого типа объекта (т. Е. Дерева, коробки, камня и т. Д.) Фактический проход визуализации следует сразу же после прохода рендеринга ячейки усеченного конуса. Это работает и дает ожидаемые результаты. Однако вместо этого я хочу выполнить все мои команды отрисовки и выполнить весь выбор усеченного конуса для различных объектов, а только после этого выполнять весь фактический рендеринг, чтобы избежать множества ненужных изменений состояния (т. Е. Переключение назад и далее между шейдерными программами). Однако, когда я делаю это, я сталкиваюсь с проблемой, что ранее созданные текстуры - те, которые я использую для считывания позиций во время фактических проходов рендеринга - все, кажется, перезаписываются последним вызовом функции отбраковки усеченного конуса, то есть все Созданные текстуры, по-видимому, содержат только информацию о положении из последнего вызова Frustum.

Например: я рендерил по порядку 4 дерева, 10 ящиков и 3 камня, и вместо этого я вижу дерево, ящик и камень во всех (трех) позициях, где я ожидал только 3 камня быть. Я не могу понять, почему это так, потому что я достаточно четко связываю новые буферы и текстуры с TRANSFORM_FEEDBACK_BUFFER каждый раз, когда вызываю функцию. Почему ранее использованные текстуры все еще получают новые данные от последнего вызова?

Код, в C, для функции отбраковки усеченного конуса:

void fcullidraw(drawcommand *tar) {
/*    printf("Fculling %s\n", tar->res->name); */
mesh *rmesh = &tar->res->amod->meshes[0];
/*    glDeleteTextures(1, &rmesh->ctex); */
if(rmesh->ctbuf == 0)
    glGenBuffers(1, &rmesh->ctbuf);
glBindBuffer(GL_TEXTURE_BUFFER, rmesh->ctbuf);
glBufferData(GL_TEXTURE_BUFFER, sizeof(instancedata) * tar->nodraws, NULL, GL_DYNAMIC_COPY);
if(rmesh->ctex == 0)
    glGenTextures(1, &rmesh->ctex);
glBindTexture(GL_TEXTURE_BUFFER, rmesh->ctex);
glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, rmesh->ctbuf);

if(rmesh->cquery == 0)
    glGenQueries(1, &rmesh->cquery);

checkactiveshader(tar->tar, findshader("icull"));

glEnable(GL_RASTERIZER_DISCARD);
glUniform1f(activeshader->radius, tar->res->amesh->bbox.radius);
glUniform3fv(activeshader->extent, 1, (const GLfloat*)&tar->res->amesh->bbox.ext);
glUniform3fv(activeshader->cp, 1, (const GLfloat*)&tar->res->amesh->bbox.cp);

glBindVertexArray(tar->res->amod->meshes[0].vao);
glBindBuffer(GL_ARRAY_BUFFER, tar->res->amod->meshes[0].posarray);
glBufferData(GL_ARRAY_BUFFER, sizeof(mat4_t) * tar->nodraws, tar->posarray, GL_DYNAMIC_DRAW);

glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, rmesh->ctbuf);

glBeginTransformFeedback(GL_POINTS);
glBeginQuery(GL_PRIMITIVES_GENERATED, rmesh->cquery);

glDrawArrays(GL_POINTS, 0, tar->nodraws);
glEndQuery(GL_PRIMITIVES_GENERATED);
glEndTransformFeedback();

glDisable(GL_RASTERIZER_DISCARD);
glGetQueryObjectuiv(rmesh->cquery, GL_QUERY_RESULT, &rmesh->visibleinstances);
}

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

Я в тупике. Я чувствую, что текстуры и буферы хорошо определены и четко хранятся отдельно, поэтому я не понимаю, как текстуры из предыдущих обращений к fcullidraw каким-то образом все еще связаны и перезаписываются TransformFeedback, если это действительно то, что происходит, и это конечно, кажется, потому что более ранние объекты будут читаться во всей матрице преобразования камня довольно аккуратно, с "правильным" вращением, переводом и всем остальным.

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

РЕДАКТИРОВАТЬ: я продолжил и обновил свою реализацию с уточнением предложенной здесь оригинальной методики, которая полностью избавляется от метода записи в текстуру, вместо того, чтобы просто записывать в буфер, привязанный к VAO, и установить обновлять один раз для каждого предоставленного экземпляра с помощью VertexAttribDivisor. Этот метод в целом выглядит чище, и, кстати, у него был дополнительный побочный эффект: у меня вообще не было исходной проблемы, так как я больше не пишу и не загружаю текстуры. Таким образом, это больше не практическая проблема для меня, но ответ на теоретический вопрос все еще ускользает от меня, поэтому, если у кого-то есть идеи, я все еще на слуху.

0 ответов

Другие вопросы по тегам