list_t* lights;
color_t ambient;
vec_t eye;
+ color_t specular;
+ scal_t shininess;
#endif
-#if RASTER_STATS
+#if VERBOSITY >= 2
unsigned total;
unsigned clipped;
unsigned culled;
-#define IF_RASTER_STATS(X) X
-#else
-#define IF_RASTER_STATS(X)
#endif
};
p->dirty = false;
#if LIGHTING
- p->ambient = color_new(S(0.05), S(0.05), S(0.05), S(1.0));
+ p->ambient = color_new(S(0.2), S(0.2), S(0.2), S(1.0));
p->lights = NULL;
+ p->specular = COLOR_WHITE;
+ p->shininess = S(1.0);
#endif
- /*= light_new(COLOR_WHITE, vec_new(S(-2.0), S(4.0), S(0.0)));*/
+
p->zbuf = (scal_t*)mem_alloc(sizeof(scal_t) * size);
for (size_t i = 0; i < size; ++i) {
p->zbuf[i] = S(1.0);
{
mem_free(p->pixels);
mem_free(p->zbuf);
+#if LIGHTING
+ list_destroy(&p->lights);
+#endif
mem_free(p);
}
void raster_printstats(raster_t* p)
{
-#if RASTER_STATS
+#if VERBOSITY >= 2
unsigned drawn = p->total - p->clipped - p->culled;
float percent = 100.0f * (float)drawn / (float)p->total;
printf("culled\t%u\n"
for (int i = 0; i < size; ++i) {
p->pixels[i] = fill;
}
-#if RASTER_STATS
+#if VERBOSITY >= 2
p->total = 0;
p->clipped = 0;
p->culled = 0;
#endif
}
+void raster_ambient(raster_t* p, color_t ambient)
+{
+#if LIGHTING
+ p->ambient = ambient;
+#endif
+}
+
void raster_light(raster_t* p, light_t light)
{
#if LIGHTING
- light_t* l = (light_t*)mem_alloc(sizeof(light_t));
- memcpy(l, &light, sizeof(light_t));
+ light_t* l = light_copy(light);
list_push2(&p->lights, l, mem_free);
#endif
}
+void raster_material(raster_t* p, color_t specular, scal_t shininess)
+{
+#if LIGHTING
+ p->specular = specular;
+ p->shininess = shininess;
+#endif
+}
+
#define _CHECK_WRITE(X) if ((X) <= 0) goto fail
#undef _CHECK_WRITE
+void raster_draw_model(raster_t* p, const model_t* model)
+{
+#if VERBOSITY >= 4
+#define PROGRESS_FMT "\033[80D\033[2K %s\t %9d / %d"
+ int tri;
+#endif
+
+ model_transformation(model, &p->model);
+ p->dirty = true;
+ raster_material(p, model_specular(model), model_shininess(model));
+ IF_RENDER_PROGRESS(tri = 0);
+ for (const list_t* ti = model_geometry(model); ti; ti = ti->link) {
+#if VERBOSITY >= 4
+ if (++tri % 100 == 0) {
+ printf(PROGRESS_FMT, model_name(model), tri, model_size(model));
+ fflush(stdout);
+ }
+#endif
+ raster_draw_tri(p, (tri_t*)ti->val);
+ }
+#if VERBOSITY >= 4
+ printf(PROGRESS_FMT"\n", model_name(model), tri, model_size(model));
+#endif
+}
+
+
/*
* See if the triangle is at all visible in the viewport. Also, minimize the
* rectangle around the area that includes the triangle.
* Determine what color is associated with the given vertex.
*/
INLINE_MAYBE
-color_t _get_vertex_color(raster_t* p, vert_t vert)
+color_t _do_phong_lighting(raster_t* p, vert_t vert)
{
#if LIGHTING
color_t color = COLOR_BLACK;
for (list_t* i = p->lights; i; i = i->link) {
light_t light = *(light_t*)i->val;
vec_t mpos = vert.v;
- vec_t lpos = light.position;
+ vec_t lpos = light.v;
vec_t vpos = p->eye;
vec_t n = vert.n;
vec_t l = vec_normalize(vec_sub(lpos, mpos));
- vec_t r = vec_sub(vec_scale(n, S(2.0) * vec_dot(n, l)), l);
+ vec_t r = vec_normalize(vec_sub(vec_scale(n, S(2.0) * vec_dot(n, l)), l));
vec_t v = vec_normalize(vec_sub(vpos, mpos));
scal_t kd = scal_max(vec_dot(l, n), S(0.0));
- color_t Id = color_new(
- light.color.r * vert.c.r * kd,
- light.color.g * vert.c.g * kd,
- light.color.b * vert.c.b * kd,
- S(1.0)
- );
- scal_t ks = scal_pow(scal_max(vec_dot(r, v), S(0.0)), S(64.0));
- color_t Is = color_new(
- light.color.r * COLOR_WHITE.r * ks,
- light.color.g * COLOR_WHITE.g * ks,
- light.color.b * COLOR_WHITE.b * ks,
- S(1.0)
- );
+ color_t Id = color_scale2(light.d, vert.c, kd);
+ scal_t ks = scal_pow(scal_max(vec_dot(r, v), S(0.0)), p->shininess);
+ color_t Is = color_scale2(light.s, p->specular, ks);
color = color_add2(color, Id, Is);
}
- color_t Ia = p->ambient;
+ color_t Ia = color_mult(p->ambient, vert.c);
return color_clamp(color_add(color, Ia));
#else
return vert.c;
return;
}
- tri_t temp = tri_transform(*triangle, p->model);
-#if LIGHTING && (!FIND_NORMALS || (!SMOOTH_COLOR && FIND_NORMALS == 2))
- temp.a.n = temp.b.n = temp.c.n = vec_normalize(tri_normal(temp));
+#if LIGHTING >= 1
+ tri_t tl = tri_transform(*triangle, p->model);
#endif
-#if !SMOOTH_COLOR
- temp.a.c = tri_color(temp);
-#endif
- color_t color1 = _get_vertex_color(p, temp.a);
-#if SMOOTH_COLOR
- color_t color2 = _get_vertex_color(p, temp.b);
- color_t color3 = _get_vertex_color(p, temp.c);
+
+#if LIGHTING == 1
+ vert_t tv = vert_new(tri_midpoint(tl));
+ tv.n = vec_normalize(tri_normal(tl));
+ tv.c = tri_color(tl);
+ color_t color = _do_phong_lighting(p, tv);
+#elif LIGHTING == 2 && SMOOTH_COLOR
+ color_t color1 = _do_phong_lighting(p, tl.a);
+ color_t color2 = _do_phong_lighting(p, tl.b);
+ color_t color3 = _do_phong_lighting(p, tl.c);
+#elif LIGHTING == 2 && !SMOOTH_COLOR
+ color_t c = tri_color(t);
+ tl.a.c = tl.b.c = tl.c.c = c;
+ color_t color1 = _do_phong_lighting(p, tl.a);
+ color_t color2 = _do_phong_lighting(p, tl.b);
+ color_t color3 = _do_phong_lighting(p, tl.c);
+#elif !LIGHTING && SMOOTH_COLOR
+ color_t color1 = t.a.c;
+ color_t color2 = t.b.c;
+ color_t color3 = t.c.c;
+#else
+ color_t color = tri_color(t);
#endif
for (int y = bottom; y < top; ++y) {
if (S(-1.0) < v.z && v.z < *n) {
#endif
color_t* c = p->pixels + y * p->w + x;
-#if SMOOTH_COLOR
+
+#if LIGHTING == 2 || (!LIGHTING && SMOOTH_COLOR)
*c = color_interp2(color1, color2, color3, b);
+#elif LIGHTING == 3 && SMOOTH_COLOR
+ *c = _do_phong_lighting(p, tri_interp(tl, b));
+#elif LIGHTING == 3 && !SMOOTH_COLOR
+ vert_t d = vert_new(tri_point(t, b));
+ d.c = tri_color(t);
+ d.n = tri_normal2(t, b);
+ *c = _do_phong_lighting(p, d);
#else
- *c = color1;
+ *c = color;
#endif
+
#if DEPTH_TEST
*n = v.z;
}