深度緩沖是在三維圖形中處理圖像深度坐標(個人認為可以理解成距離我們觀察攝像機遠近的距離)的過程----From wiki
這聽起來不好理解啊啊啊啊。
所以就舉個栗子嘍XD,就好比我可能要按由近到遠順序渲染兩個面(實際上是任意順序,我是說假如按這個順序),近處的面先渲染,之后渲染遠處的面,但是如果沒有開啟深度測試glEnable(GL_DEPTH_TEST),那么遠的面將要覆蓋掉我們近處渲染的面,顯然這不是我們所想要看到的。所以此時就需要深度測試,遠的面的深度值與近處的面的深度值進行比較,一旦遠的面深度值比較大即距離我們較遠,那么該片段就會被丟棄掉,但這與面剔除似乎是不一樣的,面剔除是根據面向觀察者和背向觀察者去判斷是否丟棄片段,不知道我這樣講是否正確,求看到此篇的大神用力的打我臉!
其中我最不理解的“丟棄片段”(為什么片段丟棄后我攝像機移動,還是能看到原先背向我的那一些片段?)后來發現僅僅是在此幀渲染時丟棄這些片段。但是之后攝像機一旦移動那么又是渲染另一幀,所以重新進入渲染管線進行渲染,同時這就是為什么我們要創建頂點數組緩沖對象的原因,否則我們就要創建VBO,設置頂點指針屬性等等復雜操作。雖然現代的OpenGL是不支持不創建VAO的。
深度緩沖區的原理:
最初先使用glClear(GL_DEPTH_BUFFER_BIT)把所有窗口上的像素的深度值設置為最大值。
然后在場景中以任意順序繪制所有物體。OpenGL計算把每一個繪制表面轉換為窗口上一些像素的集合,此時沒有啟動深度測試並不考慮是否被其他物體遮擋。所以可能導致遠的繪制表面把近的繪制表面覆蓋掉
其次,OpenGL會計算這些表面和觀察平面的距離。如果啟用了深度緩沖區,在繪制每個像素之前,OpenGL會把它的深度值和已經存儲在這個像素的深度值進行比較。如果新像素深度值<原先像素深度值,則新像素值會取代原先的像素值;反之,新像素值包括他的顏色值和深度將被丟棄。
深度測試的筆記:
1.深度緩沖是由我們使用的創建窗口庫自動創建的,我使用的是GLFW庫所以就由它創建,同時它在大部分系統上將深度值存儲為24位的浮點數
2.深度測試在渲染管線(pipeline)中是在模板測試之后
3.OpenGL執行深度測試時,如果此片段測試通過,OpenGL自動在深度緩沖區存儲片段的 z 值,否則將丟棄該片段
4.屏幕空間坐標直接有關的視區,由glViewport()函數給定(glViewport()在默認情況下,視口被設置為占據打開窗口的整個像素矩形),同時也可由片段着色器中glFragCoord的x和y的分量訪問,同時z坐標也包含了片段實際深度值
5.片段着色器的運行相當費時,提前深度測試可以更早的放棄用於那不會出現的片段(不知道算不算要點)
6. 在某些情況下,我們需要進行深度測試並相應地丟棄片段,但我們不希望更新深度緩沖區,基本上,可以使用一個只讀的深度緩沖區,此時可以通過glDepthMask(GL_FASLE)來禁止對緩沖區寫入,實際上,只要存在深度緩沖區,無論是否啟用深度測試,OpenGL在像素被繪制時都會嘗試將深度數據寫入到緩沖區內。
7.glDepthFunc()如果參數是GL_LESS,那么將設置成在片段深度值小於緩沖區深度時通過測試,否則丟棄片段,具體參數可以見下表:
深度值的精度(將平截頭題中的z值轉換成[0.0,1.0]范圍內然后進行深度值的比較):
計算這個精度有兩個轉換公式和
兩者對應的函數圖片分別如下
和
其中前者是非線性的轉換而后者是線性的轉化,但是后者的話在實踐中是幾乎從來不使用這樣的線性深度緩沖區。如果使用線性,那么100單位和1單位精度是基本一樣的,而非線性他們在z很小的時候有很高的精度(即函數變化快,較為精確),而較大的 z 值有較低的精度。因為我們所做的就是要越近的物體比較越精細(函數變化越快)才能更好的渲染細節,遠的物體比較個大概即可(此處原因是我個人理解,不知道我這樣講是否正確,求看到此篇的大神用力的打我臉!),所以常使用前者。
兩者計算比較圖
使用前者那么渲染出來的結果如下:
z值由小變大,很快顏色就由暗變亮,這就說明只要短短移動一點距離,變化就越明顯,暗色就快速的變亮
使用后者渲染圖
由暗變亮需要很長距離的變化,這就是兩者區別
最后一點,如果發現圖像閃爍考慮是否發生了深度沖突及兩個圖像的某個部分深度相同造成的
本文僅僅是為了學習,篇中有些是改了改前輩的,再加上自己的理解放入的,侵刪!歡迎大神來打我臉!!!
-----------2016/12/14