将CALayer设置为SCNMaterial的漫反射内容

时间:2021-02-01 05:27:20

I've been searching all over the internet over the past couple of days to no avail. Unfortunately, the apple documentation about this specific issue is vague and no sample code is available (at least thats what I found out). What seems to be the issue you may ask...

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

I'm trying to set a uiview's layer as the contents of the material that is used to render an iPhone model's screen (Yep, trippy :P ). The iPhone's screen's UV mapping is set from 0 to 1 so that no issue persists in mapping the texture/layer onto the texels.

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

So, instead of getting this layer to appear rendered on the iPhone, same as left image, Instead, I get this rendered onto the iPhone like right image

所以,而不是让这个图层在iPhone上呈现,与左图像相同,相反,我将其渲染到iPhone上,就像右图一样

Correct Render                                        Incorrect Render

将CALayer设置为SCNMaterial的漫反射内容

Also note, that when I set a breakpoint and debug the actual iPhone node and view it in Xcode, a completely different render is shown and the layer gets half-fixed when I continue execution:

还要注意,当我设置一个断点并调试实际的iPhone节点并在Xcode中查看它时,会显示一个完全不同的渲染,当我继续执行时,该层会得到半固定:

将CALayer设置为SCNMaterial的漫反射内容

Now then... HOW do I fix this issue??? I've tried playing with the diffuse's contents transform matrix but nothing gets fixed. I've also tried resizing the UIView to 256x256 (since the UV seems to be 256x256 as shown in blender - the 3d modelling package), but that doesn't fix anything.

现在......我如何解决这个问题?我尝试过使用漫反射内容变换矩阵,但没有任何修复。我也尝试将UIView调整为256x256(因为UV似乎是256x256,如混合器中所示 - 3d建模包),但这并没有解决任何问题。

Here is the code for the layer:

这是图层的代码:

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;

Edit
What's even weirder is that if I capture a UIImage of the view using:

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

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

    UIImage * img = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return img;
}

and use that as the diffuse's content... everything works out perfectly fine?! It's really weird and frustrating since the image's size is exactly the same as the uiview's...

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


Edit 2

编辑2

I ended up just using an image of the view as the texture, which makes things much more static than I needed. I won't set this as the answer because I'll still be waiting for a correct fix to this issue even if it in a long time. So, if you have an answer and this topic has been opened for a long time, please bump it if you can. The documentation on this section is just so poor.

我最终只是使用视图的图像作为纹理,这使得事物比我需要的更加静态。我不会将此作为答案,因为即使是在很长一段时间内,我仍然会等待正确解决这个问题。所以,如果你有一个答案并且这个主题已经打开了很长时间,请尽可能地碰到它。这部分的文档非常糟糕。

2 个解决方案

#1


5  

New post on an old thread, but this day-in-age, it's possible to set the UIView itself as SCNMaterialProperty (diffuse) contents. Intention to support this feature is communicated directly from SceneKit engineering at Apple, though the documentation has not yet been updated to reflect it.

旧帖子上的新帖子,但是这个日期,可以将UIView本身设置为SCNMaterialProperty(diffuse)内容。直接从Apple的SceneKit工程部门传达了支持此功能的意图,尽管文档尚未更新以反映它。

To tied back to the original post, do not set a UIView.layer as material property contents; instead set contents to the UIView itself.

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

#2


3  

The SceneKit docs pretty strongly suggest that, while there are cases where you can use animated CALayers as material content, that doesn't include UIView layers:

SceneKit文档非常强烈地建议,虽然在某些情况下您可以使用动画CALayers作为材质内容,但不包括UIView图层:

SceneKit cannot use a layer that is already being displayed elsewhere (for example, the backing layer of a UIView object).

SceneKit无法使用已在其他位置显示的图层(例如,UIView对象的背衬层)。

That suggests that if you want to make animated content for your material, you're better off with either Core Animation used entirely on its own or SpriteKit.

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

#1


5  

New post on an old thread, but this day-in-age, it's possible to set the UIView itself as SCNMaterialProperty (diffuse) contents. Intention to support this feature is communicated directly from SceneKit engineering at Apple, though the documentation has not yet been updated to reflect it.

旧帖子上的新帖子,但是这个日期,可以将UIView本身设置为SCNMaterialProperty(diffuse)内容。直接从Apple的SceneKit工程部门传达了支持此功能的意图,尽管文档尚未更新以反映它。

To tied back to the original post, do not set a UIView.layer as material property contents; instead set contents to the UIView itself.

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

#2


3  

The SceneKit docs pretty strongly suggest that, while there are cases where you can use animated CALayers as material content, that doesn't include UIView layers:

SceneKit文档非常强烈地建议,虽然在某些情况下您可以使用动画CALayers作为材质内容,但不包括UIView图层:

SceneKit cannot use a layer that is already being displayed elsewhere (for example, the backing layer of a UIView object).

SceneKit无法使用已在其他位置显示的图层(例如,UIView对象的背衬层)。

That suggests that if you want to make animated content for your material, you're better off with either Core Animation used entirely on its own or SpriteKit.

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