Vertex Texture Fetch(VTF) Fragment Texture Fetch ( FTF )
在vertex shader里也可以檢索紋理。我本來覺得這沒什么好奇怪的,因為我一直也覺得這很當然可以啊~當初橙書(OpenGL Shading Language Edtion2)也說過texture2D這類函數不是fragment shader專用的,倒還有texture2DLod這種在vertex shader里專用的(后面一句是馬后炮~),只是我不知道怎么用,在哪里用,以及更重要的:為什么要用。
為什么要在vertex shader里檢索紋理。
都知道,紋理里的一般是一幅圖像,無論是外部導入的還是通過FBO等手段渲染到的。既然如此,有意義的當然是圖像里的每一個像素啦,通過紋理坐標檢索紋理中的像素打印到屏幕某個地方,并可控制細節程度……反映在GPU編程中,一般就是把當前綁定的紋理的紋理單元(默認為0)傳送給Fragment Shader作為sampler,在vertex shader里用gl_TexCoord[0] = glMutiTexCoord0這樣的語句,獲取固定流水線中為每個頂點設置好的紋理坐標(頂點紋理索引,即glMutiTexCoord0),賦給本質為varying的gl_TexCoord[0],讓它帶著紋理坐標在光柵化過程中插值——對應每個像素點擁有屬于它的插值后像素紋理索引(gl_TexCoord[0]),以此作為參數用texture2D類函數檢索紋理sampler。
直接在頂點階段就檢索紋理意義何在?獲得的只是那些頂點的紋理坐標檢索出的“孤立”像素值而已。
你認識嗎?GPGPU。
[gpgpu.org]
GPGPU(General Purpose Graphic Process Unit,通用目的圖形處理單元),是應用GPU的高速并行能力和浮點運算能力進行科學計算等SIMD類型[單指令多數據]的應用。在這里,GPU-shader不僅僅著眼于圖形。而GPGPU的一個重要概念就是:紋理 =? 數組。是的,為什么不可以呢?紋理確實就是數組啊。我們能傳入shader的只有具體的數值,bool,int,float,vec,matrix,其中最大的matrix4也只有16個量。那么如果我們要把大量的數據傳入shader,譬如一個巨大的float數組,怎么辦呢?對啊,用紋理!這時候,紋理內部每個數值不再是像素的值,而是數組的數據項。我們只是通過紋理這種靈活的媒介,讓數據“進入”GPU的視野,讓shader可以對這些數據項變量進行訪問和操作。
順帶一提,現在科學計算領域已經進入GPGPU的進化時代 -CUDA時代了。好吧,不要扯遠了。
既然紋理 = 數組, VTF頂點紋理拾取的存在就不言自明了:其實不是在拾取含有圖像像素信息的那個紋理,而是在拾取含有頂點數據信息的那個“數組”啊!在這里,數組的索引就是頂點紋理坐標……看例子:
//RenderMonkey: //Vertex Program varying vec4 vertColor; uniform sampler2D baseMap;void main( void ) {//vertColor = texture2D(baseMap, gl_MultiTexCoord0.xy); 與下句等價 vertColor = texture2DLod(baseMap, gl_MultiTexCoord0.xy, 0.0); vec4 pos = gl_ModelViewMatrix * (gl_Vertex) ;gl_Position = gl_ProjectionMatrix * pos ; }//Fragment Program varying vec4 vertColor;void main( void ) {gl_FragColor = vertColor; }這個例子是說明:誒?原來Vertex Shader里也可以做紋理拾取口牙!順帶一提,這里用texture2D,和用“texture2DLod+尾參數[細節參數LOD] = 0.0”的效果是一樣的:
?
(對比用。這是FTF,傳統的fragment shader獲取紋理)
(這是VTF,頂點紋理拾取,也就是上面代碼的產物,對比兩圖哈)
紋理只是普通的紋理。只是為了證明VTF能行- -。把頂點紋理的值做插值,預料最后的結果類似于頂點顏色插值,三角片元的顏色在三角的三頂點所獲得的紋理顏色間進行線性插值,得出如此“重過渡味+模糊”的怪象(嘛~這紋理即使是那FTF出來的也是怪象)。然后測試texture2DLod這個函數,把最后的LOD參數增大調為0.4:
lod是細節參數,這跟以前的FTF(PTF)差不多。好吧,換張紋理后,再用VTF做點更有趣的:
//RenderMonkey: //Vertex Program varying vec4 vertColor; uniform sampler2D baseMap; void main( void ) { vertColor = texture2DLod(baseMap, gl_MultiTexCoord0.xy, 0.0);vec4 offset = vec4(0.0);if(gl_Vertex.z > 0.0)offset = vertColor;else if(gl_Vertex.z < 0.0)offset = vec4(1.0)-vertColor;vec4 pos = gl_ModelViewMatrix * (gl_Vertex+ offset) ; gl_Position = gl_ProjectionMatrix * pos ; } //Fragment Program varying vec4 vertColor; void main( void ) { gl_FragColor = vertColor; }能猜到結果變成這樣嗎?哈,VTF出來的vertColor果然充滿力量:
另外一個例子則用VTF做點有意義的事情。還記得高度圖紋理嗎?(我在[Terrain Texture-Array Demo] 里也用到過~)
//RenderMonkey: //Vertex Program varying vec2 texCoord; uniform sampler2D Texture0;void main(void) {vec4 vcol = texture2D( Texture0, gl_MultiTexCoord0.xy);float gray = 0.2990*vcol.r + 0.5870*vcol.g + 0.1140*vcol.b;vec4 pos = gl_Vertex;pos.z = pos.z * (1.0 - 5.0*gray);gl_Position = gl_ModelViewProjectionMatrix * pos;texCoord = gl_MultiTexCoord0.xy; }//Fragment Program uniform sampler2D Texture0; varying vec2 texCoord;void main(void) {gl_FragColor = texture2D( Texture0, texCoord ); }這里本來只有一個平整的網格,和一張類似高度圖的紋理。運用VTF把頂點對應的紋理坐標的像素值拉出來轉化為灰度(轉化法同見[基于亮度的圖像二值化處理] ),并轉化為該網格頂點的“高度”。最后的紋理只是平鋪上去(那不是陰影哦)。看,灰度高的地方對應的高度高,灰度低的地方對應的高度低。這就是高度場啊,這就是VTF最典型的應用啊!
在Vertex Shader里面,通過紋理坐標的檢取,VTF獲取的是真正的“高度值”數據……只是這些數據被儲存在一張紋理上罷了。
總結
以上是生活随笔為你收集整理的Vertex Texture Fetch(VTF) Fragment Texture Fetch ( FTF )的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【wordpress基础教程一】:wor
- 下一篇: [杭电ACM]1012u Calcula