本文介绍了如何使用 SCNTechnique 创建一个“蒙面"SceneKit/ARKit 中的门户效果?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在思考如何将 SCNTechnique 与 Scenekit 结合使用.

I'm trying to wrap my head around how to use SCNTechnique with Scenekit.

通过向两种材质添加自定义着色器,可以在 Unity 中轻松实现我尝试创建的效果,使具有过滤"着色器的对象仅在通过另一个着色器(门户)看到时才可见.我已经按照本教程在 Unity 中创建了这个:https://www.youtube.com/看?v=b9xUO0zHNXw

The effect I'm trying to create can easily be achieved in Unity by adding a custom shader to two materials, making objects with the "filtered" shader to only be visible when it is seen through the other shader (the portal). I've followed this tutorial to create this in Unity: https://www.youtube.com/watch?v=b9xUO0zHNXw

我正在尝试在 SceneKit 中实现相同的效果,但我不确定如何应用传递.我正在查看 SCNTechnique,因为它有用于 stencilStates 的选项,但我不确定这是否可行.

I'm trying to achieve the same effect in SceneKit, but I'm not sure how to apply the passes. I'm looking at SCNTechnique because it has options for stencilStates, but I'm not sure if this will work.

关于 SCNTechnique 的资源和教程很少

There are very little resources and tutorials on SCNTechnique

推荐答案

正如上面评论中提到的,我不知道如何使用 Stencil Testsocclusion 效果> 正如我们所知,这在 Unity 中相当容易(我非常宽松地使用该术语).

As mentioned in the comments above, I am not sure how to achieve an occlusion effect using Stencil Tests which as we know are fairly (and I use that term very loosely) easy to do in Unity.

话虽如此,我们可以在 Swift 中使用 transparencyrendering order 实现类似的效果.

Having said this, we can achieve a similar effect in Swift using transparency, and rendering order.

Rendering Order 简单地指:

节点的内容相对于其他节点的绘制顺序节点.

其中具有较大渲染顺序的 SCNNodes 最后渲染,反之亦然.

Whereby SCNNodes with a larger rendering order are rendered last and vice versa.

为了使物体几乎肉眼不可见,我们需要将 SCNMaterialtransparency 值设置为诸如 0.0000001.

In order to make an object virtually invisible to the naked eye we would need to set the transparency value of an SCNMaterial to a value such as 0.0000001.

那么我们将如何解决这个问题?

So how would we go about this?

在这个非常基本的例子中,它只是一个门户门和两堵墙,我们可以做这样的事情(这很容易适应更实质和更美观的东西):

In this very basic example which is simply a portal door, and two walls we can do something like this (which is easy enough to adapt into something more substantial and aesthetically pleasing):

该示例已完全注释,因此应该很容易理解我们在做什么.

The example is fully commented so it should be easy to understand what we are doing.

/// 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)

希望它为您指明正确的方向...

Hope it points you in the right direction...

仅供参考,这里有一个很好的教程,来自 Ray Wenderlich 这对你也有用...

FYI there is a good tutorial here from Ray Wenderlich which will also be of use to you...

这篇关于如何使用 SCNTechnique 创建一个“蒙面"SceneKit/ARKit 中的门户效果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 00:20