Je vais vous montrer comment utiliser ARKit et Metal pour vous serrer la main.
La finition ressemble à ceci.
Utilisez l'Occlusion de personnes d'ARKit.
People Occlusion vous donne une texture de masque humanoïde qui déforme le masque et l'image de la caméra en même temps pour obtenir une image composite déformée. On a l'impression de couper tout en étant déformé.
Vous pouvez obtenir une image comme celle-ci (elle est plus déformée que la vidéo pour plus de clarté)
Vous pouvez réaliser la vidéo ci-dessus en superposant l'image de la main déformée et l'image d'origine.
** 1. Obtenez l'échantillon officiel d'Apple **
L'exemple officiel d'Apple décrit le processus d'obtention d'une texture de masque humanoïde à l'aide de l'Occlusion de personnes, donc j'écrirai sur cette base.
Effecting People Occlusion in Custom Renderers
** 2. Passez le temps écoulé au shader **
Pour le faire balancer, il faut donner le temps écoulé à la formule de transformation.
Déclarez la structure à passer au shader.
Renderer.swift
struct Uniforms {
var time: Float = 0
}
Ensuite, déclarez les variables de gestion du temps écoulé et de l'heure de début.
Renderer.swift
class Renderer {
var uniforms = Uniforms()
private var startDate: Date = Date()
var uniformsBuffer: MTLBuffer! //Tampon à passer au shader
Ensuite, dans la méthode compositeImagesWithEncoder qui transmet les informations au shader, nous passerons ensemble le temps écoulé.
Renderer.swift
uniforms.time = time
uniformsBuffer = device.makeBuffer(bytes: &uniforms, length: MemoryLayout<Uniforms>.stride, options: [])
uniformsBuffer.label = "UniformsBuffer"
Préparez la même structure côté shader que côté Swift et recevez-la comme argument de la fonction. Le nom de l'argument est myUniforms.
Shaders.metal
struct Uniforms {
float time;
};
fragment half4 compositeImageFragmentShader(CompositeColorInOut in [[ stage_in ]],
texture2d<float, access::sample> capturedImageTextureY [[ texture(0) ]],
texture2d<float, access::sample> capturedImageTextureCbCr [[ texture(1) ]],
texture2d<float, access::sample> sceneColorTexture [[ texture(2) ]],
depth2d<float, access::sample> sceneDepthTexture [[ texture(3) ]],
texture2d<float, access::sample> alphaTexture [[ texture(4) ]],
texture2d<float, access::sample> dilatedDepthTexture [[ texture(5) ]],
constant SharedUniforms &uniforms [[ buffer(kBufferIndexSharedUniforms) ]],
constant Uniforms &myUniforms [[buffer(kBufferIndexMyUniforms)]])
{
** 3. Réécrire le shader **
Dans l'exemple officiel, réécrivez la fonction compositeImageFragmentShader de Shaders.metal comme suit.
Shaders.metal
@@ -219,8 +397,9 @@ fragment half4 compositeImageFragmentShader(CompositeColorInOut in [[ stage_in ]
half4 sceneColor = half4(sceneColorTexture.sample(s, sceneTexCoord));
float sceneDepth = sceneDepthTexture.sample(s, sceneTexCoord);
+ float2 modifier = float2(sin(cameraTexCoord.y + myUniforms.time*5)*0.2, 0); //Formule de transformation
half4 cameraColor = half4(rgb);
- half alpha = half(alphaTexture.sample(s, cameraTexCoord).r);
+ half alpha = half(alphaTexture.sample(s, cameraTexCoord + modifier).r); //Transformez le masque humanoïde
half showOccluder = 1.0;
@@ -233,8 +412,11 @@ fragment half4 compositeImageFragmentShader(CompositeColorInOut in [[ stage_in ]
showOccluder = (half)step(dilatedDepth, sceneDepth); // forwardZ case
}
+ float2 displacedUV = sceneTexCoord + modifier; //Transformez l'image
- half4 occluderResult = mix(sceneColor, cameraColor, alpha);
+ half4 displacedCol = half4(sceneColorTexture.sample(s, displacedUV)); //Acquisition d'une image humanoïde déformée
+ half4 occluderResult = mix(sceneColor, displacedCol, alpha); //Combinez l'image déformée avec l'image d'origine
half4 mattingResult = mix(sceneColor, occluderResult, showOccluder);
return mattingResult;
}
C'est là que ça compte.
Shaders.metal
float2 modifier = float2(sin(cameraTexCoord.y + myUniforms.time*5)*0.2, 0); //Formule de transformation
La coordonnée y de l'image d'entrée plus le temps écoulé est donnée à la fonction sin, et elle est affectée au modificateur. Le modificateur est une variable à ajouter à la caméra ou au masque humanoïde, et cette fois la formule n'est contenue que dans x, donc seule la direction de l'axe x fluctuera.
De plus, comme la vidéo réelle fluctue dans le sens vertical, cela contredit la formule ci-dessus, mais c'est parce que l'iPhone enregistré en mode paysage a été converti verticalement avec un logiciel de retouche d'image.
J'ai écrit sur la transformation de la figure dans cet article, alors veuillez également le voir ici.
Comment transformer des figurines ARKit et SceneKit avec un shader Metal
J'ai également mis en ligne une vidéo sur Youtube. Vidéo terminée (Youtube)
Note publie régulièrement sur le développement iOS, alors suivez-nous. https://note.com/tokyoyoshida
Nous envoyons des conseils simples sur Twitter. https://twitter.com/jugemjugemjugem
Recommended Posts