简介
在上一节,使用three.js的60版本,我们成功的实现了THREE.MeshDepthMaterial的案例。但是,我们没有办法修改它的材质的颜色。而一切都是由材质的默认属性决定的,但是Three.js库可以通过联合材质创建出新的效果(这也是材质融合起作用的地方)。
案例实现
所以,我们就需要从THREE.MeshDepthMaterial对象获得亮度,并且从THREE.MeshBasicMaterial对象获得颜色。
首先,我们需要创建两种材质对象:
var cubeMaterial = new THREE.MeshDepthMaterial();
var colorMaterial = new THREE.MeshBasicMaterial({color: 0x00ff00, transparent: true, blending: THREE.MultiplyBlending});
THREE.MeshDepthMaterial对象没有什么好设置的。而对于THREE.MeshBasicMaterial,要把transparent属性设置为true,并且指定一个融合模式。如果不将transparent属性设置为true,就只会得到绿色的物体,three.js不会执行融合操作。如果将transparent属性设置为true,three.js就会检查blending属性,以查看这个绿色的THREE.MeshBasicMaterial材质如何与背景相互作用。
在这个案例里面我们融合模式使用的THREE.MultiplyBlending对象。这种模式就是会把前景色和背景色相乘,得到想要的结果。
然后我们就调用THREE.SceneUtils.createMultiMaterialObject()方法实例化,进行融合:
var mesh = new THREE.SceneUtils.createMultiMaterialObject(cube, [colorMaterial, cubeMaterial]);
mesh.children[1].scale.set(0.97, 0.97, 0.97);
当使用THREE.SceneUtils.createMultiMaterialObject()创建网格的时候,几何体会被复制,返回一个网格组,里面的两个网格完全相同。正因为两个网格是重合相同的,所以如果立方体动起来就会发现立方体会有闪烁的效果,这是因为当渲染的物体有重合的时候,就会出现这种效果,这种情况,我们就需要设置一些偏差处理这个问题,所以我们缩小了THREE.MeshDepthMaterial网格的大小,来实现了目的。
案例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style type="text/css">
html, body {
margin: 0;
height: 100%;
}
canvas {
display: block;
}
</style>
</head>
<body onl oad="draw();">
</body>
<script src="https://johnson2heng.github.io/three.js-demo/lib/three-v60.js"></script>
<script src="https://johnson2heng.github.io/three.js-demo/lib/js/controls/OrbitControls.js"></script>
<script src="https://johnson2heng.github.io/three.js-demo/lib/js/libs/stats.min.js"></script>
<script src="https://johnson2heng.github.io/three.js-demo/lib/js/libs/dat.gui.min.js"></script>
<script>
var renderer;
function initRender() {
renderer = new THREE.WebGLRenderer({antialias: true,alpha:true});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x000000);
document.body.appendChild(renderer.domElement);
}
var camera;
function initCamera() {
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 40, 100);
camera.lookAt(new THREE.Vector3(0, 0, 0));
}
var scene;
function initScene() {
scene = new THREE.Scene();
}
function initModel() {
//辅助工具
var helper = new THREE.AxisHelper(10);
scene.add(helper);
var s = 25;
var cube = new THREE.CubeGeometry(s, s, s);
var cubeMaterial = new THREE.MeshDepthMaterial();
var colorMaterial = new THREE.MeshBasicMaterial({color: 0x00ff00, transparent: true, blending: THREE.MultiplyBlending});
for (var i = 0; i < 3000; i++) {
var mesh = new THREE.SceneUtils.createMultiMaterialObject(cube, [colorMaterial, cubeMaterial]);
mesh.children[1].scale.set(0.97, 0.97, 0.97);
mesh.position.x = 800 * ( 2.0 * Math.random() - 1.0 );
mesh.position.y = 800 * ( 2.0 * Math.random() - 1.0 );
mesh.position.z = 800 * ( 2.0 * Math.random() - 1.0 );
mesh.rotation.x = Math.random() * Math.PI;
mesh.rotation.y = Math.random() * Math.PI;
mesh.rotation.z = Math.random() * Math.PI;
mesh.updateMatrix();
scene.add(mesh);
}
}
//初始化性能插件
var stats;
function initStats() {
stats = new Stats();
document.body.appendChild(stats.dom);
}
function render() {
renderer.render(scene, camera);
}
//窗口变动触发的函数
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
render();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
//更新控制器
render();
//更新性能插件
stats.update();
//让立方体动起来
for(var i=0; i<scene.children.length; i++){
scene.children[i].rotation.x += 0.02;
scene.children[i].rotation.y += 0.02;
scene.children[i].rotation.z += 0.02;
}
//controls.update();
requestAnimationFrame(animate);
}
function draw() {
initRender();
initScene();
initCamera();
initModel();
initStats();
animate();
window.onresize = onWindowResize;
}
</script>
</html>