- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
基本上,在我的 iOS 应用程序中,我有一个模态屏幕,我在其中显示了一些 OpenGL ES 图形。在应用程序崩溃之前,我能够进入和退出此模式屏幕 6 次。我假设这是一个内存问题,但我不知道是什么和/或在哪里。
非常感谢您就此事提供的任何帮助。
在我的 OGLViewController 中:
#define OPENGL_ERROR_CHECK {GLuint error = glGetError(); ((error == GL_NO_ERROR) ? : NSLog(@"GL Error: %d", (error)));}
@interface OGLItemViewController : GLKViewController
@property (nonatomic) GLuint program;
// item ogl arrays + buffers
@property (nonatomic) NSInteger numOGLBuffers;
@property (nonatomic) GLuint* vertexArrays;
@property (nonatomic) GLuint* vertexBuffers;
// index buffer for ogl item vertices
@property (nonatomic) GLuint* indexBuffers;
@property (strong, nonatomic) EAGLContext *context;
@property (strong, nonatomic) GLKBaseEffect *effect;
@end
@implementation
- (void)viewDidLoad
{
[super viewDidLoad];
self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
OPENGL_ERROR_CHECK
glFinish(); // put this in here to make sure all previous calls have been finished
OPENGL_ERROR_CHECK
if (!self.context)
{
NSLog(@"Failed to create ES context");
}
GLKView *view = (GLKView *) self.view;
view.context = self.context;
view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
view.opaque = NO;
self.numOGLBuffers = 0;
self.vertexArrays = nil;
self.vertexBuffers = nil;
self.indexBuffers = nil;
}
- (void)setupGL
{
OPENGL_ERROR_CHECK
[EAGLContext setCurrentContext:self.context];
OPENGL_ERROR_CHECK
[self loadShaders];
OPENGL_ERROR_CHECK
self.effect = [[GLKBaseEffect alloc] init];
OPENGL_ERROR_CHECK
self.effect.light0.enabled = GL_TRUE;
OPENGL_ERROR_CHECK
self.effect.colorMaterialEnabled = GL_TRUE;
OPENGL_ERROR_CHECK
self.effect.lightModelTwoSided = GL_FALSE;
OPENGL_ERROR_CHECK
self.effect.light0.diffuseColor = GLKVector4Make(0.69f, 0.69f, 0.69f, 0.5f);
OPENGL_ERROR_CHECK
glEnable(GL_DEPTH_TEST);
OPENGL_ERROR_CHECK
Item *item = [GlobalStore sharedInstance].item
NSMutableArray *shells = item.geometry;
if (shells.count > 0)
{
_vertexArrays = malloc(shells.count * sizeof(GLuint));
_vertexBuffers = malloc(shells.count * sizeof(GLuint));
_indexBuffers = malloc(shells.count * sizeof(GLuint));
self.numOGLBuffers = shells.count;
for (int i = 0; i < shells.count; i++)
{
Geometry *geom = [shells objectAtIndex:i];
if (geom.vertexCount > 0)
{
GLuint vao = 0;
OPENGL_ERROR_CHECK
glGenVertexArraysOES(1, &vao);
OPENGL_ERROR_CHECK
glBindVertexArrayOES(vao);
OPENGL_ERROR_CHECK
_vertexArrays[i] = vao;
if (!geom.vertices)
{
[self displayError:-998]; // generic error codes that i've just canned in to see if any problems with these pointers
}
if (!geom.indices)
{
[self displayError:-997];
}
// create vertice buffer
GLuint vbo = 0;
glGenBuffers(1, &vbo);
OPENGL_ERROR_CHECK
glBindBuffer(GL_ARRAY_BUFFER, vbo);
OPENGL_ERROR_CHECK
glBufferData(GL_ARRAY_BUFFER, geom.vertexCount * sizeof(OGLVertices), geom.vertices, GL_STATIC_DRAW);
OPENGL_ERROR_CHECK
_vertexBuffers[i] = vbo;
// create index by buffer
GLuint ibo = 0;
glGenBuffers(1, &ibo);
OPENGL_ERROR_CHECK
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
OPENGL_ERROR_CHECK
glBufferData(GL_ELEMENT_ARRAY_BUFFER, geom.indexCount * sizeof(GLuint), geom.indices, GL_STATIC_DRAW);
OPENGL_ERROR_CHECK
_indexBuffers[i] = ibo;
// enable position, normal and colour attributes
glEnableVertexAttribArray(GLKVertexAttribPosition);
OPENGL_ERROR_CHECK
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(OGLVertices), (const GLvoid *) offsetof(OGLVertices, Position));
OPENGL_ERROR_CHECK
glEnableVertexAttribArray(GLKVertexAttribNormal);
OPENGL_ERROR_CHECK
glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, sizeof(OGLVertices), (const GLvoid *) offsetof(OGLVertices, Normal));
OPENGL_ERROR_CHECK
glEnableVertexAttribArray(GLKVertexAttribColor);
OPENGL_ERROR_CHECK
glVertexAttribPointer(GLKVertexAttribColor, 4, GL_FLOAT, GL_FALSE, sizeof(OGLVertices), (const GLvoid *) offsetof(OGLVertices, Colour));
OPENGL_ERROR_CHECK
}
}
glBindVertexArrayOES(0);
OPENGL_ERROR_CHECK
}
}
- (void)tearDownGL
{
[EAGLContext setCurrentContext:self.context];
self.effect = nil;
[self deleteOGLData];
}
- (void)dealloc
{
[self tearDownGL];
if ([EAGLContext currentContext] == self.context)
{
[EAGLContext setCurrentContext:nil];
}
}
- (void) viewDidDisappear:(BOOL)animated
{
[self tearDownGL];
}
- (void)deleteOGLData
{
// delete ogl buffers and arrays
if (self.numOGLBuffers > 0)
{
if (_vertexBuffers)
{
OPENGL_ERROR_CHECK
glDeleteBuffers(self.numOGLBuffers, _vertexBuffers);
OPENGL_ERROR_CHECK
free(_vertexBuffers);
_vertexBuffers = nil;
}
if (_vertexArrays)
{
glDeleteVertexArraysOES(self.numOGLBuffers, _vertexArrays);
OPENGL_ERROR_CHECK
free(_vertexArrays);
_vertexArrays = nil;
}
if (_indexBuffers)
{
glDeleteBuffers(self.numOGLBuffers, _indexBuffers);
OPENGL_ERROR_CHECK
free(_indexBuffers);
_indexBuffers = nil;
}
}
self.numOGLBuffers = 0;
glDeleteProgram(self.program);
OPENGL_ERROR_CHECK
self.program = 0;
glFinish(); // again, just put this in here to check everything has finished
OPENGL_ERROR_CHECK
}
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
OPENGL_ERROR_CHECK
glClearColor(1.0, 1.0, 1.0, 0.0);
OPENGL_ERROR_CHECK
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
OPENGL_ERROR_CHECK
// Render the object with GLKit
[self.effect prepareToDraw];
OPENGL_ERROR_CHECK
NSMutableArray *shells = [GlobalStore sharedInstance].item.geometry;
if (shells && _vertexArrays && _vertexBuffers)
{
for (int i = 0; i < shells.count; i++)
{
Geometry *geom = [shells objectAtIndex:i];
if (geom.vertexCount > 0)
{
GLuint vao = self.vertexArrays[i];
glBindVertexArrayOES(vao);
OPENGL_ERROR_CHECK
if(geom.indexCount == 0)
[self displayError:-996];
glDrawElements(GL_TRIANGLES, geom.indexCount, GL_UNSIGNED_INT, 0);
OPENGL_ERROR_CHECK
self.initialised = YES;
}
}
}
}
- (BOOL)loadShaders
{
GLuint vertShader, fragShader;
NSString *vertShaderPathname, *fragShaderPathname;
// Create shader program.
self.program = glCreateProgram();
OPENGL_ERROR_CHECK
// Create and compile vertex shader.
vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"];
if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname])
{
NSLog(@"Failed to compile vertex shader");
return NO;
}
// Create and compile fragment shader.
fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"];
if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname])
{
NSLog(@"Failed to compile fragment shader");
return NO;
}
// Attach vertex shader to program.
glAttachShader(_program, vertShader);
OPENGL_ERROR_CHECK
// Attach fragment shader to program.
glAttachShader(_program, fragShader);
OPENGL_ERROR_CHECK
// Bind attribute locations.
// This needs to be done prior to linking.
glBindAttribLocation(_program, GLKVertexAttribPosition, "position");
OPENGL_ERROR_CHECK
glBindAttribLocation(_program, GLKVertexAttribNormal, "normal");
OPENGL_ERROR_CHECK
// Link program.
if (![self linkProgram:_program])
{
NSLog(@"Failed to link program: %d", _program);
if (vertShader)
{
glDeleteShader(vertShader);
OPENGL_ERROR_CHECK
vertShader = 0;
}
if (fragShader)
{
glDeleteShader(fragShader);
OPENGL_ERROR_CHECK
fragShader = 0;
}
if (_program)
{
glDeleteProgram(_program);
OPENGL_ERROR_CHECK
_program = 0;
}
return NO;
}
// Get uniform locations.
uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix");
uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix");
// Release vertex and fragment shaders.
if (vertShader)
{
glDetachShader(_program, vertShader);
OPENGL_ERROR_CHECK
glDeleteShader(vertShader);
OPENGL_ERROR_CHECK
}
if (fragShader)
{
glDetachShader(_program, fragShader);
OPENGL_ERROR_CHECK
glDeleteShader(fragShader);
OPENGL_ERROR_CHECK
}
return YES;
}
- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file
{
GLint status;
const GLchar *source;
source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String];
if (!source)
{
NSLog(@"Failed to load vertex shader");
return NO;
}
*shader = glCreateShader(type);
OPENGL_ERROR_CHECK
glShaderSource(*shader, 1, &source, NULL);
OPENGL_ERROR_CHECK
glCompileShader(*shader);
OPENGL_ERROR_CHECK
glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
OPENGL_ERROR_CHECK
if (status == 0)
{
glDeleteShader(*shader);
OPENGL_ERROR_CHECK
return NO;
}
return YES;
}
- (BOOL)linkProgram:(GLuint)prog
{
GLint status;
glLinkProgram(prog);
OPENGL_ERROR_CHECK
glGetProgramiv(prog, GL_LINK_STATUS, &status);
OPENGL_ERROR_CHECK
if (status == 0)
{
return NO;
}
return YES;
}
- (BOOL)validateProgram:(GLuint)prog
{
GLint logLength, status;
glValidateProgram(prog);
OPENGL_ERROR_CHECK
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength);
OPENGL_ERROR_CHECK
if (logLength > 0)
{
GLchar *log = (GLchar *)malloc(logLength);
glGetProgramInfoLog(prog, logLength, &logLength, log);
OPENGL_ERROR_CHECK
NSLog(@"Program validate log:\n%s", log);
free(log);
}
glGetProgramiv(prog, GL_VALIDATE_STATUS, &status);
OPENGL_ERROR_CHECK
if (status == 0)
{
return NO;
}
return YES;
}
-(void)displayError: (GLuint) err
{
NSString *msg = [[NSString alloc] initWithFormat:@"OpenGL Error: %d", err];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle: @"Error"
message: msg
delegate:self
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
}
@end
现在 - 我不知道这样做是否正确,但在 viewdiddisappear 方法中,我确保删除所有 ogl 数据。我想确保当我退出 View 时,ogl 数据已从内存中删除。
因此,如果我进入模态视图,退出并重复 5 次以上,我将遇到黑屏崩溃,并会中断,并显示以下屏幕:
我已确保一切都在适当的情况下在单个线程中完成。我试图确保删除所有对象和缓冲区。
所以我想知道我到底做错了什么导致它突然崩溃......分析器中似乎没有任何指示。我似乎没有任何内存泄漏或任何会导致内存耗尽的内容。
(我知道我会在不需要的时候渲染每一帧 - 我会在稍后解决这个问题。)
我拥有的全局存储包含我使用的一些对象的实例。这些应该始终有效(我已经检查过了)。
最佳答案
我需要做的是删除 GLKView 可绘制对象。
在 ViewDidDisappear 方法中(可能不是合适的地方,但它有效)添加以下内容:
GLKView *view = (GLKView*) self.view;
[view deleteDrawable];
关于iOS OpenGL ES 多次加载同一对象时崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18723082/
我想要显示正在加载的 .gif,直到所有内容都已加载,包括嵌入的 iframe。但是,目前加载 gif 会在除 iframe 之外的所有内容都已加载后消失。我怎样才能让它等到 iframe 也加载完毕
首先,这是我第一次接触 Angular。 我想要实现的是,我有一个通知列表,我必须以某种方式限制 limitTo,因此元素被限制为三个,在我单击按钮后,其余的应该加载。 我不明白该怎么做: 设置“ V
我正在尝试在我的设备上运行这个非常简单的应用程序(使用 map API V2),并且出于某种原因尝试使用 MapView 时: 使用 java 文件: public class MainMap e
我正在使用 Python 2.6、Excel 2007 Professional 和最新版本的 PyXLL。在 PyXLL 中加载具有 import scipy 抛出异常,模块未加载。有没有人能够在
我想做这个: 创建并打包原始游戏。然后我想根据原始游戏中的蓝图创建具有新网格/声音/动画和蓝图的其他 PAK 文件。原始游戏不应该知道有关其他网格/动画/等的任何信息。因此,我需要在原始游戏中使用 A
**摘要:**在java项目中经常会使用到配置文件,这里就介绍几种加载配置文件的方法。 本文分享自华为云社区《【Java】读取/加载 properties配置文件的几种方法》,作者:Copy工程师。
在 Groovy 脚本中是否可以执行条件导入语句? if (test){ import this.package.class } else { import that.package.
我正在使用 NVidia 视觉分析器(来自 CUDA 5.0 beta 版本的基于 eclipse 的版本)和 Fermi 板,我不了解其中两个性能指标: 全局加载/存储效率表示实际内存事务数与请求事
有没有办法在通过 routeProvider 加载特定 View 时清除 Angular JS 存储的历史记录? ? 我正在使用 Angular 创建一个公共(public)安装,并且历史会积累很多,
使用 Xcode 4.2,在我的应用程序中, View 加载由 segue 事件触发。 在 View Controller 中首先调用什么方法? -(void) viewWillAppear:(BOO
我在某些Django模型中使用JSONField,并希望将此数据从Oracle迁移到Postgres。 到目前为止,当使用Django的dumpdata和loaddata命令时,我仍然没有运气来保持J
创建 Nib 时,我需要创建两种类型:WindowNib 或 ViewNib。我看到的区别是,窗口 Nib 有一个窗口和一个 View 。 如何将 View Nib 加载到另一个窗口中?我是否必须创建
我想将多个env.variables转换为静态结构。 我可以手动进行: Env { is_development: env::var("IS_DEVELOPMENT")
正如我从一个测试用例中看到的:https://godbolt.org/z/K477q1 生成的程序集加载/存储原子松弛与普通变量相同:ldr 和 str 那么,宽松的原子变量和普通变量之间有什么区别吗
我有一个重定向到外部网站的按钮/链接,但是外部网站需要一些时间来加载。所以我想添加一个加载屏幕,以便外部页面在显示之前完全加载。我无法控制外部网站,并且外部网站具有同源策略,因此我无法在 iFrame
我正在尝试为我的应用程序开发一个Dockerfile,该文件在初始化后加载大量环境变量。不知何故,当我稍后执行以下命令时,这些变量是不可用的: docker exec -it container_na
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我刚刚遇到一个问题,我有一个带有一些不同选项的选择标签。 现在我想检查用户选择了哪些选项。 然后我想将一个新的 html 文件加载到该网站(取决于用户选中的选项)宽度 javascript,我该怎么做
我知道两种保存/加载应用程序设置的方法: 使用PersistentStore 使用文件系统(存储,因为 SDCard 是可选的) 我想知道您使用应用程序设置的做法是什么? 使用 PersistentS
我开始使用 Vulkan 时偶然发现了我的第一个问题。尝试创建调试报告回调时(验证层和调试扩展在我的英特尔 hd vulkan 驱动程序上可用,至少它是这么说的),它没有告诉我 vkCreateDeb
我是一名优秀的程序员,十分优秀!