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

上一篇博文:

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

下一篇博文:

WebGPU学习(十):介绍“GPU实现粒子效果”

学习fractalCube.ts

最终渲染结果:

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

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

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

传输顶点的color

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

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

  • 配置swapChain

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

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

相关代码如下:


  1. const fragmentShaderGLSL = `#version 450
  2. ...
  3. layout(set = 0, binding = 2) uniform texture2D myTexture;
  4. ...
  5. void main() {
  6. vec4 texColor = texture(sampler2D(myTexture, mySampler), fragUV * 0.8 + 0.1);
  7. ...
  8. outColor = mix(texColor, fragColor, f);
  9. }`;
  10. ...
  11. const cubeTexture = device.createTexture({
  12. size: { width: canvas.width, height: canvas.height, depth: 1 },
  13. format: "bgra8unorm",
  14. usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.SAMPLED,
  15. });
  16. const sampler = device.createSampler({
  17. magFilter: "linear",
  18. minFilter: "linear",
  19. });
  20. const uniformBindGroup = device.createBindGroup({
  21. layout: bindGroupLayout,
  22. bindings: [
  23. ...
  24. {
  25. binding: 1,
  26. resource: sampler,
  27. }, {
  28. binding: 2,
  29. //传递cubeTexture到fragment shader中
  30. resource: cubeTexture.createView(),
  31. }],
  32. });
  • 绘制和拷贝

在每一帧中:

绘制带纹理的立方体;

将渲染结果(swapChainTexture)拷贝到cubeTexture中。

相关代码如下:

  1. return function frame() {
  2. const swapChainTexture = swapChain.getCurrentTexture();
  3. renderPassDescriptor.colorAttachments[0].attachment = swapChainTexture.createView();
  4. const commandEncoder = device.createCommandEncoder({});
  5. const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
  6. ...
  7. passEncoder.setBindGroup(0, uniformBindGroup);
  8. ...
  9. passEncoder.draw(36, 1, 0, 0);
  10. passEncoder.endPass();
  11. commandEncoder.copyTextureToTexture({
  12. texture: swapChainTexture,
  13. }, {
  14. texture: cubeTexture,
  15. }, {
  16. width: canvas.width,
  17. height: canvas.height,
  18. depth: 1,
  19. });
  20. device.defaultQueue.submit([commandEncoder.finish()]);
  21. ...
  22. }

分析shader代码

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

  1. const vertexShaderGLSL = `#version 450
  2. ...
  3. layout(location = 1) in vec4 color;
  4. ...
  5. layout(location = 0) out vec4 fragColor;
  6. ...
  7. void main() {
  8. ...
  9. fragColor = color;
  10. ...
  11. }`;

fragment shader的代码如下:

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

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

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

  1. if(纹理颜色 === 背景色){
  2. outColor = fragColor
  3. }
  4. else{
  5. outColor = 纹理颜色
  6. }

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

分析渲染时间线

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

第一帧

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

第一帧的渲染结果如下:

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

第二帧

分析执行的fragment shader代码:

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

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

  • 第13行和第15行代码,将纹理中的背景色替换为了fragColor

第二帧的渲染结果如下:

  • 第三帧

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

参考资料

WebGPU规范

webgpu-samplers Github Repo

WebGPU-7

WebGPU学习(九):学习“fractalCube”示例的更多相关文章

  1. WebGPU学习(七):学习“twoCubes”和“instancedCube”示例

    大家好,本文学习Chrome->webgpu-samplers->twoCubes和instancedCube示例. 这两个示例都与"rotatingCube"示例差不 ...

  2. Angular 快速学习笔记(1) -- 官方示例要点

    创建组件 ng generate component heroes {{ hero.name }} {{}}语法绑定数据 管道pipe 格式化数据 <h2>{{ hero.name | u ...

  3. SQL 数据库 学习 007 通过一个示例简单介绍什么是字段、属性、列、元组、记录、表、主键、外键 (上)

    SQL 数据库 学习 007 通过一个示例简单介绍什么是字段.属性.列.元组.记录.表.主键.外键 (上) 我们来介绍一下:数据库是如何存储数据的. 数据库是如何存储数据的 来看一个小例子 scott ...

  4. Deep Learning(深度学习)学习笔记整理系列之(五)

    Deep Learning(深度学习)学习笔记整理系列 zouxy09@qq.com http://blog.csdn.net/zouxy09 作者:Zouxy version 1.0 2013-04 ...

  5. Deep Learning(深度学习)学习笔记整理系列之(八)

    Deep Learning(深度学习)学习笔记整理系列 zouxy09@qq.com http://blog.csdn.net/zouxy09 作者:Zouxy version 1.0 2013-04 ...

  6. Deep Learning(深度学习)学习笔记整理系列之(七)

    Deep Learning(深度学习)学习笔记整理系列 zouxy09@qq.com http://blog.csdn.net/zouxy09 作者:Zouxy version 1.0 2013-04 ...

  7. Deep Learning(深度学习)学习笔记整理系列之(六)

    Deep Learning(深度学习)学习笔记整理系列 zouxy09@qq.com http://blog.csdn.net/zouxy09 作者:Zouxy version 1.0 2013-04 ...

  8. Deep Learning(深度学习)学习笔记整理系列之(四)

    Deep Learning(深度学习)学习笔记整理系列 zouxy09@qq.com http://blog.csdn.net/zouxy09 作者:Zouxy version 1.0 2013-04 ...

  9. Deep Learning(深度学习)学习笔记整理系列之(三)

    Deep Learning(深度学习)学习笔记整理系列 zouxy09@qq.com http://blog.csdn.net/zouxy09 作者:Zouxy version 1.0 2013-04 ...

  10. Deep Learning(深度学习)学习笔记整理系列之(二)

    Deep Learning(深度学习)学习笔记整理系列 zouxy09@qq.com http://blog.csdn.net/zouxy09 作者:Zouxy version 1.0 2013-04 ...

随机推荐

  1. 120、TensorFlow创建计算图(二)

    #创建一个计算流图 #大多数tensorflow程序开始于dataflow graph 的构造函数 #在这个命令中你执行了tensorflow api的函数 #创建了新的操作tf.Operation ...

  2. VS2015 编写C++的DLL,并防止DLL导出的函数名出现乱码(以串口通信为例,实现串口通信)

    参考链接:https://blog.csdn.net/songyi160/article/details/50754705 1.新建项目 建立好的项目界面如下: 接着在解决方案中找到[头文件]然后右击 ...

  3. 使用Xftp连接Centos 6.6服务器详细图文教程

    这篇文章主要介绍了使用Xftp连接Centos 6.6服务器详细图文教程,本文用详细的图文说明讲解了连接服务器和操作服务器的步骤,适合新手,需要的朋友可以参考下 一,打开Xftp软件(下载地址:Xma ...

  4. django简单实现注册登录模块

    源码下载:https://files.cnblogs.com/files/hardykay/login.zip 新建项目(我使用pycharm开发,也可以使用如下命令建立项目 ) cmd命令行,前提需 ...

  5. java反射(三)--反射与操作类

    一.反射与操作类 在反射机制的处理过程之中不仅仅只是一个实例化对象的处理操作,更多的情况下还有类的组成的操作,任何一个类的基本组成结构:父类(父接口),包,属性,方法(构造方法,普通方法)--获取类的 ...

  6. 《穷爸爸富爸爸——Cashflow》

    读<穷爸爸富爸爸>大约两年前了,当时对理财没什么概念,除了支付宝,就是京东小金库,哪个利率高就存哪个里.记忆中除了感觉这应该是有一定经济基础的人通常做的事,工薪阶级的自己还未达标,工资除了 ...

  7. 使用vue配合组件--转载

    1.由饿了么 UED (知乎专栏)设计的桌面端组件库已经开源,文档:Element,仓库: GitHub - ElemeFE/element: Desktop UI elements for Vue. ...

  8. springboot 项目启动脚本

    springboot项目启动可通过下面的shell脚本启动. startup.sh app=order-service-rest.jar appout=logs/${app/.jar/.out} ap ...

  9. Aspnetcore下面服务器热更新与配置热加载

    原文:Aspnetcore下面服务器热更新与配置热加载 Asp.net的热更新方案Appdomain在aspnetcore中不被支持了 新的方案如下: 配置文件更新选项 reloadOnChange ...

  10. 八、hibernate的查询(HQL)

    HQL:Hibernate Query Language 提供更加丰富灵活.更为强大的查询能力 HQL更接近SQL语句查询语法 面向对象的查询 "from Children where ci ...