从零开始制作红色警戒2VXL(理论部分)
仓野kiriha
2026年05月14日 00:26

写这篇东西的目的也是希望鼓励更多的有想法但是迟于行动的人能真正动起手来自己去做点什么东西出来。

理论部分

一、.pal文件

二、.vxl文件与.hva文件

三、法线(法向量)

四、.vpl文件

实践部分(计划内有这些,但是本文不包含在内,以后再说)

一、magicavoxel使用教程

二、vse1.38与vse1.39相关

三、yvory相关

四、色盘编辑器相关

五、Vpl编辑器相关

六、Voxelshop相关

理论部分的东西不多,只把我觉得重要的写在这里。

一、.pal文件

Palette文件,色盘。

顺序表。256个“格子”内存放的是rgb值。但是对于特定的“格子”有特殊处理。

0号色:背景色。有些人会称之为透明色。不论0号色是什么颜色游戏都不会绘制这一颜色。而是直接透过这个颜色露出背景,因此称为背景色。

备注:尽管游戏不会绘制该颜色,但vxl若使用了这些颜色,游戏仍然会绘制这些体素的影子。

16-31号色:阵营所属色。Remapable=yes的单位会将这部分颜色重新绘制为所属色。

备注:其他颜色的vpl调用这部分颜色时依然会重新绘制为所属色。同时,如果所属色的vpl调用了其他颜色,则不会重新绘制为所属色而是调用其他颜色。因此,所属色的vpl不应该调用其他颜色,同时其他颜色的vpl也不应该调用所属色。在此结论下,可以自行定义所属色的rgb值,个人建议是越远离常用色系越好。

240-255号色:恒定色。不管游戏内的光源或vxl朝向或vxl法线或vpl如何改变,这部分颜色永远只会绘制该格子内存放的rgb的值。可以用于模拟发光色,在暗光照环境下表现还行。

游戏内一共存在六种气候(theater),分别是沙漠,月球,温和,雪地,城镇,新城镇。每种气候对应一种色盘,分别为XXXdes,XXXlun,XXXtem,XXXsno,XXXurb,XXXubn,前面的XXX表示色盘名,原版游戏色盘名为unit,完整文件名为unittem.pal,其他气候类型的色盘同理。

以原版unittem为例,讲道理这图应该放在实践部分去讲

二、.vxl文件与.hva文件

Vxl文件保存的信息是“在哪个位置,使用了色盘上的哪一号颜色”和“在哪个位置,使用了哪一个法线(法向量)”。

Hva文件保存的信息是平移旋转缩放和帧动画等。

三、法线(法向量)

Normals。翻译为法线其实并不准确,尤其在头猫指出vxl的光照模型为blinn-phong模型之后,这个词就更应该翻译为法向量。当然这两者其实也差不太多就是了。

要理解法线,首先回顾初中学过的几何光学里,光反射时出射角=入射角。这里便涉及到入射面的法线。Vxl的法线(法向量)实际上和这里的法线(法向量)是同一个东西,其物理含义也完全一致。

回到vxl的法线上,vxl的法线色盘将256个颜色大致均匀的分布在一个球上。这意味着每个法线颜色实际上对应了一个法向量,或者说在空间中的一种朝向。一个体素的法线(法向量)则意味着这个体素在空间中的“朝向”,就好像一个体素本身就是一个虚拟的平面一样。这一点正是手动法线的核心。

关于vse的自动法线,有一篇论文,没记错的话应该是banshee在2007年巴西的某个学术会议上发表的。

https://www.ppmsite.com/sibgrapi2007_files/finding_surface_normals_from_voxels.pdf

四、vpl部分

vpl的本质是一个映射表,它本身并没有创建新的颜色(并没有引入新的rgb值),而是将一个颜色映射为同一个色盘上的另一个颜色。

游戏在绘制vxl单位时,并不会直接把.vxl里的颜色绘制出来,而是透过一定的计算让这个颜色变为色盘上的另一个颜色之后,再进行绘制。中间这个计算过程长久以来一直是黑箱,直到头猫指出这个计算遵循blinn-phong模型(https://bbs.ra2diy.com/forum.php?mod=viewthread&tid=23475(这篇帖子目前被隐藏了))。

引入vpl目的也很简单,就是模拟光照效果,让近光侧更亮,背光侧更暗,从而实现3D模型的立体感。(实际上你也可以通过修改vpl来实现没有光照效果的2D风格。)

关于blinn-phong模型,网上有很多文章,不再赘述。只简单讲解blinn-phong模型中的三个参数:高光(Specular),漫反射(Diffues)和环境光(Ambient)。

高光:光源通过反射进入视角(相机)的光。这部分光的光强一般是较为强烈的。具体到vxl里可以理解为当光源向量与法线向量夹角突破某个值时,物体表面会急剧变亮/变暗(会影响高光的亮度,但不会影响高光的范围)。

漫反射:blinn-phong模型中实际上指代的是物体表面对光的吸收率。吸收率越高则物体表面越暗。当然也可以反过来说是对光的反射率。具体到vxl里可以理解为非背光处亮度(会影响非背光处的亮度,对背光处则完全无影响)。

环境光:物体背光处的光,这部分完全没有受到光源直射,此处的颜色之所以会被观测到是因为其他物体反射了一部分光到这里,再反射进入视角(相机)。具体到vxl里可以理解为整体亮度(会同时影响高光和漫反射的亮度)。

上述的亮度既可以理解为一个物理概念,即更高的rgb值,也可以理解为一个逻辑概念,即调用更高的section。

Vpl分为32个section,这32个section意味着某个颜色可以变成同一色盘上的另外32种颜色。假设A颜色的32个section中,第16个secion为B颜色,当游戏通过计算得到此时应该调用A颜色的第16个section时,则在绘制时不取用A颜色而是取用B颜色。一般而言,section的序号越小,该section中的rgb值也越低(越暗),反之则越高(越亮)。

如果你还看不懂,那就把鬼蝉大佬的这段话读一遍,还不懂就再读一遍。

备注:

关于vpl的研究最早应该可以追溯到2006年vk的这篇贴子。

https://ppmforums.com/topic-11950/about-voxelsvpl/

而后在2011年,PPM上有一则帖子关于vpl的讨论。

https://ppmforums.com/topic-30026/voxelvpl-research/