aboutsummaryrefslogtreecommitdiff
path: root/bcardrt.c
blob: c7d3b66a1b5467407df2570b4e8fb789cd8c1fed (plain)
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
#include <u.h>
#include <libc.h>

typedef struct { double x, y, z; } vec;

vec v(double x, double y, double z) { return (vec){x,y,z}; }
vec vadd(vec a, vec b) { return v(a.x+b.x,a.y+b.y,a.z+b.z); }
vec vmul(vec u, double s) { return v(u.x*s,u.y*s,u.z*s); }
double vdot(vec a, vec b) { return a.x*b.x+a.y*b.y+a.z*b.z; }
vec vcross(vec a, vec b) { return v(a.y*b.z-a.z*b.y,a.z*b.x-a.x*b.z,a.x*b.y-a.y*b.x); }
vec vnorm(vec u) { return vmul(u,1/sqrt(vdot(u,u))); }

/* aek */
//int G[] = {247570, 280596, 280600, 249748, 18578, 18577, 231184, 16, 16};
/* rgl */
int G[] = {263948, 264338, 262288, 266128, 395408, 346256, 296720, 16, 16};

double R(void) { return frand(); }

int
TraceRay(vec src, vec dst, double *t, vec *normal)
{
	int m, k, j;
	double p;

	*t = 1e9;
	m = 0;
	p = -src.z / dst.z;
	if(p > 0.01){
		*t = p;
		*normal = v(0,0,1);
		m = 1;
	}

	for (k = 19; k--;)
		for (j = 9; j--;)
			if ((G[j] & 1<<k) != 0) {
				vec p;
				double b, c, q;

				p = vadd(src, v(-k,0,-j - 4));
				b = vdot(p, dst);
				c = vdot(p, p) - 1;
				q = b*b - c;
	
				if(q > 0){
					double s;

					s = -b - sqrt(q);
					if(s > 0.01 && s < *t){
						*t = s;
						*normal = vnorm(vadd(p, vmul(dst, *t)));
						m = 2;
					}
				}
			}
	return m;
}

vec
Sample(vec src, vec dst)
{
	vec normal, intersection, light_dir, half_vec;
	double t, lamb_f, color;
	int match;

	match = TraceRay(src, dst, &t, &normal);
	if(!match)
		return vmul(v(0.7,0.6,1), pow(1 - dst.z, 4));

	intersection = vadd(src, vmul(dst, t));
	light_dir = vnorm(vadd(v(9 + R(),9 + R(),16), vmul(intersection, -1)));
	half_vec = vadd(dst, vmul(normal, vdot(normal, dst) * -2));

	lamb_f = vdot(light_dir, normal);

	if(lamb_f < 0 || TraceRay(intersection, light_dir, &t, &normal))
		lamb_f = 0;

	color = pow(vdot(light_dir, half_vec) * (lamb_f > 0), 99);

	if((match & 1) != 0){
		intersection = vmul(intersection, 0.2);
		return vmul(((int)(ceil(intersection.x) + ceil(intersection.y)) & 1) != 0? v(3,1,1): v(3,3,3), lamb_f * 0.2 + 0.1);
	}

	return vadd(v(color,color,color), vmul(Sample(intersection, half_vec), 0.5));
}

void
main()
{
	vec cam_forward, cam_up, cam_right, c, color, delta;
	int x, y, r;

	print("P3 512 512 255\n");

	cam_forward = vnorm(v(-6,-16,0));
	cam_up = vmul(vnorm(vcross(v(0,0,1), cam_forward)), 0.002);
	cam_right = vmul(vnorm(vcross(cam_forward, cam_up)), 0.002);
	c = vadd(vmul(vadd(cam_up, cam_right), -256), cam_forward);

	for(y = 512; y--;)
		for(x = 512; x--;){
			color = v(13,13,13);
			for(r = 64; r--;){
				delta = vadd(vmul(vmul(cam_up, R() - 0.5), 99), vmul(vmul(cam_right, R() - 0.5), 99));
				color = vadd(vmul(Sample(vadd(v(17,16,8), delta), vnorm(vadd(vmul(delta, -1), vmul(vadd(vadd(vmul(cam_up, R()+x), vmul(cam_right, R()+y)), c), 16)))), 3.5), color);
			}
			print("%d %d %d\n", (int)color.x, (int)color.y, (int)color.z);
		}
	exits(nil);
}