1、什么是紫外线?
对于3D模型来说,有两个最重要的坐标系,一个是顶点的位置(X,Y,Z)坐标,一个是UV坐标。 什么是紫外线? 简单地说,它是将纹理映射到模型表面的基础。 完整的应该是UVW(因为XYZ已经用过了,所以再选三个字母来表示)。 U和V分别为图片在显示器水平和垂直方向的坐标,取值一般为0~1,即(水平方向第U个像素/图片宽度,垂直方向第V个像素方向/图片高度)。 W呢? 贴图是二维的,怎么来三个坐标? 那么,W 的方向垂直于显示器的表面。 一般用于procedural mapping或者一些3D mapping技术(记住,确实有3D mapping的概念!),在游戏中不常用,所以我们一般简称为UV。 向上。
所有图像文件都是二维平面。 水平方向为U,垂直方向为V,通过这个平面,二维UV坐标系。 我们可以定位图像上的任何像素。 但是一个问题是如何把这个二维平面贴到三维的NURBS曲面和多边形曲面上呢? 对于 NURBS 曲面。 因为它有UV参数,虽然这个UV值是用来定位表面上的点的参数,但是由于它也是二维的,所以很容易将表面上的点转换成平面图像上的像素。 因此将图像粘贴到 NURBS 非常简单。 但是对于多变形模型,贴图就成了一件麻烦的事情。 因此氛围,对于多边形的纹理,引入了一个额外的UV坐标,将多边形的顶点与图像文件上的像素进行匹配,从而可以将纹理贴图定位在多边形的表面上。 所以多边形的顶点具有三维空间坐标。 也有二维 UV 坐标。
这里的“UV”指的是u、v纹理贴图坐标的缩写(类似于空间模型的X、Y、Z轴),它定义了图像上每个点的位置信息,这些点是相互关联的与3D模型接触,确定表面纹理贴图的位置,UV是将图像上的每个点准确对应到模型物体的表面,软件对点与点之间的间隙进行图像平滑插值处理3D场景,是这样的-称为 UV 贴图。
那为什么要用UV坐标而不是标准投影坐标呢? 通常给物体贴图最标准的方式是在平面(plane)、柱面(cylindrical)、球面(spherical)、立方体(方框)坐标中投射贴图。
平面投影(planar projection method)是将图像沿x、y或z轴直接投影到物体上。 此方法用于纸张、通知、书籍封面等 - 即具有平面的物体。 平面投影的缺点是,如果物体的表面不平坦,或者物体的边缘是弯曲的,就会产生不需要的接缝和扭曲,如图A所示。避免这种情况需要创建带有alpha通道的图像来掩盖相邻平面投影接缝,会很麻烦 因此,对于厚度大、表面不平整的物体,不要使用平面投影法。 对于立方体,可以在x、y方向进行平面投影,但要注意边缝的融合。 或者使用seamless continuous Texture,并使用cubic projection。 大多数软件都有图像自动缩放功能,使图像适合表面。 显然,如果您的图像与表面的形状不同,自动缩放将改变图像的比例以适应表面。 这通常会产生不正确的结果。 理想的效果,所以在制作纹理之前测量你的物体尺寸。
2. uv贴图坐标设置及贴图规则
opengl在映射一个正方形的时候,会定义纹理贴图坐标,一串数组,相信初学者看到openggles都会头疼,不知道写什么好。 现在我就把我的研究成果分享给大家!
在启用纹理映射的情况下进行绘制时,您必须向 OpenGL ES 提供附加数据,即顶点数组中每个顶点的纹理坐标。 纹理坐标定义图像的哪一部分将映射到多边形。 它的工作方式有点奇怪。
再来看android平台下Opengl纹理系统的坐标unity 纹理投影映射,左下角为原点。
我们现在讨论如何使用这些纹理坐标。 当我们在顶点数组中指定顶点时,我们需要在另一个数组中提供纹理坐标,这个数组称为纹理坐标数组。 这里需要注意定义坐标数组的顺序,这个很关键。
float texCoords[] = new float[] {
// 正面
0.0f,0.0f,
1.0f,
0.0f,1.0f,
};
效果如下:
如果我们要截取上角为纹理的图像,上述方法得到的数组
float texCoords[] = new float[] {
// 正面
0.5f,0.5f,
1f,
0.5f,1f,1f
};
效果如下:
我们来看贴图的原始文件
你会发现截图中图片的y轴是倒过来的。 其实这是由于android图片坐标系和Opengl es坐标系不一致造成的。 最简单的修正方法就是用工具翻转原图,比用程序翻转会节省很多性能,资源也很宝贵。
对于三角形纹理贴图,只要按照我们的贴图规则,就可以顺利完成贴图。
float texCoords[] = new float[] {
0.0f,
1.0f,
0.5f,
};
影响:
看到这里,你应该知道纹理坐标数组规则定义的意义了。
平铺和贴箔
我们的纹理坐标系在两个轴上都在 0.0 到 1.0 之间运行,如果我们设置的值超出这个范围会怎样? 根据视图的设置方式unity 纹理投影映射,有两个选项。
平铺(也称为重复)
一种选择是平铺纹理。 在 OpenGL 术语中,它也被称为“重复”。 如果我们将第一个纹理坐标数组中的所有 1.0 更改为 2.0:
static const GLfloat texCoords[] = {
0.0,2.0,
2.0,
0.0,0.0,0.0
};
我们可以通过glTexParameteri()函数来设置。
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);
夹钳
另一种可能的选择是让 OpenGL ES 简单地将高于 1.0 的值钳位到 1.0,将任何低于 0.0 的值钳位到 0.0。 这实际上会导致边缘像素重复。
我们可以通过glTexParameteri()函数来设置。
glTexParameterf(GL_TEXTURE_2D,GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D,GL_CLAMP_TO_EDGE);