Skip to content

Commit

Permalink
Metal BRDF work
Browse files Browse the repository at this point in the history
  • Loading branch information
est77 committed Mar 29, 2020
1 parent 825956d commit 0156e17
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 38 deletions.
77 changes: 77 additions & 0 deletions src/appleseed/foundation/math/fresnel.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,23 @@ void normal_reflectance_dielectric(
// [3] Memo on Fresnel equations.
// https://seblagarde.wordpress.com/2013/04/29/memo-on-fresnel-equations
//
// [4] Fresnel Equations Considered Harmful.
// http://renderwonk.com/publications/mam2019/naty_mam2019.pdf
//

template <typename SpectrumType, typename T>
void fresnel_reflectance_lazanyi_schlick(
SpectrumType& reflectance,
const SpectrumType& normal_reflectance,
const T cos_theta_i,
const SpectrumType& edge_tint);

template <typename SpectrumType, typename T>
void fresnel_lazanyi_schlick_a(
SpectrumType& a,
const SpectrumType& normal_reflectance,
const SpectrumType& edge_tint,
const T edge_tint_weight);

// Compute the Fresnel reflectance for a conductor for unpolarized light.
template <typename SpectrumType, typename T>
Expand Down Expand Up @@ -461,6 +478,66 @@ void normal_reflectance_dielectric(
normal_reflectance *= normal_reflectance;
}

template <typename SpectrumType, typename T>
void fresnel_reflectance_lazanyi_schlick(
SpectrumType& reflectance,
const SpectrumType& normal_reflectance,
const T cos_theta_i,
const SpectrumType& a)
{
//
// F = r + (1 - r) * [1 - cos(theta)]^5 - a * cos(theta) * [1 - cos(theta)]^6
//

typedef typename impl::GetValueType<SpectrumType>::ValueType ValueType;

assert(cos_theta_i >= T(0.0) && cos_theta_i <= T(1.0));

const T k1 = T(1.0) - cos_theta_i;
const T k2 = k1 * k1;
const T k5 = k2 * k2 * k1;
const T k6 = k5 * k1;

reflectance = SpectrumType(T(1.0));
reflectance -= normal_reflectance;
reflectance *= static_cast<ValueType>(k5);
reflectance += normal_reflectance;

SpectrumType h(a);
h *= cos_theta_i * k6;
reflectance -= h;

clamp(reflectance, T(0.0), T(1.0));
}

template <typename SpectrumType, typename T>
void fresnel_lazanyi_schlick_a(
SpectrumType& a,
const SpectrumType& normal_reflectance,
const SpectrumType& edge_tint,
const T edge_tint_weight)
{
//
// r + (1 - r) * [1 - cos(theta_max)]^5 - h
// a = ------------------------------------------
// cos(theta_max) * [1 - cos(theta_max)]^6
//

const T cos_theta_max = std::cos(T(1.4259339988793673));
const T k1 = T(1.0) - cos_theta_max;
const T k2 = k1 * k1;
const T k4 = k2 * k2 ;
const T k5 = k4 * k1;
const T k6 = k5 * k1;

a = SpectrumType(T(1.0));
a -= normal_reflectance;
a *= k5;
a += normal_reflectance;
a -= edge_tint;
a *= edge_tint_weight / (cos_theta_max * k6 );
}

template <typename SpectrumType, typename T>
inline void fresnel_reflectance_conductor(
SpectrumType& reflectance,
Expand Down
1 change: 1 addition & 0 deletions src/appleseed/renderer/kernel/shading/closures.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -948,6 +948,7 @@ namespace

values->m_normal_reflectance.set(Color3f(p->normal_reflectance), g_std_lighting_conditions, Spectrum::Reflectance);
values->m_edge_tint.set(Color3f(p->edge_tint), g_std_lighting_conditions, Spectrum::Reflectance);
values->m_edge_tint_weight = 1.0f;
values->m_reflectance_multiplier = 1.0f;
values->m_roughness = std::max(p->roughness, 0.0f);
values->m_anisotropy = clamp(p->anisotropy, -1.0f, 1.0f);
Expand Down
30 changes: 30 additions & 0 deletions src/appleseed/renderer/modeling/bsdf/fresnel.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,4 +170,34 @@ class FresnelConductorFun
const float m_reflectance_multiplier;
};

class FresnelConductorSchlickLazanyi
{
public:
FresnelConductorSchlickLazanyi(
const Spectrum& n,
const Spectrum& a,
const float reflectance_multiplier)
: m_n(n)
, m_a(a)
, m_reflectance_multiplier(reflectance_multiplier)
{
}

void operator()(
const foundation::Vector3f& o,
const foundation::Vector3f& h,
const foundation::Vector3f& n,
Spectrum& value) const
{
const float cos_oh = std::min(std::abs(foundation::dot(o, h)), 1.0f);
foundation::fresnel_reflectance_lazanyi_schlick(value, m_n, cos_oh, m_a);
value *= m_reflectance_multiplier;
}

private:
const Spectrum& m_n;
const Spectrum& m_a;
const float m_reflectance_multiplier;
};

} // namespace renderer
76 changes: 42 additions & 34 deletions src/appleseed/renderer/modeling/bsdf/metalbrdf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ namespace
{
m_inputs.declare("normal_reflectance", InputFormatSpectralReflectance);
m_inputs.declare("edge_tint", InputFormatSpectralReflectance);
m_inputs.declare("edge_tint_weight", InputFormatFloat, "1.0");
m_inputs.declare("reflectance_multiplier", InputFormatFloat, "1.0");
m_inputs.declare("roughness", InputFormatFloat, "0.15");
m_inputs.declare("anisotropy", InputFormatFloat, "0.0");
Expand Down Expand Up @@ -130,17 +131,16 @@ namespace

values->m_roughness = std::max(values->m_roughness, shading_point.get_ray().m_min_roughness);

artist_friendly_fresnel_conductor_reparameterization(
values->m_normal_reflectance,
values->m_edge_tint,
values->m_precomputed.m_n,
values->m_precomputed.m_k);
values->m_precomputed.m_outside_ior = shading_point.get_ray().get_current_ior();

average_artist_friendly_fresnel_reflectance_conductor(
values->m_normal_reflectance,
values->m_edge_tint,
values->m_precomputed.m_fresnel_average);
if (values->m_edge_tint_weight != 0.0f)
{
fresnel_lazanyi_schlick_a(
values->m_precomputed.m_a,
values->m_normal_reflectance,
values->m_edge_tint,
values->m_edge_tint_weight);
}
else
values->m_precomputed.m_a.set(0.0f);
}

void sample(
Expand All @@ -155,10 +155,9 @@ namespace
{
const InputValues* values = static_cast<const InputValues*>(data);

const FresnelConductorFun f(
values->m_precomputed.m_n,
values->m_precomputed.m_k,
values->m_precomputed.m_outside_ior,
const FresnelConductorSchlickLazanyi f(
values->m_normal_reflectance,
values->m_precomputed.m_a,
values->m_reflectance_multiplier);

// If roughness is zero use reflection.
Expand Down Expand Up @@ -228,10 +227,9 @@ namespace
alpha_x,
alpha_y);

const FresnelConductorFun f(
values->m_precomputed.m_n,
values->m_precomputed.m_k,
values->m_precomputed.m_outside_ior,
const FresnelConductorSchlickLazanyi f(
values->m_normal_reflectance,
values->m_precomputed.m_a,
values->m_reflectance_multiplier);

const float pdf =
Expand Down Expand Up @@ -299,25 +297,17 @@ namespace
{
if (values->m_energy_compensation != 0.0f)
{
const float Ess =
get_directional_albedo(
std::abs(dot(outgoing, n)),
values->m_roughness);
const float Ess = get_directional_albedo(
std::abs(dot(outgoing, n)),
values->m_roughness);

if (Ess == 0.0f)
return;

const float Eavg = get_average_albedo(values->m_roughness);
Spectrum fterm = values->m_precomputed.m_fresnel_average;
fterm *= fterm;
fterm *= Eavg;

const Spectrum one(1.0f);
fterm /= one - values->m_precomputed.m_fresnel_average * (1.0f - Eavg);

fterm *= values->m_energy_compensation * ((1.0f - Ess) / Ess);
fterm += one;
value *= fterm;
Spectrum fms = values->m_normal_reflectance;
fms *= values->m_energy_compensation * (1.0f - Ess) / Ess;
fms += Spectrum(1.0f);
value *= fms;
}
}
};
Expand Down Expand Up @@ -376,6 +366,24 @@ DictionaryArray MetalBRDFFactory::get_input_metadata() const
.insert("use", "required")
.insert("default", "0.98"));

metadata.push_back(
Dictionary()
.insert("name", "edge_tint_weight")
.insert("label", "Edge Tint Weight")
.insert("type", "colormap")
.insert("entity_types",
Dictionary().insert("texture_instance", "Texture Instances"))
.insert("use", "optional")
.insert("min",
Dictionary()
.insert("value", "0.0")
.insert("type", "hard"))
.insert("max",
Dictionary()
.insert("value", "1.0")
.insert("type", "hard"))
.insert("default", "1.0"));

metadata.push_back(
Dictionary()
.insert("name", "reflectance_multiplier")
Expand Down
6 changes: 2 additions & 4 deletions src/appleseed/renderer/modeling/bsdf/metalbrdf.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,15 @@ APPLESEED_DECLARE_INPUT_VALUES(MetalBRDFInputValues)
{
Spectrum m_normal_reflectance;
Spectrum m_edge_tint;
float m_edge_tint_weight;
float m_reflectance_multiplier;
float m_roughness;
float m_anisotropy;
float m_energy_compensation;

struct Precomputed
{
Spectrum m_n;
Spectrum m_k;
Spectrum m_fresnel_average;
float m_outside_ior;
Spectrum m_a;
};

Precomputed m_precomputed;
Expand Down

0 comments on commit 0156e17

Please sign in to comment.