• 12
• 10
• 10
• 13
• 10

# Monte Carlo ray generation - path tracing

## Recommended Posts

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?

##### Share on other sites

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. )

##### Share on other sites

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?

##### Share on other sites
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?

##### Share on other sites

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?

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]