在SceneKit

时间:2017-01-13 06:20:35

标签: ios swift scenekit

所以我在SceneKit中有这些场景,我以编程方式创建了一堆不同高度的对象。其中大部分是简单的盒子,但其中一些是挤压路径。

我需要为它们添加一种简单的材质颜色,使颜色从较暗的值变为较浅的颜色从底部到顶部。

我一直在努力通过创建一个具有以CAGradientLayer编程方式创建的渐变图像纹理的材质来实现这一目标。这“几乎”有效。这种方法的问题是对象的所有面都会得到相同的效果,这不是我想要的。物体的顶部和底部表面应为纯色 - 顶部表面的浅色和底部的浅色。

我一直在使用着色器,但结果是相对于屏幕而不是我的对象的渐变,从而将我的3D对象渲染为2D。

以下是我创建一个简单的纯色框的方法,例如:

func createBox(with bounds: CGRect, and height: CGFloat) {
    let material = SCNMaterial()
    material.diffuse.contents = UIColor.white
    if #available(iOS 10.0, *) {
        material.lightingModel = .physicallyBased
        material.metalness.contents = 0.2
        material.roughness.contents = 0.5
    }

    let geometry = SCNBox(width: bounds.size.width, height: height, length: bounds.size.height, chamferRadius: 0.0)
    geometry.materials = [material]
    geometry.chamferRadius = 0.02

    let node = NKNode(geometry: geometry)
}

现在,由于一个盒子默认有6个不同的几何元素,我可以选择创建一个材料,将其内容设置为渐变图像,然后在materials geometry数组中添加所述材质6次1}}。这允许我单独为每个面设置一个材质,如下所示:

let material = SCNMaterial()
material.diffuse.contents = UIImage(named: "gradient-test")
geometry.materials = [material, material, material, material, material, material]

有了这个,我可以有3种不同的材料(侧面,顶部,底部),并通过反复试验在materials数组中以正确的顺序添加它们。这将转化为:

let sideMaterial = SCNMaterial()
sideMaterial.diffuse.contents = UIImage(named: "gradient")

let topMaterial = SCNMaterial()
topMaterial.diffuse.contents = UIColor.white

let bottomMaterial = SCNMaterial()
bottomMaterial.diffuse.contents = UIColor.black

// The order is side, side, side, side, top, bottom
geometry.materials = [sideMaterial, sideMaterial, sideMaterial, sideMaterial, topMaterial, bottomMaterial]

但是当我的对象一个简单的盒子而是一个挤出的路径时,我的问题会出现。以下是创建这些内容的方法:

func createFromPath(_ path: UIBezierPath, with height: CGFloat) {
    let material = SCNMaterial()
    material.diffuse.contents = UIColor.white
    if #available(iOS 10.0, *) {
        material.lightingModel = .physicallyBased
        material.metalness.contents = 0.2
        material.roughness.contents = 0.5
    }
    material.isDoubleSided = true

    let geometry = SCNShape(path: path, extrusionDepth: height)
    geometry.materials = [material]
    geometry.chamferRadius = 0.02
}

如您所见,简单的纯色很容易。但是应用相同的逻辑在侧面添加渐变纹理不再起作用,因为我的路径可能有不确定数量的面。说实话,我甚至认为像这样创建的几何体不像简单的盒子那样被分成多个“元素”。

那么,任何想法如何实现我的目标?

更新

这是我想要实现的一个非常基本的例子。如您所见,此地图中的3D“建筑物”具有微妙的自下而上的渐变。

enter image description here

0 个答案:

没有答案