IOS 中openGL使用教程2(openGL ES 入门篇 | 绘制一个多边形)
在上一篇我们学习了如何搭建IOS下openGL的开发环境,接下来我们来学习如何绘制一个多边形。
在2.0之前,es的渲染采用的是固定管线,何为固定管线,就是一套固定的模板流程,局部坐标变换 -> 世界坐标变换 ->观察坐标变换->背面消除->光照->裁剪->投影->视口计算->光栅化,程序员只需要调用固定的api修改一些配置参数就可以完成整个渲染流程了。而到了2.0,固定管线改成了可编程管线,我们对整个渲染流程可以再编程,没有固定的api给你调用,一切都依靠shader来完成。那么什么是shader呢:
GLuint _renderBuffer;
GLuint _frameBuffer; glGenRenderbuffers(, &_renderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, _renderBuffer);
[_eaglContext renderbufferStorage:GL_RENDERBUFFER fromDrawable: (id<EAGLDrawable>)self.layer]; glGenFramebuffers(, &_frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
GL_RENDERBUFFER,
_renderBuffer);
在设置缓存之前,最好先清理一次,避免重复设置
if (_frameBuffer) {
glDeleteFramebuffers(, &_frameBuffer);
_frameBuffer = ;
}
if (_renderBuffer) {
glDeleteRenderbuffers(, &_renderBuffer);
_renderBuffer = ;
}
设置好缓存之后开始编译着色器,基本上编译着色器的步骤都是固定,图像处理,滤镜实现基本都是通过着色器来完成。以下是编译着色器的代码。
GLuint _program;
GLunit _positionSlot;
_program = [MTShaderOperations compileShaders:@"Vertex"
shaderFragment:@"Fragment"];
glUseProgram(_program);
_positionSlot = glGetAttribLocation(_program, "Position");
glUseProgram(_program);
//绑定着色器中的参数
_positionSlot = glGetAttribLocation(_program, "Position");
+ (GLuint)compileShaders:(NSString *)shaderVertex shaderFragment:(NSString *)shaderFragment {
// 1 vertex和fragment两个shader都要编译
GLuint vertexShader = [MTShaderOperations compileShader:shaderVertex withType:GL_VERTEX_SHADER];
GLuint fragmentShader = [MTShaderOperations compileShader:shaderFragment withType:GL_FRAGMENT_SHADER];
// 2 连接vertex和fragment shader成一个完整的program
GLuint _glProgram = glCreateProgram();
glAttachShader(_glProgram, vertexShader);
glAttachShader(_glProgram, fragmentShader);
// link program
glLinkProgram(_glProgram);
// 3 check link status
GLint linkSuccess;
glGetProgramiv(_glProgram, GL_LINK_STATUS, &linkSuccess);
if (linkSuccess == GL_FALSE) {
GLchar messages[];
glGetProgramInfoLog(_glProgram, sizeof(messages), , &messages[]);
NSString *messageString = [NSString stringWithUTF8String:messages];
NSLog(@"%@", messageString);
exit();
}
return _glProgram;
}
+ (GLuint)compileShader:(NSString*)shaderName withType:(GLenum)shaderType {
// 1 查找shader文件
NSString* shaderPath = [[NSBundle mainBundle] pathForResource:shaderName ofType:@"glsl"];
NSError* error;
NSString* shaderString = [NSString stringWithContentsOfFile:shaderPath encoding:NSUTF8StringEncoding error:&error];
if (!shaderString) {
NSLog(@"Error loading shader: %@", error.localizedDescription);
exit();
}
// 2 创建一个代表shader的OpenGL对象, 指定vertex或fragment shader
GLuint shaderHandle = glCreateShader(shaderType);
// 3 获取shader的source
const char* shaderStringUTF8 = [shaderString UTF8String];
int shaderStringLength = (int)[shaderString length];
glShaderSource(shaderHandle, , &shaderStringUTF8, &shaderStringLength);
// 4 编译shader
glCompileShader(shaderHandle);
// 5 查询shader对象的信息
GLint compileSuccess;
glGetShaderiv(shaderHandle, GL_COMPILE_STATUS, &compileSuccess);
if (compileSuccess == GL_FALSE) {
GLchar messages[];
glGetShaderInfoLog(shaderHandle, sizeof(messages), , &messages[]);
NSString *messageString = [NSString stringWithUTF8String:messages];
NSLog(@"%@", messageString);
exit();
}
return shaderHandle;
}
当然,要编译着色器,首先我们要写好着色器代码。绘制多边形的着色器代码十分简单,如果有不懂得童鞋可以参考OpenGL着色语言(GLSL―OpenGL Shading Language)
新建一个empty文件,然后将后缀改成glsh就可以开始写着色器代码了。
Vertex Shader代码如下:
attribute vec4 Position; void main(void)
{
gl_Position = Position; }
Fragment Shader代码如下
void main(void)
{ gl_FragColor = vec4(0,1,1, 1.0);
}
编译好着色器之后,我们就可以开始绘制图形了,在这里要注意的是在openGLES中只能画三角形,所有的图形都是由三角形组成的。
还有,在定义顶点时要注意openGL中的坐标系不同于UIKit。
首先定义顶点数组
const GLfloat vertices[] = {
-, -, , //左下
, -, , //右下
-, , , //左上
, , }; //右上
绘制图形
//传入顶点参数
glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, 0, vertices);
glEnableVertexAttribArray(_positionSlot);
//绘制多边形
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
在上面我们画出了多边形,这个多边形是顶点数组按照顺序画出所有的三角形,在不少情况下,并不能符合我们的要求。我们可以试着将上面最后一句改成
glDrawArrays(GL_TRIANGLE_STRIP, 1, );
得到的图像如下

由于openGL只能画三角形,因此在顶点数组中,顶点按照怎样的顺序链接十分重要。因此在openGLES中提供了另一个方法。
//定义索引数组
const GLubyte indices[] = {
,,,
,,
};
//根据索引数组的顺序画出多边形
glDrawElements(GL_TRIANGLES, sizeof(indices)/sizeof(indices[0]), GL_UNSIGNED_BYTE, indices);
这样我们就画出了一个四边形,其他多边形也是一样的步骤。
下一篇章我们会讲如何传入一个纹理,敬请期待。
IOS 中openGL使用教程2(openGL ES 入门篇 | 绘制一个多边形)的更多相关文章
- iOS-----openGL--openGL ES iOS 入门篇2--->绘制一个多边形
在上一篇我们学习了如何搭建IOS下openGL的开发环境,接下来我们来学习如何绘制一个多边形. 在2.0之前,es的渲染采用的是固定管线,何为固定管线,就是一套固定的模板流程,局部坐标变换 -> ...
- IOS 中openGL使用教程3(openGL ES 入门篇 | 纹理贴图(texture)使用)
在这篇文章中,我们将学习如何在openGL中使用纹理贴图. penGL中纹理可以分为1D,2D和3D纹理,我们在绑定纹理对象的时候需要指定纹理的种类.由于本文将以一张图片为例,因此我们为我们的纹理对象 ...
- animation-play-state 在 ios 中不生效的解决办法(JS篇)
我们要实现动画的播放和暂停,animation-play-state 在安卓端可以使用,但是在 ios 中不起作用,这时可以使用 js 来实现相同效果. 原理 通过 js 获取当前元素的 transf ...
- IOS 中openGL使用教程1(openGL ES 入门篇 | 搭建openGL环境)
OpenGL版本 iOS系统默认支持OpenGl ES1.0.ES2.0以及ES3.0 3个版本,三者之间并不是简单的版本升级,设计理念甚至完全不同,在开发OpenGL项目前,需要根据业务需求选择合适 ...
- IOS 中openGL使用教程4(openGL ES 入门篇 | 离屏渲染)
通常情况下,我们使用openGL将渲染好的图片绘制到屏幕上,但有时候我们不想显示处理结果,这时候就需要使用离屏渲染了. 正常情况下,我们将屏幕,也就是一个CAEAGLLayer对象作为渲染目标,离屏渲 ...
- [原]OpenGL基础教程(四)VBO+纹理绘制四边形
工程下载地址:http://pan.baidu.com/s/1ntr7NHv 提取码:yf1h 一.本文牵扯知识点梳理: (1)VBO (2)纹理 (3)libpng(加载png) (4)shader ...
- sql语句中出现笛卡尔乘积 SQL查询入门篇
2014-12-29 凡尘工作室 阅 34985 转 95 本篇文章中,主要说明SQL中的各种连接以及使用范围,以及更进一步的解释关系代数法和关系演算法对在同一条查询的不同思路. 多表连接简介 ...
- Git & Github 使用教程【1】入门篇
Github教程 1-1 版本管理工具简介 主要作用:备份文件.记录历史.回到过去.多端共享.独挡一面.团队协作 2-1 版本管理工具发展历史 3-1 Git下载和安装[略] 3-2 linux下安装 ...
- [转]sql语句中出现笛卡尔乘积 SQL查询入门篇
本篇文章中,主要说明SQL中的各种连接以及使用范围,以及更进一步的解释关系代数法和关系演算法对在同一条查询的不同思路. 多表连接简介 在关系数据库中,一个查询往往会涉及多个表,因为很少有数据库只有一个 ...
随机推荐
- 转载《Android Handler、Message》
之前也是由于周末通宵看TI3比赛,一直没找到时间写博客,导致已经有好久没更新了.惭愧!后面还会恢复进度,尽量保证每周都写吧.这里也是先恭喜一下来自瑞典的Alliance战队夺得了TI3的冠军,希望明年 ...
- 转:仿QQ长按弹出功能菜单
android app普遍常用的弹出上下文菜单是列表式的.QQ列表,在上方弹出冒泡效果菜单,如图 这里讲解一下如何写出这个效果: 图片资源:两张图片,可以拼接成如上效果. 首先,我们需要写布局文件: ...
- 收藏:Linux系统信息查看命令大全
系统# uname -a # 查看内核/操作系统/CPU信息# head -n 1 /etc/issue # 查看操作系统版本# cat /proc/cpuinfo ...
- 1 error C4996: 'pcl::SAC_SAMPLE_SIZE':
使用PCL1.8 中使用粗配准拼接 错误 1 error C4996: 'pcl::SAC_SAMPLE_SIZE': This map is deprecated and is kept onl ...
- 文件权限及特殊权限管理SUID、SGID和Sticky
文件权限应用模型: 进程的发起者: 进程属主 进程的属组: 进程属组 进程的属主,是否与文件的属主相同,如果相同,进程则以文件属主的权限来访问文件:否则进程的属主所属的组,其中之一是 ...
- Monkey环境搭建
一.Monkey 1)Monkey是什么? Monkey是SDK中附带的一个工具.是Android中的一个命令行工具,可以运行在模拟器里或实际设备中.它向系统发送伪随机的用户事件流(如按键输入.触摸屏 ...
- Qt开发中的实用笔记三--关于各种类的零碎知识点:
1,QUuid()创建唯一标识码,在创建数据库实体ID和链接数据库QSqlDatabase时非常方便 2,QScrollArea与QScrollBar,如果是要在widget中添加窗口滑动QScrol ...
- ubuntu 16.04 启用root用户方法
引用:http://blog.csdn.net/sunxiaoju/article/details/51993091 1.使用:sudo passwd root设置root的密码,如下图所示: 2.使 ...
- Web 应用程序中的安全向量 – ASP.NET MVC 4 系列
Web 程序运行在标准的.基于文本的协议(HTTP 和 HTML)之上,所以特别容易受到自动攻击的伤害.本章主要介绍黑客如何滥用应用程序,以及针对这些问题的应对措施. 威胁:跨站脚本 ...
- C# 隐式类型转换
implicit(C# 参考) implicit 关键字用于声明隐式的用户定义类型转换运算符.如果可以确保转换过程不会造成数据丢失,则可使用该关键字在用户定义类型和其他类型之间进行隐式转换. clas ...