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…...
如何让QtScrcpy投屏画质提升300%?3个隐藏参数解锁超清体验
如何让QtScrcpy投屏画质提升300%?3个隐藏参数解锁超清体验 【免费下载链接】QtScrcpy Android实时投屏软件,此应用程序提供USB(或通过TCP/IP)连接的Android设备的显示和控制。它不需要任何root访问权限 项目地址: https://gitcode.com/barry-ran/QtScr…...
终极指南:如何用免费软件完全掌控Windows电脑风扇噪音与散热平衡
终极指南:如何用免费软件完全掌控Windows电脑风扇噪音与散热平衡 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com/GitHub_T…...
Java开发者如何用Dify-Java-Client快速集成AI能力到Spring Boot项目
1. 项目概述:一个面向Java开发者的AI应用构建利器如果你正在用Java技术栈,同时又对当前火热的AI应用开发感兴趣,那么你很可能遇到过这样的困境:市面上主流的AI应用开发框架和客户端库,比如OpenAI的官方SDK、LangChain等…...
2025届最火的十大AI写作平台实际效果
Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 在这个信息呈现爆炸态势的时代当中,内容创作已然变成了个人以及企业所具备的核心…...
Win10下VSCode与OpenCV环境搭建:从零到一的避坑指南
1. 环境准备:安装必要工具链 在Windows 10上搭建OpenCV开发环境,首先需要准备好三个核心工具:MinGW、CMake和VSCode。这三个工具就像盖房子需要的钢筋、水泥和施工图纸,缺一不可。 MinGW是Windows下的GNU工具集,相当…...
Java后端开发德州扑克小酒馆小程序架构与源码解析
德州扑克小酒馆小程序的核心价值,在于依托休闲娱乐场景实现小酒馆线下引流,其Java后端的架构设计与源码实现,直接决定小程序的稳定性、可扩展性与合规性。 一、架构设计核心原则(贴合场景,合规优先) 德州…...
AB下载管理器终极指南:高效管理你的下载任务
AB下载管理器终极指南:高效管理你的下载任务 【免费下载链接】ab-download-manager A Download Manager that speeds up your downloads 项目地址: https://gitcode.com/GitHub_Trending/ab/ab-download-manager AB下载管理器是一款基于Kotlin开发的开源跨平…...
网盘直链解析工具终极指南:如何3分钟实现9大网盘下载加速
网盘直链解析工具终极指南:如何3分钟实现9大网盘下载加速 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天…...
RAG落地方案
1. RAG分析1.1 为什么需要 Rerank?要理解 Rerank 的价值,得先理解向量检索到底"差"在哪。RAG 的第一阶段检索,通常用的是双塔(Bi-Encoder)架构的 Embedding 模型。它的工作方式是把 Query 和每个文档分别独立…...
Cadence 17.4重装系统后,PCB快捷键失灵?别急着重装,先检查这个‘文件类型’
Cadence 17.4重装系统后PCB快捷键失效的深度排查指南 当你在Windows系统重装后,发现Cadence 17.4的PCB编辑器快捷键全部失灵,那种感觉就像突然失去了双手——每个操作都变得异常笨拙和低效。本文将从底层文件系统原理出发,带你深入排查这个看…...
