SceneKit_入门01_旋转人物
SceneKit_入门02_如何创建工程
SceneKit_入门03_节点
SceneKit_入门04_灯光
SceneKit_入门05_照相机
SceneKit_入门06_行为动画
SceneKit_入门07_几何体
SceneKit_入门08_材质
SceneKit_入门09_物理身体
SceneKit_入门10_物理世界
SceneKit_入门11_粒子系统
SceneKit_入门12_物理行为
SceneKit_入门13_骨骼动画
SceneKit_中级01_模型之间的过渡动画
SceneKit_中级02_SCNView 详细讲解
SceneKit_中级03_切换照相机视角
SceneKit_中级04_约束的使用
SceneKit_中级05_力的使用
SceneKit_中级06_场景的切换
SceneKit_中级07_动态修改属性
SceneKit_中级08_阴影详解
SceneKit_中级09_碰撞检测
SceneKit_中级10_滤镜效果制作
SceneKit_中级11_动画事件
SceneKit_高级01_GLSL
SceneKit_高级02_粒子系统深入研究
SceneKit_高级03_自定义力
SceneKit_高级04_自定义场景过渡效果
SceneKit_高级05 检测手势点击到节点
SceneKit_高级06_加载顶点、纹理、法线坐标
SceneKit_高级07_SCNProgram用法探究
SceneKit_高级08_天空盒子制作
SceneKit_高级09_雾效果
SceneKit_大神01_掉落的文字
SceneKit_大神02_弹幕来袭
SceneKit_大神03_navigationbar上的3D文字
先说几句,由于Swift 3.0 逐渐稳定,我之后所有的教程都会使用Swift 语言,如果学习请移步我亲写的学习教程
学习目标
掌握SceneKit 框架中的三种阴影创建方式
阴影
阴影类型 :静态,动态,投射
- 静态
这个方式很简单,就是给物体节点增加一个子节点,子节点设置一个图片作为它的阴影
- 动态
设置灯光的属性castsShadow 为YES 则,物体移动时,阴影也会跟着变化
- 投射
通过设置灯光的属性gobo,来捕捉阴影
一起敲代码
- 第一步 先创建工程
- 第二步 添加库SceneKit
- 第三步 创建游戏视图
let scnView = SCNView(frame: self.view.bounds)
scnView.backgroundColor = UIColor.black
self.view.addSubview(scnView)
- 第四步 创建游戏场景
let scene = SCNScene()
scnView.scene = scene
- 第五步 创建一个照相机
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
cameraNode.camera?.automaticallyAdjustsZRange = true
cameraNode.position = SCNVector3(x: 0, y: 1000, z: 1000)
cameraNode.rotation = SCNVector4(x: 1, y: 0, z: 0, w: -Float(M_PI/4))
scnView.scene?.rootNode.addChildNode(cameraNode)
提示:
摄像机默认方向为 -Z 轴, 我设置它的位置为(0,1000,1000) ,沿自身坐标系x轴顺时针旋转了45度,这个是由于我的模型比较大,一般摄像机的位置是根据模型的大小进行调节的。
- 第六步 创建一个聚光灯
/// 1.先创建一个灯罩
let cone = SCNCone(topRadius: 1, bottomRadius: 25, height: 50)
cone.radialSegmentCount = 10
cone.heightSegmentCount = 5
/// 2.创建一个灯节点
let spotLight = SCNNode()
spotLight.geometry = cone
spotLight.geometry?.firstMaterial?.emission.contents = UIColor.yellow
spotLight.position = SCNVector3(0, 0, 0)
spotLight.light = SCNLight()
spotLight.light?.type = .spot
spotLight.light?.castsShadow = true
spotLight.light?.shadowMode = .forward
spotLight.light?.spotOuterAngle = 60
spotLight.light?.zFar = 2000
/// 创建一个支点,放等源
let handleSpot = SCNNode()
handleSpot.position = SCNVector3(0, 1000, 40)
handleSpot.addChildNode(spotLight)
scnView.scene?.rootNode.addChildNode(handleSpot)
提示:
灯光对象的属性 shadowMode 默认为.forward,如果你设置了这个属性,灯光效应下的阴影效果才能呈现出来,它会根据灯光效应去调节阴影颜色的阿尔法分量值
问题1:知道为什么要设置灯光的最远距离为2000吗?
因为灯光的最远注意默认值为100 ,由于我们将灯的指点放在1000 灯光照射不到那个距离,所以我们需要调节灯光照射的最远距离
问题2:为什么要给灯光添加一个支点,不添加可以吗?
不添加支点,是可以的,但是你要给灯光添加约束,让其对着模型,然后,你让这个灯光移动,这个时候,你会发现灯光节点一动不动,这里为什么不动,猜测是,行为和约束都要计算位置和角度,然而两者冲突了,优先使用约束。
- 第七步 为了效果明显,给灯光支点添加一个移动的行为
let moveRight = SCNAction.move(to:SCNVector3(100, 1000, 40) , duration: 2)
let moveLeft = SCNAction.move(to:SCNVector3(-100, 1000, 40) , duration: 2)
let sequence = SCNAction.sequence([moveLeft,moveRight])
handleSpot.runAction(SCNAction.repeatForever(sequence))
- 第八步,添加一个地板,让阴影有地方显示
let floor = SCNFloor()
floor.firstMaterial?.diffuse.contents = "floor.jpeg"
let floorNode = SCNNode(geometry: floor)
scnView.scene?.rootNode .addChildNode(floorNode)
- 第九步 添加一个模型对象到场景中去
let treeNode = SCNScene(named: "palm_tree.dae")?.rootNode.childNode(withName: "tree", recursively: true)
treeNode?.rotation = SCNVector4(x: 1, y: 0, z: 0, w: -Float(M_PI/2))
scene.rootNode.addChildNode(treeNode!)
- 第十步 我们想让灯光在移动过程中一直对着我们的模型,所以我们添加一个约束
let constaint = SCNLookAtConstraint(target: treeNode)
spotLight.constraints = [constaint]
友情提示:
各位小伙伴,注意了,一定要搞清楚这个约束谁是执行者添加给谁,这里的执行是是灯光节点自己,不是支点
以上我们演示了动态阴影的实现过程,我们运行看一下效果
接下来演示一下,让灯光发射有形状的光
- 随便找一张图片
- 修改上面的灯光代码
spotLight.light?.castsShadow = false
spotLight.light?.gobo?.contents = "mip.jpg"
spotLight.light?.gobo?.intensity = 0.65
运行效果
提示
一般如果我们使用这种效果的话,需要做如下设置
spotLight.light?.shadowMode = .modulated
再次运行
今天我们的内容就学习到这里,希望对你有所帮助!