OpenGL ES画板
时间:2018-12-10
本文章向大家介绍OpenGL ES画板,主要包括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(); }
三、效果图
- 清新唯美的jQuery天气预报插件(网页天气预报插件)
- 32和64位的CentOS 6.0下 安装 Mono 2.10.8 和Jexus 5.0
- 跨平台的 .NET 运行环境 Mono 3.2 新特性
- Ibatisnet Quick Start
- 常见的3种Hive参数配置方法
- 6杂域名超16万元结拍
- GridView控件使用经验
- WordPress登陆文件wp-login.php添加相关参数,安全有保障
- WordPress在RSS Feed 中输出自定义特色图像(缩略图)
- 单拼域名can.com以高达99.2万元成交!
- CI学习 CCNET Config 第一天
- IBatisNet基础组件
- 学习altas笔记[客户端JS和Altas环境初始化关系和DataTable返回数据的客户端处理]
- 在Windows 8 Hyper-V下的安装CentOS 6和SSH配置
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 玩转StyleGAN2模型:教你生成动漫人物
- R语言时间序列数据指数平滑法分析交互式动态可视化
- 再见Excel!最强国产开源在线表格Luckysheet走红GitHub
- R语言广义线性模型索赔频率预测:过度分散、风险暴露数和树状图可视化
- R语言多分类logistic逻辑回归模型在混合分布模拟单个风险损失值评估的应用
- sas神经网络:构建人工神经网络模型来识别垃圾邮件
- 图像倾斜校正算法的MATLAB实现:图像倾斜角检测及校正
- 手写dubbo框架9-SPI实现
- R语言非参数模型厘定保险费率:局部回归、广义相加模型GAM、样条回归
- VsCode插件之Live Serve探秘.(上)
- R语言小数定律的保险业应用:泊松分布模拟索赔次数
- R语言中自编基尼系数的CART回归决策树的实现
- Docker hello world
- 前端环境配置
- R数据读取(数据文件解析)