原文链接: http://student.csdn.net/space.php?uid=46868&do=blog&id=18200
关于iPhone的 OpenGL ES是建立在Xcode下,苹果推出的sdk版本中包含这个模板。我们要做的的就是帮助您建立这个模板,并在真正需要的地方方便快捷的添加有用的代码。这就是我们今天要做的。
打开 XCode并创建一个新的工程。选择”OpenGL ES Application”(图1),并且保存工程在你经常使用的位置。
图1
好吧,我要承认一点,你之前可能快速浏览过模板,或者看过模板的运行程序。我们要做的就是删除自旋的彩色立方体的代码,并添加用深度缓冲来转换视图(让它看起来更象是一个真的3d)。这将为我们的教程提供一个空间。
在3d空间里的2d。
象这个苹果的模板一样,大多数的OpenGL教程都是从忽略深度(缓冲)开始,通常使用2点的坐标系统(x,y),而不是更为标准的3点的坐标系(x,y,z)。你可能已经注意到了,苹果模板里的立方体的顶点只使用了(x,y)的坐标,这是因为他们没有使用深度。
这就是所谓的正投影。本教程系列的目的就是让你掌握3d,我将不会在正投影做重复介绍;当然,以后也许会。但现在,我们把精力保持在3d上。
启用深度缓冲
第一件事我们需要启动深度缓冲。苹果的例子中,正方形只是一个2d的物体,所以实际上不需要深度缓冲。我们需要深度所以我们启用它。苹果热心的提供了关于设置深度缓冲的代码,所以我们只需要利用它。
打开 EAGLView.m在编辑区,看下面这行代码:
复制代码
- #define USE_DEPTH_BUFFER 0
|
不用说,将0修改为1。这将打开视窗里的设置区域并创建深度缓冲。这个代码包含在createFrameBuffer这个函数中。此刻不要对这个函数担心太多。这是苹果写的,必然支持这样的写法。
现在,我们需要在OpenGL内部启用深度缓冲。要做到这一点,我们需要创建一个新的函数,这个函数将被启用在我们视窗工作的时候。我们开始创建一个新的函数,叫 setupView 并且将下列的代码添加到这个新的函数里。
复制代码
- - (void)setupView {
- const GLfloat zNear = 0.1, zFar = 1000.0, fieldOfView = 60.0;
- GLfloat size;
- glEnable(GL_DEPTH_TEST);
- glMatrixMode(GL_PROJECTION);
- size = zNear * tanf(DEGREES_TO_RADIANS(fieldOfView) / 2.0);
- // This give us the size of the iPhone display
- // 这个给我们在iphone中显示的尺寸大小
- CGRect rect = self.bounds;
- glFrustumf(-size, size, -size / (rect.size.width / rect.size.height), size / (rect.size.width / rect.size.height), zNear, zFar);
- glViewport(0, 0, rect.size.width, rect.size.height);
- glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
- }
|
所有的这些代码的作用是设置OpenGl的参数,它将操作于创建一个视窗端口正在被映射到我们显示的实际大小。就象我说的一样,我将详细谈这点,但现在,只需要注意以下内容:
glEnable(GL_DEPTH_TEST);
这将在OpenGL中启用深度测试。
你必须记得,一旦你在OpenGL中将某些事物改为“开启”,你必须在不要使用它的时候关闭它。我们开启了深度测试并且不再关闭它,它可以在视窗的这里设置。
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 我们要做的就是
用默认的颜色去清除屏幕。在OpenGL ES中使用的所有颜色都必须是是RGBA值,而不是在OpenGL中的RGB值,所以当我们清除屏幕,OpenGL ES就知道我们要用黑色来清除屏幕。它将继续使用这个颜色直到我们改变它。
这个颜色的值范围,浮点是0-1,无符号数是0-255。这个颜色的值越高,这个颜色的强度也越高。
Ok,返回文件的开头,到我们刚才修改的 #define的地方。我们需要在这里定义一个宏,这个宏将在 setupView函数中使用到。
#define USE_DEPTH_BUFFER 1
#define DEGREES_TO_RADIANS(__ANGLE) ((__ANGLE) / 180.0 * M_PI)
Draw View -绘制函数 现在,到下面的 drawView 函数。在我们的教程中,发生的所有事都在这里。你可以在这里看到,苹果给了我们一个事实上的指针,这正是我们需要做的工作。
首先,删除一切这个函数中的代码,并用我们下面的代码去填充它。
- (void)drawView {
[EAGLContext setCurrentContext:context];
glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
glViewport(0, 0, backingWidth, backingHeight);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER_OES];
}
上面的头三行代码,就是设置我们的绘制空间。后面两行代码,将我们的绘制空间与屏幕显示空间互换。如果你之前做过动画或游戏的编程,你会知道,这就是所谓的“双缓冲”。
对于那些不知道的朋友呢,我们再解释一下,我们创建了两个缓冲界面,一个用于给用户显示,一个我们清除掉并且我们在它上面进行绘制。当我们完成绘制后,我们就翻转视窗,那么用户就看到了新的视窗。为什么我们要搞的这么麻烦呢?这是为了要动画流畅。
此刻,我们不要为了显示添加任何代码了,我们仍然要做一些设置工作。
首先,在dealloc函数之前,插入以下的代码:
- (void)checkGLError:(BOOL)visibleCheck {
GLenum error = glGetError();
switch (error) {
case GL_INVALID_ENUM:
NSLog(@"GL Error: Enum argument is out of range");
break;
case GL_INVALID_VALUE:
NSLog(@"GL Error: Numeric value is out of range");
break;
case GL_INVALID_OPERATION:
NSLog(@"GL Error: Operation illegal in current state");
break;
case GL_STACK_OVERFLOW:
NSLog(@"GL Error: Command would cause a stack overflow");
break;
case GL_STACK_UNDERFLOW:
NSLog(@"GL Error: Command would cause a stack underflow");
break;
case GL_OUT_OF_MEMORY:
NSLog(@"GL Error: Not enough memory to execute command");
break;
case GL_NO_ERROR:
if (visibleCheck) {
NSLog(@"No GL Error");
}
break;
default:
NSLog(@"Unknown GL Error");
break;
}
}
OpenGL 有一个错误检测的函数,叫做(glGetError()),但是这个函数返回的出错信息,我们要手动转换下,不然开发者将无法阅读。这个就是上面这个函数的作用。
这个bool参数“visibleCheck”只能在这,有时候你可以检测并且看到这个例子调用,并且这时候他们没有错误。
最后一件事,我们需要回到 EAGLView.m 文件中,进入initWithCoder函数,并且调用我们之前创建的”setupView”函数。接下来设置” animationInterval”的值,插入下列代码来调用setupView函数。
[self setupView];
需要注意下,我们当然可以将setupView函数代码直接写在initWithCoder函数中而不是创建一个新的函数,这样的方式通常仅仅适用于只调用一次的情况下。
好了,关掉EAGLView.m,看 EAGLView.h
EAGLView.h
幸运的是,我们不需要在这里做很多的工作。我们只需要创建两个函数的原型,代码如下:
- (void)setupView;
- (void)checkGLError:(BOOL)visibleCheck;
本教程结束。。。。
下一步:
如果你编译并且在模拟器中运行本例,你只会获得一个黑色的屏幕并且不会发生任何有趣的事。在下一个教程中,我们将开始在这个屏幕中绘制图元,图元是基本单元,如点,线,三角形。