ARKit mirror/flip 相机层
ARKit mirror/flip camera layer
我制作了一个 iPad ARKit 应用程序,可以在地板上显示 3D 对象,效果很好,喜欢 ARKit!然而,iPad 将通过 HDMI 连接到电视,这样人们就可以在电视上看到除了物体之外的自己。我现在遇到的问题是视频在电视上镜像,我无法找到特定层或设置翻转视频流 and/or ARConfig ...任何帮助将不胜感激,或者是否有可能在不影响性能的情况下这样做?
P.S 它在 Swift :)
更新 1:我已经像这样镜像了 sceneView
sceneView.transform = CGAffineTransform(scaleX: -1, y: 1)
但这似乎对性能有相当大的影响...
提前致谢。
您可以使用 SCNTechnique 和金属着色器实现此目的。
它的要点是创建一个顶点着色器,创建一个全屏四边形并镜像 u
坐标:
vertex VertexOut mirrorVertex(VertexIn in [[stage_in]])
{
VertexOut out;
out.position = in.position;
// Mirror the U coordinate: (1.0 - ..)
out.uv = float2(1.0 - (in.position.x + 1.0) * 0.5, 1.0 - (in.position.y + 1.0) * 0.5);
return out;
};
片段着色器是一个简单的直通着色器:
fragment float4 mirrorFragment(VertexOut vert [[stage_in]],
texture2d<float, access::sample> colorSampler [[texture(0)]])
{
constexpr sampler s = sampler(coord::normalized,
address::clamp_to_edge,
filter::linear);
return colorSampler.sample( s, vert.uv);
}
您可以通过先在 .plist
文件中创建技术定义来创建 SCNTechnique
。您可以在此处指定通道、着色器、输入和输出目标以及序列。在这种情况下,定义非常简单:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>passes</key>
<dict>
<key>pass_mirror_camera</key>
<dict>
<key>draw</key>
<string>DRAW_SCENE</string>
<key>metalVertexShader</key>
<string>mirrorVertex</string>
<key>metalFragmentShader</key>
<string>mirrorFragment</string>
<key>inputs</key>
<dict>
<key>colorSampler</key>
<string>COLOR</string>
</dict>
<key>outputs</key>
<dict>
<key>color</key>
<string>COLOR</string>
</dict>
<key>draw</key>
<string>DRAW_QUAD</string>
</dict>
</dict>
<key>sequence</key>
<array>
<string>pass_mirror_camera</string>
</array>
</dict>
</plist>
您还需要创建一个包含顶点和片段着色器的金属着色器 (.metal
) 文件:
//
// MirrorShaders.metal
// MirrorCamera
//
// Created by Dennis Ippel on 14/05/2019.
// Copyright © 2019 Dennis Ippel. All rights reserved.
//
#include <metal_stdlib>
using namespace metal;
#include <SceneKit/scn_metal>
struct VertexIn
{
float4 position [[attribute(SCNVertexSemanticPosition)]];
};
struct VertexOut
{
float4 position [[position]];
float2 uv;
};
vertex VertexOut mirrorVertex(VertexIn in [[stage_in]])
{
VertexOut out;
out.position = in.position;
// Mirror the U coordinate: (1.0 - ..)
out.uv = float2(1.0 - (in.position.x + 1.0) * 0.5, 1.0 - (in.position.y + 1.0) * 0.5);
return out;
};
fragment float4 mirrorFragment(VertexOut vert [[stage_in]],
texture2d<float, access::sample> colorSampler [[texture(0)]])
{
constexpr sampler s = sampler(coord::normalized,
address::clamp_to_edge,
filter::linear);
return colorSampler.sample( s, vert.uv);
}
然后您可以将所有内容放在视图控制器中并将技术分配给您的 SCNView
实例:
if let path = Bundle.main.path(forResource: "MirrorCamera", ofType: "plist") {
if let dict = NSDictionary(contentsOfFile: path) {
let dict2 = dict as! [String : AnyObject]
let technique = SCNTechnique(dictionary:dict2)
sceneView.technique = technique
}
}
导致:
我制作了一个 iPad ARKit 应用程序,可以在地板上显示 3D 对象,效果很好,喜欢 ARKit!然而,iPad 将通过 HDMI 连接到电视,这样人们就可以在电视上看到除了物体之外的自己。我现在遇到的问题是视频在电视上镜像,我无法找到特定层或设置翻转视频流 and/or ARConfig ...任何帮助将不胜感激,或者是否有可能在不影响性能的情况下这样做?
P.S 它在 Swift :)
更新 1:我已经像这样镜像了 sceneView
sceneView.transform = CGAffineTransform(scaleX: -1, y: 1)
但这似乎对性能有相当大的影响...
提前致谢。
您可以使用 SCNTechnique 和金属着色器实现此目的。
它的要点是创建一个顶点着色器,创建一个全屏四边形并镜像 u
坐标:
vertex VertexOut mirrorVertex(VertexIn in [[stage_in]])
{
VertexOut out;
out.position = in.position;
// Mirror the U coordinate: (1.0 - ..)
out.uv = float2(1.0 - (in.position.x + 1.0) * 0.5, 1.0 - (in.position.y + 1.0) * 0.5);
return out;
};
片段着色器是一个简单的直通着色器:
fragment float4 mirrorFragment(VertexOut vert [[stage_in]],
texture2d<float, access::sample> colorSampler [[texture(0)]])
{
constexpr sampler s = sampler(coord::normalized,
address::clamp_to_edge,
filter::linear);
return colorSampler.sample( s, vert.uv);
}
您可以通过先在 .plist
文件中创建技术定义来创建 SCNTechnique
。您可以在此处指定通道、着色器、输入和输出目标以及序列。在这种情况下,定义非常简单:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>passes</key>
<dict>
<key>pass_mirror_camera</key>
<dict>
<key>draw</key>
<string>DRAW_SCENE</string>
<key>metalVertexShader</key>
<string>mirrorVertex</string>
<key>metalFragmentShader</key>
<string>mirrorFragment</string>
<key>inputs</key>
<dict>
<key>colorSampler</key>
<string>COLOR</string>
</dict>
<key>outputs</key>
<dict>
<key>color</key>
<string>COLOR</string>
</dict>
<key>draw</key>
<string>DRAW_QUAD</string>
</dict>
</dict>
<key>sequence</key>
<array>
<string>pass_mirror_camera</string>
</array>
</dict>
</plist>
您还需要创建一个包含顶点和片段着色器的金属着色器 (.metal
) 文件:
//
// MirrorShaders.metal
// MirrorCamera
//
// Created by Dennis Ippel on 14/05/2019.
// Copyright © 2019 Dennis Ippel. All rights reserved.
//
#include <metal_stdlib>
using namespace metal;
#include <SceneKit/scn_metal>
struct VertexIn
{
float4 position [[attribute(SCNVertexSemanticPosition)]];
};
struct VertexOut
{
float4 position [[position]];
float2 uv;
};
vertex VertexOut mirrorVertex(VertexIn in [[stage_in]])
{
VertexOut out;
out.position = in.position;
// Mirror the U coordinate: (1.0 - ..)
out.uv = float2(1.0 - (in.position.x + 1.0) * 0.5, 1.0 - (in.position.y + 1.0) * 0.5);
return out;
};
fragment float4 mirrorFragment(VertexOut vert [[stage_in]],
texture2d<float, access::sample> colorSampler [[texture(0)]])
{
constexpr sampler s = sampler(coord::normalized,
address::clamp_to_edge,
filter::linear);
return colorSampler.sample( s, vert.uv);
}
然后您可以将所有内容放在视图控制器中并将技术分配给您的 SCNView
实例:
if let path = Bundle.main.path(forResource: "MirrorCamera", ofType: "plist") {
if let dict = NSDictionary(contentsOfFile: path) {
let dict2 = dict as! [String : AnyObject]
let technique = SCNTechnique(dictionary:dict2)
sceneView.technique = technique
}
}
导致: