From b71d606158dd52fa9f3d076708c0802668e81c07 Mon Sep 17 00:00:00 2001 From: Benjamin Koltes <benjamin.koltes@student.ecp.fr> Date: Mon, 21 Mar 2016 19:46:31 +0100 Subject: [PATCH] reflexions --- __pycache__/raytracer.cpython-33.pyc | Bin 3000 -> 3415 bytes raytracer.py | 13 +++++++++++-- scenes/reflection.py | 23 +++++++++++++++++++++++ scenes/two_spheres.png | Bin 7308 -> 2977 bytes scenes/two_spheres_reflection.png | Bin 0 -> 2167 bytes 5 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 scenes/reflection.py create mode 100644 scenes/two_spheres_reflection.png diff --git a/__pycache__/raytracer.cpython-33.pyc b/__pycache__/raytracer.cpython-33.pyc index 30618db9ed94af2cbefc1ffb44ebb596ab27ebfc..89eb08a1605bcffef331f543624caa5026ea71a1 100644 GIT binary patch delta 929 zcmdlXeqBm=9uF^<lI4dm4Q>X8WCkR_%)r3lz`(#z+%-`-Lp_C)p@oqlikl&Yiy?)Z zp@o4ViiaVEharU*%;sfC;bREa;NQ4jmZ?5dgn@w}nFVT=C<6ln7Xt%>Gsr9tCI*Id z28LP|h7tyb6h?+-Muu8ehKfvv8b*dJMh2JIIEGp_h7u-*8a9R+28L!PhFW%p8g_;h z28L{Ah9VgdJBtM*mBq>+k;TT)%)n5~!BE1^P{Ybl!vWTyzzXGLGcgoZfppYzG89%Z z6v}{5cn$01G-h>uP6m)UoD5l9U`<>M6_#K}a5K2X>M_)EGt_V~l<+XraDzl^I4AF6 zmhj?YC_KavUc<$Z#S5}HhMA$3hoP32p_Y%KgoB}k59|&eh7@Lykts|dvV@Nzg$XRq z3l(o>VkqI8tji)<U(3Z%!wiznW??9L#aP3@kj2lCB>*zIhLa&nkb$X|pP^QOp@yF! zg#|>`2r!6<fC!0NL530`29PQih7?wY8bJmT@ftypg|!f2E`}^&hAa_=T49C~QHB~J zurHXv_AxU^G_x?&io}5&R3pqFQNzU`QX|YzBf=meUdzRh#{lv>HM}UT&c?vN;8zMt zN|||SnV=Mr$;iOKkjccrz>r=ovd;ZsRg1lb*yKc(ExD|qRFj`ylmb?tn^;lG$-uyn zl3A3RT#}ieR|-l*dHF@Ti8+~7sVSu(qaj?d`k=(hQVs?NhTO!G)S}G99I*1D)U+I^ zZjf0eMTyC&@kNQ18lsc!SrtVE85kJyN^_G^i{dj&Qi~En))Y^UXHA-XiB;UI6y#DD zFzHt+%)r0^H7zwI9^oi<kP)fnAVa|_i%R(!7#QFd#V6<I<QGl0;gX-s!6w9LG+CNW wQBai8n~{f6l2MFNijkjDl1Xy2E!#mxMvcw?*>jl~jW_3Vxihlx%kppo07(<Mb^rhX delta 557 zcmcaEwL@Ha9uF_qpP2VyA2}Epk{OTyGXn#I0|Ns?ar;E&43!oJhA3`^6i$W|E(Q>r zharWVA%zFb=4D9XWeC>b+qg-VsXiH`4`d8K0|NsW0|SFI$c#ir28MJ7hFWHZ5(b78 zMuuiahFTVeicE$YMusd#2A9}4hFVsJ5+;TkR)!h|hGr&)S~i9nHii@ihHPerA{h`n ziv=W=#mXR&#m3Ogz);K1P{Pho!@^L*4%WZ|VoTSsGh{O{6jgzA)N(KsRxuRHfKYf1 z%j7&}^?D8lkU1O-SzKUEoD3C~U`KE>xWwu))N(P@a59weFw}5?L~A%0N;nu&n4l<~ z8RYP076$WLPKLrm4B<6kbFz3DviKNkxj|a9_(4vKVP>f1VW{P0sO1A0P$B?!DGx&m zGY`nt6ebW^A~0EyMTAjcvJ9)VBntxrgI_5q>@xGxGC|>&$;iOKpdmOpj&+L`2Ll5` zZemGlQD$OJDJug5Lvnsjei4+FUz7sYn44Ik!9Tg4O>y!zwnPmcn5y{vq^#8B60nlw z_zEap38kwh-{zK|Je^&LQEBojc11@1&3D)jGBV0<p2wNX#Hh8IhsT|fg-3*k8vu6A BYODYN diff --git a/raytracer.py b/raytracer.py index e6b7538..2253a80 100644 --- a/raytracer.py +++ b/raytracer.py @@ -8,7 +8,7 @@ class Ray: self.starting_point = starting_point self.direction = direction -def trace_ray(ray, scene, camera): +def trace_ray(ray, scene, camera, number_iterations = 20): intersect_list = [] distance = float('inf') for o in scene.object_list: @@ -24,7 +24,16 @@ def trace_ray(ray, scene, camera): for light in scene.light_list: # color += phong_illuminate(light, class_intersect.position, class_intersect.normal, class_intersect.object, Vector([0,0,0])) color += compute_light(light, scene, class_intersect, Vector([0,0,0])) - color_object = class_intersect.object.material.color + c_x, c_y, c_z = color.coord() + color = Vector([max(min(c_x, 1), 0), max(0, min(c_y, 1)), max(0, min(c_z,1))]) + if number_iterations > 0: + D, N = ray.direction.normalized(), class_intersect.normal + reflected_direction = D - 2*(D*N)*N + new_ray = Ray(class_intersect.position + 1e-2 * reflected_direction, reflected_direction) + r = class_intersect.object.material.reflection + trace_ray_color = trace_ray(new_ray, scene, camera, number_iterations - 1) + #if trace_ray_color != Vector([0,0,0]): + color = (1 - r)*color + r*trace_ray_color c_x, c_y, c_z = color.coord() return Vector([max(min(c_x, 1), 0), max(0, min(c_y, 1)), max(0, min(c_z,1))]) diff --git a/scenes/reflection.py b/scenes/reflection.py new file mode 100644 index 0000000..cde3e1b --- /dev/null +++ b/scenes/reflection.py @@ -0,0 +1,23 @@ +# Show to python where to find the modules +import sys +sys.path.append('..') + +from scene import * +from light import Spotlight +from camera import Camera +from raytracer import raytracer_render +from matplotlib.image import imsave +import sys + +camera = Camera(200,200,1) +materiau_sphere_bleue = Material(Vector((0,0,1)), .7, .7, .7, 100, .7) +materiau_sphere_rouge = Material(Vector((1,0,0)), .7, .7, .7, 100, .7) +sphere_bleue = Sphere(Vector([0,0,3]), .8, materiau_sphere_bleue) +sphere_rouge = Sphere(Vector([0.5,0.5,2]), .5, materiau_sphere_rouge) +lumiere = Spotlight(Vector((1,1,0)), Vector((1,1,1))) +scene = Scene() +scene.add_object(sphere_bleue) +scene.add_object(sphere_rouge) +scene.add_light(lumiere) +affiche = raytracer_render(camera, scene) +imsave('two_spheres_reflection.png',affiche) diff --git a/scenes/two_spheres.png b/scenes/two_spheres.png index fc1cbb5af975fb4411ef0fa31dea1e704954f6f4..aca009bc7477dccc24c1f1bbbaa51f2ee7e61e1a 100644 GIT binary patch literal 2977 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 literal 7308 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 diff --git a/scenes/two_spheres_reflection.png b/scenes/two_spheres_reflection.png new file mode 100644 index 0000000000000000000000000000000000000000..3345277b857a806c034bb22e1094bef0573fbc05 GIT binary patch literal 2167 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 FngH+czeE54 literal 0 HcmV?d00001 -- GitLab