前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >iOS开发-OpenGL ES入门教程4

iOS开发-OpenGL ES入门教程4

作者头像
落影
发布2018-04-27 14:57:49
1.2K0
发布2018-04-27 14:57:49
举报
文章被收录于专栏:落影的专栏落影的专栏

教程

OpenGL ES入门教程1-Tutorial01-GLKit

OpenGL ES入门教程2-Tutorial02-shader入门

OpenGL ES入门教程3-Tutorial03-三维变换

这次我们用GLKit,更简单的实现图形变换、纹理贴图、着色、深度测试(代码在这)。

OpenGL ES系列教程在这里

OpenGL ES系列教程的代码地址 - 你的star和fork是我的源动力,你的意见能让我走得更远。

效果展示

核心思路

使用GLKit来进行图形变换、纹理贴图加载、深度测试,用GLKBaseEffect来管理纹理贴图和进行着色。

具体细节

1、顶点属性
代码语言:javascript
复制
typedef NS_ENUM(GLint, GLKVertexAttrib)
{
    GLKVertexAttribPosition,
    GLKVertexAttribNormal,
    GLKVertexAttribColor,
    GLKVertexAttribTexCoord0,
    GLKVertexAttribTexCoord1
} NS_ENUM_AVAILABLE(10_8, 5_0);

GLKEffects用到的顶点属性已经定义好,使用时直接用枚举量赋值。如下图,直接对顶点的位置、颜色、纹理坐标进行赋值。

代码语言:javascript
复制
    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中,仅仅需要如下三行代码,就可以完成纹理的加载。

代码语言:javascript
复制
    //纹理
    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赋值给着色器。

代码语言:javascript
复制
    //着色器
    self.mEffect = [[GLKBaseEffect alloc] init];
    self.mEffect.texture2d0.enabled = GL_TRUE;
    self.mEffect.texture2d0.name = textureInfo.name;
3、图形变换

在OpenGL ES里面,图形变换的表现形式就是矩阵操作,GLKit也提供了很多矩阵操作函数。

代码语言:javascript
复制
    //初始的投影
    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是平移变换

代码语言:javascript
复制
/**
 *  场景数据变化
 */
- (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);开启深度测试。

代码语言:javascript
复制
    //新建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即可。

代码语言:javascript
复制
/**
 *  渲染场景代码
 */
- (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的三维图形变换和光照等,这部分更多的是数学知识和物理知识,代码一般都很简单;这部分比前面的都难,但是因为知道哪里缺失,虽然不懂,但是不慌,只是有点难受。

最后的感想,计算机图形学和线性代数毕竟是基础,自己多花点时间学习,培养为核心竞争力非常不错。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016.04.06 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 教程
  • 效果展示
  • 核心思路
  • 具体细节
    • 1、顶点属性
      • 2、纹理
        • 3、图形变换
          • 4、深度测试
          • 总结
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档