您的位置:首頁>數碼>正文

如何在iPhone X上使用ARKit進行人臉追蹤

作者:jennysluo

iPhone X前置深度攝像頭帶來了Animoji和face ID, 同時也將3D Face Tracking的介面開放給了開發者。 有幸去Cupertino蘋果總部參加了iPhone X的封閉開發, 本文主要分享一下iPhone X上使用ARKit進行人臉追蹤及3D建模的相關內容。

iPhone X前置深度攝像頭識別人臉視頻(v.qq.com/x/page/v1328x4m0md.html?)

新增介面

ARFaceTrackingConfiguration

ARFaceTrackingConfiguration利用iPhone X前置深度攝像頭識別用戶的人臉。 由於不同的AR體驗對iOS設備有不同的硬體要求, 所有ARKit配置要求iOS設備至少使用A9及以上處理器, 而face tracking更是僅在帶有前置深度攝像頭的iPhone X上才會有。 因此在進行AR配置之前, 首先我們需要確認使用者設備是否支援我們將要創建的AR體驗

ARFaceTrackingConfiguration.isSupported

對於不支援該ARKit配置的設備,

提供其它的備選方案或是降級策略也是一種不錯的解決方案。 然而如果你的app確定ARKit是其核心功能, 在info.plist裡將ARKit添加到UIRequiredDeviceCapabilities裡可以確保你的app只在支援ARKit的設備上可用。

當我們配置使用ARFaceTrackingConfiguration, session會自動添加ARFaceAnchor物件到其anchor list中。 每一個face anchor提供了包含臉部位置, 方向, 拓撲結構, 以及表情特徵等資訊。 另外, 當我們開啟isLightEstimationEnabled設置, ARKit會將檢測到的人臉作為燈光探測器以估算出的當前環境光的照射方向及亮度等資訊(詳見ARDirectionalLightEstimate物件), 這樣我們可以根據真實的環境光方向及強度去對3D模型進行照射以達到更為逼真的AR效果。

ARFrame

當我們設置為基於人臉的AR(ARFaceTrackingConfiguration), session刷新的frame裡除了包含彩色攝像頭採集的顏色資訊以外(capturedImage), 還包含了由深度攝像頭採集的深度資訊(capturedDepthData)。 其結構和iPhone7P後置雙攝採集的深度資訊一樣為AVDepthData。

當設置其它AR模式時該屬性為nil。 在iPhone X上實測效果比7P後置的深度資訊更為準確, 已經可以很好的區分人像和背景區域。

需注意的是, 深度攝像頭採樣頻率和顏色攝像頭並不一致, 因此ARFrame的capturedDepthData屬性也可能是nil。 實測下來在幀率60的情況下, 每4幀裡有1幀包含深度資訊。

ARFaceAnchor

前面說過, 當我們配置使用ARFaceTrackingConfiguration, session會自動添加ARFaceAnchor物件到其anchor list中。 每一個face anchor提供了包含臉部位置, 方向, 拓撲結構, 以及表情特徵等資訊。 比較遺憾的是, 當前版本只支援單人臉識別, 未來如果ARKit提供多人臉識別後開發者應該也能較快的進行版本升級。

人臉位置和方向

父類ARAnchor的transform屬性以一個4*4矩陣描述了當前人臉在世界坐標系的位置及方向。 我們可以使用該矩陣來放置虛擬3D模型以實現貼合到臉部的效果(如果使用SceneKit,

會有更便捷的方式來完成虛擬模型的佩戴過程, 後面會詳述)。 該變換矩陣創建了一個“人臉坐標系”以將其它模型放置到人臉的相對位置, 其原點在人頭中心(鼻子後方幾釐米處), 且為右手坐標系—x軸正方向為觀察者的右方(也就是檢測到的人臉的左方), y軸正方向延人頭向上, z軸正方向從人臉向外(指向觀察者)

人臉拓撲結構 ARFaceGeometry

ARFaceAnchor的geometry屬性封裝了人臉具體的拓撲結構資訊, 包括頂點座標、紋理座標、以及三角形索引(實測下來單個人臉包含1220個3D頂點以及2304個三角面片資訊, 精准度已經相當高了)。

有了這些資料, 我們可以實現各種貼合人臉的3D面皮—比如虛擬妝容或者紋身等。 我們也可以用其創建人臉的幾何形狀以完成對虛擬3D模型的遮擋。 如果我們使用SceneKit + Metal做渲染, 可以十分方便的通過ARSCNFaceGeometry完成人臉建模, 後面會詳細說明。

面部表情追蹤

blendShapes屬性提供了當前人臉面部表情的一個高階模型, 表示了一系列的面部特徵相對于無表情時的偏移係數。

聽起來也許有些抽象, 具體來說, 可以看到blendShapes是一個NSDictionary, 其key有多種具體的面部表情參數可選, 比如ARBlendShapeLocationMouthSmileLeft代表左嘴角微笑程度, 而ARBlendShapeLocationMouthSmileRight表示右嘴角的微笑程度。 每個key對應的value是一個取值範圍為0.0 - 1.0的浮點數, 0.0表示中立情況的取值(面無表情時), 1.0表示最大程度(比如左嘴角微笑到最大值)。 ARKit裡提供了51種非常具體的面部表情形變參數, 我們可以自行選擇採用較多的或者只是採用某幾個參數來達成我們的目標, 比如, 用“張嘴”、“眨左眼”、“眨右眼”來驅動一個卡通人物。

創建人臉AR體驗

以上介紹了一下使用ARKit Face Tracking所需要瞭解的新增介面, 下面來詳細說明如何搭建一個app以完成人臉AR的真實體驗。

創建一個ARKit應用可以選擇3種渲染框架, 分別是SceneKit, SpriteKit和Metal。對於做一個自拍類的app,SceneKit無疑是一種很好的選擇。其介面方便易用,底層使用Metal2渲染,且提供了多種材質以及光照模型,通常情況下無需自訂shader即可完成3D貼臉以及3D掛件的渲染。首先我們需要添加一個ARSCNView,設置好scene以及delegate,在viewWillAppear裡添加下面兩行代碼

ARFaceTrackingConfiguration *configuration = [ARFaceTrackingConfiguration new];[self.sceneView.session runWithConfiguration:configuration];

這樣就創建好了一個ARKit Face Tracking的場景,此時前置攝像頭已經開啟並即時檢測/追蹤人臉資訊。當檢測到人臉之後,我們可以通過delegate更新人臉anchor的函數來同步更新我們自訂的3D面皮或者3D模型。

- (void)renderer:(id )renderer willUpdateNode:(SCNNode *)node forAnchor:(ARAnchor *)anchor;- (void)renderer:(id )renderer didUpdateNode:(SCNNode *)node forAnchor:(ARAnchor *)anchor;

比如我們要放置一張京劇臉譜貼合到用戶臉上,我們可以生成一個臉譜的SCNNode

- (SCNNode *)textureMaskNode{ if (!_textureMaskNode) { _textureMaskNode = [self makeFaceGeometry:^(SCNMaterial *material) { material.fillMode = SCNFillModeFill; material.diffuse.contents = [UIImage imageNamed:@"maskImage.png"]; } fillMesh:NO]; _textureMaskNode.name = @"textureMask"; } return _textureMaskNode;}- (SCNNode*)makeFaceGeometry:(void (^)(SCNMaterial*))materialSetup fillMesh:(BOOL)fillMesh{#if TARGET_OS_SIMULATOR return [SCNNode new];#else id device = self.sceneView.device; ARSCNFaceGeometry *geometry = [ARSCNFaceGeometry faceGeometryWithDevice:device fillMesh:fillMesh]; SCNMaterial *material = geometry.firstMaterial; if(material && materialSetup) materialSetup(material); return [SCNNode nodeWithGeometry:geometry]; #endif }

注意這個fillMesh參數,如果設置為NO,生成的“蒙皮”眼睛和嘴巴區域是鏤空的,反之亦然。模型建好以後,我們需要在face anchor刷新的時候同步更新3D蒙皮的幾何資訊使其與人臉達到貼合的狀態。

- (void)renderer:(id)renderer willUpdateNode:(SCNNode *)node forAnchor:(ARAnchor *)anchor{ ARFaceAnchor *faceAnchor = (ARFaceAnchor *)anchor; if (!faceAnchor || ![faceAnchor isKindOfClass:[ARFaceAnchor class]]) { return; } if (_needRenderNode) { [node addChildNode:self.textureMaskNode]; _needRenderNode = NO; } ARSCNFaceGeometry *faceGeometry = (ARSCNFaceGeometry *)self.textureMaskNode.geometry; if( faceGeometry && [faceGeometry isKindOfClass:[ARSCNFaceGeometry class]] ) { [faceGeometry updateFromFaceGeometry:faceAnchor.geometry]; }}

這裡我們是直接將蒙皮node添加到face node作為其childNode,因而不需要對其位置資訊做額外處理就能跟隨人臉移動。如果是直接加到場景的rootNode上面,還需要同步更新其位置、方向等屬性。打上方向光之後,蒙皮顯得十分貼合立體。

SCNLight *directional = [SCNLight light];directional.type = SCNLightTypeDirectional;directional.color = [UIColor colorWithWhite:1 alpha:1.0];directional.castsShadow = YES;_directionalLightNode = [SCNNode node];_directionalLightNode.light = directional;

demo裡我們做了一個戲劇變臉效果,當用戶遮擋人臉後將其臉譜換掉。實現的原理是當用戶人臉檢測不到時記一個標誌,再次檢測到使用者人臉時將其3D蒙皮的貼圖換掉。比較坑的是,ARKit 檢測不到人臉時也並未將其node移除,因此delegate也沒有回檔

- (void)renderer:(id )renderer didRemoveNode:(SCNNode *)node forAnchor:(ARAnchor *)anchor;

那麼如何知道face tracking失敗呢?可以通過每一幀刷新的時候遍歷查找到ARAnchor,檢測其isTrackFace狀態。

- (void)session:(ARSession *)session didUpdateFrame:(ARFrame *)frame{ for (ARAnchor *anchor in frame.anchors) { if ([anchor isKindOfClass:[ARFaceAnchor class]]) { ARFaceAnchor *faceAnchor = (ARFaceAnchor *)anchor; self.isTrackFace = faceAnchor.isTracked; } }}

同樣的,我們可以在人臉node上添加其他3D模型(比如3D眼鏡)的node使其跟隨人臉移動,可以達到非常逼真的效果,SceneKit支援多種格式的模型載入,比如obj、dae等。如果使用的是dae且不是放在bundle裡面,需要提前用scntool壓縮,模型載入及動畫播放所遇到的坑此處不贅述。需要注意的是,當我們給用戶戴上3D眼鏡或帽子的時候,我們當然是希望模型的後面部分能正確的被使用者的臉給擋住以免露出馬腳。因此我們需要渲染一個用來遮擋的node並即時更新其幾何資訊,使使用者在頭歪向一邊的時候3D眼鏡的鏡架能被人臉正確遮擋。

- (SCNNode *)occlusionMaskNode{ if (!_occlusionMaskNode) { _occlusionMaskNode = [self makeFaceGeometry:^(SCNMaterial *material) { material.colorBufferWriteMask = SCNColorMaskNone; material.lightingModelName = SCNLightingModelConstant; material.writesToDepthBuffer = true; } fillMesh:YES]; _occlusionMaskNode.renderingOrder = -1; _occlusionMaskNode.name = @"occlusionMask"; } return _occlusionMaskNode;}

同樣的我們需要在face anchor刷新的時候通過updateFromFaceGeometry:更新其幾何資訊。需要注意的是,由於ARKit只對人臉區域進行建模,在3D模型設計的時候還需去掉一些不必要的部件:比如眼鏡的模型就不需要添加鏡腳,因為耳朵部分並沒有東西可以去做遮擋。

3D模型設計的時候還需去掉一些不必要的部件效果視頻(v.qq.com/x/page/b0504rzu2r5.html)

如果要做類似上面視頻中的鏡片反射效果,使用SceneKit也十分方便,只需要將鏡片的反射貼圖(SCNMaterial的reflective屬性)映射到cube map即可,支持以下4種設置方案

A horizontal stripimage where 6 * image.height == image.width

A vertical strip imagewhere image.height == 6 * image.width

A spherical projectionimage (latitude/longitude) where 2 * image.height == image.width

A NSArray of 6 images.This array must contain images of the exact same dimensions, in the followingorder, in a left-handed coordinate system: +X, -X, +Y, -Y, +Z, -Z (or Right,Left, Top, Bottom, Front, Back).

除了人臉的空間位置資訊和幾何資訊,ARKit還提供了十分精細的面部表情形變參數,用來做類似張嘴觸發是完全沒問題的,我們還可以用其實現一些有趣的效果。比如,根據臉部微笑的程度去替換3D蒙皮的diffuse貼圖,使用戶笑的時候會出現誇張的效果。

- (UIImage *)meshImageWithBlendShapes:(NSDictionary *)blendShapes{ if (self.diffuseArray.count == 0) return nil; NSUInteger _count = self.diffuseArray.count; NSNumber *smileLeft = blendShapes[ARBlendShapeLocationMouthSmileLeft]; NSNumber *smileRight = blendShapes[ARBlendShapeLocationMouthSmileRight]; CGFloat smileBlend = (smileLeft.floatValue + smileRight.floatValue) / 2; smileBlend = smileBlend - 0.1; if (smileBlend < 0.0) smileBlend = 0.0; NSUInteger index = (NSUInteger)(smileBlend * _count / 0.5); if (index > _count - 1) { index = _count - 1; } return self.diffuseArray[index];}

將幾個臉部表情係數的組合映射到一個具體的分值,可以實現face dance那樣有趣的表情模仿。還可以將其映射到3D虛擬人物的形變上以實現animoji的效果,此處開發者們可自行腦洞大開:)

拍照 & 錄製

可能是由於SceneKit原本是設計用來做遊戲渲染的框架,只提供了一個截屏的介面snapshot,拍照尚可調用,而錄製並不是特別方便。如果你計畫通過SCNRenderer 的函數

+ (instancetype)rendererWithContext:(nullable EAGLContext *)context options:(nullable NSDictionary *)options;

將其放在OpenGL context裡渲染,可以避開視頻錄製的坑,但也許會遇到更新人臉geometry等其他問題。如果採用默認的Metal方案,設置一個計時器,將snapshot獲取到的UIImage轉成pixel buffer再進行視頻編碼,很難做到每秒30幀的同步輸出。如果你的app在錄製的時候UI非常乾淨,可以採用系統錄屏框架replaykit來進行螢幕錄製;如果你想完全掌控每一幀的輸出以方便在錄製過程中加上浮水印,可以用SCNRenderer的render函數

- (void)renderAtTime:(CFTimeInterval)time viewport:(CGRect)viewport commandBuffer:(id )commandBuffer passDescriptor:(MTLRenderPassDescriptor *)renderPassDescriptor

將場景渲染到一個id物件中,通過紋理綁定的方式將其轉換為CVPixelBufferRef以完成視頻編碼。某位元朋友提醒,可以通過method swizzling的方式直接獲取CAMetalLayer的nextDrawable,甚至可以避免上訴方案錄製時產生的額外GPU開銷,有興趣的朋友可以嘗試一下。

寫在末尾

這次能有機會參加Apple的封閉開發且是如此有趣的模組,在沒有網路的情況下摸索著做出demo,接觸到了最前沿的AR相關技術,對我來說是一份非常寶貴的經歷。心懷感恩,踏步前行。

demo效果視頻(v.qq.com/x/page/p1328bmunrt.html?)

最後,附上PhxPaxos源碼的位址:(github.com/Tencent/phxpaxos)

小編的話:根據發文規範,文章內不能出現連結。因此,

()括弧內均為文章連結或下載位址,如有需求請行加上https://首碼,或者可進入騰訊雲技術社區查看該文章,進行下載。

各位大大們,想看哪方面的技術性文章,盡請留言!

SpriteKit和Metal。對於做一個自拍類的app,SceneKit無疑是一種很好的選擇。其介面方便易用,底層使用Metal2渲染,且提供了多種材質以及光照模型,通常情況下無需自訂shader即可完成3D貼臉以及3D掛件的渲染。首先我們需要添加一個ARSCNView,設置好scene以及delegate,在viewWillAppear裡添加下面兩行代碼

ARFaceTrackingConfiguration *configuration = [ARFaceTrackingConfiguration new];[self.sceneView.session runWithConfiguration:configuration];

這樣就創建好了一個ARKit Face Tracking的場景,此時前置攝像頭已經開啟並即時檢測/追蹤人臉資訊。當檢測到人臉之後,我們可以通過delegate更新人臉anchor的函數來同步更新我們自訂的3D面皮或者3D模型。

- (void)renderer:(id )renderer willUpdateNode:(SCNNode *)node forAnchor:(ARAnchor *)anchor;- (void)renderer:(id )renderer didUpdateNode:(SCNNode *)node forAnchor:(ARAnchor *)anchor;

比如我們要放置一張京劇臉譜貼合到用戶臉上,我們可以生成一個臉譜的SCNNode

- (SCNNode *)textureMaskNode{ if (!_textureMaskNode) { _textureMaskNode = [self makeFaceGeometry:^(SCNMaterial *material) { material.fillMode = SCNFillModeFill; material.diffuse.contents = [UIImage imageNamed:@"maskImage.png"]; } fillMesh:NO]; _textureMaskNode.name = @"textureMask"; } return _textureMaskNode;}- (SCNNode*)makeFaceGeometry:(void (^)(SCNMaterial*))materialSetup fillMesh:(BOOL)fillMesh{#if TARGET_OS_SIMULATOR return [SCNNode new];#else id device = self.sceneView.device; ARSCNFaceGeometry *geometry = [ARSCNFaceGeometry faceGeometryWithDevice:device fillMesh:fillMesh]; SCNMaterial *material = geometry.firstMaterial; if(material && materialSetup) materialSetup(material); return [SCNNode nodeWithGeometry:geometry]; #endif }

注意這個fillMesh參數,如果設置為NO,生成的“蒙皮”眼睛和嘴巴區域是鏤空的,反之亦然。模型建好以後,我們需要在face anchor刷新的時候同步更新3D蒙皮的幾何資訊使其與人臉達到貼合的狀態。

- (void)renderer:(id)renderer willUpdateNode:(SCNNode *)node forAnchor:(ARAnchor *)anchor{ ARFaceAnchor *faceAnchor = (ARFaceAnchor *)anchor; if (!faceAnchor || ![faceAnchor isKindOfClass:[ARFaceAnchor class]]) { return; } if (_needRenderNode) { [node addChildNode:self.textureMaskNode]; _needRenderNode = NO; } ARSCNFaceGeometry *faceGeometry = (ARSCNFaceGeometry *)self.textureMaskNode.geometry; if( faceGeometry && [faceGeometry isKindOfClass:[ARSCNFaceGeometry class]] ) { [faceGeometry updateFromFaceGeometry:faceAnchor.geometry]; }}

這裡我們是直接將蒙皮node添加到face node作為其childNode,因而不需要對其位置資訊做額外處理就能跟隨人臉移動。如果是直接加到場景的rootNode上面,還需要同步更新其位置、方向等屬性。打上方向光之後,蒙皮顯得十分貼合立體。

SCNLight *directional = [SCNLight light];directional.type = SCNLightTypeDirectional;directional.color = [UIColor colorWithWhite:1 alpha:1.0];directional.castsShadow = YES;_directionalLightNode = [SCNNode node];_directionalLightNode.light = directional;

demo裡我們做了一個戲劇變臉效果,當用戶遮擋人臉後將其臉譜換掉。實現的原理是當用戶人臉檢測不到時記一個標誌,再次檢測到使用者人臉時將其3D蒙皮的貼圖換掉。比較坑的是,ARKit 檢測不到人臉時也並未將其node移除,因此delegate也沒有回檔

- (void)renderer:(id )renderer didRemoveNode:(SCNNode *)node forAnchor:(ARAnchor *)anchor;

那麼如何知道face tracking失敗呢?可以通過每一幀刷新的時候遍歷查找到ARAnchor,檢測其isTrackFace狀態。

- (void)session:(ARSession *)session didUpdateFrame:(ARFrame *)frame{ for (ARAnchor *anchor in frame.anchors) { if ([anchor isKindOfClass:[ARFaceAnchor class]]) { ARFaceAnchor *faceAnchor = (ARFaceAnchor *)anchor; self.isTrackFace = faceAnchor.isTracked; } }}

同樣的,我們可以在人臉node上添加其他3D模型(比如3D眼鏡)的node使其跟隨人臉移動,可以達到非常逼真的效果,SceneKit支援多種格式的模型載入,比如obj、dae等。如果使用的是dae且不是放在bundle裡面,需要提前用scntool壓縮,模型載入及動畫播放所遇到的坑此處不贅述。需要注意的是,當我們給用戶戴上3D眼鏡或帽子的時候,我們當然是希望模型的後面部分能正確的被使用者的臉給擋住以免露出馬腳。因此我們需要渲染一個用來遮擋的node並即時更新其幾何資訊,使使用者在頭歪向一邊的時候3D眼鏡的鏡架能被人臉正確遮擋。

- (SCNNode *)occlusionMaskNode{ if (!_occlusionMaskNode) { _occlusionMaskNode = [self makeFaceGeometry:^(SCNMaterial *material) { material.colorBufferWriteMask = SCNColorMaskNone; material.lightingModelName = SCNLightingModelConstant; material.writesToDepthBuffer = true; } fillMesh:YES]; _occlusionMaskNode.renderingOrder = -1; _occlusionMaskNode.name = @"occlusionMask"; } return _occlusionMaskNode;}

同樣的我們需要在face anchor刷新的時候通過updateFromFaceGeometry:更新其幾何資訊。需要注意的是,由於ARKit只對人臉區域進行建模,在3D模型設計的時候還需去掉一些不必要的部件:比如眼鏡的模型就不需要添加鏡腳,因為耳朵部分並沒有東西可以去做遮擋。

3D模型設計的時候還需去掉一些不必要的部件效果視頻(v.qq.com/x/page/b0504rzu2r5.html)

如果要做類似上面視頻中的鏡片反射效果,使用SceneKit也十分方便,只需要將鏡片的反射貼圖(SCNMaterial的reflective屬性)映射到cube map即可,支持以下4種設置方案

A horizontal stripimage where 6 * image.height == image.width

A vertical strip imagewhere image.height == 6 * image.width

A spherical projectionimage (latitude/longitude) where 2 * image.height == image.width

A NSArray of 6 images.This array must contain images of the exact same dimensions, in the followingorder, in a left-handed coordinate system: +X, -X, +Y, -Y, +Z, -Z (or Right,Left, Top, Bottom, Front, Back).

除了人臉的空間位置資訊和幾何資訊,ARKit還提供了十分精細的面部表情形變參數,用來做類似張嘴觸發是完全沒問題的,我們還可以用其實現一些有趣的效果。比如,根據臉部微笑的程度去替換3D蒙皮的diffuse貼圖,使用戶笑的時候會出現誇張的效果。

- (UIImage *)meshImageWithBlendShapes:(NSDictionary *)blendShapes{ if (self.diffuseArray.count == 0) return nil; NSUInteger _count = self.diffuseArray.count; NSNumber *smileLeft = blendShapes[ARBlendShapeLocationMouthSmileLeft]; NSNumber *smileRight = blendShapes[ARBlendShapeLocationMouthSmileRight]; CGFloat smileBlend = (smileLeft.floatValue + smileRight.floatValue) / 2; smileBlend = smileBlend - 0.1; if (smileBlend < 0.0) smileBlend = 0.0; NSUInteger index = (NSUInteger)(smileBlend * _count / 0.5); if (index > _count - 1) { index = _count - 1; } return self.diffuseArray[index];}

將幾個臉部表情係數的組合映射到一個具體的分值,可以實現face dance那樣有趣的表情模仿。還可以將其映射到3D虛擬人物的形變上以實現animoji的效果,此處開發者們可自行腦洞大開:)

拍照 & 錄製

可能是由於SceneKit原本是設計用來做遊戲渲染的框架,只提供了一個截屏的介面snapshot,拍照尚可調用,而錄製並不是特別方便。如果你計畫通過SCNRenderer 的函數

+ (instancetype)rendererWithContext:(nullable EAGLContext *)context options:(nullable NSDictionary *)options;

將其放在OpenGL context裡渲染,可以避開視頻錄製的坑,但也許會遇到更新人臉geometry等其他問題。如果採用默認的Metal方案,設置一個計時器,將snapshot獲取到的UIImage轉成pixel buffer再進行視頻編碼,很難做到每秒30幀的同步輸出。如果你的app在錄製的時候UI非常乾淨,可以採用系統錄屏框架replaykit來進行螢幕錄製;如果你想完全掌控每一幀的輸出以方便在錄製過程中加上浮水印,可以用SCNRenderer的render函數

- (void)renderAtTime:(CFTimeInterval)time viewport:(CGRect)viewport commandBuffer:(id )commandBuffer passDescriptor:(MTLRenderPassDescriptor *)renderPassDescriptor

將場景渲染到一個id物件中,通過紋理綁定的方式將其轉換為CVPixelBufferRef以完成視頻編碼。某位元朋友提醒,可以通過method swizzling的方式直接獲取CAMetalLayer的nextDrawable,甚至可以避免上訴方案錄製時產生的額外GPU開銷,有興趣的朋友可以嘗試一下。

寫在末尾

這次能有機會參加Apple的封閉開發且是如此有趣的模組,在沒有網路的情況下摸索著做出demo,接觸到了最前沿的AR相關技術,對我來說是一份非常寶貴的經歷。心懷感恩,踏步前行。

demo效果視頻(v.qq.com/x/page/p1328bmunrt.html?)

最後,附上PhxPaxos源碼的位址:(github.com/Tencent/phxpaxos)

小編的話:根據發文規範,文章內不能出現連結。因此,

()括弧內均為文章連結或下載位址,如有需求請行加上https://首碼,或者可進入騰訊雲技術社區查看該文章,進行下載。

各位大大們,想看哪方面的技術性文章,盡請留言!

Next Article
喜欢就按个赞吧!!!
点击关闭提示