Unity Shader实现标准Phong模型,可以控制如下选项
- 逐像素/顶点光照
- 镜面反射开关
- 漫反射开关
- 环境光开关
- 自发光开关
- 纹理贴图
- 镜面反射颜色
- 光泽度
- 漫反射颜色
- 自发光颜色
- 使用Blinn-Phong
代码如下:
Shader "Custom/Phong"
{
Properties
{
_Specular("Specular", Color) = (1,1,1,1)
_Diffuse("Diffuse", Color) = (1,1,1,1)
_Gloss("Gloss", float) = 1
_Emission("Emission", Color) = (0,0,0,0)
_MainTex ("Texture", 2D) = "white" {}
[KeywordEnum(Vertex,Fragment)] _Mode ("Mode", Float) = 0
[Toggle(ENABLE_SPECULAR)] _Enable_Specular ("Enable Specular", Float) = 0
[Toggle(ENABLE_DIFFUSE)] _Enable_Duffuse ("Enable Diffuse", Float) = 0
[Toggle(ENABLE_EMISSION)] _Enable_Emission ("Enable Emission", Float) = 0
[Toggle(ENABLE_AMBIENT)] _Enable_Ambient ("Enable Ambient", Float) = 0
[Toggle(ENABLE_BLINN_PHONG)] _Enable_Blinn_Phong ("Enable Blinn-Phong", Float) = 0
}
SubShader
{
Pass
{
Tags {
"LightMode" = "ForwardBase"
}
CGPROGRAM
#pragma target 3.0
#pragma shader_feature _MODE_VERTEX
#pragma shader_feature _MODE_FRAGMENT
#pragma shader_feature ENABLE_SPECULAR
#pragma shader_feature ENABLE_DIFFUSE
#pragma shader_feature ENABLE_EMISSION
#pragma shader_feature ENABLE_AMBIENT
#pragma shader_feature ENABLE_BLINN_PHONG
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
fixed4 _Specular;
fixed4 _Diffuse;
float _Gloss;
fixed4 _Emission;
sampler2D _MainTex;
float4 _MainTex_ST;
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 pos : SV_POSITION;
fixed3 color : COLOR0;
fixed3 worldNormal : NORMAL;
fixed3 viewDir : TEXCOORD1;
};
v2f vert(appdata v)
{
//fixed3 worldNormal = normalize(mul(transpose((float3x3)unity_WorldToObject), v.normal));
fixed3 worldNormal = normalize(mul(v.normal, (float3x3)unity_WorldToObject)); //少一次transpose计算
fixed3 worldLight = -normalize(_WorldSpaceLightPos0.xyz);
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, v.vertex).xyz);
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.pos = transpose((float4x1)o.pos);
o.color = fixed3(0,0,0);
o.worldNormal = worldNormal;
o.viewDir = viewDir;
#if _MODE_VERTEX
//环境光
#if ENABLE_AMBIENT
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
o.color+=ambient;
#endif
//漫反射
#if ENABLE_DIFFUSE
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, -worldLight)); //防止点积为负值,截取到[0,1]
o.color+=diffuse;
#endif
//镜面反射
#if ENABLE_SPECULAR
#if ENABLE_BLINN_PHONG
fixed3 halfDir = normalize(viewDir-worldLight);
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(worldNormal, halfDir)), _Gloss);
o.color+=specular;
#else
//fixed3 reflectDir = normalize(2*dot(worldLight,worldNormal)-worldLight);
fixed3 reflectDir = normalize(reflect(worldLight,worldNormal));
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(reflectDir, viewDir)), _Gloss);
o.color+=specular;
#endif
#endif
//自发光
#if ENABLE_EMISSION
o.color+=_Emission.rgb;
#endif
#endif
return o;
}
fixed4 frag(v2f i) : SV_TARGET
{
fixed3 worldLight = -normalize(_WorldSpaceLightPos0.xyz);
#if _MODE_FRAGMENT
//环境光
#if ENABLE_AMBIENT
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
i.color+=ambient;
#endif
//漫反射
#if ENABLE_DIFFUSE
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(i.worldNormal, -worldLight)); //防止点积为负值,截取到[0,1]
i.color+=diffuse;
#endif
//镜面反射
#if ENABLE_SPECULAR
#if ENABLE_BLINN_PHONG
fixed3 halfDir = normalize(i.viewDir-worldLight);
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(i.worldNormal, halfDir)), _Gloss);
i.color+=specular;
#else
//fixed3 reflectDir = normalize(2*dot(worldLight,worldNormal)-worldLight);
fixed3 reflectDir = normalize(reflect(worldLight,i.worldNormal));
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(reflectDir, i.viewDir)), _Gloss);
i.color+=specular;
#endif
#endif
//自发光
#if ENABLE_EMISSION
i.color+=_Emission.rgb;
#endif
#endif
fixed4 col = tex2D(_MainTex, i.uv);
return col*fixed4(i.color, 1);
}
ENDCG
}
}
FallBack off
}