Three.js学习之Lamber材质和Phong材质


Posted in Javascript onAugust 04, 2016

前言

材质(Material)是独立于物体顶点信息之外的与渲染效果相关的属性。通过设置材质可以改变物体的颜色、纹理贴图、光照模式等。

MeshBasicMaterial:对光照无感,给几何体一种简单的颜色或显示线框。

MeshLambertMaterial:这种材质对光照有反应,用于创建暗淡的不发光的物体。

MeshPhongMaterial:这种材质对光照也有反应,用于创建金属类明亮的物体。

1.基本材质

使用基本材质(BasicMaterial)的物体,渲染后物体的颜色始终为该材质的颜色,而不会由于光照产生明暗、阴影效果。如果没有指定材质的颜色,则颜色是随机的。其构造函数是:

THREE.MeshLambertMaterial(opt)

其中,opt可以缺省,或者为包含各属性的值。如新建一个不透明度为0.75的黄色材质:

new THREE.MeshBasicMaterial({

 color: 0xffff00,

 opacity: 0.75

});

将其应用于一个正方体(方法参见《Three.js学习之几何形状》,效果为:

Three.js学习之Lamber材质和Phong材质

源码:

<!DOCTYPE html>
<html>
 <head>
 <meta charset="UTF-8">
 <title>3.js测试7.1</title>
 </head>
 <body onload="init()">
 <canvas id="mainCanvas" width="400px" height="300px" ></canvas>
 </body>
 <script type="text/javascript" src="js/three.min.js"></script>
 <script type="text/javascript">
 function init() {
 var renderer = new THREE.WebGLRenderer({
 canvas: document.getElementById('mainCanvas')
 });
 renderer.setClearColor(0x000000);
 var scene = new THREE.Scene();
 
 // camera
 var camera = new THREE.OrthographicCamera(-5, 5, 3.75, -3.75, 0.1, 100);
 camera.position.set(25, 25, 25);
 camera.lookAt(new THREE.Vector3(0, 0, 0));
 scene.add(camera);
 
 // light
 var light = new THREE.PointLight(0xffffff, 1, 100);
 light.position.set(10, 15, 5);
 scene.add(light);
 
 var material = new THREE.MeshBasicMaterial({
 color: 0xffff00,
 opacity: 0.75
 });
 
 var cube = new THREE.Mesh(new THREE.CubeGeometry(5, 5, 5), material);
 scene.add(cube);
 
 renderer.render(scene, camera);
 }
 </script>
</html>

 BasicMaterial的几个较为常用的属性:

· visible:是否可见,默认为true

· side:渲染面片正面或是反面,默认为正面THREE.FrontSide,可设置为反面THREE.BackSide,或双面THREE.DoubleSide

· wireframe:是否渲染线而非面,默认为false

· color:十六进制RGB颜色,如红色表示为0xff0000

· map:使用纹理贴图 

对于基本材质,即使改变场景中的光源,使用该材质的物体也始终为颜色处处相同的效果。当然,这不是很具有真实感,因此,接下来我们将介绍更为真实的光照模型:Lambert光照模型以及Phong光照模型。 

2.Lamber材质与Phong材质

Lambert材质(MeshLambertMaterial)是符合Lambert光照模型的材质。Lambert光照模型的主要特点是只考虑漫反射而不考虑镜面反射的效果,因而对于金属、镜子等需要镜面反射效果的物体就不适应,对于其他大部分物体的漫反射效果都是适用的。

其光照模型公式为:

Idiffuse = Kd * Id * cos(theta)

其中,Idiffuse是漫反射光强,Kd是物体表面的漫反射属性,Id是光强,theta是光的入射角弧度。

当然,对于使用Three.js的Lambert材质,不需要了解以上公式就可以直接使用。

创建一个黄色的Lambert材质的方法为:

new THREE.MeshLambertMaterial({

 color: 0xffff00

})

在使用了光照之后,得到这样的效果:

 Three.js学习之Lamber材质和Phong材质

color是用来表现材质对散射光的反射能力,也是最常用来设置材质颜色的属性。除此之外,还可以用ambient和emissive控制材质的颜色。

ambient表示对环境光的反射能力,只有当设置了AmbientLight后,该值才是有效的,材质对环境光的反射能力与环境光强相乘后得到材质实际表现的颜色。

emissive是材质的自发光颜色,可以用来表现光源的颜色,并不是一种光源,而是一种不受光照影响的颜色。单独使用红色的自发光:

new THREE.MeshLambertMaterial({

 emissive: 0xff0000

})

效果为:

 Three.js学习之Lamber材质和Phong材质

如果同时使用红色的自发光与黄色的散射光:

new THREE.MeshLambertMaterial({

 color: 0xffff00,

 emissive: 0xff0000

})

效果为:

 Three.js学习之Lamber材质和Phong材质

球体的效果:

 Three.js学习之Lamber材质和Phong材质

   总结Lamber材质的特有属性:

ambient:设置材质的环境色,和AmbientLight光源一起使用,这个颜色会与环境光的颜色相乘。即是对光源作出反应。

emissive:设置材质发射的颜色,不是一种光源,而是一种不受光照影响的颜色。默认为黑色。 

  源码: 

<!DOCTYPE html>
<html>
 <head>
 <meta charset="UTF-8">
 <title>3.js测试7.2</title>
 </head>
 <body onload="init()">
 <canvas id="mainCanvas" width="400px" height="300px" ></canvas>
 </body>
 <script type="text/javascript" src="js/three.min.js"></script> 
 <script type="text/javascript">
 function init() {
 var renderer = new THREE.WebGLRenderer({
 canvas: document.getElementById('mainCanvas')
 });
 renderer.setClearColor(0x000000);
 var scene = new THREE.Scene();
 
 // camera
 var camera = new THREE.OrthographicCamera(-5, 5, 3.75, -3.75, 0.1, 100);
 camera.position.set(25, 25, 25);
 camera.lookAt(new THREE.Vector3(0, 0, 0));
 scene.add(camera);
 
 // light
 var light = new THREE.PointLight(0xffffff, 1, 100);
 light.position.set(10, 15, 5);
 scene.add(light);
 
 var material = new THREE.MeshLambertMaterial({
 color: 0xffff00,
 emissive: 0xff0000
 });
 
 var cube = new THREE.Mesh(new THREE.CubeGeometry(5, 5, 5), material);
 scene.add(cube);

// var sphere = new THREE.Mesh(new THREE.SphereGeometry(3, 20, 8), material);
// scene.add(sphere);
 
 renderer.render(scene, camera);
 }
 </script>
</html>

3.phong材质

Phong材质(MeshPhongMaterial)是符合Phong光照模型的材质。和Lambert不同的是,Phong模型考虑了镜面反射的效果,因此对于金属、镜面的表现尤为适合。

漫反射部分和Lambert光照模型是相同的,镜面反射部分的模型为:

        Ispecular = Ks * Is * (cos(alpha)) ^ n

其中,Ispecular是镜面反射的光强,Ks是材质表面镜面反射系数,Is是光源强度,alpha是反射光与视线的夹角,n是高光指数,越大则高光光斑越小。

由于漫反射部分与Lambert模型是一致的,因此,如果不指定镜面反射系数,而只设定漫反射,其效果与Lambert是相同的:

new THREE.MeshPhongMaterial({

 color: 0xffff00

});

Three.js学习之Lamber材质和Phong材质

同样地,可以指定emissive和ambient值,这里不再说明。下面就specular值指定镜面反射系数作说明。首先,我们只使用镜面反射,将高光设为红色,应用于一个球体:

var material = new THREE.MeshPhongMaterial({

 specular: 0xff0000

});

var sphere = new THREE.Mesh(new THREE.SphereGeometry(3, 20, 8), material);

效果为:

 Three.js学习之Lamber材质和Phong材质

可以通过shininess属性控制光照模型中的n值,当shininess值越大时,高光的光斑越小,默认值为30。我们将其设置为1000时:

new THREE.MeshPhongMaterial({

 specular: 0xff0000,

 shininess: 1000

});

效果为:

 Three.js学习之Lamber材质和Phong材质

使用黄色的镜面光,红色的散射光:

material = new THREE.MeshPhongMaterial({

 color: 0xff0000,

 specular: 0xffff00,
 
 shininess: 100

});

总结Phong材质的特有属性:

ambient:设置材质的环境色,和AmbientLight光源一起使用,这个颜色会与环境光的颜色相乘。即是对光源作出反应。

emissive:设置材质发射的颜色,不是一种光源,而是一种不受光照影响的颜色。默认为黑色

specular:指定该材质的光亮程度及其高光部分的颜色,如果设置成和color属性相同的颜色,则会得到另一个更加类似金属的材质,如果设置成grey灰色,则看起来像塑料

shininess:指定高光部分的亮度,默认值为30. 

源码: 

<!DOCTYPE html>
<html>
 <head>
 <meta charset="UTF-8">
 <title>3.js测试7.3</title>
 </head>
 <body onload="init()">
 <canvas id="mainCanvas" width="400px" height="300px" ></canvas>
 </body>
 <script type="text/javascript" src="js/three.min.js"></script>
 <script type="text/javascript">
 function init() {
 var renderer = new THREE.WebGLRenderer({
 canvas: document.getElementById('mainCanvas')
 });
 renderer.setClearColor(0x000000);
 var scene = new THREE.Scene();
 
 // camera
 var camera = new THREE.OrthographicCamera(-5, 5, 3.75, -3.75, 0.1, 100);
 camera.position.set(25, 25, 25);
 camera.lookAt(new THREE.Vector3(0, 0, 0));
 scene.add(camera);
 
 // light
 var light = new THREE.PointLight(0xffffff, 1, 200);
 light.position.set(10, 15, 25);
 scene.add(light);
 
 var material = new THREE.MeshPhongMaterial({
// specular: 0xff0000,
 color: 0xff0000,
 specular: 0xffff00,
 shininess: 100
 });
 
// var cube = new THREE.Mesh(new THREE.CubeGeometry(5, 5, 5), material);
// scene.add(cube);
 
 var sphere = new THREE.Mesh(new THREE.SphereGeometry(3, 20, 8), material);
 scene.add(sphere);
 
 renderer.render(scene, camera);
 }
 </script>
</html>

总结

本文的内容到这就结束了,文章通过详细实例及图片介绍了Three.js中的Lamber与Phong,希望对大家的学习有所帮助,小编会陆续整理Three.js的相关文章,对Three.js感兴趣的朋友们请继续支持三水点靠木。

Javascript 相关文章推荐
一段非常简单的让图片自动切换js代码
Nov 10 Javascript
通过Unicode转义序列来加密,按你说的可以算是混淆吧
May 06 Javascript
各种常用浏览器getBoundingClientRect的解析
May 21 Javascript
javascript椭圆旋转相册实现代码
Jan 16 Javascript
子页向父页传值示例
Nov 27 Javascript
回车直接实现点击某按钮的效果即触发单击事件
Feb 27 Javascript
AngularJS手动表单验证
Feb 01 Javascript
JavaScript微信定位功能实现方法
Nov 29 Javascript
Vue.js使用v-show和v-if的注意事项
Dec 13 Javascript
微信小程序checkbox组件使用详解
Jan 31 Javascript
vue-cli3单页构建大型项目方案
Apr 07 Javascript
js正则表达式简单校验方法
Jan 03 Javascript
基于JavaScript实现在新的tab页打开url
Aug 04 #Javascript
同步文本框内容JS代码实现
Aug 04 #Javascript
JS打印组合功能
Aug 04 #Javascript
Listloading.js移动端上拉下拉刷新组件
Aug 04 #Javascript
jQuery选择器总结之常用元素查找方法
Aug 04 #Javascript
Bootstrap中表单控件状态(验证状态)
Aug 04 #Javascript
Bootstrap实现input控件失去焦点时验证
Aug 04 #Javascript
You might like
PHP5中的时间相差8小时的解决办法
2008/03/28 PHP
PHP+FastCGI+Nginx配置PHP运行环境
2014/08/07 PHP
php使用fputcsv()函数csv文件读写数据的方法
2015/01/06 PHP
Joomla简单判断用户是否登录的方法
2016/05/04 PHP
Yii框架创建cronjob定时任务的方法分析
2017/05/23 PHP
javascript图像处理—仿射变换深度理解
2013/01/16 Javascript
js随机颜色代码的多种实现方式
2013/04/23 Javascript
javascript中sort()的用法实例分析
2015/01/30 Javascript
javascript中去除数组重复元素的实现方法【实例】
2016/04/12 Javascript
Jquery和JS获取ul中li标签的实现方法
2016/06/02 Javascript
第四篇Bootstrap网格系统偏移列和嵌套列
2016/06/21 Javascript
详解vue2 $watch要注意的问题
2017/09/08 Javascript
jquery animate动画持续运动的实例
2017/11/29 jQuery
详解react-native WebView 返回处理(非回调方法可解决)
2018/02/27 Javascript
vue 指定组件缓存实例详解
2018/04/01 Javascript
Jquery Datatables的使用详解
2020/01/30 jQuery
python写入中英文字符串到文件的方法
2015/05/06 Python
实例Python处理XML文件的方法
2015/08/31 Python
python如何在循环引用中管理内存
2018/03/20 Python
Python实现的计算器功能示例
2018/04/26 Python
python实现自动获取IP并发送到邮箱
2018/12/26 Python
keras和tensorflow使用fit_generator 批次训练操作
2020/07/03 Python
Python Pandas list列表数据列拆分成多行的方法实现
2020/12/14 Python
利用CSS3实现单选框动画特效示例代码
2016/09/26 HTML / CSS
webView加载html图片遇到的问题解决
2019/10/08 HTML / CSS
印尼最大的婴儿用品购物网站:Orami
2017/09/28 全球购物
联想台湾官网:Lenovo TW
2018/05/09 全球购物
戛纳奢侈品商店:Jacques Loup法国
2019/11/04 全球购物
俄罗斯建筑和装饰材料在线商店:Stroilandia
2020/07/25 全球购物
万代美国官网:PREMIUM BANDAI USA
2020/09/11 全球购物
简述安装Slackware Linux系统的过程
2012/05/08 面试题
有关打架的检讨书
2014/01/25 职场文书
五好党支部事迹材料
2014/02/06 职场文书
南京市纪委监察局整改方案
2014/09/16 职场文书
2015仓库保管员年终工作总结
2015/05/13 职场文书
Go Gin实现文件上传下载的示例代码
2021/04/02 Golang