- 博客(105)
- 收藏
- 关注
原创 游戏脚本(TS)下的ECS架构三种实现方式以及性能对比
本文探讨了在TypeScript游戏开发中ECS架构的三种组件存储方案性能对比。通过基准测试发现:Map-of-Maps方案在随机访问(快128倍)和批量遍历(仅慢1.3倍)上综合表现最优,适合大多数游戏场景;SoA方案虽在遍历性能上最佳,但随机访问性能随规模急剧恶化;Composite方案实现简单但遍历性能差。建议根据实际需求选择:纯System驱动选SoA,混合型逻辑选Map-of-Maps。测试数据表明,在5万实体规模下,Map-of-Maps能平衡两类操作需求,是TS游戏框架的最佳实践。
2025-11-24 01:08:30
1183
原创 在C++中手动实现比原生RTTI更高效的动态类型转换(dynamic_cast)
在项目关闭RTTI的情况下,或者性能极其敏感的情况下要实现不依赖于RTTI的类,手动实现一个不依赖于C++的RTTI机制的甚至效率更高的dynamic_cast
2025-10-17 19:05:53
1110
原创 Unreal故障艺术之RGB颜色分离故障
(Glitch Art) 是一种利用事物的故障进行艺术加工的艺术形式,使原本的故障缺陷反而成为一种具有特殊美感的艺术品。故障艺术的起源与发展 故障艺术起源于20世纪初的达达主义运动,是一种对传统审美观念的反叛。“Glitch”一词最早可追溯到美国太空计划,1962年宇航员约翰·格伦用其描述信号图像传输错误。20世纪70年代,故障艺术开始真正成为一个独特的设计技巧。把图片分成三个通道,然后分别做不同的偏移,最后合起来R通道采样。说白了就是在最终图片再不同的通道上进行偏移采样。
2025-09-15 19:21:18
310
原创 布隆过滤器(Bloom Filter)原理和实现
位数组(Bit Array)大小:m哈希函数数量:k集合元素数量:n(插入n个元素)对于某个特定位置的比特位,一次哈希未选中的概率为对于某个特定位置的比特位,K次哈希未选中的概率为对于某个特定位置的比特位,插入K次后未被选中的概率为我们有设x = 1/m推出对于某个特定位置的比特位,插入K次后未被选中的概率为则对于某个特定位置的比特位,插入K次后被选中的概率为则对于K个特定位置的比特位,插入K次后被选中的概率为为了使误判率最低,则要求P的最低值,后的计算比较繁琐了,
2025-08-16 14:17:28
1046
原创 深入理解契约式编程(Design by Contract)
在常见的代码编写中,为了防止程序由于意外输入崩溃,增强程序的健壮性,经常使用防御式编程,但是也造成了调试困难的问题,问题需要一层一层找到根源(题外话,笔者也写过游戏服务器代码,像一局多人对局中,如果出现了一处空指针崩溃,则会造成这个所有玩家全部对局失败,每一处指针必须全部判空处理也是老生常谈了)
2025-08-13 14:07:47
988
原创 C语言优化技巧--达夫设备(Duff‘s Device)解析
1983年,一位程序员TomDuff(曾在贝尔实验室和星球大战母公司卢卡斯影业就职过)乍一眼看上去,switch和while嵌套使用,这段代码好像有Bug但是它不仅没有Bug并且极其巧妙。
2024-12-29 02:25:01
1017
原创 碰撞检测算法之闵可夫斯基差集法(Minkowski Difference)
在游戏开发和机器人路径规划乃至于现在比较火的自动驾驶中,我们常常需要确定两个物体是否发生碰撞,有一种通过闵可夫斯基差集法求是否相交的算法
2024-12-22 21:03:47
2332
1
原创 深入条件编译优化
在代码开发中,为避免发布版本中包含不必要的断言和日志输出导致性能开销,可通过宏定义、if constexpr、模板特化或SFINAE等技术实现条件编译。这些方法确保仅在开发模式下编译相关代码,而在发布版本中完全剔除,从而减少二进制大小并提升性能。
2024-12-21 12:33:23
976
2
原创 哈希表的大小为什么最好是质数及推导过程
哈希函数是一种将任意长度的输入通过散列算法变换成固定长度的输出的函数,当不同键的哈希值相同,就会发生Hash碰撞解决这个问题的思路有两个,一个是发生碰撞后解决碰撞,另一个是避免碰撞发生碰撞后解决碰撞的方法有开放寻址法和拉链法,这些网上都能搜到,就不赘述了我下面要讨论的是通过素数来减少哈希函数的碰撞。
2024-10-10 15:58:08
1548
原创 为什么说函数传递参数最好小于四个
有一个建议说时函数传递参数最好不超过四个,原因有一个是参数太多难以维护,另一个重要的原因就是函数传递小于四个参数时候效率会更高,其实这个说法也不全对其实那么下面将探究函数参数传递相关的问题。
2024-09-29 20:54:16
1072
原创 从零简单实现一个线程安全的C++共享指针(shared_ptr)
shared_ptr主要是用来自动管理动态创建对象的销毁,记录对象被引用的次数,当引用计数清零的时候,把指向的内存区域自动释放掉。如果要手动实现一个共享指针的话就需要一个共享指针类,类中存着被指向的对象的指针。当对象被多个共享指针指向的时候,就需要一个共享的引用计数器counter。当都断的时候,引用计数器变为0,这时候清理对象A。当对象被共享指针指向的时候,引用计数器为2。当一个共享指针被释放后,引用计数器的值减1。
2024-03-23 12:18:19
1693
原创 在C++的union中使用std::string(非POD对象)的陷阱
union是C语言中的关键字,在嵌入式中比较常见,由于嵌入式内存比较稀缺,所以常用union用来节约空间,写一个简单程序来说明union的用途。将编译条件改为-std=c++11,编译通过,所以在后面可以在union中使用带构造方法的对象了;因为string不属于POD对象,有构造函数,所以在旧版中禁止了在union中使用非POD对象。union的三个变量公用一段内存,所以同时只能存储一个变量。由于内存对齐的原因,最后用了3*8 = 24字节。int占4位,double占8位,c占1位。
2024-02-06 18:48:31
1791
2
原创 游戏引擎的cpu/gpu粒子系统设计思想
网上有很多篇粒子系统源码解析,但是只是简单的接口罗列,没有从最原理出发去讲清楚粒子系统的来龙去脉,我将从粒子系统的本质去讲清楚它的设计理念,当理解了它的理念以后,很多粒子遇到的问题就会迎刃解决了,这篇文章主讲粒子的实现和一些框架级的优化方式,其实有很多优化细节就不赘述。简单说,就是几何着色器可以把单个顶点扩充成多个顶点,如果粒子的mesh都一样的话,只需要从顶点着色器中传入的单个顶点和扩展规则,就可以生成想渲染的粒子mesh,而并不需要每回传入大量的顶点了。这种情况试用语cpu对大量粒子计算和更新的情况。
2023-07-07 14:41:44
3530
原创 浅谈C++下观察者模式的实现
观察者模式中有一个称作“主题”的对象和若干个称作“观察者”的对象,“主题”和“观察者”间是一种一对多的依赖关系,当“主题”的状态发生变化时,所有“观察者”都得到通知。在许多设计中,经常涉及多个对象都对一个特殊对象中的数据变化感兴趣,而且这多个对象都希望跟踪那个特殊对象中的数据变化,也就是说当对象间存在一对多关系时,在这样的情况下就可以使用观察者模式。这时候猫作为被观察者,老鼠作为观察者,这时候执行“我来了”的事件,就不需要每次都修改执行的代码了,只需要在主函数中添加即可。
2023-07-06 17:06:27
950
1
原创 基于泰勒(Taylor)中值定理的低开销快速距离算法(Fast_Distance_2D)
最近看《3D游戏编程大师技巧(上篇)》的时候提到了一个重要的算法Fast_Distance_2D,旨在用低开销的方法去计算点和点的距离,这个算法在André LaMothe的代表作《Windows游戏编程大师技巧 (第2版)》中有着更详细的介绍,不过这种算法存在着不小的误差(2D版本的最大误差为3.5%,3D版本约为8%)完全可以用(x1-x2)的和(y1-y2)的平方和r的平方比较,而避免了开方操作,这就直接避免了开根计算。主要用到了泰勒/麦克劳林方程。
2023-06-21 14:30:11
501
1
原创 延迟渲染G-buffer所占显存带宽计算(解决移动端和抗锯齿的若干疑问)
延迟渲染需要在前面阶段,将计算的内容保留在N张G-buffer中,但是网上的文章只是提及了G-buffer应该压缩,并且尽量少用,没有说明G-buffer所占带宽应该是多少,我将在下面介绍G-buffer所占显存带宽的详细计算方法。
2023-06-16 13:17:36
2186
原创 Gouraud Shading(高洛德着色法)和其优缺点详解
Gouraud是一种插值方法,Gouraud着色法是计算机图形学中的一种插值方法,可以为多边形网格表面生成连续的明暗变化。实际使用时,通常先计算三角形每个顶点的光照,再通过双线性插值计算三角形区域中其它像素的颜色。
2023-05-31 21:24:40
2709
原创 在unreal中的基于波叠加的波浪水面材质原理和制作
到现在的水体渲染已经从材质模拟到现在ue5的粒子模拟,可谓是进步十足,现在的主流水体渲染方案有几种,线性波形叠加方法,统计模型方法,波动粒子方法,基于物理的方法,预渲染方法等,各种五花八门的方法层出不穷,本文的方法主要是基于第一种方法。光线作用于法线的时候,物体的凹凸效果是通过XY的分量决定的,这里将RG(也就是法线向量的XY分量)提出来,乘一个系数Param,系数越大,波浪越明显。在同一介质中传递的两个波相遇时,重叠范围内会遵守波的叠加原理,当两波分开后,会维持各自原本的运动,称为波的独立性。
2023-04-11 13:46:59
2297
1
原创 兰伯特光照模型(Lambert Lighting)和半兰伯特光照模型(Half-Lanbert)
介绍兰伯特光照模型(Lambert Lighting)和半兰伯特光照模型(Half-Lanbert)
2023-04-07 11:28:12
2845
原创 从底层本质上解析java是值传值还是引用传值
关于java是值传值还是引用传值,在网上找了半天发现网上对于这个问题没有一个合理的解释,特地写了这篇文章,希望能给这个问题一个正确的解释这个问题设计语言层次的设计问题,所以我会列出从底向上的的所有结构,这个结构的合理性将不言自明。
2023-04-04 12:57:03
405
原创 利用CPU的分支预测(Branch Prediction)模型优化if-else
现代计算机和编译器的结构更加智能化,会想尽办法去把CPU所有部件全部利用起来,不想让CPU的任何区域出现空闲我前面的文章提到过simd优化,将CPU的数据位宽利用起来,CPU累加器在单个时钟周期里并行完成数据位宽/数据类型大小的计算,对32位操作系统而言,32位的宽度能放下4个float类型的数据,也就能一次完成一个四维向量的累加计算,大大利用了总线的宽度下面将介绍另一种能“压榨”计算机性能的优化手段。
2023-03-28 21:39:12
1695
原创 用两个程序说明为什么推荐使用内存池
内存池(Memory Pool)是一种内存分配方式,又被称为固定大小区块规划(fixed-size-blocks allocation)。通常我们习惯直接使用new、malloc等API申请分配内存,这样做的缺点在于:由于所申请内存块的大小不定,当频繁使用时会造成大量的内存碎片并进而降低性能
2023-03-22 12:47:52
324
原创 计算机图形学:详解法线与法线贴图原理
法线贴图 (Normal Map) 是一种凹凸贴图 (Bump Map)。它们是一种特殊的纹理,可让您将表面细节(如凹凸、凹槽和划痕)添加到模型,从而捕捉光线,就像由真实几何体表示一样
2023-02-06 11:31:59
7381
原创 详解C++三种new的使用方法(在栈上用new生成对象)
new有三种使用方式:new operator,operator new()和placement new()
2023-02-01 11:28:34
1756
原创 混合架构CPU下Visual Studio编译UE引擎时CPU吃不满的原因
可以发现在编译过程中,将CPU的四个能效核心吃满了,但是性能核心却基本没用着。由于CPU是i5-12600k,这个CPU有6性能核心和4个能效核心。在编译UE5引擎源码的时候发现CPU占用率不高。
2022-12-19 23:41:11
2506
2
原创 机器人逆向运动学(IK):问题分析
在游戏开发和机器人开发中进场需要用到的一个场景是,给机器人或者游戏角色末位置的位置和姿态,求解可到达给定位置和姿态的各关节的角度值,这里就需要逆向运动学去求解这个问题
2022-12-14 14:17:31
1696
1
原创 深度探究多线程的效率以及多线程的使用建议
随着时代发展,电脑的核心数慢慢增多,在开发程序的过程中,是否选择使用多线程这是个比较大的问题,下面我通过一个程序去深入理解多线程对程序速度的影响到底有多大
2022-11-18 17:03:53
999
2
原创 操作符=重载陷阱(赋值构造其实并没有执行赋值操作)
在对”=“执行操作符重载的时候,在main中=调用的时候并没有在操作符执行重载里面执行的输出语句
2022-11-10 18:06:18
254
3
空空如也
为什么函数不能改变ts装箱后的值
2024-02-01
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅