update: 2012/04/08
reference:
1. 原文:
iPhone Development: OpenGL ES from the Ground Up: Table of Contents
(iPhone Development: OpenGL ES From the Ground Up, Part 1: Basic Concepts)
2. 翻譯: 從零開始學習OpenGL ES之一 – 基本概念
3. I touchs: OpenGL ES 小試
基本概念
A. 說明
1. 由於原文 / 譯文的 Empty OpenGL Xcode project template 已無法下載,
因此主要參考譯文的版本來重新建立專案.
2. 本文章著重在實作的部分, 相關的概念說明, 請參考原文 / 譯文的內容.
3. 原本嘗試使用 OpenGL Game Project 來實作, 發現並沒有很簡潔, 因此決定
採用 Empty Application Project.
4. 本專案採用 Xcode 4.3.2, iOS SDK 5.1.
5. 由於版本的差異與相關參考資料的不足, 本系列文章的實驗性質較重, 可能會
更改較多次, 或者無法全部實作.
(update: 2012/03/30)
6. 有找到一個範例檔, 可以參考: Empty.OpenGL.ES.Application.zip
(請直接點選 "聯通下載" 或點 "聯通下載右方箭頭" 出現的 "電信下載")
---------------------------------------------------------------------------------------------
B. 相關詞彙
1. vertex: 頂點, 代表三維空間中的一個點.
說明: OpenGL ES 只支援三角形.
2. winding: 卷繞, 表示頂點繪製的次序.
說明: a. 預設情況下, OpenGL 的三角形只有一個可見面(front face: 前面), 不被
繪製的一面稱為 backface(背面), 確認可見面, 才能使OpenGL只做一半
的計算.
b. 預設情況下, 以反時針次序繪製頂點的構成的面是 frontface. OpenGL
使用 Backface Culling(隱面消除)的技術來避免繪製視窗中多邊形的
不可見面.
3. render: 渲染, 描繪, 繪圖
---------------------------------------------------------------------------------------------
C. 新增專案
Xcode > File > New > Project... > iOS > Application >
Empty Application > Next
Product Name: OpenGLESBegin
Company Identifier: com.blogspotDevice Family: iPhone
Use Automatic Reference Counting: checked
> Next > Create
---------------------------------------------------------------------------------------------
D. 新增 Framework
新增以下的 Framework:
OpenGLES
- Is used for visualizing 2D and 3D data.
QuartzCore
- Add 2D graphics rendering support.
GLKit
- Provides libraries of commonly needed functions and classes to reduce the effort
needed to create a new OpenGL ES 2.0 application or the effort required to port
an existing OpenGL ES 1.1 application to OpenGL ES 2.0.
---------------------------------------------------------------------------------------------
E. 新增 UIViewController 子類別
1. 說明: view controller 在此專案裡是非必要的, 只是不想在將來看到以下的訊息,
所以就把它加進來了.
Application windows are expected to have a root view controller
at the end of application launch.
2. Xcode > File > New > File...
> iOS > Cocoa Touch > Objective-C class > Next
Class: ViewController
Subclass of: UIViewController> Next > Create
---------------------------------------------------------------------------------------------
F. 新增 UIView 子類別
Xcode > File > New > File...
> iOS > Cocoa Touch > Objective-C class > Next
Class: GLView
Subclass of: UIView> Next > Create
---------------------------------------------------------------------------------------------
G. 開啓 GLView.h 檔案, 修改如下:
#import <UIKit/UIKit.h>
//@add
#import <OpenGLES/EAGL.h>
#import <QuartzCore/QuartzCore.h>
#import <OpenGLES/ES1/gl.h>
#import <OpenGLES/ES1/glext.h>
@interface GLView : UIView
{
//@add
EAGLContext *glContext;
}
//@add
@property (nonatomic, strong) EAGLContext *glContext;
//@add
- (void)drawView;
@end
---------------------------------------------------------------------------------------------
H. 開啓 GLView.m 檔案, 修改如下:
#import "GLView.h"
@implementation GLView
//@add
@synthesize glContext = _glContext;
//@add
- (EAGLContext *)glContext
{
if (_glContext == nil) {
_glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
}
return _glContext;
}
//@add: 覆寫 layerClass 方法(類似 typeof), 回傳一個 OpenGL Layer 的類別
+ (Class)layerClass
{
return [CAEAGLLayer class];
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
//@add
// 從 UIView 取得 layer (CALayer), 向下轉型成 CAEAGLLayer.
// 在此為安全的, 因為 layerClass 方法已被覆寫)
CAEAGLLayer *eaglLayer = (CAEAGLLayer*) super.layer;
// 直接使用 OpenGL 設定不透明度
eaglLayer.opaque = YES;
// 設定 Current Context
[EAGLContext setCurrentContext:self.glContext];
//@add: OpenGL 初始化
// 定義:渲染(render)與幅(frame)緩衝區(buffer); GLuint 同義於 unsigned int
GLuint framebuffer, renderbuffer;
glGenFramebuffersOES(1, &framebuffer);
glGenRenderbuffersOES(1, &renderbuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, framebuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, renderbuffer);
[self.glContext renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:eaglLayer];
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER_OES, renderbuffer);
// 建構一個對應的座標系統
glViewport(0, 0, CGRectGetWidth(frame), CGRectGetHeight(frame));
[self drawView];
}
return self;
}
//@add
- (void)drawView
{
glClearColor(0.5f, 0.5f, 0.5f, 1); // 將顏色定義為灰色
glClear(GL_COLOR_BUFFER_BIT); // 執行清除操作
// 先將定義好的灰色填入緩衝區, 接著發佈到螢幕上
[self.glContext presentRenderbuffer:GL_RENDERBUFFER_OES];
}
//@add
- (void)dealloc
{
if ([EAGLContext currentContext] == self.glContext) {
[EAGLContext setCurrentContext:nil];
}
}
---------------------------------------------------------------------------------------------
I. 開啓 AppDelegate.h 檔案, 修改如下:
#import <UIKit/UIKit.h>
//@add
#import "ViewController.h"
#import "GLView.h"
@interface AppDelegate : UIResponder <UIApplicationDelegate>
{
UIWindow *window;
//@add
ViewController *viewController;
GLView *glView;
}
@property (strong, nonatomic) UIWindow *window;
//@add
@property (strong, nonatomic) ViewController *viewController;
@property (strong, nonatomic) GLView *glView;
@end
---------------------------------------------------------------------------------------------
J. 開啓 AppDelegate.m 檔案, 修改如下:
#import "AppDelegate.h"
@implementation AppDelegate
@synthesize window = _window;
//@add
@synthesize glView = _glView;
@synthesize viewController = _viewController;
- (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];
*/
//@update
CGRect screenBounds = [[UIScreen mainScreen] bounds];
self.window = [[UIWindow alloc] initWithFrame:screenBounds];
self.viewController = [[ViewController alloc] init];
self.glView = [[GLView alloc] initWithFrame:screenBounds];
self.window.rootViewController = viewController;
self.viewController.view = self.glView;
[self.window addSubview:self.viewController.view];
[self.window makeKeyAndVisible];
return YES;
}
....
---------------------------------------------------------------------------------------------
K. 隱藏狀態欄位
開啓 OpenGLESBegin-Info.plist 檔案, 新增一筆資料如下:
Key: Status bar is initially hidden
Value: YES
---------------------------------------------------------------------------------------------
L. 編譯並執行
---------------------------------------------------------------------------------------------
M. 新增 OpenGL ES 的通用檔案
1. Xcode > File > New > File...
> iOS > C and C++ > Header File > Next
Save As: OpenGLESCommon.h
Targets: OpenGLESBegin (勾選)> Create
2. 開啓 OpenGLESCommon.h 檔案, 修改如下:
/*
#ifndef OpenGLESBegin_OpenGLESCommon_h
#define OpenGLESBegin_OpenGLESCommon_h
#endif
*/
#import <OpenGLES/EAGL.h>
#import <OpenGLES/ES1/gl.h>
#import <OpenGLES/ES1/glext.h>
#pragma mark -
#pragma mark Vertex3D
#pragma mark -
// 頂點定義
typedef struct {
GLfloat x;
GLfloat y;
GLfloat z;
} Vertex3D;
// 單個頂點
static inline Vertex3D Vertex3DMake(CGFloat inX, CGFloat inY, CGFloat inZ)
{
Vertex3D ret;
ret.x = inX;
ret.y = inY;
ret.z = inZ;
return ret;
}
// 三維空間中任何兩點間的直線距離
static inline GLfloat Vertex3DCalculateDistanceBetweenVertices(Vertex3D first, Vertex3D second)
{
GLfloat deltaX = second.x - first.x;
GLfloat deltaY = second.y - first.y;
GLfloat deltaZ = second.z - first.z;
return sqrtf(deltaX*deltaX + deltaY*deltaY + deltaZ*deltaZ ); // sqrtf: 開根號
}
#pragma mark -
#pragma mark Triangle3D
#pragma mark -
// 三角形定義
typedef struct {
Vertex3D v1;
Vertex3D v2;
Vertex3D v3;
} Triangle3D;
// 三角形物體
static inline Triangle3D Triangle3DMake(Vertex3D inV1, Vertex3D inV2, Vertex3D inV3)
{
Triangle3D ret;
ret.v1 = inV1;
ret.v2 = inV2;
ret.v3 = inV3;
return ret;
}
---------------------------------------------------------------------------------------------
N. 新增常數與巨集定義檔案
1. Xcode > File > New > File...
> iOS > C and C++ > Header File > Next
Save As: ConstantsAndMacros.h
Targets: OpenGLESBegin (勾選)> Create
2. 開啓 ConstantsAndMacros.h 檔案, 修改如下: (update: 2012/03/30)
/*
#ifndef OpenGLESBegin_ConstantsAndMacros_h
#define OpenGLESBegin_ConstantsAndMacros_h
#endif
*/
// How many times a second to refresh the screen
#define kRenderingFrequency 15.0
// Defines whether to setup and use a depth buffer
#define USE_DEPTH_BUFFER 1
// Macros
#define DEGREES_TO_RADIANS(__ANGLE__) ((__ANGLE__) / 180.0 * M_PI)
2. 開啓 OpenGLESCommon.h 檔案, 修改如下: (2012/04/08 update)
....
#import <OpenGLES/EAGL.h>
#import <OpenGLES/ES1/gl.h>
#import <OpenGLES/ES1/glext.h>
//@add
#import "ConstantsAndMacros.h"
....
沒有留言:
張貼留言
注意:只有此網誌的成員可以留言。