iOS開發-OpenGL ES入門教程4

教程

OpenGL ES入門教程1-Tutorial01-GLKit
OpenGL ES入門教程2-Tutorial02-shader入門
OpenGL ES入門教程3-Tutorial03-三維變換
這次我們用GLKit,更簡單的實現圖形變換、紋理貼圖、著色、深度測試(代碼在這)。

OpenGL ES系列教程在這里
OpenGL ES系列教程的代碼地址 - 你的star和fork是我的源動力,你的意見能讓我走得更遠。

效果展示

核心思路

使用GLKit來進行圖形變換、紋理貼圖加載、深度測試,用GLKBaseEffect來管理紋理貼圖和進行著色。

具體細節

1、頂點屬性

typedef NS_ENUM(GLint, GLKVertexAttrib)
{
    GLKVertexAttribPosition,
    GLKVertexAttribNormal,
    GLKVertexAttribColor,
    GLKVertexAttribTexCoord0,
    GLKVertexAttribTexCoord1
} NS_ENUM_AVAILABLE(10_8, 5_0);

GLKEffects用到的頂點屬性已經定義好,使用時直接用枚舉量賦值。如下圖,直接對頂點的位置、顏色、紋理坐標進行賦值。

    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 8, (GLfloat *)NULL);
    //頂點顏色
    glEnableVertexAttribArray(GLKVertexAttribColor);
    glVertexAttribPointer(GLKVertexAttribColor, 3, GL_FLOAT, GL_FALSE, 4 * 8, (GLfloat *)NULL + 3);
    
    glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
    glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, 4 * 8, (GLfloat *)NULL + 6);

2、紋理

在自定義shader中使用紋理,需要用CoreGraphics把圖像轉換成bitmapdata,再申請紋理內存,把圖像數據傳進去,最后還要釋放bitmapdata。
在GLKit中,僅僅需要如下三行代碼,就可以完成紋理的加載。

    //紋理
    NSString* filePath = [[NSBundle mainBundle] pathForResource:@"for_test" ofType:@"png"];
    NSDictionary* options = [NSDictionary dictionaryWithObjectsAndKeys:@(1), GLKTextureLoaderOriginBottomLeft, nil];
    GLKTextureInfo* textureInfo = [GLKTextureLoader textureWithContentsOfFile:filePath options:options error:nil];

GLKTextureLoaderOriginBottomLeft 參數是避免紋理上下顛倒,原因是紋理坐標系和世界坐標系的原點不同。

最后創建著色器,啟用紋理,把剛剛創建的textureInfo的name賦值給著色器。

    //著色器
    self.mEffect = [[GLKBaseEffect alloc] init];
    self.mEffect.texture2d0.enabled = GL_TRUE;
    self.mEffect.texture2d0.name = textureInfo.name;

3、圖形變換

在OpenGL ES里面,圖形變換的表現形式就是矩陣操作,GLKit也提供了很多矩陣操作函數。

    //初始的投影
    CGSize size = self.view.bounds.size;
    float aspect = fabs(size.width / size.height);
    GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(90.0), aspect, 0.1f, 10.f);
    projectionMatrix = GLKMatrix4Scale(projectionMatrix, 1.0f, 1.0f, 1.0f);
    self.mEffect.transform.projectionMatrix = projectionMatrix;
    
    GLKMatrix4 modelViewMatrix = GLKMatrix4Translate(GLKMatrix4Identity, 0.0f, 0.0f, -2.0f);
    self.mEffect.transform.modelviewMatrix = modelViewMatrix;
    

GLKMatrix4MakePerspective是透視投影變換
GLKMatrix4Translate是平移變換

/**
 *  場景數據變化
 */
- (void)update {
    GLKMatrix4 modelViewMatrix = GLKMatrix4Translate(GLKMatrix4Identity, 0.0f, 0.0f, -2.0f);
    
    modelViewMatrix = GLKMatrix4RotateX(modelViewMatrix, self.mDegreeX);
    modelViewMatrix = GLKMatrix4RotateY(modelViewMatrix, self.mDegreeY);
    modelViewMatrix = GLKMatrix4RotateZ(modelViewMatrix, self.mDegreeZ);
    
    self.mEffect.transform.modelviewMatrix = modelViewMatrix;
}

在場景變換函數里面,GLKMatrix4RotateY是繞Y軸旋轉,其他的分分別是繞X、Z軸旋轉。

4、深度測試

在前面的教程介紹過,開啟深度測試需要分配深度測試的緩沖區,并掛載到相應的幀緩沖區。
在GLKit代碼中,深度測試的開啟十分簡單。
在新建上下文時調用glEnable(GL_DEPTH_TEST);開啟深度測試。

    //新建OpenGL ES 上下文
    self.mContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
    
    GLKView* view = (GLKView *)self.view;
    view.context = self.mContext;
    view.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;
    view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
    
    [EAGLContext setCurrentContext:self.mContext];
    glEnable(GL_DEPTH_TEST);
    

在渲染場景時,glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear參數加入GL_DEPTH_BUFFER_BIT即可。

/**
 *  渲染場景代碼
 */
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
    glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    
    [self.mEffect prepareToDraw];
    glDrawElements(GL_TRIANGLES, self.mCount, GL_UNSIGNED_INT, 0);
}

總結

OpenGL ES的入門已經差不多,后面還有很多很多知識,需要時再學習即可。
總結這幾篇教程花了一個星期左右。
學習過程中有幾部分最難受:

  • 第一部分是OpenGL ES的頂點屬性、紋理貼圖,對頂點到圖形的過程不理解,對OpenGL ES的數據緩存機制不了解,無知容易使人知難而退
  • 第二部分是shader和glsl,glsl無法調試、編譯信息不會查看、語法不懂等等,一個1.0 + 1都會報錯,自己卻莫名其妙,只能通過二分注釋代碼來定位問題,特別讓人泄氣;
  • 第三部分是OpenGL ES的三維圖形變換和光照等,這部分更多的是數學知識和物理知識,代碼一般都很簡單;這部分比前面的都難,但是因為知道哪里缺失,雖然不懂,但是不慌,只是有點難受。

最后的感想,計算機圖形學和線性代數畢竟是基礎,自己多花點時間學習,培養為核心競爭力非常不錯。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容