zoukankan      html  css  js  c++  java
  • OpenGL ES画板

    一、概述

    利用自定义顶点和片元着色器渲染,并且设置图片纹理颜色为画笔颜色

    二、核心代码

    - (void)renderLineFromPoint:(CGPoint)start toPoint:(CGPoint)end
    {
        //顶点缓存区
        static GLfloat *vertexBuffer = NULL;
        //顶点Max
        static NSUInteger vertexMax = 64;
        //顶点个数
        NSUInteger vertexCount = 0,count;
        CGFloat scale = self.contentScaleFactor;
        
        //点到像素转换:乘以比例因子
        start.x *= scale;
        start.y *= scale;
        end.x *= scale;
        end.y *= scale;
        
        //开辟顶点缓存区
        if (vertexBuffer == NULL) {
            vertexBuffer = malloc(vertexMax*2*sizeof(GLfloat));
        }
        
        //求得两点之间的距离
        float seq = sqrtf((end.x-start.x)*(end.x-start.x)+(end.y-start.y)*(end.y-start.y));
        /*向上取整:求得距离要产生多少个点
         kBrushPixelStep值越大,笔触越细;值越小,笔触越粗
         */
        NSInteger pointCount = ceil(seq/kBrushPixelStep);
        count = MAX(pointCount, 1);
        
        for (int i = 0; i < count; i++) {
            if (vertexCount == vertexMax) {
                //修改2倍增长
                vertexMax = 2*vertexMax;
                vertexBuffer = realloc(vertexBuffer, vertexMax*2*sizeof(GLfloat));
            }
            
            //计算两个之间的距离有多少个点,并存储在顶点缓存区中
            vertexBuffer[2*vertexCount+0] = start.x+(end.x-start.x)*((GLfloat)i/(GLfloat)count);
            vertexBuffer[2*vertexCount+1] = start.y+(end.y-start.y)*((GLfloat)i/(GLfloat)count);
            
            vertexCount++;
        }
        
        //绑定顶点数据
        glBindBuffer(GL_ARRAY_BUFFER, vboID);
        //将数据从CPU中复制到GPU中提供给OpenGL使用
        glBufferData(GL_ARRAY_BUFFER, vertexCount*2*sizeof(GLfloat), vertexBuffer, GL_DYNAMIC_DRAW);
        
        //启用指定属性
        glEnableVertexAttribArray(ATTRIB_VERTEX);
        //链接顶点属性
        glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, GL_FALSE, 2*sizeof(GLfloat), 0);
        
        //使用数据总线:传递顶点数据到顶点着色器
        glUseProgram(program[PROGRAME_POINT].id);
        //绘制顶点:绘制模型、起始点、顶点个数
        glDrawArrays(GL_POINTS, 0, (int)vertexCount);
        //绑定渲染缓存区到特定标志符上
        glBindRenderbuffer(GL_RENDERBUFFER, viewRenderBuffer);
        //开始渲染
        [context presentRenderbuffer:GL_RENDERBUFFER];
        
    }
    - (textureInfo_t)textureFromName:(NSString *)name
    {
        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));
        
        /*创建位图上下文
         参数:图片内存地址、图片宽、图片高、像素组件位数(一般设置8),每一行所占比特数、颜色空间、颜色通道
         */
        brushContext = CGBitmapContextCreate(brushData, width, height, 8, width*4, CGImageGetColorSpace(brushImage), kCGImageAlphaPremultipliedLast);
        
        //绘图
        CGContextDrawImage(brushContext, CGRectMake(0, 0, (CGFloat)width, (CGFloat)height), brushImage);
        //释放上下文
        CGContextRelease(brushContext);
        
        //申请纹理标志符
        glGenTextures(1, &texID);
        //绑定纹理
        glBindTexture(GL_TEXTURE_2D, texID);
        //设置纹理属性:缩小滤波器、线性滤波器
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        /*生成2D纹理图片
         参数:纹理目标、图像级别(0为基本级别)、颜色组件(GL_RGBA、GL_ALPHA)、图像宽、图像高、边框宽度(一般为0)、像素数据颜色格式、像素数据类型、内存中指向图像数据指针
         */
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (int)width, (int)height, 0, GL_RGBA, GL_UNSIGNED_BYTE, brushData);
        
        free(brushData);
        
        //配置纹理属性
        texture.id = texID;
        texture.width = (int)width;
        texture.height = (int)height;
        
        return texture;
    }
    - (void)setupShaders
    {
        for (int i = 0; i < NUM_PROGRAMS; i++) {
            
            //读取顶点着色器程序
            char *vsrc = readFile(pathForResource(program[i].vert));
            //读取片元着色器程序
            char *fsrc = readFile(pathForResource(program[i].frag));
            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(@"vsrcStr------%@", vsrcStr);
            NSLog(@"fsrcStr------%@", fsrcStr);
            
            GLsizei attribCt = 0;
            GLchar *attribUsed[NUM_ATTRIBS];
            GLint attrib[NUM_ATTRIBS];
            GLchar *attribName[NUM_ATTRIBS] = {
                "inVertex"
            };
            
            const char *uniformName[NUM_UNIFORMS] = {
                "MVP","pointSize","vertexColor", "texture"
            };
            
            for (int j = 0; j < NUM_ATTRIBS; j++) {
                if (strstr(vsrc, attribName[j])) {
                    attrib[attribCt] = j;
                    attribUsed[attribCt++] = attribName[j];
                }
            }
            
            //program处理:创建、链接、生成
            glueCreateProgram(vsrc, fsrc, attribCt, (const char **)&attribUsed[0], attrib, NUM_UNIFORMS, &uniformName[0], program[i].uniform, &program[i].id);
            
            free(vsrc);
            free(fsrc);
            
            if (i == PROGRAME_POINT) {
                glUseProgram(program[PROGRAME_POINT].id);
               //为当前程序指定uniform变量
                glUniform1i(program[PROGRAME_POINT].uniform[UNIFORM_TEXTURE], 0);
                
                //设置正射投影矩阵
                GLKMatrix4 projectionMatrix = GLKMatrix4MakeOrtho(0, backingWidth, 0, backingHeight, -1, 1);
                //创建模型视图矩阵:单元矩阵
                GLKMatrix4 modelViewMatrix = GLKMatrix4Identity;
                //正射投影矩阵与模型视图矩阵相乘,结果保存在MVPMatrix矩阵中
                GLKMatrix4 MVPMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix);
               
               /*为当前程序指定Uniform变量值
                参数:指明要更改的Uniform变量的位置、将要被修改的矩阵的数量、矩阵值被载入变量时是否要对举证进行变换(如转置)、将要用于更新uniform变量MVP的数组指针
                */
                glUniformMatrix4fv(program[PROGRAME_POINT].uniform[UNIFORM_MVP], 1, GL_FALSE, MVPMatrix.m);
               //为当前程序对象Uniform变量的pointSize赋值
                glUniform1f(program[PROGRAME_POINT].uniform[UNIFORM_POINT_SIZE], brushTexture.width/kBrushScale);
                //为当前程序对象Uniform变量顶点颜色赋值
                glUniform4fv(program[PROGRAME_POINT].uniform[UNIFORM_VERTEX_COLOR], 1, brushColor);
                
            }
        }
        
        glError();
    }

    三、效果图

    GitHub

  • 相关阅读:
    JavaScript 之 变量
    SqlServer 之 系统视图
    SQL Server 2008中的Hints(提示)的简单整理
    SqlServer日常积累(三)
    Asp.net 之页面处理积累(一)
    Android 之Toast
    Android 之开发积累
    go与json
    binder
    DBUS
  • 原文地址:https://www.cnblogs.com/lybSkill/p/10095696.html
Copyright © 2011-2022 走看看