# tk_refracted_water.py import tkinter as tk import math import random root = tk.Tk() canvas = tk.Canvas(root, width=600, height=600) canvas.pack() zzz = [] def shading(normal_vector, light_direction): # calculate the angle between the normal vector and the light direction dot_product = sum([a*b for a,b in zip(normal_vector, light_direction)]) dot_product = max(0, min(1, (dot_product + 1000) * 0.0005)) angle = math.acos(dot_product) # use the angle to determine the shade of blue shade = int(255 * 2 * (1 - angle / math.pi)) if shade > 255: shade -= 255 rgb = (shade, shade, 255) else: rgb = (0, 0, shade) return "#{:02x}{:02x}{:02x}".format(*rgb) def vector(x, y): if (x, y) in vectors: return vectors[x, y] else: x1 = x + random.randint(-7, 7) y1 = y + random.randint(-7, 7) z1 = random.randint(0, 20) vectors[x, y] = x1, y1, z1 return x1, y1, z1 triangles = [] depths = [] vectors = {} t = 0 for i in range(-1, 26): for j in range(-1, 26): x = i * 24 y = j * 24 x1, y1, z1 = vector(x, y) x2, y2, z2 = vector(x + 24, y) x3, y3, z3 = vector(x, y + 24) vectors[t] = [(x, y), (x + 24, y), (x, y + 24)] t += 1 triangles.append([x1, y1, x2, y2, x3, y3]) depths.append([z1, z2, z3]) x1 = x2 y1 = y2 x2, y2, z2 = vector(x + 24, y + 24) vectors[t] = [(x + 24, y + 24)] t += 1 triangles.append([x1, y1, x2, y2, x3, y3]) depths.append([z1, z2, z3]) # set the light direction light_direction = (1, 1, 1) while 1: canvas.delete('all') for i in range(len(triangles)): x1, y1, x2, y2, x3, y3 = triangles[i] z1, z2, z3 = depths[i] # calculate the normal vector using the cross product of the two vectors of the triangle a = [x2-x1, y2-y1, z2-z1] b = [x3-x1, y3-y1, z3-z1] normal_vector = [a[1]*b[2] - a[2]*b[1], a[2]*b[0] - a[0]*b[2], a[0]*b[1] - a[1]*b[0]] # call the shading function with the normal vector and light direction shade = shading(normal_vector, light_direction) # create the polygon with the returned fill color canvas.create_polygon(x1, y1, x2, y2, x3, y3, outline='', fill=shade) root.update()