问题
- 着色器行为在大多数情况的预期下,但是使用Masked UI组件,SetColorArray/SetColor/Set*的数值不会传递到着色器。
- 当被遮罩的时候,着色器似乎忽略通过脚本发送的自定义参数
原因
遮罩用的是GetModifiedMaterial方法来计算运用模板缓冲出遮罩的像素。忽略通过脚本发送的所有自定义参数,因为应用通过默认脚本的自定义着色器。当运用Setter函数(像SetColorArray)设置参数,它们会瞬间设定。在屏幕上渲染像素之前,遮罩组件在每一个遮罩物体对象会调用GetModifiedMaterial方法,将使用材质的默认设置。它会忽略自定义设置。
解决方案
为了解决问题,您必须扩展Image类(UI.Image或UI.RawImage)并重写GetModifiedMaterial方法。通过这件事,首先应用遮罩来观察可用的像素,然后把自定义值发送到着色器。例如,通过每帧创建高光遮罩效果(运用自定义着色器)的菜单按钮,方法如下:
- 创建一个帧(Canvas画布)并把按钮放在这里。
- 创建接受高光颜色自定义参数的着色器。
Shader "Test/CustomShader"
{
Properties
{
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 150
CGPROGRAM
#pragma surface surf Lambert
sampler2D _MainTex;
fixed4 _Color;
struct Input
{
float2 uv_MainTex;
};
void surf (Input IN, inout SurfaceOutput o)
{
half4 tmpTexColor = tex2D (_MainTex, IN.uv_MainTex);
// Albedo comes from a texture tinted by color
half4 color = tmpTexColor * _Color;
o.Albedo = color.rgb;
o.Alpha = color.a;
}
ENDCG
}
FallBack "Mobile/Diffuse"
}
- 创建命名为“CustomMaterial”的材质,此材质是使用上面创建的着色器。
- 将材质附到Button组件。bMaterial会执行脚本的着色器。
- 将Mask组件附到frame container。
- 创建命名为CustomRawImage.cs的脚本文件,脚本如下:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class CustomRawImage : RawImage
{
public override Material GetModifiedMaterial(Material bMaterial)
{
// Apply the mask.
Material tmp = base.GetModifiedMaterial (bMaterial);
// Pass your custom shader parameters.
tmp.SetColor("_CustomColor", Color.red);
// return the material with Mask + Customs applied.
return tmp;
}
}
- 将所有按钮的Image/RawImage组件替换成CustomRawImage脚本组件。
属性bMaterial是附到每一个按钮的材质。因为它是高光着色器效果,你可以通过另一个需要不同的材质来替换它。
更多信息
- https://docs.unity3d.com/Manual/MaterialsAccessingViaScript.html
- https://docs.unity3d.com/ScriptReference/Material.html