r_draw.c

来自「游戏类程序源代码---WinDoom 3D源程序.zip」· C语言 代码 · 共 1,020 行 · 第 1/2 页

C
1,020
字号
	if (i >= 0x70 && i<= 0x7f)
	{
	    // map green ramp to gray, brown, red
	    translationtables[i] = 0x60 + (i&0xf);
	    translationtables [i+256] = 0x40 + (i&0xf);
	    translationtables [i+512] = 0x20 + (i&0xf);
	}
	else
	{
	    // Keep all other colors as is.
	    translationtables[i] = translationtables[i+256] 
		= translationtables[i+512] = i;
	}
    }
}




//
// R_DrawSpan 
// With DOOM style restrictions on view orientation,
//  the floors and ceilings consist of horizontal slices
//  or spans with constant z depth.
// However, rotation around the world z axis is possible,
//  thus this mapping, while simpler and faster than
//  perspective correct texture mapping, has to traverse
//  the texture at an angle in all but a few cases.
// In consequence, flats are not stored by column (like walls),
//  and the inner loop has to step in texture space u and v.
//
int			ds_y; 
int			ds_x1; 
int			ds_x2;

lighttable_t*		ds_colormap; 

fixed_t			ds_xfrac; 
fixed_t			ds_yfrac; 
fixed_t			ds_xstep; 
fixed_t			ds_ystep;

// start of a 64*64 tile image 
byte*			ds_source;	

// just for profiling
int			dscount;


//
// Draws the actual span.
void R_DrawSpan (PBUFFER ViewWindowBuffer) //DQ
//void R_DrawSpan (void) 
{ 
    fixed_t		xfrac;
    fixed_t		yfrac; 
    byte*		dest; 
    int			count;
    int			spot; 
	 
#ifdef RANGECHECK 
    if (ds_x2 < ds_x1
	|| ds_x1<0
	|| ds_x2>=SCREENWIDTH  
	|| (unsigned)ds_y>SCREENHEIGHT)
    {
	I_Error( "R_DrawSpan: %i to %i at %i",
		 ds_x1,ds_x2,ds_y);
    }
//	dscount++; 
#endif 

    
    xfrac = ds_xfrac; 
    yfrac = ds_yfrac; 

	 dest = ViewWindowBuffer->Buffer + ViewWindowBuffer->YLookup[ds_y] + columnofs[ds_x1]; // DQ
    //dest = /*DQ*/RenderBuffer+ylookup[ds_y] + columnofs[ds_x1];

    // We do not check for zero spans here?
    count = ds_x2 - ds_x1;

    do 
    {
	// Current texture index in u,v.
	spot = ((yfrac>>(16-6))&(63*64)) + ((xfrac>>16)&63);

	// Lookup pixel from flat texture tile,
	//  re-index using light/colormap.
	*dest++ = ds_colormap[ds_source[spot]];

	// Next step in u,v.
	xfrac += ds_xstep; 
	yfrac += ds_ystep;
	
    } while (count--); 
} 



// UNUSED.
// Loop unrolled by 4.
#if 0
void R_DrawSpan (void) 
{ 
    unsigned	position, step;

    byte*	source;
    byte*	colormap;
    byte*	dest;
    
    unsigned	count;
    usingned	spot; 
    unsigned	value;
    unsigned	temp;
    unsigned	xtemp;
    unsigned	ytemp;
		
    position = ((ds_xfrac<<10)&0xffff0000) | ((ds_yfrac>>6)&0xffff);
    step = ((ds_xstep<<10)&0xffff0000) | ((ds_ystep>>6)&0xffff);
		
    source = ds_source;
    colormap = ds_colormap;
    dest = /*DQ*/RenderBuffer+ylookup[ds_y] + columnofs[ds_x1];	 
    count = ds_x2 - ds_x1 + 1; 
	
    while (count >= 4) 
    { 
	ytemp = position>>4;
	ytemp = ytemp & 4032;
	xtemp = position>>26;
	spot = xtemp | ytemp;
	position += step;
	dest[0] = colormap[source[spot]]; 

	ytemp = position>>4;
	ytemp = ytemp & 4032;
	xtemp = position>>26;
	spot = xtemp | ytemp;
	position += step;
	dest[1] = colormap[source[spot]];
	
	ytemp = position>>4;
	ytemp = ytemp & 4032;
	xtemp = position>>26;
	spot = xtemp | ytemp;
	position += step;
	dest[2] = colormap[source[spot]];
	
	ytemp = position>>4;
	ytemp = ytemp & 4032;
	xtemp = position>>26;
	spot = xtemp | ytemp;
	position += step;
	dest[3] = colormap[source[spot]]; 
		
	count -= 4;
	dest += 4;
    } 
    while (count > 0) 
    { 
	ytemp = position>>4;
	ytemp = ytemp & 4032;
	xtemp = position>>26;
	spot = xtemp | ytemp;
	position += step;
	*dest++ = colormap[source[spot]]; 
	count--;
    } 
} 
#endif


//
// Again..
//
void R_DrawSpanLow (PBUFFER ViewWindowBuffer) // DQ
//void R_DrawSpanLow (void) 
{ 
    fixed_t		xfrac;
    fixed_t		yfrac; 
    byte*		dest; 
    int			count;
    int			spot; 
	 
#ifdef RANGECHECK 
    if (ds_x2 < ds_x1
	|| ds_x1<0
	|| ds_x2>=SCREENWIDTH  
	|| (unsigned)ds_y>SCREENHEIGHT)
    {
	I_Error( "R_DrawSpan: %i to %i at %i",
		 ds_x1,ds_x2,ds_y);
    }
//	dscount++; 
#endif 
	 
    xfrac = ds_xfrac; 
    yfrac = ds_yfrac; 

    // Blocky mode, need to multiply by 2.
    ds_x1 <<= 1;
    ds_x2 <<= 1;
    
	 dest = ViewWindowBuffer->Buffer + ViewWindowBuffer->YLookup[ds_y] + columnofs[ds_x1]; //DQ
    //dest = /*DQ*/RenderBuffer+ylookup[ds_y] + columnofs[ds_x1];
    
    count = ds_x2 - ds_x1; 
    do 
    { 
	spot = ((yfrac>>(16-6))&(63*64)) + ((xfrac>>16)&63);
	// Lowres/blocky mode does it twice,
	//  while scale is adjusted appropriately.
	*dest++ = ds_colormap[ds_source[spot]]; 
	*dest++ = ds_colormap[ds_source[spot]];
	
	xfrac += ds_xstep; 
	yfrac += ds_ystep; 

    } while (count--); 
}

//
// R_InitBuffer 
// Creats lookup tables that avoid
//  multiplies and other hassles
//  for getting the framebuffer address
//  of a pixel to draw.
//
void R_InitBuffer( int width, int height )
   { 
    int		i; 

    // Handle resize,
    //  e.g. smaller view windows
    //  with border and/or status bar.
    viewwindowx = (SCREENWIDTH-width) >> 1; 

    // Column offset. For windows.
    for (i = 0; i < width; i++) 
       columnofs[i] = viewwindowx + i;

    // Same with base row offset.
    if (width == SCREENWIDTH) 
        viewwindowy = 0; 
    else 
        viewwindowy = (SCREENHEIGHT-SBARHEIGHT-height) >> 1; 

    // Precalculate all row offsets.
    for (i = 0; i < height; i++) 
		 // DQ start addition
	 {
		 // create a lookup table for both screens[] pitch, and the surface pitch
			ScreensViewWindowYLookup[i] = (i+viewwindowy)*SCREENWIDTH; 
			SurfaceViewWindowYLookup[i] = (i+viewwindowy)*SurfacePitch; 
	 }
		 // DQ end addition
         //ylookup[i] = screens[0] + (i+viewwindowy)*SCREENWIDTH; 
	 // DQ start addiotion
    for (i = 0; i < SCREENHEIGHT; i++) 
	 {
		 // create a lookup table for both screens[] pitch, and the surface pitch
			ScreensYLookup[i] = i*SCREENWIDTH; 
			SurfaceYLookup[i] = i*SurfacePitch; 
	 }
	 // DQ end addition
   } 
 
 


//
// R_FillBackScreen
// Fills the back screen with a pattern for variable screen sizes
// Also draws a beveled edge.
//
void R_FillBackScreen (PBUFFER BackBuffer) // DQ
//void R_FillBackScreen (void) 
   { 
    byte*	src;
    byte*	dest; 
    int		x;
    int		y; 
    patch_t*	patch;
	 BYTE * Buffer;	// DQ
	 long * YLookup;	// DQ

    // DOOM border patch.
    char	name1[] = "FLOOR7_2";

    // DOOM II border patch.
    char	name2[] = "GRNROCK";	

    char*	name;

    if ((scaledviewwidth == SCREENWIDTH)&&(viewheight == SCREENHEIGHT))
        return;
	
    if (gamemode == commercial)
        name = name2;
    else
        name = name1;
    
    src = W_CacheLumpName(name, PU_CACHE); 
    //dest = screens[1]; // DQ removed

	 Buffer = BackBuffer->Buffer;
	 YLookup = BackBuffer->YLookup;
    //for (y = 0; y < SCREENHEIGHT-SBARHEIGHT; y++) 
    for (y = 0; y < SCREENHEIGHT; y++)
       { 
		 dest = Buffer + YLookup[y];	// DQ
        for (x = 0; x < SCREENWIDTH/64; x++) 
           { 
            memcpy (dest, src+((y&63)<<6), 64); 
            dest += 64; 
           } 

        if (SCREENWIDTH & 63) 
           { 
            memcpy (dest, src+((y&63)<<6), SCREENWIDTH&63); 
            dest += (SCREENWIDTH&63); 
           } 
       } 
	
    if (scaledviewwidth == SCREENWIDTH)
        return;

    patch = W_CacheLumpName ("brdr_t",PU_CACHE);

    for (x=0 ; x<scaledviewwidth ; x+=8)
	V_DrawPatch (viewwindowx+x,viewwindowy-8, BackBuffer/*DQ 1*/, patch);
    patch = W_CacheLumpName ("brdr_b",PU_CACHE);

    for (x=0 ; x<scaledviewwidth ; x+=8)
	V_DrawPatch (viewwindowx+x,viewwindowy+viewheight, BackBuffer/*DQ 1*/, patch);
    patch = W_CacheLumpName ("brdr_l",PU_CACHE);

    for (y=0 ; y<viewheight ; y+=8)
	V_DrawPatch (viewwindowx-8,viewwindowy+y, BackBuffer/*DQ 1*/, patch);
    patch = W_CacheLumpName ("brdr_r",PU_CACHE);

    for (y=0 ; y<viewheight ; y+=8)
	V_DrawPatch (viewwindowx+scaledviewwidth,viewwindowy+y, BackBuffer/*DQ 1*/, patch);


    // Draw beveled edge. 
    V_DrawPatch (viewwindowx-8,
		 viewwindowy-8,
		  BackBuffer/*DQ 1*/, 
		 W_CacheLumpName ("brdr_tl",PU_CACHE));
    
    V_DrawPatch (viewwindowx+scaledviewwidth,
		 viewwindowy-8,
		  BackBuffer/*DQ 1*/, 
		 W_CacheLumpName ("brdr_tr",PU_CACHE));
    
    V_DrawPatch (viewwindowx-8,
		 viewwindowy+viewheight,
		  BackBuffer/*DQ 1*/, 
		 W_CacheLumpName ("brdr_bl",PU_CACHE));
    
    V_DrawPatch (viewwindowx+scaledviewwidth,
		 viewwindowy+viewheight,
		  BackBuffer/*DQ 1*/, 
		 W_CacheLumpName ("brdr_br",PU_CACHE));
} 
 

//
// Copy a screen buffer.
//
// DQ start addition
void R_VideoErase( int Y, 
						int StartX, 
						int Count, 
						PBUFFER RenderBuffer, 
						PBUFFER BackBuffer) //DQ
//void R_VideoErase( int Y, int StartX, int Count) 
// DQ end addition
//void R_VideoErase( unsigned	ofs, int count ) 
   { 
	// DQ changed ofs, which was an offset into the video buffer, to Y.  This is because
	// the pitch of a buffer is no longer always the width, and a direct copy may not work.
	// Can only copy one row at a time
	// DQ start addition

	int bytes;
	if (StartX + Count > SCREENWIDTH)
	{
		bytes = SCREENWIDTH - StartX;
	}
	else
	{
		bytes = Count;
	}
	memcpy(RenderBuffer->Buffer + RenderBuffer->YLookup[Y] + StartX, 
					BackBuffer->Buffer + BackBuffer->YLookup[Y] + StartX, 
					bytes);

	// DQ end addition
    // LFB copy.
    // This might not be a good idea if memcpy is not optimal, e.g. byte by byte on
    // a 32bit CPU, as GNU GCC/Linux libc did at one point.
	 // original
    //memcpy(RenderBuffer/*DQ screens[0]*/+ofs, screens[1]+ofs, count); 
   } 


//
// R_DrawViewBorder
// Draws the border around the view
//  for different size windows?
//
void
V_MarkRect
( int		x,
  int		y,
  int		width,
  int		height ); 
 
void R_DrawViewBorder (PBUFFER RenderBuffer, 
							  PBUFFER BackBuffer) // DQ
//void R_DrawViewBorder (void) 
   { 
    int		top;
    int		side, side2;
    //int		ofs;		// DQ removed for new prototype for R_VideoErase
    int		i; 

    if ((SCREENWIDTH > 320) && (SCREENHEIGHT != viewheight))
       {
        //ofs = (SCREENHEIGHT-SBARHEIGHT) * SCREENWIDTH;		// DQ removed
        side = ((SCREENWIDTH - 320) / 2);
        side2 = side * 2;

		  // DQ start addition
		  // for new prototype for R_VideoErase
		  for (i = SCREENHEIGHT-SBARHEIGHT; i < SCREENHEIGHT; i++)
		  {
			  // left border of status bar
			  R_VideoErase(i, 0, side, RenderBuffer/*DQ*/, BackBuffer/*DQ*/);
			  // right border of start bar
			  R_VideoErase(i, side+320, side, RenderBuffer/*DQ*/, BackBuffer/*DQ*/);
		  }

		  // DQ end addition
		  // DQ removal start
        //R_VideoErase(ofs, side);
        //ofs += (SCREENWIDTH - side);
        //for (i = 1;i < SBARHEIGHT;i++)
        //   {
        //    R_VideoErase(ofs, side2);
        //    ofs += SCREENWIDTH;
        //   }
        //R_VideoErase(ofs, side);
		  // DQ removal end
       }

    if (scaledviewwidth == SCREENWIDTH) 
        return;

    top = ((SCREENHEIGHT-SBARHEIGHT)-viewheight)/2;
    side = (SCREENWIDTH-scaledviewwidth)/2;
 
    // copy top and one line of left side 
	 // DQ start addition, but not one line of left side
	 for (i = 0; i < top; i++)
	 {
		R_VideoErase(i, 0, SCREENWIDTH, RenderBuffer/*DQ*/, BackBuffer/*DQ*/);
	 }
	 // DQ end addition
    //R_VideoErase(0, top*SCREENWIDTH+side);
 
    // copy one line of right side and bottom 
	 // DQ start addtion, but not one line of right side
	 for (i = viewheight + top; i < SCREENHEIGHT-SBARHEIGHT; i++)
	 {
		 R_VideoErase(i, 0, SCREENWIDTH, RenderBuffer/*DQ*/, BackBuffer/*DQ*/);
	 }
	 // DQ end addition
	 // DQ removal start
    //ofs = (viewheight+top)*SCREENWIDTH-side;
    //R_VideoErase (ofs, top*SCREENWIDTH+side);
 
	 // DQ start addition
	 // copy sides
	 for (i = top; i < viewheight + top; i++)
	 {
		 R_VideoErase(i, 0, side, RenderBuffer/*DQ*/, BackBuffer/*DQ*/);
		 R_VideoErase(i, SCREENWIDTH - side, side, RenderBuffer/*DQ*/, BackBuffer/*DQ*/);
	 }
	 // DQ end addition
    // copy sides using wraparound 
    //ofs = top*SCREENWIDTH + SCREENWIDTH-side; 
    //side <<= 1;
    //
    //for (i = 1; i < viewheight; i++) 
    //   { 
	 //   R_VideoErase (ofs, side); 
	 //   ofs += SCREENWIDTH; 
    //   } 
	 // DQ removal end

    // ? 
    V_MarkRect (0,0,SCREENWIDTH, SCREENHEIGHT-SBARHEIGHT); 
   } 
 
 

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?