Ⅰ 怎么在ios开发中使用opengl
一、搭建开发环境
1. 打开Xcode, 新建一个工程
选择:IOS -> Application -> Single View Application模板
输入工程名称和基本信息,勾选“UseStoryboards”,然后创建
2. 添加必要的框架
在“Build Phases”中,添加三个框架
3. 修改viewController。h
添加 “#import”,并将它修改为继承"GLKViewController"
4. 修改“view”的类
双击“MainStoryboard.storyboard”展开,选择"view"
然后,在“Identity Inspector"中,将它的类改为”GLKView“
好了,OpenGL的环境基本上搭建出来了。
二、增加自己代码
基本上,所有的代码都是加到ViewController.m文件中
1、添加全局山圆属性声明
@interface ViewController ()@property(strong,nonatomic)EAGLContext*
context;@property(strong,nonatomic)GLKBaseEffect* effect;@end@implementation
ViewController@synthesize context, effect;
2、 添加一组顶点数据
这是一个正方形顶点数组。实际上它是二个三角形接合而成的
GLfloat squareVertexData[48] ={ 0.5f, 0.5f, -0.9f, 0.0f, 0.0f, 1.0f, 1.0f,
1.0f, -0.5f, 0.5f, -0.9f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.5f, -0.5f, -0.9f,
0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.5f, -0.5f, -0.9f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.9f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, -0.5f, -0.5f, -0.9f, 0.0f,
0.0f, 1.0f, 1.0f, 1.0f,};
每行顶点数据的排列蠢樱含义是:
顶点X、顶点Y,顶点Z、法线X、法线Y、法线Z、纹理S、纹理T。
在后面解析此数组时,将参考此规则。
顶点位置用于确定在什么地方显示,法线用于光照模型计算,纹理则用在贴图中。
一般约定为“顶点以逆时针次序出现在屏幕上的面”为“正面”。
世界坐标是OpenGL中用来描述场景的坐标,Z+轴垂直屏幕向外,X+从左到右,Y+轴从下到上,是右手笛卡尔坐标系统。我们用这个坐标系来描述物体及光源的位置。
三、初始化OpenGL环境逗档塌
1、 基本的初始化代码
在ViewController.m中有个函数(void)viewDidLoad,它是程序运行时,初始化回调函数。在viewDidLoad函数内补充我们自己的初始化代码。
// 使用“ES2”创建一个“EAGLEContext”实例 self.context = [[[EAGLContext
alloc]initWithAPI:kEAGLRenderingAPIOpenGLES2]autorelease]; //
将“view”的context设置为这个“EAGLContext”实例的引用。并且设置颜色格式和深度格式。 GLKView* view =
(GLKView*)self.view; view.context = self.context; view.drawableColorFormat =
; view.drawableDepthFormat =
GLKViewDrawableDepthFormat24; //
将此“EAGLContext”实例设置为OpenGL的“当前激活”的“Context”。这样,以后所有“GL”的指令均作用在这个“Context”上。随后,发送第一个“GL”指令:激活“深度检测”。
[EAGLContext setCurrentContext:context]; glEnable(GL_DEPTH_TEST); //
创建一个GLK内置的“着色效果”,并给它提供一个光源,光的颜色为绿色。 self.effect = [[[GLKBaseEffect
alloc]init]autorelease]; self.effect.light0.enabled = GL_TRUE;
self.effect.light0.diffuseColor = GLKVector4Make(0.0f, 1.0f, 0.0f, 1.0f);
2、 运行。现在应该是粉红色屏幕了(目前场景仍是空的),说明初始化过程没问题
四、 将项点数据写入能用的顶点属性存储区
1、 写入过程
首先将数据保存进GUP的一个缓冲区中,然后再按一定规则,将数据取出,复制到各个通用顶点属性中。
注:如果顶点数据只有一种类型(如单纯的位置坐标),换言之,在读数据时,不需要确定第一个数据的内存位置(总是从0开始),则不必事先保存进缓冲区。
2、 顶点数组保存进缓冲区
//
声明一个缓冲区的标识(GLuint类型)让OpenGL自动分配一个缓冲区并且返回这个标识的值.绑定这个缓冲区到当前“Context”.最后,将我们前面预先定义的顶点数据“squareVertexData”复制进这个缓冲区中。
// 注:参数“GL_STATIC_DRAW”,它表示此缓冲区内容只能被修改一次,但可以无限次读取。 GLuint buffer;
glGenBuffers(1, &buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(squareVertexData), squareVertexData,
GL_STATIC_DRAW);
3、将缓冲区的数据复制进能用顶点属性中
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 4*8,
(char*)NULL + 0);
首先,激活顶点属性(默认它的关闭的)。“GLKVertexAttribPosition”是顶点属性集中“位置Position”属性的索引。
顶点属性集中包含五种属性:位置、法线、颜色、纹理0,纹理1。
它们的索引值是0到4。
激活后,接下来使用“glVertexAttribPointer”方法填充数据。
Ⅱ iOS-OpenGLES-入门-纹理
这是一篇OpenGlES 系统学习教程,记录自己的学习过程。
环境: Xcode10 + OpenGL ES 3.0
目标: 纹理贴图技术
这里 是demo,你的star和fork是对我最好的支持和动力。
纹理坐标在x和y轴上,范围为0到1之间(注意我们使用的是2D纹理图像)。使用纹理坐标获取纹理颜色叫做采样(Sampling)。纹理坐标起始于(0, 0),也就是纹理图片的左下角,终始于(1, 1),即纹理图片的右上角。
下面的图片展示了昌余我们是如何把纹理坐标映射到三角形上的。
纹理的部分理论知耐档滚识可以参考 这里
跟生成OpenGl 对象差不多
glTexImage2D 原型如下:
一个纹理的位置值通常称为一个纹理单元(Texture Unit)。一个纹理的默认纹理单元是0,它是默认的激活纹理单元,本文前面部分我们没有分配一个位置值。如果使用多个纹理单元需要手动分配。
纹理单元的主要目的是让我们在着色器中可以使用多于一个的纹理。通过把纹理单元赋值给采样器,我们可以一次绑定多个纹理,只要我们首先激活对应的纹理单元。就像glBindTexture一样,我们可以使用glActiveTexture激活纹理单元,传入我们需要使用的纹理单元:
你可能会奇怪为什么sampler2D变量是个uniform,我们却不用glUniform给它赋值。使用glUniform1i,我们可以给纹理采样器分配一个位置值,这样的话我们能够在一个片段着色器中设置多个纹理。
纹理上蠢毕下颠倒解决方法
注:这里使用到了Vertex Buffer Object,下篇会详解。
Ⅲ iOS-OpenGLES-入门-立方体
这是一篇OpenGlES 系统学习教程,记录自己的学习过程。
环境: Xcode10.2 + OpenGL ES 3.0
目标: 3D 立方体
这里 是demo,你的star和fork是对我最好的支持和动力。
主要有5个不同的坐标系统:
变换
为了将坐标从一个坐标系变换到另一个坐标系,我们需要用到几个变换矩阵,最重要的几个分别是 模型 (Model)、 观察 (View)、 投影 (Projection)三个矩阵。我们的顶点坐标起始于 局部空间 (Local Space),在这里它称为 局部坐标 (Local Coordinate),它在之后会变为 世界坐标 (World Coordinate), 观察坐标 (View Coordinate), 裁剪坐标 (Clip Coordinate),并最后以 屏幕坐标 [图片上传中...(坐标系变换.png-d41a13-1555986546530-0)]
(Screen Coordinate)的形式结束。下面的这张图展示了整个流程以及各个变换过程做了什么:
透视投影
在现实生活中近大远燃谨小的效果称之为 透视 。如铁轨的两条轨道,饥缓由于透视,在很远的地方看起来会相交皮肢基一样,这就是透视投影想要模仿的效果,它通过 透视投影矩阵 来完成,推导过程可以看 这里 。
正交投影
当使用正射投影时,每一个顶点坐标都会直接映射到裁剪空间中而不经过任何精细的透视除法(它仍然会进行透视除法,只是w分量没有被改变(它保持为1),因此没有起作用)。因为正射投影没有使用透视,远处的物体不会显得更小,所以产生奇怪的视觉效果。由于这个原因,正射投影主要用于二维渲染以及一些建筑或工程的程序,在这些场景中我们更希望顶点不会被透视所干扰
把以上每个步骤创建的变换矩阵:模型矩阵、观察矩阵和投影矩阵组合起来。一个顶点坐标将会根据以下过程被变换到剪裁坐标系:
注意矩阵运算的顺序是相反的(记住我们需要从右往左阅读矩阵的乘法)。最后的顶点应该被赋值到顶点着色器中的gl_Position,OpenGL将会自动进行透视除法和裁剪。
顶点数据
矩阵变换过程
最后注意点
Ⅳ 基于视锥体(平截体)的OpenGL ES性能优化
OpenGLES入门教程1-Tutorial01-GLKit
OpenGLES入门教程2-Tutorial02-shader入门
OpenGLES入门教程3-Tutorial03-三维变换
OpenGLES入门教程4-Tutorial04-GLKit进阶
OpenGLES进阶教程1-Tutorial05-地球月亮
OpenGLES进阶教程2-Tutorial06-光线
OpenGLES进阶教程3-Tutorial07-粒子效果
OpenGLES进阶教程4-Tutorial08-帧缓存
OpenGLES进阶教程5-Tutorial09-碰碰车
这一次的是性能优化。
渲染的优化不是仅仅提高渲染的速度,超过60Hz的渲染速度没有任何意义,用户永远看不到这些信息。同时在考虑用电消耗的情况下,30Hz的刷新率能延长电池的使用时间。
以下的渲染优化策略总衫销是管用的:
通过减少渲染的几何对象,在不影响显示效果的唤塌辩前提下,尽可能减少需要绘制的图元。
在一个场景中,很多物体是处于平截体外部,这些物体是用户永远看不到的对象。
计算眼睛到当前测试点的向量,提取这个向量关于平截体X、Y、Z轴的分量,分别进行判断。
测试球体会测试点更复杂,同样是对比X/Y/Z轴分量,在判断的范围加上半径的距离。
但是,考虑下面的情况
如下图,考虑球体被外切情况,得出相应的放大因子。
为什么FPS会在20FPS和30FPS之间摆动?
绘制 和 显示 并不一样。
通过CADisplayLink(hardware generated),绘制的速率可能是60FPS。
如果绘制的时间超过1/60s,理论上帧率最多为30FPS。
想象一条1s的线段,分隔成60小段,每个小段的起点都可以作为绘制的起点。
如果绘制的时间超过1/60s,那么绘制的终点会延伸到第二个小段。
这样,一条1s的线段,最多有30个绘制的时间段。
你能得到FPS,但是它不代表真正的性能,每帧持续时间是一个更佳选择。FPS不能线性评判性能表现。
最后, 即使你自己通过自定义线程(不采用CADisplayLink),把绘制时和缺间的空缺填补,实际上绘制的速率并不会变快 。
主要讲解的是数学部分的知识,OpenGL ES的部分没有引入新的技术点。
工作原因,以后更新会慢一些。能看到这里,你也是喜欢技术的,谢谢支持。来一波关注和喜欢如何 -> 我会加油更新。
附上 源码
Ⅳ android的如何使用异或方式绘图
1)使用canvas/paint方式的绘图为软件渲染,通过cpu实现;使用opengles/shader方式的绘图为硬件加速渲染,通过gpu实现。
2)surfaceview和glsurfaceview的显示一般结合opengles,悉衫使用纹理(texture),为硬件渲染,通过gpu实现
3)glsurfaceview是surfaceview的子类,在后者基础上封装了egl环境管理,以及render线程
4)opengles绘制函数及shader是平台无关的,需要egl环境对接android/ios等平台
5)android graphic 底层都与BufferQueue、Surfaceflinger等相关,具体可参毕陆数考android开发者文档
个人经验,如有不对之处请帮忙指出
作者:阿占
链接:https://www.hu.com/question/36030004/answer/65581599
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处手首。
Ⅵ iOS 使用openGLES画线缺少函数
你添OpenGL的框架了么??
Ⅶ iOS使用OpenGLES和freetype绘制字体
-------------挖个坑,还在学习中------------
第一步,理解内存、bitmap、OpenGLES、freetype的使用
第二步,
实现流程:
调用freetype的接口,将文字写入内存位图
将这块位置拷贝到一个大图上面(更到一个内存位图)
记住它在大图的起始坐标与大小
再将大图写入到纹理,就可以按四边形(两个三角形)来绘制这个文字了
主要分两步:第一步是生成位图,第二步是将位图写入纹理在渲染出来、
freetype,生成的单个字的小位图,你需要将小位图合并到一个大的位图上面(比如1024的大图,可以容纳很多个文字)
再将这个大的位局型置更新gl纹理对象,后面就是绘制三角形了
char *pBitmapDatas = new char[nWidth*nHeight*4];
这个就桐胡猜是32位的位图数据,argb 位8位
字多大,你可以通过freetype的接口做此获取的嘛
也是你自己设置的
那字位图在大位图上的位置呢?
你自己定啊,按固定大小分好格子,一个个的填充
大小取字体的最大宽度与高度
大图是为了优化速度用的
不做优化的话,直接一个文字一个贴图,也是可以的
效果是一样的
大图是为了做批渲染,优化渲染速度
Ⅷ 【iOS】(一)GPUImage的结构,滤镜链的实现原理
学了OpenGL,OpenGLES后,去阅读了GPUImage的源码,使用了一段时间,接下来,记录一下我对GPUImage使用和源码阅读的一些分析吧。
相关引用
从0打造一个GPUImage(6)-GPUImage的多滤镜处理逻辑
对于GPUImage,可以分为
上面也提了,所谓的GPUImage滤镜链弊祥就是
GPUImageOutput -> filter -> filter -> GPUImageInput
GPUImageOutput 通过target数组(里面都是实现 GPUImageInput 组件),组成了滤镜链的关系,我们需要牢牢的记住这个滤镜链的关系,这样开发的时候,我们就知道如何Debug,如何实现我们需要的效果。那么问题来了,为什么GPUImage可以实现这样的滤镜链呢?
这里租数搏我们先抛开GPUImage,用OpenGL ES去实现一个具有滤镜叠加效果的Demo,这里的Demo我是参考叶孤城的这篇文章, 从0打造一个GPUImage(6)-GPUImage的多滤镜处理逻辑
Demo需要实现的效果,是将一张图片,先后通过叠加 亮度滤毕行镜 , 饱和度滤镜 最后显示在屏幕上。
那么对应的OpenGLES,我们会怎么做呢?首先我们需要以下东西
从以上的步骤,我们可以总结以下结论
对于这个Demo的一个流程图,可以参考 从0打造一个GPUImage(6)-GPUImage的多滤镜处理逻辑 的一幅图,Demo的详细实现请看原文吧。
以上就是GPUImage对于滤镜链的实现原理,只有你懂了OpenGL ES的渲染流程,才能彻底的明白GPUImage的滤镜链的原理。所以时时刻刻记住以下关系
GPUImageOutput -> filter -> filter -> GPUImageInput
当然也可以存在多个Source,多个Input的情况,例如要给一个视频添加水印,用 GPUImageMovie 用于输出视频纹理,用 GPUImageUIElement 输出UI空间的纹理,通过一个filter进行Blend,最后用一个 GPUImageView 进行预览,用 GPUImageMovieWriter 进行输出,滤镜链关系如下
Ⅸ 如何为iOS5创建一个简单GLKit应用程序
内容: How to start an empty GLKit application for iOS 5
本教程是2D游戏引擎教程的序,但对伏孝于任何一个刚步入iOS世界,想用Xcode4开发GLKit相关应用的人,本教程都有抛针引线的作用。其中大部份内容都是摘取自我的另一篇教程“学习iOS5中GLKit关于OpenGL的基本用法”,那篇教程绘制了一个3D立方体,很值得缺族稿一读。
用XCode创建一个新的iOS应用,模版选择“Empty Application”。取个工程名(我将要编写一个游戏引擎,所以我命名为"ExampleEngine"),保持默认选择(如果是编写一个库,那在类前最好有个前缀,我用的是“EE”),保存。
接着我们添加OpenGL与GLKit相关frameworks。点击左上角的工程,然后选中TARGETS下你的target,再选中Build Phases栏,在“Link Binary With Libraries”中加入GLKit, OpenGLES,QuartzCore这三个framework。完成后,你将会在工程中看到你加入的framework,当然你也可以用拖的方式将其拖入Frameworks分组下。
确保你选择的是模拟器(如果你有开发者帐号,你可以用合法的provisioning profile来真机调试,于是你可以选择device),按⌘B 确保可以正确编译。
在AppDelegate头文件里引入GLKit头文件,这样就可以调用GLKit中的方法。
01.// AppDelegate.h
02.#import <UIKit/UIKit.h>
03.#import <GLKit/GLKit.h>
04....
GLKit了类化了UIView与UIViewController,利用它们将方便我们把OpenGL场景集成到我们的应用中。两个类都是用代理(苹果Objective-C库中一种非常通用的设计模式)的计设模式嵌入到我们的应用代码中。我们要用AppDelegate作为GLKit的代理,因此得告诉编译器AppDelegate会实现代理协议。
01.// AppDelegate.h
02....
03.@interface AppDelegate : UIResponder <UIApplicationDelegate,
04. GLKViewDelegate, GLKViewControllerDelegate>
穗纯05....
现在来创建场景。将application:didFinishLaunchingWithOptions:这个方法用下面代码替换:
01.- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
02.{
03. EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
04. [EAGLContext setCurrentContext:context];
05.
06. GLKView *view = [[GLKView alloc] initWithFrame:[[UIScreen mainScreen] bounds] context:context];
07. view.delegate = self;
08.
09. GLKViewController *controller = [[GLKViewController alloc] init];
10. controller.delegate = self;
11. controller.view = view;
12.
13. self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
14. self.window.rootViewController = controller;
15. [self.window makeKeyAndVisible];
16.
17. return YES;
18.}
■第3,4行创建OpenGL绘制时需要的上下文。
■第6,7行设置绘制场景的view。第6行,由OpenGL上下文创建屏幕大小的view。第7行指明view的代理为AppDelegate。这样绘制每一帧的时候就会调用glkview:drawInRect:这个方法。
■第9-11行,创建GLKViewController,并指明其代理类与view。代理方法中我们主要关心 glkViewControllerUpdate:
■第13-15行,将我们的controller与"window"关联,以便显示。
■第17行通知OS我们的应用已启动完成。
现在代理方没还没实现所以有警告提示,但是也可以运行。运行后,你会看到纯色的背景,看一看吧!
现在我们把这些警告去掉交改背景为灰色。在theapplication:didFinishLaunchingWithOptions:方法下面实现如下代理方法:
01.- (void)glkViewControllerUpdate:(GLKViewController *)controller {
02.// NSLog(@"in glkViewControllerUpdate");
03.}
04.
05.- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
06.// NSLog(@"in glkView:drawInRect:");
07. glClearColor(0.5, 0.5, 0.5, 0.5);
08. glClear(GL_COLOR_BUFFER_BIT);
09.}
现在再运行,你会看到灰色背景,由gl开头的API实现的。在OpenGL与GLKit中,颜色由四个分量组成,分别是红,绿,蓝与alpha(透明度),每一个分量取值范围是[0,1]。
如果你打开上面代码中的NSLog注释,你会在控制台看到如下打印。
这儿有两个方法,因为GLKit基于state与presentation的(类似于MVC的设计模式或HTML/CSS分开发设计)。State(动画,物理模拟,游戏逻辑)应在glkViewControllerUpdate:这回调中,而glkView:drawInRect应用来绘制场景的。
申明:本系列教程原稿来自网络,翻译目的仅供学习与参看,请匆用于商业目的,如果产生商业等纠纷均与翻译人、该译稿发表人无关。转载务必保留此申明。