color index mode in overlay plane

Hi!

I am using an overlay plane to render highlighted objects in the scene. But I am having trouble with the shading. All objects turn out gray and look flat shaded.

I am using a Quadro4 900 XGL. The overlay plane uses a 8 bit color index mode. I fill the entire palette with green color range.

If I disable lighting I get the correct color, but when lighting is enabled everything turns gray.

I have also tested this on a Wildcat 6210 and the result there is that everything turns black in lighted mode. But as the nVidia card the unlighted mode works as it should.

Does anybody know what I am doing wrong?

/Fredrik

The code is posted below:

This program shows two spheres. The red one is drawn in the main plane. The green is rendered in the overlay plane. Clipping planes are used to show half of each. In unlighted mode the clipping does not seem to work.(If you wonder why only the overlay sphere is visible in )

#include <windows.h>
#include <math.h>
#include <gl\gl.h>
#include <gl\glu.h>
#include <gl\glaux.h>

HDC hDC=NULL;
HGLRC hRC=NULL;
HGLRC hLRC=NULL;
HWND hWnd=NULL;
HINSTANCE hInstance;

bool keys[256]; // Array Used For The Keyboard Routine
bool layerMode = true;
bool layerColorModeIndex = true;
bool useLighting = true;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int getPF(HDC hDC, const PIXELFORMATDESCRIPTOR *pfd);

GLvoid ReSizeGLScene(GLsizei width, GLsizei height)
{
if (height==0) // Prevent A Divide By Zero By
{
height=1;
}
wglMakeCurrent(hDC,hRC);
glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
wglMakeCurrent(NULL, NULL);

wglMakeCurrent(hDC,hLRC);
glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
wglMakeCurrent(NULL, NULL);

}

void drawLight()
{
int _target = 0;
float _direction[] = { 0, 0, -1};
float _intensity = 1.0f;
float _ambientIntensity = 0.0f;
float _color[3] = {1.0, 1.0, 1.0};

int target = _target + GL_LIGHT0;
glEnable(target);

static GLfloat vec[4];
static GLfloat spec[] = {1.0f, 1.0f, 1.0f, 1.0f};
float mag = (float)sqrt( _direction[0]_direction[0] +
_direction[1]
_direction[1] +
_direction[2]*_direction[2] );

if ( mag != 0 ) mag = 1.0f/mag;

vec[0] = -_direction[0]*mag;
vec[1] = -_direction[1]*mag;
vec[2] = -_direction[2]*mag;
vec[3] = 0.0f;

glLightfv(target, GL_POSITION, vec);
vec[0] = _color[0] * _ambientIntensity;
vec[1] = _color[1] * _ambientIntensity;
vec[2] = _color[2] * _ambientIntensity;
vec[3] = 1.0f;
glLightfv(target, GL_AMBIENT, vec);
vec[0] = _color[0] * _intensity;
vec[1] = _color[1] * _intensity;
vec[2] = _color[2] * _intensity;
vec[3] = 1.0f;
glLightfv(target, GL_DIFFUSE, vec);
vec[0] = spec[0] * _intensity;
vec[1] = spec[1] * _intensity;
vec[2] = spec[2] * _intensity;
vec[3] = spec[3];
glLightfv(target, GL_SPECULAR, vec);

GLfloat _cutOffAngle = 180;
glLightfv(target, GL_SPOT_CUTOFF, &_cutOffAngle);

GLfloat _exponent = 0;
glLightfv(target, GL_SPOT_EXPONENT, &_exponent);

GLfloat _attenuation[3] = {1,0,0};
glLightfv(target, GL_CONSTANT_ATTENUATION, &_attenuation[0] );
glLightfv(target, GL_LINEAR_ATTENUATION, &_attenuation[1] );
glLightfv(target, GL_QUADRATIC_ATTENUATION, &_attenuation[2] );

}

void InitGL(GLvoid)
{
wglMakeCurrent(hDC,hRC);

GLboolean val;
glGetBooleanv(GL_INDEX_MODE, &val);
glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

if(useLighting) {
glEnable(GL_LIGHTING);
drawLight();
}

wglMakeCurrent(NULL, NULL);
wglMakeCurrent(hDC,hLRC);

glGetBooleanv(GL_INDEX_MODE, &val);

glShadeModel(GL_SMOOTH);
glClearIndex(0);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

if(useLighting) {
glEnable(GL_LIGHTING);

drawLight();

}

wglMakeCurrent(NULL, NULL);
}

int DrawGLScene(GLvoid)
{
static float trans = 0;
static float delta = 0.1f;

// if(trans > 2.0 | | trans < -2.0)
// delta = -delta;

//trans += delta;

trans = -1.2;

wglMakeCurrent(hDC,hRC);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f,trans,-6.0f);

// double eq[] = {-1.0, 0.0, 0.0};
// glClipPlane(GL_CLIP_PLANE0, eq);
// glEnable(GL_CLIP_PLANE0);

if(useLighting) {
float color[] = {1.0, 0.0, 0.0};
glMaterialfv(GL_FRONT, GL_DIFFUSE, color);
}
else
glColor3f(1.0, 0.0, 0.0);

gluSphere( gluNewQuadric(), 1, 30, 30);

wglMakeCurrent(NULL,NULL);

if(layerMode) {
wglMakeCurrent(hDC,hLRC); // Layer

trans = 1.2;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f,trans,-6.0f);

// double eq[] = {1.0, 0.0, 0.0};
// glClipPlane(GL_CLIP_PLANE0, eq);
// glEnable(GL_CLIP_PLANE0);

if(layerColorModeIndex) {
  if(useLighting) {
    GLint	indices[3];
    indices[0] = 0;//255;//_ambientIndex;
    indices[1] = 255;//_diffuseIndex;
    indices[2] = 0;//255;//_specularIndex;
    glMaterialiv(GL_FRONT, GL_COLOR_INDEXES, indices);
  }
  else
    glIndexi(255);
}
else
  glColor3f(0.0f,1.0f,0.0f);

gluSphere( gluNewQuadric(), 1, 30, 30);

wglMakeCurrent(NULL,NULL);

}

return TRUE;
}

BOOL CreateGLWindow(char* title, int width, int height,
int bits, bool fullscreenflag)
{
GLuint PixelFormat;
WNDCLASS wc;
DWORD dwExStyle;
DWORD dwStyle;
RECT WindowRect;
WindowRect.left=(long)0;
WindowRect.right=(long)width;
WindowRect.top=(long)0;
WindowRect.bottom=(long)height;

hInstance = GetModuleHandle(NULL);
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = (WNDPROC) WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = “OpenGL”;

RegisterClass(&wc);

dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
dwStyle=WS_OVERLAPPEDWINDOW;

AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);

// Create The Window
hWnd=CreateWindowEx( dwExStyle,
“OpenGL”,
title,
dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
0, 0,
WindowRect.right-WindowRect.left,
WindowRect.bottom-WindowRect.top,
NULL,
NULL,
hInstance,
NULL);

static PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
bits,
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
16,
0,
0,
PFD_MAIN_PLANE,
layerMode ? 1 : 0, // Reserved
0, 0, 0
};

hDC=GetDC(hWnd);

//PixelFormat=ChoosePixelFormat(hDC,&pfd);
PixelFormat = getPF(hDC, &pfd);
SetPixelFormat(hDC,PixelFormat,&pfd);
hRC=wglCreateContext(hDC);
wglMakeCurrent(hDC,hRC);

// Create Layer context
if(layerMode) {
hLRC = wglCreateLayerContext(hDC, 1); //
COLORREF colorMap[256];
wglGetLayerPaletteEntries(hDC, 1, 0, 256, colorMap);

for(int j = 0; j &lt; 256; ++j)
{
  colorMap[j] = j &lt;&lt; 8;
}

int err = wglSetLayerPaletteEntries(hDC, 1, 0, 256, colorMap);
BOOL r = wglRealizeLayerPalette(hDC, 1, TRUE);

LAYERPLANEDESCRIPTOR lpd;
wglDescribeLayerPlane(hDC, GetPixelFormat(hDC), 1, 
                      sizeof(LAYERPLANEDESCRIPTOR), 
                      &lpd);
if(lpd.iPixelType == PFD_TYPE_RGBA)
  layerColorModeIndex = false;//COLORMODE_RGB;
else
  layerColorModeIndex = true;//COLORMODE_INDEX;

}

ShowWindow(hWnd,SW_SHOW);
SetForegroundWindow(hWnd);
SetFocus(hWnd);
ReSizeGLScene(width, height);

InitGL();
return TRUE;
}

LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{

case WM_KEYDOWN:
  {
    keys[wParam] = TRUE;
    return 0;	
  }
  
case WM_KEYUP:	
  {
    keys[wParam] = FALSE;	
    return 0;		
  }
  
case WM_SIZE:				     
  {
    ReSizeGLScene(LOWORD(lParam),HIWORD(lParam));
    return 0;				
  }
}

// Pass All Unhandled Messages To DefWindowProc
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
BOOL done=FALSE;

if (MessageBox(NULL,“Enable lighting?”, “”,MB_YESNO|MB_ICONQUESTION)==IDNO)
{
useLighting = false;
}

// Create Our OpenGL Window
if (!CreateGLWindow(“Overlay test program”,640,480,16,FALSE))
{
return 0;
}

while(!done)
{
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if (msg.message==WM_QUIT)
{
done=TRUE;
}
else
{
TranslateMessage(&msg); // Translate The Message
DispatchMessage(&msg); // Dispatch The Message
}
}
else
{
if ((/*active && */!DrawGLScene()) | | keys[VK_ESCAPE])
{
done=TRUE;
}
else
{
if(layerMode) {
wglSwapLayerBuffers(hDC, WGL_SWAP_MAIN_PLANE | WGL_SWAP_OVERLAY1);
}
else
SwapBuffers(hDC);

  }
      
}

}
return (msg.wParam);
}

int getPF(HDC hDC, const PIXELFORMATDESCRIPTOR *pfd)
{
PIXELFORMATDESCRIPTOR tmpPfd;

unsigned int noOfPixelFormats =
DescribePixelFormat(hDC, 1, sizeof(PIXELFORMATDESCRIPTOR), &tmpPfd);

int *validPixelFormats = new int[noOfPixelFormats];

for(unsigned int i = 0 ; i < noOfPixelFormats; i++) {
validPixelFormats[i] = 1;
}

for(i = 0 ; i < noOfPixelFormats; i++) {
DescribePixelFormat(hDC, i+1, sizeof(PIXELFORMATDESCRIPTOR), &tmpPfd);

// dwFlags
if( (tmpPfd.dwFlags & pfd-&gt;dwFlags) ^ pfd-&gt;dwFlags ) 
  validPixelFormats[i] = 0; // Not valid.

// iPixelType
if(tmpPfd.iPixelType != pfd-&gt;iPixelType) 
  validPixelFormats[i] = 0; // Not valid.

// cColorBits
if(tmpPfd.cColorBits &lt; pfd-&gt;cColorBits) 
  validPixelFormats[i] = 0; // Not valid.

// cRedBits
if(tmpPfd.cRedBits &lt; pfd-&gt;cRedBits)
  validPixelFormats[i] = 0; // Not valid.

// cRedShift
if(tmpPfd.cRedShift &lt; pfd-&gt;cRedShift)
  validPixelFormats[i] = 0; // Not valid.

// cGreenBits
if(tmpPfd.cGreenBits &lt; pfd-&gt;cGreenBits)
  validPixelFormats[i] = 0; // Not valid.

// cGreenShift
if(tmpPfd.cGreenShift &lt; pfd-&gt;cGreenShift)
  validPixelFormats[i] = 0; // Not valid.

// cBlueBits
if(tmpPfd.cBlueBits &lt; pfd-&gt;cBlueBits)
  validPixelFormats[i] = 0; // Not valid.

// cBlueShift
if(tmpPfd.cBlueShift &lt; pfd-&gt;cBlueShift)
  validPixelFormats[i] = 0; // Not valid.

// cAlphaBits
if(tmpPfd.cAlphaBits &lt; pfd-&gt;cAlphaBits)
  validPixelFormats[i] = 0; // Not valid.

// cAlphaShift
if(tmpPfd.cAlphaShift &lt; pfd-&gt;cAlphaShift)
  validPixelFormats[i] = 0; // Not valid.

// cAccumBits
if(tmpPfd.cAccumBits &lt; pfd-&gt;cAccumBits)
  validPixelFormats[i] = 0; // Not valid.

// cAccumRedBits
if(tmpPfd.cAccumRedBits &lt; pfd-&gt;cAccumRedBits)
  validPixelFormats[i] = 0; // Not valid.

// cAccumGreenBits
if(tmpPfd.cAccumGreenBits &lt; pfd-&gt;cAccumGreenBits)
  validPixelFormats[i] = 0; // Not valid.

// cAccumBlueBits
if(tmpPfd.cAccumBlueBits &lt; pfd-&gt;cAccumBlueBits)
  validPixelFormats[i] = 0; // Not valid.

// cAccumAlphaBits
if(tmpPfd.cAccumAlphaBits &lt; pfd-&gt;cAccumAlphaBits)
  validPixelFormats[i] = 0; // Not valid.

// cDepthBits
if(tmpPfd.cDepthBits &lt; pfd-&gt;cDepthBits)
  validPixelFormats[i] = 0; // Not valid.

// cStencilBits
if(tmpPfd.cStencilBits &lt; pfd-&gt;cStencilBits)
  validPixelFormats[i] = 0; // Not valid.

// cAuxBuffers
if(tmpPfd.cAuxBuffers &lt; pfd-&gt;cAuxBuffers)
  validPixelFormats[i] = 0; // Not valid.

// iLayerType is no longer used.

// bReserved. // overlay and underlay planes
BYTE overlaysSupported = (tmpPfd.bReserved & 7);
BYTE overlaysWanted =  (pfd-&gt;bReserved & 7);
BYTE underlaysSupported = (tmpPfd.bReserved &gt; 3);
BYTE underlaysWanted =  (pfd-&gt;bReserved &gt; 3);

if( (overlaysSupported &lt; overlaysWanted) | |
    (underlaysSupported &lt; underlaysWanted))
  validPixelFormats[i] = 0; // Not valid.

// dwLayerMask is no longer used.

// dwVisibleMask ??

// dwDamageMask is no longer used.

}

// How many left?
int firstValid = -1;
for(i = 0 ; i < noOfPixelFormats; i++) {
if(validPixelFormats[i]) {
if(firstValid == -1)
firstValid = i+1;
}
}

return firstValid;
}

Hi Fredrick,

I believe this is a driver bug that will be fixed in a future driver release. There are a number of work-arounds that you can use with existing drivers though. Why don’t you contact me offline (cass@nvidia.com)?

Thanks -
Cass