版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35759688/article/details/77935178
一、公式
specuColor = Kd*_LightColor0*pow(max(R·V 0), _Shininess);
Kd–环境光颜色、顶点颜色、点光源的距离衰减
_LightColor0–光源颜色
R·V–反射光向量 · 观察向量
二、逐顶点着色(古罗着色)
Shader "Custom/MySpecular_Vertex"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Bright("Bright",Float) = 2
_Shininess("Shininess",Float) = 10
}
SubShader
{
Tags { "RenderType" = "Opaque" }
LOD 100
Pass
{
Tags{ "LightMode" = "ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
uniform float _Shininess;
uniform float _Bright;
uniform sampler2D _MainTex;
struct appdata
{
float4 vertex:POSITION;
float2 texcoord:TEXCOORD0;
half3 normal:NORMAL;
};
struct v2f
{
float4 pos:SV_POSITION;
float2 uv:TEXCOORD0;
fixed4 difColor : COLOR0;
fixed4 specuColor : COLOR1;
};
v2f vert(in appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.texcoord;
float3 vertexWorldPos = mul(unity_ObjectToWorld, v.vertex);
float3 N = normalize(mul((float3x3)unity_ObjectToWorld, v.normal));//法线
float3 L;//入射光方向
float atten;//点光源的距离衰减系数
if (_WorldSpaceLightPos0.w == 0)//_WorldSpaceLightPos0:平行光: (world space direction, 0);
{
L = normalize(_WorldSpaceLightPos0);
atten = 1;
}
else //_WorldSpaceLightPos0: 其他光: (world space position, 1).
{
float3 light2Vertex = _WorldSpaceLightPos0 - vertexWorldPos;
L = normalize(light2Vertex);
float Length = length(light2Vertex);
atten = 1 / Length;
}
float Kd = atten*_Bright/**UNITY_LIGHTMODEL_AMBIENT*/;
//计算入射光和法线的夹角的余弦值,并剔除小于零的值(小于0的值相当于从物体的背面向物体表面照射,没有物理意义)
float cos = max(dot(N, L), 0);
fixed4 difColor = Kd*_LightColor0 *cos;//漫反射光的颜色
//镜面反射
float3 R = reflect(-L, N);
float3 V= normalize(_WorldSpaceCameraPos - vertexWorldPos);
fixed4 specuColor = Kd* _LightColor0*pow(max(dot(R, V), 0), _Shininess);
o.difColor = difColor;
o.specuColor = specuColor;
return o;
}
fixed4 frag(in v2f i) :SV_Target
{
fixed4 col;
//纹理采样
col = tex2D(_MainTex, i.uv);
col *= i.difColor;
col += i.specuColor;
return col;
}
ENDCG
}
}
}
三、逐像素着色(冯式着色)
Shader "Custom/MySpecular_Fragment"
{
Properties
{
_MainTex("Texture", 2D) = "white" {}
_Bright("Bright",Float) = 2
_Shininess("Shininess",Float) = 10
}
SubShader
{
Tags{ "RenderType" = "Opaque" }
LOD 100
Pass
{
Tags{ "LightMode" = "ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
uniform float _Shininess;
uniform float _Bright;
uniform sampler2D _MainTex;
struct appdata
{
float4 vertex:POSITION;
float2 texcoord:TEXCOORD0;
float3 normal:NORMAL;
};
struct v2f
{
float4 pos:SV_POSITION;
float2 uv:TEXCOORD0;
float3 normalDir:TEXCOORD1;
float3 worldPos:TEXCOORD2;
};
v2f vert(in appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.texcoord;
o.normalDir = normalize(mul((float3x3)unity_ObjectToWorld, v.normal));
o.worldPos = mul((float3x3)unity_ObjectToWorld, v.vertex);
return o;
}
fixed4 frag(in v2f i) :SV_Target
{
fixed4 col;
col = tex2D(_MainTex, i.uv);
float3 N = normalize(i.normalDir);
float3 L;
float atten;
if (_WorldSpaceLightPos0.w == 0)
{
L = normalize(_WorldSpaceLightPos0);
atten = 1;
}
else
{
float3 light2Vertex = _WorldSpaceLightPos0 - i.worldPos;
L = normalize(light2Vertex);
float Length = length(light2Vertex);
atten = 1 / Length;
}
float Kd = atten*_Bright;
float4 difColor = Kd*_LightColor0*max(0, dot(N, L));
float3 R = reflect(-L, N);
float3 V = normalize(_WorldSpaceCameraPos - i.worldPos);
float4 specuColor = Kd*_LightColor0*pow(max(dot(R,V), 0), _Shininess);
col *= difColor;
col += specuColor;
return col;
}
ENDCG
}
}
}