MS的PBR高效简陋实现版
2020/03
14
00:03
Shader "MSPBRStandard"
{
Properties
{
// Main maps.
_Color("Color", Color) = (1.0, 1.0, 1.0, 1.0)
_MainTex("Albedo", 2D) = "white" {}
_Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
_Metallic("Metallic", Range(0.0, 1.0)) = 0.0
_Smoothness("Smoothness", Range(0.0, 1.0)) = 0.5
[Toggle(_CHANNEL_MAP)] _EnableChannelMap("Enable Channel Map", Float) = 0.0
[NoScaleOffset] _ChannelMap("Channel Map", 2D) = "white" {}
[Toggle(_NORMAL_MAP)] _EnableNormalMap("Enable Normal Map", Float) = 0.0
[NoScaleOffset] _NormalMap("Normal Map", 2D) = "bump" {}
// Rendering options.
[Toggle(_DIRECTIONAL_LIGHT)] _DirectionalLight("Directional Light", Float) = 1.0
[Toggle(_SPECULAR_HIGHLIGHTS)] _SpecularHighlights("Specular Highlights", Float) = 1.0
[Toggle(_REFLECTIONS)] _Reflections("Reflections", Float) = 0.0
[Toggle(_REFRACTION)] _Refraction("Refraction", Float) = 0.0
_RefractiveIndex("Refractive Index", Range(0.0, 3.0)) = 0.0
// Advanced options.
[Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend("Source Blend", Float) = 1 // "One"
[Enum(UnityEngine.Rendering.BlendMode)] _DstBlend("Destination Blend", Float) = 0 // "Zero"
[Enum(UnityEngine.Rendering.BlendOp)] _BlendOp("Blend Operation", Float) = 0 // "Add"
[Enum(UnityEngine.Rendering.CompareFunction)] _ZTest("Depth Test", Float) = 4 // "LessEqual"
_ZOffsetFactor("Depth Offset Factor", Float) = 0 // "Zero"
_ZOffsetUnits("Depth Offset Units", Float) = 0 // "Zero"
[Enum(UnityEngine.Rendering.ColorWriteMask)] _ColorWriteMask("Color Write Mask", Float) = 15 // "All"
[Enum(UnityEngine.Rendering.CullMode)] _CullMode("Cull Mode", Float) = 2 // "Back"
_RenderQueueOverride("Render Queue Override", Range(-1.0, 5000)) = -1
[Toggle(_STENCIL)] _Stencil("Enable Stencil Testing", Float) = 0.0
_StencilReference("Stencil Reference", Range(0, 255)) = 0
[Enum(UnityEngine.Rendering.CompareFunction)]_StencilComparison("Stencil Comparison", Int) = 0
[Enum(UnityEngine.Rendering.StencilOp)]_StencilOperation("Stencil Operation", Int) = 0
}
SubShader
{
Pass
{
Name "Main"
Tags{ "RenderType" = "Opaque" "LightMode" = "ForwardBase" }
LOD 100
Blend[_SrcBlend][_DstBlend]
BlendOp[_BlendOp]
ZTest[_ZTest]
Cull[_CullMode]
Offset[_ZOffsetFactor],[_ZOffsetUnits]
ColorMask[_ColorWriteMask]
Stencil
{
Ref[_StencilReference]
Comp[_StencilComparison]
Pass[_StencilOperation]
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_instancing
#pragma multi_compile _ LIGHTMAP_ON
#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON
#pragma shader_feature _CHANNEL_MAP
#pragma shader_feature _NORMAL_MAP
#pragma shader_feature _DIRECTIONAL_LIGHT
#pragma shader_feature _SPECULAR_HIGHLIGHTS
#pragma shader_feature _REFLECTIONS
#pragma shader_feature _REFRACTION
#include "UnityCG.cginc"
#include "UnityStandardConfig.cginc"
#include "UnityStandardUtils.cginc"
#if defined(_DIRECTIONAL_LIGHT) || defined(_REFLECTIONS)
#define _NORMAL
#else
#undef _NORMAL
#endif
#if defined(_NORMAL)
#define _WORLD_POSITION
#else
#undef _WORLD_POSITION
#endif
#if defined(_ALPHATEST_ON)
#define _ALPHA_CLIP
#else
#undef _ALPHA_CLIP
#endif
#if defined(_ALPHABLEND_ON)
#define _TRANSPARENT
#undef _ALPHA_CLIP
#else
#undef _TRANSPARENT
#endif
#if defined(_DIRECTIONAL_LIGHT)
#define _FRESNEL
#else
#undef _FRESNEL
#endif
struct appdata_t
{
float4 vertex : POSITION;
// The default UV channel used for texturing.
float2 uv : TEXCOORD0;
#if defined(LIGHTMAP_ON)
// Reserved for Unity's light map UVs.
float2 uv1 : TEXCOORD1;
#endif
// Used for smooth normal data (or UGUI scaling data).
float4 uv2 : TEXCOORD2;
// Used for UGUI scaling data.
float2 uv3 : TEXCOORD3;
fixed3 normal : NORMAL;
#if defined(_NORMAL_MAP)
fixed4 tangent : TANGENT;
#endif
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
float4 position : SV_POSITION;
float2 uv : TEXCOORD0;
#if defined(LIGHTMAP_ON)
float2 lightMapUV : TEXCOORD1;
#endif
#if defined(_WORLD_POSITION)
float3 worldPosition : TEXCOORD2;
#endif
#if defined(_NORMAL)
#if defined(_NORMAL_MAP)
fixed3 tangentX : COLOR3;
fixed3 tangentY : COLOR4;
fixed3 tangentZ : COLOR5;
#else
fixed3 worldNormal : COLOR3;
#endif
#endif
UNITY_VERTEX_OUTPUT_STEREO
};
fixed4 _Color;
sampler2D _MainTex;
fixed4 _MainTex_ST;
#if defined(_ALPHA_CLIP)
fixed _Cutoff;
#endif
fixed _Metallic;
fixed _Smoothness;
#if defined(_CHANNEL_MAP)
sampler2D _ChannelMap;
#endif
#if defined(_NORMAL_MAP)
sampler2D _NormalMap;
#endif
#if defined(_DIRECTIONAL_LIGHT)
fixed4 _LightColor0;
#endif
#if defined(_REFRACTION)
fixed _RefractiveIndex;
#endif
#if defined(_DIRECTIONAL_LIGHT)
static const fixed _MinMetallicLightContribution = 0.7;
static const fixed _IblContribution = 0.1;
#endif
#if defined(_SPECULAR_HIGHLIGHTS)
static const float _Shininess = 800.0;
#endif
#if defined(_FRESNEL)
static const float _FresnelPower = 8.0;
#endif
v2f vert(appdata_t v)
{
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
float4 vertexPosition = v.vertex;
#if defined(_WORLD_POSITION)
float3 worldVertexPosition = mul(unity_ObjectToWorld, vertexPosition).xyz;
#endif
fixed3 localNormal = v.normal;
#if defined(_NORMAL)
fixed3 worldNormal = UnityObjectToWorldNormal(localNormal);
#endif
o.position = UnityObjectToClipPos(vertexPosition);
#if defined(_WORLD_POSITION)
o.worldPosition.xyz = worldVertexPosition;
#endif
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
#if defined(LIGHTMAP_ON)
o.lightMapUV.xy = v.uv1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
#endif
#if defined(_NORMAL)
#if defined(_NORMAL_MAP)
fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
fixed tangentSign = v.tangent.w * unity_WorldTransformParams.w;
fixed3 worldBitangent = cross(worldNormal, worldTangent) * tangentSign;
o.tangentX = fixed3(worldTangent.x, worldBitangent.x, worldNormal.x);
o.tangentY = fixed3(worldTangent.y, worldBitangent.y, worldNormal.y);
o.tangentZ = fixed3(worldTangent.z, worldBitangent.z, worldNormal.z);
#else
o.worldNormal = worldNormal;
#endif
#endif
return o;
}
fixed4 frag(v2f i, fixed facing : VFACE) : SV_Target
{
// Texturing.
fixed4 albedo = tex2D(_MainTex, i.uv);
#ifdef LIGHTMAP_ON
albedo.rgb *= DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, i.lightMapUV));
#endif
#if defined(_CHANNEL_MAP)
fixed4 channel = tex2D(_ChannelMap, i.uv);
_Metallic = channel.r;
albedo.rgb *= channel.g;
_Smoothness = channel.a;
#else
#endif
albedo *= _Color;
// Normal calculation.
#if defined(_NORMAL)
fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(i.worldPosition.xyz));
#if defined(_REFLECTIONS)
fixed3 incident = -worldViewDir;
#endif
fixed3 worldNormal;
#if defined(_NORMAL_MAP)
fixed3 tangentNormal = UnpackNormal(tex2D(_NormalMap, i.uv));
worldNormal.x = dot(i.tangentX, tangentNormal);
worldNormal.y = dot(i.tangentY, tangentNormal);
worldNormal.z = dot(i.tangentZ, tangentNormal);
worldNormal = normalize(worldNormal) * facing;
#else
worldNormal = normalize(i.worldNormal) * facing;
#endif
#endif
#if defined(_ALPHA_CLIP)
#if !defined(_ALPHATEST_ON)
_Cutoff = 0.5;
#endif
clip(albedo.a - _Cutoff);
albedo.a = 1.0;
#endif
// Blinn phong lighting.
#if defined(_DIRECTIONAL_LIGHT)
float4 directionalLightDirection = _WorldSpaceLightPos0;
fixed diffuse = max(0.0, dot(worldNormal, directionalLightDirection));
#if defined(_SPECULAR_HIGHLIGHTS)
fixed halfVector = max(0.0, dot(worldNormal, normalize(directionalLightDirection + worldViewDir)));
fixed specular = saturate(pow(halfVector, _Shininess * pow(_Smoothness, 4.0)) * (_Smoothness * 2.0) * _Metallic);
#else
fixed specular = 0.0;
#endif
#endif
// Image based lighting (attempt to mimic the Standard shader).
#if defined(_REFLECTIONS)
fixed3 worldReflection = reflect(incident, worldNormal);
fixed4 iblData = UNITY_SAMPLE_TEXCUBE_LOD(unity_SpecCube0, worldReflection, (1.0 - _Smoothness) * UNITY_SPECCUBE_LOD_STEPS);
fixed3 ibl = DecodeHDR(iblData, unity_SpecCube0_HDR);
#if defined(_REFRACTION)
fixed4 refractColor = UNITY_SAMPLE_TEXCUBE(unity_SpecCube0, refract(incident, worldNormal, _RefractiveIndex));
ibl *= DecodeHDR(refractColor, unity_SpecCube0_HDR);
#endif
#else
fixed3 ibl = unity_IndirectSpecColor.rgb;
#endif
// Fresnel lighting.
#if defined(_FRESNEL)
fixed fresnel = 1.0 - saturate(abs(dot(worldViewDir, worldNormal)));
fixed3 fresnelColor = unity_IndirectSpecColor.rgb * (pow(fresnel, _FresnelPower) * max(_Smoothness, 0.5));
#endif
// Final lighting mix.
fixed4 output = albedo;
fixed3 ambient = glstate_lightmodel_ambient + fixed3(0.25, 0.25, 0.25);
fixed minProperty = min(_Smoothness, _Metallic);
#if defined(_DIRECTIONAL_LIGHT)
fixed oneMinusMetallic = (1.0 - _Metallic);
output.rgb = lerp(output.rgb, ibl, minProperty);
fixed3 directionalLightColor = _LightColor0.rgb;
output.rgb *= lerp((ambient + directionalLightColor * diffuse + directionalLightColor * specular) * max(oneMinusMetallic, _MinMetallicLightContribution), albedo, minProperty);
output.rgb += (directionalLightColor * albedo * specular) + (directionalLightColor * specular * _Smoothness);
output.rgb += ibl * oneMinusMetallic * _IblContribution;
#elif defined(_REFLECTIONS)
output.rgb = lerp(output.rgb, ibl, minProperty);
output.rgb *= lerp(ambient, albedo, minProperty);
#endif
#if defined(_FRESNEL)
#if !defined(_REFLECTIONS)
output.rgb += fresnelColor;
#else
output.rgb += fresnelColor * (1.0 - minProperty);
#endif
#endif
return output;
}
ENDCG
}
Pass
{
Name "Meta"
Tags { "LightMode" = "Meta" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma shader_feature EDITOR_VISUALIZATION
#pragma shader_feature _CHANNEL_MAP
#include "UnityCG.cginc"
#include "UnityMetaPass.cginc"
struct v2f
{
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
};
float4 _MainTex_ST;
v2f vert(appdata_full v)
{
v2f o;
o.vertex = UnityMetaVertexPosition(v.vertex, v.texcoord1.xy, v.texcoord2.xy, unity_LightmapST, unity_DynamicLightmapST);
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
return o;
}
sampler2D _MainTex;
sampler2D _ChannelMap;
fixed4 _Color;
fixed4 _LightColor0;
half4 frag(v2f i) : SV_Target
{
UnityMetaInput output;
UNITY_INITIALIZE_OUTPUT(UnityMetaInput, output);
output.Albedo = tex2D(_MainTex, i.uv) * _Color;
output.SpecularColor = _LightColor0.rgb;
return UnityMetaFragment(output);
}
ENDCG
}
}
}
CopyRights: The Post by BY-NC-SA For Authorization,Original If Not Noted,Reprint Please Indicate From 老刘@开发笔记
Post Link: MS的PBR高效简陋实现版
Post Link: MS的PBR高效简陋实现版