Skip to content

Commit

Permalink
Add recursive shade function
Browse files Browse the repository at this point in the history
  • Loading branch information
Makar Solomatin committed Feb 14, 2021
1 parent 697d042 commit d0a8e49
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 55 deletions.
23 changes: 13 additions & 10 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@

floormaterial = PhongMaterial(color=Vec3(0.5,0.5,0.5))
sphere0material = PhongMaterial(color=Vec3(1.,0.,0.), transparency=0.5)
sphere1material = PhongMaterial(color=Vec3(0.,0.,1.), transparency=0.7)
sphere1material = PhongMaterial(color=Vec3(0.,0.,1.), transparency=0.1, reflectivity=0.5)
sphere2material = PhongMaterial(color=Vec3(0.,1.,0.))

camera = PerspectiveCamera(640, 480, 45)
camera.setView(Vec3(0.,-10.,10.), Vec3(0.,0.,0.), Vec3(0.,0.,1.))
camera.setView(Vec3(0.,-10.,0.0), Vec3(0.,0.,0.), Vec3(0.,0.,1.))

scene = Scene()
scene.add(Triangle(Vertex(position=(0, 0, 0)),
Expand All @@ -23,15 +24,17 @@
scene.addLight(PointLight(Vec3(0,0,15)))

# Add "floor"
A = Vertex(position=(-5.0, -5.0, 0.0))
B = Vertex(position=( 5.0, -5.0, 0.0))
C = Vertex(position=( 5.0, 5.0, 0.0))
D = Vertex(position=(-5.0, 5.0, 0.0))
scene.add(Triangle(A,B,C, material=floormaterial))
# A = Vertex(position=(-5.0, -5.0, 0.0))
# B = Vertex(position=( 5.0, -5.0, 0.0))
# C = Vertex(position=( 5.0, 5.0, 0.0))
# D = Vertex(position=(-5.0, 5.0, 0.0))
# scene.add(Triangle(A,B,C, material=floormaterial))

# Add spheres
scene.add(Sphere(center=Vec3(2,-3.5,1.75), radius=1, material=sphere0material))
scene.add(Sphere(center=Vec3(2,-1.5,1.75), radius=1, material=sphere1material))
scene.add(Sphere(center=Vec3(0,-5.5,0), radius=1, material=sphere0material))
scene.add(Sphere(center=Vec3(0,-0.5,0), radius=1, material=sphere1material))
scene.add(Sphere(center=Vec3(3,-0.5,0), radius=1, material=sphere2material))
scene.add(Sphere(center=Vec3(-3,-0.5,0), radius=0.5, material=sphere2material))

imgdata = SimpleRT(shadow=True, iterations=3).render(scene)
imgdata = SimpleRT(shadow=True, iterations=7).render(scene)
imgdata.save('a.png')
73 changes: 28 additions & 45 deletions pyrt/renderer/simplert.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@ def __init__(self, shadow=False, iterations=1):
Renderer.__init__(self, "Simple Raytracer")
self.shadow = shadow
self.iterations = iterations
self.background = (0, 0, 0)
if self.shadow:
print("# Shadow Enabled")
if self.iterations>1:
print("# Iterations: " + str(self.iterations))

def _shade(self, scene: Scene, ray: Ray, hitrecord: HitRecord) -> tuple:
r = g = b = 0 # background color
r, g, b = self.background
hit = False
for element in scene.nodes:
if element.hit(ray, hitrecord):
Expand Down Expand Up @@ -69,38 +70,39 @@ def _shadow(self, scene: Scene, hitrecord: HitRecord) -> tuple:
fs /= 4.

return fs,local_num_shadow_rays

def _recurse_shade(self, scene: Scene, ray: Ray, iteration_num: int) -> tuple:
hitrecord = HitRecord()
hit, r, g, b = self._shade(scene, ray, hitrecord)

def _reflect(self, r: int, g: int, b: int, scene: Scene, ray: Ray, hitrecord: HitRecord) -> tuple:
reflect_ray = Ray(hitrecord.point, reflect3(hitrecord.normal_g, ray.direction))
reflect_hitrecord = HitRecord()

hit, rnew, gnew, bnew = self._shade(scene, reflect_ray, reflect_hitrecord)
if not hit or iteration_num == 0:
return r, g, b

if hitrecord.material.reflectivity != 0.0:
reflect_ray = Ray(hitrecord.point, reflect3(hitrecord.normal_g, ray.direction))
new_r, new_g, new_b = self._recurse_shade(scene, reflect_ray, iteration_num - 1)

if hit:
ref1 = hitrecord.material.reflectivity
ref2 = 1.-ref1
rnew = int ( ref1 * rnew + ref2 * r)
gnew = int ( ref1 * gnew + ref2 * g)
bnew = int ( ref1 * bnew + ref2 * b)
return rnew, gnew, bnew, reflect_ray, reflect_hitrecord
else:
return r,g,b,None,None

def _refract(self, r: int, g: int, b: int, scene: Scene, ray: Ray, hitrecord: HitRecord, eta: float) -> tuple:
refract_ray = Ray(hitrecord.point, refract3(hitrecord.normal_g, ray.direction, hitrecord.material.refraction))
refract_hitrecord = HitRecord()
r = int ( ref1 * new_r + ref2 * r)
g = int ( ref1 * new_g + ref2 * g)
b = int ( ref1 * new_b + ref2 * b)

hit, rnew, gnew, bnew = self._shade(scene, refract_ray, refract_hitrecord)
self.num_secondary_rays += 1

if hitrecord.material.transparency != 0.0:
refract_ray = Ray(hitrecord.point + ray.direction * 0.01, refract3(hitrecord.normal_g, ray.direction, hitrecord.material.refraction))
new_r, new_g, new_b = self._recurse_shade(scene, refract_ray, iteration_num - 1)

if hit:
ref1 = hitrecord.material.transparency
ref2 = 1.-ref1
rnew = int ( ref1 * rnew + ref2 * r)
gnew = int ( ref1 * gnew + ref2 * g)
bnew = int ( ref1 * bnew + ref2 * b)
return rnew, gnew, bnew, refract_ray, refract_hitrecord
else:
return r,g,b,None,None
r = int ( ref1 * new_r + ref2 * r)
g = int ( ref1 * new_g + ref2 * g)
b = int ( ref1 * new_b + ref2 * b)

self.num_secondary_rays += 1

return r, g, b

def render(self, scene: Scene) -> RGBImage:
if not scene.camera:
Expand All @@ -125,26 +127,7 @@ def render(self, scene: Scene) -> RGBImage:
self.num_rays += 1

# Primary Ray:
hit, r, g, b = self._shade(scene, ray, hitrecord)

if hit and hitrecord.material.reflectivity != 0.0:
refhit = hitrecord.copy()
refray = ray.copy()
for i in range(self.iterations - 1):
r, g, b, refray, refhit = self._reflect(r,g,b, scene, refray, refhit)
self.num_secondary_rays += 1
if refray is None:
break

if hit and hitrecord.material.transparency != 0.0:
refhit = hitrecord.copy()
refray = ray.copy()
for i in range(self.iterations - 1):
r, g, b, refray, refhit = self._refract(r,g,b, scene, refray, refhit, 1)
self.num_secondary_rays += 1
if refray is None:
break

r, g, b = self._recurse_shade(scene, ray, self.iterations - 1)
image.drawPixelFast8(x, y, r, g, b)


Expand Down

0 comments on commit d0a8e49

Please sign in to comment.