一、理解

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

二、思路

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. Ajax 与 JSON

    Ajax,是对Asynchronous JavaScript + XML的简写.这一技术能够向服务器请求额外的数据而无需卸载页面,会带来更好的用户体验. Ajax的核心是XMLHttpRequest对 ...

  2. phoenix使用vue--单独js(不使用app.js)

    实际中不能都在一个js里 api.js app.js admin.js --vue 后台 记录下方法 static--admin--hello.js import "phoenix_html ...

  3. 深度学习GPU集群管理软件 OpenPAI 简介

    OpenPAI:大规模人工智能集群管理平台 2018年5月22日,在微软举办的“新一代人工智能开放科研教育平台暨中国高校人工智能科研教育高峰论坛”上,微软亚洲研究院宣布,携手北京大学.中国科学技术大学 ...

  4. python学习笔记之——python模块

    1.python模块 Python 模块(Module),是一个 Python 文件,以 .py 结尾,包含了 Python 对象定义和Python语句. 模块让你能够有逻辑地组织你的 Python ...

  5. 数组转换list集合问题

    1问题的起因: 项目总要使用一个方法把数组转换成list集合,百度说有这个方法Arrays.asList可以实现 2结果报错 抛出java.lang.UnsupportedOperationExcep ...

  6. js判断字符串出现的次数

    // 判断substr字符串在str中出现的次数 isIgnore是否忽略大小写! function countSubstr(str, substr, isIgnore) { var count; v ...

  7. 转载:https://blog.csdn.net/qq_22706515/article/details/52595027

    https://blog.csdn.net/qq_22706515/article/details/52595027 包含直播,即时通讯. 大平台都有免费版或基础版,对于需求不大的情况比较适合.

  8. HAproxy simple

    下载地址 start install: wget     http://www.haproxy.org/download/1.7/src/haproxy-1.7.5.tar.gz tar   -xf  ...

  9. Oracle案例12——NBU Oracle恢复

    最近在做NBU ORACLE备份的恢复测试,执行恢复时报错ORA-27211: Failed to load Media Management Library,具体处理过程如下:一.错误信息 执行命令 ...

  10. mongodb/python3.6/mysql的安装

    1 下载与解压 在官网下载mongodb安装包 tar -zxvf mongodb-linux-x86_64-ubuntu1604-3.4.0.tgz 2 移动安装文件 sudo mv mongodb ...