美文网首页
OpenGL ES 画板

OpenGL ES 画板

作者: 我的大好时光 | 来源:发表于2018-04-13 16:26 被阅读34次

    思维导图

    画板.png

    粘出核心代码

    播放系统声音封装

    + (id)soundEffectWithContentsOfFile:(NSString *)aPath
    {
        return [[SoundEffect alloc] initWithContentsOfFile:aPath];
    }
    
    - (id)initWithContentsOfFile:(NSString *)path
    {
        if (!path)
        {
            return nil;
        }
        
        self = [super init];
        
        if (self)
        {
            //1、获取声音文件路径
            NSURL *aFileURL = [NSURL URLWithString:path];
            
            if (aFileURL == nil)
            {
                return nil;
            }
            
            //2.获取声音文件id
            SystemSoundID aSoundID;
            OSStatus error = AudioServicesCreateSystemSoundID((__bridge CFURLRef _Nonnull)(aFileURL), &aSoundID);
            
            if (error == kAudioServicesNoError)
            {
                //3.赋值
                _soundID = aSoundID;
            }
            else
            {
                NSLog(@"Error :loading sound path,%d,%@",(int)error,path);
                return nil;
            }
            
        }
        return self;
    }
    //播放系统声音
    - (void)play
    {
        AudioServicesPlaySystemSound(_soundID);
    }
    //释放
    - (void)dealloc
    {
        AudioServicesDisposeSystemSoundID(_soundID);
    }
    
    

    Shader

    {
        
        for (int i = 0; i < NUM_PROGRAMS; i++) {
            
            //读取顶点着色程序
            char *vsrc = readFile(pathForResource(program[i].vert));
            char *fsrc = readFile(pathForResource(program[i].frag));
            
            //将char->NSString 对象
            NSString *vsrcStr = [[NSString alloc]initWithBytes:vsrc length:strlen(vsrc)-1 encoding:NSUTF8StringEncoding];
            NSString *fsrcStr = [[NSString alloc]initWithBytes:fsrc length:strlen(fsrc)-1 encoding:NSUTF8StringEncoding];
            
            //打印着色程序中的代码
            NSLog(@"vsrc:%@",vsrcStr);
            NSLog(@"fsrc:%@",fsrcStr);
            
            
            //attribute
            GLsizei attribCt = 0;
            //创建字符串数组【1】
            GLchar *attribUsed[NUM_ATTRIBS];
            //
            GLint attrib[NUM_ATTRIBS];
            
            //attribute 变量名称-inVertex(point.vsh)
            GLchar *attribName[NUM_ATTRIBS] = {
                "inVertex",
            };
            
            //uniform变量名称 "MVP", "pointSize", "vertexColor", "texture",
            const GLchar *uniformName[NUM_UNIFORM] = {
                "MVP", "pointSize", "vertexColor", "texture",
            };
            
            //遍历attribute
            for (int j = 0; j < NUM_ATTRIBS; j++)
            {
                //strstr(str1,str2) 函数用于判断字符串str2是否是str1的子串。如果是,则该函数返回str2在str1中首次出现的地址;否则,返回NULL。
                //判断,attribute 变量,是否存在顶点着色器程序中。point.vsh
                if (strstr(vsrc, attribName[j]))
                {
                    //attribute个数
                    attrib[attribCt] = j;
                    //使用的attribute的名称
                    attribUsed[attribCt++] = attribName[j];
                }
            }
            
            //利用shaderUtil.c封装好的方法对programe 进行创建、链接、生成Programe
            /*
             参数1:vsrc,顶点着色器程序
             参数2:fsrc,片元着色器程序
             参数3:attribute变量个数
             参数4:attribute变量名称
             参数5:当前attribute位置
             参数6:uniform名字
             参数7:program的uniform地址
             参数8:program程序地址
             */
            glueCreateProgram(vsrc,
                              fsrc,
                              attribCt,
                              (const GLchar **)&attribUsed[0],
                              attrib,
                              NUM_UNIFORM,
                              &uniformName[0],
                              program[i].uniform,
                              &program[i].program_id);
            
            //释放vsrc,fsrc指针
            free(vsrc);
            free(fsrc);
            
            // 设置常数、初始化Uniform
            //当前的i == 0
            if (i == PROGRAM_POINT)
            {
                //使用proram program[0].id 等价,以往课程例子中的GLuint program;
                glUseProgram(program[PROGRAM_POINT].program_id);
                
                
                //为当前程序对象指定uniform变量值
                /*
                 为当前程序对象指定uniform变量MVP赋值
                 
                 void glUniform1f(GLint location,  GLfloat v0);
                 参数1:location,指明要更改的uniform变量的位置 MVP
                 参数2:v0,指明在指定的uniform变量中要使用的新值
                 
                 program[0].uniform[3] = 0
                 等价于,vsh顶点着色器程序中的uniform变量,MVP = 0;
                 其实简单理解就是做了一次初始化,清空这个mat4矩阵
                 */
                glUniform1i(program[PROGRAM_POINT].uniform[UNIFORM_TEXTURE], 0);
                
                // 投影矩阵
                /*
                 投影分为正射投影和透视投影,我们可以通过它来设置投影矩阵来设置视域,在OpenGL中,默认的投影矩阵是一个立方体,即x y z 分别是-1.0~1.0的距离,如果超出该区域,将不会被显示
                 
                 正射投影(orthographic projection):GLKMatrix4MakeOrtho(float left, float righ, float bottom, float top, float nearZ, float farZ),该函数返回一个正射投影的矩阵,它定义了一个由 left、right、bottom、top、near、far 所界定的一个矩形视域。此时,视点与每个位置之间的距离对于投影将毫无影响。
                 
                 透视投影(perspective projection):GLKMatrix4MakeFrustum(float left, float right,float bottom, float top, float nearZ, float farZ),该函数返回一个透视投影的矩阵,它定义了一个由 left、right、bottom、top、near、far 所界定的一个平截头体(椎体切去顶端之后的形状)视域。此时,视点与每个位置之间的距离越远,对象越小。
                 
                 在平面上绘制,只需要使正投影就可以了!!
                 */
                GLKMatrix4 projectionMatrix = GLKMatrix4MakeOrtho(0, backingWidth, 0, backingHeight, -1, 1);
                
                //模型矩阵,比如你要平移、旋转、缩放,就可以设置在模型矩阵上
                //这里不需要这些变换,则使用单元矩阵即可,相当于1 * ? = ?
                GLKMatrix4 modelViewMatrix = GLKMatrix4Identity;
                
                //矩阵相乘,就2个矩阵的结果交给MVPMatrix
                GLKMatrix4 MVPMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix);
                /*
                 void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
                 功能:为当前程序对象指定uniform变量值
                 参数1:location 指明要更改的uniform变量的位置 MVP
                 参数2:count 指定将要被修改的矩阵的数量
                 参数3:transpose 矩阵的值被载入变量时,是否要对矩阵进行变换,比如转置!
                 参数4:value ,指向将要用于更新uniform变量MVP的数组指针
                 */
                glUniformMatrix4fv(program[PROGRAM_POINT].uniform[UNIFORM_MVP], 1, GL_FALSE, MVPMatrix.m);
                
                //点的大小 pointSize
                /*
                 为当前程序对象指定uniform变量pointSize赋值
                 program[0].uniform[pointSize] = 纹理宽度/画笔比例
                 */
                glUniform1f(program[PROGRAM_POINT].uniform[UNIFORM_POINT_SIZE], brushTexture.width / kBrushScale);
                
                
                //笔刷颜色
                /*
                 为当前程序对象指定uniform变量vertexColor赋值
                 program[0].uniform[vertexColor] = 画笔颜色
                 
                 void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
                 功能:为当前程序对象指定uniform变量值
                 参数1:location 指明要更改的uniform变量的位置 vertexColor
                 参数2:count 指定将要被修改的4分量的数量
                 参数3:value ,指向将要用于更新uniform变量vertexColor的值
                 
                 */
                glUniform4fv(program[PROGRAM_POINT].uniform[UNIFORM_VERTEX_COLOR], 1, brushColor);
                
            }
        }
        
        glError();
        
    }
    

    创建纹理图片

    {
        CGImageRef brushImage;
        CGContextRef brushContext;
        GLubyte *brushData;
        size_t width,height;
        GLuint texId;
        textureInfo_t texture;
        
        brushImage = [UIImage imageNamed:name].CGImage;
        
        width = CGImageGetWidth(brushImage);
        height = CGImageGetHeight(brushImage);
        
        //初始化存贮图片所需要的空间
        brushData = (GLubyte *)calloc(width * height * 4, sizeof(GLubyte));
        
        //获取位图上下文
        brushContext = CGBitmapContextCreate(brushData, width, height, 8, width * 4, CGImageGetColorSpace(brushImage), kCGImageAlphaPremultipliedLast);
        
        //绘制图片
        CGContextDrawImage(brushContext, CGRectMake(0, 0, (CGFloat)width, (CGFloat)height), brushImage);
        
        //接下来不需要上下文,所以可以进行释放
        CGContextRelease(brushContext);
        
        //OpenGL ES 生成纹理
        //生成纹理标识
        glGenTextures(1, &texId);
        
        //绑定纹理标识
        glBindTexture(GL_TEXTURE_2D, texId);
        
        //设置纹理过滤方式
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        
        //指定2D纹理图像,为内存中的图像数据提供一个指针
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0, GL_RGBA, GL_UNSIGNED_BYTE, brushData);
        
        free(brushData);
        
        texture.id = texId;
        texture.width = (int)width;
        texture.height = (int)height;
        
        return texture;
    }
    

    Demo下载地址

    点击下载

    相关文章

      网友评论

          本文标题:OpenGL ES 画板

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