SCNLight

本节学习目标

今天我们要学习的SceneKit 游戏框架中的几种光以及如何使用它们!

学习任务

  1. 熟悉SCNLight 类
  2. 理解四种光源的作用
  3. 学会如何选择在游戏场景中使用光源.

光的介绍

  • 环境光(SCNLightTypeAmbient)

这种光的特点,没有方向,位置在无穷远处,光均匀的散射到物体上.

  • 点光源(SCNLightTypeOmni)

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

  • 平行方向光(SCNLightTypeDirectional)

只有照射的方向,没有位置,不会衰减

  • 聚焦光源(SCNLightTypeSpot) 可

光源有固定的位置,也有方向,也有照射区域 ,可以衰减

 SCNLight 介绍

我们使用光源,主要用到的类就是SCNLight,我们把这个类的属性分析一下。

  • 创建光对象

    +(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);
    
  • 设置每一帧计算阴影贴图的次数,默认为一次

    @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 //根据最后的颜色决定阴影,一般不太用,除非有多个光源作用的情况下
    SCNShadowModeModulated = 2 //光没有作用,只投射阴影,一般用于图案作为阴影的情况下,比如镜像渐变图像(黑白)
    
  • 阴影的深度偏移量

    @property(nonatomic) CGFloat shadowBias NS_AVAILABLE(10_10, 8_0);
    
  • 平行方向放阴影比例值调节

    @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表示平方减弱
    
  • 聚焦光的发射点的方向和光线强度最弱的时候的夹角
    @property(nonatomic) CGFloat spotInnerAngle  NS_AVAILABLE(10_10, 8_0);// 默认为0度
    @property(nonatomic) CGFloat spotOuterAngle  NS_AVAILABLE(10_10, 8_0);// 默认为45度
    
  • 当你要使用碰撞检测时,请设置下面的属性 ```swift import UIKit import SceneKit

class Test5VC: UIViewController {

var scnView:SCNView?
var lightNode:SCNNode?

override func viewDidLoad() {
    super.viewDidLoad()

    view.backgroundColor = UIColor.white

    setup()
}

func setup() {
    scnView = SCNView(frame: CGRect(x: 0, y: 100, width: view.bounds.width, height: view.bounds.height - 100))
    scnView?.center = CGPoint(x: view.bounds.midX, y: view.bounds.midY)
    scnView?.backgroundColor = UIColor.darkGray
    view.addSubview(scnView!)
    scnView?.allowsCameraControl = true

    let segment = UISegmentedControl(items: ["环境光","点光源","平行方向光","聚焦光源"])
    view.addSubview(segment)
    segment.frame = CGRect(x: 10, y: view.bounds.height - 44, width: view.bounds.width - 20, height: 36)
    segment.addTarget(self, action: #selector(lightTypeChange), for: .valueChanged)

    let scene = SCNScene()
    scnView?.scene = scene

    let box = SCNBox(width: 0.5, height: 0.5, length: 0.5, chamferRadius: 0)
    let boxNode = SCNNode(geometry: box)
    boxNode.position = SCNVector3Make(0, 0, -11)
    boxNode.geometry?.firstMaterial?.diffuse.contents = "art.scnassets/2.jpg"
    scnView?.scene?.rootNode.addChildNode(boxNode)
    scnView?.antialiasingMode = .multisampling4X

    let shpere = SCNSphere(radius: 0.1)
    let shpereNode = SCNNode(geometry: shpere)
    shpereNode.position = SCNVector3Make(0, 0, -10.5)
    shpereNode.geometry?.firstMaterial?.diffuse.contents = "art.scnassets/1.jpg"
    scnView?.scene?.rootNode.addChildNode(shpereNode)
}

@objc func lightTypeChange(sender:UISegmentedControl) {
    if lightNode != nil {
        lightNode?.removeFromParentNode()
    }

    switch sender.selectedSegmentIndex {
    case 0:
        let ambientLight = SCNLight()
        ambientLight.type = .ambient
        ambientLight.color = UIColor.red
        lightNode = SCNNode()
        lightNode?.position = SCNVector3Make(0, 100, 100)
        lightNode?.light = ambientLight
        scnView?.scene?.rootNode.addChildNode(lightNode!)

    case 1:
        let omniLight = SCNLight()
        omniLight.type = .omni
        omniLight.color = UIColor.green
        lightNode = SCNNode()
        lightNode?.position = SCNVector3Make(0, 100, 100)
        lightNode?.light = omniLight
        scnView?.scene?.rootNode.addChildNode(lightNode!)

    case 2:
        let directionalLight = SCNLight()
        directionalLight.type = .directional
        directionalLight.color = UIColor.blue
        lightNode = SCNNode()
        lightNode?.position = SCNVector3Make(0, 100, 100)
        lightNode?.light = directionalLight
        lightNode?.rotation = SCNVector4Make(1, 0, 0, Float(-Double.pi / 2.0))
        scnView?.scene?.rootNode.addChildNode(lightNode!)

    case 3:
        let spotLight = SCNLight()
        spotLight.type = .spot
        spotLight.color = UIColor.yellow
        spotLight.castsShadow = true
        spotLight.zFar = 1000
        spotLight.spotOuterAngle = CGFloat(Double.pi / 4.0)
        lightNode = SCNNode()
        lightNode?.position = SCNVector3Make(0, 0, 100)
        lightNode?.light = spotLight
        scnView?.scene?.rootNode.addChildNode(lightNode!)

    default:
        break
    }
}

} ```

results matching ""

    No results matching ""