我一直在寻找适用于iOS的新OpenGL框架,恰当地命名为GLKit,并且一直在将一些现有的OpenGL 1.0代码移植到OpenGL ES 2.0中,只是为了让我的脚趾浸入水中并掌握一切.
在阅读了API以及Apple和OpenGL文档提供的其他最佳实践的全部内容之后,我已经根深蒂固了我应该使用顶点缓冲对象并使用"元素"或更确切地说是顶点索引.似乎有很多关于通过在必要时使用填充来优化内存存储的提及,但这可能是另一天的对话;)
我刚才读到了关于使用NSMutableData而不是经典malloc/free的好处,并希望在编写我的VBO时尝试采用这种方法.到目前为止,我已经设法将一个看起来像我正在走向正确轨道的片段拼凑在一起,但我不完全确定VBO应该包含多少数据.这是我到目前为止所得到的:
//import headers
#import <GLKit/GLKit.h>
#pragma mark -
#pragma mark InterleavingVertexData
//vertex buffer object struct
struct InterleavingVertexData
{
//vertices
GLKVector3 vertices;
//normals
GLKVector3 normal;
//color
GLKVector4 color;
//texture coordinates
GLKVector2 texture;
};
typedef struct InterleavingVertexData InterleavingVertexData;
#pragma mark -
#pragma mark VertexIndices
//vertex indices struct
struct VertexIndices
{
//vertex indices
GLuint a;
GLuint b;
GLuint c;
};
typedef struct VertexIndices VertexIndices;
//create and return a vertex index with specified indices
static inline VertexIndices …Run Code Online (Sandbox Code Playgroud) 在iOS 5上开发新功能,特别是iOS 5上新的OpenGL相关功能,所以如果我的任何问题都是如此基本,我会道歉.
我正在处理的应用程序旨在接收相机帧并通过OpenGL ES在屏幕上显示它们(图形人员将接管这个并添加我知道的实际OpenGL绘图).该应用程序是开发XCode4,目标是运行iOS 5的iPhone4.目前,我使用ARC和GLKit功能,除了在将图像加载为纹理时的内存泄漏,所有工作都正常.该应用程序很快就会收到"内存警告".
具体来说,我想问一下如何释放分配的纹理
@property(retain) GLKTextureInfo *texture;
-(void)setTextureCGImage:(CGImageRef)image
{
NSError *error;
self.texture = [GLKTextureLoader textureWithCGImage:image options:nil error:&error];
if (error)
{
NSLog(@"Error loading texture from image: %@",error);
}
}
Run Code Online (Sandbox Code Playgroud)
这image是一个由相机框架构建的石英图像(来自苹果的示例代码).我知道问题不在代码的那一部分,因为如果我禁用分配,应用程序不会收到警告.
我正在使用GLKit制作一个使用OpenGL ES 2.0的iPhone应用程序.我正在使用GLKTextureLoader同步加载纹理.
问题是对于某种纹理,它无法在第一次加载它.它给出了这个错误:
The operation couldn’t be completed. (GLKTextureLoaderErrorDomain error 8.)
对于此错误代码,Apple文档说明如下:
GLKTextureLoaderErrorUncompressedTextureUpload
An uncompressed texture could not be uploaded.
Available in iOS 5.0 and later.
Declared in GLKTextureLoader.h.
Run Code Online (Sandbox Code Playgroud)
(不是很多).
当opengl上下文处于某种繁忙状态或类似的情况时,我可以尝试加载纹理吗?
笔记:
欢迎任何想法,谢谢
编辑:
更多信息:
opengl上下文在我的所有屏幕之间共享.我这样做是为了让我的着色器和纹理在屏幕之间加载.
当我进入第二个屏幕时,会发生上述问题.在第一个屏幕中,我绘制没有问题的纹理东西(尽管其他纹理).
当我在游戏世界中加载我的内容(游戏实体)时,会发生上述问题.每个实体都尝试加载纹理.我有一个简单的缓存系统,只加载一次纹理,然后为所有其他实体返回相同的id.我在一种方法中同步加载实体.第一个实体无法加载纹理然后是第二个并且成功,然后第三个实体获得缓存的ID.
我正在调用加载实体方法,viewDidAppear并且我尝试在加载任何实体之前添加睡眠2秒但没有任何改变.
编辑:
纹理加载代码:
- (GLKTextureInfo *)loadTextureAtPath:(NSString*)path ofType:(NSString*)type withKey:(NSString *)key
{
GLKTextureInfo* tex;
tex = [self textureWithKey:key];
if (tex)
return tex;
NSDictionary * options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:NO],
GLKTextureLoaderOriginBottomLeft,
nil];
NSError * error;
NSString *bundlepath …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用opengl编写游戏,但是我在使用新的glkit类和iOS的默认模板时遇到了很多麻烦.
- (void)viewDidLoad
{
[super viewDidLoad];
self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
if (!self.context) {
NSLog(@"Failed to create ES context");
}
if(!renderer)
renderer = [RenderManager sharedManager];
tiles = [[TileSet alloc]init];
GLKView *view = (GLKView *)self.view;
view.context = self.context;
view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
[self setupGL];
}
- (void)setupGL
{
int width = [[self view] bounds].size.width;
int height = [[self view] bounds].size.height;
[EAGLContext setCurrentContext:self.context];
self.effect = [[GLKBaseEffect alloc] init];
self.effect.light0.enabled = GL_TRUE;
self.effect.light0.diffuseColor = GLKVector4Make(0.4f, 0.4f, 0.4f, 1.0f);
//Configure Buffers
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); …Run Code Online (Sandbox Code Playgroud) 我有一个GLKViewController来处理一些OpenGL绘图.我已经实现了glkView:drawInRect和update方法,并将preferredFramesPerSecond属性设置为30(默认值).
问题是当用户与应用程序的其他部分交互时,委托方法停止触发.我见过这种情况的两种情况是当用户滚动UITableView或与MKMapView交互时.
有没有办法确保这些代表总是触发,无论应用程序的其余部分在做什么.我希望这些停止的唯一时间是应用程序进入后台(这是自动进行).
所以我从网络回调(voip app)获得3个独立阵列中的原始YUV数据.根据我的理解,你不能CVPixelBufferCreateWithPlanarBytes根据这里创建IOSurface支持的像素缓冲区
重要提示:您不能将CVPixelBufferCreateWithBytes()或CVPixelBufferCreateWithPlanarBytes()与kCVPixelBufferIOSurfacePropertiesKey一起使用.调用CVPixelBufferCreateWithBytes()或CVPixelBufferCreateWithPlanarBytes()将导致CVPixelBuffers不是IOSurface支持的
因此,您必须创建它CVPixelBufferCreate,但是如何将数据从回调传输回CVPixelBufferRef您创建的?
- (void)videoCallBack(uint8_t *yPlane, uint8_t *uPlane, uint8_t *vPlane, size_t width, size_t height, size_t stride yStride,
size_t uStride, size_t vStride)
NSDictionary *pixelAttributes = @{(id)kCVPixelBufferIOSurfacePropertiesKey : @{}};
CVPixelBufferRef pixelBuffer = NULL;
CVReturn result = CVPixelBufferCreate(kCFAllocatorDefault,
width,
height,
kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange,
(__bridge CFDictionaryRef)(pixelAttributes),
&pixelBuffer);
Run Code Online (Sandbox Code Playgroud)
我不确定之后该做什么?最终我想把它变成一个CIImage,然后我可以使用我的GLKView来渲染视频.人们如何在创建数据时将数据"放入"缓冲区?
我正在尝试在UIViewController中使用GLKView,我的代码看起来像这样
CustomViewController.h
#import <UIKit/UIKit.h>
#import <GLKit/GLKit.h>
@interface CustomViewController : UIViewController
{
NSString * name;
}
@property NSString * name;
Run Code Online (Sandbox Code Playgroud)
CustomViewController.m
#import "CustomViewController.h"
@interface CustomViewController ()
@end
@implementation CustomViewController
@synthesize name;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
EAGLContext * context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
CGRect mainScreen = [[UIScreen mainScreen] bounds];
GLKView * …Run Code Online (Sandbox Code Playgroud) 我使用GLKit启动了Xcode模板,但我的目的是有一个窗口显示视图的OpenGL部分和UIKit控件.
GLKViewController附带一个GLKView.我去了IB并删除了GLKView并添加了一个UIView,将新的GLKView放在我想要的大小的顶部.然后我修复了对GLKView(self.view)的引用,并将较小的GLKView委托设置为视图控制器.
我有
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[GLKViewController loadView] loaded the "2-view-9XZ-07-hga" nib but didn't get a GLKView.'
Run Code Online (Sandbox Code Playgroud)
然后我查看了docs并发现GLKViewController需要GLKView作为其视图.没有惊喜.是的,我是新来的.
在GLKView小于全屏的情况下使用GLKit的好方法是什么?或者混合UIKit和GLKit还没有完成?
(更新:很多人都在发现这个问题; Duncan的答案,使用视图控制器遏制,效果很好.)
我的应用程序用于GLKit渲染3D场景OpenGL ES.
一切都很好,除了一件事.当我在iPad中启动我的应用程序并显示后台应用程序栏(单击双击"主页"按钮)然后更改设备的方向时,场景会被错误更新(最后渲染的图像只是拉伸以填充新的矩形).
我找到了原因.当出现后台应用程序栏时,GLKViewController's paused将YES自动设置(应用程序委托接收-applicationWillResignActive:),并且在此栏关闭之前不会进行渲染.
我在Apple指南(iOS的OpenGL ES编程指南/实现多任务感知的OpenGL ES应用程序)中找到了,在收到-applicationWillResignActive:应用程序后应停止GL渲染或终止.所以似乎一切都好,除了轮换后的糟糕渲染:)
我检查了一些OpenGL游戏.当显示此栏时,它们也会"暂停",但不知何故正确更新设备旋转时暂停的场景.他们是如何做到这一点的?
我使用此链接中的代码来映射人脸的纹理.此代码使用GLKIT渲染图像.代码在模拟器中工作正常,但如果我在设备中运行它无法正常工作,则代码相同.以下是图像的屏幕截图,它在设备中工作,而不是在我的ipad中.
我用来加载纹理的代码:
- (void)loadTexture:(UIImage *)textureImage
{
glGenTextures(1, &_texture);
glBindTexture(GL_TEXTURE_2D, _texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
CGImageRef cgImage = textureImage.CGImage;
float imageWidth = CGImageGetWidth(cgImage);
float imageHeight = CGImageGetHeight(cgImage);
CFDataRef data = CGDataProviderCopyData(CGImageGetDataProvider(cgImage));
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imageWidth, imageHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, CFDataGetBytePtr(data));
}
Run Code Online (Sandbox Code Playgroud)
模拟器的图像:

设备中的相同代码提供以下输出:

有什么东西我不见了?