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;
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;
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;
}
+#include <float.h>
#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;
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; i<ytiles; i++) {
+ x = 0;
+ for(j=0; j<xtiles; j++) {
+ tileptr->x = 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; i<num_tiles; i++) {
+ tpool_enqueue(tpool, tiles + i, (tpool_callback)render_tile, 0);
+ }
+ tpool_wait(tpool);
+}
+
+static void render_tile(struct tile *tile)
+{
int i, j;
cgm_ray ray;
- cgm_vec3 *fbptr = fb.pixels;
+ cgm_vec3 *fbptr = tile->fbptr;
- for(i=0; i<fb.height; i++) {
- for(j=0; j<fb.width; j++) {
- primary_ray(&ray, j, i, 0);
- ray_trace(fbptr, &ray);
- fbptr++;
+ for(i=0; i<tile->height; i++) {
+ for(j=0; j<tile->width; 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)