mirror of
https://github.com/ncblakely/GiantsTools
synced 2024-11-05 23:05:38 +01:00
171 lines
5.5 KiB
HLSL
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;
|
|
}
|