<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      WebGPU學習(三):MSAA

      大家好,本文學習MSAA以及在WebGPU中的實現。

      上一篇博文
      WebGPU學習(二): 學習“繪制一個三角形”示例

      下一篇博文
      WebGPU學習(四):Alpha To Coverage

      學習MSAA

      介紹

      MSAA(多重采樣抗鋸齒),是硬件實現的抗鋸齒技術

      動機

      參考深入剖析MSAA

      具體到實時渲染領域中,走樣有以下三種:
      1.幾何體走樣(幾何物體的邊緣有鋸齒),幾何走樣由于對幾何邊緣采樣不足導致。
      2.著色走樣,由于對著色器中著色公式(渲染方程)采樣不足導致。比較明顯的現象就是高光閃爍。
      3.時間走樣,主要是對高速運動的物體采樣不足導致。比如游戲中播放的動畫發生跳變等。

      這里討論幾何體走樣。
      anti_aliasing_rasterization.png-27.2kB

      如上圖所示,我們要繪制一個三角形。它由三個頂點組成,紅線范圍內的三角形是片元primitive覆蓋的區域。
      primitive會被光柵化為fragment,而一個fragment最終對應屏幕上的一個像素,如圖中的小方塊所示。

      gpu會根據像素中心的采樣點是否被pritimive覆蓋來判斷是否生成該fragment和執行對應的fragment shader。

      圖中紅色的點是被覆蓋的采樣點,它所在的像素會被渲染。

      下圖是最終渲染的結果,我們看到三角形邊緣產生了鋸齒:
      anti_aliasing_rasterization_filled.png-14.2kB

      原理

      MSAA通過增加采樣點來減輕幾何體走樣。
      它包括4個步驟:
      1.針對采樣點進行覆蓋檢測
      2.每個被覆蓋的fragment執行一次fragment shader
      3.針對采樣點進行深度檢測和模版檢測
      4.解析(resolve)

      下面以4X MSAA為例(每個像素有4個采樣點),說明每個步驟:

      1.針對采樣點進行覆蓋檢測

      gpu會計算每個fragment的coverage(覆蓋率),從而得知對應像素的每個采樣點是否被覆蓋的信息。

      coverage相關知識可以參考WebGPU學習(四):Alpha To Coverage -> 學習Alpha To Coverage -> 原理

      這里為了簡化,我們只考慮通過“檢測每個像素有哪些采樣點被primitive覆蓋”來計算coverager:

      anti_aliasing_rasterization_samples.png-38.9kB

      如上圖所示,藍色的采樣點是在三角形中,是被覆蓋的采樣點。

      2.每個被覆蓋的fragment執行一次fragment shader

      如果一個像素至少有一個采樣點被覆蓋,那么會執行一次它對應的fragment(注意,只執行一次哈,不是執行4次)(它所有的輸入varying變量都是針對其像素中心點而言的,所以計算的輸出的顏色始終是針對該柵格化出的像素中心點而言的),輸出的顏色保存在color buffer中(覆蓋的采樣點都要保存同一個輸出的顏色)

      3.針對采樣點進行深度檢測和模版檢測

      所有采樣點的深度值和模版值都要存到depth buffer和stencil buffer中(無論是否被覆蓋)。

      被覆蓋的采樣點會進行深度檢測和模版檢測,通過了的采樣點會進入“解析”步驟。

      那為什么要保存所有采樣點的深度和模版值了(包括沒有被覆蓋的)?因為它們在深度檢測和模版檢測階段決定所在的fragment是否被丟棄:

      那是因為之后需要每個sample(采樣點)都執行一下depth-test,以確定整個fragment是否要流向(通往緩沖區輸出的)流水線下一階段——只有當全部fragment-sample的Depth-Test都Fail掉的時候,才決定拋棄掉這個fragment(蒙版值stencil也是這樣的,每個sample都得進行Stencil-Test)。

      4.解析

      什么是解析?

      根據深入剖析MSAA 的說法:

      像超采樣一樣,過采樣的信號必須重新采樣到指定的分辨率,這樣我們才可以顯示它。
      這個過程叫解析(resolving)。

      根據亂彈紀錄II:Alpha To Coverage 的說法:

      在把所有像素輸出到渲染緩沖區前執行Resolve以生成單一像素值。
      。。。。。。
      也該是時候談到一直說的“計算輸出的顏色”是怎么一回事了。MultiSample的Resolve階段,如果是屏幕輸出的話這個階段會發生在設備的屏幕輸出直前;如果是FBO輸出,則是發生在把這個Multisample-FBO映射到非multisample的FBO(或屏幕)的時候(見[多重采樣(MultiSample)下的FBO反鋸齒] )。Resolve,說白了就是把MultiSample的存儲區域的數據,根據一定法則映射到可以用于顯示的Buffer上了(這里的輸出緩沖區包括了Color、Depth或還有Stencil這幾個)。Depth和Stencil前面已經提及了法則了,Color方面其實也簡單,一般的顯卡的默認處理就是把sample的color取平均了。注意,因為depth-test等Test以及Coverage mask的影響下,有些sample是不參與計算的(被摒棄),例如4XMSAA下上面的0101,就只有兩個sample,又已知各sample都對應的只是同一個顏色值,所以輸出的顏色 = 2 * fragment color / 4 = 0.5 * fragment color。也就是是說該fragemnt最終顯示到屏幕(或Non-MS-FBO)上是fragment shader計算出的color值的一半——這不僅是顏色亮度減半還包括真·透明度值的減半。

      我的理解:
      “解析”是把每個像素經過上述步驟得到的采樣點的顏色值,取平均值,得到這個像素的顏色值。

      anti_aliasing_sample_points.png-6.7kB
      如上圖右邊所示,像素的2個采樣點進入了“解析”,最終該像素的顏色值為 0.5(2/4) * 原始顏色值

      經過上述所有步驟后,最終的渲染結果如下:
      anti_aliasing_rasterization_samples_filled.png-50.4kB

      總結

      MSAA能減輕幾何體走樣,但會增加color buffer、depth buffer、stencil buffer開銷。

      參考資料

      深入剖析MSAA
      亂彈紀錄II:Alpha To Coverage
      Anti Aliasing

      WebGPU實現MSAA

      有下面幾個要點:

      • 能夠查詢最大的采樣個數sample count

      目前我沒找到查詢的方法,但至少支持4個采樣點

      參考 Investigation: Multisampled Render Targets and Resolve Operations

      We can say that 4xMSAA is guaranteed on all WebGPU implementations, and we need to provide APIs for queries on whether we can create a multisampled texture with given format and sample count.

      • 設置sample count
      dictionary GPURenderPipelineDescriptor : GPUPipelineDescriptorBase {
      ...
          unsigned long sampleCount = 1;
      ...
      };
      
      dictionary GPUTextureDescriptor : GPUObjectDescriptorBase {
      ...
          unsigned long sampleCount = 1;
      ...
      };
      

      我們在WebGPU 規范中看到render pipeline descriptor和texture descriptor可以設置sampleCount。

      • 設置resolveTarget

      在“解析”步驟中,需要重新采樣到指定的分辨率:

      過采樣的信號必須重新采樣到指定的分辨率,這樣我們才可以顯示它

      所以我們應該設置color的resolveTarget(depth、stencil不支持resolveTarget),它包含“分辨率”的信息。

      我們來看下WebGPU 規范:

      dictionary GPURenderPassColorAttachmentDescriptor {
          required GPUTextureView attachment;
          GPUTextureView resolveTarget;
      
          required (GPULoadOp or GPUColor) loadValue;
          GPUStoreOp storeOp = "store";
      };
      

      resolveTarget在render pass colorAttachment descriptor中設置,它的類型是GPUTextureView。

      而GPUTextureView是從GPUTexture得來的,我們來看下GPUTexture的descriptor的定義:

      dictionary GPUExtent3DDict {
          required unsigned long width;
          required unsigned long height;
          required unsigned long depth;
      };
      typedef (sequence<unsigned long> or GPUExtent3DDict) GPUExtent3D;
      
      dictionary GPUTextureDescriptor : GPUObjectDescriptorBase {
      ...
        required GPUExtent3D size;
      ...
      };
      

      GPUTextureDescriptor的size屬性有width和height屬性,只要texture對應了屏幕大小,我們就能獲得屏幕“分辨率”的信息(depth設為1,因為分辨率只有寬、高,沒有深度)。

      實現sample

      我們對應到sample來看下。

      打開webgpu-samplers->helloTriangleMSAA.ts文件。

      代碼基本上與我們上篇文章學習的webgpu-samplers->helloTriangle.ts差不多,

      我們看下創建render pipeline代碼

          const sampleCount = 4;
      
          const pipeline = device.createRenderPipeline({
          ...
            sampleCount,
          });
      

      這里設置了sample count為4

      我們看下frame函數->render pass descrptor代碼

            const renderPassDescriptor: GPURenderPassDescriptor = {
              colorAttachments: [{
                attachment: attachment,
                resolveTarget: swapChain.getCurrentTexture().createView(),
                ...
              }],
            };
      
      • 設置attachment為多重采樣的texture的view

      該texture的創建代碼為:

          const texture = device.createTexture({
            size: {
              width: canvas.width,
              height: canvas.height,
              depth: 1,
            },
            sampleCount,
            format: swapChainFormat,
            usage: GPUTextureUsage.OUTPUT_ATTACHMENT,
          });
          const attachment = texture.createView();
      

      注意:texture的sampleCount應該與render pipeline的sampleCount一樣,都是4

      • 設置resolveTarget為swapChain對應的view

      swapChain.getCurrentTexture()獲得的texture的大小是與屏幕相同,所以它包含了屏幕分辨率的信息。

      參考資料

      helloTriangleMSAA.ts
      Investigation: Multisampled Render Targets and Resolve Operations

      posted @ 2019-12-07 22:24  楊元超  閱讀(1948)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 国产av一区二区午夜福利| 兴业县| 少妇撒尿一区二区在线视频| 小嫩批日出水无码视频免费 | 午夜福利免费视频一区二区| 亚洲成av人片在www色猫咪| 欧美日韩国产图片区一区| 亚洲啪啪精品一区二区的| 欧美浓毛大泬视频| 亚洲Av综合日韩精品久久久| 蜜桃av多人一区二区三区| 亚洲精品tv久久久久久久久久| 极品少妇无套内射视频| 昌宁县| 国产av丝袜熟女一二三| 99久久99久久精品国产片| 人妻精品人妻无码一区二区三区| 东京热大乱系列无码| 潮喷失禁大喷水av无码| 成人午夜在线观看刺激| 免费看成人欧美片爱潮app| 国产人妻大战黑人20p| 99在线精品免费视频| 久久综合亚洲鲁鲁九月天| 精品亚洲无人区一区二区| 久久久久国精品产熟女久色| 日本欧美大码a在线观看| 99久久国产综合精品女同| 亚洲日本va午夜中文字幕久久| 2020年最新国产精品正在播放| 亚欧美闷骚院| 嫩草欧美曰韩国产大片| 非会员区试看120秒6次| 日韩一区二区三区女优丝袜| 国产成人a∨激情视频厨房| 日韩人妻少妇一区二区三区| 无套内射视频囯产| 国内女人喷潮完整视频| 惠水县| 亚洲中文久久久精品无码| 精品人妻av综合一区二区|