当前位置: 首页 > news >正文

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 的高级特性着色器编程计算着色器 实战案例&#xff1a;创建一个简单的 2D 游戏游戏逻辑设计…...

SAP B1 认证考试习题 - 解析版(二)

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

《Ubuntu20.04环境下的ROS进阶学习7》

一、使用nav_msgs消息包显示小车轨迹 在我们跑实验的时候通常希望看到小车的轨迹&#xff0c;在ROS1中可以将小车的路径存储在nav_msgs::Path 这种消息类型里&#xff0c;发布出来后使用rviz来显示小车轨迹。 二、了解nav_msgs消息包 那么首先我们要来了解一下nav_msgs这个消息…...

免费视频无损压缩工具+预览视频生成工具

视频无损压缩工具 功能与作用 &#xff1a;视频无损压缩工具是一种能够减少视频文件大小&#xff0c;但同时保持视频质量的工具。它通过先进的编码技术和算法&#xff0c;有效降低视频文件的存储空间&#xff0c;同时保证视频的清晰度和观感。这对于需要分享或存储大量视频内容…...

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 消息提示框

提示&#xff1a;记录工作中遇到的需求及解决办法 文章目录 前言一、目录结构二、代码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传感器的发展&#xff0c;最近发布了具有2D图像和3D点云数据的MVTec-3D AD数据集&#xff0c;促进了多模态工业异常检测的研究。 无监督异常检测的核心思想是找出正常表示与异常之间的差异。…...

基于微信小程序的宿舍报修系统的设计与实现(lw+演示+源码+运行)

摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对成果信息管理混乱&#xff0c;出错率高&#xff0c;信息安全性差&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 保证消息传递可靠性的机制——消息确认、持久化和发送发确认&#xff0c;那么对于消息确认和发送方确认&#xff0c;如果接收方没有收到消息&#xff0c;那…...

每天一道面试题(20):锁的发生原因和避免措施

死锁的发生原因和避免措施 一、概述 在多线程编程中&#xff0c;死锁是一个常见的问题。理解死锁的成因和避免策略是提升程序稳定性和性能的重要能力。 二、普通人 vs 高手的回答 普通人回答&#xff1a; “临场发挥…” 高手回答&#xff1a; “死锁是指两个或多个线程在执…...

2024淘宝双11活动,收下这份必买好物推荐清单

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

vue-cli,element-plus,axios,proxy

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

《Zeotero的学习》

学习视频链接 Zeotera的安装 官网点击download&#xff0c;选择合适的版本进行下载&#xff0c;并安装插件。 下载完成之后&#xff0c;点击安装包&#xff0c;一路默认就可以。如果不想下载在C盘&#xff0c;可以在步骤中选择自定义路径。 Zeotero的注册 官网进行注册&am…...

大数据复习知识点1

1、HDFS和MapReduce的起源&#xff1a;HDFS起源于Google的GFS论文&#xff0c;它是为了解决大规模数据集的存储问题而设计的。而MapReduce则是Google为了解决大规模数据处理问题而提出的一种并行计算模型。 2、YARN的作用&#xff1a;YARN是Hadoop的资源管理器&#xff0c;它负…...

9.26 Buu俩题解

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

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…...

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

模型参数、模型存储精度、参数与显存

模型参数量衡量单位 M&#xff1a;百万&#xff08;Million&#xff09; B&#xff1a;十亿&#xff08;Billion&#xff09; 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的&#xff0c;但是一个参数所表示多少字节不一定&#xff0c;需要看这个参数以什么…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入&#xff0c;一个是通过INMP441麦克风模块采集音频&#xff0c;一个是通过PCM5102A模块播放音频&#xff0c;那如果我们将两者结合起来&#xff0c;将麦克风采集到的音频通过PCM5102A播放&#xff0c;是不是就可以做一个扩音器了呢…...

Mac软件卸载指南,简单易懂!

刚和Adobe分手&#xff0c;它却总在Library里给你写"回忆录"&#xff1f;卸载的Final Cut Pro像电子幽灵般阴魂不散&#xff1f;总是会有残留文件&#xff0c;别慌&#xff01;这份Mac软件卸载指南&#xff0c;将用最硬核的方式教你"数字分手术"&#xff0…...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案&#xff0c;允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

LLM基础1_语言模型如何处理文本

基于GitHub项目&#xff1a;https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken&#xff1a;OpenAI开发的专业"分词器" torch&#xff1a;Facebook开发的强力计算引擎&#xff0c;相当于超级计算器 理解词嵌入&#xff1a;给词语画"…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

STM32---外部32.768K晶振(LSE)无法起振问题

晶振是否起振主要就检查两个1、晶振与MCU是否兼容&#xff1b;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容&#xff08;CL&#xff09;与匹配电容&#xff08;CL1、CL2&#xff09;的关系 2. 如何选择 CL1 和 CL…...

「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案

在移动互联网营销竞争白热化的当下&#xff0c;推客小程序系统凭借其裂变传播、精准营销等特性&#xff0c;成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径&#xff0c;助力开发者打造具有市场竞争力的营销工具。​ 一、系统核心功能架构&…...