From ee39e383f97259441df726c76cf26dcef7e9c054 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Mon, 21 Jun 2021 06:10:38 +0300 Subject: [PATCH] multithreaded render --- src/game.c | 3 ++ src/game.h | 8 ++++++ src/geom.c | 14 +++++++--- src/level.c | 23 ++++++++++++++++ src/main.c | 3 +- src/rt.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++-------- 6 files changed, 121 insertions(+), 18 deletions(-) create mode 100644 src/game.c create mode 100644 src/game.h diff --git a/src/game.c b/src/game.c new file mode 100644 index 0000000..b314e49 --- /dev/null +++ b/src/game.c @@ -0,0 +1,3 @@ +#include "game.h" + +struct level lvl; diff --git a/src/game.h b/src/game.h new file mode 100644 index 0000000..0e263bf --- /dev/null +++ b/src/game.h @@ -0,0 +1,8 @@ +#ifndef GAME_H_ +#define GAME_H_ + +#include "level.h" + +extern struct level lvl; + +#endif /* GAME_H_ */ diff --git a/src/geom.c b/src/geom.c index ba61e87..3751286 100644 --- a/src/geom.c +++ b/src/geom.c @@ -20,7 +20,7 @@ void free_bvh_tree(struct bvhnode *tree) int ray_triangle(cgm_ray *ray, struct triangle *tri, float tmax, struct rayhit *hit) { float t, ndotdir; - cgm_vec3 vdir, bc; + cgm_vec3 vdir, bc, pos; if(fabs(ndotdir = cgm_vdot(&ray->dir, &tri->norm)) <= 1e-6) { return 0; @@ -29,17 +29,23 @@ int ray_triangle(cgm_ray *ray, struct triangle *tri, float tmax, struct rayhit * vdir = tri->v[0].pos; cgm_vsub(&vdir, &ray->origin); - if((t = cgm_vdot(&ray->dir, &vdir) / ndotdir) <= 1e-6 || t > tmax) { + if((t = cgm_vdot(&tri->norm, &vdir) / ndotdir) <= 1e-6 || t > tmax) { return 0; } + cgm_raypos(&pos, ray, t); + cgm_bary(&bc, &tri->v[0].pos, &tri->v[1].pos, &tri->v[2].pos, &pos); + + if(bc.x < 0.0f || bc.x > 1.0f) return 0; + if(bc.y < 0.0f || bc.y > 1.0f) return 0; + if(bc.z < 0.0f || bc.z > 1.0f) return 0; + if(hit) { hit->t = t; hit->ray = *ray; hit->mtl = tri->mtl; - cgm_raypos(&hit->v.pos, ray, t); - cgm_bary(&bc, &tri->v[0].pos, &tri->v[1].pos, &tri->v[2].pos, &hit->v.pos); + hit->v.pos = pos; hit->v.norm.x = tri->v[0].norm.x * bc.x + tri->v[1].norm.x * bc.y + tri->v[2].norm.x * bc.z; hit->v.norm.y = tri->v[0].norm.y * bc.x + tri->v[1].norm.y * bc.y + tri->v[2].norm.y * bc.z; diff --git a/src/level.c b/src/level.c index 1bd1c19..fcdc405 100644 --- a/src/level.c +++ b/src/level.c @@ -86,6 +86,29 @@ void destroy_level(struct level *lvl) int ray_level(cgm_ray *ray, struct level *lvl, float tmax, struct rayhit *hit) { + int found = 0; + struct rayhit hit0; + + if(!hit) { + if(ray_bvhnode(ray, lvl->st_root, tmax, 0)) return 1; + if(ray_bvhnode(ray, lvl->dyn_root, tmax, 0)) return 1; + return 0; + } + + hit0.t = FLT_MAX; + if(ray_bvhnode(ray, lvl->st_root, tmax, hit)) { + hit0 = *hit; + found = 1; + } + if(ray_bvhnode(ray, lvl->dyn_root, tmax, hit) && hit->t < hit0.t) { + hit0 = *hit; + found = 1; + } + + if(found) { + *hit = hit0; + return 1; + } return 0; } diff --git a/src/main.c b/src/main.c index d49c311..d2240e0 100644 --- a/src/main.c +++ b/src/main.c @@ -3,6 +3,7 @@ #include #include #include "miniglut.h" +#include "game.h" #include "level.h" #include "rt.h" @@ -63,8 +64,6 @@ static int keymap[NUM_INPUTS][2] = { {' ', 0} }; -static struct level lvl; - static unsigned int tex; static int tex_width, tex_height; static int tex_intfmt; diff --git a/src/rt.c b/src/rt.c index 0ad8a7c..18b7f17 100644 --- a/src/rt.c +++ b/src/rt.c @@ -1,4 +1,14 @@ +#include #include "rt.h" +#include "game.h" + +#define TILESZ 32 + +struct tile { + int x, y, width, height; + int sample; + cgm_vec3 *fbptr; +}; struct framebuffer fb; struct thread_pool *tpool; @@ -6,48 +16,102 @@ float view_xform[16]; float vfov = M_PI / 4; static float aspect; +static struct tile *tiles; +static int num_tiles; +static void render_tile(struct tile *tile); static void ray_trace(cgm_vec3 *color, cgm_ray *ray); +static void bgcolor(cgm_vec3 *color, cgm_ray *ray); static void primary_ray(cgm_ray *ray, int x, int y, int sample); int fbsize(int width, int height) { - void *tmp; + int i, j, x, y, xtiles, ytiles; + cgm_vec3 *fbptr; + struct tile *tileptr; - if(!(tmp = malloc(width * height * sizeof *fb.pixels))) { + if(!(fbptr = malloc(width * height * sizeof *fb.pixels))) { + return -1; + } + xtiles = width / TILESZ; + ytiles = height / TILESZ; + if(!(tileptr = malloc(xtiles * ytiles * sizeof *tiles))) { + free(fbptr); return -1; } free(fb.pixels); - fb.pixels = tmp; + fb.pixels = fbptr; fb.width = width; fb.height = height; + free(tiles); + tiles = tileptr; + num_tiles = xtiles * ytiles; + aspect = (float)fb.width / (float)fb.height; + y = 0; + for(i=0; ix = x; + tileptr->y = y; + tileptr->width = width - x < TILESZ ? width - x : TILESZ; + tileptr->height = height - y < TILESZ ? height - y : TILESZ; + tileptr->fbptr = fbptr + x; + tileptr++; + + x += TILESZ; + } + fbptr += width * TILESZ; + y += TILESZ; + } + return 0; } void render(void) { + int i; + + for(i=0; ifbptr; - for(i=0; iheight; i++) { + for(j=0; jwidth; j++) { + primary_ray(&ray, tile->x + j, tile->y + i, tile->sample); + ray_trace(fbptr + j, &ray); } + fbptr += fb.width; } } static void ray_trace(cgm_vec3 *color, cgm_ray *ray) { - color->x = ray->dir.x * 0.5f + 0.5f; - color->y = ray->dir.y * 0.5f + 0.5f; - color->z = 0.0f; + struct rayhit hit; + + if(ray_level(ray, &lvl, FLT_MAX, &hit)) { + color->x = hit.v.norm.x * 0.5 + 0.5; + color->y = hit.v.norm.y * 0.5 + 0.5; + color->z = hit.v.norm.z * 0.5 + 0.5; + } else { + bgcolor(color, ray); + } +} + +static void bgcolor(cgm_vec3 *color, cgm_ray *ray) +{ + color->x = color->y = color->z = 1.0f; } static void primary_ray(cgm_ray *ray, int x, int y, int sample) -- 1.7.10.4