使 SCNNode 透明,以便您可以通过它看到其他节点

问题描述 投票:0回答:1

如何使圆柱体透明,以便无论绿色的 alpha 值如何,您始终可以透过它们看到绿色的墙壁?

问题描述

(完整代码在最后)

我有一个

SCNNode()
定义为两个正方形(形成立方体的两侧),其材质定义为

var meshMaterial: SCNMaterial = {
    let mat = SCNMaterial()
    mat.diffuse.contents = UIColor.green
    mat.lightingModel = .constant
    return mat
}()

我在每面墙上放置两个圆柱体,圆柱体的不透明度设置为 0.3。透过圆柱体你可以看到绿色的墙壁。

enter image description here

问题

当我将

meshMaterial
的 alpha 设置为 1.0 以外的任何值时

var meshMaterial: SCNMaterial = {
    let mat = SCNMaterial()
    mat.diffuse.contents = UIColor.green.withAlphaComponent(0.5)
    mat.lightingModel = .constant
    return mat
}()

你再也无法透过圆柱体看到绿色的墙壁了。相反,你透过气缸看到黑色背景

enter image description here

在某些旋转角度,您可以透过圆柱体(本例中的右壁圆柱体)看到绿色

enter image description here

游乐场

这是复制该问题的完整 Playground 代码。

import UIKit
import SceneKit
import PlaygroundSupport
import SceneKit.ModelIO

// MARK: Set up Scene
let scene = SCNScene()

var sceneView: SCNView = {
    let sv = SCNView(frame: CGRect(x: 0, y: 0, width: 800, height: 800))
    sv.autoenablesDefaultLighting = false
    sv.allowsCameraControl = true
    sv.backgroundColor = .black
    sv.scene = scene
    return sv
}()

var cameraNode: SCNNode = {
    let n = SCNNode()
    n.camera = SCNCamera()
    n.camera?.contrast = 0.0
    n.camera?.wantsHDR = false
    n.position = SCNVector3(x: 0, y: 0, z: 10)
    //n.addChildNode(omniLightNode)
    return n
}()

var ambientLightNode: SCNNode = {
    let n = SCNNode()
    n.light = SCNLight()
    n.light!.type = SCNLight.LightType.ambient
    n.light!.intensity = 100
    return n
}()

private var omniLightNode: SCNNode = {
    let n = SCNNode()
    n.light = SCNLight()
    n.light!.type = SCNLight.LightType.directional
    n.light!.color = UIColor.white
    n.position = SCNVector3(x: 0, y: 10, z: 0)
    n.light!.intensity = 800
    return n
}()

scene.rootNode.addChildNode(omniLightNode)
scene.rootNode.addChildNode(ambientLightNode)
scene.rootNode.addChildNode(cameraNode)

PlaygroundPage.current.liveView = sceneView

// MARK: - Mesh
let vertices: [SCNVector3] = [
    // back square
    SCNVector3(-1, -1,  0),
    SCNVector3( 1, -1,  0),
    SCNVector3( 1,  1,  0),
    SCNVector3(-1,  1,  0),
    
    // right wall
    SCNVector3(1,  -1,  0),
    SCNVector3(1,  -1,  2),
    SCNVector3(1,   1,  2),
    SCNVector3(1,   1,  0)
]
let vertexSource = SCNGeometrySource(vertices: vertices)

let indices: [Int32] = [
    0,1,2,
    0,2,3,
    
    4,5,6,
    4,6,7
]
let indexElement = SCNGeometryElement(
    indices: indices,
    primitiveType: .triangles
)

let textures: [CGPoint] = [
    CGPoint(x: 0, y: 0),
    CGPoint(x: 0, y: 1),
    CGPoint(x: 1, y: 1),
    CGPoint(x: 1, y: 0),
    
    CGPoint(x: 0, y: 0),
    CGPoint(x: 0, y: 1),
    CGPoint(x: 1, y: 1),
    CGPoint(x: 1, y: 0)
]
let textureSource = SCNGeometrySource(textureCoordinates: textures)
let meshGeometry = SCNGeometry(
    sources: [vertexSource, textureSource],
    elements: [indexElement]
)


var meshMaterial: SCNMaterial = {
    let mat = SCNMaterial()
    mat.diffuse.contents = UIColor.green.withAlphaComponent(0.5) // <-- set alpha to 1.0 
    mat.lightingModel = .constant
    return mat
}()

meshGeometry.materials = [meshMaterial]
let meshNode = SCNNode(geometry: meshGeometry)
meshNode.position = SCNVector3(0, 0, 0)

// MARK: Cylinders

// Define a Node to hold the cylinders
let shapeNode = SCNNode()
shapeNode.position = SCNVector3(0, 0, 0)

let cylinderBack = SCNNode(
    geometry: SCNCylinder(
        radius: 0.1,
        height: 1.0
    )
)

let cylinderRight = SCNNode(
    geometry: SCNCylinder(
        radius: 0.1,
        height: 1.0
    )
)

let cylinderMaterial: SCNMaterial = {
    let mat = SCNMaterial()
    mat.lightingModel = .physicallyBased
    mat.diffuse.contents = UIColor.red
    mat.roughness.contents = 0.8
    mat.metalness.contents = 0.4
    return mat
}()

cylinderBack.geometry?.materials = [cylinderMaterial]
cylinderBack.position = SCNVector3(0, 0, 0.05)

cylinderRight.geometry?.materials = [cylinderMaterial]
cylinderRight.position = SCNVector3(1, 0, 1)

// Set Cylinders opacity
shapeNode.opacity = 0.3


sceneView.scene?.rootNode.addChildNode(meshNode)
sceneView.scene?.rootNode.addChildNode(shapeNode)

shapeNode.addChildNode(cylinderBack)
shapeNode.addChildNode(cylinderRight)
swift scenekit transparency scnnode
1个回答
0
投票

问题在于渲染顺序,这对于实现正确的透明度非常重要。有很多方法可以解决这个问题,一个简单的选择是将几何图形设计为不相互重叠,这使得排序变得困难。或者使用

renderingOrder

设置手动渲染顺序

有一篇文章详细讨论了这个主题。 https://stackoverflow.com/a/60840898/409315

© www.soinside.com 2019 - 2024. All rights reserved.