SCNMaterial學習

這個知識點既重要又不那么重要又很重要。攤手。


簡單說,這個屬性就是給geometry貼圖。(下文中的“貼圖”,就是material的意思)

每個SCNMaterial有8個視覺特性,分別對應在明暗過程中不同的貼圖效果。每個視覺特性,都是SCNMaterialProperty的一個實例,可以提供一個顏色或紋理等2D內(nèi)容。SCNMateriallightingModelName也會影響到渲染的最終效果。詳見下文。

可以使用firstMaterial或者materials屬性添加一個或多個貼圖。多個幾何圖形可以用相同的貼圖,這樣修改貼圖就可以同時改變所有使用它的幾何。

創(chuàng)建貼圖

+ (instancetype)material;

創(chuàng)建一個新的貼圖,它的8個視覺特性的默認值參見下文“視覺特性配置”。

+ (instancetype)materialWithMDLMaterial:(MDLMaterial *)mdlMaterial;

根據(jù)MDLMaterial對象創(chuàng)建貼圖。

選擇陰影模型

@property(nonatomic, copy) SCNLightingModel lightingModelName;

光影渲染方式,詳見下。

typedef NSString *SCNLightingModel;

渲染貼圖的燈光和陰影算法的常數(shù)。

Lighting model examples

SCNLightingModelPhysicallyBased:基于現(xiàn)實的抽象效果。
SCNLightingModelPhong:將ambient、diffusespecular結合起來,用Phong公式計算的效果。
SCNLightingModelLambert:只包含ambientdiffuse的效果。
SCNLightingModelConstant:只包含ambient的效果。
SCNLightingModelBlinn:將ambient、diffusespecular結合起來,用Blinn-Phong公式計算的效果。

視覺特性配置

@property(nonatomic, readonly) SCNMaterialProperty *diffuse;

漫射效果。
漫射的意思是光的數(shù)量和顏色均勻地反映在幾何表面的每一點上。它與視角沒有關系,可以理解成是設置基礎顏色或紋理。設置方法為diffuse.content,下同。
默認情況下是白色。下圖顯示的是一個實例,它的其他視覺特性使用的默認值。

Adding a diffuse texture to a material

場景中最終的渲染效果會根據(jù)所有視覺特性、燈光和其他的相關屬性共同決定。

@property(nonatomic, readonly) SCNMaterialProperty *ambient;

環(huán)境效果。
就是貼圖在在環(huán)境燈里映射出的效果。如果場景里沒有SCNLightTypeAmbient的燈光,那這個屬性將沒有效果。
默認情況下是深灰色。修改ambient不是在場景中被燈光照亮,而是直接使貼圖變成對應的顏色或紋理。貼圖默認對散射光和環(huán)境光是相同的,locksAmbientWithDiffuse默認值為YES
如下圖:

Adding an ambient color to a material

@property(nonatomic, readonly) SCNMaterialProperty *specular;

鏡面效果。
用來模擬光澤,可以通過shininess屬性來調(diào)整鏡面的銳度。
默認情況下是黑色,貼圖看起來是陰暗無光澤的。將specular設置成亮色,會讓表面看起來閃閃發(fā)光。當你將圖片設置給specular時,圖片中每個像素點的亮度決定了貼圖上對應點的光澤。
如圖:

Adding a specular map to a material
@property(nonatomic, readonly) SCNMaterialProperty *normal;

輪廓效果。
模擬輪廓效果需要每個點的方向信息。通常,geometry對象上自帶了這些信息,但是這限制了表面輪廓的細節(jié),因為一個幾何形狀只能為每個頂點提供一個法向量。如果增加頂點數(shù),又會增加性能成本。
此外,也可以使用紋理圖片來提供這些信息。由于圖片紋理可以儲存比幾何圖形更詳細的表面信息,我們可以用normal屬性來模擬粗糙的表面,比如石頭,浮雕等。
默認情況下是白色。將normal設置成純色,將根據(jù)幾何形狀進行渲染;將normal設置成圖片或其他紋理圖,將自動設置貼圖的litPerPixel=YES
如圖:

Adding a normal map to a material

@property(nonatomic, readonly) SCNMaterialProperty *reflective;

反射效果。
SceneKit不會渲染對象在場景中的真實映射,我們可以通過reflective來模擬這個效果。
默認情況下是白色,不會有反射的效果。將reflective設置成純色將只會給貼圖添加一層均勻的陰影,要想有反射效果,需要設置成圖片或其他紋理圖。
如圖:

Adding a reflective environment map to a material

@property(nonatomic, readonly) SCNMaterialProperty *emission;

發(fā)光效果。
可以利用圖片紋理來模擬表面發(fā)光的效果。不是說把貼圖當做光源,而是指發(fā)出的光不依賴與光源。想要創(chuàng)建一個看起來發(fā)光的對象,需要將幾何圖形和發(fā)光紋理與其他的光源結合起來。
默認情況下是黑色,沒有發(fā)光效果。將emission設置成純色只會均勻地增加與光源無關的顏色,要想有發(fā)光效果,需要設置成圖片或其他紋理圖,發(fā)光的部分用亮色,其他區(qū)域用暗色。
如圖:

Adding an emissive map to a material

@property(nonatomic, readonly) SCNMaterialProperty *transparent;

透明效果。
這個屬性可以選擇性地讓部分貼圖透明??梢允褂?code>transparency屬性來調(diào)整整體的透明度,或者使用SCNNodeopacity屬性來調(diào)整節(jié)點上的所有內(nèi)容。
默認情況下為黑色,表示完全不透明。將transparent設置成任何純色,會根據(jù)顏色的不透明度來整體淡化貼圖。想要讓部分貼圖透明,需要設置成圖片或其他紋理圖,然后根據(jù)alpha通道調(diào)整透明或不透明的區(qū)域。
如下圖:

Adding a transparent texture to a material

@property(nonatomic, readonly) SCNMaterialProperty *multiply;

后期效果。
在貼圖的其他視覺特性與燈光以及其他相關的場景元素結合之后,將每個渲染的像素與multiply屬性提供的顏色相乘,渲染出最終的效果??梢允褂?br> 默認情況下是白色,表示沒有后期效果。
如下圖:

Adding a multiply color to a material

以上,8個視覺特性介紹完畢。下面還有一些其他特性

@property(nonatomic, readonly) SCNMaterialProperty *ambientOcclusion;

環(huán)境遮罩。
將一個環(huán)境遮罩紋理映射到表面。如果場景中沒有環(huán)境光(SCNLightTypeAmbient),這個屬性沒有效果。
如果這個屬性不是nil,SceneKit會忽略ambient屬性。

@property(nonatomic, readonly) SCNMaterialProperty *selfIllumination;

自照明。
這個屬性適用于所有貼圖。對于某些貼圖來說,讓它們自照明是很有必要的,比如光源被遮住的時候,如果設置了selfIllumination,它們可以通過其他的光來渲染效果。

@property(nonatomic, readonly) SCNMaterialProperty *metalness;

金屬材質(zhì)。
可以把這個屬性理解成折射指數(shù)。越高的值(越亮的顏色)會使表面看起來越有金屬感。
僅在lightingModelName=SCNLightingModelPhysicallyBased 時適用。

@property(nonatomic, readonly) SCNMaterialProperty *roughness;

平滑度。
可以把這個屬性理解成細節(jié),比如表面的突起或裂縫。通過這個屬性有助于亮度的計算,可以更真實地在粗糙或光滑的表面渲染效果。
僅在lightingModelName=SCNLightingModelPhysicallyBased 時適用。

@property(nonatomic, readonly) SCNMaterialProperty *displacement;
displacement

這個是iOS11的新特性,API沒有說明,我也沒用過。以后再補充。

自定義貼圖

@property(nonatomic, copy) NSString *name;

貼圖的名字。

@property(nonatomic) CGFloat shininess;

鏡面效果的銳度。
詳見上文的specular。

@property(nonatomic) CGFloat fresnelExponent;

反射效果的反射率。
詳見上文的reflective。

@property(nonatomic) CGFloat transparency;

透明效果的透明度。
詳見上文的transparent。

@property(nonatomic) SCNTransparencyMode transparencyMode;

用來計算透明度的模式。

typedef enum SCNTransparencyMode : NSInteger {
    SCNTransparencyModeAOne = 0,
    SCNTransparencyModeRGBZero = 1,
    SCNTransparencyModeSingleLayer = 2,
    SCNTransparencyModeDualLayer = 3,
    SCNTransparencyModeDefault = SCNTransparencyModeAOne
} SCNTransparencyMode;

SCNTransparencyModeAOne:從顏色的alpha通道獲取透明度信息。1是不透明。默認值。
SCNTransparencyModeRGBZero:從顏色的亮度中獲取透明度信息。0是不透明。
SCNTransparencyModeDualLayerSCNTransparencyModeSingleLayer也是iOS11新特性,API還沒有說明。

@property(nonatomic, getter=isLitPerPixel) BOOL litPerPixel;

是否會每個點單獨照明。詳見上文normal。
默認YES,將提供更好的呈現(xiàn)效果,但是比較耗性能。改成NO會在幾何圖形的每個頂點進行照明??梢蕴岣咪秩拘阅堋?/p>

@property(nonatomic, getter=isDoubleSided) BOOL doubleSided;

是不是渲染兩面。
幾何圖形分為內(nèi)、外兩面。根據(jù)幾何和相機的位置決定哪一面是可見的。
默認NO,只渲染外表面,改為YES后,將渲染內(nèi)外兩面,此時從幾何內(nèi)部仍然可以觀察的渲染效果。

@property(nonatomic) SCNCullMode cullMode;

剔除模式,就是不渲染哪一面。

typedef enum SCNCullMode : NSInteger {
    SCNCullModeBack = 0,
    SCNCullModeFront = 1
} SCNCullMode;

通常情況下,幾何的內(nèi)表面封閉在幾何圖形內(nèi),是不可見的。因此渲染內(nèi)表面并沒有明顯的效果,還會消耗性能。
該屬性的默認值是SCNCullBack,即不渲染內(nèi)表面。測試發(fā)現(xiàn),當doubleSided==YES時,這個屬性無效。

@property(nonatomic) SCNBlendMode blendMode;

混合模式。貼圖像素和其他的像素顏色混合的模式。

typedef enum SCNBlendMode : NSInteger {
    SCNBlendModeAlpha = 0,
    SCNBlendModeAdd = 1,
    SCNBlendModeSubtract = 2,
    SCNBlendModeMultiply = 3,
    SCNBlendModeScreen = 4,
    SCNBlendModeReplace = 5,
    SCNBlendModeMax = 6
} SCNBlendMode;

SCNBlendModeAlpha默認值,將兩個像素的顏色值相乘。
SCNBlendModeAdd:將源顏色添加到目標顏色上。類似發(fā)光的效果。
SCNBlendModeSubtract:從目標顏色中減去源顏色。
SCNBlendModeMultiply:將源顏色與背景顏色相乘。
SCNBlendModeScreen:將源顏色的反色與目標顏色的反色相混合。
SCNBlendModeReplace:用源顏色替換目標顏色,忽略alpha。

@property(nonatomic) BOOL locksAmbientWithDiffuse;

是否讓環(huán)境光與漫射光相同。
在模擬真實燈光時,通常物體表面會有單一的基礎顏色或者紋理。
當這個屬性為NO時就沒有這個限制,可以使用diffuse屬性提供一種顏色或紋理,用ambient屬性提供另一種顏色或紋理。
當這個屬性是YES,或者在SCNLightingModelPhysicallyBased模式時,將忽略ambient屬性,以確保只會有一種顏色或紋理。
這個屬性在OS X v10.9以前默認值是NO,之后的版本是YES。

@property(nonatomic) BOOL writesToDepthBuffer;

在渲染貼圖時是否產(chǎn)生深度信息。
默認值是YES。

@property(nonatomic) BOOL readsFromDepthBuffer;

在渲染貼圖時是否使用深度信息。
默認值是YES。

@property(nonatomic) SCNColorMask colorBufferWriteMask;
typedef enum SCNColorMask : NSInteger {
    SCNColorMaskNone = 0,
    SCNColorMaskRed = 0x1 << 3,
    SCNColorMaskGreen = 0x1 << 2,
    SCNColorMaskBlue = 0x1 << 1,
    SCNColorMaskAlpha = 0x1 << 0,
    SCNColorMaskAll = 0xf
} SCNColorMask;
@property(nonatomic) SCNFillMode fillMode;
typedef enum SCNFillMode : NSUInteger {
    SCNFillModeFill = 0,
    SCNFillModeLines = 1
} SCNFillMode;

以上幾個屬性也是iOS11新特性,API還沒有說明。


綜上,其實蘋果自己對自己的API也不太上心,都沒完全完成就發(fā)布了。以上部分API自己也并沒有理解透徹,如有理解不正確的地方,感謝斧正。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容