OpenGL 1.1: можно ли освободить память после вызова glNormalPointer ()? - PullRequest
0 голосов
/ 08 ноября 2019

У меня есть какой-то старый код, использующий OpenGL 1.1, который таинственным образом является segfaulting. Единственное, где я могу ошибаться, это то, что я free() массив после предоставления его glNormalPointer. Это разрешено, или OpenGL требует памяти на этом указателе, чтобы остаться? Я предполагал, что данные были скопированы.

double vertices[] = { ... };
double *normals = (double *)malloc(sizeof(vertices));

CalcNormals(vertices, normals, num_vertices);  // Calculate the normal vectors.

GLuint my_display_list = glGenLists(1);
glNewList(my_display_list, GL_COMPILE);
glVertexPointer(3, GL_DOUBLE, 0, vertices);
glNormalPointer(GL_DOUBLE, 0, normals);
glDrawArrays(GL_TRIANGLES, 0, num_vertices);
glEndList();

free(normals); // Is this permitted?

// ...

glCallList(winglist);

РЕДАКТИРОВАТЬ 1: Я заметил несколько ссылок, которые говорят, что glNormalPointer и другие "команды состояния клиента" не могут быть включены в список отображения. Я предполагаю, что в этом случае включение glVertexPointer и glNormalPointer между glNewList и glEndList, вероятно, не причинит вреда, но я мог бы также сместить их вверх, чтобы это произошло до glNewList. Это вызов glDrawArrays, который действительно записывается в списке отображения, верно?

РЕДАКТИРОВАТЬ 2: Я пытался вызвать memset(normals, 0, sizeof(vertices)), чтобы принудительно очистить буфер нормалей перед его освобождением, чтобы сделать использование послеСвободная ситуация более очевидна. Поскольку сцена по-прежнему рисуется правильно, я делаю вывод, что выделенный мною буфер нормалей не используется после вызова glDrawArrays.

1 Ответ

3 голосов
/ 08 ноября 2019

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

Нет, он говорит, что они aren 't включен в список отображения. Что является правдой;это не так.

Но их эффекты могут быть.

gl*Pointer команды сохраняют указатель после того, как их команда выполнит . То есть указатель еще не используется. Он читается только при вызове команды рендеринга с использованием этого указателя в качестве состояния клиента.

Поведение glDraw* вызовов с массивами вершин на стороне клиента определяется в терминах последовательности вызовов glArrayElementвнутри пары glBegin/End, которая сама определяется в виде последовательности вызовов glVertex/Normal/etc, используя значения, считанные из массивов вершин. Списки отображения записывают эти вызовы glVertex/etc в сам список отображения. Таким образом, при записи в список отображения при рендеринге с использованием вершинных массивов на стороне клиента вы записываете содержимое массивов в список отображения.

Вы можете освободить только клиентскую памятьесли вы не попробуете читать с него снова.

...