速通自研游戏引擎 - 深入浅出 Boidmachine

速通自研游戏引擎 - 深入浅出 Boidmachine

Boidmachine 是个什么东西?

Boidmachine 最初的构想是作为一套后端无关的游戏开发框架,用于教学目的和小游戏制作,最早实践于《提瓦特幸存者 - 双人对战版》。随着2024年CiGA GameJam的到来,一个十分大胆的想法冒了出来,我决定利用半个月的空闲时间,将这个尚未开发完善的框架魔改为游戏引擎内核,并配套前端可视化编辑器,作为这次限时开发挑战赛的生产力。
从工程角度讲,这确实是一个十分冒险的行为,在前前后后一周左右的有效工作时间内,从头开始搭建全套游戏开发工具链,这意味着我几乎没有时间试错并且完全覆盖地测试,但没有什么比这种限时开发更刺激了!事实证明我做到了,一个十分保守的最小实现游戏引擎套件赶在赛题公布当天的清晨完工,并在此基础上完成了我们的作品《Unlimited Cage》
本文以此为主题分享Boidmachine的设计思想和实现细节,诚然,游戏引擎是一个非常庞大且有深度的话题,我无法确保这种极限开发过程中的解决方案是最佳思路,但是这至少是相对稳妥且“够用”的;注意,为了便于理解和讲述,本文中的代码只摘取部分核心片段简化后展示,或是无法直接复制使用的伪代码,但还是希望本文可以对正在学习和实践引擎开发的同学们起到抛砖引玉的作用。

阅读更多
《提瓦特幸存者》双人对战版游戏开发

《提瓦特幸存者》双人对战版游戏开发

在2023年11月,我开始在B站更新了提瓦特幸存者项目的视频教程,作为《从零开始的C++游戏开发》系列的第一个稍具游戏性的实战项目,代码内容和游戏玩法都极度轻量,只实现了残缺的类吸血鬼幸存者游戏的玩法,近期在相同的技术基础之上,复用进阶版游戏素材,扩展制作了本地双人对战的玩法,提供了更多游戏机制,本文介绍此项目的前因后果和开发思路。

阅读更多

新手教程 - 如何发布你的EasyX游戏

有小伙伴在交流群里问起如何发布自己的游戏,才意识到还有这个问题。之前的视频教程只是讲解了如何在VisualStudio中编写EasyX相关的代码,并没有提到如何将完成的项目发布的方法,这种问题在很多教程中都是默认学习者已经掌握了,但实际情况是如何打包发布涉及到开发工具使用和编译选项等诸多概念,想来自己初学时也踩过很多坑,便整理一下相关的内容,供新手小伙伴们参考。

群聊记录

本文以提瓦特幸存者进阶版的项目为例,以点带面地讲解新手在发布自己的程序时可能遇到的问题和对应的解决方案,本项目开发环境为VisualStudio2022,图形库为EasyX,使用其他开发环境或图形库的C++项目操作相似。

阅读更多

视频被培训机构选做直播课了,但是我却很担忧…

距离《从零开始的C++游戏开发》系列视频更新的第0期,到现在已经有将近一个半月的时间了,这是我第一次在B站这种公众空间尝试进行知识分享,有点陌生,有点紧张,但是很开心。在这不长不短的时间里面,有2000+的小伙伴因为这个系列教程关注了我,私信和评论区也得到了很多小伙伴的鼓励。虽然视频是近期才开始制作的,但是制作这套教程的想法,却早在很多年前便萌生了出来。

如果说这一切的动机是什么,可能是作为技术从业者那种最本源的热爱和分享欲,以及,对于知识传承的责任感……

有的时候,人生的经历就像小说一样充满着铺垫和预言。高中的时候,我很喜欢在学校周围的书店里面购买诸如《电脑报》之流的刊物,已经不记得从哪篇文章的边角处,瞥见了雷霄骅前辈的新闻,那时的自己对他的所作所为或是经历都一无所知,只是对这个名字大致有了印象。在大学的时候,在钻研音视频技术开发的时候,到处搜集资料时却发现,国内音视频技术圈子的知识分享,源头似乎都指向了他的博客,而当我追根溯源翻找博客评论区时,却发现,雷前辈已经逝去多年了,而视频资料,也只能找到年代久远画质模糊的录屏。回想起来,高中时报刊上的新闻,应该是他英年早逝的消息,这是我第一次,对一个远在天边曾经存在于这个世界上的陌生人,产生了天妒英才的惋惜情绪。

知乎@鹏小鹕

阅读更多

自研引擎二三事

酝酿了许久,想仔细回忆一下故事从哪里说起——我想,关于游戏开发和造轮子这件事,大致在初高中时便埋下了种子。那会儿自己和周围的同学们都是资深老二刺猿,有一部动漫经典作品叫《刀剑神域》,关于完全沉浸式VR的幻想以及使用游戏为媒介创造出一个完全虚拟的世界这种东西,对于青春热血的理工科少年来说简直有着难以想象的诱惑力,于是乎,中二病爆破的年纪便把在动漫里面缔造这一切的角色茅场晶彦作为了自己的偶像,幻想着自己也能有朝一日成为这种天才程序员,用代码模拟出一个亦真亦幻的世界。

真正有机会接触代码学习的时候,其实已经是脱离“做题家”身份的大学时代了,那时候想学编程但是求学无门,市面上成体系的教学课程太贵,刚开始使用互联网学习的自己又不知道从何下手搜索学习资料,于是乎,便歪打正着从一贴吧老哥那里求得了有偿的“自学辅导”。自学辅导的意思大概就是说,他作为码农前辈,给制定学习路线,提供学习资料,日常答疑解惑,但是你的主要学习过程,是要自己去学习钻研的,而不是培训课程那样的填鸭式教育。虽然这位老哥提供的学习资料其实都是免费的,但是对于一开始搜刮情报能力极低的自己,这无疑是莫大的帮助。 这个过程自然是有偿的,不过经过一番讨价还价,那位老哥大概是本着副业从小本生意做起的原则,同意我对一共3K的学费分10期付完,这样固定每月300的学习费用便由我自己从生活费里面挤出来。

那段时间的学习是从Java入手的,倒也合理,那些年市面上热度最高的行业大多都是在Java的基石上运转起来的,资料自然也是最多的。但是,慢慢地在学习过程中发现,Java后端,H5前端,Node.js,Android开发……自己的学习路线似乎与想要创造一个“虚拟世界”的初心越来越远。没办法,既然师傅不能提供这些资料,自己便尝试着用现有的技术知识去制作一个虚拟的世界。

阅读更多

EtherTK 解构《武士零》 - 自动法线

关于本文所提及的蒙版光照相关的前置内容,详见:EtherTK 解构《武士零》 - 蒙版光照

2D 法线贴图?

对于这篇博客的标题,其实还是犹豫了一会儿的,因为在 2D 渲染过程中,对于“能够对光照效果产生影响的贴图”这种东西的叫法,就算是工作组内的同学意见也不一致;但在我看来,如果我们把不使用法线贴图的 2D 纹理看做是法线方向始终沿 Z 轴方向的话(即在光照响应时法线对光强的贡献始终为 1),那么当我们使用另外一张蒙版遮罩贴图对这张目标贴图响应光照强度的区域进行限定时,这张蒙版遮罩贴图本身就已经起到了法线的作用——如果我们的这张蒙版遮罩贴图使用 Alpha 值来描述目标纹理的光照响应区域强度,那么目标纹理在渲染时计算每个像素的光照响应强度时,与传统法线贴图使用 RGB 分量来描述空间向量相似,使用 Alpha 通道的值直接作为衰减系数对光照效果进行计算,所得到的渲染结果是一致的;综上所述,这种蒙版遮罩与法线本质相同,所以将其称之为法线也并不为过。

——听起来可能有点绕,咱们先看一下这种法线贴图在实际渲染中的效果:
启用法线(左)/ 关闭法线(右)

而渲染上图所使用的纹理原始素材如下:
目标纹理(左)/ 法线纹理(右)

我们可以很清晰地看出,在使用法线后,光照的响应强度开始受法线贴图的 Alpha 值影响,这不仅让光源的外形更加真实,也让被渲染的目标纹理在复杂光照环境下更加立体,让画面中的物体与光效“融合”到了一起,避免了使用贴图光的剥离感。

——那么,接下来的问题便是,如何由目标纹理得到对应的法线纹理?

阅读更多

Soloud 踩坑日志

由于新作对引擎内核的音频模块提出了更高的要求,所以一直陪伴在身边的 SDL_mixer 便差不多该结束他的职业生涯了,是时候进行新的音频内核探索了,本文主要围绕着在探索过程中遇到的让人又爱又恨的 Soloud 音频库展开记录——

为什么是 Soloud ?

因为在研的下一代引擎 StarDustEngine 暂定目标仍为开源项目,截止到目前为止所依赖的所有三方库均为开源,在协议方面对于再分发和商业使用都没有太大限制,所以,对于常见音频库的选择思路:

  • OpenAL:其实玩 OpenGL 已经耗费了几乎所有精力,所有 OpenXX 的这种相对底层的库,现在的我大概保持一种敬而远之的态度;
  • FMODE:我承认他很强大,但是他太过于强大了,这种次时代的商业音频库对于我们现在能力范围内所实现的轻量级小体量引擎来说,就像是小正太在被大车开;更何况,FMODE 不仅不开源,在商业授权上也是一套又一套,一眼望过去便繁琐至极;
  • SDL_mixer:诚然,作为 SDL 全家桶中的重要一环,使用起来算是极其方便的,但是,简明的 API 所带来的反面效果便是开发者很难从相对底层的层面上去控制音频播控,从而无法实现效果器和响度调控等功能,这正是下一代引擎所必须的功能;
  • IrrKlang:算作是相对小众的老牌音频库,虽然自己没有深度使用过,但是在学习过程中看到过很多资料作者都在用其进行项目教学;仔细了解下后才发现,IrrKlang 同样没有开源,且对商业授权付费,所以依然 Pass;
  • Soloud:开源,免费,并且专为游戏打造,虽然比较小众,但是当我看到下文时,我就决定是他了:

    If you’re planning to make a multi-million budgeted console game, this library is (probably) not for you. Feel free to try it though :-)
    如果您计划制作一款预算数百万美元的主机游戏,那么这个库(可能)不适合您。不过请随意尝试一下:-)

Soloud Logo

阅读更多

EtherTK 解构《武士零》 - 冲刺特效

冲刺特效也就是俗称的“残影”,《武士零》中玩家几乎所有的冲刺操作都会或多或少地伴随着这种特效,在本次重现的思路中,残影由一系列透明度随时间变化的剪影风格序列帧构成,当然,考虑到赛博朋克的艺术风格,这些残影的颜色也主要应该由红色和蓝色构成——
武士零冲刺演示

着色器代码

想要实现剪影风格的渲染也很简单,简单来说可以使用如下的 shader 代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
in vec2 textureCoord;

out vec4 FragColor;

uniform sampler2D texture1;

uniform vec3 color;
uniform float alpha;

void main()
{
vec4 textureColor = texture(texture1, textureCoord);
if (textureColor.a == 0)
FragColor = vec4(0, 0, 0, 0);
else
FragColor = vec4(color, alpha);
}

因为要在外部程序中控制透明度渐变从而实现消逝的过程,所以我们传入了 alpha 这个 Uniform 值,由于原始素材中没有使用半透明的像素,所以我们直接将传入的透明度作为了最终的片段透明度输出,如果需要考虑到原始素材中的半透明像素,那么只需要将 FragColor = vec4(color, alpha); 变更为 FragColor = vec4(color, alpha * textureColor.a);

阅读更多

EtherTK 解构《武士零》 - 蒙版光照

其实与光照的死磕在很久之前便已经开始了,在开发第一代使用 OpenGL 可编程渲染管线的引擎时,便实现了一套简单的 2D 光照算法,那时候更多的还是借鉴自 LearnOpenGL 的 3D 光照思路,但是在对《武士零》的研究过程中,发现如果仅制作 2D 游戏的话,使用源自上个游戏技术世代的蒙版贴图,配合现代化的渲染管线,可以更简明地实现更符合艺术效果的光照效果(至少在像素风格的 2D 游戏看来是这样),本文将对该过程的探索过程进行阐述。

本文及相关程序所使用的实现依然为 EtherTk,不过由于需要更精确自由的渲染逻辑,所以底层实现由 SDL Renderer 变更为了 OpenGL。

基于公式计算的光照

此节内容更多参考自:投光物 - LearnOpenGL CN

对于游戏中的光照公式可以简化为:物体受光 = 环境光 + 聚光灯(点光源可以看作是外切角为 360° 的聚光灯),而整个世界是一片漆黑没有任何光照的,环境光作为让场景中各物体雨露均沾接受光照的光源,为物体提供了最基础的光照贡献——简单理解,在不使用光照进行渲染的场景中,不经任何处理绘制的物体纹理贴图相当于被赋予了环境光强度为 1 的白色光照;而聚光灯的技术核心,更多的是使用统一的公式和参数描述指向性光源的外形,从而计算得到世界中受此影响的像素片段。

对于聚光灯的处理,首先要计算的便是处理其径向衰减,逆向思考一下,聚光灯也可以看做是指向性的点光源,所以在处理径向衰减的思路和点光源完全相同。虽然我向来不喜欢将晦涩的数学公式搬上台面,但是无奈光照这种基于物理和经验的模拟,很难找到除去公式之外的第二种表述方式——当然,这样方便了我们,即使不能完全理解,也是可以直接套用公式实现不错的效果:
径向衰减公式

阅读更多