lightList = [Light(Point(30,30,10), Color(1, 1, 1))] objectList = [Sphere(Point(2.5,3,-10), 2, redMat), Sphere(Point(-2.5,3,-10), 2, greenMat), Sphere(Point(0,7,-10), 2, blueMat), Triangle(Point(2.5,3,-10), Point(-2.5,3,-10), Point(0,7,-10), triangleMat), Plane(Point(0,0,0), Vector(0,1,0), planeMat)] # Renderfunktion - wird pro Pixel aufgerufen def render_pix(x, y, color): img.put(color.toValidatedHexString(), (x, HEIGHT-y)) if x%320 == 0: canvas.update() # Fenster & Canvas aufbauen mw = Tk() mw._root().wm_title("Raytracer") cFrame = Frame(mw, width=WIDTH, height=HEIGHT) cFrame.pack() canvas = Canvas(cFrame, width=WIDTH, height=HEIGHT, bg="white") # Bild für Pixelunterstützung img = PhotoImage(width=WIDTH, height=HEIGHT) canvas.create_image(0, 0, image=img, anchor=NW) canvas.pack() # camera initialisieren camera = Camera(Point(0,2,10), Vector(0,1,0), Point(0,3,0), FIELD_OF_VIEW) camera.setScreenSize(WIDTH, HEIGHT) # Anfangen zu Rendern, nachdem Canvas sichtbar ist
def main(): ImageFile.MAXBLOCK = 4096*2304 # this is only required for older PIL versions, if PILs output buffer is not large enough. see: https://mail.python.org/pipermail/image-sig/1999-August/000816.html parser = argparse.ArgumentParser(description='Simple Raytracer by Tilman Ginzel') parser.add_argument('-r', '--recursive', help='sets recursive depth, e.g. -r 3 (required)', nargs=1, type=checkPositiveInt, required=True, metavar='') parser.add_argument('-s', '--size', help='sets the size, e.g. -s 400 400', nargs=2, default=[400, 400], type=checkPositiveInt, required=False, metavar='') parser.add_argument('-v', '--verbose', help='enable live visualization while processing (slower)', required=False, action='store_true') parser.add_argument('-m', '--material', help='enable materials', required=False, action='store_true') parser.add_argument('-a', '--antialiasing', help='enables 4xSSAA (hence, 4 times slower)', required=False, action='store_true') parser.add_argument('-o', '--output', help='saves image to "./saves/"', required=False, action='store_true') parser.add_argument('-set', '--setting', help='choose a setting. -set 1 - 3', required=False, nargs=1, default=[1], type=int, metavar='') parser.add_argument('-nd', '--no-display', help='this should only be set if the script runs on a server without a $DISPLAY environment variable set!', required=False, action='store_true') try: args = vars(parser.parse_args()) except: parser.print_help() sys.exit(1) settingId = args['setting'][0] if settingId == 1: # default setting setting = DefaultSetting(width=args['size'][0], height=args['size'][1], recursiveDepth=args['recursive'][0], showMaterial=args['material']) elif settingId == 2: # space setting setting = SpaceSetting(width=args['size'][0], height=args['size'][1], recursiveDepth=args['recursive'][0], showMaterial=args['material']) elif settingId == 3: # room setting setting = RoomSetting(width=args['size'][0], height=args['size'][1], recursiveDepth=args['recursive'][0], showMaterial=args['material']) else: # default setting setting = DefaultSetting(width=args['size'][0], height=args['size'][1], recursiveDepth=args['recursive'][0], showMaterial=args['material']) # display is used to set whether you want to have a visual feedback in a graphical user interface. display = not args['no_display'] # easier to read and you do not have to negotiate it on every call if display: window = Tk() window._root().wm_title('Raytracer - Tilman Ginzel (173388)') if args['verbose']: can = Canvas(window, width=setting.WIDTH, height=setting.HEIGHT) else: frame = Frame(window, width=setting.WIDTH, height=setting.HEIGHT) can = Canvas(frame, width=setting.WIDTH, height=setting.HEIGHT) frame = Frame(window) can.pack() # photoImage is used to show live changes while processing if args['verbose']: photoImage = PhotoImage(width=setting.WIDTH, height=setting.HEIGHT) can.create_image((setting.WIDTH/2, setting.HEIGHT/2), image=photoImage, state="normal") # pilImage is used to save the image after processing or if verbose is deactivated pilImage = Image.new("RGB", (setting.WIDTH, setting.HEIGHT), (0, 0, 0)) start = time.clock() processor = Processor(setting, display=display, ssaa=args['antialiasing']) print 'start processing...' for pixel in processor.startProcessing(): if display and args['verbose']: photoImage.put("#%02x%02x%02x" %((pixel[1][0], pixel[1][1], pixel[1][2])), (pixel[0][0], pixel[0][1])) if pixel[0][1] == setting.HEIGHT-1: # if y == bottom, update canvas can.update() pilImage.putpixel((pixel[0][0], pixel[0][1]), ((pixel[1][0], pixel[1][1], pixel[1][2]))) end = time.clock() print 'done' print 'duration: %2.2f seconds' %(end-start) if display and not args['verbose']: tkImage = ImageTk.PhotoImage(pilImage) label = Label(image=tkImage) label.image = tkImage label.pack() can.pack() if args['output']: saveImage(pilImage, args) if display: window.mainloop()