uv纹理坐标设定与贴图规则
1.什么是UV?
对于三维模型,有两个最重要的坐标系统,一是顶点的位置(X,Y,Z)坐标,另一个就是UV坐标。什么是UV?简单的说,就是贴图影射到模型表面的依据。 完整的说,其实应该是UVW(因为XYZ已经用过了,所以另选三个字母表示)。U和V分别是图片在显示器水平、垂直方向上的坐标,取值一般都是0~1,也 就是(水平方向的第U个像素/图片宽度,垂直方向的第V个像素/图片高度)。那W呢?贴图是二维的,何来三个坐标?嗯嗯,W的方向垂直于显示器表面,一般 用于程序贴图或者某些3D贴图技术(记住,确实有三维贴图这种概念!),对于游戏而言不常用到,所以一般我们就简称UV了。
所有的图象文件都是二维的一个平面。水平方向是U,垂直方向是V,通过这个平面的,二维的UV坐标系。我们可以定位图象上的任意一个象素。但是一个问题是如何把这个二维的平面贴到三维的NURBS表面和多边形表面呢? 对于NURBS表面。由于他本身具有UV参数,尽管这个UV值是用来定位表面上的点的参数,但由于它也是二维的,所以很容易通过换算把表面上的点和平面图象上的象素对应起来。所以把图象贴带NURBS是很直接的一件事。但是对于多变形模型来讲,贴图就变成一件麻烦的事了。所以多边形为了贴图就额外引进了一个UV坐标,以便把多边形的顶点和图象文件上的象素对应起来,这样才能在多边形表面上定位纹理贴图。所以说多边形的顶点除了具有三维的空间坐标外。还具有二维的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投影方式. 多数软件有图片自动缩放功能, 使图像与表面吻合. 显然, 如果你的图像与表面形状不同, 自动缩放就会改变图像的比例以吻合表面. 这通常会产生不理想的效果, 所以制作贴图前先测量你的物体尺寸.
2、uv纹理坐标设定与贴图规则
当opengl对一个四方形进行贴图时,会定义纹理贴图坐标,一串数组,相信初学openggl es者看到后会很头疼,不知道写得是什么东西。现在就将我的研究成果与大家分享下!
当纹理映射启动后绘图时,你必须为OpenGL ES提供其他数据,即顶点数组中各顶点的纹理坐标。纹理坐标定义了图像的哪一部分将被映射到多边形。它的工作方式有点奇怪。
下面看下在android平台下Opengl纹理系统坐标,左下角为原点。
我们现在讨论怎样使用这些纹理坐标。当我们指定顶点数组中的顶点时,我们需要在另一个数组中提供纹理坐标,它称为纹理坐标数组。这里需要注意定义坐标数组顺序,这很关键。
float texCoords[] = new float[] {
// FRONT
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
};
效果如下:
如果我们想截取图片有上角不分做纹理,按照上面方法可获的数组
float texCoords[] = new float[] {
// FRONT
0.5f, 0.5f,
1f, 0.5f,
0.5f, 1f,
1f, 1f
};
效果如下:
我们看下贴图的原始文件
你会发现截屏中的图片y轴是颠倒的,其实这是android图像坐标系统与Opengl es 坐标系统不一致导致的。最简单的修正办法将原始图片用工具翻转过来,这样会比用程序翻转节省很多性能,资源是宝贵的。
三角形纹理映射,只要按照我们的映射规则,便可以顺利完成映射。
float texCoords[] = new float[] {
0.0f, 0.0f,
1.0f, 0.0f,
0.5f, 1.0f,
};
效果:
看到这里应该知道纹理坐标数组规则定义的意义了吧。
平铺与箔拉
我们的纹理坐标系统在两个轴上都是从0.0 到 1.0,如果设置超出此范围的值会怎么样?根据视图的设置方式有两种选择。
平铺(也叫重复)
一种选择是平铺纹理。按OpenGL的术语,也叫“重复”。如果我们将第一个纹理坐标数组的所有1.0改为2.0:
static const GLfloat texCoords[] = {
0.0, 2.0,
2.0, 2.0,
0.0, 0.0,
2.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_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
uv纹理坐标设定与贴图规则的更多相关文章
- OSG学习:计算纹理坐标
在很多时候,直接指定纹理坐标是非常不方便的,如曲面纹理坐标,只有少数的曲面(如圆锥.圆柱等)可以在不产生扭曲的情况下映射到平面上,其他的曲面在映射到表面时都会产生一定程度的扭曲.一般而言,曲面表面的曲 ...
- OpenGL的glTexCoord2f纹理坐标配置
纹理坐标配置函数,先看定义: void glTexCoord2f (GLfloat s, GLfloat t); 1.glTexCoord2f()函数 有两个参数:GLfloat s, GLfloat ...
- WPF 3D: MeshGeometry3D纹理坐标的正确定义
原文 WPF 3D: MeshGeometry3D纹理坐标的正确定义 为了使基于2D的纹理显示在3D对象中,我们必须定义3D Mesh对象的纹理贴图坐标.在WPF中,此项功能则通过MeshGeomet ...
- UV纹理+修改器:VertexWeightEdit+修改器:Mask遮罩
UV纹理+修改器: VertexWeightEdit+修改器: Mask遮罩 基本流程, 如下图,准备地图一份, 黑白色即可. 纹理使用颜色绘制权重. 白色为1, 黑色为0. 新增球体, 细分多次, ...
- OpenGL超级宝典总结(二)2D/3D笛卡尔坐标、坐标裁剪、纹理坐标、MVP转换等概念
如果你想把图形渲染在正确的位置上,那么坐标的设置就很重要了.在OpenGL中,与坐标相关的主要有笛卡尔坐标.坐标裁剪.纹理坐标.MVP(Model View Projection)转换. 1.笛卡尔坐 ...
- OpenMesh 读写网格控制(读取写入纹理坐标,法向等)
OpenMesh读取网格默认是不自动读取obj网格中的法向,纹理坐标等信息的,写入网格同样也是.所以要读取(或写入)这些信息需要修改默认的选项. 先看一下其读写网格的函数 template<cl ...
- osg使用shader动态修改纹理坐标
#include <osg/Node> #include <osg/Geometry> #include <osg/Notify> #include <osg ...
- OSG绘制金字塔geode+动态纹理坐标
osg::Node* createPyramidModel() { // create the root node which will hold the model. osg::Group* roo ...
- Unity Shader 自定义纹理坐标变量写法
Properties { _R(,)) = 1.0 _ColorTex("ColorTex (RGB)", 2D) = "red" {} struct Inpu ...
随机推荐
- 在where条件中使用CASE WHEN 语句
CREATE TABLE TB_Test_Report ( id int identity, stateid int, userid int, username ) ) go ,,'a') ,,'b' ...
- 第九十七天请假 PHP TP框架 MVC模式
MVC : M->Model 模型(数据层) V->View 视图(视图层) C->Controller 控制器(逻辑层) M : 操作数据(连接数据 ...
- Explode TArray
function Explode(const Separator, S: string; Limit: Integer = 0): TArray;var SepLen : Integer; F, P ...
- exports 和 module.exports 的区别
https://cnodejs.org/topic/5231a630101e574521e45ef8 //一句话总结:exports是对module.exports的引用,require()返回的是 ...
- VC++ 浅谈VS2010中CMFCToolBar的用法
本文将给大家介绍Visual Studio 2010中CMFCToolBar的用法,CMFCToolBar可以让用户自定义工具栏图标,使用静态成员函数SetUserImages()将一个CMFCToo ...
- ViewPager + Fragment实现滑动标签页
http://blog.csdn.net/lizhenmingdirk/article/details/13631813; tab与frg的区别: http://www.cnblogs.com/tia ...
- SGU 311. Ice-cream Tycoon(线段树)
311. Ice-cream Tycoon Time limit per test: 0.5 second(s)Memory limit: 65536 kilobytes input: standar ...
- 使用rownum对oracle分页
以Student表为例进行分页 建表及插入 -- 有表结构如下 create table STUDENT ( sno INTEGER, sname ), sage INTEGER ); -- 插入数据 ...
- C#WebClient常见用法
System.Net.WebClient.DownloadFile(Uri address, String fileName) namespace:System.Net 参数: address:The ...
- 选择合适的String拼接方法(这篇博客是我抄的)
package com.test; public class FreeFile { public static void main(String[] args) { // 加号拼接 String st ...