def draw(self, passes = 8): if self._world == None: self.set_world() if self._camera == None: self.set_camera() ppu = self._camera.ppu width = int(ppu * self._camera.width) height = int(ppu * self._camera.height) self._image = Image(width, height) c = Color() t_0 = time.time() for y in range(height): lt0 = time.time() print 'drawing line', y + 1, 'of', height for x in range(width): c.set_rgb(0.0,0.0,0.0) for p in range(passes): c = c + self._world.sample(self._camera.get_ray(x,y)) self._image.set_pixel(x,y,c.dim(1.0 / passes)) lt1 = time.time() ltime = lt1 - lt0 ttime = lt1 - t_0 lleft = height - 1 - y mleft1 = ltime * lleft / 60 mleft2 = ttime / (y + 1) * lleft / 60 print 'line took {0:.3} seconds.'.format(ltime), print '{0:.5} to {1:.5} minutes left'.format(mleft1, mleft2) self._drawn = True return self
def __init__(self, center, radius, color=Color()): self._pp = Plane(Vector(), Vector(), Color()) self._pn = Plane(Vector(), Vector(), Color()) Sphere.__init__(self, center, radius, color) self.set_reflectivity(0.2) self.set_orientation(Vector()) self.set_cosine(1.0)
def __init__(self, normal = Vector(0.0,1.0,0.0), origin = Vector(0.0,0.0,0.0), orientation = Vector(1.0,0.0,0.0), c1 = Color(0.01,0.01,0.01), c2 = Color(0.99,0.99,0.99)): """Initializes plane and plane colors.""" Plane.__init__(self, normal, origin) self.set_orientation(orientation) self.set_colors(c1,c2)
def draw(self, passes=8): if self.world == None: self.set_world() ppu = self.camera_r.ppu w = int(ppu * self.camera_r.width) width = 2 * w height = int(ppu * self.camera_r.height) self.image = Image(width, height) c = Color() for y in range(height): print 'drawing line', y + 1, 'of', height for x in range(w): # draw pixel from left camera c.set_rgb(0.0, 0.0, 0.0) for p in range(passes): c = c + self.world.sample(self.camera_l.get_ray(x, y)) self.image.set_pixel(x, y, c.dim(1.0 / passes)) # draw pixel from right camera c.set_rgb(0.0, 0.0, 0.0) for p in range(passes): c = c + self.world.sample(self.camera_r.get_ray(x, y)) self.image.set_pixel(x + w, y, c.dim(1.0 / passes)) self._drawn = True return self
def __init__(self, r=1.0, normal=Vector(0.0, 1.0, 0.0), origin=Vector(0.0, 0.0, 0.0), orientation=Vector(1.0, 0.0, 0.0), c1=Color(0.01, 0.01, 0.01), c2=Color(0.99, 0.99, 0.99)): """Initializes plane and plane colors.""" CheckPlane.__init__(self, normal, origin, orientation, c1, c2) self.origin = origin self.set_orientation(orientation) self.r = r self.R = r**2.0
def __init__(self, center = Vector(0.0,0.0,0.0), radius = 1.0, color = Color(), orientation = Vector(0.0,1.0,0.0)): Sphere.__init__(self, center, radius, color) self.set_orientation(orientation) self.set_reflectivity(0.9,0.1)
def sample(self, ray, index=1.0, depth=0, last_hit=None): """Recursively traces ray within world.""" # check trace depth boundary if depth == bounds.max_depth: return Color(0.001, 0.001, 0.001) # get a trace interface i = self.trace(ray, last_hit) # detect hitting the sky if i.body == None: return self.get_sky(ray) # shade point L = self.shade(i) # add specular highlight if matte surface if i.matte: return self.highlight(L, ray, i) # if not matte, we do specular reflection else: if L < self._base_brightness: L = self._base_brightness cos_i = abs(ray.d.dot(i.normal)) R = i.body.reflectivity(i.poi) D = 1 - R Ps = R + D * ((1 - cos_i)**i.exp) Pt = 1.0 - Ps color = i.color.dim(L).dim(Pt) return color + self.sample(ray.reflect(i.poi, i.normal), index, depth + 1, i.body).dim(Ps)
def __init__(self, width, height): Png.__init__(self, width, height) self._i_width = width self._i_height = height self._scanlines = [] for i in range(height): self._scanlines.append([Color() for k in range(width)])
def run(): c = Color(0.0001, 0.0001, 0.0001) colors = [c.dup()] for i in range(99): colors.append(c.dup().gamma(0.5)) colors2 = colors[:] # p() method for c in colors: for s in c.p(): if s < 0 or s > 255: print 'p() method: samples are out of bounds' # dup() method for c in colors: if not c.dup() == c: print 'dup() method: result not equal to arg' # copy() method tmp = Color() for c in colors: tmp.copy(c) if not tmp == c: print 'copy() method: not equal to copied color'
def get_color(self, ray): cosine = ray.d.dot(self.light) if cosine < -0.5: red = 1.0 green = 2.0 * (cosine + 1.0) blue = 0.0 elif cosine < 0.0: red = 1.0 - 2.0 * (cosine + 0.5) green = 1.0 blue = 0.0 elif cosine < 0.5: red = 0.0 green = 1.0 blue = 2.0 * cosine else: red = 0.0 green = 1.0 - 2.0 * (cosine - 0.5) blue = 1.0 return Color(red, green, blue)
def run(): for r in rays: i.reset() for b in bodies: d = b.intersection(r) if d > 0.0: i.hit(b, d) i.register_hit(r) if i._body == None: print "interface didn't register a hit" else: if i._distance < 0.0: print "interface registered hit at negative distance" if i._distance > 0.1: print "interface didn't catch closest hit" if i._body.p() != 'bodystub': print "interface didn't catch body of correct type" if not i._normal == Vector(0.0, 0.0, 1.0): print "interface caught wrong surface normal." if not i._color == Color(0.5, 0.5, 0.5): print "interface caught wrong surface color."
def run(): c = Color(0.0001,0.0001,0.0001) colors = [c.dup()] for i in range(99): colors.append(c.dup().gamma(0.5)) colors2 = colors[:] # p() method for c in colors: for s in c.p(): if s < 0 or s > 255: print 'p() method: samples are out of bounds' # dup() method for c in colors: if not c.dup() == c: print 'dup() method: result not equal to arg' # copy() method tmp = Color() for c in colors: tmp.copy(c) if not tmp == c: print 'copy() method: not equal to copied color'
def __init__(self, light=Vector(0.0, 1.0, 0.0), color=Color(0.2, 0.2, 0.9)): Sky.__init__(self, light) self.color = color self._exp = _default_exponent
from py3D import Vector as V from py3D import skys, Sphere, Color, Plane from pytrace import Camera, Tracer, World ppu = 50 passes = 1 width = 3.0 height = 3.0 filename = 'Rainbows-{0}x{1}.png'.format(int(width * ppu), int(height * ppu)) cam_o = V(0.0, 10.0, 10.0) cam_f = V(0.0, 0.0, 0.0) cam = Camera(cam_o, cam_f, 3.0, 3.0) cam.set_ppu(ppu) sky = skys.Rainbow(V(0.0, 1.0, 0.0)) sphere = Sphere(V(0.0, 0.0, 0.0), 1.0, Color(0.001, 0.001, 0.001)) sphere.set_reflectivity(0.3) plane = Plane(V(0.0, 1.0, 0.0), V(0.0, 0.0, 0.0), Color(0.001, 0.001, 0.001)) plane.set_reflectivity(0.2) world = World([sphere, plane], sky) world.set_base_brightness(0.8) Tracer(world, cam).draw(passes).write(filename)
def get_color(self, point): return Color(0.5, 0.5, 0.5)
from py3D import Color, Vector from py3D import Plane, CheckPlane, Sphere win_w = 6.4 win_h = 4.0 ppu = 25 passes = 1 filename = 'room-{0}x{1}.png'.format(int(win_w * ppu), int(win_h * ppu)) ball = Sphere(Vector(0.0,0.0,0.0), 1.0, Color(0.1,0.1,0.1)) ball.set_reflectivity(0.6) floor = CheckPlane().set_reflectivity(0.0) wall_color = Color(0.1,0.1,0.1) n_wall = Plane(Vector(0.0,0.0,-1.0), Vector(0.0,0.0,6.0), wall_color.dup()) s_wall = Plane(Vector(0.0,0.0,1.0), Vector(0.0,0.0,-6.0), wall_color.dup()) w_wall = Plane(Vector(-1.0,0.0,0.0), Vector(6.0,0.0,0.0), wall_color.dup()) e_wall = Plane(Vector(1.0,0.0,0.0), Vector(-6.0,0.0,0.0), wall_color.dup()) ceiling = Plane(Vector(0.0,-1.0,0.0), Vector(0.0,6.0,0.0), wall_color.dup()) bodies = [n_wall, s_wall, w_wall, e_wall, ceiling] for b in bodies: b.set_reflectivity(0.6) bodies.append(ball) bodies.append(floor) world = World(bodies).set_base_brightness(0.9) cam = Camera(Vector(5.0,2.5,5.0), Vector(-5.0,0.0,-5.0), win_w, win_h)
from py3D import Vector, Ray, Sphere, hmSphere, Plane, CheckPlane, Color, Sky from pytrace import World, Image, rand from time import time filename = 'sample-09.png' width = 400 height = width s = hmSphere(Vector(0.0, 1.0, 0.0), 1.0, Color(0.001, 0.99, 0.25), Vector(10.0, 1.0, 0.0)) p = CheckPlane() w = World() w.add_body(s) w.add_body(p) w.set_sky(Sky(Vector(1.0, 10.0, 1.0), Color(0.2, 0.2, 0.8))) camera = Vector(0.0, 0.8, 16.0) c_dir = Vector(0.0, 0.0, -1.0).norm() c_up = Vector(0.0, 1.0, 0.0).norm() c_origin = Vector(-1.5, 2.3, 0.0) - camera c_width = 3.0 c_height = 3.0 c_x = c_dir.cross(c_up).scale(c_width / width) c_y = c_up.dup().scale(-1 * c_height / height) ray = Ray() image = Image(width, height) color = Color() loops_per_pixel = 16 t_0 = time()
from pytrace import World, Camera, Tracer from py3D import Color, Vector from py3D import Plane, CheckPlane, Sphere win_w = 6.4 win_h = 4.0 ppu = 25 passes = 1 filename = 'room-{0}x{1}.png'.format(int(win_w * ppu), int(win_h * ppu)) ball = Sphere(Vector(0.0, 0.0, 0.0), 1.0, Color(0.1, 0.1, 0.1)) ball.set_reflectivity(0.6) floor = CheckPlane().set_reflectivity(0.0) wall_color = Color(0.1, 0.1, 0.1) n_wall = Plane(Vector(0.0, 0.0, -1.0), Vector(0.0, 0.0, 6.0), wall_color.dup()) s_wall = Plane(Vector(0.0, 0.0, 1.0), Vector(0.0, 0.0, -6.0), wall_color.dup()) w_wall = Plane(Vector(-1.0, 0.0, 0.0), Vector(6.0, 0.0, 0.0), wall_color.dup()) e_wall = Plane(Vector(1.0, 0.0, 0.0), Vector(-6.0, 0.0, 0.0), wall_color.dup()) ceiling = Plane(Vector(0.0, -1.0, 0.0), Vector(0.0, 6.0, 0.0), wall_color.dup()) bodies = [n_wall, s_wall, w_wall, e_wall, ceiling] for b in bodies: b.set_reflectivity(0.6) bodies.append(ball) bodies.append(floor) world = World(bodies).set_base_brightness(0.9)
def __init__(self, normal, origin, color=Color(0.001, 0.001, 0.001)): Body.__init__(self) self.set_normal(normal) self.set_position(origin) self.set_color(color) self.set_reflectivity(0.2)
class World: """This class holds body/camera/view information and performs raytrace.""" _bodies = [] _sky = Color() _interface = Interface() _light = Vector().norm() _base_brightness = 0.2 def __init__(self, bodies=[], sky=Sky()): self._bodies = bodies self._sky = sky self._light = sky.get_light() interface = Interface() self._base_brightness = 0.2 def add_body(self, body): self._bodies.append(body) return self def set_sky(self, sky): self._sky = sky return self def get_sky(self, ray): return self._sky.get_color(ray) def get_light(self): return self._light.dup() def set_base_brightness(self, b): self._base_brightness = b return self def trace(self, ray, last_hit=None): """Finds first interaction of a ray within the world.""" self._interface.reset() for bodies in self._bodies: # check for intersection of ray with body distance = bodies.intersection(ray) if distance < 0.0: continue # move on if we're interacting with our starting point if bodies == last_hit and distance < bounds.too_close: continue # if we've got a hit, register it if it's closer self._interface.hit(bodies, distance) # end for # register the rest of our interface self._interface.register_hit(ray) return self._interface def shade(self, interface): """Detects amount of illumination at point.""" ray = Ray(interface.poi, self.get_light()) lambertian = self._light.dot(interface.normal) if lambertian < 0.0: return lambertian for bodies in self._bodies: distance = bodies.intersection(ray) if distance < 0.0: continue if bodies != interface.body or distance > bounds.too_small: lambertian = -1.0 break return lambertian def highlight(self, lambertian, ray, interface): if lambertian < 0.0: return interface.color.dim(self._base_brightness) lambertian = max(lambertian, self._base_brightness) ray.reflect(i.poi, i.normal) highlight = max(0.0, ray.d.dot(self.get_light())) highlight **= i.exp return i.color.dim(L).gamma(1 - highlight) def sample(self, ray, index=1.0, depth=0, last_hit=None): """Recursively traces ray within world.""" # check trace depth boundary if depth == bounds.max_depth: return Color(0.001, 0.001, 0.001) # get a trace interface i = self.trace(ray, last_hit) # detect hitting the sky if i.body == None: return self.get_sky(ray) # shade point L = self.shade(i) # add specular highlight if matte surface if i.matte: return self.highlight(L, ray, i) # if not matte, we do specular reflection else: if L < self._base_brightness: L = self._base_brightness cos_i = abs(ray.d.dot(i.normal)) R = i.body.reflectivity(i.poi) D = 1 - R Ps = R + D * ((1 - cos_i)**i.exp) Pt = 1.0 - Ps color = i.color.dim(L).dim(Pt) return color + self.sample(ray.reflect(i.poi, i.normal), index, depth + 1, i.body).dim(Ps)