材质就像物体的皮肤,决定了几何体的外表,例如是否像草地/金属,是否透明,是否显示线框等
一 材质
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(前后都应用材质) |
<!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属性
<!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属性,进行融合操作
<!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的效果
<!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 旋转的时候,是这个网格在旋转,而不是每个单独的旋转
<!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(发射色)属性:该材质发射的颜色,它其实并不是光源,而是一种纯粹的,不受其他光照影响的颜色,该属性的默认值是黑色
<!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 |
<!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>