opengles-坐标系和矩阵

坐标系和矩阵是opengl的基础也是难点,本文总结了opengl的各种坐标系和矩阵,如果有错误欢迎指正。

1.什么是opengl和opengl es

OpenGL(全写Open Graphics Library)是指定义了一个跨编程语言、跨平台的编程接口规格的专业的图形程序接口。OpenGL是个与硬件无关的软件接口,可以在不同的平台如Windows 95、Windows NT、Unix、Linux、MacOS、OS/2之间进行移植。因此,支持OpenGL的软件具有很好的移植性,可以获得非常广泛的应用。

Opengl2.0开始支持glsl(OpenGL Shading Language),opengl1.x是固定渲染管线的已经被淘汰无需考虑。Opengles是OpenGL裁剪定制而来的,专为手机,游戏机等嵌入式设备而设计,在安卓设备上的opengl就是opengles。

安卓使用GLSurfaceView封装和简化opengl的开发,它帮助我们建立单独的opengl线程,并且支持连续或者按需渲染,它使用EGL来处理屏幕设置,Egl是OpenGL与底层窗口系统之间的接口。

  • It provides a dedicated render thread for OpenGL so that the main thread is not stalled.
  • It supports continuous or on-demand rendering.
  • It takes care of the screen setup for you using EGL, the interface between OpenGL and the underlying window system.

2.opengl的各种坐标系和矩阵

坐标系

  1. 安卓设备坐标系

    屏幕左上点为原点,x轴向右,y轴向下,跟随屏幕方向变化而变化。

  2. 纹理坐标系 uv coordinates

    2d纹理坐标系也就是UV坐标系,水平方向是U,垂直方向是V,通过这个平面的,二维的UV坐标系。我们可以定位图象上的任意一个象素。左下角为原点,U轴向右,V轴向上,范围[0,1]。

  3. 模型坐标系 object coordinates

    归一化的右手坐标系,以模型内某一点为原点建立的坐标系,其它模型内的点的位置可以用相对于模型内的原点来表示的坐标系,该坐标系仅在模型内有效。

  4. 世界坐标系 world coordinates

    右手坐标系,屏幕中心点位原点x轴向右,y轴向上,z轴向屏幕外。可以理解为无限大的坐标系,用来描述物体或者光源的位置,跟随屏幕方向变化而变化。。

  5. 视点坐标系 eye coordinates

    以视点(相机)为原点,以视线的<u>负方向为Z轴正方向</u>的坐标系,注意是相机看向的其实是-z轴。

  6. 齐次坐标系 clip coordinates

    齐次坐标就是用N+1维来代表N维坐标,在opengl中以第四个值w表示,齐次坐标系表示同一个点并不唯一[8,4,2]、[4,2,1]表示的都是二维点[4,2]。

    齐次坐标系可以使用(x,y,z,w)表示一个点,也可以表示向量。当w==1时表示点(仅限eye坐标系及之前的坐标系),当w==0时表示向量。

    齐次坐标系使得点和向量可以用统一的vec4来表示。

  7. opengl设备标准化坐标系 ndc coordinates

    Normalized device coordinates(ndc坐标系),采用的是左手三维坐标系(也就是z轴其实是指向屏幕里的),三个坐标轴都是[-1,1],是opengl服务端唯一理解的内部坐标系,跟随屏幕方向变化而变化。

    opengl是server-client模式,应用程序是客户端,图形硬件厂商提供的OpenGL实现是服务器。而client也就是应用程序内部采用的都是右手坐标系,只是是在使用Ortho或者Perspective来生成投影矩阵的时候,近远视点分别加了负号做了转换。

    glViewport(x,y,width,height)用来函数指明标准坐标系和屏幕坐标映射计算关系,在安卓中一般用在onSurfaceChanged的回调里。一般这个计算不需要我们来做,此处只是作为补充说明。

    标准坐标转屏幕坐标公式

矩阵

opengl的矩阵是4*4的矩阵,可以用16个元素的数组表示,opengl采用column-major order(列主序矩阵),也就是一列一列从数组读取数据。由于列主序的存在,导致4×4矩阵作用于vector4(例如shader中的位置、颜色等,实际为4×1矩阵),所以vector4只能左乘变换矩阵(线性代数矩阵乘法规定,它只有在第一个矩阵的列数(column)和第二个矩阵的行数(row)相同时才有意义)。

列主序矩阵
  1. modelMatrix模型矩阵:

    模型矩阵可以包括对模型的缩放、旋转、平移操作。先缩放再旋转再平移,由于矩阵乘法不满足交换律,顺序不能变化。例如先向左转再走两步,和先走两步再像左转是完全不一样的结果。

    <u>如果要改变顺序一定要清楚其带来的影响</u>

    scaleMatrix在矩阵中的表示:
    缩放变换矩阵
    rotationMatrix矩阵中比较复杂,暂时不列出
    translateMatrix矩阵变换
    平移变换矩阵表示

    综上,最终的modelMatrix = TranslationMatrix * RotationMatrix * ScaleMatrix,从右向左乘,先变换的最先乘。

    通过左乘模型矩阵可以将局部物体坐标系坐标转化为世界坐标系的坐标

    vec4 worldCoordinateVector = modelMatrix * modelCoordinateVector;

  2. viewMatrix视图矩阵

    setLookAtM(float[] rm, int rmOffset, float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ)

    用来生成视图矩阵,主要规定视点位置、焦点位置、相机y轴up朝向。

    世界坐标系的坐标值左乘视图矩阵可以将世界坐标系转化为视点相机坐标系。

    vec4 cameraCoordinateVector = viewMatrix * worldCoordinateVector;

    理论上viewMatrix和modelMatrix是可以相互替代的,如变相机位置向左移动5厘米和改变物体位置像右移动5厘米都可以实现相同的结果,但存在多个物体的话显然移动物体合适。

  3. projectMatrix投影矩阵

    投影矩阵并不是用来计算射线碰撞的,也不是所谓的将3d物体投射到2d平面上。投影矩阵真正作用来是把相机坐映射为标准的[-1,1]的齐次坐标,也就是带w值的标准设备坐标系,并且可以clip视锥之内的点,投影内的点记为vertex(clip)。

    opengl负责将齐次坐标系转化为标准坐标,也就是PerspectiveDivide(透视除)由opengl内部调用,无需我们关心。透视除其实就是将x/y/z值分别除以w来得到屏幕标准坐标。

    vertex(ndc) = PerspectiveDivide(vertext(clip));

    一旦拿到ndc坐标,opengl会使用公式将它映射到viewport屏幕坐标,屏幕上就显示了当前点。

    关于w

    w主要是用在透视投影中的,在视点坐标系下其值一般初始化为1,而经过透视矩阵变换之后,其中会变为-z(注意负号,因为需要转为左手坐标系),经过正交投影变换后其值仍是原值,即1。

    所谓透视矩阵,就是通过各个分量divide by w来实现近大远小的透视效果的。w虽然对正交矩阵没有什么用,但是统一了正交和透视矩阵的处理,避免了直接divide z。

    正交投影

    orthoM(float[] m, int mOffset, float left, float right, float bottom, float top, float near, float far)

    用来生成正交投影,near和far分别表示近视点和远视点的距离需要为正,正交矩阵视锥是一长方体,物体没有近大远小特性,同一个物体无论远近都是一样大小的,这看起来并不自然,但是却可以保证物体无论远近都保持一致的外观,某些游戏画面就需要这个特点。

    正交矩阵应该考虑品屏幕比例,不然会导致横竖屏切换后画面变形。

    //横屏,例如800*600,横屏width是800,竖屏width为600
    float aspectRatio = (float) width / (float) height;
    orthoM(projectionMatrix, 0, -aspectRatio, aspectRatio, -1, 1, -1, 1);
    //竖屏
    orthoM(projectionMatrix, 0, -aspectRatio, aspectRatio, -1, 1, -1, 1);
    

    安卓没有任何配置的情况下,默认相机处于世界坐标系(0,0)点,默认使用的是[-1,1]的立方体正交投影,投影矩阵内的所有点在屏幕上都可见,故可以看到(0,0,0)点的物体,即使默认相机在(0,0,0)点也可以看到。

    透视投影

    perspectiveM(float[] m, float yFovInDegrees, float aspect, float n, float f)

    用来定义透视矩阵

    透视矩阵也应该考虑品屏幕比例,不然会导致横竖屏切换后画面变形,同样near和far需要为正数。

    //横屏,例如800*600,横屏width是800,竖屏width为600
    perspectiveM(projectionMatrix, 45, (float) width / (float) height, 1f, 10f);
    

    投影矩阵小结:

    1.无论是正交还是透视投影,投影矩阵作用于EyeVertex点后,会将该点转化为齐次式表示的标准化设备坐标。使用正交投影的的w并没有用,只是为了保持和透视投影处理的一致性,w值经过左乘之后没有任何变化。

    2.透视投影的w经过矩阵左乘之后会变成-z。

    3.正交投影和透视投影作用后的x,y,z值不相同(表达式不同),具体表达式可以参考下方链接。

    矩阵左乘导致坐标系的转换过程

    关于投影矩阵的数学计算,请参考如下网站,讲的非常清晰,耐心看完一定会理解的。

    http://www.songho.ca/opengl/gl_projectionmatrix.html#perspective

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容