commit b5af32e2798ef3ebff4c9e262611a6c80bbcb0bd
parent 9e168f53175fd11c3b955e0b8cfa92e00b5ee5f7
Author: averagecoder <averagecoder@noreply.codeberg.org>
Date: Mon, 24 Aug 2026 20:22:42 +0300
fix: wrong culling when inside sphere
Diffstat:
| M | src/render.c | | | 160 | +++++++++++++++++++++++++++++++++++++++++++++---------------------------------- |
1 file changed, 91 insertions(+), 69 deletions(-)
diff --git a/src/render.c b/src/render.c
@@ -453,14 +453,14 @@ draw_triangle_band(const struct render_triangle *tri, int min_y_band, int max_y_
v1 = tri->v1;
v2 = tri->v2;
- min_y = (int)MIN(v0.y, MIN(v1.y, v2.y));
- max_y = (int)MAX(v0.y, MAX(v1.y, v2.y));
+ min_y = (int)floorf(MIN(v0.y, MIN(v1.y, v2.y)));
+ max_y = (int)ceilf(MAX(v0.y, MAX(v1.y, v2.y)));
if (max_y < min_y_band || min_y > max_y_band) {
return;
}
- min_x = (int)MIN(v0.x, MIN(v1.x, v2.x));
- max_x = (int)MAX(v0.x, MAX(v1.x, v2.x));
+ min_x = (int)floorf(MIN(v0.x, MIN(v1.x, v2.x)));
+ max_x = (int)ceilf(MAX(v0.x, MAX(v1.x, v2.x)));
if (min_x >= WIDTH || max_x < 0) {
return;
}
@@ -550,8 +550,8 @@ draw_triangle_band(const struct render_triangle *tri, int min_y_band, int max_y_
x_min = (x_long < x_short) ? x_long : x_short;
x_max = (x_long < x_short) ? x_short : x_long;
- row_min_x = (int)ceilf(x_min - 0.5f);
- row_max_x = (int)floorf(x_max - 0.5f);
+ row_min_x = (int)floorf(x_min);
+ row_max_x = (int)ceilf(x_max);
if (row_min_x < min_x) row_min_x = min_x;
if (row_max_x > max_x) row_max_x = max_x;
@@ -572,36 +572,39 @@ draw_triangle_band(const struct render_triangle *tri, int min_y_band, int max_y_
b = (row_w0 * v0.b + row_w1 * v1.b + row_w2 * v2.b) * 255.0f;
for (px = row_min_x; px <= row_max_x; px++) {
- idx = py * WIDTH + px;
- if (inv_w > g_sys->zbuffer[idx] && inv_w >= min_inv_w * 0.99f) {
- wf = 1.0f / inv_w;
- tx = (int)(u_w * wf * tw) & tw_mask;
- ty = (int)(v_w * wf * th) & th_mask;
- color = pixels[ty * tw + tx];
- tex_a = (color >> 24) & 0xFF;
- if (tex_a > 127) {
- ir = (int)r; if (ir > 255) ir = 255; else if (ir < 0) ir = 0;
- ig = (int)g_val; if (ig > 255) ig = 255; else if (ig < 0) ig = 0;
- ib = (int)b; if (ib > 255) ib = 255; else if (ib < 0) ib = 0;
-
- tex_r = ((color >> 16) & 0xFF) * ir >> 8;
- tex_g = ((color >> 8) & 0xFF) * ig >> 8;
- tex_b = (color & 0xFF) * ib >> 8;
+ if (row_w0 >= -1e-4f && row_w1 >= -1e-4f && row_w2 >= -1e-4f) {
+ idx = py * WIDTH + px;
+ if (inv_w >= g_sys->zbuffer[idx] - 1e-6f && inv_w >= min_inv_w * 0.99f) {
+ wf = 1.0f / inv_w;
+ tx = (int)(u_w * wf * tw) & tw_mask;
+ ty = (int)(v_w * wf * th) & th_mask;
+ color = pixels[ty * tw + tx];
+ tex_a = (color >> 24) & 0xFF;
+ if (tex_a > 127) {
+ ir = (int)r; if (ir > 255) ir = 255; else if (ir < 0) ir = 0;
+ ig = (int)g_val; if (ig > 255) ig = 255; else if (ig < 0) ig = 0;
+ ib = (int)b; if (ib > 255) ib = 255; else if (ib < 0) ib = 0;
+
+ tex_r = ((color >> 16) & 0xFF) * ir >> 8;
+ tex_g = ((color >> 8) & 0xFF) * ig >> 8;
+ tex_b = (color & 0xFF) * ib >> 8;
+
+ f = f_w * wf;
+ if (f > 0.001f) {
+ if (f > 1.0f) f = 1.0f;
+ inv_f = 1.0f - f;
+ tex_r = (uint32_t)(tex_r * inv_f + sky_r * f);
+ tex_g = (uint32_t)(tex_g * inv_f + sky_g * f);
+ tex_b = (uint32_t)(tex_b * inv_f + sky_b * f);
+ }
- f = f_w * wf;
- if (f > 0.001f) {
- if (f > 1.0f) f = 1.0f;
- inv_f = 1.0f - f;
- tex_r = (uint32_t)(tex_r * inv_f + sky_r * f);
- tex_g = (uint32_t)(tex_g * inv_f + sky_g * f);
- tex_b = (uint32_t)(tex_b * inv_f + sky_b * f);
+ g_sys->pixels[idx] = (tex_a << 24) |
+ (tex_r << 16) | (tex_g << 8) | tex_b;
+ g_sys->zbuffer[idx] = inv_w;
}
-
- g_sys->pixels[idx] = (tex_a << 24) |
- (tex_r << 16) | (tex_g << 8) | tex_b;
- g_sys->zbuffer[idx] = inv_w;
}
}
+ row_w0 += dw0_dx; row_w1 += dw1_dx; row_w2 -= (dw0_dx + dw1_dx);
inv_w += d_inv_w_dx; u_w += d_u_w_dx; v_w += d_v_w_dx; f_w += d_f_w_dx;
r += d_r_dx_255; g_val += d_g_dx_255; b += d_b_dx_255;
}
@@ -628,8 +631,8 @@ draw_triangle_band(const struct render_triangle *tri, int min_y_band, int max_y_
x_min = (x_long < x_short) ? x_long : x_short;
x_max = (x_long < x_short) ? x_short : x_long;
- row_min_x = (int)ceilf(x_min - 0.5f);
- row_max_x = (int)floorf(x_max - 0.5f);
+ row_min_x = (int)floorf(x_min);
+ row_max_x = (int)ceilf(x_max);
if (row_min_x < min_x) row_min_x = min_x;
if (row_max_x > max_x) row_max_x = max_x;
@@ -643,44 +646,47 @@ draw_triangle_band(const struct render_triangle *tri, int min_y_band, int max_y_
inv_w = row_w0 * v0.w + row_w1 * v1.w + row_w2 * v2.w;
u_w = row_w0 * u0_w + row_w1 * u1_w + row_w2 * u2_w;
- v_w = row_w0 * v0_w + row_w1 * v1_w + row_w2 * v2.w;
+ v_w = row_w0 * v0_w + row_w1 * v1_w + row_w2 * v2_w;
f_w = row_w0 * f0_w + row_w1 * f1_w + row_w2 * f2_w;
r = (row_w0 * v0.r + row_w1 * v1.r + row_w2 * v2.r) * 255.0f;
g_val = (row_w0 * v0.g + row_w1 * v1.g + row_w2 * v2.g) * 255.0f;
b = (row_w0 * v0.b + row_w1 * v1.b + row_w2 * v2.b) * 255.0f;
for (px = row_min_x; px <= row_max_x; px++) {
- idx = py * WIDTH + px;
- if (inv_w > g_sys->zbuffer[idx] && inv_w >= min_inv_w * 0.99f) {
- ir = (int)r; if (ir > 255) ir = 255; else if (ir < 0) ir = 0;
- ig = (int)g_val; if (ig > 255) ig = 255; else if (ig < 0) ig = 0;
- ib = (int)b; if (ib > 255) ib = 255; else if (ib < 0) ib = 0;
- wf = 1.0f / inv_w;
-
- tx = (int)(u_w * wf * tw) & tw_mask;
- ty = (int)(v_w * wf * th) & th_mask;
- color = pixels[ty * tw + tx];
-
- wa = (wa_tc * ((color >> 24) & 0xFF)) >> 8;
- tex_r = ((((color >> 16) & 0xFF) * ir >> 8) * wr) >> 8;
- tex_g = ((((color >> 8) & 0xFF) * ig >> 8) * wg) >> 8;
- tex_b = ((color & 0xFF) * ib >> 8) * wb >> 8;
-
- f = f_w * wf;
- if (f > 0.001f) {
- if (f > 1.0f) f = 1.0f;
- inv_f = 1.0f - f;
- tex_r = (uint32_t)(tex_r * inv_f + sky_r * f);
- tex_g = (uint32_t)(tex_g * inv_f + sky_g * f);
- tex_b = (uint32_t)(tex_b * inv_f + sky_b * f);
- }
+ if (row_w0 >= -1e-4f && row_w1 >= -1e-4f && row_w2 >= -1e-4f) {
+ idx = py * WIDTH + px;
+ if (inv_w >= g_sys->zbuffer[idx] - 1e-6f && inv_w >= min_inv_w * 0.99f) {
+ ir = (int)r; if (ir > 255) ir = 255; else if (ir < 0) ir = 0;
+ ig = (int)g_val; if (ig > 255) ig = 255; else if (ig < 0) ig = 0;
+ ib = (int)b; if (ib > 255) ib = 255; else if (ib < 0) ib = 0;
+ wf = 1.0f / inv_w;
+
+ tx = (int)(u_w * wf * tw) & tw_mask;
+ ty = (int)(v_w * wf * th) & th_mask;
+ color = pixels[ty * tw + tx];
- bg = g_sys->pixels[idx];
- g_sys->pixels[idx] = (0xFF << 24) |
- (((tex_r * wa + ((bg >> 16) & 0xFF) * (255 - wa)) >> 8) << 16) |
- (((tex_g * wa + ((bg >> 8) & 0xFF) * (255 - wa)) >> 8) << 8) |
- ((tex_b * wa + (bg & 0xFF) * (255 - wa)) >> 8);
+ wa = (wa_tc * ((color >> 24) & 0xFF)) >> 8;
+ tex_r = ((((color >> 16) & 0xFF) * ir >> 8) * wr) >> 8;
+ tex_g = ((((color >> 8) & 0xFF) * ig >> 8) * wg) >> 8;
+ tex_b = ((color & 0xFF) * ib >> 8) * wb >> 8;
+
+ f = f_w * wf;
+ if (f > 0.001f) {
+ if (f > 1.0f) f = 1.0f;
+ inv_f = 1.0f - f;
+ tex_r = (uint32_t)(tex_r * inv_f + sky_r * f);
+ tex_g = (uint32_t)(tex_g * inv_f + sky_g * f);
+ tex_b = (uint32_t)(tex_b * inv_f + sky_b * f);
+ }
+
+ bg = g_sys->pixels[idx];
+ g_sys->pixels[idx] = (0xFF << 24) |
+ (((tex_r * wa + ((bg >> 16) & 0xFF) * (255 - wa)) >> 8) << 16) |
+ (((tex_g * wa + ((bg >> 8) & 0xFF) * (255 - wa)) >> 8) << 8) |
+ ((tex_b * wa + (bg & 0xFF) * (255 - wa)) >> 8);
+ }
}
+ row_w0 += dw0_dx; row_w1 += dw1_dx; row_w2 -= (dw0_dx + dw1_dx);
inv_w += d_inv_w_dx; u_w += d_u_w_dx; v_w += d_v_w_dx; f_w += d_f_w_dx;
r += d_r_dx_255; g_val += d_g_dx_255; b += d_b_dx_255;
}
@@ -2227,12 +2233,28 @@ draw_scene(struct sys_gfx *g, const struct mat4 *proj, const struct mat4 *view,
mc.y = g_transforms.sphere_cy[id];
mc.z = g_transforms.sphere_cz[id];
r = g_transforms.sphere_r[id] * 1.05f;
- mat_transform(&cv, &w, view, &mc);
- if (cv.z + r < 0.1f || cv.z - r > far_clp ||
- fabsf(cv.x) - r > cv.z * fov_x ||
- fabsf(cv.y) - r > cv.z * fov_y) {
- continue;
+
+ dx = mc.x - cam_x;
+ dy = mc.y - cam_y;
+ dz = mc.z - cam_z;
+ dist_sq = dx * dx + dy * dy + dz * dz;
+
+ if (dist_sq > r * r) {
+ mat_transform(&cv, &w, view, &mc);
+
+ if (cv.z + r < 0.1f || cv.z - r > far_clp) {
+ continue;
+ }
+ if (cv.z > 0.0f) {
+ if (fabsf(cv.x) - r > cv.z * fov_x ||
+ fabsf(cv.y) - r > cv.z * fov_y) {
+ continue;
+ }
+ }
+ } else {
+ mat_transform(&cv, &w, view, &mc);
}
+
if (is_occluded(g, cv.x, cv.y, cv.z, r)) {
continue;
}