首页 > web前端 > js教程 > 正文

WebGPU:在 Triangle Strip 中为每个三角形设置不同的颜色

霞舞
发布: 2025-10-11 13:05:01
原创
501人浏览过

webgpu:在 triangle strip 中为每个三角形设置不同的颜色

本文档详细介绍了如何在 WebGPU 中使用 `triangle-strip` 拓扑结构绘制三角形,并为每个三角形指定不同的颜色。核心在于理解顶点着色器和片元着色器之间的数据传递,以及如何利用插值修饰符来实现颜色区分。通过本文,你将掌握 WebGPU 中 Inter-Stage Variables 的使用,并能灵活地为 `triangle-strip` 中的每个三角形赋予独特的视觉效果。

在 WebGPU 中,要实现 triangle-strip 中每个三角形的不同颜色,关键在于理解顶点着色器和片元着色器之间的数据传递机制。直接在顶点着色器和片元着色器中声明同名变量并不能实现数据共享。我们需要使用 Inter-Stage Variables,并通过插值修饰符来控制颜色的应用方式。

Inter-Stage Variables 的使用

Inter-Stage Variables 是 WebGPU 中用于在顶点着色器和片元着色器之间传递数据的机制。它通过结构体定义,并使用 @location 属性来指定数据的位置。

以下是一个示例,展示了如何使用 Inter-Stage Variables 将三角形的索引传递给片元着色器,从而为每个三角形设置不同的颜色:

struct VSOut {
  @builtin(position) pos: vec4f,
  @location(0) @interpolate(flat) fi: i32,
};

@vertex
fn vs( @builtin(vertex_index) vi: u32 ) -> VSOut {
  var vsOut: VSOut;
  vsOut.fi = 1;
  if (vi > 0) {
    vsOut.fi = 2;
  }

  if(vi<3){
    var T = array<vec2f, 3>( vec2f(0,0), vec2f(.4,.7), vec2f(.8,0) );
    vsOut.pos = vec4f(T[vi],0,1);
    return vsOut;
  };
  vsOut.pos = vec4f(.6,-.5,0,1);
  return vsOut;
}

@fragment
fn fs(vsOut: VSOut) -> @location(0) vec4f {
  if(vsOut.fi == 1){ return vec4f(.7,.2,.2,.5); }; // color for 1st triangle ?
  return vec4f(.3,.6,.4,.5);
}
登录后复制

在这个例子中:

AI角色脑洞生成器
AI角色脑洞生成器

一键打造完整角色设定,轻松创造专属小说漫画游戏角色背景故事

AI角色脑洞生成器 176
查看详情 AI角色脑洞生成器
  1. 我们定义了一个名为 VSOut 的结构体,它包含了顶点位置 pos 和三角形索引 fi。@builtin(position) 用于声明顶点位置,@location(0) 用于指定 fi 在 Inter-Stage Variables 中的位置。
  2. @interpolate(flat) 修饰符用于禁用插值。默认情况下,Inter-Stage Variables 会在三角形的表面进行插值。@interpolate(flat) 确保传递给片元着色器的值是三角形的第一个顶点的值。
  3. 在顶点着色器 vs 中,我们根据顶点索引 vi 设置 vsOut.fi 的值。如果 vi 大于 0,则 vsOut.fi 设置为 2,否则设置为 1。
  4. 在片元着色器 fs 中,我们根据 vsOut.fi 的值选择不同的颜色。如果 vsOut.fi 等于 1,则返回红色,否则返回绿色。

完整示例代码

以下是完整的 WebGPU 代码,演示了如何使用 Inter-Stage Variables 和 @interpolate(flat) 修饰符来为 triangle-strip 中的每个三角形设置不同的颜色:

<!DOCTYPE html>
<html>
<head>
    <style>
        body{ background-color: #000 }
        canvas{ display: block; width: 600px; height: 400px; outline: 1px solid #666 }
    </style>
</head>
<body>
    <canvas width=900 height=600></canvas>
    <script type="module">
        let C = document.querySelector('canvas').getContext(`webgpu`),

        code=`

        struct VSOut {
          @builtin(position) pos: vec4f,
          @location(0) @interpolate(flat) fi: i32,
        };

        @vertex
        fn vs( @builtin(vertex_index) vi: u32 ) -> VSOut {

          // inter-stage variables are interpolated. In flat interpolation mode,
          // the values passed to the fragment shader are from the "provoking vertex"
          // which is the value set on the 1st vertex of the triangle
          var vsOut: VSOut;
          vsOut.fi = 1;
          if (vi > 0) {
            vsOut.fi = 2;
          }

          if(vi<3){
            var T = array<vec2f, 3>( vec2f(0,0), vec2f(.4,.7), vec2f(.8,0) );
            vsOut.pos = vec4f(T[vi],0,1);
            return vsOut;
          };
          vsOut.pos = vec4f(.6,-.5,0,1);
          return vsOut;
        }

        @fragment
        fn fs(vsOut: VSOut) -> @location(0) vec4f {
          if(vsOut.fi == 1){ return vec4f(.7,.2,.2,.5); }; // color for 1st triangle ?
          return vec4f(.3,.6,.4,.5);
        }`,

         format = `bgra8unorm`,
        adapter = await navigator.gpu.requestAdapter(),
         device = await adapter.requestDevice(),
              Q = device.queue,
              A = {loadOp: `clear`, storeOp: `store`}, // Attachments
              O = {colorAttachments: [ A ]},           // Render Pass Descriptor
              E, R,
         module = device.createShaderModule({ code }),
              P = device.createRenderPipeline({ layout: `auto`, primitive: { topology: `triangle-strip` },
                     vertex: { module, entryPoint: `vs`, },
                   fragment: { module, entryPoint: `fs`, targets: [{ format }] }
                  });

        C.configure({ device, format });

        function F(){
          A.view = C.getCurrentTexture().createView();

          E = device.createCommandEncoder();
          R = E.beginRenderPass(O);
          R.setPipeline(P);

          R.draw(4);
          R.end();
          Q.submit([E.finish()]);

          requestAnimationFrame(F)
        }

        F()

    </script>
</body>
</html>
登录后复制

这段代码首先获取 WebGPU 上下文,然后定义了 WGSL 代码。WGSL 代码包含了顶点着色器和片元着色器,它们使用 Inter-Stage Variables 来传递三角形索引,并根据索引设置不同的颜色。最后,代码创建了渲染管线,并使用 triangle-strip 拓扑结构绘制了两个三角形。

开启混合(Blending)

如果需要开启混合,可以在 createRenderPipeline 中配置 blend 属性。

 P = device.createRenderPipeline({ layout: `auto`, primitive: { topology: `triangle-strip` },
             vertex: { module, entryPoint: `vs`, },
           fragment: { module, entryPoint: `fs`, targets: [{ format,           blend: {
            color: {
              srcFactor: 'one',
              dstFactor: 'one-minus-src-alpha',
              operation: 'add',
            },
            alpha: {
              srcFactor: 'one',
              dstFactor: 'one-minus-src-alpha',
              operation: 'add',
            },
          }, }] }
          });
登录后复制

注意事项

  • 确保顶点着色器和片元着色器中的 @location 属性值匹配。
  • @interpolate(flat) 修饰符仅适用于禁用插值的情况。如果需要平滑的颜色过渡,可以移除该修饰符。
  • triangle-strip 的顶点顺序很重要,它决定了三角形的绘制顺序。

总结

通过本文,你学习了如何在 WebGPU 中使用 Inter-Stage Variables 和 @interpolate(flat) 修饰符来为 triangle-strip 中的每个三角形设置不同的颜色。这为创建更复杂、更具视觉吸引力的 WebGPU 应用程序奠定了基础。 掌握这些技术后,你可以进一步探索 WebGPU 的其他特性,例如纹理映射、光照和阴影等,从而创建更丰富的 3D 图形效果。

以上就是WebGPU:在 Triangle Strip 中为每个三角形设置不同的颜色的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
热门推荐
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号