opengl各個座標系理解與轉換公式

2021-10-25 08:50:35 字數 3439 閱讀 7991

1、標準化裝置座標(normalized device coordinates, ndc)

頂點座標已經在頂點著色器中處理過,它們就應該是標準化裝置座標了,標準化裝置座標是乙個x、y和z值在-1.0到1.0的一小段空間。任何落在範圍外的座標都會被丟棄/裁剪,不會顯示在你的螢幕上。

2、uv座標系

uv座標系一般以左下角為原點(0,0),經常用於貼圖上面。範圍為0-1.

opengl 乙個完整的空間變換流水線如下:

model coordinate system(模型座標系)->world coordinate system(世界座標系) --> eye coordinate system(相機座標系) --> clip coordinate system(裁減平面座標系) --> normalized device coordinate system(標準裝置座標系ndc) --> window device coordinate system(螢幕座標系)。

模型變換觀察變換,使將物體的座標從模型空間,通過旋轉移動等復合變換,轉換到了以攝像機為原點的觀察空間座標系下。在觀察空間下,z軸上的資料表示了物體距離攝像機的遠近,即深度,此時的深度值還是線性的。(觀察空間使用的是右手座標系,即 -z軸才是攝像機的正前方)

觀察空間中,只有位於視錐體內的物體才會被攝像機渲染並且可見,所以需要將範圍外的頂點剔除。但是視錐體是乙個金字塔形狀,由六個錐平面構成。使用六個錐平面直接進行裁剪判斷會很麻煩; 因此,有一種更加方便的方法是:通過乙個透視投影矩陣把頂點從觀察空間轉換到乙個裁剪空間下,轉換的過程實際是對x,y,z分量都進行了不同程度的縮放和平移。使x,y,z值滿足:直接用w分量作為裁剪的範圍值,如果變換後的x,y,z分量都位於[-w,w]這個範圍內,就說明該頂點位於裁剪空間內,反之會被剔除。 以下是推導出的透視投影矩陣和頂點相乘後的座標點(這裡不做推導過程):

far:遠裁剪平面距離

fov:錐體豎直方向的張開角度

aspect:攝像機的橫縱比

在上一步操作中,我們可以得到裁剪空間下的 z 和 w 分量:

經過透視投影變換,座標系轉換到了裁剪空間下。緊接著,我們可以通過判斷當前的 x,y,z 分量是否處於[-w,w]範圍內,來判斷座標點是否處於視錐體內,並將視錐體外的座標點剔除。在觀察空間,世界空間,模型空間下,座標點的w分量一直都是1,所以說,經過剔除後的裁剪空間下的座標點的範圍值為[-1,1]

當完成所有的裁剪工作後,就要進行真正的投影了,即把視錐體投影到螢幕空間中,從而得到真正的二維畫素座標。 期間需要進行兩步操作,齊次除法對映輸出

齊次除法:用齊次座標系的 w 分量去除以x,y,z分量。以z軸分量為例:

經過齊次除法後,座標系由裁剪空間轉換到了ndc(歸一化的裝置座標,normalized device coordinates)下,此時的x,y,z分量的範圍值為[-1,1]。

對映輸出:ndc下的x和y的座標範圍是[-1,1],而螢幕空間左下角畫素座標是(0,0),右上角的畫素座標是(pixelwidth,pixelheight),因此x和y會先除以2再加1/2,對映到[0,1],然後再分別乘以pixelwidth和pixelheight:

上面的式子對x,y值做了處理,而z分量會直接被用於深度緩衝(zbuffer),當然這個也不一定,會根據硬體選取合適的儲存格式。 除此之外,為了能將z值儲存到深度圖中,需要將其範圍對映到 [0,1]:

此時的 d 值就是 unity 中深度圖儲存的資料。因為d是關於z_ndc的函式,z_ndc是關於1/z_visw的函式,因此 d 自然不是線性的了。 (z_ndc:ndc空間下的z值;z_visw:觀察空間下的z值)

具體的轉換方式:

(1)世界座標系內的座標乘以觀察矩陣變換到眼座標空間 eye.xyzw = viewmatrix * world.xyzw;

(2)眼座標系內的座標通過乘上投影矩陣變換到裁剪空間 clip.xyzw = projectmatrix * eye.xyzw;

(3)裁剪座標系內的座標通過透視除法(也就是 w 為 1 化) 到 規範化裝置座標系 ndc.xyz = clip.xyz / clip.w;

(4)裝置規範化座標系到視窗座標系 win.z = (dfar - dnear)/2 * ndc.z + (dfar+dnear)/2;

可以看出gl_fragcoord.z 是 win.z 。dnear ,dfar 是由 gldepthrange(dnear, dfar) 給定的,按opengl 預設值 (0,1) ,win.z = ndc.z/2 + 0.5

有時候我們需要在 shader 內反算 眼座標系 或 世界座標系 內的座標, 這在後處理或延遲著色中很有用,不需要另外使用顏色快取保留物體位置資訊,減少頻寬占用。

由視窗空間座標反算規範化裝置空間座標:

ndc.xyzw = ( gl_fragcoord.xy/viewport.wh * 2.0 - 1.0, gl_fragcoord.z * 2.0 - 1.0, 1.0 );

這樣我們只需向shader 中傳入矩陣資訊就可以獲得該片元在指定空間內的座標 ,例如

注意最終結果要除以 w 分量, eye.xyz = eye.xyz/eye.w;

vec3 decodecameraspacepositionfromdepthbuffer(in vec2 texcoord) 

vec3 decodeworldspacepositionfromdepthbuffer(in vec2 texcoord)

OpenGL 世界座標系

世界座標系 在opengl中,世界座標系是以螢幕中心為原點 0,0,0 且是始終不變的。你面對螢幕,你的右邊是x正軸,上面是y正軸,螢幕指向你的為z正軸。長度單位這樣來定 視窗範圍按此單位恰好是 1,1 到 1,1 即螢幕左下角座標為 1,1 右上角座標為 1,1 這是採用了歸一化的結果 當前繪圖座...

OpenGL 座標系詳解

opengl最終將圖形渲染到的裝置螢幕本質上是2d的,我們對圖形進行渲染的過程就是將3d場景轉換為最終的2d場景的過程。opengl中定義的點從使用者構造模型的區域性座標系,經過模型變換轉為世界座標系,再經過視變換轉換為相機座標系,再經過投影變換轉換為裁剪座標系,再進行透視除法轉換為規範化裝置座標系...

OpenGL 螢幕座標向OpenGL座標轉換

螢幕座標向opengl座標轉換 很多人用opengl繪圖會遇到乙個問題即螢幕座標向opengl座標轉換,在網上流傳著如下類似的 glint viewport 4 gldouble modelview 16 gldouble projection 16 glfloat winx,winy,winz g...