GLKView设置可绘制属性

31

我正在尝试将苹果的GLPaint示例移植为使用GLKit。使用UIView,可以返回视图的CAEAGLLayer,并将drawableProperties设置为包括kEAGLDrawablePropertyRetainedBacking。这会在呈现渲染缓冲区后保留可绘制内容,正如预期的那样。删除此属性会导致绘制调用后出现闪烁,似乎部分可绘制内容被绘制到不同的缓冲区。

问题是,我现在在我的GLKView中遇到了完全相同的问题,但似乎没有办法设置drawable属性。返回CAEAGLLayer并设置属性没有效果,我也没有看到任何相关的GLKView属性来设置保留后备。

是否有其他人遇到过这个问题或有解决方案?


我没有解决方案,但请注意,在新的iPad视网膜模式下存在驱动程序错误,其中保留后备模式会完全混乱。这里有讨论和解决方法:https://dev59.com/U2HVa4cB1Zd3GeqPo6hA - orion elenzil
你在委托方法中进行绘制吗?你使用了清晰的步骤吗? - nielsbot
说实话我不记得了。最后我只是使用了CAEAGLLayer,但是用GLKit进行矩阵计算和纹理加载。 - Brett
另外,请参考https://dev59.com/U2HVa4cB1Zd3GeqPo6hA。看起来,写那篇文章的人确切地知道如何做你想要的事情。 - Liron
5个回答

8
如果您想在GLKView中获得kEAGLDrawablePropertyRetainedBacking属性,请将以下类别添加到您的项目中。
@interface CAEAGLLayer (Retained)

@end 

@implementation CAEAGLLayer (Retained)

- (NSDictionary*) drawableProperties
{
    return @{kEAGLDrawablePropertyRetainedBacking : @(YES)};
}

@end

在GLKView绑定其drawable并生成其渲染存储时,设置在由GLKView维护的CAEAGLLayer上的drawableProperties是无效的,因为GLKView会覆盖这些属性。使用此方法强制GLKView使用您类别返回的drawableProperties。


这个方法也适用于读取深度缓冲吗?我尝试过加上或不加这段代码,但读取的Z值总是0。 - Bram

7

Simeon的回答可行,但会更改应用程序中所有基于EAGL的视图的行为。我有一些需要强制使用后备的视图和一些不需要的视图,因此我想到了一种稍微不同的解决方案,即创建GLKView和CEAGLLayer的子类,如下所示:

@interface RetainedEAGLLayer : CAEAGLLayer
@end

@implementation RetainedEAGLLayer
- (void)setDrawableProperties:(NSDictionary *)drawableProperties {
    // Copy the dictionary and add/modify the retained property
    NSMutableDictionary *mutableDictionary = [[NSMutableDictionary alloc] initWithCapacity:drawableProperties.count + 1];
    [drawableProperties enumerateKeysAndObjectsUsingBlock:^(id key, id object, BOOL *stop) {
        // Copy all keys except the retained backing
        if (![key isKindOfClass:[NSString class]]
        || ![(NSString *)key isEqualToString:kEAGLDrawablePropertyRetainedBacking])
            [mutableDictionary setObject:object forKey:key];
    }];
    // Add the retained backing setting
    [mutableDictionary setObject:@(YES) forKey:kEAGLDrawablePropertyRetainedBacking];
    // Continue
    [super setDrawableProperties:mutableDictionary];
    [mutableDictionary release];
}
@end

并且这个

@interface RetainedGLKView : GLKView
@end

@implementation RetainedGLKView
+ (Class)layerClass {
    return [RetainedEAGLLayer class];
}
@end

现在,我只需要使用RetainedGLKView而不是GLKView来实现那些需要强制保留的视图。

2

不确定这是否有效,但这是我们拥有的一些代码:

GLKView * const view = (GLKView *)self.view;  
view.context = self.context;
view.delegate = self;
view.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;
view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
view.drawableMultisample = GLKViewDrawableMultisampleNone;
self.preferredFramesPerSecond = 30;

[EAGLContext setCurrentContext:self.context];
CAEAGLLayer * const eaglLayer = (CAEAGLLayer*) view.layer;
eaglLayer.opaque = YES;

希望你能够访问eaglLayer.drawableProperties。希望这可以让你设置所需的参数。

这个答案实际上不能用于设置kEAGLDrawablePropertyRetainedBacking(至少在iPad 3上不行)。当GLKView从上下文生成renderBufferStorage时,它会覆盖层属性。我在下面发布了一个答案,让你可以绕过这个问题。 - simeon

1
在你的GLKView实现文件中:
- (id)initWithCoder:(NSCoder *)aDecoder
{
    if ((self = [super initWithCoder:aDecoder]))
    {
        _eaglLayer = (CAEAGLLayer *)self.layer;

        _eaglLayer.opaque = TRUE;
        _eaglLayer.drawableProperties = @{ kEAGLDrawablePropertyRetainedBacking : [NSNumber numberWithBool:NO],
                                           kEAGLDrawablePropertyColorFormat     : kEAGLColorFormatRGBA8};

    }
    return self;
}

我不知道人们是如何把事情搞得这么复杂的;它就是这样,只有这样。

-2

你好,请尝试这个。

GLKView * const view = (GLKView *)self.view;  
view.context = self.context;
view.delegate = self;
view.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;
view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
view.drawableMultisample = GLKViewDrawableMultisampleNone;
self.preferredFramesPerSecond = 10;

[EAGLContext setCurrentContext:self.context];
CAEAGLLayer * const eaglLayer = (CAEAGLLayer*) view.layer;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接