2016-09-10 145 views
2

我有一個GLSL着色器,它給出一組貝塞爾曲線(點的三維座標)繪製3D曲線。繪圖本身是按照我想要的方式完成的,除非遮擋不能正常工作,即在某些視點下,應該位於最前面的曲線看起來仍然被遮擋,而相反:假定的曲線部分被遮擋仍然可見。GLSL着色器:遮擋順序和剔除

爲了說明,這裏是屏幕截圖的幾個例子:

1 - 彩色曲線更接近相機,因此它被正確呈現在這裏。 correct render

2 - 彩色曲線應該位於灰色曲線的後面,但它會顯示在頂部。 wrong render

我是新來的GLSL,可能不知道這種效果正確的術語,但我相信它是遮擋剔除(更新:它實際上表明與深度緩衝,術語混亂問題)。我的問題是:如何在使用GLSL着色器時處理遮擋?我是否必須在着色器程序或其他地方對待它們?

關於我的代碼,這是一個有點長(加上我使用OpenGL包裝庫),但主要步驟是:

  1. 在頂點着色器,我計算gl_Position = ModelViewProjectionMatrix * Vertex;,並進一步通過顏色信息的幾何着色器。
  2. 在幾何着色器中,我取4個控制點(lines_adjacency)及其相應的顏色,並生成一條跟隨貝塞爾曲線(我使用Bezier段之間的基本顏色插值)的三角形條。
  3. 片段着色器也很簡單:gl_FragColor = VertexIn.mColor;

關於OpenGL設置,我啓用GL_DEPTH_TEST,但它似乎沒有任何我需要的東西。另外,如果我在場景上放置任何其他非着色器幾何圖形(例如四邊形),則無論視點如何,曲線總是呈現在其頂部。

任何有關如何解決它的見解和提示,以及它爲什麼發生的讚賞。

更新解決方案

所以,最初的問題,因爲我瞭解到,是不是發現了撲殺算法,但我沒有正確處理z值的計算(見接受的答案) 。我還了解到,在正確的深度緩衝區設置下,OpenGL自己正確處理遮擋,所以我不需要重新發明輪子。

我搜索了我的GLSL程序,發現在將頂點座標轉換爲屏幕座標(vec2(vertex.xy/vertex.w) * Viewport;)時,我基本上在我的幾何着色器中將z值設置爲零。我已經通過分別計算z值(vertex.z/vertex.w)並將它們分配到發射點(gl_Position = vec4(screenCoords[i], zValues[i], 1.0);)來修復它。這解決了我的問題。

關於深度緩衝區設置,我沒有必要明確指定它們,因爲我使用的庫默認情況下正確設置了它們。

+0

使用像apitrace或renderdoc這樣的調試器來查看深度緩衝區中的深度值。 – pleluron

+0

如果我無法在理論層面弄清楚,我會嘗試。 – vicrucann

+0

你有深度緩衝區嗎?根據用於設置上下文和渲染表面的窗口系統工具包/框架,這可能是默認設置,或者您可能需要專門請求它。 –

回答

1

如果您不使用深度緩衝區,那麼最近渲染的對象將始終處於頂層。

您應該使用glEnable(GL_DEPTH_TEST)啓用它,根據您的喜好設置功能(glDepthFunc(GL_LEQUAL)),並確保每一幀都與其他所有內容一起清除(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT))。

然後確保頂點着色器正確設置最終頂點的Z值。看起來最簡單的方法是在CPU側將ModelViewProjectionMatrix的「模型」部分設置爲在深度值傳遞到着色器之前具有深度值。

只要你使用正交投影矩陣,渲染不應該受到影響(除了使繪圖順序正確)。

+0

請您澄清一下,「頂點着色器正確設置最終頂點的Z值」是什麼意思?什麼是Z值,是「gl_Position.z」?什麼是**正確的** Z值? – vicrucann

+0

vec4的Z值(如gl_Position)與X和Y一樣,但對於深度。適當的Z值是0和1之間的任何值,或者是在製作投影矩陣時設置zNear和zFar的值。 0是屏幕,1是推出你的顯示器的背面,所以當你設置深度函數爲GL_LEQUAL時,你說只渲染最接近顯示器的東西。 –

+0

更具體的例子是,如果將彩虹深度設置爲0.8,將灰度設置爲0.2,並首先渲染灰度,則彩虹上的重疊像素將無法進行深度測試,因爲0.8不小於或等於0.2。如果您翻轉繪製順序並首先繪製彩虹,則灰度重疊像素將通過深度測試。 0.2小於或等於0.8,所以它與彩色像素灰度重疊 –