将核心动画与OpenGL ES相结合

Ole*_*ann 11 iphone core-animation opengl-es ios

编辑:我想而不是下面的长解释我也可能会问:发送-setNeedsDisplay到一个实例CAEAGLLayer不会导致图层重绘(即,-drawInContext:不被调用).相反,我得到这个控制台消息:

<GLLayer: 0x4d500b0>: calling -display has no effect.
Run Code Online (Sandbox Code Playgroud)

有没有解决这个问题的方法?我可以在调用-drawInContext:-setNeedsDisplay调用吗?下面详细解释:


我有一个OpenGL场景,我想使用Core Animation动画制作动画.

遵循在CALayer中设置自定义属性动画的标准方法,我创建了一个子类,CAEAGLLayersceneCenterPoint在其中定义了一个属性,其值应该是动画的.我的图层还包含对OpenGL渲染器的引用:

#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#import "ES2Renderer.h"

@interface GLLayer : CAEAGLLayer
{
    ES2Renderer *renderer;
}

@property (nonatomic, retain) ES2Renderer *renderer;
@property (nonatomic, assign) CGPoint sceneCenterPoint;
Run Code Online (Sandbox Code Playgroud)

然后我声明属性@dynamic让CA创建访问器,覆盖+needsDisplayForKey:并实现-drawInContext:sceneCenterPoint属性的当前值传递给渲染器并要求它渲染场景:

#import "GLLayer.h"

@implementation GLLayer

@synthesize renderer;
@dynamic sceneCenterPoint;

+ (BOOL) needsDisplayForKey:(NSString *)key
{
    if ([key isEqualToString:@"sceneCenterPoint"]) {
        return YES;
    } else {
        return [super needsDisplayForKey:key];
    }
}

- (void) drawInContext:(CGContextRef)ctx
{
    self.renderer.centerPoint = self.sceneCenterPoint;
    [self.renderer render];
}
...
Run Code Online (Sandbox Code Playgroud)

(如果您可以访问WWDC 2009会话视频,则可以在会话303中查看此技术("动画制图")).

现在,当我在keyPath上为图层创建显式动画时@"sceneCenterPoint",Core Animation应该计算自定义属性的插值并调用-drawInContext:动画的每个步骤:

- (IBAction)animateButtonTapped:(id)sender
{
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"sceneCenterPoint"];
    animation.duration = 1.0;
    animation.fromValue = [NSValue valueWithCGPoint:CGPointZero];
    animation.toValue = [NSValue valueWithCGPoint:CGPointMake(1.0f, 1.0f)];
    [self.glView.layer addAnimation:animation forKey:nil];
}
Run Code Online (Sandbox Code Playgroud)

至少那是普通CALayer子类会发生的事情.当我进行子类化时CAEAGLLayer,我会在控制台上为动画的每个步骤获取此输出:

2010-12-21 13:59:22.180 CoreAnimationOpenGL[7496:207] <GLLayer: 0x4e0be20>: calling -display has no effect.
2010-12-21 13:59:22.198 CoreAnimationOpenGL[7496:207] <GLLayer: 0x4e0be20>: calling -display has no effect.
2010-12-21 13:59:22.216 CoreAnimationOpenGL[7496:207] <GLLayer: 0x4e0be20>: calling -display has no effect.
2010-12-21 13:59:22.233 CoreAnimationOpenGL[7496:207] <GLLayer: 0x4e0be20>: calling -display has no effect.
...
Run Code Online (Sandbox Code Playgroud)

因此,可能出于性能原因,OpenGL图层似乎-drawInContext:没有被调用,因为这些图层不使用标准-display方法来绘制自己.任何人都可以证实吗?有办法解决吗?

或者我可以不使用上面列出的技术吗?这意味着我必须在OpenGL渲染器中手动实现动画(这是可能的,但不是优雅的IMO).

Jef*_*ast 6

您可以覆盖display而不是drawInContext.在动画期间,动画值位于表示层中.

- (void) display
{
    GLLayer* myPresentationLayer = (GLLayer*)[self presentationLayer];
    self.renderer.centerPoint = myPresentationLayer.sceneCenterPoint;
    [self.renderer render];
}
Run Code Online (Sandbox Code Playgroud)

最后,表示层将具有模型图层值,因此您需要在开始动画之前在模型图层上设置最终值.


Dad*_*Dad 4

您是否尝试过在 OpenGL 图层上方创建一个父图层并对其进行动画处理?