如何将多个显示列表 ID 分配给 OpenGL 中的 GLU 建模?

How do I assign Multiple Display List IDs to GLU Modeling in OpenGL?

我很好奇 OpenGL 如何分配多个显示列表 ID。

目前我有:

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。

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。

这是想要的结果:

如果使用显示列表只分配一个ID,没有问题,但如果分配多个ID,将无法正常工作。

有什么想法吗?

显示列表将一系列 OpenGL 命令和数据组合在一起,以便在初始创建后可以重复执行,以提高程序的性能(有关显示列表的更多信息以及各种代码示例,请参见 here).

请注意,显示列表已在 OpenGL 3.0 中弃用并在 OpenGL 3.1 中删除,这已在此处讨论:Why were display lists deprecated in opengl 3.1?

第二个代码片段中的四个 glu*() 调用创建图形基元,这些图形基元仅存储在四个生成的显示列表之一中,即 listThree。在该显示列表中,球体、圆柱体、圆盘和部分圆盘放置在同一位置,因此会重叠。此外,四个显示列表 ID 变量 listOne, listTwo, listThree, listFour 在函数 MyCreateList() 的范围内是局部的,因此在函数调用后将无法访问它们。

如果程序要从发布的 screenshot 生成结果,则只需要一个形状(用 gluDisk() 生成)和一个显示列表。 (为什么要为该任务使用多个显示列表?)

如果这是一个教育练习,我认为它是关于将变换放入显示列表,以生成显示的倾斜景观,例如像这样(磁盘用 glScalef() 拉伸并用 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;
}


这里是一个修改后的示例,它说明了多个显示列表的使用:

/* $ 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;
}

可以在此处找到所有使用的 GL/GLU 函数的文档:
https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/

可以在此处找到所有使用过的 GLUT 函数的文档:
https://www.opengl.org/resources/libraries/glut/spec3/spec3.html

可以找到有关“旧版 OpenGL”主题的更多信息here