一、理解

顶点数据存储在申请的缓冲区中,其由数据总线传递给着色器(如果是片元着色器,还须将顶点转换成片元),再由着色器最终渲染到涂层上;

二、思路

1.设置涂层;

2.创建上下文;

3.清空缓存区;

4.创建渲染缓存区和帧缓存区;

5.开始绘制;

三、核心代码

//最终渲染

- (void)renderLayer
{
//设置窗口背景颜色
glClearColor(0.0, 0.0, 0.0, 1.0);
//清空颜色缓存
glClear(GL_COLOR_BUFFER_BIT);
//设置视口大小
CGFloat scale = [[UIScreen mainScreen] scale];
glViewport(self.frame.origin.x*scale, self.frame.origin.y*scale, self.frame.size.width*scale, self.frame.size.height*scale); //读取顶点和片元着色器程序
NSString *vertFile = [[NSBundle mainBundle] pathForResource:@"shaderv" ofType:@"glsl"];
NSString *fragFile = [[NSBundle mainBundle] pathForResource:@"shaderf" ofType:@"glsl"];
NSLog(@"vertFile:%@", vertFile);
NSLog(@"fragFile:%@", fragFile); //判断myProgram是否存在,存在则清空
if (self.myProgram) {
glDeleteProgram(self.myProgram);
self.myProgram = ;
} //加载着色器到myProgram中
self.myProgram = [self loadShader:vertFile frag:fragFile]; //创建链接
glLinkProgram(self.myProgram);
GLint linkSuccess; //获取链接状态
glGetProgramiv(self.myProgram, GL_LINK_STATUS, &linkSuccess); //判断链接是否成功
if (linkSuccess == GL_FALSE) {
//获取失败信息
GLchar message[];
glGetProgramInfoLog(self.myProgram, sizeof(message), , &message[]);
//c字符串转换成oc字符串
NSString *messageString = [NSString stringWithUTF8String:message];
NSLog(@"error:%@", messageString);
return;
} else {
//使用myProgram
glUseProgram(self.myProgram);
} //创建绘制索引数组
GLuint indices[] = {
, , ,
, , ,
, , ,
, , ,
, , ,
, ,
}; //判断顶点缓存区是否为空,为空则申请一个缓存区标志符
if (self.myVertices == ) {
glGenBuffers(, &_myVertices);
} //----------处理顶点坐标--------- /*顶点数据
1.前3个坐标值(x、y、z),后3个颜色值(RGB);
2.有先后顺序,否则绘制形状完全不同
*/
GLfloat attrArr[] =
{
-0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, //左上
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, //右上
-0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, //左下
0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, //右下
0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, //顶点
}; //将_myVertices绑定到GL_ARRAY_BUFFER标志符上
glBindBuffer(GL_ARRAY_BUFFER, _myVertices);
//把顶点坐标数据从CPU复制到GPU上
glBufferData(GL_ARRAY_BUFFER, sizeof(attrArr), attrArr, GL_DYNAMIC_DRAW); //将顶点坐标数据通过myProgram传递到顶点着色器程序的position //获取顶点属性入口
GLuint position = glGetAttribLocation(self.myProgram, "position");
/*传递数据
1.一行6个数据,前3个为坐标,后3个为颜色;
2.NULL开始位置:默认为0,指向数组首地址;
*/
glVertexAttribPointer(position, , GL_FLOAT, GL_FALSE, sizeof(GLfloat)*, NULL);
//设置合适的格式从缓存区中读取数据
glEnableVertexAttribArray(position); //处理顶点颜色数据:传递到顶点着色器的positionColor
GLuint positionColor = glGetAttribLocation(self.myProgram, "positionColor");
glVertexAttribPointer(positionColor, , GL_FLOAT, GL_FALSE, sizeof(GLfloat)*, (float *)NULL +);
glEnableVertexAttribArray(positionColor); //在myProgram中找到透视投影矩阵和模型视图矩阵
GLuint projectionMatrixSlot = glGetUniformLocation(self.myProgram, "projectionMatrix");
GLuint modelViewMatrixSlot = glGetUniformLocation(self.myProgram, "modelViewMatrix"); //创建透视投影矩阵并初始化
float width = self.frame.size.width;
float height = self.frame.size.height;
KSMatrix4 _projectionMatrix;
ksMatrixLoadIdentity(&_projectionMatrix);
float aspect = width/height;
ksPerspective(&_projectionMatrix, 30.0, aspect, 5.0f, 20.0f); //设置glsl里面的投影矩阵
glUniformMatrix4fv(projectionMatrixSlot, , GL_FALSE, (GLfloat *)&_projectionMatrix.m[][]); //开启剔除功能
glEnable(GL_CULL_FACE); //创建平移矩阵:Z轴平移-10
KSMatrix4 _modelViewMatrix;
ksMatrixLoadIdentity(&_modelViewMatrix);
ksTranslate(&_modelViewMatrix, 0.0, 0.0, -10.0); //创建旋转矩阵
KSMatrix4 _rotationMatrix;
ksMatrixLoadIdentity(&_rotationMatrix);
ksRotate(&_rotationMatrix, xDegree, 1.0, 0.0, 0.0);
ksRotate(&_rotationMatrix, yDegree, 0.0, 1.0, 0.0);
ksRotate(&_rotationMatrix, zDegree, 0.0, 0.0, 1.0); //将平移矩阵和旋转矩阵相乘,结果放到模型视图矩阵中
ksMatrixMultiply(&_modelViewMatrix, &_rotationMatrix, &_modelViewMatrix); //设置glsl里面的模型视图矩阵
glUniformMatrix4fv(modelViewMatrixSlot, , GL_FALSE, (GLfloat *)&_modelViewMatrix.m[][]); //设置绘制参数:片元、个数、索引数组
glDrawElements(GL_TRIANGLES, sizeof(indices)/sizeof(indices[]), GL_UNSIGNED_INT, indices); //由顶点着色器将缓存区中的数据渲染到显示涂层上
[self.myContext presentRenderbuffer:GL_RENDERBUFFER];
}

四、效果

以上是采用GLSL自定义着色器绘制,下面是采用GLKit框架并添加纹理来绘制

//核心代码

- (void)renderLayer
{
//顶点数据:前3个坐标(x、y、z),中间三个颜色(RGB),最后2个坐标(纹理)
GLfloat attrArr [] = {
-0.5, 0.5, 0.0, 0.0, 0.0, 0.5, 0.0, 1.0,
0.5, 0.5, 0.0, 0.0, 0.5, 0.0, 1.0, 1.0,
-0.5, -0.5, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0,
0.5, -0.5, 0.0, 0.0, 0.0, 0.5, 1.0, 0.0,
0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.5, 0.5
}; //绘图索引
GLuint indices[] =
{
, , ,
, , ,
, , ,
, , ,
, , ,
, , ,
}; //顶点个数
self.count = sizeof(indices)/sizeof(GLuint); //顶点数据存入缓存区:CPU->GPU
GLuint buffer;
glGenBuffers(, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(attrArr), attrArr, GL_STATIC_DRAW); //索引数据存入缓存区:CPU->GPU
GLuint index;
glGenBuffers(, &index);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); //传递顶点数据到着色器指定位置
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, , GL_FLOAT, GL_FALSE, sizeof(GLfloat)*, NULL); //顶点颜色数据
glEnableVertexAttribArray(GLKVertexAttribColor);
glVertexAttribPointer(GLKVertexAttribColor, , GL_FLOAT, GL_FALSE, sizeof(GLfloat)*, (GLfloat *)NULL + ); //顶点纹理数据
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
glVertexAttribPointer(GLKVertexAttribTexCoord0, , GL_FLOAT, GL_FALSE, sizeof(GLfloat)*, (GLfloat *)NULL + ); //加载纹理
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"cTest" ofType:@"jpg"];
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:@"", GLKTextureLoaderOriginBottomLeft, nil];
GLKTextureInfo *textureInfo = [GLKTextureLoader textureWithContentsOfFile:filePath options:options error:nil]; self.mEffect = [[GLKBaseEffect alloc] init];
self.mEffect.texture2d0.enabled = GL_TRUE;
self.mEffect.texture2d0.name = textureInfo.name; //创建透视投影矩阵
CGSize size = self.view.bounds.size;
float aspect = fabs(size.width/size.height);
GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(90.0), aspect, 0.1, 10.0);
//设置等比缩放
projectionMatrix = GLKMatrix4Scale(projectionMatrix, 1.0, 1.0, 1.0); self.mEffect.transform.projectionMatrix = projectionMatrix; //设置平移:Z轴负方向平移2.0
GLKMatrix4 modelViewMatrix = GLKMatrix4Translate(GLKMatrix4Identity, 0.0, 0.0, -2.0);
self.mEffect.transform.modelviewMatrix = modelViewMatrix; //设置定时器
double seconds = 0.1;
timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, , , dispatch_get_main_queue());
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, seconds*NSEC_PER_SEC, );
dispatch_source_set_event_handler(timer, ^{
self.xDegree += 0.1*self.XB;
self.yDegree += 0.1*self.YB;
self.zDegree += 0.1*self.ZB;
});
dispatch_resume(timer);
}

效果:

GitHub

OpenGL ES 渲染立体图形的更多相关文章

  1. 使用OpenGL ES绘制3D图形

    如果应用定义的顶点不在同一个平面上,并且使用三角形把合适的顶点连接起来,就可以绘制出3D图形了. 使用OpenGL  ES绘制3D图形的方法与绘制2D图形的步骤大致相同,只是绘制3D图形需要定义更多的 ...

  2. 基于Cocos2d-x学习OpenGL ES 2.0系列——OpenGL ES渲染之Shader准备(7)

    Cocos2d-x底层图形绘制是使用OpenGL ES协议的.OpenGL ES是什么呢? OpenGL ES(OpenGl for Embedded System)是OpenGL三维图形API的子集 ...

  3. 基于Cocos2d-x学习OpenGL ES 2.0系列——OpenGL ES渲染之LayerColor(8)

    在前面文章中讲述了Cocos2d-x引擎OpenGL渲染准备Shader方面,本文主要讲解使用LayerColor来讲述OpenGL的渲染过程. 1.LayerColor对象创建 添加LayerCol ...

  4. 一步步实现windows版ijkplayer系列文章之六——SDL2源码分析之OpenGL ES在windows上的渲染过程

    一步步实现windows版ijkplayer系列文章之一--Windows10平台编译ffmpeg 4.0.2,生成ffplay 一步步实现windows版ijkplayer系列文章之二--Ijkpl ...

  5. Android 中建立一个OpenGL ES的开发环境

    转自: http://wiki.eoe.cn/page/Building_an_OpenGL_ES_Environment.html 负责人:zhangql原文链接:http://docs.eoean ...

  6. 【Android Developers Training】 62. 搭建一个OpenGL ES环境

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  7. Android OpenGL ES 开发(二): OpenGL ES 环境搭建

    零:环境搭建目的 为了在Android应用程序中使用OpenGL ES绘制图形,必须要为他们创建一个视图容器.其中最直接或者最常用的方式就是实现一个GLSurfaceView和一个GLSurfaceV ...

  8. OpenGL ES: (3) EGL、EGL绘图的基本步骤、EGLSurface、ANativeWindow

    1. EGL概述 EGL 是 OpenGL ES 渲染 API 和本地窗口系统(native platform window system)之间的一个中间接口层,它主要由系统制造商实现. EGL提供如 ...

  9. 在Android中使用OpenGL ES进行开发第(一)节:概念先行

    一.前期基础是知识储备笔者计划写三篇文章来详细分析OpenGL ES基础的同时也是入门关键的三个点: ①OpenGL ES是什么?与OpenGL的关系是什么?——概念部分 ②使用OpenGL ES绘制 ...

随机推荐

  1. 浏览器根对象navigator之对象属性概览

    第1章 connection[试验] navigator.connection 是只读的,提供一个NetworkInformation 对象来获取设备的网络连接信息.例如用户设备的当前带宽或连接是否被 ...

  2. ASP.NET Claims-based认证实现认证登录-claims基础知识

    claims-based认证这种方式将认证和授权与登录代码分开,将认证和授权拆分成另外的web服务.活生生的例子就是我们的qq集成登录,未必qq集成登录采用的是claims-based认证这种模式,但 ...

  3. 一种特殊场景下的HASH JOIN的优化为NEST LOOP.

    应用场景: 有如下的SQL: select t.*, t1.ownerfrom t, t1where t.id=t1.id; 表t ,t1的数据量比较大,比如200W行.但是两张表能关联的行数却很少, ...

  4. CSS 引入方式 选择器

    ---恢复内容开始--- CSS是Cascading Style Sheets的简称,中文称为层叠样式表,用来控制网页数据的表现,可以使网页的表现与数据内容分离. 步骤: A.找到标签 B.操作标签 ...

  5. c# 多线程之-- System.Threading Timer的使用

    作用:每隔多久去执行线程里的方法. class ThreadTimerDemo { static void Main(string[] args) { // Create an AutoResetEv ...

  6. ps命令之排序

    Linux中ps命令会自动选择一列进行排序,但有时这不是我们想要的. 方法一: ps+sort sort 选项与参数: -f  :忽略大小写的差异,例如 A 与 a 视为编码相同:-b  :忽略最前面 ...

  7. flask 的管理模块的功能add_template_global、send_from_directory

    add_template_global方法 全局模板函数 add_template_global 装饰器直接将函数注册为模板全局函数. add_template_global 这个方式是自定义的全局函 ...

  8. 测试SDWebImage淡入淡出效果在UITableView中的重用显示问题

    测试SDWebImage淡入淡出效果在UITableView中的重用显示问题 这个是在上一篇教程的基础上所添加的测试环节! 效果图(从效果图中看是没有任何重用问题的): 源码: ImageCell.h ...

  9. oracle 复制表结构 复制表数据 sql 语句

    1. 复制表结构及其数据: create table table_name_new as select * from table_name_old 2. 只复制表结构: create table ta ...

  10. 铁乐学python_Day44_IO多路复用

    目录 IO模型介绍 阻塞IO(blocking IO) 非阻塞IO(non-blocking IO) 多路复用IO(IO multiplexing) 异步IO(Asynchronous I/O) IO ...