-
Notifications
You must be signed in to change notification settings - Fork 64
Hlsl bxdfs 4 #916
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
Hlsl bxdfs 4 #916
Conversation
struct SCreationParams | ||
{ | ||
scalar_type A; | ||
spectral_type ior0; | ||
spectral_type ior1; | ||
}; | ||
using creation_type = SCreationParams; | ||
|
||
struct SGGXQuery | ||
{ | ||
using scalar_type = scalar_type; | ||
|
||
scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } | ||
scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } | ||
|
||
scalar_type devsh_v; | ||
scalar_type devsh_l; | ||
}; | ||
using query_type = SGGXQuery; | ||
|
||
static this_t create(scalar_type A, NBL_CONST_REF_ARG(spectral_type) ior0, NBL_CONST_REF_ARG(spectral_type) ior1) | ||
{ | ||
this_t retval; | ||
retval.__base.ndf.A = vector2_type(A, A); | ||
retval.__base.ndf.a2 = A*A; | ||
retval.__base.ndf.one_minus_a2 = scalar_type(1.0) - A*A; | ||
retval.__base.fresnel.eta = ior0; | ||
retval.__base.fresnel.etak = ior1; | ||
retval.__base.fresnel.etak2 = ior1*ior1; | ||
return retval; | ||
} | ||
static this_t create(NBL_CONST_REF_ARG(creation_type) params) | ||
{ | ||
return create(params.A, params.ior0, params.ior1); | ||
} | ||
|
||
query_type createQuery(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction) | ||
{ | ||
query_type query; | ||
ndf_type ggx_ndf = __base.ndf; | ||
query.devsh_v = ggx_ndf.devsh_part(interaction.getNdotV2()); | ||
query.devsh_l = ggx_ndf.devsh_part(_sample.getNdotL2()); | ||
return query; | ||
} | ||
|
||
spectral_type eval(NBL_CONST_REF_ARG(query_type) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) | ||
{ | ||
if (_sample.getNdotL() > numeric_limits<scalar_type>::min && interaction.getNdotV() > numeric_limits<scalar_type>::min) | ||
{ | ||
struct SGGXG2XQuery | ||
{ | ||
using scalar_type = scalar_type; | ||
|
||
scalar_type getDevshV() NBL_CONST_MEMBER_FUNC { return devsh_v; } | ||
scalar_type getDevshL() NBL_CONST_MEMBER_FUNC { return devsh_l; } | ||
BxDFClampMode getClampMode() NBL_CONST_MEMBER_FUNC { return _clamp; } | ||
|
||
scalar_type devsh_v; | ||
scalar_type devsh_l; | ||
BxDFClampMode _clamp; | ||
}; | ||
|
||
SGGXG2XQuery g2_query; | ||
g2_query.devsh_v = query.getDevshV(); | ||
g2_query.devsh_l = query.getDevshL(); | ||
g2_query._clamp = _clamp; | ||
|
||
measure_transform_type dualMeasure = __base.template __DG<SGGXG2XQuery>(g2_query, _sample, interaction, cache); | ||
dualMeasure.maxNdotL = _sample.getNdotL(_clamp); | ||
scalar_type DG = dualMeasure.getProjectedLightMeasure(); | ||
fresnel_type f = __base.fresnel; | ||
f.clampedCosTheta = cache.getVdotH(); | ||
return f() * DG; | ||
} | ||
else | ||
return hlsl::promote<spectral_type>(0.0); | ||
} | ||
|
||
sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, const vector2_type u, NBL_REF_ARG(isocache_type) cache) | ||
{ | ||
SGGXAnisotropic<Config> ggx_aniso = SGGXAnisotropic<Config>::create(__base.ndf.A.x, __base.ndf.A.y, __base.fresnel.eta, __base.fresnel.etak); | ||
anisocache_type anisocache; | ||
sample_type s = ggx_aniso.generate(anisotropic_interaction_type::create(interaction), u, anisocache); | ||
cache = anisocache.iso_cache; | ||
return s; | ||
} |
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.
same comments as for beckmann
namespace impl | ||
{ | ||
struct sincos_accumulator | ||
{ | ||
using this_t = sincos_accumulator; | ||
|
||
static this_t create() | ||
{ | ||
this_t retval; | ||
retval.tmp0 = 0; | ||
retval.tmp1 = 0; | ||
retval.tmp2 = 0; | ||
retval.tmp3 = 0; | ||
retval.tmp4 = 0; | ||
retval.tmp5 = 0; | ||
return retval; | ||
} | ||
|
||
static this_t create(float cosA, float cosB, float cosC, float sinA, float sinB, float sinC) | ||
{ | ||
this_t retval; | ||
retval.tmp0 = cosA; | ||
retval.tmp1 = cosB; | ||
retval.tmp2 = cosC; | ||
retval.tmp3 = sinA; | ||
retval.tmp4 = sinB; | ||
retval.tmp5 = sinC; | ||
return retval; | ||
} | ||
|
||
float getArccosSumofABC_minus_PI() | ||
{ | ||
const bool AltminusB = tmp0 < (-tmp1); | ||
const float cosSumAB = tmp0 * tmp1 - tmp3 * tmp4; | ||
const bool ABltminusC = cosSumAB < (-tmp2); | ||
const bool ABltC = cosSumAB < tmp2; | ||
// apply triple angle formula | ||
const float absArccosSumABC = acos<float>(clamp<float>(cosSumAB * tmp2 - (tmp0 * tmp4 + tmp3 * tmp1) * tmp5, -1.f, 1.f)); | ||
return ((AltminusB ? ABltC : ABltminusC) ? (-absArccosSumABC) : absArccosSumABC) + ((AltminusB || ABltminusC) ? numbers::pi<float> : (-numbers::pi<float>)); | ||
} | ||
|
||
static void combineCosForSumOfAcos(float cosA, float cosB, float biasA, float biasB, NBL_REF_ARG(float) out0, NBL_REF_ARG(float) out1) | ||
{ | ||
const float bias = biasA + biasB; | ||
const float a = cosA; | ||
const float b = cosB; | ||
const bool reverse = abs<float>(min<float>(a, b)) > max<float>(a, b); | ||
const float c = a * b - sqrt<float>((1.0f - a * a) * (1.0f - b * b)); | ||
|
||
if (reverse) | ||
{ | ||
out0 = -c; | ||
out1 = bias + numbers::pi<float>; | ||
} | ||
else | ||
{ | ||
out0 = c; | ||
out1 = bias; | ||
} | ||
} | ||
|
||
float tmp0; | ||
float tmp1; | ||
float tmp2; | ||
float tmp3; | ||
float tmp4; | ||
float tmp5; | ||
}; | ||
} |
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.
See #899 (comment)
Also no need for this to stay in impl
ray_dir_info_type localL; | ||
bxdf::Reflect<scalar_type> r = bxdf::Reflect<scalar_type>::create(localV, H); | ||
localL.direction = r(cache.iso_cache.getVdotH()); |
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.
you need to use interaction.getV().reflect(r)
to build localL
otherwise in the future you'll loose ray-differentials or covariance matrices
struct SCreationParams | ||
{ | ||
scalar_type eta; | ||
}; | ||
using creation_type = SCreationParams; | ||
|
||
static this_t create(scalar_type eta) | ||
{ | ||
this_t retval; | ||
retval.eta = eta; | ||
return retval; | ||
} | ||
static this_t create(NBL_CONST_REF_ARG(creation_type) params) | ||
{ | ||
return create(params.eta); | ||
} |
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.
make the eta
a full fresnel::Dielectric
member, get rid of create
methods
struct SCreationParams | ||
{ | ||
spectral_type eta2; | ||
spectral_type luminosityContributionHint; | ||
}; | ||
using creation_type = SCreationParams; |
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.
remove creation params and its associated create
return quotient_and_pdf(_sample, interaction.isotropic); | ||
} | ||
|
||
spectral_type eta2; |
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.
hold fresnel::Dielectric
as a member instead
static this_t create(NBL_CONST_REF_ARG(spectral_type) eta2) | ||
{ | ||
static_assert(vector_traits<spectral_type>::Dimension == 3); | ||
const spectral_type rec709 = spectral_type(0.2126, 0.7152, 0.0722); | ||
return create(eta2, rec709); | ||
} |
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.
useful don't touch
// `remainderMetadata` is a variable which the generator function returns byproducts of sample generation that would otherwise have to be redundantly calculated `quotient_and_pdf` | ||
sample_type __generate_wo_clamps(NBL_CONST_REF_ARG(ray_dir_info_type) V, const vector3_type T, const vector3_type B, const vector3_type N, scalar_type NdotV, scalar_type absNdotV, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(spectral_type) eta2, NBL_CONST_REF_ARG(spectral_type) luminosityContributionHint, NBL_REF_ARG(spectral_type) remainderMetadata) | ||
{ | ||
// we will only ever intersect from the outside | ||
const spectral_type reflectance = fresnel::thinDielectricInfiniteScatter<spectral_type>(fresnel::Dielectric<spectral_type>::__call(eta2,absNdotV)); | ||
|
||
// we are only allowed one choice for the entire ray, so make the probability a weighted sum | ||
const scalar_type reflectionProb = nbl::hlsl::dot<spectral_type>(reflectance, luminosityContributionHint); | ||
|
||
scalar_type rcpChoiceProb; | ||
const bool transmitted = math::partitionRandVariable(reflectionProb, u.z, rcpChoiceProb); | ||
remainderMetadata = hlsl::mix(reflectance, hlsl::promote<spectral_type>(1.0) - reflectance, transmitted) * rcpChoiceProb; | ||
|
||
Reflect<scalar_type> r = Reflect<scalar_type>::create(V.getDirection(), N); | ||
ray_dir_info_type L; | ||
L.direction = hlsl::mix(V.reflect(r).getDirection(), V.transmit().getDirection(), transmitted); | ||
return sample_type::create(L, T, B, N); | ||
} |
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.
change the __generate_wo_clamps
into generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, const vector3_type u, NBL_REF_ARG(spectral_type) remainderMetadata)
sample_type generate(NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u) | ||
{ | ||
vector3_type dummy; | ||
return __generate_wo_clamps(interaction.getV(), interaction.getT(), interaction.getB(), interaction.getN(), interaction.getNdotV(), interaction.getNdotV(_clamp), u, eta2, luminosityContributionHint, dummy); | ||
} | ||
sample_type generate(NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_REF_ARG(vector3_type) u) | ||
{ | ||
return generate(anisotropic_interaction_type::create(interaction), u); |
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.
u
shall be taken by copy not reference #899 (comment)
Reflect<scalar_type> r = Reflect<scalar_type>::create(V.getDirection(), N); | ||
ray_dir_info_type L; | ||
L.direction = hlsl::mix(V.reflect(r).getDirection(), V.transmit().getDirection(), transmitted); | ||
return sample_type::create(L, T, B, N); |
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.
you can't build a reflected L
this way, you need to use V.reflect(r)
or V.refract(r,rcpOrientedEta)
btw it seems that the RayDirInfo needs a reflectRefract
method #899 (comment)
For ideas see #899 (comment)
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.
And #899 (comment)
static vector_t3 generate(vector_t3 _sample) | ||
{ | ||
vector_t3 retval = hemisphere_t::generate(_sample.xy); | ||
const bool chooseLower = _sample.z > T(0.5); | ||
retval.z = chooseLower ? (-retval.z) : retval.z; | ||
if (chooseLower) | ||
_sample.z -= T(0.5); | ||
_sample.z *= T(2.0); |
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.
for this to work the _sample
needs to be taken as NBL_REF_ARG
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.transmit()), ::nbl::hlsl::is_same_v, T)) | ||
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.reflect(rfl)), ::nbl::hlsl::is_same_v, T)) | ||
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.refract(rfr, rcpEta)), ::nbl::hlsl::is_same_v, T)) | ||
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((rdirinfo.reflectRefract(rr, t, rcpEta)), ::nbl::hlsl::is_same_v, T)) |
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.
oh we already have reflectRefract
! Then use it in all the BSDF generate
((NBL_CONCEPT_REQ_TYPE)(T::ray_dir_info_type)) | ||
((NBL_CONCEPT_REQ_TYPE)(T::isotropic_interaction_type)) | ||
((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) | ||
((NBL_CONCEPT_REQ_TYPE)(T::vector3_type)) | ||
((NBL_CONCEPT_REQ_TYPE)(T::matrix3x3_type)) |
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.
maybe check that T matches Isotropic first, and then you can only check for things not in that concept ?
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.
also can you add a check for decltype<T>().isotropic
existing ?
retval.VdotL = VdotL; | ||
retval.VdotH = LplusV_rcpLen * VdotL + LplusV_rcpLen; | ||
retval.LdotH = retval.VdotH; | ||
retval.NdotH = (NdotL + NdotV) * LplusV_rcpLen; | ||
retval.NdotH2 = retval.NdotH * retval.NdotH; |
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.
NdotH
member needs to be called absNdotH
and needs to be always be positive, see #899 (comment) for why
Problem is that NdotL+NdotV
can be less than 0, and in that case all dot products with H
need their signs flipped.
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.
Also #899 (comment)
H = computeMicrofacetNormal.normalized(transmitted); | ||
retval.NdotH = hlsl::dot<vector3_type>(N, H); | ||
|
||
// not coming from the medium (reflected) OR | ||
// exiting at the macro scale AND ( (not L outside the cone of possible directions given IoR with constraint VdotH*LdotH<0.0) OR (microfacet not facing toward the macrosurface, i.e. non heightfield profile of microsurface) ) | ||
const bool valid = ComputeMicrofacetNormal<scalar_type>::isValidMicrofacet(transmitted, VdotL, retval.NdotH, computeMicrofacetNormal.orientedEta); | ||
if (valid) | ||
{ | ||
retval.VdotH = hlsl::dot<vector3_type>(computeMicrofacetNormal.V,H); | ||
retval.LdotH = hlsl::dot<vector3_type>(computeMicrofacetNormal.L,H); | ||
retval.NdotH2 = retval.NdotH * retval.NdotH; | ||
} | ||
else | ||
retval.NdotH = bit_cast<scalar_type>(numeric_limits<scalar_type>::quiet_NaN); |
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.
id NdotH
is negative, we need to flip all dot products with H
and H` itself, for why see #899 (comment)
return create(interaction,_sample,orientedEtas,dummy); | ||
} | ||
|
||
bool isTransmission() NBL_CONST_MEMBER_FUNC { return getVdotHLdotH() < scalar_type(0.0); } |
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.
lots of documentation needed for this , see #899 (comment)
retval.iso_cache.VdotH = nbl::hlsl::dot<vector3_type>(tangentSpaceV,tangentSpaceH); | ||
retval.iso_cache.LdotH = retval.iso_cache.getVdotH(); | ||
retval.iso_cache.NdotH = tangentSpaceH.z; | ||
retval.iso_cache.NdotH2 = retval.iso_cache.getNdotH() * retval.iso_cache.getNdotH(); |
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.
assert that tangentSpaceH.z>=0.f
retval.TdotH = (tangentSpaceV.x + tangentSpaceL.x) * LplusV_rcpLen; | ||
retval.BdotH = (tangentSpaceV.y + tangentSpaceL.y) * LplusV_rcpLen; |
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.
care is needed, LplusV_rcpLen
should be made negative if needed by the isocache_type::createForReflection
to keep NdotH
positive
((NBL_CONCEPT_REQ_TYPE)(T::isotropic_interaction_type)) | ||
((NBL_CONCEPT_REQ_TYPE)(T::anisotropic_interaction_type)) | ||
((NBL_CONCEPT_REQ_TYPE)(T::sample_type)) | ||
((NBL_CONCEPT_REQ_TYPE)(T::spectral_type)) | ||
((NBL_CONCEPT_REQ_TYPE)(T::quotient_pdf_type)) | ||
((NBL_CONCEPT_REQ_TYPE)(T::params_isotropic_t)) | ||
((NBL_CONCEPT_REQ_TYPE)(T::params_anisotropic_t)) | ||
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.eval(param_iso)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) | ||
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.eval(param_aniso)), ::nbl::hlsl::is_same_v, typename T::scalar_type)) | ||
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.generate(iso,u)), ::nbl::hlsl::is_same_v, typename T::sample_type)) | ||
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.generate(aniso,u)), ::nbl::hlsl::is_same_v, typename T::sample_type)) | ||
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.quotient_and_pdf(param_iso)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) | ||
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.quotient_and_pdf(param_aniso)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) | ||
((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(LightSample, typename T::sample_type)) | ||
((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(concepts::FloatingPointLikeVectorial, typename T::spectral_type)) | ||
((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Isotropic, typename T::isotropic_interaction_type)) | ||
((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(surface_interactions::Anisotropic, typename T::anisotropic_interaction_type)) | ||
); | ||
#undef u | ||
#undef param_aniso | ||
#undef param_iso | ||
#undef aniso | ||
#undef iso | ||
#undef _sample | ||
#undef pdf | ||
#undef spec | ||
#undef bxdf | ||
#include <nbl/builtin/hlsl/concepts/__end.hlsl> | ||
|
||
#define NBL_CONCEPT_NAME MicrofacetBxDF | ||
#define NBL_CONCEPT_TPLT_PRM_KINDS (typename) | ||
#define NBL_CONCEPT_TPLT_PRM_NAMES (T) | ||
#define NBL_CONCEPT_PARAM_0 (bxdf, T) | ||
#define NBL_CONCEPT_PARAM_1 (spec, typename T::spectral_type) | ||
#define NBL_CONCEPT_PARAM_2 (pdf, typename T::scalar_type) | ||
#define NBL_CONCEPT_PARAM_3 (_sample, typename T::sample_type) | ||
#define NBL_CONCEPT_PARAM_4 (iso, typename T::isotropic_interaction_type) | ||
#define NBL_CONCEPT_PARAM_5 (aniso, typename T::anisotropic_interaction_type) | ||
#define NBL_CONCEPT_PARAM_6 (isocache, typename T::isocache_type) | ||
#define NBL_CONCEPT_PARAM_7 (anisocache, typename T::anisocache_type) | ||
#define NBL_CONCEPT_PARAM_8 (param_iso, typename T::params_isotropic_t) | ||
#define NBL_CONCEPT_PARAM_9 (param_aniso, typename T::params_anisotropic_t) | ||
#define NBL_CONCEPT_PARAM_10 (u, vector<typename T::scalar_type, 3>) | ||
NBL_CONCEPT_BEGIN(11) | ||
#define bxdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 | ||
#define spec NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 | ||
#define pdf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 | ||
#define _sample NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 | ||
#define iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4 | ||
#define aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5 | ||
#define isocache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_6 | ||
#define anisocache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_7 | ||
#define param_iso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_8 | ||
#define param_aniso NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_9 | ||
#define u NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_10 | ||
NBL_CONCEPT_END( | ||
((NBL_CONCEPT_REQ_TYPE)(T::scalar_type)) | ||
((NBL_CONCEPT_REQ_TYPE)(T::isotropic_interaction_type)) | ||
((NBL_CONCEPT_REQ_TYPE)(T::anisotropic_interaction_type)) | ||
((NBL_CONCEPT_REQ_TYPE)(T::sample_type)) | ||
((NBL_CONCEPT_REQ_TYPE)(T::spectral_type)) | ||
((NBL_CONCEPT_REQ_TYPE)(T::quotient_pdf_type)) | ||
((NBL_CONCEPT_REQ_TYPE)(T::isocache_type)) | ||
((NBL_CONCEPT_REQ_TYPE)(T::anisocache_type)) | ||
((NBL_CONCEPT_REQ_TYPE)(T::params_isotropic_t)) | ||
((NBL_CONCEPT_REQ_TYPE)(T::params_anisotropic_t)) | ||
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.eval(param_iso)), ::nbl::hlsl::is_same_v, T::spectral_type)) | ||
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.eval(param_aniso)), ::nbl::hlsl::is_same_v, T::spectral_type)) | ||
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.generate(iso,u,isocache)), ::nbl::hlsl::is_same_v, typename T::sample_type)) | ||
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.generate(aniso,u,anisocache)), ::nbl::hlsl::is_same_v, typename T::sample_type)) | ||
//((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.template pdf<LS,I>(_sample,iso)), ::nbl::hlsl::is_scalar_v)) | ||
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.quotient_and_pdf(param_iso)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) | ||
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((bxdf.quotient_and_pdf(param_aniso)), ::nbl::hlsl::is_same_v, typename T::quotient_pdf_type)) | ||
((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(LightSample, typename T::sample_type)) | ||
((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(concepts::FloatingPointLikeVectorial, typename T::spectral_type)) | ||
((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(CreatableIsotropicMicrofacetCache, typename T::isocache_type)) | ||
((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(AnisotropicMicrofacetCache, typename T::anisocache_type)) |
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.
I'd also make IsotropicBxDF
concept, and only check aniso functions and types (at least the signatures) in the BxDF cocnept, and isotropic in the IsotropicBxDF (basically IsotropicBxDF has to have all signatures Anisotropic one would have == has to be compatible with anisotropic interaction and cache types - worst case it will just behave isotropically).
return hlsl::promote<spectral_type>(__base.fresnel(hlsl::abs(cache.getVdotH()))[0]) * DG; | ||
} | ||
|
||
sample_type __generate_wo_clamps(const vector3_type localV, const vector3_type H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps<monochrome_type>) rcpEta, NBL_REF_ARG(anisocache_type) cache) |
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.
you need to take whole ray-dir instead of vec3 localV
(same comment for all cook torrance)
const scalar_type VdotH = cache.iso_cache.getVdotH(); | ||
Refract<scalar_type> r = Refract<scalar_type>::create(localV, H); | ||
cache.iso_cache.LdotH = hlsl::mix(VdotH, r.getNdotT(rcpEta.value2[0]), transmitted); | ||
ray_dir_info_type localL; | ||
bxdf::ReflectRefract<scalar_type> rr; | ||
rr.refract = r; | ||
localL = localL.reflectRefract(rr, transmitted, rcpEta.value[0]); | ||
|
||
return sample_type::createFromTangentSpace(localL, m); |
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.
btw when this moves to Cook Torrance, you need to make sure that you somehow "fail" the generation if the following happens:
- you choose reflect but resulting
localL.z
has different sign tolocalV.z
- you choose refract but resulting
local.z
has same sign aslocalV.z
This is simply to avoid using samples which have invalid paths.
See #899 (comment)
I think the returned aniso cache can be queried for invalidity, or the sample somehow.
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.
this is just to pass tests, in another PR we'll rework the PDF stuf into MIS-weights on BxDFs and we'll be free to do Resampled Importance Sampling
sample_type __generate_wo_clamps(const vector3_type localV, const vector3_type H, NBL_CONST_REF_ARG(matrix3x3_type) m, NBL_REF_ARG(vector3_type) u, NBL_CONST_REF_ARG(fresnel::OrientedEtaRcps<monochrome_type>) rcpEta, NBL_REF_ARG(anisocache_type) cache) | ||
{ | ||
const scalar_type localVdotH = nbl::hlsl::dot<vector3_type>(localV,H); | ||
const scalar_type reflectance = __base.fresnel(hlsl::abs(cache.getVdotH()))[0]; |
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.
need a luminosity contribution hint same as thindielectric BSDF has
scalar_type __D(NBL_CONST_REF_ARG(isocache_type) cache) | ||
{ | ||
return ndf.template D<isocache_type>(cache); | ||
} | ||
scalar_type __D(NBL_CONST_REF_ARG(anisocache_type) cache) | ||
{ | ||
return ndf.template D<anisocache_type>(cache); | ||
} | ||
|
||
template<class Query> | ||
MT __DG1(NBL_CONST_REF_ARG(Query) query) | ||
{ | ||
MT measure_transform; | ||
measure_transform.pdf = ndf.template DG1<Query>(query); | ||
return measure_transform; | ||
} | ||
template<class Query> | ||
MT __DG1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(isocache_type) cache) | ||
{ | ||
MT measure_transform; | ||
measure_transform.pdf = ndf.template DG1<Query>(query, cache); | ||
measure_transform.transmitted = cache.isTransmission(); | ||
measure_transform.VdotH = cache.getVdotH(); | ||
measure_transform.LdotH = cache.getLdotH(); | ||
measure_transform.VdotHLdotH = cache.getVdotHLdotH(); | ||
return measure_transform; | ||
} | ||
template<class Query> | ||
MT __DG1(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(anisocache_type) cache) | ||
{ | ||
MT measure_transform; | ||
measure_transform.pdf = ndf.template DG1<Query>(query, cache); | ||
measure_transform.transmitted = cache.isTransmission(); | ||
measure_transform.VdotH = cache.getVdotH(); | ||
measure_transform.LdotH = cache.getLdotH(); | ||
measure_transform.VdotHLdotH = cache.getVdotHLdotH(); | ||
return measure_transform; | ||
} | ||
|
||
template<class Query> | ||
MT __DG(NBL_CONST_REF_ARG(Query) query, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(isotropic_interaction_type) interaction, NBL_CONST_REF_ARG(isocache_type) cache) | ||
{ | ||
MT measure_transform; | ||
measure_transform.pdf = ndf.template D<isocache_type>(cache); | ||
NBL_IF_CONSTEXPR(MT::Type == ndf::MicrofacetTransformTypes::MTT_REFLECT_REFRACT) | ||
measure_transform.transmitted = cache.isTransmission(); | ||
NBL_IF_CONSTEXPR(MT::Type == ndf::MicrofacetTransformTypes::MTT_REFRACT) | ||
{ | ||
measure_transform.VdotH = cache.getVdotH(); | ||
measure_transform.LdotH = cache.getLdotH(); | ||
measure_transform.VdotHLdotH = cache.getVdotHLdotH(); | ||
} | ||
if (any<vector<bool, 2> >(ndf.A > hlsl::promote<vector2_type>(numeric_limits<scalar_type>::min))) | ||
{ | ||
measure_transform.pdf *= ndf.template correlated<Query, sample_type, isotropic_interaction_type>(query, _sample, interaction); | ||
} | ||
return measure_transform; |
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.
btw I'd really love to slap the BRDF, BTDF and BSDF code all into the same class.
and even moreso, avoid different partial specs for Anisotropic and Isotropic #899 (comment)
Description
Continuing #811 due to GH UI messing up diffs again
Testing
TODO list: