Skip to content

Instantly share code, notes, and snippets.

@soma-arc
Last active June 15, 2019 11:57
Show Gist options
  • Save soma-arc/5d53816885e64628869ed54bfb95e31d to your computer and use it in GitHub Desktop.
Save soma-arc/5d53816885e64628869ed54bfb95e31d to your computer and use it in GitHub Desktop.
glTF 2.0 PBR materials metaric-roughness shader for BRDF Explorer
analytic
# glTF 2.0 PBR Materials
# metallic-roughness
# Reference:
# glTF Specification, 2.0
# https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#metallic-roughness-material
# glTF 2.0: PBR Materials by Saurabh Bhatia. May 2017
# https://www.khronos.org/assets/uploads/developers/library/2017-gtc/glTF-2.0-and-PBR-GTC_May17.pdf
# glTF-WebGL-PBR
# https://github.com/KhronosGroup/glTF-WebGL-PBR
# variables go here...
# only floats supported right now.
# [type] [name] [min val] [max val] [default val]
::begin parameters
color u_baseColor 1. 1. 1.
float u_metallic 0. 1. 0.
float u_roughness 0. 1. 0.
::end parameters
::begin shader
const float PI = 3.14159265358979323846;
const float DIV_PI = 1.0 / PI;
const vec3 dielectricSpecular = vec3(0.04);
const vec3 BLACK = vec3(0);
// This G term is used in glTF-WebGL-PBR
// Microfacet Models for Refraction through Rough Surfaces
float G1_GGX(float alphaSq, float NoX) {
float tanSq = (1.0 - NoX * NoX) / max((NoX * NoX), 0.00001);
return 2. / (1. + sqrt(1. + alphaSq * tanSq));
}
// 1 / (1 + delta(l)) * 1 / (1 + delta(v))
float Smith_G(float alphaSq, float NoL, float NoV) {
return G1_GGX(alphaSq, NoL) * G1_GGX(alphaSq, NoV);
}
// Height-Correlated Masking and Shadowing
// Smith Joint Masking-Shadowing Function
float GGX_Delta(float alphaSq, float NoX) {
return (-1. + sqrt(1. + alphaSq * (1. / (NoX * NoX) - 1.))) / 2.;
}
float SmithJoint_G(float alphaSq, float NoL, float NoV) {
return 1. / (1. + GGX_Delta(alphaSq, NoL) + GGX_Delta(alphaSq, NoV));
}
float GGX_D(float alphaSq, float NoH) {
float c = (NoH * NoH * (alphaSq - 1.) + 1.);
return alphaSq / (c * c) * DIV_PI;
}
vec3 BRDF( vec3 L, vec3 V, vec3 N, vec3 X, vec3 Y ) {
vec3 H = normalize(L+V);
float LoH = dot(L, H);
float NoH = dot(N, H);
float VoH = dot(V, H);
float NoL = dot(N, L);
float NoV = dot(N, V);
vec3 F0 = mix(dielectricSpecular, u_baseColor, u_metallic);
vec3 cDiff = mix(u_baseColor * (1. - dielectricSpecular.r),
BLACK,
u_metallic);
float alpha = u_roughness * u_roughness;
float alphaSq = alpha * alpha;
// Schlick's approximation
vec3 F = F0 + (vec3(1.) - F0) * pow((1. - VoH), 5.);
vec3 diffuse = (vec3(1.) - F) * cDiff * DIV_PI;
float G = SmithJoint_G(alphaSq, NoL, NoV);
// float G = Smith_G(alphaSq, NoL, NoV);
float D = GGX_D(alphaSq, NoH);
float specular = (F * G * D) / (4. * NoL * NoV);
return diffuse + vec3(specular);
}
::end shader
@cesss
Copy link

cesss commented Jun 15, 2019

I believe there's a typo in line 84, because F is a vec3 and the rest of values in the expression are all floats, so the result is a vec3 and not a float. In fact, in the next line you turn specular into a vec3. On my Mac I get a compilation error at line 84. If I change line 84 so that specular is a vec3, and I remove the vec3() conversion from line 85, it seems to work fine (although I don't have any ground truth for accurately testing the result).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment