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

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

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

      WebGPU學(xué)習(xí)(二): 學(xué)習(xí)“繪制一個(gè)三角形”示例

      大家好,本文學(xué)習(xí)Chrome->webgpu-samplers->helloTriangle示例。

      上一篇博文:
      WebGPU學(xué)習(xí)(一): 開篇

      下一篇博文:
      WebGPU學(xué)習(xí)(三):MSAA

      準(zhǔn)備Sample代碼

      克隆webgpu-samplers Github Repo到本地。
      (備注:當(dāng)前的version為0.0.2)

      實(shí)際的sample代碼在src/examples/文件夾中,是typescript代碼寫的:
      截屏2019-12-04下午3.53.16.png-64.7kB

      學(xué)習(xí)helloTriangle.ts

      打開helloTriangle.ts文件,我們來看下init函數(shù)的內(nèi)容。

      首先是shader代碼

          const vertexShaderGLSL = `#version 450
            const vec2 pos[3] = vec2[3](vec2(0.0f, 0.5f), vec2(-0.5f, -0.5f), vec2(0.5f, -0.5f));
      
            void main() {
                gl_Position = vec4(pos[gl_VertexIndex], 0.0, 1.0);
            }
          `;
      
          const fragmentShaderGLSL = `#version 450
            layout(location = 0) out vec4 outColor;
      
            void main() {
                outColor = vec4(1.0, 0.0, 0.0, 1.0);
            }
          `;
      

      這里是vertex shader和fragment shader的glsl代碼。

      (webgpu支持vertex shader、fragment shader、compute shader,這里只使用了前面兩個(gè))

      “#version 450”聲明了glsl版本為4.5(它要放在glsl的第一行)

      第2行定義了三角形的三個(gè)頂點(diǎn)坐標(biāo),使用2維數(shù)組保存(每個(gè)元素為vec2類型)。因?yàn)槎荚谝粋€(gè)平面,所以頂點(diǎn)只定義了x、y坐標(biāo)(頂點(diǎn)的z為0.0)

      第5行的gl_VertexIndex為頂點(diǎn)序號(hào),每次執(zhí)行時(shí)值依次為0、1、2(vertex shader被執(zhí)行了3次,因?yàn)橹挥?個(gè)頂點(diǎn))(具體見本文末尾對(duì)draw的分析)

      第9行是fragment shader,因?yàn)槿切螢橐粋€(gè)顏色,所以所有片段的顏色為同一個(gè)固定值

      然后我們繼續(xù)看下面的代碼

          const adapter = await navigator.gpu.requestAdapter();
          const device = await adapter.requestDevice();
          // 準(zhǔn)備編譯glsl的庫(kù)
          const glslang = await glslangModule();
          // 獲得webgpu上下文
          const context = canvas.getContext('gpupresent');
      

      第4行的glslangModule是import的第三方庫(kù):

      import glslangModule from '../glslang';
      

      繼續(xù)往下看

          // 定義swapbuffer的格式為RGBA8位的無符號(hào)歸一化格式
          const swapChainFormat = "bgra8unorm";
      
          // @ts-ignore:
          const swapChain: GPUSwapChain = context.configureSwapChain({
            device,
            format: swapChainFormat,
          });
      

      @ts-ignore是typescript用來忽略錯(cuò)誤的。因?yàn)閏ontext的類型是RenderingContext,它沒有定義configureSwapChain函數(shù),如果編譯該行typescript會(huì)報(bào)錯(cuò),所以需要忽略錯(cuò)誤。

      第5行配置了swap chain。vulkan tutorial對(duì)此進(jìn)行了說明:
      swap chain是一個(gè)緩沖結(jié)構(gòu),webgpu會(huì)先將內(nèi)容渲染到swap chain的buffer中,然后再將其顯示到屏幕上;
      swap chain本質(zhì)上是等待呈現(xiàn)在屏幕上的一個(gè)圖片隊(duì)列。

      接下來就是創(chuàng)建render pipeline

          const pipeline = device.createRenderPipeline({
            layout: device.createPipelineLayout({ bindGroupLayouts: [] }),
      
            vertexStage: {
              module: device.createShaderModule({
                code: glslang.compileGLSL(vertexShaderGLSL, "vertex"),
      
                // @ts-ignore
                source: vertexShaderGLSL,
                transform: source => glslang.compileGLSL(source, "vertex"),
              }),
              entryPoint: "main"
            },
            fragmentStage: {
              module: device.createShaderModule({
                code: glslang.compileGLSL(fragmentShaderGLSL, "fragment"),
      
                // @ts-ignore
                source: fragmentShaderGLSL,
                transform: source => glslang.compileGLSL(source, "fragment"),
              }),
              entryPoint: "main"
            },
      
            primitiveTopology: "triangle-list",
      
            colorStates: [{
              format: swapChainFormat,
            }],
          });
      

      了解pipeline

      WebGPU有兩種pipeline:render pipeline和compute pipeline,這里只用了render pipeline

      這里使用render pipeline descriptor來創(chuàng)建render pipeline,它的定義如下:

      dictionary GPUPipelineDescriptorBase : GPUObjectDescriptorBase {
          required GPUPipelineLayout layout;
      };
      
      ...
      
      dictionary GPURenderPipelineDescriptor : GPUPipelineDescriptorBase {
          required GPUProgrammableStageDescriptor vertexStage;
          GPUProgrammableStageDescriptor fragmentStage;
      
          required GPUPrimitiveTopology primitiveTopology;
          GPURasterizationStateDescriptor rasterizationState = {};
          required sequence<GPUColorStateDescriptor> colorStates;
          GPUDepthStencilStateDescriptor depthStencilState;
          GPUVertexStateDescriptor vertexState = {};
      
          unsigned long sampleCount = 1;
          unsigned long sampleMask = 0xFFFFFFFF;
          boolean alphaToCoverageEnabled = false;
          // TODO: other properties
      };
      

      render pipeline可以設(shè)置綁定的資源布局、編譯的shader、fixed functions(如混合、深度、模版、cullMode等各種狀態(tài)和頂點(diǎn)數(shù)據(jù)的格式vertexState),相對(duì)于WebGL(WebGL的一個(gè)API只能設(shè)置一個(gè),如使用gl.cullFace設(shè)置cull mode),提升了性能(靜態(tài)設(shè)置了各種狀態(tài),不需要在運(yùn)行時(shí)設(shè)置),便于管理(把各個(gè)狀態(tài)集中到了一起設(shè)置)。

      分析render pipeline descriptor

      vertexStage和fragmentStage分別設(shè)置vertex shader和fragment shader:
      使用第三方庫(kù),將glsl編譯為字節(jié)碼(格式為SPIR-V);
      source和transform字段是多余的,可以刪除。

      因?yàn)閟hader沒有綁定資源(如uniform buffer, texture等),所以第2行的bindGroupLayouts為空數(shù)組,不需要bind group和bind group layout

      第25行的primitiveTopology指定片元的拓?fù)浣Y(jié)構(gòu),此處為三角形。
      它可以為以下值:

      enum GPUPrimitiveTopology {
          "point-list",
          "line-list",
          "line-strip",
          "triangle-list",
          "triangle-strip"
      };
      

      現(xiàn)在先忽略colorStates

      我們繼續(xù)分析后面的代碼,接下來定義了frame函數(shù)

      frame函數(shù)定義了每幀執(zhí)行的邏輯:

          function frame() {
            const commandEncoder = device.createCommandEncoder({});
            const textureView = swapChain.getCurrentTexture().createView();
      
            const renderPassDescriptor: GPURenderPassDescriptor = {
              colorAttachments: [{
                attachment: textureView,
                loadValue: { r: 0.0, g: 0.0, b: 0.0, a: 1.0 },
              }],
            };
      
            const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
            passEncoder.setPipeline(pipeline);
            passEncoder.draw(3, 1, 0, 0);
            passEncoder.endPass();
      
            device.defaultQueue.submit([commandEncoder.finish()]);
          }
      
          return frame;
      

      學(xué)習(xí)command buffer

      我們不能直接操作command buffer,需要?jiǎng)?chuàng)建command encoder,使用它將多個(gè)commands(如render pass的draw)設(shè)置到一個(gè)command buffer中,然后執(zhí)行submit,把command buffer提交到gpu driver的隊(duì)列中。

      根據(jù) webgpu設(shè)計(jì)文檔->Command Submission:

      Command buffers carry sequences of user commands on the CPU side. They can be recorded independently of the work done on GPU, or each other. They go through the following stages:
      creation -> "recording" -> "ready" -> "executing" -> done

      我們知道,command buffer有
      creation, recording,ready,executing,done五種狀態(tài)。

      根據(jù)該文檔,結(jié)合代碼來分析command buffer的操作流程:
      第2行創(chuàng)建command encoder時(shí),應(yīng)該是創(chuàng)建了command buffer,它的狀態(tài)為creation;
      第12行開始render pass(webgpu還支持compute pass,不過這里沒用到),command buffer的狀態(tài)變?yōu)閞ecording;
      13-14行將“設(shè)置pipeline”、“繪制”的commands設(shè)置到command buffer中;
      第15行結(jié)束render pass,(可以設(shè)置下一個(gè)pass,如compute pass,不過這里只用了一個(gè)pass);
      第17行“commandEncoder.finish()”將command buffer的狀態(tài)變?yōu)閞eady;
      然后執(zhí)行subimit,command buffer狀態(tài)變?yōu)閑xecuting,被提交到gpu driver的隊(duì)列中,不能再在cpu端被操作;
      如果提交成功,gpu會(huì)決定在某個(gè)時(shí)間處理它。

      分析render pass

      第5行的renderPassDescriptor描述了render pass,它的定義為:

      dictionary GPURenderPassDescriptor : GPUObjectDescriptorBase {
          required sequence<GPURenderPassColorAttachmentDescriptor> colorAttachments;
          GPURenderPassDepthStencilAttachmentDescriptor depthStencilAttachment;
      };
      

      這里只用到了colorAttachments。它類似于WebGL->framebuffer的colorAttachments。這里只用到了一個(gè)color buffer attachment。

      我們來看下colorAttachment的定義:

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

      這里設(shè)置attachment,將其與swap chain關(guān)聯(lián):

                attachment: textureView,
      

      我們現(xiàn)在忽略resolveTarget。

      loadValue和storeOp決定渲染前和渲染后怎樣處理attachment中的數(shù)據(jù)。
      我們看下它的類型:

      enum GPULoadOp {
          "load"
      };
      enum GPUStoreOp {
          "store",
          "clear"
      };
      
      ...
      dictionary GPUColorDict {
          required double r;
          required double g;
          required double b;
          required double a;
      };
      typedef (sequence<double> or GPUColorDict) GPUColor;
      

      loadValue如果為GPULoadOp類型,則只有一個(gè)值:“l(fā)oad”,它的意思是渲染前保留attachment中的數(shù)據(jù);
      如果為GPUColor類型(如這里的{ r: 0.0, g: 0.0, b: 0.0, a: 1.0 }),則不僅為"load",而且設(shè)置了渲染前的初始值,類似于WebGL的clearColor。

      storeOp如果為“store”,意思是渲染后保存被渲染的內(nèi)容到內(nèi)存中,后面可以被讀取;
      如果為“clear”,意思是渲染后清空內(nèi)容。

      現(xiàn)在我們回頭看下render pipeline中的colorStates:

            colorStates: [{
              format: swapChainFormat,
            }],
      

      colorStates與colorAttachments對(duì)應(yīng),也只有一個(gè),它的format應(yīng)該與swap chain的format相同

      我們繼續(xù)看render pass代碼:

            const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
            passEncoder.setPipeline(pipeline);
            passEncoder.draw(3, 1, 0, 0);
            passEncoder.endPass();
      

      draw的定義為:

      void draw(unsigned long vertexCount, unsigned long instanceCount,
                    unsigned long firstVertex, unsigned long firstInstance);
      

      三角形有3個(gè)頂點(diǎn),這里只繪制1個(gè)實(shí)例,兩者都從0開始(所以vertex shader中的gl_VertexIndex依次為0、1、2),所以第3行為“draw(3, 1, 0, 0)”

      最終渲染結(jié)果

      截屏2019-12-04下午9.53.50.png-8kB

      參考資料

      webgpu-samplers Github Repo
      vulkan tutorial
      webgpu設(shè)計(jì)文檔->Command Submission
      WebGPU-4

      posted @ 2019-12-06 08:34  楊元超  閱讀(2773)  評(píng)論(7)    收藏  舉報(bào)
      主站蜘蛛池模板: 国内极度色诱视频网站| 天堂在线中文| 亚洲午夜精品久久久久久抢| 亚洲AV日韩AV综合在线观看| 亚洲欧洲日产国无高清码图片| 国产精品久久久久aaaa| 国产成人精品一区二区三| 精品无码国产污污污免费| 一本av高清一区二区三区| 欧美牲交a欧美牲交aⅴ免费真| 精品亚洲成A人在线观看青青| 日本一区二区三区后入式| 久久一日本道色综合久久| 亚洲综合91社区精品福利| 欧美激情一区二区三区在线| 亚洲国产精品一区二区三| 亚洲国产精品久久久天堂麻豆宅男 | 国产成人亚洲精品自产在线| 无码AV无码免费一区二区| 国产久免费热视频在线观看| 2018年亚洲欧美在线v| 亚洲国产高清第一第二区| 日韩黄色av一区二区三区| 99久久精品美女高潮喷水| 久久亚洲精品国产精品尤物| 亚洲成人av在线资源| 人妻激情乱人伦视频| 国产精品一区二区三区色| 国产亚洲精品第一综合| 乱码精品一区二区亚洲区| 福泉市| 国产稚嫩高中生呻吟激情在线视频| 亚洲中文无码永久免费| 少妇人妻偷人精品系列| 亚洲高潮喷水无码AV电影| 亚洲男人电影天堂无码| 国产高潮又爽又刺激的视频| 午夜成人精品福利网站在线观看| 日韩永久永久永久黄色大片| 国产亚洲精品在av| 男女18禁啪啪无遮挡激烈网站|