【WebGPU Unleashed】1.4 对不同的顶点设置不同颜色

一部2024新的WebGPU教程,作者Shi Yan。内容很好,翻译过来与大家共享,内容上会有改动,加上自己的理解。更多精彩内容尽在 dt.sim3d.cn ,关注公众号【sky的数孪技术】,技术交流、源码下载请添加微信号:digital_twin123

在本教程中,我们将对前面的示例进行另一个细微的修改。我们不是在着色器中硬编码颜色,而是将顶点颜色作为数据传递到着色器中,从而演示更灵活、更真实的 3D 渲染方法。在线示例。

让我们先看一下着色器代码中的更改。除了 @location(0) 处的位置属性之外,我们还在@location(1) 处引入了一个新的输入参数,我们将其命名为inColor。此 inColor 参数是一个由三个浮点数组成的向量,分别代表颜色的红色、绿色和蓝色分量。在顶点阶段,我们之前对 out.color 字段进行了硬编码,现在我们只需将输入的 inColor 分配给它即可。着色器代码的其余部分保持不变。

此示例旨在说明我们如何使用不同的位置索引传递多个属性,而不仅仅是顶点位置。这是着色器编程中的一个关键概念,允许更复杂和多样化的渲染效果。

struct VertexOutput {@builtin(position) clip_position: vec4<f32>,@location(0) color: vec3<f32>,
};@vertex
fn vs_main(@location(0) inPos: vec3<f32>,@location(1) inColor: vec3<f32>
) -> VertexOutput {var out: VertexOutput;out.clip_position = vec4<f32>(inPos, 1.0);out.color = inColor;return out;
}@fragment
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {return vec4<f32>(in.color, 1.0);
}

通过为不同的顶点分配不同的颜色,我们现在可以解决之前提出的问题:如何为位于三角形中间的那些片段生成片段颜色?此设置将使我们能够观察 GPU 的颜色插值操作,提供渲染管线的顶点阶段和片段阶段之间如何处理数据的可视化演示。

现在,让我们探索如何为新着色器设置管线。新管线与前一个管线非常相似,主要区别在于我们现在需要创建一个包含所有顶点颜色的颜色缓冲区并将其输入到管线中。

这里所涉及的步骤密切反映了我们处理位置缓冲区的方式。首先,我们创建一个颜色属性描述符。请注意,我们将 ShaderLocation 设置为 1,对应于着色器中 @location(1) 处的 inColor 属性。颜色属性的格式仍然是三个浮点数的向量。

const colorAttribDesc = {shaderLocation: 1, // @location(1)offset: 0,format: 'float32x3'
};const colorBufferLayoutDesc = {attributes: [colorAttribDesc],arrayStride: 4 * 3, // sizeof(float) * 3stepMode: 'vertex'
};……const colors = new Float32Array([1.0,0.0,0.0, // 🔴0.0,1.0,0.0, // 🟢0.0,0.0,1.0 // 🔵
]);let colorBuffer = createGPUBuffer(device, colors, GPUBufferUsage.VERTEX);

接下来,我们创建缓冲区布局描述符,它通知管线如何解释每个顶点的颜色缓冲区。我们将颜色属性描述符分配给属性字段。 arrayStride 设置为 4 * 3,因为一个浮点数占用 4 个字节,每种颜色有 3 个浮点数。 stepMode 设置为顶点,因为每个顶点都有一种颜色。

使用 Float32Array 在 CPU 内存中定义 RGB 数据后(第一个顶点为红色,第二个顶点为绿色,第三个顶点为蓝色),我们继续创建 GPU 缓冲区并将数据复制到 GPU。

让我们回顾一下创建和填充 GPU 缓冲区的过程:

  1. 定义一个缓冲区描述符,指定缓冲区大小并将使用标志设置为 VERTEX,因为我们将在顶点阶段使用颜色属性。
  2. mappedAtCreation 设置为true,允许在创建缓冲区时立即复制数据。
  3. 创建 GPU 缓冲区,并使用映射的缓冲区范围在 CPU 内存中创建镜像缓冲区。
  4. 将颜色数据复制到该映射缓冲区中。
  5. 最后,取消映射缓冲区,表明数据传输已完成。

在我们的示例代码中,你可能会注意到我们没有明确看到这些步骤。这是因为这个过程是一个常见过程,我们需要在整个 WebGPU 程序中多次执行。为了简化我们的代码并减少重复,我创建了一个实用函数来封装这些步骤。

如前所述,WebGPU 的语法可能相当冗长。将通用代码块包装到可重用实用函数中通常是一个好习惯。这种方法不仅减少了我们的工作量,而且使我们的代码更具可读性和可维护性。

我创建的 createGPUBuffer 函数将所有这些步骤封装到一个可重用的函数中。它的定义如下:

function createGPUBuffer(device, buffer, usage) {const bufferDesc = {size: buffer.byteLength,usage: usage,mappedAtCreation: true};//console.log('buffer size', buffer.byteLength);let gpuBuffer = device.createBuffer(bufferDesc);if (buffer instanceof Float32Array) {const writeArrayNormal = new Float32Array(gpuBuffer.getMappedRange());writeArrayNormal.set(buffer);}else if (buffer instanceof Uint16Array) {const writeArrayNormal = new Uint16Array(gpuBuffer.getMappedRange());writeArrayNormal.set(buffer);}else if (buffer instanceof Uint8Array) {const writeArrayNormal = new Uint8Array(gpuBuffer.getMappedRange());writeArrayNormal.set(buffer);}else if (buffer instanceof Uint32Array) {const writeArrayNormal = new Uint32Array(gpuBuffer.getMappedRange());writeArrayNormal.set(buffer);}else {const writeArrayNormal = new Float32Array(gpuBuffer.getMappedRange());writeArrayNormal.set(buffer);console.error("Unhandled buffer format ", typeof gpuBuffer);}gpuBuffer.unmap();return gpuBuffer;
}

此时,我们已成功复制 GPU 上的颜色值,准备在着色器中使用。

const pipelineDesc = {layout,vertex: {module: shaderModule,entryPoint: 'vs_main',buffers: [positionBufferLayoutDesc, colorBufferLayoutDesc]},fragment: {module: shaderModule,entryPoint: 'fs_main',targets: [colorState]},primitive: {topology: 'triangle-list',frontFace: 'cw',cullMode: 'back'}
};pipeline = device.createRenderPipeline(pipelineDesc);…………commandEncoder = device.createCommandEncoder();passEncoder = commandEncoder.beginRenderPass(renderPassDesc);
passEncoder.setViewport(0, 0, canvas.width, canvas.height, 0, 1);
passEncoder.setPipeline(pipeline);
passEncoder.setVertexBuffer(0, positionBuffer);
passEncoder.setVertexBuffer(1, colorBuffer);
passEncoder.draw(3, 1);
passEncoder.end();device.queue.submit([commandEncoder.finish()]);

创建缓冲区后,我们来定义管线描述符。与我们之前的示例的主要区别是在顶点阶段的缓冲区列表中添加了 colorBufferLayoutDescriptor。这可以通知管线我们现在使用两个顶点缓冲区:一个用于位置,另一个用于颜色。

在编码渲染命令时,我们现在需要设置两个顶点缓冲区。我们使用 setVertexBuffer(0,positionBuffer) 作为位置数据,使用 setVertexBuffer(1, colorBuffer) 作为颜色数据。索引 0 和 1 对应于定义管道描述符时的缓冲区布局。渲染过程的其余部分基本保持不变。

运行此代码后,我们会看到一个视觉上有趣的结果:一个彩色三角形。每个顶点都以其指定的颜色渲染 - 红色、绿色和蓝色。然而,最有趣的方面是这些顶点之间发生的情况,我们可以观察到三角形表面颜色的平滑过渡。

这种自动颜色混合是 GPU 执行的一项功能,我们将这个过程称为插值。值得注意的是,这种插值不仅限于颜色,我们在顶点阶段输出的任何值都将由 GPU 进行插值,以便为每个片段分配适当的值,特别是对于那些不直接位于顶点的片段。

片段值的插值是根据其到顶点的相对距离,遵循双线性方案来计算的。这种机制非常有用,因为考虑到场景中的片段通常远多于顶点,单独为所有片段指定值是不切实际的,所以我们可以依靠 GPU 根据仅在每个顶点定义的值有效地生成这些值。

这种插值技术是计算机图形学中的基本概念,能够以最少的输入数据实现表面上的平滑过渡和渐变。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/444410.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

新电脑 Windows 系统初始配置

文章目录 前言1 前置配置2 安装软件2.1 通讯工具2.2 后端开发工具2.3 硬件开发工具2.4 前端开发工具2.4 其它工具 3 Windows 11 优化4 写在最后 前言 分区&#xff08;个人习惯&#xff09;&#xff1a;1TB SSD 分为 2 个分区&#xff0c;一个 256GB 分区为系统盘&#xff0c;剩…

计算机毕业设计 基于Python的豆果美食推荐系统的设计与实现 Python+Django+Vue 前后端分离 附源码 讲解 文档

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

嵌入式数据结构中线性表的具体实现

大家好,今天主要给大家分享一下,如何使用数据结构中的线性表以及具体的实现。 第一:线性表的定义和表示方法 线性表的定义 – 线性表就是零个或多个相同数据元素的有限序列。 • 线性表的表示方法 – 线性表记为: L=(a0,∙∙∙∙∙∙∙∙ai-1aiai+1 ∙∙∙∙∙∙an-1) •…

软考《信息系统运行管理员》- 4.3 信息系统软件运维的过程

4.3 信息系统软件运维的过程 文章目录 4.3 信息系统软件运维的过程日常运维日常运维的内容日常运行例行测试维护例行测试流程的关键点例行维护流程的关键点 定期测试维护 缺陷诊断与修复信息系统软件缺陷的概念信息系统软件缺陷的分类信息系统软件缺陷诊断与修复流程缺陷诊断与…

Python编程:创意爱心表白代码集

在寻找一种特别的方式来表达你的爱意吗&#xff1f;使用Python编程&#xff0c;你可以创造出独一无二的爱心图案&#xff0c;为你的表白增添一份特别的浪漫。这里为你精选了六种不同风格的爱心表白代码&#xff0c;让你的创意和情感通过代码展现出来。 话不多说&#xff0c;咱…

pyQT生成界面,更改后不清除自定义代码的方法

基本原理就是作个子类继承生成的界面&#xff0c;在子类里写代码 工程结构 dialog_ui.py 界面子类 from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtGui import QStandardItemModel, QStandardItem, QColor, QFont from PyQt5.QtCore import Qt import Ui_dialog i…

【英语】5. 考研英语语法体系

文章目录 前言句字的成分一、常规句型简单句&#xff08;5 种&#xff09;1. 定义&#xff1a;句子中只包含 *一套主谓结构* 的句子。&#xff08;一个句子只能有一个谓语动词&#xff09;2. 分类 并列句&#xff08;由关联词组成&#xff09;&#xff08;3 种&#xff09;基本…

Kubernetes系列之一快速部署一套K8s集群(kubeadm方式)

最近本人在重温云原生相关的技术&#xff0c;说到云原生&#xff0c;必然绕不开Kubernetes&#xff0c;今天想跟大家聊的就是大名顶顶的Kubernetes。相信很多朋友在学习和使用Kubernetes的过程遇到各式各样不同的问题。我将从一个初学者的角度来给大家讲解一下Kubernete从安装、…

嵌入式面试——FreeRTOS篇(八) Tickless低功耗

本篇为&#xff1a;FreeRTOS Tickless 低功耗模式篇 一、低功耗模式简介 1、低功耗介绍 答&#xff1a; 很多应用场合对于功耗的要求很严格&#xff0c;比如可穿戴低功耗产品、物联网低功耗产品等&#xff1b;一般MCU都有相应的低功耗模式&#xff0c;裸机开发时可以使用MCU的…

6-基于TMS320C6678、FPGA XC5VSX95T的6U CPCI 8路光纤信号处理卡

1、板卡概述   本板卡由我公司自主研发&#xff0c;基于CPCI架构&#xff0c;符合CPCI2.0标准&#xff0c;采用两片TI DSP TMS320C6678芯片和Xilinx公司V5系列FPGA XC5VSX95T-1FF1136芯片。包含PCI接口、GMII的以太网接口、Nor Flash接口、8路SFP光 纤&#xff0c;4路RS232。…

Maven 高级之分模块设计与继承、聚合

在软件开发中&#xff0c;随着项目规模的扩大&#xff0c;代码量和复杂度不断增加&#xff0c;传统的一体化开发模式逐渐暴露出诸多问题。为了解决这些问题&#xff0c;模块化开发应运而生&#xff0c;而 Maven 正是模块化开发的利器&#xff0c;它提供的继承和聚合机制为构建和…

小米 MIX FOLD工程固件 更换字库修复分区 资源预览与刷写说明

小米 MIX FOLD机型代号 :cetus 该手机搭载骁龙888旗舰处理器 。对于一些因为字库问题损坏导致的故障,更换字库后要先刷写对应的工程底层修复固件。绑定cpu后在写入miui量产固件。 通过博文了解 1💝💝💝-----此机型工程固件的资源刷写注意事项 2💝💝💝-----此…

hadoop入门

1.1 hadoop是什么 Hadoop是一个由Apache基金会所开发的分布式系统基础架构&#xff0c;主要是解决海量数据的存储和海量数据的分析计算的问题。通常Hadoop指的是一个更为广泛的概念Hadoop生态圈 1.2 hadoop发展历程 Hadoop创始人Doug Cutting&#xff0c;为了实现与Google类…

手把手CNVD漏洞挖掘 + 资产收集

&#x1f497;想加SRC漏洞挖掘内部圈子&#xff0c;请联系我&#xff01; &#x1f497;技术文章交流&#xff0c;请联系我&#xff01; &#x1f497;需要职业技能大赛环境WP&#xff0c;请联系我&#xff01;&#x1f36c; 博主介绍 &#x1f468;‍&#x1f393; 博主介绍&a…

C++设计模式——代理模式

欢迎来到 破晓的历程的 博客 ⛺️不负时光&#xff0c;不负己✈️ 文章目录 引言代理模式的定义代理模式的具体实现 引言 我们经常听到代理服务器「代理服务器是一个中间服务器&#xff0c;能够接收客户端的请求&#xff0c;并代表客户端向服务器发起请求&#xff0c;然后将服…

【开源免费】基于SpringBoot+Vue.JS美发门店管理系统(JAVA毕业设计)

本文项目编号 T 069 &#xff0c;文末自助获取源码 \color{red}{T069&#xff0c;文末自助获取源码} T069&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 美…

被AI坑的一天—CentOS7导入阿里云YUM源报错的 GPG密钥提示404

过于相信人工智能 配置YUM源根据AI的说法换阿里云的YUM源验证AI配置结果解决问题 配置YUM源 由于电脑受限制 , 不能访问境外网站,所以用不了centos自带的源 ,是报404的 根据AI的说法换阿里云的YUM源 编辑 /etc/yum.repos.d/CentOS-Base.repo ,更换为 配置完成后sudo yum …

【多线程】多线程(11):ABA问题,JUC的常见类

【ABA问题】 线程改变了一个数值&#xff0c;但又修改回去了&#xff0c;看上去跟没变一样&#xff0c;但实际上已经有改过了的痕迹&#xff0c;可能引发一些bug CAS中存在ABA问题&#xff0c;但大部分情况下它不会带来bug 【JUC的常见类】 JUC指的是java.util.concurrent这…

【华为HCIP实战课程十】OSPF网络DR和BDR实战讲解,网络工程师

一、DR与BDR的基础介绍 点到点同步LSA成本小 多点接入网络同步LSA成本大,需要DR/BDR 由于MA网络中,任意两台路由器都需要传递路由信息,网络中有n台路由器,则需要建立n*(n-1)/2个邻接关系。任何一台路由器的路由变化都会导致多次传递,浪费了带宽资源,DR和BDR应运而生!…

数据结构_day1

目录 大纲 1.数据结构基础知识 1.1 什么是数据结构 1.2 数据 1.3 逻辑结构 1.4 存储结构 1.4.1 顺序存储 1.4.2 链式存储 1.4.3 索引存储结构 1.4.4 散列存储 1.5 操作 2.算法基础知识 2.1 什么是算法 2.2 算法的设计 2.3 算法的特性 2.4 评价算法的好坏 大纲 数据结构、算法(理…