ARKit слой зеркала / флип камеры - PullRequest
0 голосов
/ 13 мая 2019

Я сделал приложение для iPad ARKit, которое показывает 3D-объект на полу, и оно прекрасно работает, любите ARKit!Тем не менее, iPad будет подключен к телевизору через HDMI, чтобы люди могли видеть себя на телевизоре помимо объекта.Проблема, с которой я столкнулся сейчас, заключается в том, что видео зеркально отображается на телевизоре, и я не могу найти определенный слой или установить перевернутый видеопоток и / или ARConfig ... любая помощь будет принята с благодарностью, или это так?даже возможно ли это сделать без особого влияния на производительность?

PS это в Swift :)

Обновление 1: я отразил sceneView примерно так sceneView.transform = CGAffineTransform(scaleX: -1, y: 1), но, похоже, это довольновлияние на производительность ...

Заранее спасибо.

1 Ответ

1 голос
/ 14 мая 2019

Этого можно добиться, используя 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);
}

Вы можете создать SCNTechnique, предварительно создав определение метода в файле .plist.Здесь вы указываете проходы, шейдеры, цели ввода и вывода и последовательность.В этом случае определение довольно простое:

<?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
    }
}

В результате:

Mirrored Camera

...