一、理解

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

二、思路

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. git push 提示 Everything up-to-date

    第一次在 Google Code 上弄项目,注册完毕后,尝试增加一个新文件用以测试 Git 是否好好工作.结果在 Push 时却显示 Every up-to-date,检查文件时却发现实际上一个都没更 ...

  2. Linux+db2+was部署问题总结

     Linux+db2+was部署问题总结 前段日子在住建部进行了Linux环境下,db2+rbp+was的部署,由于是集群,切涉及到了很多was的东西,搞了很长时间,在此做一个问题总结,供后续查询 ...

  3. RollViewPager图片轮播效果开源框架的使用

    RollViewPager是一个自动轮播的Viewpager, 支持无限循环. 触摸时会暂停播放,直到结束触摸一个延迟周期以后继续播放. 看起来就像这样.指示器可以为点可以为数字还可以自定义,位置也可 ...

  4. Axure中移动端原型设计方法(附IPhoneX和IPhone8最新模板)

    Axure中移动端原型设计方法(附IPhoneX和IPhone8最新模板) 2018年4月16日luodonggan Axure中基于设备模板的移动端原型设计方法(附IPhoneX和IPhone8最新 ...

  5. HBase 负载均衡

    HBase 可以根据当前集群的负载以region为单位进行rebalance.在HMaster中,后台会起一个线程定期检查是否需要进行rebalance,线程叫做BalancerChore.线程每隔  ...

  6. Java中的消息框

    JOptionPane.showMessageDialog(newFrame.getContentPane(),"弹出的是消息提示框!", "系统信息", JO ...

  7. Script" References MACLEAN‘s post Speed ​​up the index creation.

    alter session set workarea_size_policy=MANUAL; alter session set db_file_multiblock_read_count=512; ...

  8. CSS一个属性,让图片后的文字垂直居中,效果看得见

    困扰我多年的疑难,终于解决了.哈哈哈,太爽了 背景 页面经常遇到,图片后面的文字显示在图片的中间部位,也就是说文字图片垂直居中. <div class="banner"> ...

  9. <Lord don’t move that mountain>

    <Lord don’t move that mountain> Lord, don't move that mountain(主,不要移走高山) Give me strength to c ...

  10. python3: 字符串和文本(4)

    16. 以指定列宽格式化字符串[textwrap] https://docs.python.org/3.6/library/textwrap.html#textwrap.TextWrapper 假如你 ...