c# - 如何从 SpriteAtlas 获取原始纹理以在着色器中用作 alpha 蒙版?
问题描述
我有一个问题,我需要帮助来解决它。
我尝试通过自定义着色器和附加纹理作为蒙版动态着色精灵的某些部分。这不是问题,我很容易解决。
屏幕以便更好地理解:
这是真正的实现,这张图片的颜色混合是通过着色器、精灵和蒙版实现的。
但是我被迫使用地图集来节省 RAM,因为必须同时加载许多精灵(每个不同单元的 3 个状态和 5 个方向)。这是引起问题的原因。当我尝试在编辑模式下(通过使用 ExecuteInEditMode)执行此操作时,一切正常。但是当我按下“播放”按钮时,一切都崩溃了。
它的样子:
据我了解,问题是当我按下“播放”时,地图集就建立了。所以当我从中得到精灵时,我会成功地得到它。但是当我尝试从 Sprite 获取纹理以将其设置为 Shader 时,我得到了很大的纹理(完整的图集)。着色器对这张纸上的实际位置一无所知,因为像素需要着色。
所以我的问题是:如何从精灵中获取“小”纹理以将其设置为着色器?
我如何将“蒙版”设置为着色器:
public void UpdateMask(Texture tex)
{
//Debug.LogFormat("UpdateMask {0}", tex);
m_SRenderer.GetPropertyBlock(m_SpriteMbp);
m_SpriteMbp.SetTexture("_Mask", tex);
m_SRenderer.SetPropertyBlock(m_SpriteMbp);
}
一些着色器的部分:
Properties
{
[PerRendererData] _MainTex("Sprite Texture (RGB)", 2D) = "white" {}
[PerRendererData] _Mask("Alpha (A)", 2D) = "white" {}
_FriendlyColor("FriendlyColor", Color) = (1,1,1,1)
_EnemyColor("EnemyColor", Color) = (1,1,1,1)
_NeutralColor("NeutralColor", Color) = (1,1,1,1)
_Intencity("BlendingIntencity", Range(0, 1)) = 0.5
[PerRendererData] _IsFriendly("IsFriendly", Float) = 0
[PerRendererData] _IsHighlight("Outline", Range(0, 1)) = 0
[PerRendererData] _HighlightColor("Outline Color", Color) = (1,1,1,1)
}
fixed4 frag(v2f IN) : COLOR
{
fixed4 mainTex = tex2D(_MainTex, IN.texcoord) * IN.color;
fixed4 alphaMask = tex2D(_Mask, IN.texcoord) * IN.color;
fixed4 output;
fixed4 blendColor;
if (alphaMask.a > 1.0e-6)
{
if (_IsFriendly == 4)
{
blendColor = fixed4(_NeutralColor.r, _NeutralColor.g, _NeutralColor.b, alphaMask.r);
}
else
{
if (_IsFriendly == 1)
{
blendColor = fixed4(_FriendlyColor.r, _FriendlyColor.g, _FriendlyColor.b, alphaMask.r);
}
else
{
blendColor = fixed4(_EnemyColor.r, _EnemyColor.g, _EnemyColor.b, alphaMask.r);
}
}
output = BlendOverelay(mainTex, blendColor * _Intencity);
}
else
{
output = mainTex;
output.rgb *= output.a;
}
if (_IsHighlight != 0)
{
fixed4 blendedColor = BlendAdditive(output, _HighlightColor);
blendedColor.a = output.a;
blendedColor.rgb *= output.a;
output = blendedColor;
}
return output;
}
解决方案
你需要告诉精灵渲染器它在图集中的位置以及图集有多大,以便它可以将IN.texcoord
图集空间中的UV转换为精灵空间中对应的UV。然后,您可以使用精灵空间 UV 从 alpha 贴图中采样
在 C# 中,将图集偏移和比例信息设置为例如_AtlasPosition
:
public void UpdateMask(Texture tex)
{
//Debug.LogFormat("UpdateMask {0}", tex);
m_SRenderer.GetPropertyBlock(m_SpriteMbp);
m_SpriteMbp.SetTexture("_Mask", tex);
Vector4 result = new Vector4(sprite.textureRect.position.x, sprite.textureRect.position.y, sprite.textureRect.size.x, sprite.textureRect.size.y)
m_SpriteMbp.SetVector("_AtlasPosition", result)
m_SRenderer.SetPropertyBlock(m_SpriteMbp);
}
在着色器中,计算精灵空间中的当前 UV,并使用它来采样_Mask
:
fixed4 frag(v2f IN) : COLOR
{
fixed4 mainTex = tex2D(_MainTex, IN.texcoord) * IN.color;
// multiply both the position offset and size by the texel size to bring them into UV space
float4 atlasOffsetScale = _AtlasPosition * _MainTex_TexelSize.xyxy;
// apply UV position offset and scale, sample from alpha mask
fixed4 alphaMask = tex2D(_Mask, (IN.texcoord - atlasOffsetScale.xy) / atlasOffsetScale.zw) * IN.color;
fixed4 output;
fixed4 blendColor;
// ...
_MainTex_TexelSize
如果您还没有声明,则必须在着色器中声明。
如果您使用紧密包装,这将不起作用。对于 Sprite Packer,您需要DefaultPackerPolicy
在 sprite packer 中指定或在包装标签中指定 [RECT]。如果您正在使用SpriteAtlas
,则需要禁用Tight Packing
.
代码来自统一论坛上的这个线程
推荐阅读
- sql - 我想要三个表的左外连接
- python - 时间序列预测的自相关图python解释?
- python - 如何使用滚动在python中加载弹性数据?
- windows - 搜索 word 文档 (.rtf) 并更改图像分辨率的脚本
- python - 如何将变量导入到我在 python 中保存函数的文件?
- r - 数据转换为邻接矩阵
- python - 运行时错误:“未实现 op 'type_as' 的 PyTorch 转换功能。” 将 PyTorch 模型转换为 CoreML 时
- r - 使用 DT 表进行可编辑计算,表内有下拉列表 R 闪亮
- angular - “错误:目标入口点缺少依赖项”在 Angular 12 应用程序中使用 js 库(但它在 Angular 8 应用程序中有效)
- swift - 单击另一个按钮时如何更改一个按钮的操作(SwiftUI)?