通过设置normalMap属性设置为一个法向纹理,还可以指定凹凸的程度,方法是设置normalScale属性。
<!DOCTYPE html>
<html>
<head>
<title>Example 10.03 - Normal maps</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 {
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">
function init() {
var stats = initStats();
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
var webGLRenderer = new THREE.WebGLRenderer();
webGLRenderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0));
webGLRenderer.setSize(window.innerWidth, window.innerHeight);
webGLRenderer.shadowMapEnabled = true;
var sphere1 = createMesh(new THREE.BoxGeometry(15, 15, 15), "plaster.jpg");
sphere1.rotation.y = -0.5;
sphere1.position.x = 12;
scene.add(sphere1);
var sphere2 = createMesh(new THREE.BoxGeometry(15, 15, 15), "plaster.jpg", "plaster-normal.jpg");
sphere2.rotation.y = 0.5;
sphere2.position.x = -12;
scene.add(sphere2);
console.log(sphere2.geometry.faceVertexUvs);
var floorTex = THREE.ImageUtils.loadTexture("../assets/textures/general/floor-wood.jpg");
var plane = new THREE.Mesh(new THREE.BoxGeometry(200, 100, 0.1, 30), new THREE.MeshPhongMaterial({
color: 0x3c3c3c,
map: floorTex
}));
plane.position.y = -7.5;
plane.rotation.x = -0.5 * Math.PI;
scene.add(plane);
camera.position.x = 00;
camera.position.y = 12;
camera.position.z = 38;
camera.lookAt(new THREE.Vector3(0, 0, 0));
var ambiLight = new THREE.AmbientLight(0x242424);
scene.add(ambiLight);
var light = new THREE.SpotLight();
light.position.set(0, 30, 30);
light.intensity = 1.2;
scene.add(light);
var pointColor = "#ff5808";
var directionalLight = new THREE.PointLight(pointColor);
scene.add(directionalLight);
var sphereLight = new THREE.SphereGeometry(0.2);
var sphereLightMaterial = new THREE.MeshBasicMaterial({
color: 0xac6c25
});
var sphereLightMesh = new THREE.Mesh(sphereLight, sphereLightMaterial);
sphereLightMesh.castShadow = true;
sphereLightMesh.position = new THREE.Vector3(3, 3, 3);
scene.add(sphereLightMesh);
document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement);
var step = 0;
var controls = new function() {
this.normalScale = 1;
this.changeTexture = "plaster";
this.rotate = false;
this.changeTexture = function(e) {
var texture = THREE.ImageUtils.loadTexture("../assets/textures/general/" + e + ".jpg");
sphere2.material.map = texture;
sphere1.material.map = texture;
var bump = THREE.ImageUtils.loadTexture("../assets/textures/general/" + e + "-normal.jpg");
sphere2.material.normalMap = bump;
};
this.updateBump = function(e) {
sphere2.material.normalScale.set(e, e);
}
};
var gui = new dat.GUI();
gui.add(controls, "normalScale", -2, 2).onChange(controls.updateBump);
gui.add(controls, "changeTexture", ['plaster', 'bathroom', 'metal-floor']).onChange(controls.changeTexture);
gui.add(controls, "rotate");
render();
function createMesh(geom, imageFile, normal) {
if (normal) {
var t = THREE.ImageUtils.loadTexture("../assets/textures/general/" + imageFile);
var m = THREE.ImageUtils.loadTexture("../assets/textures/general/" + normal);
var mat2 = new THREE.MeshPhongMaterial();
mat2.map = t;
mat2.normalMap = m;
var mesh = new THREE.Mesh(geom, mat2);
return mesh;
} else {
var t = THREE.ImageUtils.loadTexture("../assets/textures/general/" + imageFile);
var mat1 = new THREE.MeshPhongMaterial({
map: t
});
var mesh = new THREE.Mesh(geom, mat1);
return mesh;
}
return mesh;
}
function createNormalmapShaderMaterial(diffuseMap, normalMap) {
var shader = THREE.ShaderLib["normalmap"];
var uniforms = THREE.UniformsUtils.clone(shader.uniforms);
var dT = THREE.ImageUtils.loadTexture(diffuseMap);
var nT = THREE.ImageUtils.loadTexture(normalMap);
uniforms["uShininess"].value = 50;
uniforms["enableDiffuse"].value = true;
uniforms["uDiffuseColor"].value.setHex(0xffffff);
uniforms["tDiffuse"].value = dT;
uniforms["tNormal"].value = nT;
uniforms["uNormalScale"].value.set(1, 1);
uniforms["uSpecularColor"].value.setHex(0xffffff);
uniforms["enableSpecular"].value = true;
return new THREE.ShaderMaterial({
fragmentShader: shader.fragmentShader,
vertexShader: shader.vertexShader,
uniforms: uniforms,
lights: true
});
}
var invert = 1;
var phase = 0;
function render() {
stats.update();
step += 0.1;
if (controls.rotate) {
sphere1.rotation.y -= 0.01;
sphere2.rotation.y += 0.01;
}
if (phase > 2 * Math.PI) {
invert = invert * -1;
phase -= 2 * Math.PI;
} else {
phase += 0.03;
}
sphereLightMesh.position.z = +(21 * (Math.sin(phase)));
sphereLightMesh.position.x = -14 + (14 * (Math.cos(phase)));
if (invert < 0) {
var pivot = 0;
sphereLightMesh.position.x = (invert * (sphereLightMesh.position.x - pivot)) + pivot;
}
directionalLight.position.copy(sphereLightMesh.position);
requestAnimationFrame(render);
webGLRenderer.render(scene, camera);
}
function initStats() {
var stats = new Stats();
stats.setMode(0);
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>