注意点:
1.法线的归一化 normalize (如果shader光照效果怪怪的,请查看是否归一化)
2.在计算自发光emission 直接使用的normal : appdata 中的normal 转到世界空间中的normal。emission跟光照没有关系,不受光照的影响(不是所有的地方都有自发光:添加emissionMask)
3.在计算直接光照效果 diffuse 和specular的时候, 用切线空间转换到世界空间中的法线
4.AO贴图: 只作用在 间接光照中 : Indirectlight中的 diffuse 和specular
用AO来限制他们的亮度
5.用一张图的 rgba四个通道来存储相应的遮罩等值
下面是实现代码:
Shader "FishMan/12_AOE"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_BumpMap ("Normal Map", 2D) = "bump"{}
_Metallic_AO_MASK_Smoothness("_Metallic_AO_MASK_Smoothness", 2D) = "white" {}
[HDR]_FresnelColor("FresnelColor", Color) = (0,0,0,0)
_FresnelPower("FresnelPower", Range( 0 , 30)) = 0.8
_FresnelScale("FresnelScale", Range( 0 , 1)) = 1
}
SubShader
{
Pass
{
Tags { "RenderType"="Opaque" "LightMode" = "ForwardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0
#define _FORWADR_BASE
#pragma multi_compile_fwdbase
#pragma multi_compile_fog
#include "../ExampleLibs/12_AOEimission.cginc"
ENDCG
}
Pass
{
Tags { "RenderType"="Opaque" "LightMode" = "ForwardAdd" }
Blend One One
ZWrite Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdadd
#pragma multi_compile_fog
#pragma target 3.0
#include "../ExampleLibs/12_AOEimission.cginc"
ENDCG
}
Pass
{
Tags {"LightMode"="ShadowCaster"}
CGPROGRAM
#pragma vertex vertShadowCaster
#pragma fragment fragShadowCaster
#pragma multi_compile_shadowcaster
#include "../../ShaderLibs/Shadow.cginc"
ENDCG
}
}
}
#ifndef FMST02_AO_EIMISSION
#define FMST02_AO_EIMISSION
#include "UnityCG.cginc"
#include "UnityPBSLighting.cginc" // PBS
#include "AutoLight.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal : NORMAL;
float4 tangent : TANGENT;
};
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float3 normal : TEXCOORD1;
float3 worldPos: TEXCOORD2;
#if defined(VERTEXLIGHT_ON)
float3 vertexLightColor : TEXCOORD3;
#endif
SHADOW_COORDS(4)
UNITY_FOG_COORDS(5) // 8
float3 T2WRow0 : TEXCOORD6;
float3 T2WRow1 : TEXCOORD7;
float3 T2WRow2 : TEXCOORD8;
};
sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _BumpMap;
sampler2D _Metallic_AO_MASK_Smoothness;
float4 _FresnelColor;
float _FresnelScale;
float _FresnelPower;
UnityLight CreateDirectLight(v2f i){
float3 lightDir;
// float attenuation = 1;
#if defined(DIRECTIONAL)
lightDir = _WorldSpaceLightPos0.xyz;
#else
float3 lightVec= _WorldSpaceLightPos0.xyz - i.worldPos;
lightDir = normalize(lightVec);
#endif
UNITY_LIGHT_ATTENUATION(attenuation, i, i.worldPos);
UnityLight light;
light.color = _LightColor0.rgb * attenuation;
light.dir = lightDir;
light.ndotl = saturate(dot(lightDir,i.normal));
return light;
}
UnityIndirect CreateIndirectLight (v2f i) {
UnityIndirect indirectLight;
indirectLight.diffuse = 0;
indirectLight.specular = 0;
#if defined(VERTEXLIGHT_ON)
indirectLight.diffuse = i.vertexLightColor;
#endif
#if defined(_FORWADR_BASE)
indirectLight.diffuse += max(0, ShadeSH9(float4(i.normal, 1)));
#endif
return indirectLight;
}
void CalcVertexLightColor(inout v2f i){
#if defined(VERTEXLIGHT_ON)
i.vertexLightColor = Shade4PointLights(
unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,
unity_LightColor[0].rgb, unity_LightColor[1].rgb,
unity_LightColor[2].rgb, unity_LightColor[3].rgb,
unity_4LightAtten0, i.worldPos, i.normal
);
#endif
}
v2f vert (appdata v)
{
v2f o;
UNITY_INITIALIZE_OUTPUT(v2f,o);
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.normal = UnityObjectToWorldNormal(v.normal) ;
o.worldPos = mul(unity_ObjectToWorld, v.vertex);
CalcVertexLightColor(o);
TRANSFER_SHADOW(o)
UNITY_TRANSFER_FOG(o,o.pos);
fixed3 worldNormal = o.normal;
fixed3 worldTangent = UnityObjectToWorldDir( v.tangent.xyz );
fixed tangentSign = v.tangent.w * unity_WorldTransformParams.w;
fixed3 worldBinormal = cross( worldNormal, worldTangent ) * tangentSign;
o.T2WRow0 = float3( worldTangent.x, worldBinormal.x, worldNormal.x); // * tNormal.xyz
o.T2WRow1 = float3( worldTangent.y, worldBinormal.y, worldNormal.y);
o.T2WRow2 = float3( worldTangent.z, worldBinormal.z, worldNormal.z);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 albedo = tex2D(_MainTex, i.uv);
float3 normalVal = UnpackNormal( tex2D(_BumpMap,i.uv));
fixed4 metallic_AO_MASK_Smoothness = tex2D(_Metallic_AO_MASK_Smoothness, i.uv);
float metallic = metallic_AO_MASK_Smoothness.r;
float smoothness = metallic_AO_MASK_Smoothness.a;
float occlusion = metallic_AO_MASK_Smoothness.g ;
float3 viewDir = normalize(_WorldSpaceCameraPos - i.worldPos);
#if defined(_FORWADR_BASE)
float emissionMask = metallic_AO_MASK_Smoothness.b;
float ndv = dot( normalize(i.normal), viewDir );
float fresnel = pow(1 - ndv,_FresnelPower) * _FresnelScale ;
float4 emission = fresnel * emissionMask * _FresnelColor;
#endif
i.normal = fixed3(dot(i.T2WRow0,normalVal), dot(i.T2WRow1,normalVal), dot(i.T2WRow2,normalVal));
i.normal = normalize(i.normal);
float oneMinusReflectivity ;
float3 specularTint;
albedo.rgb = DiffuseAndSpecularFromMetallic(albedo,metallic,specularTint,oneMinusReflectivity);
UnityLight light = CreateDirectLight(i);
UnityIndirect indirectLight = CreateIndirectLight(i);
indirectLight.diffuse *= occlusion;
indirectLight.specular *= occlusion;
//light.color *= occlusion;
float4 col = UNITY_BRDF_PBS(albedo,specularTint,oneMinusReflectivity,smoothness,
i.normal,viewDir,
light,indirectLight
);
UNITY_APPLY_FOG(i.fogCoord, col);
#if defined(_FORWADR_BASE)
col += emission;
#endif
return col;
}
#endif
附资源百度云:
链接: https://pan.baidu.com/s/1UdDCnt6uEfhy5IPNnEam5g
提取码: 9b6s