做了一个麻将高光和阴影的材质,第一个shader,纪念一下~直接贴代码
// 高光在第一个pass,阴影在第二个pass
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Custom/Unlit"
{
Properties
{
//_Instensity("Shineness", Range(0.5,2.0)) = 1.0 //光照强度
_MainTex("Main Tex",2D) = "white"{}//纹理贴图
_Color("Color",Color) = (1,1,1,1) //模型颜色
_ShadowColor("ShadowColor",Color)=(1,1,1,1) //阴影颜色
_ShadowFallOff("ShadowFallOff", Range(0.5,2.0)) = 1.0 //阴影衰减
_LightDir("LightDir",Vector) = (1,1,1,0) //光照方向
_Specular("Specular",Color)=(1,1,1,1) //高光颜色
_Gloss("Gloss",Range(8.0,256))=20 //高光范围
_ShadowPlane ("Shadow Plane", Range(-10,10)) = 0
}
SubShader
{
Tags{ "RenderType" = "Transparent" "Queue" = "Transparent" }
Pass {
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
fixed4 _Color; //麻将颜色
sampler2D _MainTex; //贴图
float4 _MainTex_ST; //纹理属性
fixed4 _Specular; //高光颜色
float _Gloss; //高光范围
struct a2v { //顶点着色器的输入
float4 vertex : POSITION; //模型顶点坐标
float3 normal : NORMAL; //模型空间法线方向
float4 texcoord : TEXCOORD0; //填充模型第一套纹理坐标
};
struct v2f { //顶点着色器输出
float4 pos : SV_POSITION; //顶点在裁剪空间中的位置
float2 uv : TEXCOORD0; //该顶点的第一组纹理坐标uv
float3 worldPos : TEXCOORD1;
float3 worldNormal : TEXCOORD2;
};
v2f vert(a2v v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex); //顶点坐标从模型空间转化到剪裁空间
//等价于TRANSFORM_TEX(v.texcoord,_MainTex_ST.zw,拿顶点的uv和材质球的tiling和offset做运算
//拿顶点的uv去和材质球的tiling和offset作运算,确保材质球里的缩放和偏移设置是正确的,_MainTex_ST.xy为Tiling,zw为offset
o.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;//将顶点由模型空间变换到世界空间
o.worldNormal = UnityObjectToWorldNormal(v.normal);//将法向量由模型变换到世界空间
return o;
}
fixed4 frag(v2f i) : SV_Target { //SV_Target绑定语义,作为vertex的输出,fragment的输入
float3 worldPos = i.worldPos;//世界空间坐标
fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos));//顶点到光源光照的方向
//diffuse
//tex2D函数对纹理进行采样,第一个参数是需要被采样的纹理,第二个参数是纹理坐标,返回计算得到的纹素值
//使用采样结果和颜色属性_Color的乘积作为材质的反射率albedo
fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Color.rgb;//吸收系数
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;//环境光
fixed3 worldNormal=normalize(i.worldNormal); //世界空间下法线单位矢量
fixed3 worldLightDir=normalize(_WorldSpaceCameraPos.xyz); //世界空间下光源方向单位矢量
fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(i.worldNormal, lightDir));//漫反射
fixed3 reflectDir=normalize(reflect(-worldLightDir,worldNormal)); //世界空间下反射光矢量
fixed3 viewDir=normalize(_WorldSpaceCameraPos.xyz-i.worldPos.xyz); //视野方向
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(reflectDir,viewDir)),_Gloss);//高光
return fixed4((ambient + diffuse+specular), 1.0);
}
ENDCG
}
Pass
{
Tags { "RenderQueue"="Transparent" }
Stencil
{
Ref 0
Comp equal
Pass incrWrap
Fail keep
ZFail keep
}
Blend SrcAlpha OneMinusSrcAlpha
ZWrite off
Offset -1 , 0
CGPROGRAM
#include "UnityCG.cginc"
//#include "Assets/Common/Shader/Noise.cginc"
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_instancing
struct appdata_vert
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
float4 vertex : SV_POSITION;
float4 color : COLOR;
float4 shadowEdge : TEXCOORD0;
UNITY_VERTEX_OUTPUT_STEREO
};
uniform float4 _LightDir;
uniform float4 _ShadowColor;
uniform float _ShadowPlane;
float _ShadowFallOff;
void ShadowProjectPos(inout float4 vertPos, out float alpha)
{
float3 worldOriPos = mul(unity_ObjectToWorld, float4(vertPos.xy, 0, 1)).xyz;
float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
float3 worldPos = mul(unity_ObjectToWorld, vertPos).xyz;
vertPos.y = min(worldPos.y, _ShadowPlane);
vertPos.xz = worldPos.xz - lightDir.xz * max(0, worldPos.y - _ShadowPlane) / lightDir.y;
// shadowEdgePos = vertPos;
// shadowEdgePos.xz += normalize(shadowEdgePos.xz - worldOriPos.xz) * 0.01;
alpha = 1 - smoothstep(0, 2, distance(vertPos, worldPos));
//alpha=1.0 - saturate(distance(vertPos, worldPos) * _Instensity);
}
v2f vert (appdata_vert v)
{
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
ShadowProjectPos(v.vertex, o.color.a);
o.vertex = UnityWorldToClipPos(v.vertex);
o.color.rgb = _ShadowColor.rgb;
float3 center =float3( unity_ObjectToWorld[0].w , _LightDir.w , unity_ObjectToWorld[2].w);
float falloff = 1-max(0,saturate(distance(o.vertex , center) * _ShadowFallOff));
//o.shadowEdge = 1.0-v.vertex.z/14.0;
o.color.a *= falloff;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// float2 uv = i.shadowEdge.xz - i.vertex.xz;
// return float4(uv.yyyy);
return i.color ;
}
ENDCG
}
}
FallBack "Diffuse"
}
最终效果: