⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 t3dlib9.cpp

📁 3D游戏编程大师技巧第十二章的源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:

			// interpolate u,v,z
			ui+=du;
			vi+=dv;
			zi+=dz;
			} // end for xi

		// interpolate u,v,x along right and left edge
		xl+=dxdyl;
		ul+=dudyl;
		vl+=dvdyl;
		zl+=dzdyl;
	
		xr+=dxdyr;
		ur+=dudyr;
		vr+=dvdyr;
		zr+=dzdyr;
 
		// advance screen ptr
		screen_ptr+=mem_pitch;

        // advance zbuffer ptr
        z_ptr+=zpitch;

		} // end for y

	} // end if clip
	else
	{
	// non-clip version

	// point screen ptr to starting line
	screen_ptr = dest_buffer + (ystart * mem_pitch);

    // point zbuffer to starting line
    z_ptr = zbuffer + (ystart * zpitch);

	for (yi = ystart; yi<=yend; yi++)
		{
		// compute span endpoints
		xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
		xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
		
		// compute starting points for u,v interpolants
		ui = ul + FIXP16_ROUND_UP;
		vi = vl + FIXP16_ROUND_UP;
		zi = zl + FIXP16_ROUND_UP;
	
		// compute u,v interpolants
		if ((dx = (xend - xstart))>0)
			{
			du = (ur - ul)/dx;
			dv = (vr - vl)/dx;
			dz = (zr - zl)/dx;
			} // end if
		else
			{
			du = (ur - ul);
			dv = (vr - vl);
            dz = (zr - zl);
			} // end else

		// draw span
		for (xi=xstart; xi<=xend; xi++)
			{
            // test if z of current pixel is nearer than current z buffer value
            if (zi < z_ptr[xi])
               {
			   // write textel
		       // get textel first
 			   textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];

               // extract rgb components
               r_textel  = ((textel >> 11)       ); 
               g_textel  = ((textel >> 5)  & 0x3f); 
               b_textel =   (textel        & 0x1f);

               // modulate textel with lit background color
               r_textel*=r_base; 
               g_textel*=g_base;
               b_textel*=b_base;

               // finally write pixel, note that we did the math such that the results are r*32, g*64, b*32
               // hence we need to divide the results by 32,64,32 respetively, BUT since we need to shift
               // the results to fit into the destination 5.6.5 word, we can take advantage of the shifts
               // and they all cancel out for the most part, but we will need logical anding, we will do
               // it later when we optimize more...
               screen_ptr[xi] = ((b_textel >> 5) + ((g_textel >> 6) << 5) + ((r_textel >> 5) << 11));

               // update z-buffer
               z_ptr[xi] = zi;           
               } // end if

			// interpolate u,v,z
			ui+=du;
			vi+=dv;
            zi+=dz;
			} // end for xi

		// interpolate u,v,x along right and left edge
		xl+=dxdyl;
		ul+=dudyl;
		vl+=dvdyl;
	    zl+=dzdyl;

		xr+=dxdyr;
		ur+=dudyr;
		vr+=dvdyr;
        zr+=dzdyr;

		// advance screen ptr
		screen_ptr+=mem_pitch;

        // advance zbuffer ptr
        z_ptr+=zpitch;

		} // end for y

	} // end if non-clipped

	} // end if
else
if (tri_type==TRI_TYPE_GENERAL)
	{

    //Write_Error("\nin tri general: x0=%d, y0=%d,  x1=%d, y1=%d,  x2=%d, y2=%d", x0, y0, x1, y1, x2, y2);

	// first test for bottom clip, always
	if ((yend = y2) > max_clip_y)
		yend = max_clip_y;

	// pre-test y clipping status
	if (y1 < min_clip_y)
		{
		// compute all deltas
		// LHS
		dyl = (y2 - y1);



		dxdyl = ((x2  - x1)  << FIXP16_SHIFT)/dyl;
		dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
		dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;    
        dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;    

		// RHS
		dyr = (y2 - y0);	

		dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
		dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
		dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
        dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;   		

		// compute overclip
		dyr = (min_clip_y - y0);
		dyl = (min_clip_y - y1);

		// computer new LHS starting values
		xl = dxdyl*dyl + (x1  << FIXP16_SHIFT);
		ul = dudyl*dyl + (tu1 << FIXP16_SHIFT);
		vl = dvdyl*dyl + (tv1 << FIXP16_SHIFT);
        zl = dzdyl*dyl + (tz1 << FIXP16_SHIFT);

		// compute new RHS starting values
		xr = dxdyr*dyr + (x0  << FIXP16_SHIFT);
		ur = dudyr*dyr + (tu0 << FIXP16_SHIFT);
		vr = dvdyr*dyr + (tv0 << FIXP16_SHIFT);
        zr = dzdyr*dyr + (tz0 << FIXP16_SHIFT);

		// compute new starting y
		ystart = min_clip_y;

		// test if we need swap to keep rendering left to right
		if (dxdyr > dxdyl)
			{
			SWAP(dxdyl,dxdyr,temp);
			SWAP(dudyl,dudyr,temp);
			SWAP(dvdyl,dvdyr,temp);
			SWAP(dzdyl,dzdyr,temp);
			SWAP(xl,xr,temp);
			SWAP(ul,ur,temp);
			SWAP(vl,vr,temp);
			SWAP(zl,zr,temp);
			SWAP(x1,x2,temp);
			SWAP(y1,y2,temp);
			SWAP(tu1,tu2,temp);
			SWAP(tv1,tv2,temp);
			SWAP(tz1,tz2,temp);
		
			// set interpolation restart
			irestart = INTERP_RHS;

			} // end if

		} // end if
	else
	if (y0 < min_clip_y)
		{
		// compute all deltas
		// LHS
		dyl = (y1 - y0);

		dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
		dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;  
		dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;    
        dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dyl;    

		// RHS
		dyr = (y2 - y0);	

		dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
		dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
		dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
        dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;   
		
		// compute overclip
		dy = (min_clip_y - y0);

		// computer new LHS starting values
		xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
		ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
		vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
        zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);

		// compute new RHS starting values
		xr = dxdyr*dy + (x0  << FIXP16_SHIFT);
		ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
		vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
        zr = dzdyr*dy + (tz0 << FIXP16_SHIFT);

		// compute new starting y
		ystart = min_clip_y;

		// test if we need swap to keep rendering left to right
		if (dxdyr < dxdyl)
			{
			SWAP(dxdyl,dxdyr,temp);
			SWAP(dudyl,dudyr,temp);
			SWAP(dvdyl,dvdyr,temp);
			SWAP(dzdyl,dzdyr,temp);
			SWAP(xl,xr,temp);
			SWAP(ul,ur,temp);
			SWAP(vl,vr,temp);
			SWAP(zl,zr,temp);
			SWAP(x1,x2,temp);
			SWAP(y1,y2,temp);
			SWAP(tu1,tu2,temp);
			SWAP(tv1,tv2,temp);
			SWAP(tz1,tz2,temp);
		
			// set interpolation restart
			irestart = INTERP_RHS;

			} // end if

		} // end if
	else
		{
		// no initial y clipping
	
		// compute all deltas
		// LHS
		dyl = (y1 - y0);

		dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
		dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;  
		dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;    
        dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dyl;    

		// RHS
		dyr = (y2 - y0);	

		dxdyr = ((x2 - x0)   << FIXP16_SHIFT)/dyr;
		dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
		dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   		
        dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;   		

		// no clipping y

		// set starting values
		xl = (x0 << FIXP16_SHIFT);
		xr = (x0 << FIXP16_SHIFT);

		ul = (tu0 << FIXP16_SHIFT);
		vl = (tv0 << FIXP16_SHIFT);
        zl = (tz0 << FIXP16_SHIFT);

		ur = (tu0 << FIXP16_SHIFT);
		vr = (tv0 << FIXP16_SHIFT);
        zr = (tz0 << FIXP16_SHIFT);

		// set starting y
		ystart = y0;

		// test if we need swap to keep rendering left to right
		if (dxdyr < dxdyl)
			{
			SWAP(dxdyl,dxdyr,temp);
			SWAP(dudyl,dudyr,temp);
			SWAP(dvdyl,dvdyr,temp);
			SWAP(dzdyl,dzdyr,temp);
			SWAP(xl,xr,temp);
			SWAP(ul,ur,temp);
			SWAP(vl,vr,temp);
			SWAP(zl,zr,temp);
			SWAP(x1,x2,temp);
			SWAP(y1,y2,temp);
			SWAP(tu1,tu2,temp);
			SWAP(tv1,tv2,temp);
			SWAP(tz1,tz2,temp);
		
			// set interpolation restart
			irestart = INTERP_RHS;

			} // end if

		} // end else


    // test for horizontal clipping
	if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
		(x1 < min_clip_x) || (x1 > max_clip_x) ||
		(x2 < min_clip_x) || (x2 > max_clip_x))
	{
    // clip version
	// x clipping	

	// point screen ptr to starting line
	screen_ptr = dest_buffer + (ystart * mem_pitch);

    // point zbuffer to starting line
    z_ptr = zbuffer + (ystart * zpitch);

	for (yi = ystart; yi<=yend; yi++)
		{
		// compute span endpoints
		xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
		xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
		
		// compute starting points for u,v interpolants
		ui = ul + FIXP16_ROUND_UP;
		vi = vl + FIXP16_ROUND_UP;
        zi = zl + FIXP16_ROUND_UP;
	
		// compute u,v interpolants
		if ((dx = (xend - xstart))>0)
			{
			du = (ur - ul)/dx;
			dv = (vr - vl)/dx;
            dz = (zr - zl)/dx;
			} // end if
		else
			{
			du = (ur - ul);
			dv = (vr - vl);
            dz = (zr - zl);
			} // end else

		///////////////////////////////////////////////////////////////////////

		// test for x clipping, LHS
		if (xstart < min_clip_x)
			{
			// compute x overlap
			dx = min_clip_x - xstart;

			// slide interpolants over
			ui+=dx*du;
			vi+=dx*dv;
			zi+=dx*dz;
			
			// set x to left clip edge
			xstart = min_clip_x;

			} // end if
		
		// test for x clipping RHS
		if (xend > max_clip_x)
			xend = max_clip_x;

		///////////////////////////////////////////////////////////////////////

		// draw span
		for (xi=xstart; xi<=xend; xi++)
			{
            // test if z of current pixel is nearer than current z buffer value
            if (zi < z_ptr[xi])
               {
			   // write textel
		       // get textel first
 			   textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];

               // extract rgb components
               r_textel  = ((textel >> 11)       ); 
               g_textel  = ((textel >> 5)  & 0x3f); 
               b_textel =   (textel        & 0x1f);

               // modulate textel with lit background color
               r_textel*=r_base; 
               g_textel*=g_base;
               b_textel*=b_base;

               // finally write pixel, note that we did the math such that the results are r*32, g*64, b*32
               // hence we need to divide the results by 32,64,32 respetively, BUT since we need to shift
               // the results to fit into the destination 5.6.5 word, we can take advantage of the shifts
               // and they all cancel out for the most part, but we will need logical anding, we will do
               // it later when we optimize more...
               screen_ptr[xi] = ((b_textel >> 5) + ((g_textel >> 6) << 5) + ((r_textel >> 5) << 11));

               // update z-buffer
               z_ptr[xi] = zi;           
               } // end if

			// interpolate u,v
			ui+=du;
			vi+=dv;
            zi+=dz;
			} // end for xi

		// interpolate u,v,x along right and left edge
		xl+=dxdyl;
		ul+=dudyl;
		vl+=dvdyl;
		zl+=dzdyl;
	
		xr+=dxdyr;
		ur+=dudyr;
		vr+=dvdyr;
		zr+=dzdyr;

		// advance screen ptr
		screen_ptr+=mem_pitch;

        // advance zbuffer ptr
        z_ptr+=zpitch;

		// test for yi hitting second region, if so change interpolant
		if (yi==yrestart)
			{
     		// test interpolation side change flag

			if (irestart == INTERP_LHS)
			{
			// LHS
			dyl = (y2 - y1);	

			dxdyl = ((x2 - x1)   << FIXP16_SHIFT)/dyl;
			dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
			dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;   		
			dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;  

			// set starting values
			xl = (x1  << FIXP16_SHIFT);
			ul = (tu1 << FIXP16_SHIFT);
			vl = (tv1 << FIXP16_SHIFT);
			zl = (tz1 << FIXP16_SHIFT);

			// interpolate down on LHS to even up
			xl+=dxdyl;
			ul+=dudyl;
			vl+=dvdyl;
			zl+=dzdyl;
			} // end if
			else
			{
			// RHS
			dyr = (y1 - y2);	

			dxdyr = ((x1 - x2)   << FIXP16_SHIFT)/dyr;
			dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;  
			dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;   		
			dzdyr = ((tz1 - tz2) << FIXP16_SHIFT)/dyr;   

			// set starting values
			xr = (x2  << FIXP16_SHIFT);
			ur = (tu2 << FIXP16_SHIFT);
			vr = (tv2 << FIXP16_SHIFT);
			zr = (tz2 << FIXP16_SHIFT);

			// interpolate down on RHS to even up
			xr+=dxdyr;
			ur+=dudyr;
			vr+=dvdyr;
			zr+=dzdyr;
		
			} // end else


			} // end if

		} // end for y

	} // end if
	else
	{
	// no x clipping
	// point screen ptr to starting line
	screen_ptr = dest_buffer + (ystart * mem_pitch);

    // point zbuffer to starting line
    z_ptr = zbuffer + (ystart * zpitch);

	for (yi = ystart; yi<=yend; yi++)
		{
		// compute span endpoints
		xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
		xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
		
		// compute starting points for u,v,z interpolants
		ui = ul + FIXP16_ROUND_UP;
		vi = vl + FIXP16_ROUND_UP;
		zi = zl + FIXP16_ROUND_UP;
	
		// compute u,v interpolants
		if ((dx = (xend - xstart))>0)

			{
			du = (ur - ul)/dx;
			dv = (vr - vl)/dx;
            dz = (zr - zl)/dx;
			} // end if
		else
			{
			du = (ur - ul);
			dv = (vr - vl);
            dz = (zr - zl);
			} // end else

		// draw span
		for (xi=xstart; xi<=xend; xi++)
			{
            // test if z of current pixel is nearer than current z buffer value
            if (zi < z_ptr[xi])
               {
			   // write textel
		       // get textel first
 			   textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];

               // extract rgb components
               r_textel  = ((textel >> 11)       ); 
               g_textel  = ((textel >> 5)  & 0x3f); 
               b_textel =   (textel        & 0x1f);

               // modulate textel with lit background color
               r_textel*=r_base; 
              

⌨️ 快捷键说明

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