/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Z-buffered polygon filler helpers (gouraud shading, tmapping, etc). * * Original routines by Michael Bukin. * Modified to support z-buffered polygon drawing by Bertrand Coconnier * * See readme.txt for copyright information. */ #define ZBUF_PTR float* #ifndef __bma_czscan_h #define __bma_czscan_h /* _poly_zbuf_flat: * Fills a single-color polygon scanline. */ void FUNC_POLY_ZBUF_FLAT(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; float z; unsigned long c; PIXEL_PTR d; ZBUF_PTR zb; ASSERT(addr); ASSERT(info); z = info->z; c = info->c; d = (PIXEL_PTR) addr; zb = (ZBUF_PTR) info->zbuf_addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) { if (*zb < z) { PUT_PIXEL(d, c); *zb = z; } zb++; z += info->dz; } } #ifdef _bma_zbuf_gcol /* _poly_zbuf_gcol: * Fills a single-color gouraud shaded polygon scanline. */ void FUNC_POLY_ZBUF_GCOL(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; float z; fixed c, dc; PIXEL_PTR d; ZBUF_PTR zb; ASSERT(addr); ASSERT(info); z = info->z; c = info->c; dc = info->dc; d = (PIXEL_PTR) addr; zb = (ZBUF_PTR) info->zbuf_addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) { if (*zb < z) { PUT_PIXEL(d, (c >> 16)); *zb = z; } c += dc; zb++; z += info->dz; } } #endif /* _bma_zbuf_gcol */ /* _poly_zbuf_grgb: * Fills an gouraud shaded polygon scanline. */ void FUNC_POLY_ZBUF_GRGB(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; fixed r, g, b, dr, dg, db; PIXEL_PTR d; float z; ZBUF_PTR zb; ASSERT(addr); ASSERT(info); r = info->r; g = info->g; b = info->b; dr = info->dr; dg = info->dg; db = info->db; d = (PIXEL_PTR) addr; z = info->z; zb = (ZBUF_PTR) info->zbuf_addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) { if (*zb < z) { PUT_RGB(d, (r >> 16), (g >> 16), (b >> 16)); *zb = z; } r += dr; g += dg; b += db; zb++; z += info->dz; } } /* _poly_zbuf_atex: * Fills an affine texture mapped polygon scanline. */ void FUNC_POLY_ZBUF_ATEX(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; int vmask, vshift, umask; fixed u, v, du, dv; PIXEL_PTR texture; PIXEL_PTR d; float z; ZBUF_PTR zb; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; u = info->u; v = info->v; du = info->du; dv = info->dv; texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; z = info->z; zb = (ZBUF_PTR) info->zbuf_addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) { if (*zb < z) { PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); PUT_PIXEL(d, color); *zb = z; } u += du; v += dv; zb++; z += info->dz; } } /* _poly_zbuf_atex_mask: * Fills a masked affine texture mapped polygon scanline. */ void FUNC_POLY_ZBUF_ATEX_MASK(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; int vmask, vshift, umask; fixed u, v, du, dv; PIXEL_PTR texture; PIXEL_PTR d; float z; ZBUF_PTR zb; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; u = info->u; v = info->v; du = info->du; dv = info->dv; texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; z = info->z; zb = (ZBUF_PTR) info->zbuf_addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) { if (*zb < z) { PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); if (!IS_MASK(color)) { PUT_PIXEL(d, color); *zb = z; } } u += du; v += dv; zb++; z += info->dz; } } /* _poly_zbuf_atex_lit: * Fills a lit affine texture mapped polygon scanline. */ void FUNC_POLY_ZBUF_ATEX_LIT(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; int vmask, vshift, umask; fixed u, v, c, du, dv, dc; PIXEL_PTR texture; PIXEL_PTR d; PS_BLENDER blender; float z; ZBUF_PTR zb; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; u = info->u; v = info->v; c = info->c; du = info->du; dv = info->dv; dc = info->dc; blender = MAKE_PS_BLENDER(); texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; z = info->z; zb = (ZBUF_PTR) info->zbuf_addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) { if (*zb < z) { PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); color = PS_BLEND(blender, (c >> 16), color); PUT_PIXEL(d, color); *zb = z; } u += du; v += dv; c += dc; zb++; z += info->dz; } } /* _poly_zbuf_atex_mask_lit: * Fills a masked lit affine texture mapped polygon scanline. */ void FUNC_POLY_ZBUF_ATEX_MASK_LIT(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; int vmask, vshift, umask; fixed u, v, c, du, dv, dc; PIXEL_PTR texture; PIXEL_PTR d; PS_BLENDER blender; float z; ZBUF_PTR zb; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; u = info->u; v = info->v; c = info->c; du = info->du; dv = info->dv; dc = info->dc; blender = MAKE_PS_BLENDER(); texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; z = info->z; zb = (ZBUF_PTR) info->zbuf_addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) { if (*zb < z) { PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); if (!IS_MASK(color)) { color = PS_BLEND(blender, (c >> 16), color); PUT_PIXEL(d, color); *zb = z; } } u += du; v += dv; c += dc; zb++; z += info->dz; } } /* _poly_zbuf_ptex: * Fills a perspective correct texture mapped polygon scanline. */ void FUNC_POLY_ZBUF_PTEX(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; int vmask, vshift, umask; double fu, fv, fz, dfu, dfv, dfz; PIXEL_PTR texture; PIXEL_PTR d; ZBUF_PTR zb; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; fu = info->fu; fv = info->fv; fz = info->z; dfu = info->dfu; dfv = info->dfv; dfz = info->dz; texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; zb = (ZBUF_PTR) info->zbuf_addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) { if (*zb < fz) { long u = fu / fz; long v = fv / fz; PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); PUT_PIXEL(d, color); *zb = (float) fz; } fu += dfu; fv += dfv; fz += dfz; zb++; } } /* _poly_zbuf_ptex_mask: * Fills a masked perspective correct texture mapped polygon scanline. */ void FUNC_POLY_ZBUF_PTEX_MASK(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; int vmask, vshift, umask; double fu, fv, fz, dfu, dfv, dfz; PIXEL_PTR texture; PIXEL_PTR d; ZBUF_PTR zb; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; fu = info->fu; fv = info->fv; fz = info->z; dfu = info->dfu; dfv = info->dfv; dfz = info->dz; texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; zb = (ZBUF_PTR) info->zbuf_addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) { if (*zb < fz) { long u = fu / fz; long v = fv / fz; PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); if (!IS_MASK(color)) { PUT_PIXEL(d, color); *zb = (float) fz; } } fu += dfu; fv += dfv; fz += dfz; zb++; } } /* _poly_zbuf_ptex_lit: * Fills a lit perspective correct texture mapped polygon scanline. */ void FUNC_POLY_ZBUF_PTEX_LIT(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; int vmask, vshift, umask; fixed c, dc; double fu, fv, fz, dfu, dfv, dfz; PS_BLENDER blender; PIXEL_PTR texture; PIXEL_PTR d; ZBUF_PTR zb; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; c = info->c; dc = info->dc; fu = info->fu; fv = info->fv; fz = info->z; dfu = info->dfu; dfv = info->dfv; dfz = info->dz; blender = MAKE_PS_BLENDER(); texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; zb = (ZBUF_PTR) info->zbuf_addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) { if (*zb < fz) { long u = fu / fz; long v = fv / fz; PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); color = PS_BLEND(blender, (c >> 16), color); PUT_PIXEL(d, color); *zb = (float) fz; } fu += dfu; fv += dfv; fz += dfz; c += dc; zb++; } } /* _poly_zbuf_ptex_mask_lit: * Fills a masked lit perspective correct texture mapped polygon scanline. */ void FUNC_POLY_ZBUF_PTEX_MASK_LIT(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; int vmask, vshift, umask; fixed c, dc; double fu, fv, fz, dfu, dfv, dfz; PS_BLENDER blender; PIXEL_PTR texture; PIXEL_PTR d; ZBUF_PTR zb; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; c = info->c; dc = info->dc; fu = info->fu; fv = info->fv; fz = info->z; dfu = info->dfu; dfv = info->dfv; dfz = info->dz; blender = MAKE_PS_BLENDER(); texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; zb = (ZBUF_PTR) info->zbuf_addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) { if (*zb < fz) { long u = fu / fz; long v = fv / fz; PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); if (!IS_MASK(color)) { color = PS_BLEND(blender, (c >> 16), color); PUT_PIXEL(d, color); *zb = (float) fz; } } fu += dfu; fv += dfv; fz += dfz; c += dc; zb++; } } /* _poly_zbuf_atex_trans: * Fills a trans affine texture mapped polygon scanline. */ void FUNC_POLY_ZBUF_ATEX_TRANS(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; int vmask, vshift, umask; fixed u, v, du, dv; PS_BLENDER blender; PIXEL_PTR texture; PIXEL_PTR d; PIXEL_PTR r; float z; ZBUF_PTR zb; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; u = info->u; v = info->v; du = info->du; dv = info->dv; blender = MAKE_PS_BLENDER(); texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; r = (PIXEL_PTR) info->read_addr; z = info->z; zb = (ZBUF_PTR) info->zbuf_addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), INC_PIXEL_PTR(r), x--) { if (*zb < z) { PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); color = PS_ALPHA_BLEND(blender, color, GET_PIXEL(r)); PUT_PIXEL(d, color); *zb = z; } u += du; v += dv; zb++; z += info->dz; } } /* _poly_zbuf_atex_mask_trans: * Fills a trans masked affine texture mapped polygon scanline. */ void FUNC_POLY_ZBUF_ATEX_MASK_TRANS(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; int vmask, vshift, umask; fixed u, v, du, dv; PS_BLENDER blender; PIXEL_PTR texture; PIXEL_PTR d; PIXEL_PTR r; float z; ZBUF_PTR zb; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; u = info->u; v = info->v; du = info->du; dv = info->dv; blender = MAKE_PS_BLENDER(); texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; r = (PIXEL_PTR) info->read_addr; z = info->z; zb = (ZBUF_PTR) info->zbuf_addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), INC_PIXEL_PTR(r), x--) { if (*zb < z) { PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); if (!IS_MASK(color)) { color = PS_ALPHA_BLEND(blender, color, GET_PIXEL(r)); PUT_PIXEL(d, color); *zb = z; } } u += du; v += dv; zb++; z += info->dz; } } /* _poly_zbuf_ptex_trans: * Fills a trans perspective correct texture mapped polygon scanline. */ void FUNC_POLY_ZBUF_PTEX_TRANS(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; int vmask, vshift, umask; double fu, fv, fz, dfu, dfv, dfz; PS_BLENDER blender; PIXEL_PTR texture; PIXEL_PTR d; PIXEL_PTR r; ZBUF_PTR zb; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; fu = info->fu; fv = info->fv; fz = info->z; dfu = info->dfu; dfv = info->dfv; dfz = info->dz; blender = MAKE_PS_BLENDER(); texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; r = (PIXEL_PTR) info->read_addr; zb = (ZBUF_PTR) info->zbuf_addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), INC_PIXEL_PTR(r), x--) { if (*zb < fz) { long u = fu / fz; long v = fv / fz; PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); color = PS_ALPHA_BLEND(blender, color, GET_PIXEL(r)); PUT_PIXEL(d, color); *zb = (float) fz; } fu += dfu; fv += dfv; fz += dfz; zb++; } } /* _poly_zbuf_ptex_mask_trans: * Fills a trans masked perspective correct texture mapped polygon scanline. */ void FUNC_POLY_ZBUF_PTEX_MASK_TRANS(uintptr_t addr, int w, POLYGON_SEGMENT *info) { int x; int vmask, vshift, umask; double fu, fv, fz, dfu, dfv, dfz; PS_BLENDER blender; PIXEL_PTR texture; PIXEL_PTR d; PIXEL_PTR r; ZBUF_PTR zb; ASSERT(addr); ASSERT(info); vmask = info->vmask << info->vshift; vshift = 16 - info->vshift; umask = info->umask; fu = info->fu; fv = info->fv; fz = info->z; dfu = info->dfu; dfv = info->dfv; dfz = info->dz; blender = MAKE_PS_BLENDER(); texture = (PIXEL_PTR) (info->texture); d = (PIXEL_PTR) addr; r = (PIXEL_PTR) info->read_addr; zb = (ZBUF_PTR) info->zbuf_addr; for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), INC_PIXEL_PTR(r), x--) { if (*zb < fz) { long u = fu / fz; long v = fv / fz; PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask)); unsigned long color = GET_MEMORY_PIXEL(s); if (!IS_MASK(color)) { color = PS_ALPHA_BLEND(blender, color, GET_PIXEL(r)); PUT_PIXEL(d, color); *zb = (float) fz; } } fu += dfu; fv += dfv; fz += dfz; zb++; } } #endif /* !__bma_czscan_h */