2012年6月13日 星期三

OpenGL ES 2.0 Tutorial Part 1 - 6

since: 2012/06/12
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

位移

A. 說明:
      1. 矩陣轉換, 可以讓我們在空間中輕易地移動頂點, 以取代之前用手工的方式
          在頂點陣列裡逐一修改頂點資料.

      2. 到目前為止, 我們的 vertex shader 利用投影矩陣來更改每個頂點的位置, 我們
          也可以使用一個稱為 "model-view" 的轉換, 來對物體作: 位移, 縮放旋轉矩陣
          的應用.

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

B. 開啟 SimpleVertex.glsl 檔案, 修改如下:
attribute vec4 Position;

attribute vec4 SourceColor;

varying vec4 DestinationColor;

uniform mat4 Projection;
//@add
uniform mat4 Modelview;

void main(void) {

    DestinationColor = SourceColor;
  
    //gl_Position = Projection * Position;
    //@update: add applying the modelview matrix to the position.
    gl_Position = Projection * Modelview * Position;
}

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

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

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

D. 開啟 OpenGLView.m 檔案, 修改如下:
//step01
....

- (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");
    //@add for get the reference to the model view uniform input variable
    _modelViewUniform = glGetUniformLocation(programHandle, "Modelview");
}

//step02
....
- (void)render
{
.... 
    //@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 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)];

    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); 
....
}

//step03
....
// 所有個別頂點的資訊:
// {位置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 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}}
};
*/

編譯並執行:

      說明: 由於只呼叫一次 render 方法, 因此物體不會移動.


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

E. 同步 "繪製" 與 "顯示更新頻率"
      1. 說明:
          觀念上, 我們希望使用 OpenGL 來繪製的時間點螢幕更新的頻率能夠
          同步
進行. 幸運地, Apple 提供了一個簡單的類別來處理: CADisplayLink .
          參考: CADisplayLink Class Reference .

      2. 開啟 OpenGLView.h 檔案, 修改如下:
....
//@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
//@update: Modify render method to take a parameter
- (void)render:(CADisplayLink *)displayLink;

//@add
- (GLuint)compileShader:(NSString *)shaderName withType:(GLenum)shaderType;
- (void)compileShaders;
- (void)setupVBOs; // Creating Vertex Buffer Objects
- (void)setupDisplayLink;

@end

      3. 開啟 OpenGLView.m 檔案, 修改如下:
// step01
//@add: render something
//- (void)render
- (void)render:(CADisplayLink *)displayLink
{
....
}

....
// step02
//@add
- (void)setupDisplayLink
{
    CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(render:)];

    [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];   
}

....
// step03
- (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   
       
        //@add
        [self compileShaders];
        [self setupVBOs]; // Creating Vertex Buffer Objects
       
        //[self render]; // render something  
        //@update
        [self setupDisplayLink];
    }
    return self;
}

....

      4. 編譯並執行:
     說明: 使用 CADisplayLink, 每個影格都會呼叫 render: 方法, 因而更新了基於
               目前時間點 sin() 函式的轉換, 所以物體會沿著 X 軸以 2π(2 x 3.14)
               為週期, 在 -1 ~ 1 之間作位移. 

沒有留言:

張貼留言

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