iOS开发-OpenGL ES入门教程1

作者: 落影loyinglin | 来源:发表于2016-03-25 16:29 被阅读38594次

    前言

    这里是一篇新手教程,环境是Xcode7+OpenGL ES 2.0,目标写一个OpenGL ES的hello world
    OpenGL ES系列教程在这里
    OpenGL ES系列教程的代码地址

    你的star和fork是我的源动力,你的意见能让我走得更远

    核心思路

    通过GLKit,尽量简单地实现把一张图片绘制到屏幕。

    效果展示

    具体细节

    1、新建OpenGL ES上下文

    - (void)setupConfig {
        //新建OpenGLES 上下文
        self.mContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; //2.0,还有1.0和3.0
        GLKView* view = (GLKView *)self.view; //storyboard记得添加
        view.context = self.mContext;
        view.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;  //颜色缓冲区格式
        [EAGLContext setCurrentContext:self.mContext];
    }
    

    GLKView* view = (GLKView *)self.view;这里需要在storyboard里面把view的类设置成GLKView,其他代码是OpenGL ES上下文的创建。

    2、顶点数组和索引数组

    //顶点数据,前三个是顶点坐标,后面两个是纹理坐标
        GLfloat squareVertexData[] =
        {
            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, //左下
        };
    
    

    顶点数组里包括顶点坐标,OpenGLES的世界坐标系是[-1, 1],故而点(0, 0)是在屏幕的正中间
    纹理坐标系的取值范围是[0, 1],原点是在左下角。故而点(0, 0)在左下角,点(1, 1)在右上角。
    索引数组是顶点数组的索引,把squareVertexData数组看成4个顶点,每个顶点会有5个GLfloat数据,索引从0开始。

    3、顶点数据缓存

        //顶点数据缓存
        GLuint buffer;
        glGenBuffers(1, &buffer);
        glBindBuffer(GL_ARRAY_BUFFER, buffer);
        glBufferData(GL_ARRAY_BUFFER, sizeof(squareVertexData), squareVertexData, GL_STATIC_DRAW);
        
        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);
    

    这是本章节的核心内容

    • glGenBuffers申请一个标识符
    • glBindBuffer把标识符绑定到GL_ARRAY_BUFFER
    • glBufferData把顶点数据从cpu内存复制到gpu内存
    • glEnableVertexAttribArray 是开启对应的顶点属性
    • glVertexAttribPointer设置合适的格式从buffer里面读取数据

    4、纹理贴图

    
    - (void)uploadTexture {
        //纹理贴图
        NSString* filePath = [[NSBundle mainBundle] pathForResource:@"for_test" ofType:@"jpg"];
        NSDictionary* options = [NSDictionary dictionaryWithObjectsAndKeys:@(1), GLKTextureLoaderOriginBottomLeft, nil];//GLKTextureLoaderOriginBottomLeft 纹理坐标系是相反的
        GLKTextureInfo* textureInfo = [GLKTextureLoader textureWithContentsOfFile:filePath options:options error:nil];
        //着色器
        self.mEffect = [[GLKBaseEffect alloc] init];
        self.mEffect.texture2d0.enabled = GL_TRUE;
        self.mEffect.texture2d0.name = textureInfo.name;
    }
    
    • GLKTextureLoader读取图片,创建纹理GLKTextureInfo
    • 创建着色器GLKBaseEffect,把纹理赋值给着色器

    基础

    代码带了很多注释,百度下相应的概念,会有更多解释。
    如果对OpengGL ES感兴趣,但是却毫无图形学基础的,可以看看LearnOpenGL教程

    思考题

    • 1、代码中有6个顶点坐标,能否使用更少的顶点显示一个图像?
    • 2、顶点缓存数组可以不用glBufferData,要如何实现?
    • 3、如果把这个图变成左右两只对称的熊猫,该如何改?

    这里可以下载demo代码。

    思考题答案

    思考题1:
    可以使用四个顶点,绘制2个三角形 的6个顶点中有2个是重复的,使用索引可以减少重复。

    思考题2:
    顶点缓存数组可以不用glBufferData,要如何实现?顶点数组可以通过glBufferData放入缓存,也可以直接通过glVertexAttribPointer最后一个参数,直接把顶点数组从CPU传送到GPU。区别:glBufferData里面的顶点缓存可以复用,glVertexAttribPointer是每次都会把顶点数组从CPU发送到GPU,影响性能。

    思考题3
    如果把这个图变成左右两只对称的熊猫,该如何改?把屏幕切分成4个三角形,左边两个三角形同上,右边两个三角形的纹理坐标的x值调整即可。

    一个热血青年想在业余时间做更多的尝试,做一些能帮助别人也能受惠自己的事情。
    思来想去,决定延续现在写文章的思路——用自己的经历和知识给职场填坑,让人少走弯路。

    相关文章

      网友评论

      • 7136a1c01300:大佬,你的代码我fork之后也下载不下来啊
        落影loyinglin:@7136a1c01300 工程确实比较大,推荐用命令行,git clone一下
      • kevinlishuai:思考题一:
        可以将顶点数据改为如下所示:
        GLfloat vertexData[] =
        {
        0.5, 0.5, -0.0f, 1.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, //左下
        };

        绘制模式改为: glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
        kevinlishuai:@布拉德皮蛋 你看下顶点数组 和我的 是否一致, GL_TRIANGLE_STRIP 这是模式是绘制连续的三角形
        7e12bf0a918f:这样画出来一个三角形
      • kevinlishuai:思考题二:如果 “直接通过glVertexAttribPointer最后一个参数,直接把顶点数组从CPU传送到GPU”,请问最后一个参数怎么填?
      • Stroman:兄弟我决定先学习你的教程。
      • 3d0eb8334cdd:你好 大佬,我用opengles画出的图和我想要的上下颠倒 可能是怎么回事,你遇到过么,请指教
        落影loyinglin:@海底_捞月 纹理坐标搞反了
      • Q以梦为马:学习了, 多谢大佬:smile:
      • 031856a96170:大神你好,有个问题咨询一下,我们现在需要做一个美妆的demo,人脸关键点跟踪是找的第三方的,现在需要在关键部位做效果,比如把眼睛放大,贴上睫毛,加上美瞳,瘦脸等效果,现在还在技术调研阶段,我之前没接触过OpenGL和GPUImage相关的开发,所以想咨询你一下我说的这些效果,使用GPUImage是否能全部实现?或者说只有部分功能可以实现,其他的必须使用OpenGL ES来完成?
        031856a96170:@落影loyinglin 明白了,多谢指教
        落影loyinglin:@shmmzi GPUImage用来做渲染是足够的,我们也在使用。但是一些特定的需求,还是需要自己在GPUImage的基础上写一些OpenGL ES
      • LX2014:这是我找了好久的资料,感谢作者的分享!
        落影loyinglin:@LX2015 多谢支持
      • 幻想无极:顶点坐标-0-不解
      • 转身一世琉璃白:您好,我想问一下,怎样才能把熊猫周围蓝色的背景变成透明的的呢?我改了glClearColor(0.3f, 0.6f, 1.0f, 0.0f); alpha设为0也不管用。
        Tangdixi:@转身一世琉璃白 你看下把 GLKView 的 layer 的 opaque 是什么值
      • 小沛2016:您好,
        glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (GLfloat *)NULL + 0);
        这个函数的第二个参数 您这里写的是3
        但我再网上看到一钟解析是 每个点的数据个数,我们这里每个点只有x、y2个值所以是2
        然后我把3改成2 感觉是一样的结果
        不知道大神您怎么理解呢?
        小沛2016:@落影loyinglin 大神 stride 不是一个点的属性吗 如果修改了之后 图像变形了啊
        落影loyinglin:@李境沛 你试试修改stride的属性
        落影loyinglin:@李境沛 demo没有用到z轴,所以你填2也行
      • FongG:作者大大您好,非常感谢您的分享。

        最近看了一部分openGL的入门文档,有一个疑惑,iOS 8以后出了Scenekit(库没有看过),在3D模型部分iOS 完全有更加简便的实现方式了。

        请问学习openGL除了对加深对原理的了解,还有Scenekit、ARKit所不具备的功能吗?
        熊皮皮:@Jin_先生 用OpenGL (ES)或Metal等接口,能实现更多功能,比如做通用计算,而不仅仅是图形渲染。SceneKit除了渲染功能,还添加了一些提高开发效率的类
        FongG:@落影loyinglin 感谢您的回复! 但渲染不就是用3D数据生成2D图像的过程吗,难道Scenekit构建3D场景不是用渲染吗
        落影loyinglin:@Jin_先生 图形学原理一致。gl还用于图像渲染
      • 出门右转掘金见:师兄你好,最近打算学图片处理和视频,打算把你的文章撸一遍,还请多多指教
        出门右转掘金见:@落影loyinglin 比如squareVertexData这个数组我就没看懂,基础比较差还请指教一下,这应该补哪一块的知识
        出门右转掘金见:@落影loyinglin 我刚看完你的第一篇文章感觉蒙蒙的,之前没图形处理基础,我需要看LearnOpenGL教程吗?C++基础也要补一补吗
        落影loyinglin:@_夕风 你好,一起学习。
      • 0a2868f025e0:楼主,你那个索引点是在哪个地方设置进去的
      • 0a2868f025e0:顶点数组没搞懂
      • lovelnly:您好,如何绘制对称的图像,我看过您写的思路,但是把屏幕分成4个三角形,我不是很明白,希望您可以具体的说一下!
        Tangdixi:@lovelnly 设置 texture 的 uv 坐标
      • littleDad:在代码里顶点索引和顶点数据是如何一一对应的。简单的说,设置了4个顶点数据后,我是如何确定我的顶点索引顺序是 代码中的 0 ,1,2,1,3,0 还是 其它的 顺序例如 0,1,2,2,3,0 呢?? 我是openGLES 初学者 ,抱歉这里 有疑惑
        落影loyinglin:@Little_Dad 索引的方式 有索引数组
      • 悲秋伤夏:楼主,为啥github不能下载源码
        落影loyinglin:@悲秋伤夏 git clone 。不知道就查下git怎么用吧
        悲秋伤夏:@落影loyinglin 楼主,我是菜鸟,请能给我说一下怎么用命令行呀!多谢楼主
        落影loyinglin:@悲秋伤夏 库比较大,建议用命令行拉
      • 6d9f6aa3a9d4:想请问下 作者是通过哪本书学习OpenGL ES?可否推荐下
        6d9f6aa3a9d4:@落影loyinglin 好的谢谢
        落影loyinglin:@yeBlueColor 在文集的其他文章
        落影loyinglin:@yeBlueColor 看看进阶教程1 有介绍。实践教程也有介绍一本。
      • 纯纯奶油酱:收藏了学习一下
      • Hunter琼:我想问问 能给那个图片 写个点击事件吗??
        落影loyinglin:@Hunter琼 你可以深入思考下 点击的事件是怎么实现的?如果这个view正在运动 如何判断点击进入?
      • 皮皮蟹pipixie:虽然工作年限差不多,但和你差距不是一点半点啊,准备把你所有文章学一遍,加油!!!!!
        落影loyinglin:@皮皮蟹pipixie 加油,我只是把会的写出来了。你如果把会的写出来,也有这么多呢
      • Mr_Chen_df25:你好,请问下你这个顶点索引怎么来的,每个顶点的五个数据怎么计算得来的?
      • youlianchun:应该备注一下OpenGL只支持 顶点、线段、三角形 的渲染,不然刚接触很难搞明白为啥文中squareVertexData是6组数据,为啥采用4组数据时候需要索引数组。
        Tangdixi:@熊皮皮 没记错的话 stripe 是有个奇偶规则 来决定顺序的
        熊皮皮:@youlianchun 四个顶点组成的数组,用glDrawArray TRIANGLE STRIP也能画出矩形,并不需要索引数据。
      • 我有一只小毛驴_从来都不骑:你好,请教一个问题,glVertexAttribPointer这个函数中,后两个函数中的参数是怎么算的,我试着改变最后2个参数,看到的图形是不一样的,但是我一直不明白sizeof(GLfloat) * 5这个值是怎么来的
        我有一只小毛驴_从来都不骑:@YZKMH 已经弄明白了,还是得感谢你
        YZKMH:5个float长度代表一个顶点数据的长度
      • 帅聪哥:一开始对世界坐标和纹理坐标理解挺费劲,但是经过代码测试马上就搞懂了!谢谢落影老师的分享
      • e971db44fc15:这位同志很负责任,教完之后还出思考题!谢谢这位落影老师的无私奉献!:blush::blush:
      • Even3Yu:思考题1:
        - (void)uploadVertexArray {
        //顶点数据,前三个是顶点坐标,后面两个是纹理坐标
        GLfloat squareVertexData[] =
        {
        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, 0.0f, 0.0f, //左下
        };
        GLbyte indices[] =
        {
        0,1,2,
        2,3,0
        };


        //顶点数据缓存
        GLuint buffer;
        glGenBuffers(1, &buffer);
        glBindBuffer(GL_ARRAY_BUFFER, buffer);
        glBufferData(GL_ARRAY_BUFFER, sizeof(squareVertexData), squareVertexData, GL_STATIC_DRAW);

        GLuint texturebuffer;
        glGenBuffers(1, &texturebuffer);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, texturebuffer);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

        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);
        }

        - (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
        glClearColor(0.3f, 0.6f, 1.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        //启动着色器
        [self.mEffect prepareToDraw];
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0);
        }

        思考题3:
        GLfloat squareVertexData[] =
        {
        1, -0.5, 0.0f, 1.0f, 0.0f, //右下
        1, 0.5, -0.0f, 1.0f, 1.0f, //右上
        0.0, 0.5, 0.0f, 0.0f, 1.0f, //中上
        0.0, -0.5, 0.0f, 0.0f, 0.0f, //中下

        -1, 0.5, 0.0f, 0.0f, 1.0f, //左上
        -1, -0.5, 0.0f, 0.0f, 0.0f, //左下
        0.0, -0.5, 0.0f, 1.0f, 0.0f, //中下
        0.0, 0.5, 0.0f, 1.0f, 1.0f, //中上
        };

        GLbyte indices[] =
        {
        0,1,2,
        2,3,0,
        4,5,6,
        6,7,4
        };
        修改下count

        glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_BYTE, 0);
        落影loyinglin:@lmx20062103 :+1:
        lmx20062103: GLfloat squareVertexData[] =
        {
        1, -0.5, 0.0f, 0.0f, 0.0f, //右下
        1, 0.5, -0.0f, 0.0f, 1.0f, //右上
        0.0, 0.5, 0.0f, 1.0f, 1.0f, //中上
        0.0, -0.5, 0.0f, 1.0f, 0.0f, //中下

        -1, 0.5, 0.0f, 0.0f, 1.0f, //左上
        -1, -0.5, 0.0f, 0.0f, 0.0f, //左下
        0.0, -0.5, 0.0f, 1.0f, 0.0f, //中下
        0.0, 0.5, 0.0f, 1.0f, 1.0f, //中上
        };
        即可对称。
      • 4b3bb5eef806:话说感觉 glkView 的代理 glkView:drawInRect 代码可能会让人看起来很奇怪,难道我的 prepareToDraw 一定要放在那个位置?应该不是吧,所以感觉最好把prepareToDraw放在最开始的位置,只是要先让着色器准备绘制,然后开始清除程指定颜色,然后开始从给定的顶点和片段信息绘制。不知道我理解的对不对
        熊皮皮:@Hurricancee 如果你只有一个glProgram,就像这个文档一样(只有一个GLKBaseEffect,它包含一个glProgram),在初始化EAGLContext后只调一次prepareToDraw是可以的。但是,有多个Program切换时,就得在每次绘制时prepareToDraw(它内部用了glUseProgram)成当前Program才能接收到正确的uniform等状态设置
      • ck2016:弱弱的问一下,为什么OpenGL都用三角形来绘图
        熊皮皮:@ck2016 因为OpenGL ES不支持直接使用多边形数据,只能用三角形模拟多边形。而OpenGL是直接支持多边形的,因为PC的显卡性能更强。
        0977845e140b:三个点确定一个面
      • 47e23cac8e40:对称小熊的顶点数组和索引数组如下:
        //顶点数组,前三个是顶点坐标,后面两个是纹理坐标
        GLfloat squareVertexData[] =
        {
        0.5, -0.5, 0.0f, 0.0f, 0.0f, //右下 0
        -0.5, 0.5, 0.0f, 0.0f, 1.0f, //左上 1
        -0.5, -0.5, 0.0f, 0.0f, 0.0f, //左下 2
        0.5, 0.5, 0.0f, 0.0f, 1.0f, //右上 3
        0.0, 0.5, 0.0f, 1.0f, 1.0f, //中上 4
        0.0, -0.5, 0.0f, 1.0f, 0.0f, //中下 5
        0.0, 0.5, 0.0f, 1.0f, 1.0f, //中上 6
        0.0, -0.5, 0.0f, 1.0f, 0.0f, //中下 7
        };

        //顶点索引
        GLuint indices[] =
        {
        1, 4, 5,
        5, 2, 1,
        0, 3, 6,
        6, 7, 0,
        };
      • zhao1zhihui:大神 有没有opengl 或者图像学入门的书籍 你写的opengl看了几篇 还是不懂 完全没接触过
        zhao1zhihui:@落影loyinglin 在你的简书文里面看见了 谢谢啊
        落影loyinglin:@zhao1zhihui learnOpenGL,你搜一下这个网站
      • 大胆造轮子:squareVertexData 这个数组是按什么规则写的啊?
        熊皮皮:@大胆造轮子 根据三角形的绘制顺序来定义的
      • Terrnce:楼主,您好,请问有没有OpenGL iOS方面的入门书籍推荐一下?
        落影loyinglin:@陈伟鑫 进阶教程1有书介绍
      • 暴走的西瓜:你好.对这些基础知识感觉有点看不懂.有基础点资料或者书籍么
      • PPFSaber:首先 O(∩_∩)O谢谢楼主 分享 很好的文章
        不过这里 和你的代码 有点差异 希望楼主在文章中加上
        1.缺少GLKView 的代理设置 设置storyboard 的时候和多时候不会去设置这个代理
        GLKView *view = (GLKView *)self.view;
        view.delegate = self;
        2.以及代理方法的实现
        /**
        * 渲染场景代码
        */
        - (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
        glClearColor(0.3f, 0.6f, 1.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        //启动着色器
        [self.mEffect prepareToDraw];
        glDrawElements(GL_TRIANGLES, self.mCount, GL_UNSIGNED_INT, 0);
        }
        Hunter琼:@tbago 这个框架 主要用在游戏中 在常规应用中 在那个方面用 第一次听说这个东西
        tbago:delegate不是必须的,可以参照博主Github上的代码。修改ViewController继承自GLKViewController即可。
        一叶__知秋:兄弟多亏你,我照着写结果黑屏了,应该加上代理,我就奇怪这个方法在哪调用的
      • slimsallen:没接触过 感觉学起来很吃力 是不是需要买本书 先看着
        落影loyinglin:@音乐君 可以先买一本书看看。
      • 3727939b0d64:你好,第一个demo运行之后图片渲染的区域为黑色,只有左上角的imageview,请问是什么问题
      • 路有点颠簸:你好,请问下世界坐标和纹理坐标系什么关系,你之前说到OpenGLES的世界坐标系是[-1, 1],故而点(0, 0)是在屏幕的正中间,然后又说原点是在左下角,请问这是什么意思
        落影loyinglin:@罗罗罗罗亚索 纹理坐标用来表示纹理(图片);顶点用的是浮点数;
        路有点颠簸:@落影loyinglin 你好,squareVertexData的坐标数组中,顶点坐标分别是x,y,z,是不是z都是0?设为其他值就看不见了,还有在三维坐标系中我们的屏幕的4个顶点距离每条轴都是1?所有你写的每个顶点都是零点几,还有一个就是纹理坐标有什么用,还是没能理解,谢谢
        落影loyinglin:@罗罗罗罗亚索 纹理坐标和世界坐标 没有关系
      • 践行者: :joy: 原来是索引绘图 。。 索引绘制能够节省存储空间,共享顶点属性数据,但存在的限制时共享的数据的属性时相同的。当我们需要为同一个顶点指定不同的属性,例如颜色和法向量时,索引绘制无法满足需求,这时候需要使用顶点数组为同一个顶点指定不同属性。
        Tangdixi:@践行者 对!normal 这个坑很烦,当初还想看看可不可以写动态计算 vertex 法向量的 …
        落影loyinglin:@践行者 是的。
      • 拭目以待_:大神 我想问下图片是1:1的 为什么显示出来是个长方形, 还有图片的大小是在哪里设置的?
        落影loyinglin:@拭目以待_ 因为视口是长方形
      • 5900bf190246:感觉要学好这个 至少要有计算机图形学基础、c++等功底才行啊
        落影loyinglin:@dengchenglin 图形学 就行
      • 5900bf190246:学这个需要什么样的基础啊
      • 梁小升升:我在storyboard里添加了一个GLKView,要怎么设置在这个新建的View里渲染?
        落影loyinglin:@梁小升升 先设置viewcontroller然后设置view
      • 小沛2016:您好。你githtb里的demo 可以做成和你文章的名字一样吗
      • 899e2d74bdeb:顶点缓存数组可以不用glBufferData,要如何实现?关于这个思考题,最后的绘制api是不是要用glDrawArrays替代glDrawElements这个?
        落影loyinglin:@哎疯 不是。如果不用这个API 那么则是再用到的时候再上传
      • 困惑困惑困惑:GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (GLfloat *)NULL + 3这是什么意思呢,大神
        熊皮皮:@帅聪哥 因为他前面定义数组时是x y z,s t这种形式,前三个是顶点坐标,后两个是纹理坐标,所以纹理坐标得跳过x y z三个数
        帅聪哥:为什么顶点的后面为0,纹理的却要加上3呢!
        落影loyinglin:@困惑困惑困惑 上传纹理坐标
      • 此晨:你写的地方 看懂了,不明白 openGL坐标系正方向在哪,不明白怎么通过 设置 顶点坐标系 和纹理坐标 决定 图像在屏幕显示的位置
        落影loyinglin:@Captain_FL 可以接着看后面的坐标变换
      • alanzhangg:opengl es 不是最多三个点定一个平面吗?而且后面的纹理坐标怎么只有两位?
        落影loyinglin:@alanzhangg 你发的这段话是normal,不是纹理。
        alanzhangg:and the second three have the normal of the face (the normal being a line that specifies the direction the face is aiming and that is used to calculate how the face is illuminated). If the normal is facing a light source, it will be lit; if away, it would be in shadow. 这是《pro opengl es for ios》的说法,而且系统生成是三位。估计后一位是零的话不会有什么影响,谢谢作者。
        落影loyinglin:@alanzhangg 纹理坐标是2位
      • 神经骚栋:对不起,我来晚了,相信作者写这个一定很不容易,自身深有体会.2元钱并不能代表着多大的财富,但是代表的我对作者的感激和尊重,我相信,每一个程序猿都是一个传奇!!! :sunglasses:
        落影loyinglin:@神经骚栋 加群吧578734141
        神经骚栋: @落影loyinglin 求带,求带
        落影loyinglin:@神经骚栋 谢谢支持。
      • 神秀:请问es2.0是基于gl3.2么?我看到使用了VAO,还有es2.0分核心模式兼容模式么?
      • 卟师:简书的地址,和github地址 都是你的地址和链接,然后我给你分享出去了,我看见有人举报,在这里跟你道歉.对不起
      • 卟师:你好,我抄了你的文章.所有抄的原文连接都是的简述地址,可能没有标注原作者,在这里跟你道歉
      • f82d5a5c6ea2:您好,请问 OpenGL ES 的顶点坐标必须是三维的吗,我想根据一组二维坐标点构建模型应该怎么实现呢?
        熊皮皮:@Hunter_Mz 可以是二维坐标,有几种办法实现,(1)把attribute声明成vec2,(2)还是声明为vec3,但是attribPointer指定成按照2维读取。这些都是常用的技巧
        落影loyinglin:@Hunter_Mz 可以把z坐标统一为0
      • 45a78c194da0:你好,看了上面的评论,您的意思是上面的OpenGL显示图像是苹果封装过的是嘛。您应该知道GPUImage吧,我想修改GPUImage的底层代码的话,是需要从OpenGL ES的基础开始学么,还是说苹果封装的这些学一下就够了呢,最近需要用到美颜的效果,请教您一下
        落影loyinglin:@沙滩上的鱼 苹果封装的glkit gpuimage没有用
        落影loyinglin:@沙滩上的鱼 苹果封装的glkit gpuimage没有用
        落影loyinglin:@沙滩上的鱼 你可以点开我首页,里面有gpuimage的文集。
      • 紧张的牛排:我的不太了解glEnableVertexAttribArray的作用,我用的时候有没有设置好像没有变化,楼主怎么理解啊,谢谢
        熊皮皮:@紧张的牛排 你不调用glEnableVertexAttribArray,就算上传了数据到OpenGL命令队列,Shader端也不读取数据,结果就是画不出来你要的图形。
        紧张的牛排:@落影loyinglin 好的,谢谢,我再琢磨下
        落影loyinglin:@紧张的牛排 glEnableVertexAttribArray是启用顶点属性,可以看成声明shader语言里面的顶点数组,然后接下来的glVertexAttribPointer是给数组赋值。
      • 茉莉儿:有个问题如何转换 opengles中的坐标和屏幕坐标呢
        茉莉儿:哦哦 好像懂了 那还有个问题就是我把图形 画出来了 我怎么把他保存成图片存下来
        落影loyinglin:@茉莉儿 如果是想得到OpenGL ES上的世界坐标到iOS坐标,你得先算出世界坐标显示到视口上面的坐标,然后根据视口的大小和比例,可以转换出iOS的屏幕坐标。
        落影loyinglin:@茉莉儿 屏幕坐标是指的什么坐标?
      • 落影loyinglin:代码中只有四个顶点坐标,如何显示出来一个图像?
        四个顶点,可以绘制2个三角形,两个三角形拼接成一个矩形。三角形内的任意一点,根据顶点坐标插值生成对应的顶点和纹理坐标。
        顶点缓存数组可以不用glBufferData,要如何实现?
        顶点数组可以通过glBufferData放入缓存,也可以直接通过glVertexAttribPointer最后一个参数,直接把顶点数组从CPU传送到GPU。区别:glBufferData里面的顶点缓存可以复用,glVertexAttribPointer是每次都会把顶点数组从CPU发送到GPU,影响性能。
        如果把这个图变成左右两只对称的熊猫,该如何改?
        把屏幕切分成4个三角形,左边两个三角形同上,右边两个三角形的纹理坐标的x值调整即可。
        花果山松鼠:我一开始看你这句话想的是分成4等份,以为是将左右两张图分别分成4等份,然后感觉不太对啊。后头一想,分成4等份是整个屏幕,也就是左右两个图分别分成两个三角形,然后相对于y轴对称,将纹理坐标进行调换就行了。
        陈_某_某:@落影loyinglin 认真负责好同志:+1::+1::+1:
      • 陈_某_某:思考题那三道能公布下答案吗?想了半天也没没思绪
        落影loyinglin:@_iOSer 见下面
      • 无声的叹息:您好,我在iOS上把3840*2160的视频解码成RGB的格式,然后通过glTeximag2D这个函数加载纹理,最后通过调用glkview的那个不断绘制的方法进行绘制,但是最后播放的视频变得很慢,不知道是什么原因,如果你方便的话,可以给吓思路吗? 有看过GPUImage的源码,不过不太懂,是不是解码成YUV格式的会好一些?
        熊皮皮:@无声的叹息 解码性能跟不上,或者是上传数据消耗时间过多,导致掉帧
        无声的叹息:@落影loyinglin 好的,谢谢您抽出时间解答!:blush:
        落影loyinglin:@无声的叹息 GPUImage的有个GPUImageMovie,你可以看看。
      • 陈_某_某:xcode7 模拟器内存占用57M,这个问题怎么回事?是切换上下文的问题吗?
        落影loyinglin:@_iOSer 模拟器是这样的,你用真机测试一次试试,真实的内存应该是在8M左右。附上,苹果官方的介绍:The OpenGL ES support in Simulator should be used to help you get started writing an OpenGL ES app. Never assume that Simulator reflects the real-world performance or the precise capabilities of the graphics processors used in iOS devices. Always profile and optimize your drawing code on a real device。
        陈_某_某:就你这个demo,用模拟器运行
        落影loyinglin:@_iOSer 你是怎么实现的,切换上下文会导致渲染变慢,但是应该不会增加内存。
      • hrscy:请问在 indices 索引数组中,0,1,2,1,3,0分别对应的是那个点呢?
        落影loyinglin:@hrscy indices的意义就是顶点的重复利用,所以indice里面有两个数字是重复的。OpenGL ES是一个四边形(四个顶点)是由两个三角形形成的(六个顶点)。四边形实际上只有四个顶点,为了复用所以采用索引的形式。
        hrscy:@落影loyinglin 那 indices 里面不是有 6 个数字么?如果每个数字对应一个点,那么另外 2 个点表示什么呢?
        落影loyinglin:@hrscy squareVertexData有四个顶点,放在一维数组里面。
      • 1b2ae550dc99:你好,我想问一下,是否需要在不用试图的时候将其上下文置为nil吗?
        熊皮皮:@行进的NSLog 没有多个EAGContext时可以不设置成nil,如果有,比如做多线程绘制,那就得管理好Context,否则GL状态容易乱,导致各种意外现象出现。
        落影loyinglin:@行进的NSLog 理论上是要的。但是实际开发不调用也没有问题。
      • hrscy:请问 OpenGLES 具体应用在哪些场景呢?
        落影loyinglin:@hrscy 如果大学学过图形学 不难。而且我这系列教程都是用的苹果封装过的,很方便
        hrscy:@落影loyinglin 也就是说不用苹果的 CoreAnimation 或其他封装好的框架,自己直接操作底层的 OpenGL ES 对么?那样编码实现会不会更困难呢?
        落影loyinglin:@hrscy 和视频、图像相关的底层大多数都是OpenGL ES的实现,苹果在CoreAnimation也是用的OpenGL ES。我认为在未来的VR热潮和当下的视频直播,OpenGL ES或者图形学是很重要的一块。
      • 明明明Y:最近要用OpenGL画图 已关注!
      • 长青之木:很不错,学习了~

      本文标题:iOS开发-OpenGL ES入门教程1

      本文链接:https://www.haomeiwen.com/subject/kkqdlttx.html