aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.c46
-rw-r--r--ray.c72
-rw-r--r--ray.h2
-rw-r--r--scene.h14
4 files changed, 107 insertions, 27 deletions
diff --git a/main.c b/main.c
index 9dd30d9..e4c8c1a 100644
--- a/main.c
+++ b/main.c
@@ -34,6 +34,21 @@ pthread_mutex_t percentlock;
char container[ CONTAINER_SIZE(OBJECTS, MATERIALS, LIGHTS) ];
container_t *cont = (container_t *) container;
+settings_t gfx_high = {
+ .arealight_samples = 64,
+ .envlight_samples = 64,
+ .antialias_samples = 8,
+ .depth = 16,
+};
+
+settings_t gfx_low = {
+ .arealight_samples = 16,
+ .envlight_samples = 16,
+ .antialias_samples = 2,
+ .globallight_samples = 5,
+ .depth = 1,
+};
+
// Implement random
COORD_T ray_rand(void *seed)
{
@@ -51,17 +66,18 @@ int main()
color_set(&s->ambient, 0.09, 0.09, 0.09);
color_set(&s->back, 0.8, 0.8, 0.8);
color_set(&s->env_color, 0.13, 0.13, 0.13);
- s->env_samples = 0;
+ s->env_enabled = false;
+ s->gfx = &gfx_low;
// Set viewpoint options
- vector_set(&s->view.position, 0, 5, 5);
+ vector_set(&s->view.position, 0, 5, 4);
vector_set(&s->view.target, 0, 5, 0);
s->view.width = TESTW;
s->view.height = TESTH;
// Create materials
material_t *m = add_material(cont);
- vector_set(&m->color, 0.4, 0.4, 1);
+ vector_set(&m->color, 1, 1, 1);
m->defuse = 1;
m->specular = 0;
m->shine = 80;
@@ -74,8 +90,8 @@ int main()
material_t *m2 = add_material(cont);
vector_set(&m2->color, 1, 1, 1);
m2->defuse = 0;
- m2->specular = 0.5;
- m2->shine = 50;
+ m2->specular = 0.1;
+ m2->shine = 1;
m2->reflective = 1;
material_t *mpl = add_material(cont);
@@ -99,18 +115,18 @@ int main()
object_t *o;
o = add_object(cont, TYPE_SPHERE);
- vector_set(&o->sph.center, -2, 7, 1);
- o->sph.radius = 1.5;
+ vector_set(&o->sph.center, 2, 6, -1);
+ o->sph.radius = 1;
o->m = m2;
o = add_object(cont, TYPE_SPHERE);
- vector_set(&o->sph.center, 0, 3, 1);
- o->sph.radius = 1;
+ vector_set(&o->sph.center, 0, 4, -1);
+ o->sph.radius = 1.3;
o->m = m;
o = add_object(cont, TYPE_SPHERE);
- vector_set(&o->sph.center, 2, 4, 1);
- o->sph.radius = 1;
+ vector_set(&o->sph.center, -2, 5, -2);
+ o->sph.radius = 1.3;
o->m = m;
o = add_object(cont, TYPE_PLANE);
@@ -145,15 +161,15 @@ int main()
// Used for the light ball
o = add_object(cont, TYPE_SPHERE);
- vector_set(&o->sph.center, 2, 7, 0);
- o->sph.radius = 1;
+ vector_set(&o->sph.center, 0, 7, 0);
+ o->sph.radius = 0.5;
o->m = ml;
light_t *l = add_light(cont, TYPE_L_AREA);
//vector_set(&l->point.pos, 2, 8, -1);
l->area = o;
color_set(&l->color, 1, 1, 1);
- l->radiance = 0.8;
+ l->radiance = 0.1;
pgm_write_header(stdout, TESTW, TESTH);
@@ -214,7 +230,7 @@ void *worker_func(void *arg) {
color_t *c = &office->image[ y * TESTW + x ];
//color_t c;
seed = x * y;
- ray_trace(&cont->space, TESTW - x, TESTH - y, 2, c, &seed);
+ ray_trace(&cont->space, TESTW - x, TESTH - y, c, &seed);
color_clamp(c);
}
diff --git a/ray.c b/ray.c
index c445530..e2789ca 100644
--- a/ray.c
+++ b/ray.c
@@ -9,6 +9,8 @@
#define PI 3.14159265359
+int ray_trace_recur(space_t *s, color_t *dest, ray_t *ray, unsigned hop, COORD_T scale, void *seed);
+
// https://en.wikipedia.org/wiki/Line%E2%80%93sphere_intersection
// http://viclw17.github.io/2018/07/16/raytracing-ray-sphere-intersection/
// https://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-sphere-intersection
@@ -212,7 +214,7 @@ static void contribution_from_arealight(space_t *s, color_t *dest, object_t *o,
// Do the same monte carlo as with environment but the starting point is the center of the circle.
// And the result is a point on the circle
- for (int i = 0; i < 16; i++) {
+ for (int i = 0; i < s->gfx->arealight_samples; i++) {
// Do the monte carlo random distribution thing from the article
COORD_T r1 = ray_rand(seed);
@@ -245,7 +247,7 @@ static void contribution_from_arealight(space_t *s, color_t *dest, object_t *o,
}
// Device by pdf
- color_scale(&c, &c, ((COORD_T) 1 / 16) * (2 * PI));
+ color_scale(&c, &c, ((COORD_T) 1 / s->gfx->arealight_samples) * (2 * PI));
color_add(dest, dest, &c);
@@ -281,6 +283,9 @@ static void direct_light(space_t *s, color_t *dest, object_t *o, vector_t *N, ve
// https://www.scratchapixel.com/lessons/3d-basic-rendering/global-illumination-path-tracing/global-illumination-path-tracing-practical-implementation
static void env_light(space_t *s, color_t *dest, object_t *o, vector_t *N, vector_t *point, void *seed)
{
+ if (s->gfx->envlight_samples == 0) {
+ return;
+ }
csystem_t cs;
csystem_init(&cs, N);
@@ -292,7 +297,7 @@ static void env_light(space_t *s, color_t *dest, object_t *o, vector_t *N, vecto
color_t acc;
color_set(&acc, 0, 0, 0);
- for (unsigned i = 0; i < s->env_samples; i++) {
+ for (unsigned i = 0; i < s->gfx->envlight_samples; i++) {
COORD_T r1 = ray_rand(seed);
// Calculate the random direction vector
@@ -318,13 +323,58 @@ static void env_light(space_t *s, color_t *dest, object_t *o, vector_t *N, vecto
}
// Devide by number of samples and pdf
- color_scale(&acc, &acc, ((COORD_T) 1/ s->env_samples) * (2 * PI));
+ color_scale(&acc, &acc, ((COORD_T) 1/ s->gfx->envlight_samples) * (2 * PI));
// Add to dest
color_add(dest, dest, &acc);
}
+// https://www.scratchapixel.com/lessons/3d-basic-rendering/global-illumination-path-tracing/global-illumination-path-tracing-practical-implementation
+static void global_light(space_t *s, color_t *dest, object_t *o, vector_t *N, vector_t *point, unsigned hop, void *seed)
+{
+ if (s->gfx->globallight_samples == 0) {
+ return;
+ }
+
+ // Init hemisphere translation
+ csystem_t cs;
+ csystem_init(&cs, N);
+
+ // Prepare ray
+ ray_t r;
+ r.start = point;
+
+ // Value for accumilating colors
+ color_t acc;
+ color_set(&acc, 0, 0, 0);
+
+ for (unsigned i = 0; i < s->gfx->globallight_samples; i++) {
+ COORD_T r1 = ray_rand(seed);
+
+ // Calculate the random direction vector
+ vector_t randdir;
+ csystem_hemisphere_random(&cs, r1, ray_rand(seed), &randdir);
+
+ // Convert to world cordinates using the calculated N vectors.
+ csystem_calc_real(&cs, &randdir, &randdir);
+
+ // Check the direction for obstacles
+ r.direction = &randdir;
+
+ // Cast ray in direction if we have more hops
+ if (hop < s->gfx->depth) {
+ ray_trace_recur(s, &acc, &r, hop+1, r1, seed);
+ }
+ }
+
+ // Devide by number of samples and pdf
+ color_scale(&acc, &acc, ((COORD_T) 1/ s->gfx->globallight_samples) * (2 * PI));
+
+ // Add to dest
+ color_add(dest, dest, &acc);
+}
+
int ray_trace_recur(space_t *s, color_t *dest, ray_t *ray, unsigned hop, COORD_T scale, void *seed)
{
COORD_T dist;
@@ -359,10 +409,12 @@ int ray_trace_recur(space_t *s, color_t *dest, ray_t *ray, unsigned hop, COORD_T
}
// Calculate environmental light
- if (s->env_samples) {
+ if (s->env_enabled) {
env_light(s, &c, o, &N, r.start, seed);
}
+ global_light(s, &c, o, &N, r.start, hop, seed);
+
// Calculate reflection vector
if (hop < 10 && o->m->reflective > ZERO_APROX) {
vector_scale(r.direction, &N, 2 * vector_dot(ray->direction, &N));
@@ -383,7 +435,7 @@ exit:
return 0;
}
-void ray_trace(space_t *s, unsigned int x, unsigned int y, unsigned samples, color_t *c, void *seed)
+void ray_trace(space_t *s, unsigned int x, unsigned int y, color_t *c, void *seed)
{
// Init return color. Will be accumilated with all the detected light.
color_set(c, 0, 0, 0);
@@ -397,13 +449,13 @@ void ray_trace(space_t *s, unsigned int x, unsigned int y, unsigned samples, col
// Multiple samples for antialias
// TODO better distribution of antialias probes
- for (int i = 0; i < samples; i++) {
+ for (int i = 0; i < s->gfx->antialias_samples; i++) {
color_t ctmp;
color_set(&ctmp, 0, 0, 0);
//memset(&ctmp, 0, sizeof(color_t));
// Multiple samples inside same pixel
- COORD_T tmp = (COORD_T) i/ (COORD_T) samples;
+ COORD_T tmp = (COORD_T) i/ (COORD_T) s->gfx->antialias_samples;
viewpoint_ray(&s->view, r.direction, x + tmp, y + tmp);
// Run the recursive ray trace
@@ -415,9 +467,9 @@ void ray_trace(space_t *s, unsigned int x, unsigned int y, unsigned samples, col
}
// Take the median
- if (samples > 1) {
+ if (s->gfx->antialias_samples > 1) {
// Same as deviding by samples
- color_scale(c, c, 1.0/ (COORD_T) samples);
+ color_scale(c, c, 1.0/ (COORD_T) s->gfx->antialias_samples);
}
// Add ambient
diff --git a/ray.h b/ray.h
index 085b661..124311a 100644
--- a/ray.h
+++ b/ray.h
@@ -20,6 +20,6 @@ COORD_T ray_intersect_sphere(sphere_t *s, ray_t *ray, bool skip_dist);
COORD_T ray_intersect_plane(plane_t *p, ray_t *ray, bool skip_dist);
object_t *ray_cast(space_t *s, ray_t *r, COORD_T *dist_ret, bool chk, COORD_T chk_dist);
-void ray_trace(space_t *s, unsigned int x, unsigned int y, unsigned samples, color_t *c, void *seed);
+void ray_trace(space_t *s, unsigned int x, unsigned int y, color_t *c, void *seed);
#endif
diff --git a/scene.h b/scene.h
index cbaaf3a..738f143 100644
--- a/scene.h
+++ b/scene.h
@@ -71,6 +71,17 @@ typedef struct light_s{
light_t l;
+// Graphics settings
+// Should actually sit in ray.c
+typedef struct {
+ unsigned arealight_samples;
+ unsigned antialias_samples;
+ unsigned envlight_samples;
+ unsigned globallight_samples;
+
+ unsigned depth;
+} settings_t;
+
typedef struct {
viewpoint_t view;
@@ -80,10 +91,11 @@ typedef struct {
color_t ambient;
color_t back;
+ settings_t *gfx;
// Environment light
// TODO make more general
// Slows things down alot
- unsigned env_samples;
+ bool env_enabled;
color_t env_color;
} space_t;