OpenGL 圖元、 正背面剔除撩鹿、深度測試(四)


1谦炬、基本圖元連接方式

?

圖元primitive,即圖形元素节沦,是可以編輯的最小圖形單位键思。圖元是圖形軟件用于操作和組織畫面的最基本的素材。一幅畫面由圖元組成甫贯,圖元是一組最簡單的吼鳞、最通用的幾何圖形或字符。

OpenGL的基本圖元有點(Point)叫搁、線段(Line)赔桌、多邊形(Ploygon)供炎、三角形(Triangle)、四邊形(Quadrangle)疾党。

線段又分為獨立線段音诫、不閉合的線(Line Strip)和首尾閉合的線(Line Loop)。

三角形分為獨立三角形雪位、三角形鏈(Triangle Strip)和三角扇形(Triangle Fan)竭钝。

四邊形則分為獨立的四邊形和四邊形鏈(Quadrangle Strip)。

多邊形Polygon可以看成是三角形帶GL_TRIANGLE_TRIPE組成雹洗。

圖元 描述
GL_POINTS 每個頂點在屏幕上都是單獨點
GL_LINES 每?對頂點定義?個線段
GL_LINE_STRIP 從第?個頂點依次經過各個后續(xù)頂點的線段
GL_LINE_LOOP 和GL_LINE_STRIP相同香罐,但是最后?個頂點和第?個頂點連接起來了
GL_POLYGON 按點的定義順序依次連接
GL_TRIANGLES 每3個頂點定義?個新的三?形,三角形之間是獨立的
GL_TRIANGLE_STRIP 共??個條帶(strip)上的頂點的?組三?形
GL_TRIANGLE_FAN 以?個圓點為中?呈扇形排列,共?相鄰頂點的?組三?形
primitive_1.png

?

三角形帶时肿、三角形扇

相對于GL_TRIANGLES庇茫,當我們會需要繪制?個相連的三角形時,我們可以使用GL_TRIANGLE_STRIP圖元繪制?串相連三?角形嗜侮,從?節(jié)省?量的時間港令。

優(yōu)點:
用前3個頂點指定第1個三角形之后,對于接下來的每?個三角形锈颗,只需要再指定1個頂點顷霹。需要繪制?量的三?形時,采用這種?方法可以節(jié)省?量的程序代碼和數(shù)據(jù)存儲空間击吱。
提供運算性能和節(jié)省帶寬淋淀。更少的頂點意味著數(shù)據(jù)從內存?zhèn)鬏數(shù)綀D形卡的速度更快,并且頂點著?器需要處理的次數(shù)也更少了覆醇。

primitive_2.png

primitive_3.png

2朵纷、正背面剔除(Face Culling)

?

在繪制一個3D場景的時候,處于對性能和實際情況的考慮永脓,我們是不是應該決定哪些部分是對觀察者可見的部分袍辞,哪些是觀察者不可見的部分,而不可見的部分常摧,我們是不是不應該渲染搅吁,這樣符合實際情況,也節(jié)省了性能落午。這種情況叫做“隱藏面消除”(Hidden surface elimination).例如下面這張圖片谎懦,有黑色的部分,也有紅色的部分溃斋,顯而易見界拦,黑色的部分不應該讓觀察者看到。

無論使用平面著色器還是默認光源著色器都會出現(xiàn)“隱藏面消除”問題梗劫,只不過使用用平面著色器時沒有黑影效果享甸,看不出來而已截碴。

face_culling_1.png

?

解決辦法:油畫算法

油畫算法
先繪制場景中的離觀察者較遠的物體,再繪制較近的物體
下圖先繪制紅色的部分,在繪制黃色的問題枪萄,最后繪制灰色的部分隐岛,即可解決隱藏面消除的問題。

face_culling_2.png

油畫法的弊端
油畫法雖然解決的隱藏面消除的問題瓷翻,我們進一步思考在上面的圖形繪制中聚凹,三個圖形有交匯的地方,我們是不是繪制了三遍齐帚,影響了性能妒牙。還有我們無法繪制圖形相互疊加層次混亂的問題。如下圖:

face_culling_3.png

?

解決方案: 正背面剔除(Face Culling)

我們定義一個多邊形有兩個表面对妄,我們將一個標為正面湘今,一個為背面。通常剪菱,后表面總是不可見的摩瞎,這是因為場景中大多數(shù)物體是密封的。例如盒子孝常、圓柱體旗们、箱子等,并且我們也不能把攝相機放入物體的內部构灸。因此攝相機永不可能看到多邊形的背面上渴。

看不到的面,我們是可以不繪制來提高渲染性能喜颁。OpenGL可以開啟正背面剔除做到檢查所有正面朝向觀察者的面稠氮,并渲染它們,從而丟棄背面朝向的?半开,這樣可以節(jié)約渲染資源隔披,提高渲染效率。

正面背面區(qū)分
傳遞給OpenGL繪制的頂點數(shù)據(jù)是按照一定順序傳遞的寂拆,如果我們規(guī)定逆時針的連接方向為正面锹锰,順時針的連接為背面,那么OpenGL就知道繪制計算規(guī)律漓库,按照正面的原則渲染圖形。正面和背面是有三角形的頂點定義順序和觀察者方向共同決定的园蝠,隨著觀察者的角度?向的改變渺蒿,正面背面也會跟著改變。

默認正面: 按照逆時針頂點連接順序的三角形面
默認背面: 按照順時針頂點連接順序的三?形面

face_culling_4.png

?

正背面剔除使用:

開啟表面剔除(默認背面剔除)
void glEnable(GL_CULL_FACE);

關閉表面剔除(默認背面剔除)
void glDisable(GL_CULL_FACE);

?戶選擇剔除那個面(正面/背面)
void glCullFace(GLenum mode);
mode參數(shù)為: GL_FRONT,GL_BACK,GL_FRONT_AND_BACK ,默GL_BACK

 用戶指定那個為正面
void glFrontFace(GLenum mode);
mode參數(shù)為: GL_CW,GL_CCW,默認值:GL_CCW 

例如,剔除正面實現(xiàn)(1)
glCullFace(GL_BACK); 
glFrontFace(GL_CW);

例例如,剔除正?面實現(xiàn)(2) 
glCullFace(GL_FRONT);

?

正背面剔除無法解決的問題

正背面剔除能解決顯示正面彪薛,剔除背面的功能茂装,但是無法解決同時都是正面時怠蹂,那個圖層在前,那個圖層在后少态,無法確定顯示哪個正面城侧,出現(xiàn)圖像顯示問題。

face_culling_5.png

3彼妻、深度測試

?

隱藏?消除嫌佑,除了使?正背?剔除,還可以使?深度測試來解決侨歉。

深度 :
就是在openGL坐標系中屋摇,像素點的Z坐標距離觀察者的距離。當觀察者可以放在坐標系的任意位置幽邓,所以不能簡單的說Z數(shù)值越?或越?炮温,觀察者就越靠近物體。如果觀察者在Z軸的正?向牵舵,Z值越?則靠近觀察者柒啤;如果觀察者在Z軸的負?向,Z值越?則靠近觀察者畸颅。

深度緩沖區(qū)(DepthBuffer) :
深度緩沖區(qū)在顯存中担巩。深度緩存區(qū)原理就是把距離觀察者平?(近裁剪?)的深度值與窗?中每個像素點1對1進?關聯(lián)以及存儲,每個像素都需要存儲一個深度值重斑。

深度緩沖區(qū)(DepthBuffer)和顏?緩存區(qū)(ColorBuffer)是對應的兵睛。顏?緩存區(qū)存儲像素的顏?信息,?深度緩沖區(qū)存儲像素的深度信息窥浪。深度緩存區(qū)的默認值為1.0祖很,表示最?的深度值,深度值的范圍是[0,1]之間漾脂。

  • 深度測試 : 在決定是否繪制?個物體表?時假颇,?先要將表?對應的像素的深度值與當前深度緩沖區(qū)中的值進??較,如果?于深度緩沖區(qū)中的值骨稿,則丟棄這部分笨鸡,否則利?這個像素對應的深度值和顏?值,分別更新深度緩沖區(qū)和顏?緩存區(qū)坦冠,這個過程稱為”深度測試”形耗。

 // 清空深度緩存區(qū)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

// 開啟深度測試 
glEnable(GL_DEPTH_TEST); 

// 關閉深度測試
glDisable(GL_DEPTH_TEST); 


我們可以通過 glDepthFunc(GLenum func)來修改深度測試的測試規(guī)則,那么測試的規(guī)則主要在于該函數(shù)中的枚舉值辙浑。

?

深度測試的Z-fighting(Z沖突.閃爍)問題:

開啟深度測試后激涤,OpenGL就不會再去繪制模型被遮擋的部分,這樣實現(xiàn)的顯示更加真實判呕。但是由于深度緩沖區(qū)精度的限制對于深度相差?常?的情況(例如在同?平?上進?2次制)倦踢。OpenGL就可能出現(xiàn)不能正確判斷兩者的深度值送滞,會導致深度測試的結果不可預測,顯示出來的現(xiàn)象是前?幾個畫?交錯出現(xiàn)辱挥。

同?個位置上出現(xiàn)的圖層犁嗅,且深度值出現(xiàn)精確度很低時,就會容易引起 ZFighting現(xiàn)象晤碘。表示幾個物體靠的?常的近褂微,?法確定誰在前,誰在后哼蛆。 ?出現(xiàn)顯示歧義蕊梧。

depth_test_2.png

?

解決ZFighting問題:

既然是因為靠的太近,?法區(qū)分圖層先后. 那么此時,就可以在2個圖層之間加??個微妙的間隔. OpenGL提供了"多邊形偏移"解決?案腮介。

多邊形偏移解決?法:
讓深度值之間產?間隔肥矢,如果2個圖形之間有間隔,是不是意味著就不會產??涉叠洗「矢模可以理解為在執(zhí)?深度測試前將??體的深度值做?些細微的增加,于是就能將重疊的2個圖形深度值之前有所區(qū)分灭抑。



// 啟?多邊形偏移
glEnable(GL_POLYGON_OFFSET_FILL) 

GL_POLYGON_OFFSET_POINT 對應模式: GL_POINT 
GL_POLYGON_OFFSET_LINE 對應模式: GL_LINE
GL_POLYGON_OFFSET_FILL 對應模式: GL_FILL

// 設置參數(shù)十艾,每個Fragment的深度值都會增加如下所示的偏移量: 
// ?般??,只需要將factor和units簡單賦值為-1就基本可以滿?需求。
glPolygonOffset(-1, -1)

// 關閉多邊形偏移
glDisable(GL_POLYGON_OFFSET_FILL)

// glPolygonOffset(Glfloat factor, Glfloat units);
// 每個Fragment的深度值都會增加的偏移量: Offset = ( m * factor ) + ( r * units);
// m:多邊形的深度的斜率的最?值腾节,理解?個多邊形越是與近裁剪?平?, m 就越接近于0忘嫉。
// r:能產?于窗?坐標系的深度值中可分辨的差異最?值。r是由OpenGL平臺指定的?個常量. 
// Offset:?個?于0的Offset會把模型推到離你(攝像機)更遠的位置,相應的?個?于0的Offset會把模型拉近案腺。
// ?般??,只需要將factor和units簡單賦值為-1就基本可以滿?需求庆冕。

?

如何預防ZFighting閃爍問題
  • 不要將兩個物體靠的太近,避免渲染時三?形疊在?起劈榨。這種?式要求對場景中物體插??個少量的偏移访递,那么就可能避免ZFighting現(xiàn)象。例如上?的??體和平?問題中同辣,將平?下移0.001f就可以解決這個問題拷姿。當然?動去插?這個?的偏移是要付出代價的。
  • 盡可能將近裁剪?設置得離觀察者遠?些旱函。上?我們看到响巢,在近裁剪平?附近,深度的精確度是很?的棒妨,因此盡可能讓近裁剪?遠?些的話抵乓,會使整個裁剪范圍內的精確度變??些。但是這種?式會使離觀察者較近的物體被裁減掉,因此需要調試好裁剪?參數(shù)灾炭。
  • 使?更?位數(shù)的深度緩沖區(qū),通常使?的深度緩沖區(qū)是24位的颅眶,現(xiàn)在有?些硬件使?使?32/64位的緩 沖區(qū),使精確度得到提?
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市饮睬,隨后出現(xiàn)的幾起案子沈跨,更是在濱河造成了極大的恐慌,老刑警劉巖商叹,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件燕刻,死亡現(xiàn)場離奇詭異,居然都是意外死亡剖笙,警方通過查閱死者的電腦和手機卵洗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來弥咪,“玉大人过蹂,你說我怎么就攤上這事【壑粒” “怎么了酷勺?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長扳躬。 經常有香客問我脆诉,道長,這世上最難降的妖魔是什么贷币? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任击胜,我火速辦了婚禮,結果婚禮上片择,老公的妹妹穿的比我還像新娘潜的。我一直安慰自己,他們只是感情好字管,可當我...
    茶點故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布啰挪。 她就那樣靜靜地躺著,像睡著了一般嘲叔。 火紅的嫁衣襯著肌膚如雪亡呵。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天硫戈,我揣著相機與錄音锰什,去河邊找鬼。 笑死,一個胖子當著我的面吹牛汁胆,可吹牛的內容都是我干的梭姓。 我是一名探鬼主播,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼嫩码,長吁一口氣:“原來是場噩夢啊……” “哼誉尖!你這毒婦竟也來了?” 一聲冷哼從身側響起铸题,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤铡恕,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后丢间,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體探熔,經...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年烘挫,在試婚紗的時候發(fā)現(xiàn)自己被綠了诀艰。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡墙牌,死狀恐怖涡驮,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情喜滨,我是刑警寧澤捉捅,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站虽风,受9級特大地震影響棒口,放射性物質發(fā)生泄漏。R本人自食惡果不足惜辜膝,卻給世界環(huán)境...
    茶點故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一无牵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧厂抖,春花似錦茎毁、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至墙懂,卻和暖如春橡卤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背损搬。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工碧库, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留柜与,地道東北人。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓嵌灰,卻偏偏與公主長得像弄匕,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子伞鲫,可洞房花燭夜當晚...
    茶點故事閱讀 44,601評論 2 353