1
0
mirror of https://github.com/ncblakely/GiantsTools synced 2024-12-23 15:57:22 +01:00
GiantsTools/Sdk/External/DirectXTK/Src/Shaders/PBRCommon.fxh
2021-01-23 15:40:09 -08:00

171 lines
5.5 KiB
HLSL

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//
// http://go.microsoft.com/fwlink/?LinkId=248926
// http://go.microsoft.com/fwlink/?LinkId=248929
// http://go.microsoft.com/fwlink/?LinkID=615561
// http://create.msdn.com/en-US/education/catalog/sample/stock_effects
struct CommonVSOutputPixelLighting
{
float4 Pos_ps;
float3 Pos_ws;
float3 Normal_ws;
};
struct VSOut_Velocity
{
VSOutputPixelLightingTx current;
float4 prevPosition : TEXCOORD4;
};
CommonVSOutputPixelLighting ComputeCommonVSOutputPixelLighting(float4 position, float3 normal)
{
CommonVSOutputPixelLighting vout;
vout.Pos_ps = mul(position, WorldViewProj);
vout.Pos_ws = mul(position, World).xyz;
vout.Normal_ws = normalize(mul(normal, WorldInverseTranspose));
return vout;
}
static const float PI = 3.14159265f;
static const float EPSILON = 1e-6f;
// Shlick's approximation of Fresnel
// https://en.wikipedia.org/wiki/Schlick%27s_approximation
float3 Fresnel_Shlick(in float3 f0, in float3 f90, in float x)
{
return f0 + (f90 - f0) * pow(1.f - x, 5.f);
}
// Burley B. "Physically Based Shading at Disney"
// SIGGRAPH 2012 Course: Practical Physically Based Shading in Film and Game Production, 2012.
float Diffuse_Burley(in float NdotL, in float NdotV, in float LdotH, in float roughness)
{
float fd90 = 0.5f + 2.f * roughness * LdotH * LdotH;
return Fresnel_Shlick(1, fd90, NdotL).x * Fresnel_Shlick(1, fd90, NdotV).x;
}
// GGX specular D (normal distribution)
// https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf
float Specular_D_GGX(in float alpha, in float NdotH)
{
const float alpha2 = alpha * alpha;
const float lower = (NdotH * NdotH * (alpha2 - 1)) + 1;
return alpha2 / max(EPSILON, PI * lower * lower);
}
// Schlick-Smith specular G (visibility) with Hable's LdotH optimization
// http://www.cs.virginia.edu/~jdl/bib/appearance/analytic%20models/schlick94b.pdf
// http://graphicrants.blogspot.se/2013/08/specular-brdf-reference.html
float G_Shlick_Smith_Hable(float alpha, float LdotH)
{
return rcp(lerp(LdotH * LdotH, 1, alpha * alpha * 0.25f));
}
// A microfacet based BRDF.
//
// alpha: This is roughness * roughness as in the "Disney" PBR model by Burley et al.
//
// specularColor: The F0 reflectance value - 0.04 for non-metals, or RGB for metals. This follows model
// used by Unreal Engine 4.
//
// NdotV, NdotL, LdotH, NdotH: vector relationships between,
// N - surface normal
// V - eye normal
// L - light normal
// H - half vector between L & V.
float3 Specular_BRDF(in float alpha, in float3 specularColor, in float NdotV, in float NdotL, in float LdotH, in float NdotH)
{
// Specular D (microfacet normal distribution) component
float specular_D = Specular_D_GGX(alpha, NdotH);
// Specular Fresnel
float3 specular_F = Fresnel_Shlick(specularColor, 1, LdotH);
// Specular G (visibility) component
float specular_G = G_Shlick_Smith_Hable(alpha, LdotH);
return specular_D * specular_F * specular_G;
}
// Diffuse irradiance
float3 Diffuse_IBL(in float3 N)
{
return IrradianceTexture.Sample(IBLSampler, N);
}
// Approximate specular image based lighting by sampling radiance map at lower mips
// according to roughness, then modulating by Fresnel term.
float3 Specular_IBL(in float3 N, in float3 V, in float lodBias)
{
float mip = lodBias * NumRadianceMipLevels;
float3 dir = reflect(-V, N);
return RadianceTexture.SampleLevel(IBLSampler, dir, mip);
}
// Apply Disney-style physically based rendering to a surface with:
//
// V, N: Eye and surface normals
//
// numLights: Number of directional lights.
//
// lightColor[]: Color and intensity of directional light.
//
// lightDirection[]: Light direction.
float3 LightSurface(
in float3 V, in float3 N,
in int numLights, in float3 lightColor[3], in float3 lightDirection[3],
in float3 albedo, in float roughness, in float metallic, in float ambientOcclusion)
{
// Specular coefficiant - fixed reflectance value for non-metals
static const float kSpecularCoefficient = 0.04;
const float NdotV = saturate(dot(N, V));
// Burley roughness bias
const float alpha = roughness * roughness;
// Blend base colors
const float3 c_diff = lerp(albedo, float3(0, 0, 0), metallic) * ambientOcclusion;
const float3 c_spec = lerp(kSpecularCoefficient, albedo, metallic) * ambientOcclusion;
// Output color
float3 acc_color = 0;
// Accumulate light values
for (int i = 0; i < numLights; i++)
{
// light vector (to light)
const float3 L = normalize(-lightDirection[i]);
// Half vector
const float3 H = normalize(L + V);
// products
const float NdotL = saturate(dot(N, L));
const float LdotH = saturate(dot(L, H));
const float NdotH = saturate(dot(N, H));
// Diffuse & specular factors
float diffuse_factor = Diffuse_Burley(NdotL, NdotV, LdotH, roughness);
float3 specular = Specular_BRDF(alpha, c_spec, NdotV, NdotL, LdotH, NdotH);
// Directional light
acc_color += NdotL * lightColor[i] * (((c_diff * diffuse_factor) + specular));
}
// Add diffuse irradiance
float3 diffuse_env = Diffuse_IBL(N);
acc_color += c_diff * diffuse_env;
// Add specular radiance
float3 specular_env = Specular_IBL(N, V, roughness);
acc_color += c_spec * specular_env;
return acc_color;
}