Darken/Lighten ARKit 摄像头在物体后面馈送
Darken/Lighten ARKit camera feed behind objects
我目前正在做一个 ARKit 项目,我想在这个项目中使实际的摄像头画面变暗,以便 3D 场景中的对象更加突出。
目前我找到的 2 个解决方案:
A) 手动将 CIFilter 应用于相机帧并将其设置为 SceneKit 场景的背景图像,如 this SO post 中的回答
这里的问题是 fps 显着降低。
B) 像这样设置背景颜色:
sceneView.scene.background.contents = UIColor(white: 0.0, alpha: 0.2)
遗憾的是,alpha <1 的颜色仍然是不透明的,所以无论我设置什么 alpha,我都看不到任何相机画面。
谁能想出一个不同的技巧来使相机画面变暗?
你的选项 B 不成立有两个原因:
- 场景视图是不透明的,所以它后面没有任何东西可以混合部分透明的背景颜色。
sceneView.scene.background
是实际显示相机图像的颜色,因此如果您将其设置为某种颜色,您将不再显示相机图像。
您可能会考虑的其他一些选项(大部分未经测试):
根据您链接的答案,使用 SCNTechnique
设置 multipass 渲染。在第一遍中,使用 excludeCategoryMask
(和您的场景内容)渲染整个场景设置为只渲染背景,使用使所有像素变暗(或模糊或其他)的着色器。在第二遍中,仅渲染您想要在没有该着色器的情况下出现的节点(使用简单的直通着色器)。
保留选项 B,但使场景视图不透明。将视图的 backgroundColor
(不是场景的background
)设置为纯色,并将场景background
的transparency
设置为淡出该颜色的相机画面。
使用几何为您的场景创建 "physical" 背景 — 例如一个 SCNPlane
大尺寸,作为相机的子级放置在比任何其他场景内容远得多的固定距离处。设置飞机的背景颜色和透明度。
使用多个视图 — ARSCNView
,不透明且背景清晰,另一个(不一定是 SceneKit 视图)只显示相机画面。扰乱其他视图(或放入其他有趣的东西,如 UIVisualEffectView
)以遮挡相机画面。
File a bug with Apple 关于 sceneView.background
没有获得节点和材质获得的全套着色自定义选项(过滤器、着色器修改器、完整着色器程序)等,没有这些自定义背景比自定义场景的其他方面要困难得多。
对于那些想要实施 rickster 选项的人"Use geometry to create a "这里是我的代码(它的平面和透明度在 .scnassets 中制作)"Use geometry to create a "物理“场景背景”
guard let backgroundPlane = sceneView.scene.rootNode.childNode(withName: "background", recursively: false) else { return }
backgroundPlane.removeFromParentNode()
backgroundPlane.position = SCNVector3Make(0, 0, -2)
sceneView.pointOfView?.addChildNode(backgroundPlane)
我通过使用 SCNSphere
几何体创建 SCNNode
并使用 ARSCNView.pointOfView
.
将其连接到相机来实现此效果
override func viewDidLoad() {
super.viewDidLoad()
let sphereFogNode = makeSphereNode()
arView.pointOfView!.addChildNode(sphereFogNode)
view.addSubview(arView)
}
private static func makeSphereGeom() -> SCNSphere {
let sphere = SCNSphere(radius: 5)
let material = SCNMaterial()
material.diffuse.contents = UIColor(white: 1.0, alpha: 0.7)
material.isDoubleSided = true
sphere.materials = [material]
return sphere
}
private static func makeSphereNode() -> SCNNode {
SCNNode(geometry: makeSphereGeom())
}
剪裁外球体
这会使相机和球体边界外的任何东西变暗。命中测试 (ARFrame.hitTest
) 不考虑球体边界。您可以从球体外部接收结果。
通过球体的不透明度可以看到球体之外的事物。好像不透明的东西在球体外面也会变得透明
白色部分是球体内部的平面,灰色部分是球体外部的平面。该平面是纯白色且不透明的。我尝试使用 SCNScene.fog*
将 SceneKit 图形剪裁到球体之外,但似乎雾并没有遮挡渲染的内容,只是影响了它的外观。 SCNCamera.zFar
也不起作用,因为它根据 Z 距离进行剪辑,而不是根据相机和目标之间的直线距离进行剪辑。
只要让你的球体足够大,一切都会很好。
我目前正在做一个 ARKit 项目,我想在这个项目中使实际的摄像头画面变暗,以便 3D 场景中的对象更加突出。
目前我找到的 2 个解决方案:
A) 手动将 CIFilter 应用于相机帧并将其设置为 SceneKit 场景的背景图像,如 this SO post 中的回答 这里的问题是 fps 显着降低。
B) 像这样设置背景颜色:
sceneView.scene.background.contents = UIColor(white: 0.0, alpha: 0.2)
遗憾的是,alpha <1 的颜色仍然是不透明的,所以无论我设置什么 alpha,我都看不到任何相机画面。
谁能想出一个不同的技巧来使相机画面变暗?
你的选项 B 不成立有两个原因:
- 场景视图是不透明的,所以它后面没有任何东西可以混合部分透明的背景颜色。
sceneView.scene.background
是实际显示相机图像的颜色,因此如果您将其设置为某种颜色,您将不再显示相机图像。
您可能会考虑的其他一些选项(大部分未经测试):
根据您链接的答案,使用
SCNTechnique
设置 multipass 渲染。在第一遍中,使用excludeCategoryMask
(和您的场景内容)渲染整个场景设置为只渲染背景,使用使所有像素变暗(或模糊或其他)的着色器。在第二遍中,仅渲染您想要在没有该着色器的情况下出现的节点(使用简单的直通着色器)。保留选项 B,但使场景视图不透明。将视图的
backgroundColor
(不是场景的background
)设置为纯色,并将场景background
的transparency
设置为淡出该颜色的相机画面。使用几何为您的场景创建 "physical" 背景 — 例如一个
SCNPlane
大尺寸,作为相机的子级放置在比任何其他场景内容远得多的固定距离处。设置飞机的背景颜色和透明度。使用多个视图 —
ARSCNView
,不透明且背景清晰,另一个(不一定是 SceneKit 视图)只显示相机画面。扰乱其他视图(或放入其他有趣的东西,如UIVisualEffectView
)以遮挡相机画面。File a bug with Apple 关于
sceneView.background
没有获得节点和材质获得的全套着色自定义选项(过滤器、着色器修改器、完整着色器程序)等,没有这些自定义背景比自定义场景的其他方面要困难得多。
对于那些想要实施 rickster 选项的人"Use geometry to create a "这里是我的代码(它的平面和透明度在 .scnassets 中制作)"Use geometry to create a "物理“场景背景”
guard let backgroundPlane = sceneView.scene.rootNode.childNode(withName: "background", recursively: false) else { return }
backgroundPlane.removeFromParentNode()
backgroundPlane.position = SCNVector3Make(0, 0, -2)
sceneView.pointOfView?.addChildNode(backgroundPlane)
我通过使用 SCNSphere
几何体创建 SCNNode
并使用 ARSCNView.pointOfView
.
override func viewDidLoad() {
super.viewDidLoad()
let sphereFogNode = makeSphereNode()
arView.pointOfView!.addChildNode(sphereFogNode)
view.addSubview(arView)
}
private static func makeSphereGeom() -> SCNSphere {
let sphere = SCNSphere(radius: 5)
let material = SCNMaterial()
material.diffuse.contents = UIColor(white: 1.0, alpha: 0.7)
material.isDoubleSided = true
sphere.materials = [material]
return sphere
}
private static func makeSphereNode() -> SCNNode {
SCNNode(geometry: makeSphereGeom())
}
剪裁外球体
这会使相机和球体边界外的任何东西变暗。命中测试 (ARFrame.hitTest
) 不考虑球体边界。您可以从球体外部接收结果。
通过球体的不透明度可以看到球体之外的事物。好像不透明的东西在球体外面也会变得透明
白色部分是球体内部的平面,灰色部分是球体外部的平面。该平面是纯白色且不透明的。我尝试使用 SCNScene.fog*
将 SceneKit 图形剪裁到球体之外,但似乎雾并没有遮挡渲染的内容,只是影响了它的外观。 SCNCamera.zFar
也不起作用,因为它根据 Z 距离进行剪辑,而不是根据相机和目标之间的直线距离进行剪辑。
只要让你的球体足够大,一切都会很好。