-
Notifications
You must be signed in to change notification settings - Fork 67
Iridescent fresnel, bxdfs #918
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 9 commits
4b3224a
9c71906
0f51306
f205d4e
f6daa6f
09402ea
a77c337
aa0f6e8
d2cb193
33fc955
0f6c7a2
d8b6773
65239d9
9a8b77e
702ec8d
76ad0ed
53c930f
23de8ed
ff9e03f
18b3922
a5d8f5c
f3dd05c
68d3614
aebfecf
b53fa1b
946b050
1a2f561
4b8a06b
5782a49
55471ca
64be771
8f9a114
8a71f40
dee1b61
cd9b18b
0984c7e
3d7ded6
1908749
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -345,14 +345,16 @@ struct Schlick | |
| using vector_type = T; | ||
| using eta_type = vector_type; | ||
|
|
||
| NBL_CONSTEXPR_STATIC_INLINE bool ReturnsMonochrome = vector_traits<vector_type>::Dimension == 1; | ||
|
|
||
| static Schlick<T> create(NBL_CONST_REF_ARG(T) F0) | ||
| { | ||
| Schlick<T> retval; | ||
| retval.F0 = F0; | ||
| return retval; | ||
| } | ||
|
|
||
| T operator()(const scalar_type clampedCosTheta) | ||
| T operator()(const scalar_type clampedCosTheta) NBL_CONST_MEMBER_FUNC | ||
| { | ||
| assert(clampedCosTheta >= scalar_type(0.0)); | ||
| assert(hlsl::all(hlsl::promote<T>(0.02) < F0 && F0 <= hlsl::promote<T>(1.0))); | ||
|
|
@@ -379,6 +381,8 @@ struct Conductor | |
| using vector_type = T; | ||
| using eta_type = vector_type; | ||
|
|
||
| NBL_CONSTEXPR_STATIC_INLINE bool ReturnsMonochrome = vector_traits<vector_type>::Dimension == 1; | ||
|
|
||
| static Conductor<T> create(NBL_CONST_REF_ARG(T) eta, NBL_CONST_REF_ARG(T) etak) | ||
| { | ||
| Conductor<T> retval; | ||
|
|
@@ -397,40 +401,25 @@ struct Conductor | |
| return retval; | ||
| } | ||
|
|
||
| // TODO: will probably merge with __call at some point | ||
| static void __polarized(const T orientedEta, const T orientedEtak, const T cosTheta, NBL_REF_ARG(T) Rp, NBL_REF_ARG(T) Rs) | ||
| static void __polarized(const T orientedEta, const T etaLen2, const T clampedCosTheta, NBL_REF_ARG(T) Rp, NBL_REF_ARG(T) Rs) | ||
| { | ||
| T cosTheta_2 = cosTheta * cosTheta; | ||
| T sinTheta2 = hlsl::promote<T>(1.0) - cosTheta_2; | ||
| const T cosTheta_2 = clampedCosTheta * clampedCosTheta; | ||
| const T eta = orientedEta; | ||
| const T eta2 = eta*eta; | ||
| const T etak = orientedEtak; | ||
| const T etak2 = etak*etak; | ||
|
|
||
| const T etaLen2 = eta2 + etak2; | ||
| assert(hlsl::all(etaLen2 > hlsl::promote<T>(hlsl::exp2<scalar_type>(-numeric_limits<scalar_type>::digits)))); | ||
| T t1 = etaLen2 * cosTheta_2; | ||
| const T etaCosTwice = eta * cosTheta * scalar_type(2.0); | ||
| const T etaCosTwice = eta * clampedCosTheta * hlsl::promote<T>(2.0); | ||
devshgraphicsprogramming marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| const T rs_common = etaLen2 + cosTheta_2; | ||
| Rs = (rs_common - etaCosTwice) / (rs_common + etaCosTwice); | ||
| const T rp_common = t1 + hlsl::promote<T>(1.0); | ||
| Rp = (rp_common - etaCosTwice) / (rp_common + etaCosTwice); | ||
| } | ||
|
|
||
| T operator()(const scalar_type clampedCosTheta) | ||
| T operator()(const scalar_type clampedCosTheta) NBL_CONST_MEMBER_FUNC | ||
| { | ||
| const scalar_type cosTheta_2 = clampedCosTheta * clampedCosTheta; | ||
| //const float sinTheta2 = 1.0 - cosTheta_2; | ||
|
|
||
| assert(hlsl::all(etaLen2 > hlsl::promote<T>(hlsl::exp2<scalar_type>(-numeric_limits<scalar_type>::digits)))); | ||
| const T etaCosTwice = eta * clampedCosTheta * hlsl::promote<T>(2.0); | ||
|
|
||
| const T rs_common = etaLen2 + hlsl::promote<T>(cosTheta_2); | ||
| const T rs2 = (rs_common - etaCosTwice) / (rs_common + etaCosTwice); | ||
|
|
||
| const T rp_common = etaLen2 * cosTheta_2 + hlsl::promote<T>(1.0); | ||
| const T rp2 = (rp_common - etaCosTwice) / (rp_common + etaCosTwice); | ||
| T rs2, rp2; | ||
| __polarized(eta, etaLen2, hlsl::promote<T>(clampedCosTheta), rp2, rs2); | ||
|
|
||
| return (rs2 + rp2) * hlsl::promote<T>(0.5); | ||
| } | ||
|
|
@@ -455,6 +444,8 @@ struct Dielectric | |
| using vector_type = T; | ||
| using eta_type = vector_type; | ||
|
|
||
| NBL_CONSTEXPR_STATIC_INLINE bool ReturnsMonochrome = vector_traits<vector_type>::Dimension == 1; | ||
|
|
||
| static Dielectric<T> create(NBL_CONST_REF_ARG(OrientedEtas<T>) orientedEta) | ||
| { | ||
| Dielectric<T> retval; | ||
|
|
@@ -463,15 +454,13 @@ struct Dielectric | |
| return retval; | ||
| } | ||
|
|
||
| // TODO: will probably merge with __call at some point | ||
| static void __polarized(const T orientedEta, const T cosTheta, NBL_REF_ARG(T) Rp, NBL_REF_ARG(T) Rs) | ||
| static void __polarized(const T orientedEta2, const T cosTheta, NBL_REF_ARG(T) Rp, NBL_REF_ARG(T) Rs) | ||
| { | ||
| T sinTheta2 = hlsl::promote<T>(1.0) - cosTheta * cosTheta; | ||
| const T eta = orientedEta; | ||
| const T eta2 = eta * eta; | ||
| const T sinTheta2 = hlsl::promote<T>(1.0) - cosTheta * cosTheta; | ||
|
|
||
| T t0 = hlsl::sqrt(eta2 - sinTheta2); | ||
| T t2 = eta2 * cosTheta; | ||
| // the max() clamping can handle TIR when orientedEta2<1.0 | ||
| T t0 = hlsl::sqrt(hlsl::max(orientedEta2 - sinTheta2, hlsl::promote<T>(0.0))); | ||
| T t2 = orientedEta2 * cosTheta; | ||
|
|
||
| T rp = (t0 - t2) / (t0 + t2); | ||
| Rp = rp * rp; | ||
|
|
@@ -481,19 +470,13 @@ struct Dielectric | |
|
|
||
| static T __call(NBL_CONST_REF_ARG(T) orientedEta2, const scalar_type clampedCosTheta) | ||
| { | ||
| const scalar_type sinTheta2 = scalar_type(1.0) - clampedCosTheta * clampedCosTheta; | ||
|
|
||
| // the max() clamping can handle TIR when orientedEta2<1.0 | ||
| const T t0 = hlsl::sqrt<T>(hlsl::max<T>(orientedEta2 - sinTheta2, hlsl::promote<T>(0.0))); | ||
| const T rs = (hlsl::promote<T>(clampedCosTheta) - t0) / (hlsl::promote<T>(clampedCosTheta) + t0); | ||
|
|
||
| const T t2 = orientedEta2 * clampedCosTheta; | ||
| const T rp = (t0 - t2) / (t0 + t2); | ||
| T rs2, rp2; | ||
| __polarized(orientedEta2, hlsl::promote<T>(clampedCosTheta), rp2, rs2); | ||
|
|
||
| return (rs * rs + rp * rp) * scalar_type(0.5); | ||
| return (rs2 + rp2) * hlsl::promote<T>(0.5); | ||
| } | ||
|
|
||
| T operator()(const scalar_type clampedCosTheta) | ||
| T operator()(const scalar_type clampedCosTheta) NBL_CONST_MEMBER_FUNC | ||
| { | ||
| return __call(orientedEta2, clampedCosTheta); | ||
| } | ||
|
|
@@ -560,37 +543,47 @@ struct iridescent_helper | |
| return xyz / scalar_type(1.0685e-7); | ||
| } | ||
|
|
||
| T __call(const scalar_type clampedCosTheta) | ||
| template<typename Params> | ||
| static T __call(NBL_CONST_REF_ARG(Params) params, const scalar_type clampedCosTheta) | ||
| { | ||
| const vector_type wavelengths = vector_type(colorspace::scRGB::wavelength_R, colorspace::scRGB::wavelength_G, colorspace::scRGB::wavelength_B); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suppy colorspace from |
||
|
|
||
| scalar_type cosTheta_1 = clampedCosTheta; | ||
| const vector_type eta12 = params.getEta12(); | ||
| const vector_type eta23 = params.getEta23(); | ||
| const vector_type etak23 = params.getEtak23(); | ||
| const scalar_type cosTheta_1 = clampedCosTheta; | ||
| vector_type cosTheta_2; | ||
|
|
||
| vector_type R12p, R23p, R12s, R23s; | ||
| const vector_type scale = scalar_type(1.0)/eta12; | ||
| const vector_type cosTheta2_2 = hlsl::promote<vector_type>(1.0) - hlsl::promote<vector_type>(1-cosTheta_1*cosTheta_1) * scale * scale; | ||
| const vector_type cosTheta2_2 = hlsl::promote<vector_type>(1.0) - hlsl::promote<vector_type>(1.0-cosTheta_1*cosTheta_1) * scale * scale; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this you can declare a |
||
|
|
||
| cosTheta_2 = hlsl::sqrt(cosTheta2_2); | ||
| cosTheta_2 = hlsl::sqrt(hlsl::max(cosTheta2_2, hlsl::promote<vector_type>(0.0))); | ||
|
||
| Dielectric<vector_type>::__polarized(eta12, hlsl::promote<vector_type>(cosTheta_1), R12p, R12s); | ||
|
|
||
| // Reflected part by the base | ||
| // if kappa==0, base material is dielectric | ||
| NBL_IF_CONSTEXPR(SupportsTransmission) | ||
| Dielectric<vector_type>::__polarized(eta23, cosTheta_2, R23p, R23s); | ||
| Dielectric<vector_type>::__polarized(eta23 * eta23, cosTheta_2, R23p, R23s); | ||
| else | ||
| Conductor<vector_type>::__polarized(eta23, etak23, cosTheta_2, R23p, R23s); | ||
| { | ||
| vector_type etaLen2 = eta23 * eta23 + etak23 * etak23; | ||
| Conductor<vector_type>::__polarized(eta23, etaLen2, cosTheta_2, R23p, R23s); | ||
| } | ||
|
|
||
| // Check for total internal reflection | ||
| R12s = hlsl::mix(R12s, hlsl::promote<vector_type>(1.0), cosTheta2_2 <= hlsl::promote<vector_type>(0.0)); | ||
| R12p = hlsl::mix(R12p, hlsl::promote<vector_type>(1.0), cosTheta2_2 <= hlsl::promote<vector_type>(0.0)); | ||
|
|
||
| R23s = hlsl::mix(R23s, hlsl::promote<vector_type>(0.0), cosTheta2_2 <= hlsl::promote<vector_type>(0.0)); | ||
| R23p = hlsl::mix(R23p, hlsl::promote<vector_type>(0.0), cosTheta2_2 <= hlsl::promote<vector_type>(0.0)); | ||
|
||
|
|
||
| // Compute the transmission coefficients | ||
| vector_type T121p = hlsl::promote<vector_type>(1.0) - R12p; | ||
| vector_type T121s = hlsl::promote<vector_type>(1.0) - R12s; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. actually it would make sense to compute a
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also it would make sense to have a because you can make a and then you can compute then obviously you compute |
||
|
|
||
| // Optical Path Difference | ||
| const vector_type D = hlsl::promote<vector_type>(2.0 * Dinc) * thinFilmIor * cosTheta_2; | ||
| const vector_type D = hlsl::promote<vector_type>(2.0 * params.getDinc()) * params.getThinFilmIor() * cosTheta_2; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| const vector_type Dphi = hlsl::promote<vector_type>(2.0 * numbers::pi<scalar_type>) * D / wavelengths; | ||
|
|
||
| vector_type phi21p, phi21s, phi23p, phi23s, r123s, r123p, Rs; | ||
|
|
@@ -639,6 +632,25 @@ struct iridescent_helper | |
|
|
||
| return hlsl::max(colorspace::scRGB::FromXYZ(I), hlsl::promote<vector_type>(0.0)) * hlsl::promote<vector_type>(0.5); | ||
| } | ||
| }; | ||
|
|
||
| template<typename T, bool SupportsTransmission NBL_PRIMARY_REQUIRES(concepts::FloatingPointLikeVectorial<T>) | ||
| struct iridescent_base | ||
| { | ||
| using scalar_type = typename vector_traits<T>::scalar_type; | ||
| using vector_type = T; | ||
|
|
||
| scalar_type getDinc() NBL_CONST_MEMBER_FUNC { return Dinc; } | ||
| vector_type getThinFilmIor() NBL_CONST_MEMBER_FUNC { return thinFilmIor; } | ||
| vector_type getEta12() NBL_CONST_MEMBER_FUNC { return eta12; } | ||
| vector_type getEta23() NBL_CONST_MEMBER_FUNC { return eta23; } | ||
| vector_type getEtak23() NBL_CONST_MEMBER_FUNC | ||
| { | ||
| NBL_IF_CONSTEXPR(SupportsTransmission) | ||
| return hlsl::promote<vector_type>(0.0); | ||
| else | ||
| return etak23; | ||
| } | ||
|
|
||
| scalar_type Dinc; // thickness of thin film in nanometers, rec. 100-25000nm | ||
| vector_type thinFilmIor; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. still you are storking don't take
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
if you want more semantically clear initialization make creation parameter structs for |
||
|
|
@@ -656,32 +668,24 @@ struct Iridescent<T, false NBL_PARTIAL_REQ_BOT(concepts::FloatingPointLikeVector | |
| using scalar_type = typename vector_traits<T>::scalar_type; | ||
| using vector_type = T; // assert dim==3? | ||
| using eta_type = vector_type; | ||
| using base_type = impl::iridescent_base<T, false>; | ||
|
|
||
| static this_t create(scalar_type Dinc, vector_type ior1, vector_type ior2, vector_type ior3, vector_type iork3) | ||
| { | ||
| this_t retval; | ||
| retval.helper.Dinc = Dinc; | ||
| retval.helper.thinFilmIor = ior2; | ||
| retval.helper.eta12 = ior2/ior1; | ||
| retval.helper.eta23 = ior3/ior2; | ||
| retval.helper.etak23 = iork3/ior2; | ||
| return retval; | ||
| } | ||
|
||
| NBL_CONSTEXPR_STATIC_INLINE bool ReturnsMonochrome = vector_traits<vector_type>::Dimension == 1; | ||
|
|
||
| T operator()(const scalar_type clampedCosTheta) | ||
| T operator()(const scalar_type clampedCosTheta) NBL_CONST_MEMBER_FUNC | ||
| { | ||
| return helper.__call(clampedCosTheta); | ||
| return impl::iridescent_helper<T,false>::template __call<base_type>(__base, clampedCosTheta); | ||
| } | ||
|
|
||
| OrientedEtaRcps<eta_type> getOrientedEtaRcps() NBL_CONST_MEMBER_FUNC | ||
| { | ||
| OrientedEtaRcps<eta_type> rcpEta; | ||
| rcpEta.value = hlsl::promote<eta_type>(1.0) / helper.eta23; | ||
| rcpEta.value = hlsl::promote<eta_type>(1.0) / __base.eta23; | ||
| rcpEta.value2 = rcpEta.value * rcpEta.value; | ||
| return rcpEta; | ||
| } | ||
|
|
||
| impl::iridescent_helper<T,false> helper; | ||
| base_type __base; | ||
| }; | ||
|
|
||
| template<typename T> | ||
|
|
@@ -692,28 +696,20 @@ struct Iridescent<T, true NBL_PARTIAL_REQ_BOT(concepts::FloatingPointLikeVectori | |
| using scalar_type = typename vector_traits<T>::scalar_type; | ||
| using vector_type = T; // assert dim==3? | ||
| using eta_type = vector<scalar_type, 1>; | ||
| using base_type = impl::iridescent_base<T, true>; | ||
|
|
||
| static this_t create(scalar_type Dinc, vector_type ior1, vector_type ior2, vector_type ior3) | ||
| { | ||
| this_t retval; | ||
| retval.helper.Dinc = Dinc; | ||
| retval.helper.thinFilmIor = ior2; | ||
| retval.helper.eta12 = ior2/ior1; | ||
| retval.helper.eta23 = ior3/ior2; | ||
| retval.helper.etak23 = hlsl::promote<vector_type>(0.0); | ||
| return retval; | ||
| } | ||
| NBL_CONSTEXPR_STATIC_INLINE bool ReturnsMonochrome = vector_traits<vector_type>::Dimension == 1; | ||
|
|
||
| T operator()(const scalar_type clampedCosTheta) | ||
| T operator()(const scalar_type clampedCosTheta) NBL_CONST_MEMBER_FUNC | ||
| { | ||
| return helper.__call(clampedCosTheta); | ||
| return impl::iridescent_helper<T,true>::template __call<base_type>(__base, clampedCosTheta); | ||
| } | ||
|
|
||
| scalar_type getRefractionOrientedEta() NBL_CONST_MEMBER_FUNC { return helper.eta23[0]; } | ||
| scalar_type getRefractionOrientedEta() NBL_CONST_MEMBER_FUNC { return __base.eta23[0]; } | ||
| OrientedEtaRcps<eta_type> getOrientedEtaRcps() NBL_CONST_MEMBER_FUNC | ||
| { | ||
| OrientedEtaRcps<eta_type> rcpEta; | ||
| rcpEta.value = hlsl::promote<eta_type>(1.0) / helper.eta23[0]; | ||
| rcpEta.value = hlsl::promote<eta_type>(1.0) / __base.eta23[0]; | ||
| rcpEta.value2 = rcpEta.value * rcpEta.value; | ||
| return rcpEta; | ||
| } | ||
|
|
@@ -722,15 +718,15 @@ struct Iridescent<T, true NBL_PARTIAL_REQ_BOT(concepts::FloatingPointLikeVectori | |
| { | ||
| const bool flip = NdotI < scalar_type(0.0); | ||
| this_t orientedFresnel; | ||
| orientedFresnel.helper.Dinc = helper.Dinc; | ||
| orientedFresnel.helper.thinFilmIor = helper.thinFilmIor; | ||
| orientedFresnel.helper.eta12 = hlsl::mix(helper.eta12, hlsl::promote<vector_type>(1.0)/helper.eta12, flip); | ||
| orientedFresnel.helper.eta23 = hlsl::mix(helper.eta23, hlsl::promote<vector_type>(1.0)/helper.eta23, flip); | ||
| orientedFresnel.helper.etak23 = hlsl::promote<vector_type>(0.0); | ||
| orientedFresnel.__base.Dinc = __base.Dinc; | ||
| orientedFresnel.__base.thinFilmIor = __base.thinFilmIor; | ||
| orientedFresnel.__base.eta12 = hlsl::mix(__base.eta12, hlsl::promote<vector_type>(1.0)/__base.eta12, flip); | ||
| orientedFresnel.__base.eta23 = hlsl::mix(__base.eta23, hlsl::promote<vector_type>(1.0)/__base.eta23, flip); | ||
| orientedFresnel.__base.etak23 = hlsl::promote<vector_type>(0.0); | ||
| return orientedFresnel; | ||
| } | ||
|
|
||
| impl::iridescent_helper<T,true> helper; | ||
| base_type __base; | ||
| }; | ||
|
|
||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -339,6 +339,8 @@ struct Beckmann | |
| if (isInfinity) | ||
| { | ||
| quant_type dmq; | ||
| dmq.microfacetMeasure = scalar_type(0.0); | ||
| dmq.projectedLightMeasure = scalar_type(0.0); | ||
|
Comment on lines
+342
to
+343
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. both should be set to |
||
| return dmq; | ||
| } | ||
| scalar_type dg1 = D / (scalar_type(1.0) + query.getLambdaV()); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -278,7 +278,11 @@ struct GGX | |
| isInfinity = hlsl::isinf(D); | ||
| quant_type dmq; | ||
| if (isInfinity) | ||
| { | ||
| dmq.microfacetMeasure = scalar_type(0.0); | ||
| dmq.projectedLightMeasure = scalar_type(0.0); | ||
|
Comment on lines
+282
to
+283
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. both should be set to |
||
| return dmq; | ||
| } | ||
|
|
||
| scalar_type dg1_over_2NdotV = D * query.getG1over2NdotV(); | ||
| dmq.microfacetMeasure = scalar_type(2.0) * interaction.getNdotV(BxDFClampMode::BCM_ABS) * dg1_over_2NdotV; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cool but this method/function should not be part of
ConductororDielectricclass, can make it free floating infresnelnamespace if you want