Hi, i''ve been having problems with enabling lighting on my scene that uses blending. Without lights the transparent polygons are drawn correctly yet as soon as I enable lighting all polygons are totally opaque, regardless of alpha value.
I have included the source of my project, its just something simple that I''m playing with to learn gl and it has loads of rubbish in it but it should work and yet doesn''t

Interestingly if I use GL_ONE instead of GL_ONE_MINUS_SRC_ALPHA for the blending function then everything becomes transparent and I can''t stop it. Hmm
If someone could help me with this I would be very grateful
Thanks
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
#include <gl\gl.h>
#include <gl\glu.h>
#include <gl\glaux.h>
#include <gl\glut.h>
#define ESCAPE 27
#define ARRMAX 40
#define SCALE 20
#define GRAVITY 60
#define BOUNCE 1.0
#define CAMINT 0.9
GLuint texture[2];
////////////////////////////////
//Texture Initialisation Code //
////////////////////////////////
//Loads the image
AUX_RGBImageRec *LoadBMP(char *Filename)
{
FILE *File=NULL; //Create a file handle
if(!Filename) //Make sure filename was given
return NULL; //It wasn''t so b0rk
File=fopen(Filename, "r"); //Check if exists
if(File)
{
fclose(File);
return auxDIBImageLoad(Filename); //Load and return a pointer
}
return NULL;
}
//Load BMPs and convert to textures
int LoadGLTextures(int NoOfTex, char**FNames)
{
int Status=TRUE;
AUX_RGBImageRec *TextureImage[1]; //Storage for the texture
//Clear the image record to make sure its empty
memset(TextureImage,0,sizeof(void *)*1); //Set pointer to NULL
//Load the bitmaps, check for errors
for (int i=0; i<NoOfTex; i++)
{
if(!(TextureImage[i]=LoadBMP(FNames[i])))
{
Status = FALSE;
}
}
if(!Status) return FALSE;
for (i=0; i<NoOfTex; i++)
{
//Now that bmp loaded need to convert to texture
//Number of textures, Where to store textures (declared above)
glGenTextures(1, &texture[i]); //Create the texture
//Tell OpenGL memory is available at &texture[0] for a texture
glBindTexture(GL_TEXTURE_2D, texture[i]);
//Create the actual texture
glTexImage2D(GL_TEXTURE_2D,
0, //Levels of detail
3, //Components (RGB)
TextureImage[i]->sizeX, //Get X size from the loaded data
TextureImage[i]->sizeY,
0, //Border
GL_RGB, //Data type
GL_UNSIGNED_BYTE, //Representation
TextureImage[i]->data); //Data
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
//Garbage collection
if(TextureImage[i])
{
if(TextureImage[i]->data)
{
free(TextureImage[i]->data);
}
free(TextureImage[i]);
}
}
return Status;
}
// GL Initialisation Code
// Here we will put variables which we wish to be global
///////////////////////////////////////////////////////////
GLint window; // The number of our GLUT window
GLint Xsize=500;
GLint Ysize=500;
int MatrixStylee = 0, AutoRot = 0;
float cam_angle = 0, cam_pitch = 0;
GLfloat LightAmbient[] = { 0.5, 0.5, 0.5, 0.5 };
GLfloat LightDiffuse[] = { 1.0, 1.0, 1.0, 0.5 };
GLfloat LightPosition[] = { 0.0, 0.0, 2.0, 1.0 }; /* position */
GLfloat parray[ARRMAX][7];
// 0 = X pos
// 1 = Y pos
// 2 = Z pos
// 3 = X velocity
// 4 = Y velocity
// 5 = Z velocity
// 6 = radius
//Called by the window resize code
//Sets the viewport perspective and stuff
GLvoid Transform(GLfloat Width, GLfloat Height)
{
glViewport(0, 0, Width, Height); // Set the viewport
glMatrixMode(GL_PROJECTION); // Select the projection matrix
glLoadIdentity(); // Reset The Projection Matrix
//gluPerspective(FOV, Aspect, Near Clip, Far Clip)
gluPerspective(45.0,Width/Height,2,1000.0); // Calculate The Aspect Ratio Of The Window
glMatrixMode(GL_MODELVIEW); // Switch back to the modelview matrix
}
// The function called when our window is resized
// Sets vars then calls Transform
GLvoid ReSizeGLScene(GLint Width, GLint Height)
{
if (Height==0) Height=1; // Sanity checks
if (Width ==0) Width=1;
Transform( Width , Height ); // Perform the transformation
}
// A general OpenGL initialization function. Sets all of the initial parameters
// Called by main() before jumping into the GLUT loop
GLvoid InitGL(GLfloat Width, GLfloat Height)
{
char * FNArray[2] ={"crate.bmp", "check2.bmp"};
glClearColor(0.0, 0.0, 0.0, 0.5); // Clear The Background Colour To Black
glClearDepth(1.0f); // Depth Buffer Setup
glPointSize(2.0);
glLineWidth(1.0);
glShadeModel(GL_SMOOTH);
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
//glBlendFunc( GL_SRC_ALPHA, GL_ONE);
glEnable(GL_BLEND);
glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmbient); // add lighting. (ambient)
glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDiffuse); // add lighting. (diffuse)
glLightfv(GL_LIGHT0, GL_POSITION,LightPosition); // set light position.
glEnable(GL_LIGHT0); // turn light 0 on.
glEnable(GL_LIGHTING);
if(!LoadGLTextures(2, FNArray))
{
//Something went wrong
MessageBox(NULL, "Couldn''t load textures", "Texture Load Error", MB_OK|MB_ICONEXCLAMATION);
}
Transform( Width, Height ); // Perform the transformation
}
float gettime(){
static clock_t t_old = 0;
clock_t t_new, elapsed;
t_new = clock();
elapsed = t_new - t_old;
t_old = t_new;
return (float) elapsed / CLOCKS_PER_SEC;
}
//The main drawing function. This is the function which will be
//called when a "redisplay" is requested.
GLvoid DrawGLScene()
{
int i =0;
float R;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear screen & depth buffer
glPushMatrix();
glLoadIdentity();
//Global scene modifiers
glTranslatef(0.0,-40.0,-175.0);
glRotatef(cam_angle, 0.0, 1.0, 0.0);
glRotatef(cam_pitch, 1.0, 0.0, 0.0);
glColor4f(1.0, 1.0, 1.0, 1.0);
//Draw the floor
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture[0]); //Select floor texture
glBegin(GL_QUADS);
glNormal3f( 0.0f, 5.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-70.0, 0, -70.0);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-70.0, 0, 70.0);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(70.0, 0, 70.0);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(70.0, 0, -70.0);
glEnd();
glDisable(GL_TEXTURE_2D);
//Draw the objects
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture[1]);
for(i=0; i<ARRMAX; i++)
{
glPushMatrix();
glTranslatef(parray[i][0], parray[i][1], parray[i][2]);
//glutSolidSphere(parray[6],20,20);
</font>
<font color=gray>//glutSolidCube(parray[6]);
</font>
R = parray[<font color=purple>i</font>][<font color=purple>6</font>];
glBegin(GL_QUADS);
<font color=gray>// Front Face
</font>
glNormal3f( 0.0f, 0.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-R, -R, R);
glTexCoord2f(1.0f, 0.0f); glVertex3f( R, -R, R);
glTexCoord2f(1.0f, 1.0f); glVertex3f( R, R, R);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-R, R, R);
<font color=gray>// Back Face
</font>
glNormal3f( 0.0f, 0.0f,-1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-R, -R, -R);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-R, R, -R);
glTexCoord2f(0.0f, 1.0f); glVertex3f( R, R, -R);
glTexCoord2f(0.0f, 0.0f); glVertex3f( R, -R, -R);
<font color=gray>// Top Face
</font>
glNormal3f( 0.0f, 1.0f, 0.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-R, R, -R);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-R, R, R);
glTexCoord2f(1.0f, 0.0f); glVertex3f( R, R, R);
glTexCoord2f(1.0f, 1.0f); glVertex3f( R, R, -R);
<font color=gray>// Bottom Face
</font>
glNormal3f( 0.0f,-1.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-R, -R, -R);
glTexCoord2f(0.0f, 1.0f); glVertex3f( R, -R, -R);
glTexCoord2f(0.0f, 0.0f); glVertex3f( R, -R, R);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-R, -R, R);
<font color=gray>// Right face
</font>
glNormal3f( 1.0f, 0.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( R, -R, -R);
glTexCoord2f(1.0f, 1.0f); glVertex3f( R, R, -R);
glTexCoord2f(0.0f, 1.0f); glVertex3f( R, R, R);
glTexCoord2f(0.0f, 0.0f); glVertex3f( R, -R, R);
<font color=gray>// Left Face
</font>
glNormal3f(-1.0f, 0.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-R, -R, -R);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-R, -R, R);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-R, R, R);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-R, R, -R);
glEnd();
glPopMatrix();
}
glDisable(GL_TEXTURE_2D);
<font color=gray>//Draw the walls
</font>
<font color=gray>//Walls are transparent so draw last. Draw back faces first.
</font>
<font color=gray>//Keep depth buffer ENABLED, no cheating
</font>
<font color=gray>//Counter clockwise for objects facing us
</font>
glColor4f(0.0, 0.6, 0.3, 0.35);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture[<font color=purple>1</font>]);
glBegin(GL_QUADS);
<font color=gray>//Back wall
</font>
glNormal3f(0.0f, 0.0f, 1.0f);
glVertex3f(-70, 15, -70);
glVertex3f(-70, 0, -70);
glVertex3f(70, 0, -70);
glVertex3f(70, 15, -70);
<font color=gray>//Left wall
</font>
glNormal3f(1.0f, 0.0f, 0.0f);
glVertex3f(-70, 15, 70);
glVertex3f(-70, 0, 70);
glVertex3f(-70, 0, -70);
glVertex3f(-70, 15, -70);
<font color=gray>//Right wall
</font>
glNormal3f(-1.0f, 0.0f, 0.0f);
glVertex3f(70, 15, 70);
glVertex3f(70, 0, 70);
glVertex3f(70, 0, -70);
glVertex3f(70, 15, -70);
<font color=gray>//Front wall
</font>
glNormal3f(0.0f, 0.0f, -1.0f);
glVertex3f(-70, 15, 70);
glVertex3f(-70, 0, 70);
glVertex3f(70, 0, 70);
glVertex3f(70, 15, 70);
glEnd();
glDisable(GL_TEXTURE_2D);
glPopMatrix();
glFlush();
glutSwapBuffers(); <font color=gray>//Double buffer swapover
</font>
}
<font color=gray>// Timer function, called every 40ms, will redraw if passed a 1
</font>
<font color=gray>// Passes its argument to itself. Arg comes from the Viz func below
</font>
GLvoid Timer( <font color=blue>int</font> value )
{
<font color=blue>if</font>( value ) glutPostRedisplay();
glutTimerFunc(40,Timer,value);
}
GLvoid Animate(<font color=blue>int</font> t)
{
<font color=blue>int</font> i = 0;
<font color=blue>float</font> time_step, bfact;
time_step = gettime();
<font color=blue>if</font> (AutoRot)
{
cam_angle = cam_angle + CAMINT;
<font color=blue>if</font> (cam_angle > 360) cam_angle = 0;
}
<font color=blue>if</font> (!MatrixStylee)
{
<font color=blue>for</font> (i = 0; i<ARRMAX; i++)
{
parray[<font color=purple>i</font>][<font color=purple>0</font>] += parray[<font color=purple>i</font>][<font color=purple>3</font>]*time_step;;
parray[<font color=purple>i</font>][<font color=purple>1</font>] += parray[<font color=purple>i</font>][<font color=purple>4</font>]*time_step;;
parray[<font color=purple>i</font>][<font color=purple>2</font>] += parray[<font color=purple>i</font>][<font color=purple>5</font>]*time_step;;
parray[<font color=purple>i</font>][<font color=purple>4</font>] = parray[<font color=purple>i</font>][<font color=purple>4</font>] -(GRAVITY*time_step);
<font color=gray>//Code to make the balls bounce
</font>
<font color=gray>//Floor
</font>
<font color=blue>if</font> (parray[<font color=purple>i</font>][<font color=purple>1</font>]-parray[<font color=purple>i</font>][<font color=purple>6</font>] < 0)
{
<font color=gray>//Apply a random scaling factor to the bounce coefficient
</font>
bfact = (<font color=blue>float</font>(rand())/131070) + 0.75;
parray[<font color=purple>i</font>][<font color=purple>4</font>] = parray[<font color=purple>i</font>][<font color=purple>4</font>] * -(BOUNCE * bfact);
parray[<font color=purple>i</font>][<font color=purple>1</font>] = parray[<font color=purple>i</font>][<font color=purple>6</font>];
}
<font color=gray>//Left
</font>
<font color=blue>if</font> (parray[<font color=purple>i</font>][<font color=purple>0</font>]-parray[<font color=purple>i</font>][<font color=purple>6</font>] < -70)
{
parray[<font color=purple>i</font>][<font color=purple>3</font>] = -parray[<font color=purple>i</font>][<font color=purple>3</font>];
parray[<font color=purple>i</font>][<font color=purple>0</font>] = -70 + parray[<font color=purple>i</font>][<font color=purple>6</font>];
}
<font color=gray>//Right
</font>
<font color=blue>if</font> (parray[<font color=purple>i</font>][<font color=purple>0</font>]+parray[<font color=purple>i</font>][<font color=purple>6</font>] > 70)
{
parray[<font color=purple>i</font>][<font color=purple>3</font>] = -parray[<font color=purple>i</font>][<font color=purple>3</font>];
parray[<font color=purple>i</font>][<font color=purple>0</font>] = 70 - parray[<font color=purple>i</font>][<font color=purple>6</font>];
}
<font color=gray>//Back
</font>
<font color=blue>if</font> (parray[<font color=purple>i</font>][<font color=purple>2</font>]-parray[<font color=purple>i</font>][<font color=purple>6</font>] < -70)
{
parray[<font color=purple>i</font>][<font color=purple>5</font>] = -parray[<font color=purple>i</font>][<font color=purple>5</font>];
parray[<font color=purple>i</font>][<font color=purple>2</font>] = -70 + parray[<font color=purple>i</font>][<font color=purple>6</font>];
}
<font color=gray>//Front
</font>
<font color=blue>if</font> (parray[<font color=purple>i</font>][<font color=purple>2</font>]+parray[<font color=purple>i</font>][<font color=purple>6</font>] > 70)
{
parray[<font color=purple>i</font>][<font color=purple>5</font>] = -parray[<font color=purple>i</font>][<font color=purple>5</font>];
parray[<font color=purple>i</font>][<font color=purple>2</font>] = 70 - parray[<font color=purple>i</font>][<font color=purple>6</font>];
}
}
}
glutTimerFunc(40,Animate,1);
}
<font color=gray>//Called when visibility status changes
</font>
<font color=gray>//Sets the value passed by the timer
</font>
GLvoid Viz(<font color=blue>int</font> state)
{
<font color=blue>switch</font> (state)
{
<font color=blue>case</font> GLUT_VISIBLE:
Timer(1);
<font color=blue>break</font>;
<font color=blue>case</font> GLUT_NOT_VISIBLE:
Timer(0);
<font color=blue>break</font>;
<font color=blue>default</font>:
<font color=blue>break</font>;
}
}
<font color=gray>//Called when a key is pressed
</font>
<font color=gray>//X and Y are coords of mouse at keypress
</font>
<font color=blue>void</font> NormalKey(GLubyte key, GLint x, GLint y)
{
<font color=blue>int</font> i = 0;
<font color=blue>float</font> f,g,h,radius;
<font color=blue>switch</font> (key)
{
<font color=blue>case</font> ESCAPE :
glutDestroyWindow(window); <font color=gray>// Kill window
</font>
exit(0); <font color=gray>// Very dirty exit
</font>
<font color=blue>break</font>;
<font color=blue>case</font> ''g'' :
<font color=gray>//Seed the random generator
</font>
srand(time(0));
<font color=gray>//Populate the array with particles
</font>
<font color=blue>for</font> (i = 0; i < ARRMAX; i++)
{
<font color=gray>//Random float between -1 and 1
</font>
f = (<font color=blue>float</font>(rand())/16383.5) - 1 ;
g = (<font color=blue>float</font>(rand())/16383.5);
h = (<font color=blue>float</font>(rand())/16383.5) - 1 ;
<font color=gray>//Apply scaling factor to velocities
</font>
f=f*SCALE; g=g*SCALE; h=h*SCALE;
radius = (<font color=blue>float</font>(rand())/16383.5) + 1;
parray[<font color=purple>i</font>][<font color=purple>0</font>] = 0.0;
parray[<font color=purple>i</font>][<font color=purple>1</font>] = 12.0;
parray[<font color=purple>i</font>][<font color=purple>2</font>] = 0.0;
parray[<font color=purple>i</font>][<font color=purple>3</font>] = f;
parray[<font color=purple>i</font>][<font color=purple>4</font>] = g;
parray[<font color=purple>i</font>][<font color=purple>5</font>] = h;
parray[<font color=purple>i</font>][<font color=purple>6</font>] = radius;
}
<font color=blue>break</font>;
<font color=blue>case</font> ''m'' :
<font color=blue>if</font> (MatrixStylee)
MatrixStylee = 0;
<font color=blue>else</font>
MatrixStylee = 1;
<font color=blue>break</font>;
<font color=blue>case</font> ''r'' :
<font color=blue>if</font> (AutoRot)
AutoRot = 0;
<font color=blue>else</font>
AutoRot = 1;
<font color=blue>break</font>;
<font color=blue>default</font>:
<font color=blue>break</font>;
}
}
<font color=blue>void</font> SpecialKey(<font color=blue>int</font> key, <font color=blue>int</font> x, <font color=blue>int</font> y){
<font color=blue>switch</font>(key){
<font color=blue>case</font> GLUT_KEY_RIGHT:
cam_angle-=5;
<font color=blue>if</font>(cam_angle<0)
cam_angle=360;
<font color=blue>break</font>;
<font color=blue>case</font> GLUT_KEY_LEFT:
cam_angle+=5;
<font color=blue>if</font>(cam_angle>360)
cam_angle=0;
<font color=blue>break</font>;
<font color=blue>case</font> GLUT_KEY_UP:
cam_pitch-=1;
<font color=blue>if</font>(cam_pitch<0)
cam_pitch=360;
<font color=blue>break</font>;
<font color=blue>case</font> GLUT_KEY_DOWN:
cam_pitch+=1;
<font color=blue>if</font>(cam_pitch>360)
cam_pitch=0;
<font color=blue>break</font>;
<font color=blue>default</font>:
<font color=blue>break</font>;
}
<font color=blue>return</font>;
}
<font color=gray>// Main Code
</font>
<font color=gray>//————————
</font>
<font color=blue>int</font> WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
<font color=blue>int</font> nCmdShow)
{
<font color=gray>// Initialisation and window creation
</font>
<font color=gray>//glutInit(&argc, argv); // Initialize GLUT state.
</font>
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); <font color=gray>// RGB and Alpha, Single buffer, Z buffer (depth)
</font>
glutInitWindowSize(Xsize,Ysize); <font color=gray>// set initial window size.
</font>
glutInitWindowPosition(0,0); <font color=gray>// upper left corner of the screen.
</font>
window = glutCreateWindow(<font color=darkred>"OpenGL"</font>); <font color=gray>// Open a window with a title.
</font>
InitGL(Xsize,Ysize); <font color=gray>// Initialize our window.
</font>
<font color=gray>// Now register the various callback functions
</font>
glutDisplayFunc(DrawGLScene); <font color=gray>// Function to do all our OpenGL drawing.
</font>
glutReshapeFunc(ReSizeGLScene); <font color=gray>// Called when window is resized
</font>
glutKeyboardFunc(NormalKey); <font color=gray>// Normal key is pressed
</font>
glutSpecialFunc(SpecialKey); <font color=gray>// ''Special'' key is pressed
</font>
<font color=gray>//glutIdleFunc(DrawGLScene); // What to call when there''s spare time
</font>
glutTimerFunc(40,Timer,1); <font color=gray>// Call Timer in 40 ms
</font>
glutTimerFunc(400,Animate,1);
glutVisibilityFunc(Viz); <font color=gray>// Call Viz if visibility changes
</font>
<font color=gray>// Now drop into the event loop from which we never return
</font>
glutMainLoop(); <font color=gray>// Start Event Processing Engine
</font>
<font color=blue>return</font> 1;
}
</pre><!–ENDSCRIPT–>