OpenGL ES 入門: GLKit應用加載圖片

控制器使用GLKViewController數組

//.h文件
#import <UIKit/UIKit.h>
#import <GLKit/GLKit.h>

@interface ViewController : GLKViewController

@end

//.m文件
#import <OpenGLES/ES3/gl.h>
#import <OpenGLES/ES3/glext.h>

@interface ViewController ()

@end

@implementation ViewController
{
    EAGLContext *_content;//上下文
    GLKBaseEffect *effect;//繪製工具類
}
複製代碼

1.初始化上下文&設置當前上下文緩存

- (void)setBaseContent{
    //creat context
    _content = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
    if (!_content){
        NSLog(@"content failed");
    }
    //set context
    [EAGLContext setCurrentContext: _content];
    //view 關聯context
    //注意:ViewController在storyBoard內,其view類型修已經改成了GLKView
    GLKView *glkView = (GLKView *)self.view;
    glkView.context = _content;
    //清屏顏色
    glClearColor(0.5, 0.5, 0.5, 1.0);
}
複製代碼

在初始化context時,咱們須要選擇咱們使用的OpenGL ES的版本,分別有以下幾種:bash

kEAGLRenderingAPIOpenGLES1 = 1, 固定管線
     kEAGLRenderingAPIOpenGLES2 = 2,
     kEAGLRenderingAPIOpenGLES3 = 3,
複製代碼

EAGLContext是蘋果iOS平臺下實現OpenGL ES渲染層。其中kEAGLRenderingAPIOpenGLES1相似前幾篇文章說的固定管線。而kEAGLRenderingAPIOpenGLES2和kEAGLRenderingAPIOpenGLES3,在這裏使用哪一個,區別不大,只是版本不一樣而已。工具

下面須要配置視圖建立的渲染緩衝區,以及設置背景顏色性能

glkView.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;
glkView.drawableDepthFormat = GLKViewDrawableDepthFormat24;
複製代碼

drawableColorFormat: 顏色緩衝區格式 在OpenGL ES中有一個緩存區,它用以存儲在屏幕中顯示的顏色。你可使用其屬性設置緩衝區中的每一個像素的顏色格式。 GLKViewDrawableColorFormatRGBA8888 = 0 默認值,緩衝區的每一個像素的最小組成部分(RGBA)使用8個bit,(因此每一個像素4個字節, 4*8個bit) GLKViewDrawableColorFormatRGB565 若是你的APP容許更小範圍的顏色,便可設置這個。會讓你的APP消耗更小的資源(內存和處理時間)ui

drawableDepthFormat: 深度緩存區格式 GLKViewDrawableDepthFormatNone = 0, 意味着徹底沒有深度緩衝區 GLKViewDrawableDepthFormat16, GLKViewDrawableDepthFormat24, 若是你要使用這個屬性(通常用於3D遊戲),你應該選擇GLKViewDrawableDepthFormat16或GLKViewDrawableDepthFormat24。這裏的差異是使用GLKViewDrawableDepthFormat16將消耗更少的資源spa

加載紋理數據(使用GLBaseEffect)指針

使用本地圖片做爲紋理code

- (void)loadTexture{
    //讀取圖片紋理
    NSString *filePath = [[NSBundle mainBundle] pathForResource: @"summerDay" ofType: @"png"];
    //設置紋理參數
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: @(1), GLKTextureLoaderOriginBottomLeft, nil];
    //紋理信息類
    GLKTextureInfo *texInfo = [GLKTextureLoader textureWithContentsOfFile: filePath options:options error:nil];
    //GLKit 提供GLKBaseEffect 完成着色器工做(頂點/片元)
    effect = [[GLKBaseEffect alloc] init];
    effect.texture2d0.enabled = GL_TRUE;
    effect.texture2d0.name = texInfo.name;
}
複製代碼

注意: 在設置紋理參數的時,須要注意一點,紋理座標默認左下角爲原點(0,0),而iOS座標系中,默認手機屏幕的左上角爲原點(0,0),因此須要特別注意這一點,須要設置GLKTextureLoaderOriginBottomLeft,否則圖片顯示的時候,會發生翻轉。orm

加載頂點&紋理數據

設置繪製的頂點/紋理數據

- (void)setDrawContent{
    //1.設置頂點數組
    GLfloat vertexData[] = {
        0.5, -0.5, 0.0f,    1.0f, 0.0f, //右下
        0.5, 0.5, -0.0f,    1.0f, 1.0f, //右上
        -0.5, 0.5, 0.0f,    0.0f, 1.0f, //左上
        0.5, -0.5, 0.0f,    1.0f, 0.0f, //右下
        -0.5, 0.5, 0.0f,    0.0f, 1.0f, //左上
        -0.5, -0.5, 0.0f,   0.0f, 0.0f, //左下
    };
    //2.開闢頂點緩衝區
    //建立頂點緩存區標識符ID
    GLuint bufferId;
    glGenBuffers(1, &bufferId);
    //綁定頂點緩存區
    glBindBuffer(GL_ARRAY_BUFFER, bufferId);
    //將頂點數組的數據copy到頂點緩存區中(GPU顯存中)
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);
    
    //3.打開屬性通道讀取對應數據.
    //頂點數據
    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (GLfloat *)NULL + 0);
    //紋理數據
    glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
    glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (GLfloat *)NULL + 3);
}
複製代碼
  • 這個案例中,咱們把頂點座標、紋理座標放在同一數組中,也能夠分開,可是爲了簡化代碼量,因此選擇放在一塊兒寫。
  • 開闢頂點緩衝區,主要目的是爲了追求性能更高,提早分配一塊顯存,將頂點數據預先傳入到顯存中,而關於頂點相關的計算都是在GPU中進行的,因此這樣性能有了很大的提升。
  • 方法glVertexAttribPointer表示上傳頂點數據到顯存的方法,即設置合適的方式從buffer裏讀取數據。

參數1: 指定要修改的屬性的索引值
參數2: 每次讀取數量(如position是由3個(x,y,z)組成,而顏色是4個(r,g,b,a),紋理則是2個.)
參數3: 指定數組中每一個組件的數據類型。可用的符號常量有GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FIXED, 和 GL_FLOAT,初始值爲GL_FLOAT。
參數4: 指定當被訪問時,固定點數據值是否應該被歸一化(GL_TRUE)或者直接轉換爲固定點值(GL_FALSE)
參數5: 指定連續頂點屬性之間的偏移量。若是爲0,那麼頂點屬性會被理解爲:它們是緊密排列在一塊兒的。初始值爲0 參數6: 指定一個指針,指向數組中第一個頂點屬性的第一個組件。初始值爲0

上述代碼中,對於頂點來講,每次讀取3個,數據類型爲浮點型,偏移量即讀取下一組頂點數據,須要移動5個位置,頂點讀取位置對應從數組的一開始讀取,因此最後一個參數寫成(GLfloat *)NULL + 0,這裏這樣的寫法是爲了方便讀者理解,也能夠直接寫成NULL。因此對於紋理的最後一個參數寫成(GLfloat *)NULL + 3也不難理解。

注意點:

在iOS中,默認狀況下,出於性能考慮,全部頂點着色器的屬性(Attribute)變量都是關閉的,意味着,頂點數據在着色器(服務端)是不可用的。即便你已經使用glBufferData方法,將頂點數據從內存拷貝到頂點緩衝區中(GPU顯存中); 因此,必須由glEnableVertexAttribArray方法打開通道,指定訪問屬性,才能讓頂點着色器可以訪問到從CPU複製到GPU的數據。 注意: 數據在GPU端是否可見,即着色器可否讀取到數據,由是否啓用了對應的屬性決定,這就是glEnableVertexAttribArray的功能,容許頂點着色器讀取GPU(服務端)數據。 GLKVertexAttribPosition, // 頂點 GLKVertexAttribNormal, // 法線 GLKVertexAttribColor, // 顏色 GLKVertexAttribTexCoord0, // 紋理 GLKVertexAttribTexCoord1

繪製視圖的內容

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
    //1.清除顏色緩存區
    glClear(GL_COLOR_BUFFER_BIT);
    //2.準備繪製
    [cEffect prepareToDraw];
    //3.開始繪製
    glDrawArrays(GL_TRIANGLES, 0, 6);
}
複製代碼

OK,案例內容結束,下面看實現效果(其實就是咱們平時用UIImageView加載一張圖片而已)

相關文章
相關標籤/搜索