X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Frend.c;h=8547ca68a027752bded75b82d3e88849c18f811e;hb=3bf187fe037df34459f04bf4e625f38afb80fcf8;hp=09f7f97e21e36492cf11f3654e346519025aab4e;hpb=a8b3d0279566b8a49ea64d7e9e3dfa958364e347;p=retroray diff --git a/src/rend.c b/src/rend.c index 09f7f97..8547ca6 100644 --- a/src/rend.c +++ b/src/rend.c @@ -16,24 +16,38 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "rend.h" -#include "rt.h" +#include "app.h" +#include "geom.h" +#include "util.h" +#include "gfxutil.h" +#include "scene.h" + +static int calc_light(const struct rayhit *hit, const struct light *lt, + const cgm_vec3 *vdir, cgm_vec3 *dcol, cgm_vec3 *scol); struct img_pixmap renderbuf; -struct img_pixmap dbgimg; + +int max_ray_depth; +cgm_vec3 ambient; static int rx, ry, rwidth, rheight; static int roffs; static int xstep, ystep; +static int pan_x, pan_y; + +static struct light def_light = {0, {0, 0, 0}, {1, 1, 1}}; + int rend_init(void) { img_init(&renderbuf); - img_init(&dbgimg); - img_load(&dbgimg, "data/foo.jpg"); - img_convert(&dbgimg, IMG_FMT_RGBA32); + cgm_vcons(&ambient, 0.05, 0.05, 0.05); rx = ry = rwidth = rheight = roffs = 0; + pan_x = pan_y = 0; + + max_ray_depth = 6; return 0; } @@ -49,6 +63,12 @@ void rend_size(int xsz, int ysz) } } +void rend_pan(int xoffs, int yoffs) +{ + pan_x = xoffs; + pan_y = yoffs; +} + void rend_begin(int x, int y, int w, int h) { int i; @@ -91,20 +111,48 @@ static void fillrect(uint32_t *fb, int x, int y, int w, int h, uint32_t c) int render(uint32_t *fb) { - int i, j, offs; - uint32_t *src, *dest; + int i, j, w, h, offs, r, g, b; + uint32_t *dest, pcol; + cgm_vec3 color; + cgm_ray ray; - src = (uint32_t*)dbgimg.pixels + roffs; dest = (uint32_t*)renderbuf.pixels + roffs; - if(fb) fb += roffs; + if(fb) { + fb += roffs; + } + + if(xstep < 1) xstep = 1; + if(ystep < 1) ystep = 1; + + if(scn_num_lights(scn) == 0) { + primray(&ray, renderbuf.width / 2, renderbuf.height / 2); + def_light.pos = ray.origin; + } for(i=0; i rheight) h = rheight - i; + for(j=0; j 1.0f) color.x = 1.0f; + if(color.y > 1.0f) color.y = 1.0f; + if(color.z > 1.0f) color.z = 1.0f; + r = cround64(color.x * 255.0f); + g = cround64(color.y * 255.0f); + b = cround64(color.z * 255.0f); + pcol = PACK_RGB32(r, g, b); + offs = i * renderbuf.width + j; - dest[offs] = src[offs]; + dest[offs] = pcol; + if(fb) { - fb[offs] = src[offs]; - fillrect(fb, j, i, xstep, ystep, src[offs]); + w = xstep; + if(j + w > rwidth) w = rwidth - j; + + fillrect(fb, j, i, w, h, pcol); } } } @@ -117,3 +165,97 @@ int render(uint32_t *fb) } return 0; } + +int ray_trace(const cgm_ray *ray, int maxiter, cgm_vec3 *res) +{ + struct rayhit hit; + + if(!scn_intersect(scn, ray, &hit)) { + *res = bgcolor(ray); + return 0; + } + + *res = shade(ray, &hit, maxiter); + return 1; +} + +cgm_vec3 bgcolor(const cgm_ray *ray) +{ + return cgm_vvec(0, 0, 0); +} + +cgm_vec3 shade(const cgm_ray *ray, const struct rayhit *hit, int maxiter) +{ + int i, num_lights; + cgm_vec3 color, dcol, scol, texel, vdir; + struct material *mtl; + struct light *lt; + + dcol = ambient; + cgm_vcons(&scol, 0, 0, 0); + + mtl = hit->obj->mtl; + + vdir = ray->dir; + cgm_vneg(&vdir); + cgm_vnormalize(&vdir); + + if(!(num_lights = scn_num_lights(scn))) { + calc_light(hit, &def_light, &vdir, &dcol, &scol); + } + for(i=0; ilights[i]; + calc_light(hit, lt, &vdir, &dcol, &scol); + } + + if(mtl->texmap) { + texel = mtl->texmap->lookup(mtl->texmap, hit); + cgm_vmul(&dcol, &texel); + } + + color = dcol; + cgm_vadd(&color, &scol); + return color; +} + +static int calc_light(const struct rayhit *hit, const struct light *lt, + const cgm_vec3 *vdir, cgm_vec3 *dcol, cgm_vec3 *scol) +{ + float ndotl, ndoth, spec; + cgm_vec3 ldir, hdir; + cgm_ray ray; + struct material *mtl = hit->obj->mtl; + + ldir = lt->pos; + cgm_vsub(&ldir, &hit->pos); + + ray.origin = hit->pos; + ray.dir = ldir; + + if(scn_intersect(scn, &ray, 0)) { + return 0; /* in shadow */ + } + + cgm_vnormalize(&ldir); + + hdir = *vdir; + cgm_vadd(&hdir, &ldir); + cgm_vnormalize(&hdir); + + ndotl = cgm_vdot(&hit->norm, &ldir); + if(ndotl < 0.0f) ndotl = 0.0f; + ndoth = cgm_vdot(&hit->norm, &hdir); + if(ndoth < 0.0f) ndoth = 0.0f; + + spec = pow(ndoth, mtl->shin); + + dcol->x += mtl->kd.x * ndotl * lt->color.x; + dcol->y += mtl->kd.y * ndotl * lt->color.y; + dcol->z += mtl->kd.z * ndotl * lt->color.z; + + scol->x += mtl->ks.x * spec * lt->color.x; + scol->y += mtl->ks.y * spec * lt->color.y; + scol->z += mtl->ks.z * spec * lt->color.z; + + return 1; +}