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

WebGPU:使用 Triangle Strip 为每个三角形绘制不同颜色

心靈之曲
发布: 2025-10-13 08:48:34
原创
915人浏览过

webgpu:使用 triangle strip 为每个三角形绘制不同颜色

本文介绍了如何在 WebGPU 中使用 `triangle-strip` 拓扑结构为每个三角形绘制不同的颜色。核心在于理解顶点着色器和片元着色器之间的数据传递,并使用 Inter-Stage Variables 以及 `flat` 插值模式来实现对每个三角形颜色控制。通过修改顶点着色器和片元着色器,并结合 blend 设置,最终实现为每个三角形赋予不同颜色的效果。

在 WebGPU 中,要实现 triangle-strip 模式下每个三角形拥有不同颜色,关键在于理解顶点着色器和片元着色器之间的数据传递机制。默认情况下,顶点着色器和片元着色器是相互独立的,它们之间的变量不能直接共享。为了解决这个问题,我们需要使用 Inter-Stage Variables。

Inter-Stage Variables

Inter-Stage Variables 允许我们从顶点着色器向片元着色器传递数据。这些变量需要在顶点着色器中定义,并通过一个结构体返回。同时,在片元着色器中,该结构体作为输入参数接收。@location 装饰器用于指定变量的位置,建立顶点着色器和片元着色器之间的数据通道。

示例代码:

以下代码展示了如何使用 Inter-Stage Variables 来传递三角形索引,从而在片元着色器中根据索引设置不同的颜色。

<!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);                 // color for 2nd triangle
}`,

 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>
登录后复制

代码解释:

  1. 定义结构体 VSOut: 该结构体包含了顶点位置 pos 和三角形索引 fi。@builtin(position) 声明 pos 为内置变量,用于指定顶点位置。@location(0) 声明 fi 变量位于 location 0,用于和片元着色器对应。@interpolate(flat) 关闭了插值,保证每个三角形的 fi 值是固定的。

  2. 顶点着色器 vs: 根据顶点索引 vi 设置 fi 的值。vi < 3 时,fi 设置为 1,否则设置为 2。

  3. 片元着色器 fs: 根据接收到的 vsOut.fi 值,选择不同的颜色。如果 vsOut.fi 为 1,则返回红色,否则返回绿色。

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

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

    AI角色脑洞生成器176
    查看详情 AI角色脑洞生成器

插值模式

默认情况下,Inter-Stage Variables 会在三角形内部进行插值。这意味着片元着色器接收到的值是三角形顶点值的加权平均。为了避免颜色在三角形内部渐变,我们需要关闭插值。可以使用 @interpolate(flat) 装饰器来实现。加上这个装饰器后,片元着色器接收到的值将是三角形第一个顶点的值。

注意事项:

  • triangle-strip 的顶点顺序非常重要。每个三角形的第一个顶点决定了 @interpolate(flat) 装饰器传递的值。
  • 确保顶点着色器和片元着色器中的 @location 值匹配,否则数据将无法正确传递。

添加 Blend 设置

如果需要实现透明效果,可以添加 blend 设置。

<!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);                 // color for 2nd triangle
}`,

 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,           blend: {
            color: {
              srcFactor: 'one',
              dstFactor: 'one-minus-src-alpha',
              operation: 'add',
            },
            alpha: {
              srcFactor: 'one',
              dstFactor: 'one-minus-src-alpha',
              operation: 'add',
            },
          }, }] }
          });

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>
登录后复制

在 createRenderPipeline 中,对 fragment 的 target 添加 blend 属性,可以实现混合效果。

总结:

通过使用 Inter-Stage Variables 和 flat 插值模式,我们可以在 WebGPU 中轻松地为 triangle-strip 的每个三角形赋予不同的颜色。这种方法为实现更复杂的渲染效果提供了基础。同时,需要理解顶点顺序和插值模式,才能正确地控制每个三角形的颜色。

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

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

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

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

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