Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added missing brdf and tonemapping files to viewer
- Loading branch information
1 parent
b95afd2
commit d38c8ce
Showing
2 changed files
with
230 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
// Adapted from https://github.com/KhronosGroup/glTF-Sample-Viewer/blob/master/src/shaders/brdf.glsl | ||
|
||
#pragma once | ||
#include <cmath> | ||
|
||
// | ||
// Fresnel | ||
// | ||
// http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html | ||
// https://github.com/wdas/brdf/tree/master/src/brdfs | ||
// https://google.github.io/filament/Filament.md.html | ||
inline vec3 F_None(vec3 f0, vec3 f90, float VdotH) { | ||
return f0; | ||
} | ||
|
||
// The following equation models the Fresnel reflectance term of the spec equation (aka F()) | ||
// Implementation of fresnel from [4], Equation 15 | ||
inline vec3 F_Schlick(vec3 f0, vec3 f90, float VdotH) { | ||
return f0 + (f90 - f0) * pow(clamp(1 - VdotH, 0.0f, 1.0f), 5); | ||
} | ||
|
||
inline vec3 F_CookTorrance(vec3 f0, vec3 f90, float VdotH) { | ||
vec3 f0_sqrt = sqrt(f0); | ||
vec3 ior = (1 + f0_sqrt) / (1 - f0_sqrt); | ||
vec3 c = vec3(VdotH); | ||
vec3 g = sqrt(ior * ior + c*c - 1); | ||
return 0.5f * pow(g-c, vec3(2)) / | ||
pow(g+c, vec3(2)) * (1 + pow(c*(g+c) - 1, 2) / pow(c*(g-c) + 1, 2)); | ||
} | ||
|
||
// Smith Joint GGX | ||
// Note: Vis = G / (4 * NdotL * NdotV) | ||
// see Eric Heitz. 2014. Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs. Journal of Computer Graphics Techniques, 3 | ||
// see Real-Time Rendering. Page 331 to 336. | ||
// see https://google.github.io/filament/Filament.md.html#materialsystem/specularbrdf/geometricshadowing(specularg) | ||
inline float V_GGX(float NdotL, float NdotV, float alphaRoughness) { | ||
float r2 = alphaRoughness * alphaRoughness; | ||
|
||
float GGXV = NdotL * sqrt(NdotV * NdotV * (1 - r2) + r2); | ||
float GGXL = NdotV * sqrt(NdotL * NdotL * (1 - r2) + r2); | ||
|
||
float GGX = GGXV + GGXL; | ||
return (GGX > 0) ? 0.5f / GGX : 0; | ||
} | ||
|
||
// Anisotropic GGX visibility function, with height correlation. | ||
// T: Tanget, B: Bi-tanget | ||
inline float V_GGX_anisotropic(float NdotL, float NdotV, float BdotV, | ||
float TdotV, float TdotL, float BdotL, float anisotropy, float at, float ab) { | ||
float GGXV = NdotL * length(vec3(at * TdotV, ab * BdotV, NdotV)); | ||
float GGXL = NdotV * length(vec3(at * TdotL, ab * BdotL, NdotL)); | ||
float v = 0.5f / (GGXV + GGXL); | ||
return clamp(v, 0.f, 1.f); | ||
} | ||
|
||
// https://github.com/google/filament/blob/master/shaders/src/brdf.fs#L136 | ||
// https://github.com/google/filament/blob/master/libs/ibl/src/CubemapIBL.cpp#L179 | ||
// Note: Google call it V_Ashikhmin and V_Neubelt | ||
inline float V_Ashikhmin(float NdotL, float NdotV) { | ||
return clamp(1 / (4 * (NdotL + NdotV - NdotL * NdotV)), 0.f, 1.f); | ||
} | ||
|
||
// https://github.com/google/filament/blob/master/shaders/src/brdf.fs#L131 | ||
inline float V_Kelemen(float LdotH) { | ||
// Kelemen 2001, "A Microfacet Based Coupled Specular-Matte BRDF Model with Importance Sampling" | ||
return 0.25f / (LdotH * LdotH); | ||
} | ||
|
||
// The following equation(s) model the distribution of microfacet normals across the area being drawn (aka D()) | ||
// Implementation from "Average Irregularity Representation of a Roughened Surface for Ray Reflection" by T. S. Trowbridge, and K. P. Reitz | ||
// Follows the distribution function recommended in the SIGGRAPH 2013 course notes from EPIC Games [1], Equation 3. | ||
inline float D_GGX(float NdotH, float alphaRoughness) { | ||
float alphaRoughnessSq = alphaRoughness * alphaRoughness; | ||
float f = (NdotH * NdotH) * (alphaRoughnessSq - 1) + 1; | ||
return alphaRoughnessSq / (M_PIf32 * f * f); | ||
} | ||
|
||
// Anisotropic GGX NDF with a single anisotropy parameter controlling the normal orientation. | ||
// See https://google.github.io/filament/Filament.html#materialsystem/anisotropicmodel | ||
// T: Tanget, B: Bi-tanget | ||
inline float D_GGX_anisotropic(float NdotH, float TdotH, float BdotH, | ||
float anisotropy, float at, float ab) { | ||
|
||
float a2 = at * ab; | ||
vec3 f = vec3(ab * TdotH, at * BdotH, a2 * NdotH); | ||
float w2 = a2 / dot(f, f); | ||
return a2 * w2 * w2 / M_PIf32; | ||
} | ||
|
||
inline float D_Ashikhmin(float NdotH, float alphaRoughness) { | ||
// Ashikhmin 2007, "Distribution-based BRDFs" | ||
float a2 = alphaRoughness * alphaRoughness; | ||
float cos2h = NdotH * NdotH; | ||
float sin2h = 1.0 - cos2h; | ||
float sin4h = sin2h * sin2h; | ||
float cot2 = -cos2h / (a2 * sin2h); | ||
return 1 / (M_PIf32 * (4 * a2 + 1) * sin4h) * (4 * exp(cot2) + sin4h); | ||
} | ||
|
||
//Sheen implementation------------------------------------------------------------------------------------- | ||
// See https://github.com/sebavan/glTF/tree/KHR_materials_sheen/extensions/2.0/Khronos/KHR_materials_sheen | ||
|
||
// Estevez and Kulla http://www.aconty.com/pdf/s2017_pbs_imageworks_sheen.pdf | ||
inline float D_Charlie(float sheenRoughness, float NdotH) { | ||
sheenRoughness = max(sheenRoughness, 0.000001f); //clamp (0,1] | ||
float alphaG = sheenRoughness * sheenRoughness; | ||
float invR = 1 / alphaG; | ||
float cos2h = NdotH * NdotH; | ||
float sin2h = 1 - cos2h; | ||
return (2 + invR) * pow(sin2h, invR * 0.5f) / (2 * M_PIf32); | ||
} | ||
|
||
//https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#acknowledgments AppendixB | ||
inline vec3 BRDF_lambertian(vec3 f0, vec3 f90, vec3 diffuseColor, float VdotH) { | ||
// see https://seblagarde.wordpress.com/2012/01/08/pi-or-not-to-pi-in-game-lighting-equation/ | ||
return (1 - F_Schlick(f0, f90, VdotH)) * (diffuseColor / M_PIf32); | ||
} | ||
|
||
// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#acknowledgments AppendixB | ||
inline vec3 BRDF_specularGGX(vec3 f0, vec3 f90, float alphaRoughness, | ||
float VdotH, float NdotL, float NdotV, float NdotH) { | ||
|
||
vec3 F = F_Schlick(f0, f90, VdotH); | ||
float Vis = V_GGX(NdotL, NdotV, alphaRoughness); | ||
float D = D_GGX(NdotH, alphaRoughness); | ||
return F * Vis * D; | ||
} | ||
|
||
inline vec3 BRDF_specularAnisotropicGGX(vec3 f0, vec3 f90, | ||
float alphaRoughness, float VdotH, float NdotL, float NdotV, float NdotH, | ||
float BdotV, float TdotV, float TdotL, float BdotL, float TdotH, float BdotH, | ||
float anisotropy) { | ||
|
||
// Roughness along tangent and bitangent. | ||
// Christopher Kulla and Alejandro Conty. 2017. Revisiting Physically Based Shading at Imageworks | ||
float at = max(alphaRoughness * (1 + anisotropy), 0.00001f); | ||
float ab = max(alphaRoughness * (1 - anisotropy), 0.00001f); | ||
|
||
vec3 F = F_Schlick(f0, f90, VdotH); | ||
float V = V_GGX_anisotropic(NdotL, NdotV, BdotV, TdotV, TdotL, BdotL, | ||
anisotropy, at, ab); | ||
float D = D_GGX_anisotropic(NdotH, TdotH, BdotH, anisotropy, at, ab); | ||
|
||
return F * V * D; | ||
} | ||
|
||
// f_sheen | ||
inline vec3 BRDF_specularSheen(vec3 sheenColor, float sheenIntensity, | ||
float sheenRoughness, float NdotL, float NdotV, float NdotH) { | ||
float sheenDistribution = D_Charlie(sheenRoughness, NdotH); | ||
float sheenVisibility = V_Ashikhmin(NdotL, NdotV); | ||
return sheenColor * sheenIntensity * sheenDistribution * sheenVisibility; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
#pragma once | ||
|
||
// linear to sRGB approximation | ||
// see http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html | ||
inline vec3 linearTosRGB(vec3 color) { | ||
const float GAMMA = 2.2; | ||
const float INV_GAMMA = 1.0 / GAMMA; | ||
|
||
return pow(color, vec3(INV_GAMMA)); | ||
} | ||
|
||
// sRGB to linear approximation | ||
// see http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html | ||
inline vec3 sRGBToLinear(vec3 srgbIn) { | ||
const float GAMMA = 2.2; | ||
return vec3(pow(srgbIn.xyz, vec3(GAMMA))); | ||
} | ||
|
||
inline vec4 sRGBToLinear(vec4 srgbIn) { | ||
return vec4(sRGBToLinear(srgbIn.xyz), srgbIn.w); | ||
} | ||
|
||
// Uncharted 2 tone map | ||
// see: http://filmicworlds.com/blog/filmic-tonemapping-operators/ | ||
inline vec3 toneMapUncharted2Impl(vec3 color) { | ||
const float A = 0.15; | ||
const float B = 0.50; | ||
const float C = 0.10; | ||
const float D = 0.20; | ||
const float E = 0.02; | ||
const float F = 0.30; | ||
return ((color*(A*color+C*B)+D*E)/(color*(A*color+B)+D*F))-E/F; | ||
} | ||
|
||
inline vec3 toneMapUncharted(vec3 color) { | ||
const float W = 11.2; | ||
color = toneMapUncharted2Impl(2 * color); | ||
vec3 whiteScale = 1 / toneMapUncharted2Impl(W); | ||
return linearTosRGB(color * whiteScale); | ||
} | ||
|
||
// Hejl Richard tone map | ||
// see: http://filmicworlds.com/blog/filmic-tonemapping-operators/ | ||
inline vec3 toneMapHejlRichard(vec3 color) { | ||
color = max(vec3(0.0), color - vec3(0.004)); | ||
return (color * (6.2f * color + .5f)) / | ||
(color * (6.2f * color + 1.7f) + 0.06f); | ||
} | ||
|
||
// ACES tone map | ||
// see: https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/ | ||
inline vec3 toneMapACES(vec3 color) { | ||
const float A = 2.51; | ||
const float B = 0.03; | ||
const float C = 2.43; | ||
const float D = 0.59; | ||
const float E = 0.14; | ||
return linearTosRGB(clamp((color * (A * color + B)) / (color * (C * color + D) + E), 0.f, 1.f)); | ||
} | ||
|
||
inline vec3 toneMap(vec3 color, float exposure) { | ||
color *= exposure; | ||
/* | ||
#ifdef TONEMAP_UNCHARTED | ||
return toneMapUncharted(color); | ||
#endif | ||
#ifdef TONEMAP_HEJLRICHARD | ||
return toneMapHejlRichard(color); | ||
#endif | ||
#ifdef TONEMAP_ACES | ||
return toneMapACES(color); | ||
#endif | ||
*/ | ||
return linearTosRGB(color); | ||
} |