一、理解

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

二、思路

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. h5笔记

    标签 更语义化标签 header标签 nav标签 section标签 article标签 aside标签 widget标签 footer标签 为什么要有语义化标签 能够便于开发者阅读和写出更优雅的代码 ...

  2. content-box与border-box区别

    理解box-sizing属性border-box,content-box,其实也是理解正常盒模型与异常盒模型. 正常盒模型 正常盒模型,是指块元素box-sizing属性为content-box的盒模 ...

  3. RPC簡介

    RPC 技术原理       RPC ( Remote Procedure Call Protocol,远程过程调用协议 ): 客户端在不知道调用细节的情况下,调用存在于远程计算机上的某个对象,就像调 ...

  4. javascript的继承实现

    javascript虽然是一门面向对象的语言,但是它的继承机制从一开始设计的时候就不同于传统的其他面向对象语言,是基于原型的继承机制,但是在这种机制下,继承依然有一些不同的实现方式. 方法一:类式继承 ...

  5. c# 从一个服务器 访问另外一个服务器上的文件

    页面调用 function fnOpen(path) { window.open("~/FileHelp.ashx? url="); //window.open(url); } 后 ...

  6. 异度之刃 Xenoblade 后感

    WII版重置的N3DS劣化版异度之刃终于通关了.在出色的自制系统的快乐NTR的帮助下,充分体验到了神作的剧情史诗感. 关于游戏的玩法系统,从现在来看8年前的游戏,缺点显而易见,特别是跑地图这回事,地图 ...

  7. 使用 Azure 门户创建 Linux 虚拟机

    可以通过 Azure 门户创建 Azure 虚拟机. 此方法提供一个基于浏览器的用户界面,用于创建和配置虚拟机和所有相关的资源. 本快速入门介绍了如何创建虚拟机并在 VM 上安装 webserver. ...

  8. 制作动态logo教程

    本人从事iOS开发工作,但对特效制作很感兴趣,现提供一份教程,制作本人logo的教程. 上图是用 Photoshop 与 After Effects 与 GIF Movie Gear 合力制作的动态图 ...

  9. 解决linux buffer/cache 消耗内存过高引发的问题

    工作中接到DBA报障某台服务器 跑一些大的数据,服务器就无法远程连接,报错,抓过日志叫DELL工程师检测也没问题,系统也重装过, 现在些一些较大的数据就会报如 图错误,由于服务器远在异地城市IDC机房 ...

  10. 修改Linux SSH连接端口和禁用IP,安装DDoS deflate

    测试系统:centos7 修改连接端口 修改配置文件 vi /etc/ssh/sshd_config 去掉port 22的注释,添加新的端口配置 port your_port_num 自定义端口选择建 ...