SceneKit_中级08_阴影详解

2022-05-13 16:06:30 浏览数 (2)

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

让学习成为一种习惯

  • 第三步 创建游戏视图
代码语言:javascript复制
    let scnView = SCNView(frame: self.view.bounds)
    scnView.backgroundColor = UIColor.black
    self.view.addSubview(scnView)
  • 第四步 创建游戏场景
代码语言:javascript复制
    let scene = SCNScene()
    scnView.scene = scene
  • 第五步 创建一个照相机
代码语言:javascript复制
    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度,这个是由于我的模型比较大,一般摄像机的位置是根据模型的大小进行调节的。

  • 第六步 创建一个聚光灯
代码语言:javascript复制
    /// 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:为什么要给灯光添加一个支点,不添加可以吗?

不添加支点,是可以的,但是你要给灯光添加约束,让其对着模型,然后,你让这个灯光移动,这个时候,你会发现灯光节点一动不动,这里为什么不动,猜测是,行为和约束都要计算位置和角度,然而两者冲突了,优先使用约束。

  • 第七步 为了效果明显,给灯光支点添加一个移动的行为
代码语言:javascript复制
 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))
  • 第八步,添加一个地板,让阴影有地方显示
代码语言:javascript复制
let floor = SCNFloor()
floor.firstMaterial?.diffuse.contents = "floor.jpeg"
let floorNode = SCNNode(geometry: floor)
scnView.scene?.rootNode .addChildNode(floorNode)
  • 第九步 添加一个模型对象到场景中去
代码语言:javascript复制
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!)
  • 第十步 我们想让灯光在移动过程中一直对着我们的模型,所以我们添加一个约束
代码语言:javascript复制
let constaint = SCNLookAtConstraint(target: treeNode)
 spotLight.constraints = [constaint]

友情提示:

各位小伙伴,注意了,一定要搞清楚这个约束谁是执行者添加给谁,这里的执行是是灯光节点自己,不是支点

以上我们演示了动态阴影的实现过程,我们运行看一下效果

让学习成为一种习惯

接下来演示一下,让灯光发射有形状的光

  • 随便找一张图片

让学习成为一种习惯

  • 修改上面的灯光代码
代码语言:javascript复制
spotLight.light?.castsShadow = false
spotLight.light?.gobo?.contents = "mip.jpg"
spotLight.light?.gobo?.intensity = 0.65

运行效果

让学习成为一种习惯

提示

一般如果我们使用这种效果的话,需要做如下设置

代码语言:javascript复制
spotLight.light?.shadowMode = .modulated

再次运行

Scenekit_11.gif

今天我们的内容就学习到这里,希望对你有所帮助!

0 人点赞