美文网首页
OpenGL ES CameraPreview时正交矩阵的计算原

OpenGL ES CameraPreview时正交矩阵的计算原

作者: 土贝口小土孩 | 来源:发表于2019-06-12 10:07 被阅读0次

    转载请注明出处:https://www.jianshu.com/p/8049014b7952

    刚开始学习opengl时,对突然出现的这些坐标感到很无措。后来理解了才知道是顶点坐标以及纹理坐标。
    但是做Camera预览时,又遇到了无法理解的透视矩阵参数设置,网上搜了半天也没有人讲明白,最终和别的朋友研究了好几天,才最终搞透其计算原理,在此分享一下。

    图形顶点和纹理的坐标展示:

    1.png

    顶点的坐标数据如上面截图所示,这两组数据该这样理解,首先确定4个图形顶点的坐标(第一组数据),这是一个正方形,其坐标系为openGL坐标系,以中心点为原点,见下左图;第二组数据右边的一个坐标系是纹理坐标系,已左上角为原点(android中应该做了转换,原本的opengl中是以左下角为原点的)。

    纹理就是贴图,就是将纹理矩形中按照图中标记的顺序(也就是纹理坐标数组的顺序),挨个纹理顶点都对应到图形顶点绘制的矩形中,这样就完成了把纹理完全贴到了opengl绘制的图形中。

    因为手机设备的宽高一般是不相等的(或者说显示区域不相等),所以几乎没有显示区域是一个规则的矩形,这样就需要进行矩阵变换,在不产生拉伸的情况下将图片绘制到屏幕中。这个矩阵就需要下面的逻辑来获取出来。

    3.png

    仅讨论竖屏情景(w<h),在Camera preview时,会计算一个映射矩阵,如上面的函数,imgWidth和imgHeight代表Camera中preview到的图片的大小,如720x1280(一般Camera中传上来的图片都是w>h的,如1280x720,这里为了与屏幕的方向保持一致,所以将w和h换了下位置);viewWidth和viewHeight代表的是手机中显示区域的大小。

    将这两个矩形的高归一,两个矩形的大小就变为了:(sWhImg,1)和(sWhView,1),这里的归一表示将两个矩形等比缩小,将纵坐标变为1。

    第一种情况,当sWhImg > sWhView****时

    这种情况表示图片较大,显示区域较小,图片如果要全部显示到屏幕上,需要在x轴上做收缩动作,示意图如下,左侧中绿色代表屏幕显示区域,紫色代表图片,右侧的蓝色正方形为纹理大小。

    4.png

    Matrix.orthoM函数表示正交投影,表示的是一个物体的左右上下前后在屏幕上展现的部分,因为这里是二维的,所有就光考虑左右上下(x轴和y轴)。y轴方向需要完全展示。X轴方向需要展示的部分是这样计算的:在上文中,我们已经得知纹理的宽高均为1,图片要拉伸并贴到整个纹理中,在高均为1的情况下,宽要从sWhImg 变为1,当图片的宽为sWhImg时,屏幕需要显示的部分为sWhView,那当图片的宽被拉伸到1的情况下,屏幕需要显示的部分也要进行等比拉伸(scale),宽度为x,x的值是多少呢?

    1560304825(1).png

    所以最终我们的正交矩阵,左右之间的范围为(-sWhView/sWhImg,sWhView/sWhImg),上下的范围为(-1,1)

    第二种情况,当sWhView > sWhImg****时

    这种情况下,说明如果将高(h)归一化了之后,图片的大小不足以在显示区域内展示,如果要展示的话,必然会发生图片的拉伸。这种情况下,需要将宽(w)归一,当w为1时,h则分别变为了1/sWhView和1/sWhImg,因为sWhView比较大,那么1/sWhView必然比较小,这样图片在x轴上跟显示区域一样大,在Y轴上比显示区域要大,这样就跟第一种情况下类似,在Y轴方向上,截取图片的一部分显示在屏幕中,这样就不会产生拉伸。如下图所示。

    5.jpg

    图片的宽为1,对应到纹理中,宽不变,高从1/sWhImg变为了1,被拉伸了(拉伸和压缩统一被称为拉伸,单词为stretch)。屏幕需要显示的纹理同样发生了拉伸,变为了y,y的计算方式与上面相同

    1560304908(1).jpg

    正交矩阵中,左右的可见范围为(-1,1),上下的可见范围为(-sWhImg/sWhView, sWhImg/sWhView)。

    相关文章

      网友评论

          本文标题:OpenGL ES CameraPreview时正交矩阵的计算原

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