OpenGL顶点坐标与纹理坐标
引言
这里先给自己打个广告,前些天闲来无事,在GitHub Pages上搭建了个博客,基于Jekyll模板搭建的,参考了码志作者的博客模板,在此表示感谢。同时欢迎大家来我的博客捧场。
顶点坐标系
这里不说Android的坐标系,只分析OpenGL的坐标系,而且本文只分析二维坐标系,三维坐标系不在分析范围。
在分析OpenGL顶点坐标系之前,我们先来看一张图。
OpenGL_ coordinate.jpg图中是一个手机的截屏,屏幕中央有一张图片,图片的中间是可见区域,四周的半透明区域为非可见区域,可见区域为控件GLSurfaceView。
坐标系说明
图中标出了四个坐标系。红色坐标系和白色坐标系不用说大家应该都知道。分别是屏幕坐标系,和GLSurfaceView控件的坐标系。坐标原点都是左上角,向右为x正轴,向下为y正轴。剩下的紫色坐标系,大家应该能够猜到,它就是OpenGL的世界坐标系,OpenGL的定点坐标就是以该坐标系作为参考。另外一个橙色坐标系待会再说明他是做什么用的。
OpenGL世界坐标系以绘图区域的中心点为坐标原点,向右为x正轴,向上为y正轴。另外,OpenGL世界坐标系中的点是用(-1,1)之间的浮点数来表示的,即绘图区域边缘四个顶点的坐标,从左上角顺时针依次是,(-1,1)、(1,1)、(1,-1)、(-1,-1),如图所示。
OpenGL相关函数说明
图中的绘图区域比GLSurfaceView控件本身大,这个是怎么设置的呢?我们来看下面这个函数:
GLES20.glViewport(int x, int y, int width, int height);
该方法用来设置GLSurfaceView控件的绘图区域,有四个参数,前两个参数用来确定绘图区域与控件边缘的偏移,后两个参数确定绘图区域的宽和高。
既然前两个参数是一个坐标点,它就应该有一个参考坐标系,上面我们在分析图中的坐标系的时候,还剩了一个橙色坐标系没有分析,它就是用来确定绘图区域偏移的坐标系。
该坐标系以GLSurfaceView控件左下角为坐标原点,向右为x正轴,向上为y正轴。所以,确定该绘图区域的函数调用参数应该是这样的:
GLES20.glViewport(-270, -270, 810, 1440);
实际应用
在实际应用中,通常是用float一维数组来给定绘制顶点组合,如下:
//定义顶点坐标
float[] coordinate = new float[]{
-1.0f, -1.0f, //左下角坐标
1.0f, -1.0f, //右下角坐标
-1.0f, 1.0f, //左上角坐标
1.0f, 1.0f //右上角坐标
}
上面的数组是android中进行OpenGL绘制时经常用到的顶点坐标数组,该数组定义了四个顶点,对应于glViewport确定的绘制区域的四个角。
纹理坐标系
先简单描述一个场景,在绘图区域中贴一张图片。首先,顶点坐标是确定的,如上文中提到的coordinate数组。然后就是纹理坐标了,其实纹理坐标很好理解,它的坐标系以纹理左下角为坐标原点,向右为x正轴方向,向上为y轴正轴方向。他的总长度是1。即纹理图片的四个角的坐标分别是:(0,0)
、(1,0)
、(0,1)
、(1,1)
,分别对应左下、右下、左上、右上四个顶点。
如果使用整张纹理素材进行贴图,则传如下坐标数组:
float[] TEXTURE_NO_ROTATION[] = {
0.0f, 1.0f,//左上角
1.0f, 1.0f,//右上角
0.0f, 0.0f,//左下角
1.0f, 0.0f,//右下角
};
如果只想取纹理的上半部分,则传入坐标数组如下:
float[] TEXTURE_NO_ROTATION[] = {
0.0f, 0.5f,//左上角
1.0f, 0.5f,//右上角
0.0f, 0.0f,//左下角
1.0f, 0.0f,//右下角
};
大家会发现,取纹理上半部分,传的确是下半部分的坐标,同时,纹理坐标点与顶点坐标点也是上下颠倒的。这个具体逻辑不是很清楚,曾经在一个帖子中看到一个大神解释说是因为android读取图片的方式不同导致的。这种读取方式使得一张图片读取到内存中,会出现上下翻转,如果真的是这样,你在处理纹理坐标时,先在大脑中将图片上下翻转一次,在按正常逻辑来选取纹理区域,应该就会清晰多了。
作者也是初学OpenGL编程,对OpenGL坐标系理解的也不是很深刻,在学习与实践中,了解了一些,记录了下来,一是方便以后回顾,二是给一些对OpenGL坐标系概念模糊的同学一点点指引。
以上内容难免会有错误,如发现错误还请留言指正。欢迎与大家共同探讨,共同进步。