美文网首页
OpenGles 入门练习(一)

OpenGles 入门练习(一)

作者: 不辣先生 | 来源:发表于2019-04-15 11:42 被阅读0次

    目的:1,为了加深记忆和理解;2,记录疑问以及希望路过大神解答;3,本文为小白文,针对相关API的理解注释希望能给跟我一样的小白一些参考
    主要参照大神的文章:
    iOS开发-OpenGL ES入门教程1
    从零讲解 iOS OpenGL ES 的纹理渲染
    OpenGL顶点坐标与纹理坐标
    顶点缓存对象VBO
    由于本人对于图像学是0理解,对于OpenGL也是只知其名,翻了很多大神的资料还有一些没列出来的是因为找不到浏览记录,在此向各位大佬致谢!!!
    我觉得入门的基本点:1,理解坐标系;2,了解渲染流程;3,熟悉各个api工作职责以及参数意义;
    个人在照着大神文章撸的时候,为了加深对坐标系的理解,对坐标调整做了练习

       //顶点数据,前三个是顶点坐标(x、y、z轴),后面两个是纹理坐标(x,y)
     //GL_TRIANGLE_FAN
        GLfloat vertexData[] = {
            0.5f,0.5f,0.0f,   1.0f,1.0f,//右上
            0.5f,-0.5f,0.0f,  1.0f,0.0f,//右下
            -0.5f,-0.5f,0.0f, 0.0f,0.0f,//左下
            -0.5f,0.5f,0.0f,  0.0f,1.0f, //左上
    
        };
        
    //    GL_TRIANGLE_STRIP
    //    GLfloat vertexData[] = {
    //        0.5f,-0.5f,0.0f,  1.0f,0.0f,//右下
    //        0.5f,0.5f,0.0f,   1.0f,1.0f,//右上
    //        -0.5f,-0.5f,0.0f, 0.0f,0.0f,//左下
    //        -0.5f,0.5f,0.0f,  0.0f,1.0f, //左上
    //
    //    };
    

    上面两组不同的坐标代表的可以用不同的绘制模式得到相同的结果,绘制代码为

    //GL_TRIANGLE_FAN 这个参数为绘制模式
     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);//使用顶点数组绘制图元
    

    下面介绍一种通过顶点索引数组渲染的方式
    // 上下对称
    // GLfloat squareVertexData[] =
    // {
    // 0.5, 0.0, 0.0f, 1.0f, 0.0f, //右中下
    // 0.5, 1, 0.0f, 1.0f, 1.0f, //右上
    // -0.5, 1.0, 0.0f, 0.0f, 1.0f, //左上
    // -0.5, 0, 0.0f, 0.0, 0.0f, //左下
    //
    // -0.5, 0.0, 0.0f, 0.0f, 1.0f, //左上
    // -0.5, -1, 0.0f, 0.0f, 0.0f, //左下
    // 0.5, -1, 0.0f, 1.0f, 0.0f, //右下
    // 0.5, 0.0, 0.0f, 1.0f, 1.0f, //右上
    // };
    //
    // GLbyte indices[] =
    // {
    // 0,1,2,
    // 2,3,0,
    // 4,5,6,
    // 6,7,4
    // };
    在传递数据给GPU的时候要做相应的改变,代码如下

     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
    

    绘制的时候

        glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_BYTE, 0);
    

    疑问:1>如何按照指定的rect渲染,猜测是调整顶点坐标点值的大小?
    2>纹理坐标系原点的位置为纹理的左下角,(1,1)为纹理的右上角,而不是屏幕?(这个我的理解应该是这样的,但不确认)
    下面环节就是API介绍

    GLuint buffer;
    
    
        /*
         创建缓存对象并且返回缓存对象的标示符,第一个为需要创建的缓存数量,第二个为用于存储单一ID或多个ID的GLuint变量或数组的地址
         */
        glGenBuffers(1, &buffer);
        /*
         当缓存对象创建之后,在使用缓存对象之前,我们需要将缓存对象连接到相应的缓存上。
      glBindBuffer()有2个参数:target与buffertarget告诉VBO该缓存对象将保存顶点数组数据还是索引数组数据:GL_ARRAY_BUFFER或GL_ELEMENT_ARRAY。任何顶点属性,如顶点坐标、纹理坐标、法线与颜色分量数组都使用GL_ARRAY_BUFFER。用于glDraw[Range]Elements()的索引数据需要使用GL_ELEMENT_ARRAY绑定。注意,target标志帮助VBO确定缓存对象最有效的位置,如有些系统将索引保存AGP或系统内存中,将顶点保存在显卡内存中。当第一次调用glBindBuffer(),VBO用0大小的内存缓存初始化该缓存,并且设置VBO的初始状态,如用途与访问属性。
         */
        glBindBuffer(GL_ARRAY_BUFFER, buffer);
        /*
         将数据拷贝到缓存对象,第一个参数target可以为GL_ARRAY_BUFFER或GL_ELEMENT_ARRAY。size为待传递数据字节数量。第三个参数为源数据数组指针,如data为NULL,则VBO仅仅预留给定数据大小的内存空间。最后一个参数usage标志位VBO的另一个性能提示,它提供缓存对象将如何使用:static、dynamic或stream、与read、copy或draw
         */
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);
        
        /*
         开启顶点数据,并缓存 默认情况下,出于性能考虑,所有顶点着色器的属性(Attribute)变量都是关闭的,意味着数据在着色器端是不可见的,哪怕数据已经上传到GPU,由glEnableVertexAttribArray启用指定属性,才可在顶点着色器中访问逐顶点的属性数据。glVertexAttribPointer或VBO只是建立CPU和GPU之间的逻辑连接,从而实现了CPU数据上传至GPU。但是,数据在GPU端是否可见,即,着色器能否读取到数据,由是否启用了对应的属性决定,这就是glEnableVertexAttribArray的功能,允许顶点着色器读取GPU(服务器端)数据。
         */
        glEnableVertexAttribArray(GLKVertexAttribPosition);
        /*
         向gpu传入顶点数据的方法,将vbo中的数据传递给顶点数组
         参数:
         1): index , 指定要修改的顶点属性的索引值
         2): size, 指定每个顶点属性的组件数量。必须为1、2、3或者4。初始值为4。(如position是由3个(x,y,z)组成,而颜色是4个(r,g,b,a))
         3): type, 指定数组中每个组件的数据类型。可用的符号常量有GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT,GL_UNSIGNED_SHORT, GL_FIXED, 和 GL_FLOAT,初始值为GL_FLOAT
         4): 指定当被访问时,固定点数据值是否应该被归一化(GL_TRUE)或者直接转换为固定点值(GL_FALSE)
         5): stride,  指定连续顶点属性之间的偏移量。如果为0,那么顶点属性会被理解为:它们是紧密排列在一起的。初始值为0
         6): 指定第一个组件在数组的第一个顶点属性中的偏移量。该数组与GL_ARRAY_BUFFER绑定,储存于缓冲区中。初始值为0;
         */
        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);
    

    纹理贴图

     NSString *filePath = [[NSBundle mainBundle] pathForResource:@"for_test" ofType:@"jpg"];
    //    GLKTextureLoaderOriginBottomLeft 纹理坐标系是相反的
        NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:@(1),GLKTextureLoaderOriginBottomLeft, nil];
        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;
    

    疑问:options key为GLKTextureLoaderOriginBottomLeft是不是指纹理坐标系是左下角为原点的意思,值为1又是为啥呢?然后这里纹理坐标系是相反的参照的是UIKit坐标系吗?如果是的化我觉得称之为水平轴翻转180度更适合理解,uikit坐标系是屏幕左上角为原点吧,我理解相反的意思是(0,0)应该对应(1,1)
    接下来是渲染绘图环节

    - (void)glkView:(GLKView *)view drawInRect:(CGRect)rect{
    //    就是用来设置这个 “  底色 ” 的,即所谓的背景颜色。glClearColor ( ) 只起到Set 的作用,并不Clear 任何
        glClearColor(0.3f, 0.6f, 1.0f, 1.0f);
    //    是用来清除屏幕颜色,即将屏幕的所有像素点都还原为 “底色
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
        //启动着色器
        [self.mEffect prepareToDraw];
        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);//使用顶点数组绘制图元
        //    glDrawElements(<#GLenum mode#>, <#GLsizei count#>, <#GLenum type#>, <#const GLvoid *indices#>)--->使用索引数组绘制图元
        
        
    }
    

    使用顶点索引绘图api为glDrawElements
    关于此api请查询百度百科,这里简单贴一下百度百科的参数以及功能释义:
    glDrawElements是一个OPENGL的图元绘制函数,从数组中获得数据渲染图元。

    函数原型为:

    void glDrawElements( GLenum mode, GLsizei count,

    GLenum type, const GLvoid *indices);

    其中:

    mode指定绘制图元的类型,它应该是下列值之一,GL_POINTS, GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_TRIANGLES, GL_QUAD_STRIP, GL_QUADS, and GL_POLYGON.

    count为以mode类型连接的顶点的总数,且根据不同的mode,count小于或等于单个mode类型图元的顶点数*图元数

    type为索引值的类型,只能是下列值之一:GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, or GL_UNSIGNED_INT。

    indices:指向索引存贮位置的指针
    百度百科链接

    相关文章

      网友评论

          本文标题:OpenGles 入门练习(一)

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