Display list problem

Hi,

I have run into a problem with colours in a display list and can’t work out what is going on. What happens is this:

  1. Build a display list consisting of data points colour-coded according to elevation.

  2. Plot it (no problem.)

  3. Draw something else (lines) in the same viewport - either in immediate mode or as a display list, the same thing happens either way.

  4. Replot when the user changes the view by dragging the mouse.

  5. All the colours in the display list are lost. The points plot OK, but they are all white. This happens until I regenerate the display list. Then it works again - once - before turning white.

If I just plot the contents of the one display list there is no problem. It is plotting two things in the same window that does it, but I don’t see why the one should affect the other.

Any ideas what would cause this?

Alex

It sounds like your second drawing routine changes some state and does not set it back to the original state that’s expected by your first display list.

Do you draw one list with lighting and the other without lighting? Perhaps you enable/disable color material in one of the lists, and forget to change it back?

It does sound a bit like that, but I’m not doing much changing of states - …not intentionally, anyway. I’m just plotting some points, then some lines, and there is no lighting, no textures, nothing complex. I’m drawing points and lines, and using things like glColor3f, glEnable GL_DEPTH_TEST, glShadeModel GL_FLAT. It’s all fairly standard stuff.

Except that it doesn’t work properly.

(The only thing that is significantly different from things I have done before is that there are two viewports, and I am using wglMakeCurrent to switch between them. That shouldn’t cause a problem, though, and I’m not sure that is what is doing it.)

Originally posted by alex_2007:
(The only thing that is significantly different from things I have done before is that there are two viewports, and I am using wglMakeCurrent to switch between them. That shouldn’t cause a problem, though, and I’m not sure that is what is doing it.)
Viewports are not context sensitive at the opposite of windows or threads. So you need to call the appropriate viewport before rendering to the effective one.

glViewport (...) // vp 1
// draw
glViewport (...) // vp 2
// draw

Are you using wglShareLists (or the appropriate function for your platform if it is not windows) to share the display lists between the two contexts you are using? They are not shared by default.

If not, call it after you create the second context and share it with the first, before any lists are created.

It’s not wglShareLists. (I am using Windows, btw.) Different display lists are used in the two viewports. One viewport shows a subset, while the other is an overview of the whole thing, so it isn’t just a case of showing the same data from different angles, and nothing is shared between the two viewports.

I’d dump the frame with GLIntercept then read through to be sure the state isn’t changed, or worse just left in an unexpected state.

Its a good way to test that your color data is what you think it is when you send it to glColor__.

Hope that helps.

Hello again and thanks for the suggestions. This problem is still unsolved but I have been doing some testing and have narrowed down the source of the problem.

I have created a new, simpler application from scratch for troubleshooting purposes. It has got two viewports, each one displaying the same thing: 100,000 points, randomly distributed within the volume of a cube, with lines outlining the cube. The two viewports have separate display lists. Each cube can be rotated independently using the mouse. When this happens the display is refreshed using glCallList.

The cube is outlined in blue (with 12 lines along the edges.) When I made the points in the cube all the same colour (red for one, green for the other) there was no problem. Both cubes could be rotated and the colours were fine. However, as soon as I assigned a unique colour to each point everything turned blue the second time the display list was executed. For some reason the points did not retain their colours and inherited the blue from the lines that were plotted previously.

The difference is whether glColor3f goes inside or outside the loop when creating the display list as in the following two examples.

The first method works. The colour is set OUTSIDE the loop:

glNewList Subset(i).ListNumber, GL_COMPILE ’ compile display list
If i = 0 Then ’ left viewport
glColor3f 1, 0, 0 ’ red
Else ’ right viewport
glColor3f 0, 1, 0 ’ green
End If
glBegin GL_POINTS
For j& = 1 To lngNumPoints& ’ each of 100,000 points in array
With PointsList(j&)
glVertex3f .x, .y, .z ’ add vertex
End With
Next j&
glEnd
glEndList

The second method doesn’t work. The colour is set INSIDE the loop:

glNewList Subset(i).ListNumber, GL_COMPILE ’ compile display list
glBegin GL_POINTS
For j& = 1 To lngNumPoints& ’ each of 100,000 points in array
If i = 0 Then ’ left viewport
glColor3f 1, 0, 0 ’ red
Else ’ right viewport
glColor3f 0, 1, 0 ’ green
End If
With PointsList(j&)
glVertex3f .x, .y, .z ’ add vertex
End With
Next j&
glEnd
glEndList

(Language is Visual Basic. i is the index number for the viewport (0 or 1.) Properties for the viewports, including the display list numbers, are stored in a two-element array. I used indents in the code examples but they don’t seem to come through here.)

Can anyone explain what is going on here? I don’t understand it.

Just to confirm… if you comment out the portion of the second drawing method where it is creating the display list, and call that same method for immediately mode rendering - then it works as you expect?

I haven’t tried immediate mode rendering for the cube recently. I will test that and see what the effect is.

(btw, this problem does not relate to having more than one viewport, although previously I was presuming that it did. I have cut the application down even more. It only has one viewport and is about as simple as it can be, but the same thing happens.)

I have tried using immediate mode and it works. The problem relates to the display list. For some reason the display list doesn’t seem to like having glColor3f calls for each point, and would rather ignore them.

Display list is compiled like this:

glNewList DisplayListNumber, GL_COMPILE
__Call DrawCube
glEndList

Where the DrawCube function is like this:

Private Sub DrawCube()
__Dim j as Long
__glBegin GL_POINTS
____For j = 1 To lngNumPoints ’ each of 100,000 points
______glColor3f 1, 0, 0 ’ red
______With PointsList(j)
________glVertex3f .x, .y, .z
______End With
____Next j
__glEnd
End Sub

And the scene is rendered like this (in its simplest form, skipping any rotations):

glClear GL_COLOR_BUFFER_BIT Or GL_DEPTH_BUFFER_BIT
glCallList DisplayListNumber ’ draw points in red
Call DrawOutline ’ draw lines in blue
SwapBuffers pic.hDC ’ double buffering

The above method uses the display list, and doesn’t work properly since the colour is set for each point. If I bypass the display list by replacing the line “glCallList DisplayListNumber” with “Call DrawCube” then it works as it should.

Can you post the part of your code (or just explain) where you call glGenLists and glDeleteLists? Also, how do you set up or reset the state for drawing - lighting, texturing, etc. even if you aren’t using those pipeline features.

glGenLists and glDeleteLists are not used, since there is only one display list, which is created at the beginning and remains until the end. DisplayListNumber is a constant, 1. Previously where there were two viewports the display list numbers were 1 and 2.

The main ‘setup’ part is as follows, and is run on startup:

Private Sub StartOpenGL() ’ called when window displayed

’ Select the pixel format
SetupPixelFormat pic.hDC

’ Create the rendering context and make it current
hGLRC& = wglCreateContext(pic.hDC)
wglMakeCurrent pic.hDC, hGLRC&

End Sub

Private Sub SetupPixelFormat(ByVal lhDC As Long) ’ to set pixel format

Dim pfd As PIXELFORMATDESCRIPTOR
Dim PixelFormat As Integer

’ Initialize pixel format
pfd.nSize = Len(pfd)
pfd.nVersion = 1
pfd.dwFlags = PFD_SUPPORT_OPENGL Or PFD_DRAW_TO_WINDOW Or PFD_DOUBLEBUFFER Or PFD_TYPE_RGBA
pfd.iPixelType = PFD_TYPE_RGBA
pfd.cColorBits = 16
pfd.cDepthBits = 16
pfd.iLayerType = PFD_MAIN_PLANE

’ Choose a pixel format that best matches that described in pfd
PixelFormat = ChoosePixelFormat(lhDC, pfd)
If PixelFormat = 0 Then MsgBox “Could not retrieve pixel format!”

’ Set the pixel format for the device context
SetPixelFormat lhDC, PixelFormat, pfd

End Sub

The view is initialised at the beginning as well. It is done like this:

Private Sub InitView()

With pic
    glViewport 0, 0, .ScaleWidth, .ScaleHeight
    glMatrixMode GL_PROJECTION
    glLoadIdentity
    gluPerspective 28, .ScaleWidth / .ScaleHeight, 50, 100000 ' ?
End With

' Position the camera...
glMatrixMode GL_MODELVIEW
glLoadIdentity
gluLookAt 0, 0, 5000, _
    0, 0, 0, _
    0, 1, 0 ' looking down (up vector is the y axis)

End Sub

With the bits that I posted above, that’s really about it as far as OpenGL functions go.

I’ve never written a display list without using OpenGL to generate and reserve the integer ID of the display list. That may be because I’ve always needed a lot more than a couple lists. I’m not sure if it is required or not. The reference uses the word “can” instead of “must” but I’ve never seen it done any other way. Then again that part of the reference was written before the PNG spec’s “can, should, must” naming convention era.

I’m assuming you tried using glGenLists(1) just to rule that problem out after my last post.

Outside of your list creation, perhaps before each call to display the compiled list, you may want to call glIsList to validate that OpenGL is still recognizing your list name integer ID as valid (GL_TRUE).

Not it, I’m afraid… I have added a couple of lines :-

Before calling glNewList:
DisplayListNumber = glGenLists(1)

Before calling glCallList:
If glIsList(DisplayListNumber) = GL_FALSE Then MsgBox “glIsList() returned False!”

The cube still turns blue, and glIsList() always returns GL_TRUE.

I don’t think glGenLists is in any way obligatory. I have actually never used it since I haven’t used multiple display lists simultaneously. The OpenGL red book includes examples like…

glNewList(1, GL_COMPILE);
draw_some_geometric_objects();
glEndList();

…so I think if you’ve only got one list it is fine to just call it number 1.

Does the same color problem occur with other primitves in the display list (change from points to lines, polygons, etc. just to test)?

What is in the display list doesn’t matter. I have tried points, lines, and triangles. Also the number of vertices doesn’t change anything - could be 100, could be 100,000, the result is still the same.

The next thing I would try is different hardware and driver versions. Do you have access to another system to rule out a driver bug? Have you updated to the latest driver already?

Is it just this program of yours? You mentioned having other programs in the past that had multiple display lists. Have any of them had this problem before? If not, were they VB as well? Since you have boiled down the problem to minimal code have you tried it with other languages like C++?

I haven’t got access to another system to test it at the moment. Would find it difficult to test with C++ as well, since my knowledge of it isn’t great. Although I have done similar things before, I have never had any problem like this - but then I wouldn’t expect to since to, since I have found that it happens under very specific circumstances.

Although I can’t explain why it happens, I have worked out when it happens, and how it can be avoided. The deciding factor seems to be whether calls to glColor3f are placed inside or outside glBegin… glEnd.

I would summarise the situation like this:

If Object B is plotted after Object A, then Object A may lose its assigned colours and inherit the colour of Object B on the next loop if:

  1. A display list is used for Object A, and
  2. glColor3f is called for each primitive in Object A, and
  3. glColor3f is called only once for Object B, to apply to all primitives.

It can be prevented from happening by assigning the same colour to all primitives in Object A i.e.

glColor3f 1, 0, 0 ’ red - OUTSIDE LOOP
glBegin GL_POINTS
__For each point
____glVertex3f x, y, z
__Next point
glEnd

Rather than:

glBegin GL_POINTS
__For each point
____glColor3f 1, 0, 0 ’ red - INSIDE LOOP
____glVertex3f x, y, z
__Next point
glEnd

But of course that may not be practical since Object A may be multicoloured.

It can also be prevented by assigning colours individually to the primitives in Object B, even if they are all the same colour i.e.

glBegin GL_LINE_LOOP
__glColor3f 0, 0, 1 ’ blue
__glVertex3f x1, y1, z1
__glVertex3f x2, y2, z2
__glVertex3f x3, y3, z3
__glVertex3f x4, y4, z4
glEnd

Rather than:

glColor3f 0, 0, 1 ’ blue
glBegin GL_LINE_LOOP
__glVertex3f x1, y1, z1
__glVertex3f x2, y2, z2
__glVertex3f x3, y3, z3
__glVertex3f x4, y4, z4
glEnd

(For this to work, glColor3f must go inside each glBegin…glEnd pair.)

So, in this case I can avoid the problem by using individual colours in Object B rather than a single glColor3f call at the beginning of the function.