SceneKit:增加用于 SCNNode 材质的纹理的清晰度?

Posted

技术标签:

【中文标题】SceneKit:增加用于 SCNNode 材质的纹理的清晰度?【英文标题】:SceneKit: increase sharpness of texture used for SCNNode material? 【发布时间】:2017-01-25 06:55:18 【问题描述】:

我们的应用程序允许用户上传自定义图像作为 SCNNodes 的材料,您可以从下面的屏幕截图和代码中看到。

屏幕截图 1 显示材质使用比例为 1 时的 SCNNodes。

屏幕截图 2 显示了相同的节点,比例为 2。

虽然使用 2 的比例会显着锐化纹理/材质,但由于 wrapSwrapT 属性,它也会重复图像。对这些属性使用 MirrorClamp 而不是 Repeat 没有帮助。

在 SceneKit 或 UIKit 中,您提供更高分辨率的图像并按比例缩小以提高不同设备的清晰度。例如,对于一个 50x50 的按钮,您提供一个 100x100 的图像。通过在底部的 UIKit 组件中查看相同图像的锐度,您可以看到相同图像的 UIKit 锐度和 SceneKit 锐度之间的对比。

1) 您如何将相同的原理应用于 SceneKit?

2) 更重要的是,如何在避免重复行为的同时实现截图 2 的纹理/材质清晰度?

代码:

// Create box geometry
let box = SCNBox(width: 1.0, height: 1.0, length: 1.0, chamferRadius: 0.0)
box.firstMaterial!.diffuse.contents = style.getContents() // This returns a UIImage
box.firstMaterial!.specular.contents = UIColor.whiteColor()

// Increase resolution for image styles
let scale = Float(2)
if style.type == .Image 
    box.firstMaterial!.diffuse.contentsTransform = SCNMatrix4MakeScale(scale, scale, scale)
    //box.firstMaterial!.locksAmbientWithDiffuse = true
    box.firstMaterial!.diffuse.wrapS = .Repeat
    box.firstMaterial!.diffuse.wrapT = .Repeat
    box.firstMaterial!.diffuse.mipFilter = .Linear

纹理:

屏幕截图 1:

屏幕截图 2:

【问题讨论】:

您是否将这些图像添加到几何体的面?例如,它们是立方体的侧面还是类似的东西? 是的,代码在问题中。将澄清问题,但内容正在设置为 UIImage。 @Confused 如果你想重现盒子,还添加了纹理。 我认为你需要更大的纹理。没有其他方法可以获得我能想到的清晰度。 @Confused 谢谢。我们需要什么尺寸?使用 SpriteKit 和 UIKit,很容易估计纹理大小,因为它与组件的大小有关(例如,100px 图像对应 50px 按钮对应 2x 分辨率)。 【参考方案1】:

您需要考虑图像将在屏幕上占据的实际像素、最接近相机的位置以及最大程度的透视失真。

因此,举例来说,靠近相机的立方体,在场景的左侧,可能有一个非常靠近相机“镜头”的边缘,并且占据了(例如)大部分 y屏幕的轴(高度)。如果这是一种常见情况,那么在您的游戏中,以猜测这个(真实)像素大小为目标,您将了解需要多大的纹理才能获得清晰度。

这是 3D 引擎中存在 LOD(细节级别)功能的原因之一,因此场景中的所有对象都不需要始终拥有最好、最高质量的纹理,也不需要最大数量的多边形来表达它们的形状。

大多数 3D 引擎中还有不同类型的纹理处理算法,用于平滑处理。如果它们存在于 SceneKit 中,将它们关闭也将是获得清晰(呃)纹理的一大优势。

几何细节层次

(不直接适用于您的请求,但显示了它是如何工作的)

https://developer.apple.com/reference/scenekit/scnlevelofdetail

纹理“缩放”(mip 映射)

这更适用。这个“技巧”真的很老了,我记得从第一张 3D 卡片开始。它使您的纹理更小:

https://developer.apple.com/reference/scenekit/scnmaterialproperty/1395398-mipfilter

第二次看,我认为这是非常自动的:

从上面的页面:

"SceneKit 自动为材质创建多个 mipmap 级别 属性的图像内容,每个都是原始图像的一小部分 尺寸。渲染时,SceneKit 会自动从 最接近正在渲染的尺寸的 mipmap 级别。”

【讨论】:

非常感谢!那么这是否意味着我们不应该对 mipfilter 使用线性,因为您说更平滑的纹理将有助于产生更清晰的纹理?这么光滑对纹理来说不是一件好事吗? 我对它的阅读倾向于让我认为你应该把它放在线性上,但我不知道。试试吧。 Scene Kit 中的大多数东西都按照我期望的方式工作。有些完全令人困惑。 OK 会试试的。您能否详细说明您暗示平滑度和锐度之间存在负相关的意思? 另外,我们似乎没有滥用 scale 属性,对吧(即,比例为 2 的重复效果是预期行为)?如果为真,则意味着应该使用 1 的比例,至少对于 SCNBoxes。 平滑度(对于像素)通常会柔化事物,降低清晰度。但我不确定我们说的是同一件事。在缩放时,是的,2 可以正常工作,但不能使用。把它留为 1。它与 2D/UIKit 等中的 2x 和 3x 图形不同。

以上是关于SceneKit:增加用于 SCNNode 材质的纹理的清晰度?的主要内容,如果未能解决你的问题,请参考以下文章

Scenekit:如何获取节点的所有材质?

SceneKit:理解 SCNNode 的 pivot 属性

SceneKit - 在另一个 SCNNode 上添加 SCNNode

在 SceneKit 中缩放 SCNNode

SceneKit - 如何知道带有 MDLObject 的 SCNNode 是不是已加载并可见?

如何在 SceneKit 中移动旋转的 SCNNode?