/* Copyright (C) 1996-1997 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // d_scan.c // // Portable C scan-level rasterization code, all pixel depths. // // TODO: Fix this mess up, some of the codes formatting is utterly broken on most editors #include "globaldef.h" #include "r_local.h" #include "d_local.h" unsigned char *r_turb_pbase, *r_turb_pdest, *r_turb_prefst;; fixed16_t r_turb_s, r_turb_t, r_turb_sstep, r_turb_tstep; int *r_turb_turb; int r_turb_spancount; void D_DrawTurbulent8Span (void); void D_DrawTurbulent8SpanT (void); extern int fogcolr, fogcolg, fogcolb, fogthick, fogrange; // leilei - fog extern byte bumpmap[256]; extern pixel_t transTable[256][256]; // for shrooms effect pixel_t waterTable[256][256]; extern float oldwateralpha; byte menumap[256][16]; // haha hack extern pixel_t addTable[256][256]; // Additive blending effect extern pixel_t mulTable[256][256]; // Multiply blending effect (for colormod) extern pixel_t ditherTable[262144][4]; static byte *foggmap; extern int wootel[32][32][32]; extern cvar_t *r_tranquality; extern cvar_t *r_wateralpha; extern float fademap[256]; // Used in generation of certain alpha tables extern int oldwaterblend; void SetFogMap (void) { foggmap = (byte *)host_fogmap; } void WaterTablgeGet (void) { float ay, ae; int i, j, l, c, o; float red, green, blue; int ooh; ooh = (int)r_tranquality->value; ay = r_wateralpha->value; // water surface ae = 1 - ay; // base pixels for (l=0;l<255;l++) { for (c=0 ; c<255 ; c++) { if (oldwaterblend == 1){ // additive red = host_basepal[c*3] + (host_basepal[l*3] *ay); green = host_basepal[c*3+1] + (host_basepal[l*3+1] *ay); blue = host_basepal[c*3+2] + (host_basepal[l*3+2] *ay); } else if (oldwaterblend == 2){ // multiplicative red = host_basepal[c*3] *ae + ((host_basepal[c*3] * (host_basepal[l*3] * 0.05)) * ay); green = host_basepal[c*3+1] *ae + ((host_basepal[c*3+1]* (host_basepal[l*3+1] * 0.05)) * ay); blue = host_basepal[c*3+2] *ae + ((host_basepal[c*3+2] * (host_basepal[l*3+2] * 0.05)) * ay); } else if (oldwaterblend == 4){ // multiplicative red = host_basepal[c*3] *ae + ((host_basepal[l*3] * 0.1 * (host_basepal[c*3] * 0.5)) * ay); green = host_basepal[c*3+1] *ae + ((host_basepal[l*3+1] * 0.1 * (host_basepal[c*3+1] * 0.5)) * ay); blue = host_basepal[c*3+2] *ae + ((host_basepal[l*3+2] * 0.1 * (host_basepal[c*3+2] * 0.5)) * ay); } else if (oldwaterblend == 5){ // weird alpha thing /* how it works - goes through each color row from transparent(0) to opaque (16) this would also be used for the future (can you say decals?) */ red = host_basepal[c*3] *(fademap[l] * ae) + (host_basepal[l*3] * (fademap[l]+0.3 * ay)); green = host_basepal[c*3+1] *(fademap[l] * ae) + (host_basepal[l*3+1] * (fademap[l]+0.3 * ay)); blue = host_basepal[c*3+2] * (fademap[l] * ae) + (host_basepal[l*3+2] * (fademap[l]+0.3 * ay)); } else { red = host_basepal[c*3] *ae + (host_basepal[l*3] * ay); green = host_basepal[c*3+1] *ae + (host_basepal[l*3+1] * ay); blue = host_basepal[c*3+2] *ae + (host_basepal[l*3+2] * ay); } if (red > 255) red = 255; if (green > 255) green = 255; if (blue > 255) blue = 255; if (red < 0) red = 0; if (green < 0) green = 0; if (blue < 0) blue = 0; if (ooh) waterTable[l][c] = BestColor(red,green,blue, 0, 255); // High quality color tables get best color else if (palmap2) waterTable[l][c] = FindColor18(red,green,blue); else waterTable[l][c] = FindColor(red,green,blue); // Since we do this live we must do thisfast! or i'll cry. } } } /* ============= D_AlphaShift This way is for like uh mods that use vid_cshift in ways intended for GLQuake use (i.e. contrasting a centerprint visually) it's a hacky workaround to play prydon gate ============= */ extern int shiftshif; extern int shiftalpha; void D_AlphaShift (void) { int x,y; byte *pbuf; VID_UnlockBuffer (); S_ExtraUpdate (); VID_LockBuffer (); if (shiftalpha < 20) return; for (y=0 ; y 220) pbuf[x] = (int)shiftshif; } } VID_UnlockBuffer (); S_ExtraUpdate (); VID_LockBuffer (); } extern void *acolormap; // FIXME: should go away /* ============= D_WarpScreen // this performs a slight compression of the screen at the same time as // the sine warp, to keep the edges from wrapping ============= */ void D_WarpScreen (void) { int w, h; int u,v; byte *dest; int *turb; int *col; byte **row; byte *rowptr[MAXHEIGHT+(AMP2*2)]; int column[MAXWIDTH+(AMP2*2)]; float wratio, hratio; w = r_refdef.vrect.width; h = r_refdef.vrect.height; wratio = w / (float)scr_vrect.width; hratio = h / (float)scr_vrect.height; for (v=0 ; v>16)&(CYCLE-1)])>>16)&63; tturb = ((r_turb_t + r_turb_turb[(r_turb_s>>16)&(CYCLE-1)])>>16)&63; *r_turb_pdest++ = *(r_turb_pbase + (tturb<<6) + sturb); r_turb_s += r_turb_sstep; r_turb_t += r_turb_tstep; } while (--r_turb_spancount > 0); } // // if (foguse) // leilei - fogged case // *pdest++ = (byte*)foggmap[pbase[(s >> 16) + (t >> 16) * cachewidth] + (forg >> 2 & 0xFF00)]; // else // *pdest++ = pbase[(s >> 16) + (t >> 16) * cachewidth]; // #endif // !id386 int ferg; void D_DrawTurbulent8Span_Fog (void) { int sturb, tturb; do { sturb = ((r_turb_s + r_turb_turb[(r_turb_t>>16)&(CYCLE-1)])>>16)&63; tturb = ((r_turb_t + r_turb_turb[(r_turb_s>>16)&(CYCLE-1)])>>16)&63; *r_turb_pdest++ = foggmap[(*(r_turb_pbase + (tturb<<6) + sturb)) + (ferg >> 2 & 0xFF00)]; r_turb_s += r_turb_sstep; r_turb_t += r_turb_tstep; } while (--r_turb_spancount > 0); } int gmcol; int izi, izistep, izistep2, sturb, tturb, teste; // mk transwater short *pz; // mk transwater extern cvar_t *temp1; extern cvar_t *r_waterquality; extern cvar_t *r_wateralpha; int depthen; void D_DrawTurbulent8SpanAlphaRefractions (void) { int sturb, tturb; int refsturb, reftturb; int refractsturb, refracttturb; unsigned char temp, tempd2, tempd3, temp3, temp4; int bleeh, bleeh2; float wa; //int pixsize = 2 * ( scr_vrect.width/ 640); int pixsize = 2; //wa = r_wateralpha->value; // wa = depthen / 8192; depthen = (depthen) >> 2; do { if (*pz <= (izi >> 16)) { sturb = ((r_turb_s + r_turb_turb[(r_turb_t>>16)&(CYCLE-1)])>>16)&63; tturb = ((r_turb_t + r_turb_turb[(r_turb_s>>16)&(CYCLE-1)])>>16)&63; refractsturb = ((r_turb_s + r_turb_turb[(r_turb_t>>16)&(CYCLE-1)] * 4)>>16)&16; refracttturb = ((r_turb_t + r_turb_turb[(r_turb_s>>16)&(CYCLE-1)] * 4)>>16)&16; temp = *(r_turb_pbase + (tturb<<6) + sturb); tempd3 = *(r_turb_pdest + ((refracttturb) + refractsturb >> pixsize)); // if ((*r_turb_pdest) < screenwidth) //screenwidth * pspan->v // tempd3 = *(r_turb_pdest + (int)((bumpmap[temp] - bumpmap[temp] /2)* (float)temp2->value)); // else // tempd3 = *(r_turb_pdest); temp3 = tempd3; if (foguse) *r_turb_pdest = foggmap[waterTable[temp][temp3]+ (ferg >> 2 & 0xFF00)]; else *r_turb_pdest = waterTable[temp][temp3]; } *r_turb_pdest++; izi += izistep; pz++; r_turb_s += r_turb_sstep; r_turb_t += r_turb_tstep; } while (--r_turb_spancount > 0); } void D_DrawTurbulent8SpanAlpha (void) { int sturb, tturb; unsigned char temp; do { if (*pz <= (izi >> 16)) { sturb = ((r_turb_s + r_turb_turb[(r_turb_t>>16)&(CYCLE-1)])>>16)&63; tturb = ((r_turb_t + r_turb_turb[(r_turb_s>>16)&(CYCLE-1)])>>16)&63; temp = *(r_turb_pbase + (tturb<<6) + sturb); if (foguse) *r_turb_pdest = foggmap[waterTable[temp][*r_turb_pdest]+ (ferg >> 2 & 0xFF00)]; else *r_turb_pdest = waterTable[temp][*r_turb_pdest]; } *r_turb_pdest++; izi += izistep; pz++; r_turb_s += r_turb_sstep; r_turb_t += r_turb_tstep; } while (--r_turb_spancount > 0); } // Leilei - this is very simple. void D_DrawGelWaterSpan (void) { do { if (*pz <= (izi >> 16)) { if (foguse) *r_turb_pdest = foggmap[menumap[*r_turb_pdest][gmcol] + (ferg >> 2 & 0xFF00)]; else *r_turb_pdest = menumap[*r_turb_pdest][gmcol]; } *r_turb_pdest++; izi += izistep; pz++; } while (--r_turb_spancount > 0); } void D_DrawGelWaterSpanRefractions (void) { int refsturb, reftturb; int refractsturb, refracttturb; int pixsize = 2; unsigned char temp, tempd2, tempd3, temp3, temp4; depthen = (depthen) >> 2; do { if (*pz <= (izi >> 16)) { refractsturb = ((r_turb_s + r_turb_turb[(r_turb_t>>16)&(CYCLE-1)] * 4)>>16)&16; refracttturb = ((r_turb_t + r_turb_turb[(r_turb_s>>16)&(CYCLE-1)] * 4)>>16)&16; tempd3 = transTable[*(r_turb_pdest + ((refracttturb)+refractsturb >> 2))][*(r_turb_pdest+((refractsturb) + refracttturb >> 2))]; temp3 = tempd3; if (foguse) *r_turb_pdest = foggmap[menumap[temp3][gmcol] + (ferg >> 2 & 0xFF00)]; else *r_turb_pdest = menumap[temp3][gmcol]; } *r_turb_pdest++; izi += izistep; pz++; r_turb_s += r_turb_sstep; r_turb_t += r_turb_tstep; } while (--r_turb_spancount > 0); } extern cvar_t *r_waterblend; /* ============= Turbulent8 ============= */ extern int waterinsight; // leilei - water pixel shader extern vec3_t reflectorg; // leilei - water reflection extern cvar_t *r_wateralpha; void Turbulent8 (espan_t *pspan) { int count; fixed16_t snext, tnext; float sdivz, tdivz, zi, z, du, dv, spancountminus1; float sdivz16stepu, tdivz16stepu, zi16stepu; int wb; int gelmode; int watqual; float zer; wb = (int)r_waterblend->value; if (wb == 3 || r_wateralpha->value < 1) gelmode = 1; // leilei - skip the turb crap when in gelmode watqual = (int)r_waterquality->value; r_turb_turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1)); r_turb_sstep = 0; // keep compiler happy r_turb_tstep = 0; // ditto r_turb_pbase = (unsigned char *)cacheblock; sdivz16stepu = d_sdivzstepu * 16; tdivz16stepu = d_tdivzstepu * 16; zi16stepu = d_zistepu * 16; // mk transwater - begin // we count on FP exceptions being turned off to avoid range problems izistep = (int)(d_zistepu * 0x8000 * 0x10000); izistep2 = izistep*2; // mk transwater - end // leilei - this is for the simple water // reuses our menu background tables to blend it // finds the nearest 'average' color from the color index if (wb == 3){ // old values: 57 (breaks e3m1 slime/teleport), // gmcol = r_turb_pbase[2836]; // sample a pixel (TODO: Average a pixel on load) if (gmcol < 16) gmcol = 0; else if (gmcol < 32) gmcol = 1; else if (gmcol < 48) gmcol = 2; else if (gmcol < 64) gmcol = 3; else if (gmcol < 80) gmcol = 4; else if (gmcol < 96) gmcol = 5; else if (gmcol < 112) gmcol = 6; else if (gmcol < 128) gmcol = 7; else if (gmcol < 144) gmcol = 8; else if (gmcol < 160) gmcol = 9; else if (gmcol < 176) gmcol = 10; else if (gmcol < 192) gmcol = 11; else if (gmcol < 208) gmcol = 12; else if (gmcol < 224) gmcol = 13; // stupid elses huh? else if (gmcol < 240) gmcol = 14; else gmcol = 2; // stupid. } do { r_turb_pdest = (unsigned char *)((byte *)d_viewbuffer + (screenwidth * pspan->v) + pspan->u); pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u; // mk - transwater count = pspan->count; // calculate the initial s/z, t/z, 1/z, s, and t and clamp du = (float)pspan->u; dv = (float)pspan->v; sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu; tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu; zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point // we count on FP exceptions being turned off to avoid range problems // mk transwoter izi = (int)(zi * 0x8000 * 0x10000); // mk transwarter r_turb_s = (int)(sdivz * z) + sadjust; if (r_turb_s > bbextents) r_turb_s = bbextents; else if (r_turb_s < 0) r_turb_s = 0; r_turb_t = (int)(tdivz * z) + tadjust; if (r_turb_t > bbextentt) r_turb_t = bbextentt; else if (r_turb_t < 0) r_turb_t = 0; do { // calculate s and t at the far end of the span if (count >= 16) r_turb_spancount = 16; else r_turb_spancount = count; count -= r_turb_spancount; if (count) { // calculate s/z, t/z, zi->fixed s and t at far end of span, // calculate s and t steps across span by shifting sdivz += sdivz16stepu; tdivz += tdivz16stepu; zi += zi16stepu; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point snext = (int)(sdivz * z) + sadjust; if (snext > bbextents) snext = bbextents; else if (snext < 16) snext = 16; // prevent round-off error on <0 steps from // from causing overstepping & running off the // edge of the texture tnext = (int)(tdivz * z) + tadjust; if (tnext > bbextentt) tnext = bbextentt; else if (tnext < 16) tnext = 16; // guard against round-off error on <0 steps r_turb_sstep = (snext - r_turb_s) >> 4; r_turb_tstep = (tnext - r_turb_t) >> 4; } else { // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so // can't step off polygon), clamp, calculate s and t steps across // span by division, biasing steps low so we don't run off the // texture spancountminus1 = (float)(r_turb_spancount - 1); sdivz += d_sdivzstepu * spancountminus1; tdivz += d_tdivzstepu * spancountminus1; zi += d_zistepu * spancountminus1; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point snext = (int)(sdivz * z) + sadjust; if (snext > bbextents) snext = bbextents; else if (snext < 16) snext = 16; // prevent round-off error on <0 steps from // from causing overstepping & running off the // edge of the texture tnext = (int)(tdivz * z) + tadjust; if (tnext > bbextentt) tnext = bbextentt; else if (tnext < 16) tnext = 16; // guard against round-off error on <0 steps if (r_turb_spancount > 1) { r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1); r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1); } } r_turb_s = r_turb_s & ((CYCLE<<16)-1); r_turb_t = r_turb_t & ((CYCLE<<16)-1); if (foguse){ ferg = (int)(z / 1024); if (ferg > 32762) ferg = 32762; } // leilei - fog depthen = (int)z / 1024; // skip_turb: // mk transwater begin // leilei modified this to accomodate our waterTable // TODO: for hlbsp, use the rendertype/renderamt stuff // and add/transtable instead of watertable if (r_wateralpha->value < 1){ if (r_drawwater){ if (watqual){ if (wb == 3){ D_DrawGelWaterSpanRefractions (); } else{ D_DrawTurbulent8SpanAlphaRefractions (); } } else { if (wb == 3){ D_DrawGelWaterSpan (); } else{ D_DrawTurbulent8SpanAlpha (); } } } } else { if (foguse){ D_DrawTurbulent8Span_Fog (); } else { D_DrawTurbulent8Span (); } } r_turb_s = snext; r_turb_t = tnext; } while (count > 0); } while ((pspan = pspan->pnext) != NULL); } #if !id386 /* ============= D_DrawSpans8 ============= */ void D_DrawSpans8 (espan_t *pspan) { int count, spancount; unsigned char *pbase, *pdest; fixed16_t s, t, snext, tnext, sstep, tstep; float sdivz, tdivz, zi, z, du, dv, spancountminus1; float sdivz8stepu, tdivz8stepu, zi8stepu; sstep = 0; // keep compiler happy tstep = 0; // ditto pbase = (unsigned char *)cacheblock; sdivz8stepu = d_sdivzstepu * 8; tdivz8stepu = d_tdivzstepu * 8; zi8stepu = d_zistepu * 8; do { pdest = (unsigned char *)((byte *)d_viewbuffer + (screenwidth * pspan->v) + pspan->u); count = pspan->count; // calculate the initial s/z, t/z, 1/z, s, and t and clamp du = (float)pspan->u; dv = (float)pspan->v; sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu; tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu; zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point s = (int)(sdivz * z) + sadjust; if (s > bbextents) s = bbextents; else if (s < 0) s = 0; t = (int)(tdivz * z) + tadjust; if (t > bbextentt) t = bbextentt; else if (t < 0) t = 0; do { // calculate s and t at the far end of the span if (count >= 8) spancount = 8; else spancount = count; count -= spancount; if (count) { // calculate s/z, t/z, zi->fixed s and t at far end of span, // calculate s and t steps across span by shifting sdivz += sdivz8stepu; tdivz += tdivz8stepu; zi += zi8stepu; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point snext = (int)(sdivz * z) + sadjust; if (snext > bbextents) snext = bbextents; else if (snext < 8) snext = 8; // prevent round-off error on <0 steps from // from causing overstepping & running off the // edge of the texture tnext = (int)(tdivz * z) + tadjust; if (tnext > bbextentt) tnext = bbextentt; else if (tnext < 8) tnext = 8; // guard against round-off error on <0 steps sstep = (snext - s) >> 3; tstep = (tnext - t) >> 3; } else { // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so // can't step off polygon), clamp, calculate s and t steps across // span by division, biasing steps low so we don't run off the // texture spancountminus1 = (float)(spancount - 1); sdivz += d_sdivzstepu * spancountminus1; tdivz += d_tdivzstepu * spancountminus1; zi += d_zistepu * spancountminus1; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point snext = (int)(sdivz * z) + sadjust; if (snext > bbextents) snext = bbextents; else if (snext < 8) snext = 8; // prevent round-off error on <0 steps from // from causing overstepping & running off the // edge of the texture tnext = (int)(tdivz * z) + tadjust; if (tnext > bbextentt) tnext = bbextentt; else if (tnext < 8) tnext = 8; // guard against round-off error on <0 steps if (spancount > 1) { sstep = (snext - s) / (spancount - 1); tstep = (tnext - t) / (spancount - 1); } } pdest += spancount; switch (spancount) { case 8: pdest[-8] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 7: pdest[-7] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 6: pdest[-6] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 5: pdest[-5] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 4: pdest[-4] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 3: pdest[-3] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 2: pdest[-2] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 1: pdest[-1] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; } s = snext; t = tnext; } while (count > 0); } while ((pspan = pspan->pnext) != NULL); } #endif /* ============= D_DrawSpans qbism/mh ============= */ void D_DrawSpans16_C (espan_t *pspan) //qbism up it from 8 to 16. This + unroll = big speed gain! { int count, spancount; unsigned char *pbase, *pdest; fixed16_t s, t, snext, tnext, sstep, tstep; float sdivz, tdivz, zi, z, du, dv, spancountminus1; float sdivzstepu, tdivzstepu, zistepu; int forg= 0; // leilei - fog // float zf; // leilei - fog // int fogcount, fogcount2; // leilei - fog int beep = 512; int boop = 512; int feg = 0; sstep = 0; // keep compiler happy tstep = 0; // ditto pbase = (unsigned char *)cacheblock; sdivzstepu = d_sdivzstepu * 16; tdivzstepu = d_tdivzstepu * 16; zistepu = d_zistepu * 16; do { pdest = (unsigned char *)((byte *)d_viewbuffer + (screenwidth * pspan->v) + pspan->u); count = pspan->count; // fogcount2 = count; // calculate the initial s/z, t/z, 1/z, s, and t and clamp du = (float)pspan->u; dv = (float)pspan->v; sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu; tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu; zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point s = (int)(sdivz * z) + sadjust; if (s > bbextents) s = bbextents; else if (s < 0) s = 0; t = (int)(tdivz * z) + tadjust; if (t > bbextentt) t = bbextentt; else if (t < 0) t = 0; do { // calculate s and t at the far end of the span spancount = count > 15 ? 16 : count; // mh count -= spancount; if (count) { // calculate s/z, t/z, zi->fixed s and t at far end of span, // calculate s and t steps across span by shifting sdivz += sdivzstepu; tdivz += tdivzstepu; zi += zistepu; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point snext = (int)(sdivz * z) + sadjust; if (snext > bbextents) snext = bbextents; else if (snext <= 16) snext = 16; // prevent round-off error on <0 steps from // from causing overstepping & running off the // edge of the texture feg++; tnext = (int)(tdivz * z) + tadjust; if (tnext > bbextentt) tnext = bbextentt; else if (tnext < 16) tnext = 16; // guard against round-off error on <0 steps sstep = (snext - s) >> 4; tstep = (tnext - t) >> 4; feg++; if (foguse){ int te; forg = (int)(z / 1024); if (forg > 32762) forg = 32762; } // leilei - fog } else { // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so // can't step off polygon), clamp, calculate s and t steps across // span by division, biasing steps low so we don't run off the // texture spancountminus1 = (float)(spancount - 1); sdivz += d_sdivzstepu * spancountminus1; tdivz += d_tdivzstepu * spancountminus1; zi += d_zistepu * spancountminus1; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point snext = (int)(sdivz * z) + sadjust; if (snext > bbextents) snext = bbextents; else if (snext < 16) snext = 16; // prevent round-off error on <0 steps from // from causing overstepping & running off the // edge of the texture tnext = (int)(tdivz * z) + tadjust; if (tnext > bbextentt) tnext = bbextentt; else if (tnext < 16) tnext = 16; // guard against round-off error on <0 steps if (spancount > 1) { sstep = (snext - s) / (spancount - 1); tstep = (tnext - t) / (spancount - 1); } feg++; } if (foguse){ int te; forg = (int)(z / 1024); if (forg > 32762) forg = 32762; } // leilei - fog //qbism- Duff's Device loop unroll per mh. pdest += spancount; if (foguse){ switch (spancount) { case 16: pdest[-16] = foggmap[pbase[(s >> 16) + (t >> 16) * cachewidth] + (forg >> 2 & 0xFF00)]; s += sstep; t += tstep; case 15: pdest[-15] = foggmap[pbase[(s >> 16) + (t >> 16) * cachewidth] + (forg + 512 >> 2 & 0xFF00)]; s += sstep; t += tstep; case 14: pdest[-14] = foggmap[pbase[(s >> 16) + (t >> 16) * cachewidth] + (forg >> 2 & 0xFF00)]; s += sstep; t += tstep; case 13: pdest[-13] = foggmap[pbase[(s >> 16) + (t >> 16) * cachewidth] + (forg + 512 >> 2 & 0xFF00)]; s += sstep; t += tstep; case 12: pdest[-12] = foggmap[pbase[(s >> 16) + (t >> 16) * cachewidth] + (forg >> 2 & 0xFF00)]; s += sstep; t += tstep; case 11: pdest[-11] = foggmap[pbase[(s >> 16) + (t >> 16) * cachewidth] + (forg + 512 >> 2 & 0xFF00)]; s += sstep; t += tstep; case 10: pdest[-10] = foggmap[pbase[(s >> 16) + (t >> 16) * cachewidth] + (forg >> 2 & 0xFF00)]; s += sstep; t += tstep; case 9: pdest[-9] = foggmap[pbase[(s >> 16) + (t >> 16) * cachewidth] + (forg + 512 >> 2 & 0xFF00)]; s += sstep; t += tstep; case 8: pdest[-8] = foggmap[pbase[(s >> 16) + (t >> 16) * cachewidth] + (forg >> 2 & 0xFF00)]; s += sstep; t += tstep; case 7: pdest[-7] = foggmap[pbase[(s >> 16) + (t >> 16) * cachewidth] + (forg + 512 >> 2 & 0xFF00)]; s += sstep; t += tstep;; case 6: pdest[-6] = foggmap[pbase[(s >> 16) + (t >> 16) * cachewidth] + (forg >> 2 & 0xFF00)]; s += sstep; t += tstep; case 5: pdest[-5] = foggmap[pbase[(s >> 16) + (t >> 16) * cachewidth] + (forg + 512 >> 2 & 0xFF00)]; s += sstep; t += tstep; case 4: pdest[-4] = foggmap[pbase[(s >> 16) + (t >> 16) * cachewidth] + (forg >> 2 & 0xFF00)]; s += sstep; t += tstep; case 3: pdest[-3] = foggmap[pbase[(s >> 16) + (t >> 16) * cachewidth] + (forg + 512 >> 2 & 0xFF00)]; s += sstep; t += tstep; case 2: pdest[-2] = foggmap[pbase[(s >> 16) + (t >> 16) * cachewidth] + (forg >> 2 & 0xFF00)]; s += sstep; t += tstep; case 1: pdest[-1] = foggmap[pbase[(s >> 16) + (t >> 16) * cachewidth] + (forg + 512 >> 2 & 0xFF00)]; s += sstep; t += tstep; } } else { switch (spancount) { case 16: pdest[-16] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 15: pdest[-15] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 14: pdest[-14] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 13: pdest[-13] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 12: pdest[-12] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 11: pdest[-11] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 10: pdest[-10] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 9: pdest[-9] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 8: pdest[-8] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 7: pdest[-7] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 6: pdest[-6] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 5: pdest[-5] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 4: pdest[-4] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 3: pdest[-3] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 2: pdest[-2] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 1: pdest[-1] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; } } s = snext; t = tnext; if(beep){ boop =512; beep = 0; } else if(boop){ beep =512; boop = 0; } } while (count > 0); } while ((pspan = pspan->pnext) != NULL); } void D_DrawSpansBlank (espan_t *pspan) //Blank version { int count, spancount; unsigned char *pbase, *pdest; fixed16_t s, t, snext, tnext, sstep, tstep; float sdivz, tdivz, zi, z, du, dv, spancountminus1; float sdivzstepu, tdivzstepu, zistepu; sstep = 0; // keep compiler happy tstep = 0; // ditto pbase = (unsigned char *)cacheblock; sdivzstepu = d_sdivzstepu * 16; tdivzstepu = d_tdivzstepu * 16; zistepu = d_zistepu * 16; do { pdest = (unsigned char *)((byte *)d_viewbuffer + (screenwidth * pspan->v) + pspan->u); count = pspan->count; // calculate the initial s/z, t/z, 1/z, s, and t and clamp du = (float)pspan->u; dv = (float)pspan->v; sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu; tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu; zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point s = (int)(sdivz * z) + sadjust; if (s > bbextents) s = bbextents; else if (s < 0) s = 0; t = (int)(tdivz * z) + tadjust; if (t > bbextentt) t = bbextentt; else if (t < 0) t = 0; do { // calculate s and t at the far end of the span spancount = count > 15 ? 16 : count; // mh count -= spancount; if (count) { // calculate s/z, t/z, zi->fixed s and t at far end of span, // calculate s and t steps across span by shifting sdivz += sdivzstepu; tdivz += tdivzstepu; zi += zistepu; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point snext = (int)(sdivz * z) + sadjust; if (snext > bbextents) snext = bbextents; else if (snext <= 16) snext = 16; // prevent round-off error on <0 steps from // from causing overstepping & running off the // edge of the texture tnext = (int)(tdivz * z) + tadjust; if (tnext > bbextentt) tnext = bbextentt; else if (tnext < 16) tnext = 16; // guard against round-off error on <0 steps sstep = (snext - s) >> 4; tstep = (tnext - t) >> 4; } else { // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so // can't step off polygon), clamp, calculate s and t steps across // span by division, biasing steps low so we don't run off the // texture spancountminus1 = (float)(spancount - 1); sdivz += d_sdivzstepu * spancountminus1; tdivz += d_tdivzstepu * spancountminus1; zi += d_zistepu * spancountminus1; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point snext = (int)(sdivz * z) + sadjust; if (snext > bbextents) snext = bbextents; else if (snext < 16) snext = 16; // prevent round-off error on <0 steps from // from causing overstepping & running off the // edge of the texture tnext = (int)(tdivz * z) + tadjust; if (tnext > bbextentt) tnext = bbextentt; else if (tnext < 16) tnext = 16; // guard against round-off error on <0 steps if (spancount > 1) { sstep = (snext - s) / (spancount - 1); tstep = (tnext - t) / (spancount - 1); } } //qbism- Duff's Device loop unroll per mh. pdest += spancount; switch (spancount) { case 16: pdest[-16] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 15: pdest[-15] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 14: pdest[-14] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 13: pdest[-13] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 12: pdest[-12] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 11: pdest[-11] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 10: pdest[-10] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 9: pdest[-9] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 8: pdest[-8] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 7: pdest[-7] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 6: pdest[-6] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 5: pdest[-5] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 4: pdest[-4] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 3: pdest[-3] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 2: pdest[-2] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; case 1: pdest[-1] = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; } s = snext; t = tnext; } while (count > 0); } while ((pspan = pspan->pnext) != NULL); } /* ============= D_DrawSpans qbism/mh ============= */ /* ============= D_DrawSpans8_C_Filter Code adapted from Fabien Sanglard's Quake2 port adds filtering from https://github.com/fabiensanglard/Quake-2/tree/master/ref_soft ============= */ int kernel[2][2][2] = { { {16384, 0}, {49152, 16384} }, { {32768, 49152}, {0, 32768} } }; int gernel[2][11][2] = { { {16384, 0}, {16384, 32}, {16384, 64}, {16384, 128}, {16384, 256}, {49152, 512}, {49152, 1024}, {49152, 2048}, {49152, 4096}, {49152, 8192}, {49152, 16384} }, { {32768, 49152}, {0, 32768} } }; void D_DrawSpans8_C_Filter (espan_t *pspan) { int count, spancount; unsigned char *pbase, *pdest; fixed16_t s, t, snext, tnext, sstep, tstep; float sdivz, tdivz, zi, z, du, dv, spancountminus1; float sdivz8stepu, tdivz8stepu, zi8stepu; int forg; // leilei - fog sstep = 0; // keep compiler happy tstep = 0; // ditto pbase = (unsigned char *)cacheblock; sdivz8stepu = d_sdivzstepu * 8; tdivz8stepu = d_tdivzstepu * 8; zi8stepu = d_zistepu * 8; do { pdest = (unsigned char *)((byte *)d_viewbuffer + (screenwidth * pspan->v) + pspan->u); count = pspan->count; // calculate the initial s/z, t/z, 1/z, s, and t and clamp du = (float)pspan->u; dv = (float)pspan->v; sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu; tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu; zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point s = (int)(sdivz * z) + sadjust; if (s > bbextents) s = bbextents; else if (s < 0) s = 0; t = (int)(tdivz * z) + tadjust; if (t > bbextentt) t = bbextentt; else if (t < 0) t = 0; do { // calculate s and t at the far end of the span spancount = count > 7 ? 8 : count; // mh count -= spancount; if (count) { // calculate s/z, t/z, zi->fixed s and t at far end of span, // calculate s and t steps across span by shifting sdivz += sdivz8stepu; tdivz += tdivz8stepu; zi += zi8stepu; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point snext = (int)(sdivz * z) + sadjust; if (snext > bbextents) snext = bbextents; else if (snext < 8) snext = 8; // prevent round-off error on <0 steps from // from causing overstepping & running off the // edge of the texture tnext = (int)(tdivz * z) + tadjust; if (tnext > bbextentt) tnext = bbextentt; else if (tnext < 8) tnext = 8; // guard against round-off error on <0 steps sstep = (snext - s) >> 3; tstep = (tnext - t) >> 3; } else { // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so // can't step off polygon), clamp, calculate s and t steps across // span by division, biasing steps low so we don't run off the // texture spancountminus1 = (float)(spancount - 1); sdivz += d_sdivzstepu * spancountminus1; tdivz += d_tdivzstepu * spancountminus1; zi += d_zistepu * spancountminus1; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point snext = (int)(sdivz * z) + sadjust; if (snext > bbextents) snext = bbextents; else if (snext < 8) snext = 8; // prevent round-off error on <0 steps from // from causing overstepping & running off the // edge of the texture tnext = (int)(tdivz * z) + tadjust; if (tnext > bbextentt) tnext = bbextentt; else if (tnext < 8) tnext = 8; // guard against round-off error on <0 steps if (spancount > 1) { sstep = (snext - s) / (spancount - 1); tstep = (tnext - t) / (spancount - 1); } } if (foguse){ forg = (int)(z / 1024); if (forg > 32762) forg = 32762; } // leilei - fog do { int idiths = s; int iditht = t; int X = (pspan->u + spancount) & 1; int Y = (pspan->v)&1; idiths += kernel[X][Y][0]; iditht += kernel[X][Y][1]; idiths = idiths >> 16; idiths = idiths ? idiths -1 : idiths; iditht = iditht >> 16; iditht = iditht ? iditht -1 : iditht; *pdest++ = *(pbase + idiths + iditht * cachewidth); s += sstep; t += tstep; } while (--spancount > 0); s = snext; t = tnext; } while (count > 0); } while ((pspan = pspan->pnext) != NULL); } // leilei experimental rendering #ifdef EXPREND void D_DrawDeferredSpans8_C (espan_t *pspan) { int count, spancount; unsigned char *pbase, *pdest, *pshadow; fixed16_t s, t, snext, tnext, sstep, tstep; float sdivz, tdivz, zi, z, du, dv, spancountminus1; float sdivz8stepu, tdivz8stepu, zi8stepu; int forg; // leilei - fog sstep = 0; // keep compiler happy tstep = 0; // ditto pbase = (unsigned char *)cacheblock; sdivz8stepu = d_sdivzstepu * 8; tdivz8stepu = d_tdivzstepu * 8; zi8stepu = d_zistepu * 8; do { // pdest = (unsigned char *)((byte *)d_viewbuffer + // (screenwidth * pspan->v) + pspan->u); pdest = (unsigned char *)((byte *)d_shadowbuffer + (screenwidth * pspan->v) + pspan->u); count = pspan->count; // calculate the initial s/z, t/z, 1/z, s, and t and clamp du = (float)pspan->u; dv = (float)pspan->v; sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu; tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu; zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point s = (int)(sdivz * z) + sadjust; if (s > bbextents) s = bbextents; else if (s < 0) s = 0; t = (int)(tdivz * z) + tadjust; if (t > bbextentt) t = bbextentt; else if (t < 0) t = 0; do { // calculate s and t at the far end of the span spancount = count > 7 ? 8 : count; // mh count -= spancount; if (count) { // calculate s/z, t/z, zi->fixed s and t at far end of span, // calculate s and t steps across span by shifting sdivz += sdivz8stepu; tdivz += tdivz8stepu; zi += zi8stepu; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point snext = (int)(sdivz * z) + sadjust; if (snext > bbextents) snext = bbextents; else if (snext < 8) snext = 8; // prevent round-off error on <0 steps from // from causing overstepping & running off the // edge of the texture tnext = (int)(tdivz * z) + tadjust; if (tnext > bbextentt) tnext = bbextentt; else if (tnext < 8) tnext = 8; // guard against round-off error on <0 steps sstep = (snext - s) >> 3; tstep = (tnext - t) >> 3; } else { // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so // can't step off polygon), clamp, calculate s and t steps across // span by division, biasing steps low so we don't run off the // texture spancountminus1 = (float)(spancount - 1); sdivz += d_sdivzstepu * spancountminus1; tdivz += d_tdivzstepu * spancountminus1; zi += d_zistepu * spancountminus1; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point snext = (int)(sdivz * z) + sadjust; if (snext > bbextents) snext = bbextents; else if (snext < 8) snext = 8; // prevent round-off error on <0 steps from // from causing overstepping & running off the // edge of the texture tnext = (int)(tdivz * z) + tadjust; if (tnext > bbextentt) tnext = bbextentt; else if (tnext < 8) tnext = 8; // guard against round-off error on <0 steps if (spancount > 1) { sstep = (snext - s) / (spancount - 1); tstep = (tnext - t) / (spancount - 1); } } if (foguse){ forg = (int)(z / 1024); if (forg > 32762) forg = 32762; } // leilei - fog do { int idiths = s; int iditht = t; int X = (pspan->u + spancount) & 1; int Y = (pspan->v)&1; idiths += kernel[X][Y][0]; iditht += kernel[X][Y][1]; idiths = idiths >> 16; idiths = idiths ? idiths -1 : idiths; iditht = iditht >> 16; iditht = iditht ? iditht -1 : iditht; *pdest++ = *(pbase + idiths + iditht * cachewidth); s += sstep; t += tstep; } while (--spancount > 0); s = snext; t = tnext; } while (count > 0); } while ((pspan = pspan->pnext) != NULL); } #endif // leilei experiment void D_DrawSpans8_C_FilterAlter (espan_t *pspan) { int count, spancount; unsigned char *pbase, *pdest; fixed16_t s, t, snext, tnext, sstep, tstep; float sdivz, tdivz, zi, z, du, dv, spancountminus1; float sdivz8stepu, tdivz8stepu, zi8stepu; int forg; // leilei - fog sstep = 0; // keep compiler happy tstep = 0; // ditto pbase = (unsigned char *)cacheblock; sdivz8stepu = d_sdivzstepu * 8; tdivz8stepu = d_tdivzstepu * 8; zi8stepu = d_zistepu * 8; do { pdest = (unsigned char *)((byte *)d_viewbuffer + (screenwidth * pspan->v) + pspan->u); count = pspan->count; // calculate the initial s/z, t/z, 1/z, s, and t and clamp du = (float)pspan->u; dv = (float)pspan->v; sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu; tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu; zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point s = (int)(sdivz * z) + sadjust; if (s > bbextents) s = bbextents; else if (s < 0) s = 0; t = (int)(tdivz * z) + tadjust; if (t > bbextentt) t = bbextentt; else if (t < 0) t = 0; do { // calculate s and t at the far end of the span spancount = count > 7 ? 8 : count; // mh count -= spancount; if (count) { // calculate s/z, t/z, zi->fixed s and t at far end of span, // calculate s and t steps across span by shifting sdivz += sdivz8stepu; tdivz += tdivz8stepu; zi += zi8stepu; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point snext = (int)(sdivz * z) + sadjust; if (snext > bbextents) snext = bbextents; else if (snext < 8) snext = 8; // prevent round-off error on <0 steps from // from causing overstepping & running off the // edge of the texture tnext = (int)(tdivz * z) + tadjust; if (tnext > bbextentt) tnext = bbextentt; else if (tnext < 8) tnext = 8; // guard against round-off error on <0 steps sstep = (snext - s) >> 3; tstep = (tnext - t) >> 3; } else { // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so // can't step off polygon), clamp, calculate s and t steps across // span by division, biasing steps low so we don't run off the // texture spancountminus1 = (float)(spancount - 1); sdivz += d_sdivzstepu * spancountminus1; tdivz += d_tdivzstepu * spancountminus1; zi += d_zistepu * spancountminus1; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point snext = (int)(sdivz * z) + sadjust; if (snext > bbextents) snext = bbextents; else if (snext < 8) snext = 8; // prevent round-off error on <0 steps from // from causing overstepping & running off the // edge of the texture tnext = (int)(tdivz * z) + tadjust; if (tnext > bbextentt) tnext = bbextentt; else if (tnext < 8) tnext = 8; // guard against round-off error on <0 steps if (spancount > 1) { sstep = (snext - s) / (spancount - 1); tstep = (tnext - t) / (spancount - 1); } } if (foguse){ forg = (int)(z / 1024); if (forg > 32762) forg = 32762; } // leilei - fog do { int idiths = s; int iditht = t; int there; int teem = temp2->value; int X = (pspan->u + spancount) & 1; int Y = (pspan->v)&1; idiths += kernel[X][Y][0]; iditht += kernel[X][Y][1]; // idiths += noisetable[X>>teem][Y]; // iditht += noisetable[Y<> 16; // idiths = idiths ? idiths -teem : idiths; // there = teem >> 16; iditht = iditht >> 16; // iditht = iditht ? iditht -teem : iditht; *pdest++ = *(pbase + 0 * cachewidth); s += sstep; t += tstep; } while (--spancount > 0); s = snext; t = tnext; } while (count > 0); } while ((pspan = pspan->pnext) != NULL); } extern qboolean r_dowarp; extern int r_docrap; extern byte *r_warpbuffer; /* ============= D_DrawSpans16_C_Filter Code adapted from Fabien Sanglard's Quake2 port adds filtering from https://github.com/fabiensanglard/Quake-2/tree/master/ref_soft ============= */ // leilei - macrofying attempt......... #define SurfaceSpancount16(i) { switch (spancount) { case 16: i(16); case 15: i(15); case 14: i(14); case 13: i(13); case 12: i(12); case 11: i(11); case 10: i(10); case 9: i(9); case 8: i(8); case 7: i(7); case 6: i(6); case 5: i(5); case 4: i(4); case 3: i(3); case 2: i(2); case 1: i(1); } } void D_DrawSpans16_C_Filter (espan_t *pspan) //qbism- up it from 8 to 16 { int count, spancount; unsigned char *pbase, *pdest; fixed16_t s, t, snext, tnext, sstep, tstep; float sdivz, tdivz, zi, z, du, dv, spancountminus1; float sdivzstepu, tdivzstepu, zistepu; int idiths, iditht, X, Y; // filter stuff int forg= 0; // leilei - fog int beep, boop, bap; int fogra = 0; sstep = 0; // keep compiler happy tstep = 0; // ditto pbase = (unsigned char *)cacheblock; sdivzstepu = d_sdivzstepu * 16; tdivzstepu = d_tdivzstepu * 16; zistepu = d_zistepu * 16; bap = 1; do { pdest = (unsigned char *)((byte *)d_viewbuffer + (screenwidth * pspan->v) + pspan->u); count = pspan->count; // calculate the initial s/z, t/z, 1/z, s, and t and clamp du = (float)pspan->u; dv = (float)pspan->v; sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu; tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu; zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point s = (int)(sdivz * z) + sadjust; if (s > bbextents) s = bbextents; else if (s < 0) s = 0; t = (int)(tdivz * z) + tadjust; if (t > bbextentt) t = bbextentt; else if (t < 0) t = 0; do { // calculate s and t at the far end of the span spancount = count > 15 ? 16 : count; // mh count -= spancount; if (count) { // calculate s/z, t/z, zi->fixed s and t at far end of span, // calculate s and t steps across span by shifting sdivz += sdivzstepu; tdivz += tdivzstepu; zi += zistepu; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point snext = (int)(sdivz * z) + sadjust; if (snext > bbextents) snext = bbextents; else if (snext <= 16) snext = 16; // prevent round-off error on <0 steps from // from causing overstepping & running off the // edge of the texture tnext = (int)(tdivz * z) + tadjust; if (tnext > bbextentt) tnext = bbextentt; else if (tnext < 16) tnext = 16; // guard against round-off error on <0 steps sstep = (snext - s) >> 4; tstep = (tnext - t) >> 4; bap *= -1; } else { // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so // can't step off polygon), clamp, calculate s and t steps across // span by division, biasing steps low so we don't run off the // texture spancountminus1 = (float)(spancount - 1); sdivz += d_sdivzstepu * spancountminus1; tdivz += d_tdivzstepu * spancountminus1; zi += d_zistepu * spancountminus1; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point snext = (int)(sdivz * z) + sadjust; if (snext > bbextents) snext = bbextents; else if (snext < 16) snext = 16; // prevent round-off error on <0 steps from // from causing overstepping & running off the // edge of the texture tnext = (int)(tdivz * z) + tadjust; if (tnext > bbextentt) tnext = bbextentt; else if (tnext < 16) tnext = 16; // guard against round-off error on <0 steps if (spancount > 1) { sstep = (snext - s) / (spancount - 1); tstep = (tnext - t) / (spancount - 1); } bap *= -1; } if (foguse){ forg = (int)((float)0x10000 / zi / 1024); if (forg > 32762) forg = 32762; } beep = 0; boop = 256 * bap; // if spans are far apart, filter. pdest += spancount; #define SUBDIV16FILTERFOG(i) { idiths = s; iditht = t; X = (pspan->u + i) & 1; Y = (pspan->v)& 1; idiths += kernel[X][Y][0]; iditht += kernel[X][Y][1]; idiths = idiths >> 16; idiths = idiths ? idiths -1: idiths; iditht = iditht >> 16; iditht = iditht ? iditht -1 : iditht; pdest[-i] = foggmap[*(pbase + idiths + iditht * cachewidth) + (forg + boop >> 2 & 0xFF00)]; s += sstep; t += tstep; boop *= -1; } #define SUBDIV16FILTERFOGDITHER(i) { idiths = s; iditht = t; X = (pspan->u + i) & 1; Y = (pspan->v)& 1; idiths += kernel[X][Y][0]; iditht += kernel[X][Y][1]; idiths = idiths >> 16; idiths = idiths ? idiths -1: idiths; iditht = iditht >> 16; iditht = iditht ? iditht -1 : iditht; pdest[-i] = foggmap[*(pbase + idiths + iditht * cachewidth) + (smoothtable[forg][i] >> 2 & 0xFF00)]; s += sstep; t += tstep; } #define SUBDIV16FILTERNOFOG(i) { idiths = s; iditht = t; X = (pspan->u + i) & 1; Y = (pspan->v)& 1; idiths += kernel[X][Y][0]; iditht += kernel[X][Y][1]; idiths = idiths >> 16; idiths = idiths ? idiths -1: idiths; iditht = iditht >> 16; iditht = iditht ? iditht -1 : iditht; pdest[-i] = *(pbase + idiths + iditht * cachewidth); s += sstep; t += tstep; } if (foguse == 2){ SurfaceSpancount16(SUBDIV16FILTERFOGDITHER); } else if (foguse){ SurfaceSpancount16(SUBDIV16FILTERFOG); } else{ SurfaceSpancount16(SUBDIV16FILTERNOFOG); } s = snext; t = tnext; // if(beep){ boop =256; beep = 0; } // else if(boop){ beep =256; boop = 0; } } while (count > 0); } while ((pspan = pspan->pnext) != NULL); } void D_DrawSpans16_C_Filter_64 (espan_t *pspan) //qbism- up it from 8 to 16 { int count, spancount; unsigned char *pbase, *pdest; fixed16_t s, t, snext, tnext, sstep, tstep; float sdivz, tdivz, zi, z, du, dv, spancountminus1; float sdivzstepu, tdivzstepu, zistepu; int idiths, iditht, X, Y; // filter stuff int forg= 0; // leilei - fog int beep, boop, bap; int fogra = 0; sstep = 0; // keep compiler happy tstep = 0; // ditto pbase = (unsigned char *)cacheblock; sdivzstepu = d_sdivzstepu * 16; tdivzstepu = d_tdivzstepu * 16; zistepu = d_zistepu * 16; bap = 1; do { pdest = (unsigned char *)((byte *)d_viewbuffer + (screenwidth * pspan->v) + pspan->u); count = pspan->count; // calculate the initial s/z, t/z, 1/z, s, and t and clamp du = (float)pspan->u; dv = (float)pspan->v; sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu; tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu; zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point s = (int)(sdivz * z) + sadjust; if (s > bbextents) s = bbextents; else if (s < 0) s = 0; t = (int)(tdivz * z) + tadjust; if (t > bbextentt) t = bbextentt; else if (t < 0) t = 0; do { // calculate s and t at the far end of the span spancount = count > 15 ? 16 : count; // mh count -= spancount; if (count) { // calculate s/z, t/z, zi->fixed s and t at far end of span, // calculate s and t steps across span by shifting sdivz += sdivzstepu; tdivz += tdivzstepu; zi += zistepu; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point snext = (int)(sdivz * z) + sadjust; if (snext > bbextents) snext = bbextents; else if (snext <= 16) snext = 16; // prevent round-off error on <0 steps from // from causing overstepping & running off the // edge of the texture tnext = (int)(tdivz * z) + tadjust; if (tnext > bbextentt) tnext = bbextentt; else if (tnext < 16) tnext = 16; // guard against round-off error on <0 steps sstep = (snext - s) >> 4; tstep = (tnext - t) >> 4; bap *= -1; } else { // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so // can't step off polygon), clamp, calculate s and t steps across // span by division, biasing steps low so we don't run off the // texture spancountminus1 = (float)(spancount - 1); sdivz += d_sdivzstepu * spancountminus1; tdivz += d_tdivzstepu * spancountminus1; zi += d_zistepu * spancountminus1; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point snext = (int)(sdivz * z) + sadjust; if (snext > bbextents) snext = bbextents; else if (snext < 16) snext = 16; // prevent round-off error on <0 steps from // from causing overstepping & running off the // edge of the texture tnext = (int)(tdivz * z) + tadjust; if (tnext > bbextentt) tnext = bbextentt; else if (tnext < 16) tnext = 16; // guard against round-off error on <0 steps if (spancount > 1) { sstep = (snext - s) / (spancount - 1); tstep = (tnext - t) / (spancount - 1); } bap *= -1; } if (foguse){ forg = (int)((float)0x10000 / zi / 1024); if (forg > 32762) forg = 32762; } beep = 0; boop = 256 * bap; // if spans are far apart, filter. pdest += spancount; #define SUBDIV1664FILTERFOG(i) { idiths = s; iditht = t; X = (pspan->u + i) & 1; Y = (pspan->v)& 1; idiths += kernel[X][Y][0]; iditht += kernel[X][Y][0]; idiths = idiths >> 16; idiths = idiths ? idiths -1: idiths; iditht = iditht >> 16; iditht = iditht ? iditht -1 : iditht; pdest[-i] = foggmap[*(pbase + idiths + iditht * cachewidth) + (forg + boop >> 2 & 0xFF00)]; s += sstep; t += tstep; boop *= -1; } #define SUBDIV1664FILTERFOGDITHER(i) { idiths = s; iditht = t; X = (pspan->u + i) & 1; Y = (pspan->v)& 1; idiths += kernel[X][Y][0]; iditht += kernel[X][Y][0]; idiths = idiths >> 16; idiths = idiths ? idiths -1: idiths; iditht = iditht >> 16; iditht = iditht ? iditht -1 : iditht; pdest[-i] = foggmap[*(pbase + idiths + iditht * cachewidth) + (smoothtable[forg][i] >> 2 & 0xFF00)]; s += sstep; t += tstep; } #define SUBDIV1664FILTERNOFOG(i) { idiths = s; iditht = t; X = (pspan->u + i) & 1; Y = (pspan->v)& 1; idiths += kernel[X][Y][0]; iditht += kernel[X][Y][0]; idiths = idiths >> 16; idiths = idiths ? idiths -1: idiths; iditht = iditht >> 16; iditht = iditht ? iditht -1 : iditht; pdest[-i] = *(pbase + idiths + iditht * cachewidth); s += sstep; t += tstep; } if (foguse == 2){ SurfaceSpancount16(SUBDIV1664FILTERFOGDITHER); } else if (foguse){ SurfaceSpancount16(SUBDIV1664FILTERFOG); } else{ SurfaceSpancount16(SUBDIV1664FILTERNOFOG); } s = snext; t = tnext; // if(beep){ boop =256; beep = 0; } // else if(boop){ beep =256; boop = 0; } } while (count > 0); } while ((pspan = pspan->pnext) != NULL); } void D_DrawSpans16_C_Dither (espan_t *pspan) //qbism up it from 8 to 16. This + unroll = big speed gain! { int count, spancount; unsigned char *pbase, *pdest; fixed16_t s, t, snext, tnext, sstep, tstep; float sdivz, tdivz, zi, z, du, dv, spancountminus1; float sdivzstepu, tdivzstepu, zistepu; int n; int forg= 0; // leilei - fog unsigned char fogg[3]; unsigned short *src; pbase = (unsigned char *)cacheblock; sdivzstepu = d_sdivzstepu * 16; tdivzstepu = d_tdivzstepu * 16; zistepu = d_zistepu * 16; do { pdest = (unsigned char *)((byte *)d_viewbuffer + (screenwidth * pspan->v) + pspan->u); count = pspan->count; // calculate the initial s/z, t/z, 1/z, s, and t and clamp du = (float)pspan->u; dv = (float)pspan->v; sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu; tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu; zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point s = (int)(sdivz * z) + sadjust; if (s > bbextents) s = bbextents; else if (s < 0) s = 0; t = (int)(tdivz * z) + tadjust; if (t > bbextentt) t = bbextentt; else if (t < 0) t = 0; do { // calculate s and t at the far end of the span // if (count >= 16) // spancount = 16; // else // spancount = count; spancount = count > 15 ? 16 : count; count -= spancount; if (count) { // calculate s/z, t/z, zi->fixed s and t at far end of span, // calculate s and t steps across span by shifting sdivz += sdivzstepu; tdivz += tdivzstepu; zi += zistepu; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point snext = (int)(sdivz * z) + sadjust; if (snext > bbextents) snext = bbextents; else if (snext <= 16) snext = 16; // prevent round-off error on <0 steps from // from causing overstepping & running off the // edge of the texture tnext = (int)(tdivz * z) + tadjust; if (tnext > bbextentt) tnext = bbextentt; else if (tnext < 16) tnext = 16; // guard against round-off error on <0 steps sstep = (snext - s) >> 4; tstep = (tnext - t) >> 4; } else { // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so // can't step off polygon), clamp, calculate s and t steps across // span by division, biasing steps low so we don't run off the // texture spancountminus1 = (float)(spancount - 1); sdivz += d_sdivzstepu * spancountminus1; tdivz += d_tdivzstepu * spancountminus1; zi += d_zistepu * spancountminus1; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point snext = (int)(sdivz * z) + sadjust; if (snext > bbextents) snext = bbextents; else if (snext < 16) snext = 16; // prevent round-off error on <0 steps from // from causing overstepping & running off the // edge of the texture tnext = (int)(tdivz * z) + tadjust; if (tnext > bbextentt) tnext = bbextentt; else if (tnext < 16) tnext = 16; // guard against round-off error on <0 steps if (spancount > 1) { sstep = (snext - s) / (spancount - 1); tstep = (tnext - t) / (spancount - 1); } } n = ((pspan->v & 1) << 1) | (pspan->u & 1); pdest += spancount; if (foguse){ forg = (int)(z / 1024); if (forg > 32762) forg = 32762; //forgf = forg / 32768; // get down to the 1.0's } // leilei - fog if(foguse){ switch (spancount) { case 16: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-16] = foggmap[ditherTable[*src & 0x7FFF][n] + (forg >> 2 & 0xFF00)]; n ^= 1; s += sstep; t += tstep; case 15: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-15] = foggmap[ditherTable[*src & 0x7FFF][n] + (forg >> 2 & 0xFF00)]; n ^= 1; s += sstep; t += tstep; case 14: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-14] = foggmap[ditherTable[*src & 0x7FFF][n] + (forg >> 2 & 0xFF00)]; n ^= 1; s += sstep; t += tstep; case 13: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-13] = foggmap[ditherTable[*src & 0x7FFF][n] + (forg >> 2 & 0xFF00)]; n ^= 1; s += sstep; t += tstep; case 12: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-12] = foggmap[ditherTable[*src & 0x7FFF][n] + (forg >> 2 & 0xFF00)]; n ^= 1; s += sstep; t += tstep; case 11: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-11] = foggmap[ditherTable[*src & 0x7FFF][n] + (forg >> 2 & 0xFF00)]; n ^= 1; s += sstep; t += tstep; case 10: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-10] = foggmap[ditherTable[*src & 0x7FFF][n] + (forg >> 2 & 0xFF00)]; n ^= 1; s += sstep; t += tstep; case 9: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-9] = foggmap[ditherTable[*src & 0x7FFF][n] + (forg >> 2 & 0xFF00)]; n ^= 1; s += sstep; t += tstep; case 8: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-8] = foggmap[ditherTable[*src & 0x7FFF][n] + (forg >> 2 & 0xFF00)]; n ^= 1; s += sstep; t += tstep; case 7: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-7] = foggmap[ditherTable[*src & 0x7FFF][n] + (forg >> 2 & 0xFF00)]; n ^= 1; s += sstep; t += tstep; case 6: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-6] = foggmap[ditherTable[*src & 0x7FFF][n] + (forg >> 2 & 0xFF00)]; n ^= 1; s += sstep; t += tstep; case 5: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-5] = foggmap[ditherTable[*src & 0x7FFF][n] + (forg >> 2 & 0xFF00)]; n ^= 1; s += sstep; t += tstep; case 4: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-4] = foggmap[ditherTable[*src & 0x7FFF][n] + (forg >> 2 & 0xFF00)]; n ^= 1; s += sstep; t += tstep; case 3: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-3] = foggmap[ditherTable[*src & 0x7FFF][n] + (forg >> 2 & 0xFF00)]; n ^= 1; s += sstep; t += tstep; case 2: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-2] = foggmap[ditherTable[*src & 0x7FFF][n] + (forg >> 2 & 0xFF00)]; n ^= 1; s += sstep; t += tstep; case 1: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-1] = foggmap[ditherTable[*src & 0x7FFF][n] + (forg >> 2 & 0xFF00)]; n ^= 1; s += sstep; t += tstep; } } else { switch (spancount) { #ifdef THIRTYTWOBITHACK case 16: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-16] = *src & 0x7FFF; n ^= 1; s += sstep; t += tstep; case 15: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-15] = *src & 0x7F00; n ^= 1; s += sstep; t += tstep; case 14: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-14] = *src & 0x7FFF; n ^= 1; s += sstep; t += tstep; case 13: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-13] = *src & 0x7FFF; n ^= 1; s += sstep; t += tstep; case 12: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-12] = *src & 0x7FFF; n ^= 1; s += sstep; t += tstep; case 11: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-11] = *src & 0x7FFF; n ^= 1; s += sstep; t += tstep; case 10: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-10] = *src & 0x7FFF; n ^= 1; s += sstep; t += tstep; case 9: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-9] = *src & 0x7FFF; n ^= 1; s += sstep; t += tstep; case 8: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-8] = *src & 0x7FFF; n ^= 1; s += sstep; t += tstep; case 7: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-7] = *src & 0x7FFF; n ^= 1; s += sstep; t += tstep; case 6: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-6] = *src & 0x7FFF; n ^= 1; s += sstep; t += tstep; case 5: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-5] = *src & 0x7FFF; n ^= 1; s += sstep; t += tstep; case 4: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-4] = *src & 0x7FFF; n ^= 1; s += sstep; t += tstep; case 3: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-3] = *src & 0x7FFF; n ^= 1; s += sstep; t += tstep; case 2: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-2] = *src & 0x7FFF; n ^= 1; s += sstep; t += tstep; case 1: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-1] = *src & 0x7FFF; n ^= 1; s += sstep; t += tstep; #else case 16: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-16] = ditherTable[*src & 0x7FFF][n]; n ^= 1; s += sstep; t += tstep; case 15: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-15] = ditherTable[*src & 0x7FFF][n]; n ^= 1; s += sstep; t += tstep; case 14: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-14] = ditherTable[*src & 0x7FFF][n]; n ^= 1; s += sstep; t += tstep; case 13: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-13] = ditherTable[*src & 0x7FFF][n]; n ^= 1; s += sstep; t += tstep; case 12: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-12] = ditherTable[*src & 0x7FFF][n]; n ^= 1; s += sstep; t += tstep; case 11: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-11] = ditherTable[*src & 0x7FFF][n]; n ^= 1; s += sstep; t += tstep; case 10: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-10] = ditherTable[*src & 0x7FFF][n]; n ^= 1; s += sstep; t += tstep; case 9: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-9] = ditherTable[*src & 0x7FFF][n]; n ^= 1; s += sstep; t += tstep; case 8: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-8] = ditherTable[*src & 0x7FFF][n]; n ^= 1; s += sstep; t += tstep; case 7: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-7] = ditherTable[*src & 0x7FFF][n]; n ^= 1; s += sstep; t += tstep; case 6: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-6] = ditherTable[*src & 0x7FFF][n]; n ^= 1; s += sstep; t += tstep; case 5: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-5] = ditherTable[*src & 0x7FFF][n]; n ^= 1; s += sstep; t += tstep; case 4: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-4] = ditherTable[*src & 0x7FFF][n]; n ^= 1; s += sstep; t += tstep; case 3: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-3] = ditherTable[*src & 0x7FFF][n]; n ^= 1; s += sstep; t += tstep; case 2: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-2] = ditherTable[*src & 0x7FFF][n]; n ^= 1; s += sstep; t += tstep; case 1: src = (unsigned short *)pbase; src += (s >> 16) + (t >> 16) * cachewidth; pdest[-1] = ditherTable[*src & 0x7FFF][n]; n ^= 1; s += sstep; t += tstep; #endif } } s = snext; t = tnext; } while (count > 0); } while ((pspan = pspan->pnext) != NULL); } void D_DrawSpans16_C_Dither_Filter (espan_t *pspan) //the slowest spans on earth. { int count, spancount; unsigned char *pbase, *pdest; unsigned short *src; fixed16_t s, t, snext, tnext, sstep, tstep; float sdivz, tdivz, zi, z, du, dv, spancountminus1; float sdivzstepu, tdivzstepu, zistepu; int n; int idiths, iditht, X, Y; // filter stuff int forg; // leilei - fog sstep = 0; // keep compiler happy tstep = 0; // ditto pbase = (unsigned char *)cacheblock; sdivzstepu = d_sdivzstepu * 16; tdivzstepu = d_tdivzstepu * 16; zistepu = d_zistepu * 16; do { pdest = (unsigned char *)((byte *)d_viewbuffer + (screenwidth * pspan->v) + pspan->u); count = pspan->count; // calculate the initial s/z, t/z, 1/z, s, and t and clamp du = (float)pspan->u; dv = (float)pspan->v; sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu; tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu; zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point s = (int)(sdivz * z) + sadjust; s = s > bbextents ? bbextents : (s < 0 ? 0 : s); t = (int)(tdivz * z) + tadjust; t = t > bbextentt ? bbextentt : (t < 0 ? 0 : t); do { // calculate s and t at the far end of the span spancount = count > 15 ? 16 : count; count -= spancount; if (count) { // calculate s/z, t/z, zi->fixed s and t at far end of span, // calculate s and t steps across span by shifting sdivz += sdivzstepu; tdivz += tdivzstepu; zi += zistepu; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point snext = (int)(sdivz * z) + sadjust; if (snext > bbextents) snext = bbextents; else if (snext <= 16) snext = 16; // prevent round-off error on <0 steps from // from causing overstepping & running off the // edge of the texture tnext = (int)(tdivz * z) + tadjust; if (tnext > bbextentt) tnext = bbextentt; else if (tnext < 16) tnext = 16; // guard against round-off error on <0 steps sstep = (snext - s) >> 4; tstep = (tnext - t) >> 4; } else { // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so // can't step off polygon), clamp, calculate s and t steps across // span by division, biasing steps low so we don't run off the // texture spancountminus1 = (float)(spancount - 1); sdivz += d_sdivzstepu * spancountminus1; tdivz += d_tdivzstepu * spancountminus1; zi += d_zistepu * spancountminus1; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point snext = (int)(sdivz * z) + sadjust; if (snext > bbextents) snext = bbextents; else if (snext < 16) snext = 16; // prevent round-off error on <0 steps from // from causing overstepping & running off the // edge of the texture tnext = (int)(tdivz * z) + tadjust; if (tnext > bbextentt) tnext = bbextentt; else if (tnext < 16) tnext = 16; // guard against round-off error on <0 steps if (spancount > 1) { sstep = (snext - s) / (spancount - 1); tstep = (tnext - t) / (spancount - 1); } } n = ((pspan->v & 1) << 1) | (pspan->u & 1); if (foguse){ forg = (int)(z / 1024); if (forg > 32762) forg = 32762; } // leilei - fog pdest += spancount; switch (spancount) { case 16: idiths = s; iditht = t; X = (pspan->u + 16) & 1; Y = (pspan->v)& 1; idiths += kernel[X][Y][0]; iditht += kernel[X][Y][1]; idiths = idiths >> 16; idiths = idiths ? idiths -1: idiths; iditht = iditht >> 16; iditht = iditht ? iditht -1 : iditht; src = (unsigned short *)pbase; src += idiths + iditht * cachewidth; pdest[-16] = ditherTable[*src & 0x7FFF][n]; n ^= 1; s += sstep; t += tstep; case 15: idiths = s; iditht = t; X = (pspan->u + 15) & 1; Y = (pspan->v)& 1; idiths += kernel[X][Y][0]; iditht += kernel[X][Y][1]; idiths = idiths >> 16; idiths = idiths ? idiths -1: idiths; iditht = iditht >> 16; iditht = iditht ? iditht -1 : iditht; src = (unsigned short *)pbase; src += idiths + iditht * cachewidth; pdest[-15] = ditherTable[*src & 0x7FFF][n]; n ^= 1; s += sstep; t += tstep; case 14: idiths = s; iditht = t; X = (pspan->u + 14) & 1; Y = (pspan->v)& 1; idiths += kernel[X][Y][0]; iditht += kernel[X][Y][1]; idiths = idiths >> 16; idiths = idiths ? idiths -1: idiths; iditht = iditht >> 16; iditht = iditht ? iditht -1 : iditht; src = (unsigned short *)pbase; src += idiths + iditht * cachewidth; pdest[-14] = ditherTable[*src & 0x7FFF][n]; n ^= 1; s += sstep; t += tstep; case 13: idiths = s; iditht = t; X = (pspan->u + 13) & 1; Y = (pspan->v)& 1; idiths += kernel[X][Y][0]; iditht += kernel[X][Y][1]; idiths = idiths >> 16; idiths = idiths ? idiths -1: idiths; iditht = iditht >> 16; iditht = iditht ? iditht -1 : iditht; src = (unsigned short *)pbase; src += idiths + iditht * cachewidth; pdest[-13] = ditherTable[*src & 0x7FFF][n]; n ^= 1; s += sstep; t += tstep; case 12: idiths = s; iditht = t; X = (pspan->u + 12) & 1; Y = (pspan->v)& 1; idiths += kernel[X][Y][0]; iditht += kernel[X][Y][1]; idiths = idiths >> 16; idiths = idiths ? idiths -1: idiths; iditht = iditht >> 16; iditht = iditht ? iditht -1 : iditht; src = (unsigned short *)pbase; src += idiths + iditht * cachewidth; pdest[-12] = ditherTable[*src & 0x7FFF][n]; n ^= 1; s += sstep; t += tstep; case 11: idiths = s; iditht = t; X = (pspan->u + 11) & 1; Y = (pspan->v)& 1; idiths += kernel[X][Y][0]; iditht += kernel[X][Y][1]; idiths = idiths >> 16; idiths = idiths ? idiths -1: idiths; iditht = iditht >> 16; iditht = iditht ? iditht -1 : iditht; src = (unsigned short *)pbase; src += idiths + iditht * cachewidth; pdest[-11] = ditherTable[*src & 0x7FFF][n]; n ^= 1; s += sstep; t += tstep; case 10: idiths = s; iditht = t; X = (pspan->u + 10) & 1; Y = (pspan->v)& 1; idiths += kernel[X][Y][0]; iditht += kernel[X][Y][1]; idiths = idiths >> 16; idiths = idiths ? idiths -1: idiths; iditht = iditht >> 16; iditht = iditht ? iditht -1 : iditht; src = (unsigned short *)pbase; src += idiths + iditht * cachewidth; pdest[-10] = ditherTable[*src & 0x7FFF][n]; n ^= 1; s += sstep; t += tstep; case 9: idiths = s; iditht = t; X = (pspan->u + 9) & 1; Y = (pspan->v)& 1; idiths += kernel[X][Y][0]; iditht += kernel[X][Y][1]; idiths = idiths >> 16; idiths = idiths ? idiths -1: idiths; iditht = iditht >> 16; iditht = iditht ? iditht -1 : iditht; src = (unsigned short *)pbase; src += idiths + iditht * cachewidth; pdest[-9] = ditherTable[*src & 0x7FFF][n]; n ^= 1; s += sstep; t += tstep; case 8: idiths = s; iditht = t; X = (pspan->u + 8) & 1; Y = (pspan->v)& 1; idiths += kernel[X][Y][0]; iditht += kernel[X][Y][1]; idiths = idiths >> 16; idiths = idiths ? idiths -1: idiths; iditht = iditht >> 16; iditht = iditht ? iditht -1 : iditht; src = (unsigned short *)pbase; src += idiths + iditht * cachewidth; pdest[-8] = ditherTable[*src & 0x7FFF][n]; n ^= 1; s += sstep; t += tstep; case 7: idiths = s; iditht = t; X = (pspan->u + 7) & 1; Y = (pspan->v)& 1; idiths += kernel[X][Y][0]; iditht += kernel[X][Y][1]; idiths = idiths >> 16; idiths = idiths ? idiths -1: idiths; iditht = iditht >> 16; iditht = iditht ? iditht -1 : iditht; src = (unsigned short *)pbase; src += idiths + iditht * cachewidth; pdest[-7] = ditherTable[*src & 0x7FFF][n]; n ^= 1; s += sstep; t += tstep; case 6: idiths = s; iditht = t; X = (pspan->u + 6) & 1; Y = (pspan->v)& 1; idiths += kernel[X][Y][0]; iditht += kernel[X][Y][1]; idiths = idiths >> 16; idiths = idiths ? idiths -1: idiths; iditht = iditht >> 16; iditht = iditht ? iditht -1 : iditht; src = (unsigned short *)pbase; src += idiths + iditht * cachewidth; pdest[-6] = ditherTable[*src & 0x7FFF][n]; n ^= 1; s += sstep; t += tstep; case 5: idiths = s; iditht = t; X = (pspan->u + 5) & 1; Y = (pspan->v)& 1; idiths += kernel[X][Y][0]; iditht += kernel[X][Y][1]; idiths = idiths >> 16; idiths = idiths ? idiths -1: idiths; iditht = iditht >> 16; iditht = iditht ? iditht -1 : iditht; src = (unsigned short *)pbase; src += idiths + iditht * cachewidth; pdest[-5] = ditherTable[*src & 0x7FFF][n]; n ^= 1; s += sstep; t += tstep; case 4: idiths = s; iditht = t; X = (pspan->u + 4) & 1; Y = (pspan->v)& 1; idiths += kernel[X][Y][0]; iditht += kernel[X][Y][1]; idiths = idiths >> 16; idiths = idiths ? idiths -1: idiths; iditht = iditht >> 16; iditht = iditht ? iditht -1 : iditht; src = (unsigned short *)pbase; src += idiths + iditht * cachewidth; pdest[-4] = ditherTable[*src & 0x7FFF][n]; n ^= 1; s += sstep; t += tstep; case 3: idiths = s; iditht = t; X = (pspan->u + 3) & 1; Y = (pspan->v)& 1; idiths += kernel[X][Y][0]; iditht += kernel[X][Y][1]; idiths = idiths >> 16; idiths = idiths ? idiths -1: idiths; iditht = iditht >> 16; iditht = iditht ? iditht -1 : iditht; src = (unsigned short *)pbase; src += idiths + iditht * cachewidth; pdest[-3] = ditherTable[*src & 0x7FFF][n]; n ^= 1; s += sstep; t += tstep; case 2: idiths = s; iditht = t; X = (pspan->u + 2) & 1; Y = (pspan->v)& 1; idiths += kernel[X][Y][0]; iditht += kernel[X][Y][1]; idiths = idiths >> 16; idiths = idiths ? idiths -1: idiths; iditht = iditht >> 16; iditht = iditht ? iditht -1 : iditht; src = (unsigned short *)pbase; src += idiths + iditht * cachewidth; pdest[-2] = ditherTable[*src & 0x7FFF][n]; n ^= 1; s += sstep; t += tstep; case 1: idiths = s; iditht = t; X = (pspan->u + 1) & 1; Y = (pspan->v)& 1; idiths += kernel[X][Y][0]; iditht += kernel[X][Y][1]; idiths = idiths >> 16; idiths = idiths ? idiths -1: idiths; iditht = iditht >> 16; iditht = iditht ? iditht -1 : iditht; src = (unsigned short *)pbase; src += idiths + iditht * cachewidth; pdest[-1] = ditherTable[*src & 0x7FFF][n]; n ^= 1; s += sstep; t += tstep; } s = snext; t = tnext; } while (count > 0); } while ((pspan = pspan->pnext) != NULL); } extern cvar_t *temp2; // Bilinear filtering from flquake void D_DrawSpans8_C_Bilinear (espan_t *pspan) { int count, spancount; unsigned char *pbase, *pdest; fixed16_t s, t, snext, tnext, sstep, tstep; float sdivz, tdivz, zi, z, du, dv, spancountminus1; float sdivz8stepu, tdivz8stepu, zi8stepu; int forg = 0; // leilei - fog sstep = 0; // keep compiler happy tstep = 0; // ditto pbase = (unsigned char *)cacheblock; sdivz8stepu = d_sdivzstepu * 8; tdivz8stepu = d_tdivzstepu * 8; zi8stepu = d_zistepu * 8; do { pdest = (unsigned char *)((byte *)d_viewbuffer + (screenwidth * pspan->v) + pspan->u); count = pspan->count; // calculate the initial s/z, t/z, 1/z, s, and t and clamp du = (float)pspan->u; dv = (float)pspan->v; sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu; tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu; zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point s = (int)(sdivz * z) + sadjust; if (s > bbextents) s = bbextents; else if (s < 0) s = 0; t = (int)(tdivz * z) + tadjust; if (t > bbextentt) t = bbextentt; else if (t < 0) t = 0; do { // calculate s and t at the far end of the span spancount = count > 7 ? 8 : count; // mh count -= spancount; if (count) { // calculate s/z, t/z, zi->fixed s and t at far end of span, // calculate s and t steps across span by shifting sdivz += sdivz8stepu; tdivz += tdivz8stepu; zi += zi8stepu; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point snext = (int)(sdivz * z) + sadjust; if (snext > bbextents) snext = bbextents; else if (snext < 8) snext = 8; // prevent round-off error on <0 steps from // from causing overstepping & running off the // edge of the texture tnext = (int)(tdivz * z) + tadjust; if (tnext > bbextentt) tnext = bbextentt; else if (tnext < 8) tnext = 8; // guard against round-off error on <0 steps sstep = (snext - s) >> 3; tstep = (tnext - t) >> 3; } else { // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so // can't step off polygon), clamp, calculate s and t steps across // span by division, biasing steps low so we don't run off the // texture spancountminus1 = (float)(spancount - 1); sdivz += d_sdivzstepu * spancountminus1; tdivz += d_tdivzstepu * spancountminus1; zi += d_zistepu * spancountminus1; z = (float)0x10000 / zi; // prescale to 16.16 fixed-point snext = (int)(sdivz * z) + sadjust; if (snext > bbextents) snext = bbextents; else if (snext < 8) snext = 8; // prevent round-off error on <0 steps from // from causing overstepping & running off the // edge of the texture tnext = (int)(tdivz * z) + tadjust; if (tnext > bbextentt) tnext = bbextentt; else if (tnext < 8) tnext = 8; // guard against round-off error on <0 steps if (spancount > 1) { sstep = (snext - s) / (spancount - 1); tstep = (tnext - t) / (spancount - 1); } } if (foguse){ forg = (int)(z / 1024); if (forg > 32762) forg = 32762; } // leilei - fog do { if (foguse) // leilei - fogged case *pdest++ = foggmap[pbase[(s >> 16) + (t >> 16) * cachewidth] + (forg >> 2 & 0xFF00)]; else *pdest++ = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep; } while (--spancount > 0); s = snext; t = tnext; } while (count > 0); } while ((pspan = pspan->pnext) != NULL); } #if !id386 /* ============= D_DrawZSpans ============= */ void D_DrawZSpans (espan_t *pspan) { int count, doublecount, izistep; int izi; short *pdest; unsigned ltemp; double zi; float du, dv; // FIXME: check for clamping/range problems // we count on FP exceptions being turned off to avoid range problems izistep = (int)(d_zistepu * 0x8000 * 0x10000); do { pdest = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u; count = pspan->count; // calculate the initial 1/z du = (float)pspan->u; dv = (float)pspan->v; zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; // we count on FP exceptions being turned off to avoid range problems izi = (int)(zi * 0x8000 * 0x10000); if ((long)pdest & 0x02) { *pdest++ = (short)(izi >> 16); izi += izistep; count--; } if ((doublecount = count >> 1) > 0) { do { ltemp = izi >> 16; izi += izistep; ltemp |= izi & 0xFFFF0000; izi += izistep; *(int *)pdest = ltemp; pdest += 2; } while (--doublecount > 0); } if (count & 1) *pdest = (short)(izi >> 16); } while ((pspan = pspan->pnext) != NULL); } #endif