《立方体纹理映射》由会员分享,可在线阅读,更多相关《立方体纹理映射(11页珍藏版)》请在金锄头文库上搜索。
1、立方体纹理映射1 问题描述与算法思想1.1 纹理映射简介纹理映射( Texture Mapping )是将纹理空间中的纹理像素映射到屏幕空间 中的像素的过程。在三维图形中,纹理映射( Texture Mapping )的方法运用得 最广,尤其描述具有真实感的物体。比如绘制一面砖墙,就可以使用一幅具有 真实感的图像或者照片作为纹理贴到一个矩形上,这样,一面逼真的砖墙就画 好了。如果不用纹理映射的方法,这墙上的每一块砖都要作为一个独立的多边 形来绘制。另外,纹理映射能够保证在变换多边形时,多边形上的纹理也会随 之变化。例如,用透视投影模式观察墙面时,离视点远的墙壁的砖块的尺寸就 会缩小,而离视点近
2、的就会大些,这些是符合视觉规律的。此外,纹理映射也 被用在其他一些领域。如飞行仿真中常把一大片植被的图像映射到一些大多边 形上用以表示地面,或者用大理石、木材等自然物质的图像作为纹理映射到多 边形上表示相应的物体。纹理对象通过一个单独的数字来标识。这允许硬件能 够在内存中保存多个纹理,而不是每次使用的时候再加载它们,从而减少了运 算量,提高了速度。纹理映射是真实感图像制作的一个重要部分,运用它可以 方便的制作出极具真实感的图形而不必花过多时间来考虑物体的表面细节。然 而纹理加载的过程可能会影响程序运行速度,当纹理图像非常大时,这种情况 尤为明显。如何妥善的管理纹理,减少不必要的开销,是系统优化
3、时必须考虑 的一个问题。还好,相关软件提供了纹理对象对象管理技术来解决上述问题。 与显示列表一样,纹理对象通过一个单独的数字来标识。立方体映射( cube-map )纹理是一种特殊类型的纹理,用于环境映射,使 用一组图像并把他们作为立方体的面。立方体映射的 6 个面用正方形并且大小 相同的 6 个子纹理表示。要从立方体纹理中采样的时候,使用的纹理坐标是 3 维,并且被看做来自原点的方向。方向指向用来读取纹理的立方体映射表面的 位置。立方体纹理映射主要思想是通过观察向量和表面的法向量反射来确定采 样的纹理坐标。1.2 实验目的1)掌握位图纹理读入方法;2)掌握立方体纹理映射算法。1.3 功能要求
4、1)建立三维坐标系 Oxyz ,远点位于屏幕客户区中心, x 轴水平向右为正, y 轴 垂直向上为正, z 轴垂直于屏幕指向观察者。2)设置屏幕背景色为黑色。3)读入六张构成天空盒的位图作为纹理映射到立方体的可见表面上。4)按下鼠标左键缩小立方体,按下鼠标右键增大立方体。5)使用键盘方向旋转纹理立方体。6)使用动画按钮播放或停止立方体动画。1.4 算法原理(算法思想)立方体进行纹理映射是纹理对象并不是直接绑定到着色器,而是绑定到一个纹理单元,纹理单元的索引将会传递给做涩琪。要绑定到一个纹理单元,先 要将其激活,可以使用 glActive Texture ()函数。可以使用多个纹理单元,每 个纹
5、理单元可以绑定到相同的或者不同的纹理对象。只要纹理对象的类型不同, 一个纹理单元可以绑定多个纹理对象。通过采样器变量来使用多个纹理。在片 元着色器中,采样函数需要通过采样器变量访问变量来访问多个纹理单元。采 样器对象与纹理对象不同。纹理对象中包含了纹理数据以及配置采样操作的参 数,这些参数是采样状态额一部分。另外也可以创建一个采样对象,用采样状 态参数配置它,并把它绑定到纹理单元中。这样,采样器对象会覆盖纹理对象 中定义的采样状态。2 总体设计:功能类的结构设计1) 定义CFace类,将面片定点索引号和位图定点索引号绑定在一起,Normal为 面片的法失量;2) 定义 COLORRE类型的 I
6、mage 二维数组,用 void CTestView:Readlmage(int nface) 函数读入纹理图片;3) void CTestView:ReadFace() 定义面表,将四边形面片三维顶点的索引号和 位图二维顶点的索引号对应起来;4) void CTestView:DrawObject( CDC*pD)绘制立方体,在绘制立方体之前先对立方体进行背面剔除以提高效率,绘制时先调用Readlmage()函数读入纹理,再调用 ZBuffer 类的 SetPoint ()函数绑定纹理, 最后根据 TextureMap() 函数根据位图颜色绘制立方体的可见面;5) 在CZBuffer类中添加
7、纹理映射函数 TextureMap (),填充立方体每个可见 面内部时,使用COLORREF型的clr变量读出Image纹理数组对应点的颜色值 进行绘制;6) void CTestView:lnitParameter() ,透视变换参数初始化,设定用户坐标 系的视点球坐标;7) void CTestView:PerProject(CP3 P) ,进行透视变换。实现世界坐标系到 观察坐标系的转换及屏幕坐标系到二维坐标系的转换;8) void CTestView:OnLButtonDown(UlNT nFlags, CPoint point) ,鼠标左键函数;void CTestView:OnRB
8、uttonDblClk(UINT nFlags, CPoint point),鼠标右键函数。点击鼠标左键使立方体缩小,点击右键使立方体增大;9) void CTestView:OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) , 键盘控制函数,点击键盘不同按键控制立方体的旋转;10) void CTestView:ClearImaMem() ,最终删除纹理对象。3 详细设计(流程图)生成纹理T建立点X透视变换参绘制将位图拷删除纹结4源程序(核心功能程序)4.1绘制立方体void CTestView:DrawObject(CDC* pDC) 绘制立
9、方体CPi3 Point4;/ 面的顶点坐标CP2 Texture4;/ 面的纹理坐标 CZBuffer *zbuf=new CZBuffer; zbuf-InitDeepBuffer(800,800,-1000); for(int nFace=0;nFace=0)/ 背面剔除 for(int nEdge=0;nEdgeSetPoint(Point,Texture,4);/ 初始化 (绑定顶点和各个顶点的纹理坐标点)zbuf-CreateBucket();/ 创建桶表zbuf-CreateEdge();/ 创建边表 zbuf-TextureMap(pDC,Image);/ 纹理映 射zbuf-
10、ClearMemory();ClearImaMem();delete zbuf;4.2 读入图片void CTestView:ReadImage(int nface)/ 读入图 片BYTETexture=IDB_FRONT,IDB_BACK,IDB_LEFT,IDB_RIGHT,IDB_TOP,IDB_BOTTOM;CBitmap NewBitmap;NewBitmap.LoadBitmap(Texturenface);/ 调 入位图资源NewBitmap.GetBitmap(&bmp);/ 获 得 CBitmap 的信息到 Bitmap 结构体中intnbytesize=(bmp.bmWid
11、th*bmp.bmHeight*bmp .bmBitsPixel+7)/8;/ 获得位图的总字节数im=new BYTEnbytesize;/ 开辟装载位图的 缓冲区NewBitmap.GetBitmapBits(nbytesize,(LPVOID)im);/ 将位图拷贝到缓冲区Image=new COLORREF*bmp.bmHeight;/ 建立二维颜色数组for(int n1=0;n1=0;n1-)/ 位 图高度for(int n2=0;n2=bmp.bmWidth-1;n2+)/ 位图宽度int pos=n1*bmp.bmWidthBytes+4*n2;/ 位置Imagen1n2=RG
12、B(impos+2,impos+1,im pos);delete im;4.3 鼠标键盘操作函数void CTestView:OnLButtonDown(UINT nFlags, CPoint point)/ 鼠标左键函数/ TODO: Add your message handler code here and/or call defaultR+=100;Invalidate(FALSE);CView:OnLButtonDown(nFlags, point);void CTestView:OnRButtonDblClk(UINTnFlags, CPoint point)/ 鼠标右键函数/ T
13、ODO: Add your message handler codehere and/or call defaultR-=100;Invalidate(FALSE);CView:OnRButtonDblClk(nFlags, point);void CTestView:OnKeyDown(UINT nChar,UINT nRepCnt, UINT nFlags)/ TODO: Add your message handler code here and/or call defaultif(!Play)switch(nChar)case VK_UP:afa=-5; tran.RotateX(afa); break;case VK_DOWN: afa=5; tran.RotateX(afa); break;case VK_LEFT: beta=-5; tran.RotateY(beta); break;case VK_RIGHT: beta=5; tran.RotateY(beta); break;default:break;Invalidate(FALSE);nRepCnt,CView:OnKeyDown(nChar, nFlags);5运行效果图6结论与总结这一次的课程设