Vulkan shader模組使用

2021-10-04 20:29:39 字數 3757 閱讀 2449

與之前的影象api不同,vulkan中的著色器**必須以二進位制位元組碼的格式使用,而不是像glslhlsl這樣具有比較好的可讀性的語法。此位元組格式成為spir-v,它可以與vulkan和opencl一同使用。這是一種可以編寫圖形和計算著色器的格式,但我們重點介紹本教程中vulkan圖形流水線使用的著色器。

使用二進位制位元組碼格式的優點之一是 使得gpu廠商編寫將著色器**轉換為本地**的編譯器複雜度減少了很多。經驗表明使用可讀性比較強的語法,比如glsl一些gpu廠商相當靈活地理解這個標準。這導致一種情況會發生,比如編寫好,並在乙個廠商的gpu執行的不錯的著色器程式,可能在其他的gpu廠商的gpu驅動程式執行異常,可能是語法的問題,或者更糟的是不同gpu廠商編寫的編譯器差異,導致著色器執行錯誤。如果直接使用編譯好的二進位制位元組碼格式,可以避免這種情況。

glsl是具有c風格語法的著色語言。在程式中需要定義編寫main函式作為入口。glsl不會使用輸入引數和返回值作為輸出,而是使用全域性變數來處理輸入和輸出。該語言包括很多功能簡化圖形程式設計,比如內建的基於向量和矩陣的叉積操作函式,矩陣和向量乘法操作函式。向量型別為vec,數字表示分量的數量。例如3d位置儲存在vec3中。可以通過諸如.x之類的成員訪問單個分量,也可以通過多個分量建立乙個新的向量。比如,表示式vec3(1.0, 2.0, 3.0).xy擷取前兩個分量,並賦予新的vec2中。向量的建構函式也可以採用向量物件和標量值的組合。比如vec3可以用vec3(vec2(1.0, 2.0), 3.0)構造。

如前面提到的一樣,我們需要編寫乙個vertex shader和乙個fragment shader繪製三角形在螢幕。下面兩個小節會**與之相關的glsl**,並展示如何生成兩個spir-v二進位制檔案,最後載入到程式中。

頂點著色器:

頂點著色器處理每乙個頂點資料。它的屬性,如世界座標,顏色,法線和紋理uv座標作為輸入。輸出的是最終的clip coordinates 裁剪座標和需要傳遞到片元著色器的屬性,包括顏色和紋理uv座標。這些值會在光柵化階段進行內插值,以產生平滑的過度。

裁剪座標 clip coordinate 是乙個來此頂點著色器的思維向量,隨後通過向量最後乙個分量進行整體歸一化操作。這些歸一化後的裝置座標是homogeneous coordinates最終對映到緩衝區範圍為[-1, 1]的[-1, 1]座標系統,如下所示:

如果之前的計算機圖形比較熟悉的話,對這部分會比較熟悉。如果你之前使用過opengl,你會注意到y座標軸是反轉的,z座標軸的範圍與direct3d是一致的範圍,從0到1.

對於第乙個三角形,我們不會做任何轉換操作,我們將三個頂點的位置指定為歸一化裝置座標,建立如下圖形:

通常情況下頂點座標資料是儲存在乙個頂點緩衝區中,但是在vulkan中建立乙個頂點緩衝區並填充資料的過程並不是直接的。所以我們後置這些步驟,直到我們滿意的看到乙個三角形出現在螢幕上。同時我們需要做一些非正統的事情:將座標直接包含在頂點著色器的內部。**如下所示:

#version 450

#extension gl_arb_separate_shader_objects : enable

out gl_pervertex ;

vec2 positions[3] = vec2(

vec2(0.0, -0.5),

vec2(0.5, 0.5),

vec2(-0.5, 0.5)

);void main()

main函式的執行應用於每個頂點,內建的gl_vertexindex變數包含了當前頂點的索引資訊。通常是頂點緩衝區的索引,但是在這裡我們硬編碼到頂點資料的集合中。每個頂點的位置從常量陣列中訪問,並與zw分量組合使用,以產生裁剪座標中的有效位置資訊。內建的gl_position變數作為輸出。最後vulkan中使用shader,需要確保gl_arg_separate_shader_objects擴充套件開啟。

片元著色器:

由頂點著色器的位置資料形成的三角形用片段著色器填充螢幕上的區域中。片段著色器針對乙個或者多個framebuffer幀緩衝區的每個片元產生具體的顏色和深度資訊。乙個簡單的片段著色器為完成的三角形輸出紅色資訊的**如下:

#version 450

#extension gl_arb_separate_shader_objects : enable

layout(location = 0) out vec4 outcolor;

void main()

fragment sahder中的main函式與vertex shader中的main函式類似,會為每乙個片元呼叫處理。顏色的資訊在glsl中是4個分量組成的向量,包括r,g,b和alpha通道,值域收斂在[0, 1]範圍內。不像頂點著色器的gl_position,它沒有內建的變數為當前片元輸出顏色資訊。在這裡必須為framebuffer定義輸出變數,layout(location = 0)修飾符明確framebuffer的索引。紅色資訊寫進outcolor變數中,該變數鏈結第乙個framebuffer中,索引為0

輸入color

我們針對兩個型別的著色器嘗試做一些改變,完成上圖的效果。首先,我們需要為每個頂點設定差異化的顏色。頂點著色器應該包含乙個顏色陣列,就像位置資訊的陣列一樣:

vec3 colors[3] = vec3(

vec3(1.0, 0.0, 0.0),

vec3(0.0, 1.0, 0.0),

vec3(0.0, 0.0, 1.0)

);

現在我們需要把每個頂點的顏色傳遞到片段著色器中,從而輸出經過插值後的顏色資訊到framebuffer中。為頂點著色器添增加輸出顏色支援,在main函式中定義如下:

layout(location = 0) out vec3 fragcolor;

void main()

下一步,我們需要將片段著色器的輸入匹配頂點著色器的輸出:

layout(location = 0) in vec3 fragcolor;

void main()

輸入的變數不一定要同名,它們將通過location索引指令鏈結在一起。main函式中修改將要輸出的顏色alpha值。就像之前討論的一樣,fragcolor將會為三個頂點所屬的片元自動進行內插值,形成平滑的顏色過度。

Python webbrowser模組的使用

webbrowser模組提供了乙個高階介面來顯示基於web的文件,大部分情況下只需要簡單的呼叫open 方法。webbrowser定義了如下的異常 exception webbrowser.error,當瀏覽器控制項發生錯誤是會丟擲這個異常 webbrowser有以下方法 webbrowser.op...

python模組使用 python的模組使用

模組是python組織 的基本方式。乙個python指令碼可以單獨執行,也可以匯入到另乙個指令碼中執行,當指令碼被匯入執行時,我們將其稱為模組 module 所有的.py檔案都可以作為乙個模組匯入 模組名與指令碼的檔名相同 例如我們編寫了乙個名為hello.py的指令碼,則可以在另乙個指令碼中用im...

Nginx PageSpeed模組配置和使用

官方文件 pagespeed開啟和相關配置 今天給 新增了https支援,之後發現 之前用的pagespeed 不起作用了,檔案不能合併,找到文件 新增ssl支援就可以了 pagespeed sslcertdirectory directory pagespeed sslcertfile file ...