图形学的学习

来源:互联网 发布:大阪 香港知乎 编辑:程序博客网 时间:2024/05/16 12:12

http://down.51cto.com/zt/6508/ 图形学教程 


1.什么是uv? 

所有的图象文件都是二维的一个平面。水平方向是U,垂直方向是V,通过这个平面的,二维的UV坐标系。我们可以定位图象上的任意一个象素。但是一个问题是如何把这个二维的平面贴到三维的NURBS表面和多边形表面呢? 
对于NURBUS表面。由于他本身具有UV参数,尽管这个UV值是用来定位表面上的点的参数,但由于它也是二维的,所以很容易通过换算把表面上的点和平面图象上的象素对应起来。所以把图象贴带NURBUS表面上是很直接的一件事。 
但是对于多变形模型来讲,贴图就变成一件麻烦的事了。所以多边形为了贴图就额外引进了一个UV坐标,以便把多边形的顶点和图象文件上的象素对应起来,这样才能在多边形表面上定位纹理贴图。所以说多边形的顶点除了具有三维的空间坐标外。还具有二维的UV坐标。 
对于纹理贴图而言,一张贴图的U和V坐标的数值范围都是0到1,而不管他的实际分辨率是多少,MAYA会自动把UV纹理坐标换算成贴图的象素坐标。(以上文字摘自MAYA4.5高级教程)。 

2. 什么是UV? 
"UV"这里是指u,v纹理贴图坐标的简称(它和空间模型的X, Y, Z轴是类似的). 它定义了图片上每个点的位置的信息. 这些点与3D模型是相互联系的, 以决定表面纹理贴图的位置. UV就是将图像上每一个点精确对应到模型物体的表面. 在点与点之间的间隙位置由软件进行图像光滑插值处理. 这就是所谓的UV贴图. 
那为什么用UV坐标而不是标准的投影坐标呢? 通常给物体纹理贴图最标准的方法就是以planar(平面),cylindrical(圆柱), spherical(球形),cubic(方盒)坐标方式投影贴图. 

Planar projection(平面投影方式)是将图像沿x,y或z轴直接投影到物体. 这种方法使用于纸张, 布告, 书的封面等 - 也就是表面平整的物体.平面投影的缺点是如果表面不平整, 或者物体边缘弯曲, 就会产生如图A的不理想接缝和变形. 避免这种情况需要创建带有alpha通道的图像, 来掩盖临近的平面投影接缝, 而这会是非常烦琐的工作. 所以不要对有较大厚度的物体和不平整的表面运用平面投影方式. 对于立方体可以在x, y方向分别进行平面投影, 但是要注意边缘接缝的融合. 或者采用无缝连续的纹理, 并使用cubic投影方式. 多数软件有图片自动缩放功能, 使图像与表面吻合. 显然, 如果你的图像与表面形状不同, 自动缩放就会改变图像的比例以吻合表面. 这通常会产生不理想的效果, 所以制作贴图前先测量你的物体尺寸.


顶点(vertexs) 图元(primitives) 片元(fragments片断) 像素(pixels) 

阶段1.  顶点 ->图元

几何顶点被组合为图元(点,线段或多边形),然后图元被合成片元,最后片元被转换为帧缓存中的象素数据。

阶段2.  图元  ->片元

图元被分几步转换为片元:图元被适当的裁剪,颜色和纹理数据也相应作出必要的调整,相关的坐标被转换为窗口坐标。最后,光栅化将裁剪好的图元转换为片元。

1) 裁剪

在裁剪时点,线段和多边形处理略微不同。对于点,要么保留原始状态(在裁剪体内部),要么被裁掉(在裁剪体外部)。对于线段和多边形来说,如果部分在裁剪体外部,则需要在裁剪点生成新的几何顶点。对于多边形,还需要在新增的顶点间增加完整的边。不论裁剪了线段还是多边形,都需要给新增几何点赋予边界标志、法线、颜色和纹理坐标信息。

裁剪过程时两步:

a 应用程序指定裁剪(Application-specific clipping),一旦组合图元完成后,如果在程序中用glClipPlane()函数定义了任意的裁剪面,就进行裁剪。

b 视景体裁剪(View volume clipping),随后,图元被投影矩阵投影(进入裁剪坐标系),被相应的视景体裁剪。投影矩阵可以由glFrustum() 或者glOrtho()定义,投影矩阵的操作和上面其他矩阵变换的操作相同。

2) 转换到窗口坐标

裁剪坐标在转换为窗口坐标之前,要除以规格化设备坐标(normalized device coordinates)的w值进行规范化。然后对这些规范化数据进行视口变换(viewport)计算生成窗口坐标。可以用glDepthRange()和glViewport()控制视口大小,决定屏幕上显示图象的区域。

3) 光栅化

光栅化是将一个图元转变为一个二维图象(其实只是布满平面,没有真正的替换帧缓存区)的过程。二维图象上每个点都包含了颜色、深度和纹理数据。将该点和相关信息叫做一个片元(fragment)。(yuyu注:这就是片元和像素之间的关键区别,虽然两者的直观印象都是的像素,但是片元比像素多了许多信息,在光栅化中纹理映射之后图元信息转化为了像素)在这个阶段,对象素绘制和位图进行操作需要用到当前栅格位置(用glRasterPos*()定义)。正如上面讨论的,三种图元的光栅化方法是不同的,另外,象素块和位图也需要光栅化。

a)图元

采用glPointSize(), glLineWidth(), glLineStipple()和 glPolygonStipple()函数可以选择图元的光栅化维数和模式。另外,还可以用glCullFace(), glFrontFace()和glPolygonMode()控制多边形正反面不同的光栅化效果。

b)象素

有几个函数实现象素保存和转换。函数glPixelStore*()用于内存中的象素是如何保存的。glPixelTransfer*() and glPixelMap*()用于象素在写入帧缓冲区前是如何处理的。glDrawPixels()定义了一个象素矩形。用glPixelZoom()实现象素的缩放。

c)位图

位图是具有特定片元模式的0和1的矩形。每个片元有相同的相关数据。可以用glBitmap()定义。

d)纹理存储

纹理贴图是将指定的部分纹理图象映射到每个图元上。每个片元(fragment)具有的纹理坐标属性,该坐标与纹理图象坐标对应,得到纹理图象该位置的颜色值来修改片元的RGBA颜色,从而完成这个映射过程。用glTexImage2D()或glTexImage1D()来定义纹理图象。glTexParameter*()和glTexEnv*()来控制纹理如何解释和应用到一个片元上。

e)雾

已经光栅化的片元具有纹理贴图修正后颜色,可以采用融合因子再融合雾颜色,该融合因子大小根据视点和片元间的距离来定。用glFog*()指定雾化颜色和融合因子。

 

 

阶段3.  片元->像素

 

OpenGL允许光栅化生成一个片元,只要该片元通过一系列检测就可以修改帧缓冲区中对应象素。如果它通过测试,片元数据可以直接替换帧缓冲区中的已有值,或者和已有值合并,这取决于设置的模式。

1)象素所有权(ownership)检测

第一个测试是判断在帧缓冲区中的象素所对应的某个片元是否属于当前OpenGL上下文。如果属于,片元进行下一个测试。如果不属于,窗口系统决定是否忽略该片元,或者是否进行下一步片元操作。

2)裁剪检测

用glScissor()函数,可以定义一个任意屏幕校准矩形,在该矩形外的片元将被忽略。

3)Alpha检测

Alpha测试只能在RGBA模式下进行,如果片元的alpha值超出一个固定参照值,片元将被忽略,这个比较函数可以用glAlphaFunc()实现并设定参考值。

4)模版检测

当模版缓冲区的值超出一个参照值,模版测试将有条件的忽略该片元。这个比较函数和固定值可以用glStencilFunc()实现。不论图元通过或没有通过模版测试,模版缓冲区中的值会根据glStencilOp()函数进行修改。

5)深度检测

当深度缓冲区的值与参照值的比较失败,深度测试忽略该片元。GlDepthFuc()用来执行这个比较命令。如果模版启用,深度比较的结果会影响模版缓冲区值的更新。

6)融合

融合合并了一个片元R、G、B和A值和存储在帧缓冲区对应位置的这些值。融合只能在RGBA模式下实现,它的实现需要片元的alpha值和对应当前存储象素,还需要RGB值。用glBendFun()控制,可以修改融合因子的源和目标。

7)抖动

如果启动抖动,片元的颜色或者颜色索引采用抖动算法。这个算法只需要片元的颜色值和它的x和y坐标。

8)逻辑操作

最后,在片元和帧缓冲区对应值之间要进行一个逻辑操作,结果将替换当前帧缓冲区的值。用glLogicOp定义想要的逻辑操作。这个逻辑操作只能在颜色索引模式下运行,而不能在RGBA模式运行。

 

象素

   在OpenGL流水线的上个阶段,片元转换为帧缓冲区中的象素。帧缓冲区实际上是一组逻辑缓冲区——包括颜色缓冲区、深度缓冲区、模版缓冲区和累积缓冲区。颜色缓冲区包括左、前右、后左、后右和一些辅助缓存值(auxiliary buffers)。可以直接从中读取或者复制。对于OpenGL不同上下文,这些缓冲区可能不全

1)帧缓冲区操作

用glDrawBuffer为绘图选择一个颜色缓冲区。另外在预片元化(per-fragment)操作后,可以用四个不同函数保留写入这些逻辑缓冲区的操作,glIndexMask(), glColorMask(), glDepthMask(), and glStencilMask()。glAccum()对累积缓冲区进行操作。最后glClearColor(), glClearIndex(), glClearDepth(), glClearStencil()和glClearAccum().对不同缓冲区中指定相对应的颜色值、颜色索引值、深度值、模板值和累积值。

2)读取和复制象素

用glReadPixel()从帧缓冲区中把象素读到内存中,进行各种操作,保存处理结果。另外,可以用glCopyPixel()从帧缓冲区中复制一块象素到另一个帧混存。glReadBuffer()可以读取和复制颜色缓冲区中的象素。


0 0
原创粉丝点击