WebGL游戏站优化实录【myshmup.com】
myshmup.com 允许在浏览器中创建 shmup(射击)游戏。 你可以使用具有创意通用许可证的资源或上传自己的艺术作品和声音。 创建的游戏可以在网站上发布。 该平台不需要编码,游戏对象的配置是在用户界面的帮助下执行的。 后端是使用Django框架开发的。 编辑器 UI 用 Javascript 编写并使用 REACT 框架 游戏用 Typescript 编写并调用低级 Webgl API 进行渲染。
在这篇文章中,我将解释我在游戏部分使用的优化,以确保在大多数浏览器中获得流畅的 60PS 体验。

推荐:用 NSDT编辑器 快速搭建可编程3D场景
1、Webgl API
Webgl(Web 图形库)API 允许使用现代 GPU 在浏览器内渲染图形。 为了让 GPU 工作,你需要提供两个称为着色器的函数:顶点着色器和片段着色器。 着色器是用类似于 C++ 的 GLSL(GL Shader Language)编写的。
顶点着色器旨在计算场景的顶点位置。 然后,顶点着色器的输出被发送到片段着色器,片段着色器计算渲染的所有像素的颜色。 在 myshmup.com 中,我使用了一对简单的顶点和片段着色器。 它们仅处理 2D 矩形作为原始形状,每个矩形都有自己的纹理要绘制在其表面上。 可以调整纹理颜色以启用闪烁效果。 大多数渲染工作包括向着色器提供每帧所需的数据。
2、简单的实现

当我第一次尝试使用 Webgl 渲染 2D 游戏时,我编写了一对在屏幕上绘制纹理的着色器。 着色器由打字稿函数处理,该函数一次绘制一个游戏对象。 这个低级函数由绘制函数调用,以游戏对象作为输入。 为屏幕上可见的每个游戏对象调用绘制函数。
gameObjects.forEach( gameObject => draw(gameObject) );
虽然这种方法对于对象数量较少的情况效果很好,但当在最近的 mac book pro 上游戏对象数量超过 50 个时,这种方法的结果非常差。 出事了…
3、尽可能减少Draw Call次数

每个渲染帧都是 CPU 和 GPU 共同完成工作的结果。 CPU 为 GPU 准备数据和指令。 GPU 内存位于 GPU 上。 它称为 VRAM,与主 RAM 分开。 因此,我们需要在经典 RAM 和 GPU VRAM 之间传输数据。 在每次绘制调用时,GPU 都必须等待。 只有将所需数据从 RAM 推送到 VRAM 后才能开始渲染。 准备就绪后,由于其高并行化级别,显卡可以开始高效地完成其工作。
它就像一家工厂:它的设计目的是在给定批次中生产大量商品,但批次的设置时间可能很长。 你不想使用这条生产线进行手工作业,每批次生产一个物体,你希望每批次生产数百个木托盘,以优化生产成本。
我们现在了解最小化每帧执行的绘制调用次数的重要性。 CPU 到 GPU 的数据传输开销是快速渲染的主要瓶颈。
4、实例绘制

我们的目标是尽量减少绘制调用的数量。 为此,我们将使用相同纹理的所有游戏对象打包在一起。 想想射击游戏中敌人或英雄的所有子弹。 它们在屏幕上数量众多(因此有“弹幕地狱”的表达方式),但它们具有相同的纹理。 这只是在不同位置绘制相同的精灵。 装饰也是如此,它们通常由屏幕上重复的瓷砖制成。 你无需将游戏对象集处理为简单数组,而是在渲染之前准备数据。 你构建一个贴图,其中键是纹理 ID,值是使用该纹理的对象数组。 然后你可以只为每个纹理调用一次绘制函数。 对于有大量重复精灵的 shmup 来说,这是一个巨大的节省。
textures.forEach( texture => draw(texture.gameObjects))
为了在一批中多次使用相同纹理绘制对象数组,我们应该使用 Webgl 2 的“实例绘制”功能。此功能在 Webgl 1 中作为一个选项提供。为了简单起见,我们决定使用 Webgl 2 尽管它并不与当今所有的浏览器兼容。
5、纹理图集

我实现了实例绘制,一切都很好。 经过一年的开发,我向公众发布了该网站。 组织了一次游戏开发活动,所有游戏都是使用 myshmup.com 创建的。 每个参与者都在短时间内创造了非常原创的游戏。 Game Jam 的获胜者发布了一个受 TRON 电影启发的带有霓虹灯像素艺术的关卡。 他创造了大量的装饰瓷砖和可破坏的地面敌人来提供丰富的游戏环境。 然后又出现了这样的情况:在我最先进的、潮人认可的 mac book pro 上,游戏有时会出现滞后。 什么问题? 该游戏在给定时间显示的不同纹理的数量比简单游戏中的要多。 接下来做什么?
灵丹妙药是“纹理图集”技巧。 这个想法是创建一个非常大的纹理:在 myshmup.com 中,图集大小是 4096 x 4096 像素。 然后你只需在这个大纹理中绘制所有游戏对象的纹理即可。 当你将一个纹理复制到图集中时,你可以跟踪与其关联的纹理坐标,以便以后可以检索它。 如果你的图集太小,只需创建另一个图集。
实现纹理图集后,我获得了 Webgl 必杀技。 我每帧只调用一次绘制函数。 好吧,说实话,更准确的说法是每层每帧只调用一次绘制函数。 这意味着 myshmup.com 中有 10 个平局:游戏中有 6 个视差层,另外 4 个用于游戏 UI(得分栏和按钮)。 就是这样。 我可以有 1000 个对象,每帧只会绘制 10 次。 GPU 像天才一样完成繁重的工作和渲染一切。
6、得到的教训

myshmup.com 纹理图集示例
这次 webgl 优化之旅充满了惊喜。 如果实现实例化绘图和纹理图集看起来像是过度设计,请相信我,事实并非如此。 在浏览器中拥有流畅的动作游戏是关键。 只有在那之后,我才对我的平台提供流畅娱乐的稳健性充满信心。 当你拥有几乎恒定的 60 FPS 帧速率时,喜悦是发自内心的!
原文链接:WebGL射击游戏的优化 — BimAnt
相关文章:
WebGL游戏站优化实录【myshmup.com】
myshmup.com 允许在浏览器中创建 shmup(射击)游戏。 你可以使用具有创意通用许可证的资源或上传自己的艺术作品和声音。 创建的游戏可以在网站上发布。 该平台不需要编码,游戏对象的配置是在用户界面的帮助下执行的。 后端是使用Django框架开…...
6、Mysql免安装版本的配置与使用(2023-08)
1、下载 官网:https://www.mysql.com/downloads/ 点击前往 1.1 官网首页 1.2 首页往下翻,到达下图点击 1.3 选择如图Mysql Cimmunity Server 1.4 选择版本 1.5 点击开始下载 2、安装 2.1 配置环境变量 打开电脑环境变量,在环境变量path中…...
docker之简介与安装
环境配置问题 没有虚拟机,我们往往是打包代码发给对方,然后让对方安装相应的环境,比如node、数据库,要是配置不同,项目很有可能无法运行,还会报错,如果多个人想要运行这份代码,那还得…...
vue之动态表单(优化)
代码资源在这儿 ↑ vue之动态表单优化 vue2js动态表单优化vue3ts动态表单优化 vue2js动态表单优化 效果图 目录结构 五个文件的完整代码: 以下是App.vue <template><div><router-view></router-view><Formpage /></div> </templa…...
web连接桌面打开gptmap
一:环境配置 需要的材料: python-3.10.4 我使用的是这个版本的,3.8.10 该版本和以下版本组件组合,验证过能正常运行(python 3.6.8测试异常) websockify 该项目有python版本和node js版本 noVNC 形式的app…...
做好需求分析的4大关键认知
探索如何正确的需求分析?本文详细介绍了4大关键点,帮助您明确用户与产品需求、深入挖掘用户动机,并为产品经理提供筛选需求的实用建议。 一、什么是需求分析以及重要性 需求分析指的是在建立一个新的或改变一个现存的产品时,确定新…...
Max Compute 操作记录
编译 max compute-spark git clone https://github.com/aliyun/MaxCompute-Spark cd spark-3.x mvn clean package -DskipTests在 target 目录下生成 以下两个文件。 spark-examples_2.12-1.0.0-SNAPSHOT-shaded.jar spark-examples_2.12-1.0.0-SNAPSHOT.jar2. DataWorks 上传…...
Windows 11 + Ubuntu20.04 双系统 坑里爬起来
ThinkPad x390 安装双系统,原有的磁盘太小,扩充了磁盘重新装系统,出现的问题,加以记录。 1. windows和ubuntu谁先安装,两个都可以,一般建议先安装windows,后安装ubuntu 2. 安装windows后&…...
touch手势事件及功能封装
文章目录 基本概念事件类型事件对象的属性touch事件封装单击,双击滑动方向(上下左右)距离角度 缩放旋转 常用功能封装滑动图片浏览实现拖拽操作游戏角色移动、跳跃 封装手写板功能 在现代Web开发中,移动设备的普及使得触摸屏交互成…...
面试问题记录
1.多线程,线程池 1.如何创建线程 实现 Runnable 接口,重写run方法;实现 Callable 接口,重写call方法;继承 Thread 类,重写run方法。 2.基础线程机制 Executors:可以创建四种类型的线程池&am…...
ZooKeeper的应用场景(集群管理、Master选举)
5 集群管理 随着分布式系统规模的日益扩大,集群中的机器规模也随之变大,因此,如何更好地进行集群管理也显得越来越重要了。 所谓集群管理,包括集群监控与集群控制两大块,前者侧重对集群运行时状态的收集,后…...
面试算法编程题
面试算法编程题记录 题目 : 羊圈里的狼 题目背景 : 一到了晚上,草原牧民的羊就会被赶进羊圈里。这时,野外的狼群就会打羊羔的主意。为了保护羊羔,牧民需要将羊圈里的狼赶走或杀死。由于来的狼很多,他需要快速甄别哪些狼在羊圈里面…...
JVM——JDK 监控和故障处理工具总结
文章目录 JDK 命令行工具jps:查看所有 Java 进程jstat: 监视虚拟机各种运行状态信息 jinfo: 实时地查看和调整虚拟机各项参数jmap:生成堆转储快照**jhat**: 分析 heapdump 文件**jstack** :生成虚拟机当前时刻的线程快照 JDK 可视化分析工具JConsole:Java 监视与管理控制台连接…...
多维时序 | MATLAB实现WOA-CNN鲸鱼算法优化卷积神经网络的数据多变量时间序列预测
多维时序 | MATLAB实现WOA-CNN鲸鱼算法优化卷积神经网络的数据多变量时间序列预测 目录 多维时序 | MATLAB实现WOA-CNN鲸鱼算法优化卷积神经网络的数据多变量时间序列预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 多维时序 | MATLAB实现WOA-CNN鲸鱼算法优化卷积神经…...
ZoomIt v7.1
ZoomIt 是用于技术展示和演示的屏幕缩放、注释和录制工具。 还可以使用 ZoomIt 将屏幕截图截取到剪贴板或文件。 ZoomIt 在系统托盘中不显眼地运行,可使用可自定义的热键激活,它能够放大屏幕区域,在缩放时四处移动,并在缩放后的图…...
E8—Aurora 64/66B ip实现GTX与GTY的40G通信2023-08-12
1. 场景 要在贴有K7系列FPGA芯片的板子和贴有KU系列FPGA芯片的板子之间通过光模块光纤QSFP实现40G的高速通信。可以选择的方式有多种,但本质的方案就一种,即实现4路GTX与GTY之间的通信。可以选择8B/10B编码通过GT IP核实现,而不能通过Aurora…...
js下载后端返回的文件
文件流下载 后端返回文件流形式,前端下载 // res 为请求返回的数据对象const file_data res.data // 后端返回的文件流const blob new Blob([file_data]) const href window.URL.createObjectURL(blob) // 创建下载的链接 const file_name decodeURI(res.header…...
计组 | 并行操作
前言 记录一些计组相关联的题集与知识点,方便记忆与理解。 并行 什么是并行处理 广义地讲,并行性有两种含义:一是同时性,指两个或多个事件在同一时刻发生;二是并发性,指两个或多个事件在同一时间间隔内发生…...
rabbitmq容器启动后修改连接密码
1、进入容器 docker exec -it rabbitmq bash 2、查看当前用户列表 rabbitmqctl list_users 3、修改密码 rabbitmqctl change_password [username] ‘[NewPassword]’ 4、修改后退出容器 ctrlpq 5、退出容器后即可生效,不需要重启容器...
PHP中的curl详细解析和常见大坑
这篇文章主要介绍了 PHP 中使用 CURL 之 php curl 详细解析和常见大坑 ,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧。好啦,长话短说再长说,祭出今天的工具——CURL(Client URL Library),当然今天以 PHP…...
shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...
遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...
pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
CSS设置元素的宽度根据其内容自动调整
width: fit-content 是 CSS 中的一个属性值,用于设置元素的宽度根据其内容自动调整,确保宽度刚好容纳内容而不会超出。 效果对比 默认情况(width: auto): 块级元素(如 <div>)会占满父容器…...
让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...
MySQL JOIN 表过多的优化思路
当 MySQL 查询涉及大量表 JOIN 时,性能会显著下降。以下是优化思路和简易实现方法: 一、核心优化思路 减少 JOIN 数量 数据冗余:添加必要的冗余字段(如订单表直接存储用户名)合并表:将频繁关联的小表合并成…...
