WebGPU学习(九):学习“fractalCube”示例

简介: WebGPU学习(九):学习“fractalCube”示例

大家好,本文学习Chrome->webgpu-samplers->fractalCube示例。

上一篇博文:

WebGPU学习(八):学习“texturedCube”示例

学习fractalCube.ts

最终渲染结果:

该示例展示了如何用上一帧渲染的结果作为下一帧的纹理。

“texturedCube”示例相比,该示例的纹理并不是来自图片,而是来自上一帧渲染的结果

下面,我们打开fractalCube.ts文件,分析相关代码:

传输顶点的color

它与“texturedCube”示例->“传递顶点的uv数据”类似,这里不再分析

上一帧渲染的结果作为下一帧的纹理

  • 配置swapChain

因为swapChain保存了上一帧渲染的结果,所以将其作为下一帧纹理的source,它的usage需要增加GPUTextureUsage.COPY_SRC:

  const swapChain = context.configureSwapChain({
    device,
    format: "bgra8unorm",
    usage: GPUTextureUsage.OUTPUT_ATTACHMENT | GPUTextureUsage.COPY_SRC,
  });
  • 创建空纹理和sampler,设置到uniform bind group中

代码如下:

  const cubeTexture = device.createTexture({
    size: { width: canvas.width, height: canvas.height, depth: 1 },
    format: "bgra8unorm",
    usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.SAMPLED,
  });
 
  const sampler = device.createSampler({
    magFilter: "linear",
    minFilter: "linear",
  });
 
  const uniformBindGroup = device.createBindGroup({
    layout: bindGroupLayout,
    bindings: [
    ...
    {
      binding: 1,
      resource: sampler,
    }, {
      binding: 2,
      resource: cubeTexture.createView(),
    }],
  });
  • 绘制和拷贝

在每一帧中:

绘制带纹理的立方体;

将渲染结果拷贝到纹理中。

相关代码如下:

  return function frame() {
    const swapChainTexture = swapChain.getCurrentTexture();
                   
    renderPassDescriptor.colorAttachments[0].attachment = swapChainTexture.createView();
    
    const commandEncoder = device.createCommandEncoder({});
    const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
    ...
    passEncoder.setBindGroup(0, uniformBindGroup); 
    ...
    passEncoder.draw(36, 1, 0, 0);
    passEncoder.endPass();
 
    commandEncoder.copyTextureToTexture({
      texture: swapChainTexture,
    }, {
      texture: cubeTexture,
    }, {
      width: canvas.width,
      height: canvas.height,
      depth: 1,
    });
    
    device.defaultQueue.submit([commandEncoder.finish()]); 
   
    ...
 
  }

分析shader代码

vertex shader与“texturedCube”示例相比,增加了color attribute:

  const vertexShaderGLSL = `#version 450
  ...
  layout(location = 1) in vec4 color;
  ...
  layout(location = 0) out vec4 fragColor;
  ...
  void main() {
    ...
    fragColor = color;
    ...
  }`;

fragment shader的代码如下:

  const fragmentShaderGLSL = `#version 450
  layout(set = 0, binding = 1) uniform sampler mySampler;
  layout(set = 0, binding = 2) uniform texture2D myTexture;
  layout(location = 0) in vec4 fragColor;
  layout(location = 1) in vec2 fragUV;
  layout(location = 0) out vec4 outColor;
  void main() {
    vec4 texColor = texture(sampler2D(myTexture, mySampler), fragUV * 0.8 + 0.1);
    // 1.0 if we're sampling the background
    float f = float(length(texColor.rgb - vec3(0.5, 0.5, 0.5)) < 0.01);
    outColor = mix(texColor, fragColor, f);
  }`;

第10行对fragUV进行了处理,我们会在分析渲染时间线中分析它。

第13行和第15行相当于做了if判断:

if(纹理颜色 === 背景色){
    outColor = fragColor
}
else{
    outColor = 纹理颜色
}

这里之所以不用if判断而使用计算的方式,是为了减少条件判断,提高gpu的并行性

分析渲染时间线

下面分析下渲染的时间线:

第一帧

因为纹理为空纹理,它的颜色为背景色,所以fragment shader的outColor始终为fragColor,因此立方体的所有片段的颜色均为fragColor。

第一帧的渲染结果如下:

第一帧绘制结束后,渲染结果会被拷贝到纹理中。

第二帧

分析执行的fragment shader代码:

  const fragmentShaderGLSL = `#version 450
  layout(set = 0, binding = 1) uniform sampler mySampler;
  layout(set = 0, binding = 2) uniform texture2D myTexture;
  layout(location = 0) in vec4 fragColor;
  layout(location = 1) in vec2 fragUV;
  layout(location = 0) out vec4 outColor;
  void main() {
    vec4 texColor = texture(sampler2D(myTexture, mySampler), fragUV * 0.8 + 0.1);
    // 1.0 if we're sampling the background
    float f = float(length(texColor.rgb - vec3(0.5, 0.5, 0.5)) < 0.01);
    outColor = mix(texColor, fragColor, f);
  }`;
  • 第10行的“fragUV * 0.8 + 0.1”是为了取纹理坐标u、v方向的[0.1-0.9]部分,从而使纹理中立方体所占比例更大。

得到的纹理区域如下图的红色区域所示:

  • 第13行和第15行代码,将纹理中的背景色替换为了fragColor,使纹理中立方体区域的颜色保持不变

第二帧的渲染结果如下:

  • 第三帧

依次类推,第三帧的渲染结果如下:

参考资料

WebGPU规范

webgpu-samplers Github Repo

WebGPU-7

相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
相关文章
|
5月前
|
存储 并行计算 前端开发
【C++ 函数 基础教程 第五篇】C++深度解析:函数包裹与异步计算的艺术(二)
【C++ 函数 基础教程 第五篇】C++深度解析:函数包裹与异步计算的艺术
67 1
|
5月前
|
数据安全/隐私保护 C++ 容器
【C++ 函数 基础教程 第五篇】C++深度解析:函数包裹与异步计算的艺术(一)
【C++ 函数 基础教程 第五篇】C++深度解析:函数包裹与异步计算的艺术
90 0
|
2月前
|
数据采集 存储 JavaScript
构建你的第一个Python爬虫:从理论到实践
【8月更文挑战第27天】本文旨在为初学者提供一个关于如何构建简单Python网络爬虫的指南。我们将从网络爬虫的基础概念讲起,然后通过一个实际的项目案例来展示如何抓取网页数据,并将其存储在本地文件中。文章将介绍必要的工具和库,并逐步引导读者完成一个简单的爬虫项目,以加深对网络数据抓取过程的理解。
|
2月前
|
机器学习/深度学习 人工智能 自然语言处理
【人工智能】TensorFlow简介,应用场景,使用方法以及项目实践及案例分析,附带源代码
TensorFlow是由Google Brain团队开发的开源机器学习库,广泛用于各种复杂的数学计算,特别是涉及深度学习的计算。它提供了丰富的工具和资源,用于构建和训练机器学习模型。TensorFlow的核心是计算图(Computation Graph),这是一种用于表示计算流程的图结构,由节点(代表操作)和边(代表数据流)组成。
45 0
|
4月前
|
Web App开发 前端开发 JavaScript
WebGPU学习(八):学习“texturedCube”示例
WebGPU学习(八):学习“texturedCube”示例
|
5月前
|
JSON 人工智能 数据库
【AI大模型应用开发】【LangChain系列】1. 全面学习LangChain输入输出I/O模块:理论介绍+实战示例+细节注释
【AI大模型应用开发】【LangChain系列】1. 全面学习LangChain输入输出I/O模块:理论介绍+实战示例+细节注释
173 0
【AI大模型应用开发】【LangChain系列】1. 全面学习LangChain输入输出I/O模块:理论介绍+实战示例+细节注释
Threejs入门进阶实战案例(6):对象的通用属性/函数
Threejs入门进阶实战案例(6):对象的通用属性/函数
46 0
|
5月前
|
机器学习/深度学习 监控 算法
OpenAI Gym 高级教程——深度强化学习库的高级用法
OpenAI Gym 高级教程——深度强化学习库的高级用法
344 0
|
机器学习/深度学习 自然语言处理 算法
【机器学习实战】10分钟学会Python怎么用EM期望最大化进行参数估计(十五)
【机器学习实战】10分钟学会Python怎么用EM期望最大化进行参数估计(十五)
199 0
|
人工智能 JavaScript 前端开发
(建议收藏深读)GPT 高阶玩法 - 万字 GPT 模型自动化应用指南( javaScript 示例)(下)
(建议收藏深读)GPT 高阶玩法 - 万字 GPT 模型自动化应用指南( javaScript 示例)(下)
743 0
下一篇
无影云桌面