opengl三維觀察

2021-07-25 07:14:13 字數 4522 閱讀 5571

1.      相機

產生目標場景檢視的變換過程類似於用照相機進行拍照。用照相機進行拍照的步驟大致如下:

·把照相機固定在三腳架上,並讓它對準場景(檢視變換);

·對場景進行安排,使各個物體在**中的位置是我們所希望的(模型變換)

·選擇照相機鏡頭,並調整放大倍數(投影變換)

·確定最終**的大小(視口變換)

完成這些步驟之後,就可以進行拍照(或者繪製場景)了。

2.      投影方式

opengl提供了兩種投影方式:正射投影和透視投影。

a)      正射投影(orthographic projection)

又叫平行投影。這種投影的視景體是乙個矩形的平行管道,因此無論物體距離相機多遠,投影之後物體的大小尺寸不變。這也正是為什麼在正射投影模式下前後移動茶壺看不出來。此種模式下,不需要設定照相機位置、方向以及視點的位置,也就是說不需要glulookat函式。

正射投影函式void glortho(gldoubleleft, gldouble right, gldouble bottom, gldouble top, gldouble near, gldoublefar)建立乙個平行視景體,實際上這個函式的操作是建立乙個正射投影矩陣,並且用這個矩陣乘以當前矩陣。其中近裁剪平面是乙個矩陣,矩形左下角點三維空間座標是(left, bottom,-near),右上角點(right, top,-near);遠裁剪平面也是乙個矩形,左下角點空間座標是(left, bottom,far),右上角點是(right, top,-far)。所有的near和far值同時為正或者同時為負,物體在視點後面時far和near都為正值。

b)      透視投影(perspective projection)

透視投影符合人的心理習慣,即離視點近的物體大,離視點遠的物體小,遠到極點即為消失,成為滅點。它的視景體類似於乙個頂部和底部被切除掉的稜錐,也就是稜臺。

透視投影函式voidgluperspective(gldouble fovy, gldouble aspect, gldouble znear, gldouble zfar),建立乙個對稱透視視景體。其操作是建立乙個對稱的透視投影矩陣,並且用這個矩陣乘以當前矩陣。引數fovy定義視野在x-z平面的角度,範圍是[0.0,180.0];引數aspect是投影平面寬度與高度的比率;引數znear和far分別是遠近裁剪面到眼睛的距離,它們總為正值。

3.      深度測試

深度其實就是畫素點在3d世界中距離攝像機的距離,深度快取中儲存著每個畫素點的深度之,深度值越大,則離攝像機越遠。

在不使用深度測試的時候,如果我們先繪製乙個距離較近的物體,再繪製距離較遠的物體,則距離遠的物體因為後繪製,會把距離近的物體覆蓋掉,這不符合現實世界表現。而有了深度緩衝以後,繪製物體的順序就不那麼重要了,都能夠按照遠近順序進行現實。

啟用深度測試的**如下:

glenable(

gl_depth_test

);//

啟用深度測試,根據座標遠近自動隱藏被遮住的物體

4.      設定光源

沒有光照效果的物體看起來是二維的,沒有立體的感覺。通過新增光照,更容易表現三維的物體。

在opengl中,僅支援有限數量的光源。gl_light0~7f分別代表八個光源。使用glenable函式可以開啟它們,例如:

glenable(

gl_lighting

);//

啟用燈光

gllightfv函式具有三個引數,第乙個引數指明設定哪乙個光源的屬性,第二個引數指明設定該光源的哪個屬性,第三個引數則是指明把該屬性值設定成多少。gl_ambient屬性表示該光源發出的光,經過非常多次的反射後,最終遺留在整個光照環境中的顏色。gl_position屬性表示光源所在的位置。同樣適用glenable函式開啟光源。

glfloat

white = ;

glfloat

light_pos = ;

//在opengl

中總共可以設定

8個光源

gllightfv(

gl_light0

, gl_position

, light_pos);

//設定

0號光源的位置屬性

gllightfv(

gl_light0

, gl_ambient

, white);

//設定

0號光源的環境光屬性

glenable(

gl_light0

);//啟用0

號光源

4.      在控制整體進行上下左右移動的時候,我想到了幾種解決方案:

i.           相機在世界座標系中右移,即eye[0]+=0.1f。

ii.           物體在世界座標系中左移,即center[0]+=0.1f.

figure 1 i操作方式

在上圖所示的解決方案中,隨著視點右移,物體呈現出旋轉的效果,但是位置仍然位於整個視野**。

figure 2 ii操作方式

在上圖所示的解決方案中,隨著物體的左移,它在視野中的位置的確也向左移動了,但是此時不再是正視,而是略微傾斜。

以上兩種解決辦法都沒有達到我想要的效果,於是我將二者進行結合,在改變物體位置的同時改變視點,效果如下圖:

float ftranslate;//整體平移因子

float frotate = 0.0f;//整體旋轉因子

float trotate = 0.0f;//茶壺旋轉因子

bool tanim = false;//茶壺旋轉

bool bpersp = false;//渲染

bool banim = false;//整體旋轉

bool bwire = false;//填充、線框

int wheight = 0;

int wwidth = 0;

float place = ;

void draw_leg()

void draw_scene()

void updateview(int width, int height)

void reshape(int width, int height)

wheight = height;

wwidth = width;

updateview(wheight, wwidth);

}void idle()

float eye = ;

float center = ;

void key(unsigned char k, int x, int y)

//退出

case 'p': //切換投影方式

case ' ': //空格控制旋轉

case 'o': //o控制顯示模式:填充\線框

case 'a':

case 'd':

case 'w':

case 's':

case 'z':

case 'c':

//茶壺相關操作

case 'l':

case 'j':

case 'i':

case 'k':

case 'e': }}

void redraw()

; glfloat light_pos = ;

//在opengl中總共可以設定8個光源

gllightfv(gl_light0, gl_position, light_pos);//設定0號光源的位置屬性

gllightfv(gl_light0, gl_ambient, white);//設定0號光源的環境光屬性

glenable(gl_light0);//啟用0號光源

// gltranslatef(0.0f, 0.0f,-6.0f); // place the ******** at center

glrotatef(frotate, 0, 1.0f, 0); // rotate around y axis

glrotatef(-90, 1, 0, 0);//繞x軸逆時針90

glscalef(0.2, 0.2, 0.2);

draw_scene(); // draw scene

if (banim)

frotate += 0.5f;//旋轉

if (tanim)

trotate += 0.5f;

glutswapbuffers();//交換緩衝區

}int main (int argc, char *argv)

如有錯誤,請批評指正(*/ω╲*)

opengl三維程式設計

void gluperspective gldouble fovy,gldouble aspect,gldouble znear,gldouble zfar 引數fovy定義視野在x z平面的角度取值是 0.0,180.0 引數aspect是投影平面寬度與高度的比率 引數znear和zfar分別是近...

opengl三維幾何變換例項

include intmain int argc,char ar void display void init 以下例子加入到display方法中即可執行 opengl三維旋轉 繞平行於座標軸的軸旋轉 此例為原點繞經過 0,0,5 垂直於xz平面的旋轉軸進行旋轉 glmatrixmode gl mo...

QT與OpenGL之三維旋轉

效果 由於上傳大小的限制,只能製作短暫的效果。在開始前,你應該在pro中新增 libs glut.libglut32.lib 同時你也應該將這兩個庫加到qt的bin目錄下。glwidget.h ifndef glwidget h define glwidget h include include n...