Forum

Kernel-based dithering of MDL affine triangles

Post tutorials on how to do certain tasks within game or engine code here.

Moderator: InsideQC Admins

Kernel-based dithering of MDL affine triangles

Postby mankrip » 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:
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);
}


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:
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
[...]
}
Ph'nglui mglw'nafh mankrip Hell's end wgah'nagl fhtagn.
==-=-=-=-=-=-=-=-=-=-==
Dev blog / Twitter / YouTube
User avatar
mankrip
 
Posts: 908
Joined: Fri Jul 04, 2008 3:02 am

Return to Programming Tutorials

Who is online

Users browsing this forum: No registered users and 1 guest