I made a opengl program where you can move your view back and forth and side to side, and a cube with a light “in” it all three directions.
I filmed it as I used it:
http://www.youtube.com/watch?v=0KjwX3R-m7Y
Here is the code, which uses parts of tutorial 7 from nehe:
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#if defined(__APPLE__) && defined(__MACH__)
#include <OpenGL/gl.h> // Header File For The OpenGL32 Library
#include <OpenGL/glu.h> // Header File For The GLu32 Library
#else
#include <GL/gl.h> // Header File For The OpenGL32 Library
#include <GL/glu.h> // Header File For The GLu32 Library
#endif
#include "SDL.h"
#include <Math.h>
/* lighting on/off (1 = on, 0 = off) */
int light = 0;
GLfloat x=0;
GLfloat y=1;
GLfloat z=5.0f; // depth into the screen.
float xrot = 0;
float yrot = 0;
GLfloat lx=0;
GLfloat ly=0.5;
GLfloat lz=0;
/* white ambient light at half intensity (rgba) */
GLfloat LightAmbient[] = { 2,2,2, 1.0f };
/* super bright, full intensity diffuse light. */
GLfloat LightDiffuse[] = { 2,2,2, 1.0f };
GLuint filter = 0; /* Which Filter To Use (nearest/linear/mipmapped) */
GLuint texture[3]; /* Storage for 3 textures. */
SDL_Surface *LoadBMP(char *filename)
{
Uint8 *rowhi, *rowlo;
Uint8 *tmpbuf, tmpch;
SDL_Surface *image;
int i, j;
image = SDL_LoadBMP(filename);
if ( image == NULL ) {
fprintf(stderr, "Unable to load %s: %s
", filename, SDL_GetError());
return(NULL);
}
/* GL surfaces are upsidedown and RGB, not BGR :-) */
tmpbuf = (Uint8 *)malloc(image->pitch);
if ( tmpbuf == NULL ) {
fprintf(stderr, "Out of memory
");
return(NULL);
}
rowhi = (Uint8 *)image->pixels;
rowlo = rowhi + (image->h * image->pitch) - image->pitch;
for ( i=0; i<image->h/2; ++i ) {
for ( j=0; j<image->w; ++j ) {
tmpch = rowhi[j*3];
rowhi[j*3] = rowhi[j*3+2];
rowhi[j*3+2] = tmpch;
tmpch = rowlo[j*3];
rowlo[j*3] = rowlo[j*3+2];
rowlo[j*3+2] = tmpch;
}
memcpy(tmpbuf, rowhi, image->pitch);
memcpy(rowhi, rowlo, image->pitch);
memcpy(rowlo, tmpbuf, image->pitch);
rowhi += image->pitch;
rowlo -= image->pitch;
}
free(tmpbuf);
return(image);
}
// Load Bitmaps And Convert To Textures
GLvoid LoadGLTextures(GLvoid)
{
// Load Texture
SDL_Surface *image1;
image1 = LoadBMP("Media/crate.bmp");
if (!image1) {
SDL_Quit();
exit(1);
}
// Create Textures
glGenTextures(3, &texture[0]);
// texture 1 (poor quality scaling)
glBindTexture(GL_TEXTURE_2D, texture[0]); // 2d texture (x and y size)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); // cheap scaling when image bigger than texture
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); // cheap scaling when image smalled than texture
// 2d texture, level of detail 0 (normal), 3 components (red, green, blue), x size from image, y size from image,
// border 0 (normal), rgb color data, unsigned byte data, and finally the data itself.
glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->w, image1->h, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->pixels);
// texture 2 (linear scaling)
glBindTexture(GL_TEXTURE_2D, texture[1]); // 2d texture (x and y size)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // scale linearly when image bigger than texture
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // scale linearly when image smalled than texture
glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->w, image1->h, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->pixels);
// texture 3 (mipmapped scaling)
glBindTexture(GL_TEXTURE_2D, texture[2]); // 2d texture (x and y size)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // scale linearly when image bigger than texture
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST); // scale linearly + mipmap when image smalled than texture
glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->w, image1->h, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->pixels);
// 2d texture, 3 colors, width, height, RGB in that order, byte data, and the data.
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, image1->w, image1->h, GL_RGB, GL_UNSIGNED_BYTE, image1->pixels);
};
/* A general OpenGL initialization function. Sets all of the initial parameters. */
GLvoid InitGL(GLsizei Width, GLsizei Height) // We call this right after our OpenGL window is created.
{
glViewport(0, 0, Width, Height);
LoadGLTextures(); // load the textures.
glEnable(GL_TEXTURE_2D); // Enable texture mapping.
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // This Will Clear The Background Color To Black
glClearDepth(1.0); // Enables Clearing Of The Depth Buffer
glDepthFunc(GL_LESS); // The Type Of Depth Test To Do
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // Reset The Projection Matrix
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f); // Calculate The Aspect Ratio Of The Window
glMatrixMode(GL_MODELVIEW);
glEnable ( GL_COLOR_MATERIAL );
glColorMaterial ( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
}
void drawcube(float x,float y,float z,float a,float b,float c)
{
// Front Face (note that the texture's corners have to match the quad's corners)
glNormal3f(x+(a/2),y+(b/2),z); // front face points out of the screen on z.
glTexCoord2f(0.0f, 0.0f); glVertex3f(x,y, z+c); // Bottom Left Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f(x+a,y, z+c); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f(x+a,y+b, z+c); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f(x,y+b, z+c); // Top Left Of The Texture and Quad
// Back Face
glNormal3f(x+(a/2),y+(b/2),z+c); // back face points into the screen on z.
glTexCoord2f(1.0f, 0.0f); glVertex3f(x,y,z); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f(x,y+b,z); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f(x+a,y+b,z); // Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f(x+a,y,z); // Bottom Left Of The Texture and Quad
// Top Face
glNormal3f(x+(a/2),y+b,z+(c/2)); // top face points up on y.
glTexCoord2f(0.0f, 1.0f); glVertex3f(x,y+b,z); // Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f(x,y+b, z+c); // Bottom Left Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f(x+a,y+b, z+c); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f(x+a,y+b,z); // Top Right Of The Texture and Quad
// Bottom Face
glNormal3f(x+(a/2),y,z+(c/2)); // bottom face points down on y.
glTexCoord2f(1.0f, 1.0f); glVertex3f(x,y,z); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f(x+a,y,z); // Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f(x+a,y, z+c); // Bottom Left Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f(x,y, z+c); // Bottom Right Of The Texture and Quad
// Right face
glNormal3f(x+a,y+(b/2),z+(c/2)); // right face points right on x.
glTexCoord2f(1.0f, 0.0f); glVertex3f(x+a,y,z); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f(x+a,y+b,z); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f(x+a,y+b, z+c); // Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f(x+a,y, z+c); // Bottom Left Of The Texture and Quad
// Left Face
glNormal3f(x,y+(b/2),z+(c/2)); // left face points left on x.
glTexCoord2f(0.0f, 0.0f); glVertex3f(x,y,z); // Bottom Left Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f(x,y, z+c); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f(x,y+b, z+c); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f(x,y+b,z); // Top Left Of The Texture and Quad
}
/* The main drawing function. */
void DrawGLScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The View
glTranslatef(-x,-y,-z); // move z units out from the screen.
/* position of light (x, y, z, (position of light)) */
GLfloat LightPosition[] = { lx, ly, lz, 1.0f };
// set up light number 1.
//glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); // add lighting. (ambient)
glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); // add lighting. (diffuse).
glLightfv(GL_LIGHT1, GL_POSITION,LightPosition); // set light position.
glEnable(GL_LIGHT1); // turn light 1 on.
glBindTexture(GL_TEXTURE_2D, texture[filter]); // choose the texture to use.
glBegin(GL_QUADS); // begin drawing a cube
drawcube(0,0,0,2,2,2);
drawcube(3,0,0,2,2,2);
drawcube(lx,ly,lz,0.5,0.5,0.5);
glEnd();
glBindTexture(GL_TEXTURE_2D, NULL);
glBegin(GL_QUADS);
glColor3f(0,1,0);
drawcube(-100,0,-100,200,0.01,200);
glColor3f(0,0,1);
drawcube(-1000,1000,-1000,2000,0.01,2000);
glEnd(); // done with the polygon.
glColor3d(1,1,1);
// swap buffers to display, since we're double buffered.
SDL_GL_SwapBuffers();
}
int main(int argc, char **argv)
{
int done;
Uint8 *keys;
/* Initialize SDL for video output */
if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
fprintf(stderr, "Unable to initialize SDL: %s
", SDL_GetError());
exit(1);
}
/* Create a 640x480 OpenGL screen */
if ( SDL_SetVideoMode(1280, 960, 0, SDL_OPENGL) == NULL ) {
fprintf(stderr, "Unable to create OpenGL screen: %s
", SDL_GetError());
SDL_Quit();
exit(2);
}
/* Set the title bar in environments that support it */
SDL_WM_SetCaption("Jeff Molofee's GL Code Tutorial ... NeHe '99", NULL);
/* Loop, drawing and checking events */
InitGL(1280,960);
done = 0;
while ( ! done ) {
DrawGLScene();
/* This could go in a separate function */
{ SDL_Event event;
while ( SDL_PollEvent(&event) ) {
if ( event.type == SDL_QUIT ) {
done = 1;
}
if ( event.type == SDL_KEYDOWN ) {
switch(event.key.keysym.sym) {
case SDLK_ESCAPE:
done = 1;
break;
case SDLK_l:
printf("Light was: %d
", light);
light = light ? 0 : 1; // switch the current value of light, between 0 and 1.
printf("Light is now: %d
", light);
if (!light) {
glDisable(GL_LIGHTING);
} else {
glEnable(GL_LIGHTING);
}
break;
case SDLK_f:
printf("Filter was: %d
", filter);
filter += 1;
if (filter>2)
filter = 0;
printf("Filter is now: %d
", filter);
break;
}
}
}
}
/* Check current key state for special commands */
keys = SDL_GetKeyState(NULL);
if ( keys[SDLK_UP] == SDL_PRESSED )
{
z-=0.1;
}
if ( keys[SDLK_DOWN] == SDL_PRESSED )
{
z+=0.1;
}
if ( keys[SDLK_LEFT] == SDL_PRESSED )
{
x-=0.1;
}
if ( keys[SDLK_RIGHT] == SDL_PRESSED )
{
x+=0.1;
}
if ( keys[SDLK_w] == SDL_PRESSED ) {
lz-=0.03;
}
if ( keys[SDLK_s] == SDL_PRESSED ) {
lz+=0.03;
}
if ( keys[SDLK_a] == SDL_PRESSED ) {
lx-=0.03;
}
if ( keys[SDLK_d] == SDL_PRESSED ) {
lx+=0.03;
}
if( keys[SDLK_PAGEDOWN] == SDL_PRESSED)
{
ly-=0.03;
}
if( keys[SDLK_PAGEUP] == SDL_PRESSED)
{
ly+=0.03;
}
}
SDL_Quit();
return 1;
}
When the light goes to the left of the cubes, no sides light up, and when it goes to the right, all sides seem to light up. Why is this? How can I fix my lighting?
edit: oh, and the ground doesn’t light up at all