轻量封装WebGPU渲染系统示例<20>- 美化一下元胞自动机(源码)

本文主要是介绍轻量封装WebGPU渲染系统示例<20>- 美化一下元胞自动机(源码),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

当前示例源码github地址:

https://github.com/vilyLei/voxwebgpu/blob/feature/rendering/src/voxgpu/sample/GameOfLifePretty.ts

系统特性:

1. 用户态与系统态隔离。

2. 高频调用与低频调用隔离。

3. 面向用户的易用性封装。

4. 渲染数据(内外部相关资源)和渲染机制分离。

5. 用户操作和渲染系统调度并行机制。

6. 数据/语义驱动。

7. 异步并行的场景/模型载入。

8. computing与rendering用法机制一致性。

        1). 构造过程一致性。

        2). 启用过程一致性。

        3). 自动兼容到material多pass以及material graph机制中。

当前示例运行效果:

WGSL顶点与片段shader:

struct VertexInput {@location(0) pos: vec3f,@location(1) uv : vec2f,@builtin(instance_index) instance: u32
};struct VertexOutput {@builtin(position) pos: vec4f,@location(0) cell: vec2f,@location(1) uv: vec2f,@location(2) instance: f32,
};
@group(0) @binding(0) var<uniform> grid: vec2f;
@group(0) @binding(1) var<storage> cellState: array<u32>;
@group(0) @binding(2) var<storage> lifeState: array<f32>;
@vertex
fn vertMain(input: VertexInput) -> VertexOutput {let i = f32(input.instance);let cell = vec2f(i % grid.x, floor(i / grid.x));let cellOffset = cell / grid * 2.0;var state = f32(cellState[input.instance]);let gridPos = (input.pos.xy * state + 1.0) / grid - 1.0 + cellOffset;var output: VertexOutput;output.pos = vec4f(gridPos, 0.0, 1.0);output.cell = cell;output.uv = input.uv;output.instance = i;return output;
}@fragment
fn fragMain(input: VertexOutput) -> @location(0) vec4f {let c = input.cell / grid;var dis = length(input.uv - vec2<f32>(0.5, 0.5));dis = min(dis/0.15, 1.0);let i = u32(input.instance);var f = clamp((lifeState[i])/100.0, 0.0005, 1.0);dis = (1.0 - pow(dis, 100.0)) * (1.0 - f) + f;var c3 = vec3f(c, (1.0 - c.x) * (1.0 - f) + f) * dis;return vec4f(c3, 1.0);
}

此示例基于此渲染系统实现,当前示例TypeScript源码如下:

export class GameOfLifePretty {private mRscene = new RendererScene();initialize(): void {console.log("GameOfLifePretty::initialize() ...");const rc = this.mRscene;rc.initialize();this.initScene();}private createUniformValues(): { ufvs0: WGRUniformValue[]; ufvs1: WGRUniformValue[] }[] {const gridsSizesArray = new Float32Array([gridSize, gridSize]);const cellStateArray0 = new Uint32Array(gridSize * gridSize);for (let i = 0; i < cellStateArray0.length; i++) {cellStateArray0[i] = Math.random() > 0.6 ? 1 : 0;}const cellStateArray1 = new Uint32Array(gridSize * gridSize);for (let i = 0; i < cellStateArray1.length; i++) {cellStateArray1[i] = i % 2;}const lifeStateArray3 = new Float32Array(gridSize * gridSize);for (let i = 0; i < lifeStateArray3.length; i++) {lifeStateArray3[i] = i % 2;}let shared = true;let sharedData0 = { data: cellStateArray0 };let sharedData1 = { data: cellStateArray1 };let sharedData3 = { data: lifeStateArray3 };const v0 = new WGRUniformValue({ data: gridsSizesArray, stride: 2, shared });v0.toVisibleAll();// build rendering uniformsconst va1 = new WGRStorageValue({ sharedData: sharedData0, stride: 1, shared }).toVisibleVertComp();const vb1 = new WGRStorageValue({ sharedData: sharedData1, stride: 1, shared }).toVisibleVertComp();const vc1 = new WGRStorageValue({ sharedData: sharedData3, stride: 1, shared }).toVisibleAll();// build computing uniformsconst compva1 = new WGRStorageValue({ sharedData: sharedData0, stride: 1, shared }).toVisibleVertComp();const compva2 = new WGRStorageValue({ sharedData: sharedData1, stride: 1, shared }).toVisibleComp();compva2.toBufferForStorage();const compvb1 = new WGRStorageValue({ sharedData: sharedData1, stride: 1, shared }).toVisibleVertComp();const compvb2 = new WGRStorageValue({ sharedData: sharedData0, stride: 1, shared }).toVisibleComp();compvb2.toBufferForStorage();const compv3 = new WGRStorageValue({ sharedData: sharedData3, stride: 1, shared }).toVisibleComp();compv3.toBufferForStorage();return [{ ufvs0: [v0, va1, vc1], ufvs1: [v0, vb1, vc1] },{ ufvs0: [v0, compva1, compva2, compv3], ufvs1: [v0, compvb1, compvb2, compv3] }];}private mEntity: FixScreenPlaneEntity;private mStep = 0;private createMaterial(shaderCodeSrc: WGRShderSrcType, uniformValues: WGRUniformValue[], shadinguuid: string, instanceCount: number): WGMaterial {return new WGMaterial({shadinguuid,shaderCodeSrc,instanceCount,uniformValues});}private createCompMaterial(shaderCodeSrc: WGRShderSrcType, uniformValues: WGRUniformValue[], shadinguuid: string, workgroupCount = 2): WGCompMaterial {return new WGCompMaterial({shadinguuid,shaderCodeSrc,uniformValues}).setWorkcounts(workgroupCount, workgroupCount);}private initScene(): void {const rc = this.mRscene;const ufvsObjs = this.createUniformValues();const instanceCount = gridSize * gridSize;const workgroupCount = Math.ceil(gridSize / shdWorkGroupSize);let shaderSrc = {shaderSrc: {code: shaderWGSL,uuid: "shader-gameOfLife",vertEntryPoint: "vertMain",fragEntryPoint: "fragMain"}} as WGRShderSrcType;let compShaderSrc = {compShaderSrc: {code: compShdCode,uuid: "shader-computing",compEntryPoint: "compMain"}};const materials: WGMaterial[] = [// build ping-pong rendering processthis.createMaterial(shaderSrc, ufvsObjs[0].ufvs0, "rshd0", instanceCount),this.createMaterial(shaderSrc, ufvsObjs[0].ufvs1, "rshd1", instanceCount),// build ping-pong computing processthis.createCompMaterial(compShaderSrc, ufvsObjs[1].ufvs1, "compshd0", workgroupCount),this.createCompMaterial(compShaderSrc, ufvsObjs[1].ufvs0, "compshd1", workgroupCount),];let entity = new FixScreenPlaneEntity({x: -0.8, y: -0.8, width: 1.6, height: 1.6,materials});rc.addEntity(entity);materials[0].visible = false;materials[2].visible = false;this.mEntity = entity;}private mFrameDelay = 3;run(): void {let rendering = this.mEntity.isRendering();if (rendering) {if (this.mFrameDelay > 0) {this.mFrameDelay--;return;}this.mFrameDelay = 3;const ms = this.mEntity.materials;for (let i = 0; i < ms.length; i++) {ms[i].visible = (this.mStep % 2 + i) % 2 == 0;}this.mStep++;}this.mRscene.run(rendering);}
}

这篇关于轻量封装WebGPU渲染系统示例<20>- 美化一下元胞自动机(源码)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/360207

相关文章

JAVA系统中Spring Boot应用程序的配置文件application.yml使用详解

《JAVA系统中SpringBoot应用程序的配置文件application.yml使用详解》:本文主要介绍JAVA系统中SpringBoot应用程序的配置文件application.yml的... 目录文件路径文件内容解释1. Server 配置2. Spring 配置3. Logging 配置4. Ma

2.1/5.1和7.1声道系统有什么区别? 音频声道的专业知识科普

《2.1/5.1和7.1声道系统有什么区别?音频声道的专业知识科普》当设置环绕声系统时,会遇到2.1、5.1、7.1、7.1.2、9.1等数字,当一遍又一遍地看到它们时,可能想知道它们是什... 想要把智能电视自带的音响升级成专业级的家庭影院系统吗?那么你将面临一个重要的选择——使用 2.1、5.1 还是

python实现pdf转word和excel的示例代码

《python实现pdf转word和excel的示例代码》本文主要介绍了python实现pdf转word和excel的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价... 目录一、引言二、python编程1,PDF转Word2,PDF转Excel三、前端页面效果展示总结一

在MyBatis的XML映射文件中<trim>元素所有场景下的完整使用示例代码

《在MyBatis的XML映射文件中<trim>元素所有场景下的完整使用示例代码》在MyBatis的XML映射文件中,trim元素用于动态添加SQL语句的一部分,处理前缀、后缀及多余的逗号或连接符,示... 在MyBATis的XML映射文件中,<trim>元素用于动态地添加SQL语句的一部分,例如SET或W

高效管理你的Linux系统: Debian操作系统常用命令指南

《高效管理你的Linux系统:Debian操作系统常用命令指南》在Debian操作系统中,了解和掌握常用命令对于提高工作效率和系统管理至关重要,本文将详细介绍Debian的常用命令,帮助读者更好地使... Debian是一个流行的linux发行版,它以其稳定性、强大的软件包管理和丰富的社区资源而闻名。在使用

Redis延迟队列的实现示例

《Redis延迟队列的实现示例》Redis延迟队列是一种使用Redis实现的消息队列,本文主要介绍了Redis延迟队列的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习... 目录一、什么是 Redis 延迟队列二、实现原理三、Java 代码示例四、注意事项五、使用 Redi

Ubuntu系统怎么安装Warp? 新一代AI 终端神器安装使用方法

《Ubuntu系统怎么安装Warp?新一代AI终端神器安装使用方法》Warp是一款使用Rust开发的现代化AI终端工具,该怎么再Ubuntu系统中安装使用呢?下面我们就来看看详细教程... Warp Terminal 是一款使用 Rust 开发的现代化「AI 终端」工具。最初它只支持 MACOS,但在 20

windows系统下shutdown重启关机命令超详细教程

《windows系统下shutdown重启关机命令超详细教程》shutdown命令是一个强大的工具,允许你通过命令行快速完成关机、重启或注销操作,本文将为你详细解析shutdown命令的使用方法,并提... 目录一、shutdown 命令简介二、shutdown 命令的基本用法三、远程关机与重启四、实际应用

Debian如何查看系统版本? 7种轻松查看Debian版本信息的实用方法

《Debian如何查看系统版本?7种轻松查看Debian版本信息的实用方法》Debian是一个广泛使用的Linux发行版,用户有时需要查看其版本信息以进行系统管理、故障排除或兼容性检查,在Debia... 作为最受欢迎的 linux 发行版之一,Debian 的版本信息在日常使用和系统维护中起着至关重要的作

在Pandas中进行数据重命名的方法示例

《在Pandas中进行数据重命名的方法示例》Pandas作为Python中最流行的数据处理库,提供了强大的数据操作功能,其中数据重命名是常见且基础的操作之一,本文将通过简洁明了的讲解和丰富的代码示例,... 目录一、引言二、Pandas rename方法简介三、列名重命名3.1 使用字典进行列名重命名3.编