SCNLight
本节学习目标
今天我们要学习的SceneKit 游戏框架中的几种光以及如何使用它们!
学习任务
- 熟悉SCNLight 类
- 理解四种光源的作用
- 学会如何选择在游戏场景中使用光源.
光的介绍
- 环境光(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
}
}
} ```