赞
踩
前言:材质就像物体的皮肤,决定几何体的外表。例如:定义一个几何体看起来是否像金属,透明与否,或者显示为线框,得到THREEJS.Mesh对象添加到Threejs渲染的场景中。
创建三维对象主要使用的材质:
MeshBasicMaterial(网格基础材质) | 可赋予简单颜色 |
MeshDepthMaterial(网格深度材质) | 根据摄像机距离进行调色 |
MeshNormalMaterial(网格法向材质) | 根据法向量计算物体颜色 |
MeshLambertMaterial(网格Lambert 材质) | 考虑光照影响的材质,用于创建不光亮的物体 |
MeshPhongMaterial(网格 Phong式材质) | 考虑光照影响的材质,用于创建光亮的物体 |
MeshStandardMaterial(网格标准材质) | 它能够计算出表面与光线的正确互动关系,从面便 染出的物体看起来更加真实(新) |
MeshPhysicalMaterial(网格物理材质) | 这是MeshPhongMaterial的扩展材质(新) |
MeshToonMaterial(网格卡通材质) | MeshPhongMaterial的扩展材质,更卡通化 |
ShadowMaterial(阴影材质) | 专门用于接收阴影图的特殊材质。在该材质中只有 阴影图像,非阴影部分为完全透明的区域 |
ShaderMaterial(着色器材质) | 这种材质允许使用自定义的着色器程序,直接控制顶点的放置方式及像素的着色方式 |
LineBasicMaterial(直线基础材质) | 这种材质可以用于THREE.Line(直线)几何体,用来创建着色的直线 |
LineDashMaterial(虚线材质) | 创建出一种虚线的效果 |
Three.js 提供了一个材质基类 THREE. Material,它列出了所有的共有属性。这些共有属性分成了三类,如下所示:
基础属性 : 这些属性是最常用的。通过这些属性,可以控制物体的不透明度、是否可见以及如何被引用(通过ID或是自定义名称)。
融合属性 : 每个物体都有一系列的融合属性。这些属性决定了物体如何与背景融合。
高级属性 : 有一些高级属性可以控制底层WebGL上下文对象渲染物体的方式。大多数情况下是不需要使用这些属性的。
基础属性这里就不罗列了,需要可以查看源码
//材质的共有属性 THREE.Material = function () { Object.defineProperty( this, 'id', { value: THREE.MaterialIdCount ++ } ); this.uuid = THREE.Math.generateUUID(); this.name = ''; this.type = 'Material'; this.side = THREE.FrontSide; this.opacity = 1; this.transparent = false; this.blending = THREE.NormalBlending; this.blendSrc = THREE.SrcAlphaFactor; this.blendDst = THREE.OneMinusSrcAlphaFactor; this.blendEquation = THREE.AddEquation; this.depthTest = true; this.depthWrite = true; this.polygonOffset = false; this.polygonOffsetFactor = 0; this.polygonOffsetUnits = 0; this.alphaTest = 0; this.overdraw = 0; // Overdrawn pixels (typically between 0 and 1) for fixing //antialiasing gaps in CanvasRenderer this.visible = true; this.needsUpdate = true; };
MeshBasicMaterial是一种基础材质,不考虑场景中是否有光照影响。一般使用该材质的网格会被渲染成基础几何,也可显示边框使用。
在使用该材质时常用属性通常对以下属性进行调试:
- var meshMaterial = new THREE.MeshBasicMaterial({
- color: 0x7777ff,
- //wireframe : true, //开启wireframe属性,将模型渲染成线框
- //opacity : 0.01
- //wireframeLinewidth: 20 //测试线宽,看不出变化
- //name : 'Material-1',
- //transparent: true, //开启透明度
- //opacity : 0.5 //设置透明度(0-1)
- });
实例 :
可通过插件GUI对网格对象属性进行调试,该实例中并未添加光照(不受光照影响)。
MeshDepthMaterial材质无法设置对象颜色,通过设置多种材质用以改变物体颜色。该方案又称联合材质。
创建方案:
- //Math.ceil() “向上取整”, 即小数部分直接舍去,并向正数部分进1
- //Math.random()是令系统随机选取大于等于 0.0 且小于 1.0 的伪随机 double 值
- var cubeSize = Math.ceil(3 + (Math.random() * 3)); //cubeSize随机 3 4 5 6
- var boxGeometry = new THREE.BoxGeometry(cubeSize,cubeSize,cubeSize);
- var meshDepthMaterial = new THREE.MeshDepthMaterial();
- var meshBasicMaterial = new THREE.MeshBasicMaterial({
- color: controls.color,
- transparent: true,
- //材质融合MultiplyBlending将前景色与背景色(MeshDepthMaterial渲染的方块)相乘
- blending: THREE.MultiplyBlending
- });
- //混合材质创建网格
- //顺序不要放错
- var cube = new THREE.SceneUtils.createMultiMaterialObject(boxGeometry,[meshBasicMaterial,meshDepthMaterial]);
- //将第一种材质对象缩小,解决闪光现象
- //闪光现象 : 当一个物体作用在另一个物体上时,并且有一个物体是透明的,存在这种现象
- cube.children[1].scale.set(0.99, 0.99, 0.99);
- cube.castShadow = true;
-
- // position the cube randomly in the scene
- //Math.round() “四舍五入”, 该函数返回的是一个四舍五入后的的整数
- cube.position.x = -60 + Math.round((Math.random() * 100));
- cube.position.y = Math.round((Math.random() * 10));
- cube.position.z = -100 + Math.round((Math.random() * 150));
-
- scene.add(cube);
一般项目建模型时经常使用联合材质,概念要清晰。感兴趣的话可以自己测试一下,注意可能会出现闪光,个人理解是两个Mesh没有重合好。解决的话需要缩小一个即可。
MeshLambertMaterial(常用)用于创建暗淡不光亮的表面。而且会对场景中的光源产生反应。MeshLambertMaterial材质的独有属性搭配基础属性适用于多种场景。
MeshLambertMaterial材质的常用属性:
color | 材质的环境色(会与环境光颜色相乘) |
emissive(自发光) | 并非光源,在暗处也可见 |
创建方式:
var meshMaterial = new THREE.MeshLambertMaterial({color: 0x7777ff});
展示效果:
MeshPhongMaterial可以创建光亮的材质,与MeshLambertMaterial属性基本一样,不同的是通过MeshPhongMaterial可以实现高光效果。该材质下的模型既可以模拟金属质感的物体,还可以模拟塑料质感的物体。
MeshPhongMaterial材质的常用属性:
color | 材质的环境色(会与环境光颜色相乘) |
emissive(自发光) | 并非光源,在暗处也可见 |
specular(高光颜色) | 指定该材质的光亮程度及高光部分颜色 |
shiness(高光度) | 镜面高光的清晰程度(默认30)光滑度高的表面清晰度高 |
创建方案:
- var material = new THREE.MeshPhongMaterial({
- color: 0x7777ff
- });
常用属性方式:
- var controls = new function (){
- this.transparent = false;
- this.opacity = 1;
- this.visible = true;
- this.ambient = 0x0c0c0c;
- //材质自身颜色不受光照影响
- this.emissive = material.emissive.getHex();
- //高光 即可模仿塑料质感 又可模仿金属质感
- this.specular = material.specular.getHex();
- //高光部分轮廓的清晰程度
- this.shininess = material.shininess;
- //对应的对象那一面有材质
- this.side = "front";
- //材质的环境光
- this.color = material.color.getStyle();
-
- this.wrapAround = false;
- this.wrapR = 1;
- this.wrapG = 1;
- this.wrapB = 1;
-
- this.selectedMesh = "cube";
- }
测试效果:建议对比MeshLambertMaterial材质进行测试。
简单测试感觉没啥区别。高光效果暂时没找到运用的demo。后续测试
THRFE.ShaderMaterial是Threejs库中最通用、最复杂的材质之一。通过自己定制的着色器,直接在WebGL环境中运行。着色器可以将Threejs中的JavaScript网格转换为屏幕上的像素。通过这些自定义的着色器,可以明确地指定对象如何渲染,以及如何覆盖或修改Threejs库中的默认值。
THREE.ShaderMaterial有一些我们已经见过的可以设置的属性。Three.js传人这些属性的所有信息,但是仍然必须在自己的着色器程序中处理这些信息。
着色器时使用类似与C语言的GLSL语言编写的(应该是OpenES 着色语言)
部分代码:
-
- <script id="fragment-shader-6" type="x-shader/x-fragment">
-
-
- uniform float time;
- uniform vec2 resolution;
-
-
- void main( void )
- {
-
- vec2 uPos = ( gl_FragCoord.xy / resolution.xy );//normalize wrt y axis
- //suPos -= vec2((resolution.x/resolution.y)/2.0, 0.0);//shift origin to center
-
- uPos.x -= 1.0;
- uPos.y -= 0.5;
-
- vec3 color = vec3(0.0);
- float vertColor = 2.0;
- for( float i = 0.0; i < 15.0; ++i )
- {
- float t = time * (0.9);
-
- uPos.y += sin( uPos.x*i + t+i/2.0 ) * 0.1;
- float fTemp = abs(1.0 / uPos.y / 100.0);
- vertColor += fTemp;
- color += vec3( fTemp*(10.0-i)/10.0, fTemp*i/10.0, pow(fTemp,1.5)*1.5 );
- }
-
- vec4 color_final = vec4(color, 1.0);
- gl_FragColor = color_final;
- }
-
- </script>
着色器测试效果:
基础属性:
color | 该属性定义线的颜色。如果指定了vertexColors,这个属性就会被忽略 |
linewidth | 该属性定义线的宽度 |
vertexColors | 设置成THREEVertexColors值,就可以给每个顶点指定一种颜色 |
创建方案:
- var material = new THREE.LineBasicMaterial({
-
- opacity: 1,
- linewidth: 0.1,
- vertexColors: THREE.VertexColors
- });
实例效果:
还可以通过LineDashMaterial(虚线材质)产生虚线效果:
- lines.computeLineDistances();
- var material = new THREE.LineDashedMaterial({
- vertexColors: true,
- color: 0xcccccc,
- dashSize: 0.1, //虚线段的长度
- gapSize: 0.6, //虚线段间隔的宽度
- scale: 1
- });
- var line = new THREE.Line(lines, material);
- line.position.set(25, -30, -60);
- scene.add(line);
必须强调的是:调用computeLineDistanceO(用来计算线段顶点之间的距离)。如果不这么做,间隔就不会正确地显示。
Threejs提供了很多材质用于给几何体指定皮肤。从简单的THREE.MeshBasicMaterial到复杂的 THREE.ShaderMaterial,通过THREE.ShaderMaterial可以提供自己的顶点着色器和着色器程序。材质共享很多基础属性。如果你知道如何使用一种材质,可能也知道如何使用其他材质。注意,不是所有的材质都对场景中的光源做出反应。如能希望一个材质计算光照的影响,如果希望一个材质计算光照的影响,应该尽量使用准材质THREE.MeshStandardMatcrial。而当你需要更多控制时,可以考虑使用THRE MeshPhysicalMaterial、THREE.MeshPhongMaterial或 THREE.MeshLambertMaterial。 仅仅从代码确定某种材质属性的效果是非常困难的。通常,使用dat.GUI控制面板来试验这些性是一个不错的方法。
同样的是,材质的大部分属性都可以在运行时修改。但是有一些属性(例如 side)不能在运行时修改。如果你要修改这些属性的值,需要将needsUpdate属性设置为 true。要了解运行时哪些属性可以修改,哪些不属性不能修改,
最新的两种材质测试属性测试效果在简单的场景并不能体现出来。有dmeo的小伙伴可以给我留言讨论一下效果。感谢。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。