ARKit 镜像/翻转相机层

Posted

技术标签:

【中文标题】ARKit 镜像/翻转相机层【英文标题】:ARKit mirror/flip camera layer 【发布时间】:2019-05-13 09:18:30 【问题描述】:

我制作了一个 iPad ARKit 应用程序,它可以在地板上显示 3D 对象,效果很好,喜欢 ARKit!然而,iPad 将通过 HDMI 连接到电视,这样人们就可以在电视上看到除了物体之外的自己。我现在遇到的问题是视频镜像在电视上,我无法找到特定的图层或设置翻转视频流和/或 ARConfig ......任何帮助将不胜感激,或者是甚至可以在不影响性能的情况下这样做吗?

P.S 它在 Swift 中 :)

更新 1:我已经像这样镜像了 sceneView sceneView.transform = CGAffineTransform(scaleX: -1, y: 1) 但这似乎对性能有相当大的影响......

提前致谢。

【问题讨论】:

【参考方案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
    

导致:

【讨论】:

以上是关于ARKit 镜像/翻转相机层的主要内容,如果未能解决你的问题,请参考以下文章

镜像翻转

利用OpenCV的flip()函数实现图像的水平镜像(水平翻转)垂直镜像(垂直翻转)

Androidandroid镜像翻转

镜像命令演示使文字不翻转

图像镜像翻转

Swift - 实现图片(UIImage)的水平翻转(镜像),垂直翻转