Quasirandom sampler

Discussion related to the LuxCore functionality, implementations and API.
User avatar
alpistinho
Developer
Developer
Posts: 198
Joined: Thu Jul 05, 2018 11:38 pm
Location: Rio de Janeiro

Quasirandom sampler

Post by alpistinho »

Dade wrote: Sat Feb 23, 2019 3:31 pm
kintuX wrote: Sat Feb 23, 2019 2:51 pm The Unreasonable Effectiveness of Quasirandom Sequences
"I present a new low discrepancy quasirandom sequence that offers substantial improvement over current state-of-the art sequences eg Sobol, Niederreiter,…"
http://extremelearning.com.au/unreasonable-effectiveness-of-quasirandom-sequences/
Uh, I looked and tried the code, it is incredible simple. It may be worth trying even if people where complaining of regular Sobol patterns ... I don't want even start to think what they will say about this.
I just gave it a shot and after quite a long time trying to understand the code I've got something running...
Screenshot from 2019-03-04 17-38-15.png
Why am I under the impression that something is not right :lol:
Support LuxCoreRender project with salts and bounties
User avatar
Dade
Developer
Developer
Posts: 5672
Joined: Mon Dec 04, 2017 8:36 pm
Location: Italy

Re: CGI tech news box

Post by Dade »

alpistinho wrote: Mon Mar 04, 2019 8:40 pm I just gave it a shot and after quite a long time trying to understand the code I've got something running...

Screenshot from 2019-03-04 17-38-15.png

Why am I under the impression that something is not right :lol:
Have you tried to run the rendering for a very loooong time ? It may be just the samples correlation I was talking about. Plain Sobol, without shuffling looks similar.
Support LuxCoreRender project with salts and bounties
User avatar
alpistinho
Developer
Developer
Posts: 198
Joined: Thu Jul 05, 2018 11:38 pm
Location: Rio de Janeiro

Re: CGI tech news box

Post by alpistinho »

Dade wrote: Mon Mar 04, 2019 10:54 pm Have you tried to run the rendering for a very loooong time ? It may be just the samples correlation I was talking about. Plain Sobol, without shuffling looks similar.
I will try that, but I am not confident. I was expecting the patterns to be more like this: https://www.shadertoy.com/view/4dtBWH

Besides it does not look like to be converging to anything, so I guess I botched something. I will try to post some questions to better understand how the sampler interfaces with the rest of the code, because I am pretty sure I am missing some parts still
Support LuxCoreRender project with salts and bounties
User avatar
alpistinho
Developer
Developer
Posts: 198
Joined: Thu Jul 05, 2018 11:38 pm
Location: Rio de Janeiro

Re: CGI tech news box

Post by alpistinho »

Hi,

As expected the result does not converge to the right output.

So, I was investigating and I have at least a couple of questions about the Sampler interface:

1. The GetSample method can return 3 different values based on how it is called. If the index is 0 or 1, the value returned is sample0 or sample1, that hold the value for the current pixel being rendered plus a small offset that I assume is to randomly sample the area of the current pixel.
If the index argument is any other value, the value returned depends on the Sampler type. Random returns an absolute random value and the Sobol returns the next value in the Sobol sequence based on the pass and index values in some way I don't understand.

What is this random value used for when the index value is not 0 or 1?
I see that this method is mainly called by the engines such as pathtracer. On this class the method is called with index 0 and 1 like that:

Code: Select all

const float filmX = sampler->GetSample(0);
const float filmY = sampler->GetSample(1);
But it is also called like that:

Code: Select all

camera->GenerateRay(sampleResult.filmX, sampleResult.filmY, &eyeRay, &volInfo,
sampler->GetSample(2), sampler->GetSample(3), sampler->GetSample(4));

const bool isLightVisible = DirectLightSampling(
		device, scene,
		eyeRay.time,
		sampler->GetSample(sampleOffset + 1),
		sampler->GetSample(sampleOffset + 2),
		sampler->GetSample(sampleOffset + 3),
		sampler->GetSample(sampleOffset + 4),
		sampler->GetSample(sampleOffset + 5),
		depthInfo, 
		pathThroughput, bsdf, volInfo, &sampleResult);
And in this second case, all are covered by the default case on the switch.

Why do this calls the GetSampler with varying argument values if the result is always the same?

I've tried to implement this new sequence based on the Random and Sobol samplers, but substituting how the values are chosen. To debug I've substituted this new sequence for some rndGen->floatValue() calls in order to compare the results with what I get using the new sequence.

When I use rndGen->floatValue() to determine the sample0 and sample1 values I see no big difference in the rendering, but when I return a random value for the case where index != 0,1 the result looks correct.

I've put some prints and the value return appears to be in the correct range
Support LuxCoreRender project with salts and bounties
User avatar
B.Y.O.B.
Developer
Developer
Posts: 4146
Joined: Mon Dec 04, 2017 10:08 pm
Location: Germany
Contact:

Re: CGI tech news box

Post by B.Y.O.B. »

Do you have your changes in a fork online somewhere, so we can take a look?
User avatar
alpistinho
Developer
Developer
Posts: 198
Joined: Thu Jul 05, 2018 11:38 pm
Location: Rio de Janeiro

Re: CGI tech news box

Post by alpistinho »

Sure, it's here: https://github.com/Alpistinho/LuxCore on the r2_sampler branch.

To use the sampler just put R2 in the configuration file.
Support LuxCoreRender project with salts and bounties
User avatar
Dade
Developer
Developer
Posts: 5672
Joined: Mon Dec 04, 2017 8:36 pm
Location: Italy

Re: Quasirandom sampler

Post by Dade »

You are not setting correctly the R2 sample dimension. R2Sampler::RequestSamples(const u_int size) tell you the sample dimensions (aka size) needed by the rendering engine and you are just ignoring the argument. Check the orginal code example at http://extremelearning.com.au/unreasona ... sequences/, where it uses "n=2", you have to use "n=size".

Each single sample produced by a sampler has a dimension and it is defined by the call to RequestSamples(). The sampler has a current sample, calling R2Sampler::GetSample(i) return the value of the "i" dimension, calling R2Sampler::NextSample() will move to the next one.

Samplers work exactly like in PBRT.
Support LuxCoreRender project with salts and bounties
User avatar
alpistinho
Developer
Developer
Posts: 198
Joined: Thu Jul 05, 2018 11:38 pm
Location: Rio de Janeiro

Re: Quasirandom sampler

Post by alpistinho »

Hi,

Thanks for the directions, I think I understand how it should work now.
It is still not working and it seems that the RequestSamples method is called at the beginning and not called again, so the samples are always the same. I will have a look at this tomorrow.

About something tangentially related on the SobolSequence code, how is that not a memory leak?

Code: Select all

void SobolSequence::RequestSamples(const u_int size) {
	directions = new u_int[size * SOBOL_BITS];
	GenerateDirectionVectors(directions, size);
}

SobolSequence::~SobolSequence() {
	delete[] directions;
}
Is the RequestSamples only called once per object lifetime?
Support LuxCoreRender project with salts and bounties
User avatar
Dade
Developer
Developer
Posts: 5672
Joined: Mon Dec 04, 2017 8:36 pm
Location: Italy

Re: Quasirandom sampler

Post by Dade »

alpistinho wrote: Wed Mar 06, 2019 2:41 am Is the RequestSamples only called once per object lifetime?
Yes, it is called once before starting to use samples to define their dimensions (why would you call it multiple times ?).
Support LuxCoreRender project with salts and bounties
User avatar
alpistinho
Developer
Developer
Posts: 198
Joined: Thu Jul 05, 2018 11:38 pm
Location: Rio de Janeiro

Re: Quasirandom sampler

Post by alpistinho »

I had understood that it would be called every time the samples would be calculated and subsequent calls for GetSample would always return the same result until a new RequestSample was called.

I am reading the Sobol code to understand how it is done over there and it appears to me that what prevents the SobolSequence::GetSample from always returning the same value for the same index is the rngPass variable being modified between calls. Is that correct?
I had thought that the Sobol sequence would be followed sequentially for a longer time before changing the rngPass, but maybe that and the Cranley-Patterson rotation is what you were referring to by "shuffling".
Dade wrote: Mon Mar 04, 2019 10:54 pm Have you tried to run the rendering for a very loooong time ? It may be just the samples correlation I was talking about. Plain Sobol, without shuffling looks similar.
Support LuxCoreRender project with salts and bounties
Post Reply