问题描述
我正在思考如何将 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 Tests
occlusion 效果> 正如我们所知,这在 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
中使用 transparency
和 rendering 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.
为了使物体几乎肉眼不可见,我们需要将 SCNMaterial
的 transparency
值设置为诸如 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 中的门户效果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!