0.本文示例代码地址
3D模型的外放光效果相对来说容易实现一些。这篇文章描述了如何实现2D图片的外发光效果。
思路:在片元着色器中,进行一个“模糊”操作。针对当前像素 p 进行纹理采样,并做判断:
- 若采样结果 alpha 值为0,则 p 为透明像素,此时根据一个制定长度的“十字格”来取 p 周围像素的 alpha 值并进行平均,得到 p 的 alpha 值,rgb 值为参数设置的外发光颜色值。
- 若采样结果 alpha 非 0,则p非透明像素,直接返回采样结果颜色。
代码如下:
Shader "Custom_Shader/Outlight"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_LightColor ("Light Color", Color) = (1.0, 1.0, 1.0, 1.0)
_Size ("Size", Int) = 1
}
SubShader {
Blend SrcAlpha OneMinusSrcAlpha
CGINCLUDE
#include "UnityCG.cginc"
struct v2f {
float4 pos : SV_POSITION;
float2 uv: TEXCOORD0;
};
sampler2D _MainTex;
float4 _MainTex_ST;
half4 _MainTex_TexelSize;
float4 _LightColor;
int _Size;
ENDCG
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
v2f vert(appdata_img IN)
{
v2f OUT;
OUT.pos = UnityObjectToClipPos(IN.vertex);
OUT.uv = TRANSFORM_TEX(IN.texcoord, _MainTex);
return OUT;
}
fixed4 frag(v2f IN) : SV_Target
{
fixed4 color = tex2D(_MainTex, IN.uv);
fixed4 c = _LightColor;
float sum = tex2D(_MainTex, IN.uv).a;
for (int i = 1; i <= _Size; i ++) {
sum += tex2D(_MainTex, IN.uv + _MainTex_TexelSize.xy * half2(i, 0)).a;
sum += tex2D(_MainTex, IN.uv + _MainTex_TexelSize.xy * half2(-1 * i, 0)).a;
sum += tex2D(_MainTex, IN.uv + _MainTex_TexelSize.xy * half2(0, 1 * i)).a;
sum += tex2D(_MainTex, IN.uv + _MainTex_TexelSize.xy * half2(0, -1 * i)).a;
}
c.a = sum / (4 * _Size + 1);
return step(0.1, color.a) * color + step(0.1, 1-color.a) * c;
}
ENDCG
}
}
}
效果:
外发光
这个方法在某些特殊的像素处理效果不太好,比如图中刀尖的部分,可以考虑将“模糊核”由十字格改成“圆形”来进行模糊,效果会好一些
将上面代码中的片段着色器改成如下代码
fixed4 frag2(v2f IN) : SV_TARGET
{
fixed4 color = tex2D(_MainTex, IN.uv);
fixed4 c = _LightColor;
float sum = tex2D(_MainTex, IN.uv).a;
for (int i = -_Size ; i <= _Size; i ++) {
for (int j = -_Size; j <= _Size; j ++) {
if (abs(i) != abs(j))
{
sum += tex2D(_MainTex, IN.uv + _MainTex_TexelSize.xy * half2(i, j)).a;
}
}
}
c.a = sum / (_Size * _Size * 2);
return step(0.1, color.a) * color + step(0.1, 1-color.a) * c;
}
得到效果
外发光优化
网友评论