本文 gitbook 地址,可获得更佳阅读体验: https://app.gitbook.com/@galaxyzeta/s/unity3d/
制作竞技类游戏的时候往往会用到 Team Coloring,需要给同一个模型 / Sprite 图的一部分加上队伍颜色。
双Sprite方法
- 两张 Sprite,一张表示不变的部分,另一张表示需要变更的部分。
- 变更部分使用白色遮罩,在渲染时,同时渲染这两张 Sprite,对于遮罩,调整 SpriteRenderer 的 Color 属性,即可变更为任意颜色。
这种方法的缺点:
- 绘制像素画时,需要额外画一张遮罩,比较麻烦。
- 由于 SpriteRenderer 只能绘制一张 Sprite,两个 Sprite 的绘制就要放到两个物体中。
- 如果加上动画,需要维护两个 Animator。
因此决定采用 Shader 方法实现,具体参考了这篇文档:
https://gamedevelopment.tutsplus.com/tutorials/how-to-use-a-shader-to-dynamically-swap-a-sprites-colors–cms-25129
Shader 方法
实现思路比较简单,使用两张 Texture,一张是原本的 Sprite Texture,另一张是用于替换的查找表(LUT),这张 Texture 是用代码生成的。 为了方便起见,我使用了 Universal Render Pipeline(URP)作为默认渲染管线,因为它提供了基于 Shader Graph 的着色器编写,使用起来比较方便。 Shader Graph 如下:
原理:
- LUT 是一张 1 x 256 大小的 2D RGBA 图像。
- 原有 Sprite 每个像素点的 R 值作为 LUT 查找索引。
- 在片元着色阶段,遍历每一个像素点,使用该点的 Red 值在 LUT 中查找(图中的 Vector2 --> UV 部分)。如果 LUT 中的点对应的 Alpha = 1,表示进行替换,反之不进行替换。对于是否替换可使用 Lerp 节点进行操作,将 LUT alpha 作为 Lerp 的插值进度即可。
- 最终输出需要保持原有图像的 Alpha 值。
Shader 完成后,开始编写相关代码,如下所示:
using UnityEngine;
public class TeamColoring : MonoBehaviour {
private SpriteRenderer spriteRenderer;
public TeamEnum team;
public int replaceColorRedValue = 118;
void Start() {
spriteRenderer = GetComponent<SpriteRenderer>();
Texture2D lut = InitLUT();
Color col = Gamemanager.instance.GetTeamColor(team);
lut.SetPixel(replaceColorRedValue, 0, col);
lut.Apply();
spriteRenderer.material.SetTexture("_Lut", lut);
}
public Texture2D InitLUT() {
Texture2D lut = new Texture2D(256, 1, TextureFormat.RGBA32, false, false);
lut.filterMode = FilterMode.Point;
for(int i=0; i<256; i++) {
lut.SetPixel(i, 0, new Color(1,1,1,0));
}
return lut;
}
}
|