美文网首页
Hello Triangle

Hello Triangle

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

    代码分析说明:

    import { makeSample, SampleInit } from '../../components/SampleLayout';
    // 导入Shader 代码
    // 顶点着色器 着色器语言 使用WGSL语言
    import triangleVertWGSL from '../../shaders/triangle.vert.wgsl';
    // 片段着色器 使用WGSL语言
    import redFragWGSL from '../../shaders/red.frag.wgsl';
    
    // 页面初始化, 传入Canvas HTMLDOM 对象 与 页面状态
    const init: SampleInit = async ({ canvas, pageState }) => {
      // 申请一个适配器
      const adapter = await navigator.gpu.requestAdapter();
     // 通过适配器申请一个设备,大部分的API都是挂在设备上的 
     const device = await adapter.requestDevice();
     // 页面状态没有激活时,不执行
      if (!pageState.active) return;
     
      // 通过Canvas获取WebGPU的上下文 
      const context = canvas.getContext('webgpu') as GPUCanvasContext;
     // 获取屏幕像素比
      const devicePixelRatio = window.devicePixelRatio;
    
     // 设置画布Canvas的大小  
      canvas.width = canvas.clientWidth * devicePixelRatio;
      canvas.height = canvas.clientHeight * devicePixelRatio;
      // 获取显卡的最佳格式
      const presentationFormat = navigator.gpu.getPreferredCanvasFormat();
    
      // 配置GUP 上下文
      context.configure({
        device,
        format: presentationFormat,
        alphaMode: 'premultiplied',  // 透明模式,前乘 
      });
    
     // 创建渲染管线
      const pipeline = device.createRenderPipeline({
        layout: 'auto',  // 默认的布局
        vertex: {
          module: device.createShaderModule({  // 创建Shader对象
            code: triangleVertWGSL,
          }),
          entryPoint: 'main',  // 入口函数
        },
        fragment: {
          module: device.createShaderModule({ // 创建Shader对象
            code: redFragWGSL,
          }),
          entryPoint: 'main',  // 入口函数
          targets: [
            {
              format: presentationFormat,   // 绘制格式
            },
          ],
        },
        primitive: {
          topology: 'triangle-list',  // 三角方式绘制
        },
      });
    
      function frame() {
        // Sample is no longer the active page.
        if (!pageState.active) return;
      
       // 创建编码器 
        const commandEncoder = device.createCommandEncoder();
        // 绘制的view来自画布上下文
        const textureView = context.getCurrentTexture().createView();
    
        // 绘制描述
        const renderPassDescriptor: GPURenderPassDescriptor = {
        // 颜色的绘制方式  
        colorAttachments: [
            {
              view: textureView,  // 绘制的视图
              clearValue: { r: 0.0, g: 0.0, b: 0.0, a: 1.0 },  // 清屏色
              loadOp: 'clear',  // 此附件的清除值加载到渲染过程中
              storeOp: 'store', // 绘制的结果存储
            },
          ],
        };
      
       // 开始编码由 descriptor 描述的渲染过程。
        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> {
      // 渲染为红色 r g b a
      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 创建渲染管线
    6. device.createCommandEncoder 创建编码器
    7. commandEncoder.beginRenderPass 开始编码由 descriptor 描述的渲染过程。
    8. passEncoder.setPipeline 设置渲染管线
    9. passEncoder.draw 设置绘制顶点数
    10. passEncoder.end 编码结束
    11. commandEncoder.finish 完成编码
    12. device.queue.submit 提交编码器

    相关文章

      网友评论

          本文标题:Hello Triangle

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