2014年3月9日星期日(DEMO8-6,画家算法)

概括说,就是先绘制离视点远的物体,再绘制离视点近的物体,这样离视点较近的物体将自动覆盖背景。

可以根据渲染列表中的每个多边形的Z值,从后到前的顺序排列

对于多边形较小,且不是凹的,不互相重叠,是可行的。

排序是根据相机坐标进行,所以要在世界坐标系到相机坐标变换之后和相机坐标到透视坐标之前进行。

 

定义几个常量用来排序渲染列表中的多边形

 

#define SORT_POLYLIST_AVGZ                  0

#define SORT_POLYLIST_NEARZ                     1

#define                           SORT_POLYLIST_FARZ                  2

比较函数随之分三个,比较NEARZ,AVGZ和FARZ,用来当判断标准。

 

int ddraw_liushuixian::Compare_AvgZ_PolyF4DV1( const void * arg1, const void * arg2 )

{

    float                 z1, z2;

    POLYF4DV1_PTR         poly_1, poly_2;

 

    poly_1                                      = * ( ( POLYF4DV1_PTR * ) ( arg1 ));

    poly_2                                      = * ( ( POLYF4DV1_PTR * ) ( arg2 ));

 

    z1                                          = ( float ) 0.33333 * ( poly_1->tvlist[0].z + poly_1->tvlist[1].z + poly_1->tvlist[2].z );

    z2                                          = ( float ) 0.33333 * ( poly_2->tvlist[0].z + poly_2->tvlist[1].z + poly_2->tvlist[2].z );

 

    if ( z1 > z2 )

    {

         return -1;

    }

    else

    if ( z1 < z2)

    {

         return 1;

    }

    else

    {

         return 0;

    }

 

   

}

 

int ddraw_liushuixian::Compare_NearZ_PolyF4DV1( const void * arg1, const void * arg2 )

{

    float                 z1, z2;

    POLYF4DV1_PTR         poly_1, poly_2;

 

    poly_1                                      = * ( ( POLYF4DV1_PTR * ) ( arg1 ));

    poly_2                                      = * ( ( POLYF4DV1_PTR * ) ( arg2 ));

 

    z1                                          = MIN( poly_1->tvlist[0].z, poly_1->tvlist[1].z );

    z1                                          = MIN( z1, poly_1->tvlist[2].z );

    z2                                          = MIN( poly_2->tvlist[0].z, poly_2->tvlist[1].z );

    z2                                          = MIN( z2, poly_2->tvlist[2].z );

 

    if ( z1 > z2 )

    {

        return -1;

    }

    else

         if ( z1 < z2)

         {

             return 1;

         }

         else

         {

             return 0;

         }

 

 

}

 

int ddraw_liushuixian::Compare_FarZ_PolyF4DV1( const void * arg1, const void * arg2 )

{

    float                 z1, z2;

    POLYF4DV1_PTR         poly_1, poly_2;

 

    poly_1                                      = * ( ( POLYF4DV1_PTR * ) ( arg1 ));

    poly_2                                      = * ( ( POLYF4DV1_PTR * ) ( arg2 ));

 

    z1                                          = MAX( poly_1->tvlist[0].z, poly_1->tvlist[1].z );

    z1                                          = MAX( z1, poly_1->tvlist[2].z );

    z2                                          = MAX( poly_2->tvlist[0].z, poly_2->tvlist[1].z );

    z2                                          = MAX( z2, poly_2->tvlist[2].z );

 

    if ( z1 > z2 )

    {

         return -1;

    }

    else

         if ( z1 < z2)

         {

             return 1;

         }

         else

         {

             return 0;

         }

 

 

}

 

按照各种情况进行排序

int ddraw_liushuixian::Sort_RENDERLIST4DV1( RENDERLIST4DV1_PTR rend_list, int sort_method )

{

    switch( sort_method )

    {

    case SORT_POLYLIST_AVGZ:

         {

            qsort( ( void *) rend_list->poly_ptrs, rend_list->num_polys, sizeof( POLYF4DV1_PTR ), Compare_AvgZ_PolyF4DV1 );

         }

         break;

    case SORT_POLYLIST_NEARZ:

         {

            qsort( ( void *) rend_list->poly_ptrs, rend_list->num_polys, sizeof( POLYF4DV1_PTR ), Compare_NearZ_PolyF4DV1);

         }

         break;

    case SORT_POLYLIST_FARZ:

         {

            qsort( ( void *) rend_list->poly_ptrs, rend_list->num_polys, sizeof( POLYF4DV1_PTR ), Compare_FarZ_PolyF4DV1 );

         }

         break;

 

    default:

         break;

    }

}

 

下面,进行主程序看看,

在GAME_MAIN()的每帧中,设定一个Z排序模式,

static int zsort_mode     = 1;

 

    liushuixian.Insert_OBJECT4DV1_RENDERLIST4DV12( * math, & render_list, & obj_player, 0, 0 );

                  liushuixian.Insert_OBJECT4DV1_RENDERLIST4DV12( * math, & render_list, & obj_tank, 0, 0 );

             liushuixian.Insert_OBJECT4DV1_RENDERLIST4DV12( * math, & render_list, & obj_tower,0,0 );

 

 

光照是在渲染列表中进行,

 

int ddraw_liushuixian::Light_RENDERLIST4DV1_World16( ddraw_math math, int rgb_format, RENDERLIST4DV1_PTR rend_list, CAM4DV1_PTR cam, LIGHTV1_PTR lights, int max_lights )

{

    unsigned     int               r_base, g_base, b_base,            //原来的颜色值

                                       r_sum, g_sum, b_sum,           //全部光源的总体光照效果

                                       shaded_color;                      //最后的颜色

    float                              dp,                                //点积

                                       dist,                              //表面和光源之间的距离

                                        i,                                 //强度

                                       nl,                                //法线长度

                                       atten;                             //衰减计算结果

 

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

    {

         POLYF4DV1_PTR                  curr_poly             = rend_list->poly_ptrs[poly];

 

   

         if ( ! ( curr_poly->state & OBJECT4DV1_STATE_ACTIVE ) ||

             ( curr_poly-> state & OBJECT4DV1_STATE_CULLED ) ||

             ! ( curr_poly->state & OBJECT4DV1_STATE_VISIBLE))

             {

                  return ( 0 );

             }

        

         //检查多边形的着色模式

         if ( curr_poly->attr & POLY4DV1_ATTR_SHADE_MODE_FLAT ||

             curr_poly->attr & POLY4DV1_ATTR_SHADE_MODE_GOURAUD )

         {

             //提取多边形颜色的RGB

             if ( rgb_format == DD_PIXEL_FORMAT565 )

             {

                  _RGB565FROM16BIT( curr_poly->color, & r_base, & g_base, & b_base );

                  //转换成.8.8格式

                  r_base                                 <<= 3;

                  g_base                                 <<= 2;

                  b_base                                 <<= 3;

             }

             else

             {

                  _RGB555FROM16BIT( curr_poly->color, & r_base, & g_base, & b_base );

                  //转换成.8.8格式

                  r_base                                 <<= 3;

                  g_base                                 <<= 3;

                  b_base                                 <<= 3;

             }

 

             //初始化总体光照颜色

             r_sum                                       = 0;

             g_sum                                       = 0;

             b_sum                                       = 0;

 

             //遍历光照

             for ( int curr_light = 0; curr_light < max_lights; curr_light ++)

             {

                  //光源是否被打开

                  if ( lights[curr_light].state== LIGHTV1_STATE_OFF)

                  {

                      continue;

                  }

 

                  //判断光源类型

                  if ( lights[curr_light].attr & LIGHTV1_ATTR_AMBIENT )

                  {

                      r_sum                              += ( ( lights[curr_light].c_ambient.r * r_base) / 256 );

                      g_sum                              += ( ( lights[curr_light].c_ambient.g * g_base) / 256 );

                      b_sum                              += ( ( lights[curr_light].c_ambient.b * b_base) / 256 );

 

                  }

                  else

                      if ( lights[curr_light].attr & LIGHTV1_ATTR_INFINITE )

                      {

                          VECTOR4D u, v, n;

                          math.VECTOR4D_Build( & curr_poly->tvlist[0], & curr_poly->tvlist[1], & u );

                          math.VECTOR4D_Build( & curr_poly->tvlist[0], & curr_poly->tvlist[1], & v );

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

 

                          nl                                 = math.VECTOR4D_length(&n);

 

                          dp                                 = math.VECTOR4D_DOT( &n, & lights[curr_light].dir );

 

                          if ( dp > 0 )

                          {

                               i                              = 128 * dp / nl;

                               r_sum                          += (  lights[curr_light].c_diffuse.r * r_base * i ) / ( 256 * 128);

                               g_sum                          += (  lights[curr_light].c_diffuse.g * g_base * i ) / ( 256 * 128);

                               b_sum                          += (  lights[curr_light].c_diffuse.b * b_base * i ) / ( 256 * 128);

 

                          }

 

 

                      }

                      else

                          if ( lights[curr_light].attr & LIGHTV1_ATTR_POINT )

                          {

                               VECTOR4D u, v, n, l;

                               math.VECTOR4D_Build( & curr_poly->tvlist[0], & curr_poly->tvlist[1], & u );

                               math.VECTOR4D_Build( & curr_poly->tvlist[0], & curr_poly->tvlist[1], & v );

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

 

                               nl                                 = math.VECTOR4D_length(&n);

 

                               //计算从表面到光源的向量

                               math.VECTOR4D_Build( &curr_poly->tvlist[0], & lights[curr_light].pos, &l );

                               //计算距离和衰减

                               dist                           = math.VECTOR4D_length( &l);

 

 

                               dp                                 = math.VECTOR4D_DOT( &n, & l);

 

                               if ( dp > 0 )

                               {

                                   atten                          = ( lights[curr_light].kc + lights[curr_light].kl * dist + lights[curr_light].kq * dist * dist );

                                   i                              = 128 * dp / ( nl * dist * atten );

                                   r_sum                          += (  lights[curr_light].c_diffuse.r * r_base * i ) / ( 256 * 128);

                                   g_sum                          += (  lights[curr_light].c_diffuse.g * g_base * i ) / ( 256 * 128);

                                   b_sum                          += (  lights[curr_light].c_diffuse.b * b_base * i ) / ( 256 * 128);

 

                               }

 

 

                          }

                          else

                               if ( lights[curr_light].attr & LIGHTV1_ATTR_SPOTLIGHT1 )

                              {

                                   VECTOR4D u, v, n, l;

                                   math.VECTOR4D_Build( & curr_poly->tvlist[0], & curr_poly->tvlist[1], & u );

                                   math.VECTOR4D_Build( & curr_poly->tvlist[0], & curr_poly->tvlist[1], & v );

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

                                   nl                                 = math.VECTOR4D_length(&n);

 

                                   //计算从表面到光源的向量

                                   math.VECTOR4D_Build( &curr_poly->tvlist[0], & lights[curr_light].pos, &l );

                                   //计算距离和衰减

                                   dist                           = math.VECTOR4D_length( &l);

 

 

                                   dp                                 = math.VECTOR4D_DOT( &n, & lights[curr_light].dir );

 

                                   if ( dp > 0 )

                                   {

                                       atten                          = ( lights[curr_light].kc + lights[curr_light].kl * dist + lights[curr_light].kq * dist * dist );

                                       i                              = 128 * dp / ( nl * atten );

                                       r_sum                          += (  lights[curr_light].c_diffuse.r * r_base * i ) / ( 256 * 128);

                                       g_sum                          += (  lights[curr_light].c_diffuse.g * g_base * i ) / ( 256 * 128);

                                       b_sum                          += (  lights[curr_light].c_diffuse.b * b_base * i ) / ( 256 * 128);

 

                                   }

 

 

                               }  

                               else

                                   if ( lights[curr_light].attr & LIGHTV1_ATTR_SPOTLIGHT2 )

                                   {

                                       VECTOR4D u, v, n, d, s;

                                       math.VECTOR4D_Build( & curr_poly->tvlist[0], & curr_poly->tvlist[1], & u );

                                       math.VECTOR4D_Build( & curr_poly->tvlist[0], & curr_poly->tvlist[1], & v );

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

 

                                       nl                                 = math.VECTOR4D_length(&n);

                                       dp                                 = math.VECTOR4D_DOT( &n, & lights[curr_light].dir );

 

                                       if ( dp > 0 )

                                       {

                                            //计算从表面到光源的向量

                                            math.VECTOR4D_Build( & lights[curr_light].pos, &  curr_poly->tvlist[0],  &s );

                                            dist                      = math.VECTOR4D_length( &s);

 

                                            float    dpsl              = math.VECTOR4D_DOT( & s, & lights[curr_light].dir ) / dist;

 

                                            if ( dpsl > 0)

                                            {

                                                atten                     = ( lights[curr_light].kc + lights[curr_light].kl * dist + lights[curr_light].kq * dist * dist );

                                                float    dpsl_exp     = dpsl;

                                                for ( int e_index = 1; e_index < ( int ) lights[curr_light].pf; e_index++ )

                                                {

                                                     dpsl              *= dpsl;

                                                }

                                                i                         = 128 * dp * dpsl_exp / ( nl * atten );

                                                r_sum                     += (  lights[curr_light].c_diffuse.r * r_base * i ) / ( 256 * 128);

                                                g_sum                     += (  lights[curr_light].c_diffuse.g * g_base * i ) / ( 256 * 128);

                                                b_sum                      += (  lights[curr_light].c_diffuse.b * b_base * i ) / ( 256 * 128);

                                            }

 

 

                                       }

 

 

                                   }  

             }

             //确保颜色分量不溢出

             if ( r_sum   > 255 )

             {

                  r_sum                                                = 255;

 

             }

             if ( g_sum   > 255 )

             {

                  g_sum                                                = 255;

 

             }

             if ( b_sum   > 255 )

             {

                  b_sum                                                = 255;

 

             }

 

             //写入颜色

             if ( rgb_format == DD_PIXEL_FORMAT565 )

             {

 

                  shaded_color                                    = _RGB16BIT565( r_sum, g_sum, b_sum );

             }

             else

                  if ( rgb_format == DD_PIXEL_FORMAT555 )

                  {

                      shaded_color                                    = _RGB16BIT555( r_sum, g_sum, b_sum );

                  }

                  curr_poly->color                                     = ( int ) ( ( shaded_color << 16 ) | curr_poly->color );

         }

         else

         {

    //       curr_poly->color                                     = ( int ) ( ( curr_poly->color << 16 ) | curr_poly->color );

 

         }

 

    }

}

 

在GAME_Main()中光照处理列表

    liushuixian.Light_RENDERLIST4DV1_World16( *math, DD_PIXEL_FORMAT565, &render_list, & cam, lightGroup, 4 );

然后进行Z排序,OK了。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值