草庐IT

iphone - OpenGl ES 2.0 和 GLKit : From GLKBaseEffect shaders to OpenGl

coder 2024-01-26 原文

我正在使用 OpenGL ES 2.0 和 GLKit 编写 2D 游戏。我的架构基于 Ian Terrel 的游戏教程。

我最近发现 GLKBaseEffect(提供简单的着色器管理)泄漏,有时会使我的应用程序崩溃。我现在正在使用我自己的着色器文件(基于 Ray Wenderlich 教程),但此时,我刚刚成功显示了 openGl 背景色。我的形状颜色和纹理不再显示。

重要:我错误地设置了当前上下文,现在 openGL 显示无效 Drawable。

这是我的 shape.m 代码的一部分:

@implementation P3Shape

const GLushort indices[] = {
    0,1,2,3
};

typedef struct {
    float Position[2];
    float Color[4];
    float TexCoord[2];
} Vertex;

//testing
const Vertex Vertices[] = {
    // Front
    {{10, -15}, {1, 0, 0, 1}, {1, 0}},
    {{10, 15}, {0, 1, 0, 1}, {1, 0}},
    {{-10, 10}, {0, 0, 1, 1}, {0, 0}},
    {{-10, -1}, {0, 0, 0, 1}, {0, 1}},
};

- (id)initWithLayer:(CAEAGLLayer *)layer {
    self = [super init];
    if (self) {
        [...]
        _currentContext = [P3SessionState currentContext];
        _eaglLayer = layer;
        _eaglLayer.opaque = YES;
        [self setupRenderBuffer];        
        [self setupFrameBuffer]; 
        [self addToProgram];
        [self createBuffers];
    }
    return self;
}


- (int)numVertices {
    return 0;
}

- (void) addToProgram {
    // setted before in the gamemanager
    GLuint programHandle = [P3SessionState programHandle];

    _positionSlot = glGetAttribLocation(programHandle, "Position");
    _colorSlot = glGetAttribLocation(programHandle, "SourceColor");

    _projectionUniform = glGetUniformLocation(programHandle, "Projection");
    _modelViewUniform = glGetUniformLocation(programHandle, "Modelview");

    _texCoordSlot = glGetAttribLocation(programHandle, "TexCoordIn");
    _textureUniform = glGetUniformLocation(programHandle, "Texture");
}

- (void)setupRenderBuffer {
    glGenRenderbuffers(1, &_colorRenderBuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderBuffer);        
    [_currentContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:_eaglLayer];    
}

- (void)setupFrameBuffer {    
    GLuint framebuffer;
    glGenFramebuffers(1, &framebuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);   
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _colorRenderBuffer);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthRenderBuffer);
}

- (void)createBuffers {
    // Static index data
    glGenBuffers(1, &indexBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    glGenBuffers(1, &vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
}

// initialize the vertex data

- (GLKVector2 *)vertices {
    if (vertexData == nil) {
        vertexData = [NSMutableData dataWithLength:sizeof(GLKVector2)*self.numVertices];
    }
    return [vertexData mutableBytes];
}

// set a textureImage, allocate a glname and enable the GL_TEXTURE_2D and all
- (void)setTextureImage:(UIImage *)image {
    CGImageRef spriteImage = image.CGImage;
    if (!spriteImage) {
        NSLog(@"Failed to load image %@", image);
        exit(1);
    }

    size_t width = CGImageGetWidth(spriteImage);
    size_t height = CGImageGetHeight(spriteImage);

    GLubyte * spriteData = (GLubyte *) calloc(width*height*4, sizeof(GLubyte));

    CGContextRef spriteContext = CGBitmapContextCreate(spriteData, width, height, 8, width*4, CGImageGetColorSpace(spriteImage), kCGImageAlphaPremultipliedLast);    

    CGContextDrawImage(spriteContext, CGRectMake(0, 0, width, height), spriteImage);

    CGContextRelease(spriteContext);

    GLuint texName;
    glGenTextures(1, &texName);
    glBindTexture(GL_TEXTURE_2D, texName);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, spriteData);

    free(spriteData);        
    _imageTexture = texName;
}    

- (GLKVector2 *)textureCoordinates {
    if (textureCoordinateData == nil)
        textureCoordinateData = [NSMutableData dataWithLength:sizeof(GLKVector2)*self.numVertices];
    return [textureCoordinateData mutableBytes];
}


- (void)render {

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glClearColor(0, 104.0/255.0, 55.0/255.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glUniformMatrix4fv(_modelViewUniform, 1, 0, modelview.m);
    glUniformMatrix4fv(_projectionUniform, 1, 0, projectionMatrix.m);

    glEnableVertexAttribArray(_positionSlot);

    glEnableVertexAttribArray(_colorSlot);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);

    glVertexAttribPointer(_positionSlot, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
    glVertexAttribPointer(_colorSlot, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) (sizeof(float) * 3));
    if(texture != nil) {
        glEnableVertexAttribArray(_texCoordSlot);
        glActiveTexture(GL_TEXTURE0); // unneccc in practice
        glBindTexture(GL_TEXTURE_2D, _imageTexture);
        glUniform1i(_textureUniform, 0); // unnecc in practice
        glVertexAttribPointer(_texCoordSlot, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) (sizeof(float) * 7));
    }

        glDrawElements(GL_TRIANGLE_FAN, sizeof(indices)/sizeof(GLushort), GL_UNSIGNED_SHORT, (void*)0);
    }
    //is cleanup code that tells the shader that we’re done using vertex position data.
    glDisableVertexAttribArray(GLKVertexAttribPosition);

    if (texture != nil)
        glDisableVertexAttribArray(GLKVertexAttribTexCoord0);

    [_currentContext presentRenderbuffer:GL_RENDERBUFFER];

    glDisable(GL_BLEND);
}

// draw the shape in the selected scene
- (void)renderInScene:(P3Scene *)theScene {

    projectionMatrix = [theScene projectionMatrix];

    modelview = GLKMatrix4Multiply(GLKMatrix4MakeTranslation(0, 0, 0), GLKMatrix4MakeRotation(0, 0, 0, 1));
    modelview = GLKMatrix4Multiply(modelview, GLKMatrix4MakeScale(scale.x, scale.y, 1));

    [self render];
}

-(void)update:(NSTimeInterval)dt {
    if(self.toDraw)
        [spriteAnimation update:dt];
}

@end

如您所见,我正在使用顶点数组和基本颜色进行测试,但没有任何区别。 OpenGl 似乎设置正确,因为渲染函数中的 glClearColor(0, 104.0/255.0, 55.0/255.0, 1.0); 使我的 View 呈绿色。

这里是 pastebin 上的文件:

P3Shape.m on pastebin

以及创建 ogl 程序的经理

P3GameManager.m on pastebin

有什么想法吗?

编辑:我的着色器可能有问题?

顶点:

attribute vec4 Position; 
attribute vec4 SourceColor; 

varying vec4 DestinationColor; 

uniform mat4 Projection;
uniform mat4 Modelview;

attribute vec2 TexCoordIn; // New
varying vec2 TexCoordOut; // New

void main(void) { 
    DestinationColor = SourceColor; 
    gl_Position = Projection * Modelview * Position;
    TexCoordOut = TexCoordIn; // New
}

和片段:

varying lowp vec4 DestinationColor;

varying lowp vec2 TexCoordOut; // New
uniform sampler2D Texture; // New

void main(void) {
    gl_FragColor = DestinationColor * texture2D(Texture, TexCoordOut); // New
}

最佳答案

我建议使用 GLKViewController 和 GLKView 来简化您的设置。同样,用 GLKTextureLoader 替换您的纹理加载。

我还没有看到任何 GLKBaseEffect 内存泄漏和导致崩溃的问题。我建议发布一个关于这个特定问题的新问题,如果您不需要自定义着色器(看起来您不需要),则返回使用 GLKBaseEffect 。将使您的代码更易于管理和调试。

关于iphone - OpenGl ES 2.0 和 GLKit : From GLKBaseEffect shaders to OpenGl,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12117772/

有关iphone - OpenGl ES 2.0 和 GLKit : From GLKBaseEffect shaders to OpenGl的更多相关文章

  1. ruby-on-rails - 如何在 Ruby on Rails 中实现由 JSF 2.0 (Primefaces) 驱动的 UI 魔法 - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭10年前。问题1)我想知道ruby​​onrails是否有功能类似于primefaces的gem。我问的原因是如果您使用primefaces(http://www.primefaces.org/showcase-labs/ui/home.jsf),开发人员无需担心javascript或jquery的东西。据我所知,JSF是一个规范,基于规范的各种可用实现,prim

  2. ruby - Jekyll 2.0 中的 SCSS 生成错误 - 2

    我的项目布局如下:-Project-css-import.scss-_sass/main.scssimport.scss的内容是:------@import"main.scss";我期望发生的是将main.scss导入到import.scss中,然后,import.scss将在生成的_site/目录中编译为import.css。相反,我收到以下错误Conversionerror:Therewasanerrorconverting'css/import.scss'.jekyll2.0.3|Error:InvalidCSSafter"-":expectednumberorfunction,

  3. ruby - 在 Amazon OpsWorks 上使用 Ruby 2.0 - 2

    我想在AmazonOpsWorks上使用Ruby2.0,所以我正在尝试以下操作:选择自定义Recipe并将它们设置到我的forkhttps://github.com/aws/opsworks-cookbooks在此处更新所有版本号https://github.com/aws/opsworks-cookbooks/blob/master/ruby/attributes/ruby.rb到2.0值。虽然这似乎没有任何效果。自定义说明书是否会覆盖其内置的说明书?OpsWorks是否使用Recipe中的Ruby配方来进行基本的Ruby设置?同样的问题也适用于Nginx-我可以通过更改Recipe

  4. ruby-on-rails - Ruby 1.9.3 -> 2.0 别名方法和扩展 - 2

    我正在尝试将Ruby1.9.3应用程序升级到2.0,除了一个小问题外,一切似乎都很顺利。我写了一个模块,我将其包含在我的模型中以覆盖activerecorddestroy。它将现有的destroy方法别名为destroy!,然后覆盖destroy以更改记录上的deleted_at时间戳。仅当我升级到ruby​​2.0时,destroy!不再破坏记录,但其行为就像我的新覆盖方法一样。知道为什么会这样吗?下面是更相关的代码部分。完整要点here.defself.included(base)base.class_evaldoalias_method:destroy!,:destroyalia

  5. 来自哈希的ruby 2.0命名参数 - 2

    如果我在ruby​​中有一个接受命名参数的方法...defsmoosh(first:nil,second:nil)first+secondend如果键匹配,将散列传递给该方法的最简单方法是什么:params={first:'peanut',second:'butter'}smoosh(params)以上会产生参数错误。更新:这似乎是Sinatra参数工作方式的问题。当我这样做时:get'a_sinatra_route'dohash=params.clonehash.symbolize_keys!smoosh(hash)end它工作正常。仅自行传递参数时,它不起作用。(即使您可以使用符号

  6. ruby 2.0 未定义方法 ObjectSpace.trace_object_allocations - 2

    在ruby​​2.0.0/247或head上试过这个:require'objspace'ObjectSpace.trace_object_allocations->undefinedmethod`trace_object_allocations'forObjectSpace:Module文档说它应该可以工作http://www.ruby-doc.org/stdlib-2.0/libdoc/objspace/rdoc/ObjectSpace.html知道我错过了什么吗? 最佳答案 对于更高的ruby​​版本,您仍然可能会遇到如下错误:

  7. ruby-on-rails - Ruby on Rails : 4. 2.0 rails 和 bin/rails 的区别 - 2

    所以从Rails4.1.x开始,似乎有一种推荐的方法是在应用程序文件夹下使用rails。而不是传统的:railsserverRails官方指南推荐使用bin/railsserver看起来bin/rails正在引用带有附加内容的rails。与rails相比,使用bin/rails的额外好处是什么?第二个问题是——我习惯于使用railsserver、railsconsole等,而不是bin/railsserver、bin/railsconsole。如果不使用bin/rails,我会丢失任何东西吗(比如误加载一些库等)?谢谢。 最佳答案

  8. Ruby 2.0 抛出 "[BUG] Stack consistency error" - 2

    我正在学习RubyKoans中的练习在about_proxy_object_project.rb中有这段代码:classProxydefinitialize(target_object)@object=target_objectend#Thismethodwasaddedbymedefmethod_missing(method_name,*args,&block)@object.sendmethod_nameendend这样调用:deftest_tv_methods_still_perform_their_functiontv=Proxy.new(Television.new)#Tel

  9. ruby - 为什么默认情况下 Ruby (2.0 +) 中的 Enumerators 不是惰性的? - 2

    为什么RubyEnumerator默认情况下不像Enumerator::Lazy那样?有没有人想要使用非惰性Enumerator的情况?已编辑:下面是对向后兼容性答案的评论,解释了为什么我还不相信:假设我们已将这些“重大”更改添加到Ruby2.0.0,这是一个主要版本,您将在进行切换之前彻底测试您的代码(特别是如果您要生产),不是吗?编辑#2我怀疑它与效率有关(如果有任何问题请告诉我),所以我做了以下基准测试:(当然有些地方惰性更好。这可能是为了证明为什么Ruby不是一直在使用lazy?)require'fruity'require'prime'comparedolazy{g=Prim

  10. iphone - 扩展 restful_authentication/AuthLogic 以支持匿名 iPhone 的延迟登录的最佳方法是什么? - 2

    我正在构建一个与RubyonRails后端对话的iPhone应用程序。RubyonRails应用程序还将为Web用户提供服务。restful_authentication插件是提供快速和可定制的用户身份验证的绝佳方式。但是,我希望iPhone应用程序的用户在新列中存储一个由手机的唯一标识符([[UIDevicedevice]uniqueIdentifier])自动创建的帐户。稍后,当用户准备好创建用户名/密码时,帐户将更新为包含用户名和密码,iPhone唯一标识符保持不变。用户在设置用户名/密码之前不能访问该网站。然而,他们可以使用iPhone应用程序,因为该应用程序可以使用它的标识符

随机推荐