2012年4月17日 星期二

OpenGL ES 入門: 六. 紋理及紋理映射之二

since: 2012/04/16
update: 2012/04/17

reference:
1. 原文:
iPhone Development: OpenGL ES From the Ground Up, Part 6: Textures and Texture Mapping

2. 翻譯:
從零開始學習OpenGL ES之六 – 紋理及紋理映射

紋理及紋理映射: 更多的映射, 平鋪和箝位

A. 更多的映射方式
      1. 上個例子中這個圖像都被映射到繪製的正方形上. 那是因為設定的紋理坐標
          所決定的. 我們可以改變坐標陣列僅使用來源圖像中心部分.

          開啓 ViewController.m 檔案, 修改如下:
....
// 紋理映射
- (void)TextureMapping
{
.... 
    static const Vertex3D vertices[] = {
        {-1.0,  1.0, -0.0},
        { 1.0,  1.0, -0.0},
        {-1.0, -1.0, -0.0},
        { 1.0, -1.0, -0.0}
    };
   
    static const Vector3D normals[] = {
        {0.0, 0.0, 1.0},
        {0.0, 0.0, 1.0},
        {0.0, 0.0, 1.0},
        {0.0, 0.0, 1.0}
    };
   
    // Feel free to comment these texture coordinates out and use one
    // of the ones below instead, or play around with your own values.
    /*
    static const GLfloat texCoords[] = {
        0.0, 1.0,
        1.0, 1.0,
        0.0, 0.0,
        1.0, 0.0
    };
    */
   
    static const GLfloat texCoords[] = {
        0.25, 0.75,
        0.75, 0.75,
        0.25, 0.25,
        0.75, 0.25
    };   
   
    glLoadIdentity();
    glTranslatef(0.0, 0.0, -3.0);
    glRotatef(rot, 1.0, 1.0, 1.0); 
....
}
....

      編譯並執行:
      銀幕上只顯示了紋理的中心部分.

      2. 類似地, 如果我們只希望顯示紋理的左下部:
          開啓 ViewController.m 檔案, 修改如下:
....
// 紋理映射
- (void)TextureMapping
{
.... 
    static const Vertex3D vertices[] = {
        {-1.0,  1.0, -0.0},
        { 1.0,  1.0, -0.0},
        {-1.0, -1.0, -0.0},
        { 1.0, -1.0, -0.0}
    };
   
    static const Vector3D normals[] = {
        {0.0, 0.0, 1.0},
        {0.0, 0.0, 1.0},
        {0.0, 0.0, 1.0},
        {0.0, 0.0, 1.0}
    };
   
    // Feel free to comment these texture coordinates out and use one
    // of the ones below instead, or play around with your own values.    
    // 顯示完整的紋理
    /*
    static const GLfloat texCoords[] = {
        0.0, 1.0,
        1.0, 1.0,
        0.0, 0.0,
        1.0, 0.0
    };
    */
    
    // 顯示紋理的中心部分
    /*
    static const GLfloat texCoords[] = {
        0.25, 0.75,
        0.75, 0.75,
        0.25, 0.25,
        0.75, 0.25
    };    
    */
  
    // 顯示紋理的左下部
    static const GLfloat texCoords[] = {
        0.0, 0.5,
        0.5, 0.5,
        0.0, 0.0,
        0.5, 0.0
    };
   
    glLoadIdentity();
    glTranslatef(0.0, 0.0, -3.0);
    glRotatef(rot, 1.0, 1.0, 1.0); 
....
}
....

      編譯並執行:

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

B. 還有更多的方式
      1. 說明:
          我們可以通過非常規方式的映射來扭曲紋理.
 
      2. 開啓 ViewController.m 檔案, 修改如下:
....
- (void)TextureMapping
{
    NSLog(@"ViewController => TextureMapping");
   
    //@update for more mapping
    //static GLfloat rot = 0.0;
   
    glColor4f(0.0, 0.0, 0.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
   
    /*
    static const Vertex3D vertices[] = {
        {-1.0,  1.0, -0.0},
        { 1.0,  1.0, -0.0},
        {-1.0, -1.0, -0.0},
        { 1.0, -1.0, -0.0}
    };
   
    static const Vector3D normals[] = {
        {0.0, 0.0, 1.0},
        {0.0, 0.0, 1.0},
        {0.0, 0.0, 1.0},
        {0.0, 0.0, 1.0}
    };
    */
    //@update for more mapping
    static const Vertex3D vertices[] = {
        {-1.0,  1.0, -0.0},
        { 1.0,  1.0, -0.0},
        { 0.0, -1.0, -0.0},
       
    };
    static const Vector3D normals[] = {
        {0.0, 0.0, 1.0},
        {0.0, 0.0, 1.0},
        {0.0, 0.0, 1.0},
    };
   
    // Feel free to comment these texture coordinates out and use one
    // of the ones below instead, or play around with your own values.   
    // 顯示完整的紋理
    /*
    static const GLfloat texCoords[] = {
        0.0, 1.0,
        1.0, 1.0,
        0.0, 0.0,
        1.0, 0.0
    };
    */
   
    // 顯示紋理的中心部分
    /*
    static const GLfloat texCoords[] = {
        0.25, 0.75,
        0.75, 0.75,
        0.25, 0.25,
        0.75, 0.25
    };   
    */
   
    // 顯示紋理的左下部
    /*
    static const GLfloat texCoords[] = {
        0.0, 0.5,
        0.5, 0.5,
        0.0, 0.0,
        0.5, 0.0
    };
    */
    //@update for more mapping
    static const GLfloat texCoords[] = {
        0.0, 1.0,
        1.0, 0.0,
        0.0, 0.0,
    };
     
    glLoadIdentity();
    glTranslatef(0.0, 0.0, -3.0);
    //@update for more mapping
    //glRotatef(rot, 1.0, 1.0, 1.0);
   
    //@update for more mapping
    glBindTexture(GL_TEXTURE_2D, texture[0]);
   
    glVertexPointer(3, GL_FLOAT, 0, vertices);
    glNormalPointer(GL_FLOAT, 0, normals);
    glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
   
    //glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    //@update for more mapping
    glDrawArrays(GL_TRIANGLES, 0, 3);

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
   
    //@update for more mapping
    /*
    static NSTimeInterval lastDrawTime;
    if (lastDrawTime)
    {
        NSTimeInterval timeSinceLastDraw = [NSDate timeIntervalSinceReferenceDate] - lastDrawTime;
        rot +=  60 * timeSinceLastDraw;               
    }
    lastDrawTime = [NSDate timeIntervalSinceReferenceDate];
     */
}
....

      3. 編譯並執行:
          紋理正方形左下角的弧形花紋現在處於三角形的底部了.
          (紋理上的任何一點都可以映射到多邊形的任何一點)

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

C. 平鋪(貼磚)和箝位
      1. 說明:
          我們的紋理坐標系統在兩個軸上都是從 0.01.0, 如果設置超出此範圍的值時,
          根據視圖的設置方式有兩種選擇
: 平鋪 Tiling (也叫重複)或箝位 Clamping.

      2. 平鋪(也叫重複)
           a. 開啓 ViewController.m 檔案, 修改如下:
....
-(void)setupView:(GLView *)view
{
....
    // Configuring the Image
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   
    //@add for Tiling
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
....
}
....
- (void)TextureMapping
{
    NSLog(@"ViewController => TextureMapping");
   
    static GLfloat rot = 0.0;
   
    glColor4f(0.0, 0.0, 0.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
   
    static const Vertex3D vertices[] = {
        {-1.0,  1.0, -0.0},
        { 1.0,  1.0, -0.0},
        {-1.0, -1.0, -0.0},
        { 1.0, -1.0, -0.0}
    };
   
    static const Vector3D normals[] = {
        {0.0, 0.0, 1.0},
        {0.0, 0.0, 1.0},
        {0.0, 0.0, 1.0},
        {0.0, 0.0, 1.0}
    };
   
    // Feel free to comment these texture coordinates out and use one
    // of the ones below instead, or play around with your own values.   
    // 顯示完整的紋理
    /*
    static const GLfloat texCoords[] = {
        0.0, 1.0,
        1.0, 1.0,
        0.0, 0.0,
        1.0, 0.0
    };
    */
   
    // 顯示紋理的中心部分
    /*
    static const GLfloat texCoords[] = {
        0.25, 0.75,
        0.75, 0.75,
        0.25, 0.25,
        0.75, 0.25
    };   
    */
   
    // 顯示紋理的左下部
    /*
    static const GLfloat texCoords[] = {
        0.0, 0.5,
        0.5, 0.5,
        0.0, 0.0,
        0.5, 0.0
    };
    */
   
    //@update for Tiling
    static const GLfloat texCoords[] = {
        0.0, 2.0,
        2.0, 2.0,
        0.0, 0.0,
        2.0, 0.0
    };
   
    glLoadIdentity();
    glTranslatef(0.0, 0.0, -3.0);
    glRotatef(rot, 1.0, 1.0, 1.0);
   
    glVertexPointer(3, GL_FLOAT, 0, vertices);
    glNormalPointer(GL_FLOAT, 0, normals);
    glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
   
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
   
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
   
    static NSTimeInterval lastDrawTime;
    if (lastDrawTime)
    {
        NSTimeInterval timeSinceLastDraw = [NSDate timeIntervalSinceReferenceDate] - lastDrawTime;
        rot +=  60 * timeSinceLastDraw;               
    }
    lastDrawTime = [NSDate timeIntervalSinceReferenceDate];
}
....

           b. 編譯並執行:

      3. 箝位
           a. 說明
               讓 OpenGL ES 簡單地將超過 1.0 的值限制為1.0, 任何低於 0.0 的值限制為 0.0.
               這實際會引起邊緣像素重複, 從而產生奇怪的效果
.

           b. 開啓 ViewController.m 檔案, 修改如下:
....
-(void)setupView:(GLView *)view
{
....
    // Configuring the Image
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   
    //@add for Tiling
    /*
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    */

    //@add for Clamping
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
....
}
....

           c. 編譯並執行:

沒有留言:

張貼留言

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