diff options
Diffstat (limited to 'kon/konsofren.h')
| -rw-r--r-- | kon/konsofren.h | 36 |
1 files changed, 24 insertions, 12 deletions
diff --git a/kon/konsofren.h b/kon/konsofren.h index 2c396b1..498c79b 100644 --- a/kon/konsofren.h +++ b/kon/konsofren.h @@ -1105,15 +1105,19 @@ static double kon_lightFactor_(const kon_light_t *light, kon_vec3_t toLight, kon } static uint32_t kon_applyLight_(uint32_t color, double factor, const double rgb[3]) { - uint32_t out = color & 0xFF000000u; + uint32_t mr = (uint32_t)(rgb[0] * factor * 65536.0 + 0.5); + uint32_t mg = (uint32_t)(rgb[1] * factor * 65536.0 + 0.5); + uint32_t mb = (uint32_t)(rgb[2] * factor * 65536.0 + 0.5); - for (int i = 0; i < 3; i++) { - int shift = 16 - i * 8; - double channel = (double)((color >> shift) & 0xFF) * rgb[i] * factor; - out |= (channel >= 255.0 ? 255u : (uint32_t)(channel + 0.5)) << shift; - } + uint32_t r = (((color >> 16) & 0xFF) * mr + 32768) >> 16; + uint32_t g = (((color >> 8) & 0xFF) * mg + 32768) >> 16; + uint32_t b = ((color & 0xFF) * mb + 32768) >> 16; + + if (r > 255) r = 255; + if (g > 255) g = 255; + if (b > 255) b = 255; - return out; + return (color & 0xFF000000u) | (r << 16) | (g << 8) | b; } /* the triangle rasterizer works in doubles so huge coordinates near the camera don't lose precision */ @@ -1156,6 +1160,12 @@ static double kon_edge_(double ax, double ay, double bx, double by, double px, d return (bx - ax) * (py - ay) - (by - ay) * (px - ax); } +/* x - floor(x) without a call to floor, which is not a single instruction without SSE4 */ +static inline double kon_fraction_(double x) { + x -= (double)(long long)x; + return x < 0.0 ? x + 1.0 : x; +} + static void kon_rasterizeTriangle_(kon_framebuffer_t *fb, const kon_rasterVertex_t *a, const kon_rasterVertex_t *b, const kon_rasterVertex_t *c, const kon_material_t *material, const kon_light_t *light, kon_renderFlags_t flags) { const kon_rasterVertex_t *in[3] = {a, b, c}; @@ -1243,13 +1253,15 @@ static void kon_rasterizeTriangle_(kon_framebuffer_t *fb, const kon_rasterVertex uint32_t texel = material->color; double iw = l0 * invW[0] + l1 * invW[1] + l2 * invW[2]; + double w = 1.0 / iw; + if (texture) { /* uv / w is what varies linearly on screen, dividing by 1 / w again undoes the perspective */ - double u = (l0 * uw[0] + l1 * uw[1] + l2 * uw[2]) / iw; - double v = (l0 * vw[0] + l1 * vw[1] + l2 * vw[2]) / iw; + double u = (l0 * uw[0] + l1 * uw[1] + l2 * uw[2]) * w; + double v = (l0 * vw[0] + l1 * vw[1] + l2 * vw[2]) * w; - u -= floor(u); - v -= floor(v); + u = kon_fraction_(u); + v = kon_fraction_(v); if (material->filter == KON_FILTER_LINEAR) { texel = kon_sampleLinear_(texture, KON_RECT(0, 0, texture->width, texture->height), @@ -1265,7 +1277,7 @@ static void kon_rasterizeTriangle_(kon_framebuffer_t *fb, const kon_rasterVertex } if (light) { - texel = kon_applyLight_(texel, (l0 * lw[0] + l1 * lw[1] + l2 * lw[2]) / iw, lightRgb); + texel = kon_applyLight_(texel, (l0 * lw[0] + l1 * lw[1] + l2 * lw[2]) * w, lightRgb); } uint32_t alpha = texel >> 24; |
