第十一节 - 材质对几何模型的影响

材质对几何模型的影响

我们先建立一个工程,然后在聊。

第一步,创建游戏专用视图

    SCNView *scnView  = [[SCNView alloc]initWithFrame:self.view.bounds];
    scnView.backgroundColor = [UIColor blackColor];
    scnView.scene = [SCNScene scene];
    [self.view addSubview:scnView];

第二步,创建摄像头

  // 创建摄像头
  SCNCamera *camera = [SCNCamera camera];
  SCNNode *cameraNode = [SCNNode node];
  cameraNode.camera = camera;
  cameraNode.position = SCNVector3Make(0, 0, 5);
  [scnView.scene.rootNode addChildNode:cameraNode];

第三步:添加一个球体模型到视图中

    SCNSphere *sphere = [SCNSphere sphereWithRadius:1];
    SCNNode *sphereNode = [SCNNode nodeWithGeometry:sphere];
    [scnView.scene.rootNode addChildNode:sphereNode];

运行一下:

[图片上传中...(image-4ca708-1510628124400-23)]

准备工作已经做好,接下来,正式进入我们今天的内容


材质详解

我们需要了解两个类SCNMaterialProperty 和 SCNMaterial * SCNMatrialProperty

有什么用?

1.包含颜色,纹理和其他可视元素等材质属性
2.控制纹理的包装、过滤和纹理坐标变换
3.纹理的可视属性决定了物体在灯光和阴影下的样子

设置纹理属性的方法有哪些?(contents)

1.使用UIImage (可以直接设置图片的名称)
2.六个图片的数组
3.Core Animation 的layer 对象
4.Sprite Kit 纹理提供的静态图片

在什么地方可以使用SCNMatrialProperty

1.材质属性
2.SCNScene 的background
3.SCNLight的gobo属性
4.绑定纹理采样器自定义GLSL着色器源代码片段 在类中实现 SCNShadable 属性

a.如何创建纹理属性

+ (instancetype)materialPropertyWithContents:(id)contents

提示:

也可以使用GLSL 创建,由于内容过于多,暂时不讲,中级篇也不讲,高级会详细讲解。

b.纹理的属性的内容

var contents: AnyObject?

可以为一下几个对象

颜色(NSColor/UIColor / CGColorRef)
图片(NSImage/UIImage/CGImageRef)
图片名称(NSString)或者路径(NSURL)
图片数组(NSArray)
核心动画层(CALayer)
纹理(SKText,MDLTexture,MTLTexture,GLKTextureInfo)
2D 场景(SKScene)

注意

1.如果设置图片数组时,这个图片必须为六张,并且大小要一致
2.Core Animation layer 使用 AVPlayerLayer
或者AVCaptureVideoPreviewLayer 呈现 捕捉到的视频画面 3.可以动态的改变contents

c.设置材质性能因子(取值范围0-1,默认值为1)

var intensity: CGFloat

会产生什么影响呢?

1.normal 属性,强度变化的正常映射的表面的表观粗糙度。降低强度使表面显得更光滑
2.multiply 使用白色降低强度混物的材料性的颜色,有效降低颜色乘法效应强度
3.对于其他属性,会让内容变暗淡

怎么动态的改变属性内容呢?

千万别着急,现在还不是时候.中级篇会讲

d.转换应用材料属性的内容

@property(nonatomic) SCNMatrix4 contentsTransform

先给两张图理解一下,它干的事情吧,之后练习中我们再详细介绍它都可以进行哪些变化. 它变换的到底是什么:

纹理坐标对应显示的图片区域的大小

[图片上传中...(image-ba24de-1510628124399-22)]

[图片上传中...(image-f47556-1510628124399-21)]

e.包装模式(纹理坐标的的包装行为)

帮你理解一下

比如正方体的表面是100 我们提供的图片是50 这是我们可以,一种是原图显示,或者放大显示,或者重复显示,这个包装模式就是控制这些显示方式的.

var wrapS: SCNWrapMode // 控制水平
var wrapT: SCNWrapMode // 控制垂直
默认的值为:SCNWrapModeClamp.

我们看一下都有哪些可选项:

typedef enum {
//纹理坐标超高系统产生颜色的范围,将使用纹理边缘的颜色填充
 SCNWrapModeClamp = 1,
// 当纹理坐标超高系统产生颜色的范围,将重复使用纹理图片
 SCNWrapModeRepeat = 2,  
//当纹理坐标超高系统产生颜色的范围 使用指定的颜色填充
 SCNWrapModeClampToBorder = 3,
// 当纹理左边超过系统差生颜色的范围,将翻转纹理图片
 SCNWrapModeMirror = 4, 
 } SCNWrapMode;

注意:

使用SCNWrapModeClampToBorder 时,使用borderColor 属性的颜色,代替超过图片之外的颜色。

f.纹理滤波

这个属性有什么用?

当材料表面的部分出现较大或小于原来的纹理图像时,纹理过滤决定了材料属性的内容的外观

@property(nonatomic) SCNFilterMode minificationFilter

可选项

typedef enum : NSInteger {
 //
 SCNFilterModeNone = 0,
 // 当这个位置没有纹理颜色时,会采样离他最近的颜色值
 SCNFilterModeNearest = 1,
 //当这个位置没有纹理颜色时,线性插值颜色作为自己的颜色
 SCNFilterModeLinear = 2,
} SCNFilterMode;

默认值为 SCNFilterModeLinear

mipmap滤波

var mipFilter: SCNFilterMode

有什么用?

当材料表面的部分出现较大或小于原来的纹理图像时,纹理过滤决定了材料属性的内容的外观 , 主要针对(mipmap) Mipmap(有时候拼写成mipmap)是一种电脑图形图像技术,用于在三维图像的二维代替物中达到立体感效应

mipmap 有多厉害

可以增加渲染的性能:当渲染的图片比较小时,SceneKit 会自动创建若干个mipmap层,给材质属性的图片内容,渲染的时候,SceneKit 会自动采样mipmap层

可选值为

typedef enum : NSInteger {
SCNFilterModeNone = 0, // 默认值 不用mipmap
 SCNFilterModeNearest = 1,
 SCNFilterModeLinear = 2, // 线性
} SCNFilterMode;

给张图理解一下

[图片上传中...(image-cdc24-1510628124399-20)]

非均质性(各向异性)纹理滤波

var maxAnisotropy: CGFloat

你应该了解的?

1.用来过滤、处理当视角变化导致3D物体表面倾斜时造成的纹理错误
2.各向异性滤波,可以提供纹理渲染质量,当纹理的表面出现在一个相对于相机的极端角度,这时往往是通过采样多个mipmap层渲染每个像素,提高渲染质量,但是消耗的渲染的成本。
3.SceneKit自动增加或降低需要最大限度地提高渲染质量渲染每个像素的各向异性,由该属性指定的限制,渲染时所使用的最大各向异性水平依赖于使用中的图形硬件,如果设置值为MAXFloat 约束使用最高的GPU 支持的 各向异性的值.
4.maxAnisotropy的值小于等于1 则禁止使用各向异性

注意:

如果使用各向异性滤波,必须使用mipmap ,也就是说mipFilter 的值不能为SCNFilterModeNone.

给张图理解一下各向异性

[图片上传中...(image-d6800c-1510628124399-19)]

纹理通道

@property(nonatomic) NSInteger mappingChannel

先解释一下这属性

几何对象可能有多个纹理坐标源,每个都对应一个独一无二的通道数字,你可以使用这些通道数字,去绘制材质的内容通过不同的方式

举个例子帮你理解一下:

[图片上传中...(image-4587cd-1510628124399-18)]

很简单:

表示一个相框的一个几何体可能会使用一组纹理坐标来映射相框架本身的材质,另一组纹理坐标用于将图片放置到框架中

到目前为止,我们把SCNMatrialProperty的属性内容,已经全部讲解完毕,你理解了没?接下来,我们还要学习一个特别重要的类(SCNMaterial)

SCNMaterial

上面的工程建好的你,可以跟着下面的步骤做。

讲解这个类,我们换一种方式,我喜欢图文并茂,我相信你也喜欢。

这几点你要记牢了

1.材质可以在多个几何体重复使用
2.它是管理光线和阴影属性以及决定几何表面呈现出来的样子
3.一个几何体可以设置多个材质

a.漫发射属性(diffuse) 我们有一样图片是这样的:

[图片上传中...(image-4fc0b6-1510628124399-17)]

上代码:

sphere.firstMaterial.diffuse.contents = @"earth-diffuse.jpg";

运行结果:

[图片上传中...(image-5e1304-1510628124399-16)]

总结一下:

1.这个属性设置的几何体的基本的颜色,好比是你穿的衣服。
2.如果你不设置这个属性,它默认的contents内容是颜色white

其实它的过程像穿衣服一样

[图片上传中...(image-a603b4-1510628124399-15)]

影响环境光的相应属性(ambient)

先上代码:

  sphere.firstMaterial.locksAmbientWithDiffuse = YES;
  sphere.firstMaterial.ambient.contents = [UIColor blueColor];

  // 添加环境光
   SCNNode *ambientlightNode = [SCNNode node];
   ambientlightNode.light =[SCNLight light];
   ambientlightNode.light.type = SCNLightTypeAmbient;
   [scnView.scene.rootNode addChildNode:ambientlightNode];

给张图理解一下

[图片上传中...(image-475029-1510628124399-14)]

镜面材质属性(高光)

有什么效果?

当光照射到物体表面是,物体反射出来颜色

添加一张高光照片

[图片上传中...(image-c62f29-1510628124399-13)]

上代码:

sphere.firstMaterial.specular.contents = @"earth-specular.jpg";

运行结果:

[图片上传中...(image-5534ed-1510628124399-12)]

小提示:

如果你想要所有部分全部显示高光,你可以给他设置白色

再给张图理解一下

[图片上传中...(image-e8abb0-1510628124399-11)]

设置法线取向

理解:

1.按理来说,我们的法线都是垂直我们的表面的,通过这个属性,可以模拟光在每个顶点的取向。
2.可以通过纹理图片作为法线地图,使用RGB 表示 XYZ

下图就是一样模拟法线坐标的图像

[图片上传中...(image-34ccfc-1510628124399-10)]

映射(reflectiv)

你可以这样理解:

给材质外边加一个罩子,光能透过这个罩子照射到物体上,比如映射属性为白色反射所有光,所以你看不见任何颜色,黑色吸收任何光,光能照射到物体上,物体能反射光,所以你能看见。 下面是一张反射属性纹理图:

[图片上传中...(image-9a5b56-1510628124399-9)]

代码:

sphere.firstMaterial.reflective.contents = @"earth-reflective.jpg";
// 映射因子没有上限值
sphere.firstMaterial.fresnelExponent = 10;

执行结果:

[图片上传中...(image-8e2d3b-1510628124399-8)]

设置自身发光

特点:

自己能发光,不能照亮别的物体

首先我们添加一个黑色的聚光灯

 SCNNode *spotLightNode = [SCNNode node];
spotLightNode.position = SCNVector3Make(0, 50, 0);
spotLightNode.rotation = SCNVector4Make(1, 0, 0, -M_PI/2.0);
spotLightNode.light = [SCNLight light];
spotLightNode.light.color = [UIColor blackColor];
spotLightNode.light.type = SCNLightTypeSpot;
[scnView.scene.rootNode addChildNode:spotLightNode];

运行结果:

[图片上传中...(image-77c75e-1510628124399-7)]

我们添加一个自身发光的纹理图片

[图片上传中...(image-7d79db-1510628124399-6)]

代码:

sphere.firstMaterial.emission.contents = @"earth-emissive.jpg";

设置材质的透明度

什么意思?

也就是说,让这个几何物体的部分或者全部能变成透明的,不好理解看图

上代码:

sphere.firstMaterial.transparent.contents = @"cloudsTransparency.png";
sphere.firstMaterial.transparencyMode = SCNTransparencyModeRGBZero;
// 设置透明比例 0为不透 没有上限
 sphere.firstMaterial.transparency = 2;

运行结果:

[图片上传中...(image-49229c-1510628124399-5)]

[图片上传中...(image-6afaca-1510628124399-4)]

设置一个颜色值和物体着色完成够的值相乘

我们先给物体添加一个自身材质属性和发光材质属性

 sphere.firstMaterial.diffuse.contents = @"earth-diffuse.jpg" ;
 sphere.firstMaterial.emission.contents = @"earth-emissive.jpg";

运行结果:

[图片上传中...(image-b0bd0c-1510628124399-3)]

接下来,我们让这个结果和绿色相乘

 sphere.firstMaterial.multiply.contents = [UIColor greenColor];

运行结果:

[图片上传中...(image-3094bc-1510628124399-2)]

设置自照明

注意:

如果selfIllumination属性不为nil, emission 属性则不起作用 代码: // 把所用的光照全部去掉 sphere.firstMaterial.selfIllumination.contents = [UIColor blueColor];

运行结果:

[图片上传中...(image-eabdcc-1510628124398-1)]

材质可以有名字的

@property(nonatomic, copy) NSString *name

如何渲染球体内部

  // 默认渲染一边
  sphere.firstMaterial.doubleSided = true;
 // 剔除正面
  sphere.firstMaterial.cullMode = SCNCullFront;
 // 剔除反面

sphere.firstMaterial.cullMode = SCNCullBack;

混合渲染模式

确定如何使用这种材料的像素颜色与渲染目标中的其他像素颜色混合的模式

enum SCNBlendMode : Int {
case Alpha // 默认值
case Add
case Subtract
case Multiply
case Screen
case Replace
}

渲染材质是否产生深度信息

// 默认YES
var writesToDepthBuffer: Bool
@property(nonatomic) BOOL writesToDepthBuffer
// 渲染是否优先读取深度信息 默认为YES
var readsFromDepthBuffer: Bool

光照模式

NSString *const SCNLightingModelPhong 
NSString *const SCNLightingModelBlinn
NSString *const SCNLightingModelLambert 
NSString *const SCNLightingModelConstant

[图片上传中...(image-81e518-1510628124398-0)]

每个都有对应的计算公式,举个例子,比如SCNLightingModelBlinn

color = ambient* al + diffuse* max(0, dot(N, L)) + specular*pow(max(0, dot(H, N)), shininess)

可能暂时用不到,用到了再去官方资料查找就好了。

本节的内容有点多,理解不了没有关系,在使用过程中慢慢体会就行,后面我们大量使用今天的内容,既然开始了,就坚持下去。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容