diff --git a/examples/19.png b/examples/19.png new file mode 100644 index 0000000..f3a327f Binary files /dev/null and b/examples/19.png differ diff --git a/examples/19_refraction.py b/examples/19_refraction.py new file mode 100644 index 0000000..47bca49 --- /dev/null +++ b/examples/19_refraction.py @@ -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") diff --git a/main.py b/main.py deleted file mode 100644 index ae932e2..0000000 --- a/main.py +++ /dev/null @@ -1,49 +0,0 @@ -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 = 1000 -height = 800 - -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))) - -scene.add( - Triangle( - Vertex(position=(-1.5,10,0)), - Vertex(position=(3.5,10,0)), - Vertex(position=(1,10,5.)), - material=PhongMaterial(color=Vec3(1,1,1)) - ) -) - -#scene.add( -# Sphere( -# center=Vec3(1, 10, 0), -# radius = 1.5, -# material=PhongMaterial(color=Vec3(1, 1, 0)) -# ) -#) - -scene.add( - Sphere( - center=Vec3(0, 0, 0), - radius=1.5, - material=PhongMaterial(color=Vec3(.9, .9, .9), transparency=0.4, refraction=1.33) - ) -) - -scene.setCamera(camera) -engine = SimpleRT(iterations=10) -image = engine.render(scene) -image.save("a.png") diff --git a/pyrt/math/constants.py b/pyrt/math/constants.py index de9ad1e..dccba79 100644 --- a/pyrt/math/constants.py +++ b/pyrt/math/constants.py @@ -5,3 +5,4 @@ """ G_EPSILON = 1E-11 +G_REFRACTION_EPSILON = 1E-4 \ No newline at end of file diff --git a/pyrt/math/vecops.py b/pyrt/math/vecops.py index 34ce6d8..38efb61 100644 --- a/pyrt/math/vecops.py +++ b/pyrt/math/vecops.py @@ -103,13 +103,15 @@ 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 else: return I * eta - N * (eta * d + math.sqrt(k)) - # --------------------------------------------------------------------------------------------------------------------- diff --git a/pyrt/renderer/simplert.py b/pyrt/renderer/simplert.py index 3053cd7..18b7f56 100644 --- a/pyrt/renderer/simplert.py +++ b/pyrt/renderer/simplert.py @@ -91,7 +91,7 @@ def _recurse_shade(self, scene: Scene, ray: Ray, iteration_num: int) -> tuple: if hitrecord.material.transparency > G_EPSILON: refract_ray = Ray( - hitrecord.point + normalize3(ray.direction) * G_EPSILON, + 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)