2012年6月13日 星期三

OpenGL ES 2.0 Tutorial Part 1 - 7

since: 2012/06/13
update: 2012/06/13


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
6. I touchs: OpenGL ES 2.0 Tutorial Part 1 - 5
7. I touchs: OpenGL ES 2.0 Tutorial Part 1 - 6

旋轉

A. 開啟 OpenGLView.h 檔案, 修改如下:
....
@interface OpenGLView : UIView
{
    //@add
    CAEAGLLayer *_eaglLayer;
    EAGLContext *_context;
    GLuint _colorRenderBuffer;
   
    //@add
    GLuint _positionSlot;
    GLuint _colorSlot;
   
    //@add for uniform
    GLuint _projectionUniform;
    GLuint _modelViewUniform;
   
    //@add
    float _currentRotation;
}
....

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

B. 開啟 OpenGLView.m 檔案, 修改如下:

....
- (void)render:(CADisplayLink *)displayLink
{
....
    //@add for modelView transform (before the call to glViewport)
    CC3GLMatrix *modelView = [CC3GLMatrix matrix];
    //
    // CC3VectorMake: Returns a CC3Vector structure constructed from the vector components
    //
    // CC3Vector CC3VectorMake(GLfloat x, GLfloat y, GLfloat z);  
    //
    // 說明:
    // 1. 沿著 Z 軸的位移, 固定為 -7
    // 2. 無沿著 Y 軸的位移
    // 3. 沿著 X 軸的位移: (sin 的值介於 -1 ~ 1; 週期為 2π)
    //    以每 3.14x2 秒為週期, 值介於 -1 ~ 1 之間.
    [modelView populateFromTranslation:CC3VectorMake(sin(CACurrentMediaTime()), 0, -7)];
   
    //@add for rotation
    //
    // increment by 90 degrees every second
    _currentRotation += displayLink.duration * 90;
    //
    // add a rotation to the model view matrix:
    // The rotation is along both the x and y axis, and 0 along the z axis.
    [modelView rotateBy:CC3VectorMake(_currentRotation, _currentRotation, 0)];
   
    glUniformMatrix4fv(_modelViewUniform, 1, 0, modelView.glMatrix);
   

    //@add: draw our new vertex data to the screen
    //
    // 1. 設定要繪製在 UIView 上的範圍, 此處為畫到整個視窗上
    glViewport(0, 0, self.frame.size.width, self.frame.size.height);
....
}
....

      編譯並執行:
      可以看到正方形(平面)以 3D 的方式翻轉.

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

C. 3D 立方體
     1. 開啟 OpenGLView.m 檔案, 修改如下:
// step01
....

// 所有個別頂點的資訊:
// {位置1, 顏色1}, {位置2, 顏色2}, {位置3, 顏色3}, {位置4, 顏色4}
//@update: Revert vertices back to z-value 0
/*
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 3D Cube
// 8 個頂點
const Vertex Vertices[] = {
    {{1, -1, 0}, {1, 0, 0, 1}},
    {{1, 1, 0}, {1, 0, 0, 1}},
    {{-1, 1, 0}, {0, 1, 0, 1}},
    {{-1, -1, 0}, {0, 1, 0, 1}},
    {{1, -1, -1}, {1, 0, 0, 1}},
    {{1, 1, -1}, {1, 0, 0, 1}},
    {{-1, 1, -1}, {0, 1, 0, 1}},
    {{-1, -1, -1}, {0, 1, 0, 1}}
};

....
// step02
// 產生三角形的頂點索引:
//
// 每三個頂點組成一個三角形:
// 第一個三角形: 由頂點索引為 0, 1 與 2 所組成
// 第二個三角形: 由頂點索引為 2, 3 與 0 所組成
/*
const GLubyte Indices[] = {
    0, 1, 2,
    2, 3, 0
};
*/

//@update for 3D Cube
// 6 個面
const GLubyte Indices[] = {
    // Front
    0, 1, 2,
    2, 3, 0,
    // Back
    4, 6, 5,
    4, 7, 6,
    // Left
    2, 7, 3,
    7, 6, 2,
    // Right
    0, 4, 1,
    4, 1, 5,
    // Top
    6, 2, 1,
    1, 6, 5,
    // Bottom
    0, 3, 7,
    0, 7, 4   
};

....
      2. 編譯並執行:
          你可以看到立方體的內部, 這樣看起來不是很正確.

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

D. 啟動深度測試(depth testing)

      1. 說明:
          當啟動 depth testing, OpenGL 就可以對每個要繪製的 pixel 之 Z 軸
          保持追蹤; 只有當該 pixel 前方沒有東西時, 才會繪製出這個 pixel.

      2. 開啟 OpenGLView.h 檔案, 修改如下:
....
@interface OpenGLView : UIView
{
    //@add
    CAEAGLLayer *_eaglLayer;
    EAGLContext *_context;
    GLuint _colorRenderBuffer;
   
    //@add
    GLuint _positionSlot;
    GLuint _colorSlot;
   
    //@add for uniform
    GLuint _projectionUniform;
    GLuint _modelViewUniform;
   
    //@add
    float _currentRotation;
    GLuint _depthRenderBuffer;
}
....
//@add
- (GLuint)compileShader:(NSString *)shaderName withType:(GLenum)shaderType;
- (void)compileShaders;
- (void)setupVBOs; // Creating Vertex Buffer Objects
- (void)setupDisplayLink;
- (void)setupDepthBuffer;

@end

      3. 開啟 OpenGLView.m 檔案, 修改如下:
// step01
....
//@add
- (void)setupDepthBuffer
{
    // creates a depth buffer
    glGenRenderbuffers(1, &_depthRenderBuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, _depthRenderBuffer);
    // alloacates the storage
    //
    // use glRenderbufferStorage not
    //
renderBufferStorage(special case for the color render buffer)
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, self.frame.size.width, self.frame.size.height);   
}
....

// step02
....
- (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: associate the new depth buffer with the render buffer.
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthRenderBuffer);
}
....

// step03
....
- (void)render:(CADisplayLink *)displayLink
{
    // 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);
    //@update: clear the depth buffer
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST); // enable depth testing
....
}
....

// step04
....
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        //@add
        [self setupLayer]; // Set layer to opaque(不透明)      
        [self setupContext]; // Create OpenGL context 
       
        //@add
        [self setupDepthBuffer];
       
        [self setupRenderBuffer]; // Create a render buffer       
        [self setupFrameBuffer]; // Create a frame buffer   
       
        //@add
        [self compileShaders];
        [self setupVBOs]; // Creating Vertex Buffer Objects
       
        //[self render]; // render something  
        //@update
        [self setupDisplayLink];
    }
    return self;
}
....

      4. 編譯並執行:
           正常的旋轉立方體

沒有留言:

張貼留言

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