How to fix a light source in OpenGL while rotating an object?

I have glutSolidTeapot (which has its own surface normals automatically generated according to opengl.org) and a light source emitting scattered light. The problem arises when I try to turn the kettle: it seems that the light source is also turning, not remaining in the same position in which I determined it (it essentially follows the teapot). As you can see in my code, I only change the position of the lighting during initialization, so it does not undergo glRotatef (), since it is called after setting the position of the light.

Despite many hours trying to solve this problem, I really do not know what this behavior can be explained.

Insert glEnable (GL_NORMALIZE); initialization also does not solve the problem.

I think that the desired result should be a teapot with a shiny right side (because the light comes from this direction), regardless of what angle the teapot rotates.

If you want to test my code, press the Spacebar to rotate the kettle.

#include <math.h>
#include <stdlib.h>

#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
#include <windows.h>     
#endif

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>     

void onInitialization( ) { //creating the light source
 glEnable(GL_LIGHTING);
 glEnable(GL_DEPTH_TEST); 

 GLfloat diffuse[]={0.8, 0.8, 0.8, 1.0};
 GLfloat pos[]={0.5, 0.0, 0.8, 0.0};

 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
 glLightfv(GL_LIGHT0, GL_POSITION, pos);

 glEnable(GL_LIGHT0);

 glRotatef(-90, 1, 0, 0); //we want to see the top of the teapot
}

void onDisplay( ) {
    glClearColor(0.1f, 0.2f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

 //rotating on every frame (for testing purposes only)
 glRotatef(5, 0,1,0);
 glutSolidTeapot(0.4);

    glFinish();
    glutSwapBuffers();
}


void onKeyboard(unsigned char key, int x, int y) {
 if (key==32){ //do rotation upon hitting the Space key
  glutPostRedisplay();
 }
}

int main(int argc, char **argv) {
    glutInit(&argc, argv); 
    glutInitWindowSize(600, 600);
    glutInitWindowPosition(100, 100);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
    glutCreateWindow("Teapot");

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    onInitialization();

    glutDisplayFunc(onDisplay);
    glutKeyboardFunc(onKeyboard);

    glutMainLoop();

    return 0;
}
+5
source share
6 answers

I think change

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

to

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

is a good place to start.

+2
source

I also believe that your application "destroys" the model representation of the matrix; it was never recounted from scratch. You should start each frame using LoadIdentity (), then emit a light source, then rotate as desired and finally emit geometry.

, , , lalalalalalalala , .

glLoadIdentity(), , , , . , -hello-world , , ( (-v), (), (v)), , , "load identity, place light" , , .

, .

+1

.

+1

. , OnLoad ... , . #, OpenTK, , .:)

- , , . ( LookAt), . , : , .:) , , . .

protected override void OnRenderFrame(FrameEventArgs e)
 {
        base.OnRenderFrame(e);

        GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
        System.Threading.Thread.Sleep(10); //useful thing to lower CPU usage

        //I can set the eye position at runtime, it not necessary to have this
        modelview = Matrix4.LookAt(this.eye, Vector3.Zero, Vector3.UnitY);

        GL.MatrixMode(MatrixMode.Modelview);                       
        GL.LoadMatrix(ref modelview);           

        //**this is the key - you have to set the light position every time**
        GL.Light(LightName.Light0, LightParameter.Position, new float[4] { 1000, 1000, 0, 0 });


        // We don't want the walls to rotate so we push the current matrix
        GL.PushMatrix();

         GL.Rotate(move, Vector3.UnitY);
         move += 0.5f;

         GL.Color3(1.0f, 1.0f, 1.0f);

           GL.Begin(BeginMode.Triangles);
           //the object that will rotate             
           GL.End();
        GL.PopMatrix();              


        GL.Begin(BeginMode.Quads);
        //some quads (walls) in the background that will stay still
        GL.End();                                                

        SwapBuffers();
    }

, , , , . , .

+1

:

ModelView , glLight *().

, - " "; , . ; , .

, "" ; . LoadIdentity(), , , , .

0

, glLoadIdentity() , .

, , - :

glLoadIdentity();

// first object
glPushMatrix();
glTranslate(...);
glRotate(...)
glPopMatrix();

// second object
glPushMatrix();
glTranslate(...);
glRotate(...);
glPopMatrix();
0

All Articles