Forum

Adding Smooth Sky Scroll To WinQuake

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

Moderator: InsideQC Admins

Adding Smooth Sky Scroll To WinQuake

Postby Baker » Sun Jul 27, 2014 8:15 pm

This adds MK's smooth sky scroll from Makaqu to WinQuake. It is a minimal implementation: 6 changed files: d_sky.c, r_sky.c, d_iface.h, d_edge.c, r_shared.h, r_surf.c

But only 2 files are changed much: d_sky.c, r_sky.c

1. r_surf.c - find R_GenTile function. And remove it.
2. r_shared.h - find this and remove

Code: Select all
extern int   r_skymade;
extern void R_MakeSky (void);


3. d_edge.c - find this and remove

Code: Select all
            if (!r_skymade)
            {
               R_MakeSky ();
            }


4. d_iface.h --- find these and remove

Code: Select all
// these are currently for internal use only, and should not be used by drivers
extern byte            *r_skysource;

Code: Select all
void R_GenTile (msurface_t *psurf, void *pdest);


5. r_sky.c - find these and remove

Code: Select all
int r_skymade;

// TODO: clean up these routines

byte   bottomsky[128*131];
byte   bottommask[128*131];
byte   newsky[128*256];   // newsky and topsky both pack in here, 128 bytes
                     //  of newsky on the left of each scan, 128 bytes
                     //  of topsky on the right, because the low-level
                     //  drawers need 256-byte scan widths


Code: Select all
/*
=================
R_MakeSky
=================
*/
void R_MakeSky (void)
{
   int         x, y;
   int         ofs, baseofs;
   int         xshift, yshift;
   unsigned   *pnewsky;
   static int   xlast = -1, ylast = -1;

   xshift = skytime*skyspeed;
   yshift = skytime*skyspeed;

   if ((xshift == xlast) && (yshift == ylast))
      return;

   xlast = xshift;
   ylast = yshift;

   pnewsky = (unsigned *)&newsky[0];

   for (y=0 ; y<SKYSIZE ; y++)
   {
      baseofs = ((y+yshift) & SKYMASK) * 131;

// FIXME: clean this up
#if UNALIGNED_OK

      for (x=0 ; x<SKYSIZE ; x += 4)
      {
         ofs = baseofs + ((x+xshift) & SKYMASK);

      // PORT: unaligned dword access to bottommask and bottomsky

         *pnewsky = (*(pnewsky + (128 / sizeof (unsigned))) &
                  *(unsigned *)&bottommask[ofs]) |
                  *(unsigned *)&bottomsky[ofs];
         pnewsky++;
      }

#else

      for (x=0 ; x<SKYSIZE ; x++)
      {
         ofs = baseofs + ((x+xshift) & SKYMASK);

         *(byte *)pnewsky = (*((byte *)pnewsky + 128) &
                  *(byte *)&bottommask[ofs]) |
                  *(byte *)&bottomsky[ofs];
         pnewsky = (unsigned *)((byte *)pnewsky + 1);
      }

#endif

      pnewsky += 128 / sizeof (unsigned);
   }

   r_skymade = 1;
}


/*
=================
R_GenSkyTile
=================
*/
void R_GenSkyTile (void *pdest)
{
   int         x, y;
   int         ofs, baseofs;
   int         xshift, yshift;
   unsigned   *pnewsky;
   unsigned   *pd;

   xshift = skytime*skyspeed;
   yshift = skytime*skyspeed;

   pnewsky = (unsigned *)&newsky[0];
   pd = (unsigned *)pdest;

   for (y=0 ; y<SKYSIZE ; y++)
   {
      baseofs = ((y+yshift) & SKYMASK) * 131;

// FIXME: clean this up
#if UNALIGNED_OK

      for (x=0 ; x<SKYSIZE ; x += 4)
      {
         ofs = baseofs + ((x+xshift) & SKYMASK);

      // PORT: unaligned dword access to bottommask and bottomsky

         *pd = (*(pnewsky + (128 / sizeof (unsigned))) &
               *(unsigned *)&bottommask[ofs]) |
               *(unsigned *)&bottomsky[ofs];
         pnewsky++;
         pd++;
      }

#else

      for (x=0 ; x<SKYSIZE ; x++)
      {
         ofs = baseofs + ((x+xshift) & SKYMASK);

         *(byte *)pd = (*((byte *)pnewsky + 128) &
                  *(byte *)&bottommask[ofs]) |
                  *(byte *)&bottomsky[ofs];
         pnewsky = (unsigned *)((byte *)pnewsky + 1);
         pd = (unsigned *)((byte *)pd + 1);
      }

#endif

      pnewsky += 128 / sizeof (unsigned);
   }
}


In r_setskyframe remove ...

Code: Select all
   r_skymade = 0;


6. r_sky.c - find this ....

Code: Select all
void R_InitSky (texture_t *mt)
{
   int         i, j;
   byte      *src;

   src = (byte *)mt + mt->offsets[0];

   for (i=0 ; i<128 ; i++)
   {
      for (j=0 ; j<128 ; j++)
      {
         newsky[(i*256) + j + 128] = src[i*256 + j + 128];
      }
   }

   for (i=0 ; i<128 ; i++)
   {
      for (j=0 ; j<131 ; j++)
      {
         if (src[i*256 + (j & 0x7F)])
         {
            bottomsky[(i*131) + j] = src[i*256 + (j & 0x7F)];
            bottommask[(i*131) + j] = 0;
         }
         else
         {
            bottomsky[(i*131) + j] = 0;
            bottommask[(i*131) + j] = 0xff;
         }
      }
   }

   r_skysource = newsky;
}


And replace with ...

Code: Select all
void R_InitSky (texture_t *mt)
{

   skyoverlay = (byte *)mt + mt->offsets[0]; // Manoel Kasimier - smooth sky
   skyunderlay = skyoverlay+128; // Manoel Kasimier - smooth sky
}


7A. d_sky.c - replace this ...

Code: Select all
/*
=================
D_Sky_uv_To_st
=================
*/
void D_Sky_uv_To_st (int u, int v, fixed16_t *s, fixed16_t *t)
{
   float   wu, wv, temp;
   vec3_t   end;

   if (r_refdef.vrect.width >= r_refdef.vrect.height)
      temp = (float)r_refdef.vrect.width;
   else
      temp = (float)r_refdef.vrect.height;

   wu = 8192.0 * (float)(u-((int)R_CANVAS_width>>1)) / temp;
   wv = 8192.0 * (float)(((int)R_CANVAS_height>>1)-v) / temp;

   end[0] = 4096*vpn[0] + wu*vright[0] + wv*vup[0];
   end[1] = 4096*vpn[1] + wu*vright[1] + wv*vup[1];
   end[2] = 4096*vpn[2] + wu*vright[2] + wv*vup[2];
   end[2] *= 3;
   VectorNormalize (end);

   temp = skytime*skyspeed;   // TODO: add D_SetupFrame & set this there
   *s = (int)((temp + 6*(SKYSIZE/2-1)*end[0]) * 0x10000);
   *t = (int)((temp + 6*(SKYSIZE/2-1)*end[1]) * 0x10000);
   }


With this ....

Code: Select all
static float   timespeed1, timespeed2; // Manoel Kasimier - smooth sky

extern byte   *skyunderlay, *skyoverlay; // Manoel Kasimier - smooth sky

/*
=================
D_Sky_uv_To_st
=================
*/
void D_Sky_uv_To_st (int u, int v, fixed16_t *s, fixed16_t *t
               , fixed16_t *s2, fixed16_t *t2) // Manoel Kasimier - smooth sky
{
   float   wu, wv;//, temp; // Manoel Kasimier - edited
   vec3_t   end;

   // ToChriS - begin
   wu = (u - xcenter) / xscale;
   wv = (ycenter - v) / yscale;

   end[0] = vpn[0] + wu*vright[0] + wv*vup[0];
   end[1] = vpn[1] + wu*vright[1] + wv*vup[1];
   end[2] = vpn[2] + wu*vright[2] + wv*vup[2];
   // ToChriS - end
   end[2] *= 3;
   VectorNormalize (end);
   *s = (int)((timespeed1 + 6*(SKYSIZE/2-1)*end[0]) * 0x10000); // Manoel Kasimier - smooth sky - edited
   *t = (int)((timespeed1 + 6*(SKYSIZE/2-1)*end[1]) * 0x10000); // Manoel Kasimier - smooth sky - edited
   *s2 = (int)((timespeed2 + 6*(SKYSIZE/2-1)*end[0]) * 0x10000); // Manoel Kasimier - smooth sky
   *t2 = (int)((timespeed2 + 6*(SKYSIZE/2-1)*end[1]) * 0x10000); // Manoel Kasimier - smooth sky
}


unsigned char D_DrawSkyPixelOpaque (unsigned char pixel1, unsigned char pixel2)
{
   return pixel2 ? pixel2 : pixel1;
}


7B. d_sky.c --- final step ...

Find:

Code: Select all
void D_DrawSkyScans8 (espan_t *pspan)
{
   int            count, spancount, u, v;
   unsigned char   *pdest;
   fixed16_t      s, t, snext, tnext, sstep, tstep;
   int            spancountminus1;

   sstep = 0;   // keep compiler happy
   tstep = 0;   // ditto

   do
   {
      pdest = (unsigned char *)((byte *)d_viewbuffer +
            (screenwidth * pspan->v) + pspan->u);

      count = pspan->count;

   // calculate the initial s & t
      u = pspan->u;
      v = pspan->v;
      D_Sky_uv_To_st (u, v, &s, &t);

      do
      {
         if (count >= SKY_SPAN_MAX)
            spancount = SKY_SPAN_MAX;
         else
            spancount = count;

         count -= spancount;

         if (count)
         {
            u += spancount;

         // calculate s and t at far end of span,
         // calculate s and t steps across span by shifting
            D_Sky_uv_To_st (u, v, &snext, &tnext);

            sstep = (snext - s) >> SKY_SPAN_SHIFT;
            tstep = (tnext - t) >> SKY_SPAN_SHIFT;
         }
         else
         {
         // calculate s and t at last pixel in span,
         // calculate s and t steps across span by division
            spancountminus1 = (float)(spancount - 1);

            if (spancountminus1 > 0)
            {
               u += spancountminus1;
               D_Sky_uv_To_st (u, v, &snext, &tnext);

               sstep = (snext - s) / spancountminus1;
               tstep = (tnext - t) / spancountminus1;
            }
         }

         do
         {
            *pdest++ = r_skysource[((t & R_SKY_TMASK) >> 8) +
                  ((s & R_SKY_SMASK) >> 16)];
            s += sstep;
            t += tstep;
         } while (--spancount > 0);

         s = snext;
         t = tnext;

      } while (count > 0);

   } while ((pspan = pspan->pnext) != NULL);
}

And replace with ...

Code: Select all
/*
=================
D_DrawSkyScans8
=================
*/
void D_DrawSkyScans8 (espan_t *pspan)
{
   int            count, spancount, u, v;
   unsigned char   *pdest;
   fixed16_t      s, t, snext, tnext, sstep, tstep;
   int            spancountminus1;

   fixed16_t      s2, t2, snext2, tnext2, sstep2, tstep2; // Manoel Kasimier - smooth sky
   timespeed1=skytime*skyspeed;//*4; // Fightoon modification
   timespeed2=timespeed1*2.0;//*-1; // Fightoon modification
   sstep2 = 0;
   tstep2 = 0;
   // Manoel Kasimier - smooth sky - end

   sstep = 0;   // keep compiler happy
   tstep = 0;   // ditto

   do
   {
      pdest = (unsigned char *)((byte *)d_viewbuffer +
            (screenwidth * pspan->v) + pspan->u);

      count = pspan->count;

   // calculate the initial s & t
      u = pspan->u;
      v = pspan->v;
      D_Sky_uv_To_st (u, v, &s, &t, &s2, &t2); // Manoel Kasimier - smooth sky - edited

      do
      {
         if (count >= SKY_SPAN_MAX)
            spancount = SKY_SPAN_MAX;
         else
            spancount = count;

         count -= spancount;

         if (count)
         {
            u += spancount;

         // calculate s and t at far end of span,
         // calculate s and t steps across span by shifting
            D_Sky_uv_To_st (u, v, &snext, &tnext, &snext2, &tnext2); // Manoel Kasimier - smooth sky - edited
            
            sstep = (snext - s) >> SKY_SPAN_SHIFT;
            tstep = (tnext - t) >> SKY_SPAN_SHIFT;

            sstep2 = (snext2 - s2) >> SKY_SPAN_SHIFT; // Manoel Kasimier - smooth sky
            tstep2 = (tnext2 - t2) >> SKY_SPAN_SHIFT; // Manoel Kasimier - smooth sky

         }
         else
         {
         // calculate s and t at last pixel in span,
         // calculate s and t steps across span by division
            spancountminus1 = (float)(spancount - 1);

            if (spancountminus1 > 0)
            {
               u += spancountminus1;
               D_Sky_uv_To_st (u, v, &snext, &tnext, &snext2, &tnext2); // Manoel Kasimier - smooth sky - edited

               sstep = (snext - s) / spancountminus1;
               tstep = (tnext - t) / spancountminus1;
               sstep2 = (snext2 - s2) / spancountminus1; // Manoel Kasimier - smooth sky
               tstep2 = (tnext2 - t2) / spancountminus1; // Manoel Kasimier - smooth sky
            }
         }

         do
         {
            // Manoel Kasimier - smooth sky - begin
            *pdest++ = D_DrawSkyPixelOpaque(skyunderlay[((t  & R_SKY_TMASK) >> 8) + ((s  & R_SKY_SMASK) >> 16)],
                              skyoverlay [((t2 & R_SKY_TMASK) >> 8) + ((s2 & R_SKY_SMASK) >> 16)]);
            // Manoel Kasimier - smooth sky - end
            s += sstep;
            t += tstep;
            s2 += sstep2; // Manoel Kasimier - smooth sky
            t2 += tstep2; // Manoel Kasimier - smooth sky
         } while (--spancount > 0);

         s = snext;
         t = tnext;
         s2 = snext2; // Manoel Kasimier - smooth sky
         t2 = tnext2; // Manoel Kasimier - smooth sky

      } while (count > 0);

   } while ((pspan = pspan->pnext) != NULL);
}
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
User avatar
Baker
 
Posts: 3660
Joined: Tue Mar 14, 2006 5:15 am

Re: Adding Smooth Sky Scroll To WinQuake

Postby mankrip » Sun Jul 27, 2014 11:45 pm

These changes also fixes the sky scaling on zoom, and allows the usage of multiple sky textures on the same scene.

For example, you can have a daytime sky in a window, and a nighttime sky in another. Or a regular sky in the lower floors of a skyscraper, and a starry sky in its rooftop.
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

Re: Adding Smooth Sky Scroll To WinQuake

Postby Baker » Sun Jul 27, 2014 11:56 pm

I thought this was a great of enough fix but seems to come with extra bonus fix. :D
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
User avatar
Baker
 
Posts: 3660
Joined: Tue Mar 14, 2006 5:15 am


Return to Programming Tutorials

Who is online

Users browsing this forum: No registered users and 1 guest