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:
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();