Как использовать SCNTechnique для создания «замаскированного» портального эффекта в SceneKit / ARKit? - PullRequest
0 голосов
/ 25 сентября 2018

Я пытаюсь понять, как использовать SCNTechnique со Scenekit.

Эффект, который я пытаюсь создать, может быть легко достигнут в Unity, добавив пользовательский шейдер к двум материалам, создав объектыс «фильтрованным» шейдером, чтобы быть видимым только тогда, когда он виден через другой шейдер (портал).Я следовал этому руководству, чтобы создать его в Unity: https://www.youtube.com/watch?v=b9xUO0zHNXw

Я пытаюсь добиться того же эффекта в SceneKit, но я не уверен, как применить проходы.Я смотрю на SCNTechnique, потому что у него есть опции для stencilStates, но я не уверен, что это сработает.

Существует очень мало ресурсов и учебных пособий по SCNTechnique

1 Ответ

0 голосов
/ 25 сентября 2018

Как уже упоминалось в комментариях выше, я не уверен, как достичь эффекта occlusion с использованием Stencil Tests, который, как мы знаем, довольно (и я использую этот термин очень свободно) легко сделать в Unity.

Сказав это, мы можем достичь аналогичного эффекта в Swift, используя t ransparency, а rendering order.

Rendering Order просто означает:

Порядок отображения содержимого узла относительно других узлов.

При этом SCNNodes с большим порядком рендеринга отображается последним, и наоборот.

В порядкечтобы сделать объект практически невидимым невооруженным глазом, нам нужно было бы установить значение transparency для SCNMaterial на значение, такое как 0.0000001.

Так как бы мы поступили об этом?

В этом очень простом примере, который является просто дверью портала и двумя стенами, мы можем сделать что-то вроде этого (что достаточно легко приспособить к чему-то более существенному и эстетически приятному):

Примерполностью прокомментирован, поэтому должно быть легко понять, чтомы делаем.

/// Generates A Portal Door And Walls Which Can Only Be Seen From Behind e.g. When Walking Through The Portsal
///
/// - Returns: SCNNode
func portalNode() -> SCNNode{

    //1. Create An SCNNode To Hold Our Portal
    let portal = SCNNode()

    //2. Create The Portal Door
    let doorFrame = SCNNode()

    //a. Create The Top Of The Door Frame
    let doorFrameTop = SCNNode()
    let doorFrameTopGeometry = SCNPlane(width: 0.55, height: 0.1)
    doorFrameTopGeometry.firstMaterial?.diffuse.contents = UIColor.black
    doorFrameTopGeometry.firstMaterial?.isDoubleSided = true
    doorFrameTop.geometry = doorFrameTopGeometry
    doorFrame.addChildNode(doorFrameTop)
    doorFrameTop.position = SCNVector3(0, 0.45, 0)

    //b. Create The Left Side Of The Door Frame
    let doorFrameLeft = SCNNode()
    let doorFrameLeftGeometry = SCNPlane(width: 0.1, height: 1)
    doorFrameLeftGeometry.firstMaterial?.diffuse.contents = UIColor.black
    doorFrameLeftGeometry.firstMaterial?.isDoubleSided = true
    doorFrameLeft.geometry = doorFrameLeftGeometry
    doorFrame.addChildNode(doorFrameLeft)
    doorFrameLeft.position = SCNVector3(-0.25, 0, 0)

    //c. Create The Right Side Of The Door Frame
    let doorFrameRight = SCNNode()
    let doorFrameRightGeometry = SCNPlane(width: 0.1, height: 1)
    doorFrameRightGeometry.firstMaterial?.diffuse.contents = UIColor.black
    doorFrameRightGeometry.firstMaterial?.isDoubleSided = true
    doorFrameRight.geometry = doorFrameRightGeometry
    doorFrame.addChildNode(doorFrameRight)
    doorFrameRight.position = SCNVector3(0.25, 0, 0)

    //d. Add The Portal Door To The Portal And Set Its Rendering Order To 200 Meaning It Will Be Rendered After Our Masks
    portal.addChildNode(doorFrame)
    doorFrame.renderingOrder = 200
    doorFrame.position = SCNVector3(0, 0, -1)

    //3. Create The Left Wall Enclosure To Hold Our Wall And The Occlusion Node
    let leftWallEnclosure = SCNNode()

    //a. Create The Left Wall And Set Its Rendering Order To 200 Meaning It Will Be Rendered After Our Masks
    let leftWallNode = SCNNode()
    let leftWallMainGeometry = SCNPlane(width: 0.5, height: 1)
    leftWallNode.geometry = leftWallMainGeometry
    leftWallMainGeometry.firstMaterial?.diffuse.contents = UIColor.red
    leftWallMainGeometry.firstMaterial?.isDoubleSided = true
    leftWallNode.renderingOrder = 200

    //b. Create The Left Wall Mask And Set Its Rendering Order To 10 Meaning It Will Be Rendered Before Our Walls
    let leftWallMaskNode = SCNNode()
    let leftWallMaskGeometry = SCNPlane(width: 0.5, height: 1)
    leftWallMaskNode.geometry = leftWallMaskGeometry
    leftWallMaskGeometry.firstMaterial?.diffuse.contents = UIColor.blue
    leftWallMaskGeometry.firstMaterial?.isDoubleSided = true
    leftWallMaskGeometry.firstMaterial?.transparency = 0.0000001
    leftWallMaskNode.renderingOrder = 10
    leftWallMaskNode.position = SCNVector3(0, 0, 0.001)

    //c. Add Our Wall And Mask To The Wall Enclosure
    leftWallEnclosure.addChildNode(leftWallMaskNode)
    leftWallEnclosure.addChildNode(leftWallNode)

    //4. Add The Left Wall Enclosure To Our Portal
    portal.addChildNode(leftWallEnclosure)
    leftWallEnclosure.position = SCNVector3(-0.55, 0, -1)

    //5. Create The Left Wall Enclosure
    let rightWallEnclosure = SCNNode()

    //a. Create The Right Wall And Set Its Rendering Order To 200 Meaning It Will Be Rendered After Our Masks
    let rightWallNode = SCNNode()
    let rightWallMainGeometry = SCNPlane(width: 0.5, height: 1)
    rightWallNode.geometry = rightWallMainGeometry
    rightWallMainGeometry.firstMaterial?.diffuse.contents = UIColor.red
    rightWallMainGeometry.firstMaterial?.isDoubleSided = true
    rightWallNode.renderingOrder = 200

    //b. Create The Right Wall Mask And Set Its Rendering Order To 10 Meaning It Will Be Rendered Before Our Walls
    let rightWallMaskNode = SCNNode()
    let rightWallMaskGeometry = SCNPlane(width: 0.5, height: 1)
    rightWallMaskNode.geometry = rightWallMaskGeometry
    rightWallMaskGeometry.firstMaterial?.diffuse.contents = UIColor.blue
    rightWallMaskGeometry.firstMaterial?.isDoubleSided = true
    rightWallMaskGeometry.firstMaterial?.transparency = 0.0000001
    rightWallMaskNode.renderingOrder = 10
    rightWallMaskNode.position = SCNVector3(0, 0, 0.001)

    //c. Add Our Wall And Mask To The Wall Enclosure
    rightWallEnclosure.addChildNode(rightWallMaskNode)
    rightWallEnclosure.addChildNode(rightWallNode)

    //6. Add The Left Wall Enclosure To Our Portal
    portal.addChildNode(rightWallEnclosure)
    rightWallEnclosure.position = SCNVector3(0.55, 0, -1)

    return portal
}

Что можно проверить следующим образом:

 let portal = portalNode()
 portal.position = SCNVector3(0, 0, -1.5)
 self.sceneView.scene.rootNode.addChildNode(portal)

Надеюсь, что это указывает вам правильное направление ...

К вашему сведениюхороший урок от Ray Wenderlich , который также будет вам полезен ...

...