deepstone
diff src/scantmpl.h @ 25:5ff8ce78059a
first pass at converting the rasterizer to fixed point
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 22 Sep 2013 02:21:30 +0300 |
parents | 1e9f0b3616fa |
children | 11d14f688485 |
line diff
1.1 --- a/src/scantmpl.h Sat Sep 21 20:18:28 2013 +0300 1.2 +++ b/src/scantmpl.h Sun Sep 22 02:21:30 2013 +0300 1.3 @@ -1,61 +1,44 @@ 1.4 -/* 1.5 -256-color 3D graphics hack for real-mode DOS. 1.6 -Copyright (C) 2011 John Tsiombikas <nuclear@member.fsf.org> 1.7 - 1.8 -This program is free software: you can redistribute it and/or modify 1.9 -it under the terms of the GNU General Public License as published by 1.10 -the Free Software Foundation, either version 3 of the License, or 1.11 -(at your option) any later version. 1.12 - 1.13 -This program is distributed in the hope that it will be useful, 1.14 -but WITHOUT ANY WARRANTY; without even the implied warranty of 1.15 -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1.16 -GNU General Public License for more details. 1.17 - 1.18 -You should have received a copy of the GNU General Public License 1.19 -along with this program. If not, see <http://www.gnu.org/licenses/>. 1.20 -*/ 1.21 -static void SCAN_EDGE(struct vertex *v0, struct vertex *v1) 1.22 +static void SCAN_EDGE(VERTEX *v0, VERTEX *v1) 1.23 { 1.24 int i, start, end; 1.25 - float dx, dy, dfdx; 1.26 + fixed dx, dy, dfdx; 1.27 #ifdef INTERP_DEPTH 1.28 - float z, dz, dfdz; 1.29 + fixed z, dz, dfdz; 1.30 #endif 1.31 #ifdef INTERP_ENERGY 1.32 - float e, de, dfde; 1.33 + fixed e, de, dfde; 1.34 #endif 1.35 #ifdef INTERP_TEX 1.36 - float u, v, du, dv, dfdu, dfdv; 1.37 + fixed u, v, du, dv, dfdu, dfdv; 1.38 #endif 1.39 - float x; 1.40 - struct vertex *edge; 1.41 + fixed x; 1.42 + VERTEX *edge; 1.43 1.44 dy = v1->pos.y - v0->pos.y; 1.45 - if(dy < 1e-6 && dy > -1e-6) { 1.46 + if(dy < FIXED_EPSILON && dy > -FIXED_EPSILON) { 1.47 return; 1.48 } 1.49 1.50 dx = v1->pos.x - v0->pos.x; 1.51 - dfdx = dx / dy; 1.52 + dfdx = fixed_div(dx, dy); 1.53 1.54 #ifdef INTERP_DEPTH 1.55 dz = v1->pos.z - v0->pos.z; 1.56 - dfdz = dz / dy; 1.57 + dfdz = fixed_div(dz, dy); 1.58 #endif 1.59 #ifdef INTERP_ENERGY 1.60 de = v1->energy - v0->energy; 1.61 - dfde = de / dy; 1.62 + dfde = fixed_div(de, dy); 1.63 #endif 1.64 #ifdef INTERP_TEX 1.65 du = v1->tc.x - v0->tc.x; 1.66 dv = v1->tc.y - v0->tc.y; 1.67 - dfdu = du / dy; 1.68 - dfdv = dv / dy; 1.69 + dfdu = fixed_div(du, dy); 1.70 + dfdv = fixed_div(dv, dy); 1.71 #endif 1.72 1.73 - if(dy < 0.0) { 1.74 - struct vertex *tmp = v0; 1.75 + if(dy < 0) { 1.76 + VERTEX *tmp = v0; 1.77 v0 = v1; 1.78 v1 = tmp; 1.79 edge = (st->ord == MGL_CCW) ? vright : vleft; 1.80 @@ -63,8 +46,8 @@ 1.81 edge = (st->ord == MGL_CCW) ? vleft : vright; 1.82 } 1.83 1.84 - start = (int)ROUND(v0->pos.y); 1.85 - end = (int)ROUND(v1->pos.y); 1.86 + start = (int)fixed_round(v0->pos.y); 1.87 + end = (int)fixed_round(v1->pos.y); 1.88 1.89 if(start >= 0) { 1.90 1.91 @@ -80,18 +63,18 @@ 1.92 v = v0->tc.y; 1.93 #endif 1.94 } else { 1.95 - float lines = -v0->pos.y; 1.96 + fixed lines = -v0->pos.y; 1.97 1.98 - x = v0->pos.x + dfdx * lines; 1.99 + x = v0->pos.x + fixed_mul(dfdx, lines); 1.100 #ifdef INTERP_DEPTH 1.101 - z = v0->pos.z + dfdz * lines; 1.102 + z = v0->pos.z + fixed_mul(dfdz, lines); 1.103 #endif 1.104 #ifdef INTERP_ENERGY 1.105 - e = v0->energy + dfde * lines; 1.106 + e = v0->energy + fixed_mul(dfde, lines); 1.107 #endif 1.108 #ifdef INTERP_TEX 1.109 - u = v0->tc.x + dfdu * lines; 1.110 - v = v0->tc.y + dfdv * lines; 1.111 + u = v0->tc.x + fixed_mul(dfdu, lines); 1.112 + v = v0->tc.y + fixed_mul(dfdv, lines); 1.113 #endif 1.114 start = 0; 1.115 } 1.116 @@ -132,22 +115,22 @@ 1.117 int x0, x1, len, tmp, cidx; 1.118 #if defined(INTERP_DEPTH) || defined(INTERP_ENERGY) || defined(INTERP_TEX) 1.119 int i; 1.120 - float x, dx; 1.121 + fixed x, dx; 1.122 #endif 1.123 #ifdef INTERP_DEPTH 1.124 - float z, dz, dfdz; 1.125 + fixed z, dz, dfdz; 1.126 #endif 1.127 #ifdef INTERP_ENERGY 1.128 - float e, de, dfde; 1.129 + fixed e, de, dfde; 1.130 #endif 1.131 #ifdef INTERP_TEX 1.132 unsigned int tx, ty; 1.133 - float u, v, du, dv, dfdu, dfdv; 1.134 + fixed u, v, du, dv, dfdu, dfdv; 1.135 #endif 1.136 - struct vertex *left, *right; 1.137 + VERTEX *left, *right; 1.138 1.139 - x0 = (int)ROUND(vleft[y].pos.x); 1.140 - x1 = (int)ROUND(vright[y].pos.x); 1.141 + x0 = (int)fixed_round(vleft[y].pos.x); 1.142 + x1 = (int)fixed_round(vright[y].pos.x); 1.143 1.144 if(x1 < x0) { 1.145 if(st->flags & MGL_CULL_FACE) { 1.146 @@ -174,13 +157,13 @@ 1.147 len = x1 - x0; 1.148 assert(len >= 0); 1.149 /* no interpolation at all, just memset the whole scanline */ 1.150 - memset(sline + x0, cidx + left[y].energy * st->col_range, len); 1.151 + memset(sline + x0, cidx + fixed_int(fixed_mul(left[y].energy, fixedi(st->col_range))), len); 1.152 #else 1.153 /* otherwise do a loop and interpolate whatever needs interpolating */ 1.154 x = left[y].pos.x; 1.155 dx = right[y].pos.x - x; 1.156 1.157 - if(dx < 0.5 && dx > -0.5) { 1.158 + if(dx < fixedf(0.5) && dx > -fixedf(0.5)) { 1.159 return; 1.160 } 1.161 1.162 @@ -188,41 +171,41 @@ 1.163 #ifdef INTERP_DEPTH 1.164 z = left[y].pos.z; 1.165 dz = right[y].pos.z - z; 1.166 - dfdz = dz / dx; 1.167 + dfdz = fixed_div(dz, dx); 1.168 #endif 1.169 #ifdef INTERP_ENERGY 1.170 e = left[y].energy; 1.171 de = right[y].energy - e; 1.172 - dfde = de / dx; 1.173 + dfde = fixed_div(de, dx); 1.174 #endif 1.175 #ifdef INTERP_TEX 1.176 u = left[y].tc.x; 1.177 v = left[y].tc.y; 1.178 du = right[y].tc.x - u; 1.179 dv = right[y].tc.y - v; 1.180 - dfdu = du / dx; 1.181 - dfdv = dv / dx; 1.182 + dfdu = fixed_div(du, dx); 1.183 + dfdv = fixed_div(dv, dx); 1.184 #endif 1.185 } else { 1.186 - float dist = -left[y].pos.x; 1.187 + fixed dist = -left[y].pos.x; 1.188 1.189 #ifdef INTERP_DEPTH 1.190 dz = right[y].pos.z - left[y].pos.z; 1.191 - dfdz = dz / dx; 1.192 - z = left[y].pos.z + dfdz * dist; 1.193 + dfdz = fixed_div(dz, dx); 1.194 + z = left[y].pos.z + fixed_mul(dfdz, dist); 1.195 #endif 1.196 #ifdef INTERP_ENERGY 1.197 de = right[y].energy - left[y].energy; 1.198 - dfde = de / dx; 1.199 - e = left[y].energy + dfde * dist; 1.200 + dfde = fixed_div(de, dx); 1.201 + e = left[y].energy + fixed_mul(dfde, dist); 1.202 #endif 1.203 #ifdef INTERP_TEX 1.204 du = right[y].tc.x - left[y].tc.x; 1.205 dv = right[y].tc.y - left[y].tc.y; 1.206 - dfdu = du / dx; 1.207 - dfdv = dv / dx; 1.208 - u = left[y].tc.x + dfdu * dist; 1.209 - v = left[y].tc.y + dfdv * dist; 1.210 + dfdu = fixed_div(du, dx); 1.211 + dfdv = fixed_div(dv, dx); 1.212 + u = left[y].tc.x + fixed_mul(dfdu, dist); 1.213 + v = left[y].tc.y + fixed_mul(dfdv, dist); 1.214 #endif 1.215 x0 = 0; 1.216 } 1.217 @@ -234,10 +217,14 @@ 1.218 1.219 #ifdef INTERP_DEPTH 1.220 long pix = (sline + x0 + i) - fb->pixels; 1.221 +#ifdef RAST_FLOAT 1.222 unsigned short zval = (unsigned short)(z * USHRT_MAX); 1.223 +#else 1.224 + unsigned short zval = (unsigned short)((z >> 1) & 0xffff); 1.225 +#endif 1.226 unsigned short *zptr = fb->zbuf[ZTILE(pix)] + ZTILE_OFFS(pix); 1.227 1.228 - if(z < 0.0 || z >= 1.0 || zval > *zptr) { 1.229 + if(z < 0 || z >= fixedi(1) || zval > *zptr) { 1.230 # ifdef INTERP_TEX 1.231 u += dfdu; 1.232 v += dfdv; 1.233 @@ -253,18 +240,18 @@ 1.234 z += dfdz; 1.235 #endif 1.236 #ifdef INTERP_TEX 1.237 - tx = (unsigned int)(u * st->tex.width) & st->tex.xmask; 1.238 - ty = (unsigned int)(v * st->tex.height) & st->tex.ymask; 1.239 + tx = (unsigned int)fixed_int(fixed_mul(u, fixedi(st->tex.width))) & st->tex.xmask; 1.240 + ty = (unsigned int)fixed_int(fixed_mul(v, fixedi(st->tex.height))) & st->tex.ymask; 1.241 c = st->tex.pixels[(ty << st->tex.xshift) + tx]; 1.242 1.243 u += dfdu; 1.244 v += dfdv; 1.245 #endif 1.246 #ifdef INTERP_ENERGY 1.247 - c += e * st->col_range; 1.248 + c += fixed_int(fixed_mul(e, fixedi(st->col_range))); 1.249 e += dfde; 1.250 #else 1.251 - c += left[y].energy * st->col_range; 1.252 + c += fixed_int(fixed_mul(left[y].energy, fixedi(st->col_range))); 1.253 #endif 1.254 sline[x0 + i] = c; 1.255 }