上一節的3D幾何模型,看起來感覺與真實物件還有點距離,差在哪裡呢?這些模型有其形而無其質,外表就像用黏土捏出來的粗胚,既未上色,又缺乏質感。如何讓3D模型具有真實的外觀呢?其中關鍵就在燈光與材質。
本節想要製作一個大理石巧克力口味的甜甜圈,先看看下圖執行的結果,不管是光影、紋理、色澤,是不是比起上一節逼真多了:
要讓3D模型展現真實質感,理論上並不容易,因為要考慮色澤、材質、表面紋理、反光特性、光源角度…等等非常多因素,想想看,若僅靠(視覺)圖片,我們如何區分同樣紅色的蘋果與籃球?當然只能靠外觀 — 兩者的形狀、圖案(紋理)、表面(光滑或粗糙、會不會反光)等不同特性。
這也是過去50年來研究3D繪圖的核心課題,所幸,經過多年的發展,困難的部分都已在 SceneKit 套件中解決了,現在很輕易就能用 Swift 程式做出逼真的3D模型。
有多容易呢?只要寫20幾行即可,完整程式碼如下:
// 6-1c 材質(SCNMaterial)與燈光(SCNLight)
// Created by Heman, 2024/03/05
import SceneKit
import SwiftUI
struct 材質與燈光: View {
let 幾何場景 = SCNScene()
var body: some View {
SceneView(scene: 幾何場景, options: [.allowsCameraControl])
.onAppear {
let 甜甜圈 = SCNTorus(ringRadius: 1.0, pipeRadius: 0.4)
let 甜甜圈節點 = SCNNode(geometry: 甜甜圈)
甜甜圈節點.rotation = SCNVector4(x: 1.0, y: 0.0, z: 1.0, w: .pi/3)
let 大理石材質 = SCNMaterial()
大理石材質.diffuse.contents = UIImage(named: "大理石紋")
大理石材質.specular.contents = UIColor.white
甜甜圈.materials = [大理石材質]
let 光源 = SCNLight()
let 燈光節點 = SCNNode()
燈光節點.light = 光源
燈光節點.position = SCNVector3(x: 0, y: 10, z: 0)
幾何場景.rootNode.addChildNode(甜甜圈節點)
幾何場景.rootNode.addChildNode(燈光節點)
幾何場景.background.contents = UIColor.green
}
}
}
import PlaygroundSupport
PlaygroundPage.current.setLiveView(材質與燈光())
這其中,讓甜甜圈改頭換面的關鍵,就是用 SceneKit 的材質物件 SCNMaterial:
let 大理石材質 = SCNMaterial()
大理石材質.diffuse.contents = UIImage(named: "大理石紋")
大理石材質.specular.contents = UIColor.white
甜甜圈.materials = [大理石材質]
SCNMaterial 物件有非常多屬性(30+個,畢竟影響質感的因素很多),其中有3個最基本,是材質外觀的主要屬性:
其它屬性則用來修飾細部或特殊效果,例如本範例將高光部位(.specular)設為白色,讓反光更顯眼。材質的屬性內容(contents)可以設定為某個數值、顏色、圖片、影片或甚至動畫效果。