-1

Situation: I'm making a lighting example using OpenGL. My goal is that, there will be 20 random colored spheres, a cube and three light source as you see picture below.

https://i.stack.imgur.com/b4uwu.png

Problem: The cube you see above affected by light sources only when I remove the pushMatrix and Popmatrix, but as you see the spheres affected smoothly by these three light sources(red,green and blue). Color of the Cube is changing because of the reasons I couldn't realize. I have to make this cube affected by three light sources like spheres and always white colored.

Code Parts:

This is the meteor's draw method;

void meteor::draw(){

glPushMatrix();

   glTranslatef(posx,posy,posz);
   glutSolidSphere(radious,40,20);


   GLfloat MaterialColor[] = {red, green, blue, 1.0};
   GLfloat ambientColor[] = {red, green, blue, 1.0}; 

       glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambientColor);
   glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor);



glPopMatrix();

}

This is the cube's draw method;

void Ship::draw(){
 glPushMatrix();

   glTranslatef (posx, posy, 95.0);
   glutSolidCube(5.0);

       glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, MaterialColor1);
   glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor1);

 glPopMatrix();

}

And this is the display method that draws all the objects on the screen:

void display (void)
{
   GLfloat position0[] = { 8.0, -10.0, 100.0, 1.0}; //red
   GLfloat position1[] = { -8.0, -10.0, 100.0, 1.0};
   GLfloat position2[] = { 0.0, 10.0, 100.0, 1.0};

  GLfloat LightColor[]=  {1.0f,0.0f,0.0f};//red
    GLfloat LightColor1[]= {0.0f,1.0f,0.0f};//green
    GLfloat LightColor2[]= {0.0f,0.0f,1.0f};//blue

glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glPushMatrix();

   gluLookAt (0.0, 0.0, 500.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);   


glPushMatrix();

            glLightfv (GL_LIGHT0, GL_POSITION, position0);
            glLightfv (GL_LIGHT0, GL_DIFFUSE, LightColor);



            glLightfv (GL_LIGHT1, GL_POSITION, position1);
            glLightfv (GL_LIGHT1, GL_DIFFUSE, LightColor1);


            glLightfv (GL_LIGHT2, GL_POSITION, position2);
            glLightfv (GL_LIGHT2, GL_DIFFUSE, LightColor2);


  //This is where the spheres are drawn
            for(iter1 = objects.begin(); iter1 != objects.end(); ++iter1)
                        {

                            (*iter1)->draw();


                        }
 //This is where the spheres are drawn

              shipCan->draw();



glPopMatrix ();

glPopMatrix();

glFlush();
}

If you want to see the rest of the code, I can supply it.

Erdi İzgi
  • 1,262
  • 2
  • 15
  • 33
  • I find the answer. Because of my reputation,after 8 hours I will be able to write the solution that i've found. – Erdi İzgi Dec 14 '13 at 21:51
  • Let me guess, you found that you've to tesselate down the cube, because using the fixed function pipeline illumination is calculated only at the vertices? I strongly suggest you learn how to do modern OpenGL programming. It's far easier in the end. Here's an excellent tutorial http://arcsynthesis.org/gltut – datenwolf Dec 15 '13 at 01:20
  • @datenwolf You are right, its close your solution but the mistake wasn't only my cube, spheres had the same problem. I will learn modern OpenGL no doubt. The link is very useful. Very appreciated :) – Erdi İzgi Dec 15 '13 at 10:52

1 Answers1

0

I find the answer. Everybody should understand the OpenGL rendering pipeline first. OpenGL works like a state machine. For example if you define a color before drawing sth on the screen, it sends its information to Graphic Card. And all the objects takes this color. If you don't change this color before drawing another object, the color will remain as the same.

I move all the glMaterialFv functions to outside the glPushMatrix() functions like that:

Before:

void meteor::draw(){

glPushMatrix();

glTranslatef(posx,posy,posz);
glutSolidSphere(radious,40,20);


GLfloat MaterialColor[] = {red, green, blue, 1.0};
GLfloat ambientColor[] = {red, green, blue, 1.0}; 

   glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambientColor);
   glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor);



glPopMatrix();

 }

Now:

void meteor::draw(){

 GLfloat MaterialColor[] = {red, green, blue, 1.0};
  GLfloat ambientColor[] = {red, green, blue, 1.0}; 

   glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambientColor);
   glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor);

glPushMatrix();

glTranslatef(posx,posy,posz);
glutSolidSphere(radious,40,20);

glPopMatrix();

 }

With this change, I send the material information to graphic card and then draw. So there is no mistake on the screen.

Erdi İzgi
  • 1,262
  • 2
  • 15
  • 33