2012年6月7日 星期四

OpenGL ES 2.0 Tutorial Part 1 - 1

since: 2012/06/07
update: 2012/06/07


reference:
1. OpenGL ES 2.0 for iPhone Tutorial | Ray Wenderlich

新增專案

A. 說明:
    1. 本文章主要是翻譯 OpenGL ES 2.0 for iPhone Tutorial 的內容.

    2. 只會翻譯跟實作有關重要部分, 並將實作改成使用 ARC
         (Automatic Reference Counting) 的方式.

    3. 原始文章有使用到 Cocos3D 的 Math Library files.

    4. 原文使用 OpenGL ES 2.0 (programmable pipeline), 能對物體的光影特效
        作更佳的處理. 如 Fabien Sanglard 中那隻 Doom3 裡的 Hellknight. 
        備註: 你可以下載來編譯執行看看.

----------------------------------------------------------------------------------

B. 新增專案
      1. Xcode > File > New > Project... > iOS > Application >
         Empty Application > Next
       Product Name: HelloOpenGLES
       Company Identifier: com.blogspot
       Device Family: iPhone
       Use Automatic Reference Counting: checked
       > Next > Create

    2. 新增 Framework:

     OpenGLES
     
- Is used for visualizing 2D and 3D data.

     QuartzCore

     - Add 2D graphics rendering support.

      3. 新增 UIView 子類別檔案:
          Xcode > File > New > File...
          > iOS > Cocoa Touch > Objective-C class > Next
      Class: OpenGLView
      Subclass of: UIView
      > Next > Create

----------------------------------------------------------------------------------

C. 開啟 OpenGLView.h 檔案, 修改如下:
#import <UIKit/UIKit.h>
//@add
#import <QuartzCore/QuartzCore.h>
#include <OpenGLES/ES2/gl.h>
#include <OpenGLES/ES2/glext.h>

@interface OpenGLView : UIView
{
    //@add
    CAEAGLLayer *_eaglLayer;
    EAGLContext *_context;
    GLuint _colorRenderBuffer;
}

//@add
- (void)setupLayer; // Set layer to opaque(不透明)
- (void)setupContext; // Create OpenGL context
- (void)setupRenderBuffer; // Create a render buffer
- (void)setupFrameBuffer; // Create a frame buffer
- (void)render; // render something

@end

備註: 1. EGL 可以簡單的看成是: "Embedded-System Graphics Library".
               參考: EGL (OpenGL) - Wikipedia

          2.
EAGL 代表 The EGL API implemented by Apple.

          3. CAEAGL 的 CA 是 Core Animation 的意思. 

          4. CAEAGLLayer 是在 iOS 的應用程式中, 支援繪製 OpenGL 內容的類別.
              參考: CAEAGLLayer Class Reference

          5. EAGLContext: 用來管理使用 OpenGL ES 繪圖所需要的: 狀態資訊,
              繪圖指令與資源. 參考: EAGLContext Class Reference

          6. 關於 EGLEAGL 的差異性, 請參考: Khronos EGL and Apple EAGL .

----------------------------------------------------------------------------------

D. 開啟 OpenGLView.m 檔案, 修改如下:
#import "OpenGLView.h"

@implementation OpenGLView

//@add: overwrite the layerClass method
//
// To set up a view to display OpenGL content,
// you need to set it's default layer to CAEAGLLayer
+ (Class)layerClass
{
    return [CAEAGLLayer class];
}

//@add: Set layer to opaque(不透明) for performance reasons
//
// By default, CALayers are set to non-opaque (i.e. transparent).
- (void)setupLayer
{
    _eaglLayer = (CAEAGLLayer *)self.layer;
    _eaglLayer.opaque = YES;
}

//@add: Create OpenGL context
- (void)setupContext 
{  
    // use OpenGL ES 2.0 API
    EAGLRenderingAPI api = kEAGLRenderingAPIOpenGLES2;
    _context = [[EAGLContext alloc] initWithAPI:api];
   
    if (!_context) {
        NSLog(@"Failed to initialize OpenGLES 2.0 context");
        exit(1);
    }
   
    if (![EAGLContext setCurrentContext:_context]) {
        NSLog(@"Failed to set current OpenGL context");
        exit(1);
    }
}

//@add: Create a render buffer
//
// render buffer is an OpenGL object that stores the rendered image
// to present to the screen.

- (void)setupRenderBuffer
{
    // Create a new render buffer object
    //
    // This returns a unique integer for the the render buffer
    // (we store it here in _colorRenderBuffer).

    glGenRenderbuffers(1, &_colorRenderBuffer);
   
    // Tell OpenGL "whenever I refer to GL_RENDERBUFFER,
    // I really mean _colorRenderBuffer."

    glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderBuffer);       
   
    // Allocate some storage for the render buffer
    [_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:_eaglLayer];   
}

//@add: Create a frame buffer
//
// A frame buffer is an OpenGL object that contains a render buffer,
// and some other buffers.

- (void)setupFrameBuffer
{   
    GLuint framebuffer;
    glGenFramebuffers(1, &framebuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
   
    // Attach the render buffer you created earlier to the frame buffer's
    // GL_COLOR_ATTACHMENT0 slot.

    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                              GL_RENDERBUFFER, _colorRenderBuffer);
}

//@add: render something
- (void)render
{
    // Specify the RGB and alpha (transparency) values to use when clearing the screen.
    //
    //glClearColor(0, 104.0/255.0, 55.0/255.0, 1.0); // 除法會降低效能
    glClearColor(0.0, 0.4078, 0.2157, 1.0);
   
    // Actually perform the clearing
    glClear(GL_COLOR_BUFFER_BIT);
   
    // Present the render/color buffer to the UIView's layer!
    [_context presentRenderbuffer:GL_RENDERBUFFER];
}

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        //@add
        [self setupLayer]; // Set layer to opaque(不透明)       
        [self setupContext]; // Create OpenGL context               
        [self setupRenderBuffer]; // Create a render buffer        
        [self setupFrameBuffer]; // Create a frame buffer               
        [self render]; // render something    
    }
    return self;
}

----------------------------------------------------------------------------------

E. 開啟 AppDelegate.h 檔案, 修改如下:
#import <UIKit/UIKit.h>
//@add
#import "OpenGLView.h"

@interface AppDelegate : UIResponder <UIApplicationDelegate>
{
    //@add
    OpenGLView *glView;
}

@property (strong, nonatomic) UIWindow *window;
//@add
@property (strong, nonatomic) OpenGLView *glView;

@end

----------------------------------------------------------------------------------

F. 開啟 AppDelegate.m 檔案, 修改如下:
#import "AppDelegate.h"

@implementation AppDelegate

@synthesize window = _window;
//@add
@synthesize glView = _glView;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

{
    /*
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    self.window.backgroundColor = [UIColor whiteColor];
    
    [self.window makeKeyAndVisible];
    return YES;
    */
   
    //@update
    CGRect screenBounds = [[UIScreen mainScreen] bounds];
    self.window = [[UIWindow alloc] initWithFrame:screenBounds];
    self.window.backgroundColor = [UIColor whiteColor];   
   
    self.glView = [[OpenGLView alloc] initWithFrame:screenBounds];
    [self.window addSubview:self.glView];
   
    [self.window makeKeyAndVisible];
   
    return YES;
}
....

----------------------------------------------------------------------------------

G. 編譯並執行:
      備註: 會出現以下訊息, 先暫時不處理.
                 Application windows are expected to have a root view controller
                 at the end of application launch

沒有留言:

張貼留言

注意:只有此網誌的成員可以留言。