為什么要使用燈光
AR就是在現(xiàn)實中插入新物體,一些時候,新物體看起來會不真實幼东。如何能讓物體看起來和現(xiàn)實的場景融為一體呢愚臀?一個很好的辦法就是使用燈光。
舉個例子辩越,如果在一個全黑的房間放入一個明亮的物體嘁扼,看起來的效果就特別不真實,如下圖黔攒。
燈光的類別
Ambient(全景燈光): 燈光從每個方向過來趁啸,而且燈光的強度都是一致的,所以看起來沒有陰影督惰。
** directional(定向光)**:該燈光只有方向不傅,沒有光源,可以想象從無限遠的地方發(fā)射出光源赏胚。
omni(泛光燈): 該燈光有方向蛤签,也有光源,燈光的強度和距離有關(guān)系栅哀,距離越近震肮,強度越大。
spot(聚光燈):和泛光燈一樣留拾,有方向也有光源戳晌,而且是以錐形的方式到平面上,就如同現(xiàn)實中的聚光燈一樣痴柔。
ARKit燈光估計技術(shù)
ARKit使用燈光估計技術(shù)沦偎,根據(jù)場景進行分析估算出全景燈光的強度,返回值1000代表中間值咳蔚,小于這個值則變暗豪嚎,大于這個值則變亮,打開燈光估計技術(shù)谈火,只需要在場景配置里設(shè)置lightEstimationEnabled 屬性即可:
configuration.lightEstimationEnabled = YES;
在ARSCNViewDelegate里侈询,就可以使用估計出來的燈光值進行一些工作,具體怎么做糯耍,下面的章節(jié)一一解釋扔字。
- (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
}
添加場景燈光
有3種設(shè)置燈光的辦法:
1:autoenablesDefaultLighting會加入一個Onmi (泛光燈),該燈光的位置是攝像頭的位置,方向也是攝像頭的拍攝方向温技。不過該默認燈光有下面幾個特點:
- 燈光的強度一直都是1000(中性值)革为。
- 該燈光的方向可以隨時改變,方向都是從攝像頭方向出去舵鳞,就好像是你拿著火炬時的感覺震檩。
2:automaticallyUpdatesLighting會自動基于燈光估計技術(shù)加入燈光,聽起來好像很完美蜓堕,不過貌似沒有生效抛虏。
3:在這里我們自定義燈光,把圖片里面的燈光俩滥,利用燈光估計技術(shù)提取出來.
- (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
}
圖片如下:
調(diào)節(jié)燈光的強度
在代理里面嘉蕾,利用燈光估計技術(shù),獲得實時的燈光強度霜旧,設(shè)置入場景错忱。
- (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
//估計出來的燈光設(shè)置進去
CGFloat intensity = estimate.ambientIntensity / 1000.0;
self.sceneView.scene.lightingEnvironment.intensity = intensity;
}
光線跟蹤:基于物理的渲染(PBR)
先看幾張渲染圖,體會一下挂据,PBR的細節(jié)比較復(fù)雜,具體參看PBR.
當你給物體加入紋理的時候以清,你需要提供以下信息:
Albedo(反照率):這是模型的基本顏色。它映射到物質(zhì)的漫反射部分崎逃,它是在光照或陰影信息中沒有任何烘烤的物質(zhì)紋理掷倔。
Roughness(粗糙度):描述材料的粗糙程度,粗糙的表面顯示出暗淡的反射个绍,平滑的材料顯示明亮的鏡面反射勒葱。
Metalness(金屬度):相當于材料光澤的粗略方法浪汪。
比較難以理解,大家可以看看這里PBR詳細介紹
利用PBR技術(shù)添加物體紋理
從http://freepbr.com/ 抓取一些紋理的圖片下來凛虽,設(shè)置成紋理:
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"];
可以看到這里的燈光模式設(shè)置成了PBR.
具體可以參考demo:
demo