This commit is contained in:
Frater 2026-05-09 21:53:45 +02:00
commit eae91de89d
8 changed files with 641 additions and 280 deletions

View file

@ -1,42 +1,101 @@
#define RASTER_H
uint8_t *backbuffer, *vga = (uint8_t*)0xA0000;
uint16_t *zbuffer;
#include "defines.h"
// Prototypes pour le compilateur C
extern void scanline_gouraud_asm(int width, uint8_t *dest, uint16_t *zbuf, int z, int dz_step, int intensity, int di_step);
extern void scanline_zonly_asm(int width, uint16_t *zbuf, int z, int dz_step);
// extern void scanline_gouraud_asm(int width, uint8_t *dest, uint16_t *zbuf, int z, int dz_step, int intensity, int di_step);
extern void scanline_zonly_asm(int width, uint16_t *zbuf, int z, int dz_step);
/*
#pragma aux scanline_gouraud_asm = \
"test ecx, ecx" "jz d" \
"l:" "mov ax, dx" "cmp ax, [esi]" "jae s" "mov [esi], ax" "mov [edi], bh" \
"s:" "add edx, ebp" "add ebx, eax" "inc edi" "add esi, 2" "dec ecx" "jnz l" "d:" \
parm [ecx] [edi] [esi] [edx] [ebp] [ebx] [eax] modify [ax ecx edi esi edx ebx];
"test ecx, ecx" \
"jz done" \
"loop_l:" \
"mov eax, edx" \
"shr eax, 16" /* EAX = Z entier * / \
"cmp ax, [esi]" \
"jae skip_p" \
"mov [esi], ax" /* Z-Write * / \
"mov eax, ebx" \
"shr eax, 8" \
"mov [edi], al" /* Color-Write * / \
"skip_p:" \
"add edx, ebp" /* + dz_step (EBP) * / \
"add ebx, [esp+4]" /* + di_step (LU SUR LA PILE) * / \
"inc edi" \
"add esi, 2" \
"dec ecx" \
"jnz loop_l" \
"done:" \
parm [ecx] [edi] [esi] [edx] [ebp] [ebx] \
modify [eax ecx edi esi edx ebx];
*/
#pragma aux scanline_zonly_asm = \
"test ecx, ecx" "jz d" \
"l:" "mov ax, dx" "cmp ax, [esi]" "jae s" "mov [esi], ax" \
"s:" "add edx, ebx" "add esi, 2" "dec ecx" "jnz l" "d:" \
parm [ecx] [esi] [edx] [ebx] modify [ax ecx esi edx];
"test ecx, ecx" \
"jz done_z" \
"loop_z:" \
"mov eax, edx" \
"shr eax, 16" \
"cmp ax, [esi]" \
"jae skip_z" \
"mov [esi], ax" \
"skip_z:" \
"add edx, ebx" \
"add esi, 2" \
"dec ecx" \
"jnz loop_z" \
"done_z:" \
parm [ecx] [esi] [edx] [ebx] \
modify [eax ecx esi edx];
#include "defines.h"
// Ajout de base_color en paramètre
void scanline_gouraud_c(int width, uint8_t *dest, uint16_t *zbuf, int z, int dz_step, int intensity, int di_step, uint8_t base_color) {
int i;
uint8_t shade;
// On calcule le décalage de bloc (ex: couleur 1 commence à l'index 16)
uint8_t color_offset = (uint8_t)(base_color << 4);
for (i = 0; i < width; i++) {
uint16_t zv = (uint16_t)(z >> 16);
if (zv < zbuf[i]) {
zbuf[i] = zv;
// On extrait l'intensité (on travaille en 16.16 pour la précision)
shade = (uint8_t)(intensity >> 16);
if (shade > 15) shade = 15; // Sécurité pour ne pas déborder sur la couleur suivante
dest[i] = color_offset + shade;
}
z += dz_step;
intensity += di_step;
}
}
void draw_line_z(Point2D *p1, Point2D *p2, uint8_t col, int z_test) {
int dx = abs(p2->x - p1->x), dy = abs(p2->y - p1->y);
int sx = (p1->x < p2->x) ? 1 : -1, sy = (p1->y < p2->y) ? 1 : -1;
int err = dx - dy, steps = (dx > dy) ? dx : dy;
fixed z_step = (steps > 0) ? (p2->z - p1->z) / steps : 0, cz = p1->z;
int x = p1->x, y = p1->y;
int dx, dy, sx, sy, err, steps, x, y, e2;
fixed z_step, cz;
uint16_t zv;
dx = abs(p2->x - p1->x); dy = abs(p2->y - p1->y);
sx = (p1->x < p2->x) ? 1 : -1; sy = (p1->y < p2->y) ? 1 : -1;
err = dx - dy;
steps = (dx > dy) ? dx : dy;
z_step = (steps > 0) ? (p2->z - p1->z) / steps : 0;
cz = p1->z;
x = p1->x; y = p1->y;
while (1) {
if (x >= 0 && x < 320 && y >= 0 && y < 200) {
uint16_t zv = (uint16_t)f_to_int(cz);
zv = (uint16_t)f_to_int(cz);
if (!z_test || zv <= zbuffer[y * 320 + x]) {
backbuffer[y * 320 + x] = col;
if (z_test) zbuffer[y * 320 + x] = zv;
}
}
if (x == p2->x && y == p2->y) break;
int e2 = 2 * err;
e2 = 2 * err;
if (e2 > -dy) { err -= dy; x += sx; }
if (e2 < dx) { err += dx; y += sy; }
cz += z_step;
@ -48,23 +107,27 @@ void swap_pt(Point2D **a, Point2D **b) {
}
void fill_triangle_gouraud(Point2D *p1, Point2D *p2, Point2D *p3, uint8_t base_color) {
int y, total_height, width, start_x, end_x, dz_step, intensity_1, intensity_2, di_step, clip_x, w, start_z, start_i, second_half;
fixed dx13, dz13, di13, xA, zA, iA, xB, zB, iB, dx12, dz12, di12, dx23, dz23, di23, cx1, cz1, ci1, cx2, cz2, ci2, tx, tz, ti;
uint8_t *dest;
uint16_t *zbuf;
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);
int total_height = p3->y - p1->y;
total_height = p3->y - p1->y;
if (total_height == 0) return;
// Incréments pour l'arête principale (p1 -> p3)
fixed dx13 = ((p3->x - p1->x) << 16) / total_height;
fixed dz13 = (p3->z - p1->z) / total_height;
fixed di13 = ((p3->intensity - p1->intensity) << 16) / total_height;
dx13 = ((p3->x - p1->x) << 16) / total_height;
dz13 = (p3->z - p1->z) / total_height;
di13 = ((p3->intensity - p1->intensity) << 16) / total_height;
fixed xA = int_to_f(p1->x), zA = p1->z, iA = int_to_f(p1->intensity);
fixed xB = xA, zB = zA, iB = iA;
xA = int_to_f(p1->x); zA = p1->z; iA = int_to_f(p1->intensity);
xB = xA; zB = zA; iB = iA;
fixed dx12 = 0, dz12 = 0, di12 = 0;
fixed dx23 = 0, dz23 = 0, di23 = 0;
dx12 = 0; dz12 = 0; di12 = 0;
dx23 = 0; dz23 = 0; di23 = 0;
if (p2->y > p1->y) {
dx12 = ((p2->x - p1->x) << 16) / (p2->y - p1->y);
@ -77,37 +140,50 @@ void fill_triangle_gouraud(Point2D *p1, Point2D *p2, Point2D *p3, uint8_t base_c
di23 = ((p3->intensity - p2->intensity) << 16) / (p3->y - p2->y);
}
for (int y = p1->y; y < p3->y; y++) {
int second_half = (y >= p2->y);
fixed cx1 = xA, cz1 = zA, ci1 = iA;
fixed cx2 = xB, cz2 = zB, ci2 = iB;
for (y = p1->y; y < p3->y; y++) {
second_half = (y >= p2->y);
cx1 = xA; cz1 = zA; ci1 = iA;
cx2 = xB; cz2 = zB; ci2 = iB;
if (cx1 > cx2) { // Tri horizontal pour tracer de gauche à droite
fixed tx = cx1; cx1 = cx2; cx2 = tx;
fixed tz = cz1; cz1 = cz2; cz2 = tz;
fixed ti = ci1; ci1 = ci2; ci2 = ti;
if (cx1 > cx2) {
tx = cx1; cx1 = cx2; cx2 = tx;
tz = cz1; cz1 = cz2; cz2 = tz;
ti = ci1; ci1 = ci2; ci2 = ti;
}
int start_x = f_to_int(cx1), end_x = f_to_int(cx2);
int width = end_x - start_x;
start_x = f_to_int(cx1); end_x = f_to_int(cx2);
width = end_x - start_x;
if (y >= 0 && y < 200 && width > 0) {
int dz_step = (cz2 - cz1) / width;
int intensity_1 = f_to_int(ci1), intensity_2 = f_to_int(ci2);
int di_step = ((intensity_2 - intensity_1) << 8) / width;
dz_step = (cz2 - cz1) / width;
// intensity_1 = f_to_int(ci1);
// intensity_2 = f_to_int(ci2);
intensity_1 = p1->intensity;
intensity_2 = p2->intensity;
// di_step = ((intensity_2 - intensity_1) << 8) / width;
di_step = (ci2 - ci1) / width;
clip_x = start_x < 0 ? 0 : start_x;
int clip_x = start_x < 0 ? 0 : start_x;
if (clip_x < 320) {
int w = width - (clip_x - start_x);
w = width - (clip_x - start_x);
if (clip_x + w > 320) w = 320 - clip_x;
if (w > 0) {
int start_z = cz1 + (clip_x - start_x) * dz_step;
int start_i = ((base_color + intensity_1) << 8) + (clip_x - start_x) * di_step;
start_z = cz1 + (clip_x - start_x) * dz_step;
/*start_i = ((base_color + intensity_1) << 8) + (clip_x - start_x) * di_step;
dest = backbuffer + (y * 320) + clip_x;
zbuf = zbuffer + (y * 320) + clip_x;
//scanline_gouraud_asm(w, dest, zbuf, start_z, dz_step, start_i, di_step);
scanline_gouraud_c(w, dest, zbuf, start_z, dz_step, start_i, di_step);*/
uint8_t *dest = vid.backbuffer + (y * 320) + clip_x;
uint16_t *zbuf = vid.zbuffer + (y * 320) + clip_x;
scanline_gouraud_asm(w, dest, zbuf, start_z, dz_step, start_i, di_step);
start_i = ci1 + (clip_x - start_x) * di_step;
dest = backbuffer + (y * 320) + clip_x;
zbuf = zbuffer + (y * 320) + clip_x;
scanline_gouraud_c(w, dest, zbuf, start_z, dz_step, start_i, di_step, base_color);
}
}
}
@ -123,20 +199,24 @@ void fill_triangle_gouraud(Point2D *p1, Point2D *p2, Point2D *p3, uint8_t base_c
}
void fill_triangle_zonly(Point2D *p1, Point2D *p2, Point2D *p3) {
int y, total_height, width, start_x, end_x, dz_step, clip_x, w, start_z, second_half;
fixed dx13, dz13, xA, zA, xB, zB, dx12, dz12, dx23, dz23, cx1, cz1, cx2, cz2, tx, tz;
uint16_t *zbuf;
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);
int total_height = p3->y - p1->y;
total_height = p3->y - p1->y;
if (total_height == 0) return;
fixed dx13 = ((p3->x - p1->x) << 16) / total_height;
fixed dz13 = (p3->z - p1->z) / total_height;
dx13 = ((p3->x - p1->x) << 16) / total_height;
dz13 = (p3->z - p1->z) / total_height;
fixed xA = int_to_f(p1->x), zA = p1->z;
fixed xB = xA, zB = zA;
xA = int_to_f(p1->x); zA = p1->z;
xB = xA; zB = zA;
fixed dx12 = 0, dz12 = 0, dx23 = 0, dz23 = 0;
dx12 = 0; dz12 = 0; dx23 = 0; dz23 = 0;
if (p2->y > p1->y) {
dx12 = ((p2->x - p1->x) << 16) / (p2->y - p1->y);
@ -147,29 +227,29 @@ void fill_triangle_zonly(Point2D *p1, Point2D *p2, Point2D *p3) {
dz23 = (p3->z - p2->z) / (p3->y - p2->y);
}
for (int y = p1->y; y < p3->y; y++) {
int second_half = (y >= p2->y);
fixed cx1 = xA, cz1 = zA, cx2 = xB, cz2 = zB;
for (y = p1->y; y < p3->y; y++) {
second_half = (y >= p2->y);
cx1 = xA; cz1 = zA; cx2 = xB; cz2 = zB;
if (cx1 > cx2) {
fixed tx = cx1; cx1 = cx2; cx2 = tx;
fixed tz = cz1; cz1 = cz2; cz2 = tz;
tx = cx1; cx1 = cx2; cx2 = tx;
tz = cz1; cz1 = cz2; cz2 = tz;
}
int start_x = f_to_int(cx1), end_x = f_to_int(cx2);
int width = end_x - start_x;
start_x = f_to_int(cx1); end_x = f_to_int(cx2);
width = end_x - start_x;
if (y >= 0 && y < 200 && width > 0) {
int dz_step = (cz2 - cz1) / width;
int clip_x = start_x < 0 ? 0 : start_x;
dz_step = (cz2 - cz1) / width;
clip_x = start_x < 0 ? 0 : start_x;
if (clip_x < 320) {
int w = width - (clip_x - start_x);
w = width - (clip_x - start_x);
if (clip_x + w > 320) w = 320 - clip_x;
if (w > 0) {
int start_z = cz1 + (clip_x - start_x) * dz_step;
uint16_t *zbuf = vid.zbuffer + (y * 320) + clip_x;
start_z = cz1 + (clip_x - start_x) * dz_step;
zbuf = zbuffer + (y * 320) + clip_x;
scanline_zonly_asm(w, zbuf, start_z, dz_step);
}
}
@ -183,4 +263,4 @@ void fill_triangle_zonly(Point2D *p1, Point2D *p2, Point2D *p3) {
xB += dx23; zB += dz23;
}
}
}
}