讲师中心 微信公众号
AI工具推荐 视频效率加速

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

酷瑶酱_7106

酷瑶酱_7106

发布时间:2025-10-13 08:48:34

|

952人浏览过

|

来源于php中文网

原创

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。

    Html2md
    Html2md

    使用 Readability + Turndown 将 HTML 页面转换为干净的、Agent 友好的 Markdown。去除导航栏、广告、页脚、Cookie 横幅、社交按钮等干扰元素。支持 URL...

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

插值模式

默认情况下,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 的每个三角形赋予不同的颜色。这种方法为实现更复杂的渲染效果提供了基础。同时,需要理解顶点顺序和插值模式,才能正确地控制每个三角形的颜色。

热门AI工具

更多
豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

墨刀AI
墨刀AI Hot

一款AI图像与设计工具,主要用于产品经理的专属智能体,适合需要提升相关任务效率的用户。

讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

咔片AIPPT

一款在线AI演示文稿制作工具,可根据主题和内容需求辅助生成PPT结构与页面,提高演示材料制作效率。

超级简历WonderCV

一款AI办公效率工具,主要用于免费求职简历模版下载制作,应届生职场人必备简历制作神器,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

相关专题

更多
golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

4854

2025.06.09

golang结构体方法
golang结构体方法

本专题整合了golang结构体相关内容,请阅读专题下面的文章了解更多。

5011

2025.07.04

location.assign
location.assign

在前端开发中,我们经常需要使用JavaScript来控制页面的跳转和数据的传递。location.assign就是JavaScript中常用的一个跳转方法。通过location.assign,我们可以在当前窗口或者iframe中加载一个新的URL地址,并且可以保存旧页面的历史记录。php中文网为大家带来了location.assign的相关知识、以及相关文章等内容,供大家免费下载使用。

2862

2023.06.27

CSS position定位有几种方式
CSS position定位有几种方式

有4种,分别是静态定位、相对定位、绝对定位和固定定位。更多关于CSS position定位有几种方式的内容,可以访问下面的文章。

352

2023.11.23

Gradle插件开发入门教程
Gradle插件开发入门教程

本专题介绍Gradle插件开发的基本流程,涵盖插件类编写、自定义任务注册、扩展参数设计和插件应用方法,帮助你理解插件如何组织构建逻辑,减少多个项目之间的重复配置。

40

2026.10.22

Gradle Wrapper配置教程
Gradle Wrapper配置教程

本专题介绍Gradle Wrapper的基本作用,涵盖文件组成、生成方法、版本配置和任务调用,帮助你理解项目如何使用指定的Gradle版本,减少不同开发环境带来的构建差异。

20

2026.10.22

Golangci-lint检查器使用教程
Golangci-lint检查器使用教程

本专题整理Golangci-lint常用Linters的用途与配置方法,覆盖错误处理、无效代码、安全、复杂度、命名和依赖检查,帮助项目合理选规则。

20

2026.10.22

Gradle怎么构建Java项目
Gradle怎么构建Java项目

本专题介绍Gradle Java项目构建方法,涵盖Java插件配置、依赖声明、源码编译、测试执行和打包检查,帮助你理解各阶段的任务关系,逐步完成项目构建。

0

2026.10.22

PHP时间戳漏洞修复教程
PHP时间戳漏洞修复教程

本专题汇总PHP常见时间戳漏洞,包括2038年溢出、时区漂移、时间戳伪造、重放攻击、时间盲注与日志审计失效等,并给出升级64位环境、使用 DateTimeImmutable、统一UTC、严格超时校验、预处理绑定、hash_equals 比对等修复方案,帮助开发者快速排查和加固时间相关代码。

20

2026.10.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
GDB 17.2 官方文档集合
GDB 17.2 官方文档集合

共0课时 | 0人学习

Bootstrap 入门安装配置
Bootstrap 入门安装配置

共0课时 | 0人学习

38+ PhpStorm 提示和技巧
38+ PhpStorm 提示和技巧

共1课时 | 227人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn