iOS开发学习OpenGL ES系列 -- 摄像机

在讲摄像机之前先介绍一下3D渲染中的MVP:分别是模型矩阵(model)、观察矩阵(view)、投影矩阵(Projection)。其中模型矩阵操作的是单个3D模型,可以进行平移、缩放、旋转或者组合变换。观察矩阵可以理解为3D世界中的摄像机,当摄像机的位置发生改变,拍摄的角度不一样,呈现在屏幕上的效果自然会有变化。这一操作会改变物体的顶点位置。投影矩阵在上一篇讲过,分为正射投影和透视投影,透视投影有远小近大的效果,更为真实。这里大概了解一下MVP,接下来修改代码正式步入3D世界,这里引入了三个矩阵,所以顶点着色器中需要添加接受属性:

attribute vec4 position;
attribute vec4 color;

varying vec4 fColor;

uniform mat4 pMatrix;
uniform mat4 vMatrix;
uniform mat4 mMatrix;

void main(void) {
    fColor = color;
    mat4 mvp = pMatrix * vMatrix * mMatrix;
    gl_Position = mvp * position;
}

mMatrix、vMatrix、pMatrix分别是模型矩阵、观察矩阵、投影矩阵。这里将mvp直接相乘,结果再与position相乘。注意相乘的顺序先进行模型矩阵变换,再是观察矩阵,最后是投影矩阵变换。

相应的工程中添加三个属性:

GLKMatrix4 projectionMatrix; // 投影矩阵
GLKMatrix4 modelMatrix; // 模型矩阵
GLKMatrix4 cameraMatrix; // 观察矩阵

在viewDidLoad中进行初始化:

// projectionMatrix 投影矩阵。 呈现更为真实的3D效果这里设置投影矩阵为透视投影。
 float aspect = self.view.frame.size.width / self.view.frame.size.height;
 float fovyRadians =GLKMathDegreesToRadians(90);
 projectionMatrix = GLKMatrix4MakePerspective(fovyRadians, aspect, 0.0, 100.0);
 
 // modelMatrix 模型矩阵 初始化模型矩阵为单位矩阵
 modelMatrix = GLKMatrix4Identity;
 
 // cameraMatrix 观察矩阵
 cameraMatrix = GLKMatrix4MakeLookAt(0, 0, 2, 0, 0, 0, 0, 1, 0);

GLKit提供了创建观察矩阵的函数:
GLKMatrix4MakeLookAt(float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ)

参数float eyeX, float eyeY, float eyeZ定义摄像机的位置。float centerX, float centerY, float centerZ摄像机看向的点。光是这样还不行,相机还可以自转360.所以还需要float upX, float upY, float upZ三个参数确定相机向上的朝向。我们可以设置这9个参数以控制摄像机从不同的角度观察物体。

目前创建的观察矩阵是固定的不动的,我们把projectionMatrix、modelMatrix和cameraMatrix赋值到Vertex Shader:

GLuint modeLocation = glGetUniformLocation(program, "mMatrix");
glUniformMatrix4fv(modeLocation, 1, 0, modelMatrix.m);
    
GLuint projectionLocation = glGetUniformLocation(program, "pMatrix");
glUniformMatrix4fv(projectionLocation, 1, 0, projectionMatrix.m);
    
GLuint cameraLocation = glGetUniformLocation(program, "vMatrix");
glUniformMatrix4fv(cameraLocation, 1, 0, cameraMatrix.m);

运行效果:

这跟前面的透视投影没什么区别。上一篇中视点在(0,0,0)位置,可视区域在Z轴负方向,成像在(0,0,0)和可视区域之间。而这里设置相机在(0,0,2)位置,朝向(0,0,0)也就是Z的负方向,其余设置一样。所以这里创建观察矩阵其实就是代替了上一篇中的视点,所以展示效果是一样的。只不过前面的默认视点在(0,0,0)位置固定不动,而这里我们可以通过修改GLKMatrix4MakeLookAt的参数来控制相机位置与方向,以展示出物体不同角度的图像。下面我们重新定义观察矩阵:

// cameraMatrix = GLKMatrix4MakeLookAt(0, 0, 2, 0, 0, 0, 0, 1, 0);
cameraMatrix = GLKMatrix4MakeLookAt(0, 1, 2, 0, 0, 0, 0, 1, 0);

把相机的y轴改为1,看一下效果:

改变了相机的y值,朝向和向上不变,很明显有俯视向下看的感觉。

// cameraMatrix = GLKMatrix4MakeLookAt(0, 1, 2, 0, 0, 0, 0, 1, 0);
cameraMatrix = GLKMatrix4MakeLookAt(0, sin(change), 3, 0, 0, 0, 0, 1, 0);

这次让相机的y在[-1,1]之间变化,修改z为3,并去掉旋转,看下效果:

首先看到的图像肯定是变小了,这是因为相机的z修改为3,把距离拉远了1个单位。再观察感觉矩形是在绕着X轴自转,其实并不这样,因为我们改变相机的y是在[-1,1]之间,并且z是固定的,所以只能是直线性的上下移动,也就造成了这种最终效果。

这里还可以修改GLKMatrix4MakeLookAt的float upX, float upY, float upZ来控制相机的向上朝向。

// cameraMatrix = GLKMatrix4MakeLookAt(0, sin(change), 3, 0, 0, 0, 0, 1, 0);
cameraMatrix = GLKMatrix4MakeLookAt(0, sin(change), 3, 0, 0, 0, 1, 0, 0);

这里设置相机朝向为x正方向,效果图就不上传了,有兴趣的可以自己尝试修改这些参数来控制相机。当然需要注意的是物体的可视区域与相机位置。否则你有可能什么都看不到。

关于OpenGL ES的相机就说到这里了,如果文中有错误或者有补充的知识点欢迎留言讨论,谢谢!

本例源码:LearningOpenGL ES GitHub

如果修改相机的向上朝向为X正方向的话,屏幕上的 图像会逆时针旋转90度,而且再不是上下摆动,变成了左右摆动。这是因为相机向上朝向由Y的正方向变为X的正方向,相机旋转了90度,原来的右上角为绿色,旋转之后变为蓝色。原来是Y轴朝上,相机是上下滑动变为现在的X轴朝上而左右滑动。

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

推荐阅读更多精彩内容