前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SceneKit_入门08_材质

SceneKit_入门08_材质

作者头像
酷走天涯
发布2022-05-13 15:50:43
1.2K0
发布2022-05-13 15:50:43
举报

SceneKit_入门01_旋转人物

SceneKit_入门02_如何创建工程

SceneKit_入门03_节点

SceneKit_入门04_灯光

SceneKit_入门05_照相机

SceneKit_入门06_行为动画

SceneKit_入门07_几何体

SceneKit_入门08_材质

SceneKit_入门09_物理身体

SceneKit_入门10_物理世界

SceneKit_入门11_粒子系统

SceneKit_入门12_物理行为

SceneKit_入门13_骨骼动画

SceneKit_中级01_模型之间的过渡动画

SceneKit_中级02_SCNView 详细讲解

SceneKit_中级03_切换照相机视角

SceneKit_中级04_约束的使用

SceneKit_中级05_力的使用

SceneKit_中级06_场景的切换

SceneKit_中级07_动态修改属性

SceneKit_中级08_阴影详解

SceneKit_中级09_碰撞检测

SceneKit_中级10_滤镜效果制作

SceneKit_中级11_动画事件

SceneKit_高级01_GLSL

SceneKit_高级02_粒子系统深入研究

SceneKit_高级03_自定义力

SceneKit_高级04_自定义场景过渡效果

SceneKit_高级05 检测手势点击到节点

SceneKit_高级06_加载顶点、纹理、法线坐标

SceneKit_高级07_SCNProgram用法探究

SceneKit_高级08_天空盒子制作

SceneKit_高级09_雾效果

SceneKit_大神01_掉落的文字

SceneKit_大神02_弹幕来袭

SceneKit_大神03_navigationbar上的3D文字

让学习成为一种习惯

干活来袭前奏
  • 创建工程

让学习变成一件开心的事情

  • 添加游戏框架

学习是一件很开心的事情

  • 第一步,创建游戏专用视图
代码语言:javascript
复制
    SCNView *scnView  = [[SCNView alloc]initWithFrame:self.view.bounds];
    scnView.backgroundColor = [UIColor blackColor];
    scnView.scene = [SCNScene scene];
    [self.view addSubview:scnView];
  • 第二步,创建摄像头
代码语言:javascript
复制
  // 创建摄像头
  SCNCamera *camera = [SCNCamera camera];
  SCNNode *cameraNode = [SCNNode node];
  cameraNode.camera = camera;
  cameraNode.position = SCNVector3Make(0, 0, 5);
  [scnView.scene.rootNode addChildNode:cameraNode];
  • 第三步:添加一个球体模型到视图中
代码语言:javascript
复制
    SCNSphere *sphere = [SCNSphere sphereWithRadius:1];
    SCNNode *sphereNode = [SCNNode nodeWithGeometry:sphere];
    [scnView.scene.rootNode addChildNode:sphereNode];

运行一下:

恭喜你,简直太厉害了

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


材质详解

我们需要了解两个类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.如何创建纹理属性

代码语言:javascript
复制
+ (instancetype)materialPropertyWithContents:(id)contents

提示:

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

b.纹理的属性的内容

代码语言:javascript
复制
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)

代码语言:javascript
复制
var intensity: CGFloat

会产生什么影响呢?

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

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

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

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

代码语言:javascript
复制
@property(nonatomic) SCNMatrix4 contentsTransform

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

它变换的到底是什么:

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

变换前

变换后

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

帮你理解一下

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

代码语言:javascript
复制
var wrapS: SCNWrapMode // 控制水平
var wrapT: SCNWrapMode // 控制垂直
默认的值为:SCNWrapModeClamp.

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

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

注意:

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

f.纹理滤波

这个属性有什么用?

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

代码语言:javascript
复制
@property(nonatomic) SCNFilterMode minificationFilter

可选项

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

默认值为 SCNFilterModeLinear

mipmap滤波

代码语言:javascript
复制
var mipFilter: SCNFilterMode

有什么用?

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

mipmap 有多厉害

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

可选值为

代码语言:javascript
复制
typedef enum : NSInteger {
SCNFilterModeNone = 0, // 默认值 不用mipmap
 SCNFilterModeNearest = 1,
 SCNFilterModeLinear = 2, // 线性
} SCNFilterMode;

给张图理解一下

学习你要花时间的

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

代码语言:javascript
复制
var maxAnisotropy: CGFloat

你应该了解的?

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

注意:

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

给张图理解一下各向异性

让学习成为一种习惯

纹理通道

代码语言:javascript
复制
@property(nonatomic) NSInteger mappingChannel

先解释一下这属性

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

举个例子帮你理解一下:

学习快乐

很简单:

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

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

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

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

这几点你要记牢了

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

a.漫发射属性(diffuse)

我们有一样图片是这样的:

纹理图片,没有你可以截图

上代码:

代码语言:javascript
复制
sphere.firstMaterial.diffuse.contents = @"earth-diffuse.jpg";

运行结果:

你应该也成功了吧

总结一下:

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

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

你应该记住了吧

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

先上代码:

代码语言:javascript
复制
  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];

给张图理解一下

学习开心

镜面材质属性(高光)

有什么效果?

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

添加一张高光照片

白色区域就是能显示高光的部分

上代码:

代码语言:javascript
复制
sphere.firstMaterial.specular.contents = @"earth-specular.jpg";

运行结果:

让学习成为习惯

小提示:

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

再给张图理解一下

你理解了没?

设置法线取向

理解:

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

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

效果图

映射(reflectiv)

你可以这样理解:

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

映射纹理图

代码:

代码语言:javascript
复制
sphere.firstMaterial.reflective.contents = @"earth-reflective.jpg";
// 映射因子没有上限值
sphere.firstMaterial.fresnelExponent = 10;

执行结果:

添加反射后的运行结果图

设置自身发光

特点:

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

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

代码语言:javascript
复制
 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];

运行结果:

啥都看不见

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

这是一张图片,其实就是说,纹理坐标对应的点发射这样的光,黑色表示不发光

代码:

代码语言:javascript
复制
sphere.firstMaterial.emission.contents = @"earth-emissive.jpg";

设置材质的透明度

什么意思?

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

上代码:

代码语言:javascript
复制
sphere.firstMaterial.transparent.contents = @"cloudsTransparency.png";
sphere.firstMaterial.transparencyMode = SCNTransparencyModeRGBZero;
// 设置透明比例 0为不透 没有上限
 sphere.firstMaterial.transparency = 2;

运行结果:

学习是一件很开心的事情

让学习变成习惯

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

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

代码语言:javascript
复制
 sphere.firstMaterial.diffuse.contents = @"earth-diffuse.jpg" ;
 sphere.firstMaterial.emission.contents = @"earth-emissive.jpg";

运行结果:

学习要开心

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

代码语言:javascript
复制
 sphere.firstMaterial.multiply.contents = [UIColor greenColor];

运行结果:

学习吧,年轻人

设置自照明

注意:

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

运行结果:

就是这个效果

材质可以有名字的

代码语言:javascript
复制
@property(nonatomic, copy) NSString *name

如何渲染球体内部

代码语言:javascript
复制
  // 默认渲染一边
  sphere.firstMaterial.doubleSided = true;
 // 剔除正面
  sphere.firstMaterial.cullMode = SCNCullFront;
 // 剔除反面

sphere.firstMaterial.cullMode = SCNCullBack;

混合渲染模式

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

代码语言:javascript
复制
enum SCNBlendMode : Int {
case Alpha // 默认值
case Add
case Subtract
case Multiply
case Screen
case Replace
}

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

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

光照模式

代码语言:javascript
复制
NSString *const SCNLightingModelPhong 
NSString *const SCNLightingModelBlinn
NSString *const SCNLightingModelLambert 
NSString *const SCNLightingModelConstant

看下面的图稍微理解一下

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

代码语言:javascript
复制
color = ambient* al + diffuse* max(0, dot(N, L)) + specular*pow(max(0, dot(H, N)), shininess)

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

本节的内容有点多,希望能够理解,后面我们大量使用今天的内容。

代码库,听说经常给人点赞都当老板了!

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-05-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 干活来袭前奏
  • 材质详解
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档