Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Correctly interpret material roughness as perceptual and convert to material #34

Merged
merged 4 commits into from
Jul 8, 2017
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions shaders/pbr-frag.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ struct PBRInfo
vec3 baseColor;
vec3 reflectance0;
vec3 reflectance90;
float alpha;
};

const float M_PI = 3.141592653589793;
Expand All @@ -72,7 +73,7 @@ const float c_MinRoughness = 0.04;
// Implementation of diffuse from "Physically-Based Shading at Disney" by Brent Burley
vec3 disneyDiffuse(PBRInfo pbrInputs)
{
float f90 = 2.*pbrInputs.LdotH*pbrInputs.LdotH*pbrInputs.roughness - 0.5;
float f90 = 2.*pbrInputs.LdotH*pbrInputs.LdotH*pbrInputs.alpha - 0.5;

return (pbrInputs.baseColor/M_PI)*(1.0+f90*pow((1.0-pbrInputs.NdotL),5.0))*(1.0+f90*pow((1.0-pbrInputs.NdotV),5.0));
}
Expand Down Expand Up @@ -106,7 +107,7 @@ float geometricOcclusionCookTorrance(PBRInfo pbrInputs)
// implementation of microfacet occlusion from “An Inexpensive BRDF Model for Physically based Rendering” by Christophe Schlick
float geometricOcclusionSchlick(PBRInfo pbrInputs)
{
float k = pbrInputs.roughness * 0.79788; // 0.79788 = sqrt(2.0/3.1415);
float k = pbrInputs.alpha * 0.79788; // 0.79788 = sqrt(2.0/3.1415);
// alternately, k can be defined with
// float k = (pbrInputs.roughness + 1)*(pbrInputs.roughness + 1)/8;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could be wrong here, but in Schlick's paper, he presents k=sqrt(2*m*m / PI) (Equation 19). Does that suggest that we should keep pbrInputs.roughness here?

Also, I noticed in the Epic paper that they only did this alpha remapping (roughness + 1)/2) * (roughness + 1)/2), for analytic light sources and that with IBL the results at glancing angles is too dark.


Expand All @@ -120,8 +121,8 @@ float geometricOcclusionSmith(PBRInfo pbrInputs)
{
float NdotL2 = pbrInputs.NdotL * pbrInputs.NdotL;
float NdotV2 = pbrInputs.NdotV * pbrInputs.NdotV;
float v = ( -1. + sqrt ( pbrInputs.roughness * (1. - NdotL2 ) / NdotL2 + 1.)) * 0.5;
float l = ( -1. + sqrt ( pbrInputs.roughness * (1. - NdotV2 ) / NdotV2 + 1.)) * 0.5;
float v = ( -1. + sqrt ( pbrInputs.alpha * (1. - NdotL2 ) / NdotL2 + 1.)) * 0.5;
float l = ( -1. + sqrt ( pbrInputs.alpha * (1. - NdotV2 ) / NdotV2 + 1.)) * 0.5;
return (1. / max((1. + v + l ),0.000001));
}

Expand All @@ -138,14 +139,14 @@ float SmithG1(float NdotV, float r)

float geometricOcclusionSmithGGX(PBRInfo pbrInputs)
{
return SmithG1_var2(pbrInputs.NdotL, pbrInputs.roughness) * SmithG1_var2(pbrInputs.NdotV, pbrInputs.roughness);
return SmithG1_var2(pbrInputs.NdotL, pbrInputs.alpha) * SmithG1_var2(pbrInputs.NdotV, pbrInputs.alpha);
}

// 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
float GGX(PBRInfo pbrInputs)
{
float roughnessSq = pbrInputs.roughness*pbrInputs.roughness;
float roughnessSq = pbrInputs.alpha*pbrInputs.alpha;
float f = (pbrInputs.NdotH * roughnessSq - pbrInputs.NdotH) * pbrInputs.NdotH + 1.0;
return roughnessSq / (M_PI * f * f);
}
Expand Down Expand Up @@ -226,6 +227,9 @@ void main() {
vec3 specularEnvironmentR0 = specularColor.rgb;
vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90;

// roughness is perceptual roughness; alpha is material roughness
float alpha = roughness*roughness;

PBRInfo pbrInputs = PBRInfo(
NdotL,
NdotV,
Expand All @@ -236,7 +240,8 @@ void main() {
metallic,
diffuseColor,
specularEnvironmentR0,
specularEnvironmentR90
specularEnvironmentR90,
alpha
);

vec3 F = fresnelSchlick2(pbrInputs);
Expand Down