OpenGL ES画板
一、概述
利用自定义顶点和片元着色器渲染,并且设置图片纹理颜色为画笔颜色
二、核心代码
- (void)renderLineFromPoint:(CGPoint)start toPoint:(CGPoint)end
{
//顶点缓存区
static GLfloat *vertexBuffer = NULL;
//顶点Max
static NSUInteger vertexMax = ;
//顶点个数
NSUInteger vertexCount = ,count;
CGFloat scale = self.contentScaleFactor; //点到像素转换:乘以比例因子
start.x *= scale;
start.y *= scale;
end.x *= scale;
end.y *= scale; //开辟顶点缓存区
if (vertexBuffer == NULL) {
vertexBuffer = malloc(vertexMax**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, ); for (int i = ; i < count; i++) {
if (vertexCount == vertexMax) {
//修改2倍增长
vertexMax = *vertexMax;
vertexBuffer = realloc(vertexBuffer, vertexMax**sizeof(GLfloat));
} //计算两个之间的距离有多少个点,并存储在顶点缓存区中
vertexBuffer[*vertexCount+] = start.x+(end.x-start.x)*((GLfloat)i/(GLfloat)count);
vertexBuffer[*vertexCount+] = start.y+(end.y-start.y)*((GLfloat)i/(GLfloat)count); vertexCount++;
} //绑定顶点数据
glBindBuffer(GL_ARRAY_BUFFER, vboID);
//将数据从CPU中复制到GPU中提供给OpenGL使用
glBufferData(GL_ARRAY_BUFFER, vertexCount**sizeof(GLfloat), vertexBuffer, GL_DYNAMIC_DRAW); //启用指定属性
glEnableVertexAttribArray(ATTRIB_VERTEX);
//链接顶点属性
glVertexAttribPointer(ATTRIB_VERTEX, , GL_FLOAT, GL_FALSE, *sizeof(GLfloat), ); //使用数据总线:传递顶点数据到顶点着色器
glUseProgram(program[PROGRAME_POINT].id);
//绘制顶点:绘制模型、起始点、顶点个数
glDrawArrays(GL_POINTS, , (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*, sizeof(GLubyte)); /*创建位图上下文
参数:图片内存地址、图片宽、图片高、像素组件位数(一般设置8),每一行所占比特数、颜色空间、颜色通道
*/
brushContext = CGBitmapContextCreate(brushData, width, height, , width*, CGImageGetColorSpace(brushImage), kCGImageAlphaPremultipliedLast); //绘图
CGContextDrawImage(brushContext, CGRectMake(, , (CGFloat)width, (CGFloat)height), brushImage);
//释放上下文
CGContextRelease(brushContext); //申请纹理标志符
glGenTextures(, &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, , GL_RGBA, (int)width, (int)height, , 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 = ; 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)- encoding:NSUTF8StringEncoding];
NSString *fsrcStr = [[NSString alloc] initWithBytes:fsrc length:strlen(fsrc)- encoding:NSUTF8StringEncoding];
NSLog(@"vsrcStr------%@", vsrcStr);
NSLog(@"fsrcStr------%@", fsrcStr); GLsizei attribCt = ;
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 = ; j < NUM_ATTRIBS; j++) {
if (strstr(vsrc, attribName[j])) {
attrib[attribCt] = j;
attribUsed[attribCt++] = attribName[j];
}
} //program处理:创建、链接、生成
glueCreateProgram(vsrc, fsrc, attribCt, (const char **)&attribUsed[], attrib, NUM_UNIFORMS, &uniformName[], 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], ); //设置正射投影矩阵
GLKMatrix4 projectionMatrix = GLKMatrix4MakeOrtho(, backingWidth, , backingHeight, -, );
//创建模型视图矩阵:单元矩阵
GLKMatrix4 modelViewMatrix = GLKMatrix4Identity;
//正射投影矩阵与模型视图矩阵相乘,结果保存在MVPMatrix矩阵中
GLKMatrix4 MVPMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); /*为当前程序指定Uniform变量值
参数:指明要更改的Uniform变量的位置、将要被修改的矩阵的数量、矩阵值被载入变量时是否要对举证进行变换(如转置)、将要用于更新uniform变量MVP的数组指针
*/
glUniformMatrix4fv(program[PROGRAME_POINT].uniform[UNIFORM_MVP], , 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], , brushColor); }
} glError();
}
三、效果图
OpenGL ES画板的更多相关文章
- 【AR实验室】OpenGL ES绘制相机(OpenGL ES 1.0版本)
0x00 - 前言 之前做一些移动端的AR应用以及目前看到的一些AR应用,基本上都是这样一个套路:手机背景显示现实场景,然后在该背景上进行图形学绘制.至于图形学绘制时,相机外参的解算使用的是V-SLA ...
- OpenGL ES 3.0: 图元重启(Primitive restart)
[TOC] 背景概述 在OpenGL绘制图形时,可能需要绘制多个并不相连的图形.这样的情况下这几个图形没法被当做一个图形来处理.也就需要多次调用 DrawArrays 或 DrawElements. ...
- opengl es中不同的绘制方式
opengl es中不同的绘制方式 转载请保留出处:http://xiaxveliang.blog.163.com/blog/static/297080342013467344263/ 1. GL_P ...
- OpenGL ES无法获取贴图数据原因
最近在做一个项目,要从贴图中获取图像数据,查了很多资料,也琢磨很久,获取到的数据都是0.终于在一次偶然的机会,发现了端倪,成功了. 不得不说这"一分灵感"真的很重要 以下是在获取贴 ...
- OpenGL ES(一.概念)
OpenGL ES是以手持和嵌入式设备为目标的高级3D图形应用程序编程接口,主要的支持平台是iOS,Android,Linux和Windows 1.顶点着色器 他可以用于通过矩阵变换位置,计算照明公式 ...
- IOS 中openGL使用教程1(openGL ES 入门篇 | 搭建openGL环境)
OpenGL版本 iOS系统默认支持OpenGl ES1.0.ES2.0以及ES3.0 3个版本,三者之间并不是简单的版本升级,设计理念甚至完全不同,在开发OpenGL项目前,需要根据业务需求选择合适 ...
- OpenGL ES crash notes 01 - Nice to meet you
这篇笔记完全参照<OpenGL.ES.3.0.Programming.Guide.2nd.Edition>,摘出部分内容只为学习参考. 为什么要用英文:无论是D3D的SDK还是OES的Sp ...
- android opengl es代码功能
/* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Versi ...
- [cocos2d-x]OPENGL ES支持的像素格式
OPENGL ES最多支持32位颜色值. 支持的像素格式有以下几种: 客户端格式 GL格式 GL数据类型 字节数 RGBA8888 GL_RGBA GL_UNSIGNED_BYTE 4 RGB888 ...
随机推荐
- Android解析ActivityManagerService(一)AMS启动流程和AMS家族
前言 此前在Android系统启动流程.应用进程以及深入四大组件这三个系列文章中,都提及到了AMS,但都没有系统的来讲解它,本文就以AMS为主来进行讲解,其中会有一些知识点与这些系列文章有所重合,这里 ...
- 二、vue学习--父元素如何获取子元素的值,子元素如何获取父元素的值
下图是父元素: 下图是子元素,获取父元素的值,使用props定义属性,这样就可以获取到父元素上传过来的set .place.type,拿到值就可以做一些自己的逻辑处理 二.子元素给父元素传值? 下 ...
- scrapy实战--爬取报刊名称及地址
目标:爬取全国报刊名称及地址 链接:http://news.xinhuanet.com/zgjx/2007-09/13/content_6714741.htm 目的:练习scrapy爬取数据 学习过s ...
- 使用GTID给Galera集群做数据库异步复制
一.为什么要做Galera集群异步复制 Galera集群解决了数据库高可用的问题,但是存在局限性,例如耗时的事务处理可能会导致集群性能急剧下降,甚至出现阻塞现象.而不幸的是,类似报表等业务需求就需要做 ...
- windows 端口映射
netsh interface portproxy add v4tov4 listenport=8765 listenaddress=0.0.0.0 connectaddress=172.19.24. ...
- 测试TextKit渲染大文本的效率
测试TextKit渲染大文本的效率 TextKit可以用来做精美的电子书,而电子书通常都是txt格式的,那么渲染txt格式的文本的效率如何呢? 以下来进行测试. #import "RootV ...
- 固定UIScrollView滑动的方向
固定UIScrollView滑动的方向 一般而言,我们通过这两个参数CGRectMake以及contentSize就可以自动的让UIScrollView只往一个方向滚动.但我遇到过非常奇葩的情况,那就 ...
- word 排版用到双直线、波浪线、虚线 、直线、隔行线等技巧
在办公或毕业设计时,有时排版需要插入双直线.波浪线.虚线 .直线.隔行线等而烦恼, 今天小白与大家分享技巧如下: 感谢您的阅读,如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮.本文欢迎各位转载,但 ...
- IE漏洞的调试心得
在调试漏洞的过程中,个人感觉最棘手的就是ie浏览器的漏洞和flash player的漏洞了.这里打算记录一下学习过程中的心得(主要是基于uaf类),以方便新人学习. 首先,ie漏洞与众不同的是,程序的 ...
- 阿里云MaxCompute被Forrester评为全球云端数据仓库领导者
参考消息网3月19日报道 日前,全球权威调研机构佛瑞斯特研究公司(Forrester)发布<2018年一季度云端数据仓库>报告.报告对大数据服务商的主要功能.区域表现.细分市场和典型客户等 ...