先看效果图:背景图和按钮等都能置灰
理解原理:在相机渲染成像的最后一帧,unity会回调OnRenderImage函数,在回调函数里面,将源Texture加上Shader的混合,输出到新Texture,则成最终屏幕效果。
使用步骤:
- 新建材质球,将shader赋值给材质球。
- 新建c#代码,挂载到Camera上,并赋值材质球。
- 最后就可以通过调整材质球的Inspector中的属性值,查看置灰效果。(这步可根据自己项目,自行代码控制)。
代码部分:
Shader代码:
Shader "Sevol/ScreenGray" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_grayColor("color",Color)= (1,1,1,1)//自定义灰度颜色
}
SubShader {
Pass {
ZTest Always Cull Off ZWrite Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float3 _grayColor;
struct v2f {
float4 pos : SV_POSITION;
half2 uv: TEXCOORD0;
};
v2f vert(appdata_img v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.texcoord;
return o;
}
fixed4 frag(v2f i) : SV_Target {
fixed4 renderTex = tex2D(_MainTex, i.uv);
float gray = dot(renderTex.rgb, _grayColor);//置灰后的灰色值
fixed4 targetColor = fixed4(gray, gray, gray,renderTex.a);//只接受灰度rgb,alpha使用源图像值
fixed4 finalColor = lerp(renderTex,targetColor,1);//将原来的颜色与灰色做插值运算
return finalColor;
}
ENDCG
}
}
Fallback Off
}
?C#代码:(需要挂载到Camera上,且Canvas不能是Overlay模式,因为Overlay模式会在所有渲染完成后,再执行屏幕输出,那么OnRenderImage就不会起作用)
using UnityEngine;
public class ScreenGray : MonoBehaviour
{
public Material curMaterial;
//屏幕后处理函数,设置shader参数
void OnRenderImage(RenderTexture sourceTexture, RenderTexture destTexture)
{
if (curMaterial != null)
{
Graphics.Blit(sourceTexture, destTexture, curMaterial);
}
else
{
Graphics.Blit(sourceTexture, destTexture);
}
}
}
参考文档:
官网文档 OnRenderImage函数:
MonoBehaviour-OnRenderImage(RenderTexture,RenderTexture) - Unity 脚本 API
官方文档 Graphics.Blit 函数:
Graphics-Blit - Unity 脚本 API
|