第六節(jié) - 燈光詳解

燈光篇

本節(jié)學習目標

今天我們要學習的SceneKit 游戲框架中的幾種光以及如何使用它們!

學習任務

1.熟悉SCNLight 類 2.理解四種光源的作用 3.學會如何選擇在游戲場景中使用光源.

光的介紹

  • 環(huán)境光(SCNLightTypeAmbient)

這種光的特點,沒有方向,位置在無窮遠處,光均勻的散射到物體上.

環(huán)境光
  • 點光源(SCNLightTypeOmni)

有固定的位置,方向360度,可以衰減

點光源
  • 平行方向光(SCNLightTypeDirectional)

只有照射的方向,沒有位置,不會衰減

平行方向光源
  • 聚焦光源(SCNLightTypeSpot) 可

光源有固定的位置,也有方向,也有照射區(qū)域 ,可以衰減

聚焦光源

SCNLight 介紹

我們使用光源,主要用到的類就是SCNLight,我們把這個類的屬性分析一下。

  • 創(chuàng)建光對象

     +(instancetype)light; 
    
  • 設置燈光類型,就是上面講的那個類型

    @property(nonatomic, copy) NSString *type;
    
  • 燈光的顏色

     @property(nonatomic, retain) id color;
    
  • 燈光的名字,可以用來索引燈光用

    @property(nonatomic, copy, nullable) NSString *name;
    
  • 是否支持投射陰影,注意,這個屬性只在點光源或者平行方向光源起作用

    @property(nonatomic) BOOL castsShadow; 
    
  • 設置陰影的顏色,默認為透明度為50%的黑色

    @property(nonatomic, retain) id shadowColor;
    
  • 設置陰影的采樣角度 默認值為3

    @property(nonatomic) CGFloat shadowRadius;
    
  • 設置陰影貼圖的大小,陰影貼圖越大,陰影越精確,但計算速度越慢。如果設置為{ 0 0}陰影貼圖的大小自動選擇,默認為{0,0}

    @property(nonatomic) CGSize shadowMapSize NS_AVAILABLE(10_10, 8_0);
    
  • 設置每一幀計算陰影貼圖的次數(shù),默認為一次

     @property(nonatomic) NSUInteger shadowSampleCount NS_AVAILABLE(10_10, 8_0);
    
  • 設置陰影模式(默認)

    @property(nonatomic) SCNShadowMode shadowMode NS_AVAILABLE(10_10, 8_0);
    // 可選值為下面三種
    SCNShadowModeForward   = 0, 通過Alpha值得變化決定陰影
    SCNShadowModeDeferred  = 1, 根據(jù)最后的顏色決定陰影,一般不太用,除非有多個光源作用的情況下
     SCNShadowModeModulated = 2 光沒有作用,只投射陰影,一般用于圖案作為陰影的情況下,比如鏡像漸變圖像(黑白)
    
  • 陰影的深度偏移量

    @property(nonatomic) CGFloat shadowBias NS_AVAILABLE(10_10, 8_0);
    
  • 平行方向放陰影比例值調(diào)節(jié)

     @property(nonatomic) CGFloat orthographicScale NS_AVAILABLE(10_10, 8_0);
    
  • 光作用的范圍

     @property(nonatomic) CGFloat zFar NS_AVAILABLE(10_10, 8_0);
     @property(nonatomic) CGFloat zNear NS_AVAILABLE(10_10, 8_0);
    
  • 光衰減的開始距離和結束距離(Omni or Spot light)

    @property(nonatomic) CGFloat attenuationStartDistance NS_AVAILABLE(10_10, 8_0);// 默認為0
    @property(nonatomic) CGFloat attenuationEndDistance NS_AVAILABLE(10_10, 8_0);// 默認為1
    @property(nonatomic) CGFloat attenuationFalloffExponent NS_AVAILABLE(10_10, 8_0);// 1 表示線性減弱 2表示平方減弱
    
  • 聚焦光的發(fā)射點的方向和光線強度最弱的時候的夾角

    @property(nonatomic) CGFloat spotInnerAngle  NS_AVAILABLE(10_10, 8_0);// 默認為0度
    @property(nonatomic) CGFloat spotOuterAngle  NS_AVAILABLE(10_10, 8_0);// 默認為45度
    
  • 當你要使用碰撞檢測時,請設置下面的屬性

    @property(nonatomic) NSUInteger categoryBitMask NS_AVAILABLE(10_10, 8_0);
    
  • 點光源材質(zhì)屬性(只支持spot類型)

    @property(nonatomic, readonly, nullable) SCNMaterialProperty *gobo NS_AVAILABLE(10_9, 8_0);
    

你最愛的代碼部分

我們已經(jīng)熟悉了光源類的具體使用方法,下面我們就來驗證一下理論的真實性!

第一步.創(chuàng)建工程

創(chuàng)建工程

第二步.添加游戲框架

image

第三步.創(chuàng)建一個游戲框架專屬的視圖(SCNView類型)

    self.gameView = [[SCNView alloc]initWithFrame:self.view.bounds];
    self.gameView.backgroundColor = [UIColor blackColor];
    [self.view addSubview:self.gameView];
運行一下,如果界面是下面這樣,表示創(chuàng)建成功
![運行結果](http://upload-images.jianshu.io/upload_images/1594482-f87efb77b12fb74d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

我們把攝像機控制打開,方便我們觀察視圖

     self.gameView.allowsCameraControl = true;

第四步.設置場景

友情提示

SCNView 對象的scene 屬性,系統(tǒng)默認為nil,所以我們必須手動創(chuàng)建scene

    self.gameView.scene = [SCNScene scene];

第五步.我們給游戲視圖中添加一個正方形塊節(jié)點和一個球體節(jié)點

    // 創(chuàng)建正方塊
    SCNBox *box = [SCNBox boxWithWidth:0.5 height:0.5 length:0.5 chamferRadius:0];// 正方體

    // 創(chuàng)建球體
    SCNSphere *sphere = [SCNSphere sphereWithRadius:0.1];// 設置球體半徑為0.1

    // 把兩個結合體綁定到節(jié)點上
    SCNNode *boxNode = [SCNNode node];
    boxNode.geometry = box;
    boxNode.position = SCNVector3Make(0, 0, -11); // 把節(jié)點的位置固定在(0,0,-11)
    SCNNode *sphereNode = [SCNNode node];
    sphereNode.geometry = sphere;
    sphereNode.position = SCNVector3Make(0, 0, -10); // 把節(jié)點的位置固定在(0,0,-11)

    // 添加節(jié)點到場景中去
    [self.gameView.scene.rootNode addChildNode:boxNode];
    [self.gameView.scene.rootNode addChildNode:sphereNode];

運行結果:

Scenekit_03.gif

第六步.我們給場景中只添加一個環(huán)境光

 SCNLight *light = [SCNLight light]; // 創(chuàng)建燈光
 light.type = SCNLightTypeAmbient; // 設置燈光類型
 light.color = [UIColor yellowColor]; // 設置燈光顏色

SCNNode *lightNode = [SCNNode node];
lightNode.light  = light;
[self.gameView.scene.rootNode addChildNode:lightNode];

運行結果

環(huán)境光

問題1:設置顏色為yellowColor 為什么物體不是yellow呢?

因為物體材質(zhì)中沒有黃色成分,比如你傳的是一件綠色的衣服,你用黃光照射他,你不可能看見衣服是綠色或者黃色的,這里你可以把物體的顏色變?yōu)辄S色試試看。

問題2:那為什么和不添加環(huán)境光一樣的效果呢?

因為系統(tǒng)本身如果我們不提供任何光源,它會自動添加環(huán)境光,如果檢測到我們添加了光源,它將不會幫我們添加環(huán)境光

第七步.我們向游戲場景中只添加一個點光源

SCNLight *light = [SCNLight light];// 創(chuàng)建光對象
light.type = SCNLightTypeOmni;// 設置類型
light.color = [UIColor yellowColor]; // 設置光的顏色

SCNNode *lightNode = [SCNNode node];
lightNode.position = SCNVector3Make(0, 0, 100); // 設置光源節(jié)點的位置
lightNode.light  = light;
[self.gameView.scene.rootNode addChildNode:lightNode]; // 添加到場景中去

運行結果:

Scenekit_03.gif

我們的點光源的位置為(0,0,100),我們把位置改為(0,100,100),看一下效果,對比一下,你就掌握了這種光的特點

改變位置后

點光源的特顯,你應該明白了!我們繼續(xù)!

第八步.只添加一個平行方向光源

我們一開始說了這種光源的特點:只有方向,沒有位置,我們驗證一下

SCNLight *light = [SCNLight light];// 創(chuàng)建光對象
light.type = SCNLightTypeDirectional;// 設置類型
light.color = [UIColor yellowColor]; // 設置光的顏色

SCNNode *lightNode = [SCNNode node];
lightNode.position = SCNVector3Make(0, 10, -100); // 設置光源節(jié)點的位置
lightNode.light  = light;
[self.gameView.scene.rootNode addChildNode:lightNode]; // 添加到場景中去

位置為(0,0,-100)運行結果

Scenekit_03.gif

下面我們把它的位置放在(1000,1000,1000) 看一下結果

位置在(1000,1000,1000)

一點變化也沒有,接著下面我們改變一下照射方向,這種光的默認方向為z軸負方向,我們把它設置成Y軸負方向

lightNode.rotation = SCNVector4Make(1, 0, 0, -M_PI/2.0);

看一下運行結果

光照方向Y軸負方向

我相信你已經(jīng)明白了這種光的特點.

第九步.添加聚焦光源

 SCNLight *light = [SCNLight light];// 創(chuàng)建光對象
light.type = SCNLightTypeSpot;// 設置類型
light.color = [UIColor yellowColor]; // 設置光的顏色
light.castsShadow = TRUE;// 捕捉陰影
SCNNode *lightNode = [SCNNode node];
lightNode.position = SCNVector3Make(0, 0, -9); // 設置光源節(jié)點的位置
lightNode.light  = light;
[self.gameView.scene.rootNode addChildNode:lightNode]; // 添加到場景中去

運行結果:

聚焦光源

我們試著使用一下照射范圍的屬性,讓它只照射到球

SCNLight *light = [SCNLight light];// 創(chuàng)建光對象
light.type = SCNLightTypeSpot;// 設置類型
light.color = [UIColor yellowColor]; // 設置光的顏色
light.castsShadow = TRUE;// 捕捉陰影

light.zFar = 10; // 設置它最遠能照射單位10 的地方,也就是說只能照到 球體的位置
SCNNode *lightNode = [SCNNode node];
lightNode.position = SCNVector3Make(0, 0, 0); // 設置光源節(jié)點的位置
lightNode.light  = light;
[self.gameView.scene.rootNode addChildNode:lightNode]; // 添加到場景中去

運行:

讓學習成為一種習慣

有的朋友要問了,那怎么還能看見后面的立方體的,這是因為物體都存在漫反射,這個屬于自然現(xiàn)象,你用手電筒可以去試試!那如何才能讓它看不見后面的立方體呢?設置光的發(fā)射角度,上代碼:

 light.spotOuterAngle = 2;

運行結果:

讓學習成為一種習慣

上面的幾種光的基本特性講解完畢,本節(jié)的內(nèi)容你掌握了嗎?

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容