美文网首页
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