Fog prerequisites

There’s probably something very basic I don’t understand about fog in OpenGL even though I’ve red the relevant red book chapter. When trying to turn it on it just colors everything with the fog’s declared color and no amount of tweaking with the fog parameters will change that. Do I need lighting turned on? Materials? Normals? According to my understanding none of these should be needed. Here’s some (very basic) code.

init(near is 1,far is 70):

glClearColor(col[BACK][0],col[BACK][1],col[BACK][2],col[BACK][3]);
glEnable(GL_DEPTH_TEST);
glEnable(GL_FOG);
glFogi(GL_FOG_MODE, GL_LINEAR);
glFogf(GL_FOG_START,3);
glFogf(GL_FOG_END, 50);
//glFogf (GL_FOG_DENSITY, 0.1);
glFogfv (GL_FOG_COLOR, col+RED);

don’t think it’s realted but here’s the rendering code (grid=20):

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glLoadIdentity();
glTranslatef(0,-2,-5);
glRotated(10, 1.0, 0.0, 0.0);

glColor4fv(col+COL_BLUE);
glBegin(GL_QUADS);
glVertex3f(-GRID_SIZE, 0,-GRID_SIZE);
glVertex3f(-GRID_SIZE, 0, GRID_SIZE);
glVertex3f( GRID_SIZE, 0, GRID_SIZE);
glVertex3f( GRID_SIZE, 0,-GRID_SIZE);
glEnd();
glColor4fv(col+COL_GREY);
glBegin(GL_LINES);
for(i=-GRID_SIZE;i<=GRID_SIZE;i+=1) {
glVertex3f( i, 0,-GRID_SIZE);
glVertex3f( i, 0, GRID_SIZE);
glVertex3f(-GRID_SIZE, 0, i);
glVertex3f( GRID_SIZE, 0, i);
}
glEnd();

maybe it has something to do with the pixel format (?):

pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24;
pfd.cDepthBits = 16;
pfd.iLayerType = PFD_MAIN_PLANE;

if (!SetPixelFormat(win.hDC, ChoosePixelFormat(win.hDC, &pfd), &pfd))
  PostQuitMessage(0); 

Any ideas at this stage would be greatly(!) appreciated.

Read :
http://sjbaker.org/steve/omniv/projection_abuse.html
Check you dont abuse GL_PROJECTION.

glMatrixMode appears only twice in my code, both at the same place:

void resize( GLsizei width, GLsizei height ) {
float
ymax = Z_NEAR * tan((45 * M_PI)/ 360.0 ),
aspect = (float) width / height;

glViewport( 0, 0, width, height );

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

glFrustum(-ymax * aspect, // xmin
ymax * aspect, // xmax
-ymax, // ymin
ymax, // ymax
Z_NEAR, // znear
Z_FAR); // zfar

glMatrixMode( GL_MODELVIEW );
}

as far as I can tell this is ok.

Here is a simple test program. It’s only two functions and should compile in any win32 environment without helper libs.

UP/DOWN = fog on/off
LEFT/RIGHT = cycle fog types

What’s wrong with it?

#define _USE_MATH_DEFINES
#include <math.h>
#include <windows.h>
#include <GL/gl.h>

#define GRID_SIZE 10

#define Z_NEAR 1
#define Z_FAR 30

#define COL_BACK 0
#define COL_WHITE 1
#define COL_RED 2

// R,G,B,Alpha
float col[4] = {
{0.1, 0.1, 0.1, 1.0},
{0.9, 0.9, 0.9 , 1.0},
{0.7, 0.0, 0.0 , 1.0}
};

HDC hDC;

long WINAPI WProc (HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) {
PIXELFORMATDESCRIPTOR pfd={0};
PAINTSTRUCT ps;
RECT rect;
HGLRC hRC=NULL;
long ret = 1;
int pixelformat;
float ymax,aspect;
static int mode=GL_EXP;

switch (uMsg) {
case WM_CREATE:
hDC = GetDC(hWnd);
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24;
pfd.cDepthBits = 16;
pfd.iLayerType = PFD_MAIN_PLANE;

  if (!SetPixelFormat(hDC, ChoosePixelFormat(hDC, &pfd), &pfd))
    PostQuitMessage(0); 
  hRC = wglCreateContext(hDC); 
  wglMakeCurrent(hDC, hRC); 
  GetClientRect(hWnd, &rect);
  glClearColor(col[COL_BACK][0],col[COL_BACK][1],col[COL_BACK][2],col[COL_BACK][3]); 
  glEnable(GL_DEPTH_TEST);
  // fall through
case WM_SIZE: 
  GetClientRect(hWnd, &rect); 
  ymax = Z_NEAR * tan((45 * M_PI)/ 360.0 ),
  aspect = (float) rect.right / rect.bottom;
  glViewport(0,0,rect.right,rect.bottom); 
  glMatrixMode(GL_PROJECTION); 
  glLoadIdentity(); 
  glFrustum(-ymax * aspect, // xmin
    ymax * aspect, // xmax
    -ymax,          // ymin
    ymax,          // ymax
    Z_NEAR,        // znear
    Z_FAR);        // zfar
  glMatrixMode( GL_MODELVIEW ); 
  break; 
case WM_PAINT: 
  BeginPaint(hWnd,&ps); 
  EndPaint(hWnd,&ps); 
  break; 
case WM_CLOSE: 
  if (hRC) 
    wglDeleteContext(hRC); 
  if (hDC) 
    ReleaseDC(hWnd,hDC); 
  hRC = 0; 
  hDC = 0; 
  DestroyWindow(hWnd); 
  break; 
case WM_DESTROY: 
  if(hRC) 
    wglDeleteContext(hRC); 
  if(hDC) 
    ReleaseDC(hWnd,hDC); 
  PostQuitMessage (0); 
  break; 
case WM_KEYDOWN: 
  switch (wParam) { 
    case VK_LEFT:
    case VK_RIGHT: 
      if(mode==GL_LINEAR) {
        glFogi(GL_FOG_MODE, mode=GL_EXP);
        glFogf (GL_FOG_DENSITY, 0.1);
      } else
        if(mode==GL_EXP) {
          glFogi(GL_FOG_MODE, mode=GL_EXP2);
          glFogf (GL_FOG_DENSITY, 0.2);
        } else {
          glFogi(GL_FOG_MODE, mode=GL_LINEAR);
          glFogf(GL_FOG_START,15);
          glFogf(GL_FOG_END,30);
        } 
      break; 
    case VK_UP: 
      glEnable(GL_FOG);
      glFogfv(GL_FOG_COLOR, col+COL_RED);
      break; 
    case VK_DOWN: 
      glDisable(GL_FOG);
      break;  
  }
default: 
  ret=DefWindowProc (hWnd, uMsg, wParam, lParam); 

}

return ret;
}

int WINAPI WinMain (HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) {
HWND hWnd;
MSG msg;
WNDCLASS wclass={0};
int i;

// register window class
wclass.style = CS_OWNDC;
wclass.lpfnWndProc = (WNDPROC)WProc;
wclass.hInstance = hInstance;
wclass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wclass.lpszMenuName = “test fog”;
wclass.lpszClassName = “test fog”;
if (!RegisterClass (&wclass))
return FALSE;

// create window
hWnd = CreateWindow (“test fog”,
“test fog”,
WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
if (!hWnd)
return FALSE;

ShowWindow (hWnd, nCmdShow);
UpdateWindow (hWnd);

// GL loop
while (1) {
while(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
if(GetMessage(&msg, NULL, 0, 0)<1)
return TRUE;
DispatchMessage(&msg);
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glLoadIdentity();
glTranslatef(0,-1,-17);
glRotated(10, 1.0, 0.0, 0.0);
glColor4fv(col+COL_WHITE);
glBegin(GL_LINES);
for(i=-GRID_SIZE;i&lt;=GRID_SIZE;i+=1) {
  glVertex3f(i,0,-GRID_SIZE);
  glVertex3f(i,0, GRID_SIZE);
  glVertex3f(-GRID_SIZE,0,i);
  glVertex3f( GRID_SIZE,0,i);
}
glEnd();
glBegin(GL_QUADS);
for(i=-GRID_SIZE;i&lt;=GRID_SIZE;i+=1) {
  glVertex3f(i+1,0,i+1);
  glVertex3f(i,0,i+1);
  glVertex3f(i,0,i);
  glVertex3f(i+1,0,i);
}
glEnd();
glFlush();
SwapBuffers(hDC); 

}
}

Update: Addign a single line made it work (glBindTexture(GL_TEXTURE_2D,0):wink:
Still no explanation for this behavior…

In case anyone is interested, it seems that (at least in my opengl implementation) you need to glEnable fog after every buffer switch.

Really? Please do tell us what vendor and driver version you’re seeing this in!