【问题标题】:Set CALayer as SCNMaterial's diffuse contents将 CALayer 设置为 SCNMaterial 的漫反射内容
【发布时间】:2016-07-11 11:43:52
【问题描述】:

过去几天我一直在互联网上搜索,但无济于事。不幸的是,有关此特定问题的苹果文档含糊不清,并且没有可用的示例代码(至少这是我发现的)。您可能会问什么问题...

我正在尝试将 uiview 的图层设置为用于渲染 iPhone 模型屏幕的材料的内容(是的,trippy :P)。 iPhone 屏幕的 UV 映射设置为从 0 到 1,因此在将纹理/图层映射到纹素时不会出现任何问题。

所以,不是让这个层在 iPhone 上呈现,与左图相同,而是像右图一样呈现在 iPhone 上

正确的渲染                                      不正确的渲染

另外请注意,当我设置断点并调试实际的 iPhone 节点并在 Xcode 中查看它时,会显示完全不同的渲染,并且当我继续执行时,图层会半固定:

那么……我该如何解决这个问题???我尝试过使用漫反射的内容变换矩阵,但没有得到任何修复。我还尝试将 UIView 的大小调整为 256x256(因为 UV 似乎是 256x256,如 blender - 3d 建模包中所示),但这并不能解决任何问题。

这是图层的代码:

UIView *screen = [[UIView alloc] initWithFrame:self.view.bounds];
screen.backgroundColor = [UIColor redColor];

UIView *temp = [[UIView alloc] initWithFrame:CGRectMake(0, 0, screen.bounds.size.width, 60)];
temp.backgroundColor = [UIColor colorWithRed:0 green:(112.f/255.f) blue:(235.f/255.f) alpha:1];

UILabel *label = [[UILabel alloc] initWithFrame:CGRectInset(temp.bounds, 40, 0)];
label.frame = CGRectOffset(label.frame, 40, 0);
label.textColor = [UIColor colorWithRed:0 green:(48.f/255.f) blue:(84.f/255.f) alpha:1];
label.text = @"Select Track";
label.font = [UIFont fontWithName:@"HelveticaNeue-Light" size:30];
label.minimumScaleFactor = 0.001;
label.adjustsFontSizeToFitWidth = YES;
label.lineBreakMode = NSLineBreakByClipping;
[temp addSubview:label];

UIView *separator = [[UIView alloc] initWithFrame:CGRectMake(0, temp.bounds.size.height - 2, temp.bounds.size.width, 2)];
separator.backgroundColor = [UIColor colorWithRed:0 green:(48.f/255.f) blue:(84.f/255.f) alpha:1];
[temp addSubview:separator];
[screen addSubview:temp];
screen.layer.contentsGravity = kCAGravityCenter;

编辑
更奇怪的是,如果我使用以下方法捕获视图的 UIImage:

- (UIImage *) imageWithView:(UIView *)view
{
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0);
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];

    UIImage * img = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return img;
}

并将其用作漫反射的内容...一切都很好?!这真的很奇怪和令人沮丧,因为图像的大小与 uiview 的大小完全相同......


编辑 2

我最终只使用视图的图像作为纹理,这使得事情比我需要的更加静态。我不会将此设置为答案,因为即使在很长一段时间内我仍然会等待此问题的正确解决方案。所以,如果你有答案并且这个话题已经打开了很长时间,如果可以的话,请顶一下。这部分的文档太差了。

【问题讨论】:

  • 我们可以看看您是如何设置 SCNScene 和 SCNView 的吗?当你使用纯色作为材质而不是 CALayer 时,它是否有效?
  • @HalMueller 我使用的是创建 SceneKit 应用程序时提供的默认代码,并且只更改场景名称和节点名称。 CALayer 的代码显示为here。它将使用纯色,因为该层实际上是在某种意义上映射的,允许它覆盖整个“iPhone 屏幕”。似乎映射使得图层溢出纹素区域之外......但是当我在 ib 中使用纹理图像时,它非常适合并且看起来正确。
  • 我建议尝试将shouldRasterize = YES; 添加到您的CALayer,并在将CALayer 分配给内容后立即调用[SCNTransaction flush];
  • 如果 Core Animation 尝试在动画的每一帧重新创建位图,您将失去使用 Core Animation 的所有性能优势,因为这类似于 Core Graphics 在 blitting 到屏幕之前绘制到上下文中。
  • @ColdSteel 使用 CALayers 作为纹理的原因是为了拥有尽可能高性能的动画纹理。同样,如果 SpriteKit 被用作 SceneKit 中的纹理。 CALayers 有一些 SpriteKit 没有的能力,因此对它们很有吸引力。

标签: ios objective-c scenekit calayer


【解决方案1】:

旧帖子上的新帖子,但在当今时代,可以将 UIView 本身设置为 SCNMaterialProperty (diffuse) contents。支持此功能的意图是直接从 Apple 的 SceneKit 工程部门传达的,尽管文档尚未更新以反映这一点。

要绑定到原始帖子,请不要将 UIView.layer 设置为材质属性内容;而是将内容设置为 UIView 本身。

[更新:根据下面 Lance 的评论,对视图的支持可能会越来越差,而不是越来越好。]

【讨论】:

  • 太好了,我验证它有效。不幸的是,它不支持透明度。
  • 哎呀!你提交错误了吗?
  • @Bobjt 截至 2020 年,UIView 尚不完全受支持。我不断从后台线程调用 ARKit_4[20429:4746699] [Animation] +[UIView setAnimationsEnabled:]。不支持从 UIView 或子类的后台线程执行任何操作,这可能会导致意外和阴险的行为stackoverflow.com/questions/59446393/…
  • 如果支持越来越差,我会删除这篇文章。出于好奇,谁在调用 setAnimationsEnabled?
  • @Bobjt 我正在关注这个答案:stackoverflow.com/a/48712156/4833705。 diffuse.contents 属性是导致错误的原因。我认为您目前不应该删除答案。我正在使用我的一个 TSI 来了解 Apple 技术人员对此问题的看法。一旦我得到他们的答复,我会通知你
【解决方案2】:

SceneKit docs 强烈建议,虽然在某些情况下您可以使用动画 CALayers 作为素材内容,但不包括 UIView 层:

SceneKit 不能使用已经在别处显示的层(例如,UIView 对象的支持层)。

这表明,如果您想为您的材质制作动画内容,最好使用完全独立使用的 Core Animation 或 SpriteKit。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-21
    • 2011-11-14
    • 1970-01-01
    • 2018-07-31
    • 2012-01-24
    • 2013-01-06
    相关资源
    最近更新 更多