add flat & flat shading render

This commit is contained in:
Frater 2026-05-15 13:08:20 +02:00
commit 0d98a2077b
6 changed files with 139 additions and 2 deletions

View file

@ -1,5 +1,7 @@
# Moteur 3D DOS (TESTING)
**Version : 0.15**
## Vue d'ensemble
Moteur 3D software en C ciblant le DOS 32-bit via l'extender **CauseWay** (ou DOS/4GW).

View file

@ -1,5 +1,7 @@
# Moteur 3D DOS (TESTING)
**Version : 0.15**
## Vue d'ensemble
Moteur 3D software en C ciblant le DOS 32-bit via l'extender **CauseWay** (ou DOS/4GW).

View file

@ -12,6 +12,11 @@ int main(void) {
int anglex, angley, key, render, o;
fixed bx, by, bz, distance;
printf("Moteur 3D DOS (TESTING) - Version 0.15\n");
printf("Compile le %s a %s\n\n", __DATE__, __TIME__);
printf("Appuyez sur une touche pour demarrer le rendu...\n");
getch();
anglex = angley = key = 0;
render = MODE_SOLID;
distance = int_to_f(300);
@ -122,7 +127,9 @@ int main(void) {
switch (key) {
case 59: render = MODE_WIRE; break; /* F1 */
case 60: render = MODE_HIDDEN; break; /* F2 */
case 61: render = MODE_SOLID; break; /* F3 */
case 61: render = MODE_FLAT; break; /* F3 */
case 62: render = MODE_FLAT_SHADING; break; /* F4 */
case 63: render = MODE_SOLID; break; /* F5 */
case 71: distance -= int_to_f(10); break; /* Home : Rapprocher le centre */
case 79: distance += int_to_f(10); break; /* End : Eloigner le centre */
case 72: anglex = ((anglex - 3) % 360 + 360) % 360; break; /* Flèche Haut */

View file

@ -14,7 +14,9 @@
#define MODE_WIRE 0
#define MODE_HIDDEN 1
#define MODE_SOLID 2
#define MODE_FLAT 2
#define MODE_FLAT_SHADING 3
#define MODE_SOLID 4
#define SCREEN_W 320
#define SCREEN_H 200
@ -141,6 +143,7 @@ void flip(void);
void close_vga(void);
void fill_triangle_gouraud(Point2D *p1, Point2D *p2, Point2D *p3, uint8_t base_color);
void fill_triangle_flat(Point2D *p1, Point2D *p2, Point2D *p3, uint8_t color);
void draw_line_z(Point2D *p1, Point2D *p2, uint8_t col, int z_test);
void save_mesh(Mesh *m, const char *fn);

View file

@ -110,6 +110,9 @@ void render_universe(Universe *uni, Camera *cam, int mode) {
Object3D *obj;
Face *f;
Point2D *p1, *p2, *p3;
fixed avg_i;
int s;
uint8_t shade;
for (o = 0; o < uni->num_objects; o++) {
obj = &uni->objects[o];
@ -156,6 +159,33 @@ void render_universe(Universe *uni, Camera *cam, int mode) {
draw_line_z(p3, p1, wire_col, 1);
}
break;
case MODE_FLAT:
if (front) {
if (f->force_wire) {
draw_line_z(p1, p2, wire_col, 1);
draw_line_z(p2, p3, wire_col, 1);
draw_line_z(p3, p1, wire_col, 1);
} else {
fill_triangle_flat(p1, p2, p3, wire_col);
}
}
break;
case MODE_FLAT_SHADING:
if (front) {
if (f->force_wire) {
draw_line_z(p1, p2, wire_col, 1);
draw_line_z(p2, p3, wire_col, 1);
draw_line_z(p3, p1, wire_col, 1);
} else {
avg_i = (p1->intensity + p2->intensity + p3->intensity) / 3;
s = f_to_int(avg_i);
if (s < 0) shade = 0;
else if (s > 15) shade = 15;
else shade = (uint8_t)s;
fill_triangle_flat(p1, p2, p3, (uint8_t)((obj->color << 4) | shade));
}
}
break;
case MODE_SOLID:
default:
if (front) {

View file

@ -117,6 +117,99 @@ void fill_triangle_gouraud(Point2D *p1, Point2D *p2, Point2D *p3, uint8_t base_c
}
}
/* Rendu d'une scanline avec z-buffer (couleur unie) */
void scanline_flat_c(int width, uint8_t *dest, uint16_t *zbuf,
fixed z, fixed dz_step, uint8_t color) {
int i;
uint16_t zv;
for (i = 0; i < width; i++) {
zv = (uint16_t)(z >> 16);
if (zv < zbuf[i]) {
zbuf[i] = zv;
dest[i] = color;
}
z += dz_step;
}
}
void fill_triangle_flat(Point2D *p1, Point2D *p2, Point2D *p3, uint8_t color) {
int y, width, start_x, end_x, clip_x, w, second_half, total_height;
fixed dx13, dz13, xA, zA, xB, zB, dx12, dz12, dx23, dz23;
fixed cx1, cz1, cx2, cz2, tx, tz;
fixed dz_step, start_z;
uint8_t *dest;
uint16_t *zbuf;
/* Tri des points par ordonnée (Y) */
if (p1->y > p2->y) swap_pt(&p1, &p2);
if (p1->y > p3->y) swap_pt(&p1, &p3);
if (p2->y > p3->y) swap_pt(&p2, &p3);
total_height = p3->y - p1->y;
if (total_height == 0) return;
/* Gradients pour le côté long (p1 vers p3) */
dx13 = ((p3->x - p1->x) << 16) / total_height;
dz13 = (p3->z - p1->z) / total_height;
xA = int_to_f(p1->x); zA = p1->z;
if (p1->y == p2->y) {
xB = int_to_f(p2->x); zB = p2->z;
} else {
xB = xA; zB = zA;
}
/* Gradients pour les côtés courts */
dx12 = (p2->y > p1->y) ? ((p2->x - p1->x) << 16) / (p2->y - p1->y) : 0;
dz12 = (p2->y > p1->y) ? (p2->z - p1->z) / (p2->y - p1->y) : 0;
dx23 = (p3->y > p2->y) ? ((p3->x - p2->x) << 16) / (p3->y - p2->y) : 0;
dz23 = (p3->y > p2->y) ? (p3->z - p2->z) / (p3->y - p2->y) : 0;
for (y = p1->y; y < p3->y; y++) {
second_half = (y >= p2->y);
cx1 = xA; cz1 = zA;
cx2 = xB; cz2 = zB;
/* Tri horizontal */
if (cx1 > cx2) {
tx = cx1; cx1 = cx2; cx2 = tx;
tz = cz1; cz1 = cz2; cz2 = tz;
}
start_x = f_to_int(cx1);
end_x = f_to_int(cx2) + 1;
width = end_x - start_x;
if (y >= 0 && y < SCREEN_H && width > 0) {
dz_step = (cz2 - cz1) / width;
clip_x = (start_x < 0) ? 0 : start_x;
w = width - (clip_x - start_x);
if (clip_x + w > SCREEN_W) w = SCREEN_W - clip_x;
if (w > 0) {
start_z = cz1 + (clip_x - start_x) * dz_step;
dest = backbuffer + (y * SCREEN_W) + clip_x;
zbuf = zbuffer + (y * SCREEN_W) + clip_x;
scanline_flat_c(w, dest, zbuf, start_z, dz_step, color);
}
}
xA += dx13; zA += dz13;
if (!second_half) {
xB += dx12; zB += dz12;
} else {
if (y == p2->y) {
xB = int_to_f(p2->x); zB = p2->z;
}
xB += dx23; zB += dz23;
}
}
}
void draw_line_z(Point2D *p1, Point2D *p2, uint8_t col, int z_test) {
int dx, dy, sx, sy, err, steps, x, y, e2;
fixed z_step, cz;