2014年3月24日星期一(9-1GOURAUD SHADER)

第九章开头就说,核心引擎要修改和添加的代码超过15000行,因此,先开始进行吧。幸好,看了下,大部分没动。主要是进行GOURAUD着色和基本纹理映射

因此,我觉得有必?要再加个DDRAW_TEXTURE类。

 

 

 

//为帮助纹理应设函数分析三角形定义的常量

#define           TRI_TYPE_NONE                               0

#define           TRI_TYPE_FLAT_TOP                      1

#define           TRI_TYPE_FLAT_BOTTOM                   2

#define           TRI_TYPE_FLAT_MASK                          3

#define           TRI_TYPE_GENERAL                       4

#define           INTERP_LHS                                  0

#define           INTERP_RHS                                  1

#define                                         MAX_VERTICES_PER_POLY                  6

新的多边形顶点结构定义

 

//多边形和多边形的属性

#define POLY4DV2_ATTR_2SIDED                0x0001

#define POLY4DV2_ATTR_TRANSPARENT           0x0002

#define POLY4DV2_ATTR_8BITCOLOR                 0x0004

#define POLY4DV2_ATTR_RGB16                     0x0008

#define POLY4DV2_ATTR_RGB24                     0x0010

 

#define POLY4DV2_ATTR_SHADE_MODE_PURE       0x0020

#define POLY4DV2_ATTR_SHADE_MODE_CONSTANT   0x0020

#define POLY4DV2_ATTR_SHADE_MODE_EMISSIVE   0x0020

 

#define POLY4DV2_ATTR_SHADE_MODE_FLAT       0x0040

#define POLY4DV2_ATTR_SHADE_MODE_GOURAUD    0x0080

#define POLY4DV2_ATTR_SHADE_MODE_PHONG      0x0100

#define POLY4DV2_ATTR_SHADE_MODE_FASTPHONG  0x0100

#define POLY4DV2_ATTR_SHADE_MODE_TEXTURE    0x0200

 

#define POLY4DV2_ATTR_ENABLE_MATERIAL       0x0800            //根据材质进行光照计算

#define POLY4DV2_ATTR_DISABLE_MATERIAL      0x1000            //根据多边形颜色进行光照

 

//多边形和多边形面的状态

#define  POLY4DV2_STATE_NULL                    0x0000

#define  POLY4DV2_STATE_ACTIVE              0x0001

#define  POLY4DV2_STATE_CLIPPED                 0x0002

#define  POLY4DV2_STATE_BACKFACE                0x0004

#define  POLY4DV2_STATE_LIT                     0x0008

 

//用于简单模型,指定着色模式

#define  VERTEX_FLAGS_OVERRIDE_MASK         0xf000

#define VERTEX_FLAGS_OVERRIDE_CONSTANT      0x1000

#define VERTEX_FLAGS_OVERRIDE_PURE          0x1000

#define VERTEX_FLAGS_OVERRIDE_FLAT          0x2000

#define VERTEX_FLAGS_OVERRIDE_GOURAUD       0x4000

#define VERTEX_FLAGS_OVERRIDE_TEXTURE       0x8000

 

#define  VERTEX_FLAGS_INVERT_TEXTURE_U      0x0080            //反转纹理坐标U

#define  VERTEX_FLAGS_INVERT_TEXTURE_V      0x0100            //反转纹理坐标V

#define  VERTEX_FLAGS_INVERT_SWAP_UV            0x0800            //将纹理坐标U和V互换

 

#define OBJECT4DV2_MAX_VERTICES                 4096

#define OBJECT4DV2_MAX_POLYS                8192

 

#define OBJECT4DV2_STATE_NULL               0x0000

#define OBJECT4DV2_STATE_ACTIVE                 0x0001

#define OBJECT4DV2_STATE_VISIBLE            0x0002

#define OBJECT4DV2_STATE_CULLED                 0x0004

 

#define  OBJECT4DV2_ATTR_SINGLE_FRAME       0x0001            //单帧物体

#define  OBJECT4DV2_ATTR_MULTI_FRAME            0x0002            //多帧物体

#define  OBJECT4DV2_ATTR_TEXTURES           0x0004            //指出物体是否包含带纹理的多边形

#define  RENDERLIST4DV2_MAX_POLYS           32768

 

#define VERTEX4DTV1_ATTR_NULL               0x0000            //顶点为空

#define VERTEX4DTV1_ATTR_POINT              0x0001            //顶点

#define VERTEX4DTV1_ATTR_NORMAL                 0x0002            //法线

#define VERTEX4DTV1_ATTR_TEXTURE            0x0004            //纹理坐标

 

新增的整型数学库

ypedef struct VECTOR2DI_TYP

{

    union

    {

         int M[2];

         struct

         {

             int x, y;

         };

    };

}VECTOR2DI ,POINT2DI, * VECTOR2DI_PTR, * POINT2DI_PTR;

typedef struct VECTOR3DI_TYP

{

    union

    {

         int M[3];

         struct

         {

             int x, y, z;

         };

    };

}VECTOR3DI ,POINT3DI, * VECTOR3DI_PTR, * POINT3DI_PTR;

 

typedef struct VECTOR4DI_TYP

{

    union

    {

         int M[4];

         struct

         {

             int x, y, z, w;

         };

    };

}VECTOR4DI ,POINT4DI, * VECTOR4DI_PTR, * POINT4DI_PTR;

 

加上一个宏,比较浮点数

#define  FCMP( a,b )                            (( fabs( a - b ) < EPSILON_E3) ? 1 : 0 )

能进行的,则先一步步来。

 

先加上个顶点数据结构

 

//包含两个纹理坐标和顶点法线的D齐次顶点

typedef struct VERTEX4DTV1_TYP

{

    union

    {

         float             M[12];                                 //以数组方式存储

    };

 

    //通过名称存取

    struct

    {

         float             x, y, z, w;                            //

         float             nx, ny, nz, nw;                        //法线(向量或点)

         float             u0, v0;                                //纹理坐标

 

         float             color;                                 //经过光照处理后的顶点颜色

         int               attr;                                  //属性

    };

 

    //高级类型

    struct

    {

         POINT4D           v;                                     //顶点

         VECTOR4D     n;                                     //法线

         POINT2D           t;                                     //纹理坐标

    };

}VERTEX4DTV2, * VERTEX4DTV2_PTR;

接着进行复制和初始化,一样的。

 

void DDRAW_LIUSHUIXIAN_TEXTURE::VERTEX4DTV1_COPY( VERTEX4DTV1_PTR vdst, VERTEX4DTV1_PTR vsrc )

{

    * vdst                             = * vsrc;

}

void DDRAW_LIUSHUIXIAN_TEXTURE::VERTEX4DTV1_Init( VERTEX4DTV1_PTR vdst, VERTEX4DTV1_PTR vsrc )

{

    * vdst                             = * vsrc;

}

 

新增一个多变性结构2.0版本

 

//多边形结构

typedef struct POLY4DV2_TYP

{

    int                                state;                    //状态信息

    int                                attr;                     //多边形的物理属性,如材质等

    int                                color;                    //多边形的颜色

    int                                lit_color[3];             //用于存储经过光照处理后的顶点颜色,

                                                                  //对于恒定着色,多边形颜色存储在第一个元素钟,

                                                                  //对于GOURAUD颜色,顶点颜色分别存储在三个元素中

    BITMAP_IMAGE_PTR               texture;              //指向纹理信息的指针,用于简单纹理映射

    int                                material;                 //材质,-1表示无材质

    VERTEX4DTV1_PTR                    vlist;                    //顶点列表

    POINT2D_PTR                        tlist;                    //纹理坐标列表

    int                                vert[3];              //顶点列表元素的索引

    int                                text[3];              //指向纹理坐标列表的索引

    float                              nlength;              //法线长度

}POLY4DV2, * POLY4DV2_PTR;

类似地

 

//外部自包含结构

typedef struct POLYF4DV2_TYP

{

    int                                state;                    //状态信息

    int                                attr;                     //多边形的物理属性,如材质等

    int                                color;                    //多边形的颜色

    int                                lit_color[3];             //用于存储经过光照处理后的顶点颜色,

                                                                  //对于恒定着色,多边形颜色存储在第一个元素钟,

                                                                  //对于GOURAUD颜色,顶点颜色分别存储在三个元素中

    BITMAP_IMAGE_PTR               texture;              //指向纹理信息的指针,用于简单纹理映射

    int                                material;                 //材质,-1表示无材质

    float                              nlength;              //法线长度

    VECTOR4D                       normal;                   //多边形法线

    float                              avg_z;                    //平均Z值,用于简单排序

 

    VERTEX4DTV1                        vlist[3];                 //顶点列表

    VERTEX4DTV1                        tvlist[3];                //变换后的顶点

    POLYF4DV2_TYP         *            next;                     //指向列表中下一个多边形的指针

    POLYF4DV2_TYP         *            prev;                     //指向列表中前一个多边形的指针

}POLYF4DV2, * POLYF4DV2_PTR;

 

 

//物体结构

typedef struct OBJECT4DV2_TYP

{

    int                                id;                       //物体的数值ID

    char                           name[64];                 //物体的字符串名称

 

    int                                state;                    //物体状态信息

    int                                attr;                     //物体的物理属性,如材质等

    int                                material;                 //材质,-1表示无材质

 

    float               *               avg_radius;               //物体的平均半径,用于碰撞检测,包含OBJECT4DV2_MAX_FRAMES个元素

    float               *               max_radius;               //物体的最大半径,包含OBJECT4DV2_MAX_FRAMES个元素

 

    POINT4D                            world_pos;                //物体在世界坐标系中的位置

    VECTOR4D                       dir;                 //物体加载时在局部坐标系下的旋转角度,

    VECTOR4D                       ux, uy, uz;               //记录物体变换后的朝向

    int                                num_vertices;             //每帧物体包含的顶点数

 

    int                                num_frames;               //帧数

    int                                total_vertices;           //全部顶点

    int                                curr_frame;               //当前帧

 

 

    VERTEX4DTV1_PTR                    vlist_local;          //存储顶点局部坐标的数组

    VERTEX4DTV1_PTR                    vlist_trans;          //存储顶点交换后坐标的数组

    //指向顶点列表的开头

    VERTEX4DTV1_PTR                    head_vlist_local;

    VERTEX4DTV1_PTR                    head_vlist_trans;

 

    //纹理坐标列表

    POINT2D_PTR                        tlist;                    //3*最大多边形

    BITMAP_IMAGE_PTR               texture;              //指向纹理信息的指针,用于简单纹理映射

 

    int                                num_polys;                //物体的多边形数

    POLY4DV2_PTR                   plist;                    //存储多边形数组

 

    int                                ivar1, ivar2;

    float                              fvar1, fvar2;

 

 

}OBJECT4DV2, * OBJECT4DV2_PTR;

还有个结构体的设定帧数,不在结构体内进行,

 

//指定当前帧

int DDRAW_LIUSHUIXIAN_TEXTURE::Set_OBJECT4DV2_Frame( OBJECT4DV2_PTR obj, int frame )

{

    //检查物体是否有效

    if ( ! obj )

    {

         return ( 0 );

    }

 

    //检查物体是否多帧

    if ( ! ( obj->attr & OBJECT4DV2_ATTR_MULTI_FRAME))

    {

         return ( 0 );

    }

 

    //物体有效且多帧的,将指针指向当前帧数据

 

    //检查frame是否越界

    if ( frame < 0 )

    {

         frame                     = 0;

    }

    else

    if ( frame >= obj->num_frames )

    {

         frame                     = obj->num_frames - 1;

    }

   

    //设置当前帧

    obj->curr_frame                = frame;

 

    //让指针指向顶点列表中相应的帧

    obj->vlist_local          = & ( obj->head_vlist_local[frame * obj->num_vertices]);

    obj->vlist_trans          = & ( obj->head_vlist_trans[frame * obj->num_vertices]);

 

 

}

 

下面列出了一些函数,

要删除物体,

 

int DDRAW_LIUSHUIXIAN_TEXTURE::Destroy_OBJECT4DV2( OBJECT4DV2_PTR obj )

{

    if ( obj->head_vlist_local)

    {

         free( obj->head_vlist_local );

    }

    if ( obj->head_vlist_trans)

    {

         free( obj->head_vlist_trans );

    }

    if ( obj->tlist)

    {

         free( obj->tlist );

    }

    if ( obj->plist)

    {

         free( obj->plist );

    }

    if ( obj->avg_radius)

    {

         free( obj->avg_radius );

    }

    if ( obj->max_radius)

    {

         free( obj->max_radius );

    }

 

    memset( ( void * ) obj, 0, sizeof( OBJECT4DV2) );

 

    return ( 1 );

 

 

}

 

初始化OBJECT4DV2,新版本

 

int DDRAW_LIUSHUIXIAN_TEXTURE::Init_OBJECT4DV2( OBJECT4DV2_PTR obj, int num_vertices, int num_polys, int num_frames, int destroy )

{

    if ( destroy )

    {

         Destroy_OBJECT4DV2(obj);

    }

    obj->vlist_local          = ( VERTEX4DTV1_PTR ) malloc( sizeof( VERTEX4DTV1) * num_vertices * num_frames );

    memset( ( void * ) obj->vlist_local, 0, sizeof( VERTEX4DTV1 ) * num_vertices * num_frames );

    obj->vlist_trans          = ( VERTEX4DTV1_PTR ) malloc( sizeof( VERTEX4DTV1) * num_vertices * num_frames );

    memset( ( void * ) obj->vlist_trans, 0, sizeof( VERTEX4DTV1 ) * num_vertices * num_frames );

 

    //纹理坐标数总是多边形数*3

    obj->tlist                     = ( POINT2D_PTR) malloc( sizeof( POINT2D) * num_polys * 3 );

    memset( ( void * ) obj->tlist, 0,  sizeof( POINT2D) * num_polys * 3  );

    obj->avg_radius                = ( float * ) malloc( sizeof( float) * num_frames );

    memset( ( void * ) obj->avg_radius, 0,  sizeof( float) * num_frames   );

    obj->max_radius                = ( float * ) malloc( sizeof( float) * num_frames );

    memset( ( void * ) obj->max_radius, 0,  sizeof( float) * num_frames   );

 

    //为多边形列表分配内存

    obj->plist                     = ( POLY4DV2_PTR )malloc( sizeof( POLY4DV2 ) * num_polys );

    memset( ( void * ) obj->plist, 0, sizeof( POLY4DV2 ) * num_polys );

 

    //设置指针

    obj->head_vlist_local     = obj->vlist_local;

    obj->head_vlist_trans     = obj->vlist_trans;

 

    //设置一些内部变量

    obj->num_frames                = num_frames;

    obj->num_polys                 = num_polys;

    obj->num_vertices         = num_vertices;

    obj->total_vertices            = num_vertices * num_frames;

 

    return ( 1 );

 

   

 

}

 

int DDRAW_LIUSHUIXIAN_TEXTURE::Compute_OBJECT4DV2_Poly_Normals( ddraw_math math, OBJECT4DV2_PTR obj )

{

    if ( ! obj )

    {

         return 0;

    }

 

    //处理物体的每个多边形

    for( int poly = 0; poly < obj->num_polys; poly ++ )

    {

         //获取多边形

         POLY4DV2_PTR              curr_poly         = & obj->plist[poly];

 

         //获取顶点列表中的顶点索引

         int                            vindex_0     = curr_poly->vert[0];

         int                            vindex_1     = curr_poly->vert[1];

         int                            vindex_2     = curr_poly->vert[2];

 

         //计算多边形的面法线,

         //顶点是按照顺时针方向排列的,u=p0->p1,v=p0->p2,n=UXV;

         VECTOR4D                  u, v, n;

         //计算u和v

         math.VECTOR4D_Build( & obj->vlist_local[vindex_0].v, & obj->vlist_local[vindex_1].v, & u );

         math.VECTOR4D_Build( & obj->vlist_local[vindex_0].v, & obj->vlist_local[vindex_2].v, & v );

         //计算叉积

         math.VECTOR4D_CROSS( & u, &v, &n );

   

         obj->plist[poly].nlength               = math.VECTOR4D_length( & n);

 

    }

 

    return 1;

}

下面,进行GOURAUD光照处理的顶点法线,这个问题也困扰我很久了,就是由多个多边形和多个顶点组成的模型,如何求每个顶点的法线,其实很简单,就是根据各个多边形的面积加权求平均。每次对模型变换时,必须对顶点法线页进行变换

int DDRAW_LIUSHUIXIAN_TEXTURE::Compute_OBJECT4DV2_Vertex_Normals( ddraw_math math, OBJECT4DV2_PTR obj )

{

    if ( ! obj )

    {

         return 0;

    }

 

    int                                polys_touch_vertex[OBJECT4DV2_MAX_VERTICES];

    memset( ( void *) polys_touch_vertex, 0, sizeof( int ) * OBJECT4DV2_MAX_VERTICES );

    //处理物体的每个多边形

    for( int poly = 0; poly < obj->num_polys; poly ++ )

    {

         //获取多边形

         POLY4DV2_PTR              curr_poly         = & obj->plist[poly];

         //检查多变性是否需要顶点法线

         if ( curr_poly.attr & POLY4DV2_ATTR_SHADE_MODE_GOURAUD )

         {   //获取顶点列表中的顶点索引

             int                            vindex_0     = curr_poly->vert[0];

             int                            vindex_1     = curr_poly->vert[1];

             int                            vindex_2     = curr_poly->vert[2];

 

             //计算多边形的面法线,

             //顶点是按照顺时针方向排列的,u=p0->p1,v=p0->p2,n=UXV;

             VECTOR4D                  u, v, n;

             //计算u和v

             math.VECTOR4D_Build( & obj->vlist_local[vindex_0].v, & obj->vlist_local[vindex_1].v, & u );

             math.VECTOR4D_Build( & obj->vlist_local[vindex_0].v, & obj->vlist_local[vindex_2].v, & v );

             //计算叉积

             math.VECTOR4D_CROSS( & u, &v, &n );

 

             //将共用顶点的多边形数+1

             polys_touch_vertex[vindex_0]++;

             polys_touch_vertex[vindex_1]++;

             polys_touch_vertex[vindex_2]++;

 

            

             math.VECTOR4D_ADD( & obj->vlist_local[vindex_0].n, & n, & obj->vlist_local[vindex_0].n );

             math.VECTOR4D_ADD( & obj->vlist_local[vindex_1].n, & n, & obj->vlist_local[vindex_1].n );

             math.VECTOR4D_ADD( & obj->vlist_local[vindex_2].n, & n, & obj->vlist_local[vindex_2].n );

         }

    }

    for ( int vertex = 0; vertex < obj->num_vertices; vertex ++ )

    {

         if ( polys_touch_vertex[vertex] >= 1)

         {

             obj->vlist_local[vertex].nx                 /= polys_touch_vertex[vertex];

             obj->vlist_local[vertex].ny                 /= polys_touch_vertex[vertex];

             obj->vlist_local[vertex].nz                 /= polys_touch_vertex[vertex];

             //将法线归一化

             math.VECTOR4D_Normalize( & obj->vlist_local[vertex].n );

 

         }

    }

 

    return 1;

}

然后,在此基础上,是加载PLG/PLX函数的新版本。

int DDRAW_LIUSHUIXIAN_TEXTURE::Load_OBJECT4DV2_PLG( ddraw_math math, OBJECT4DV2_PTR obj, char * filename, VECTOR4D_PTR scale, VECTOR4D_PTR pos, VECTOR4D_PTR rot, int vertex_flags )

{

    FILE *        fp;                       //文件指针

    char         buffer[256];          //缓冲区

    char *        token_string;             //指向要分析的物体数据文本的指针

 

    //先找到物体描述符

 

    //第一步清空和初始化OBJ

    memset( obj, 0, sizeof(OBJECT4DV2) );

    //将物体状态设置为可见和活动的

    obj->state                                      = OBJECT4DV2_STATE_ACTIVE | OBJECT4DV2_STATE_VISIBLE;

 

    //设置物体的位置

    obj->world_pos.x                            = pos->x;

    obj->world_pos.y                            = pos->y;

    obj->world_pos.z                            = pos->z;

    obj->world_pos.w                            = pos->w;

 

    //设置物体包含的帧数

    obj->num_frames                                 = 1;

    obj->curr_frame                                 = 0;

    obj->attr                                       = OBJECT4DV2_ATTR_SINGLE_FRAME;

 

    //第步,读取文件

    fp                                              = fopen( filename, "r" );

    //第步,读取物体描述符

    token_string                                = Get_Line_PLG(buffer, 255, fp );

    //分析物体描述符

    sscanf(token_string, "%s %d %d", obj->name, & obj->num_vertices, & obj->num_polys );

    //为存储顶点数和多边形数的变量分配内存

    Init_OBJECT4DV2( obj, obj->num_vertices, obj->num_polys, obj->num_frames );

    //第步:加载顶点列表

    for ( int vertex = 0; vertex < obj->num_vertices; vertex++ )

    {

         token_string                           = Get_Line_PLG( buffer, 255, fp );

         //分析顶点

         sscanf( token_string, "%f %f %f", & obj->vlist_local[vertex].x, & obj->vlist_local[vertex].y, & obj->vlist_local[vertex].z );

         obj->vlist_local[vertex].w             = 1;

 

         //缩放顶点坐标

         obj->vlist_local[vertex].x             *= scale->x;

         obj->vlist_local[vertex].y             *= scale->y;

         obj->vlist_local[vertex].z             *= scale->z;

         //设置顶点的D

         SET_BIT( obj->vlist_local[vertex].attr, VERTEX4DTV1_ATTR_POINT );

 

    }

    //计算平均半径和最大半径

    Compute_OBJECT4DV2_RADIUS(obj);

 

    int                   poly_surface_desc     = 0;         //PLG/PLX多边形描述符

    int                   poly_num_verts            = 0;         //当前多边形得顶点数(这里设定为)

    char              tmp_string[8];                              //存储多边形描述符的字符串

 

    //第步:加载多边形列表

    for( int poly = 0; poly < obj->num_polys; poly++ )

    {

         token_string                           = Get_Line_PLG( buffer, 255,fp );

 

         //假定所有模型都是由三角形组成,则每个多边形都有个顶点,将面描述符、顶点数和顶点列表存储到变量中

         sscanf( token_string, "%s %d %d %d %d", tmp_string, & poly_num_verts, & obj->plist[poly].vert[0],

             & obj->plist[poly].vert[1], & obj->plist[poly].vert[2]);

 

         //对于x开头的进制进行检测

         if ( tmp_string[0] == '0' && toupper( tmp_string[1]) == 'X' )

         {

             sscanf( tmp_string, "%x", & poly_surface_desc );

 

         }

         else

             poly_surface_desc                      = atoi( tmp_string );

 

         //让多边形顶点列表指向物体的顶点列表

         obj->plist[poly].vlist                          = obj->vlist_local;

 

         //存储顶点列表和多边形顶点索引值后,分析多边形描述符,并据此相应地设置多边形

         //提取多边形描述符中的每个位字段

         if( poly_surface_desc & PLX_2SIDED_FLAG )

         {

             SET_BIT( obj->plist[poly].attr, POLY4DV1_ATTR_2SIDED );

         }

         //设置颜色模式

         //如果是位

         if ( poly_surface_desc & PLX_COLOR_MODE_RGB_FLAG)

         {

             SET_BIT( obj->plist[poly].attr, POLY4DV2_ATTR_RGB16 );

             //提取RGB

             int               red                       = ( ( poly_surface_desc & 0x0f00) >> 8 );

             int               greeen                    = ( ( poly_surface_desc & 0x00f0) >> 4 );

             int               blue                  = ( poly_surface_desc & 0x000f );

 

             obj->plist[poly].color                      = _RGB16BIT565( red * 16, greeen * 16, blue * 16 );

         }

         else

         {

             //使用位颜色索引

             SET_BIT( obj->plist[poly].attr, POLY4DV2_ATTR_8BITCOLOR );

             //提取最后的位即可得到颜色索引

             obj->plist[poly].color                      = ( poly_surface_desc & 0x00ff );

         }

 

         //处理着色模式

         int                   shade_mode                = ( poly_surface_desc & PLX_SHADE_MODE_MASK );

 

         //设置多边形的着色模式

         switch ( shade_mode )

         {

         case PLX_SHADE_MODE_PURE_FLAG:

             {

 

                  SET_BIT( obj->plist[poly].attr, POLY4DV2_ATTR_SHADE_MODE_PURE );

 

 

             }

             break;

 

         case PLX_SHADE_MODE_FLAT_FLAG:

             {

                  SET_BIT( obj->plist[poly].attr, POLY4DV2_ATTR_SHADE_MODE_FLAT );

             }

             break;

 

         case PLX_SHADE_MODE_GOURAUD_FLAG:

             {

 

                  SET_BIT( obj->plist[poly].attr, POLY4DV2_ATTR_SHADE_MODE_GOURAUD );

                  SET_BIT( obj->vlist_local[obj->plist[poly].vert[0]].attr, VERTEX4DTV1_ATTR_NORMAL );

                  SET_BIT( obj->vlist_local[obj->plist[poly].vert[1]].attr, VERTEX4DTV1_ATTR_NORMAL );

                  SET_BIT( obj->vlist_local[obj->plist[poly].vert[2]].attr, VERTEX4DTV1_ATTR_NORMAL );

 

             }

             break;

 

         case PLX_SHADE_MODE_PHONG_FLAG:

             {

                  SET_BIT( obj->plist[poly].attr, POLY4DV1_ATTR_SHADE_MODE_PHONG );

                  SET_BIT( obj->vlist_local[obj->plist[poly].vert[0]].attr, VERTEX4DTV1_ATTR_NORMAL );

                  SET_BIT( obj->vlist_local[obj->plist[poly].vert[1]].attr, VERTEX4DTV1_ATTR_NORMAL );

                  SET_BIT( obj->vlist_local[obj->plist[poly].vert[2]].attr, VERTEX4DTV1_ATTR_NORMAL );

 

             }

             break;

         default:

             break;

 

         }

         //设置材质模式

         SET_BIT( obj->plist[poly].attr, POLY4DV2_ATTR_DISABLE_MATERIAL );

 

         //最后将多边形设置为活动状态

         obj->plist[poly].state                          = POLY4DV2_STATE_ACTIVE;

 

         //将多边形的顶点列表指针指向物体的顶点列表

         obj->plist[poly].vlist                          = obj->vlist_local;

         obj->plist[poly].tlist                          = obj->tlist;

    }

 

    //计算多边形法线的长度

    Compute_OBJECT4DV2_Poly_Normals( math, obj );

    //计算使用GOURAUD着色的多边形,计算其顶点法线

    Compute_OBJECT4DV2_Vertex_Normals( math, obj );

    //关闭文件

    fclose( fp );

 

    return ( 1 );

 

 

 

 

}

先加入光栅化逻辑

 

#define RASTERIZER_ACCURATE                     0

#define RASTERIZER_FAST                         1

#define RASTERIZER_FASTEST                  2

#define RASTERIZER_MODE                         RASTERIZER_ACCURATE

 

 

新的三角形渲染函数加入浮点数坐标

 

//绘制平底三角形

void ddraw_math::Draw_Bottom_Tri2_16( float x1, float y1, float x2, float y2, float x3, float y3, float color, UCHAR * _dest_buffer, int mempitch )

{

    float dx_right, dx_left, xs, xe,height;

    float temp_x, temp_y, right, left;

 

    int          iy1, iy3, loop_y;

 

    //将目标缓存转换为USHORT类型

    USHORT   *   dest_buffer       = ( USHORT * )_dest_buffer;

    //下一次扫描线的目标地址

 

    USHORT * dest_addr        = NULL;

    mempitch                  = ( mempitch >> 1 );

 

 

    if ( x3 < x2 )

    {

         SWAP( x2, x3, temp_x );

 

    }

 

    height                         = y3- y1;

    dx_left                        = ( x2 - x1 ) / height;

    dx_right                  = ( x3 - x1 ) / height;

 

    xs                             = x1;

    xe                             = x1;

 

#if( RASTERIZER_MODE == RASTERIZER_ACCURATE )

    if ( y1 < m_min_clip_y )

    {

         xs                        = xs + dx_left * ( -y1 + m_min_clip_y );

         xe                        = xe + dx_right * ( -y1 + m_min_clip_y );

         y1                        = m_min_clip_y;

 

         iy1                       = y1;

 

    }

    else

    {

         iy1                       = ceil( y1 );

         xs                        = xs + dx_left * ( -y1 + iy1 );

         xe                        = xe + dx_right * ( -y1 + iy1 );  

    }

 

    if ( y3 > m_max_clip_y )

    {

         y3                        = m_max_clip_y;

         iy3                       = y3 - y1;

    }

    else

    {

         iy3                       = ceil( y3 ) - 1;

    }

#endif

 

#if( ( RASTERIZER_MODE == RASTERIZER_FAST )  || ( RASTERIZER_MODE == RASTERIZER_FASTEST ) )

    if ( y1 < m_min_clip_y )

    {

         xs                        = xs + dx_left * ( -y1 + m_min_clip_y );

         xe                        = xe + dx_right * ( -y1 + m_min_clip_y );

         y1                        = m_min_clip_y;

 

 

    }

 

    if ( y3 > m_max_clip_y )

    {

         y3                        = m_max_clip_y;

    }

 

    iy1                            = ceil( y1 );

    iy3                            = ceil( y3 ) - 1;

 

#endif

 

 

    dest_addr                      = dest_buffer + iy1 * mempitch;

 

    if ( x1 >= m_min_clip_x && x1 <= m_max_clip_x && x2 >= m_min_clip_x && x2 <= m_max_clip_x && x3 >= m_min_clip_x && x3 <= m_max_clip_x )

    {

         for( loop_y = iy1; loop_y<= iy3; loop_y++, dest_addr += mempitch )

         {

             Mem_Set_WORD( dest_addr + ( unsigned int ) ( xs ), color, ( unsigned int ) ( ( int)xe -(int) xs + 1 ) );

             xs                    += dx_left;

             xe                    += dx_right;

         }

    }

    else

    {

         for( loop_y = iy1; loop_y<= iy3; loop_y++, dest_addr += mempitch )

         {

             left              = xs;

             right                 = xe;

 

             xs                    += dx_left;

             xe                    += dx_right;

 

             if ( left < m_min_clip_x )

             {

                  left         = m_min_clip_x;

                  if ( right < m_min_clip_x )

                  {

 

                      return;

 

                  }

             }

             if ( right > m_max_clip_x )

             {

                  right             = m_max_clip_x;

                  if ( left > m_max_clip_x )

                  {

                      return;

 

                  }

             }

 

             Mem_Set_WORD( dest_addr + ( unsigned int ) left, color, ( unsigned int ) ( ( int)right -(int) left + 1 ) );

         }

    }

 

 

}

 

 

void ddraw_math::Draw_Bottom_Tri2( float x1, float y1, float x2, float y2, float x3, float y3, int color, UCHAR * _dest_buffer, int mempitch )

{

    float dx_right, dx_left, xs, xe,height;

    float temp_x, temp_y, right, left;

 

    int          iy1, iy3, loop_y;

 

   

    //下一次扫描线的目标地址

 

    UCHAR dest_addr        = NULL;

 

 

 

    if ( x3 < x2 )

    {

         SWAP( x2, x3, temp_x );

 

    }

 

    height                         = y3- y1;

    dx_left                        = ( x2 - x1 ) / height;

    dx_right                  = ( x3 - x1 ) / height;

 

    xs                             = x1;

    xe                             = x1;

 

#if( RASTERIZER_MODE == RASTERIZER_ACCURATE )

    if ( y1 < m_min_clip_y )

    {

         xs                        = xs + dx_left * ( -y1 + m_min_clip_y );

         xe                        = xe + dx_right * ( -y1 + m_min_clip_y );

         y1                        = m_min_clip_y;

 

         iy1                       = y1;

 

    }

    else

    {

         iy1                       = ceil( y1 );

         xs                        = xs + dx_left * ( -y1 + iy1 );

         xe                        = xe + dx_right * ( -y1 + iy1 );  

    }

 

    if ( y3 > m_max_clip_y )

    {

         y3                        = m_max_clip_y;

         iy3                       = y3 - 1;

    }

    else

    {

         iy3                        = ceil( y3 ) - 1;

    }

#endif

 

#if( ( RASTERIZER_MODE == RASTERIZER_FAST )  || ( RASTERIZER_MODE == RASTERIZER_FASTEST ) )

    if ( y1 < m_min_clip_y )

    {

         xs                        = xs + dx_left * ( -y1 + m_min_clip_y );

         xe                        = xe + dx_right * ( -y1 + m_min_clip_y );

         y1                        = m_min_clip_y;

 

 

    }

 

    if ( y3 > m_max_clip_y )

    {

         y3                        = m_max_clip_y;

    }

 

    iy1                            = ceil( y1 );

    iy3                            = ceil( y3 ) - 1;

 

#endif

 

 

    dest_addr                      = _dest_buffer + iy1 * mempitch;

 

    if ( x1 >= m_min_clip_x && x1 <= m_max_clip_x && x2 >= m_min_clip_x && x2 <= m_max_clip_x && x3 >= m_min_clip_x && x3 <= m_max_clip_x )

    {

         for( loop_y = iy1; loop_y<= iy3; loop_y++, dest_addr += mempitch )

         {

             memset( ( UCHAR * )dest_addr + ( unsigned int ) ( xs ), color, ( unsigned int ) ( ( int)xe -(int) xs + 1 ) );

             xs                    += dx_left;

             xe                    += dx_right;

         }

    }

    else

    {

         for( loop_y = iy1; loop_y<= iy3; loop_y++, dest_addr += mempitch )

         {

             left              = xs;

             right                 = xe;

 

             xs                    += dx_left;

             xe                    += dx_right;

 

             if ( left < m_min_clip_x )

             {

                  left         = m_min_clip_x;

                  if ( right < m_min_clip_x )

                  {

 

                      return;

 

                  }

             }

             if ( right > m_max_clip_x )

             {

                  right             = m_max_clip_x;

                  if ( left > m_max_clip_x )

                  {

                      return;

 

                  }

             }

 

             memset( ( UCHAR *) dest_addr + ( unsigned int ) left, color, ( unsigned int ) ( ( int)right -(int) left + 1 ) );

         }

    }

 

 

}

没有区别啊。

对于平顶三角形,

 

void ddraw_math::Draw_Top_Tri2( float x1, float y1, float x2, float y2, float x3, float y3, int color, UCHAR * _dest_buffer, int mempitch )

{

    float dx_right, dx_left, xs, xe,height;

    float temp_x, temp_y, right, left;

    int iy1, iy3, loop_y;

    UCHAR * dest_addr = NULL;

    if ( x2 < x1 )

    {

         SWAP(x1, x2, temp_x );

 

    }

 

    height                         = y3- y1;

    dx_left                        = ( x3 - x1 ) / height;

    dx_right                   = ( x3 - x2 ) / height;

 

    xs                             = x1;

    xe                             = x2;

 

#if ( RASTERIZER_MODE == RASTERIZER_ACCURATE )

 

    if ( y1 < m_min_clip_y )

    {

         xs                        = xs + dx_left * ( -y1 + m_min_clip_y );

         xe                        = xe + dx_right * ( -y1 + m_min_clip_y );

         y1                        = m_min_clip_y;

         iy1                       = y1;

 

    }

    else

    {

         iy1                       = ceil( y1 );

         xs                        = xs + dx_left * ( -y1 + iy1 );

         xe                        = xe + dx_right * ( -y1 + iy1 );

 

    }

    if ( y3 > m_max_clip_y )

    {

         y3                        = m_max_clip_y;

         iy3                       = y3 - 1;

    }

    else

    {

         iy3                       = ceil( y3 ) - 1;

    }

#endif

 

#if ( ( RASTERIZER_MODE == RASTERIZER_FAST ) || ( RASTERIZER_MODE == RASTERIZER_FASTEST ) )

 

    if ( y1 < m_min_clip_y )

    {

         xs                        = xs + dx_left * ( -y1 + m_min_clip_y );

         xe                        = xe + dx_right * ( -y1 + m_min_clip_y );

         y1                        = m_min_clip_y;

 

    }

    else

 

    if ( y3 > m_max_clip_y )

    {

         y3                        = m_max_clip_y;

    }

    iy1                            = ceil( y1 );

    iy3                            = ceil( y3 ) - 1;

   

#endif

 

 

    dest_addr                      = _dest_buffer + iy1 * mempitch;

 

    if ( x1 >= m_min_clip_x && x1 <= m_max_clip_x && x2 >= m_min_clip_x && x2 <= m_max_clip_x && x3 >= m_min_clip_x && x3 <= m_max_clip_x )

    {

         for( loop_y = iy1; loop_y<= iy3; loop_y++, dest_addr += mempitch )

         {

             memset( ( UCHAR *) dest_addr + ( unsigned int ) xs, color, ( unsigned int ) ( (int) xe - ( int ) xs + 1 ) );

             xs                    += dx_left;

             xe                    += dx_right;

         }

    }

    else

    {

         for( temp_y = iy1; temp_y<= iy3; temp_y++, dest_addr += mempitch )

         {

             left              = xs;

             right                 = xe;

 

             xs                    += dx_left;

             xe                    += dx_right;

 

             if ( left < m_min_clip_x )

             {

                  left         = m_min_clip_x;

                  if ( right < m_min_clip_x )

                  {

 

                      continue;

 

                  }

             }

             if ( right > m_max_clip_x )

             {

                  right             = m_max_clip_x;

                  if ( left > m_max_clip_x )

                  {

                      continue;

 

                  }

             }

 

             memset( ( UCHAR * ) dest_addr + ( unsigned int ) left, color, ( unsigned int ) ( ( int ) right - (int )left + 1 ));

         }

    }

 

 

}

 

 

void ddraw_math::Draw_Top_Tri2_16( float x1, float y1, float x2, float y2, float x3, float y3, int color, UCHAR * _dest_buffer, int mempitch )

{

    float dx_right, dx_left, xs, xe,height;

    float temp_x, temp_y, right, left;

    int iy1, iy3, loop_y;

    USHORT   *        dest_buffer               = ( USHORT * )_dest_buffer;

    USHORT  *         dest_addr                 = NULL;

    mempitch                               = ( mempitch >> 1 );

 

    if ( x2 < x1 )

    {

         SWAP(x1, x2, temp_x );

 

    }

 

    height                         = y3- y1;

    dx_left                        = ( x3 - x1 ) / height;

    dx_right                  = ( x3 - x2 ) / height;

 

    xs                             = x1;

    xe                             = x2;

 

#if ( RASTERIZER_MODE == RASTERIZER_ACCURATE )

 

    if ( y1 < m_min_clip_y )

    {

         xs                        = xs + dx_left * ( -y1 + m_min_clip_y );

         xe                        = xe + dx_right * ( -y1 + m_min_clip_y );

         y1                        = m_min_clip_y;

         iy1                       = y1;

 

    }

    else

    {

         iy1                       = ceil( y1 );

         xs                        = xs + dx_left * ( -y1 + iy1 );

         xe                        = xe + dx_right * ( -y1 + iy1 );

 

    }

    if ( y3 > m_max_clip_y )

    {

         y3                        = m_max_clip_y;

         iy3                       = y3 - 1;

    }

    else

    {

         iy3                       = ceil( y3 ) - 1;

    }

#endif

 

#if ( ( RASTERIZER_MODE == RASTERIZER_FAST ) || ( RASTERIZER_MODE == RASTERIZER_FASTEST ) )

 

    if ( y1 < m_min_clip_y )

    {

         xs                        = xs + dx_left * ( -y1 + m_min_clip_y );

         xe                        = xe + dx_right * ( -y1 + m_min_clip_y );

         y1                        = m_min_clip_y;

 

    }

   

 

         if ( y3 > m_max_clip_y )

         {

             y3                        = m_max_clip_y;

         }

         iy1                            = ceil( y1 );

         iy3                            = ceil( y3 ) - 1;

 

#endif

 

 

         dest_addr                      = dest_buffer + iy1 * mempitch;

 

         if ( x1 >= m_min_clip_x && x1 <= m_max_clip_x && x2 >= m_min_clip_x && x2 <= m_max_clip_x && x3 >= m_min_clip_x && x3 <= m_max_clip_x )

         {

             for( loop_y = iy1; loop_y<= iy3; loop_y++, dest_addr += mempitch )

             {

                  Mem_Set_WORDdest_addr + ( unsigned int ) ( xs ), color, ( unsigned int ) ( (int) xe - ( int ) xs + 1 ) );

                  xs                    += dx_left;

                  xe                    += dx_right;

             }

         }

         else

         {

             for( loop_y = iy1; loop_y<= iy3; loop_y++, dest_addr += mempitch )

             {

                  left              = xs;

                  right                 = xe;

 

                  xs                    += dx_left;

                  xe                    += dx_right;

 

                  if ( left < m_min_clip_x )

                  {

                      left         = m_min_clip_x;

                      if ( right < m_min_clip_x )

                      {

 

                          continue;

 

                      }

                  }

                  if ( right > m_max_clip_x )

                  {

                      right             = m_max_clip_x;

                      if ( left > m_max_clip_x )

                      {

                          continue;

 

                      }

                  }

 

                  Mem_Set_WORDdest_addr + ( unsigned int ) ( left ), color, ( unsigned int ) ( ( int ) right - (int )left + 1 ));

             }

         }

 

 

}

 

下面,普通三角形,切割为平底和平顶

 

 

void ddraw_math::Draw_Triangle_2D2( float x1, float y1, float x2, float y2, float x3, float y3, int color, UCHAR * dest_buffer, int mempitch )

{

    float temp_x, temp_y, new_x;

 

    if( ( FCMP( x1, x2) && FCMP(x2, x3)) || ( FCMP( y1, y2) && FCMP( y2, y3)) )

        return;

 

    if ( y2 < y1 )

    {

         SWAP( x1, x2, temp_x );

         SWAP( y1, y2, temp_y );

    }

    if ( y3 < y1 )

    {

         SWAP( x1, x3, temp_x );

         SWAP( y1, y3, temp_y );

    }

 

    if ( y3 < y2 )

    {

         SWAP( x2, x3, temp_x );

         SWAP( y2, y3, temp_y );

    }

 

    if ( y3 < m_min_clip_y || y1 > m_max_clip_y ||

         ( x1 < m_min_clip_x && x2 < m_min_clip_x && x3 < m_min_clip_x) ||

         ( x1 > m_max_clip_x && x2 > m_max_clip_x && x3 > m_max_clip_x )

         )

    {

         return;

    }

 

    if ( FCMP( y1, y2 ) )

    {

         Draw_Top_Tri2( x1, y1, x2, y2, x3, y3, color, dest_buffer, mempitch );

    }

    else if( FCMP( y2, y3 ))

    {

         Draw_Bottom_Tri2( x1, y1, x2, y2, x3, y3, color, dest_buffer, mempitch );

    }

    else

    {

         new_x                 = x1 + ( y2 - y1) * ( x3 - x1 ) / ( y3 - y1);

         Draw_Bottom_Tri2( x1, y1, new_x, y2, x2, y2, color, dest_buffer, mempitch );

         Draw_Top_Tri2( x2, y2, new_x, y2, x3, y3, color, dest_buffer, mempitch );

    }

 

 

}

16位版本

 

void ddraw_math::Draw_Triangle_2D2_16( float x1, float y1, float x2, float y2, float x3, float y3, int color, UCHAR * dest_buffer, int mempitch )

{

    float temp_x, temp_y, new_x;

 

    if( ( FCMP( x1, x2) && FCMP(x2, x3)) || ( FCMP( y1, y2) && FCMP( y2, y3)) )

         return;

 

    if ( y2 < y1 )

    {

         SWAP( x1, x2, temp_x );

         SWAP( y1, y2, temp_y );

    }

    if ( y3 < y1 )

    {

         SWAP( x1, x3, temp_x );

         SWAP( y1, y3, temp_y );

    }

 

    if ( y3 < y2 )

    {

         SWAP( x2, x3, temp_x );

         SWAP( y2, y3, temp_y );

    }

 

    if ( y3 < m_min_clip_y || y1 > m_max_clip_y ||

         ( x1 < m_min_clip_x && x2 < m_min_clip_x && x3 < m_min_clip_x) ||

         ( x1 > m_max_clip_x && x2 > m_max_clip_x && x3 > m_max_clip_x )

         )

    {

         return;

    }

 

    if ( FCMP( y1, y2 ) )

    {

         Draw_Top_Tri2_16( x1, y1, x2, y2, x3, y3, color, dest_buffer, mempitch );

    }

    else if( FCMP( y2, y3 ))

    {

         Draw_Bottom_Tri2_16( x1, y1, x2, y2, x3, y3, color, dest_buffer, mempitch );

    }

    else

    {

         new_x                 = x1 + ( y2 - y1) * ( x3 - x1 ) / ( y3 - y1);

         Draw_Bottom_Tri2_16( x1, y1, new_x, y2, x2, y2, color, dest_buffer, mempitch );

         Draw_Top_Tri2_16( x2, y2, new_x, y2, x3, y3, color, dest_buffer, mempitch );

    }

 

 

}

2014年4月4日星期五(9-1,GOURAUD着色处理)

这章的前提引擎,除了3DSMAX和COB模型的载入代码外,都写完了,正式进入GOURAUD着色,

就是三角形每个顶点法线(而不是多边形法线)执行光照计算,,并将RGB颜色存储在顶点中。然后用线性插值计算三角形中各点颜色,

在扫描每行时,是按照梯度逐像素插值。

DEMO9-1没考虑光照因素,。

思路很简单,但是代码很长,

 

 

void ddraw_math::Draw_Gouraud_Triangle16( POLYF4DV2_PTR face, UCHAR * _dest_buffer, int mem_pitch )

{

    int                   v0 = 0, v1 = 1, v2 = 2, temp = 0, tri_type = TRI_TYPE_NONE, irestartINTERP_LHS;

 

    int                   dx, dy, dyl, dyr,     //存储差值

         u, v, w,              //RGB

         du, dv, dw,

         xi, yi,                   //当前的x和y坐标

         ui,vi,wi,                 //当前的RGB

         index_x, index_y,     //循环变量

         x, y,                     //存储一般性X和Y坐标

         xstart, xend,ystart, yrestart, yend, xl,

         dxdyl, xr, dxdyr, dudyl, ul, dvdyl, vl, dwdyl,

         wl, dudyr, ur, dvdyr, vr, dwdyr, wr;

 

    int                   x0, y0, tu0, tv0, tw0,    //顶点的初始颜色

         x1, y1, tu1, tv1, tw1,   

         x2, y2, tu2, tv2, tw2;   

 

    int                   r_base0, g_base0, b_base0, //顶点的初始颜色

         r_base1, g_base1, b_base1,

         r_base2, g_base2, b_base2;

 

    USHORT       *        screen_ptr                     = NULL,

         *        screen_line                    = NULL,

         *        tempmap                        = NULL,

         *        dest_buffer                    = (USHORT * )_dest_buffer;;

 

    //将内存跨距的单位调整为字

    mem_pitch                                            >>= 1;

 

    //判断三角形是否在屏幕内

    if ( ( ( face->tvlist[0].y < m_min_clip_y) &&

         ( face->tvlist[1].y < m_min_clip_y) &&

         ( face->tvlist[2].y < m_min_clip_y) ) ||

 

         ( ( face->tvlist[0].y > m_max_clip_y) &&

         ( face->tvlist[1].y > m_max_clip_y) &&

         ( face->tvlist[2].y > m_max_clip_y) ) ||

 

         ( ( face->tvlist[0].x < m_min_clip_x) &&

         ( face->tvlist[1].x < m_min_clip_x) &&

         ( face->tvlist[2].x < m_min_clip_x) ) ||

 

         ( ( face->tvlist[0].x > m_max_clip_x) &&

         ( face->tvlist[1].x > m_max_clip_x) &&

         ( face->tvlist[2].x > m_max_clip_x) ) )

 

    {

         return;

    }

 

    //判断三角形是否退化为直线

    if ( ( ( face->tvlist[0].x == face->tvlist[1].x ) &&

         ( face->tvlist[1].x == face->tvlist[2].x ) ) ||

         ( ( face->tvlist[0].y == face->tvlist[1].y ) &&

         ( face->tvlist[1].y == face->tvlist[2].y ) ) )

    {

         return;

    }

 

    //对顶点进行排序

    if ( face->tvlist[v1].y < face->tvlist[v0].y )

    {

         SWAP( v0, v1, temp );

    }

 

    if ( face->tvlist[v2].y < face->tvlist[v0].y )

    {

         SWAP( v0, v2, temp );

    }

 

    if ( face->tvlist[v2].y < face->tvlist[v1].y )

    {

         SWAP( v1, v2, temp );

    }

 

 

    //判断三角形是否平顶

    if ( face->tvlist[v0].y == face->tvlist[v1].y )

    {

         //设置三角形类型

         tri_type                       = TRI_TYPE_FLAT_TOP;

         //将顶点从左到右的顺序排列

         if ( face->tvlist[v1].x < face->tvlist[v0].x )

         {

             SWAP( v0, v1, temp );

         }

    }

    else

         //判断三角形是否平底

         if ( face->tvlist[v1].y == face->tvlist[v2].y )

         {

             //设置三角形类型

             tri_type                       = TRI_TYPE_FLAT_BOTTOM;

             //将顶点从左到右的顺序排列

             if ( face->tvlist[v2].x < face->tvlist[v1].x )

             {

                  SWAP( v1, v2, temp );

             }

         }

         else

             //肯定是常规三角形

         {

             tri_type                       = TRI_TYPE_GENERAL;

         }

 

         _RGB565FROM16BIT( face->lit_color[v0], & r_base0, & g_base0, & b_base0 );

         _RGB565FROM16BIT( face->lit_color[v1], & r_base1, & g_base1, & b_base1 );

         _RGB565FROM16BIT( face->lit_color[v2], & r_base2, & g_base2, & b_base2 );

 

         //扩展到位

         r_base0                                <<= 3;

         g_base0                                <<= 3;

         b_base0                                <<= 3;

 

         r_base1                                <<= 3;

         g_base1                                <<= 3;

         b_base1                                <<= 3;

 

         r_base2                                <<= 3;

         g_base2                                <<= 3;

         b_base2                                <<= 3;

 

    //提取各个顶点的坐标值和RGB

         x0                                     = ( int ) ( face->tvlist[v0].x + 0.5 );

         y0                                     = ( int ) ( face->tvlist[v0].y + 0.5 );

         tu0                                    = r_base0;

         tv0                                    = g_base0;

         tw0                                    = b_base0;

 

         x1                                     = ( int ) ( face->tvlist[v1].x + 0.5 );

         y1                                     = ( int ) ( face->tvlist[v1].y + 0.5 );

        tu1                                     = r_base1;

         tv1                                    = g_base1;

         tw1                                    = b_base1;

 

         x2                                     = ( int ) ( face->tvlist[v2].x + 0.5 );

         y2                                     = ( int ) ( face->tvlist[v2].y + 0.5 );

         tu2                                    = r_base2;

         tv2                                    = g_base2;

         tw2                                    = b_base2;

 

         //设置斜率转折点

         yrestart                           = y1;

 

         //判断三角形类型

         if ( tri_type & TRI_TYPE_FLAT_MASK )

         {

             if ( tri_type & TRI_TYPE_FLAT_TOP )

             {

                  //计算各种差值

                  dy                             = y2 - y0;

                  dxdyl                          = ( ( x2 - x0 ) << FIXP16_SHIFT ) / dy;

                  dudyl                          = ( ( tu2 - tu0 ) << FIXP16_SHIFT ) / dy;

                  dvdyl                          = ( ( tv2 - tv0 ) << FIXP16_SHIFT ) / dy;

                  dwdyl                          = ( ( tw2 - tw0 ) << FIXP16_SHIFT ) / dy;

                  dxdyr                          = ( ( x2 - x1 ) << FIXP16_SHIFT ) / dy;

                  dudyr                          = ( ( tu2 - tu1 ) << FIXP16_SHIFT ) / dy;

                  dvdyr                          = ( ( tv2 - tv1 ) << FIXP16_SHIFT ) / dy;

                  dwdyr                          = ( ( tw2 - tw1 ) << FIXP16_SHIFT ) / dy;

 

                  //垂直裁剪测试

                  if ( y0 < m_min_clip_y )

                  {

                      //垂直计算Y坐标差值

                      dy                        = ( m_min_clip_y - y0 );

                      //计算第一条扫描线起点的各种值

                      xl                        = dxdyl * dy + ( x0 << FIXP16_SHIFT );

                      ul                        = dudyl * dy + ( tu0 << FIXP16_SHIFT );

                      vl                        = dvdyl * dy + ( tv0 << FIXP16_SHIFT );

                      wl                        = dwdyl * dy + ( tw0 << FIXP16_SHIFT );

 

                      //计算第一条扫描线终点的各种值

                      xr                        = dxdyr * dy + ( x1 << FIXP16_SHIFT );

                      ur                        = dudyr * dy + ( tu1 << FIXP16_SHIFT );

                      vr                        = dvdyr * dy + ( tv1 << FIXP16_SHIFT );

                      wr                        = dwdyr * dy + ( tw1 << FIXP16_SHIFT );

 

                      //计算第一条扫描线的Y坐标

                      ystart                    = m_min_clip_y;

                  }

                  else

                  {

                      //不用裁剪

                      //设置第一条扫描线起点和终点的各种值

                      xl                        = ( x0 << FIXP16_SHIFT );

                      ul                        = ( tu0 << FIXP16_SHIFT );

                      vl                        = ( tv0 << FIXP16_SHIFT );

                      wl                        = ( tw0 << FIXP16_SHIFT );

 

                      xr                        = ( x1 << FIXP16_SHIFT );

                      ur                        = ( tu1 << FIXP16_SHIFT );

                      vr                        = ( tv1 << FIXP16_SHIFT );

                      wr                        = ( tw1 << FIXP16_SHIFT );

 

                      //计算第一条扫描线的Y坐标

                      ystart                    = y0;

 

                  }

 

             }

             else   //肯定是平底三角形

             {

                  //计算各种差值

                  dy                             = y1 - y0;

                  dxdyl                          = ( ( x1 - x0 ) << FIXP16_SHIFT ) / dy;

                  dudyl                          = ( ( tu1 - tu0 ) << FIXP16_SHIFT ) / dy;

                  dvdyl                          = ( ( tv1 - tv0 ) << FIXP16_SHIFT ) / dy;

                  dwdyl                          = ( ( tw1 - tw0 ) << FIXP16_SHIFT ) / dy;

                  dxdyr                          = ( ( x2 - x0 ) << FIXP16_SHIFT ) / dy;

                  dudyr                          = ( ( tu2 - tu0 ) << FIXP16_SHIFT ) / dy;

                  dvdyr                          = ( ( tv2 - tv0 ) << FIXP16_SHIFT ) / dy;

                  dwdyr                          = ( ( tw2 - tw0 ) << FIXP16_SHIFT ) / dy;

 

                  //垂直裁剪测试

                  if ( y0 < m_min_clip_y )

                  {

                      //垂直计算Y坐标差值

                      dy                        = ( m_min_clip_y - y0 );

                      //计算第一条扫描线起点的各种值

                      xl                        = dxdyl * dy + ( x0 << FIXP16_SHIFT );

                      ul                        = dudyl * dy + ( tu0 << FIXP16_SHIFT );

                      vl                        = dvdyl * dy + ( tv0 << FIXP16_SHIFT );

                      wl                        = dwdyl * dy + ( tw0 << FIXP16_SHIFT );

 

                      //计算第一条扫描线终点的各种值

                      xr                        = dxdyr * dy + ( x0 << FIXP16_SHIFT );

                      ur                        = dudyr * dy + ( tu0 << FIXP16_SHIFT );

                      vr                        = dvdyr * dy + ( tv0 << FIXP16_SHIFT );

                      wr                        = dwdyr * dy + ( tw0 << FIXP16_SHIFT );

 

                      //计算第一条扫描线的Y坐标

                      ystart                    = m_min_clip_y;

                  }

                  else

                  {

                      //不用裁剪

                      //设置第一条扫描线起点和终点的各种值

                      xl                        = ( x0 << FIXP16_SHIFT );

                      ul                        = ( tu0 << FIXP16_SHIFT );

                      vl                        = ( tv0 << FIXP16_SHIFT );

                      wl                        = ( tw0 << FIXP16_SHIFT );

 

                      xr                        = ( x0 << FIXP16_SHIFT );

                      ur                        = ( tu0 << FIXP16_SHIFT );

                      vr                        = ( tv0 << FIXP16_SHIFT );

                      wr                        = ( tw0 << FIXP16_SHIFT );

 

                      //计算第一条扫描线的Y坐标

                      ystart                    = y0;

 

                  }

 

             }

 

             //总是检测三角形最下面的部分是否会被裁剪掉

             if (( yend = y2 ) > m_max_clip_y )

             {

                  yend                      = m_max_clip_y;

             }

 

             //水平裁剪测试

             if ( ( x0 < m_min_clip_x ) || ( x0 > m_max_clip_x ) ||

                   ( x1 < m_min_clip_x ) || ( x1 > m_max_clip_x ) ||

                   ( x2 < m_min_clip_x ) || ( x2 > m_max_clip_x ) )

             {

                  //裁剪版本

                  //让指screen_ptr指向第一条扫描线起点在缓存的位置

                  screen_ptr                     = dest_buffer + ( ystart * mem_pitch );

                  for ( yi = ystart; yi <= yend; yi++ )

                  {

                      //计算扫描线起点和终点的X坐标

                      xstart                    = ( ( xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT );

                      xend                  = ( ( xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT );

                      //计算扫描线起点和终点的坐标

                      ui                        = ul + FIXP16_ROUND_UP;

                      vi                        = vl + FIXP16_ROUND_UP;

                      wi                        = wl + FIXP16_ROUND_UP;

                      //计算扫描线上的RGB梯度

                      if ( ( dx = ( xend - xstart )) > 0 )

                      {

                          du                    = ( ur - ul ) / dx;

                          dv                    = ( vr - vl ) / dx;

                          dw                    = ( wr - wl ) / dx;

 

                      }

                      else

                      {

                          du                    = ( ur - ul );

                          dv                    = ( vr - vl );

                          dw                    = ( wr - wl );

 

                      }

                      //扫描线起点水平裁剪测试

                      if ( xstart < m_min_clip_x )

                      {

                          //计算起点移动距离

                          dx                    = m_min_clip_x - xstart;

                          //重新计算扫描线起点的RGB

                          ui                    += dx * du;

                          vi                    += dx * dv;

                          wi                    += dx * dw;

 

                          //重新设置循环起始条件

                          xstart                = m_min_clip_x;

                      }

 

                      //终点水平测试

                      if ( xend > m_max_clip_x )

                      {

                          xend              = m_max_clip_x;

                      }

 

                      //绘制扫描线

                      for( xi = xstart; xi <= xend; xi ++ )

                      {

                          //绘制像素,假设格式为.6.5

                          screen_ptr[xi]        = ( ( ui >> ( FIXP16_SHIFT + 3)) << 11 ) +

                               ( ( vi >> ( FIXP16_SHIFT + 2)) << 5 ) +

                               ( wi >> ( FIXP16_SHIFT + 3 ));

 

                          //计算下一个像素的RGB

                          ui                    += du;

                          vi                    += dv;

                          wi                    += dw;

                      }

 

                      //计算下一条扫描线起点和终点的x坐标和RGB值

                      xl                        += dxdyl;

                      ul                        += dudyl;

                      vl                        += dvdyl;

                      wl                        += dwdyl;

                      xr                        += dxdyr;

                      ur                        += dudyr;

                      vr                        += dvdyr;

                      wr                        += dwdyr;

 

                      //让指针screen_ptr指向视频缓存的下一行

                      screen_ptr                += mem_pitch;

 

                  }

 

             }

 

             //三角形没有被裁剪时的绘制代码

             else

             {

                  screen_ptr                     = dest_buffer + ( ystart * mem_pitch );

                  for ( yi = ystart; yi <= yend; yi++ )

                  {

                      //计算扫描线起点和终点的X坐标

                      xstart                    = ( ( xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT );

                      xend                  = ( ( xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT );

                      //计算扫描线起点和终点的坐标

                      ui                        = ul + FIXP16_ROUND_UP;

                      vi                        = vl + FIXP16_ROUND_UP;

                      wi                        = wl + FIXP16_ROUND_UP;

                      //计算扫描线上的RGB梯度

                      if ( ( dx = ( xend - xstart )) > 0 )

                      {

                          du                    = ( ur - ul ) / dx;

                          dv                    = ( vr - vl ) / dx;

                          dw                    = ( wr - wl ) / dx;

 

                      }

                      else

                      {

                          du                    = ( ur - ul );

                          dv                    = ( vr - vl );

                          dw                    = ( wr - wl );

 

                      }

                 

 

                      //绘制扫描线

                      for( xi = xstart; xi <= xend; xi ++ )

                      {

                          //绘制像素,假设格式为.6.5

                          screen_ptr[xi]        = ( ( ui >> ( FIXP16_SHIFT + 3)) << 11 ) +

                               ( ( vi >> ( FIXP16_SHIFT + 2)) << 5 ) +

                               ( wi >> ( FIXP16_SHIFT + 3 ));

 

                          //计算下一个像素的RGB

                          ui                    += du;

                          vi                    += dv;

                          wi                    += dw;

                      }

 

                      //计算下一条扫描线起点和终点的x坐标和RGB值

                      xl                        += dxdyl;

                      ul                        += dudyl;

                      vl                        += dvdyl;

                      wl                        += dwdyl;

                      xr                        += dxdyr;

                      ur                        += dudyr;

                      vr                        += dvdyr;

                      wr                        += dwdyr;

 

                      //让指针screen_ptr指向视频缓存的下一行

                      screen_ptr                += mem_pitch;

 

                  }

             }

 

         }

         else

             //绘制常规三角形

         if ( tri_type == TRI_TYPE_GENERAL )

         {

             if (( yend = y2 ) > m_max_clip_y )

             {

                  yend                      = m_max_clip_y;

             }

             if ( y1 < m_min_clip_y )

             {

                  //垂直计算Y坐标差值

                  //左侧

                  dyl                       = ( y2 - y1  );

 

                  dxdyl                          = ( ( x2 - x1 ) << FIXP16_SHIFT ) / dyl;

                  dudyl                          = ( ( tu2 - tu1 ) << FIXP16_SHIFT ) / dyl;

                  dvdyl                          = ( ( tv2 - tv1 ) << FIXP16_SHIFT ) / dyl;

                  dwdyl                          = ( ( tw2 - tw1 ) << FIXP16_SHIFT ) / dyl;

 

                  //右侧

                  dyr                            = ( y2 - y0  );

 

                  dxdyr                          = ( ( x2 - x0 ) << FIXP16_SHIFT ) / dyr;

                  dudyr                          = ( ( tu2 - tu0 ) << FIXP16_SHIFT ) / dyr;

                  dvdyr                          = ( ( tv2 - tv0 ) << FIXP16_SHIFT ) / dyr;

                  dwdyr                          = ( ( tw2 - tw0 ) << FIXP16_SHIFT ) / dyr;

 

 

                  //垂直计算Y坐标差值

                  dyr                            = ( m_min_clip_y - y0 );

                  dyl                            = ( m_min_clip_y - y1 )   ;

                  //计算第一条扫描线起点的各种值

                  xl                        = dxdyl * dyl + ( xl << FIXP16_SHIFT );

                  ul                        = dudyl * dyl + ( tu1 << FIXP16_SHIFT );

                  vl                        = dvdyl * dyl + ( tv1 << FIXP16_SHIFT );

                  wl                        = dwdyl * dyl + ( tw1 << FIXP16_SHIFT );

 

                  //计算第一条扫描线终点的各种值

                  xr                        = dxdyr * dyr + ( x0 << FIXP16_SHIFT );

                  ur                        = dudyr * dyr + ( tu0 << FIXP16_SHIFT );

                  vr                        = dvdyr * dyr + ( tv0 << FIXP16_SHIFT );

                  wr                        = dwdyr * dyr + ( tw0 << FIXP16_SHIFT );

 

                  //计算第一条扫描线的Y坐标

                  ystart                    = m_min_clip_y;

 

                  if ( dxdyr > dxdyl )

                  {

                      SWAP( dxdyl, dxdyr, temp );

                      SWAP( dudyl, dudyr, temp );

                      SWAP( dvdyl, dvdyr, temp );

                      SWAP( dwdyl, dwdyr, temp );

                      SWAP( xl, xr, temp );

                      SWAP( ul, ur, temp );

                      SWAP( vl, vr, temp );

                      SWAP( wl, wr, temp );

                      SWAP( x1, x2, temp );

                      SWAP( y1, y2, temp );

                      SWAP( tu1, tu2, temp );

                      SWAP( tv1, tv2, temp );

                      SWAP( tw1, tw2, temp );

 

                      irestart          = INTERP_RHS;

 

                  }

             }

             else

                  if ( y0 < m_min_clip_y )

                  {

                      //垂直计算Y坐标差值

                      //左侧

                      dyl                            = ( y1 - y0  );

 

                      dxdyl                          = ( ( x1 - x0 ) << FIXP16_SHIFT ) / dyl;

                      dudyl                          = ( ( tu1 - tu0 ) << FIXP16_SHIFT ) / dyl;

                      dvdyl                          = ( ( tv1 - tv0 ) << FIXP16_SHIFT ) / dyl;

                      dwdyl                          = ( ( tw1 - tw0 ) << FIXP16_SHIFT ) / dyl;

 

                      //右侧

                      dyr                            = ( y2 - y0  );

 

                      dxdyr                          = ( ( x2 - x0 ) << FIXP16_SHIFT ) / dyr;

                      dudyr                          = ( ( tu2 - tu0 ) << FIXP16_SHIFT ) / dyr;

                      dvdyr                          = ( ( tv2 - tv0 ) << FIXP16_SHIFT ) / dyr;

                      dwdyr                          = ( ( tw2 - tw0 ) << FIXP16_SHIFT ) / dyr;

 

 

                      //垂直计算Y坐标差值

                      dy                             = ( m_min_clip_y - y0 );

                 

                      //计算第一条扫描线起点的各种值

                      xl                             = dxdyl * dy + ( x0 << FIXP16_SHIFT );

                      ul                             = dudyl * dy + ( tu0 << FIXP16_SHIFT );

                      vl                             = dvdyl * dy + ( tv0 << FIXP16_SHIFT );

                      wl                             = dwdyl * dy + ( tw0 << FIXP16_SHIFT );

 

                      //计算第一条扫描线终点的各种值

                      xr                             = dxdyr * dy + ( x0 << FIXP16_SHIFT );

                      ur                             = dudyr * dy + ( tu0 << FIXP16_SHIFT );

                      vr                             = dvdyr * dy + ( tv0 << FIXP16_SHIFT );

                      wr                             = dwdyr * dy + ( tw0 << FIXP16_SHIFT );

 

                      //计算第一条扫描线的Y坐标

                      ystart                         = m_min_clip_y;

 

                      if ( dxdyr < dxdyl )

                      {

                          SWAP( dxdyl, dxdyr, temp );

                          SWAP( dudyl, dudyr, temp );

                          SWAP( dvdyl, dvdyr, temp );

                          SWAP( dwdyl, dwdyr, temp );

                          SWAP( xl, xr, temp );

                          SWAP( ul, ur, temp );

                          SWAP( vl, vr, temp );

                          SWAP( wl, wr, temp );

                          SWAP( x1, x2, temp );

                          SWAP( y1, y2, temp );

                          SWAP( tu1, tu2, temp );

                          SWAP( tv1, tv2, temp );

                          SWAP( tw1, tw2, temp );

 

                          irestart          = INTERP_RHS;

 

                      }

                  }

                  else

                  {

                      dyl                            = ( y1 - y0  );

 

                      dxdyl                          = ( ( x1 - x0 ) << FIXP16_SHIFT ) / dyl;

                      dudyl                          = ( ( tu1 - tu0 ) << FIXP16_SHIFT ) / dyl;

                      dvdyl                          = ( ( tv1 - tv0 ) << FIXP16_SHIFT ) / dyl;

                      dwdyl                          = ( ( tw1 - tw0 ) << FIXP16_SHIFT ) / dyl;

 

                      //右侧

                      dyr                            = ( y2 - y0  );

 

                      dxdyr                          = ( ( x2 - x0 ) << FIXP16_SHIFT ) / dyr;

                      dudyr                          = ( ( tu2 - tu0 ) << FIXP16_SHIFT ) / dyr;

                      dvdyr                          = ( ( tv2 - tv0 ) << FIXP16_SHIFT ) / dyr;

                      dwdyr                          = ( ( tw2 - tw0 ) << FIXP16_SHIFT ) / dyr;

 

                      xl                             = ( x0 << FIXP16_SHIFT );

                      ul                             = ( tu0 << FIXP16_SHIFT );

                      vl                             = ( tv0 << FIXP16_SHIFT );

                      wl                             = ( tw0 << FIXP16_SHIFT );

 

                      xr                             = ( x0 << FIXP16_SHIFT );

                      ur                             = ( tu0 << FIXP16_SHIFT );

                      vr                             = ( tv0 << FIXP16_SHIFT );

                      wr                             = ( tw0 << FIXP16_SHIFT );

 

                      ystart                         = y0;

 

 

                      if ( dxdyr < dxdyl )

                      {

                          SWAP( dxdyl, dxdyr, temp );

                          SWAP( dudyl, dudyr, temp );

                          SWAP( dvdyl, dvdyr, temp );

                          SWAP( dwdyl, dwdyr, temp );

                          SWAP( xl, xr, temp );

                          SWAP( ul, ur, temp );

                          SWAP( vl, vr, temp );

                          SWAP( wl, wr, temp );

                          SWAP( x1, x2, temp );

                          SWAP( y1, y2, temp );

                          SWAP( tu1, tu2, temp );

                          SWAP( tv1, tv2, temp );

                          SWAP( tw1, tw2, temp );

 

                          irestart          = INTERP_RHS;

                      }

 

 

                  }

                  //水平裁剪测试

                  if ( ( x0 < m_min_clip_x ) || ( x0 > m_max_clip_x ) ||

                      ( x1 < m_min_clip_x ) || ( x1 > m_max_clip_x ) ||

                      ( x2 < m_min_clip_x ) || ( x2 > m_max_clip_x ) )

                  {

                      //裁剪版本

                      //让指screen_ptr指向第一条扫描线起点在缓存的位置

                      screen_ptr                     = dest_buffer + ( ystart * mem_pitch );

                      for ( yi = ystart; yi <= yend; yi++ )

                      {

                          //计算扫描线起点和终点的X坐标

                          xstart                    = ( ( xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT );

                          xend                  = ( ( xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT );

                          //计算扫描线起点和终点的坐标

                          ui                        = ul + FIXP16_ROUND_UP;

                          vi                        = vl + FIXP16_ROUND_UP;

                          wi                        = wl + FIXP16_ROUND_UP;

                          //计算扫描线上的RGB梯度

                          if ( ( dx = ( xend - xstart )) > 0 )

                          {

                               du                    = ( ur - ul ) / dx;

                               dv                    = ( vr - vl ) / dx;

                               dw                    = ( wr - wl ) / dx;

 

                          }

                          else

                          {

                               du                    = ( ur - ul );

                               dv                    = ( vr - vl );

                               dw                    = ( wr - wl );

 

                          }

                          //扫描线起点水平裁剪测试

                          if ( xstart < m_min_clip_x )

                          {

                               //计算起点移动距离

                               dx                    = m_min_clip_x - xstart;

                               //重新计算扫描线起点的RGB

                               ui                    += dx * du;

                               vi                    += dx * dv;

                               wi                    += dx * dw;

 

                               //重新设置循环起始条件

                               xstart                = m_min_clip_x;

                          }

 

                          //终点水平测试

                          if ( xend > m_max_clip_x )

                          {

                               xend              = m_max_clip_x;

                          }

 

                          //绘制扫描线

                          for( xi = xstart; xi <= xend; xi ++ )

                          {

                               //绘制像素,假设格式为.6.5

                               screen_ptr[xi]        = ( ( ui >> ( FIXP16_SHIFT + 3)) << 11 ) +

                                   ( ( vi >> ( FIXP16_SHIFT + 2)) << 5 ) +

                                   ( wi >> ( FIXP16_SHIFT + 3 ));

 

                               //计算下一个像素的RGB

                               ui                    += du;

                               vi                    += dv;

                               wi                    += dw;

                          }

 

                          //计算下一条扫描线起点和终点的x坐标和RGB值

                          xl                        += dxdyl;

                          ul                        += dudyl;

                          vl                        += dvdyl;

                          wl                        += dwdyl;

                          xr                        += dxdyr;

                          ur                        += dudyr;

                          vr                        += dvdyr;

                          wr                        += dwdyr;

 

                          //让指针screen_ptr指向视频缓存的下一行

                          screen_ptr                += mem_pitch;

 

                          if ( yi == yrestart )

                          {

                               if ( irestart == INTERP_LHS )

                               {

                                   dyl               = ( y2 - y1 );

 

                                   dxdyl             = ( ( x2 - x1 ) << FIXP16_SHIFT ) / dyl;

                                   dudyl             = ( ( tu2 - tu1 ) << FIXP16_SHIFT ) / dyl;

                                   dvdyl             = ( ( tv2 - tv1 ) << FIXP16_SHIFT ) / dyl;

                                   dwdyl             = ( ( tw2 - tw1 ) << FIXP16_SHIFT ) / dyl;

 

                                   xl                = ( xl << FIXP16_SHIFT );

                                   ul                = ( tu1 << FIXP16_SHIFT );

                                   vl                = ( tv1 << FIXP16_SHIFT );

                                   wl                = ( tw1 << FIXP16_SHIFT );

 

                                   xl                += dxdyl;

                                   ul                += dudyl;

                                   vl                += dvdyl;

                                   wl                += dwdyl;

 

 

                               }

                               else

                               {

                                   dyr               = ( y1 - y2 );

 

                                   dxdyr             = ( ( x1 - x2 ) << FIXP16_SHIFT ) / dyr;

                                   dudyr             = ( ( tu1 - tu2 ) << FIXP16_SHIFT ) / dyr;

                                   dvdyr             = ( ( tv1 - tv2 ) << FIXP16_SHIFT ) / dyr;

                                   dwdyr             = ( ( tw1 - tw2 ) << FIXP16_SHIFT ) / dyr;

 

                                   xr                = ( x2 << FIXP16_SHIFT );

                                   ur                = ( tu2 << FIXP16_SHIFT );

                                   vr                = ( tv2 << FIXP16_SHIFT );

                                   wr                = ( tw2 << FIXP16_SHIFT );

 

                                   xr                += dxdyr;

                                   ur                += dudyr;

                                   vr                += dvdyr;

                                   wr                += dwdyr;

 

 

                               }

                          }

 

                      }

 

                  }

                  else

                  {

                      //裁剪版本

                      //让指screen_ptr指向第一条扫描线起点在缓存的位置

                      screen_ptr                     = dest_buffer + ( ystart * mem_pitch );

                      for ( yi = ystart; yi <= yend; yi++ )

                      {

                          //计算扫描线起点和终点的X坐标

                          xstart                    = ( ( xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT );

                          xend                  = ( ( xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT );

                          //计算扫描线起点和终点的坐标

                          ui                        = ul + FIXP16_ROUND_UP;

                          vi                        = vl + FIXP16_ROUND_UP;

                          wi                        = wl + FIXP16_ROUND_UP;

                          //计算扫描线上的RGB梯度

                          if ( ( dx = ( xend - xstart )) > 0 )

                          {

                               du                    = ( ur - ul ) / dx;

                               dv                    = ( vr - vl ) / dx;

                               dw                    = ( wr - wl ) / dx;

 

                          }

                          else

                          {

                               du                    = ( ur - ul );

                               dv                    = ( vr - vl );

                               dw                    = ( wr - wl );

 

                          }

   

 

                          //绘制扫描线

                          for( xi = xstart; xi <= xend; xi ++ )

                          {

                               //绘制像素,假设格式为.6.5

                               screen_ptr[xi]        = ( ( ui >> ( FIXP16_SHIFT + 3)) << 11 ) +

                                   ( ( vi >> ( FIXP16_SHIFT + 2)) << 5 ) +

                                    ( wi >> ( FIXP16_SHIFT + 3 ));

 

                               //计算下一个像素的RGB

                               ui                    += du;

                               vi                    += dv;

                               wi                    += dw;

                          }

 

                          //计算下一条扫描线起点和终点的x坐标和RGB值

                          xl                        += dxdyl;

                          ul                        += dudyl;

                          vl                        += dvdyl;

                          wl                        += dwdyl;

                          xr                        += dxdyr;

                          ur                        += dudyr;

                          vr                        += dvdyr;

                          wr                        += dwdyr;

 

                          //让指针screen_ptr指向视频缓存的下一行

                          screen_ptr                += mem_pitch;

 

                          if ( yi == yrestart )

                          {

                               if ( irestart == INTERP_LHS )

                               {

                                   dyl               = ( y2 - y1 );

 

                                   dxdyl             = ( ( x2 - x1 ) << FIXP16_SHIFT ) / dyl;

                                   dudyl             = ( ( tu2 - tu1 ) << FIXP16_SHIFT ) / dyl;

                                   dvdyl             = ( ( tv2 - tv1 ) << FIXP16_SHIFT ) / dyl;

                                   dwdyl             = ( ( tw2 - tw1 ) << FIXP16_SHIFT ) / dyl;

 

                                   xl                = ( xl << FIXP16_SHIFT );

                                   ul                = ( tu1 << FIXP16_SHIFT );

                                   vl                = ( tv1 << FIXP16_SHIFT );

                                   wl                = ( tw1 << FIXP16_SHIFT );

 

                                   xl                += dxdyl;

                                   ul                += dudyl;

                                   vl                += dvdyl;

                                   wl                += dwdyl;

 

 

                               }

                               else

                               {

                                   dyr               = ( y1 - y2 );

 

                                   dxdyr             = ( ( x1 - x2 ) << FIXP16_SHIFT ) / dyr;

                                   dudyr             = ( ( tu1 - tu2 ) << FIXP16_SHIFT ) / dyr;

                                   dvdyr             = ( ( tv1 - tv2 ) << FIXP16_SHIFT ) / dyr;

                                   dwdyr             = ( ( tw1 - tw2 ) << FIXP16_SHIFT ) / dyr;

 

                                   xr                = ( x2 << FIXP16_SHIFT );

                                   ur                = ( tu2 << FIXP16_SHIFT );

                                   vr                = ( tv2 << FIXP16_SHIFT );

                                   wr                = ( tw2 << FIXP16_SHIFT );

 

                                   xr                += dxdyr;

                                   ur                += dudyr;

                                   vr                += dvdyr;

                                   wr                += dwdyr;

 

 

                               }

                          }

 

                      }

                  }

         }

        

}

 

 

 

 

下面进行DEMO,绘制GOURAUD SHADER三角形

相比而言,调用的代码就简单多了,

在Game_Init()初始化中

 

 

    ddraw->DDraw_Init( main_window_handle, SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, WINDOWED_APP );

srand( mytool.Start_Clock() );

ddraw->DDraw_Fill_Surface( ddraw->getbackSurface(), 0 );

 

在每帧循环中GAME_MAIN()

 

int Game_Main(void *parms = NULL, int num_parms = 0)

{

    // check of user is trying to exit

    if (KEYDOWN(VK_ESCAPE) )

         PostMessage(main_window_handle, WM_DESTROY,0,0);

    srand( mytool.Start_Clock() );

    ddraw->DDraw_Fill_Surface( ddraw->getbackSurface(), 0 );

 

    ddraw->DDraw_Lock_Back_Surface();

 

    POLYF4DV2         face;

    face.tvlist[0].x                   = ( int ) RAND_RANGE( 0, SCREEN_WIDTH - 1 );

    face.tvlist[0].y                   = ( int ) RAND_RANGE( 0, SCREEN_HEIGHT - 1 );

    face.lit_color[0]                  = _RGB16BIT565( RAND_RANGE( 0, 255 ), RAND_RANGE( 0, 255), RAND_RANGE( 0, 255 ));

    face.tvlist[1].x                   = ( int ) RAND_RANGE( 0, SCREEN_WIDTH - 1 );

    face.tvlist[1].y                   = ( int ) RAND_RANGE( 0, SCREEN_HEIGHT - 1 );

    face.lit_color[1]                  = _RGB16BIT565( RAND_RANGE( 0, 255 ), RAND_RANGE( 0, 255), RAND_RANGE( 0, 255 ));

    face.tvlist[2].x                   = ( int ) RAND_RANGE( 0, SCREEN_WIDTH - 1 );

    face.tvlist[2].y                   = ( int ) RAND_RANGE( 0, SCREEN_HEIGHT - 1 );

    face.lit_color[2]                  = _RGB16BIT565( RAND_RANGE( 0, 255 ), RAND_RANGE( 0, 255), RAND_RANGE( 0, 255 ));

    math->Draw_Gouraud_Triangle16( & face, ddraw->getbackbuffer(), ddraw->getbacklpitch());

 

    ddraw->DDraw_Unlock_Back_Surface();

 

    ddraw->DDraw_Flip();

    mytool.Wait_Clock( 30 );

 

    return(1);

 

} // end Game_Main

结果如下,OK了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值