前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ARKit示例 - 第4部分:现实主义 - 照明和PBR

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

作者头像
iOSDevLog
发布2018-09-20 10:37:53
1.2K0
发布2018-09-20 10:37:53
举报
文章被收录于专栏:iOSDevLogiOSDevLog

在柜台上的虚拟立方体

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

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

youtube

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

场景照明

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

强度

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

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

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

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

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

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

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

不同照明模式的示例 - SceneKit

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

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

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

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

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

autoenablesDefaultLighting

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

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

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

代码语言:javascript
复制
self.sceneView.autoenablesDefaultLighting = NO;
automaticallyUpdatesLighting

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

lightEstimationEnabled

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

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

灯光

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

代码语言:javascript
复制
- (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:

代码语言:javascript
复制
configuration.lightEstimationEnabled = YES;

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

代码语言:javascript
复制
- (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/抓取了一些纹理并使用它们渲染材料:

代码语言:javascript
复制
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获得的值:

代码语言:javascript
复制
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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.08.23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 场景照明
    • 强度
      • autoenablesDefaultLighting
        • automaticallyUpdatesLighting
          • lightEstimationEnabled
          • 灯光
          • 光估计
          • 基于物理的渲染
          • UI改进
          • 下一个
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档