2012年6月9日 星期六

OpenGL ES 2.0 Tutorial Part 1 - 5

since: 2012/06/09
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 的效果, 需要在物體上套用一個投影轉換.
         如下圖所示:

     2. 基本上, 我們會有一個 near plane(近端平面)與 far plane(遠端平面), 要顯示的
         物體就置於二個平面之間. 靠近 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 檔案, 修改如下:
....
@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.mCC3GLMatrix.m 裡找到不少個錯誤,
                  都是跟 ARC 有關的.

     2. 開啟 CC3Foundation.m 檔案, 修正如下:
....
-(id) copyAutoreleased {
    //@fixed for ARC
    //return [[self copy] autorelease];
    return [self copy];
}
....
     3. 開啟 CC3GLMatrix.m 檔案, 修正如下:
....
-(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 軸)看起來, 正方形的距離似乎是拉遠了一些.

沒有留言:

張貼留言

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