Skip to content

Commit

Permalink
Add refraction
Browse files Browse the repository at this point in the history
  • Loading branch information
Makar Solomatin committed Feb 12, 2021
1 parent abf01e2 commit 697d042
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 3 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.idea
.pyc
.vscode
__pycache__/
*.egg-info/
.installed.cfg
Expand Down
37 changes: 37 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from pyrt.geometry.sphere import Sphere
from typing import List
from pyrt.math import *
from pyrt.light import *
from pyrt.geometry import Triangle, Vertex, Sphere
from pyrt.material import PhongMaterial
from pyrt.camera import PerspectiveCamera
from pyrt.renderer import SimpleRT
from pyrt.scene import Scene

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)

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

scene = Scene()
scene.add(Triangle(Vertex(position=(0, 0, 0)),
Vertex(position=(0, 5, 0)),
Vertex(position=(1, 5, 0)), material=PhongMaterial()))
scene.setCamera(camera)
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))

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

imgdata = SimpleRT(shadow=True, iterations=3).render(scene)
imgdata.save('a.png')
3 changes: 2 additions & 1 deletion pyrt/material/material.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class Material(object):

"""Base Material Class"""

def __init__(self, color: Vec3 = Vec3(0.,0.,0.), shininess: float = 0.0, reflectivity: float = 0.5, refraction: float = 1.0):
def __init__(self, color: Vec3 = Vec3(0.,0.,0.), shininess: float = 0.0, reflectivity: float = 0.5, refraction: float = 1.0, transparency = 0.0):
self.color = color
self.shininess = shininess
self.reflectivity = reflectivity
Expand All @@ -28,6 +28,7 @@ def __init__(self, color: Vec3 = Vec3(0.,0.,0.), shininess: float = 0.0, reflect
Also check the "refract3" function in math/vecops.py
"""
self.refraction = refraction
self.transparency = transparency

@abstractmethod
def shade(self, camera: Camera, ray: Ray, hitrecord: HitRecord, lights: list) -> Vec3:
Expand Down
4 changes: 2 additions & 2 deletions pyrt/material/phongmaterial.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ class PhongMaterial(Material):

"""Base Material Class"""

def __init__(self, color: Vec3 = Vec3(1.,1.,1.), shininess: float = 10.0, reflectivity: float = 0.0, refraction: float = 1.0):
Material.__init__(self, color, shininess, reflectivity, refraction)
def __init__(self, color: Vec3 = Vec3(1.,1.,1.), shininess: float = 10.0, reflectivity: float = 0.0, refraction: float = 1.0, transparency = 0.0):
Material.__init__(self, color, shininess, reflectivity, refraction, transparency)

def shade(self, camera: Camera, ray: Ray, hitrecord: HitRecord, lights: list) -> Vec3:
"""
Expand Down
25 changes: 25 additions & 0 deletions pyrt/renderer/simplert.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,22 @@ def _reflect(self, r: int, g: int, b: int, scene: Scene, ray: Ray, hitrecord: Hi
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()

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

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

def render(self, scene: Scene) -> RGBImage:
if not scene.camera:
Expand Down Expand Up @@ -119,6 +135,15 @@ def render(self, scene: Scene) -> RGBImage:
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

image.drawPixelFast8(x, y, r, g, b)

Expand Down

0 comments on commit 697d042

Please sign in to comment.