2013-03-31 63 views
0

我剛開始試圖從簡單的「繪製立方體」openGl tutorial。在獲得OpenGL的最終勝利後,我仍然有非常奇怪的結果。我的問題是,對象傾向於調整自己以匹配窗口大小。相反,我希望窗口大小決定渲染區域 - 窗口越大,您可能會看到的越多。OpenGL座標是什麼?忽略OpenGL的窗口大小

這裏是調整的一些截圖:
Normal size
Resized
圖像保存爲有意聯繫!

這個自動調整行爲帶來了一個問題,在OpenGL中使用的座標是什麼。

+0

看一看這個[問題](http://stackoverflow.com/questions/15536​​333/keeping-a-square -clipping體積平方無論-的視口尺寸式的OpenGL/15536​​710#15536​​710)。我認爲它解決了你的問題。 – radical7

回答

2

首先要記住的是:OpenGL是一個繪圖API。它不保留一個場景或類似的東西。

因此,OpenGL所做的是將幾何輸入座標以頂點屬性的形式映射到屏幕空間。在舊的固定函數中,有一個叫做「頂點位置」的特殊頂點屬性,或者只是簡短的「頂點」(實際頂點不僅僅是位置)。

位置被轉換成在一個三步工藝窗口空間:

1.轉化成圖/眼空間:這是通過與模型視圖矩陣頂點位置相乘完成。

某些進一步的計算,如照度計算在視圖空間中完成。

2.轉換爲剪輯空間:將視圖空間位置轉換爲剪輯空間。這通常被稱爲投影和恰當地描述這種轉變的矩陣被稱爲投影矩陣

剪裁空間一些特殊的事情發生,概括爲剪裁,你不擔心呢。

3.在最後一步中,將修剪後的幾何圖形轉換爲標準化設備座標(NDC)。 NDC空間實際上是朝向視口的1:1映射,即,NDC體積的界限直接對應於使用glViewport設置的視口的偏移量和維度。

你不能改變的第三步發生的方式,第1步是保留的東西轉化成視覺空間。所以任何調整都必須在第二步中進行。

所以,你需要做的是:投影限制必須與視口範圍成正比。像這樣的例子

glViewport(0, 0, width, height); 
glMatrixMode(GL_PROJECTION); 
glLoadIdentity(); 
glOrtho(-width/2, width/2, -height/2, height/2, -1, 1); 

哦,只是在一個普遍的說法:你應該總是設置視圖和投影設置的繪圖功能。如果你看到那些把報表窗口大小調整處理程序的教程,只是忽略它,只是做在繪圖代碼反正。從長遠來看,這真的可以簡化事情。

+0

我喜歡你的一般說明,但我的問題是我絕對沒有想法,如何獲得窗口尺寸(將谷歌,但我害怕新的邪惡功能,準備告訴我我是多麼的跛腳)和還有如何應用gluPerspective(發現在等待回覆的互聯網上),這隻需要widht /高度 - 因此調整大小會導致縮放(也許一些翻譯可以使用,但是這是正確的?)。 –

+0

好吧,genpfault發佈了你的解釋,所以我的資源是完整的。謝謝:) –

+1

@TomášZato:窗口尺寸超出了OpenGL的範圍。您可能正在使用像GLFW,GLUT或SDL這樣的框架(您鏈接的教程使用GLUT)。 glutGet(GLUT_WINDOW_WIDTH)和glutGet(GLUT_WINDOW_HEIGHT)是你正在尋找的。 – datenwolf

1

有趣的部分:

glMatrixMode(GL_PROJECTION); 
glLoadIdentity(); 
double w = glutGet(GLUT_WINDOW_WIDTH)/300.0; 
double h = glutGet(GLUT_WINDOW_HEIGHT)/300.0; 
glOrtho(-1 * w, 1 * w, -1 * h, 1 * h, 10, -10); 

glMatrixMode(GL_MODELVIEW); 
glLoadIdentity(); 

在背景:

#include <GL/glut.h> 

void display(); 
void specialKeys(); 

double rotate_y=0; 
double rotate_x=0; 

void display(){ 
    // Clear screen and Z-buffer 
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); 

    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    double w = glutGet(GLUT_WINDOW_WIDTH)/300.0; 
    double h = glutGet(GLUT_WINDOW_HEIGHT)/300.0; 
    glOrtho(-1 * w, 1 * w, -1 * h, 1 * h, 10, -10); 

    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 

    // Rotate when user changes rotate_x and rotate_y 
    glRotatef(rotate_x, 1.0, 0.0, 0.0); 
    glRotatef(rotate_y, 0.0, 1.0, 0.0); 

    //Multi-colored side - FRONT 
    glBegin(GL_POLYGON); 

    glColor3f(1.0, 0.0, 0.0);  glVertex3f( 0.5, -0.5, -0.5);  // P1 is red 
    glColor3f(0.0, 1.0, 0.0);  glVertex3f( 0.5, 0.5, -0.5);  // P2 is green 
    glColor3f(0.0, 0.0, 1.0);  glVertex3f(-0.5, 0.5, -0.5);  // P3 is blue 
    glColor3f(1.0, 0.0, 1.0);  glVertex3f(-0.5, -0.5, -0.5);  // P4 is purple 

    glEnd(); 

    // White side - BACK 
    glBegin(GL_POLYGON); 
    glColor3f( 1.0, 1.0, 1.0); 
    glVertex3f( 0.5, -0.5, 0.5); 
    glVertex3f( 0.5, 0.5, 0.5); 
    glVertex3f(-0.5, 0.5, 0.5); 
    glVertex3f(-0.5, -0.5, 0.5); 
    glEnd(); 

    // Purple side - RIGHT 
    glBegin(GL_POLYGON); 
    glColor3f( 1.0, 0.0, 1.0); 
    glVertex3f(0.5, -0.5, -0.5); 
    glVertex3f(0.5, 0.5, -0.5); 
    glVertex3f(0.5, 0.5, 0.5); 
    glVertex3f(0.5, -0.5, 0.5); 
    glEnd(); 

    // Green side - LEFT 
    glBegin(GL_POLYGON); 
    glColor3f( 0.0, 1.0, 0.0); 
    glVertex3f(-0.5, -0.5, 0.5); 
    glVertex3f(-0.5, 0.5, 0.5); 
    glVertex3f(-0.5, 0.5, -0.5); 
    glVertex3f(-0.5, -0.5, -0.5); 
    glEnd(); 

    // Blue side - TOP 
    glBegin(GL_POLYGON); 
    glColor3f( 0.0, 0.0, 1.0); 
    glVertex3f( 0.5, 0.5, 0.5); 
    glVertex3f( 0.5, 0.5, -0.5); 
    glVertex3f(-0.5, 0.5, -0.5); 
    glVertex3f(-0.5, 0.5, 0.5); 
    glEnd(); 

    // Red side - BOTTOM 
    glBegin(GL_POLYGON); 
    glColor3f( 1.0, 0.0, 0.0); 
    glVertex3f( 0.5, -0.5, -0.5); 
    glVertex3f( 0.5, -0.5, 0.5); 
    glVertex3f(-0.5, -0.5, 0.5); 
    glVertex3f(-0.5, -0.5, -0.5); 
    glEnd(); 

    glFlush(); 
    glutSwapBuffers(); 
} 

void specialKeys(int key, int x, int y) { 
    // Right arrow - increase rotation by 5 degree 
    if (key == GLUT_KEY_RIGHT) 
    rotate_y += 5; 

    // Left arrow - decrease rotation by 5 degree 
    else if (key == GLUT_KEY_LEFT) 
    rotate_y -= 5; 

    else if (key == GLUT_KEY_UP) 
    rotate_x += 5; 

    else if (key == GLUT_KEY_DOWN) 
    rotate_x -= 5; 

    // Request display update 
    glutPostRedisplay(); 
} 

int main(int argc, char* argv[]){ 
    // Initialize GLUT and process user parameters 
    glutInit(&argc,argv); 

    // Request double buffered true color window with Z-buffer 
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); 

    // Create window 
    glutCreateWindow("Awesome Cube"); 

    // Enable Z-buffer depth test 
    glEnable(GL_DEPTH_TEST); 

    // Callback functions 
    glutDisplayFunc(display); 
    glutSpecialFunc(specialKeys); 

    // Pass control to GLUT for events 
    glutMainLoop(); 

    // Return to OS 
    return 0; 
} 
+0

謝謝!在這段代碼中我有很多靈感:)我會嘗試應用它。 –

+0

請問爲什麼glMatrixMode被調用兩次?爲什麼窗口大小除以300? –

+0

一次切換到投影矩陣堆棧,一次切換到模型視圖堆棧。你在技術上可以通過一個[但你真的不應該這樣做](http://sjbaker.org/steve/omniv/projection_abuse.html)。 GLUT默認爲300x300像素的窗口(並且你沒有通過'glutInitWindowSize()'重寫),所以我認爲這是你想要保持的大小。 – genpfault