Fermat
Public Types | Public Methods | Static Public Methods | Public Members | List of all members
Bsdf Struct Reference

Detailed description

Composite BSDF class

This class defines the Bidirectional Scattering Distribution Function employed throughout Fermat. At present time, this model is rather simple, and consists of five layered components only:
  • a diffuse reflection component
  • a diffuse transmission component
  • a glossy reflection component layered on top of the diffuse layer
  • a glossy transmission component layered on top of the diffuse layer
  • a clearcoat layer on top of all of the above

The interaction between the top clearcoat layer and the inner layers below that is modeled approximately, computing only the Fresnel transmission factor to enter the clearcoat, but without modeling the change due to refraction of the input and output directions a la Weidlich and Wilkie. This is done because the approach from Weidlich and Wilkie simulates only first-order scattering, and results in dramatic energy loss for rough materials. It is also questionable whether that would be more correct, given that accounting for multiple-scattering through the various layers can be modeled without altering the final lobe directions, and while only changing the statistics of the inner layer distributions, as described in: "Efficient Rendering of Layered Materials using an Atomic Decomposition with Statistical Operators", Laurent Belcour - in ACM Transactions on Graphics, Association for Computing Machinery, 2018. While we plan to adopt the full machinery of the latter in the future, we currently just crudely approximate it.

The inner layers of the BSDF use Fresnel coefficients to determine how much light undergoes glossy reflection, and how much undergoes transmission. Part of the radiance transmitted from the upper glossy layer undergoes diffuse scattering. Again, the interaction between the glossy layer and the underlying diffuse layer is modeled in a simplified manner, as if the layer was infinitely thin and the diffusely reflected particles were not interacting again with the upper layer.

#include <bsdf.h>

Public Types

enum  ComponentIndex {
  kDiffuseReflectionIndex = 0u, kDiffuseTransmissionIndex = 1u, kGlossyReflectionIndex = 2u, kGlossyTransmissionIndex = 3u,
  kClearcoatReflectionIndex = 4u, kNumComponents = 5u
}
 
enum  ComponentType {
  kAbsorption = 0u, kDiffuseReflection = 0x1u, kDiffuseTransmission = 0x2u, kGlossyReflection = 0x4u,
  kGlossyTransmission = 0x8u, kClearcoatReflection = 0x10u, kDiffuseMask = 0x3u, kGlossyMask = 0xCu,
  kReflectionMask = 0x5u, kTransmissionMask = 0xAu, kAllComponents = 0xFFu
}
 
typedef cugar::LambertTransBsdf diffuse_trans_component
 
typedef cugar::LambertBsdf diffuse_component
 
typedef cugar::GGXSmithBsdf glossy_component
 

Public Methods

FERMAT_HOST_DEVICE Bsdf ()
 
FERMAT_HOST_DEVICE Bsdf (const Bsdf &bsdf)
 
FERMAT_HOST_DEVICE Bsdf (const TransportType transport, const RenderingContextView renderer, const MeshMaterial material, const float mollification_factor=1.0f, const float mollification_bias=0.0f, const float min_roughness=0.0f)
 
FERMAT_HOST_DEVICE Bsdf (const TransportType transport, const RenderingContextView renderer, const cugar::Vector3f diffuse, const cugar::Vector3f specular, const float roughness, const cugar::Vector3f diffuse_trans, const float opacity=1.0f, const float ior=1.0f)
 
FERMAT_HOST_DEVICE const diffuse_trans_componentdiffuse_trans () const
 
FERMAT_HOST_DEVICE const diffuse_componentdiffuse () const
 
FERMAT_HOST_DEVICE const glossy_componentglossy () const
 
FERMAT_HOST_DEVICE const glossy_componentglossy_trans () const
 
FERMAT_HOST_DEVICE float get_eta (const float NoV) const
 
FERMAT_HOST_DEVICE float get_inv_eta (const float NoV) const
 
FERMAT_FORCEINLINE FERMAT_HOST_DEVICE cugar::Vector3f f (const cugar::DifferentialGeometry &geometry, const cugar::Vector3f w_i, const cugar::Vector3f w_o, const ComponentType components=kAllComponents) const
 
FERMAT_FORCEINLINE FERMAT_HOST_DEVICE void f (const cugar::DifferentialGeometry &geometry, const cugar::Vector3f w_i, const cugar::Vector3f w_o, cugar::Vector3f *f) const
 
FERMAT_FORCEINLINE FERMAT_HOST_DEVICE void f_and_p (const cugar::DifferentialGeometry &geometry, const cugar::Vector3f w_i, const cugar::Vector3f w_o, cugar::Vector3f *f, float *p, const cugar::SphericalMeasure measure=cugar::kProjectedSolidAngle, bool RR=true) const
 
FERMAT_FORCEINLINE FERMAT_HOST_DEVICE void f_and_p (const cugar::DifferentialGeometry &geometry, const cugar::Vector3f w_i, const cugar::Vector3f w_o, cugar::Vector3f &f, float &p, const cugar::SphericalMeasure measure=cugar::kProjectedSolidAngle, const bool RR=true, const ComponentType components=kAllComponents) const
 
FERMAT_FORCEINLINE FERMAT_HOST_DEVICE float p (const cugar::DifferentialGeometry &geometry, const cugar::Vector3f w_i, const cugar::Vector3f w_o, const cugar::SphericalMeasure measure=cugar::kProjectedSolidAngle, const bool RR=true, const ComponentType components=kAllComponents) const
 
FERMAT_FORCEINLINE FERMAT_HOST_DEVICE void sampling_weights (const cugar::DifferentialGeometry &geometry, const cugar::Vector3f V, float &diffuse_refl_prob, float &diffuse_trans_prob, float &glossy_refl_prob, float &glossy_trans_prob) const
 
FERMAT_FORCEINLINE FERMAT_HOST_DEVICE void sampling_weights (const cugar::DifferentialGeometry &geometry, const cugar::Vector3f V, float *w) const
 
FERMAT_FORCEINLINE FERMAT_HOST_DEVICE void normalize_sampling_weights (float *w_p, float &coat_reflection_prob, float &coat_transmission_prob, const bool RR, const ComponentType components=kAllComponents) const
 
FERMAT_FORCEINLINE FERMAT_HOST_DEVICE void fresnel_weights (const float VoH, const float eta, cugar::Vector3f &r_coeff, cugar::Vector3f &t_coeff) const
 
FERMAT_FORCEINLINE FERMAT_HOST_DEVICE void fresnel_weights (const cugar::DifferentialGeometry &geometry, const cugar::Vector3f V, const cugar::Vector3f L, cugar::Vector3f &r_coeff, cugar::Vector3f &t_coeff) const
 
FERMAT_FORCEINLINE FERMAT_HOST_DEVICE void inner_component_weights (const cugar::DifferentialGeometry &geometry, const cugar::Vector3f V, const cugar::Vector3f L, cugar::Vector3f &diffuse_refl_coeff, cugar::Vector3f &diffuse_trans_coeff, cugar::Vector3f &glossy_refl_coeff, cugar::Vector3f &glossy_trans_coeff) const
 
FERMAT_FORCEINLINE FERMAT_HOST_DEVICE void inner_component_weights (const cugar::DifferentialGeometry &geometry, const cugar::Vector3f V, const cugar::Vector3f L, cugar::Vector3f *w) const
 
FERMAT_FORCEINLINE FERMAT_HOST_DEVICE void component_weights (const cugar::DifferentialGeometry &geometry, const cugar::Vector3f w_i, const cugar::Vector3f w_o, cugar::Vector3f &Fc_1, cugar::Vector3f &Tc_1, cugar::Vector3f &Fc_2, cugar::Vector3f &Tc_2, cugar::Vector3f *w) const
 
FERMAT_FORCEINLINE FERMAT_HOST_DEVICE void component_weights (const cugar::DifferentialGeometry &geometry, const cugar::Vector3f w_i, const cugar::Vector3f w_o, cugar::Vector3f *w) const
 
FERMAT_HOST_DEVICE FERMAT_FORCEINLINE bool sample_component (const cugar::DifferentialGeometry &geometry, const float z[3], const cugar::Vector3f in, const ComponentType out_comp, cugar::Vector3f &out, float &out_p, float &out_p_proj, cugar::Vector3f &out_g, const bool evaluate_full_bsdf=false) const
 
FERMAT_HOST_DEVICE FERMAT_FORCEINLINE bool sample (const cugar::DifferentialGeometry &geometry, const float z[3], const cugar::Vector3f in, ComponentType &out_comp, cugar::Vector3f &out, float &out_p, float &out_p_proj, cugar::Vector3f &out_g, bool RR=true, bool evaluate_full_bsdf=false, const ComponentType components=kAllComponents) const
 
FERMAT_FORCEINLINE FERMAT_HOST_DEVICE bool clearcoat_transmission (const cugar::DifferentialGeometry &geometry, const cugar::Vector3f w_i, cugar::Vector3f &H, float &cos_theta_i, float &eta, cugar::Vector3f &Fc_1, cugar::Vector3f &Tc_1) const
 
FERMAT_FORCEINLINE FERMAT_HOST_DEVICE float compression_factor (const cugar::DifferentialGeometry &geometry, const cugar::Vector3f w_i, const cugar::Vector3f w_o) const
 
FERMAT_FORCEINLINE FERMAT_HOST_DEVICE float glossy_reflectance (const float cos_theta) const
 

Static Public Methods

static FERMAT_HOST_DEVICE uint32 component_count ()
 
static FERMAT_HOST_DEVICE uint32 component_index (const ComponentType comp)
 
static FERMAT_HOST_DEVICE ComponentType component_mask (const ComponentIndex comp)
 

Public Members

diffuse_component m_diffuse
 
diffuse_trans_component m_diffuse_trans
 
glossy_component m_glossy
 
glossy_component m_glossy_trans
 
cugar::Vector3f m_fresnel
 
cugar::Vector3f m_reflectivity
 
float m_ior
 
float m_opacity
 
float m_clearcoat_ior
 
const float * m_glossy_reflectance
 
TransportType m_transport
 

Member Enumeration Documentation

◆ ComponentIndex

component type indices

◆ ComponentType

component type bitmasks

Constructor & Destructor Documentation

◆ Bsdf() [1/4]

FERMAT_HOST_DEVICE Bsdf::Bsdf ( )
inline

constructor

◆ Bsdf() [2/4]

FERMAT_HOST_DEVICE Bsdf::Bsdf ( const Bsdf bsdf)
inline

copy constructor

◆ Bsdf() [3/4]

FERMAT_HOST_DEVICE Bsdf::Bsdf ( const TransportType  transport,
const RenderingContextView  renderer,
const MeshMaterial  material,
const float  mollification_factor = 1.0f,
const float  mollification_bias = 0.0f,
const float  min_roughness = 0.0f 
)
inline

constructor

◆ Bsdf() [4/4]

FERMAT_HOST_DEVICE Bsdf::Bsdf ( const TransportType  transport,
const RenderingContextView  renderer,
const cugar::Vector3f  diffuse,
const cugar::Vector3f  specular,
const float  roughness,
const cugar::Vector3f  diffuse_trans,
const float  opacity = 1.0f,
const float  ior = 1.0f 
)
inline

constructor

Member Function Documentation

◆ component_count()

static FERMAT_HOST_DEVICE uint32 Bsdf::component_count ( )
inlinestatic

return the number of components

◆ component_index()

static FERMAT_HOST_DEVICE uint32 Bsdf::component_index ( const ComponentType  comp)
inlinestatic

return the 0-based index corresponding to a given component

◆ component_mask()

static FERMAT_HOST_DEVICE ComponentType Bsdf::component_mask ( const ComponentIndex  comp)
inlinestatic

return the bitmask corresponding to a given component

◆ component_weights() [1/2]

FERMAT_FORCEINLINE FERMAT_HOST_DEVICE void Bsdf::component_weights ( const cugar::DifferentialGeometry geometry,
const cugar::Vector3f  w_i,
const cugar::Vector3f  w_o,
cugar::Vector3f Fc_1,
cugar::Vector3f Tc_1,
cugar::Vector3f Fc_2,
cugar::Vector3f Tc_2,
cugar::Vector3f w 
) const
inline

evaluate the component weights of all layers - including the clearcoat

◆ component_weights() [2/2]

FERMAT_FORCEINLINE FERMAT_HOST_DEVICE void Bsdf::component_weights ( const cugar::DifferentialGeometry geometry,
const cugar::Vector3f  w_i,
const cugar::Vector3f  w_o,
cugar::Vector3f w 
) const
inline

evaluate the component weights of all layers - including the clearcoat

◆ compression_factor()

FERMAT_FORCEINLINE FERMAT_HOST_DEVICE float Bsdf::compression_factor ( const cugar::DifferentialGeometry geometry,
const cugar::Vector3f  w_i,
const cugar::Vector3f  w_o 
) const
inline

apply the radiance compression factor of (eta_t / eta_i)^2

◆ diffuse()

FERMAT_HOST_DEVICE const diffuse_component& Bsdf::diffuse ( ) const
inline

return the diffuse reflection component

◆ diffuse_trans()

FERMAT_HOST_DEVICE const diffuse_trans_component& Bsdf::diffuse_trans ( ) const
inline

return the diffuse transmission component

◆ f() [1/2]

FERMAT_FORCEINLINE FERMAT_HOST_DEVICE cugar::Vector3f Bsdf::f ( const cugar::DifferentialGeometry geometry,
const cugar::Vector3f  w_i,
const cugar::Vector3f  w_o,
const ComponentType  components = kAllComponents 
) const
inline

evaluate the BSDF f(V,L)

Parameters
geometrythe local differential geometry
inthe incoming direction
outthe outgoing direction
componentsthe components to consider

◆ f() [2/2]

FERMAT_FORCEINLINE FERMAT_HOST_DEVICE void Bsdf::f ( const cugar::DifferentialGeometry geometry,
const cugar::Vector3f  w_i,
const cugar::Vector3f  w_o,
cugar::Vector3f f 
) const
inline

evaluate the BSDF f(V,L) separately for all components

◆ f_and_p() [1/2]

FERMAT_FORCEINLINE FERMAT_HOST_DEVICE void Bsdf::f_and_p ( const cugar::DifferentialGeometry geometry,
const cugar::Vector3f  w_i,
const cugar::Vector3f  w_o,
cugar::Vector3f f,
float *  p,
const cugar::SphericalMeasure  measure = cugar::kProjectedSolidAngle,
bool  RR = true 
) const
inline

evaluate the BSDF f(V,L) and its pdf p(V,L) in a single call

◆ f_and_p() [2/2]

FERMAT_FORCEINLINE FERMAT_HOST_DEVICE void Bsdf::f_and_p ( const cugar::DifferentialGeometry geometry,
const cugar::Vector3f  w_i,
const cugar::Vector3f  w_o,
cugar::Vector3f f,
float &  p,
const cugar::SphericalMeasure  measure = cugar::kProjectedSolidAngle,
const bool  RR = true,
const ComponentType  components = kAllComponents 
) const
inline

evaluate the BSDF f(V,L) and its p(V,L) in a single call

◆ fresnel_weights() [1/2]

FERMAT_FORCEINLINE FERMAT_HOST_DEVICE void Bsdf::fresnel_weights ( const float  VoH,
const float  eta,
cugar::Vector3f r_coeff,
cugar::Vector3f t_coeff 
) const
inline

compute the Fresnel reflection and transmission weights

◆ fresnel_weights() [2/2]

FERMAT_FORCEINLINE FERMAT_HOST_DEVICE void Bsdf::fresnel_weights ( const cugar::DifferentialGeometry geometry,
const cugar::Vector3f  V,
const cugar::Vector3f  L,
cugar::Vector3f r_coeff,
cugar::Vector3f t_coeff 
) const
inline

compute the Fresnel reflection and transmission weights

◆ get_eta()

FERMAT_HOST_DEVICE float Bsdf::get_eta ( const float  NoV) const
inline

return the incident ior ratio

◆ get_inv_eta()

FERMAT_HOST_DEVICE float Bsdf::get_inv_eta ( const float  NoV) const
inline

return the incident inverse ior ratio

◆ glossy()

FERMAT_HOST_DEVICE const glossy_component& Bsdf::glossy ( ) const
inline

return the glossy reflection component

◆ glossy_trans()

FERMAT_HOST_DEVICE const glossy_component& Bsdf::glossy_trans ( ) const
inline

return the glossy transmission component

◆ inner_component_weights() [1/2]

FERMAT_FORCEINLINE FERMAT_HOST_DEVICE void Bsdf::inner_component_weights ( const cugar::DifferentialGeometry geometry,
const cugar::Vector3f  V,
const cugar::Vector3f  L,
cugar::Vector3f diffuse_refl_coeff,
cugar::Vector3f diffuse_trans_coeff,
cugar::Vector3f glossy_refl_coeff,
cugar::Vector3f glossy_trans_coeff 
) const
inline

deprecated evaluate the Fresnel weight for the glossy component - after the clearcoat

◆ inner_component_weights() [2/2]

FERMAT_FORCEINLINE FERMAT_HOST_DEVICE void Bsdf::inner_component_weights ( const cugar::DifferentialGeometry geometry,
const cugar::Vector3f  V,
const cugar::Vector3f  L,
cugar::Vector3f w 
) const
inline

evaluate the component weights of the inner layers - after the clearcoat

◆ normalize_sampling_weights()

FERMAT_FORCEINLINE FERMAT_HOST_DEVICE void Bsdf::normalize_sampling_weights ( float *  w_p,
float &  coat_reflection_prob,
float &  coat_transmission_prob,
const bool  RR,
const ComponentType  components = kAllComponents 
) const
inline

normalize the sampling weights of the inner layers given the coat sampling probability

◆ p()

FERMAT_FORCEINLINE FERMAT_HOST_DEVICE float Bsdf::p ( const cugar::DifferentialGeometry geometry,
const cugar::Vector3f  w_i,
const cugar::Vector3f  w_o,
const cugar::SphericalMeasure  measure = cugar::kProjectedSolidAngle,
const bool  RR = true,
const ComponentType  components = kAllComponents 
) const
inline

evaluate the total projected probability p(V,L) = p(L|V)

Parameters
geometrythe local differential geometry
w_ithe incoming direction
w_othe outgoing direction
measurethe spherical measure to use
RRindicate whether to use Russian-Roulette or not

◆ sample()

FERMAT_HOST_DEVICE FERMAT_FORCEINLINE bool Bsdf::sample ( const cugar::DifferentialGeometry geometry,
const float  z[3],
const cugar::Vector3f  in,
ComponentType out_comp,
cugar::Vector3f out,
float &  out_p,
float &  out_p_proj,
cugar::Vector3f out_g,
bool  RR = true,
bool  evaluate_full_bsdf = false,
const ComponentType  components = kAllComponents 
) const
inline

sample an outgoing direction

Parameters
geometrythe local differential geometry
zthe incoming direction
inthe incoming direction
out_compthe output component
outthe outgoing direction
out_pthe output solid angle pdf
out_p_projthe output projected solid angle pdf
out_gthe output sample value = f/p_proj
RRindicate whether to use Russian-Roulette or not
evaluate_full_bsdfndicate whether to evaluate the full BSDF, or just an unbiased estimate
componentsthe components to consider

◆ sample_component()

FERMAT_HOST_DEVICE FERMAT_FORCEINLINE bool Bsdf::sample_component ( const cugar::DifferentialGeometry geometry,
const float  z[3],
const cugar::Vector3f  in,
const ComponentType  out_comp,
cugar::Vector3f out,
float &  out_p,
float &  out_p_proj,
cugar::Vector3f out_g,
const bool  evaluate_full_bsdf = false 
) const
inline

sample a given component

Parameters
geometrythe local differential geometry
zthe input random numbers, relative to the given component
inthe incoming direction
out_compthe given component
outthe outgoing direction
out_pthe output solid angle pdf
out_p_projthe output projected solid angle pdf
out_gthe output sample value = f/p_proj
RRindicate whether to use Russian-Roulette or not
evaluate_full_bsdfndicate whether to evaluate the full BSDF, or just an unbiased estimate
componentsthe components to consider

◆ sampling_weights() [1/2]

FERMAT_FORCEINLINE FERMAT_HOST_DEVICE void Bsdf::sampling_weights ( const cugar::DifferentialGeometry geometry,
const cugar::Vector3f  V,
float &  diffuse_refl_prob,
float &  diffuse_trans_prob,
float &  glossy_refl_prob,
float &  glossy_trans_prob 
) const
inline

evaluate the sampling weights for the inner layers

◆ sampling_weights() [2/2]

FERMAT_FORCEINLINE FERMAT_HOST_DEVICE void Bsdf::sampling_weights ( const cugar::DifferentialGeometry geometry,
const cugar::Vector3f  V,
float *  w 
) const
inline

evaluate the sampling weights for the inner layers


The documentation for this struct was generated from the following file: