图形数据在许多地方被使用,最常见的莫过于ThingDef,而在讲述到使用图形数据的地方时,我不会再次阐述图形数据的内容,而希望大家能够回过头来看这篇文章。图形数据提供了一个图像的贴图,绘制大小等数据,我们今天来学习其各项参数。
<graphicData>
<texPath>Things/Building/Power/SolarCollector</texPath>
<graphicClass>Graphic_Single</graphicClass>
<drawSize>(4,4)</drawSize>
<shadowData>
<volume>(3.5,0.75,3.4)</volume>
<offset>(0,0,0)</offset>
</shadowData>
<damageData>
<rect>(0,0.6,4,2.8)</rect>
</damageData>
</graphicData>
太阳能发电机的贴图数据。
先介绍最简单的几个,
texPath:贴图路径
graphicClass:渲染类型
drawSize:绘制大小
此三者最常用
下面是具体分析和用法,请按需求参阅。
>>>texPath:贴图路径。
如mod文件夹/Textures/Weapons/Baguette
则为<texPath>Weapons/Baguette</texPath>
请注意,根据graphicClass的不同,有时候路径要求指向一个png文件,有时则要求指向一个文件夹。
>>>graphicClass:图形的class
它决定了一个图形应该以怎么样的方式被读取,怎么样的形式被渲染。常用的有以下:
Graphic_Single:单贴图
Graphic_Multi:区分东南西北四个朝向的贴图
Graphic_Random:随机贴图
Graphic_Cluster:随机贴图+随机偏移
Graphic_Flicker:火焰的动态贴图
Graphic_StackCount:可堆叠物品的贴图
Graphic_Appearances根据材料不同改变纹理的贴图
下面是具体分析和使用方法,大家可以根据需求选择阅读或直接跳过。
Graphic_Single:最常用的一个,渲染单图像。路径要求是一个png文件。
Graphic_Multi:也是常用的,渲染四向贴图。常用于可以调整朝向的建筑、以及生物等。路径要求是“一类”png文件:
以机甲举例,不难发现路径指向的位置并没有对应的front.png,取而代之的是另外三个png文件。这就是“一类”的含义。每个png文件有自己的后缀,为_east,_north,_south,_west。四个png文件共同组成了整个图形,它们将会在渲染对象朝向不同方向时被调用并呈现。其中,_east和_west由于左右对称,在缺少其中一个的情况下,游戏将会自动取另一个的镜像作为代替,这也是例子中有了_east就没有_west的原因;而在东朝向与西朝向的贴图需要区分开的时候,就得两个都指明出来。
Graphic_Terrain:用于地板的渲染,用法与Single类型相同。其在渲染地板时会被自动调用,游戏Defs内没有任何实例。
如图所示,地板的贴图由16x16的块构成,游戏渲染地板时将会从中选择一块来渲染。
Graphic_Collection:它不能直接写在defs内,它代表的是“渲染多贴图的物品”。写在这里是为了讲解其读取方式。
其路径要求指向一个文件夹,然后该文件夹内的文件按照文件名,按A~Z进行排序。通常情况下使用该类型,我们会使用完全相同的名字加上一个A~Z的大写字母后缀来使其排序,正如例子中做的这样。要十分注意,路径指向的要写文件夹名字,而不是文件夹内的文件名字,只是通常情况下文件夹名字与文件名字相同罢了。
以下四种都属于Graphic_Collection,路径读取方法相同,且这些类型可以直接写在Defs内
Graphic_Random:属于Graphic_Collection的一种,用于渲染同一个物体的随机贴图。这个随机种子基于物品ID,也就是说一个物品在生成后,其对应的贴图就不会再变化了。
Graphic_Cluster:属于Graphic_Collection的一种,用于血迹、灰尘等“脏东西”。他们渲染时从文件夹内的所有文件中随机挑选一个作为贴图。与Random不同,其的随机是使用的简单随机器,也就是说你在重新加载文档后,它的样子就会重新随机生成一次,并且,其渲染位置并不像其他的类型那样居中,而是会有一个随机的偏差。
Graphic_Flicker:属于Graphic_Collection的一种,用于渲染火焰。
渲染时将会在这些贴图间按时间依次播放,形成火焰的动态效果。并且火焰的渲染大小也是由Flicker读取的。可惜其播放每帧停留的时间是固定的,实际上难以用于做动态贴图。
Graphic_StackCount:属于Graphic_Collection的一种,用于渲染可以堆叠的物品。
其中,排序的第一个文件固定为堆叠数为1时的贴图;排序的最后一个文件固定为堆叠满的贴图,其余中间项则按照堆叠的百分比来决定。由于原版中一般只有三个文件,所以堆叠数大于1且未堆满时,就固定是第2个文件【如例子中为WoodLog_b】。且假设有ABCDE四个文件,那么A代表1个堆叠,B应该代表1~33%,C代表34%~66%,D代表67%到99%,E则代表100%的满堆叠
Graphic_Appearances:用于墙体和围栏。大家注意墙和围栏在不同材料下纹理是不同的。
这个路径仍然要求指向一个文件夹,在读取时按后缀来读取。如石砖纹理后缀为Bricks,就只读取Wall_Atlas_Bricks。
嗯,以上就是常用的graphicClass类型
>>>shaderType:非必须参数,着色器类型
由于本人在渲染方面没怎么研究...我就不详细阐述其具体工作原理,仅放一些常用的类型作为参考和教学。
Cutout开头的着色器类型属于同一族,他们均不会读取透明度,且会对贴图边缘进行修正。
Cutout:最简单的着色器,无透明度。在不写shaderType的情况下默认为此。
CutoutComplex:此着色器可以自动填充颜色,无透明度。规律如下:
在使用时,附带一个同名且有后缀_m的图片,称为蒙版。蒙版中颜色为红色的部分就是自动填充颜色的部分。最常见的地方在于可以变换材料的武器,如图中的锈刀,刀柄部分希望保持灰色,而刀刃部分根据制作材料变换颜色。常用的蒙版中,红色的值是(255,0,0),而在实际应用中,我们可以用更暗的红色,如(127,0,0),此时填充颜色就会先乘该值(即x(127/255))再进行填充,也就是填充颜色的比重下降。
可以自动填充两种颜色,颜色一是红色,颜色二则是绿色,他们分别进行渲染。实际上,这里是通过颜色通道进行识别的,所以你在蒙版中使用了(255,255,0)时,同一个位置就会被着色两次。原版中,床就是使用了两个自动填充色。颜色一为床的材料,颜色二为床的床单,如医疗床是蓝色,囚犯床是橙色。
值得注意的是与Graphic_Multi混用的时候,后缀是_southm这样的,而非_south_m或_m_south。在床那里就是例子。
Transparent开头的属于同一族,他们会读取透明度,不会对贴图边缘进行修正。且Transparent的覆盖问题十分迷幻,使用时要多加注意。
Transparent:简单着色器
TransparentPostLight:该着色器将会无视光照系统,即任意光照下均显示原贴图的亮度。
>>>shaderParameters:非必须参数,着色器参数,需要有unity基础的人使用。故不做分析。
>>>color:非必须参数,颜色一,将会覆盖材料的颜色。详见上文CutoutComplex部分。
>>>colorTwo:非必须参数,颜色二。
>>>drawSize:非必须参数,默认为1或(1,1)。单位是格子。
它决定了该贴图的渲染大小,如床的大小是(2,2),在长宽相等的情况下可以简写为一个数字。注意区分该项与建筑物中的size,size指的是实际碰撞体积,而drawSize是贴图渲染大小,它们俩是完全独立的,比如一个9x9的全息投影,占地可以只有1x1
>>>drawOffset:非必须参数,渲染偏移,格式为(x,y,z),x以向右为正方向,z以向上为正方向,y决定了这个东西与其他东西在渲染时的图像覆盖问题。
>>>drawOffsetNorth、drawOffsetEast、drawOffsetSouth、drawOffsetWest:非必须参数,渲染偏移,格式为(x,y,z),用法与drawOffset相同,但只在固定朝向时生效,如drawOffsetSouth仅在事物朝下时生效。它们生效时会覆盖drawOffset。
>>>onGroundRandomRotateAngle:非必须参数,仅用于物品(武器、衣服什么的),填写一个小数,实际使用时贴图会发生相应的随机旋转,如一把武器的改参数为360,那么武器掉落在地上时就会有0~360°的随机角
>>>drawRotated:非必须参数,默认为true。在false的情况下,渲染时将视其永久为朝北(朝上)
>>>allowFlip:非必须参数,允许翻转,默认为true。在false的情况下无法通过朝东和朝西的其中一个来自动生成另一个
>>>flipExtraRotation:非必须参数,填写小数。意为翻转后额外的旋转角(因为原有的旋转角也会受翻转影响)
>>>allowAtlasing:非必须参数,默认值为true。在代码里我没发现任何调用到这个数据的地方,应该是作者忘记删或者忘记加效果了。
>>>renderQueue:非必须参数,填整数,意为渲染队列。擅长unity的可以自己玩玩。这里不做学习。
>>>shadowData:非必须参数,影子数据,是一个复合数据
volume,体积,填(x,y,z)
offset,影子中心相对于物体中心的偏移量,填(x,y,z)
>>>damageData,非必须参数,受损贴图数据,是一个复合数据
rect,格式为(x,y,width,height),四个参数均为数字,可以小数。x,y指的是整个受损贴图距离整体左下角的距离,width,height为水平长度和竖直长度。假设我们的原建筑是1x1,希望整个建筑被受损贴图覆盖则为(0,0,1,1)
rectN、rectE、rectS、rectW,非必须参数,用法与drawOffset相同,但只在固定朝向时生效。如rectS仅在事物朝下时生效。它们生效时会覆盖rect。
scratches,非必须参数,为一个list,内填刮痕贴图的路径。生效时似乎会在物体的随机部分渲染刮痕,但原版内未找到例子。
cornerTL、cornerTR、cornerBL、cornerBR、edgeLeft、edgeRight、edgeTop、edgeBot:均填一个贴图路径。这些贴图将在建筑的不同位置呈现,假设一个建筑3x3,那么对应关系如下
>>>linkType:非必须参数,填一种连接类型,用于电缆、墙体等可连接建筑。这里用栅栏的贴图举例:
(透明的是蓝图,蓝图部分等到建筑章节再分析,有两种栏杆是因为金属栏杆的贴图纹理不同)
连接类型有:
(感谢国人作者Zayl提供的预览图帮助)
None,不填默认为此,不使用连接
嗯...就是这样。
Basic,典型的连接
CornerFiller,注意观察右下角3x4的部分,除最外面暴露的一圈正常渲染以外,其他部分均自动被纯色填充。游戏中的墙体就是使用了这个,这使得两格厚及以上的墙之间不会产生缝隙,看起来更加舒服。
Transmitter、TransmitterOverlay,原版中没有任何实例,使用时与Basic似乎没什么区别。通过代码解析可以推断其会与“能够传输电线且无法连接的物体”产生额外连线,但我尝试写了这样的一个物体却没发现有什么效果,可能是我操作失误吧。不做分析。
Asymmetric,“非对称连接”,配合GraphicData中的asymmetricLink一起使用,稍后我们会分析。
>>>linkFlags:连接标签,填写方法比较特殊,既可以当作简单参数填,也可以当List。
游戏原版中所有实例都是作为List,即使是单元素。所以无所谓啦(
内容可以填以下的几个东西。当两个东西的所有linkFlags中存在相同项,这两个东西就可以连接。
None:不连接
MapEdge:与地图边缘连接
Rock:石头、墙体、栅栏
Wall:墙和栅栏
Sandbags:沙袋
PowerConduit:电缆
Barricade:路障
Fences:栅栏
>>>asymmetricLink:非必须参数,配合linkType.Asymmetric一起使用。复合结构,有以下内容:
linkFlags:与上文的linkFlags用法相同,但此处生效时会触发“非对称”连接
linkToDoors:是否与门相连
drawDoorBorderEast、drawDoorBorderWest 当与门相连时触发特殊变化,有以下参数:
color:颜色,(r,g,b)
size:渲染尺寸乘数,(x,y),x向右,y向上
offset:渲染中心的位置偏移,(x,y,z),x向右,z向上,y是图层覆盖问题。
<linkType>Asymmetric</linkType>
<linkFlags>
<li>Fences</li>
</linkFlags>
<asymmetricLink>
<linkFlags>
<li>Wall</li>
<li>Rock</li>
</linkFlags>
<linkToDoors>true</linkToDoors>
<drawDoorBorderEast>
<color>(0,0,0)</color>
<size>(0.04, 0.77)</size>
<offset>(0.5, 0, -0.08)</offset>
</drawDoorBorderEast>
<drawDoorBorderWest>
<color>(0,0,0)</color>
<size>(0.04, 0.77)</size>
<offset>(-0.5, 0, -0.08)</offset>
</drawDoorBorderWest>
</asymmetricLink>
原版例子是栅栏,其在与门相连时,门左右两边的栅栏会有特殊的尺寸和位置变换,来使其与门的连接更加平和。