shader编程其实是对GPU编程,我们的shader编程不像untiy脚本对CPU编程那样,它需要简介,简单。接下来做几个很有意思的shader
Shader "Custom/CartoonShader" {
Properties {
_BorderColor("BorderColor",Color)=(0.6,0,0,1)
_CenterX("CenterX",float)=.5
_CenterY("CenterY",float)=.5
_Distance("Distance",float)=0
_Background("Background",2D)="black"{}
//属性代码块主要unity编辑面板和CG交互。
}
CGINCLUDE
#include "UnityCG.cginc"
float4 _BorderColor;
float _CenterX;
float _CenterY;
float _Distance;
sampler2D _Background;
float4 _Background_ST;
//根据属性块中的属性来定义相应的变量。
struct input
{
float4 vertex:POSITION;
float2 uv:TEXCOORD;
};
struct output
{
float4 pos:SV_POSITION;
float2 uv:TEXCOORD0;
};
output vert(input i)
{
output o;
o.pos=mul(UNITY_MATRIX_MVP,i.vertex);
o.uv.xy = TRANSFORM_TEX(i.uv, _Background);
#if !UNITY_UV_STARTS_AT_TOP//主要区分openGL的屏幕原点和Dx屏幕原点。
o.uv.y = 1 - o.uv.y;
#endif
return o;
}
float4 frag(output o):COLOR
{
#if !UNITY_UV_STARTS_AT_TOP//同样这句注释意思和上面一样
float realY = _ScreenParams.y - _CenterY;
#else
float realY = _CenterY;
#endif
float distance = length (half2(o.uv.x * _ScreenParams.x, o.uv.y * _ScreenParams.y) - half2(_CenterX, realY));
float4 screenColor = float4(0,0,0,0);
float delta = distance - _Distance;
fixed4 maskColor = lerp(_BorderColor, tex2D(_Background, o.uv.xy), clamp(delta / 5, 0, 1));
return lerp(screenColor, maskColor, (clamp(delta, -15, 0) / 15) + 1);
//这里代码就只有2个插值了,应该很好理解
}
ENDCG
SubShader
{
Tags { "Queue" = "Transparent" }
LOD 200
Lighting Off
pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
ENDCG
Blend SrcAlpha OneMinusSrcAlpha
}
}
FallBack "Diffuse"
}
这里就是一个类似于技能冷却的效果。
Shader "Custom/CoolShader" {
Properties {
_BkColor("BkColor",Color)=(0.6,0,0,1)
_CenterX("CenterX",float)=.5
_CenterY("CenterY",float)=.5
_Angle("Angle",float)=0
_Constant("Constant",float)=0
_Background("Background",2D)="black"{}
}
CGINCLUDE
#include "UnityCG.cginc"
float4 _BkColor;
float _CenterX;
float _CenterY;
float _Angle;
float _Constant;
sampler2D _Background;
float4 _Background_ST;
struct input
{
float4 vertex:POSITION;
float2 uv:TEXCOORD;
};
struct output
{
float4 pos:SV_POSITION;
float2 uv:TEXCOORD0;
};
output vert(input i)
{
output o;
o.pos=mul(UNITY_MATRIX_MVP,i.vertex);
o.uv.xy=TRANSFORM_TEX(i.uv,_Background);
#if !UNITY_UV_STARTS_AT_TOP
o.uv.y = 1 - o.uv.y;
#endif
return o;
}
float4 frag(output o):COLOR
{
#if !UNITY_UV_STARTS_AT_TOP
float realY=_ScreenParams.y-_CenterY;
#else
float realY = _CenterY;
#endif
float2 vector1 =normalize(float2(_CenterX,0));
float2 vector2 =normalize(float2(o.uv.x*_ScreenParams.x,o.uv.y*_ScreenParams.y)-float2(_CenterX,realY));
float angle=acos(dot(vector1,vector2));
if(_Angle<=_Constant)
{
if(angle<_Angle && vector2.y>=0)
{
return tex2D(_Background,o.uv.xy);
}
else
{
return _BkColor;
}
}
else if(_Angle>_Constant)
{
if(angle<(2*_Constant-_Angle)&&vector2.y<0)
return _BkColor;
else
{
return tex2D(_Background,o.uv.xy);
}
}
else
{
return _BkColor;
}
}
ENDCG
SubShader
{
Tags { "Queue" = "Transparent" }
LOD 200
Lighting Off
pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
ENDCG
Blend SrcAlpha OneMinusSrcAlpha
}
}
FallBack "Diffuse"
}
这里我这个shader写的有的不好的,因为用了大量的条件判断语句,这shader里面这应该是绝对避免的。但是如果我们不用条件语句就无法完成这样的效果,如果是这样的话,我建议你还是勉强的用一下,如果可以用UnityCG.cginc库里面的函数的话,那就不用这种繁琐的条件语句,大量的条件数据会降低GPU的执行效率,因为GPU是并行的,等于它还要等待判断结果结束,才可以跳到下一个条件中去,这会大大降低GPU的处理效率的。这里我就sb一把了。强烈建议不要用条件语句!强烈建议不要用条件语句!强烈建议不要用条件语句!
Shader "Custom/Pixelate" {
Properties {
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Scale ("1/单位格子的大下", Range(0,350)) = 50
}
CGINCLUDE
#include "UnityCG.cginc"
sampler2D _MainTex;
half4 _MainTex_ST;
half _Scale;
fixed4 _Color;
struct output
{
half4 pos:SV_POSITION;
half2 uv:TEXCOORD0;
};
output vert(appdata_full i)
{
output o;
o.pos=mul(UNITY_MATRIX_MVP,i.vertex);
o.uv.xy=TRANSFORM_TEX(i.texcoord,_MainTex);
return o;
}
half4 frag (output o):COLOR
{
half ratio= 1/_Scale;
half2 PixpleUV=half2(ratio*ceil(o.uv.x/ratio),ratio*ceil(o.uv.y/ratio));
return tex2D(_MainTex,PixpleUV)*_Color;
}
ENDCG
SubShader
{
Tags { "RenderType"="Opaque" }
Lighting Off
LOD 200
GrabPass { "_ScreenContent" }
Pass
{
CGPROGRAM
#pragma fragment frag
#pragma vertex vert
ENDCG
}
}
FallBack "Diffuse"
}
这个着色器代码的主要作用是暗中马赛克的效果,用来模糊图片。从上面的shader代码可以看出来其实写这种着色器代码不是很难吧,难点是在你不知道一个效果的原理,当我告诉你这个马赛克效果原理的时候你一定会觉得很简单,我们知道之所以图片会清晰是每个像素的颜色会不同,即使是相近像素也会用插值进行过度,如果我把10*10这么大个像素快都贴一种颜色,你看起来不就迷糊了嘛。这些只是shader的简单
当然这样还是显示不出来,这里还要配合GL库里面的方法来实现。这里先简介几个shader。