OpenGL on iOS 上的纹理和着色器
如何在iOS上开始使用OpenGL。
引言
本文演示了在iOS上使用OpenGL纹理以及常见的单例、MVC、出口和测试工作模式是多么容易。因此,OpenGL 是一项有用的技术,在其他平台上也可以使用。缺点是,2004年的非常旧的2.0版本是标准的,“新的”是OpenGL 3.0(2008年)。
截图:带有图片选择和红色滤镜效果滑块。
背景
我想更好地理解OpenGL,因为它具有良好的图形性能并兼容于其他项目。
使用代码
包含的示例项目源自Xcode的普通模板,遵循MVC模型,即模型-视图-控制器,它确实有助于将代码分离成有用的部分。因此,ViewController类充分利用了它的名称,它控制着视图的工作方式。重要的是Displaylink,因为它是由显示器或更好的GPU计时器回调以进行新的像素输出。
- (void)startDisplayLinkIfNeeded { if (!_displayLink) { self.displayLink = [CADisplayLink displayLinkWithTarget:_viewOpenGL selector:@selector(display)]; [_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; } }
GUI在Main.storyboard中配置,其中存储了控件。它们通过Outlet“连接”到ViewController。我在mobiforge找到一个不错的教程。但是现在先不说这些了。
开始使用OpenGL
为了某种程度上利用OpenGL,我设计了一个OpenGLContext类,它在Objective-C中采用了典型的单例设计模式。
+ (instancetype)sharedInstance { static OpenGLContext *theInstance = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ theInstance = [[OpenGLContext alloc] init]; }); return theInstance; }
此对象持有EAGLContext的属性,以便在iOS上使用OpenGL。
@property(strong, nonatomic) EAGLContext *context;
这是使其工作的算法。如果我们有上下文,我们就完成了;否则,如果可以创建V3上下文,那就很好;否则,我们创建一个V2上下文。重要的是最后一行,将上下文设置为当前上下文。这是一个直接与显示驱动程序交互的全局函数。
- (int) createContext { if( self.context != nil ) return 1; self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3]; if (!self.context) { NSLog(@"[Warn] Hardware doenst support OpenGL ES 3.0 context"); self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; if (!self.context) { NSLog(@"[Error] failed to create an OpenGL ES 2.0 context"); return -1; } } [EAGLContext setCurrentContext:self.context]; return 0; }
OpenGL中的纹理
纹理是OpenGL中的位图,因此我们需要一些纹理来查看一些彩色像素。代码在其他平台上看起来应该类似。
//set alignment
glPixelStorei(GL_PACK_ALIGNMENT, 1);
//activate textures
glEnable(GL_TEXTURE_2D);
//get an free and valid ID
glGenTextures(1, &texture);
//make active
glActiveTexture(GL_TEXTURE0 + texture);
// Bind the texture
glBindTexture(GL_TEXTURE_2D, texture);
// Setup texture parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);//disable mipmapping
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//set the bits of the texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, colorData);
深入着色器
着色器是OpenGL中用于操纵图形输出的小型子程序。有两个独立的程序,一个称为顶点着色器,它计算坐标;另一个是片段着色器,它生成像素的颜色。要将它们加载到OpenGL中,需要对其进行编译、链接和加载。这在OpenGLProgram类中完成。
我还想指出着色器的复杂领域,它们具有不同类型的变量,这些变量在工作中起着重要作用。因此,我写了一些解释。
#version 100 //a compile-time constant, or a function parameter that is read-only uniform mat4 modelViewProjectionMatrix; //linkage between a vertex shader and OpenGL ES for per-vertex data attribute vec4 position; attribute vec2 texcoord; //linkage between a vertex shader and a fragment shader for interpolated data varying vec2 v_texcoord; void main() { gl_Position = position; v_texcoord = texcoord.xy; }
我的代码的核心是滑块的这个处理程序。滑块的值可以更改,并进入操纵纹理输出的OpenGL程序。
- (IBAction)onChange:(id)sender { float value = [_slider value]; NSLog(@"Slider = %f", value); NSString *sFloat = [NSString stringWithFormat:@"%.2f",value]; NSDictionary *dic = @{@"RED_FACTOR": sFloat}; OpenGLProgram *shader = [[OpenGLProgram alloc] init]; [shader loadShaders:@"Shader3" FragmentModify:dic]; [[_openGLContext shaders] setObject:shader atIndexedSubscript:2]; self.shader = [_openGLContext useProgramAtIndex:2]; [_shader linkValue:"pixel" Texture:_textureOpenGL]; [self.viewOpenGL display]; }
在Xcode中测试
Xcode对编写软件测试有一些很好的支持,我喜欢使用它。看看它 - 它真的值得。大多数情况下,使用measureBlock API进行性能测试是小菜一碟。
关注点
通过深入研究OpenGL,我学习了很多复杂的东西,这对于具有良好性能的大型图形输出非常有帮助。
Apple为嵌入式系统提供了良好的OpenGL文档,他们称之为OpenGL ES。
接下来是使用Apple的Metal 新技术,听起来真的很棒。
像往常一样,我提供一个指向著名的Ray Wenderlich的链接,在那里可以找到许多有趣且解释良好的内容。
历史
初始版本。