summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonAki <konaki@anokonaki.org>2026-10-10 18:49:02 +0800
committerKonAki <konaki@anokonaki.org>2026-10-10 18:49:02 +0800
commitcbcbb4b69d07c7c80264838e427e699b38208313 (patch)
treeb6b31897cd869950c46f267f9df946fb1394b43a
parentc47f1364a24b40477d97e64fd41040cbcb4bdd9e (diff)
konsofren: cheaper per-pixel lighting
-rw-r--r--kon/konsofren.h36
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;