Skip to content

Commit

Permalink
Merge pull request #28 from slmtnm/refraction
Browse files Browse the repository at this point in the history
Fix previous refraction pull request changes
  • Loading branch information
martinchristen authored Sep 22, 2021
2 parents c8fd503 + 91e62d4 commit 6fc0ccb
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 8 deletions.
Binary file added examples/19.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
46 changes: 46 additions & 0 deletions examples/19_refraction.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from pyrt.geometry.vertex import Vertex
from pyrt import material
from pyrt.math import Vec3
from pyrt.scene import Scene
from pyrt.light import PointLight
from pyrt.geometry import Sphere, Triangle
from pyrt.material import PhongMaterial
from pyrt.camera import PerspectiveCamera
from pyrt.renderer import SimpleRT
from PIL import Image

width = 400
height = 300

camera = PerspectiveCamera(width, height, 60)
camera.setView(Vec3(0,-10,0), Vec3(0,0,0), Vec3(0,0,1))

scene = Scene()
scene.addLight(PointLight(Vec3(-1,-8,1)))

# Triangle behind lens
A = Vertex(position=(-1.5, 6, 0))
B = Vertex(position=(3.5, 6, 0))
C = Vertex(position=(1, 6, 5.))
scene.add(Triangle(A, B, C, material=PhongMaterial(color=Vec3(1,1,1))))

# Floor
A = Vertex(position=(-5.0, -5.0, -2.0))
B = Vertex(position=( 5.0, -5.0, -2.0))
C = Vertex(position=( 5.0, 5.0, -2.0))
D = Vertex(position=(-5.0, 5.0, -2.0))

floormaterial = PhongMaterial(color=Vec3(.2,.2,.2) )
scene.add(Triangle(A,B,C, material=floormaterial))
scene.add(Triangle(A,C,D, material=floormaterial))

# Two lenses
scene.add(Sphere(Vec3(-1, 5.7, -1), 2.5, PhongMaterial(color=Vec3(.9, .9, .9),
transparency=.8, refraction=1.5)))
scene.add(Sphere(Vec3(2.8, 5, .5), 1.8, PhongMaterial(color=Vec3(.9, .9, .9),
transparency=.8, refraction=1.5)))

scene.setCamera(camera)
engine = SimpleRT(iterations=4, shadow=True)
image = engine.render(scene)
image.save("16.png")
5 changes: 3 additions & 2 deletions pyrt/geometry/sphere.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from ..geometry import Shape
from ..math import Ray, HitRecord, Vec2, Vec3, dot3, G_EPSILON
from ..material import Material, PhongMaterial
from ..material import Material, PhongMaterial, TextureMaterial, NormalMappedMaterial
from .bbox import BBox
from math import sqrt, pi, asin, atan2

Expand Down Expand Up @@ -73,7 +73,8 @@ def hit(self, ray: Ray, hitrecord: HitRecord) -> bool:
hitrecord.normal = hitrecord.normal_g
hitrecord.color = Vec3(1., 1., 1.) # spheres don't have interpolated colors, set to white
hitrecord.material = self.material
hitrecord.texcoord = self.calcTexcoord(hitrecord.point)
if isinstance(hitrecord.material, TextureMaterial) or isinstance(hitrecord.material, NormalMappedMaterial):
hitrecord.texcoord = self.calcTexcoord(hitrecord.point)
return True
return False

Expand Down
5 changes: 3 additions & 2 deletions pyrt/geometry/triangle.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"""

from ..geometry import Shape, Vertex
from ..material import PhongMaterial
from ..material import PhongMaterial, TextureMaterial, NormalMappedMaterial
from ..math import *


Expand Down Expand Up @@ -202,7 +202,8 @@ def hit(self, ray: Ray, hitrecord: HitRecord) -> bool:
cV = self.c.color - self.a.color
hitrecord.color = self.a.color + cU * u + cV * v
hitrecord.material = self.material
hitrecord.texcoord = self.calcTexcoord(hitrecord.point)
if isinstance(hitrecord.material, TextureMaterial) or isinstance(hitrecord.material, NormalMappedMaterial):
hitrecord.texcoord = self.calcTexcoord(hitrecord.point)

# why would we?
# hitrecord.point = ray.start + t * ray.direction
Expand Down
1 change: 1 addition & 0 deletions pyrt/math/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
"""

G_EPSILON = 1E-11
G_REFRACTION_EPSILON = 1E-4
5 changes: 4 additions & 1 deletion pyrt/math/vecops.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,10 @@ def refract3(N, I, eta):
I: Incident vector
eta: Refraction koefficient
"""
d = dot3(I, N)
d = dot3(N, I)
if d > 0:
return refract3(I, N * -1, 1 / eta)
eta = 1 / eta
k = 1 - eta * eta * (1 - d * d)
if k < 0:
return I
Expand Down
9 changes: 6 additions & 3 deletions pyrt/renderer/simplert.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def _recurse_shade(self, scene: Scene, ray: Ray, iteration_num: int) -> tuple:
if not hit or iteration_num == 0:
return r, g, b

if hitrecord.material.reflectivity != 0.0:
if abs(hitrecord.material.reflectivity) > G_EPSILON:
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)

Expand All @@ -90,8 +90,11 @@ def _recurse_shade(self, scene: Scene, ray: Ray, iteration_num: int) -> tuple:

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))
if abs(hitrecord.material.transparency) > G_EPSILON:
refract_ray = Ray(
hitrecord.point + ray.direction * G_REFRACTION_EPSILON,
refract3(normalize3(hitrecord.normal_g), normalize3(ray.direction), hitrecord.material.refraction)
)
new_r, new_g, new_b = self._recurse_shade(scene, refract_ray, iteration_num - 1)

ref1 = hitrecord.material.transparency
Expand Down

0 comments on commit 6fc0ccb

Please sign in to comment.