赞
踩
上篇我们已经介绍了 three.js 中高级材质中的 MeshLambertMaterial 材质。本篇将要介绍的是另一种与之对应的高级材质 MeshPhongMaterial 材质。通过它可以创建一种光亮表面的材质效果。这种材质的属性基本跟 MeshLambertMaterial 暗淡材质一样,除此之外,我们列出 MeshPhongMaterial 材质中比较感兴趣的特有属性,如下表所示:
属性 | 描述 |
---|---|
ambient (环境光颜色) | 同 MeshLambertMaterial 材质 |
emissive (自发光颜色) | 同 MeshLambertMaterial 材质 |
specular (镜面反射光颜色) | 此属性指定该材质的镜面反射光部分的颜色。如果将它设置成跟 color 属性相同的颜色,则会得到一种更加类似金属的材质;如果设置成 gray 灰色,材质将变得像塑料 |
shininess (镜面反射光强度) | 此属性指定 specular 镜面反射光部分的亮度。默认值是 30 |
- <!DOCTYPE html>
- <html>
- <head>
- <title>示例 04.07 - MeshPhongMaterial</title>
- <script src="../build/three.js"></script>
- <script src="../build/js/controls/OrbitControls.js"></script>
- <script src="../build/js/libs/stats.min.js"></script>
- <script src="../build/js/libs/dat.gui.min.js"></script>
- <script src="../jquery/jquery-3.2.1.min.js"></script>
- <style>
- body {
- /* 设置 margin 为 0,并且 overflow 为 hidden,来完成页面样式 */
- margin: 0;
- overflow: hidden;
- }
- /* 统计对象的样式 */
- #Stats-output {
- position: absolute;
- left: 0px;
- top: 0px;
- }
- </style>
- </head>
- <body>
-
- <!-- 用于 WebGL 输出的 Div -->
- <div id="webgl-output"></div>
- <!-- 用于统计 FPS 输出的 Div -->
- <div id="stats-output"></div>
-
- <!-- 运行 Three.js 示例的 Javascript 代码 -->
- <script type="text/javascript">
-
- var scene;
- var camera;
- var render;
- var webglRender;
- var canvasRender;
- var controls;
- var stats;
- var guiParams;
-
- var ground;
- var cube;
- var sphere;
- var plane;
- var activeMesh;
-
- var meshMaterial;
-
- var ambientLight;
- var spotLight;
- var cameraHelper;
-
- $(function() {
- stats = initStats();
- scene = new THREE.Scene();
-
- webglRender = new THREE.WebGLRenderer( {antialias: true, alpha: true} ); // antialias 抗锯齿
- webglRender.setSize(window.innerWidth, window.innerHeight);
- webglRender.setClearColor(0xeeeeee, 1.0);
- webglRender.shadowMap.enabled = true; // 允许阴影投射
- render = webglRender;
-
- camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 30, 1000); // 2147483647
- camera.position.set(-45.5, 68.2, 90.9);
-
- var target = new THREE.Vector3(10, 0 , 0);
- controls = new THREE.OrbitControls(camera, render.domElement);
- controls.target = target;
- camera.lookAt(target);
-
- $('#webgl-output')[0].appendChild(render.domElement);
- window.addEventListener('resize', onWindowResize, false);
-
- ambientLight = new THREE.AmbientLight(0x0c0c0c);
- scene.add(ambientLight);
-
- spotLight = new THREE.SpotLight(0xffffff);
- spotLight.position.set(0, 30, 60);
- spotLight.castShadow = true;
- scene.add(spotLight);
- cameraHelper = new THREE.CameraHelper(spotLight.shadow.camera);
- scene.add(cameraHelper);
-
- // 加入一个平面
- var groundGeometry = new THREE.PlaneGeometry(100, 100, 4, 4);
- var groundMaterial = new THREE.MeshBasicMaterial({color: 0x777777});
- ground = new THREE.Mesh(groundGeometry, groundMaterial);
- ground.rotation.set(-0.5 * Math.PI, 0, 0); // 沿着 X轴旋转-90°
- scene.add(ground);
-
- // 定义 cube, sphere, plane
- var cubeGeometry = new THREE.BoxGeometry(15, 15, 15);
- var sphereGeometry = new THREE.SphereGeometry(14, 30, 30);
- var planeGeometry = new THREE.PlaneGeometry(14, 14, 4, 4);
-
- // 材质
- meshMaterial = new THREE.MeshPhongMaterial({color: 0x7777ff, transparent: false, opacity: 1.0});
- cube = new THREE.Mesh(cubeGeometry, meshMaterial);
- sphere = new THREE.Mesh(sphereGeometry, meshMaterial);
- plane = new THREE.Mesh(planeGeometry, meshMaterial);
- cube.castShadow = true;
- sphere.castShadow = true;
- plane.castShadow = true;
-
- cube.position.set(0, 12, 0);
- sphere.position.set(0, 14, 0);
- plane.position.set(0, 12, 0);
-
- /** 用来保存那些需要修改的变量 */
- guiParams = new function() {
- this.rotationSpeed = 0.02;
- this.opacity = meshMaterial.opacity;
- this.transparent = meshMaterial.transparent;
- this.visible = meshMaterial.visible;
- this.ambient = '#ffffff';
- this.emissive = '#2a2a2a';
- this.specular = '#ffffff';
- this.shininess = 5;
- this.side = 'front';
- this.color = '#ff000e';
- this.selectedMesh = 'sphere';
- this.spotLight = true;
-
- this.addMesh = function(e) {
- scene.remove(activeMesh);
-
- switch (e) {
- case "cube":
- activeMesh = cube;
- break;
- case "sphere":
- activeMesh = sphere;
- break;
- case "plane":
- activeMesh = plane;
- break;
- }
- scene.add(activeMesh);
- };
- this.updateMaterial = function() {
- meshMaterial.opacity = this.opacity;
- meshMaterial.transparent = this.transparent;
- meshMaterial.visible = this.visible;
- meshMaterial.ambient = new THREE.Color(this.ambient);
- meshMaterial.emissive = new THREE.Color(this.emissive);
- meshMaterial.specular = new THREE.Color(this.specular);
- meshMaterial.shininess = this.shininess;
- meshMaterial.color = new THREE.Color(this.color);
- switch (this.side) {
- case "front":
- meshMaterial.side = THREE.FrontSide;
- break;
- case "back":
- meshMaterial.side = THREE.BackSide;
- break;
- case "double":
- meshMaterial.side = THREE.DoubleSide;
- break;
- }
- meshMaterial.needsUpdate = true;
- }
- }
- /** 定义 dat.GUI 对象,并绑定 guiParams 的几个属性 */
- var gui = new dat.GUI();
- var folder = gui.addFolder('Mesh');
- folder.open();
- folder.add(guiParams, 'opacity', 0.1, 1.0).onChange(function(e) {
- guiParams.updateMaterial();
- });
- folder.add(guiParams, 'transparent').onChange(function(e) {
- guiParams.updateMaterial();
- });
- folder.addColor(guiParams, 'ambient').onChange(function(e) {
- guiParams.updateMaterial();
- });
- folder.addColor(guiParams, 'emissive').onChange(function(e) {
- guiParams.updateMaterial();
- });
- folder.addColor(guiParams, 'specular').onChange(function(e) {
- guiParams.updateMaterial();
- });
- folder.add(guiParams, 'shininess', 1, 200).onChange(function(e) {
- guiParams.updateMaterial();
- });
- folder.add(guiParams, 'visible').onChange(function(e) {
- guiParams.updateMaterial();
- });
- folder.add(guiParams, 'side', ['front', 'back', 'double']).onChange(function(e) {
- console.log(e);
- guiParams.updateMaterial();
- });
- folder.addColor(guiParams, 'color').onChange(function(e) {
- guiParams.updateMaterial();
- });
- folder.add(guiParams, 'selectedMesh', ['cube', 'sphere', 'plane']).onChange(function(e) {
- guiParams.addMesh(e);
- });
- gui.add(guiParams, 'spotLight').onChange(function(e) {
- scene.remove(spotLight);
- scene.remove(cameraHelper);
- if (e) {
- scene.add(spotLight);
- scene.add(cameraHelper);
- }
- });
-
- guiParams.updateMaterial();
- guiParams.addMesh(guiParams.selectedMesh);
-
- renderScene();
- });
-
- /** 渲染场景 */
- function renderScene() {
- stats.update();
- rotateMesh(); // 旋转物体
-
- requestAnimationFrame(renderScene);
- render.render(scene, camera);
- }
-
- /** 初始化 stats 统计对象 */
- function initStats() {
- stats = new Stats();
- stats.setMode(0); // 0 为监测 FPS;1 为监测渲染时间
- $('#stats-output').append(stats.domElement);
- return stats;
- }
-
- /** 当浏览器窗口大小变化时触发 */
- function onWindowResize() {
- camera.aspect = window.innerWidth / window.innerHeight;
- camera.updateProjectionMatrix();
- render.setSize(window.innerWidth, window.innerHeight);
- }
-
- /** 旋转物体 */
- function rotateMesh() {
- scene.traverse(function(mesh) {
- if (mesh instanceof THREE.Mesh && mesh != ground) {
- //mesh.rotation.x += guiParams.rotationSpeed;
- mesh.rotation.y += guiParams.rotationSpeed;
- //mesh.rotation.z += guiParams.rotationSpeed;
- }
- });
- }
-
- </script>
- </body>
- </html>
这个示例大体上跟上一篇的基本一样,所以不再过多嗷述,读者可以自行参考上一篇中提到的相关引导建议去试验。
未完待续···
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。