我剛開始試圖從簡單的「繪製立方體」openGl tutorial。在獲得OpenGL的最終勝利後,我仍然有非常奇怪的結果。我的問題是,對象傾向於調整自己以匹配窗口大小。相反,我希望窗口大小決定渲染區域 - 窗口越大,您可能會看到的越多。OpenGL座標是什麼?忽略OpenGL的窗口大小
這裏是調整的一些截圖:
Normal size
Resized
圖像保存爲有意聯繫!
這個自動調整行爲帶來了一個問題,在OpenGL中使用的座標是什麼。
我剛開始試圖從簡單的「繪製立方體」openGl tutorial。在獲得OpenGL的最終勝利後,我仍然有非常奇怪的結果。我的問題是,對象傾向於調整自己以匹配窗口大小。相反,我希望窗口大小決定渲染區域 - 窗口越大,您可能會看到的越多。OpenGL座標是什麼?忽略OpenGL的窗口大小
這裏是調整的一些截圖:
Normal size
Resized
圖像保存爲有意聯繫!
這個自動調整行爲帶來了一個問題,在OpenGL中使用的座標是什麼。
首先要記住的是: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);
哦,只是在一個普遍的說法:你應該總是設置視圖和投影設置的繪圖功能。如果你看到那些把報表窗口大小調整處理程序的教程,只是忽略它,只是做在繪圖代碼反正。從長遠來看,這真的可以簡化事情。
我喜歡你的一般說明,但我的問題是我絕對沒有想法,如何獲得窗口尺寸(將谷歌,但我害怕新的邪惡功能,準備告訴我我是多麼的跛腳)和還有如何應用gluPerspective(發現在等待回覆的互聯網上),這隻需要widht /高度 - 因此調整大小會導致縮放(也許一些翻譯可以使用,但是這是正確的?)。 –
好吧,genpfault發佈了你的解釋,所以我的資源是完整的。謝謝:) –
@TomášZato:窗口尺寸超出了OpenGL的範圍。您可能正在使用像GLFW,GLUT或SDL這樣的框架(您鏈接的教程使用GLUT)。 glutGet(GLUT_WINDOW_WIDTH)和glutGet(GLUT_WINDOW_HEIGHT)是你正在尋找的。 – datenwolf
有趣的部分:
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;
}
謝謝!在這段代碼中我有很多靈感:)我會嘗試應用它。 –
請問爲什麼glMatrixMode被調用兩次?爲什麼窗口大小除以300? –
一次切換到投影矩陣堆棧,一次切換到模型視圖堆棧。你在技術上可以通過一個[但你真的不應該這樣做](http://sjbaker.org/steve/omniv/projection_abuse.html)。 GLUT默認爲300x300像素的窗口(並且你沒有通過'glutInitWindowSize()'重寫),所以我認爲這是你想要保持的大小。 – genpfault
看一看這個[問題](http://stackoverflow.com/questions/15536333/keeping-a-square -clipping體積平方無論-的視口尺寸式的OpenGL/15536710#15536710)。我認爲它解決了你的問題。 – radical7