OpenGL ES GLKit初探

#GLKit框架 GLKit框架的設計目的是爲了簡化OpenGL/OpenGL ES的應用開發。它的出現加快了OpenGL或OpenGL ES應用程序的開發。使用數學庫、背景紋理加載,預先建立着色器效果,以及標準視圖和視圖控制器來實現渲染循環。 GLKit框架提供了功能和類,能夠減小建立新的基於着色器的應⽤程序所需的⼯做量, 或者支持依賴早期版本的OpenGL ES或OpenGL提供的固定函數頂點或⽚段處理的現有 應用程序。數組

#GLKView 、GLKViewController 在iOS平臺下,蘋果給咱們封裝好了GLKViewController這樣的一個類,簡化了咱們經過OpenGL ES渲染圖形的工做。bash

//初始化GLKView
- (instancetype)initWithFrame:(CGRect)frame context:(EAGLContext *)context;

//顏色渲染緩衝區格式
@property (nonatomic) GLKViewDrawableColorFormat drawableColorFormat;

//深度渲染緩衝區格式
@property (nonatomic) GLKViewDrawableDepthFormat drawableDepthFormat;

//模板渲染緩衝區格式
@property (nonatomic) GLKViewDrawableStencilFormat drawableStencilFormat;

//多重採樣緩衝區格式
@property (nonatomic) GLKViewDrawableMultisample drawableMultisample;

//幀緩衝區屬性
@property (nonatomic, readonly) NSInteger drawableWidth;    //緩衝區對象寬度
@property (nonatomic, readonly) NSInteger drawableHeight;  //緩衝區對象高度

/**
*  GLKViewDelegate必須實現的方法:在這個方法裏進行繪圖
* - (void)glkView:(GLKView *)view drawInRect:(CGRect)rect;
*/
@property (nullable, nonatomic, assign) IBOutlet id <GLKViewDelegate> delegate;

//將底層的FrameBuffer對象綁定到OpenGL ES
- (void)bindDrawable;

//刪除視圖FrameBuffer對象 
- (void)deleteDrawable;

//繪製視圖內容並將其做爲圖像對象返回
@property (readonly, strong) UIImage *snapshot;

//布爾,指定視圖是否響應使得視圖內容無效的信息
@property (nonatomic) BOOL enableSetNeedsDisplay;

//當即重繪
- (void)display;
複製代碼

#GLKTextureInfo 使用GLKTextureLoader能夠建立加載OpenGL紋理信息:框架

GLKTextureInfo *textureInfo = [GLKTextureLoader textureWithContentsOfFile:filePath options:nil error:nil];

GLKTextureInfo有如下信息:
    GLuint                      name;        //紋理名稱
    GLenum                      target;    //紋理綁定的目標
    GLuint                      width;        //加載紋理的寬度
    GLuint                      height;        //加載紋理的高度
    GLKTextureInfoAlphaState    alphaState;  //加載紋理中alpha狀態
    GLKTextureInfoOrigin        textureOrigin;  //加載紋理的原點位置
    BOOL                        containsMipmaps;  //布爾值,加載的紋理是否包含mip貼圖
複製代碼

#GLKBaseEffect GLKBaseEffect是OpenGL ES提供的一種簡單的光照/着色系統,用於基於着色器的渲染。 #####配置光照ide

//爲基元兩側計算光照 (系統去作,開發者來控制開關)
@property (nonatomic, assign)         GLboolean                          lightModelTwoSided;
//計算渲染圖元光照使⽤的材質屬性
@property (nonatomic, readonly)       GLKEffectPropertyMaterial          *material; 
//環境顏⾊色,應⽤用效果渲染的全部圖元
@property (nonatomic, assign)         GLKVector4                         lightModelAmbientColor;

//第一、二、3個光照屬性
GLKEffectPropertyLight              *_light0, *_light1, *_light2;
複製代碼

#####配置紋理函數

//配置第一、2個紋理
GLKEffectPropertyTexture            *_texture2d0, *_texture2d1;
//紋理應用於渲染圖元的順序
NSArray                             *_textureOrder;
複製代碼

#####配置霧化性能

GLKEffectPropertyFog                *_fog;
複製代碼

#####配置顏色信息ui

//表示計算光照與材質交互時是否使用顏色頂點屬性
@property (nonatomic, assign)         GLboolean                          colorMaterialEnabled;
//是否使用常量顏色
@property (nonatomic, assign)         GLboolean                          useConstantColor; 
//不提供每一個頂點顏色數據時使用常量顏⾊
@property (nonatomic, assign)         GLKVector4                         constantColor; 
複製代碼

#####準備繪製效果atom

- (void) prepareToDraw;    //準備繪製效果(必須在繪製前寫上)
複製代碼

#下面演示使用GLKit來畫一個圖片到屏幕上spa

配置環境

//配置環境
- (void)setupUpEnv {
    //初始化上下文
    context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];

    if (context == nil) {
        NSLog(@"content create fail");
        return;
    }
    
    [EAGLContext setCurrentContext:context];
    
    //獲取GLKView 設置context
    GLKView * view = (GLKView *)self.view;
    view.context = context;
    view.delegate = self;
    
    //配置視圖建立的渲染緩衝區
    view.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;
    view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
    
    //配置背景顏色
    glClearColor(0, 1, 1, 1);
}
複製代碼

###配置頂點數據設計

// 設置頂點數據數組(頂點座標、紋理座標)
- (void)setUpVertexData {
    
        //頂點數據和紋理數據都存在一個數組中 ,6個頂點,每五個數據 前三個爲xyz頂點座標  後兩個爲紋理座標st
    GLfloat vertexData [] = {
        0.6, -0.5, 0.0f,    1.0f, 0.0f, //右下
        0.6, 0.5, -0.0f,    1.0f, 1.0f, //右上
        -0.6, 0.5, 0.0f,    0.0f, 1.0f, //左上
        
        0.6, -0.5, 0.0f,    1.0f, 0.0f, //右下
        -0.6, 0.5, 0.0f,    0.0f, 1.0f, //左上
        -0.6, -0.5, 0.0f,   0.0f, 0.0f, //左下
    };
    
    //將頂點數據copyj到頂點緩衝區 : 這樣作會提早分配一塊顯存,將頂點數據copy進去,這樣能夠性能更高
    GLuint bufferID;
    glGenBuffers(1, &bufferID);         //建立頂點緩衝區的標識符ID
    glBindBuffer(GL_ARRAY_BUFFER, bufferID);    //綁定頂點緩衝區
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW); //將頂點數據copy到頂點緩衝區
    
    
    
    
    /**打開讀取通道(默認是關閉的,這一步是必需要寫的)
     方法簡介 : 上傳頂點數據到顯存的方法(設置合適的方式從buffer裏面讀取數據)
         glVertexAttribPointer(GLuint indx , GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *ptr)
     * 參數列表:
     * indx :指定要修改的頂點屬性索引值 :好比 GLKVertexAttribPosition表明頂點 GLKVertexAttribTexCoord0表明紋理
     * size :每次讀取的數量 (如position是由3個(x,y,z)組成,而顏色是4個(r,g,b,a),紋理則是2個.)
     * type :指定數組中每一個組件的數據類型。可用的有GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT,GL_UNSIGNED_SHORT, GL_FIXED, 和 GL_FLOAT,初始值爲GL_FLOAT。
     * normalized :指定當被訪問時,固定點數據值是否應該被歸一化(GL_TRUE)或者直接轉換爲固定點值(GL_FALSE)
     * stride :指定連續頂點屬性之間的偏移量。若是爲0,那麼頂點屬性會被理解爲:它們是緊密排列在一塊兒的。初始值爲0
     * ptr :指定一個指針,指向數組中第一個屬性組件
     */
    
    //頂點座標數據
    glEnableVertexAttribArray(GLKVertexAttribPosition);
    /** 每次讀3個數據,即x y z。 頂點偏移量爲5:
    * 第一個頂點從下標0開始,第二個頂點從下標5開始,以此類推。。。
    * (GLfloat *)NULL + 0 :表示首次讀取的位置,由於此時讀取是從顯存讀的  因此不能用數組地址去取  (GLfloat *)NULL表示首地址
    */
    glVertexAttribPointer(GLKVertexAttribPosition , 3, GL_FLOAT,GL_FALSE, 5, (GLfloat *)NULL + 0);
    
    //紋理座標數據
    glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
    glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, 5, (GLfloat *)NULL + 3);
}
複製代碼

###配置頂點數據

//配置紋理
- (void)setUpTexture {
    NSString * filePath = [[NSBundle mainBundle] pathForResource:@"memory" ofType:@"jpg"];
    
    //由於紋理座標和屏幕座標是須要翻轉的,因此這裏須要配置一下映射關係
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:@(1),GLKTextureLoaderOriginBottomLeft, nil];
    
    GLKTextureInfo * textureInfo = [GLKTextureLoader textureWithContentsOfFile:filePath options:options error:nil];
    
    //使用 GLKBaseEffect 完成着色器的工做
    cEffect = [[GLKBaseEffect alloc] init];
    cEffect.texture2d0.enabled = GL_TRUE;
    cEffect.texture2d0.name = textureInfo.name;
}
複製代碼

###GLKViewDelegate開始繪圖

#pragma mark - GLKViewDelegate
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
    glClear(GL_COLOR_BUFFER_BIT);
    
    //重要的一步!!!
    [cEffect prepareToDraw];
    
    //開始繪製
    glDrawArrays(GL_TRIANGLES, 0, 6);
}
複製代碼

###viewDidLoad裏依次調用

[self setupUpEnv];
    [self setUpVertexData];
    [self setUpTexture];
複製代碼

運行效果以下:

image.png
相關文章
相關標籤/搜索