miaoYu

3D WebGL入门之材料

原文链接: codepen.io

这是3D入门系列文章的第三部分,如果你还没有看其他部分,最好先看一下:


我们生活在一个被材料包围的世界,在Three.js中有非常多材料供我们使用,也非常多的参数可配置。以我的经验来看,每个人都会经历被材料支配的恐惧。所以在这篇文章中,我会避免说太多的东西。

取而代之,我会介绍一些关于材料很有用的案例,希望对于你有所帮助。

首先什么是材料?

Three.js 官方文档最简洁的解释:材料用于描述物体的外表。就像在真实世界的物体,材料决定了物体是怎样出现在3D世界的。在文章的后面,我们通过材料来定义物体的颜色,材质,以及如何反射光线。

这里有一些很棒的材料

普通网格材料(MeshNormalMaterial)

普通网格材料不是最有用的材料,因为你可以控制地方很少,这是因为网格平面的颜色是由它的位置决定的。它可以制作一些彩虹颜色的物体,我非常喜欢:) 值得注意的是这个材料不受光源影响。

  `var material = new THREE.MeshNormalMaterial();`

<iframe height='265' scrolling='no' title='Icosahedron with MeshNormalMaterial' src='//codepen.io/rachsmith/embed/OMKEvV/?height=265&theme-id=0&default-tab=result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen Icosahedron with MeshNormalMaterial by Rachel Smith (@rachsmith) on CodePen. </iframe>

兰伯特材料(MeshLambertMaterial)

兰伯特材料指的是一个钟没有光泽的材料,可以想象成一种磨砂材料,就像哑光塑料。你可以定义颜色也可添加纹理(图片)。

Three.js 颜色设置

它会接收一个16进制的颜色参数,比如0xffffff。幸运的是,Three.js提供了一个很方便的颜色对象来操作颜色。你可以通过传入16进制,rgba或者hsl来创造颜色。

// 使用16进制
var color = new THREE.Color("#6f4171");
// 使用rgba
var color = new THREE.Color("rgba(188, 141, 190, 1)");

然后,你可以用color对象的方法获取颜色的16进制值。

  `var hex = color.getHex()`

color对象提供了大量的方法供我们使用。在后续的文章中我们也会用到一些,如果你等不及了,可以直接去看官方文档

创造一个单色的兰伯特材料

var color = new THREE.Color( "#7833aa" );
var material = new THREE.MeshLambertMaterial( {color: color.getHex()} );

<iframe height='265' scrolling='no' title='Icosahedron with MeshLambertMaterial - point lighting' src='//codepen.io/rachsmith/embed/EKYyeB/?height=265&theme-id=0&default-tab=result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen Icosahedron with MeshLambertMaterial - point lighting by Rachel Smith (@rachsmith) on CodePen. </iframe>

在上面的demo中,我用了2个点光源照射在兰伯特材料上,当物体与光线碰撞创造出一个漂亮哑光,但是仍然有太多的阴影。我们来看看更多光线照射是什么样的。

<iframe height='265' scrolling='no' title='Icosahedron with MeshLambertMaterial - directional lighting' src='//codepen.io/rachsmith/embed/bpbePv/?height=265&theme-id=0&default-tab=result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen Icosahedron with MeshLambertMaterial - directional lighting by Rachel Smith (@rachsmith) on CodePen. </iframe>

上面的场景有超级多的光线,整个场景被照亮了。我们也可以创造一个透明渲染器,让一个光线穿过物体。

  `var renderer = new THREE.WebGLRenderer({alpha: true});`

使用线框 用以上的材料都有线框这个配置项,用线框替代整个平面被铺满。实现这个,你只需把wireframe这个选项设为true。

  `var material = new THREE.MeshLambertMaterial( {color: color.getHex(), wireframe: true} );`

<iframe height='265' scrolling='no' title='Icosahedron with MeshLambertMaterial - wireframe' src='//codepen.io/rachsmith/embed/vGBWog/?height=265&theme-id=0&default-tab=result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen Icosahedron with MeshLambertMaterial - wireframe by Rachel Smith (@rachsmith) on CodePen. </iframe>

为哑光材料加上材质(图片)

紫色的材料非常漂亮,但是也许你需要让它变得更漂亮,比如用一张图片包裹到物体上。用一张砖纹理图片创建一个砖墙,或者你建一个3D的气球把你老板的照片放上去。

// create a loader to get an image from a URL
var textureLoader = new THREE.TextureLoader();
// we've gotta set this to use cross-origin images
textureLoader.crossOrigin = true;
// load in the image
textureLoader.load('https://s3-us-west-2.amazonaws.com/s.cdpn.io/53148/chrispizza.png', function(texture) {
  // this code makes the texture repeat
  texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
  texture.repeat.set( 2, 2 );
  // set the texture as the map for the material
  var material = new THREE.MeshLambertMaterial( {map: texture} );
}

<iframe height='265' scrolling='no' title='Sphere with image texture' src='//codepen.io/rachsmith/embed/GZKjqO/?height=265&theme-id=0&default-tab=result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen Sphere with image texture by Rachel Smith (@rachsmith) on CodePen. </iframe>

有光泽的材料(MeshPhongMaterial)

现在我们来讨论有光泽的材料(MeshPhongMaterial),这种材料除了有光泽,和磨砂材料(MeshLamberMaterial)非常相似。因为它们很像,所以你已经知道如何创建MeshPhongMaterial或者添加图片材质。

var color = new THREE.Color( "#7833aa" );
var material = new THREE.MeshPhongMaterial( {color: color.getHex()} );

<iframe height='265' scrolling='no' title='Icosahedron with MeshPhongMaterial - directional lighting' src='//codepen.io/rachsmith/embed/ONLRQo/?height=265&theme-id=0&default-tab=result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen Icosahedron with MeshPhongMaterial - directional lighting by Rachel Smith (@rachsmith) on CodePen. </iframe>

看到物体上反射的斑点了吗?这就是为什么叫有光泽的材料了。有一对属性值得注意,一个是shinyness,默认30,控制光泽度;另外一个specular,控制光泽的颜色。

var color = new THREE.Color( "#7833aa" );
var material = new THREE.MeshPhongMaterial( {color: color.getHex(), specular: 0x009900, shinyness: 20 } );

<iframe height='265' scrolling='no' title='Icosahedron with MeshPhongMaterial - directional lighting - specular color' src='//codepen.io/rachsmith/embed/aNomGB/?height=265&theme-id=0&default-tab=result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen Icosahedron with MeshPhongMaterial - directional lighting - specular color by Rachel Smith (@rachsmith) on CodePen. </iframe>

上面的demo,我加入了绿色的光色,配合紫色看起来很怪,我只是为了示范这个属性是如何工作的。

现在你可以用MeshPhongMaterial做一些很有意思的效果了,但是我觉得最有趣的部分使用凹凸贴图。凹凸贴图是一个黑白贴图,当光亮照到物体时它可以让物体产生凹凸感。用这种方式很容易就可以创造山脊和凸起,而不需要做复杂的几何体。

var textureLoader = new THREE.TextureLoader();
textureLoader.crossOrigin = true;
textureLoader.load('https://s3-us-west-2.amazonaws.com/s.cdpn.io/53148/4268-bump.jpg', function(texture) {
// 应用凹凸贴图
var material = new THREE.MeshPhongMaterial( {color: color.getHex(), bumpMap: texture} );
});

<iframe height='265' scrolling='no' title='Icosahedron with MeshPhongMaterial - bump map' src='//codepen.io/rachsmith/embed/WweGKW/?height=265&theme-id=0&default-tab=result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen Icosahedron with MeshPhongMaterial - bump map by Rachel Smith (@rachsmith) on CodePen. </iframe>

很棒吧!加入凹凸贴图后,让物体看起来有真实的凹凸感。酷吗?我只接受“非常酷”这个回答。

#### 查看第四部分: 动画