update: 2012/06/09
reference:
1. OpenGL ES 2.0 for iPhone Tutorial | Ray Wenderlich
2. I touchs: OpenGL ES 2.0 Tutorial Part 1 - 1
3. I touchs: OpenGL ES 2.0 Tutorial Part 1 - 2
4. I touchs: OpenGL ES 2.0 Tutorial Part 1 - 3
5. I touchs: OpenGL ES 2.0 Tutorial Part 1 - 4
投影
A. 說明:
1. 要讓物體在 2D 的螢幕上呈現出 3D 的效果, 需要在物體上套用一個投影轉換.
如下圖所示:
物體就置於二個平面之間. 靠近 near plane 的物件, 經過投影縮放後看起來會
小一些; 靠近 far plane 的物件, 經過投影縮放後看起來會大一些, 這是模仿人類
眼睛運作的方式.
----------------------------------------------------------------------------------
B. 開啟 SimpleVertex.glsl 檔案, 修改如下:
(備註: shaders 裡的註解要用英文)
attribute vec4 Position;
attribute vec4 SourceColor;
varying vec4 DestinationColor;
//@add for Projection
//
// uniform: This means that we just pass in a constant value for all vertices,
// rather than a per-vertex value.
//
// mat4: a 4×4 matrix(used to scale, rotate, or translate vertices)
//
// We'll pass in a matrix that moves our vertices around according to the Projection.
uniform mat4 Projection;
void main(void) {
DestinationColor = SourceColor;
//gl_Position = Position;
//@update for Projection
//
// Set the final position of the vertex to be the Projection multiplied by the Position.
gl_Position = Projection * Position;
}
----------------------------------------------------------------------------------
C. 將投影矩陣的內容傳給 Vertex Shader:
1. 說明:
要將投影矩陣的內容傳給 Vertex Shader, 實際上會牽涉到一些複雜的線性代數.
在這邊, 將直接採用 Cocos3d 的某些數學函式庫, Cocos3D 是一個功能全面的
3D 繪圖架構, 它跟 Cocos2D 有良好的整合性. 最主要的原因是, 我們可以在此
專案中輕易地引入 Cocos3D 所包含的 Objective-C 向量與矩陣函式庫.
2. 先下載原作者調整好的 Cocos3D Math Library files , 其中已移除了一些不會
用到的相依性檔案, 下載解壓縮後, 將檔案全部加入到專案裡, 確定勾選:
"Copy items into destination group's folder (if needed)" .
備註: 記得先將檔案加入到專案下(targets: HelloOpenGLES),
之後才可拖拉到新增的群組裡.(比較不會有路徑的問題)
3. 開啟 OpenGLView.h 檔案, 修改如下:
....之後才可拖拉到新增的群組裡.(比較不會有路徑的問題)
3. 開啟 OpenGLView.h 檔案, 修改如下:
@interface OpenGLView : UIView
{
//@add
CAEAGLLayer *_eaglLayer;
EAGLContext *_context;
GLuint _colorRenderBuffer;
//@add
GLuint _positionSlot;
GLuint _colorSlot;
//@add for projection
GLuint _projectionUniform;
}
....
4. 開啟 OpenGLView.m 檔案, 修改如下:
// step01
#import "OpenGLView.h"
//@add for projection
#import "CC3GLMatrix.h"
....
// step02
//@add
- (void)compileShaders
{
....
//@add for projection (at bottom of compileShaders)
//
// get the handle we need to set the Projection input variable in the vertex shader.
_projectionUniform = glGetUniformLocation(programHandle, "Projection");
}
....
// step03
//@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);
//@add for projection (before the call to glViewport)
//
// create a projection matrix
CC3GLMatrix *projection = [CC3GLMatrix matrix];
float h = 4.0f * self.frame.size.height / self.frame.size.width;
[projection populateFromFrustumLeft:-2 andRight:2 andBottom:-h/2 andTop:h/2 andNear:4 andFar:10];
// pass data to the vertex shader
//
// glMatrix: converts them matrix into the array format OpenGL uses.
glUniformMatrix4fv(_projectionUniform, 1, 0, projection.glMatrix);
//@add: draw our new vertex data to the screen
//
// 1. 設定要繪製在 UIView 上的範圍, 此處為畫到整個視窗上
glViewport(0, 0, self.frame.size.width, self.frame.size.height);
....
}
// step04
....
// 所有個別頂點的資訊:
// {位置1, 顏色1}, {位置2, 顏色2}, {位置3, 顏色3}, {位置4, 顏色4}
/*
const Vertex Vertices[] = {
{{1, -1, 0}, {1, 0, 0, 1}},
{{1, 1, 0}, {0, 1, 0, 1}},
{{-1, 1, 0}, {0, 0, 1, 1}},
{{-1, -1, 0}, {0, 0, 0, 1}}
};
*/
//@update for projection
//
// to fit within the near/far planes.
// This just sets the z-coordinate for each vertex to -7.
const Vertex Vertices[] = {
{{1, -1, -7}, {1, 0, 0, 1}},
{{1, 1, -7}, {0, 1, 0, 1}},
{{-1, 1, -7}, {0, 0, 1, 1}},
{{-1, -1, -7}, {0, 0, 0, 1}}
};
....
----------------------------------------------------------------------------------
D. 除錯
1. Product > Analyze
說明: 在 CC3Foundation.m 與 CC3GLMatrix.m 裡找到不少個錯誤,
都是跟 ARC 有關的.
2. 開啟 CC3Foundation.m 檔案, 修正如下:
....
-(id) copyAutoreleased {
//@fixed for ARC
//return [[self copy] autorelease];
return [self copy];
}
....
3. 開啟 CC3GLMatrix.m 檔案, 修正如下:都是跟 ARC 有關的.
2. 開啟 CC3Foundation.m 檔案, 修正如下:
....
-(id) copyAutoreleased {
//@fixed for ARC
//return [[self copy] autorelease];
return [self copy];
}
....
....
-(id) init {
if ( [self isKindOfClass: [CC3GLArrayMatrix class]] ) {
if( (self = [self initParent]) ) {
[self populateZero];
}
return self;
} else {
//@fixed for ARC
//[self release];
return [[CC3GLArrayMatrix alloc] init];
}
}
....
+(id) matrix {
if ( [self isSubclassOfClass: [CC3GLArrayMatrix class]] ) {
//@fixed for ARC
//return [[[self alloc] init] autorelease];
return [[self alloc] init];
} else {
return [CC3GLArrayMatrix matrix];
}
}
....
-(id) initIdentity {
if ( [self isKindOfClass: [CC3GLArrayMatrix class]] ) {
if( (self = [self initParent]) ) {
[self populateIdentity];
}
return self;
} else {
//@fixed for ARC
//[self release];
return [[CC3GLArrayMatrix alloc] initIdentity];
}
}
....
+(id) identity {
if ( [self isSubclassOfClass: [CC3GLArrayMatrix class]] ) {
//@fixed for ARC
//return [[[self alloc] initIdentity] autorelease];
return [[self alloc] initIdentity];
} else {
return [CC3GLArrayMatrix identity];
}
}
....
-(id) initFromGLMatrix: (GLfloat*) aGLMtx {
if ( [self isKindOfClass: [CC3GLArrayMatrix class]] ) {
if( (self = [self initParent]) ) {
[self populateFromGLMatrix: aGLMtx];
}
return self;
} else {
//@fixed for ARC
//[self release];
return [[CC3GLArrayMatrix alloc] initFromGLMatrix: aGLMtx];
}
}
....
+(id) matrixFromGLMatrix: (GLfloat*) aGLMtx {
if ( [self isSubclassOfClass: [CC3GLArrayMatrix class]] ) {
//@fixed for ARC
//return [[[self alloc] initFromGLMatrix: aGLMtx] autorelease];
return [[self alloc] initFromGLMatrix: aGLMtx];
} else {
return [CC3GLArrayMatrix matrixFromGLMatrix: aGLMtx];
}
}
....
-(id) initWithFirstElement: (GLfloat) e00 remainingElements: (va_list) args {
if ( [self isKindOfClass: [CC3GLArrayMatrix class]] ) {
if( (self = [self initParent]) ) {
GLfloat* p = self.glMatrix;
*p++ = e00;
for (int i = 1; i < 16; i++) {
*p++ = (GLfloat)va_arg(args, double);
}
}
} else {
//@fixed for ARC
//[self release];
self = [[CC3GLArrayMatrix alloc] initWithFirstElement: e00 remainingElements: args];
}
return self;
}
....
+(id) matrixWithElements: (GLfloat) e00, ... {
va_list args;
va_start(args, e00);
CC3GLMatrix* mtx = [[CC3GLArrayMatrix alloc] initWithFirstElement: e00 remainingElements: args];
va_end(args);
//@fixed for ARC
//return [mtx autorelease];
return mtx;
}
....
-(id) initOnGLMatrix: (GLfloat*) aGLMtx {
//@fixed for ARC
//[self release];
return [[CC3GLPointerMatrix alloc] initOnGLMatrix: aGLMtx];
}
....
+(id) matrixOnGLMatrix: (GLfloat*) aGLMtx {
if ( [self isSubclassOfClass: [CC3GLPointerMatrix class]] ) {
//@fixed for ARC
//return [[[self alloc] initOnGLMatrix: aGLMtx] autorelease];
return [[self alloc] initOnGLMatrix: aGLMtx];
} else {
return [CC3GLPointerMatrix matrixOnGLMatrix: aGLMtx];
}
}
....
- (id) copyWithZone: (NSZone*) zone {
//@fixed for ARC
//return [[CC3GLArrayMatrix matrixFromGLMatrix: self.glMatrix] retain];
return [CC3GLArrayMatrix matrixFromGLMatrix: self.glMatrix];
}
....
----------------------------------------------------------------------------------
E. 編譯並執行
從螢幕上(Z 軸)看起來, 正方形的距離似乎是拉遠了一些.
沒有留言:
張貼留言
注意:只有此網誌的成員可以留言。