下面是截取的部分光照计算shader片段,回答相关问题
#define PI 3.14159265359f
#define METALLIC 0
#define NDF_GGX 1
#define FRESNEL_SCHLICK 1
#define GEOMETRIC_SMITH_SCHLICK_GGX 1
#define DISNEY_BRDF 1
......
struct GBufferVertexShaderOutput
{
float4 Position : SV_POSITION;
float3 Normal : NORMAL0;
float2 TexCoord : TEXCOORD0;
float3x3 tangentToWorld : TEXCOORD2;
float4 pos : NORMAL1;
};
float3 Diffuse(float3 pAlbedo)
{
return pAlbedo/PI;
}
float sqr(float x)
{
return x*x;
}
float GTR2_aniso(float NdH, float HdX, float HdY, float ax, float ay)
{
return 1.0f / (PI * ax*ay * sqr(sqr(HdX/ax) + sqr(HdY/ay) + NdH*NdH));
}
float smithG_GGX(float NdV, float alphaG)
{
float a = alphaG*alphaG;
float b = NdV*NdV;
return 1.0f / (NdV + sqrt(a + b - a*b));
}
float GTR1(float NdH, float a)
{
if (a >= 1.0f)
{
return 1.0f / PI;
}
float a2 = a*a;
float t = 1.0f + (a2 - 1.0f) * NdH * NdH;
return (a2 - 1.0f) / (PI*log(a2)*t);
}
//////////////////////////////////////////////////////////////////////
float NormalDistribution_GGX(float a, float b)
{
// Isotropic ggx.
float a2 = a*a;
float b2 = b * b;
float denominator = b2 * (a2 - 1.0f) + 1.0f;
denominator *= denominator;
denominator *= PI;
return a2 / denominator;
}
float Geometric_GGX(float a, float dotValue)
{
float a2 = a * a;
return (2.0f * dotValue) / (dotValue + sqrt(a2 + ((1.0f - a2) * (dotValue * dotValue))));
}
float Geometric_Smith_GGX(float a, float b, float c)
{
return Geometric_GGX(a, b) * Geometric_GGX(a, c);
}
float Geometric_Smith_Schlick_GGX(float a, float b, float c)
{
//2)? ? ?
}
//////////////////////////////////////////////////////////////////////
float3 Fresnel_None(float3 specularColor)
{
return specularColor;
}
float Fresnel_Schlick(float u)
{
float m = saturate( 1.0f - u);
float m2 = m*m;
return m2*m2*m;
}
float3 Fresnel_Schlick(float3 specularColor, float3 h, float3 v)
{
//1)return (specularColor + (1.0f - specularColor) * ? ? ?;
}
//////////////////////////////////////////////////////////////////////
float Specular_D(float a, float b)
{
return NormalDistribution_GGX(a, b);
}
float3 Specular_F(float3 specularColor, float3 h, float3 v)
{
#ifdef FRESNEL_NONE
return Fresnel_None(specularColor);
#elif FRESNEL_SCHLICK
return Fresnel_Schlick(specularColor, h, v);
#endif
}
float Specular_G(float a, float b, float c, float d, float e, float f)
{
#ifdef GEOMETRIC_SMITH_GGX
return Geometric_Smith_GGX(a, b, c);
#elif GEOMETRIC_SMITH_SCHLICK_GGX
return Geometric_Smith_Schlick_GGX(a, b, c);
#endif
}
float3 Specular(float3 specularColor, float3 h, float3 v, float3 l, float a, float NdL, float NdV, float NdH, float VdH, float LdV)
{
//3)return ((Specular_D(??, ??) * Specular_G(??, ??, ??, ??, ??, ??)) * Specular_F(specularColor, v, h) ) / (4.0f * NdL * NdV + 0.0001f);
}
float3 ComputeLight(float3 albedoColor,float3 specularColor, float3 normal, float roughness, float3 lightPosition, float3 lightColor, float3 lightDir, float3 viewDir)
{
// Compute some useful values.
float NdL = saturate(dot(normal, lightDir));
float NdV = saturate(dot(normal, viewDir));
float3 h = normalize(lightDir + viewDir);
float NdH = saturate(dot(normal, h));
float VdH = saturate(dot(viewDir, h));
float LdV = saturate(dot(lightDir, viewDir));
float a = max(0.001f, roughness * roughness);
float3 cDiff = Diffuse(albedoColor);
float3 cSpec = Specular(specularColor, h, viewDir, lightDir, a, NdL, NdV, NdH, VdH, LdV);
return lightColor * NdL * (cDiff * (1.0f - cSpec) + cSpec);
}
//////////////////////////////////////////////////////////////////////
float3 DisneyBRDF(float3 baseColor,out float3 specularColor, float3 normal, float roughness, float3 lightDir, float3 viewDir, float3 X, float3 Y, out float3 diffuse)
{
// Compute some useful values.
float NdL = saturate(dot(normal, lightDir));
float NdV = saturate(dot(normal, viewDir));
float3 h = normalize(lightDir + viewDir);
float NdH = saturate(dot(normal, h));
float VdH = saturate(dot(viewDir, h));
float LdV = saturate(dot(lightDir, viewDir));
float LdH = saturate(dot(lightDir, h));
float a = max(0.001f, roughness * roughness);
float luminance = 0.3f * baseColor.x + 0.6f * baseColor.y + 0.1f * baseColor.z;
float3 tint = luminance > 0.0f ? baseColor/luminance : 1.0f; // Normalize luminance to isolate hue+sat.
specularColor = lerp(g_Specular * 0.08f * lerp(1.0f, tint, g_SpecularTint), baseColor, g_Metallic);
float3 CSheen = lerp(1.0f, tint, g_SheenTint);
float FL = Fresnel_Schlick(NdL);
float FV = Fresnel_Schlick(NdV);
float Fd90 = 0.5f + 2.0f * LdH * LdH * a;
float Fd = lerp(1.0f, Fd90, FL) * lerp(1.0f, Fd90, FV);
float Fss90 = LdH * LdH * a;
float Fss = lerp(1.0f, Fss90, FL) * lerp(1.0f, Fss90, FV);
float ss = 1.25f * (Fss * (1.0f / (NdL + NdV + 0.0001f) - 0.5f) + 0.5f);
// Specular
float aspect = sqrt(1.0f - g_Anisotropic*0.9f);
float ax = max(0.001f, sqr(a)/aspect);
float ay = max(0.001f, sqr(a)*aspect);
float Ds = GTR2_aniso(NdH, dot(h, X), dot(h, Y), ax, ay);
float FH = Fresnel_Schlick(LdH);
float3 Fs = lerp(specularColor, 1.0f, FH);
float roughg = sqr(a*0.5f+0.5f);
float Gs = smithG_GGX(NdL, roughg) * smithG_GGX(NdV, roughg);
// Sheen
float3 Fsheen = FH * g_Sheen * CSheen;
float Dr = GTR1(NdH, lerp(0.1f, 0.001f, g_ClearcoatGloss));
float Fr = lerp(0.04f, 1.0f, FH);
float Gr = smithG_GGX(NdL, 0.25f) * smithG_GGX(NdV, 0.25f);
diffuse = ((1.0f/PI) * lerp(Fd, ss, g_Subsurface) * baseColor + Fsheen) * (1.0f - g_Metallic);
return (diffuse + Gs*Fs*Ds + 0.25f*g_Clearcoat*Gr*Fr*Dr)*NdL;
}
//////////////////////////////////////////////////////////////////////
float4 main(GBufferVertexShaderOutput input) : SV_TARGET
{
......
#ifdef METALLIC
// Lerp with metallic value to find the good diffuse and specular.
float3 realAlbedo = albedoColor - albedoColor * metallic;
// 0.03 default specular value for dielectric.
float3 realSpecularColor = lerp(0.03f, albedoColor, metallic);
#elif DISNEY_BRDF
float3 realAlbedo = albedoColor + g_UserAlbedo * g_OverrideAlbedo;
float3 realSpecularColor = lerp(0.03f, albedoColor, metallic);
#endif
#ifndef DISNEY_BRDF
float3 light1 = ComputeLight( realAlbedo, realSpecularColor, normal, roughness, lightPosition.xyz, lightColor, lightDir, viewDir);
#else
float3 spec = 0.0f;
float3 diffuse = 0.0f;
float3 light1 = DisneyBRDF(albedoColor, spec, normal, roughness, lightDir, viewDir, input.tangentToWorld[0], input.tangentToWorld[1], diffuse);
#endif
......
}
1)解释一下菲涅尔效果主要作用,并补全Fresnel_Schlick函数
2)补全Geometric_Smith_Schlick_GGX函数
3)补全Specular函数