Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Shader "PhysicallyBased/PBRV4" {
- Properties {
- _Color ("Albedo Color", Color) = (0.5, 0.5, 0.5, 1)
- _AlbedoMap ("Albedo Map", 2D) = "white" {}
- _MultiMap ("Multipurpose (R = Rough, G = AO, B = Metalness)", 2D) = "white" {}
- _Normal ("Normal", 2D) = "bump" {}
- _Roughness ("Roughness Multiplier (Default to 1 when using roughness maps)", Float) = 0.5
- _Metalness ("Metalness Multiplier (Default to 1 when using metalness maps)", Float) = 0
- }
- SubShader {
- Tags { "RenderType"="Opaque" }
- LOD 200
- Pass {
- Name "ForwardBase"
- Tags {"LightMode"="ForwardBase"}
- CGPROGRAM
- // Needed for OpenGL to compile when using texCUBElod
- #pragma glsl
- // Allows Unity to switch between Linear and Gamma space. The tonemapper must update afterwards
- #pragma multi_compile Linear Gamma
- // Allows disabling tonemapping which may not be needed in simple light setups.
- #pragma multi_compile tonemappingEnabled tonemappingDisabled
- #pragma target 3.0
- #pragma exclude_renderers flash
- #pragma multi_compile_fwdbase
- #pragma vertex vert
- #pragma fragment frag
- #include "UnityCG.cginc"
- #include "AutoLight.cginc"
- ////////////// Vertex Shader
- struct VertexInput {
- float4 vertex : POSITION;
- float4 texcoord : TEXCOORD0;
- float3 normal : NORMAL;
- float4 tangent : TANGENT;
- };
- struct VertexOutput {
- float4 pos : SV_POSITION;
- float4 uv0 : TEXCOORD0;
- float4 posWorld : TEXCOORD1;
- float3 normalWorld : TEXCOORD2;
- float3 tangentWorld : TEXCOORD3;
- float3 binormalWorld : TEXCOORD4;
- LIGHTING_COORDS(5,6)
- };
- VertexOutput vert (VertexInput v) {
- VertexOutput o;
- o.uv0 = v.texcoord;
- o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
- o.posWorld = mul(_Object2World, v.vertex);
- // Construct the vectors for transforming normal maps to world space
- o.normalWorld = normalize(mul(float4(v.normal, 0.0), _World2Object).xyz);
- o.tangentWorld = normalize(mul(_Object2World, float4(v.tangent.xyz, 0.0)).xyz);
- o.binormalWorld = normalize(cross(o.normalWorld, o.tangentWorld) * v.tangent.w);
- TRANSFER_VERTEX_TO_FRAGMENT(o);
- return o;
- }
- ////////////// Properties
- half4 _Color;
- sampler2D _AlbedoMap; half4 _AlbedoMap_ST;
- sampler2D _MultiMap; half4 _MultiMap_ST;
- sampler2D _Normal; half4 _Normal_ST;
- half _Metalness;
- half _Roughness;
- // Light Color
- uniform float4 _LightColor0;
- // Sky
- uniform samplerCUBE _SpecCubeIBL;
- // Spherical Harmonics
- uniform float3 _SH0;
- uniform float3 _SH1;
- uniform float3 _SH2;
- uniform float3 _SH3;
- uniform float3 _SH4;
- uniform float3 _SH5;
- uniform float3 _SH6;
- uniform float3 _SH7;
- uniform float3 _SH8;
- uniform float W;
- uniform float _ExposureBias;
- uniform float IBLMask;
- uniform float IndirectStrength;
- #define DielectricSpecular (0.04, 0.04, 0.04)
- #define Pi 3.14159
- #define InvPi 0.318309
- ////////////// Functions
- // Tonemapping - Uncharted 2
- inline float3 Uncharted2Tonemap(float3 x) {
- return ((x*(0.22*x+0.03)+0.002)/(x*(0.22*x+0.30)+0.06))-(0.0333);
- }
- inline float3 Tonemap(float3 X) {
- float3 curr = Uncharted2Tonemap(_ExposureBias * X); // Hardcoded Exposure Adjustment
- float3 whiteScale = 1.0/Uncharted2Tonemap(W);
- float3 color = curr*whiteScale;
- #ifdef Gamma
- color = pow(color, 0.4545);
- #endif
- return color;
- }
- ////////////// Specular BRDF
- // Same cost but likely better than pow(x, 5)
- inline float pow5(float i) {
- float i5 = i * i;
- return i5 * i5 * i;
- }
- // Fresnel - Schlick
- inline float3 F_Schlick(float3 f0, float u) {
- float InvU = 1.0 - u;
- return f0 + (1.0 - f0) * pow5(InvU);
- }
- // Distribution - [Lagarde 2014, "Moving Frostbite to Physically Based Rendering"
- inline float D_GGX_Frost(float NdotH, float m2) {
- float f = (NdotH * m2 - NdotH) * NdotH + 1;
- return m2 / (f * f);
- }
- // Geometric - [Lagarde 2014, "Moving Frostbite to Physically Based Rendering"]
- inline float V_SmithGGXCorrelated (float NdotV, float NdotL, float alphaG2 ) {
- float Lambda_GGXV = NdotL * sqrt (( -NdotV * alphaG2 + NdotV ) * NdotV + alphaG2 );
- float Lambda_GGXL = NdotV * sqrt (( -NdotL * alphaG2 + NdotL ) * NdotL + alphaG2 );
- return 0.5 / ( Lambda_GGXV + Lambda_GGXL );
- }
- // Spherical Harmonics - Marmoset
- inline float3 SHLookup(float3 dir) {
- //l = 0 band (constant)
- float3 result = _SH0.xyz;
- //l = 1 band
- result += _SH1.xyz * dir.y;
- result += _SH2.xyz * dir.z;
- result += _SH3.xyz * dir.x;
- //l = 2 band
- float3 swz = dir.yyz * dir.xzx;
- result += _SH4.xyz * swz.x;
- result += _SH5.xyz * swz.y;
- result += _SH7.xyz * swz.z;
- float3 sqr = dir * dir;
- result += _SH6.xyz * ( 3.0*sqr.z - 1.0 );
- result += _SH8.xyz * ( sqr.x - sqr.y );
- return abs(result);
- }
- // RGBM to linear color - Marmoset
- inline float3 fromRGBM(float4 c) {
- //c.a *= 6.0;
- //return c.rgb * lerp(c.a, toLinearFast1(c.a), IS_LINEAR);
- //7 instructions
- ///
- //combined 6.0 * toLinear
- float4 IGL; //.xyz: modified versions of IS_GAMMA_LINEAR, .w: c.a*c.a
- IGL =
- float4(
- 19.35486, // 3.22581 * 6.0,
- -87.468483312, //-3.22581 * 0.7532 * 36.0,
- -171.964060128, //-3.22581 * 0.2468 * 216.0,
- c.a
- ) *
- float4(
- unity_ColorSpaceGrey.r,
- unity_ColorSpaceGrey.r,
- unity_ColorSpaceGrey.r,
- c.a
- ) +
- float4(
- -3.6774, //-0.6129 * 6.0,
- 43.73410608, // 1.6129 * 0.7532 * 36.0,
- 85.98176352, // 1.6129 * 0.2468 * 216.0,
- 0.0
- );
- return c.rgb * dot(IGL.xyz, float3(c.a, IGL.w, c.a*IGL.w));
- //4 instructions
- ///
- }
- // BRDF for cubemaps
- inline float3 EnvBRDFApprox( float3 SpecularColor, float Roughness, float NoV ) {
- // [ Lazarov 2013, "Getting More Physical in Call of Duty: Black Ops II" ]
- // Adaptation to fit Unreal G term.
- const float4 c0 = { -1, -0.0275, -0.572, 0.022 };
- const float4 c1 = { 1, 0.0425, 1.04, -0.04 };
- float4 r = Roughness * c0 + c1;
- float a004 = min( r.x * r.x, exp2( -9.28 * NoV ) ) * r.x + r.y;
- float2 AB = float2( -1.04, 1.04 ) * a004 + r.zw;
- AB.y *= saturate( 50.0 * SpecularColor.g );
- return SpecularColor * AB.x + AB.y;
- }
- ////////////// Fragment Shader
- float4 frag(VertexOutput i) : COLOR {
- // Construct the world space normal direction
- float3 normalLocal = UnpackNormal(tex2D(_Normal, TRANSFORM_TEX(i.uv0.rg, _Normal)));
- float3x3 local2WorldTranspose = float3x3(
- i.tangentWorld,
- i.binormalWorld,
- i.normalWorld);
- float3 normalDir = normalize(mul(normalLocal, local2WorldTranspose));
- // Construct the world space view direction
- float3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.posWorld.xyz);
- // Construct the world space reflection direction
- float3 reflectionDir = normalize(reflect(-viewDir, normalDir));
- // Construct the world space light direction
- float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
- float ambientOcclusion = 1.0;
- // Dot Products
- float3 halfDir = normalize (viewDir + lightDir);
- float LdotH = saturate(dot(lightDir, halfDir));
- float NdotH = saturate(dot(normalDir, halfDir));
- float NdotL = saturate(dot(normalDir, lightDir));
- float NdotV = abs(dot(normalDir, viewDir)) + 1e-5f; // avoid artifact
- float3 MultiMap = tex2D(_MultiMap, TRANSFORM_TEX(i.uv0.rg, _MultiMap)).rgb;
- #ifdef Gamma
- MultiMap = pow(MultiMap, 2.2);
- #endif
- // Roughness Parameters
- float RoughLin = saturate(clamp(_Roughness, 0.0374, .999) * MultiMap.r);
- float Roughness = RoughLin * RoughLin;
- float RoughSqr = Roughness * Roughness;
- // Metal Parameter
- float Metalness = saturate(_Metalness) * MultiMap.b;
- // Albedo Paremeter
- float3 AlbedoColor = _Color.rgb * tex2D(_AlbedoMap, TRANSFORM_TEX(i.uv0.rg, _AlbedoMap)).rgb;
- #ifdef Gamma
- AlbedoColor = pow(AlbedoColor, 2.2);
- #endif
- // Construct Specular
- float3 SpecularColor = (DielectricSpecular - DielectricSpecular * Metalness) + AlbedoColor * Metalness; // 2 mad
- // Remove metal colors from Albedo
- AlbedoColor = AlbedoColor - AlbedoColor * Metalness; // 1 mad
- // f0 is the refractive % of specular
- float3 f0 = SpecularColor;
- // BRDF
- float3 F = F_Schlick(f0, LdotH);
- float D = D_GGX_Frost(NdotH, RoughSqr);
- float Vis = V_SmithGGXCorrelated(NdotV, NdotL, RoughSqr);
- float3 DirectSpec = F * (D * Vis * InvPi);
- // Attenuation for diffuse and specular reflection
- float DirectAttenuation = LIGHT_ATTENUATION(i) * NdotL;
- float3 DirectAttenColor = _LightColor0.rgb * DirectAttenuation * Pi;
- // Direct Diffuse
- float3 SimpleEnergyConservation = 1.0 - F_Schlick(f0, NdotL);
- float3 DirectDiff = AlbedoColor * InvPi * SimpleEnergyConservation;
- // Combined Direct Light
- float3 Direct = (DirectDiff + DirectSpec) * DirectAttenColor;
- // Indirect Diffuse contribution
- float3 IndirectDiff = SHLookup(normalDir) * AlbedoColor;
- // Indirect Specular contribution
- float4 lookup = float4(reflectionDir, RoughLin * 8.0);
- float4 specCubeHDR = texCUBElod(_SpecCubeIBL, lookup);
- float3 specCube = fromRGBM(specCubeHDR);
- #ifdef Gamma
- specCube = pow(specCube, 2.2);
- #endif
- float3 EnvBRDF = EnvBRDFApprox(f0, RoughLin, NdotV);
- // Combine diffuse and specular Indirect
- float3 Indirect = IndirectDiff + specCube * EnvBRDF;
- IBLMask = 1.0 - saturate(-normalDir.g) * IBLMask;
- Indirect *= IBLMask * IndirectStrength;
- // Ambient Occlusion
- ambientOcclusion = MultiMap.g;
- // Final
- float3 finalColor = Direct + Indirect * ambientOcclusion;
- #ifdef tonemappingEnabled
- finalColor = Tonemap(finalColor);
- #endif
- #ifdef tonemappingDisabled
- #ifdef Gamma
- finalColor = pow(finalColor, 0.4545);
- #endif
- #endif
- return float4(finalColor, 1.0);
- }
- ENDCG
- }
- Pass {
- Name "ForwardAdd"
- Tags {"LightMode"="ForwardAdd"}
- Blend One One
- CGPROGRAM
- // Allows Unity to switch between Linear and Gamma space. The tonemapper must update afterwards
- #pragma multi_compile Linear Gamma
- #pragma target 3.0
- #pragma exclude_renderers flash
- #pragma multi_compile_fwdadd
- #pragma vertex vert
- #pragma fragment frag
- #include "UnityCG.cginc"
- #include "AutoLight.cginc"
- ////////////// Vertex Shader
- struct VertexInput {
- float4 vertex : POSITION;
- float4 texcoord : TEXCOORD0;
- float3 normal : NORMAL;
- float4 tangent : TANGENT;
- };
- struct VertexOutput {
- float4 pos : SV_POSITION;
- float4 uv0 : TEXCOORD0;
- float4 posWorld : TEXCOORD1;
- float3 normalWorld : TEXCOORD2;
- float3 tangentWorld : TEXCOORD3;
- float3 binormalWorld : TEXCOORD4;
- LIGHTING_COORDS(5,6)
- };
- VertexOutput vert (VertexInput v) {
- VertexOutput o;
- o.uv0 = v.texcoord;
- o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
- o.posWorld = mul(_Object2World, v.vertex);
- // Construct the vectors for transforming normal maps to world space
- o.normalWorld = normalize(mul(float4(v.normal, 0.0), _World2Object).xyz);
- o.tangentWorld = normalize(mul(_Object2World, float4(v.tangent.xyz, 0.0)).xyz);
- o.binormalWorld = normalize(cross(o.normalWorld, o.tangentWorld) * v.tangent.w);
- TRANSFER_VERTEX_TO_FRAGMENT(o);
- return o;
- }
- ////////////// Properties
- half4 _Color;
- sampler2D _AlbedoMap; half4 _AlbedoMap_ST;
- sampler2D _MultiMap; half4 _MultiMap_ST;
- sampler2D _Normal; half4 _Normal_ST;
- half _Metalness;
- half _Roughness;
- // Light Color
- uniform float4 _LightColor0;
- #define DielectricSpecular (0.04, 0.04, 0.04)
- #define Pi 3.14159
- #define InvPi 0.318309
- ////////////// Functions
- ////////////// Specular BRDF
- // Same cost but likely better than pow(x, 5)
- inline float pow5(float i) {
- float i5 = i * i;
- return i5 * i5 * i;
- }
- // Fresnel - Schlick
- inline float3 F_Schlick(float3 f0, float u) {
- float InvU = 1.0 - u;
- return f0 + (1.0 - f0) * pow5(InvU);
- }
- // Distribution - [Lagarde 2014, "Moving Frostbite to Physically Based Rendering"
- inline float D_GGX_Frost(float NdotH, float m2) {
- float f = (NdotH * m2 - NdotH) * NdotH + 1;
- return m2 / (f * f);
- }
- // Geometric - [Lagarde 2014, "Moving Frostbite to Physically Based Rendering"]
- inline float V_SmithGGXCorrelated (float NdotV, float NdotL, float alphaG2 ) {
- float Lambda_GGXV = NdotL * sqrt (( -NdotV * alphaG2 + NdotV ) * NdotV + alphaG2 );
- float Lambda_GGXL = NdotV * sqrt (( -NdotL * alphaG2 + NdotL ) * NdotL + alphaG2 );
- return 0.5 / ( Lambda_GGXV + Lambda_GGXL );
- }
- ////////////// Fragment Shader
- float4 frag(VertexOutput i) : COLOR {
- // Construct the world space normal direction
- float3 normalLocal = UnpackNormal(tex2D(_Normal, TRANSFORM_TEX(i.uv0.rg, _Normal)));
- float3x3 local2WorldTranspose = float3x3(
- i.tangentWorld,
- i.binormalWorld,
- i.normalWorld);
- float3 normalDir = normalize(mul(normalLocal, local2WorldTranspose));
- // Construct the world space view direction
- float3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.posWorld.xyz);
- // Construct the world space light direction
- float3 lightDir;
- // Directional light?
- if (0.0 == _WorldSpaceLightPos0.w) {
- lightDir = normalize(_WorldSpaceLightPos0.xyz); }
- // Point or Spot light
- else {
- float3 vertexToLightSource = _WorldSpaceLightPos0.xyz - i.posWorld.xyz;
- float distance = length(vertexToLightSource);
- lightDir = normalize(vertexToLightSource); }
- // Dot Products
- float3 halfDir = normalize (viewDir + lightDir);
- float LdotH = saturate(dot(lightDir, halfDir));
- float NdotH = saturate(dot(normalDir, halfDir));
- float NdotL = saturate(dot(normalDir, lightDir));
- float NdotV = abs(dot(normalDir, viewDir)) + 1e-5f; // avoid artifact
- float3 MultiMap = tex2D(_MultiMap, TRANSFORM_TEX(i.uv0.rg, _MultiMap)).rgb;
- #ifdef Gamma
- MultiMap = pow(MultiMap, 2.2);
- #endif
- // Roughness Parameters
- float RoughLin = saturate(clamp(_Roughness, 0.0374, .999) * MultiMap.r);
- float Roughness = RoughLin * RoughLin;
- float RoughSqr = Roughness * Roughness;
- // Metal Parameter
- float Metalness = saturate(_Metalness) * MultiMap.b;
- // Albedo Paremeter
- float3 AlbedoColor = _Color.rgb * tex2D(_AlbedoMap, TRANSFORM_TEX(i.uv0.rg, _AlbedoMap)).rgb;
- #ifdef Gamma
- AlbedoColor = pow(AlbedoColor, 2.2);
- #endif
- // Construct Specular
- float3 SpecularColor = (DielectricSpecular - DielectricSpecular * Metalness) + AlbedoColor * Metalness; // 2 mad
- // Remove metal colors from Albedo
- AlbedoColor = AlbedoColor - AlbedoColor * Metalness; // 1 mad
- // f0 is the refractive % of specular
- float3 f0 = SpecularColor;
- // BRDF
- float3 F = F_Schlick(f0, LdotH);
- float D = D_GGX_Frost(NdotH, RoughSqr);
- float Vis = V_SmithGGXCorrelated(NdotV, NdotL, RoughSqr);
- float3 DirectSpec = F * (D * Vis * InvPi);
- // Attenuation for diffuse and specular reflection
- float DirectAttenuation = LIGHT_ATTENUATION(i) * NdotL;
- float3 DirectAttenColor = _LightColor0.rgb * DirectAttenuation * Pi;
- // Direct Diffuse
- float3 SimpleEnergyConservation = 1.0 - F_Schlick(f0, NdotL);
- float3 DirectDiff = AlbedoColor * InvPi * SimpleEnergyConservation;
- // Final
- float3 finalColor = (DirectDiff + DirectSpec) * DirectAttenColor;
- #ifdef Gamma
- finalColor = pow(finalColor, 0.4545);
- #endif
- return float4(finalColor, 1.0);
- }
- ENDCG
- }
- }
- FallBack "Diffuse"
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement