//工作太忙,一直没有放出来。根据自己对PRB的理解,加上对硬件的考虑,用CubeMap模拟出来一个满足自己需求的可以在手机上上跑的伪PRB的状态。
Shader "AnimalClamp/MyPBR_Test01" {
Properties{
_MainTex("Base (RGB)", 2D) = "white" {}
_MainTint("Diffuse Color", Color) = (1, 1, 1, 1)
_Cubemap("Sky CubeMap", CUBE) = ""{}
_ReflAmount("Reflection Amount", Range(0.01, 1)) = 0.5
_SpecCol("Specular Color", Color) = (1, 1, 1, 1)
_Gloss("Gloss", Range(0, 1)) = 0.5
_Ref("Ref", Range(0, 1)) = 0.5
[HideInInspector]_nMips("nMipsF", Range(0, 5)) = 0.5
}
SubShader
{
Pass
{
Tags{ "LightMode" = "ForwardBase" }
Cull Back
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#pragma target 3.0
sampler2D _MainTex;
samplerCUBE _Cubemap;
float4 _MainTint;
float _ReflAmount;
float4 _SpecCol;
float _nMips;
float _Gloss;
float _Ref;
float3 _LightColor0;
#define PI 3.1415926535
#define E 2.71828
struct v2f
{
float4 pos:SV_POSITION;
float3 lightDir:TEXCOORD0;
float3 viewDir:TEXCOORD1;
float3 normal:TEXCOORD2;
float2 uv:TEXCOORD3;
float3 reflection:TEXCOORD4;
};
float3 EnvironmentBRDF(float g, float NoV, float3 rf0)
{
float4 t = float4(1 / 0.96, 0.475, (0.0275 - 0.25 * 0.04) / 0.96, 0.25);
t *= float4(g, g, g, g);
t += float4(0, 0, (0.015 - 0.75 * 0.04) / 0.96, 0.75);
float a0 = t.x * min(t.y, exp2(-9.28 * NoV)) + t.z;
float a1 = t.w;
return saturate(a0 + rf0 * (a1 - a0));
}
v2f vert(appdata_full v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.normal = v.normal;
o.lightDir = ObjSpaceLightDir(v.vertex);
o.viewDir = ObjSpaceViewDir(v.vertex);
float3 posW = mul(unity_ObjectToWorld, v.vertex).xyz;
float3 I = posW - _WorldSpaceCameraPos.xyz;
float3 N = mul(unity_ObjectToWorld, v.normal).xyz;
o.reflection = reflect(I, normalize(N));
o.uv = v.texcoord.xy;
return o;
}
float4 frag(v2f i) :COLOR
{
float3 worldView = normalize(mul((float3x3)unity_WorldToObject, normalize(i.viewDir)));
float3 worldLight = normalize(mul((float3x3)unity_WorldToObject, normalize(i.lightDir)));
float3 worldNormal = normalize(mul((float3x3)unity_WorldToObject, normalize(i.normal)));
float halfDir = normalize(worldLight + worldView);//半角向量方向
float3 reflectDir = i.reflection;// reflect(i.I, worldNormal);//反射光线方向 reflect(worldLight, worldNormal)
//BRDF实现
float4 t = float4(1 / 0.96, 0.475, (0.0275 - 0.25 * 0.04) / 0.96, 0.25);
t *= _Gloss;
t += float4(0, 0, (0.015 - 0.75 * 0.04) / 0.96, 0.75);
float a0 = t.x * min(t.y, exp2(-9.28 * dot(worldNormal, worldView))) + t.z;
float a1 = t.w;
float3 environmentBRDF = saturate(a0 + _Ref * (a1 - a0));
float3 lightShadow = _LightColor0 * dot(worldLight, worldNormal);
//Lighting实现
float spe = pow(8192, _Gloss);//经验公式
float d = (spe + 2) / (8 * PI) * pow(clamp(dot(worldNormal, worldView), 0, 1), spe);// 这里最后一个 worldView 应该用 halfDir,使用clamp是为了不使光线直向相机的时候导致模型变黑
float k = 2 / sqrt(PI * (spe + 2));
float v = 1 / ((dot(worldNormal, worldLight) * (1 - k) + k) * (dot(worldNormal, worldView) * (1 - k) + k));
float spec = d * environmentBRDF * v;
float4 col = tex2D(_MainTex, i.uv) * _MainTint;
float4 c = col;
c.rgb += (_SpecCol + (1 - _SpecCol)* environmentBRDF) * spec * dot(worldLight, worldView);//* light.rgb;
c += spec * _SpecCol * dot(worldLight, worldView);
float3 emission = texCUBElod(_Cubemap, float4(reflectDir, _nMips - _Gloss * _nMips)).rgb * _ReflAmount * dot(worldView, worldNormal) * 1.5;
emission += emission * d * dot(worldLight, worldView) * _LightColor0 * 2;
return c + float4(emission, 1);// c * dot(worldNormal, worldLight) + float4(emission, 1);
}
ENDCG
}
}FallBack "Diffuse"
}