现在的位置: 首页 > 综合 > 正文

OpenGL ES之glFrustumf设置投影视角详解 OpenGL ES之glFrustum函数

2014年01月24日 ⁄ 综合 ⁄ 共 2185字 ⁄ 字号 评论关闭

-(void)setClipping
{

float aspectRatio;
const float zNear = 0.1; //1
const float zFar = 1000; //2
const float fieldOfView = 60.0; //3
GLfloat size;
CGRect frame = [[UIScreen mainScreen] bounds]; //4

aspectRatio=(float)frame.size.width/(float)frame.size.height; //5


//Set the OpenGL projection matrix.

glMatrixMode(GL_PROJECTION); //6
glLoadIdentity();
size = zNear * tanf(GLKMathDegreesToRadians (fieldOfView) / 2.0); //7
glFrustumf(-size, size, -size /aspectRatio, size /aspectRatio, zNear, zFar); //8
glViewport(0, 0, frame.size.width, frame.size.height); //9
//Make the OpenGL ModelView matrix the default.
glMatrixMode(GL_MODELVIEW); //10

}

glFrustumf中文API文档参考OpenGL ES之glFrustum函数

        第1、2行指定了近裁面和远裁面的距离。这两个值的意思是,任何远于1000或近于0.1的对象都将被过滤掉。你可能会问一千什么?就是一千!单位看你自己设想。你可以把它想象成光年,或者英尺,都无所谓。不信的话你自己随便设置一下试试。

        第3行设定视角为60度。

        第4行获取屏幕的尺寸大小。

        第5行根据屏幕的尺寸计算最终屏幕的纵横比例。它的高度和宽度的值决定了相对高度的视域(FOV),如果将其翻转的话,将变成相对于宽度的视域。如果我们要设置一个60度视域,就像一个宽角度镜头,那么它将基于窗口的高度而非宽度。当渲染到一个非正方形的屏幕上时尤为重要。

        由于glfrustumf影响的是投影矩阵,所以我们需要确认将当前矩阵从模型视图矩阵设置成投影矩阵。第6行就是要做这个滴。

第7行计算锥形视角的左右上下的限制值。你可以把它想象成3D空间中的虚拟窗口。原点在屏幕中央,所以x轴和y轴的值都是从-size到+size。这就是为什么会有GLKMathDegreesToRadians (fieldOfView) / 2.0将窗口分为两部分——视角的角度是从-30度到+30度的。乘以zNear就可以计算出近剪裁面在坐标轴各个方向上的大小。这就是正切函数的作用了,眼睛在z轴上,到原点的距离是zNear,视域被z轴分为上下两部分各为30度,所以就可以明白size就是近剪裁面在x和y轴上的长度。

    第8行将计算的左右上下以及近剪裁面和远剪裁面的值传进glFrustumf函数。这里下边和上边的值都除以了aspectRatio(屏幕宽高比),而左右边没有,这是因为调用glLoadIdentity函数标准化投影矩阵的时候将所有的顶点数据都标准化到了-1~1的范围内,屏幕宽度和高度实际大小不一样,但都被标准化成了1。所以如果左右值和上下值一样的话得到的就是一个宽度比较大而高度比较小的长方形,而不是预期的正方形,所以左右值不变,而上下值要除以宽高比。

        第9行用来设置视口,一般为屏幕的大小。不过你可以根据需要来设置坐标和宽度、高度。

        第10行为将当前的矩阵从投影矩阵设置为模型视图矩阵。

     

        由于设置投影视角的方法基本上是固定的,只不过需要调整一下近剪裁面和远剪裁面以及视角的大小,所以可以将setClipping函数进一步封装为:

-(void)setClippingWithNear:(const float)zNear far:(const float)zFar angle:(const float) fieldOfView
{

float aspectRatio;
GLfloat size;
CGRect frame = [[UIScreen mainScreen] bounds]; //4

aspectRatio=(float)frame.size.width/(float)frame.size.height; //5


//Set the OpenGL projection matrix.

glMatrixMode(GL_PROJECTION); //6
glLoadIdentity();
size = zNear * tanf(GLKMathDegreesToRadians (fieldOfView) / 2.0); //7
glFrustumf(-size, size, -size /aspectRatio, size /aspectRatio, zNear, zFar); //8
glViewport(0, 0, frame.size.width, frame.size.height); //9
//Make the OpenGL ModelView matrix the default.
glMatrixMode(GL_MODELVIEW); //10

}

抱歉!评论已关闭.