Skip to content

Commit

Permalink
Add clearcoat term to BRDF
Browse files Browse the repository at this point in the history
  • Loading branch information
szellmann committed May 10, 2024
1 parent 9268819 commit 0a14e5c
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 7 deletions.
2 changes: 2 additions & 0 deletions DeviceCopyableObjects.h
Original file line number Diff line number Diff line change
Expand Up @@ -1405,6 +1405,8 @@ struct Material
} normal;
AlphaMode alphaMode;
float alphaCutoff;
MaterialParamF clearcoat;
MaterialParamF clearcoatRoughness;
float ior;
} asPhysicallyBased;
};
Expand Down
56 changes: 50 additions & 6 deletions renderer/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,43 @@ inline vec3 getPerturbedNormal(const dco::Material &mat,
return pn;
}

VSNRAY_FUNC
inline float pow2(float f)
{
return f*f;
}

VSNRAY_FUNC
inline float pow5(float f)
{
return f*f*f*f*f;
}

VSNRAY_FUNC
inline vec3 F_Schlick(float u, vec3 f0)
{
return f0 + (vec3f(1.f) - f0) * pow5(1.f - u);
}

VSNRAY_FUNC
inline float F_Schlick(float u, float f0)
{
return f0 + (1.f - f0) * pow5(1.f - u);
}

VSNRAY_FUNC
inline float D_GGX(float NdotH, float alpha)
{
return (alpha*alpha*heaviside(NdotH))
/ (constants::pi<float>()*pow2(NdotH*NdotH*(alpha*alpha-1.f)+1.f));
}

VSNRAY_FUNC
inline float V_Kelemen(float LdotH, const float EPS)
{
return 0.25f / fmaxf(EPS, (LdotH * LdotH));
}

VSNRAY_FUNC
inline vec3 evalPhysicallyBasedMaterial(const dco::Material &mat,
const dco::Geometry &geom,
Expand All @@ -664,6 +701,10 @@ inline vec3 evalPhysicallyBasedMaterial(const dco::Material &mat,
mat.asPhysicallyBased.metallic, geom, samplers, primID, uv);
const float roughness = getF(
mat.asPhysicallyBased.roughness, geom, samplers, primID, uv);
const float clearcoat = getF(
mat.asPhysicallyBased.clearcoat, geom, samplers, primID, uv);
const float clearcoatRoughness = getF(
mat.asPhysicallyBased.clearcoatRoughness, geom, samplers, primID, uv);
const float ior = mat.asPhysicallyBased.ior;

const float alpha = roughness*roughness;
Expand All @@ -681,19 +722,16 @@ inline vec3 evalPhysicallyBasedMaterial(const dco::Material &mat,
mat.asPhysicallyBased.baseColor, geom, samplers, primID, uv).xyz();

// Fresnel
auto pow2 = [](float f) { return f*f; };
auto pow5 = [](float f) { return f*f*f*f*f; };
vec3 f0 = lerp(vec3(pow2((1.f-ior)/(1.f+ior))), diffuseColor, metallic);
vec3 F = f0 + (vec3(1.f) - f0) * pow5(1.f - VdotH);
vec3 F = F_Schlick(VdotH, f0);

// Metallic materials don't reflect diffusely:
diffuseColor = lerp(diffuseColor, vec3f(0.f), metallic);

vec3 diffuseBRDF = constants::inv_pi<float>() * diffuseColor;

// GGX microfacet distribution
float D = (alpha*alpha*heaviside(NdotH))
/ (constants::pi<float>()*pow2(NdotH*NdotH*(alpha*alpha-1.f)+1.f));
float D = D_GGX(NdotH, alpha);

// Masking-shadowing term
float G = ((2.f * NdotL * heaviside(LdotH))
Expand All @@ -704,7 +742,13 @@ inline vec3 evalPhysicallyBasedMaterial(const dco::Material &mat,
float denom = 4.f * NdotV * NdotL;
vec3 specularBRDF = (F * D * G) / max(EPS,denom);

return (diffuseBRDF + specularBRDF) * lightIntensity;
// Clearcoat
float Dc = D_GGX(clearcoatRoughness, NdotH);
float Vc = V_Kelemen(LdotH, EPS);
float Fc = F_Schlick(VdotH, 0.04f) * clearcoat;
float Frc = (Dc * Vc) * Fc;

return ((diffuseBRDF + specularBRDF) * (1.f - Fc) + Frc) * lightIntensity;
}

VSNRAY_FUNC
Expand Down
29 changes: 29 additions & 0 deletions scene/surface/material/PBM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@ void PBM::commit()
m_roughness.sampler = getParamObject<Sampler>("roughness");
m_roughness.attribute = toAttribute(getParamString("roughness", "none"));

m_clearcoat.value = 0.f;
getParam("clearcoat", ANARI_FLOAT32, &m_clearcoat.value);
m_clearcoat.sampler = getParamObject<Sampler>("clearcoat");
m_clearcoat.attribute = toAttribute(getParamString("clearcoat", "none"));

m_clearcoatRoughness.value = 0.f;
getParam("clearcoatRoughness", ANARI_FLOAT32, &m_clearcoatRoughness.value);
m_clearcoatRoughness.sampler = getParamObject<Sampler>("clearcoatRoughness");
m_clearcoatRoughness.attribute
= toAttribute(getParamString("clearcoatRoughness", "none"));

m_ior = 1.5f;
getParam("ior", ANARI_FLOAT32, &m_ior);

Expand Down Expand Up @@ -77,6 +88,24 @@ void PBM::commit()
vmat.asPhysicallyBased.roughness.samplerID = UINT_MAX;
}

vmat.asPhysicallyBased.clearcoat.f = m_clearcoat.value;
vmat.asPhysicallyBased.clearcoat.attribute = m_clearcoat.attribute;
if (m_clearcoat.sampler) {
vmat.asPhysicallyBased.clearcoat.samplerID
= m_clearcoat.sampler->visionaraySampler().samplerID;
} else {
vmat.asPhysicallyBased.clearcoat.samplerID = UINT_MAX;
}

vmat.asPhysicallyBased.clearcoatRoughness.f = m_clearcoatRoughness.value;
vmat.asPhysicallyBased.clearcoatRoughness.attribute = m_clearcoatRoughness.attribute;
if (m_clearcoatRoughness.sampler) {
vmat.asPhysicallyBased.clearcoatRoughness.samplerID
= m_clearcoatRoughness.sampler->visionaraySampler().samplerID;
} else {
vmat.asPhysicallyBased.clearcoatRoughness.samplerID = UINT_MAX;
}

vmat.asPhysicallyBased.ior = m_ior;

if (m_normal.sampler) {
Expand Down
2 changes: 1 addition & 1 deletion scene/surface/material/PBM.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ struct PBM : public Material
float value{1.f};
helium::IntrusivePtr<Sampler> sampler;
dco::Attribute attribute;
} m_opacity, m_metallic, m_roughness;
} m_opacity, m_metallic, m_roughness, m_clearcoat, m_clearcoatRoughness;

float m_ior{1.5f};

Expand Down

0 comments on commit 0a14e5c

Please sign in to comment.