OpenGL顶点坐标与纹理坐标

作者: 化作春泥_ | 来源:发表于2017-07-18 09:52 被阅读702次

    引言

    这里先给自己打个广告,前些天闲来无事,在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坐标系概念模糊的同学一点点指引。

    以上内容难免会有错误,如发现错误还请留言指正。欢迎与大家共同探讨,共同进步。

    相关文章

      网友评论

      • 4a2fe695d88e:感谢作者的分享。
        以及弱弱的说一句,屏幕坐标系x轴的坐标应该是(1080,0)哈~

      本文标题:OpenGL顶点坐标与纹理坐标

      本文链接:https://www.haomeiwen.com/subject/dzuckxtx.html