WebAssembly与WebGPU:游戏开发的新时代
文章目录
- WebAssembly简介
- WebGPU简介
- Wasm + WebGPU 在游戏开发中的优势
- 创建一个简单的WebAssembly模块
- 使用WebGPU绘制一个三角形
- WebAssembly 的高级特性
- 内存管理
- 异步加载与多线程
- WebGPU 的高级特性
- 着色器编程
- 计算着色器
- 实战案例:创建一个简单的 2D 游戏
- 游戏逻辑设计
- 结合 WebAssembly
WebAssembly简介
- 定义: WebAssembly是一种二进制指令格式,旨在为高性能应用程序提供一种可移植的目标平台。
- 特点:
- 小而快加载
- 运行速度快
- 支持多种编程语言编译
- 用途: 主要用于加速网页应用性能,特别是在计算密集型任务上。
WebGPU简介
- 定义: WebGPU API 是一个用于访问现代图形和计算硬件的新 JavaScript API。
- 特点:
- 基于现代图形API (如DirectX 12, Metal)
- 提供低级别访问GPU的能力
- 支持并行计算
- 用途: 适用于复杂3D渲染、物理模拟等高性能需求场景。
Wasm + WebGPU 在游戏开发中的优势
- 高性能: 利用Wasm的高效执行环境结合WebGPU对GPU的直接控制,可以实现接近原生应用的性能表现。
- 跨平台: 由于Wasm本身的设计就是跨平台的,加上WebGPU也支持多种硬件后端,使得游戏能够更容易地部署到不同设备上。
- 易维护与更新: 基于Web技术栈,开发者可以利用现有的工具链进行开发、调试及维护。
创建一个简单的WebAssembly模块
// 定义Wasm模块接口
const importObject = {env: {memoryBase: 0,tableBase: 0,memory: new WebAssembly.Memory({initial: 1}),table: new WebAssembly.Table({initial: 0, element: 'anyfunc'}),}
};// 加载Wasm模块
fetch('example.wasm').then(response => response.arrayBuffer()).then(bytes => WebAssembly.instantiate(bytes, importObject)).then(results => {const instance = results.instance;// 调用Wasm模块中的函数instance.exports.add(1, 2); // 假设该函数接收两个参数并返回它们的和});
使用WebGPU绘制一个三角形
// 获取WebGPU设备
navigator.gpu.requestAdapter().then(adapter => {return adapter.requestDevice();
}).then(device => {// 创建渲染管线const pipeline = device.createRenderPipeline({layout: device.createPipelineLayout({ bindGroupLayouts: [] }),vertexStage: {module: device.createShaderModule({code: `[[stage(vertex)]] fn main() -> [[builtin(position)]] vec4<f32> {var positions : array<vec2<f32>, 3> = array<vec2<f32>, 3>(vec2<f32>(-0.5, -0.5),vec2<f32>(0.5, -0.5),vec2<f32>(0.0, 0.5));var position = positions[0u]; // 简化起见,这里只取第一个顶点位置return vec4<f32>(position, 0.0, 1.0);}`,}),entryPoint: 'main',},primitiveTopology: 'triangle-list',colorStates: [{ format: 'bgra8unorm' }],});// 创建帧缓冲区const swapChain = device.createSwapChain(canvas, {usage: GPUTextureUsage.RENDER_ATTACHMENT,format: 'bgra8unorm',});// 渲染循环function render() {const context = device.getContext();const commandEncoder = device.createCommandEncoder();const textureView = swapChain.getCurrentTexture().createView();const renderPassDescriptor = {colorAttachments: [{attachment: textureView,loadValue: { r: 0.1, g: 0.2, b: 0.3, a: 1.0 },}],};const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);passEncoder.setPipeline(pipeline);passEncoder.draw(3, 1, 0, 0);passEncoder.endPass();device.queue.submit([commandEncoder.finish()]);requestAnimationFrame(render);}requestAnimationFrame(render);
});
WebAssembly 的高级特性
内存管理
- 内存布局:
WebAssembly
使用线性内存布局,可以通过memory
对象进行访问。 - 内存操作: 可以通过 get 和 set 方法读写内存。
- 内存增长: 可以动态增加内存大小。
const memory = new WebAssembly.Memory({ initial: 1, maximum: 10 });
console.log(memory.buffer.byteLength); // 输出 65536 (1 MB)// 扩展内存
memory.grow(1);
console.log(memory.buffer.byteLength); // 输出 131072 (2 MB)
异步加载与多线程
- 异步加载: 可以通过 fetch 或其他异步方法加载 Wasm 模块。
- 多线程: 使用 WebAssembly.Threading API 支持多线程操作。
// 异步加载 Wasm 模块
fetch('example.wasm').then(response => response.arrayBuffer()).then(bytes => WebAssembly.compileAsync(bytes)).then(module => {WebAssembly.instantiate(module, importObject).then(results => {const instance = results.instance;// 调用 Wasm 函数instance.exports.add(1, 2);});});// 多线程支持
if ('workerGlobalScope' in self) {self.importScripts('wasm_worker.js');const worker = new Worker('wasm_worker.js');worker.postMessage({ type: 'run', data: [1, 2] });
}
WebGPU 的高级特性
着色器编程
- 顶点着色器: 处理顶点数据。
- 片段着色器: 处理像素颜色。
[[block]]
struct VertexInput {@builtin(position) pos: vec4<f32>,
};[[block]]
struct VertexOutput {@builtin(position) pos: vec4<f32>,
};[[stage(vertex)]]
fn vs_main(@builtin(vertex_index) vertex_index: u32) -> VertexOutput {var input: VertexInput = VertexInput(pos: vec4<f32>(0.0, 0.0, 0.0, 1.0));var output: VertexOutput = VertexOutput(pos: input.pos);return output;
}[[stage(fragment)]]
fn fs_main() -> @location(0) vec4<f32> {return vec4<f32>(1.0, 0.0, 0.0, 1.0);
}
计算着色器
计算着色器: 执行并行计算任务。
[[block]]
struct ComputeData {result: array<i32, 1>,
};[[group(0), binding(0)]]
var<storage, read_write> data: array<i32, 1>;[[stage(compute), workgroup_size(1)]]
fn cs_main([[builtin(global_invocation_id)]] global_id: vec3<u32>) {data[0] = global_id.x * global_id.y * global_id.z;
}
实战案例:创建一个简单的 2D 游戏
游戏逻辑设计
- 状态管理: 使用对象或类来管理游戏状态。
- 事件处理: 监听键盘和鼠标事件。
class Game {constructor(canvas) {this.canvas = canvas;this.context = canvas.getContext('2d');this.width = canvas.width;this.height = canvas.height;this.player = { x: 100, y: 100 };this.enemies = [];this.init();}init() {this.enemies.push({ x: 200, y: 200 });this.enemies.push({ x: 300, y: 300 });window.addEventListener('keydown', event => {if (event.key === 'ArrowUp') {this.player.y -= 10;} else if (event.key === 'ArrowDown') {this.player.y += 10;} else if (event.key === 'ArrowLeft') {this.player.x -= 10;} else if (event.key === 'ArrowRight') {this.player.x += 10;}});this.animate();}animate() {requestAnimationFrame(() => this.animate());this.update();this.render();}update() {// 更新敌人位置for (let enemy of this.enemies) {enemy.x += Math.random() * 10 - 5;enemy.y += Math.random() * 10 - 5;}}render() {this.context.clearRect(0, 0, this.width, this.height);this.context.fillStyle = 'blue';this.context.fillRect(this.player.x, this.player.y, 20, 20);this.context.fillStyle = 'red';for (let enemy of this.enemies) {this.context.fillRect(enemy.x, enemy.y, 20, 20);}}
}const canvas = document.getElementById('gameCanvas');
const game = new Game(canvas);
结合 WebAssembly
- 加载 Wasm 模块: 在游戏初始化时加载 Wasm 模块。
- 调用 Wasm 函数: 在游戏更新和渲染过程中调用 Wasm 函数。
class Game {constructor(canvas) {this.canvas = canvas;this.context = canvas.getContext('2d');this.width = canvas.width;this.height = canvas.height;this.player = { x: 100, y: 100 };this.enemies = [];this.init();}async init() {const importObject = {env: {memoryBase: 0,tableBase: 0,memory: new WebAssembly.Memory({ initial: 1 }),table: new WebAssembly.Table({ initial: 0, element: 'anyfunc' }),}};const response = await fetch('game_wasm.wasm');const bytes = await response.arrayBuffer();const { instance } = await WebAssembly.instantiate(bytes, importObject);this.wasm = instance.exports;this.enemies.push({ x: 200, y: 200 });this.enemies.push({ x: 300, y: 300 });window.addEventListener('keydown', event => {if (event.key === 'ArrowUp') {this.player.y -= 10;} else if (event.key === 'ArrowDown') {this.player.y += 10;} else if (event.key === 'ArrowLeft') {this.player.x -= 10;} else if (event.key === 'ArrowRight') {this.player.x += 10;}});this.animate();}animate() {requestAnimationFrame(() => this.animate());this.update();this.render();}update() {// 更新敌人位置for (let enemy of this.enemies) {enemy.x += this.wasm.randomMove(10);enemy.y += this.wasm.randomMove(10);}}render() {this.context.clearRect(0, 0, this.width, this.height);this.context.fillStyle = 'blue';this.context.fillRect(this.player.x, this.player.y, 20, 20);this.context.fillStyle = 'red';for (let enemy of this.enemies) {this.context.fillRect(enemy.x, enemy.y, 20, 20);}}
}const canvas = document.getElementById('gameCanvas');
const game = new Game(canvas);
相关文章:
WebAssembly与WebGPU:游戏开发的新时代
文章目录 WebAssembly简介WebGPU简介Wasm WebGPU 在游戏开发中的优势创建一个简单的WebAssembly模块使用WebGPU绘制一个三角形WebAssembly 的高级特性内存管理异步加载与多线程 WebGPU 的高级特性着色器编程计算着色器 实战案例:创建一个简单的 2D 游戏游戏逻辑设计…...

SAP B1 认证考试习题 - 解析版(二)
前一篇:《SAP B1 认证考试习题 - 解析版(一)》 题目纯享版合集:《SAP B1 认证考试习题 - 纯享版》 三、采购流程 30. 下列哪个凭证在采购流程中是必须要完成的 A. 采购订单 B. 收货采购订单 C. 应付发票 D. 退货 E. 应付贷…...

《Ubuntu20.04环境下的ROS进阶学习7》
一、使用nav_msgs消息包显示小车轨迹 在我们跑实验的时候通常希望看到小车的轨迹,在ROS1中可以将小车的路径存储在nav_msgs::Path 这种消息类型里,发布出来后使用rviz来显示小车轨迹。 二、了解nav_msgs消息包 那么首先我们要来了解一下nav_msgs这个消息…...

免费视频无损压缩工具+预览视频生成工具
视频无损压缩工具 功能与作用 :视频无损压缩工具是一种能够减少视频文件大小,但同时保持视频质量的工具。它通过先进的编码技术和算法,有效降低视频文件的存储空间,同时保证视频的清晰度和观感。这对于需要分享或存储大量视频内容…...
OIDC9-OIDC集成登录功能(SpringBoot3.0)
1.项目依赖 <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <…...

使用Vue.extend( ) 模仿 elementui 创建一个类似 message 消息提示框
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、目录结构二、代码1. 创建 m-Toast.vue 文件2. 创建 global.js 文件3. 在 main.js 文件中导入 global.js 文件4. 在 App.vue 文件中使用 全局方法创建的 组件 前言 在此之前一直不明白Vue.extend( )干什么用的…...
ansible部署二进制mysql 8
1、配置文件 ll /ansible -rw-r--r-- 1 root root 836 Sep 22 12:09 my.cnf -rw-r--r-- 1 root root 810 Sep 22 07:21 mysql.service -rw-r--r-- 1 root root 2731 Sep 22 12:32 mysql.yam2、my.cnf内容 rootbole:/ansible# cat my.cnf [mysql] #设置m…...

【2023工业3D异常检测文献】基于混合融合的多模态工业异常检测方法Multi-3D-Memory (M3DM)
Multimodal Industrial Anomaly Detection via Hybrid Fusion 1、Background 随着3D传感器的发展,最近发布了具有2D图像和3D点云数据的MVTec-3D AD数据集,促进了多模态工业异常检测的研究。 无监督异常检测的核心思想是找出正常表示与异常之间的差异。…...

基于微信小程序的宿舍报修系统的设计与实现(lw+演示+源码+运行)
摘 要 互联网发展至今,无论是其理论还是技术都已经成熟,而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播,搭配信息管理工具可以很好地为人们提供服务。针对成果信息管理混乱,出错率高,信息安全性差&am…...

前端练习总结(1)
前端实习练习题 前端实习笔试题0920 visibility:hidden display:none把鼠标移到按钮并点击时 hover active focus的顺序代码输出结果1代码输出结果2CSS中哪些属性可以继承cookie sessionStorage localstorage区别面向对象基本特征有哪些,请具体说明下列关于v-model的说法,哪项…...

计算机网络自顶向下(1)---网络基础
目录 1.网络的分类 2.网络协议 3.网络分层结构 1.OSI七层模型 2.TCP/IP四层模型 3.网络与OS的关系 4.网络传输基本流程 1.协议报头 5.网络中的地址管理 1.IP地址 2.端口号 6.传输层协议 1.TCP协议 2.UDP协议 3.网络字节序 7.socket 1.网络的分类 局域网&…...

Pandas -----------------------基础知识(五)
索引和列操作函数缺失值 索引和列操作 # 1 加载数据 # 1.1 从链家租房数据集中获取天通苑租房区域的所有数据存储在df2中 # 1.2 从df2中获取价格列存储在df2_price对象 import pandas as pd df pd.read_csv(/root/pandas_code_ling/data/b_LJdata.csv) df2 df[df[区域] 天通苑…...

RabbitMQ 高级特性——重试机制
文章目录 前言重试机制配置文件设置生命交换机、队列和绑定关系生产者发送消息消费消息 前言 前面我们学习了 RabbitMQ 保证消息传递可靠性的机制——消息确认、持久化和发送发确认,那么对于消息确认和发送方确认,如果接收方没有收到消息,那…...
每天一道面试题(20):锁的发生原因和避免措施
死锁的发生原因和避免措施 一、概述 在多线程编程中,死锁是一个常见的问题。理解死锁的成因和避免策略是提升程序稳定性和性能的重要能力。 二、普通人 vs 高手的回答 普通人回答: “临场发挥…” 高手回答: “死锁是指两个或多个线程在执…...

2024淘宝双11活动,收下这份必买好物推荐清单
双11如何真正值得购买的好物呢?为了帮助大家把握住这次难得的购物良机,我们特别推出了这份“2024淘宝双11必买好物推荐清单”。这份清单涵盖数码电子、家居生活、个护健康等多个领域的优质产品。无论你是科技爱好者,还是注重生活品质的消费者…...

vue-cli,element-plus,axios,proxy
一、vue-cli vue-cli俗称vue脚手架,是vue官方提供的快速生成vue 工程化项目的工具。 1.官网:https://cn.vuejs.org/ 中文官网: https://cli.vuejs.org/zh/ 特点:基于webpack,功能丰富且易于扩展,支持创建vue2和vu…...

《Zeotero的学习》
学习视频链接 Zeotera的安装 官网点击download,选择合适的版本进行下载,并安装插件。 下载完成之后,点击安装包,一路默认就可以。如果不想下载在C盘,可以在步骤中选择自定义路径。 Zeotero的注册 官网进行注册&am…...
大数据复习知识点1
1、HDFS和MapReduce的起源:HDFS起源于Google的GFS论文,它是为了解决大规模数据集的存储问题而设计的。而MapReduce则是Google为了解决大规模数据处理问题而提出的一种并行计算模型。 2、YARN的作用:YARN是Hadoop的资源管理器,它负…...

9.26 Buu俩题解
[CISCN2019 华东北赛区]Web2 看wp写完之后写的 知识点 存储型XSS与过滤绕过sql注入 题解 好几个页面,存在登录框可以注册,存在管理员页面(admin.php) ->既然存在管理员页面,且直接访问admin.php提示我们 说明存在身份验证࿰…...

Mitsuba 渲染基础
Mitsuba 渲染基础 0. Abstract1. 安装 Mitsuba21.1 下载 Mitsuba2 源码1.2 选择后端 (variants)1.3 编译 2. [Mitsuba2PointCloudRenderer](https://github.com/tolgabirdal/Mitsuba2PointCloudRenderer)2.1 Mitsuba2 渲染 XML2.2 Scene 场景的 XML 文件格式2.2.1 chair.npy to…...

第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...

css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
基于matlab策略迭代和值迭代法的动态规划
经典的基于策略迭代和值迭代法的动态规划matlab代码,实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
Caliper 负载(Workload)详细解析
Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...
「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案
在移动互联网营销竞争白热化的当下,推客小程序系统凭借其裂变传播、精准营销等特性,成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径,助力开发者打造具有市场竞争力的营销工具。 一、系统核心功能架构&…...