gl_FragCoord

gl_FragCoord 表示當前片元着色器處理的候選片元窗口相對座標信息,是一個 vec4 類型的變量 (x, y, z, 1/w), 其中 x, y 是當前片元的窗口座標,OpenGL 默認以窗口左下角爲原點, 在 着色器中通過佈局限定符可以重新設定原點,比如窗口左上角爲原點 origin_upper_left,窗口大小由 glViewport() 函數指定。x, y 默認是像素中心 而非 整數, 原點 的窗口座標值爲 (0.5, 0.5), 小數部分恆爲 0.5, 當viewport 範圍 爲(0,0,800,600)時, x, y 的取值範圍爲(0.5, 0.5, 799.5, 599.5), 當在着色器中佈局限定符設置爲 pixel_center_integer 時, x, y 取值爲整數。

第三個分量 z 表示的是當前片元的深度信息,由 vertex shader 處理過後系統插值得到, gl_FragCoord.z 的產生過程:

假設 OpenGL 變換的各座標系統定義如下: world.xyzw 表示 世界座標系的座標, eye.xyzw 表示眼座標系(也叫觀察座標系,還有叫相機座標系,呃。。。) 的座標, clip.xyzw 表示 裁剪座標系的座標 , ndc.xyzw 表示 規範化設備座標系座標, win.xyzw 表示 窗口座標系座標, OpenGL 一個完整的空間變換流水線如下:

world coordinate system --> eye coordinate system --> clip coordinate system --> normalized device coordinate system --> window device coordinate system。

gl_FragCoord.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 中傳入 矩陣信息 , 就可以獲得該片元在指定空間內的座標 ,例如

eye.xyzw = projectionMatrixInverse * ndc.xyzw;
world.xyzw = modelViewProjectionMatrixInverse * ndc.xyzw
注意最終結果要除以 w 分量, eye.xyz = eye.xyz/eye.w;

第四個分量 gl_FragCoord.w

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章