【问题标题】:How to use SCNTechnique to create a "masked" portal effect in SceneKit / ARKit?如何使用 SCNTechnique 在 SceneKit / ARKit 中创建“蒙版”门户效果?
【发布时间】:2019-02-28 11:29:06
【问题描述】:

我正在努力思考如何将 SCNTechnique 与 Scenekit 结合使用。

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

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

关于 SCNTechnique 的资源和教程很少

【问题讨论】:

  • 您必须使用 SCNTechnique 吗?基本上你要问的是在看门的时候遮挡除门以外的某些部分?
  • @BlackMirrorz,我想遮挡它,但当你走进门户时,它也会切换,你周围的一切都是可见的。似乎有一种方法可以使用遮罩层来做到这一点,但它不会给你同样的效果,因为你可以穿过被遮罩的墙壁
  • 在 Unity 中使用 Stencil 测试完成了同样的事情,我认为您需要考虑在 ARCamera 和 A SceneKit 相机之间切换。不幸的是,我不知道如何快速做到这一点 :( 虽然有兴趣知道如何。如果您想要一个仅使用标准遮挡的基本示例,我可以向您展示一个简单的示例。
  • @BlackMirrorz,我很想看一个例子,谢谢!
  • 您最终使用了 SCNTechnique @mikehobi 吗?我也想做

标签: ios shader scenekit arkit scntechnique


【解决方案1】:

正如上面的 cmets 中提到的,我不确定如何使用 Stencil Tests 实现 occlusion 效果,正如我们所知,在 Unity 中很容易做到(我使用这个术语非常松散)。

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

Rendering Order只是指:

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

其中SCNNodes 渲染顺序较大,最后渲染,反之亦然。

为了使对象几乎肉眼不可见,我们需要将SCNMaterialtransparency 值设置为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 的很好的教程,它也对你有用...

【讨论】:

  • 感谢这个例子。不幸的是,这不允许我完全做我想做的事。拥有一个不仅仅是立方体的门户是我所希望的,尤其是有一个无限的天空盒。我想我可能需要更多地研究着色器来实现我想要的。谢谢!
  • 别担心 :) 看看你的进展会很有趣 :)
  • 是否有可能在不编码但使用 SceneKit 3d 编辑器的情况下实现相同的效果?我想下载一个房间的模型并通过门户效果访问它
猜你喜欢
  • 2018-12-25
  • 1970-01-01
  • 1970-01-01
  • 2017-12-11
  • 2018-01-25
  • 2021-12-01
  • 2022-10-25
  • 2018-09-01
  • 1970-01-01
相关资源
最近更新 更多