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;
+}