Ich bin neugierig, wie OpenGL mehrere Anzeigelisten-IDs zuweist.
Aktuell habe ich:
void MyCreateList() {
MyListID = glGenLists(1);
glNewList(MyListID, GL_COMPILE);
//gluSphere(qobj, 1.0, 20, 20); //Sphere
//gluCylinder(qobj, 1.0, 0.0, 2.0, 20, 8); //Cylinder
gluDisk(qobj, 0.25, 1.0, 20, 3); //Disk
//gluPartialDisk(qobj, 0.5, 1.0, 26, 13, 0, 180); //PartialDisk
glEndList();
}
=> ID einer Anzeigeliste.
void MyCreateList() {
GLuint listOne, listTwo, listThree, listFour;
listOne = glGenLists(4);
listTwo = listOne + 1;
listThree = listTwo + 1;
listFour = listThree + 1;
glNewList(listThree, GL_COMPILE);
gluSphere(qobj, 1.0, 20, 20); //Sphere
gluCylinder(qobj, 1.0, 0.0, 2.0, 20, 8); //Cylinder
gluDisk(qobj, 0.25, 1.0, 20, 3); //Disk
gluPartialDisk(qobj, 0.5, 1.0, 26, 13, 0, 180); //PartialDisk
glEndList();
}
=> ID mehrerer Anzeigelisten.
Hier ist das gewünschte Ergebnis:
Geben Sie hier die Bildbeschreibung ein
Wenn Sie mithilfe der Anzeigeliste nur eine ID zuweisen, gibt es kein Problem, aber wenn Sie mehr als eine ID zuweisen, funktioniert es nicht.
Irgendwelche Ideen?
Lösung des Problems
Eine Anzeigeliste speichert eine Folge von OpenGL-Befehlen und -Daten in einer Einheit auf der Grafikkarte, sodass sie nach ihrer ursprünglichen Erstellung wiederholt ausgeführt werden kann, ohne dass ineffiziente Datenübertragungen zwischen CPU/RAM und GPU/VRAM mehr erforderlich sind.
(Beachten Sie, dass Anzeigelisten in OpenGL 3.0 veraltet sind und in OpenGL 3.1 entfernt wurden, was hier bereits besprochen wurde: Warum wurden Anzeigelisten in OpenGL 3.1 abgelehnt? )
Die vier glu*()
Aufrufe in Ihrem zweiten Code-Snippet erstellen Grafik-Primitive, die nur in einer der vier generierten Anzeigelisten gespeichert werden, nämlich in listThree
. In dieser Anzeigeliste werden die Kugel, der Zylinder, die Scheibe und die Teilscheibe an derselben Position platziert und überlappen sich daher. Außerdem sind die vier Anzeigelisten-ID-Variablen listOne, listTwo, listThree, listFour
lokal für den Gültigkeitsbereich der Funktion MyCreateList()
, sodass nach dem Funktionsaufruf nicht auf sie zugegriffen werden kann.
Wenn das Programm das Ergebnis aus dem geposteten Screenshot generieren soll, dann wird nur ein Shape (generiert mit gluDisk()
) und eine Anzeigeliste benötigt. (Warum sollten für diese Aufgabe mehrere Anzeigelisten verwendet werden?)
Wenn dies eine pädagogische Übung ist, geht es meiner Meinung nach darum, Transformationen in eine Anzeigeliste einzufügen, um die gezeigte schiefe Scape zu erzeugen, zum Beispiel so (Disk gedehnt mit glScalef()
und gedreht mit glRotatef()
):
/* $ gcc -Wall -pedantic skewed.c -o skewed -lGL -lGLU -lglut &&./skewed */
#include <GL/glut.h>
static GLuint _displayList = 0;
static void _create_display_list(void)
{
GLUquadricObj *qobj = NULL;
_displayList = glGenLists(1);
qobj = gluNewQuadric();
glNewList(_displayList, GL_COMPILE);
glPushMatrix();
glRotatef(30.0f, 0.0f, 0.0f, 1.0f);
glScalef(0.8f, 1.0f, 0.8f);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
gluDisk(qobj, 0.25, 1.0, 20, 3);
glPopMatrix();
glEndList();
gluDeleteQuadric(qobj);
qobj = NULL;
}
static void _reshape(GLint w, GLint h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-1.0f, 1.0f, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
static void _display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glCallList(_displayList);
glFlush();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutCreateWindow("test");
glutDisplayFunc(_display);
glutReshapeFunc(_reshape);
_create_display_list();
glutMainLoop();
return 0;
}

Und hier ein modifiziertes Beispiel, das die Verwendung mehrerer Anzeigelisten veranschaulicht:
/* $ gcc -Wall -pedantic test_gl.c -o test_gl -lGL -lGLU -lglut &&./test_gl */
#include <GL/glut.h>
static GLuint _displayList = 0;
static void _create_display_lists(void)
{
GLUquadricObj *qobj = NULL;
_displayList = glGenLists(4);
/* shapes (white) */
qobj = gluNewQuadric();
glNewList(_displayList + 2, GL_COMPILE);
glPushMatrix();
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glTranslatef(-2.0f, -2.0f, 0.0f);
gluSphere(qobj, 1.0, 20, 20);
glTranslatef(4.0f, 0.0f, 0.0f);
gluCylinder(qobj, 1.0, 0.0, 2.0, 20, 8);
glTranslatef(0.0f, 4.0f, 0.0f);
gluDisk(qobj, 0.25, 1.0, 20, 3);
glTranslatef(-4.0f, 0.0f, 0.0f);
gluPartialDisk(qobj, 0.5, 1.0, 26, 13, 0, 180);
glPopMatrix();
glEndList();
gluDeleteQuadric(qobj);
qobj = NULL;
/* diagonal line (cyan) */
glNewList(_displayList, GL_COMPILE);
glBegin(GL_LINES);
glColor4f(1.0f, 1.0f, 0.0f, 1.0f);
glVertex4f(-3.0f, 3.0f, 0.0f, 1.0f);
glVertex4f(3.0f, 3.0f, 0.0f, 1.0f);
glEnd();
glEndList();
/* horizontal line (yellow) */
glNewList(_displayList + 1, GL_COMPILE);
glBegin(GL_LINES);
glColor4f(0.0f, 1.0f, 1.0f, 1.0f);
glVertex4f(-3.0f, -3.0f, 0.0f, 1.0f);
glVertex4f(3.0f, 3.0f, 0.0f, 1.0f);
glEnd();
glEndList();
/* diagonal line (magenta) */
glNewList(_displayList + 3, GL_COMPILE);
glBegin(GL_LINES);
glColor4f(1.0f, 0.0f, 1.0f, 1.0f);
glVertex4f(-3.0f, 3.0f, 0.0f, 1.0f);
glVertex4f(3.0f, -3.0f, 0.0f, 1.0f);
glEnd();
glEndList();
}
static void _reshape(GLint w, GLint h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-4.0f, 4.0f, -4.0f, 4.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
static void _display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glCallList(_displayList);
glCallList(_displayList + 1);
glCallList(_displayList + 2);
glCallList(_displayList + 3);
glFlush();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutCreateWindow("test");
glutDisplayFunc(_display);
glutReshapeFunc(_reshape);
glLineWidth(5.0f);
glDisable(GL_DEPTH_TEST);
_create_display_lists();
glutMainLoop();
return 0;
}

Die Dokumentation aller verwendeten GL/GLU-Funktionen finden Sie dort:
https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/
Die Dokumentation aller verwendeten GLUT-Funktionen finden Sie dort:
https://www.opengl.org/resources/libraries/glut/spec3/spec3.html
Weitere Informationen zum Thema "Legacy OpenGL" finden Sie hier (Immediate Mode, Matrix Stack Manipulation, Fixed-Function Lighting, Materials etc. wird heute nicht mehr verwendet, ist aber zum Testen, Lernen und Erstellen kleiner Programme gut zu verwenden, die meisten Treiber unterstützen dies immer noch.).