X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Frasterize;a=blobdiff_plain;f=raster.c;h=b4f466fcb0504dfc9b69a7a32e8770e7b01f1b93;hp=23b1d69d19f5f0f855ec843ff4532ee379ed6fa7;hb=95850b98f73ad7033af60a30e324e9c3cda55389;hpb=c875478cdd823c7df8fdc859941bd9e5948c9315 diff --git a/raster.c b/raster.c index 23b1d69..b4f466f 100644 --- a/raster.c +++ b/raster.c @@ -30,14 +30,13 @@ struct raster 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 }; @@ -57,10 +56,12 @@ raster_t* raster_alloc(int width, int height, color_t fill) 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); @@ -73,13 +74,16 @@ void raster_destroy(raster_t* p) { 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" @@ -96,7 +100,7 @@ void raster_clear(raster_t* p, color_t fill) 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; @@ -139,15 +143,29 @@ void raster_eye(raster_t* p, vec_t eye) #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 @@ -240,6 +258,32 @@ fail: fprintf(stderr, "Cannot write to %s: %s\n", filename, strerror(errno)); #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. @@ -286,38 +330,29 @@ bool _try_cull_backface(tri_t t) * 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; + color.a = vert.c.a; 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; @@ -356,17 +391,31 @@ void raster_draw_tri(raster_t* p, const tri_t* triangle) 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)); -#endif -#if !SMOOTH_COLOR - temp.a.c = tri_color(temp); +#if LIGHTING >= 1 + tri_t tl = tri_transform(*triangle, p->model); #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) { @@ -380,11 +429,27 @@ void raster_draw_tri(raster_t* p, const tri_t* triangle) if (S(-1.0) < v.z && v.z < *n) { #endif color_t* c = p->pixels + y * p->w + x; -#if SMOOTH_COLOR - *c = color_interp2(color1, color2, color3, b); + color_t newC; + +#if LIGHTING == 2 || (!LIGHTING && SMOOTH_COLOR) + newC = color_interp2(color1, color2, color3, b); +#elif LIGHTING == 3 && SMOOTH_COLOR + newC = _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); + newC = _do_phong_lighting(p, d); #else - *c = color1; + newC = color; #endif + +#if BLENDING + *c = color_blend(*c, newC); +#else + *c = newC; +#endif + #if DEPTH_TEST *n = v.z; }