[英]How to correctly linearize depth in OpenGL ES in iOS?
我正在嘗試使用OpenGL為iOS應用程序渲染forrest場景。 為了使它更好一些,我想在場景中實現深度效果。 但是我需要OpenGL深度緩沖區的線性化深度值才能這樣做。 目前我在片段着色器中使用了一個計算(我在這里找到)。
因此我的terrain片段着色器看起來像這樣:
#version 300 es
precision mediump float;
layout(location = 0) out lowp vec4 out_color;
float linearizeDepth(float depth) {
return 2.0 * nearz / (farz + nearz - depth * (farz - nearz));
}
void main(void) {
float depth = gl_FragCoord.z;
float linearized = (linearizeDepth(depth));
out_color = vec4(linearized, linearized, linearized, 1.0);
}
但是,這會產生以下輸出:
正如你所看到的,你越遠“越遠”,得到的深度值就越“條紋”(特別是在船后面)。 如果地形圖塊靠近相機,輸出有點可以..
我甚至嘗試了另一種計算:
float linearizeDepth(float depth) {
return 2.0 * nearz * farz / (farz + nearz - (2.0 * depth - 1.0) * (farz - nearz));
}
這導致了一個太高的價值,所以我通過划分來縮小它:
float linearized = (linearizeDepth(depth) - 2.0) / 40.0;
然而,它給出了類似的結果。
那么如何在近平面和遠平面之間實現平滑,線性的過渡,沒有任何條紋? 有沒有人有類似的問題?
問題是你存儲了被截斷的非線性值,因此當你稍后查看深度值時,你會得到波動的結果,因為你失去了准確性,你離znear平面越遠。 無論你評價什么,你都不會獲得更好的結果,除非:
精度損失較低
您可以更改znear,zfar
值,使它們更接近。 盡可能多地放大znear,以便更准確的區域覆蓋更多的場景。
另一個選擇是每個深度緩沖區使用更多位(16位太低)不確定是否可以在OpenGL ES中執行此操作,但在標准OpenGL中,您可以在大多數卡上使用24,32位。
使用線性深度緩沖
因此將線性值存儲到深度緩沖區中。 有兩種方法。 一個是計算深度,因此在所有基礎操作之后,您將獲得線性值。
另一種選擇是使用單獨的紋理/ FBO並將線性深度直接存儲到它。 問題是你不能在同一個渲染過程中使用它的內容。
[Edit1]線性深度緩沖區
要線性化深度緩沖區本身(而不僅僅是從中獲取的值),請嘗試:
頂點:
varying float depth;
void main()
{
vec4 p=ftransform();
depth=p.z;
gl_Position=p;
gl_FrontColor = gl_Color;
}
分段:
uniform float znear,zfar;
varying float depth; // original z in camera space instead of gl_FragCoord.z because is already truncated
void main(void)
{
float z=(depth-znear)/(zfar-znear);
gl_FragDepth=z;
gl_FragColor=gl_Color;
}
場景參數是:
// 24 bits per Depth value
const double zang = 60.0;
const double znear= 0.01;
const double zfar =20000.0;
簡單的旋轉板覆蓋整個深度視野。 展位圖像由glReadPixels(0,0,scr.xs,scr.ys,GL_DEPTH_COMPONENT,GL_FLOAT,zed);
並在CPU端轉換為2D RGB紋理。 然后渲染為單個QUAD
覆蓋單位矩陣的整個屏幕......
現在要從線性深度緩沖區獲取原始深度值,您只需執行以下操作:
z = znear + (zfar-znear)*depth_value;
我使用古老的東西只是為了保持這個簡單,所以把它移到你的個人資料......
請注意,我不在OpenGL ES和IOS中進行編碼,所以我希望我沒有錯過與此相關的內容(我習慣於Win和PC)。
為了顯示差異,我將另一個旋轉的板添加到同一場景(因此它們相交)並使用彩色輸出(不再獲得深度):
正如您所見,線性深度緩沖區要好得多(對於覆蓋大部分深度FOV的場景)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.