Если под «не в непосредственном режиме» вы подразумеваете загрузку вашей геометрии на графическую карту и выполнение вызовов для ее рендеринга, то есть несколько способов сделать это. Простейшим является использование списка отображения для предварительной компиляции списка команд OpenGL для выполнения
Gluint list = glGenLists(1);
// Release with glDeleteLists(list,1);
glNewList(list,GL_COMPILE);
// Drawing code here
glEndList();
Затем отрендерить его с помощью
glCallList(list);
Потенциально более гибкий и быстрый способ заключается в расширении объектов буфера вершин (чтобы получить доступ к расширениям, легко найдите библиотеку GLEW). Вы можете предварительно загрузить свою геометрию в VBO, а затем визуализировать ее с помощью вызовов OpenGL:
float data[2] = {...};
GLuint buffer;
glGenBuffersARB(1,&buffer);
// Release with glDeleteBuffersARB(1,&buffer);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffer);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(data), data, GL_STATIC_DRAW_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
затем нарисуйте что-то вроде
GLuint indices[] = {0};
glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffer);
glVertexPointer(3, GL_FLOAT, sizeof(float)*2, ((GLubyte*)NULL)+0);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawElements(GL_POINTS,sizeof(indices)/(sizeof(indices[0])),GL_UNSIGNED_INT,indices);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
Возможно, вы также захотите поискать с помощью буферов индексов для загрузки индексов (или альтернативных процедур рисования). Боюсь, мне уже поздно вспоминать о различных способах использования буферов вершин и индексов.
Я бы добавил, что если вы просто рисуете одну точку, то большая часть этого не нужна (вам нужно рисовать десятки или сотни тысяч точек, чтобы она была медленной), и она только сделает код труднее читать, понимать и поддерживать.