gba-x3dtest
diff src/polyfill.c @ 9:b0ed38f13261
working on the rasterizer
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 22 Jun 2014 05:16:10 +0300 |
parents | fb0a0d6a8b52 |
children | c398d834d64a |
line diff
1.1 --- a/src/polyfill.c Thu Jun 19 05:53:46 2014 +0300 1.2 +++ b/src/polyfill.c Sun Jun 22 05:16:10 2014 +0300 1.3 @@ -5,14 +5,18 @@ 1.4 #include "fixed.h" 1.5 #include "gbasys.h" 1.6 1.7 -static void fill_scanline(int y, int x0, int x1, uint16_t color); 1.8 +#define VNEXT(x, n) (((x) + 1) % (n)) 1.9 +#define VPREV(x, n) ((x) > 0 ? (x) - 1 : (n) - 1) 1.10 + 1.11 +static void fill_scanline_pal(int y, int x0, int x1, uint8_t color); 1.12 +static void fill_scanline_rgb(int y, int x0, int x1, uint16_t color); 1.13 1.14 void draw_poly(int num, const pvec3 *verts, uint16_t color) 1.15 { 1.16 int i, topidx = 0, botidx = 0; 1.17 - int lidx[2], ridx[2]; 1.18 + int lidx[2] = {-1, -1}, ridx[2] = {-1, -1}; 1.19 int32_t y, topy, boty; 1.20 - int32_t ldy, rdy, ldxdy, rdxdy; 1.21 + int32_t ldy = 0, rdy = 0, ldxdy, rdxdy; 1.22 int32_t lx, rx; 1.23 int start, end; 1.24 1.25 @@ -30,22 +34,46 @@ 1.26 } 1.27 1.28 lidx[0] = ridx[0] = topidx; 1.29 - lidx[1] = topidx ? topidx - 1 : num - 1; 1.30 - ridx[1] = (topidx + 1) % num; 1.31 + 1.32 + /* find starting left edge */ 1.33 + lidx[1] = VPREV(lidx[0], num); 1.34 + ldy = verts[lidx[1]].y - verts[lidx[0]].y; 1.35 + 1.36 + while(ldy == 0) { 1.37 + lidx[0] = lidx[1]; 1.38 + lidx[1] = VPREV(lidx[1], num); 1.39 + 1.40 + if(lidx[1] == topidx) { 1.41 + return; /* degenerate */ 1.42 + } 1.43 + 1.44 + ldy = verts[lidx[1]].y - verts[lidx[0]].y; 1.45 + } 1.46 + lx = verts[lidx[0]].x; 1.47 + ldxdy = x16div(verts[lidx[1]].x - lx, ldy); 1.48 + 1.49 + /* find starting right edge */ 1.50 + ridx[1] = VNEXT(ridx[0], num); 1.51 + rdy = verts[ridx[1]].y - verts[ridx[0]].y; 1.52 + 1.53 + while(rdy == 0) { 1.54 + ridx[0] = ridx[1]; 1.55 + ridx[1] = VNEXT(ridx[1], num); 1.56 + 1.57 + if(ridx[1] == topidx) { 1.58 + return; /* degenerate */ 1.59 + } 1.60 + 1.61 + rdy = verts[ridx[1]].y - verts[ridx[0]].y; 1.62 + } 1.63 + rx = verts[ridx[0]].x; 1.64 + rdxdy = x16div(verts[ridx[1]].x - rx, rdy); 1.65 + 1.66 1.67 if(verts[ridx[1]].x < verts[lidx[1]].x) { 1.68 - return; /* backface (CCW) */ 1.69 + return; /* backface (CCW) */ 1.70 } 1.71 1.72 - lx = rx = verts[lidx[0]].x; 1.73 - 1.74 - /* TODO handle ldy == 0 or rdy == 0 */ 1.75 - ldy = verts[lidx[1]].y - verts[lidx[0]].y; 1.76 - ldxdy = x16div(verts[lidx[1]].x - lx, ldy); 1.77 - 1.78 - rdy = verts[ridx[1]].y - verts[ridx[0]].y; 1.79 - rdxdy = x16div(verts[ridx[1]].x - rx, rdy); 1.80 - 1.81 start = topy >> 16; 1.82 end = boty >> 16; 1.83 1.84 @@ -53,18 +81,12 @@ 1.85 1.86 y = topy; 1.87 for(i=start; i<end; i++) { 1.88 - unsigned short x0, x1; 1.89 - 1.90 - x0 = lx < 0 ? 0 : (lx >> 16); 1.91 - x1 = (rx >> 16) >= WIDTH ? WIDTH - 1 : (rx >> 16); 1.92 - 1.93 - if(i >= 0 && x1 > x0) { 1.94 - fill_scanline(i, x0, x1, color); 1.95 - } 1.96 + short x0, x1; 1.97 1.98 if(y >= verts[lidx[1]].y) { 1.99 + lx = verts[lidx[1]].x; 1.100 lidx[0] = lidx[1]; 1.101 - lidx[1] = lidx[1] ? lidx[1] - 1 : num - 1; 1.102 + lidx[1] = VPREV(lidx[1], num); 1.103 ldy = verts[lidx[1]].y - verts[lidx[0]].y; 1.104 if(ldy < 0) { 1.105 break; 1.106 @@ -72,8 +94,9 @@ 1.107 ldxdy = x16div(verts[lidx[1]].x - lx, ldy); 1.108 } 1.109 if(y >= verts[ridx[1]].y) { 1.110 + rx = verts[ridx[1]].x; 1.111 ridx[0] = ridx[1]; 1.112 - ridx[1] = (ridx[1] + 1) % num; 1.113 + ridx[1] = VNEXT(ridx[1], num); 1.114 rdy = verts[ridx[1]].y - verts[ridx[0]].y; 1.115 if(rdy < 0) { 1.116 break; 1.117 @@ -81,13 +104,58 @@ 1.118 rdxdy = x16div(verts[ridx[1]].x - rx, rdy); 1.119 } 1.120 1.121 + x0 = lx < 0 ? 0 : (lx >> 16); 1.122 + x1 = (rx >> 16) >= WIDTH ? WIDTH - 1 : (rx >> 16); 1.123 + 1.124 + if(i >= 0 && x1 > x0) { 1.125 +#ifdef PALMODE 1.126 + fill_scanline_pal(i, x0, x1, (uint8_t)color); 1.127 +#else 1.128 + fill_scanline_rgb(i, x0, x1, color); 1.129 +#endif 1.130 + } 1.131 + 1.132 lx += ldxdy; 1.133 rx += rdxdy; 1.134 y += 65536; 1.135 } 1.136 } 1.137 1.138 -static void fill_scanline(int y, int x0, int x1, uint16_t color) 1.139 + 1.140 +static void fill_scanline_pal(int y, int x0, int x1, uint8_t color) 1.141 +{ 1.142 +#if 1 1.143 + int i, num_pairs, num_pix = x1 - x0; 1.144 + uint16_t *pixels = (uint16_t*)back_buffer->pixels + (y * WIDTH + x0) / 2; 1.145 + uint16_t colpair = (uint16_t)color | ((uint16_t)color << 8); 1.146 + 1.147 + if(x0 & 1) { 1.148 + uint16_t pix = *pixels & 0xff; 1.149 + *pixels++ = pix | ((uint16_t)color << 8); 1.150 + --num_pix; 1.151 + } 1.152 + 1.153 + num_pairs = (num_pix & 0xfffe) / 2; 1.154 + 1.155 + for(i=0; i<num_pairs; i++) { 1.156 + *pixels++ = colpair; 1.157 + } 1.158 + 1.159 + if(num_pix & 1) { 1.160 + uint16_t pix = *pixels & 0xff00; 1.161 + *pixels = pix | color; 1.162 + } 1.163 +#else 1.164 + int i; 1.165 + uint8_t *pixels = (uint8_t*)back_buffer->pixels + y * WIDTH + x0; 1.166 + 1.167 + for(i=x0; i<x1; i++) { 1.168 + *pixels++ = color; 1.169 + } 1.170 +#endif 1.171 +} 1.172 + 1.173 +static void fill_scanline_rgb(int y, int x0, int x1, uint16_t color) 1.174 { 1.175 int i; 1.176 uint16_t *pixels = (uint16_t*)back_buffer->pixels + y * WIDTH + x0; 1.177 @@ -108,5 +176,14 @@ 1.178 return; 1.179 } 1.180 1.181 +#ifdef PALMODE 1.182 + pixels += (y * WIDTH + x) / 2; 1.183 + if(x & 1) { 1.184 + *pixels = (*pixels & 0xff) | (color << 8); 1.185 + } else { 1.186 + *pixels = (*pixels & 0xff00) | color; 1.187 + } 1.188 +#else 1.189 pixels[y * WIDTH + x] = color; 1.190 +#endif 1.191 }