西蒙iphone-OpenGL ES 教程 -01

 关于iPhone的 OpenGL ES是建立在Xcode下,苹果推出的sdk版本中包含这个模板。我们要做的的就是帮助您建立这个模板,并在真正需要的地方方便快捷的添加有用的代码。这就是我们今天要做的。

      打开 XCode并创建一个新的工程。选择”OpenGL ES Application”(图1),并且保存工程在你经常使用的位置。
西蒙iphone-OpenGL ES 教程 -01 - 勇者之尊 - 等待
                                                    图1
       好吧,我要承认一点,你之前可能快速浏览过模板,或者看过模板的运行程序。我们要做的就是删除自旋的彩色立方体的代码,并添加用深度缓冲来转换视图(让它看起来更象是一个真的3d)。这将为我们的教程提供一个空间。

在3d空间里的2d。

       象这个苹果的模板一样,大多数的OpenGL教程都是从忽略深度(缓冲)开始,通常使用2点的坐标系统(x,y),而不是更为标准的3点的坐标系(x,y,z)。你可能已经注意到了,苹果模板里的立方体的顶点只使用了(x,y)的坐标,这是因为他们没有使用深度。

       这就是所谓的正投影。本教程系列的目的就是让你掌握3d,我将不会在正投影做重复介绍;当然,以后也许会。但现在,我们把精力保持在3d上。

启用深度缓冲
第一件事我们需要启动深度缓冲。苹果的例子中,正方形只是一个2d的物体,所以实际上不需要深度缓冲。我们需要深度所以我们启用它。苹果热心的提供了关于设置深度缓冲的代码,所以我们只需要利用它。

打开 EAGLView.m在编辑区,看下面这行代码:
复制代码
  1. #define USE_DEPTH_BUFFER 0

         不用说,将0修改为1。这将打开视窗里的设置区域并创建深度缓冲。这个代码包含在createFrameBuffer这个函数中。此刻不要对这个函数担心太多。这是苹果写的,必然支持这样的写法。

        现在,我们需要在OpenGL内部启用深度缓冲。要做到这一点,我们需要创建一个新的函数,这个函数将被启用在我们视窗工作的时候。我们开始创建一个新的函数,叫 setupView 并且将下列的代码添加到这个新的函数里。

复制代码
  1. - (void)setupView {

  2.     const GLfloat zNear = 0.1, zFar = 1000.0, fieldOfView = 60.0;
  3.     GLfloat size;

  4.     glEnable(GL_DEPTH_TEST);
  5.     glMatrixMode(GL_PROJECTION);
  6.     size = zNear * tanf(DEGREES_TO_RADIANS(fieldOfView) / 2.0);

  7. // This give us the size of the iPhone display
  8. // 这个给我们在iphone中显示的尺寸大小
  9.     CGRect rect = self.bounds;
  10.     glFrustumf(-size, size, -size / (rect.size.width / rect.size.height), size / (rect.size.width / rect.size.height), zNear, zFar);
  11.     glViewport(0, 0, rect.size.width, rect.size.height);

  12.     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
  13. }

        所有的这些代码的作用是设置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;

     本教程结束。。。。
下一步:
      如果你编译并且在模拟器中运行本例,你只会获得一个黑色的屏幕并且不会发生任何有趣的事。在下一个教程中,我们将开始在这个屏幕中绘制图元,图元是基本单元,如点,线,三角形。
 
阅读更多
个人分类: OpenGL ES
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭