ARKit示例 - 第4部分:现实主义 - 照明和PBR

在柜台上的虚拟立方体

在本文中,我们将在场景中插入更逼真的虚拟内容。我们可以通过使用称为基于物理的渲染(PBR)的技术使用更详细的模型来实现这一点,并且还可以更准确地表示场景中的光照。

要查看更新,请查看下面的视频,而不仅仅是平面实心钻孔立方体,我们现在添加了一些基于PBR的材料,这些材料为我们提供了一个更加逼真的物体,似乎适合现实世界,具有可变的光照和反射。

youtube

如果您还没有阅读本系列中的其他文章,可以在此处找到列表。

场景照明

增强现实的主要目标之一是将虚拟内容与现实世界混合。有时我们添加的内容可能是风格化的,看起来并不“真实”,但有时候我们要插入的内容看起来和感觉都像是我们正在交互的实际空间的一部分。

强度

为了达到高水平的真实感,照明场景非常重要。尝试在虚拟场景中尽可能地模拟真实世界的照明将使您插入的内容感觉更真实。

例如,如果你在光线昏暗的房间里插入一个使用强光点亮的3D模型,它看起来完全不合适,反之亦然,在明亮的房间里昏暗的3D物体会感觉不适地点。

在黑暗环境中一个明亮的立方体 - 感觉完全不合适

在明亮的位置(也是灯的方向关闭)的黑色立方体

因此,让我们从一开始就建立起更高和更高水平的现实主义。首先,如果您的虚拟场景没有灯光,那么就像在现实世界中所有内容都是黑色一样,没有光线反射物体表面。如果我们关闭场景中的灯光并插入一些立方体,您将看到以下结果:

真实世界表面上的两个虚拟立方体,在场景中没有任何光照

现在我们需要为场景添加一些灯光,在3D图形中,可以添加各种不同类型的灯光到场景中:

不同照明模式的示例 - SceneKit

环境  - 模拟从各个方向撞击物体的等量光。正如您所看到的那样,因为光从各个方向均匀地击中物体,所以没有阴影。

定向  光具有方向但没有光源位置,只是想象一个从表面发光的无限位置。

Omni  - 也称为聚光灯。这是一个有方向(如方向)但也有位置的灯。如果要根据几何体与光源的距离执行光的强度计算,这非常有用。

聚光灯  - 聚光灯就像全方位一样,但是除了方向和位置之外,聚光灯的强度会以锥形形状下降,就像桌面上的聚光灯一样。

还有一些其他类型的灯光,但我们并不需要使用那些现在,更多信息可以读取的SceneKit文档SCNLight

autoenablesDefaultLighting

SceneKit SCNView有一个叫做财产autoenablesDefaultLighting如果设置为true,SceneKit将一个Onmi定向光添加到场景中,距离摄像机的位置,并在摄像头的方向指向,这是一个很好的起点,它是在您添加自己的光源之前,默认情况下在项目中启用(即本系列前几篇文章中的所有多维数据集点亮)。这个简单设置的几个问题是:

  • 光的强度总是1000,这意味着“正常”,因此再次将内容放置在不同的光照条件下看起来不正确。
  • 光线有一个变化的方向,所以当你在一个物体周围走动时,它总是看起来就像你的视线中的光线(就像你手持火炬一样),这种情况通常并非如此,大多数场景都有静态照明,因此当您四处移动时,您的模型看起来会不自然。

我们将为我们的应用关闭此功能:

self.sceneView.autoenablesDefaultLighting = NO;

automaticallyUpdatesLighting

ARKit的ARSCNView有一个名为automaticUpdatesLighting的属性,文档中说这将根据估计的光强度自动为场景添加灯光。听起来不错,但据我所知它没有做任何事情,将其与其他属性设置为各种组合似乎没有做任何事情,不确定这是SDK的这个版本中的错误还是我做错了什么(更有可能),但这并不重要,因为我们可以通过另一种方式获得估计照明,我们现在将做。

lightEstimationEnabled

ARSessionConfiguration类具有alightEtimationEnabled属性,将其设置为true,在每个捕获的ARFrame中,我们将获得可用于渲染场景的lightEstimate值。

有了这些信息,我们可以在每一帧中采用lightEstimate并修改场景中灯光的强度,以模拟现实世界场景的环境光强度,这有助于上面提到的太亮/太暗的问题。

灯光

首先让我们为场景添加一个灯光,我们将添加一个直接向下指向的聚光灯,并将其插入到原点上方几米处的场景中。这大致模拟了我在我家里制作视频的环境,我在天花板上有聚光灯。您要添加聚光灯:

- (void)insertSpotLight:(SCNVector3)position {
  SCNLight *spotLight = [SCNLight light];
  spotLight.type = SCNLightTypeSpot;
  spotLight.spotInnerAngle = 45;
  spotLight.spotOuterAngle = 45;
  SCNNode *spotNode = [SCNNode new];
  spotNode.light = spotLight;
  spotNode.position = position;
  // By default the stop light points directly down the negative
  // z-axis, we want to shine it down so rotate 90deg around the 
  // x-axis to point it down
  spotNode.eulerAngles = SCNVector3Make(-M_PI / 2, 0, 0);
  [self.sceneView.scene.rootNode addChildNode: spotNode];
}

除了聚光灯外,我们还添加了一个环境光,这是因为在现实世界中,通常有多个光源和光线从墙壁和其他物理物体反射,为物体的所有侧面提供光。这个过程与上面类似,我将从这里省略。当我们这样做时,我们现在可以插入一块几何体,让它感觉更像它实际上是场景的一部分。

光估计

最后,我们提到了lightEstimation,ARKit可以分析场景并估计环境光强度。它将返回一个值1000,表示低于中性的“中性”值,上面的值更亮。要启用光照估计,您需要在场景配置中将lightEstimationEnabled属性设置为true:

configuration.lightEstimationEnabled = YES;

完成此操作后,您可以在ARSCNViewDelegate协议中实现以下方法,并修改我们添加到场景中的聚光灯和环境光的强度:

- (void)renderer:(id <SCNSceneRenderer>)renderer updateAtTime:(NSTimeInterval)time {
  ARLightEstimate *estimate = self.sceneView.session.currentFrame.lightEstimate;
  if (!estimate) {
    return;
  }
  // TODO: Put this on the screen
  NSLog(@"light estimate: %f", estimate.ambientIntensity);
  // Here you can now change the .intensity property of your lights
  // so they respond to the real world environment
}

现在这很酷,观看下面的视频,你可以看到当我调暗我家里的灯光时虚拟立方体也会变暗,因为虚拟灯光变暗了!随着灯光变亮,它会变得更亮。

youtube

从中可以看出,让灯光与现实世界相匹配是很棘手的,但我们有一个有用的钝工具,以照明估计的形式,可以帮助我们一些现实主义。我认为这里的一般准则是,理想情况下,确保您的用户在光线充足的环境中使用您的应用程序,该环境具有可以轻松建模的一致照明。

基于物理的渲染

好的,所以我们有了基本照明的概念,我们将把99%的光投射掉:)我们将不再尝试为场景添加灯光并处理复杂性,而是保持照明估算功能,但使用称为基于物理的渲染技术。

使用此技术呈现的对象的一些示例如下所示:

Image from https://www.marmoset.co/posts/tag/pbr/page/5/

Image from: https://medium.com/@avihay/amazing-physically-based-rendering-using-the-new-ios-10-scenekit-2489e43f7021

有关这个有趣的SceneKit文章,请查看这篇文章:

惊人的基于物理渲染使用新的IOS 10 SceneKit 如何简单地使用新推出的iOS版10基于物理的渲染器,并没有得到很大的期待结果...medium.com

我不会在本文中尝试解释此过程的所有细节,因为有许多优秀的资源,但基本概念是当您对对象进行纹理处理时,您提供的信息包括:

反照率  - 这是模型的基色。它映射到材质的漫反射组件,它是材质纹理,在光照或阴影信息中没有任何烘焙。

粗糙度  - 描述材料的粗糙程度,较粗糙的表面显示较暗的反射,更光滑的材料显示更明亮的镜面反射。

金属度  - 相当于材料的光泽程度。

有关更详细的说明,请参阅https://www.marmoset.co/posts/tag/pbr/page/5/

出于我们的目的,我们只想渲染我们的立方体和平面更真实,因为我从http://freepbr.com/抓取了一些纹理并使用它们渲染材料:

mat = [SCNMaterial new];
mat.lightingModelName = SCNLightingModelPhysicallyBased;
mat.diffuse.contents = [UIImage imageNamed:@"wood-albedo.png"];
mat.roughness.contents = [UIImage imageNamed:@"wood-roughness.png"];
mat.metalness.contents = [UIImage imageNamed:@"wood-metal.png"];
mat.normal.contents = [UIImage imageNamed:@"wood-normal.png"];

您需要将材质的lightingModelName设置为SCNLightingModelPhysicallyBased并设置各种材质类型。

最后一个重要的部分是你必须告诉你的SCNScene你正在使用PBR照明,当你这样做时,场景的光源实际上来自你指定的图像,例如我使用这个图像:

示例环境地图,来自:https://medium.com/@avihay/amazing-physically-based-rendering-using-the-new-ios-10-scenekit-2489e43f7021

因此,从这个图像中获取几何体的光照,考虑将几何体周围的图像作为背景投影,然后SceneKit使用此背景来确定几何体是如何被照亮的。

最后一部分是从ARKit获取光估计值并将其应用于此环境图像的强度。ARKit返回值1000以表示中性光照,因此更小,更暗,更亮。对于中性,照明环境值的值为1.0,因此我们需要缩放从ARKit获得的值:

UIImage *env = [UIImage imageNamed: @"spherical.jpg"];
self.sceneView.scene.lightingEnvironment.contents = env;

UI改进

我改变了UI,所以现在如果你用一根手指在平面上按住,它将改变材料,对于立方体也是如此,按住以更改立方体的材料。用两根手指按住即可发生爆炸。

我还添加了一个切换按钮,一旦您对找到的平面感到满意就停止平面检测,并添加一个设置屏幕来打开/关闭各种调试项目。

与往常一样,您可以在此处找到此项目的代码:https//github.com/markdaws/arkit-by-example

下一个

到目前为止,我们编写了应用程序假设快乐的路径,没有什么会出错,但在现实世界中,尤其是跟踪,我们知道并非总是如此。当涉及到ARKit以使我们的应用程序更加健壮时,我们需要处理许多场景,在下一篇文章中我们将退后一步并处理错误和降级案例。

原文:https://blog.markdaws.net/arkit-by-example-part-4-realism-lighting-pbr-b9a0bedb013e 作者:Mark Dawson

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏腾讯移动品质中心TMQ的专栏

【Android场景化性能测试】UI流畅度篇

承接《Android场景化性能测试-方向与框架篇》,本篇详述UI流畅度的测试方法,重点在于获得流畅度SM数据之后,如何利用好。

8274
来自专栏CSDN技术头条

我猜,每个程序员对着电梯都想过调度算法吧!

但说起电梯调度算法,我觉得还是可以给大家科普一下,好为大家在等电梯之余,打发时间而做出一点贡献。(电梯调度算法可以参考各种硬盘换道算法,下面内容整理自网络)

4844
来自专栏Golang语言社区

体育竞技游戏的团队AI

很多人问游戏AI该怎么做?随着游戏类型的多元化,非 MMO或者卡牌的游戏越来越多,对AI的需求也越来越强了。而市面上关于 AI的书,网上找得到的文章,也都流于一...

1674
来自专栏AI研习社

博客 | Github开源人体姿态识别项目OpenPose中文文档

人体姿态识别与估计的应用场景:抖音尬舞机、体育动作教学、3D健身教练、3D试衣、绘画辅助、游戏人物动作采集。

8364
来自专栏IT技术精选文摘

浅析eBay联盟营销的上下文广告机制

1673
来自专栏AI派

还没准备好数据呢,为什么要着急用算法呢

开始之前,通知下我的读者,随着订阅读者越来越多,为了对读者们负责,有以下几件事情需要告知下:

2036
来自专栏机器之心

资源 | OpenAI开源机器人模拟Python库mujoco-py:可高效处理并行模拟

选自OpenAI 机器之心编译 参与:黄小天 OpenAI 宣布开源一个高性能的 Python 库,它可用于使用 MuJoCo 引擎(在上年的机器人研究中开发出...

3704
来自专栏腾讯数据中心

变频冷机在超低负载下如何安全又节能运行?

使用变频冷机是为了节能,节能的前提是“冷机处于非满载工况下运行”。但如果当冷机负载太低(低于30%以下),冷机不仅无法有效节能,甚至不能正常工作——此时冷机会反...

3082
来自专栏量子位

陈天奇团队发布NNVM编译器,性能优于MXNet,李沐撰文介绍

夏乙 若朴 编译整理 量子位 出品 | 公众号 QbitAI 亚马逊和华盛顿大学今天合作发布了开源的端到端深度学习编译器NNVM compiler。 先提醒一句...

4696
来自专栏阮一峰的网络日志

信息机器Memex

1945年,一个美国科学家Vannevar Bush在《大西洋月刊》上发表了一篇文章《As We May Think》,提出一种信息机器的构想,就像下图中的样子...

38511

扫码关注云+社区

领取腾讯云代金券