Kernel-based dithering of MDL affine triangles
Posted: Tue Oct 22, 2013 10:52 pm
This one requires more work. The code is completely unoptimized, and there's no perspective correction.
Creating new cvars and other required variables is up to you.
Here's the code:
And here's the code for padding the MDL skins. Padding is only performed on the top and on the bottom of the skin, because if the skin width changes, the texture mapping gets more innacurate. As a plus, this code finds, fixes and warns about bad skin vertices:
Creating new cvars and other required variables is up to you.
Here's the code:
Code: Select all
// mankrip - d_dither - begin
int dither_kernel[2][2][2] =
{
{
{
-8192
, -24576
}
, {
24576
, -8192
}
}
, {
{
8192
, 24576
}
, {
-24576
, 8192
}
}
};
int shading_dither_kernel[2][2] =
// same as dither_kernel[X][Y][0] >> 7
// set to >> 7 for less accuracy and more smoothness
{
{
-8192 >> 7
, 24576 >> 7
}
, {
8192 >> 7
, -24576 >> 7
}
};
// mankrip - d_dither - end
/*
================
D_PolysetDrawSpans8
================
*/
void D_PolysetDrawSpans8_ColorKeyed (void)
{
spanpackage_t
* pspanpackage = pstart
;
int
lcount
, lsfrac
, ltfrac
, llight
, lzi
;
short
* lpz
;
byte
* lpdest
, * lptex
;
// mankrip - begin
int
dith_switch
;
// mankrip - end
do
{
lcount = d_aspancount - pspanpackage->count;
errorterm += erroradjustup;
if (errorterm >= 0)
{
errorterm -= erroradjustdown;
d_aspancount += d_countextrastep;
}
else
d_aspancount += ubasestep;
if (lcount)
{
lpdest = pspanpackage->pdest;
// mankrip - begin
u = (int) (lpdest - (byte *)d_viewbuffer);
Y = (u / screenwidth) & 1; // v & 1;
X = (u % screenwidth) & 1; // u & 1;
dith_switch = X;
// mankrip - end
lptex = pspanpackage->ptex;
lpz = pspanpackage->pz;
lsfrac = pspanpackage->sfrac;
ltfrac = pspanpackage->tfrac;
llight = pspanpackage->light;
lzi = pspanpackage->zi;
do
{
if ((lzi >> 16) >= *lpz)
if (*lptex != TRANSPARENT_COLOR) // mankrip - transparent pixels in alias models
{
if (d_dither.value)
{
idiths = (lsfrac + dither_kernel[dith_switch][Y][0]) >> 16;
iditht = (ltfrac + dither_kernel[dith_switch][Y][1]) >> 16;
}
else
{
idiths = lsfrac >> 16;
iditht = ltfrac >> 16;
}
if (r_fullbright.value)
llight = 63; // for debug
dith_switch = !dith_switch;
*lpdest = ((byte *)acolormap)[*(lptex + idiths + iditht * r_affinetridesc.skinwidth) + ( (llight + ( (d_ditherlight.value) ? (shading_dither_kernel[dith_switch][Y]) : 0)) & 0xFF00)]; // mankrip
*lpz = lzi >> 16;
}
lpdest++;
lpz++;
lzi += r_zistepx;
llight += r_lstepx;
lsfrac += r_sstepx; // s += sstep; // mankrip
ltfrac += r_tstepx; // t += tstep; // mankrip
} while (--lcount);
}
pspanpackage++;
} while (pspanpackage->count != -999999);
}
Code: Select all
void * Mod_LoadAliasSkin (void * pin, int *pskinindex, int skinwidth, int skinheight, aliashdr_t *pheader)
{
int
i
, skinsize = skinheight * skinwidth
;
byte *pskin, *pinskin;
unsigned short *pusskin;
pskin = Hunk_AllocName ( skinwidth * (skinheight + 4) * r_pixbytes, loadname); // mankrip
pinskin = (byte *)pin;
*pskinindex = (byte *)pskin - (byte *)pheader;
RemapBackwards_Pixels (pinskin, skinsize); // mankrip
if (r_pixbytes == 1)
{
// mankrip - begin
// copy the top line twice
Q_memcpy (pskin , pinskin, skinwidth);
Q_memcpy (pskin + skinwidth, pinskin, skinwidth);
// copy the bottom line twice
Q_memcpy (pskin + (skinheight + 2) * skinwidth, pinskin + (skinheight - 1) * skinwidth, skinwidth);
Q_memcpy (pskin + (skinheight + 3) * skinwidth, pinskin + (skinheight - 1) * skinwidth, skinwidth);
// copy the center
Q_memcpy (pskin + 2 * skinwidth, pinskin, skinsize);
// mankrip - end
}
else
Sys_Error ("Mod_LoadAliasSkin: driver set invalid r_pixbytes: %d\n", r_pixbytes);
pinskin += skinsize;
return (void *)pinskin;
}
void Mod_LoadAliasModel (model_t *mod, void *buffer)
{
[...]
// mankrip - begin
int
s
, t
, badverts = 0
;
// mankrip - end
[...]
pmodel->skinheight += 4; // mankrip - extra for dithering
// set base s and t vertices
[...]
for (i=0 ; i<pmodel->numverts ; i++)
{
pstverts[i].onseam = LittleLong (pinstverts[i].onseam);
// mankrip - begin
// extra for dithering
s = LittleLong (pinstverts[i].s);
if (s < 0)
{
badverts = true;
s = 0;
}
else if (s > pmodel->skinwidth - 1)
{
badverts = true;
s = pmodel->skinwidth - 1;
}
t = LittleLong (pinstverts[i].t) + 2;
if (t < 2)
{
badverts = true;
t = 2;
}
else if (t > pmodel->skinheight - 5)
{
badverts = true;
t = pmodel->skinheight - 5;
}
// put s and t in 16.16 format
pstverts[i].s = (s << 16);
pstverts[i].t = (t << 16);
// mankrip - end
}
// mankrip - begin
if (badverts)
Con_Printf ("Mod_LoadAliasModel:\n %s has bad skin verts\n", mod->name);
// mankrip - end
[...]
}