Apple Engine

Apple, iPhone, iOS, その周辺のことについて

WWDC 2017 の SceneKit サンプル Fox 2 を調べる その34

引き続き GameController クラスの残りの関数を見てゆく。

今回はクリア時の演出、レンダリングのクオリティ、デバッグの関数について。

 

クリア時の演出

クリア時に Music_victory.mp3 の BGM を 鳴らし、 2D UI の overlay の showEndScreen() 呼び、ロゴと Congratulation の画像を出す。

func showEndScreen() {
    guard let victoryMusic = SCNAudioSource(named: "audio/Music_victory.mp3") else { return }
    victoryMusic.volume = 0.5

    self.scene?.rootNode.addAudioPlayer(SCNAudioPlayer(source: victoryMusic))

    self.overlay?.showEndScreen()
}

 

レンダリングクオリティ設定

いくつかの関数を設定後、イニシャライズ時に呼ぶ configureRenderingQuality の関数でそれらを呼ぶ。
EXR などの tvOS で使用できなものや負荷が多いのを切っている。

以下、設定する関数。

 

SCNMaterialProperty で EXR の拡張子を png にする。

func turnOffEXRForMAterialProperty(property: SCNMaterialProperty) {
    if var propertyPath = property.contents as? NSString {
        if propertyPath.pathExtension == "exr" {
            propertyPath = ((propertyPath.deletingPathExtension as NSString).appendingPathExtension("png")! as NSString)
            property.contents = propertyPath
        }
    }
}

 

バックグラウンドのテクスチャで turnOffEXRForMAterialProperty を使い EXR を止め、全てのマテリアルで自己発光を止める。

func turnOffEXR() {
    self.turnOffEXRForMAterialProperty(property: scene!.background)
    self.turnOffEXRForMAterialProperty(property: scene!.lightingEnvironment)

    scene?.rootNode.enumerateChildNodes { (child: SCNNode, _: UnsafeMutablePointer<ObjCBool>) in
        if let materials = child.geometry?.materials {
            for material in materials {
                self.turnOffEXRForMAterialProperty(property: material.selfIllumination)
            }
        }
    }
}

 

全てのノーマルマップを止める。

func turnOffNormalMaps() {
    scene?.rootNode.enumerateChildNodes({ (child: SCNNode, _: UnsafeMutablePointer<ObjCBool>) in
        if let materials = child.geometry?.materials {
            for material in materials {
                material.normal.contents = SKColor.black
            }
        }
    })
}

 

全ての HDR の処理を止める。

func turnOffHDR() {
    scene?.rootNode.enumerateChildNodes({ (child: SCNNode, _: UnsafeMutablePointer<ObjCBool>) in
        child.camera?.wantsHDR = false
    })
}

 

カメラの被写界深度の効果を止める。

func turnOffDepthOfField() {
    scene?.rootNode.enumerateChildNodes({ (child: SCNNode, _: UnsafeMutablePointer<ObjCBool>) in
        child.camera?.wantsDepthOfField = false
    })
}

 

全てのライトの Shadow Sample を 上限 1 にする。

func turnOffSoftShadows() {
    scene?.rootNode.enumerateChildNodes({ (child: SCNNode, _: UnsafeMutablePointer<ObjCBool>) in
        if let lightSampleCount = child.light?.shadowSampleCount {
            child.light?.shadowSampleCount = min(lightSampleCount, 1)
        }
    })
}

 

全てのポストプロセスを止める。
シャドウキャスケード(カメラ位置によるリアルタイムでのシャドウマップのクオリティの変更)、シャドウマップのサイズを 1024x1024 にする。

func turnOffPostProcess() {
    scene?.rootNode.enumerateChildNodes({ (child: SCNNode, _: UnsafeMutablePointer<ObjCBool>) in
        if let light = child.light {
            light.shadowCascadeCount = 0
            light.shadowMapSize = CGSize(width: 1024, height: 1024)
        }
    })
}

 

画面前面の 2D UI 表示を消す。

func turnOffOverlay() {
    sceneRenderer?.overlaySKScene = nil
}

 

全ての Shader Modifiers を取得し、Geomety のエントリーポイントのシェーダー(Vertex Shader の処理)を消す。

func turnOffVertexShaderModifiers() {
    scene?.rootNode.enumerateChildNodes({ (child: SCNNode, _: UnsafeMutablePointer<ObjCBool>) in
        if var shaderModifiers = child.geometry?.shaderModifiers {
            shaderModifiers[SCNShaderModifierEntryPoint.geometry] = nil
            child.geometry?.shaderModifiers = shaderModifiers
        }

        if let materials = child.geometry?.materials {
            for material in materials where material.shaderModifiers != nil {
                var shaderModifiers = material.shaderModifiers!
                shaderModifiers[SCNShaderModifierEntryPoint.geometry] = nil
                material.shaderModifiers = shaderModifiers
            }
        }
    })
}

 

植物の表示を止める。

func turnOffVegetation() {
    scene?.rootNode.enumerateChildNodes({ (child: SCNNode, _: UnsafeMutablePointer<ObjCBool>) in
        guard let materialName = child.geometry?.firstMaterial?.name as NSString? else { return }
        if materialName.hasPrefix("plante") {
            child.isHidden = true
        }
    })
}

 

tvOS 用に表示クオリティを変えるため、これまで作成した関数を実行する。
SCNView を渡しているが、内部で使用していない。

func configureRenderingQuality(_ view: SCNView) {
        
#if os( tvOS )
    self.turnOffEXR()
    self.turnOffNormalMaps()
    self.turnOffHDR()
    self.turnOffDepthOfField()
    self.turnOffSoftShadows()
    self.turnOffPostProcess()
    self.turnOffOverlay()
    self.turnOffVertexShaderModifiers()
    self.turnOffVegetation()
#endif
}

 

デバッグ処理。
WWDC 2017 のデモ用でそのままでは使用できない。 カメラの F 値、焦点距離、ボタンを押すとカメラの表示位置が変わる。

func fStopChanged(_ value: CGFloat) {
    sceneRenderer!.pointOfView!.camera!.fStop = value
}

func focusDistanceChanged(_ value: CGFloat) {
    sceneRenderer!.pointOfView!.camera!.focusDistance = value
}

func debugMenuSelectCameraAtIndex(_ index: Int) {
    if index == 0 {
        let key = self.scene?.rootNode .childNode(withName: "key", recursively: true)
        key?.opacity = 1.0
    }
    self.setActiveCamera("CameraDof\(index)")
}

 

次回は GameController の最終部分、ゲームコントローラーやゲーム操作部分の関数について見てゆく。