ARKIT--灯光和纹理

为什么要使用灯光

AR就是在现实中插入新物体,一些时候,新物体看起来会不真实。如何能让物体看起来和现实的场景融为一体呢?一个很好的办法就是使用灯光。
举个例子,如果在一个全黑的房间放入一个明亮的物体,看起来的效果就特别不真实,如下图。

ARKIT--灯光和纹理_第1张图片
image.png

灯光的类别

ARKIT--灯光和纹理_第2张图片
image.png

Ambient(全景灯光): 灯光从每个方向过来,而且灯光的强度都是一致的,所以看起来没有阴影。
** directional(定向光)**:该灯光只有方向,没有光源,可以想象从无限远的地方发射出光源。
omni(泛光灯): 该灯光有方向,也有光源,灯光的强度和距离有关系,距离越近,强度越大。
spot(聚光灯):和泛光灯一样,有方向也有光源,而且是以锥形的方式到平面上,就如同现实中的聚光灯一样。

ARKit灯光估计技术

ARKit使用灯光估计技术,根据场景进行分析估算出全景灯光的强度,返回值1000代表中间值,小于这个值则变暗,大于这个值则变亮,打开灯光估计技术,只需要在场景配置里设置lightEstimationEnabled 属性即可:

configuration.lightEstimationEnabled = YES;

在ARSCNViewDelegate里,就可以使用估计出来的灯光值进行一些工作,具体怎么做,下面的章节一一解释。

- (void)renderer:(id )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
}

添加场景灯光

有3种设置灯光的办法:
1:autoenablesDefaultLighting会加入一个Onmi (泛光灯),该灯光的位置是摄像头的位置,方向也是摄像头的拍摄方向。不过该默认灯光有下面几个特点:

  • 灯光的强度一直都是1000(中性值)。
  • 该灯光的方向可以随时改变,方向都是从摄像头方向出去,就好像是你拿着火炬时的感觉。

2:automaticallyUpdatesLighting会自动基于灯光估计技术加入灯光,听起来好像很完美,不过貌似没有生效。

3:在这里我们自定义灯光,把图片里面的灯光,利用灯光估计技术提取出来.

- (void)setupLights {
  // Turn off all the default lights SceneKit adds since we are handling it ourselves
  self.sceneView.autoenablesDefaultLighting = NO;
  self.sceneView.automaticallyUpdatesLighting = NO;
  
  UIImage *env = [UIImage imageNamed: @"./Assets.scnassets/Environment/spherical.jpg"];
  self.sceneView.scene.lightingEnvironment.contents = env;
  
  //TODO: wantsHdr
}

图片如下:


ARKIT--灯光和纹理_第3张图片
image.png

调节灯光的强度

在代理里面,利用灯光估计技术,获得实时的灯光强度,设置入场景。

- (void)renderer:(id )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
//估计出来的灯光设置进去
CGFloat intensity = estimate.ambientIntensity / 1000.0;
self.sceneView.scene.lightingEnvironment.intensity = intensity;
}

光线跟踪:基于物理的渲染(PBR)

先看几张渲染图,体会一下,PBR的细节比较复杂,具体参看PBR.

ARKIT--灯光和纹理_第4张图片
image.png

ARKIT--灯光和纹理_第5张图片
image.png

当你给物体加入纹理的时候,你需要提供以下信息:
Albedo(反照率):这是模型的基本颜色。它映射到物质的漫反射部分,它是在光照或阴影信息中没有任何烘烤的物质纹理。
Roughness(粗糙度):描述材料的粗糙程度,粗糙的表面显示出暗淡的反射,平滑的材料显示明亮的镜面反射。
Metalness(金属度):相当于材料光泽的粗略方法。
比较难以理解,大家可以看看这里 PBR详细介绍

利用PBR技术添加物体纹理

从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"];

可以看到这里的灯光模式设置成了PBR.
具体可以参考demo:
demo

你可能感兴趣的:(ARKIT--灯光和纹理)