2009-11-18 84 views
5

我有一個glutSolidTeapot(它的表面法線根據opengl.org自動生成)和一個發出漫射光的光源。當我嘗試旋轉茶壺時,問題就出現了:它看起來像光源也在旋轉,而不是保持在我定義的相同位置(它基本上遵循茶壺)。正如你在我的代碼中看到的那樣,我只是在初始化時修改了光照位置,所以它不會受到glRotatef()的影響,因爲它在之後調用設置光源位置。如何在旋轉對象時在OpenGL中注入光源?

儘管花了很多時間試圖解決這個問題,我真的不知道這種行爲可以歸因於什麼。

粘貼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; 
} 
+0

我會手動旋轉點而不使用glRotate!這會有點煩人,但那會100%解決你的問題。我自己也遇到了這個問題,找不到任何其他解決方案。 – 2012-03-16 06:20:09

回答

2

我想改變

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

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

是一個良好的開端。

+0

謝謝,你幫了很多。 – kahoon 2009-11-18 19:07:05

+5

問題是最後一個MatrixMode保持活動狀態。 – Andreas 2009-12-01 14:24:43

0

FAQ states

的光的位置由 當前模型視圖矩陣在 時間的位置與 調用glLight *(指定)變換。

換句話說,燈光沒有定位在某種魔術靜態的「世界座標系」中;就像任何幾何圖形一樣,它們乘以模型視圖矩陣。這是有道理的;你經常想讓燈鎖定在幾何體上。

我也認爲你的應用程序「破壞」模型視圖矩陣;它從來沒有從頭開始重新計算。您應該使用LoadIdentity()開始每個幀,然後發射光源,然後根據需要旋轉,最後發射幾何。

+0

如果模型視圖矩陣被破壞,我認爲我使用的旋轉不起作用。無論如何,我嘗試了你的建議(再次,因爲我以前嘗試過這樣的事情),但它沒有奏效。我知道光的位置乘以當前的矩陣,但它們只能在初始化時相乘,並且從來沒有,因爲我沒有碰它。 – kahoon 2009-11-18 18:27:25

1

我也認爲你的應用程序「破壞」模型視圖 矩陣;它從來沒有從頭開始重新計算。你應該在 之間用LoadIdentity()開始每個幀,然後發射光源,然後根據需要旋轉,最後發射 幾何。

這不行,這不行,這不行,lalalalalalalala和常見問題是公然錯誤,簡單明瞭。

只有在glLoadIdentity()後面發光才能獲得攝像機綁定的光線,在僅轉換或僅旋轉原點周圍的模型的簡單情況下可以工作。但是,當你開始做非平凡的,非喜歡的事物時,例如圍繞不同於原點的點旋轉對象(translate(-v),rotate(angle),translate(v)),然後移動它,使旋轉中心被帶到相機的前面,然後「負載標識,地點燈」技術開始失敗壯觀和在很多方面,使得很難推斷甚至正在進行。

不,我不知道解決方案。

0

在我看來你應該做的不僅是在渲染例程開始時調用glLoadIdentity(),而且還要推動和彈出模型視圖矩陣。

用於與全局固定光源和其自主承擔定位並旋轉該僞代碼將執行特技兩個對象的場景:

glLoadIdentity(); 

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

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

我正在那樣做,但燈光仍在移動。此外,我正在做什麼說在其他答案:( – 2010-07-11 18:00:43

1

嘗試手動每個頂點設置正常值。

1

我遇到了同樣的問題,並得到了解決方案。問題是,我設置的燈光位置只有OnLoad程序的一部分...我認爲這是最好的張貼一些代碼。我在C#中使用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'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(); 
    } 

我把這個從我的程序,並刪除了很多東西,在這裏不重要,所以也許這看起來有點怪異。我希望它有幫助。