From 399df0323dcd1cafe860565fd82598321aff52ee Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Tue, 22 Dec 2020 03:41:22 +0200 Subject: [PATCH] foo --- liberebus/src/erebus.c | 89 +++++++++++++++++++++++++++++++++++++++++++-- liberebus/src/erebus.h | 27 ++++++++++---- liberebus/src/surf.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++- liberebus/src/util.c | 8 +++-- 4 files changed, 205 insertions(+), 12 deletions(-) diff --git a/liberebus/src/erebus.c b/liberebus/src/erebus.c index da07635..af2b2d9 100644 --- a/liberebus/src/erebus.c +++ b/liberebus/src/erebus.c @@ -1,10 +1,95 @@ +#include #include "erebus.h" -int erb_init(void) +struct erb_rend { + int fb_width, fb_height, fb_npix; + float *fb_pixels; + int *fb_nsamples; +}; + +struct erb_rend *erb_create(void) +{ + struct erb_rend *erb; + + if(!(erb = calloc(1, sizeof *erb))) { + return 0; + } + return erb; +} + +void erb_destroy(struct erb_rend *erb) { + if(!erb) return; + free(erb->fb_pixels); + free(erb); +} + +int erb_allocframe(struct erb_rend *erb, int width, int height) +{ + float *newfb; + int *newns; + int npix; + + if(width == erb->fb_width && height == erb->fb_height) { + return 0; + } + + npix = width * height; + + if(!(newfb = malloc(npix * 3 * sizeof *erb->fb_pixels))) { + goto err; + } + if(!(newns = malloc(npix * sizeof *erb->fb_nsamples))) { + free(newfb); + goto err; + } + + free(erb->fb_pixels); + free(erb->fb_nsamples); + + erb->fb_pixels = newfb; + erb->fb_nsamples = newns; + erb->fb_width = width; + erb->fb_height = height; + erb->fb_npix = npix; return 0; + +err: + fprintf(stderr, "erb_allocframe: failed to allocate %dx%d framebuffer\n", width, height); + return -1; +} + +float *erb_getframe(struct erb_rend *erb) +{ + return erb->fb_pixels; } -void erb_cleanup(void) +void erb_begin(struct erb_rend *erb) { + memset(erb->fb_pixels, 0, erb->fb_npix * 3 * sizeof *erb->fb_pixels); + memset(erb->fb_nsamples, 0, erb->fb_npix * sizeof *erb->fb_nsamples); +} + +float *erb_end(struct erb_rend *erb) +{ + int i, n; + float s; + float *pptr = erb->fb_pixels; + int *nptr = erb->fb_nsamples; + + for(i=0; ifb_npix; i++) { + n = *nptr; + if(n > 1) { + s = 1.0f / n; + *pptr++ *= s; + *pptr++ *= s; + *pptr++ *= s; + *nptr++ = 1; + } else { + pptr += 3; + nptr++; + } + } + + return erb->fb_pixels; } diff --git a/liberebus/src/erebus.h b/liberebus/src/erebus.h index 6ec33e3..fcb097b 100644 --- a/liberebus/src/erebus.h +++ b/liberebus/src/erebus.h @@ -3,6 +3,7 @@ #include +struct erb_rend; struct erb_node; struct erb_surf; struct erb_ray; @@ -10,6 +11,7 @@ struct erb_hit; struct erb_aabb; typedef int (*erb_intersect_func)(struct erb_surf *surf, struct erb_ray *ray, struct erb_hit *hit); +typedef void (*erb_hitgeom_func)(struct erb_surf *surf, struct erb_hit *hit); typedef void (*erb_sample_func)(struct erb_surf *surf, cgm_vec3 *pos); typedef void (*erb_bbox_func)(struct erb_surf *surf, struct erb_aabb *bb); @@ -32,6 +34,7 @@ struct erb_surf { int bbox_valid; erb_intersect_func isect; /* intersection routine */ + erb_hitgeom_func hitgeom; /* calculate derived values of the erb_hit structure */ erb_sample_func sample; /* random sample generation */ erb_bbox_func calc_bbox; /* bounds calculation */ @@ -47,11 +50,25 @@ struct erb_ray { struct erb_hit { float t, err; + cgm_vec3 pos, lpos; /* global and local space hit positions */ struct erb_surf *surf; + float total_dist; + + /* derived by calc_hit */ + cgm_vec3 norm, tang; + float u, v; }; -int erb_init(void); -void erb_cleanup(void); +struct erb_rend *erb_create(void); +void erb_destroy(struct erb_rend *erb); + +int erb_allocframe(struct erb_rend *erb, int width, int height); +float *erb_getframe(struct erb_rend *erb); + +/* clears the framebuffer and sample counters to begin rendering a new frame */ +void erb_begin(struct erb_rend *erb); +/* finalizes the frame, averaging samples (optional) */ +float *erb_end(struct erb_rend *erb); /* transformation nodes */ struct erb_node *erb_node(void); @@ -61,10 +78,8 @@ int erb_node_rmchild(struct erb_node *n, struct erb_node *c); int erb_node_addsurf(struct erb_node *n, struct erb_surf *s); int erb_node_rmsurf(struct erb_node *n, struct erb_surf *s); +/* sets the transformation matrix and also calculates the inverse */ void erb_node_setxform(struct erb_node *n, float *mat); -void erb_node_mulxform(struct erb_node *n, float *mat); -void erb_node_translate(struct erb_node *n, float x, float y, float z); -/* TODO ... more ... */ /* surfaces */ struct erb_surf *erb_surface(int datasz); @@ -73,6 +88,6 @@ struct erb_surf *erb_surf_sphere(float rad); struct erb_surf *erb_surf_box(float xsz, float ysz, float zsz); /* utility functions */ -void erb_xform_ray(struct erb_ray *ray, float *mat); +void erb_xform_ray(struct erb_ray *inray, float *mat, cgm_vec3 *org, cgm_vec3 *dir); #endif /* RENDLIB_H_ */ diff --git a/liberebus/src/surf.c b/liberebus/src/surf.c index 7d8d38a..8f2d4db 100644 --- a/liberebus/src/surf.c +++ b/liberebus/src/surf.c @@ -9,14 +9,17 @@ struct box_data { }; static int null_isect(struct erb_surf *surf, struct erb_ray *ray, struct erb_hit *hit); +static void null_hitgeom(struct erb_surf *surf, struct erb_hit *hit); static void null_sample(struct erb_surf *surf, cgm_vec3 *pos); static void null_bbox(struct erb_surf *surf, struct erb_aabb *bb); static int sph_isect(struct erb_surf *surf, struct erb_ray *ray, struct erb_hit *hit); +static void sph_hitgeom(struct erb_surf *surf, struct erb_hit *hit); static void sph_sample(struct erb_surf *surf, cgm_vec3 *pos); static void sph_bbox(struct erb_surf *surf, struct erb_aabb *bb); static int box_isect(struct erb_surf *surf, struct erb_ray *ray, struct erb_hit *hit); +static void box_hitgeom(struct erb_surf *surf, struct erb_hit *hit); static void box_sample(struct erb_surf *surf, cgm_vec3 *pos); static void box_bbox(struct erb_surf *surf, struct erb_aabb *bb); @@ -30,6 +33,7 @@ struct erb_surf *erb_surface(int datasz) return 0; } surf->isect = null_isect; + surf->hitgeom = null_hitgeom; surf->sample = null_sample; surf->calc_bbox = null_bbox; return surf; @@ -52,6 +56,7 @@ struct erb_surf *erb_surf_sphere(float rad) return 0; } surf->isect = sph_isect; + surf->hitgeom = sph_hitgeom; surf->sample = sph_sample; surf->calc_bbox = sph_bbox; sdata = (struct sph_data*)surf->data; @@ -68,6 +73,7 @@ struct erb_surf *erb_surf_box(float xsz, float ysz, float zsz) return 0; } surf->isect = box_isect; + surf->hitgeom = box_hitgeom; surf->sample = box_sample; surf->calc_bbox = box_bbox; bdata = (struct box_data*)surf->data; @@ -81,6 +87,11 @@ static int null_isect(struct erb_surf *surf, struct erb_ray *ray, struct erb_hit return 0; } +static void null_hitgeom(struct erb_surf *surf, struct erb_hit *hit) +{ + fprintf(stderr, "BUG: null_hitgeom called\n"); +} + static void null_sample(struct erb_surf *surf, cgm_vec3 *pos) { pos->x = pos->y = pos->z = 0; @@ -94,22 +105,102 @@ static void null_bbox(struct erb_surf *surf, struct erb_aabb *bb) static int sph_isect(struct erb_surf *surf, struct erb_ray *ray, struct erb_hit *hit) { - return 0; + float a, b, c, d, sqrt_d, q, t, t0, t1; + cgm_vec3 org, dir; + struct sph_data *sdata = (struct sph_data*)surf->data; + + if(surf->node) { + erb_xform_ray(ray, surf->node->inv_xform, &org, &dir); + } else { + org = ray->o; + dir = ray->d; + } + + a = cgm_vdot(&dir, &dir); + b = 2.0f * cgm_vdot(&org, &dir); + c = cgm_vdot(&org, &org) - sdata->rad * sdata->rad; + + d = b * b - 4.0f * a * c; + if(d <= 0.0f) return 0; + + sqrt_d = sqrt(d); + q = b < 0.0f ? -0.5f * (b - sqrt_d) : -0.5f * (b + sqrt_d); + + t0 = q / a; + t1 = c / q; + if(t1 < t0) { + float ttmp = t0; + t0 = t1; + t1 = ttmp; + } + + if(t0 > ray->tmax || t1 < ray->tmin) { + return 0; + } + t = t0 < ray->tmin ? t1 : t0; + if(t > ray->tmax) { + return 0; + } + + if(hit) { + hit->t = t; + hit->err = 5e-4f * t; /* PBR 3.2.6 */ + hit->surf = surf; + hit->pos = ray->o; + cgm_vadd_scaled(&hit->pos, &ray->d, t); + hit->lpos = org; + cgm_vadd_scaled(&hit->lpos, &dir, t); + hit->total_dist = ray->total_dist + t; + } + + return 1; +} + +static void sph_hitgeom(struct erb_surf *surf, struct erb_hit *hit) +{ + float theta, phi; + + hit->norm = hit->lpos; + cgm_vnormalize(&hit->norm); + + cgm_uvec_to_sph(&theta, &phi, &hit->norm); + + hit->u = (theta + M_PI) / (2.0 * M_PI); + hit->v = phi / M_PI; + + hit->tang.x = hit->norm.z; + hit->tang.y = hit->norm.y; + hit->tang.z = -hit->norm.x; + + if(surf->node) { + cgm_vmul_m3v3(&hit->norm, surf->node->xform); + cgm_vmul_m3v3(&hit->tang, surf->node->xform); + } } static void sph_sample(struct erb_surf *surf, cgm_vec3 *pos) { + /* TODO */ } static void sph_bbox(struct erb_surf *surf, struct erb_aabb *bb) { + struct sph_data *sdata = (struct sph_data*)surf->data; + + cgm_vcons(&bb->pos, 0, 0, 0); + bb->sz.x = bb->sz.y = bb->sz.z = sdata->rad; } +/* TODO boxen */ static int box_isect(struct erb_surf *surf, struct erb_ray *ray, struct erb_hit *hit) { return 0; } +static void box_hitgeom(struct erb_surf *surf, struct erb_hit *hit) +{ +} + static void box_sample(struct erb_surf *surf, cgm_vec3 *pos) { } diff --git a/liberebus/src/util.c b/liberebus/src/util.c index a52f35a..dc0eb98 100644 --- a/liberebus/src/util.c +++ b/liberebus/src/util.c @@ -1,7 +1,9 @@ #include "erebus.h" -void erb_xform_ray(struct erb_ray *ray, float *mat) +void erb_xform_ray(struct erb_ray *ray, float *mat, cgm_vec3 *org, cgm_vec3 *dir) { - cgm_vmul_m4v3(&ray->o, mat); - cgm_vmul_m3v3(&ray->d, mat); + *org = ray->o; + *dir = ray->d; + cgm_vmul_m4v3(org, mat); + cgm_vmul_m3v3(dir, mat); } -- 1.7.10.4