Monte Carlo ray generation - path tracing

Started by
6 comments, last by IsItSharp 6 years, 10 months ago

I try to implement the Halton sequence with this simple code:


def Halton(base,ix):
    r = 0
    f = 1.0 / base
    i = ix
    while(i > 0):
        r += f * (i%base)
        f /= base
        i /= base
    return r

i thought the output values are limited to [0..1] but sometimes i get values like "1.01953125" or "1.1861979166666667", why is that and how can i limit the Halton sequence to the given interval?

Advertisement

I try to implement the Halton sequence with this simple code:


def Halton(base,ix):
    r = 0
    f = 1.0 / base
    i = ix
    while(i > 0):
        r += f * (i%base)
        f /= base
        i /= base
    return r

i thought the output values are limited to [0..1] but sometimes i get values like "1.01953125" or "1.1861979166666667", why is that and how can i limit the Halton sequence to the given interval?

Try changing the line "i /= base" to something like "i = math.floor(i / base)". ( https://en.wikipedia.org/wiki/Halton_sequence if you look at the pseudocode, it has the floor operation too. )

Thanks the floor function fixed it. I am wondering how i could use the halton sequence to sample a pixel? Would it be better to store the precalculated values in an array and choose the value according to the current samples / pixel? For example if i am in the 2nd sample i would choose the 2nd value of the 2- and 3-base halton series?

Yes, a precalculated array is the way to go.

Also, are you really computing the tangent of fov for every single ray? That looks expensive. Why don't you compute that once and then use it for every ray?

I implemented a new class called "Sampler" which generates either random values, halton (2,3) values or sobol values and stores them before in an array before rendering. I tried every one and compared the results at 10 samples, and i am kind of disappointed by halton and sobol, they both look horrible, why is that?

randomsampler.pnghaltonsampler.pngsobolsampler.png

This is my computeSamples(x,y)-function:


def computeSample(x,y):
    samplePoint = sampler.getSamplePoint(x,y)

    jitterX = samplePoint[0]
    jitterY = samplePoint[1]

    x += jitterX
    y += jitterY

    xdir = (x / width) * 2.0 - 1.0
    ydir = ((y / height) * 2.0 - 1.0) * aspect

    direction = Point3D(xdir,ydir,zdir).normalize()
    ray = Ray(camera,direction)

    return trace(ray,1)

And this is my "Sampler":


class Sampler:
    def __init__(self,type,width,height):
        self.type = type
        self.width = width
        self.height = height
        self.samplePoints = []
        self.counter = 0
        for x in range(width):
            for y in range(height):
                if(self.type is SampleType.Random):
                    self.samplePoints.append([random(),random()])
                elif(self.type is SampleType.Halton):
                    self.samplePoints.append([Halton(2,self.counter),Halton(3,self.counter)])
                elif(self.type is SampleType.Sobol):
                    sobolValue = i4_sobol(2,self.counter)
                    self.samplePoints.append([sobolValue[0][0],sobolValue[0][1]])
                elif(self.type is SampleType.NoneS):
                    self.samplePoints.append([0,0])
                self.counter += 1

    def getSamplePoint(self,x,y):
        return self.samplePoints[x*self.height+y]

This topic is closed to new replies.

Advertisement