美文网首页
Hello Triangle MSAA

Hello Triangle MSAA

作者: 不决书 | 来源:发表于2024-01-13 17:33 被阅读0次

代码分析说明:
部分说明请参考 Hello Triangle 以下只解释该功能的实现部分代码

import { makeSample, SampleInit } from '../../components/SampleLayout';

import triangleVertWGSL from '../../shaders/triangle.vert.wgsl';
import redFragWGSL from '../../shaders/red.frag.wgsl';

const init: SampleInit = async ({ canvas, pageState }) => {
  const adapter = await navigator.gpu.requestAdapter();
  const device = await adapter.requestDevice();

  if (!pageState.active) return;
  const context = canvas.getContext('webgpu') as GPUCanvasContext;

  const devicePixelRatio = window.devicePixelRatio;
  canvas.width = canvas.clientWidth * devicePixelRatio;
  canvas.height = canvas.clientHeight * devicePixelRatio;
  const presentationFormat = navigator.gpu.getPreferredCanvasFormat();

  context.configure({
    device,
    format: presentationFormat,
    alphaMode: 'premultiplied',
  });
  
 // 采样次数
  const sampleCount = 4;

  const pipeline = device.createRenderPipeline({
    layout: 'auto',
    vertex: {
      module: device.createShaderModule({
        code: triangleVertWGSL,
      }),
      entryPoint: 'main',
    },
    fragment: {
      module: device.createShaderModule({
        code: redFragWGSL,
      }),
      entryPoint: 'main',
      targets: [
        {
          format: presentationFormat,
        },
      ],
    },
    primitive: {
      topology: 'triangle-list',
    },
    // 渲染管线中添加采样次数
    multisample: {
      count: 4,
    },
  });

  // 采样所使用的纹理
  const texture = device.createTexture({
    size: [canvas.width, canvas.height],
    sampleCount,
    format: presentationFormat,
   // 设置纹理的用例为渲染附件
    usage: GPUTextureUsage.RENDER_ATTACHMENT,
  });
  // 该纹理为渲染的view 
  const view = texture.createView();

  function frame() {
    // Sample is no longer the active page.
    if (!pageState.active) return;

    const commandEncoder = device.createCommandEncoder();

    const renderPassDescriptor: GPURenderPassDescriptor = {
      colorAttachments: [
        {
          // 渲染的view
          view,
          // 如果view是多采样的,该纹理子资源将接收此颜色附件的解析输出
          resolveTarget: context.getCurrentTexture().createView(),
          clearValue: { r: 0.0, g: 0.0, b: 0.0, a: 1.0 },
          loadOp: 'clear',
          storeOp: 'discard',
        },
      ],
    };

    const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
    passEncoder.setPipeline(pipeline);
    passEncoder.draw(3);
    passEncoder.end();

    device.queue.submit([commandEncoder.finish()]);
    requestAnimationFrame(frame);
  }

  requestAnimationFrame(frame);
};

顶点着色器

@vertex
fn main(
  @builtin(vertex_index) VertexIndex : u32
) -> @builtin(position) vec4<f32> {
  var pos = array<vec2<f32>, 3>(
    vec2(0.0, 0.5),
    vec2(-0.5, -0.5),
    vec2(0.5, -0.5)
  );

  return vec4<f32>(pos[VertexIndex], 0.0, 1.0);
}

片元着色器

@fragment
fn main() -> @location(0) vec4<f32> {
  return vec4(1.0, 0.0, 0.0, 1.0);
}

总结步骤:

  1. navigator.gpu.requestAdapter申请适配器

  2. adapter.requestDevice 申请设备

  3. canvas.getContext('webgpu') 获取GPU上下文

  4. context.configure 配置上下文,将设备传给上下文

  5. device.createRenderPipeline 创建渲染管线, 并设置多重渲染的次数 multisample

6.device.createTexture 创建多重渲染的纹理,将纹理的view 传入编码器

  1. device.createCommandEncoder 创建编码器
  2. commandEncoder.beginRenderPass 开始编码由 descriptor 描述的渲染过程, 将view设置为多重渲染纹理的view, resolveTarget设置为canvas的 view

9 passEncoder.setPipeline 设置渲染管线

  1. passEncoder.draw 设置绘制顶点数
  2. passEncoder.end 编码结束
  3. commandEncoder.finish 完成编码
  4. device.queue.submit 提交编码器

相关文章

网友评论

      本文标题:Hello Triangle MSAA

      本文链接:https://www.haomeiwen.com/subject/ifzfodtx.html