5

我有一个 glutSolidTeapot(根据 opengl.org 自动生成其表面法线)和一个发射漫射光的光源。当我尝试旋转茶壶时,问题就出现了:光源似乎也在旋转,而不是保持在我定义的相同位置(它基本上跟随茶壶)。正如您在我的代码中看到的,我只在初始化时修改光照位置,因此它不受 glRotatef() 的影响,因为它在设置光照位置后调用。

尽管花了很多时间试图解决这个问题,但我真的不知道这种行为可以归因于什么。

粘贴 glEnable(GL_NORMALIZE); 在初始化中也没有解决问题。

我认为所需的输出应该是右侧有光泽的茶壶(因为光线来自那个方向),无论茶壶旋转什么角度。

如果您想测试我的代码,请按空格键旋转茶壶。

#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;
}
4

6 回答 6

2

我认为改变

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

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

是一个很好的起点。

于 2009-11-18T18:41:32.813 回答
2

我还认为您的应用程序“破坏”了模型视图矩阵;它永远不会从头开始重新计算。您应该以 LoadIdentity() 开始每一帧,然后发射光源,然后根据需要旋转,最后发射几何图形。

这不起作用,这不起作用,这不起作用,lalalalalalalala,FAQ显然是错误的,简单明了。

当您仅平移或仅围绕原点旋转模型时,在 glLoadIdentity() 之后发射光以获得相机绑定光将在简单的情况下起作用。但是当你开始做一些非平凡的、非你好世界的事情时,比如围绕一个与原点不同的点(translate(-v)、rotate(angle)、translate(v))旋转一个对象,然后移动它以便旋转中心被带到摄像机前,然后“加载标识,放置灯光”技术开始严重失败,并且很难推断出正在发生的事情。

不,我不知道解决方案。

于 2009-12-06T13:09:12.877 回答
1

尝试手动设置每个顶点的正常值。

于 2012-02-12T13:26:08.857 回答
1

我遇到了同样的问题并得到了解决方案。问题是我在程序的OnLoad部分设置了灯光位置......我认为最好发布一些代码。我使用 OpenTK 在 C# 中工作,因为我知道我永远不会进入图形业务。:)

结果是一个茶壶或其他一些物体随着具有固定位置的光而旋转。我可以移动眼睛位置(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's 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();
    }

我从我的程序中取出了这个并删除了很多在这里不重要的东西,所以它看起来有点奇怪。我希望它有所帮助。

于 2012-02-20T19:53:20.437 回答
0

常见问题解答指出

在调用 glLight*() 指定位置时,当前 ModelView 矩阵会转换灯光的位置。

换句话说,灯光没有定位在某种神奇的静态“世界坐标系”中;就像任何几何图形一样,它们乘以模型视图矩阵。这是有道理的;您经常希望将灯光锁定到几何体。

我还认为您的应用程序“破坏”了模型视图矩阵;它永远不会从头开始重新计算。您应该以 LoadIdentity() 开始每一帧,然后发射光源,然后根据需要旋转,最后发射几何图形。

于 2009-11-18T18:18:18.877 回答
0

在我看来,您应该做的不仅是在渲染例程开始时调用 glLoadIdentity(),而且还要推送和弹出模型视图矩阵。

对于具有全局固定光源和两个独立定位和旋转的对象的场景,此伪代码可以解决问题:

glLoadIdentity();

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

// second object
glPushMatrix();
glTranslate(...);
glRotate(...);
glPopMatrix();
于 2009-12-08T15:29:39.307 回答