獲取示例代碼
前言
前面我們介紹了幾何體的相關(guān)知識(shí)胜蛉,這篇我將為大家介紹材質(zhì),那什么是材質(zhì)呢色乾?簡單來說誊册,就是你的幾何體的外觀,比如是什么顏色暖璧,反光強(qiáng)度等等案怯。那么在SceneKit中我們可以改變幾何體的哪些外觀呢?接下來我將一一介紹澎办。
光照模型
提到材質(zhì)就不得不提到光照模型嘲碱。在現(xiàn)實(shí)生活中,我們有太陽局蚀,日光燈麦锯,蠟燭等可以產(chǎn)生光的光源,光照射在物體上琅绅,不同的物體呈現(xiàn)出不同的質(zhì)感扶欣,這些都是很平常的事情。但是在計(jì)算機(jī)里,想要使用光源照射3D模型料祠,產(chǎn)生出想要的質(zhì)感就不是那么平常了骆捧。在OpenGL中,我們需要使用Shader根據(jù)提供的材質(zhì)參數(shù)和光照來計(jì)算每個(gè)像素的顏色髓绽,從而產(chǎn)生物體被光照射的感覺敛苇。想要了解Shader中是如何實(shí)現(xiàn)光照模型的可以看我的兩篇文章基本光照和高級光照。其中有涉及到lambert和blinn兩種光照模型顺呕。下面我將結(jié)合SceneKit簡單的介紹這兩種光照模型枫攀。
Lambert
在SceneKit中,使用SCNMaterial
來表示材質(zhì)塘匣。SCNMaterial
的一個(gè)屬性lightingModel
表示的就是使用何種光照模型巷帝。如果我們選擇Lambert光照模型忌卤,并且設(shè)置如下屬性驰徊,并且把material賦給球形幾何體geometry
。
let material = SCNMaterial()
material.lightingModel = .lambert
material.diffuse.contents = UIColor.red
material.ambient.contents = UIColor.init(white: 0.1, alpha: 1)
material.locksAmbientWithDiffuse = false
geometry.materials = [material]
那么渲染出來的球體將會(huì)如下所示棍厂。
我們使用的燈光在
(0,6,3)
處超陆,所以球體上面是照射到燈光的,下面是灰色的时呀。這里涉及到了兩個(gè)光照分量,diffuse
和ambient
谨娜。diffuse
表示幾何體的本色,所以燈光照射到的部分就是本色紅色趴梢,注意我用的燈光是白色的漠畜,如果燈光是其他顏色,則會(huì)和幾何體的本色混合坞靶,也就是兩個(gè)顏色進(jìn)行3維向量乘法憔狞。那燈光照射不到的地方呢?就是ambient
環(huán)境光彰阴。環(huán)境光的出現(xiàn)是為了讓燈光照射不到的地方不會(huì)是全黑瘾敢,你可以試試把環(huán)境光改成其他顏色,看看渲染結(jié)果如何。由于PBR光照模型中ambient
和diffuse
是鎖定的廉丽,所以需要把locksAmbientWithDiffuse
設(shè)置為false
倦微,否則ambient
只能和diffuse
取相同的值。關(guān)于PBR光照模型我會(huì)在后面的文章單獨(dú)介紹正压。最后將material
賦值給幾何體欣福,這里material
是被放在一個(gè)數(shù)組里賦值的,如果你的幾何體有多個(gè)element焦履,系統(tǒng)會(huì)根據(jù)順序?yàn)槊總€(gè)element提供不同的材質(zhì)拓劝。第n個(gè)element會(huì)得到第n%材質(zhì)個(gè)數(shù)
個(gè)材質(zhì)。
diffuse還和法線相關(guān)嘉裤,法線和光線的夾腳越小郑临,則越亮。法線就是上一篇代碼里的
normals
屑宠。
總的來說厢洞,Lambert模型就是最終顏色=光線和法線夾腳系數(shù)*光照顏色*本色diffuse + 環(huán)境色ambient
。
Blinn
Blinn光照模型其實(shí)就是在lambert基礎(chǔ)上加上高光典奉,我們將光照模型修改為.blinn
躺翻,再設(shè)置高光的屬性。
material.lightingModel = .blinn
material.specular.contents = UIColor.white
material.shininess = 1.0
當(dāng)光線被反射后和我們視線的夾腳比較小的時(shí)候卫玖,在金屬或者玻璃等反光材質(zhì)下公你,會(huì)看到非常亮的區(qū)域,我們稱之為高光假瞬。越是光滑的物體陕靠,高光區(qū)域會(huì)越小。我們用shininess
來表示物體的表面有多閃(光滑)脱茉,它的值從0到1剪芥。值越大,越光滑芦劣。下面是值為0.2和1的效果圖粗俱。material.specular
表示高光的顏色,不過最終呈現(xiàn)的高光顏色受material.specular
和燈光的顏色共同影響寸认,是它們顏色值的三維向量相乘偏塞。
材質(zhì)參數(shù)的取值
上面我只給材質(zhì)的參數(shù)賦予了顏色值灸叼,除了顏色古今,還可以賦予貼圖,或者說是圖片氓拼。diffuse
和specular
都是可以接受圖片對象的抵碟。比如給diffuse
賦值一張地球的貼圖。
material.diffuse.contents = UIImage.init(named: "earth.jpg")
效果如下撬统。
specular接受的貼圖就比較特殊,是一張黑白兩色的圖颅崩。圖中黑色對應(yīng)的地方將沒有高光蕊苗。
下面兩張圖分別是使用了和沒使用specular貼圖的效果圖朽砰。第一張圖中明顯大海部分沒有高光。
不管是什么貼圖,都是需要幾何體提供UV數(shù)據(jù)的造锅,也就是所謂的貼圖坐標(biāo)哥蔚,在上一篇的代碼中有涉及到。
let uvs: [CGPoint] = [
CGPoint(x: 0, y: 1),
CGPoint(x: 0, y: 0),
CGPoint(x: 1, y: 0),
CGPoint(x: 1, y: 1),
]
let uvSource = SCNGeometrySource.init(textureCoordinates:
uvs)
系統(tǒng)提供的球形幾何體已經(jīng)有了UV數(shù)據(jù)渤愁,所以才可以輕松的進(jìn)行貼圖抖格,關(guān)于貼圖的更多信息,會(huì)在后面的文章中介紹收奔,或者你也可以去看我寫的基于OpenGL的貼圖文章滓玖。
反射貼圖
SceneKit還提供了反射貼圖功能呢撞,可以使用CubeMap或者SphereMap來當(dāng)作環(huán)境貼圖殊霞。這里我只為大家演示一下,更深入的介紹會(huì)在后面的文章中進(jìn)行棒卷。下面是設(shè)置反射貼圖的代碼祝钢。cube-X.jpg
等圖片都在demo項(xiàng)目中拦英。
material.reflective.contents = [
UIImage.init(named: "cube-1.jpg"),
UIImage.init(named: "cube-2.jpg"),
UIImage.init(named: "cube-3.jpg"),
UIImage.init(named: "cube-4.jpg"),
UIImage.init(named: "cube-5.jpg"),
UIImage.init(named: "cube-6.jpg"),
]
material.fresnelExponent = 1.7
效果圖如下疤估。是不是有一種被玻璃包裹的感覺。反射貼圖主要就是通過對CubeMap或者SphereMap的反射钞瀑,模擬物體反射周圍環(huán)境的一種技術(shù)雕什。
法線貼圖
我們上面有說過我們會(huì)給幾何體提供法線數(shù)據(jù)贷岸,但是這些數(shù)據(jù)是每個(gè)頂點(diǎn)才有一個(gè)吧碾,頂點(diǎn)之間區(qū)域的法線就只能通過線性插值來計(jì)算了倦春。法線貼圖則是通過貼圖的方式來彌補(bǔ)這一缺陷,更多原理性質(zhì)的介紹就不在這展開了尿庐,下面是例子用的法線貼圖。
代碼設(shè)置也很簡單凡泣。
material.normal.contents = UIImage.init(named: "earth_NRM.png")
效果如下鞋拟。是不是瞬間有了凹凸感惹资。
總結(jié)
這篇文章主要介紹了材質(zhì)的一些基本功能褪测,還有很多其他的功能是沒有提到的。東西其實(shí)很多懈叹,要在一篇文章中全部鋪開不現(xiàn)實(shí)澄成,看完這一篇讀者心中對光照模型和材質(zhì)有個(gè)基本了解就可以了环揽。后面的文章會(huì)針對材質(zhì)中比較復(fù)雜的特性逐一進(jìn)行深入介紹庵佣。