Three.js开发指南---使用three.js的材质(第四章)

时间:2021-08-14 03:08:20

 

材质就像物体的皮肤,决定了几何体的外表,例如是否像草地/金属,是否透明,是否显示线框等

一 材质

  THREE.js的材质分为多种,Three.js提供了一个材质基类THREE.Material,

  该基类拥有three.js所有材质的公有属性,分为三类:基础属性,融合属性,高级属性

  基础属性:ID,name,透明度,是否可见,是否需要刷新等

  融合属性:决定了物体如何与背景融合

  高级属性:可以控制WEBGL上下文渲染物体的方法,大多数情况下,是不会用这些属性,我们这里不再讨论

   1.1 基础属性

属性 描述
ID(描述符) 用来标识材质,在创建时赋值
name(名称) 通过该属性克赋予该材质名称
opacity(透明度) 定义物体有多透明,与transparent属性一起使用
transparent(是否透明) 设置为true时,会根据opacity的值来设置透明度,设置为false时,则只着色
overdraw(过度描绘) 当使用THREE.CanvasRenderer画布渲染器绘制对象的时候,物体之间可能会有空隙,这时设置该值为true,多边形会被渲染的稍微大一点,
visible(是否可见) 定义该材质是否可见
side(侧面)

决定了几何体的哪一面应用该材质,

THREE.FrontSide应用到几何体的前(外)面;

THREE.BackSide应用到几何体的后(内)面;

THREE.DoubleSide应用到几何体的内外两侧

needUpdate(是否刷新) 设置该值为true后,如果材质发生改变,就会使用新的材质刷新它的缓存

  

 

 

  1.2 融合属性

属性 描述  
blending(融合) 决定物体上的材质如何跟背景融合,一般是NormalBlending,这种模式一般只显示材质的上层  
blendsrc(融合源)

通过指定融合源,融合目标来指定源如何跟目标融合以及融合时如何使用目标,以达到创建自定义的融合模式

融合源的默认值SrcAlphaFactor:使用alpha透明度通道进行融合

融合目标的默认值OneMinusSrcAlphaFactor:融合目标也使用融合源的alpha通道进行融合

blendingequation只读blendsrc和blenddst的值的叠加方式创建自定义的融合方式

 
blenddst(融合目标)  
blendingequation(融合公式)  

  1.3 基础材质(MeshBasicMaterial)

     MeshBasicMaterial是一种简单的材质,这种材质不考虑光照的影响。

    使用这种材质的网格会被渲染成一些简单的平面多边形,而且可以通过设置wireframe的值会显示几何体的线框

属性 描述
color 设置材质的颜色
wireframe 是否将材质渲染成线框
wireframeLinewidth 如果设置了wireframe的值,则该属性则设置了线框的宽度,即线框的宽度
wireframeLinecap(线框的端点)

该属性定义了线框模式下端点的显示方式,有butt平,round圆,square方,

但是在实际的应用中,该值很难看出效果,而且webglrenderer不支持该属性

wireframeLinejoin(线框线段连接点)  定义线段的连接点如何显示,webglrenderer不支持该属性
 shading(着色方式)

 THREE.SmoothShading平滑着色,和THREE.FlatShading平面着色,

平面着色的话,每个面是什么颜色就会被渲染成什么颜色,

而平滑着色的话可以使物体的表面看起来变的更光滑一些

 vertexColors(顶点颜色) 可以通过该属性为每一个顶点定义不同的颜色,但是canvasRenderer不支持
 fog(雾化) 当前材质是否会受全局雾化效果的影响
side(面)

该属性可以指定几何体的哪个面应用了材质,

由于材质多应用于物体前面的面上,

所以当旋转的时候,会有一部分时间是不可见的(其实是物体背面没有应用材质)

side属性的值有front(只有物体的前面应用材质)和double(前后都应用材质)

Three.js开发指南---使用three.js的材质(第四章) 

 

 

 

<!DOCTYPE html>

<html>

<head>
<title>1</title>
<script type="text/javascript" src="three.js"></script>
<script type="text/javascript" src="dat.gui.js"></script>
<script type="text/javascript" src="CanvasRenderer.js"></script>
<script type="text/javascript" src="Projector.js"></script>
<style>
body
{
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin
: 0;
overflow
: hidden;
}
</style>
</head>
<body>

<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div>

<!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript">
//var scene
function init() {
//生成一个场景
var scene=new THREE.Scene();


//生成一个相机
//参数:视场,长宽比,近面,远面
var camera=new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,1000);
camera.position.x=-20;
camera.position.y
=40;
camera.position.z
=30;
camera.lookAt(scene.position);
scene.add(camera);

var render;

//生成一个webgl的渲染器
var webGLrender=new THREE.WebGLRenderer();
webGLrender.setClearColor(
0xEEEEEE);
webGLrender.setSize(window.innerWidth,window.innerHeight);
webGLrender.shadowMapEnabled
=true;
//允许阴影映射,渲染阴影需要大量的资源,因此我们需要告诉渲染器我们需要阴影
render=webGLrender;

//生成一个canvas的渲染器,渲染器有什么不同?
var canvasRender=new THREE.CanvasRenderer();
canvasRender.setSize(window.innerWidth,window.innerHeight);
//允许阴影映射,渲染阴影需要大量的资源,因此我们需要告诉渲染器我们需要阴影
//scene.add(canvasRender);


//生成基本材质,并将该材质应用于下面中的球体,方块或者平面
var material=new THREE.MeshBasicMaterial({color: 0x77777ff});

material.needsUpdate
=true;

//生成一个地面平面,并添加到场景中
//参数:长,宽,长分为多少份,宽分为多少份
var groundGeometry = new THREE.PlaneGeometry(100, 200, 20, 20);
var groundMaterial = new THREE.MeshBasicMaterial({color: 0x777777});
var ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.receiveShadow
= true;
ground.rotation.x
= -0.5 * Math.PI;
scene.add(ground);

//生成一个方块,并添加到场景中
var cubeGeometry=new THREE.BoxGeometry(10,10,10);
var cube=new THREE.Mesh(cubeGeometry,material);
cube.castShadow
=true;
cube.position.set(
0,3,2);
scene.add(cube);

//生成一个圆球,暂时不添加到场景,使用图形界面选择物体
var sphereGeometry=new THREE.SphereGeometry(10,10,10);
var sphere=new THREE.Mesh(sphereGeometry,material);
sphere.castShadow
=true;
sphere.position.set(
0,3,2);
//scene.add(sphere);
//生成一个平面,暂时不添加到场景,使用图形界面选择物体
var planeGeometry=new THREE.PlaneGeometry(10,10,10);
var plane=new THREE.Mesh(planeGeometry,material);
plane.position.set(
0,3,2);

//生成环境光,弱化阴影
var ambientLight = new THREE.AmbientLight(0x0c0c0c);
scene.add(ambientLight);


//生成聚光灯
var spotLight0 = new THREE.SpotLight(0xffffff);
spotLight0.position.set(
-40, 60, -10);
spotLight0.castShadow
=true;
scene.add(spotLight0);

//增加图形控制界面
var controls=new function(){
this.rotationSpeed=0.02;
this.opacity=material.opacity;//透明度
this.transparent=material.transparent;
this.visible=material.visible;

this.wireframe=material.wireframe;
this.shading=material.shading;
this.wireframeLineWidth=material.wireframeLineWidth;
this.selectedMesh = "矩形";
this.switchRender=function(){
if(render instanceof THREE.WebGLRenderer){
render
=canvasRender;
}
else{
render
=webGLrender;
}
document.getElementById(
"WebGL-output").innerHTML='';
document.getElementById(
"WebGL-output").appendChild(render.domElement);
}
this.color=material.color.getStyle();
};

var gui=new dat.GUI();
//上面controls里面的opacity必须与下面的一致
var childGui=gui.addFolder("材质的共有属性");
childGui.add(controls,
"opacity",0,1).onChange(function(e){
material.opacity
=e;
});
//注意,当opacity设置的值不为1时,以opacity为主
childGui.add(controls,"transparent").onChange(function(e){
material.transparent
=e;
});
childGui.add(controls,
"wireframe").onChange(function(e){
material.wireframe
=e;
});
//如果visible的值为false,即不可见,不管opacity的值为多少,物体都是不可见的
childGui.add(controls,"visible").onChange(function(e){
material.visible
=e;
});
//addColor注意,增加颜色的图形控制,需要使用addColor方法
childGui.addColor(controls,"color").onChange(function(e){

material.color.setStyle(e);
});
childGui.add(controls,
"selectedMesh",["cube","sphere","plane"]).onChange(function(e){
scene.remove(plane);
scene.remove(cube);
scene.remove(sphere);
switch(e){
case 'cube':
scene.add(cube);
break;
case 'sphere':
scene.add(sphere);
break;
case 'plane':
scene.add(plane);
break;
}
});

//gui的一个参数是一个对象,该对象控制的属性是add的函数的第二个参数
//即controls的this.switchRender必须与下面的属性一致,即上面代码的switchRender必须与下面语句的switchRender保持一致
gui.add(controls, 'switchRender');
document.getElementById(
"WebGL-output").append(render.domElement);

function renderScene(){

requestAnimationFrame(renderScene);
render.render(scene, camera);
}
//scene.fog=new THREE.Fog(0xffffff,0.015,100);
renderScene();
}

window.onload
= init;

</script>
</body>
</html>

 

  1.4 基于深度着色的材质------MeshDepthMaterial

    该种材质的外观不是由光照或者材质属性visible决定的,而是物体和相机的距离决定,

    因此使用这种材质很容易创建出逐渐消失的效果

    注意这个demo使用了场景的overrideMaterial属性

 Three.js开发指南---使用three.js的材质(第四章)

<!DOCTYPE html>

<html>

<head>
<title>1</title>
<script type="text/javascript" src="three.js"></script>
<script type="text/javascript" src="dat.gui.js"></script>
<style>
body
{
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin
: 0;
overflow
: hidden;
}
</style>
</head>
<body>

<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div>

<!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript">
//var scene
function init() {
//生成一个场景
var scene=new THREE.Scene();

//这里我们使用场景的overrideMaterial属性,即场景中的所有物体都应用这一种材质
scene.overrideMaterial = new THREE.MeshDepthMaterial();


//生成一个相机
//参数:视场,长宽比,近面,远面
var camera=new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,10,100);
camera.position.x=-50;
camera.position.y
=40;
camera.position.z
=50;
camera.lookAt(scene.position);
scene.add(camera);

var render;

//生成一个webgl的渲染器
var webGLrender=new THREE.WebGLRenderer();
webGLrender.setClearColor(
0xEEEEEE);
webGLrender.setSize(window.innerWidth,window.innerHeight);
webGLrender.shadowMapEnabled
=true;
//允许阴影映射,渲染阴影需要大量的资源,因此我们需要告诉渲染器我们需要阴影
render=webGLrender;



//生成一个方块,并添加到场景中
var cubeGeometry=new THREE.BoxGeometry(10,10,10);
var cube=new THREE.Mesh(cubeGeometry,new THREE.MeshLambertMaterial({"color":0xeeeeee}));
cube.castShadow
=true;
cube.position.set(
0,3,2);
scene.add(cube);



//增加图形控制界面
var controls=new function(){
this.cameraNear=camera.near;
this.cameraFar=camera.far;
this.rotationSpeed=0.02;
this.addCube=function(){
var size=Math.random()*3+3;
var cubeGeo=new THREE.BoxGeometry(4,4,10,10);
var cube=new THREE.Mesh(cubeGeo,new THREE.MeshLambertMaterial({color:Math.random()*0xffffff}));
cube.castShadow
=true;
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);
}

};

var gui=new dat.GUI();
gui.add(controls,
"cameraNear",0,50).onChange(function(e){
camera.near
=e;
});
gui.add(controls,
"cameraFar",0,50).onChange(function(e){
camera.far
=e;
});
gui.add(controls,
"rotationSpeed",0,0.3);
gui.add(controls,
'addCube');

for(var i=0;i<10;i++){
controls.addCube();
}

//gui的一个参数是一个对象,该对象控制的属性是add的函数的第二个参数
//即controls的this.switchRender必须与下面的属性一致

document.getElementById(
"WebGL-output").append(render.domElement);




function renderScene(){
scene.traverse(
function(e){
if(e instanceof THREE.Mesh){
e.rotation.x
+=controls.rotationSpeed;
e.rotation.y
+=controls.rotationSpeed;
e.rotation.z
+=controls.rotationSpeed;
}
});
requestAnimationFrame(renderScene);
render.render(scene, camera);
}
//scene.fog=new THREE.Fog(0xffffff,0.015,100);
renderScene();
}

window.onload
= init;

</script>
</body>
</html>

 

 

  1.5 联合材质

    当一个几何体应用多种材质的时候,使用的就不是THREE.Mesh来创建网格了,

    而是THREE.SceneUtil.createMultiMaterialObject方法

    另外需要注意的细节,我们需要把MeshBasicMaterial材质的transparent值设置为true,

    只有材质的transparent的值为true,three.js才会检查该材质的blending属性,进行融合操作

Three.js开发指南---使用three.js的材质(第四章)

<!DOCTYPE html>

<html>

<head>
<title>1</title>
<script type="text/javascript" src="three.js"></script>
<script type="text/javascript" src="dat.gui.js"></script>
<style>
body
{
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin
: 0;
overflow
: hidden;
}
</style>
</head>
<body>

<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div>

<!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript">
//var scene
function init() {
//生成一个场景
var scene=new THREE.Scene();

//生成一个相机
//参数:视场,长宽比,近面,远面
var camera=new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,10,100);
camera.position.x=-50;
camera.position.y
=40;
camera.position.z
=50;
camera.lookAt(scene.position);
scene.add(camera);

var render;

//生成一个webgl的渲染器
var webGLrender=new THREE.WebGLRenderer();
webGLrender.setClearColor(
0xEEEEEE);
webGLrender.setSize(window.innerWidth,window.innerHeight);
webGLrender.shadowMapEnabled
=true;
//允许阴影映射,渲染阴影需要大量的资源,因此我们需要告诉渲染器我们需要阴影
render=webGLrender;


//增加图形控制界面
var controls=new function(){
this.cameraNear=camera.near;
this.cameraFar=camera.far;
this.rotationSpeed=0.02;
this.addCube=function(){
var size=Math.random()*3+3;
var cubeGeo=new THREE.BoxGeometry(4,4,10,10);
var basicMaterial=new THREE.MeshBasicMaterial({
color:
0x00ff00,
transparent:
true,//注意这里一定要设置基础材质的透明度为true
blending: THREE.MultiplyBlending
//这里的融合方式选择的是MultiplyBlending
//即最终展示的颜色是前景颜色和背景的颜色相乘后得到的
});
var depthMaterial=new THREE.MeshDepthMaterial();
var cube=new THREE.SceneUtils.createMultiMaterialObject(cubeGeo,[basicMaterial,depthMaterial]);

//cube.children[1].scale.set(0.99,0.99,0.99);
cube.castShadow=true;
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);
}

};

var gui=new dat.GUI();
gui.add(controls,
"cameraNear",0,50).onChange(function(e){
camera.near
=e;
});
gui.add(controls,
"cameraFar",0,50).onChange(function(e){
camera.far
=e;
});
gui.add(controls,
"rotationSpeed",0,0.3);
gui.add(controls,
'addCube');

for(var i=0;i<10;i++){
controls.addCube();
}


document.getElementById(
"WebGL-output").append(render.domElement);




function renderScene(){
scene.traverse(
function(e){
if(e instanceof THREE.Mesh){
e.rotation.x
+=controls.rotationSpeed;
e.rotation.y
+=controls.rotationSpeed;
e.rotation.z
+=controls.rotationSpeed;
}
});
requestAnimationFrame(renderScene);
render.render(scene, camera);
}
//scene.fog=new THREE.Fog(0xffffff,0.015,100);
renderScene();
}

window.onload
= init;

</script>
</body>
</html>

 

 

  1.6 计算法向量颜色的材质------MeshNormalMaterial

    将该材质应用到几何体对象的时候,几何体对象的每一面的颜色都是从该面向外的法向量计算得到的

    法向量决定了光反射的方向,在三维物体上映射材质时起辅助作用,还可以在计算光照,阴影时提供信息,为物体表面的像素上色

    法向量所指的方向决定每个面从MeshNormalMaterial材质获取的颜色

   //圆球每个面的法向量都不同我可以理解,但是法向量如何与颜色相联系在一起,没有搞明白

     下面的demo,设置transparent为true,opacity为0.5,我们不仅可以看到计算法向颜色的材质,还可以看到材质共有的属性side的值front,back,both的效果

 Three.js开发指南---使用three.js的材质(第四章)Three.js开发指南---使用three.js的材质(第四章)Three.js开发指南---使用three.js的材质(第四章)

 

 

 

Three.js开发指南---使用three.js的材质(第四章)Three.js开发指南---使用three.js的材质(第四章)Three.js开发指南---使用three.js的材质(第四章)

 

<!DOCTYPE html>

<html>

<head>
<title>1</title>
<script type="text/javascript" src="three.js"></script>
<script type="text/javascript" src="dat.gui.js"></script>
<style>
body
{
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin
: 0;
overflow
: hidden;
}
</style>
</head>
<body>

<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div>

<!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript">
//var scene
function init() {
//生成一个场景
var scene=new THREE.Scene();

//生成一个相机
//参数:视场,长宽比,近面,远面
var camera=new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,10,100);
camera.position.x=-50;
camera.position.y
=40;
camera.position.z
=50;
camera.lookAt(scene.position);
scene.add(camera);

var render;

//生成一个webgl的渲染器
var webGLrender=new THREE.WebGLRenderer();
webGLrender.setClearColor(
0xEEEEEE);
webGLrender.setSize(window.innerWidth,window.innerHeight);
webGLrender.shadowMapEnabled
=true;
//允许阴影映射,渲染阴影需要大量的资源,因此我们需要告诉渲染器我们需要阴影
render=webGLrender;

var ambientLight = new THREE.AmbientLight(0x0c0c0c);
scene.add(ambientLight);

// add spotlight for the shadows
var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(
-40, 60, -10);
spotLight.castShadow
= true;
scene.add(spotLight);

var sphereGeometry = new THREE.SphereGeometry(14, 20, 20);
var meshMaterial = new THREE.MeshNormalMaterial({color: 0x7777ff});
var sphere = new THREE.Mesh(sphereGeometry, meshMaterial);
sphere.position.x
= 0;
sphere.position.y
= 3;
sphere.position.z
= 2;
for (var f = 0, fl = sphere.geometry.faces.length; f < fl; f++) {
var face = sphere.geometry.faces[f];
f
==0?console.log(face)&&console.log(sphere.geometry.vertices[face.a]):"";
var centroid = new THREE.Vector3(0, 0, 0);
centroid.add(sphere.geometry.vertices[face.a]);
centroid.add(sphere.geometry.vertices[face.b]);
centroid.add(sphere.geometry.vertices[face.c]);
centroid.divideScalar(
3);//这个函数没有看明白是做什么的

var arrow = new THREE.ArrowHelper(
face.normal,
//面的法向量
centroid,//该面的质心
2,
0x3333FF,//颜色
0.5,
0.5);
sphere.add(arrow);
}

scene.add(sphere);


//增加图形控制界面
var controls=new function(){
this.opacity=1;
this.transparent=false;
this.rotationSpeed=0.02;
this.side="front";

};

var gui=new dat.GUI();
gui.add(controls,
"opacity",0,1).onChange(function(e){
meshMaterial.opacity
=e;
});
gui.add(controls,
"transparent").onChange(function (e) {
meshMaterial.transparent
= e
});
gui.add(controls,
"rotationSpeed",0,0.3);
gui.add(controls,
'side',["front","back","double"]).onChange(function(e){
switch(e){
case "front":
meshMaterial.side
=THREE.FrontSide;
break;
case "back":
meshMaterial.side
=THREE.BackSide;
break;
case "double":
meshMaterial.side
=THREE.DoubleSide;
break;
}

});

//gui的一个参数是一个对象,该对象控制的属性是add的函数的第二个参数
//即controls的this.switchRender必须与下面的属性一致

document.getElementById(
"WebGL-output").append(render.domElement);




function renderScene(){
scene.traverse(
function(e){
if(e instanceof THREE.Mesh){
e.rotation.x
+=controls.rotationSpeed;
e.rotation.y
+=controls.rotationSpeed;
e.rotation.z
+=controls.rotationSpeed;
}
});
requestAnimationFrame(renderScene);
render.render(scene, camera);
}
//scene.fog=new THREE.Fog(0xffffff,0.015,100);
renderScene();
}

window.onload
= init;

</script>
</body>
</html>

 

  1.7 为几何体的每一面都指定材质的材质----MeshFaceMaterial

    这种并不是真正的材质,而更像一种材质容器,通过MeshFaceMaterial可以为几何体的每一个面都指定不同的材质

<!DOCTYPE html>

<html>

<head>
<title>1</title>
<script type="text/javascript" src="three.js"></script>
<script type="text/javascript" src="dat.gui.js"></script>
<style>
body
{
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin
: 0;
overflow
: hidden;
}
</style>
</head>
<body>

<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div>

<!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript">
//var scene
function init() {
//生成一个场景
var scene=new THREE.Scene();

//生成一个相机
//参数:视场,长宽比,近面,远面
var camera=new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,10,100);
camera.position.x=-50;
camera.position.y
=40;
camera.position.z
=50;
camera.lookAt(scene.position);
scene.add(camera);

var render;

//生成一个webgl的渲染器
var webGLrender=new THREE.WebGLRenderer();
webGLrender.setClearColor(
0xEEEEEE);
webGLrender.setSize(window.innerWidth,window.innerHeight);
webGLrender.shadowMapEnabled
=true;
//允许阴影映射,渲染阴影需要大量的资源,因此我们需要告诉渲染器我们需要阴影
render=webGLrender;

var ambientLight = new THREE.AmbientLight(0x0c0c0c);
scene.add(ambientLight);

// add spotlight for the shadows
var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(
-40, 60, -10);
spotLight.castShadow
= true;
scene.add(spotLight);


//生成一个有6个基础材质的数组
var materials=[];
materials.push(
new THREE.MeshBasicMaterial({color:"red"}));
materials.push(
new THREE.MeshBasicMaterial({color:"blue"}));
materials.push(
new THREE.MeshBasicMaterial({color:"yellow"}));
materials.push(
new THREE.MeshBasicMaterial({color:"green"}));
materials.push(
new THREE.MeshBasicMaterial({color:"white"}));
materials.push(
new THREE.MeshBasicMaterial({color:"black"}));
//这6个基础材质的数组作为参数传递给MeshFaceMaterial
var faceMaterial=new THREE.MeshFaceMaterial(materials);

//生成一个方块应用faceMaterial,即为每个面指定一种材质
var cubeGeom=new THREE.CubeGeometry(6,6,6);
var cube=new THREE.Mesh(cubeGeom,faceMaterial);
scene.add(cube);


//增加图形控制界面
var controls=new function(){

this.rotationSpeed=0.02;

};

var gui=new dat.GUI();

gui.add(controls,
"rotationSpeed",0,0.3);


//gui的一个参数是一个对象,该对象控制的属性是add的函数的第二个参数
//即controls的this.switchRender必须与下面的属性一致

document.getElementById(
"WebGL-output").append(render.domElement);




function renderScene(){
scene.traverse(
function(e){
if(e instanceof THREE.Mesh){
e.rotation.x
+=controls.rotationSpeed;
e.rotation.y
+=controls.rotationSpeed;
e.rotation.z
+=controls.rotationSpeed;
}
});
requestAnimationFrame(renderScene);
render.render(scene, camera);
}
//scene.fog=new THREE.Fog(0xffffff,0.015,100);
renderScene();
}

window.onload
= init;

</script>
</body>
</html>

 这里的demo做了一个魔方

  1 一共需要生成27个方块

  2 每个方块的每个面都应用材质数组中材质,即每一个小方块的各个面颜色都不同

  3 方块的长宽要比10小一些,留个空隙

  4 注意一下每个方块的position

  5 这些方块追加到一个网格中,然后再将网格追加到场景中

  6 旋转的时候,是这个网格在旋转,而不是每个单独的旋转

Three.js开发指南---使用three.js的材质(第四章)

 

  

<!DOCTYPE html>

<html>

<head>
<title>1</title>
<script type="text/javascript" src="three.js"></script>
<script type="text/javascript" src="dat.gui.js"></script>
<style>
body
{
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin
: 0;
overflow
: hidden;
}
</style>
</head>
<body>

<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div>

<!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript">
//var scene
function init() {
//生成一个场景
var scene=new THREE.Scene();

//生成一个相机
//参数:视场,长宽比,近面,远面
var camera=new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,10,100);
camera.position.x=-50;
camera.position.y
=40;
camera.position.z
=50;
camera.lookAt(scene.position);
scene.add(camera);

var render;

//生成一个webgl的渲染器
var webGLrender=new THREE.WebGLRenderer();
webGLrender.setClearColor(
0xEEEEEE);
webGLrender.setSize(window.innerWidth,window.innerHeight);
webGLrender.shadowMapEnabled
=true;
//允许阴影映射,渲染阴影需要大量的资源,因此我们需要告诉渲染器我们需要阴影
render=webGLrender;

var ambientLight = new THREE.AmbientLight(0x0c0c0c);
scene.add(ambientLight);

// add spotlight for the shadows
var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(
-40, 60, -10);
spotLight.castShadow
= true;
scene.add(spotLight);


//生成一个有6个基础材质的数组
var materials=[],group=new THREE.Mesh();
materials.push(
new THREE.MeshBasicMaterial({color:"red"}));
materials.push(
new THREE.MeshBasicMaterial({color:"blue"}));
materials.push(
new THREE.MeshBasicMaterial({color:"yellow"}));
materials.push(
new THREE.MeshBasicMaterial({color:"green"}));
materials.push(
new THREE.MeshBasicMaterial({color:"white"}));
materials.push(
new THREE.MeshBasicMaterial({color:"black"}));
//这6个基础材质的数组作为参数传递给MeshFaceMaterial
var faceMaterial=new THREE.MeshFaceMaterial(materials);

//生成27个方块,每三个应用一种材质,即为每个面指定一种材质
for(var x=0;x<3;x++){
for(var y=0;y<3;y++){
for(var z=0;z<3;z++){
var cubeGeom=new THREE.BoxGeometry(9,9,9,9);
var cube=new THREE.Mesh(cubeGeom,faceMaterial);
cube.position.set(x
*10-10,y*10,z*10-10
);
group.add(cube);

}
}
}
scene.add(group);


//增加图形控制界面
var controls=new function(){

this.rotationSpeed=0.02;

};

var gui=new dat.GUI();

gui.add(controls,
"rotationSpeed",0,0.3);


//gui的一个参数是一个对象,该对象控制的属性是add的函数的第二个参数
//即controls的this.switchRender必须与下面的属性一致

document.getElementById(
"WebGL-output").append(render.domElement);




function renderScene(){
group.rotation.x
+=controls.rotationSpeed;
group.rotation.y
+=controls.rotationSpeed;
group.rotation.z
+=
controls.rotationSpeed;
requestAnimationFrame(renderScene);
render.render(scene, camera);
}
//scene.fog=new THREE.Fog(0xffffff,0.015,100);
renderScene();
}

window.onload
= init;

</script>
</body>
</html>

 

 1.8 高级材质

    1 MeshLambertMaterial:会对光源做出反应,可以用来创建暗淡的材质

      MeshLambertMaterial材质的ambient(环境色)属性:该材质的环境色,跟AmbientLight光源一起使用,这个颜色会与AmbientLight光源的颜色相乘,该属性的默认值是白色

      MeshLambertMaterial材质的emissive(发射色)属性:该材质发射的颜色,它其实并不是光源,而是一种纯粹的,不受其他光照影响的颜色,该属性的默认值是黑色

Three.js开发指南---使用three.js的材质(第四章)

 

<!DOCTYPE html>

<html>

<head>
<title>1</title>
<script type="text/javascript" src="three.js"></script>
<script type="text/javascript" src="dat.gui.js"></script>
<style>
body
{
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin
: 0;
overflow
: hidden;
}
</style>
</head>
<body>

<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div>

<!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript">
//var scene
function init() {
//生成一个场景
var scene=new THREE.Scene();

//生成一个相机
//参数:视场,长宽比,近面,远面
var camera=new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,10,100);
camera.position.x=-20;
camera.position.y
=30;
camera.position.z
=40;
camera.lookAt(scene.position);
scene.add(camera);

var render;

//生成一个webgl的渲染器
var webGLrender=new THREE.WebGLRenderer();
webGLrender.setClearColor(
0xEEEEEE);
webGLrender.setSize(window.innerWidth,window.innerHeight);
webGLrender.shadowMapEnabled
=true;
//允许阴影映射,渲染阴影需要大量的资源,因此我们需要告诉渲染器我们需要阴影
render=webGLrender;

var ambientLight = new THREE.AmbientLight(0x0c0c0c);
scene.add(ambientLight);

// add spotlight for the shadows
var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(
-40, 60, -10);
spotLight.castShadow
= true;
scene.add(spotLight);

var planeGeometry = new THREE.PlaneGeometry(1000, 1000, 4, 4);
var plane = new THREE.Mesh(planeGeometry, new THREE.MeshBasicMaterial({color: 0x555555}));
plane.rotation.x
=-Math.PI/2;
plane.position.y=0;
scene.add(plane);

//生成一个有6个基础材质的数组
var cubeGeom=new THREE.BoxGeometry(10,10,10);
var material=new THREE.MeshLambertMaterial({
color:
0x7777ff
});
var cube=new THREE.Mesh(cubeGeom,material);
cube.position.x
=0;
cube.position.y
=13;
cube.position.z
=2;
scene.add(cube);

//增加图形控制界面
var controls=new function(){
this.ambient=material.ambient.getHex();
this.emissive=material.emissive.getHex();
this.rotationSpeed=0.02;
this.opacity=material.opacity;
this.transparent=material.transparent;
this.side="front";

};

var gui=new dat.GUI();

gui.add(controls,
"rotationSpeed",0,0.3);
gui.add(controls,
"opacity",0,1).onChange(function(e){
material.opacity
=e;
});
gui.add(controls,
"transparent").onChange(function(e){
material.transparent
=e;
});
gui.add(controls,
"side",["front","back","double"]).onChange(function(e){

switch(e){
case "front":
material.side
=THREE.FrontSide;
break;
case "back":
material.side
=THREE.BackSide;
break;
case "double":
material.side
=THREE.DoubleSide;
break;
}
material.needsUpdate
=true;
});
//使用addColor方法,添加gui颜色选择器
gui.addColor(controls,"ambient").onChange(function(e){
//颜色选择器获取到的是gbs,需要转化THREE的color格式
material.ambient=new THREE.Color(e);
});
gui.addColor(controls,
"emissive").onChange(function(e){
material.emissive
=new THREE.Color(e);
});

//gui的一个参数是一个对象,该对象控制的属性是add的函数的第二个参数
//即controls的this.switchRender必须与下面的属性一致

document.getElementById(
"WebGL-output").append(render.domElement);




function renderScene(){
cube.rotation.x
+=controls.rotationSpeed;
cube.rotation.y
+=controls.rotationSpeed;
cube.rotation.z
+=controls.rotationSpeed;
requestAnimationFrame(renderScene);
render.render(scene, camera);
}
//scene.fog=new THREE.Fog(0xffffff,0.015,100);
renderScene();
}

window.onload
= init;

</script>
</body>
</html>

 

    2 MeshPhongMaterial:会对光源做出反应,可以用来创建光亮的材质

名称 描述
specular(镜面)

该属性指定该材质的光亮程度及其高光部分的颜色,

如果将它设置跟color的颜色相同,就会得到一种类似于金属的材质

如果设置成灰色,材质就会显得更像塑料

shininess 该属性指定高光部分的亮度,默认值是30

 

    Three.js开发指南---使用three.js的材质(第四章)Three.js开发指南---使用three.js的材质(第四章)

<!DOCTYPE html>

<html>

<head>
<title>Example 04.06 - Mesh Lambert material</title>
<script type="text/javascript" src="../libs/three.js"></script>

<script type="text/javascript" src="../libs/stats.js"></script>
<script type="text/javascript" src="../libs/dat.gui.js"></script>
<script type="text/javascript" src="../libs/CanvasRenderer.js"></script>
<script type="text/javascript" src="../libs/Projector.js"></script>

<style>
body
{
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin
: 0;
overflow
: hidden;
}
</style>
</head>
<body>

<div id="Stats-output">
</div>
<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div>

<!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript">

// once everything is loaded, we run our Three.js stuff.
function init() {

var stats = initStats();

// create a scene, that will hold all our elements such as objects, cameras and lights.
var scene = new THREE.Scene();

// create a camera, which defines where we're looking at.
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

// create a render and set the size
var renderer;
var webGLRenderer = new THREE.WebGLRenderer();
webGLRenderer.setClearColor(
new THREE.Color(0xEEEEEE, 1.0));
webGLRenderer.setSize(window.innerWidth, window.innerHeight);
webGLRenderer.shadowMapEnabled
= true;

var canvasRenderer = new THREE.CanvasRenderer();
canvasRenderer.setSize(window.innerWidth, window.innerHeight);
renderer
= webGLRenderer;

var groundGeom = new THREE.PlaneGeometry(100, 100, 4, 4);
var groundMesh = new THREE.Mesh(groundGeom, new THREE.MeshBasicMaterial({color: 0x555555}));
groundMesh.rotation.x
= -Math.PI / 2;
groundMesh.position.y
= -20;
scene.add(groundMesh);

var sphereGeometry = new THREE.SphereGeometry(14, 20, 20);
var cubeGeometry = new THREE.BoxGeometry(15, 15, 15);
var planeGeometry = new THREE.PlaneGeometry(14, 14, 4, 4);


var meshMaterial = new THREE.MeshLambertMaterial({color: 0x7777ff});
var sphere = new THREE.Mesh(sphereGeometry, meshMaterial);
var cube = new THREE.Mesh(cubeGeometry, meshMaterial);
var plane = new THREE.Mesh(planeGeometry, meshMaterial);

// position the sphere
sphere.position.x = 0;
sphere.position.y
= 3;
sphere.position.z
= 2;


cube.position
= sphere.position;
plane.position
= sphere.position;


// add the sphere to the scene
scene.add(cube);

// position and point the camera to the center of the scene
camera.position.x = -20;
camera.position.y
= 30;
camera.position.z
= 40;
camera.lookAt(
new THREE.Vector3(10, 0, 0));

// add subtle ambient lighting
var ambientLight = new THREE.AmbientLight(0x0c0c0c);
scene.add(ambientLight);

// add spotlight for the shadows
var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(
-30, 60, 60);
spotLight.castShadow
= true;
scene.add(spotLight);

// add the output of the renderer to the html element
document.getElementById("WebGL-output").appendChild(renderer.domElement);

// call the render function
var step = 0;

var controls = new function () {
this.rotationSpeed = 0.02;
this.bouncingSpeed = 0.03;

this.opacity = meshMaterial.opacity;
this.transparent = meshMaterial.transparent;
this.overdraw = meshMaterial.overdraw;
this.visible = meshMaterial.visible;
this.emissive = meshMaterial.emissive.getHex();
this.ambient = meshMaterial.ambient.getHex();
this.side = "front";

this.color = meshMaterial.color.getStyle();
this.wrapAround = false;
this.wrapR = 1;
this.wrapG = 1;
this.wrapB = 1;

this.selectedMesh = "cube";

};

var gui = new dat.GUI();


var spGui = gui.addFolder("Mesh");
spGui.add(controls,
'opacity', 0, 1).onChange(function (e) {
meshMaterial.opacity
= e
});
spGui.add(controls,
'transparent').onChange(function (e) {
meshMaterial.transparent
= e
});
spGui.add(controls,
'visible').onChange(function (e) {
meshMaterial.visible
= e
});
spGui.addColor(controls,
'ambient').onChange(function (e) {
meshMaterial.ambient
= new THREE.Color(e)
});
spGui.addColor(controls,
'emissive').onChange(function (e) {
meshMaterial.emissive
= new THREE.Color(e)
});
spGui.add(controls,
'side', ["front", "back", "double"]).onChange(function (e) {
console.log(e);
switch (e) {
case "front":
meshMaterial.side
= THREE.FrontSide;
break;
case "back":
meshMaterial.side
= THREE.BackSide;
break;
case "double":
meshMaterial.side
= THREE.DoubleSide;
break;
}
meshMaterial.needsUpdate
= true;

});
spGui.addColor(controls,
'color').onChange(function (e) {
meshMaterial.color.setStyle(e)
});
spGui.add(controls,
'selectedMesh', ["cube", "sphere", "plane"]).onChange(function (e) {

scene.remove(plane);
scene.remove(cube);
scene.remove(sphere);

switch (e) {
case "cube":
scene.add(cube);
break;
case "sphere":
scene.add(sphere);
break;
case "plane":
scene.add(plane);
break;

}


scene.add(e);
});

spGui.add(controls,
'wrapAround').onChange(function (e) {

meshMaterial.wrapAround
= e;
meshMaterial.needsUpdate
= true;
});

spGui.add(controls,
'wrapR', 0, 1).step(0.01).onChange(function (e) {
meshMaterial.wrapRGB.x
= e;
});

spGui.add(controls,
'wrapG', 0, 1).step(0.01).onChange(function (e) {
meshMaterial.wrapRGB.y
= e;
});

spGui.add(controls,
'wrapB', 0, 1).step(0.01).onChange(function (e) {
meshMaterial.wrapRGB.z
= e;

});

render();

function render() {
stats.update();

cube.rotation.y
= step += 0.01;
plane.rotation.y
= step;
sphere.rotation.y
= step;

// render using requestAnimationFrame
requestAnimationFrame(render);
renderer.render(scene, camera);
}

function initStats() {

var stats = new Stats();

stats.setMode(
0); // 0: fps, 1: ms


// Align top-left
stats.domElement.style.position = 'absolute';
stats.domElement.style.left
= '0px';
stats.domElement.style.top
= '0px';

document.getElementById(
"Stats-output").appendChild(stats.domElement);

return stats;
}
}
window.onload
= init;
</script>
</body>
</html>

 

 

    3 ShaderMaterial:最通用也是最难用的材质,通过ShaderMaterial可以创建自己的着色程序,直接在webgl环境中运行,

    着色器可以将three.js中的js对象转化为屏幕上的像素,

    注意着色器不是js编写的,而是类似于c的GLSL语言,所以下面这个demo只是一个例子,并不做过多的解释

<!DOCTYPE html>

<html>

<head>
<title>Example 04.08 - Shader material - http://glsl.heroku.com/</title>
<script type="text/javascript" src="../libs/three.js"></script>

<script type="text/javascript" src="../libs/stats.js"></script>
<script type="text/javascript" src="../libs/dat.gui.js"></script>
<style>
body
{
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin
: 0;
overflow
: hidden;
}
</style>
</head>
<body>

<script id="vertex-shader" type="x-shader/x-vertex">
uniform
float time;
varying vec2 vUv;


void main()
{
vec3 posChanged
= position;
posChanged.x
= posChanged.x*(abs(sin(time*1.0)));
posChanged.y
= posChanged.y*(abs(cos(time*1.0)));
posChanged.z
= posChanged.z*(abs(sin(time*1.0)));
//gl_Position = projectionMatrix * modelViewMatrix * vec4(position*(abs(sin(time)/2.0)+0.5),1.0);
gl_Position = projectionMatrix * modelViewMatrix * vec4(posChanged,1.0);
}

</script>

<script id="fragment-shader-1" type="x-shader/x-fragment">
precision highp
float;
uniform
float time;
uniform
float alpha;
uniform vec2 resolution;
varying vec2 vUv;

void main2(void)
{
vec2 position
= vUv;
float red = 1.0;
float green = 0.25 + sin(time) * 0.25;
float blue = 0.0;
vec3 rgb
= vec3(red, green, blue);
vec4 color
= vec4(rgb, alpha);
gl_FragColor
= color;
}

#define PI
3.14159
#define TWO_PI (PI
*2.0)
#define N
68.5

void main(void)
{
vec2 center
= (gl_FragCoord.xy);
center.x
=-10.12*sin(time/200.0);
center.y=-10.12*cos(time/200.0);

vec2 v
= (gl_FragCoord.xy - resolution/20.0) / min(resolution.y,resolution.x) * 15.0;
v.x
=v.x-10.0;
v.y
=v.y-200.0;
float col = 0.0;

for(float i = 0.0; i < N; i++)
{
float a = i * (TWO_PI/N) * 61.95;
col += cos(TWO_PI*(v.y * cos(a) + v.x * sin(a) + sin(time*0.004)*100.0 ));
}

col
/= 5.0;

gl_FragColor
= vec4(col*1.0, -col*1.0,-col*4.0, 1.0);
}


</script>

<script id="fragment-shader-2" type="x-shader/x-fragment">
// from http://glsl.heroku.com/e#7906.0


uniform
float time;
uniform vec2 resolution;

// 2013-03-30 by @hintz

#define CGFloat
float
#define M_PI
3.14159265359

vec3 hsvtorgb(
float h, float s, float v)
{
float c = v * s;
h
= mod((h * 6.0), 6.0);
float x = c * (1.0 - abs(mod(h, 2.0) - 1.0));
vec3 color;

if (0.0 <= h && h < 1.0)
{
color
= vec3(c, x, 0.0);
}
else if (1.0 <= h && h < 2.0)
{
color
= vec3(x, c, 0.0);
}
else if (2.0 <= h && h < 3.0)
{
color
= vec3(0.0, c, x);
}
else if (3.0 <= h && h < 4.0)
{
color
= vec3(0.0, x, c);
}
else if (4.0 <= h && h < 5.0)
{
color
= vec3(x, 0.0, c);
}
else if (5.0 <= h && h < 6.0)
{
color
= vec3(c, 0.0, x);
}
else
{
color
= vec3(0.0);
}

color
+= v - c;

return color;
}

void main(void)
{

vec2 position
= (gl_FragCoord.xy - 0.5 * resolution) / resolution.y;
float x = position.x;
float y = position.y;

CGFloat a
= atan(x, y);

CGFloat d
= sqrt(x*x+y*y);
CGFloat d0
= 0.5*(sin(d-time)+1.5)*d;
CGFloat d1
= 5.0;

CGFloat u
= mod(a*d1+sin(d*10.0+time), M_PI*2.0)/M_PI*0.5 - 0.5;
CGFloat v = mod(pow(d0*4.0, 0.75),1.0) - 0.5;

CGFloat dd
= sqrt(u*u+v*v);

CGFloat aa
= atan(u, v);

CGFloat uu
= mod(aa*3.0+3.0*cos(dd*30.0-time), M_PI*2.0)/M_PI*0.5 - 0.5;
// CGFloat vv = mod(dd*4.0,1.0) - 0.5;

CGFloat d2
= sqrt(uu*uu+v*v)*1.5;

gl_FragColor
= vec4( hsvtorgb(dd+time*0.5/d1, sin(dd*time), d2), 1.0 );
}

</script>

<script id="fragment-shader-3" type="x-shader/x-fragment">
uniform vec2 resolution;
uniform
float time;

vec2 rand(vec2 pos)
{
return fract( 0.00005 * (pow(pos+2.0, pos.yx + 1.0) * 22222.0));
}
vec2 rand2(vec2 pos)
{
return rand(rand(pos));
}

float softnoise(vec2 pos, float scale)
{
vec2 smplpos
= pos * scale;
float c0 = rand2((floor(smplpos) + vec2(0.0, 0.0)) / scale).x;
float c1 = rand2((floor(smplpos) + vec2(1.0, 0.0)) / scale).x;
float c2 = rand2((floor(smplpos) + vec2(0.0, 1.0)) / scale).x;
float c3 = rand2((floor(smplpos) + vec2(1.0, 1.0)) / scale).x;

vec2 a
= fract(smplpos);
return mix(
mix(c0, c1, smoothstep(
0.0, 1.0, a.x)),
mix(c2, c3, smoothstep(
0.0, 1.0, a.x)),
smoothstep(
0.0, 1.0, a.y));
}

void main(void)
{
vec2 pos
= gl_FragCoord.xy / resolution.y;
pos.x
+= time * 0.1;
float color = 0.0;
float s = 1.0;
for(int i = 0; i < 8; i++)
{
color
+= softnoise(pos+vec2(i)*0.02, s * 4.0) / s / 2.0;
s
*= 2.0;
}
gl_FragColor
= vec4(color);
}

</script>

<script id="fragment-shader-4" type="x-shader/x-fragment">


uniform
float time;
uniform vec2 resolution;

vec2 rand(vec2 pos)
{
return
fract(
(
pow(
pos
+2.0,
pos.yx
+2.0
)
*555555.0
)
);
}

vec2 rand2(vec2 pos)
{
return rand(rand(pos));
}

float softnoise(vec2 pos, float scale) {
vec2 smplpos
= pos * scale;
float c0 = rand2((floor(smplpos) + vec2(0.0, 0.0)) / scale).x;
float c1 = rand2((floor(smplpos) + vec2(1.0, 0.0)) / scale).x;
float c2 = rand2((floor(smplpos) + vec2(0.0, 1.0)) / scale).x;
float c3 = rand2((floor(smplpos) + vec2(1.0, 1.0)) / scale).x;

vec2 a
= fract(smplpos);
return mix(mix(c0, c1, smoothstep(0.0, 1.0, a.x)),
mix(c2, c3, smoothstep(
0.0, 1.0, a.x)),
smoothstep(
0.0, 1.0, a.x));
}

void main( void ) {
vec2 pos
= gl_FragCoord.xy / resolution.y - time * 0.4;

float color = 0.0;
float s = 1.0;
for (int i = 0; i < 6; ++i) {
color
+= softnoise(pos + vec2(0.01 * float(i)), s * 4.0) / s / 2.0;
s
*= 2.0;
}
gl_FragColor
= vec4(color,mix(color,cos(color),sin(color)),color,1);
}

</script>

<script id="fragment-shader-5" type="x-shader/x-fragment">

uniform
float time;
uniform vec2 resolution;

// tie nd die by Snoep Games.

void main( void ) {

vec3 color
= vec3(1.0, 0., 0.);
vec2 pos
= (( 1.4 * gl_FragCoord.xy - resolution.xy) / resolution.xx)*1.5;
float r=sqrt(pos.x*pos.x+pos.y*pos.y)/15.0;
float size1=2.0*cos(time/60.0);
float size2=2.5*sin(time/12.1);

float rot1=13.00; //82.0+16.0*sin(time/4.0);
float rot2=-50.00; //82.0+16.0*sin(time/8.0);
float t=sin(time);
float a = (60.0)*sin(rot1*atan(pos.x-size1*pos.y/r,pos.y+size1*pos.x/r)+time);
a
+= 200.0*acos(pos.x*2.0+cos(time/2.0))+asin(pos.y*5.0+sin(time/2.0));
a
=a*(r/50.0);
a=200.0*sin(a*5.0)*(r/30.0);
if(a>5.0) a=a/200.0;
if(a<0.5) a=a*22.5;
gl_FragColor
= vec4( cos(a/20.0),a*cos(a/200.0),sin(a/8.0), 1.0 );
}


</script>

<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>

<div id="Stats-output">
</div>
<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div>

<!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript">

// once everything is loaded, we run our Three.js stuff.
function init() {

var stats = initStats();

// create a scene, that will hold all our elements such as objects, cameras and lights.
var scene = new THREE.Scene();

// create a camera, which defines where we're looking at.
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

// create a render and set the size

var renderer = new THREE.WebGLRenderer();
renderer.setClearColor(
new THREE.Color(0x000000, 1.0));
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMapEnabled
= true;


var cubeGeometry = new THREE.BoxGeometry(20, 20, 20);

var meshMaterial1 = createMaterial("vertex-shader", "fragment-shader-1");
var meshMaterial2 = createMaterial("vertex-shader", "fragment-shader-2");
var meshMaterial3 = createMaterial("vertex-shader", "fragment-shader-3");
var meshMaterial4 = createMaterial("vertex-shader", "fragment-shader-4");
var meshMaterial5 = createMaterial("vertex-shader", "fragment-shader-5");
var meshMaterial6 = createMaterial("vertex-shader", "fragment-shader-6");


var material = new THREE.MeshFaceMaterial(
[meshMaterial1,
meshMaterial2,
meshMaterial3,
meshMaterial4,
meshMaterial5,
meshMaterial6]);
// var material = new THREE.MeshFaceMaterial([meshMaterial2, meshMaterial2, meshMaterial1, meshMaterial1, meshMaterial1, meshMaterial1]);

var cube = new THREE.Mesh(cubeGeometry, material);


// add the sphere to the scene
scene.add(cube);

// position and point the camera to the center of the scene
camera.position.x = 30;
camera.position.y
= 30;
camera.position.z
= 30;
camera.lookAt(
new THREE.Vector3(0, 0, 0));

// add subtle ambient lighting
var ambientLight = new THREE.AmbientLight(0x0c0c0c);
scene.add(ambientLight);

// add spotlight for the shadows
var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(
-40, 60, -10);
spotLight.castShadow
= true;
scene.add(spotLight);

// add the output of the renderer to the html element
document.getElementById("WebGL-output").appendChild(renderer.domElement);

// call the render function
var step = 0;
var oldContext = null;

var controls = new function () {
this.rotationSpeed = 0.02;
this.bouncingSpeed = 0.03;

this.opacity = meshMaterial1.opacity;
this.transparent = meshMaterial1.transparent;

this.visible = meshMaterial1.visible;
this.side = "front";

this.wireframe = meshMaterial1.wireframe;
this.wireframeLinewidth = meshMaterial1.wireframeLinewidth;

this.selectedMesh = "cube";

this.shadow = "flat";

};


render();

function render() {
stats.update();

cube.rotation.y
= step += 0.01;
cube.rotation.x
= step;
cube.rotation.z
= step;


cube.material.materials.forEach(
function (e) {
e.uniforms.time.value
+= 0.01;
});


// render using requestAnimationFrame
requestAnimationFrame(render);
renderer.render(scene, camera);
}

function initStats() {

var stats = new Stats();

stats.setMode(
0); // 0: fps, 1: ms


// Align top-left
stats.domElement.style.position = 'absolute';
stats.domElement.style.left
= '0px';
stats.domElement.style.top
= '0px';

document.getElementById(
"Stats-output").appendChild(stats.domElement);

return stats;
}

function createMaterial(vertexShader, fragmentShader) {
var vertShader = document.getElementById(vertexShader).innerHTML;
var fragShader = document.getElementById(fragmentShader).innerHTML;

var attributes = {};
var uniforms = {
time: {type:
'f', value: 0.2},
scale: {type:
'f', value: 0.2},
alpha: {type:
'f', value: 0.6},
resolution: {type:
"v2", value: new THREE.Vector2()}
};

uniforms.resolution.value.x
= window.innerWidth;
uniforms.resolution.value.y
= window.innerHeight;

var meshMaterial = new THREE.ShaderMaterial({
uniforms: uniforms,
attributes: attributes,
vertexShader: vertShader,
fragmentShader: fragShader,
transparent:
true

});


return meshMaterial;
}


}
window.onload
= init;
</script>
</body>
</html>

 

1.9 线段几何体的材质

  下面这两种材质只能应用于特定的几何体:THREE.Line(线段)

  1.9.1 LineBaseMaterial:可以设置线段的颜色,宽度,端点,连接点等属性

  1.9.2 LineDashedMaterial:与上面的LineBaseMaterial属性一样,但是可以通过指定短划线和空格的长度,创造出来虚线的效果

  

<!DOCTYPE html>

<html>

<head>
<title>Example 04.09 - Linematerial</title>
<script type="text/javascript" src="../libs/three.js"></script>

<script type="text/javascript" src="../libs/stats.js"></script>
<style>
body
{
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin
: 0;
overflow
: hidden;
}
</style>
</head>
<body>

<div id="Stats-output">
</div>
<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div>

<!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript">

// once everything is loaded, we run our Three.js stuff.
function init() {

//var stats = initStats();

// create a scene, that will hold all our elements such as objects, cameras and lights.
var scene = new THREE.Scene();

// create a camera, which defines where we're looking at.
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

// create a render and set the size
var renderer = new THREE.WebGLRenderer();

renderer.setClearColor(
new THREE.Color(0x000000, 1.0));
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMapEnabled
= true;


// position and point the camera to the center of the scene
camera.position.x = -30;
camera.position.y
= 40;
camera.position.z
= 30;
camera.lookAt(scene.position);

// 环境光 没有特定的光源,该光源不会影响阴影的产生,使用该光源是为了弱化阴影或者添加一些颜色
var ambientLight = new THREE.AmbientLight(0x0c0c0c);
scene.add(ambientLight);

//聚光灯光源,最常使用的光源,锥形效果
var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(
-40, 60, -10);
spotLight.castShadow
= true;
scene.add(spotLight);

/*本处书中给出的例子是gosper曲线,涉及到数学曲线、,本人没有看懂,所以使用了随机生成的点,附带上Gosper函数,
能看懂的朋友,可以留言给我,谢谢了!
function gosper(a, b) {

var turtle = [0, 0, 0];
var points = [];
var count = 0;

rg(a, b, turtle);


return points;

//右走
function rt(x) {
turtle[2] += x;
}

//左走
function lt(x) {
turtle[2] -= x;
}

function fd(dist) {
// ctx.beginPath();
points.push({x: turtle[0], y: turtle[1], z: Math.sin(count) * 5});
// ctx.moveTo(turtle[0], turtle[1]);

var dir = turtle[2] * (Math.PI / 180);
turtle[0] += Math.cos(dir) * dist;
turtle[1] += Math.sin(dir) * dist;

points.push({x: turtle[0], y: turtle[1], z: Math.sin(count) * 5});
// ctx.lineTo(turtle[0], turtle[1]);
// ctx.stroke();

}

function rg(st, ln, turtle) {

st--;
ln = ln / 2.6457;
if (st > 0) {
// ctx.strokeStyle = '#111';
rg(st, ln, turtle);
rt(60);
gl(st, ln, turtle);
rt(120);
gl(st, ln, turtle);
lt(60);
rg(st, ln, turtle);
lt(120);
rg(st, ln, turtle);
rg(st, ln, turtle);
lt(60);
gl(st, ln, turtle);
rt(60);
}
if (st == 0) {
fd(ln);
rt(60);
fd(ln);
rt(120);
fd(ln);
lt(60);
fd(ln);
lt(120);
fd(ln);
fd(ln);
lt(60);
fd(ln);
rt(60)
}
}

function gl(st, ln, turtle) {
st--;
ln = ln / 2.6457;
if (st > 0) {
// ctx.strokeStyle = '#555';
lt(60);
rg(st, ln, turtle);
rt(60);
gl(st, ln, turtle);
gl(st, ln, turtle);
rt(120);
gl(st, ln, turtle);
rt(60);
rg(st, ln, turtle);
lt(120);
rg(st, ln, turtle);
lt(60);
gl(st, ln, turtle);
}
if (st == 0) {
lt(60);
fd(ln);
rt(60);
fd(ln);
fd(ln);
rt(120);
fd(ln);
rt(60);
fd(ln);
lt(120);
fd(ln);
lt(60);
fd(ln);
}
}
}


*/
var points=[];
function getPoints(){
var rmd_x=Math.random()*50;
var rmd_y=Math.random()*50;
var rmd_z=Math.random()*50;
points.push({x:rmd_x, y: rmd_y, z: rmd_z});
}

for(var j=0;j<100;j++){
getPoints();
}

//生成一个几何体
var lines = new THREE.Geometry();
var colors = [];
var i = 0;
//该几何体的顶点由getPoint函数生成的点组成
points.forEach(function (e) {
lines.vertices.push(
new THREE.Vector3(e.x, e.z, e.y));
colors[i]
= new THREE.Color(0xffffff);
colors[i].setHSL(e.x
/ 100 + 0.5, ( e.y * 20 ) / 300, 0.8);
//色调,饱和度,亮度
i++;
});

//该几何体的颜色就是上面得到的颜色
lines.colors = colors;
/*这里有几个点不是很理解,linewidth是设置线段的宽度的,但是这里即使设置到50,也没有任何反应,不知道是哪里写错了
有能找到问题的欢迎留言给我,另外透明度的opacity属性也不起作用
*/


var material = new THREE.LineBasicMaterial({
opacity:
1.0,
linewidth:
4,
vertexColors: THREE.VertexColors
});

var line = new THREE.Line(lines, material);
line.position.set(
25, -30, -60);
scene.add(line);

// add the output of the renderer to the html element
document.getElementById("WebGL-output").appendChild(renderer.domElement);

// call the render function
var step = 0;
render();

function render() {
//stats.update();
line.rotation.z = step += 0.01;

requestAnimationFrame(render);
renderer.render(scene, camera);
}
};

window.onload
= init;


</script>
</body>
</html>

LineDashedMaterial与LineBasicMaterial相似,多了几个属性,dashSize:短划线的长度,gapSize间隔的长度

<!DOCTYPE html>

<html>

<head>
<title>Example 04.09 - Linematerial</title>
<script type="text/javascript" src="../libs/three.js"></script>

<script type="text/javascript" src="../libs/stats.js"></script>
<style>
body
{
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin
: 0;
overflow
: hidden;
}
</style>
</head>
<body>

<div id="Stats-output">
</div>
<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div>

<!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript">

// once everything is loaded, we run our Three.js stuff.
function init() {

//var stats = initStats();

// create a scene, that will hold all our elements such as objects, cameras and lights.
var scene = new THREE.Scene();

// create a camera, which defines where we're looking at.
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

// create a render and set the size
var renderer = new THREE.WebGLRenderer();

renderer.setClearColor(
new THREE.Color(0x000000, 1.0));
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMapEnabled
= true;


// position and point the camera to the center of the scene
camera.position.x = -30;
camera.position.y
= 40;
camera.position.z
= 30;
camera.lookAt(scene.position);

// 环境光 没有特定的光源,该光源不会影响阴影的产生,使用该光源是为了弱化阴影或者添加一些颜色
var ambientLight = new THREE.AmbientLight(0x0c0c0c);
scene.add(ambientLight);

//聚光灯光源,最常使用的光源,锥形效果
var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(
-40, 60, -10);
spotLight.castShadow
= true;
scene.add(spotLight);


var points=[];
function getPoints(){
var rmd_x=Math.random()*50;
var rmd_y=Math.random()*50;
var rmd_z=Math.random()*50;
points.push({x:rmd_x, y: rmd_y, z: rmd_z});
}

for(var j=0;j<100;j++){
getPoints();
}

//生成一个几何体
var lines = new THREE.Geometry();
var colors = [];
var i = 0;
//该几何体的顶点由getPoint函数生成的点组成
points.forEach(function (e) {
lines.vertices.push(
new THREE.Vector3(e.x, e.z, e.y));
colors[i]
= new THREE.Color(0xffffff);
colors[i].setHSL(e.x
/ 100 + 0.5, ( e.y * 20 ) / 300, 0.8);
//色调,饱和度,亮度
i++;
});

//该几何体的颜色就是上面得到的颜色
lines.colors = colors;

//必须调用该方法,如果不调用,间隔就不能显示出来
lines.computeLineDistances();
var material = new
THREE.LineDashedMaterial({
dashSize:
10,//短划线的长度
gapSize:1,//间隔的长度
scale: 0.4,//缩放的比例
vertexColors:THREE.VertexColors//为每个顶点指定一个颜色
});

var line = new THREE.Line(lines, material);
line.position.set(
25, -30, -60);
scene.add(line);

// add the output of the renderer to the html element
document.getElementById("WebGL-output").appendChild(renderer.domElement);

// call the render function
var step = 0;
render();

function render() {
//stats.update();
line.rotation.z = step += 0.01;

requestAnimationFrame(render);
renderer.render(scene, camera);
}
};

window.onload
= init;


</script>
</body>
</html>

 

相关文章