在OpenGL ES中使用UIMotionEffect

时间:2014-02-12 22:01:21

标签: ios objective-c opengl-es ios7

我专门为我的应用程序使用OpenGL ES(2.0)。我试图让UIMotionEffect使用我的一个OpenGL对象 - 我需要的只是“倾斜”值。

UIInterpolatingMotionEffect只能应用于UIView,黑客就是将UIInterpolatingMotionEffect应用于UIView并从每帧抓取值,而不是渲染假定的UIView。但它似乎是唯一的解决方案。

我尝试将UIMotionEffect子类化,但无法弄清楚- (NSDictionary *)keyPathsAndRelativeValuesForViewerOffset:(UIOffset)viewerOffset是如何工作的(即调用它以及如何检索我需要的值)。

关于如何在OpenGL中使用UIMotionEffect的任何想法?

2 个答案:

答案 0 :(得分:5)

我最后测试了@rickster建议的方法:将UIInterpolatingMotionEffect连接到我自己定制的GLKView / GL View传递键并检索它们。不幸的是,这个想法在皇室成功了。

首先,传递给UIInterpolatingMotionEffect的密钥必须是UIView可动画的属性,并且不能是自定义变量/属性。考虑到大多数人不希望他们的整个背景在单向/强度上出现视差,这种方法会失败。

其次,您不能只检索值。如果您将center.x作为密钥传递,UIInterpolatingMotionEffect将不会更新center.x,因为这些更改被视为“动画”。因此,您可以检索动画center.x,例如[[view.layer presentationLayer] center];

最终注释:只需在主线程上创建一个单独的UIView,将其添加到UIViewController并系统地从中检索值(也在主线程上)。到目前为止,我发现这是最简单的解决方案。

此外,由于我需要在单独的线程上检索值,因此我通常会抛出一个值,因为我调度到主线程以检索当前值,同时检索最后一个值集(make确定变量是线程安全的/原子的。)

修改

由于它最好在主线程上访问presentationLayer,但是我的方法被调用一个不是main的线程,我调度主线程来检索值并将它放在一个原子属性中。然后我会在线程外返回原子属性。这确保我的辅助线程不会被主线程阻塞,我可以检索我需要的值。

这是我用来从不是主线程的线程中检索值的代码:

@property (atomic) GLKVector2 currentOffset;
@property (atomic, readonly) GLKVector2 offset;

- (GLKVector2)offset
{
    dispatch_async(dispatch_get_main_queue(), ^{
        CGRect frame = [[self.view.layer presentationLayer] frame];
        self.currentOffset = (GLKVector2){-frame.origin.x, -frame.origin.y};
    });

    return self.currentOffset;
}

答案 1 :(得分:1)

UIInterpolatingMotionEffect通过使用键值编码为UIView上的任何数字属性设置值。这可以是您定义的任何属性,而不仅仅是UIView类中内置的属性。

您需要某种UIView才能在屏幕上显示您的内容。如果您在iOS上使用OpenGL ES,那么(最好)使用GLKView,这是一个UIView子类,用于管理自己的GL帧缓冲区,并为您提供编写GL绘图代码以进行渲染的位置进入那些帧缓冲区。 (如果您没有使用GLKView,那么您可能正在使用某种使用UIView呈现其内容的自定义CAEAGLLayer子类。)

无论哪种方式,如果您已经在屏幕上显示了GL渲染内容,您已经拥有UIView 。如果该视图不是您自己的自定义子类(无论是直接UIView子类还是GLKView子类),您可以将其设置为一个,并在其上定义自己的自定义属性。然后设置UIInterpolatingMotionEffect以使用这些属性。在视图子类或任何负责GL渲染的对象中,读取这些属性的值并使用它们来设置场景。 (例如,您可以使用它们来设置ModelView矩阵,并将其传递给着色器制服。)