ARKit尝试翻译五_Custom Views

Displaying an AR Experience with Metal

通过渲染摄像机图像和使用位置跟踪信息来显示覆盖内容,构建自定义AR视图。

arkit包括查看容易显示AR的经验与SceneKit或SpriteKit类。但是,如果你建立你自己的渲染引擎(或与第三方引擎集成),ARKit还提供了所有必要的支持,以显示一个自定义视图AR体验。


在任何AR经验中,第一步是配置一个arsession对象来管理摄像机捕获和运动处理。会话定义并保持设备所在的真实世界空间与虚拟空间之间的对应关系,并在其中模拟AR内容。要在自定义视图中显示AR体验,您需要:

1.从会话中检索视频帧和跟踪信息。

2.将这些框架图像渲染为视图的背景。

3.使用跟踪信息在相机图像上方定位和绘制AR内容。

Note

本文介绍Xcode项目模板代码中找到。对于完整的示例代码,使用增强现实模板创建新的iOS应用程序,并从“内容技术”弹出菜单中选择“金属”菜单。

Get Video Frames and Tracking Data from the Session

创建和维护自己arsession实例,并运行一个会话配置,该会话配置适合于要支持的AR体验。(要做到这一点,请参见建立一个基本的AR体验)会话捕获摄像机的视频,跟踪设备的位置和方向在一个模拟的3D空间,并提供arframe物体.每一个这样的对象都包含一个单独的视频帧图像和从帧被捕获的时刻的位置跟踪信息。有两种访问方式arframe AR会话产生的对象,取决于您的应用程序是否支持拉或推设计模式。

如果你喜欢控制帧定时(拉设计模式),使用会话的帧属性获取当前帧图像和跟踪信息每次重画视图的内容。使用这种方法的arkit Xcode模板:

// in Renderer class, called from MTKViewDelegate.draw(in:) via Renderer.update()

func updateGameState(){

guardletcurrentFrame = session.currentFrameelse{return}        updateSharedUniforms(frame: currentFrame)   

 updateAnchors(frame: currentFrame)    

updateCapturedImageTextures(frame: currentFrame)

if viewportSizeDidChange {       

 viewportSizeDidChange =false

 updateImagePlane(frame: currentFrame)    

}

}

另外,如果您的应用程序设计有利于推模式,实现会议:didupdateframe:委托方法,该会话将为它捕获的每个视频帧调用一次(默认为每秒60帧)。

在获得一个框架,你需要绘制相机图像,并更新和渲染任何内容覆盖你的AR经验包括。

Draw the Camera Image

创建和维护自己arsession实例,并运行一个会话配置,该会话配置适合于要支持的AR体验。(要做到这一点,请参见建立一个基本的AR体验)会话捕获摄像机的视频,跟踪设备的位置和方向在一个模拟的3D空间,并提供arframe物体.每一个这样的对象都包含一个单独的视频帧图像和从帧被捕获的时刻的位置跟踪信息。

有两种访问方式arframe AR会话产生的对象,取决于您的应用程序是否支持拉或推设计模式。

如果你喜欢控制帧定时(拉设计模式),使用会话的帧属性获取当前帧图像和跟踪信息每次重画视图的内容。使用这种方法的arkit Xcode模板:

// in Renderer class, called from MTKViewDelegate.draw(in:) via Renderer.update()

func updateGameState(){

guardletcurrentFrame = session.currentFrameelse{return}

updateSharedUniforms(frame: currentFrame)

updateAnchors(frame: currentFrame)

updateCapturedImageTextures(frame: currentFrame)

if viewportSizeDidChange {

viewportSizeDidChange =false

updateImagePlane(frame: currentFrame)

}

}

Draw the Camera Image

每个arframe对象的capturedimage属性包含从设备照相机捕获的像素缓冲区。若要将此图像作为自定义视图的背景绘制,则需要从图像内容创建纹理并提交使用这些纹理的GPU渲染命令。

像素缓冲区的内容是biplanar YCbCr编码(也称为YUV)数据格式;渲染的图像就需要将像素数据的图像的RGB格式。用金属渲染,可以在GPU着色器代码中最有效地执行转换。API的使用cvmetaltexturecache创建从像素缓冲区一个缓冲的亮度两金属材质(Y)和色度(CbCr)飞机:

func updateCapturedImageTextures(frame: ARFrame){/

/ Create two textures (Y and CbCr) from the provided frame's captured imageletpixelBuffer = frame.capturedImage

if(CVPixelBufferGetPlaneCount(pixelBuffer) <2) {return}

capturedImageTextureY = createTexture(fromPixelBuffer: pixelBuffer, pixelFormat:.r8Unorm, planeIndex:0)!

capturedImageTextureCbCr = createTexture(fromPixelBuffer: pixelBuffer, pixelFormat:.rg8Unorm, planeIndex:1)!

}

func createTexture(fromPixelBuffer pixelBuffer: CVPixelBuffer, pixelFormat: MTLPixelFormat, planeIndex: Int)->MTLTexture? {

varmtlTexture:MTLTexture? =nilletwidth =CVPixelBufferGetWidthOfPlane(pixelBuffer, planeIndex)letheight =CVPixelBufferGetHeightOfPlane(pixelBuffer, planeIndex)vartexture:CVMetalTexture? =nilletstatus =CVMetalTextureCacheCreateTextureFromImage(nil, capturedImageTextureCache, pixelBuffer,nil, pixelFormat, width, height, planeIndex, &texture)ifstatus == kCVReturnSuccess {

mtlTexture =CVMetalTextureGetTexture(texture!)

}returnmtlTexture

}

其次,编码渲染命令,画两个纹理使用分段函数执行YCbCr到RGB转换颜色的变换矩阵:

fragment float4 capturedImageFragmentShader(ImageColorInOut in [[stage_in]],

texture2d capturedImageTextureY [[ texture(kTextureIndexY) ]],

texture2d capturedImageTextureCbCr [[ texture(kTextureIndexCbCr) ]]) {

constexpr sampler colorSampler(mip_filter::linear,

mag_filter::linear,

min_filter::linear);

const float4x4 ycbcrToRGBTransform = float4x4(

float4(+1.164380f, +1.164380f, +1.164380f, +0.000000f),

float4(+0.000000f, -0.391762f, +2.017230f, +0.000000f),

float4(+1.596030f, -0.812968f, +0.000000f, +0.000000f),

float4(-0.874202f, +0.531668f, -1.085630f, +1.000000f)

);

// Sample Y and CbCr textures to get the YCbCr color at the given texture coordinate

float4 ycbcr = float4(capturedImageTextureY.sample(colorSampler, in.texCoord).r,

capturedImageTextureCbCr.sample(colorSampler, in.texCoord).rg, 1.0);

// Return converted RGB color

return ycbcrToRGBTransform * ycbcr;

}

Note

使用displaytransformwithviewportsize:定位:方法确保相机图像覆盖整个视图。对于这种方法的例子,以及完整的金属管道安装代码,看到完整的Xcode模板。(创建一个新的iOS应用程序的增强现实模板,并选择金属从内容技术弹出菜单。)

Track and Render Overlay Content

AR的经验通常侧重于渲染3D覆盖内容,使内容似乎是在相机图像中看到的真实世界的一部分。为了实现这种错觉,使用aranchor类来模拟你自己3D内容相对于真实世界空间的位置和方向。锚提供转换,您可以在渲染过程中引用。

例如,Xcode模板创建一个锚位于设备前端约20厘米,每当用户点击屏幕

func handleTap(gestureRecognize: UITapGestureRecognizer){

// Create anchor using the camera's current position

if letcurrentFrame = session.currentFrame {// Create a transform with a translation of 0.2 meters in front of the cameravartranslation = matrix_identity_float4x4

translation.columns.3.z = -0.2lettransform = simd_mul(currentFrame.camera.transform, translation)// Add a new anchor to the sessionletanchor =ARAnchor(transform: transform)

session.add(anchor: anchor)

}

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容