/
main.py
118 lines (104 loc) · 4.81 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import sys
import os
import math
import random
from tqdm import tqdm
sys.path.append("./src/core/")
from geometry import *
from hitable import *
from shape import *
from camera import *
from material import *
import numpy as np
import matplotlib.pyplot as plt
import cProfile
MAX_FLOAT = sys.float_info.max
random.seed(123)
def color(r: ray, world: list,depth = 0,max_depth = 4):
rec = hit_record()
hit_anything,rec = iterate_hit_list(r,0.001,MAX_FLOAT,world)
if (hit_anything):
# print(rec.normal)
scattered = ray(vec3(0,0,0),vec3(0,0,0))
attenuation = vec3(0,0,0)
if_scatter,(scattered,attenuation) = rec.mat.scatter(r,rec)
if (depth < max_depth and if_scatter):
return attenuation * color( scattered,world,depth + 1,max_depth)
else:
return vec3(0.0,0.0,0.0)
else:
unit_direction = unit_vector(r.direction)
t = 0.5 * (unit_direction.y() + 1.0)
return (1.0 -t ) * vec3(1.0,1.0,1.0) + t * vec3(0.5,0.7,1.0)
def random_scene():
hit_object_list = []
hit_object_list.append(sphere(vec3(0,-1000,0),1000,lambertian(vec3(0.5,0.5,0.5))))
for a in range(-11,11,1):
for b in range(-11,11,1):
choose_mat = random.random()
center = vec3(a + 0.9 * random.random(),0.2, b + 0.9 * random.random())
if( (center-vec3(4,0.2,0)).length() > 0.9):
if(choose_mat < 0.8): #diffuse
hit_object_list.append(sphere(center,0.2,
lambertian(vec3(random.random() * random.random(),
random.random() * random.random(),
random.random() * random.random()))))
elif(choose_mat < 0.95): #metal
hit_object_list.append(sphere(center,0.2,
metal(vec3(0.5 * (1 + random.random()),
0.5 * (1 + random.random()),
0.5 * (1 + random.random())),
0.5 * random.random())))
else:
hit_object_list.append(sphere(center,0.2,dielectric(1.5)))
hit_object_list.append(sphere( vec3(0, 1, 0), 1.0, dielectric(1.5) ))
hit_object_list.append(sphere( vec3(-4, 1, 0 ), 1.0, lambertian(vec3(0.4, 0.2, 0.1))))
hit_object_list.append(sphere( vec3(4, 1, 0), 1.0, metal(vec3(0.7,0.6,0.5),0.0)))
return hit_object_list
def main(filename: str = 'output',output_res: tuple = (200,100),num_samples= 100):
nx = output_res[0];
ny = output_res[1];
num_samples = num_samples
output = np.zeros((nx,ny,3))
#f.write("P3\n" + str(nx) + " " + str(ny) + "\n255\n");
hit_object_list = []
R = math.cos(math.pi/4)
# hit_object_list.append(sphere(vec3(-R,0,-1),R,lambertian(vec3(0, 0, 1))))
# hit_object_list.append(sphere(vec3(R,0,-1),R,lambertian(vec3(1, 0, 0))))
# hit_object_list.append(sphere(vec3(0,0,-1),0.5,lambertian(vec3(0.1,0.2,0.5))))
# hit_object_list.append(sphere(vec3(0,-100.5,-1),100,lambertian(vec3(0.8,0.8,0.0))))
# hit_object_list.append(sphere(vec3(1,0,-1),0.5,metal(vec3(0.8,0.6,0.2))))
# hit_object_list.append(sphere(vec3(-1,0,-1),0.5,dielectric(1.5)))
# hit_object_list.append(sphere(vec3(-1,0,-1),-0.45,dielectric(1.5)))
hit_object_list = random_scene()
#print("hit this")
lookfrom = vec3(13,2,3)
lookat = vec3(0,0,0)
dist_to_focus = 10
aperture = 0.1
cam = camera(lookfrom,lookat,vec3(0,1,0),20,float(nx)/float(ny),aperture,dist_to_focus)
with tqdm(total = ny * nx) as pbar:
for j in range(ny-1 ,-1,-1):
for i in range(0,nx):
col = vec3(0,0,0)
for s in range(0,num_samples):
u = float(i + random.random())/float(nx)
v = float(j + random.random())/float(ny)
r = cam.get_ray(u,v)
#p = r(2.0)
col += color(r,hit_object_list,0)
pbar.update(1)
col /= float(num_samples)
col = vec3(math.sqrt(col[0]),math.sqrt(col[1]),math.sqrt(col[2]))
ir = int(255.99 * col.x0);
ig = int(255.99 * col.x1);
ib = int(255.99 * col.x2);
output[i,j,:] = np.array([ir,ig,ib])
#f.write(str(ir) + " " + str(ig) + " " + str(ib) + "\n");
plt.imsave(filename + ".png",np.rot90(output).astype(np.uint8))
#f.close()
if __name__ == "__main__":
#cProfile.runctx('main()',None,("random_spheres",(200,100),64))
main("./unit_tests/random_spheres_unit_test",(200,100),64)
#510 s in c++
#main("./test",(400,300),32)