Skip to content

Commit ae8fa4e

Browse files
authored
Move GeneralizedSchlick lobe from testrender to BSDL library (#2078)
Unify DielectricRefl and DielectricBoth into a single DielectricBSDF<Fresnel> template that handles both reflection-only and reflection+refraction modes via a runtime `dorefr` flag. This replaces the old union of two separate structs in DielectricLobe with a single `spec` member, simplifying the code and enabling reuse with alternative Fresnel models. Key changes: - Merge DielectricRefl and DielectricBoth into DielectricBSDF<Fresnel>, parameterized on the Fresnel type. The eval/sample methods branch on `dorefr` internally. The existing DielectricReflFront, DielectricBothFront, and DielectricBothBack now inherit from DielectricBSDF<DielectricFresnel> for table-baking purposes. - Propagate colored Fresnel through the dielectric eval/sample paths: Fresnel eval() now returns Power instead of float, so reflection and refraction weights carry the spectral information directly (needed for Schlick's colored F0/F90). - Add refraction_eta() accessor to DielectricFresnel so the templated code can obtain the refraction IOR uniformly across Fresnel types. - Introduce SchlickFresnel (inheriting DielectricFresnel) with generalized Schlick F0/F90/exponent parametrization and TIR handling. SchlickLobe reuses DielectricBSDF<SchlickFresnel> directly. The refraction IOR is derived from F0 via the inverse Schlick approximation. - Add BSDL_WRAP macro in testrender/shading.cpp to eliminate boilerplate for wrapping BSDL lobes (MxConductor, MxDielectric, MxGeneralizedSchlick). The old per-class MxGeneralizedSchlick via CLOSURE_*_PARAM macros is replaced by the BSDL auto-registration path. - Update test references and bump AA samples for the schlick-glass test to reduce noise with the new implementation. Signed-off-by: Alejandro Conty <aconty@imageworks.com>
1 parent 826b75e commit ae8fa4e

File tree

15 files changed

+405
-307
lines changed

15 files changed

+405
-307
lines changed

src/libbsdl/include/BSDL/MTX/bsdf_dielectric_decl.h

Lines changed: 20 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
#pragma once
77

8-
#include <BSDL/SPI/bsdf_dielectric_decl.h>
98
#include <BSDL/bsdf_decl.h>
109
#include <BSDL/microfacet_tools_decl.h>
1110

@@ -20,14 +19,17 @@ struct DielectricFresnel {
2019
static BSDL_INLINE_METHOD DielectricFresnel from_table_index(float tx,
2120
bool backside);
2221
BSDL_INLINE_METHOD float table_index() const;
22+
BSDL_INLINE_METHOD float refraction_eta() const { return eta; }
2323

2424
float eta;
2525

2626
static constexpr float IOR_MIN = 1.001f;
2727
static constexpr float IOR_MAX = 5.0f;
2828
};
2929

30-
struct DielectricRefl {
30+
// Microfacet dielectric, generic over the Fresnel model.
31+
// Concrete types (Dielectric, Schlick) inherit from this.
32+
template<typename Fresnel> struct DielectricBSDF {
3133
// describe how tabulation should be done
3234
static constexpr int Nc = 16;
3335
static constexpr int Nr = 16;
@@ -38,20 +40,17 @@ struct DielectricRefl {
3840
return std::max(float(i) * (1.0f / (Nc - 1)), 1e-6f);
3941
}
4042

41-
explicit BSDL_INLINE_METHOD
42-
DielectricRefl(float cosNO, float roughness_index, float fresnel_index);
43-
4443
BSDL_INLINE_METHOD
45-
DielectricRefl(const GGXDist& dist, const DielectricFresnel& fresnel,
46-
float cosNO, float roughness);
44+
DielectricBSDF(const GGXDist& dist, const Fresnel& fresnel, float cosNO,
45+
float roughness, bool dorefr);
4746

48-
DielectricRefl() = default;
47+
DielectricBSDF() = default;
4948

5049
BSDL_INLINE_METHOD Sample eval(Imath::V3f wo, Imath::V3f wi) const;
5150
BSDL_INLINE_METHOD Sample sample(Imath::V3f wo, float randu, float randv,
5251
float randw) const;
5352

54-
BSDL_INLINE_METHOD DielectricFresnel fresnel() const { return f; }
53+
BSDL_INLINE_METHOD Fresnel fresnel() const { return f; }
5554

5655
struct Energy {
5756
float data[Nf * Nr * Nc];
@@ -60,81 +59,44 @@ struct DielectricRefl {
6059

6160
protected:
6261
GGXDist d;
63-
DielectricFresnel f;
64-
float E_ms; // No fresnel here
62+
Fresnel f;
63+
float E_ms;
64+
bool dorefr;
6565
};
6666

67-
struct DielectricReflFront : public DielectricRefl {
68-
DielectricReflFront() = default;
67+
// For table baking purposes, they can't be templated because of the baking
68+
// logic in genluts.cpp
69+
struct DielectricReflFront : public DielectricBSDF<DielectricFresnel> {
6970
explicit BSDL_INLINE_METHOD DielectricReflFront(float cosNO,
7071
float roughness_index,
7172
float fresnel_index);
72-
static BSDL_INLINE_METHOD Energy& get_energy();
7373
static const char* lut_header()
7474
{
7575
return "MTX/bsdf_dielectric_reflfront_luts.h";
7676
}
7777
static const char* struct_name() { return "DielectricReflFront"; }
78+
static BSDL_INLINE_METHOD Energy& get_energy();
7879
};
79-
80-
struct DielectricBoth {
81-
static constexpr int Nc = 16;
82-
static constexpr int Nr = 16;
83-
static constexpr int Nf = 32;
84-
85-
static constexpr float get_cosine(int i)
86-
{
87-
return std::max(float(i) * (1.0f / (Nc - 1)), 1e-6f);
88-
}
89-
90-
DielectricBoth() = default;
91-
explicit BSDL_INLINE_METHOD DielectricBoth(float cosNO,
92-
float roughness_index,
93-
float fresnel_index,
94-
bool backside);
95-
BSDL_INLINE_METHOD
96-
DielectricBoth(const GGXDist& dist, const DielectricFresnel& fresnel);
97-
98-
BSDL_INLINE_METHOD DielectricFresnel fresnel() const { return f; }
99-
100-
BSDL_INLINE_METHOD Sample eval(Imath::V3f wo, Imath::V3f wi) const;
101-
BSDL_INLINE_METHOD Sample sample(Imath::V3f wo, float randu, float randv,
102-
float randw) const;
103-
104-
struct Energy {
105-
float data[Nf * Nr * Nc];
106-
};
107-
static constexpr const char* NS = "mtx";
108-
109-
protected:
110-
GGXDist d;
111-
DielectricFresnel f;
112-
};
113-
114-
struct DielectricBothFront : public DielectricBoth {
115-
DielectricBothFront() = default;
80+
struct DielectricBothFront : public DielectricBSDF<DielectricFresnel> {
11681
explicit BSDL_INLINE_METHOD DielectricBothFront(float cosNO,
11782
float roughness_index,
11883
float fresnel_index);
119-
static BSDL_INLINE_METHOD Energy& get_energy();
12084
static const char* lut_header()
12185
{
12286
return "MTX/bsdf_dielectric_bothfront_luts.h";
12387
}
12488
static const char* struct_name() { return "DielectricBothFront"; }
89+
static BSDL_INLINE_METHOD Energy& get_energy();
12590
};
126-
127-
struct DielectricBothBack : public DielectricBoth {
128-
DielectricBothBack() = default;
91+
struct DielectricBothBack : public DielectricBSDF<DielectricFresnel> {
12992
explicit BSDL_INLINE_METHOD
13093
DielectricBothBack(float cosNO, float roughness_index, float fresnel_index);
131-
static BSDL_INLINE_METHOD Energy& get_energy();
132-
13394
static const char* lut_header()
13495
{
13596
return "MTX/bsdf_dielectric_bothback_luts.h";
13697
}
13798
static const char* struct_name() { return "DielectricBothBack"; }
99+
static BSDL_INLINE_METHOD Energy& get_energy();
138100
};
139101

140102
template<typename BSDF_ROOT> struct DielectricLobe : public Lobe<BSDF_ROOT> {
@@ -192,10 +154,7 @@ template<typename BSDF_ROOT> struct DielectricLobe : public Lobe<BSDF_ROOT> {
192154
protected:
193155
BSDL_INLINE_METHOD Power get_tint(float cosNI) const;
194156

195-
union {
196-
DielectricRefl refl;
197-
DielectricBoth both;
198-
} spec;
157+
DielectricBSDF<DielectricFresnel> spec;
199158
Power refl_tint;
200159
Power refr_tint;
201160
Power wo_absorption;

0 commit comments

Comments
 (0)