计算机图形学实验zbuffer算法.docx
- 文档编号:28073079
- 上传时间:2023-07-08
- 格式:DOCX
- 页数:13
- 大小:17.01KB
计算机图形学实验zbuffer算法.docx
《计算机图形学实验zbuffer算法.docx》由会员分享,可在线阅读,更多相关《计算机图形学实验zbuffer算法.docx(13页珍藏版)》请在冰豆网上搜索。
计算机图形学实验zbuffer算法
实验六9-7
一、实验题目
z-buffer算法的代表性案例是绘制三个相互交叉的红绿蓝条,如图9-85所示,请使用MFC编程实现。
二、实验思想
Z-Buffer算法建立两个缓冲器:
深度缓冲器,用以存储图像空间中每一像素相应的深度值,初始化为最大深度值(zs坐标)。
帧缓冲器,用以存储图像空间中的每个像素的颜色,初始化为屏幕的背景色。
1帧缓冲器初始值置为背景色。
2确定深度缓冲器的宽度、高度和初始深度。
一般将初始深度置为最大深度值。
3对于多边形表面中的每一像素(xs,ys),计算其深度值zs(xs,ys)。
4将zs(xs,ys)与存储在z缓冲器中该位置的深度值zBuffer(xs,ys)进行比较。
5如果zs(xs,ys)≤zBuffer(xs,ys),则将此像素的颜色写入帧缓冲器,且用z(xs,ys)重置zbuffer(xs,ys)。
三、实验代码
CZBuffer:
:
~CZBuffer()
{
delete[]P;
}
voidCZBuffer:
:
SetPoint(CPi3p[],intm)
{
P=newCPi3[m];
for(inti=0;i { P[i]=p[i]; } PNum=m; } voidCZBuffer: : CreateBucket()//创建桶表 { intyMin,yMax; yMin=yMax=P[0].y; for(inti=0;i { if(P[i].y { yMin=P[i].y;//扫描线的最小值 } if(P[i].y>yMax) { yMax=P[i].y;//扫描线的最大值 } } for(inty=yMin;y<=yMax;y++) { if(yMin==y)//建立桶头结点 { HeadB=newCBucket;//建立桶的头结点 CurrentB=HeadB;//CurrentB为CBucket当前结点指针 CurrentB->ScanLine=yMin; CurrentB->pET=NULL;//没有连接边链表 CurrentB->next=NULL; } else//建立桶的其它结点 { CurrentB->next=newCBucket; CurrentB=CurrentB->next; CurrentB->ScanLine=y; CurrentB->pET=NULL; CurrentB->next=NULL; } } } voidCZBuffer: : CreateEdge()//创建边表 { for(inti=0;i { CurrentB=HeadB; intj=(i+1)%PNum;//边的第二个顶点,P[i]和P[j]构成边 if(P[i].y { Edge=newCAET; Edge->x=P[i].x;//计算ET表的值 Edge->yMax=P[j].y; Edge->k=(P[j].x-P[i].x)/(P[j].y-P[i].y);//代表1/k Edge->pb=P[i];//绑定顶点和颜色 Edge->pe=P[j]; Edge->next=NULL; while(CurrentB->ScanLine! =P[i].y)//在桶内寻找该边的yMin { CurrentB=CurrentB->next;//移到yMin所在的桶结点 } } if(P[j].y { Edge=newCAET; Edge->x=P[j].x; Edge->yMax=P[i].y; Edge->k=(P[i].x-P[j].x)/(P[i].y-P[j].y); Edge->pb=P[i]; Edge->pe=P[j]; Edge->next=NULL; while(CurrentB->ScanLine! =P[j].y) { CurrentB=CurrentB->next; } } if(int(P[j].y)! =P[i].y) { CurrentE=CurrentB->pET; if(CurrentE==NULL) { CurrentE=Edge; CurrentB->pET=CurrentE; } else { while(CurrentE->next! =NULL) { CurrentE=CurrentE->next; } CurrentE->next=Edge; } } } } voidCZBuffer: : Gouraud(CDC*pDC)//填充多边形 { doubleCurDeep=0.0;//当前扫描线的深度 doubleDeepStep=0.0;//当前扫描线随着x增长的深度步长 doubleA,B,C,D;//平面方程Ax+By+Cz+D=0的系数 CVectorV21(P[1],P[2]),V10(P[0],P[1]); CVectorVN=V21*V10; A=VN.X();B=VN.Y();C=VN.Z(); D=-A*P[1].x-B*P[1].y-C*P[1].z; DeepStep=-A/C;//计算直线deep增量步长 CAET*T1,*T2; HeadE=NULL; for(CurrentB=HeadB;CurrentB! =NULL;CurrentB=CurrentB->next) { for(CurrentE=CurrentB->pET;CurrentE! =NULL;CurrentE=CurrentE->next) { Edge=newCAET; Edge->x=CurrentE->x; Edge->yMax=CurrentE->yMax; Edge->k=CurrentE->k; Edge->pb=CurrentE->pb; Edge->pe=CurrentE->pe; Edge->next=NULL; AddEt(Edge); } EtOrder(); T1=HeadE; if(T1==NULL) { return; } while(CurrentB->ScanLine>=T1->yMax)//下闭上开 { T1=T1->next; HeadE=T1; if(HeadE==NULL) return; } if(T1->next! =NULL) { T2=T1; T1=T2->next; } while(T1! =NULL) { if(CurrentB->ScanLine>=T1->yMax)//下闭上开 { T2->next=T1->next; T1=T2->next; } else { T2=T1; T1=T2->next; } } CRGBCa,Cb,Cf;//Ca、Cb代边上任意点的颜色,Cf代表面上任意点的颜色 Ca=Interpolation(CurrentB->ScanLine,HeadE->pb.y,HeadE->pe.y,HeadE->pb.c,HeadE->pe.c); Cb=Interpolation(CurrentB->ScanLine,HeadE->next->pb.y,HeadE->next->pe.y,HeadE->next->pb.c,HeadE->next->pe.c); BOOLFlag=FALSE; doublexb,xe;//扫描线的起点和终点坐标 for(T1=HeadE;T1! =NULL;T1=T1->next) { if(Flag==FALSE) { xb=T1->x; CurDeep=-(xb*A+CurrentB->ScanLine*B+D)/C;//z=-(Ax+By-D)/C Flag=TRUE; } else { xe=T1->x; for(doublex=xb;x { Cf=Interpolation(x,xb,xe,Ca,Cb); if(CurDeep>=ZB[ROUND(x)+Width/2][CurrentB->ScanLine+Height/2])//如果新采样点的深度大于原采样点的深度 { ZB[ROUND(x)+Width/2][CurrentB->ScanLine+Height/2]=CurDeep;//xy坐标与数组下标保持一致 pDC->SetPixel(ROUND(x),CurrentB->ScanLine,RGB(Cf.red*255,Cf.green*255,Cf.blue*255)); } CurDeep+=DeepStep; } Flag=FALSE; } } for(T1=HeadE;T1! =NULL;T1=T1->next)//边的连续性 { T1->x=T1->x+T1->k; } } deleteHeadB; deleteHeadE; deleteCurrentE; deleteCurrentB; deleteEdge; } voidCZBuffer: : AddEt(CAET*NewEdge)//合并ET表 { CAET*CE; CE=HeadE; if(CE==NULL) { HeadE=NewEdge; CE=HeadE; } else { while(CE->next! =NULL) { CE=CE->next; } CE->next=NewEdge; } } voidCZBuffer: : EtOrder()//边表的冒泡排序算法 { CAET*T1,*T2; intCount=1; T1=HeadE; if(T1==NULL) { return; } if(T1->next==NULL)//如果该ET表没有再连ET表 { return;//桶结点只有一条边,不需要排序 } while(T1->next! =NULL)//统计结点的个数 { Count++; T1=T1->next; } for(inti=1;i { T1=HeadE; if(T1->x>T1->next->x)//按x由小到大排序 { T2=T1->next; T1->next=T1->next->next; T2->next=T1; HeadE=T2; } else { if(T1->x==T1->next->x) { if(T1->k>T1->next->k)//按斜率由小到大排序 { T2=T1->next; T1->next=T1->next->next; T2->next=T1; HeadE=T2; } } } T1=HeadE; while(T1->next->next! =NULL) { T2=T1; T1=T1->next; if(T1->x>T1->next->x)//按x由小到大排序 { T2->next=T1->next; T1->next=T1->next->next; T2->next->next=T1; T1=T2->next; } else { if(T1->x==T1->next->x) { if(T1->k>T1->next->k)//按斜率由小到大排序 { T2->next=T1->next; T1->next=T1->next->next; T2->next->next=T1; T1=T2->next; } } } } } } CRGBCZBuffer: : Interpolation(doublet,doublet1,doublet2,CRGBc1,CRGBc2)//线性插值 { CRGBc; c=(t-t2)/(t1-t2)*c1+(t-t1)/(t2-t1)*c2; returnc; } voidCZBuffer: : InitDeepBuffer(intwidth,intheight,doubledepth)//初始化深度缓冲 { Width=width,Height=height; ZB=newdouble*[Width]; for(inti=0;i ZB[i]=newdouble[Height]; for(i=0;i for(intj=0;j ZB[i][j]=double(depth); } 四、程序结果截图
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 计算机 图形学 实验 zbuffer 算法