185 lines
7.0 KiB
HLSL
185 lines
7.0 KiB
HLSL
#ifndef UNITY_PBS_LIGHTING_INCLUDED
|
|
#define UNITY_PBS_LIGHTING_INCLUDED
|
|
|
|
#include "UnityShaderVariables.cginc"
|
|
#include "UnityStandardConfig.cginc"
|
|
#include "UnityLightingCommon.cginc"
|
|
#include "UnityGlobalIllumination.cginc"
|
|
|
|
//-------------------------------------------------------------------------------------
|
|
// Default BRDF to use:
|
|
#if !defined (UNITY_BRDF_PBS) // allow to explicitly override BRDF in custom shader
|
|
#if (SHADER_TARGET < 30) || defined(SHADER_API_PSP2)
|
|
// Fallback to low fidelity one for pre-SM3.0
|
|
#define UNITY_BRDF_PBS BRDF3_Unity_PBS
|
|
#elif defined(SHADER_API_MOBILE)
|
|
// Somewhat simplified for mobile
|
|
#define UNITY_BRDF_PBS BRDF2_Unity_PBS
|
|
#else
|
|
// Full quality for SM3+ PC / consoles
|
|
#define UNITY_BRDF_PBS BRDF1_Unity_PBS
|
|
#endif
|
|
#endif
|
|
|
|
//-------------------------------------------------------------------------------------
|
|
// BRDF for lights extracted from *indirect* directional lightmaps (baked and realtime).
|
|
// Baked directional lightmap with *direct* light uses UNITY_BRDF_PBS.
|
|
// For better quality change to BRDF1_Unity_PBS.
|
|
// No directional lightmaps in SM2.0.
|
|
|
|
#if !defined(UNITY_BRDF_PBS_LIGHTMAP_INDIRECT)
|
|
#define UNITY_BRDF_PBS_LIGHTMAP_INDIRECT BRDF2_Unity_PBS
|
|
#endif
|
|
#if !defined (UNITY_BRDF_GI)
|
|
#define UNITY_BRDF_GI BRDF_Unity_Indirect
|
|
#endif
|
|
|
|
//-------------------------------------------------------------------------------------
|
|
|
|
|
|
inline half3 BRDF_Unity_Indirect (half3 baseColor, half3 specColor, half oneMinusReflectivity, half oneMinusRoughness, half3 normal, half3 viewDir, half occlusion, UnityGI gi)
|
|
{
|
|
half3 c = 0;
|
|
#if defined(DIRLIGHTMAP_SEPARATE)
|
|
gi.indirect.diffuse = 0;
|
|
gi.indirect.specular = 0;
|
|
|
|
#ifdef LIGHTMAP_ON
|
|
c += UNITY_BRDF_PBS_LIGHTMAP_INDIRECT (baseColor, specColor, oneMinusReflectivity, oneMinusRoughness, normal, viewDir, gi.light2, gi.indirect).rgb * occlusion;
|
|
#endif
|
|
#ifdef DYNAMICLIGHTMAP_ON
|
|
c += UNITY_BRDF_PBS_LIGHTMAP_INDIRECT (baseColor, specColor, oneMinusReflectivity, oneMinusRoughness, normal, viewDir, gi.light3, gi.indirect).rgb * occlusion;
|
|
#endif
|
|
#endif
|
|
return c;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// Surface shader output structure to be used with physically
|
|
// based shading model.
|
|
|
|
//-------------------------------------------------------------------------------------
|
|
// Metallic workflow
|
|
|
|
// Define output struct unless it's already defined
|
|
#ifndef SurfaceOutputStandard
|
|
struct SurfaceOutputStandard
|
|
{
|
|
half3 Albedo; // base (diffuse or specular) color
|
|
half3 Normal; // tangent space normal, if written
|
|
half3 Emission;
|
|
half Metallic; // 0=non-metal, 1=metal
|
|
half Smoothness; // 0=rough, 1=smooth
|
|
half Occlusion; // occlusion (default 1)
|
|
half Alpha; // alpha for transparencies
|
|
};
|
|
#endif
|
|
|
|
inline half4 LightingStandard (SurfaceOutputStandard s, half3 viewDir, UnityGI gi)
|
|
{
|
|
s.Normal = normalize(s.Normal);
|
|
|
|
half oneMinusReflectivity;
|
|
half3 specColor;
|
|
s.Albedo = DiffuseAndSpecularFromMetallic (s.Albedo, s.Metallic, /*out*/ specColor, /*out*/ oneMinusReflectivity);
|
|
|
|
// shader relies on pre-multiply alpha-blend (_SrcBlend = One, _DstBlend = OneMinusSrcAlpha)
|
|
// this is necessary to handle transparency in physically correct way - only diffuse component gets affected by alpha
|
|
half outputAlpha;
|
|
s.Albedo = PreMultiplyAlpha (s.Albedo, s.Alpha, oneMinusReflectivity, /*out*/ outputAlpha);
|
|
|
|
half4 c = UNITY_BRDF_PBS (s.Albedo, specColor, oneMinusReflectivity, s.Smoothness, s.Normal, viewDir, gi.light, gi.indirect);
|
|
c.rgb += UNITY_BRDF_GI (s.Albedo, specColor, oneMinusReflectivity, s.Smoothness, s.Normal, viewDir, s.Occlusion, gi);
|
|
c.a = outputAlpha;
|
|
return c;
|
|
}
|
|
|
|
inline half4 LightingStandard_Deferred (SurfaceOutputStandard s, half3 viewDir, UnityGI gi, out half4 outDiffuseOcclusion, out half4 outSpecSmoothness, out half4 outNormal)
|
|
{
|
|
half oneMinusReflectivity;
|
|
half3 specColor;
|
|
s.Albedo = DiffuseAndSpecularFromMetallic (s.Albedo, s.Metallic, /*out*/ specColor, /*out*/ oneMinusReflectivity);
|
|
|
|
half4 c = UNITY_BRDF_PBS (s.Albedo, specColor, oneMinusReflectivity, s.Smoothness, s.Normal, viewDir, gi.light, gi.indirect);
|
|
c.rgb += UNITY_BRDF_GI (s.Albedo, specColor, oneMinusReflectivity, s.Smoothness, s.Normal, viewDir, s.Occlusion, gi);
|
|
|
|
outDiffuseOcclusion = half4(s.Albedo, s.Occlusion);
|
|
outSpecSmoothness = half4(specColor, s.Smoothness);
|
|
outNormal = half4(s.Normal * 0.5 + 0.5, 1);
|
|
half4 emission = half4(s.Emission + c.rgb, 1);
|
|
return emission;
|
|
}
|
|
|
|
inline void LightingStandard_GI (
|
|
SurfaceOutputStandard s,
|
|
UnityGIInput data,
|
|
inout UnityGI gi)
|
|
{
|
|
gi = UnityGlobalIllumination (data, s.Occlusion, s.Smoothness, s.Normal);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------------
|
|
// Specular workflow
|
|
|
|
// Define output struct unless it's already defined
|
|
#ifndef SurfaceOutputStandardSpecular
|
|
struct SurfaceOutputStandardSpecular
|
|
{
|
|
half3 Albedo; // diffuse color
|
|
half3 Specular; // specular color
|
|
half3 Normal; // tangent space normal, if written
|
|
half3 Emission;
|
|
half Smoothness; // 0=rough, 1=smooth
|
|
half Occlusion; // occlusion (default 1)
|
|
half Alpha; // alpha for transparencies
|
|
};
|
|
#endif
|
|
|
|
inline half4 LightingStandardSpecular (SurfaceOutputStandardSpecular s, half3 viewDir, UnityGI gi)
|
|
{
|
|
s.Normal = normalize(s.Normal);
|
|
|
|
// energy conservation
|
|
half oneMinusReflectivity;
|
|
s.Albedo = EnergyConservationBetweenDiffuseAndSpecular (s.Albedo, s.Specular, /*out*/ oneMinusReflectivity);
|
|
|
|
// shader relies on pre-multiply alpha-blend (_SrcBlend = One, _DstBlend = OneMinusSrcAlpha)
|
|
// this is necessary to handle transparency in physically correct way - only diffuse component gets affected by alpha
|
|
half outputAlpha;
|
|
s.Albedo = PreMultiplyAlpha (s.Albedo, s.Alpha, oneMinusReflectivity, /*out*/ outputAlpha);
|
|
|
|
half4 c = UNITY_BRDF_PBS (s.Albedo, s.Specular, oneMinusReflectivity, s.Smoothness, s.Normal, viewDir, gi.light, gi.indirect);
|
|
c.rgb += UNITY_BRDF_GI (s.Albedo, s.Specular, oneMinusReflectivity, s.Smoothness, s.Normal, viewDir, s.Occlusion, gi);
|
|
c.a = outputAlpha;
|
|
return c;
|
|
}
|
|
|
|
inline half4 LightingStandardSpecular_Deferred (SurfaceOutputStandardSpecular s, half3 viewDir, UnityGI gi, out half4 outDiffuseOcclusion, out half4 outSpecSmoothness, out half4 outNormal)
|
|
{
|
|
// energy conservation
|
|
half oneMinusReflectivity;
|
|
s.Albedo = EnergyConservationBetweenDiffuseAndSpecular (s.Albedo, s.Specular, /*out*/ oneMinusReflectivity);
|
|
|
|
half4 c = UNITY_BRDF_PBS (s.Albedo, s.Specular, oneMinusReflectivity, s.Smoothness, s.Normal, viewDir, gi.light, gi.indirect);
|
|
c.rgb += UNITY_BRDF_GI (s.Albedo, s.Specular, oneMinusReflectivity, s.Smoothness, s.Normal, viewDir, s.Occlusion, gi);
|
|
|
|
outDiffuseOcclusion = half4(s.Albedo, s.Occlusion);
|
|
outSpecSmoothness = half4(s.Specular, s.Smoothness);
|
|
outNormal = half4(s.Normal * 0.5 + 0.5, 1);
|
|
half4 emission = half4(s.Emission + c.rgb, 1);
|
|
return emission;
|
|
}
|
|
|
|
inline void LightingStandardSpecular_GI (
|
|
SurfaceOutputStandardSpecular s,
|
|
UnityGIInput data,
|
|
inout UnityGI gi)
|
|
{
|
|
gi = UnityGlobalIllumination (data, s.Occlusion, s.Smoothness, s.Normal);
|
|
}
|
|
|
|
#endif // UNITY_PBS_LIGHTING_INCLUDED
|