fistcommit
This commit is contained in:
commit
80d8141b5a
8 changed files with 497 additions and 0 deletions
186
src/part3D/raster.c
Normal file
186
src/part3D/raster.c
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
#define RASTER_H
|
||||
|
||||
uint8_t *backbuffer, *vga = (uint8_t*)0xA0000;
|
||||
uint16_t *zbuffer;
|
||||
|
||||
|
||||
|
||||
// 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);
|
||||
|
||||
#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];
|
||||
|
||||
#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];
|
||||
|
||||
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;
|
||||
while (1) {
|
||||
if (x >= 0 && x < 320 && y >= 0 && y < 200) {
|
||||
uint16_t 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;
|
||||
if (e2 > -dy) { err -= dy; x += sx; }
|
||||
if (e2 < dx) { err += dx; y += sy; }
|
||||
cz += z_step;
|
||||
}
|
||||
}
|
||||
|
||||
void swap_pt(Point2D **a, Point2D **b) {
|
||||
Point2D *t = *a; *a = *b; *b = t;
|
||||
}
|
||||
|
||||
void fill_triangle_gouraud(Point2D *p1, Point2D *p2, Point2D *p3, uint8_t base_color) {
|
||||
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;
|
||||
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;
|
||||
|
||||
fixed xA = int_to_f(p1->x), zA = p1->z, iA = int_to_f(p1->intensity);
|
||||
fixed xB = xA, zB = zA, iB = iA;
|
||||
|
||||
fixed dx12 = 0, dz12 = 0, di12 = 0;
|
||||
fixed dx23 = 0, dz23 = 0, di23 = 0;
|
||||
|
||||
if (p2->y > p1->y) {
|
||||
dx12 = ((p2->x - p1->x) << 16) / (p2->y - p1->y);
|
||||
dz12 = (p2->z - p1->z) / (p2->y - p1->y);
|
||||
di12 = ((p2->intensity - p1->intensity) << 16) / (p2->y - p1->y);
|
||||
}
|
||||
if (p3->y > p2->y) {
|
||||
dx23 = ((p3->x - p2->x) << 16) / (p3->y - p2->y);
|
||||
dz23 = (p3->z - p2->z) / (p3->y - p2->y);
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int start_x = f_to_int(cx1), end_x = f_to_int(cx2);
|
||||
int 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;
|
||||
|
||||
int clip_x = start_x < 0 ? 0 : start_x;
|
||||
if (clip_x < 320) {
|
||||
int 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;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xA += dx13; zA += dz13; iA += di13;
|
||||
if (!second_half) {
|
||||
xB += dx12; zB += dz12; iB += di12;
|
||||
} else {
|
||||
if (y == p2->y) { xB = int_to_f(p2->x); zB = p2->z; iB = int_to_f(p2->intensity); }
|
||||
xB += dx23; zB += dz23; iB += di23;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fill_triangle_zonly(Point2D *p1, Point2D *p2, Point2D *p3) {
|
||||
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;
|
||||
if (total_height == 0) return;
|
||||
|
||||
fixed dx13 = ((p3->x - p1->x) << 16) / total_height;
|
||||
fixed dz13 = (p3->z - p1->z) / total_height;
|
||||
|
||||
fixed xA = int_to_f(p1->x), zA = p1->z;
|
||||
fixed xB = xA, zB = zA;
|
||||
|
||||
fixed dx12 = 0, dz12 = 0, dx23 = 0, dz23 = 0;
|
||||
|
||||
if (p2->y > p1->y) {
|
||||
dx12 = ((p2->x - p1->x) << 16) / (p2->y - p1->y);
|
||||
dz12 = (p2->z - p1->z) / (p2->y - p1->y);
|
||||
}
|
||||
if (p3->y > p2->y) {
|
||||
dx23 = ((p3->x - p2->x) << 16) / (p3->y - p2->y);
|
||||
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;
|
||||
|
||||
if (cx1 > cx2) {
|
||||
fixed tx = cx1; cx1 = cx2; cx2 = tx;
|
||||
fixed 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;
|
||||
|
||||
if (y >= 0 && y < 200 && width > 0) {
|
||||
int dz_step = (cz2 - cz1) / width;
|
||||
int clip_x = start_x < 0 ? 0 : start_x;
|
||||
|
||||
if (clip_x < 320) {
|
||||
int 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;
|
||||
scanline_zonly_asm(w, zbuf, start_z, dz_step);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue