美文网首页OpenGLOpenGLES
iOS-OpenGL ES入门教程(二)最简单的纹理Demo

iOS-OpenGL ES入门教程(二)最简单的纹理Demo

作者: 安东_Ace | 来源:发表于2018-04-25 16:30 被阅读554次

    前言

    上一篇介绍了绘制OpenGL ES的Hello world也就是一个三角形。现在我们介绍下OpenGL ES的一个另一个基础,纹理,并且编写一个最简单的demo绘制一张图片。

    纹理

    初学呢,我们可以把纹理理解为一张图片,我们可以将整张图片绘制到圆形,矩形等目标图形中,既可以绘制部分图,也可以重复使用图片绘制,也就是纹理了哈。

    矩形图

    我们目标是绘制一个矩形图,在OpenGL ES中任何复杂的图形都是由点,线和三角形组成的哈。很简单,一个矩形就是两个三角形组成。嚯嚯。So easy。

    矩形

    好滴,那么矩形的六个顶点有了哈

    const GLfloat vertices[] = {
            1, -1, 0.0f,   //D
            1, 1,  0.0f,   //B
            -1, 1, 0.0f,   //A
            
            1, -1, 0.0f,   //D
            -1, 1, 0.0f,   //A
            -1, -1, 0.0f,   //C 
    }; 
    

    很明显我们的顶点是需要和纹理坐标一一对应的,如下图,


    顶点和纹理映射图

    需要注意的是:纹理坐标系是左下角为坐标系顶点,而顶点坐标系屏幕中心为顶点

    好滴,那么我们的数据源就有了哈。

    //顶点数据
    typedef struct {
        GLKVector3 positionCoords; 
        GLKVector2 textureCoords;//纹理
    }SceneVertex;
    
    //矩形的六个顶点
    static const SceneVertex vertices[] = {
        {{1, -1, 0.0f,},{1.0f,0.0f}}, //右下
        {{1, 1,  0.0f},{1.0f,1.0f}}, //右上
        {{-1, 1, 0.0f},{0.0f,1.0f}}, //左上
        
        {{1, -1, 0.0f},{1.0f,0.0f}}, //右下
        {{-1, 1, 0.0f},{0.0f,1.0f}}, //左上
        {{-1, -1, 0.0f},{0.0f,0.0f}}, //左下
    };
    

    textureCoords即是纹理位置。

    设置OpenGLES上下文

    //新建OpenGLES 上下文
        GLKView *view = (GLKView *)self.view;
        view.context = [[EAGLContext alloc]initWithAPI: kEAGLRenderingAPIOpenGLES2];
        //设置当前上下文
        [EAGLContext setCurrentContext:view.context];
        
        self.baseEffect = [[GLKBaseEffect alloc]init];
        self.baseEffect.useConstantColor = GL_TRUE;
        self.baseEffect.constantColor = GLKVector4Make(1.0f, 1.0f, 1.0f, 1.0f);
    

    这是第一步。

    设置顶点缓存buffer

    - (void)fillVertexArray{
        glGenBuffers(1, &vertextBufferID);
        glBindBuffer(GL_ARRAY_BUFFER, vertextBufferID); //绑定指定标识符的缓存为当前缓存
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
        
        
        glEnableVertexAttribArray(GLKVertexAttribPosition); //顶点数据缓存
        glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(SceneVertex), NULL + offsetof(SceneVertex, positionCoords));
        glEnableVertexAttribArray(GLKVertexAttribTexCoord0); //纹理
        glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(SceneVertex), NULL + offsetof(SceneVertex, textureCoords));
        
    }
    

    这里我们生成绑定了顶点和纹理buffer,并且设置了对应的指针偏移量。

    生成纹理

    这里我们使用GLkit中的GLKTextureInfo方便的生成图片纹理。

       //获取图片
        CGImageRef imageRef = [[UIImage imageNamed:@"Demo.jpg"] CGImage];
        
        //通过图片数据产生纹理缓存
        //GLKTextureInfo封装了纹理缓存的信息,包括是否包含MIP贴图
        GLKTextureInfo *textureInfo = [GLKTextureLoader textureWithCGImage:imageRef options:nil error:NULL];
        self.baseEffect.texture2d0.name = textureInfo.name;
        self.baseEffect.texture2d0.target = textureInfo.target;
    

    GLKBaseEffect让我们避开了写shader Language。

    绘制 & 释放

    最后一步就是绘制了,这步非常简单

    - (void)glkView:(GLKView *)view drawInRect:(CGRect)rect{
        //清除背景色
        glClearColor(0.0f,0.0f,0.0f,1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        [self.baseEffect prepareToDraw];
        glDrawArrays(GL_TRIANGLES, 0, 6);
    }
    
    
    - (void)dealloc{
        GLKView *view = (GLKView *)self.view;
        [EAGLContext setCurrentContext:view.context];
        if ( 0 != vertextBufferID) {
            glDeleteBuffers(1,
                            &vertextBufferID);
            vertextBufferID = 0;
        }
        [EAGLContext setCurrentContext:nil];
    }
    
    

    小思考:因为这次绘制的是静态图,所以我们直接在viewdidload里面就生成绑定好了顶点数据缓存,而不是在drawInRect方法中。如果要做一些动态变化,就需要在drawInRect方法中动态刷新缓存数据

    看下最后运行结果


    运行结果-彭于晏

    图片正常显示了,但是倒立了,这个是因为CoreGraphics的坐标系问题。我们生成纹理的时候option加个坐标系变换就OK了。

     NSDictionary* options = [NSDictionary dictionaryWithObjectsAndKeys:@(1), GLKTextureLoaderOriginBottomLeft, nil];
        GLKTextureInfo *textureInfo = [GLKTextureLoader textureWithCGImage:imageRef options:options error:NULL];
    

    小思考: 我们这里实现了最简单的纹理图片绘制,但是由于图标本身的尺寸被全屏展示后出现了拉伸,怎么保证图片按比例的绘制在屏幕中呢?

    Demo代码地址:LearnOpenGLESDemo

    参考书籍:1. OpenGL ES应用开发实践指南:iOS卷

    相关文章

      网友评论

        本文标题:iOS-OpenGL ES入门教程(二)最简单的纹理Demo

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