第一章_基礎_1.3紋理介紹


基礎夯實-紋理介紹

紋理三大問

  • 紋理是什么:一種可供着色器讀寫的結構化存儲形式
    Image[Height][Width][4]
  • 為什么出現了紋理:
    • 通過犧牲幾何細節,減低了建模工作量,減低了模型數據儲存空間,同時也提升了讀取速度。能夠高效修改表面材質和模型。[Texturing is a technique for efficiently modeling variations in a surface’s material and finish.]
  • 紋理管線:
    模型空間位置=>投影函數[展uv階段用到的:平面映射,圓柱映射,立方體映射]
    =>紋理映射=>紋理坐標=>通訊函數[Wrap,Repeat,Mirror,Clamp,Border,Offset,Tilling]=>紋理空間坐標=>
    紋理采樣[避免依賴紋理讀取][SAMPLER:Uniform類型的變量]=>紋理值
    • 依賴紋理讀取:在RTR4中的原文解釋是[1]

Texel 紋素

  • 紋素:圖像紋理上的像素通常被稱為紋素,以區分它和屏幕上的像素。[2]

Texturing pipeline 紋理管線

  • 紋理管線:紋理化的過程廣義上被描述成為紋理化管線。[3]
  • 紋理管線的過程:紋理化的始點一般是模型上的局部坐標,也可以是世界坐標。以達到模型移動之后,紋理也跟着移動的目的。使用投影函數(projector function),獲取到的坐標叫做紋理坐標(texture coordinates),投影函數被用作於獲取紋理。這一過程叫做映射(Mapping)。有的時候用作紋理的圖像就被叫做為紋理,這其實是不太嚴謹的。
    在使用剛剛獲取的紋理坐標來獲取紋理之前,還會使用一個或多個通訊函數(corresponder functions)來將紋理坐標轉換到紋理空間(Texture Space location)。紋理空間的坐標將會從紋理獲取對應的值(Obtain value),而獲取到的值還可以是數組的索引值來檢索另外一張圖像紋理的像素,會被進一步被潛在地被轉換(value transform function),最后獲取到的數值被用作於修改模型表面的某種屬性。[4]
    • 例子:一面磚牆的例子
      模型空間坐標(x,y,z)為(-2.3,7.1,88.2)---Object space location
      使用投影函數[projector Function]將三維坐標(x,y,z)轉換成二維坐標(u,v)
      假設投影得到的UV坐標為(0.32,0.29),這個紋理坐標將會用於查找圖像上的顏色---parameter space coordinates
      假設紋理分辨率為256*256,所以在通信函數[Corresponder Function]中將返回實際圖像中坐標位置(0.32,0.29) * (256,256)=(81.92,74.24)。---texture space location
      去掉分數后,像素(81,74)就在圖像上會被尋獲[Obtain Value],得到顏色值(0.9,0.8,0.7)。---texture value
      由於紋理的顏色空間是SRGB,想用於着色計算就必須轉換成Linear空間[Value Transform Function],最后轉換為(0.787,0.604,0.448)---transformed texture value
      注:本例使用的投影方式相當於正交投影,磚牆其表面的一個值經過這個投影方式返回[0,1]的UV值

The Corresponder Function 通訊函數

  • API裁剪紋理
    使得只有裁剪過后的子圖像運用到后續着色中
  • 矩陣變換[適用於頂點着色器或片元着色器]
    常見變換有:
    Translating,Rotating,Scaling,Shearing(剪切)
    需要注意的是:紋理圖像本身沒有發生變化,是紋理坐標空間發生了變化。[5]
  • 包裹/尋址模式 Wrap Mode/Texture Addressing Mode
    • Wrap,Repeat/Tile
    • Mirror
    • Clamp/Clamp to edge
    • Border/Clamp to border

Texture Values 紋理值

紋理值一般包括:

  • 圖像紋理 Image Texturing
  • 程序紋理 Procedural Texturing

Image Texturing 圖像紋理化

  • Rapidly sample
  • Filter Textured images
    [解決紋理映射在模型表面后,經過旋轉,縮放之后一個像素可能覆蓋多個紋素的情況]
    • Magnification 放大插值方式
      • 解決少數幾個紋素覆蓋多個像素
      • Nearest neighbor filtering 最鄰近點插值濾波[常用於制作像素化風格(pixelation)]
        像素化的產生原因是:當放大的時候,像素當前的值直接取離像素中心最近的紋素。
      • Bilinear filtering 雙線性插值濾波(使用2*2的濾波器)
        • 雙線性插值舉例:
          假設取得點P(u,v)=(81.92,74.24)
          從樣本位置減去像素中心-(0.5,0.5)=(81.42,73.74)
          最接近樣本位置的四個像素點范圍是t(x,y)=(81,73),t(x+1,y+1)=(82,74)
          樣本中心相對於該四個像素中心形成的坐標系的位置是(0.42,0.74)
          所以插值顏色=
          \((1-0.42)*(1-0.74)*t(x,y)+\)
          \(0.42*(1-0.74)*t(x+1,y)+\)
          \((1-0.42)*0.74*t(x,y+1)+\)
          \(0.42*0.74*t(x+1,y+1)\)
          四個紋素的權重值之和為1
      • Cubic filtering 三次卷積插值濾波/立方卷積插值 (使用4 * 4或者5 * 5濾波器)
        卷積采樣公式:

        \(F(i+v,j+u)=\sum_{row=-1}^{2}\sum_{col=-1}^{2}f(i+row,j+col)S(row-v)S(col-u)\)

        \(S(x)=\left\{\begin{matrix} (a+2)|x|^3-(a+3)|x|^2+1 & |x|\leq1\\ a|x|^3-5a|x|^2+8a|x|-4a & 1<|x|<2\\ 0&其他 \end{matrix}\right.\)

        • 立方卷積插值舉例:
          假設取得點P(u,v)=(81.92,74.24)
          向下取整取最鄰近的像素點作為原點P00=(81,74),u=0.92,v=0.24
          計算取樣原點P00周圍其他15個紋素的S(row-v)*S(col-u)的值
          最后卷積求得采樣結果
      • Qu´ılez光滑曲線插值
        • 主要思路:使用光滑的曲線在2*2的紋素組之間進行插值
        • 常見的插值曲線:
          • smoothstep:\(x^3(3-2x)\)
          • quintic:\(x^3(6x^2-15x+10)\)
        • 采樣例子:
          假設取得點P=(81.92,74.24)
          u'=81.92 * 256+0.5=20972.02,v'=74.24 * 256+0.5=19005.94[+0.5:保證在插值曲線上x=0,s(x)=0.5,從而固定曲線的位置在(0,0.5); 256*:使得frac取小數曲線在0~1之間出現256個y≈1的點保證在紋理像素點數量和當前曲線的頻率相匹配]
          u'=0.02,v'=0.94
          u'=(s(u')-0.5+20972)/256[/256:Remap回(0,256);-0.5偏移(0,0.5)到(0,0)]
          v'=(s(v')-0.5+19005)/256
          然后再用雙線性插值的辦法進行插值
          參考Graphtoy曲線:[6]
      • 插值效果對比
        最鄰近<線性<Qu´ılez曲線插值<立方卷積插值
    • Minnification 縮小插值方式
      • 解決多個紋素覆蓋一個像素,造成紋素跨度過大導致顏色丟失與閃爍
      • 為了保障采樣質量,需要確保紋理的信號頻率不大於采樣頻率的一半,即每個紋素至少對應一個像素,所以要么提高采樣頻率,要么降低紋理的頻率。
      • 提高采樣頻率:
        • Nearest neighbor filtering 最鄰近點插值濾波
          • 原理與放大插值一樣,由於一個像素映射時覆蓋了多個紋素導致出現偽影(artifacts)
            這樣的偽影會根據觀察者的視角的移動而發生變化,屬於時效性的走樣。
        • Bilinear filtering 最鄰近點插值濾波
          • 原理與放大插值一樣,但是如果一個像素映射是覆蓋了超過4個紋素的時候,就又會產生走樣現象
      • 降低紋理的頻率:
        • 紋理走樣處理思路:都是通過預處理紋理創建出一組紋素對應一個像素快速近似的數據結構。
        • MipMapping
          • 處理過程:原始紋理被反復使用濾波器降采樣成更小的圖像,直到紋理的一個維度或者兩個維度都等於一個紋素大小。
          • 高質量的Mipmap兩大要素:
            • Good Filtering
              • box filter
                • 2*2的均值filter,質量差,存在會模糊低頻的問題。
              • 好的Filter有:高斯,Lanczos,Kaiser類似的Filter,有一些API本身就支持效果比較好的Filter內置在GPU中
            • Gamma correction
              由於大部分的紋理貼圖儲存空間是非線性空間(SRGB?),不進行Gamma矯正會導致使用完濾波器之后,會修改Mipmap的感知亮度。不使用Gamma矯正,當離物體得越遠,物體整體會變得更加得暗,對比度和細節也會受到影響。所以使用SRGB紋理的時候,參與着色之前,必須將其轉換成Linear空間
          • 訪問使用Mipmap,計算LOD(Level of Detail)
            • 利用像素單元形成的四邊形中,較長的邊緣來近似像素的覆蓋范圍
            • 另一種是最常用的,測量四個導數的絕對值的最大值作為測量值(\(\frac{\partial u}{\partial x},\frac{\partial v}{\partial x},\frac{\partial u}{\partial y},\frac{\partial v}{\partial y}\))
              • float mipmapLevel(float2 uv) {
                float dx = ddx(uv);//dudv/dx
                float dy = ddy(uv);//dudv/dy
                float d = max(dot(dx, dx), dot(dy, dy));
                return 0.5 * log2(d);
                //log2(sqrt(d))小於等於0則說明d<=1則texel小於等於pixel需要放大紋理插值
                //大於0這說明需要使用縮小濾波后的Mipmap
                //Log2是由於縮小濾波的層級一共有Log2(max(Width,Height))
                }
              • DDX,DDY需要注意:
                由於它是基於相鄰像素的梯度來計算的,所以只能在FragmentShader中使用,而不能用在VertexShader,要想在VS中使用Mipmap,需要手動計算LOD
              • 三線性插值 (u,v,d)三元組獲取Mipmap
                d是float類型,采樣每個像素時,對d最近的兩層Level做一次雙線性過濾,整個過程叫做三線性插值。
          • 內存消耗:比原本多了1/3
          • 存在問題:過度模糊[overblurring],由於假設貼圖投射到屏幕空間時都是各向同性的,但實際運用過程中,紋理空間中UV的跨度是不均勻的,是各向異性的。訪問MipMap的時候檢索的是正方形區域,檢索矩形區域是不可能的,為了避免走樣,我們選擇最大跨度的方向作為正方形邊長,這就通常導致采樣的紋素在UV方向上跨度不一致的時候,跨度小的方向采樣到的LOD偏大(模糊)[即max(dot(dx, dx), dot(dy, dy));]
        • Anisotropic Filtering 各向異性過濾方法:
          • RipMap

            • 預處理不光生成正方形區域,也生成了各種比例的矩形區域
            • 缺點:部分解決UV跨度局限在正方形區域問題,但是實際上還是使用了一個矩形來近似采樣,有的時候在斜向對角的情況拿一個矩形去框住采樣區域也是不太合適的,也包含了太多無關緊要的采樣區域,這樣得出來的采樣結果也是會存在一定的過度模糊的效應。

            crbsII.md.png

          • Summed Area Table 積分圖

            • 使用SAT之前,首先得創建一個與紋理大小相同的數組,數組的每個位置需要計算當前這個位置和原點(0,0)形成的矩形中所有紋素之和。
            • 在紋理化的過程中,像素單元投影回紋理被矩形綁定,然后訪問SAT求和區域以計算矩形的平均顏色,平均值計算公式如下:

            D3D:注意坐標原點為左上

            crbrdA.png

            示例:
            求(4,4)到(2,3)矩形區域
            C=(28+5-8-17)/(3*2)=4/3=(1+2+1+0+2+2)/(3 *2)
            注意:(1,2)為包圍盒的左上角
            OpenGL:RTR4配圖 注意坐標原點為左下

            crbDZd.png


            \(c=\frac{ s[x_{ur},y_{ur}]-s[x_{ur},y_{ll}]-s[x_{ll},y_{ur}]+s[x_{ll},y_{ll}] }{ (x_{ur}-x_{ll})(y_{ur}-y_{ll}) }\)

            注意:\((x_{ll}+1,y_{ll}+1)\)為包圍盒的左下角

            • 缺點:跟RipMap類似,也是由於在對角線視角,存在像素投影到紋理空間的矩形區域是斜着的,存在有無關緊要的采樣區域,從而造成一定的模糊效應。耗費內存多,額外需要至少2倍的內存開銷,更大的紋理也需要更高的精度。
            • 優點:在各向異性過濾的方法中速度算是比較快的。
          • Unconstrained Anisotropic Filtering 無約束各向異性過濾

            • 原理:重用現有的Mipmap硬件,在將像素投影回紋理空間后,在投影形成的四邊形區域中,使用最短的邊作為d決定LOD,使得Mipmap樣本的平均面積變小(減少模糊),然后創建平行於四邊形的最長邊並且穿過中心的各向異性線。當各向異性過濾的數值在1:1到2:1[指各向異性數值2X,4X,8X,16X,具體采樣的時候應該是各向異性過濾線跟d的比值?]之間時,沿着這條線采集兩個樣本。在各向異性過濾數值較高的情況下沿軸取的采樣點就越多。
            • 內存影響不大,開啟之后不會消耗3倍的紋理緩存,只會多1/3的緩存消耗
            • 采樣次數增加,各向異性過濾基於三線性過濾的,當uv不是1:1時,各向異性過濾就會比三線性插值采樣更多的點,[16X各向異性過濾采樣不一定采樣采夠128次,需要采樣精度到了的時候才會采夠128次]
          • EWA過濾

            • 原理:不使用矩形區域覆蓋投影形成的四邊形區域,而是使用橢圓形逐步擴大,使得橢圓能夠恰好包裹住四邊形區域,減少不必要的采樣區域。
  • Texture coordinate systems differences in DirectX and OpenGL
    • DirectX the Upper Left corner[左上角] of texture is (0,0),and the lower right is (1,1)
    • OpenGL the texel (0,0) is located in the lower left[左下角],a y-axis-flip from DirectX.
    • 浮點型紋理坐標空間像素的中心
      • Truncating 截斷 DirectX 10 向OpenGL靠攏,中心改為(0.5,0.5),使用向下取整
      • Rounding 四舍五入 DirectX 9.0 定義中心為(0,0)
    • 紋理大小
      紋理圖像應用在GPU上通常是POT(power-of-two)2的整數次冪貼圖。現代的GPU能夠處理任意大小的非2的整數次冪大小的貼圖了NPOT(non-power-of-two),但是仍有部分老舊的移動GPU是不支持對NPOT紋理進行mipmapping處理的。現在DX12最大支持16384^2大小的紋素。

優化與紋理應用

  • 優化
    • CPU提交命令優化
      • 紋理圖集,紋理數組
        通過打包紋理到一起,降低反復紋理傳輸指令到命令緩沖區的次數,減少因為頻繁改變紋理所帶來的消耗。
    • GPU降低帶寬優化
      • 壓縮紋理
        通過硬件解碼,減少包體大小,內存使用率提升
  • 常見的紋理
    • CubeMap立方體貼圖
      • 常用於HDR,LightProbe
    • Bump Map
      • 不增加頂點的情況下,改變幾何體表面的法線,定義出一個虛擬的高度,模擬凹凸不平的效果
    • Displacement Map
      • 位移貼圖是把頂點作位置的移動,需要模型的點比較多。可以使用動態曲面細分的技巧,減少所需的頂點。

  1. One term worth explaining at this point is dependent texture read, which has two definitions. The first applies to mobile devices in particular.When accessing a texture via texture2D or similar, a dependent texture read occurs whenever the pixel shader calculates texture coordinates instead of using the unmodified texture coordinates passed in from the vertex shader [66]. Note that this means any change at all to the incoming texture coordinates, even such simple actions as swapping the u and v values. Older mobile GPUs, those that do not support OpenGL ES 3.0, run more efficiently when the shader has no dependent texture reads, as the texel data can then be prefetched. The other, older, definition of this term was particularly important for early desktop GPUs. In this context a dependent texture read occurs when one texture’s coordinates are dependent on the result of some previous texture’s values. For example, one texture might change the shading normal, which in turn changes the coordinates used to access a cube map. Such functionality was limited or even non-existent on early GPUs. Today such reads can have an impact on performance, depending on the number of pixels being computed in a batch, among other factors.See Section 23.8 for more information.
    機翻:在這一點上值得解釋的一個術語是依賴紋理讀取,它有兩個定義。 第一種特別適用於移動設備。 當通過texture2D或類似的方法訪問紋理時,每當像素着色器計算紋理坐標時,就會發生一個相關的紋理讀取,而不是使用從頂點着色器[66]傳入的未修改的紋理坐標。 請注意,這意味着對傳入紋理坐標的任何更改,即使是交換u和v值這樣的簡單操作。 舊的移動GPU,那些不支持OpenGLES3.0的,當着色器沒有依賴的紋理讀取時,運行效率更高,因為文本數據可以被預取。對於早期的桌面GPU來說,這個術語的另一個更古老的定義尤為重要。 在此上下文中,當一個紋理的坐標依賴於某些先前紋理的值的結果時,就會發生依賴的紋理讀取。 例如,一個紋理可能會改變着色法線,從而又會改變用於訪問立方體映射的坐標。這些功能在早期的GPU上是有限的,甚至是不存在的。今天,這種讀取可以影響性能,這取決於在批處理中計算的像素數,以及其他因素。 詳情見第23.8節。 ↩︎

  2. The pixels in the image texture are often called texels, to differentiate them from the pixels on the screen. ↩︎

  3. Texturing can be described by a generalized texture pipeline. ↩︎

  4. A location in space is the starting point for the texturing process. This location can be in world space, but is more often in the model’s frame of reference, so that as the model moves, the texture moves along with it. Using Kershaw’s terminology [884], this point in space then has a projector function applied to it to obtain a set of numbers, called texture coordinates, that will be used for accessing the texture. This process is called mapping, which leads to the phrase texture mapping. Sometimes the texture image itself is called the texture map, though this is not strictly correct.
    Before these new values may be used to access the texture, one or more corresponder functions can be used to transform the texture coordinates to texture space. These texture-space locations are used to obtain values from the texture, e.g., they may be array indices into an image texture to retrieve a pixel. The retrieved values are then potentially transformed yet again by a value transform function, and finally these new values are used to modify some property of the surface, such as the material or shading normal. Figure 6.2 shows this process in detail for the application of a single texture. The reason for the complexity of the pipeline is that each step provides the user with a useful control. It should be noted that not all steps need to be activated at all times. ↩︎

  5. This is because texture transforms actually affect the space that determines where the image is seen. The image itself is not an object being transformed; the space defining the image’s location is being changed. ↩︎

  6. https://graphtoy.com/?f1(x,t)=x&v1=true&f2(x,t)=frac(2f1(x,t)+0.5)&v2=false&f3(x,t)=trunc(2f1(x,t)+0.5)&v3=false&f4(x,t)=f2(x,t)%C2%B3(6f2(x,t)%C2%B2-15*f2(x,t)+10)&v4=true&f5(x,t)=(f4(x,t)-0.5+f3(x,t))/2&v5=true&f6(x,t)=(f4(x,t))/2&v6=true&grid=true&coords=-0.1721714803184537,0.23028612085331285,1.6334672766021194 ↩︎


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM