WebGPU學習(四):Alpha To Coverage
大家好,本文學習與MSAA相關的Alpha To Coverage以及在WebGPU中的實現。
上一篇博文
WebGPU學習(三):MSAA
下一篇博文
WebGPU學習(五): 現代圖形API技術要點和WebGPU支持情況調研
學習Alpha To Coverage
前置知識
- WebGPU學習(三):MSAA
- 一個fragment對應一個像素
介紹
開啟了MSAA和Alpha To Coverage后,fragment的alpha值(fragment shader輸出的顏色的alpha值)會影響該fragment對應像素的采樣點是否被覆蓋。
動機
原理
覆蓋檢測
通過WebGPU學習(三):MSAA對MSAA原理的介紹,我們知道gpu要經過覆蓋檢測的步驟,來決定哪些采樣點被覆蓋。沒有被覆蓋的采樣點不會進入“解析”步驟。
覆蓋檢測的結果是計算出每個fragment的coverage(覆蓋率)。
根據亂彈紀錄II:Alpha To Coverage 的說法,開啟MSAA后,每個fragment帶了一個新屬性coverage(覆蓋率),它是一個二進制的bit掩碼mask。
以4X MSAA為例,每個fragment的coverage為xxxx,其中x為0或1。它的每一位對應像素的一個采樣點sample,0表示該sample沒被覆蓋,1表示被覆蓋。
所以coverage這個掩碼對應了采樣點的覆蓋情況。
如何計算coverage
1.用戶可以設置一個固定的coverage掩碼,這里命名為FixedSampleMask
2.gpu檢測每個像素有哪些采樣點被primitive覆蓋,得到該采樣點的coverage掩碼,這里命名為RasterizerCoverageMask
3.如果開啟了Alpha To Coverage,則會將fragment的alpha值轉換為coverage掩碼,這里命名為AlphaCoverageMask
轉換的算法可以參考亂彈紀錄II:Alpha To Coverage :
一個fragment的Alpha值在0~1間,它對應著一個dither mask。還是以4XMSAA為例,這個dither mask也是xxxx的形式,Alpha為0對應了0000,alpha為1對應了1111,至于中間的值的對應關系,OpenGL是交由顯卡制造商決定的——其實一般就是類似[0~0.249 -> 0000, 0.25~0.499 -> 0001, 0.5~0.749 -> 0011, 0.75~0.99-> 0111]這樣。
4.fragment shader可以輸出該fragment的coverage掩碼,這里稱為FragShaderSampleMaskOutput
像素最終的coverage = FixedSampleMask & RasterizerCoverageMask & AlphaCoverageMask & FragShaderSampleMaskOutput
(“&”是邏輯與運算,如0011 & 0010 = 0010)
參考資料
WebGPU實現Alpha To Coverage
暫時沒有實現的sample,我們根據WebGPU規范和相關資料,分析下WebGPU如何實現Alpha To Coverage。
- 在render pipeline descriptor中設置固定的coverage掩碼FixedSampleMask和是否開啟Alpha To Coverage:
dictionary GPURenderPipelineDescriptor : GPUPipelineDescriptorBase {
...
unsigned long sampleMask = 0xFFFFFFFF;
boolean alphaToCoverageEnabled = false;
...
};
我們注意到sampleMask是unsigned long類型,它是32位的,而coverage應該是二進制的(如4X MSAA的coverage是4位的二進制),所以這里是進行了進制轉換。
舉例來說:
對于4X MSAA,如果設置sampleMask為0x1(十六進制),則它轉換為二進制是0001;
如果設置sampleMask為0x3,則它轉換為二進制是0010
- 可以在fragment shader中設置輸出的coverage掩碼FragShaderSampleMaskOutput
根據Investigation: Multisample Coverage,我們知道Vulkan->SPIR-V的fragment shader支持內置的SampleMask變量。
因為Chrome實現的WebGPU也使用SPIR-V作為shader編譯后的字節碼,所以WebGPU在這點上應該與Vulkan類似。
我沒有搜索到SPIR-V中關于SampleMask的詳細資料,但是考慮到Chrome實現的WebGPU使用GLSL 4.5,所以我們可以看下它關于gl_SampleMask的說明:
Name
gl_SampleMask — specifies the sample coverage mask for the current fragment
Declaration
out int gl_SampleMask[] ;
我們看到gl_SampleMask的每個元素的類型是32位的,所以也進行了進制轉換。
又因為它是數組,所以它支持coverage為超過32位的二進制(如支持64X MSAA)
用代碼來說明:
//in fragment shader
gl_SampleMask[0] = 1; //對于4X MSAA來說,相當于設置該fragment的coverage為0001
//in fragment shader
gl_SampleMask[0] = 2;
gl_SampleMask[1] = 1; //對于64X MSAA來說,可能相當于設置該fragment的coverage為000...1000...10 (前面的000...1有32位,后面的000...10有32位) (我不能確定這是否正確!)
-
如果開啟了Alpha To Coverage,則不能在fragment shader中輸出coverage掩碼
-
如果開啟了Alpha To Coverage,將alpha轉換為掩碼的算法在不同的瀏覽器中不一樣
參考資料
Investigation: Multisample Coverage
Minutes for GPU Web meeting 2019-04-29
OpenGL->gl_SampleMask





浙公網安備 33010602011771號