你們好,本文學習與MSAA相關的Alpha To Coverage以及在WebGPU中的實現。html
上一篇博文
WebGPU學習(三):MSAAgit
下一篇博文
WebGPU學習(五): 現代圖形API技術要點和WebGPU支持狀況調研github
開啓了MSAA和Alpha To Coverage後,fragment的alpha值(fragment shader輸出的顏色的alpha值)會影響該fragment對應像素的採樣點是否被覆蓋。web
參考亂彈紀錄II:Alpha To Coverage:
算法
經過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表示被覆蓋。google
因此coverage這個掩碼對應了採樣點的覆蓋狀況。code
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)
暫時沒有實現的sample,咱們根據WebGPU規範和相關資料,分析下WebGPU如何實現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
根據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