1. 程式人生 > >Vulkan程式設計指南翻譯 第七章 圖形管線 第4節 建立簡單的圖形管線(下)

Vulkan程式設計指南翻譯 第七章 圖形管線 第4節 建立簡單的圖形管線(下)

這一節實在太長了,拖了好久。還是分開發吧。

7.4.3  輸入組裝

圖形管線的輸入組裝階段接受頂點資料,並把它們分組,組成圖元,以供管線接下來的部分處理。它是通過一個VkPipelineInputAssemblyStateCreateInfo型別的資料描述的,通過VkGraphicsPipelineCreateInfo型別資料的pInputAssemblyState成員傳遞。VkPipelineInputAssemblyStateCreateInfo的定義是:

typedef struct VkPipelineInputAssemblyStateCreateInfo {

VkStructureType sType;

const void* pNext;

VkPipelineInputAssemblyStateCreateFlags flags;

VkPrimitiveTopology topology;

VkBool32 primitiveRestartEnable;

} VkPipelineInputAssemblyStateCreateInfo;

sType域應置為VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFOpNext應置為nullptrflags域被保留使用,應置為0。圖元拓撲型別由topology指定,應該是受Vulkan

支援的圖元拓撲型別之一。它們是VkPrimitiveTopology型別的列舉。列舉中最簡單的成員是list拓撲,如下所示:

VK_PRIMITIVE_TOPOLOGY_POINT_LIST: Each vertex is used to construct an

independent point.

VK_PRIMITIVE_TOPOLOGY_LINE_LIST: Vertices are grouped into pairs, each pair

forming a line segment from the first to the second vertex.

VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: Vertices are grouped into triplets forming

Triangles.

接下來是stripfan圖元。這些是頂點組成的圖元(線段或者三角形)再組成的,每一個線段或者三角形都與上一個共享一個或者兩個頂點。stripfan圖元如下所示:

VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: The first two vertices in a draw form a single

line segment. Each new vertex after them forms a new line segment from the last processed

vertex. The result is a connected sequence of lines.

VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: The first three vertices in a draw form a

single triangle. Each subsequent vertex forms a new triangle along with the last two vertices.

The result is a connected row of triangles, each sharing an edge with the last.

VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: The first three vertices in a draw form a

single triangle. Each subsequent vertex forms a new triangle along with the last vertex and the

first vertex in the draw.

Strip and fan拓撲並不複雜,但是如果對它們不熟悉可能不容易繪製出來。Figure 7.2展示了它們圖形化的佈局。

Figure 7.2: Strip (Left) and Fan (Right) Topologies

接下來是鄰接圖元,通常是幾何著色器啟用了才被使用,可以攜帶有關於在同一個mesh裡鄰近圖元的附加資訊。鄰接圖元拓撲有:

VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: Every four vertices in the

draw form a single primitive, with the center two vertices forming a line and the first and last

vertex in each group of four being presented to the geometry shader, when present.

VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: The first four vertices in

the draw form a single primitive, with the center two vertices forming a line segment and the

first and last being presented to the geometry shader as adjacency information. Each subsequent

vertex essentially slides this window of four vertices along by one, forming a new line segment

and presenting the new vertex as adjacency information.

VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: Similar to lines with

adjacency, each group of six vertices is formed into a single primitive, with the first, third, and

fifth in each group constructing a triangle and the second, fourth, and sixth being presented to

the geometry shader as adjacency information.

VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: This is perhaps the

most confusing primitive topology and certainly needs a diagram to visualize. Essentially, the

strip begins with the first six vertices forming a triangle with adjacency information as in the list

case. For every two new vertices, a new triangle is formed, with the odd-numbered vertices

forming the triangle and the even-numbered vertices providing adjacency information.

鄰接圖元很難被視覺化出來--特別是VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY拓撲。Figure 7.3示例了在VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY拓撲中頂點的佈局。在這張圖中你可以看到從12個頂點中形成了兩個三角形。頂點由外層包裹一個三角形,奇數序號的頂點形成了中心三角形(AB),偶數序號的頂點形成了並不會被渲染的虛擬的三角形,但是,攜帶有鄰接的資訊。這個概念也同樣在三角形strip圖元中適用,Figure 7.4展示瞭如何應用到VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY

Figure 7.3: Triangles with Adjacency Topology

Figure 7.4: Triangle Strip with Adjacency Topology

鄰接拓撲通常在幾何著色器存在時才被使用,因為幾何著色器是唯一能夠看到鄰接頂點的階段。然而,也可能沒有幾何著色器的情況下使用鄰接圖元,鄰接的頂點直接被扔掉了而已。

7.4.4  細分狀態

7.4.5  視口狀態

7.4.6  柵格化狀態

7.4.7  多采樣狀態

多采樣是為影象內每一個畫素生成多個樣本的過程。用來對抗走樣,在影象直接使用時能很大程度上提升影象質量。當你進行多采樣時,顏色和深度-stencil附件必須是多采樣影象,並且管線的多采樣狀態應該通過VkGraphicsPipelineCreateInfopMultisampleState域合理設定。這個一個指向VkPipelineMultisampleStateCreateInfo型別資料的指標,該型別定義為:

typedef struct VkPipelineMultisampleStateCreateInfo {

VkStructureType sType;

const void* pNext;

VkPipelineMultisampleStateCreateFlags flags;

VkSampleCountFlagBits rasterizationSamples;

VkBool32 sampleShadingEnable;

float minSampleShading;

const VkSampleMask* pSampleMask;

VkBool32 alphaToCoverageEnable;

VkBool32 alphaToOneEnable;

} VkPipelineMultisampleStateCreateInfo;

VkPipelineMultisampleStateCreateInfosType域應置為VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFOpNext應置為nullptrflags域被保留使用,應置為0

7.4.8  深度stencil測試狀態

深度-stencil狀態控制瞭如何進行深度和stencil測試和如何決定片元如何通過這些測試。深度和stencil測試可以在片元著色器執行之前或之後進行。預設情況下,深度測試在片元著色器執行之後發生。1

1. Most implementations will only keep up the appearance that the depth and stencil tests are running after the fragment shader and, if possible, run the tests before running the shader to avoid running shader code when the test would fail.

要在深度測試之前執行片元著色器,我們可以設定我們的片元著色器入口為SPIR-V EarlyFragmentTests執行模式。

Depth-stencil狀態通過VkGraphicsPipelineCreateInfo型別的成員pDepthStencilState,一個指向VkPipelineDepthStencilStateCreateInfo型別資料的指標來配置。VkPipelineDepthStencilStateCreateInfo的定義是:

typedef struct VkPipelineDepthStencilStateCreateInfo {

VkStructureType sType;

const void* pNext;

VkPipelineDepthStencilStateCreateFlags flags;

VkBool32 depthTestEnable;

VkBool32 depthWriteEnable;

VkCompareOp depthCompareOp;

VkBool32 depthBoundsTestEnable;

VkBool32 stencilTestEnable;

VkStencilOpState front;

VkStencilOpState back;

float minDepthBounds;

float maxDepthBounds;

} VkPipelineDepthStencilStateCreateInfo;

VkPipelineDepthStencilStateCreateInfosType域應置為VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_CREATE_INFOpNext應置為nullptrflags域被保留使用,應置為0

如果depthTestEnable被設定為VK_TRUE,那麼深度測試被開啟。如果深度測試被啟用,那麼測試演算法可通過depthCompareOp選擇,它是VkCompareOp列舉值之一。可用的深度測試操作將在第十章“片元處理”中深入的講解。如果depthTestEnable被設定為VK_FALSE,那麼深度測試被關閉。depthCompareOp被啟用,所有的片元被認為已經通過了深度測試。需要注意,當深度測試被關閉是,將不會有深度緩衝區寫入操作。

如果通過了深度測試(或者深度測試被關閉),那麼片元測試繼續到stencil測試。如果VkPipelineDepthStencilCreateInfostencilTestEnable被設定為VK_TRUE,那麼stencil測試被開啟。當stencil測試被開啟時,front and back成員給正面和背面圖元提供了單獨的狀態。如果stencil測試被禁用了,所有的圖元被認為通過了stencil測試。

關於深度和stencil測試,將會在第十章“片元處理”中深入講解。

7.4.9  顏色混合狀態

Vulkan圖形管線的最後一個階段是顏色混合階段。這個階段負責把片元寫入顏色附件。在很多情況下,這是一個非常簡單的哦操作,僅僅是把附件的資料覆蓋為片元著色器的輸出即可。然而,顏色混合可以把幀緩衝區中已存在的值做混合,在片元著色器的輸出和當前的幀快取區的內容之間進行簡單的邏輯操作。

顏色混合狀態通過VkGraphicsPipelineCreateInfopColorBlendState成員指定。這是一個指向VkPipelineColorBlendStateCreateInfo型別例項的指標,該型別定義是:

typedef struct VkPipelineColorBlendStateCreateInfo {

VkStructureType sType;

const void* pNext;

VkPipelineColorBlendStateCreateFlags flags;

VkBool32 logicOpEnable;

VkLogicOp logicOp;

uint32_t attachmentCount;

const VkPipelineColorBlendAttachmentState* pAttachments;

float blendConstants[4];

} VkPipelineColorBlendStateCreateInfo;

VkPipelineColorBlendStateCreateInfosType域應置為VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFOpNext應置為nullptrflags域被保留使用,應置為0

logicOpEnable域指定了在片元著色器的輸出和顏色附件的內容之間是否進行邏輯操作。當logicOpEnableVK_FALSE時,邏輯操作被禁用,片元著色器的輸出被未經改變的寫入到顏色附件。當logicOpEnableVK_TRUE時,邏輯操作被支援他的附件啟用。採用的邏輯操作對於每個附件來說都是一樣的,它是VkLogicOp列舉型別的一個成員。每一個列舉的意義和關於邏輯操作的更多資訊在第十章“片元處理”中給出。

每一個附件可以有不同的格式,可以支援不同混合操作。這些是通過一個VkPipelineColorBlendAttachmentState型別陣列來指定的,陣列的地址通過VkPipelineColorBlendStateCreateInfo.型別資料的成員pAttachments來傳遞。附件個數通過attachmentCount設定。VkPipelineColorBlendAttachmentState的定義是:

typedef struct VkPipelineColorBlendAttachmentState {

VkBool32 blendEnable;

VkBlendFactor srcColorBlendFactor;

VkBlendFactor dstColorBlendFactor;

VkBlendOp colorBlendOp;

VkBlendFactor srcAlphaBlendFactor;

VkBlendFactor dstAlphaBlendFactor;

VkBlendOp alphaBlendOp;

VkColorComponentFlags colorWriteMask;

} VkPipelineColorBlendAttachmentState;

對已每一個顏色附件,VkPipelineColorBlendAttachmentState的成員控制了是否開啟混合,源和目標的比例因子,何種混合操作(),需要更新輸出影象的哪個通道。

如果VkPipelineColorBlendAttachmentStatecolorBlendEnable域為VK_TRUE,那麼剩餘的引數控制了混合的狀態。混合將會在第十章講到。當colorBlendEnableVK_FALSE是,VkPipelineColorBlendAttachmentState中的混合相關的引數被忽略,該附件的混合被禁用。

不管colorBlendEnable的狀態如何,最後一個域:colorWriteMask,控制了輸出影象的哪個通道寫入到福建。這是一個位域,由VkColorComponentFlagBits列舉的一個或多個值組橫。四個通道,由VK_COLOR_COMPONENT_R_BIT, VK_COLOR_COMPONENT_G_BIT,

VK_COLOR_COMPONENT_B_BIT, and VK_COLOR_COMPONENT_A_BIT表示,可以被單獨的設定。如果對應某個通道的標誌位沒有被包含在colorWriteMask,那麼這個通道將不會被修改。只有被colorWriteMask包含的通道將通過渲染到附件來更新。