本来应该进行9-4和那个RAISER3D的游戏,不过由于要进行的是软引擎,故先避免之 。直接开第十章,
本节的主要内容是3D裁剪,
裁剪就是尽可能少地将图元传给3D流水线的下一个阶段。
首先,介绍了物体空间裁剪。定义是:根据特定的裁剪区域对基本图元组成的几何体进行裁剪,是根据对象的数学表示进行的,然后把裁剪后的多边形(这里是三角形)传给下一个阶段。问题是有可能生成新的多边形,需要重构成新的三角形。
以前都是空间的2D裁剪,就是说将直线或者三角形投影到视平面上进后,根据矩形视平面对其进行裁剪。
在物理空间的3D裁剪,问题是多边形可能穿过近裁剪面或者Z=0平面。于是,采取如下方法:
1, 对所有物体进行提出操作
2, 执行背面消除
3, 根据视景体对所有多边形裁剪,只对近裁剪面对多边形进行完整的裁剪,并将裁剪后的多边形重新分割为三角形,其他裁剪面值执行剔除操作,
4, 将余下的多边形传递到3D流水线的下一个阶段,在光栅化阶段对超出视平面和屏幕空间边界的三角形进行2D裁剪。
接下来介绍了图像空间裁剪。也就是屏幕(或者视平面的2D裁剪),这样第一比较麻烦,第二会丢失Z缓存。
因此,用物理空间裁剪的方法。
下面介绍裁剪。点测试是基础,边测试只要判断两个端点即可。
1,2D点测试
点在矩形内:( xmin <= x <= xmax )且( ymin<= y <= ymax )
2,3D点测试:
(1) 裁剪区域长方体
(xmin<=x<=xmax )且(ymin<= y <=ymax)且(zmin<=z<=zmax)
(2) 视景体为棱锥台。对于平面ptop、pbotton、pright、pleft、pfar、pNear,需判断点是否在裁剪面内侧(即正半空间),即各个法线指向的一侧。+1表示正半空间,-1表示负半空间,0表示位于平面上,
判断方法是把点的坐标代入平面方程中。
方法如下:
对于平面方程a(x-x0)+b(y-y0)+c(z-z0) = 0,其中法线向量为<a,b,c>,(x0,y0,z0)为平面上的一个点。则对于
Hs=a*(x-x0)+b*(y-y0)+c*(z-z0),只需将点(x,y,z)代入。
若Hs=0,则该点位于平面上;
若Hs>0,则该点位于平面的正半空间中;
若Hs<0,则该点位于平面的负半空间中。
1, 线段裁剪分2D裁剪(用无限长直线裁剪线段)和3D裁剪(用平面裁剪线段)。多边形裁剪可简化为线段裁剪。
(1)2D线段裁剪只考虑X=XL和Y=YL两种情形,即,水平直线或垂直直线对三角形进行裁剪。
对于线段P=P0 + ( P1 – P0 ) * t,即
x=x0 + ( x1 – x0 ) * t
y = y0 + ( y1-y0 ) * t,
分别 代入X坐标(或者Y坐标),若(0<=t<=1 ),则相交,否则不相交。
当然,前提是端点P0和P1不重合,且两条直线不能平行。
(2)3D空间中的线段裁剪
对于点法式平面方程:
Nx * ( x – x0 ) + ny * ( y – y0 ) + nz * ( z – z0 ) = 0
其中,法线为(nx,ny,nz),平面上的点为(x0,y0,z0),
直线方程p1->p2:
P = p1 + ( p2 – p1 ) * t ( 0<=t<=1),
X=x1 + ( x2 –x1 ) * t;
Y=y1+(y2-y1) * t;
Z=z1+(z2-z1) * t;
则可以得到t的值,并以此计算出交点。
下面的几种裁剪算法:
1,Cohen-Sutherland裁剪算法
此算法主要用来排除完全在区域外和区域内。通过编码的方式,省却了很多if,else语句。
编码方式为b3b2b1b0,。为TRUE时的含义如下,
B3: y>ymax,位于上边缘上方
B2:y<ymin,位于下边缘下方
B1:x>xmax,位于右边缘右方
B0,x<xmin,.位于左边缘左方。
若未通过测试,则代表线段与裁剪区域边界有1个或2个交点,需要进行裁剪。可以采用的方法之一,就是使用线段穿过的裁剪区域边界对线段进行裁剪,浙江增加1条或2条线段,然后对这些线段应用该算法。
1, Cyrus-Back/梁友栋-Barksy裁剪算法
与第一个算法类似,不过使用的参数方程来代替X,Y变量。由于不实现该算法,故省略之。
2, Weiler-Anthon裁剪算法
由于是为了实现,而不是学术研究,故只介绍简化后的算法。
这个算法出发点:认为多边形是由顶点构成的。这里只考虑三角形。
按照一定顺序遍历各顶点,顶点或者在裁剪区域内,或者在裁剪区域外,如果第一个顶点在裁剪区域内,则输出它;否则,则遍历到下一个顶点,若三角形边的起点和终点状态不同(一个在裁剪区域内,一个在裁剪区域外),则计算这条边与边界的交点,并输出它。若起点在裁剪区域内,则计算在进入和离开裁剪区域的两个交点。
总之,裁剪只要找出多边形与裁剪边界交点即可。
这里,使用多边形级别的裁剪。,在相机变换后进行裁剪/剔除;剔除完全在视景体外的多边形,同时只对穿过近裁剪面的多边形进行裁剪。,对于上、下、左、右裁剪面的多边形,则不去管,因为光栅化函数将在图像空间对其进行裁剪。
理论比比叨叨地讲了半天,下面终于进行编程了。裁剪由于属于流水线部分,故写在DDRAW_LIUSHUIXIAN_TEXTURE类里。或许应该建立个子类。
(1)
先看左右裁剪面方程为,
Tan(theta/2) = |x| / z,即
|x| = tan(theta/2) * z
若 |x| = tan( theta/2 )* z.则顶点在裁剪面上
若 |x| < tan( theta/2) * z.则顶点在裁剪面内侧
若 |x| > tan( theta/2) * z.则顶点在裁剪面外侧。
同样,上下平面,以y代替x,同样适用。
(2) 远近裁剪面:对于三角形面三个顶点vi(xi,yi,zi)(i=0,1,2)
完全在远裁剪面之外(v0.z>far_clip_z且v1.z>far_clip_z且v2.z>far_clip_z)
完全在近裁剪面之外(v0.z<near_clip_z且v1.z<near_clip_z且v2.z<far_clip_z)
穿过远裁剪面:不考虑
穿过近裁剪面
1) 一个顶点在视景体内,2个顶点在视景体外
对2条与近裁剪面相交的边进行裁剪,用新顶点覆盖原来的顶点即可。必要时重新计算纹理坐标和法线。
2) 两个顶点在视景体内,1个顶点在视景体内
裁剪后,将会成为一个四边形,必须分割为2个三角形,其中,两个顶点不变的三角形代替以前的三角形。1个顶点不变的三角形插入到渲染列表尾部。
(3) 计算纹理坐标
用插值的方式。
接下来就是裁剪函数的代码了,书上还是注释的比较详细的。
int DDRAW_LIUSHUIXIAN_TEXTURE::Insert_POLYF4DV2_RENDERLIST4DV2(RENDERLIST4DV2_PTR rend_list,POLYF4DV2_PTR poly,ddraw_math math)
{
if(rend_list->num_polys>= RENDERLIST4DV2_MAX_POLYS )
return( 0 );
memcpy(( void * ) & rend_list->poly_data[rend_list->num_polys], ( void* ) poly, sizeof(POLYF4DV2 ) );
if(rend_list->num_polys== 0 )
{
rend_list->poly_data[0].next = NULL;
rend_list->poly_data[0].prev = NULL;
}
else
{
rend_list->poly_data[rend_list->num_polys].next = NULL;
rend_list->poly_data[rend_list->num_polys].prev = & rend_list->poly_data[rend_list->num_polys-1];
rend_list->poly_data[rend_list->num_polys-1].next = & rend_list->poly_data[rend_list->num_polys];
}
rend_list->num_polys++;
return( 1 );
}
裁剪代码如下:
void DDRAW_LIUSHUIXIAN_TEXTURE::Clip_Polys_RENDERLIST4DV2( ddraw_math * math2, RENDERLIST4DV2_PTR rend_list,CAM4DV1_PTR cam,int clip_flags)
{
//内部裁剪码
#define CLIP_CODE_GZ 0x0001 //z> z_max
#define CLIP_CODE_LZ 0x0002 //z< z_min
#define CLIP_CODE_IZ 0x0004 // z_min < z < z_max
#define CLIP_CODE_GX 0x0001 //x> x_max
#define CLIP_CODE_LX 0x0002 //x< x_min
#define CLIP_CODE_IX 0x0004 // x_min < x < x_max
#define CLIP_CODE_GY 0x0001 //y> y_max
#define CLIP_CODE_LY 0x0002 //y< y_min
#define CLIP_CODE_IY 0x0004 // y_min < y < y_max
#define CLIP_CODE_NULL 0x0000
int vertex_ccodes[3]; //用于存储裁剪标记
int num_verts_in; //位于视景体内部的顶点数
int v0, v1, v2; //顶点索引
float z_factor, //用于裁剪计算
z_test; //用于裁剪计算
float xi, yi, x01i, y01i, x02i, y02i, //交点坐标
t1, t2, //参数化t值
ui, vi, u01i, v01i, u02i, v02i; //交点纹理坐标
int last_poly_index, //渲染列表中最后一个有效的多边形
insert_poly_index; //新多边形的插入位置
VECTOR4D u, v, n; //用于向量计算
POLYF4DV2 temp_poly; //将多边形分割成个时,用于存储新增的多边形
//设置last_poly_index和insert_poly_index,使其对英语渲染列表末尾,以免分割多边形次
insert_poly_index = last_poly_index =rend_list->num_polys;
//遍历渲染列表,对其中的多边形进行裁剪/剔除
for(int poly =0; poly < last_poly_index;poly++ )
{
//获得当前多边形
POLYF4DV2_PTR curr_poly = rend_list->poly_ptrs[poly];
//该多边形有效么?仅当多边形处于活动状态、为被
if( curr_poly == NULL||
! ( curr_poly->state& POLY4DV2_STATE_ACTIVE) ||
( curr_poly->state& POLY4DV2_STATE_CLIPPED) ||
( curr_poly->state& POLY4DV2_STATE_BACKFACE ))
{
continue;
}
//根据左右裁剪面进行剔除
if(clip_flags & CLIP_POLY_X_PLANE)
{
z_factor= ( 0.5 ) * cam->viewplane_width/ cam->view_dist;
//顶点
z_test = z_factor * curr_poly->tvlist[0].z;
if(curr_poly->tvlist[0].x > z_test )
vertex_ccodes[0] =CLIP_CODE_GX;
elseif( curr_poly->tvlist[0].x< - z_test )
vertex_ccodes[0] =CLIP_CODE_LX;
else
vertex_ccodes[0] =CLIP_CODE_IX;
//顶点
z_test = z_factor * curr_poly->tvlist[1].z;
if(curr_poly->tvlist[1].x > z_test )
vertex_ccodes[1] =CLIP_CODE_GX;
elseif( curr_poly->tvlist[1].x< - z_test )
vertex_ccodes[1] =CLIP_CODE_LX;
else
vertex_ccodes[1] =CLIP_CODE_IX;
//顶点
z_test = z_factor * curr_poly->tvlist[2].z;
if(curr_poly->tvlist[2].x > z_test )
vertex_ccodes[2] =CLIP_CODE_GX;
elseif( curr_poly->tvlist[1].x< - z_test )
vertex_ccodes[2] =CLIP_CODE_LX;
else
vertex_ccodes[2] =CLIP_CODE_IX;
//进行简单拒绝测试,即多边形是否完全在左裁剪面或者右裁剪面外侧
if(( ( vertex_ccodes[0] == CLIP_CODE_GX ) &&
( vertex_ccodes[1] == CLIP_CODE_GX) &&
( vertex_ccodes[2] == CLIP_CODE_GX) ) ||
( ( vertex_ccodes[0] == CLIP_CODE_LX) &&
( vertex_ccodes[1] == CLIP_CODE_LX) &&
( vertex_ccodes[2] == CLIP_CODE_LX) ) )
{
//将完全在裁剪面外侧的多边形裁剪掉
SET_BIT( curr_poly->state, POLY4DV2_STATE_CLIPPED);
//进入下一个多边形
continue;
}
}
//根据上下裁剪面进行剔除
if(clip_flags & CLIP_POLY_X_PLANE)
{
z_factor= ( 0.5 ) * cam->viewplane_width/ cam->view_dist;
//顶点
z_test = z_factor * curr_poly->tvlist[0].z;
if(curr_poly->tvlist[0].y > z_test )
vertex_ccodes[0] =CLIP_CODE_GY;
elseif( curr_poly->tvlist[0].y< - z_test )
vertex_ccodes[0] =CLIP_CODE_LY;
else
vertex_ccodes[0] =CLIP_CODE_IY;
//顶点
z_test = z_factor * curr_poly->tvlist[1].z;
if(curr_poly->tvlist[1].y > z_test )
vertex_ccodes[1] =CLIP_CODE_GY;
elseif( curr_poly->tvlist[1].y< - z_test )
vertex_ccodes[1] =CLIP_CODE_LY;
else
vertex_ccodes[1] =CLIP_CODE_IY;
//顶点
z_test = z_factor * curr_poly->tvlist[2].z;
if(curr_poly->tvlist[2].y > z_test )
vertex_ccodes[2] =CLIP_CODE_GY;
elseif( curr_poly->tvlist[1].y< - z_test )
vertex_ccodes[2] =CLIP_CODE_LY;
else
vertex_ccodes[2] =CLIP_CODE_IY;
//进行简单拒绝测试,即多边形是否完全在左裁剪面或者右裁剪面外侧
if(( ( vertex_ccodes[0] == CLIP_CODE_GY ) &&
( vertex_ccodes[1] == CLIP_CODE_GY) &&
( vertex_ccodes[2] == CLIP_CODE_GY) ) ||
( ( vertex_ccodes[0] == CLIP_CODE_LY) &&
( vertex_ccodes[1] == CLIP_CODE_LY) &&
( vertex_ccodes[2] == CLIP_CODE_LY) ) )
{
//将完全在裁剪面外侧的多边形裁剪掉
SET_BIT( curr_poly->state, POLY4DV2_STATE_CLIPPED);
//进入下一个多边形
continue;
}
}
//根据远/近裁剪面进行裁剪/剔除
if(clip_flags & CLIP_POLY_Z_PLANE)
{
//重置内部顶点计数器,该变量用于对最终的三角形分类
num_verts_in = 0;
//顶点
if(curr_poly->tvlist[0].z > cam->far_clip_z )
{
vertex_ccodes[0] =CLIP_CODE_GZ;
}
elseif( curr_poly->tvlist[0].z< cam->near_clip_z)
{
vertex_ccodes[0] =CLIP_CODE_LZ;
}
else
{
vertex_ccodes[0] =CLIP_CODE_IZ;
num_verts_in ++;
}
//顶点
if(curr_poly->tvlist[1].z > cam->far_clip_z )
{
vertex_ccodes[1] =CLIP_CODE_GZ;
}
elseif( curr_poly->tvlist[1].z< cam->near_clip_z)
{
vertex_ccodes[1] =CLIP_CODE_LZ;
}
else
{
vertex_ccodes[1] =CLIP_CODE_IZ;
num_verts_in ++;
}
//顶点
if(curr_poly->tvlist[2].z > cam->far_clip_z )
{
vertex_ccodes[2] =CLIP_CODE_GZ;
}
elseif( curr_poly->tvlist[2].z< cam->near_clip_z)
{
vertex_ccodes[2] =CLIP_CODE_LZ;
}
else
{
vertex_ccodes[2] =CLIP_CODE_IZ;
num_verts_in ++;
}
//进行简单拒绝测试,即多边形是否完全在左裁剪面或者右裁剪面外侧
if(( ( vertex_ccodes[0] == CLIP_CODE_GZ ) &&
( vertex_ccodes[1] == CLIP_CODE_GZ) &&
( vertex_ccodes[2] == CLIP_CODE_GZ) ) ||
( ( vertex_ccodes[0] == CLIP_CODE_LZ) &&
( vertex_ccodes[1] == CLIP_CODE_LZ) &&
( vertex_ccodes[2] == CLIP_CODE_LZ) ) )
{
//将完全在裁剪面外侧的多边形裁剪掉
SET_BIT( curr_poly->state, POLY4DV2_STATE_CLIPPED);
//进入下一个多边形
continue;
}
}
//判断是否有顶点在近裁剪面外侧
if(( ( vertex_ccodes[0] | vertex_ccodes[1] | vertex_ccodes[2]) & CLIP_CODE_LZ ) )
{
//2种情景:
//1,三角形有个顶点在近裁剪面内部
//2,或者个顶点在近裁剪面内部
//第一步:根据内外侧顶点数对三角形进行分类
//情形:简单情形:裁剪后的三角形覆盖原来的三角形
if(num_verts_in == 1 )
{
//第一步,找出位于内侧的顶点
if( vertex_ccodes[0]== CLIP_CODE_IZ )
{
v0 = 0;
v1 = 1;
v2 = 2;
}
else
if( vertex_ccodes[1]== CLIP_CODE_IZ )
{
v0 = 1;
v1 = 2;
v2 = 0;
}
else
{
v0 = 2;
v1 = 0;
v2 = 1;
}
//第步:对每条边进行裁剪
//创建参数化线段p = v0 + v01 * t
//对三角形边v0->v1,进行裁剪
math2->VECTOR4D_Build(& curr_poly->tvlist[v0].v, & curr_poly->tvlist[v1].v, & v );
//交点的z坐标为near_clip_z,因此,t值如下
t1 = ( ( cam->near_clip_z - curr_poly->tvlist[v0].z ) / v.z );
//代入t,得到交点的x,y坐标
xi =curr_poly->tvlist[v0].x + v.x * t1;
yi =curr_poly->tvlist[v0].y + v.y * t1;
//用交点覆盖原来的原点
curr_poly->tvlist[v1].x = xi;
curr_poly->tvlist[v1].y = yi;
curr_poly->tvlist[v1].z = cam->near_clip_z;
//对三角形边v0->v2,进行裁剪
math2->VECTOR4D_Build(& curr_poly->tvlist[v0].v, & curr_poly->tvlist[v2].v, & v );
//交点的z坐标为near_clip_z,因此,t值如下
t2 = ( ( cam->near_clip_z - curr_poly->tvlist[v0].z ) / v.z );
//代入t,得到交点的x,y坐标
xi =curr_poly->tvlist[v0].x + v.x * t2;
yi =curr_poly->tvlist[v0].y + v.y * t2;
//用交点覆盖原来的原点
curr_poly->tvlist[v2].x = xi;
curr_poly->tvlist[v2].y = yi;
curr_poly->tvlist[v2].z = cam->near_clip_z;
//检查多边形是否带纹理,
//如果带纹理,则对纹理坐标进行裁剪
if( curr_poly->attr & POLY4DV2_ATTR_SHADE_MODE_TEXTURE)
{
ui =curr_poly->tvlist[v0].u0 + ( curr_poly->tvlist[v1].u0 - curr_poly->tvlist[v0].u0 ) * t1;
vi =curr_poly->tvlist[v0].v0 + ( curr_poly->tvlist[v1].v0 - curr_poly->tvlist[v0].v0 ) * t1;
curr_poly->tvlist[v1].u0= ui;
curr_poly->tvlist[v1].v0= vi;
ui =curr_poly->tvlist[v0].u0 + ( curr_poly->tvlist[v2].u0 - curr_poly->tvlist[v0].u0 ) * t2;
vi =curr_poly->tvlist[v0].v0 + ( curr_poly->tvlist[v2].v0 - curr_poly->tvlist[v0].v0 ) * t2;
curr_poly->tvlist[v2].u0= ui;
curr_poly->tvlist[v2].v0= vi;
}
//最后,重新计算法线长度
//计算u和
math2->VECTOR4D_Build(& curr_poly->tvlist[v0].v, & curr_poly->tvlist[v1].v, & u );
math2->VECTOR4D_Build(& curr_poly->tvlist[v0].v, & curr_poly->tvlist[v2].v, & v );
//计算叉积
math2->VECTOR4D_CROSS(& u, & v,& n );
//计算并存储法线长度
curr_poly->nlength= math2->VECTOR4D_length(& n );
}
else
//情形:被裁减后三角形变为四边形,覆盖一个,插入渲染列表末尾个
if(num_verts_in == 2 )
{
//第步,复制多边形
memcpy( & temp_poly,curr_poly, sizeof(POLY4DV2 ) );
//第一步,找出位于外侧的顶点
if( vertex_ccodes[0]== CLIP_CODE_LZ )
{
v0 = 0;
v1 = 1;
v2 = 2;
}
else
if( vertex_ccodes[1]== CLIP_CODE_LZ )
{
v0 = 1;
v1 = 2;
v2 = 0;
}
else
{
v0 = 2;
v1 = 0;
v2 = 1;
}
//第步:对每条边进行裁剪
//创建参数化线段p = v0 + v01 * t
//对三角形边v0->v1,进行裁剪
math2->VECTOR4D_Build(& curr_poly->tvlist[v0].v, & curr_poly->tvlist[v1].v, & v );
//交点的z坐标为near_clip_z,因此,t值如下
t1 = ( ( cam->near_clip_z - curr_poly->tvlist[v0].z ) / v.z );
//代入t,得到交点的x,y坐标
x01i =curr_poly->tvlist[v0].x + v.x * t1;
y01i =curr_poly->tvlist[v0].y + v.y * t1;
//对三角形边v0->v2,进行裁剪
math2->VECTOR4D_Build(& curr_poly->tvlist[v0].v, & curr_poly->tvlist[v2].v, & v );
//交点的z坐标为near_clip_z,因此,t值如下
t2 = ( ( cam->near_clip_z - curr_poly->tvlist[v0].z ) / v.z );
//代入t,得到交点的x,y坐标
x02i =curr_poly->tvlist[v0].x + v.x * t2;
y02i = curr_poly->tvlist[v0].y + v.y * t2;
//用交点覆盖原来的三角形的顶点
curr_poly->tvlist[v0].x = x01i;
curr_poly->tvlist[v0].y = y01i;
curr_poly->tvlist[v0].z = cam->near_clip_z;
//使用原来的顶点和两个交点创建一个新三角形
//该三角形被插入到渲染列表的末尾
temp_poly.tvlist[v1].x = x01i;
temp_poly.tvlist[v1].y = y01i;
temp_poly.tvlist[v1].z = cam->near_clip_z;
temp_poly.tvlist[v0].x = x02i;
temp_poly.tvlist[v0].y = y02i;
temp_poly.tvlist[v0].z = cam->near_clip_z;
//检查多边形是否带纹理,
//如果带纹理,则对纹理坐标进行裁剪
if( curr_poly->attr & POLY4DV2_ATTR_SHADE_MODE_TEXTURE)
{
//计算多边形的纹理坐标
u01i =curr_poly->tvlist[v0].u0 + ( curr_poly->tvlist[v1].u0 - curr_poly->tvlist[v0].u0 ) * t1;
v01i =curr_poly->tvlist[v0].v0 + ( curr_poly->tvlist[v1].v0 - curr_poly->tvlist[v0].v0 ) * t1;
//计算多边形的纹理坐标
u02i =curr_poly->tvlist[v0].u0 + ( curr_poly->tvlist[v2].u0 - curr_poly->tvlist[v0].u0 ) * t2;
v02i =curr_poly->tvlist[v0].v0 + ( curr_poly->tvlist[v2].v0 - curr_poly->tvlist[v0].v0 ) * t2;
//覆盖原来的纹理坐标
//多边形
curr_poly->tvlist[v1].u0= u01i;
curr_poly->tvlist[v1].v0= v01i;
//多边形
temp_poly.tvlist[v0].u0 = u02i;
temp_poly.tvlist[v0].u0 = v02i;
temp_poly.tvlist[v1].u0 = u01i;
temp_poly.tvlist[v1].u0 = v01i;
}
//最后,重新计算法线长度
//计算u和v
math2->VECTOR4D_Build(& curr_poly->tvlist[v0].v, & curr_poly->tvlist[v1].v, & u );
math2->VECTOR4D_Build(& curr_poly->tvlist[v0].v, & curr_poly->tvlist[v2].v, & v );
//计算叉积
math2->VECTOR4D_CROSS(& u, & v,& n );
//计算并存储法线长度
curr_poly->nlength= math2->VECTOR4D_length(& n );
//现在计算多边形(temp_poly)的法线长度
//计算u和v
math2->VECTOR4D_Build(& temp_poly.tvlist[v0].v, & temp_poly.tvlist[v1].v, & u );
math2->VECTOR4D_Build(& temp_poly.tvlist[v0].v, & temp_poly.tvlist[v2].v, & v );
//计算叉积
math2->VECTOR4D_CROSS(& u, & v,& n );
//计算并存储法线长度
temp_poly.nlength= math2->VECTOR4D_length(& n );
//现在将多边形插入到渲染列表末尾
Insert_POLYF4DV2_RENDERLIST4DV2( rend_list, & temp_poly,math2 );
}
}
}
}
现在看main.cpp了
定义个物体数量
#define NUM_OBJECTS 6
位置变化了
vpos = {0,0,150,1},
物体
OBJECT4DV2_PTR obj_work;
OBJECT4DV2_PTR obj_array[NUM_OBJECTS];
几个模型
// filenames of objects to load
char *object_filenames[NUM_OBJECTS] = { "cube_flat_01.cob",
"cube_gouraud_01.cob",
"cube_flat_textured_01.cob",
"sphere02.cob",
"sphere03.cob",
"hammer03.cob",
};
int curr_object = 0;
在初始化中
摄像机换了位置
liushuixian.Init_CAM4DV1( * math,&cam, // the camera object
CAM_MODEL_EULER,// the euler model
&cam_pos, // initial camera position
&cam_dir, // initial camera angles
&cam_target, // no target
100.0, // near and farclipping planes
1000.0,
120.0, // field ofview in degrees
SCREEN_WIDTH, // size offinal screen viewport
SCREEN_HEIGHT);
//放大扩大倍数
math->VECTOR4D_INITXYZ(&vscale,20.00,20.00,20.00);
物体数组
for(int index_obj= 0; index_obj < NUM_OBJECTS;index_obj ++ )
{
liushuixian_texture.Load_OBJECT4DV2_COB( * math,matiGroup, & obj_array[index_obj],object_filenames[index_obj],
&vscale, &vpos, &vrot, VERTEX_FLAGS_SWAP_YZ|
VERTEX_FLAGS_TRANSFORM_LOCAL /*|
VERTEX_FLAGS_TRANSFORM_LOCAL_WORLD*/ );
}
curr_object = 0;
obj_work= & obj_array[curr_object];
设置灯光时,引入新的灯光数据类型
#define LIGHTV2_ATTR_AMBIENT 0x0001 //环境光源
#define LIGHTV2_ATTR_DIRECTIONAL 0x0002
#define LIGHTV2_ATTR_INFINITE 0x0002 //无穷远光源
#define LIGHTV2_ATTR_POINT 0x0004 //点光源
#define LIGHTV2_ATTR_SPOTLIGHT1 0x0008 //1类(简单)聚光灯
#define LIGHTV2_ATTR_SPOTLIGHT2 0x0010 //2类(复杂)聚光灯
#define LIGHTV2_STATE_ON 1 //光源打开
#define LIGHTV2_STATE_OFF 0 //光源关闭
#define TRANSFORM_COPY_LOCAL_TO_TRANS 3
typedef struct LIGHTV2_TYP
{
int state; //光照状态
int id; //光源ID
int attr; //光源类型及其他属性
RGBAV1 c_ambient; //环境光强度
RGBAV1 c_diffuse; //散射光强度
RGBAV1 c_specular; //镜面反射光强度
POINT4D pos; //光源位置
POINT4D tpos;
VECTOR4D dir; //光源方向
VECTOR4D tdir; //光源方向
float kc,kl,kq; //衰减因子
float spot_inner; //聚光灯内锥角
float spot_outer; //聚光灯外锥角
float pf; //聚光灯指数因子
int iaux1,iaux2; //auxiliary vars for future expansion
float faux1,faux2;
void* ptr;
}LIGHTV2, * LIGHTV2_PTR;
另外,重置灯光
int DDRAW_LIGHT::Reset_Lights_LIGHTV2(LIGHTV2_PTR lights,int max_lights,int num_lights)
{
staticint first_time =1;
memset(lights, 0, max_lights* sizeof( LIGHTV2));
//重置光源数
num_lights = 0;
first_time = 0;
return( 1 );
}
初始化灯光也随之更新。
int DDRAW_LIGHT::Init_Light_LIGHTV2(ddraw_math math2, LIGHTV2_PTRlight_gr, intindex, int _state, int _attr, RGBAV1 _c_ambient, RGBAV1_c_diffuse, RGBAV1_c_specular, POINT4D_PTR_pos, VECTOR4D_PTR_dir, float kc, float kl, float kq, float _spot_inner, float_spot_outer, float_pf )
{
if ( index < 0 || index >= MAX_LIGHTS)
{
return( 0 );
}
//初始化光源
light_gr[index].state = _state;
light_gr[index].id = index;
light_gr[index].attr = _attr;
light_gr[index].c_ambient = _c_ambient;
light_gr[index].c_diffuse = _c_diffuse;
light_gr[index].c_specular = _c_specular;
light_gr[index].kc = kc;
light_gr[index].kl = kl;
light_gr[index].kq = kq;
if( _pos )
{
math2.VECTOR4D_COPY(& light_gr[index].pos, _pos ); //光源位置
math2.VECTOR4D_COPY(& light_gr[index].tpos, _pos );
}
if( _dir )
{
math2.VECTOR4D_COPY( & light_gr[index].dir, _dir ); //光源方向
// math2.VECTOR4D_COPY(& light_gr[index].dir, _dir );
//归一化
math2.VECTOR4D_Normalize( & light_gr[index].dir );
math2.VECTOR4D_COPY( & light_gr[index].tdir,& light_gr[index].dir );
}
light_gr[index].spot_inner = _spot_inner;
light_gr[index].spot_outer = _spot_outer;
light_gr[index].pf = _pf;
//返回光源索引
returnindex;
}
与之对应的初始化
light.Init_Light_LIGHTV2( * math,lightGroup,AMBIENT_LIGHT_INDEX,LIGHTV2_STATE_ON, LIGHTV2_ATTR_AMBIENT,gray, black,black, NULL,NULL, 0, 0, 0, 0, 0, 0 );
在Game_Main()中,
设定裁剪模式
staticint x_clip_mode = 1;
staticint y_clip_mode = 1;
staticint z_clip_mode = 1;
//重置物体
liushuixian_texture.Reset_OBJECT4DV2(obj_work);
//generate rotation matrix around y axis
math->Build_XYZ_Rotation_MATRIX4x4(x_ang, y_ang, z_ang, &mrot);
// Build_XYZ_Rotation_MATRIX4x4(x_ang, y_ang,z_ang, &mrot);
//rotate the local coords of the object
liushuixian_texture.Transform_OBJECT4DV2( obj_work,&mrot, TRANSFORM_LOCAL_TO_TRANS,1,* math );
//perform world transform
liushuixian_texture.Model_To_World_OBJECT4DV2(obj_work,* math, TRANSFORM_TRANS_ONLY);
//insert the object into render list
liushuixian_texture.Insert_OBJECT4DV2_RENDERLIST4DV2(* math, &rend_list,obj_work,0);
光照代码如下
int DDRAW_LIUSHUIXIAN_TEXTURE::Light_RENDERLIST4DV2_World2_16( ddraw_math math,int rgb_format,RENDERLIST4DV2_PTR rend_list,CAM4DV1_PTR cam,LIGHTV2_PTR lights,int max_lights)
{
unsigned int r_base,g_base, b_base, //原来的颜色值
r_sum,g_sum, b_sum, //全部光源的总体光照效果
r_sum0,g_sum0, b_sum0,
r_sum1,g_sum1, b_sum1,
r_sum2,g_sum2, b_sum2,
ri,gi, bi,
shaded_color; //最后的颜色
float dp, //点积
dist, //表面和光源之间的距离
dists,
i, //强度
nl, //法线长度
atten; //衰减计算结果
VECTOR4D u,v, n, l, d, s;
for( int poly =0; poly < rend_list->num_polys; poly++)
{
POLYF4DV2_PTR curr_poly = rend_list->poly_ptrs[poly];
if( ! ( curr_poly->state& POLY4DV2_STATE_ACTIVE) ||
( curr_poly->state& POLY4DV2_STATE_CLIPPED) ||
( curr_poly->state& POLY4DV2_STATE_BACKFACE) ||
( curr_poly->state& POLY4DV2_STATE_LIT ))
{
continue;
}
SET_BIT(curr_poly->state,POLY4DV2_STATE_LIT );
//检查多边形的着色模式
if( curr_poly->attr& POLY4DV2_ATTR_SHADE_MODE_FLAT )
{
//提取多边形颜色的RGB值
_RGB565FROM16BIT(curr_poly->color,& r_base, & g_base,& b_base );
//转换成.8.8格式
r_base <<= 3;
g_base <<= 2;
b_base <<=3;
//初始化总体光照颜色
r_sum = 0;
g_sum = 0;
b_sum = 0;
n.z =FLT_MAX;
//遍历光照
for( int curr_light= 0; curr_light < max_lights; curr_light ++)
{
//光源是否被打开
if ( lights[curr_light].state==LIGHTV2_STATE_OFF)
{
continue;
}
//判断光源类型
if ( lights[curr_light].attr& LIGHTV2_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& LIGHTV2_ATTR_INFINITE )
{
if( n.z == FLT_MAX)
{
math.VECTOR4D_Build(& curr_poly->tvlist[0].v, & curr_poly->tvlist[1].v,& u );
math.VECTOR4D_Build(& curr_poly->tvlist[0].v, & curr_poly->tvlist[2].v,& v );
math.VECTOR4D_CROSS(& u, &v,&n );
}
nl =curr_poly->nlength;
dp =math.VECTOR4D_DOT(&n, & lights[curr_light].tdir);
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& LIGHTV2_ATTR_POINT )
{
if ( n.z == FLT_MAX)
{
math.VECTOR4D_Build(& curr_poly->tvlist[0].v, & curr_poly->tvlist[1].v,& u );
math.VECTOR4D_Build(& curr_poly->tvlist[0].v, & curr_poly->tvlist[2].v,& v );
math.VECTOR4D_CROSS(& u, &v,&n );
}
nl =curr_poly->nlength;
//计算从表面到光源的向量
math.VECTOR4D_Build(& curr_poly->tvlist[0].v, & lights[curr_light].tpos,&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& LIGHTV2_ATTR_SPOTLIGHT1 )
{
if (n.z == FLT_MAX)
{
math.VECTOR4D_Build(& curr_poly->tvlist[0].v, & curr_poly->tvlist[1].v,& u );
math.VECTOR4D_Build(& curr_poly->tvlist[0].v, & curr_poly->tvlist[2].v,& v );
math.VECTOR4D_CROSS(& u, &v,&n );
}
nl =curr_poly->nlength;
//计算从表面到光源的向量
math.VECTOR4D_Build(& curr_poly->tvlist[0].v, & lights[curr_light].tpos,&l );
//计算距离和衰减
dist =math.VECTOR4D_length(&l);
dp =math.VECTOR4D_DOT(&n, & lights[curr_light].tdir);
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& LIGHTV2_ATTR_SPOTLIGHT2 )
{
if (n.z == FLT_MAX )
{
math.VECTOR4D_Build(& curr_poly->tvlist[0].v, & curr_poly->tvlist[1].v,& u );
math.VECTOR4D_Build(& curr_poly->tvlist[0].v, & curr_poly->tvlist[2].v,& v );
math.VECTOR4D_CROSS(& u, &v,&n );
}
nl =curr_poly->nlength;
dp =math.VECTOR4D_DOT(&n, & lights[curr_light].tdir);
if ( dp > 0 )
{
//计算从表面到光源的向量
math.VECTOR4D_Build(& lights[curr_light].tpos, & curr_poly->tvlist[0].v, &s );
dists =math.VECTOR4D_length(&s);
float dpsl =math.VECTOR4D_DOT(& s, & lights[curr_light].tdir) / dists;
if ( dpsl > 0)
{
atten =( lights[curr_light].kc + lights[curr_light].kl* dists + lights[curr_light].kq* dists * dists);
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;
}
//写入颜色
curr_poly->lit_color[0] =_RGB16BIT565( r_sum,g_sum, b_sum);
}
else
if( curr_poly->attr& POLY4DV2_ATTR_SHADE_MODE_GOURAUD )
{
//提取多边形颜色的RGB值
_RGB565FROM16BIT( curr_poly->color, & r_base,& g_base, & b_base);
//转换成.8.8格式
r_base <<=3;
g_base <<=2;
b_base <<= 3;
//初始化顶点的累积RGB值
r_sum0 =0;
g_sum0 =0;
b_sum0 =0;
r_sum1 =0;
g_sum1 =0;
b_sum1 =0;
r_sum2 =0;
g_sum2 =0;
b_sum2 =0;
//遍历光照
for ( int curr_light = 0; curr_light< max_lights; curr_light++)
{
//光源是否被打开
if ( lights[curr_light].state==LIGHTV2_STATE_OFF)
{
continue;
}
//判断光源类型
if ( lights[curr_light].attr& LIGHTV2_ATTR_AMBIENT )
{
ri +=( ( lights[curr_light].c_ambient.r * r_base) / 256 );
gi +=( ( lights[curr_light].c_ambient.g * g_base) / 256 );
bi +=( ( lights[curr_light].c_ambient.b * b_base) / 256 );
//环境光源对每个顶点的影响相同
r_sum0 += ri;
g_sum0 +=gi;
b_sum0 +=bi;
r_sum1 +=ri;
g_sum1 +=gi;
b_sum1 +=bi;
r_sum2 +=ri;
g_sum2 +=gi;
b_sum2 +=bi;
}
else
if ( lights[curr_light].attr& LIGHTV2_ATTR_INFINITE )
{
//顶点
dp =math.VECTOR4D_DOT(& curr_poly->tvlist[0].n, & lights[curr_light].tdir);
if ( dp > 0 )
{
i =128 * dp;
r_sum0 +=( lights[curr_light].c_diffuse.r * r_base * i ) / ( 256 * 128);
g_sum0 +=( lights[curr_light].c_diffuse.g * g_base * i ) / ( 256 * 128);
b_sum0 +=( lights[curr_light].c_diffuse.b * b_base * i ) / ( 256 * 128);
}
//顶点
dp =math.VECTOR4D_DOT(& curr_poly->tvlist[1].n, & lights[curr_light].tdir);
if ( dp > 0 )
{
i =128 * dp;
r_sum1 +=( lights[curr_light].c_diffuse.r * r_base * i ) / ( 256 * 128);
g_sum1 += ( lights[curr_light].c_diffuse.g * g_base * i ) / ( 256 * 128);
b_sum1 +=( lights[curr_light].c_diffuse.b * b_base * i ) / ( 256 * 128);
}
//顶点
dp =math.VECTOR4D_DOT(& curr_poly->tvlist[2].n, & lights[curr_light].tdir);
if ( dp > 0 )
{
i =128 * dp ;
r_sum2 +=( lights[curr_light].c_diffuse.r * r_base * i ) / ( 256 * 128);
g_sum2 +=( lights[curr_light].c_diffuse.g * g_base * i ) / ( 256 * 128);
b_sum2 +=( lights[curr_light].c_diffuse.b * b_base * i ) / ( 256 * 128);
}
}
else
if ( lights[curr_light].attr& LIGHTV2_ATTR_POINT )
{
//计算从表面到光源的向量
math.VECTOR4D_Build(& curr_poly->tvlist[0].v, & lights[curr_light].tpos,&l );
//计算距离和衰减
dist =math.VECTOR4D_length(&l);
//顶点
dp =math.VECTOR4D_DOT(&curr_poly->tvlist[0].n, & l);
if ( dp > 0 )
{
atten =( lights[curr_light].kc + lights[curr_light].kl* dist + lights[curr_light].kq* dist * dist);
i =128 * dp / ( dist* atten );
r_sum0 +=( lights[curr_light].c_diffuse.r * r_base * i ) / ( 256 * 128);
g_sum0 +=( lights[curr_light].c_diffuse.g * g_base * i ) / ( 256 * 128);
b_sum0 +=( lights[curr_light].c_diffuse.b * b_base * i ) / ( 256 * 128);
}
//顶点
dp =math.VECTOR4D_DOT(&curr_poly->tvlist[1].n, & l);
if ( dp > 0 )
{
atten =( lights[curr_light].kc + lights[curr_light].kl* dist + lights[curr_light].kq* dist * dist);
i =128 * dp / ( dist* atten );
r_sum1 +=( lights[curr_light].c_diffuse.r * r_base * i ) / ( 256 * 128);
g_sum1 +=( lights[curr_light].c_diffuse.g * g_base * i ) / ( 256 * 128);
b_sum1 +=( lights[curr_light].c_diffuse.b * b_base * i ) / ( 256 * 128);
}
//顶点
dp =math.VECTOR4D_DOT(&curr_poly->tvlist[2].n, & l);
if ( dp > 0 )
{
atten =( lights[curr_light].kc + lights[curr_light].kl* dist + lights[curr_light].kq* dist * dist);
i =128 * dp / ( dist* atten );
r_sum2 +=( lights[curr_light].c_diffuse.r * r_base * i ) / ( 256 * 128);
g_sum2 +=( lights[curr_light].c_diffuse.g * g_base * i ) / ( 256 * 128);
b_sum2 +=( lights[curr_light].c_diffuse.b * b_base * i ) / ( 256 * 128);
}
}
else
if ( lights[curr_light].attr& LIGHTV2_ATTR_SPOTLIGHT1 )
{
//计算从表面到光源的向量
math.VECTOR4D_Build(& curr_poly->tvlist[0].v, & lights[curr_light].tpos,&l );
//计算距离和衰减
dist =math.VECTOR4D_length(&l);
//顶点
dp =math.VECTOR4D_DOT(&curr_poly->tvlist[0].n, & lights[curr_light].tdir);
if ( dp > 0 )
{
atten =( lights[curr_light].kc + lights[curr_light].kl* dist + lights[curr_light].kq* dist * dist);
i =128 * dp / ( atten);
r_sum0 +=( lights[curr_light].c_diffuse.r * r_base * i ) / ( 256 * 128);
g_sum0 +=( lights[curr_light].c_diffuse.g * g_base * i ) / ( 256 * 128);
b_sum0 += ( lights[curr_light].c_diffuse.b * b_base * i ) / ( 256 * 128);
}
//顶点
dp =math.VECTOR4D_DOT(&curr_poly->tvlist[1].n, & lights[curr_light].tdir);
if ( dp > 0 )
{
atten =( lights[curr_light].kc + lights[curr_light].kl* dist + lights[curr_light].kq* dist * dist);
i =128 * dp / ( atten);
r_sum1 +=( lights[curr_light].c_diffuse.r * r_base * i ) / ( 256 * 128);
g_sum1 += ( lights[curr_light].c_diffuse.g * g_base * i ) /( 256 * 128);
b_sum1 +=( lights[curr_light].c_diffuse.b * b_base * i ) / ( 256 * 128);
}
//顶点
dp =math.VECTOR4D_DOT(&curr_poly->tvlist[2].n, & lights[curr_light].tdir);
if ( dp > 0 )
{
atten =( lights[curr_light].kc + lights[curr_light].kl* dist + lights[curr_light].kq* dist * dist);
i =128 * dp / ( atten);
r_sum2 +=( lights[curr_light].c_diffuse.r * r_base * i ) / ( 256 * 128);
g_sum2 +=( lights[curr_light].c_diffuse.g * g_base * i ) / ( 256 * 128);
b_sum2 +=( lights[curr_light].c_diffuse.b * b_base * i ) / ( 256 * 128);
}
}
else
if ( lights[curr_light].attr& LIGHTV2_ATTR_SPOTLIGHT2 )
{
//顶点
dp =math.VECTOR4D_DOT(&curr_poly->tvlist[0].n, & lights[curr_light].tdir);
if ( dp > 0 )
{
math.VECTOR4D_Build(& lights[curr_light].tpos, & curr_poly->tvlist[0].v,& s );
dists =math.VECTOR4D_length(& s );
float dpsl =math.VECTOR4D_DOT(& s, & lights[curr_light].tdir) / dists;
if ( dpsl > 0)
{
atten =( lights[curr_light].kc + lights[curr_light].kl* dists + lights[curr_light].kq* dists * dists);
float dpsl_exp =dpsl;
for ( int e_index = 1; e_index< ( int ) lights[curr_light].pf;e_index ++ )
{
dpsl_exp *=dpsl;
}
i =128 * dp * dpsl_exp/ ( atten );
r_sum0 +=( lights[curr_light].c_diffuse.r * r_base * i ) / ( 256 * 128);
g_sum0 +=( lights[curr_light].c_diffuse.g * g_base * i ) / ( 256 * 128);
b_sum0 +=( lights[curr_light].c_diffuse.b * b_base * i ) / ( 256 * 128);
}
}
//顶点
dp =math.VECTOR4D_DOT(&curr_poly->tvlist[1].n, & lights[curr_light].tdir);
if ( dp > 0 )
{
math.VECTOR4D_Build(& lights[curr_light].tpos, & curr_poly->tvlist[1].v,& s );
dists =math.VECTOR4D_length(& s );
float dpsl =math.VECTOR4D_DOT(& s, & lights[curr_light].tdir) / dists;
if ( dpsl > 0)
{
atten =( lights[curr_light].kc + lights[curr_light].kl* dists + lights[curr_light].kq* dists * dists);
float dpsl_exp =dpsl;
for ( int e_index = 1; e_index< ( int ) lights[curr_light].pf;e_index ++ )
{
dpsl_exp *=dpsl;
}
i =128 * dp * dpsl_exp/ ( atten );
r_sum1 +=( lights[curr_light].c_diffuse.r * r_base * i ) / ( 256 * 128);
g_sum1 +=( lights[curr_light].c_diffuse.g * g_base * i ) / ( 256 * 128);
b_sum1 +=( lights[curr_light].c_diffuse.b * b_base * i ) / ( 256 * 128);
}
}
//顶点
dp = math.VECTOR4D_DOT(&curr_poly->tvlist[2].n, & lights[curr_light].tdir);
if ( dp > 0 )
{
math.VECTOR4D_Build(& lights[curr_light].tpos, & curr_poly->tvlist[2].v,& s );
dists =math.VECTOR4D_length(& s );
float dpsl =math.VECTOR4D_DOT(& s, & lights[curr_light].tdir) / dists;
if ( dpsl > 0)
{
atten =( lights[curr_light].kc + lights[curr_light].kl* dists + lights[curr_light].kq* dists * dists);
float dpsl_exp =dpsl;
for ( int e_index = 1; e_index< ( int ) lights[curr_light].pf;e_index ++ )
{
dpsl_exp *=dpsl;
}
i =128 * dp * dpsl_exp/ ( atten );
r_sum2 += ( lights[curr_light].c_diffuse.r * r_base * i ) / ( 256 * 128);
g_sum2 +=( lights[curr_light].c_diffuse.g * g_base * i ) / ( 256 * 128);
b_sum2 +=( lights[curr_light].c_diffuse.b * b_base * i ) / ( 256 * 128);
}
}
}
}
//确保颜色分量不溢出
if ( r_sum0 > 255 )
{
r_sum0 =255;
}
if ( g_sum0 > 255 )
{
g_sum0 =255;
}
if ( b_sum0 > 255 )
{
b_sum0 = 255;
}
if ( r_sum1 > 255 )
{
r_sum1 =255;
}
if ( g_sum1 > 255 )
{
g_sum1 =255;
}
if ( b_sum1 > 255 )
{
b_sum1 =255;
}
if ( r_sum2 > 255 )
{
r_sum2 =255;
}
if ( g_sum2 > 255 )
{
g_sum2 =255;
}
if ( b_sum2 > 255 )
{
b_sum2 =255;
}
//写入颜色
curr_poly->lit_color[0] = _RGB16BIT565( r_sum0,g_sum0, b_sum0);
curr_poly->lit_color[1] = _RGB16BIT565( r_sum1,g_sum1, b_sum1);
curr_poly->lit_color[2] = _RGB16BIT565( r_sum2,g_sum2, b_sum2);
}
else
{
curr_poly->lit_color[0] = curr_poly->color;
}
}
return( 1 );
}
运行结果如下图所示