-
Notifications
You must be signed in to change notification settings - Fork 15
BxDF tests #165
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
base: master
Are you sure you want to change the base?
BxDF tests #165
Conversation
|
why do you have random things from sorakrit here instead of your own branch against his or I literally can't see whats yours and what's @keptsecret's. |
| SBxDFTestResources retval; | ||
|
|
||
| retval.rng = nbl::hlsl::Xoroshiro64Star::construct(seed); | ||
| retval.u = float32_t3(rngFloat01(retval.rng), rngFloat01(retval.rng), 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.
the third random number is sometimes necessary to discern discrete BxDF branches:
- reflection vs refraction in e.g. glass
- diffuse vs specular in e.g. plastic
- choosing a leaf BxDF in a mixture/tree of BxDFs
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.
your new code is still testing with u.z=0
while the jacobian test can't work with varying u.z, its important to test varying u.xy for different constant values of u.z
I'm pretty sure the Chi2 and bucket/histogram tests can handle varying u.z (and you should vary it)
| struct STestMeta | ||
| { | ||
| float32_t4 result; | ||
| #ifndef __HLSL_VERSION | ||
| std::string bxdfName; | ||
| std::string testName; | ||
| #endif | ||
| }; |
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.
returning a result as a vec4 is quite a bit meh, I'd actually provide a callback (via static polymorphism) which is only called upon a failure
struct FailureCallbackConceptExample
{
void __call(NBL_CONST_REF_ARG(SBxDFTestResources) failedFor, NBL_CONST_REF_ARG(sample_t) failedAt);
};then you can print in C++, mark booleans, append to vector, break & repeat call or whatever
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.
perfect C++ callback
printf(...your error message...);
for (volatile bool repeat=true; gDebuggerAttached&&repeat; )
{
repeat = false; // I can set to true with debugger and repeat as many times as I want till I find the cause
__debugbreak();
failedFor.test(failedAt);
}| t.meta.result = t.test(); | ||
| t.meta.testName = "u offset"; | ||
| return t.meta; | ||
| } |
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.
setting those thousands of times will be expensive, function should be void and not return anything, callback instead of meta
| static STestMeta run(uint32_t2 seed) | ||
| { | ||
| this_t t; | ||
| t.init(seed); |
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 make the function take uint32_t as an argument, then run a hash function (wide not deep)
https://rene.ruhr/gfx/gpuhash/
This will make it easy to invoke multiple run(uint32_t invocationID) in parallel independently, be it on CPU with for loop or GPU with gl_GlobalInvocationID.x
| if NBL_CONSTEXPR_FUNC (is_basic_brdf_v<BxDF>) | ||
| { | ||
| s = base_t::bxdf.generate(base_t::anisointer, base_t::rc.u.xy); | ||
| sx = base_t::bxdf.generate(base_t::anisointer, base_t::rc.u.xy + float32_t2(base_t::rc.h,0)); | ||
| sy = base_t::bxdf.generate(base_t::anisointer, base_t::rc.u.xy + float32_t2(0,base_t::rc.h)); | ||
| } | ||
| if NBL_CONSTEXPR_FUNC (is_microfacet_brdf_v<BxDF>) | ||
| { | ||
| s = base_t::bxdf.generate(base_t::anisointer, base_t::rc.u.xy, cache); | ||
| sx = base_t::bxdf.generate(base_t::anisointer, base_t::rc.u.xy + float32_t2(base_t::rc.h,0), dummy); | ||
| sy = base_t::bxdf.generate(base_t::anisointer, base_t::rc.u.xy + float32_t2(0,base_t::rc.h), dummy); | ||
| } | ||
| if NBL_CONSTEXPR_FUNC (is_basic_bsdf_v<BxDF>) | ||
| { | ||
| s = base_t::bxdf.generate(base_t::anisointer, base_t::rc.u); | ||
| sx = base_t::bxdf.generate(base_t::anisointer, base_t::rc.u + float32_t3(base_t::rc.h,0,0)); | ||
| sy = base_t::bxdf.generate(base_t::anisointer, base_t::rc.u + float32_t3(0,base_t::rc.h,0)); | ||
| } | ||
| if NBL_CONSTEXPR_FUNC (is_microfacet_bsdf_v<BxDF>) | ||
| { | ||
| s = base_t::bxdf.generate(base_t::anisointer, base_t::rc.u, cache); | ||
| float32_t3 ux = base_t::rc.u + float32_t3(base_t::rc.h,0,0); | ||
| sx = base_t::bxdf.generate(base_t::anisointer, ux, dummy); | ||
| float32_t3 uy = base_t::rc.u + float32_t3(0,base_t::rc.h,0); | ||
| sy = base_t::bxdf.generate(base_t::anisointer, uy, dummy); | ||
| } |
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.
h should be a parameter of each individual specialized BxDF test, because its specific to the differential test and also may need to change depending on the BxDF getting tested
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 maybe compute the perturbed u above for readability
| float32_t2x2 m = float32_t2x2(sx.TdotL - s.TdotL, sy.TdotL - s.TdotL, sx.BdotL - s.BdotL, sy.BdotL - s.BdotL); | ||
| float det = nbl::hlsl::determinant<float32_t2x2>(m); | ||
|
|
||
| return float32_t4(nbl::hlsl::abs<float32_t3>(pdf.value() - brdf), nbl::hlsl::abs<float>(det*pdf.pdf/s.NdotL) * 0.5); |
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 needs to be done better semantically with a callback, one thing for each individually.
Alos pdf.value() does not equal brdf in general!!!!!
P.s. the *0.5 thing on the PDF to Jacobian ratio was a thing for visualization, you should really have a callback which gets triggered if the value is too far from 1.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.
you need to skip checking anything that produces an "impossible" s, so if eval or quotient is 0, you can skip the rest of the function (but not before you check pdf and quotient for 0 and INF respectively - the checks also check for NaN)
add more simple tests for:
pdf>0because something you generated cannot have 0 probability of getting generatedquotient<INFalways because our importance sampler's job is to prevent that!- positivity, all
pdf,quotient, andevalneed to be>=0 - recprocity (eval must be equal if we swap L and V around, make a method/function to swap L and V around in
s, the interaction, thebxdfitself and thecache)
Leave lots of comments.
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 when pdf is close to INF (above some super high threshold) you need to back off the last test you have here
| retval.V.direction = nbl::hlsl::normalize<float32_t3>(projected_hemisphere_generate<float>(rngUniformDist<float32_t2>(retval.rng))); | ||
| retval.N = nbl::hlsl::normalize<float32_t3>(projected_hemisphere_generate<float>(rngUniformDist<float32_t2>(retval.rng))); |
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.
not projected hemisphere, just hemisphere.
Also not hemisphere but full sphere, because its good to test that BRDFs handle invalid (below hemisphere) correctly
…ng/Nabla-Examples-and-Tests into bxdf_unit_tests
…ng/Nabla-Examples-and-Tests into bxdf_unit_tests
| namespace nbl | ||
| { | ||
| namespace hlsl | ||
| { |
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.
don't have examples add to nbl::hlsl namespace, you can do using namespace nbl::hlsl; instead
| #endif | ||
| #if 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.
don't disable tests in final example, leave them all in
| } | ||
|
|
||
| float eps = 1e-3; // epsilon | ||
| uint32_t state; // init state seed, for debugging |
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.
continuing #165 (comment)
then call it halfSeed
No description provided.