-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.c
100 lines (78 loc) · 2.72 KB
/
main.c
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
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <unistd.h>
#include "vec.h"
#include "sdl.h"
#include "SDL2/SDL.h"
static const double width = 640, height = 480, fov = 5;
struct sphere {
double *point;
double radius;
double specularity;
};
double *light;
struct sphere sphere;
colour_t cast_ray(double *origin, double *direction)
{
colour_t retval;
double closest_len = vec_dot(direction, sphere.point);
double closest_dist = vec_len(vec_addm(vec_addm(vec_blank(3), direction, closest_len), sphere.point, -1));
if (closest_dist >= sphere.radius) {
retval = argb8888(255, 0, 0, 0);
goto fail;
}
double *hit_pos = vec_perm(vec_addm(vec_blank(3), direction, closest_len - sqrt(sphere.radius * sphere.radius - closest_dist * closest_dist)));
double *hit_normal = vec_perm(vec_norm(vec_addm(hit_pos, sphere.point, -1)));
/*double *hit_reflect = vec_norm(vec_addm(vec_addm(vec_blank(3), hit_normal, -vec_dot(direction, hit_normal)), direction, 2));*/
/*double specular = vec_dot(hit_reflect, vec_norm(vec_addm(light, hit_pos, -1)));*/
double specular = 0;
/*if (specular < 0)*/
/*specular = 0;*/
double diffuse = vec_dot(hit_normal, vec_norm(vec_addm(light, hit_pos, -1)));
if (diffuse < 0)
diffuse = 0;
double bright = diffuse * (1.0 - sphere.specularity) + specular * sphere.specularity;
if (bright > 1)
bright = 1;
/*retval = (colour_t){{bright * (hit_normal[2] + 1.0) * 0.5 * 255, bright * (hit_normal[1] + 1.0) * 0.5 * 255, bright * (hit_normal[0] + 1.0) * 0.5 * 255, 255}};*/
retval = argb8888(255,
bright * (hit_normal[0] + 1.0) * 0.5 * 255,
bright * (hit_normal[1] + 1.0) * 0.5 * 255,
bright * (hit_normal[2] + 1.0) * 0.5 * 255);
vec_del(hit_pos);
vec_del(hit_normal);
fail:
return retval;
}
int main(void)
{
double *eye = vec_perm(vec(0, 0, 0));
sphere = (struct sphere){vec_perm(vec(0.0, 0.0, -0.9)), 0.3, 0.1};
light = vec_perm(vec(1.0, -1.0, -0.0));
sdl_prepare(width, height);
for (size_t i = 0; i < width * height; i++)
sdl_buffer[i] = argb8888(255, 0, 0, 0);
for (double fov = 0; fov < 180; fov += 0.5) {
double plane_hwidth = sin((fov / 180.0 * M_PI) / 2.0);
double dpp = plane_hwidth / (width / 2.0);
double plane_hheight = (height / 2.0) * dpp;
double hdpp = dpp / 2;
uint32_t begun = SDL_GetTicks();
#pragma omp parallel for
for (uint16_t x = 0; x < (uint16_t)width; x++)
#pragma omp parallel for
for (uint16_t y = 0; y < (uint16_t)height; y++) {
double *ray = vec_perm(vec_norm(vec(plane_hwidth - x * dpp + hdpp, -plane_hheight + y * dpp + hdpp, -1)));
sdl_buffer[y * (uint16_t)width + x] = cast_ray(eye, ray);
vec_del(ray);
}
sdl_draw();
}
/*sleep(10);*/
vec_del(eye);
vec_del(sphere.point);
vec_del(light);
return 0;
}