天天看點

Vulkan程式設計指南翻譯 第六章 着色器和管線 第5節 第6段 圖像采樣

這一節實在太長了,分篇來翻譯。

Sampled Images

當着色器從圖像讀資料時,他們可以可以使用兩種方式。第一種是原生加載,從圖像的指定位置直接讀取格式化的或非格式化的資料,第二種是使用采樣器對圖像采樣。采樣包括:在圖像坐标空間做基礎變形或者紋素過濾來光滑圖像傳回到着色器。

采樣器的狀态通過一個采樣器對象表示,它可像圖像或者緩沖區一樣被綁定到描述符集合。可調用函數vkCreateSampler()來建立一個采樣器對象,其原型如下:

         VkResultvkCreateSampler (

VkDevice                                               device,

const VkSamplerCreateInfo*          pCreateInfo,

const VkAllocationCallbacks*         pAllocator,

VkSampler*                                          pSampler);

将建立采樣器的裝置通過device傳遞,采樣器剩下的參數通過一個VkSamplerCreateInfo類型資料的指針pCreateInfo傳遞。一個裝置上可以建立的采樣器個數的上限取決于與Vulkan實作。可以保證的是至少有4000個。如果你的應用程式有可能建立超過這個數量的采樣器,那麼你需要檢查裝置本身支援建立多少個采樣器。一個裝置可以管理的采樣器個數包含在VkPhysicalDeviceLimits類型資料的maxSamplerAllocationCount域,可調用vkGetPhysicalDeviceProperties()函數來擷取VkPhysicalDeviceLimits資料。VkSamplerCreateInfo原型如下:

         typedefstruct VkSamplerCreateInfo {

VkStructureType sType;

const void* pNext;

VkSamplerCreateFlags flags;

VkFilter magFilter;

VkFilter minFilter;

VkSamplerMipmapMode mipmapMode;

VkSamplerAddressMode addressModeU;

VkSamplerAddressMode addressModeV;

VkSamplerAddressMode addressModeW;

float mipLodBias;

VkBool32 anisotropyEnable;

float maxAnisotropy;

VkBool32 compareEnable;

VkCompareOp compareOp;

float minLod;

float maxLod;

VkBorderColor borderColor;

VkBool32 unnormalizedCoordinates;

} VkSamplerCreateInfo;

VkSamplerCreateInfo的sType域應置為VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,pNext應置為nullptr。Flags域被保留應置為0。

圖像過濾

magFilter 和 minFilter域指定了圖像在被放大或縮小時将被使用的過濾模式。圖像是放大還是縮小是通過比較被計算的相鄰像素間采樣坐标來決定。如果采樣坐标的梯度大于1,那麼圖像是被縮小的。否則,它是被放大的。magFilter 和 minFilter是VkFilter枚舉的成員。VkFilter的成員如下:

• VK_FILTER_NEAREST: When sampling, the nearest texel in the image ischosen and returned

directly to the shader.

• VK_FILTER_LINEAR: A 2 × 2 footprint containing the texelcoordinates is used to produce a

weighted average of four texels, and thisaverage is returned to the shader

VK_FILTER_NEAREST模式将使Vulkan在從一張圖像采樣時簡單選擇指定坐标臨近的紋素。在很多情況下,這就導緻blocky喝着帶鋸齒的圖像,導緻渲染出來的圖像閃爍。VK_FILTER_LINEAR告訴Vulkan當采樣時對圖像采用線性過濾。

當你正在使用線性過濾來處理圖像時,需要擷取的采樣點也許在1D紋理的兩個紋素中間,或者2D紋理的4個紋素中間。Vulkan将從周圍的紋素讀取資料,然後基于到每個點的距離給予不同的權重計算出結果。這在Figure 6.2中給出了圖示,采樣點在x,它處于四個紋素A,B,C和D的中間。盡管紋理坐标的整數部分是{u, v},紋理坐标的小數部分是{α, β}。

要擷取紋素A、B的線性權重之和,可按照下面的關系來簡單的計算

Tu0 = αA + (1 −α) B

這也可以寫成

Tu0 = B + α (B−A)

同理,C與D的權重之和通過下面的公式來算

Tu1 = αC + (1 −α) D or

Tu1 = D−α (D−C)

然後,兩個臨時量Tu0 and Tu1可被結合來算單一一個權重之和,結合β和相似的機制

T = βTu0 + (1 −β) Tu1 or

T = Tu1 + β(Tu1 −Tu0)

這可以拓展到任何維數,盡管在Vulkan中紋理的維數最多隻有3。

Mipmapping

mipmapMode域指定了當圖像被采樣時使用多少層mipmaps。其值是VkSamplerMipmapMode枚舉的一個成員,枚舉成員如下:

• VK_SAMPLER_MIPMAP_MODE_NEAREST: The computed level-of-detail isrounded to the

nearest integer, and that level is used toselect the mipmap level. If sampling from the base

level, then the filtering mode specified inmagFilter is used to sample from that level;

otherwise, the minFilter filter is used.

• VK_SAMPLER_MIPMAP_MODE_LINEAR: The computed level of detail isrounded both up

and down, and the two resulting mipmaplevels are sampled. The two resulting texel values are

then blended and returned to the shader.

要從一個圖像中選擇mipmap,Vulkan将計算紋理中被采樣的坐标的導數。關于數學的部分在Vulkan 規範裡有講述。簡單來說,被選擇的level是紋理坐标維數中導數最大的一個做log2的結果。這個level可以通過采樣器或者着色器的參數來調整,或者完全在着色器裡指定。不管源是什麼,結果可能不是整數。

當mipmap模式是VK_SAMPLER_MIPMAP_MODE_NEAREST,被選擇的mipmap level是簡單的取其整數部分,然後那單一一層被采樣,盡管隻是一層圖像。當mipmap模式是VK_SAMPLER_MIPMAP_MODE_LINEAR時,采樣點從鄰近的上一層和下一層取得,使用minFilter域指定的過濾模式,然後這兩個采樣點依據其權重來合稱為一個點,和前面講述的線性采樣相近。

注意,過濾模式隻适用于縮小,亦即此過程在mipmap層采樣而并不在原圖像采樣。到紋理坐标導數的log2 比1小時,那麼第0層就被使用,是以隻有一層能夠被采樣使用了。這就是放大,使用magFilter指定的過濾模式來從原圖像中采樣。

VkSamplerCreateInfo中接下來的三個域addressModeU,addressModeV, 和 addressModeW,用來指定紋理坐标系之外采樣時選用的變形。可選的模式如下:

• VK_SAMPLER_ADDRESS_MODE_REPEAT: As the texture coordinateprogresses from 0.0 to

1.0 and beyond, it is wrapped back to 0.0,effectively using only the fractional part of the

coordinate to sample from the image. Theeffect is to tile the image indefinitely.

• VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT: The texture coordinateprogresses

from 0.0 to 1.0 as normal, and then in therange 1.0 to 2.0, the fractional part is subtracted from

1.0 to form a new coordinate moving backtoward 0.0. The effect is to alternately tile the normal

and mirror-image version of a texture.

• VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE: Texture coordinates beyond1.0 are

clamped to 1.0, and negative coordinatesare clamped to 0.0. This clamped coordinate is used to

sample from the image. The effect is thatthe texels along the edge of the image are used to fill

any area that would be sampled outside theimage.

• VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER: Sampling from the textureoutside

its bounds will result in texels of theborder color, as specified in the borderColor field,

being returned rather than data from theimage.

• VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE: This is a hybrid modethat

first applies a single mirroring of thetexture coordinate and then behaves like

VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE.

在Figure 6.3展示了每一種應用到圖像的采樣器尋址模式的效果。在圖中,左上角的圖像展示了VK_SAMPLER_ADDRESS_MODE_REPEAT尋址模式。你可以看到,在幀之間紋理隻是簡單的重複。右上角的圖像展示VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT模式的結果。每一個重複都會在X或Y方向上鏡像。

Figure6.3: Effect of Sampling Modes

左下角的圖像表示對紋理使用了VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE尋址模式。這裡,最後一行或者一列的像素在采樣坐标離開紋理範圍後被無限重複。最後,右下角的圖像展示了VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER模式的結果。這個紋理在建立時使用了黑色的邊框,是以,在紋理之外的部分就是空白的,但是Vulkan會從黑色采樣。這允許你可以看清原來的紋理。

當過濾模式是VK_FILTER_LINEAR,wrapping或者clamping紋理坐标被應用到每一個在2×2範圍内生成的用來産生紋素的坐标。結果就是圖像被wrapped時過濾也被應用上了。

對于VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER過濾模式,當紋素是從邊界采樣時(),邊界的顔色被替換了而非從圖像中讀取。被使用的顔色取決于borderColor域的值。這不是一個完整的顔色規範,隻是VkBorderColor枚舉類型的一個成員,它允許一個小的、預定義的顔色集合可選。它們是:

• VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK: Returns floating-pointzeros to the

shader in all channels

• VK_BORDER_COLOR_INT_TRANSPARENT_BLACK: Returns integer zeros to theshader in

all channels

• VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK: Returns floating-point zeros inthe R, G,

and B channels, and floating-point one in A

• VK_BORDER_COLOR_INT_OPAQUE_BLACK: Returns integer zeros in R, G,and B, and

integer one in A

• VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE: Returns floating-point ones tothe shader in

all channels

• VK_BORDER_COLOR_INT_OPAQUE_WHITE: Returns integer ones to theshader in all

Channels

VkSamplerCreateInfo的mipLodBias域指定了在被添加到選擇mipmap之前計算的level ofdetail 的一個浮點內插補點。這允許你你把在mipmap鍊中把level of detail調高或調低,使生成的被過濾的紋理看起來更加銳利或者模糊。

如果你想要使用各向異性過濾,設定anisotropyEnable為VK_TRUE。各向異性過濾的細節是依賴于Vulkan實作的。各向異性管理通常在投影範圍内做采樣,而不是在固定的2×2範圍内。通過在範圍内使用更多的采樣點來逼近範圍内采樣。因為采樣的個數可能非常大,各向異性過濾可能對性能産生負面影響。同樣,在一些極端情況下,投影的範圍可能非常大,這會導緻影響到很大區域和模糊的過濾效果。為了限制這些效果,你可以對各向異性的範圍做剪裁,設定maxAnisotropy在1.0和裝置允許的最大值之間。可調用vkGetPhysicalDeviceProperties()并檢查VkPhysicalDeviceLimits類型資料的maxSamplerAnisotropy域來獲知該最大值。

當采樣子用于深度圖像時,可以配置來進行比較操作并傳回比較的結果而不是存儲在圖像原生的值。當這種模式啟用時,從圖像中取出的采樣點之間進行比較,結果便是通過采樣後資料的分數部分。這可用來實作一個名為spercentage closer filtering, or PCF的技術。要開啟這個模式,需設定compareEnable為VK_TRUE,并給compareOp設定比較操作。

compareOp是VkCompareOp枚舉的一個成員,該枚舉在Vulkan中用于很多地方。如将在第七章“圖形管線”中見到,這個枚舉會被用于指定深度測試操作。可用的操作和它們在着色器通路深度資源時的語境在Table 6.2中展示。

采樣器可被配置來限制在一個帶有mipmaps的圖像mip levels中一個子集。被限制的mipmap範圍通過minLod and maxLod指定,它倆包含了應被采樣的最低(最高分辨率)和最高(最低分辨率)的mipmaps。要在整個mipmaps鍊上做采樣,設定minLod to 0.0, 并設定 maxLod為高到不能再進行clamp的level of detail層。

最後,unnormalizedCoordinates是一個标志位,當被設定為VK_TRUE時,表示圖像被用于采樣的坐标是以原生紋素為機關。而不是從0.0到1.0歸一化的值。這允許可從圖像裡顯式的取出紋素。然而,這種模式存在幾個限制。當unnormalizedCoordinates是VK_TRUE時,minFilter 和 magFilter必須是相同的,mipmapMode必須是VK_SAMPLER_MIPMAP_MODE_NEAREST,anisotropyEnable必須是VK_FALSE。

當你使用完了采樣器,你應該調用vkDestroySampler()銷毀它,其原型如下:

         voidvkDestroySampler (

VkDevice device,

VkSampler sampler,

const VkAllocationCallbacks* pAllocator);

device是擁有該采樣器對象的裝置,sampler是需被銷毀的采樣器對象。如果在建立采樣器對象時使用了主機記憶體配置設定器,一個相容的記憶體配置設定器也需要通過pAllocator參數傳入。否則,pAllocator應置為nullptr。

總結

本章覆寫了Vulkan支援的着色語言的基礎、SPIR-V,包含了如何Vulkan如何接收SPIR-V着色器module,包含這些着色器的管線如何構造。你看到可如何狗仔計算着色器并用它來建立計算管線,如何分發工作到管線,如何讓管線通路資源以産生資料。在接下來的章節裡,我們将繼續深入管線的概念來建立擁有多階段的管線對象并使用更多的進階特性。