2012年2月16日 星期四
從Depth map取得Eye-Space空間座標
如何從Screen-space反推三為空間座標呢?有以下幾個步驟:
STEP 1:
在Depth pass中,使用F32格式的Render target,儲存線性空間的Z值資訊,但什麼是線性
空間的Z值資訊呢?簡單說就是空間座標轉換到世界座標後的Z值,而非線性的Z值指的是轉換
到世界座標後,在經由Projection matrix傳換過後的Z值
STEP 2:
要在Screen-space下工作,可以想像成Image process一樣,對一張圖片做濾鏡的處哩,但三
維空間都是三角形怎麼模擬二維空間做影像處裡呢?說穿了就是畫兩個三角形拼成矩形暫滿整
各畫面,那要怎麼畫兩個三角形剛剛好暫滿畫面呢?
在Clipping Space中,整各會出現在畫面上的空間座標在範圍:[-1,-1,-1] ~ [1,1,1]中,比較簡
單的做法是,直接給予兩個三角形的Pos分別為:
Tri 0: (-1.0f, 1.0f,0.0f), (1.0f,1.0f,0.0f), (-1.0f,-1.0f,0.0f)
Tri 1: (1.0f, 1.0f,0.0f), (-1.0f,-1.0f,0.0f), (1.0f,-1.0f,0.0f)
然後在Vertex shader中完全不做座標轉換!!
struct OUT
{
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};
OUT vs_main( float3 pos : POSITION, float2 uv : TEXCOORD0 )
{
OUT out;
out.pos = float4( pos.x, pos.y, pos.z, 1.0f );
out.uv = uv;
return out;
}
STEP 3:
當完成step 2之後,我們進入Pixel shader的每一點都可以看作是圖片上的Pixel,如次就可以在
Screen-space上工作啦!!接下來就是使用texcoord去取出step 1中F32 Render-target的Z值來
反推每一點的空間座標(世界座標),反推的過程需要一點數學,簡單的說你怎麼推算出projection-matrix的,就反向帶回去即可,概念如下:
R: width/height
clipping sapce =
x' = x * 1/(z*R*tan(a/2))
y' = y * 1/(z*tan(a/2))
so, 反推回x, y等於
x = x' * (z*R*tan(a/2))
y = y' * (z*tan(a/2))
NVIDIA:
const float fovy = 40.0 * 3.14159265 / 180.0; //40 deg in radian
const float invFocalLenX = tan(fovy * 0.5) * width / height;
const float invFocalLenY = tan(fovy * 0.5);
vec3 uv_to_eye(vec2 uv, float eye_z)
{
uv = (uv * vec2(2.0, -2.0) - vec2(1.0, -1.0));
return vec3(uv * vec2(invFocalLenX, invFocalLenY) * eye_z, eye_z);
}
vec3 fetch_eye_pos(vec2 uv)
{
float z = texture2D(tex1, uv).a; // Depth/Normal buffer
return uv_to_eye(uv, z);
}
訂閱:
張貼留言 (Atom)
沒有留言:
張貼留言