c++winapiopengllightingglu

Unable to glTranslate() light source


I am having a problem translating the light source.

I have coded a program that accepts up, down, left, and right keys to increase/decrease the x, y, and z values to reposition the light source. But the problem right now is the x, y, and z value does change but the light source remains in the same place. I believe the problem shall be somewhere inside the void lighting() function.

below is my code:

#include <Windows.h>
#include <gl/GL.h>
#include <math.h>
#include <gl/GLU.h>

#pragma comment (lib, "OpenGL32.lib") //link library
#pragma comment(lib, "Winmm.lib")

#define WINDOW_TITLE "Lighting"

bool isOrtho = true;
float ONear = -10.0, OFar = 10.0;   //Ortho Near & Far
float PNear = 1.0, PFar = 21.0;     //Perspective Near & Far
float exeDif[3] = { 1.0,0.0,0.0 };  //Red diffuse light
float x =6 , y=0, z=0;
float exePosD[3] = { 6,0,0 };
float exeDifM[3] = { 1.0,0.0,0.0 };
bool isLightOn = false;     //is light on?

LRESULT WINAPI WindowProcedure(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_DESTROY:
        PostQuitMessage(0);//quit application
        break;

    case WM_KEYDOWN:
        if (wParam == VK_ESCAPE) PostQuitMessage(0);
        else if (wParam == VK_SPACE) {
            isLightOn = !isLightOn;
        }
        else if (wParam == VK_UP) {
            y = y + 1.0;
        }
        else if (wParam == VK_DOWN) {
            y = y - 1.0;
        }
        else if (wParam == VK_LEFT) {
            x = x - 1.0;
        }
        else if (wParam == VK_RIGHT) {
            x = x + 1.0;
        }
        else if (wParam == 'Q') {
            z = z - 1.0;
        }
        else if (wParam == 'E') {
            z = z + 1.0;
        }

        break;
    default:
        break;
    }

    return DefWindowProc(hWnd, msg, wParam, lParam);
}

bool initPixelFormat(HDC hdc)
{
    PIXELFORMATDESCRIPTOR pfd;
    ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR));

    pfd.cAlphaBits = 8;
    pfd.cColorBits = 32;
    pfd.cDepthBits = 24;
    pfd.cStencilBits = 0;

    pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;

    pfd.iLayerType = PFD_MAIN_PLANE;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
    pfd.nVersion = 1;

    // choose pixel format returns the number most similar pixel format available
    int n = ChoosePixelFormat(hdc, &pfd);

    // set pixel format returns whether it sucessfully set the pixel format
    if (SetPixelFormat(hdc, n, &pfd))
    {
        return true;
    }
    else
    {
        return false;
    }
}

void lighting() {
    if (isLightOn) {
        glEnable(GL_LIGHTING);          //Turon on lighting for the whole scene
    }
    else {
        //Turn off lighting for the whole screen
        glDisable(GL_LIGHTING);
    }
    
    glPushMatrix();
    glTranslatef(x, y, z);
    glLightfv(GL_LIGHT0, GL_POSITION, exePosD);
    glPopMatrix();

    glLightfv(GL_LIGHT0, GL_DIFFUSE, exeDif);

    glEnable(GL_LIGHT0);
}

void projection() {
    glMatrixMode(GL_PROJECTION);    //refer to projection matrix
    glLoadIdentity();               //reset projection matrix
    if (isOrtho) {
        //Ortho View
        glOrtho(-10.0, 10.0, -10.0, 10.0, ONear, OFar); //Ortho view
    }
    else {
        //Perspective view
        gluPerspective(20, 1.0, -1.0, 1.0);
        glFrustum(-10.0, 10.0, -10.0, 10.0, PNear, PFar);
    }
}

void drawSphere(double r) {
    GLUquadricObj* sphere = NULL;
    sphere = gluNewQuadric();
    gluQuadricDrawStyle(sphere, GLU_FILL);
    gluSphere(sphere, r, 30, 30);
    gluDeleteQuadric(sphere);
}

void display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);

    projection();                   //projection
    lighting();

    glMatrixMode(GL_MODELVIEW);     //refer to modelview matrix
    glLoadIdentity();               //reset
    drawSphere(3.0);

    //red color diffuse
    glMaterialfv(GL_FRONT, GL_DIFFUSE, exeDifM);

    glColor3f(0.0, 0.0, 1.0);       //blue
    drawSphere(3.0);
}


int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int nCmdShow)
{
    WNDCLASSEX wc;
    ZeroMemory(&wc, sizeof(WNDCLASSEX));

    wc.cbSize = sizeof(WNDCLASSEX);
    wc.hInstance = GetModuleHandle(NULL);
    wc.lpfnWndProc = WindowProcedure;
    wc.lpszClassName = WINDOW_TITLE;
    wc.style = CS_HREDRAW | CS_VREDRAW;

    if (!RegisterClassEx(&wc)) return false;

    HWND hWnd = CreateWindow(WINDOW_TITLE, WINDOW_TITLE, WS_OVERLAPPEDWINDOW,
        720, 10, 300, 300,
        NULL, NULL, wc.hInstance, NULL);

    //--------------------------------
    //  Initialize window for OpenGL
    //--------------------------------

    HDC hdc = GetDC(hWnd);

    //  initialize pixel format for the window
    initPixelFormat(hdc);

    //  get an openGL context
    HGLRC hglrc = wglCreateContext(hdc);

    //  make context current
    if (!wglMakeCurrent(hdc, hglrc)) return false;

    //--------------------------------
    //  End initialization
    //--------------------------------

    ShowWindow(hWnd, nCmdShow);

    MSG msg;
    ZeroMemory(&msg, sizeof(msg));

    while (true)
    {
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            if (msg.message == WM_QUIT) break;

            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        display();

        SwapBuffers(hdc);
    }

    UnregisterClass(WINDOW_TITLE, wc.hInstance);

    return true;
}

This is the output screen:


Solution

  • The light position is transformed with the modelview matrix, but not with the projection matrix. Therefore you need to switch to the modelview matrix after projection() and before lighting():

    projection();                   //projection
    
    glMatrixMode(GL_MODELVIEW);     //refer to modelview matrix
    glLoadIdentity();        
    
    lighting();