Created concepts for samplers, added quotient_and_pdf variants to satisfy the concepts#1001
Created concepts for samplers, added quotient_and_pdf variants to satisfy the concepts#1001karimsayedre wants to merge 46 commits intomasterfrom
Conversation
…isfy the concepts
…concepts - Move codomain_and_*Pdf and domain_and_*Pdf structs into their own warp_and_pdf.hlsl header - Keeping quotient_and_pdf.hlsl focused on importance sampling quotients for BxDFs - Add SampleWithPDF, SampleWithRcpPDF, and SampleWithDensity concepts to validate sample types - Used concept composition (NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT) to build ResamplableSampler on TractableSampler and BijectiveSampler on ResamplableSampler
… projected/spherical triangle
There was a problem hiding this comment.
I wonder if
const scalar_type tmp = _sample.z - scalar_type(0.5);
retval.z *= sign(tmp);
if (tmp)
_sample.z = tmp;
_sample.z *= 2.0;
would be faster
| if (pyramidAngles()) | ||
| return 0.f; |
There was a problem hiding this comment.
instead check for the solidAngle being 0 or below a threshold
There was a problem hiding this comment.
then you can fold pyramidAngles into the create
| const scalar_type u = subTriSolidAngleRatio > numeric_limits<scalar_type>::min ? subTriSolidAngleRatio : 0.0; | ||
|
|
||
| const scalar_type sinBC_s_product = sinB_ * sinC_; | ||
|
|
||
| // 1 ULP below 1.0, ensures (1.0 - cosBC_s) is strictly positive in float | ||
| const scalar_type one_below_one = bit_cast<scalar_type>(bit_cast<uint_type>(scalar_type(1)) - uint_type(1)); | ||
| const scalar_type one_below_one = ieee754::nextTowardZero(scalar_type(1.0)); | ||
| const scalar_type cosBC_s = sinBC_s_product > numeric_limits<scalar_type>::min ? (cosA + cosB_ * cosC_) / sinBC_s_product : triCosC; | ||
| const scalar_type v_denom = scalar_type(1.0) - (cosBC_s < one_below_one ? cosBC_s : triCosC); |
There was a problem hiding this comment.
replace the ?s with hlsl::select
include/nbl/builtin/hlsl/sampling/projected_spherical_triangle.hlsl
Outdated
Show resolved
Hide resolved
include/nbl/builtin/hlsl/sampling/projected_spherical_triangle.hlsl
Outdated
Show resolved
Hide resolved
|
|
||
| struct cache_type | ||
| { | ||
| // TODO: should we cache `r`? |
There was a problem hiding this comment.
no, what for?
the PDF is constant
| typename Linear<scalar_type>::cache_type linearYCache; | ||
|
|
||
| vector2_type p; | ||
| p.y = lineary.generate(u.y, linearCache); | ||
| p.y = lineary.generate(u.y, linearYCache); | ||
|
|
||
| const vector2_type ySliceEndPoints = vector2_type(bilinearCoeffs[0] + p.y * bilinearCoeffDiffs[0], bilinearCoeffs[1] + p.y * bilinearCoeffDiffs[1]); | ||
| Linear<scalar_type> linearx = Linear<scalar_type>::create(ySliceEndPoints); | ||
| p.x = linearx.generate(u.x, linearCache); | ||
| p.x = linearx.generate(u.x, cache.linearXCache); | ||
|
|
||
| cache.pdf = nbl::hlsl::mix(ySliceEndPoints[0], ySliceEndPoints[1], p.x) * fourOverTwiceAreasUnderXCurveSum; | ||
| // pre-multiply by normalization so forwardPdf is just addition | ||
| cache.normalizedStart = ySliceEndPoints[0] * fourOverTwiceAreasUnderXCurveSum; | ||
| cache.linearXCache.diffTimesX *= fourOverTwiceAreasUnderXCurveSum; |
There was a problem hiding this comment.
the reason I came up with this refactor #1001 (comment) was motivated exactly by doing less work in bilinear
| const T twopi = T(2.0) * numbers::pi<T>; | ||
| phi += hlsl::mix(T(0.0), twopi, phi < T(0.0)); | ||
| return vector_t2(_sample.z, phi / twopi); | ||
| return vector_t2(_sample.z, impl::phiSampleFromDirection(_sample.x, _sample.y)); |
There was a problem hiding this comment.
this was just a polar sampling with corrected/linear r instead of square root
Btw we should use concentric because its higher quality, since the would-be-r needs to be squared, you'd need to pass dominant from the concentric mapping back to multiply the XY coordinates by it again
then you can use sqrt(1-dominant*dominant) as the z-coordinate for the hemisphere
| vector_t3 retval = hemisphere_t::__generate(vector_t2(hemiX, _sample.y)); | ||
| retval.z = chooseLower ? (-retval.z) : retval.z; | ||
| return retval; | ||
| return impl::directionFromZandPhi(T(1.0) - T(2.0) * _sample.x, _sample.y); |
There was a problem hiding this comment.
to make it polar vs concentric mapping agnostic, you could
const float tmp = _sample.u*2.0-1.0;
_sample.u = abs(tmp);
L = callHemisphere(_sample,cache);
L.z *= sign(tmp);
There was a problem hiding this comment.
its also easy to invert
const float dir = sign(L.z)*0.5;
L.z = abs(L.z);
_sample = hemisphere.invert(L);
_sample.x = _sample.x*dir+0.5;
# Conflicts: # examples_tests
…() for floats, separeted SMaxError into a separate file with support to other types than float
| static density_type forwardPdf(const cache_type cache) | ||
| static density_type forwardPdf(const codomain_type v, const cache_type cache) | ||
| { | ||
| return cache.L_z * numbers::inv_pi<T>; | ||
| return v.z * numbers::inv_pi<T>; | ||
| } | ||
|
|
||
| static weight_type forwardWeight(const cache_type cache) | ||
| static weight_type forwardWeight(const codomain_type v, const cache_type cache) | ||
| { | ||
| return forwardPdf(cache); | ||
| return forwardPdf(v, cache); | ||
| } | ||
|
|
||
| static density_type backwardPdf(const codomain_type L) | ||
| { | ||
| assert(L.z > 0); | ||
|
|
||
| cache_type c; | ||
| c.L_z = L.z; | ||
| return forwardPdf(c); | ||
| return forwardPdf(L, c); | ||
| } |
There was a problem hiding this comment.
this is all wrong it should have been domain_type !!!!
| ((NBL_CONCEPT_REQ_EXPR_RET_TYPE) ((_sampler.generate(u, cache)), ::nbl::hlsl::is_same_v, typename T::codomain_type)) | ||
| ((NBL_CONCEPT_REQ_EXPR_RET_TYPE) ((_sampler.forwardPdf(cache)), ::nbl::hlsl::is_same_v, typename T::density_type))); | ||
| ((NBL_CONCEPT_REQ_EXPR_RET_TYPE) ((_sampler.forwardPdf(v, cache)), ::nbl::hlsl::is_same_v, typename T::density_type))); | ||
| #undef cache |
There was a problem hiding this comment.
nooo, it was meant to be u,cache
# Conflicts: # examples_tests
Examples PR
Notes:
quotient_and_pdf()methods inUniformHemisphere,UniformSphere,ProjectedHemisphere, andProjectedSphereshadow the struct typesampling::quotient_and_pdf<Q, P>fromquotient_and_pdf.hlsl. DXC can't resolve the return type because the method name takes precedence over the struct name during lookup. Fixed by fully qualifying with::nbl::hlsl::sampling::quotient_and_pdf<U, T>.