浅谈three.js

xiaoxiao2021-02-28  73

THREE.js 可以这么理解three+js three 代表3 维世界,js javascript, 这是一个让我们可以在浏览器中绘制3D 效果的javascript 库,通过webgl html5 canvas 提供硬件3D 加速渲染,这样Web 开发人员就可以借助系统显卡来在浏览器里更流畅地展示3D 场景和模型了. THREE.js 中有三个主要的概念,相机(Camera )、场景(Scene )、Renderer (渲染器) 1. 照相机(Camera 学习Camera 之前我们先了解一下THREE.js 中使用的坐标系,如图所示: 构造函数 OrthographicCamera(left, right, top, bottom, near, far); 实例说明 camera = new THREE.OrthographicCamera(-2, 2, 1.5, -1.5, 1, 10); camera.position.set(0, 0, 5); var cubeGeometry = new THREE.CubeGeometry(1,1,1); // 创建一个正方体 var material = new THREE.MeshBasicMaterial({ color : 0xff0000, wireframe : true }); var cube = new THREE.Mesh(cubeGeometry, material); scene.add(cube); renderer.render(scene, camera); 但是这里有一个很奇怪的问题,命名创建的是一个长度为1 的正方体,为啥投影是长方体?这里canvas 面板的长宽比是2:1 ,但是相机的(right-left /(top-bottom) 比例是4 3 ,因此  垂直方向上面被压缩了,所以显示的是一个长方体。 将(right-left /(top-bottom) 的比例同样调整为2:1 camera = new THREE.OrthographicCamera(-2, 2, 1, -1, 1, 10); 2. 光源(Light) 光是自然界中常见的现象,我们把正在发光的物体成为光源。与光相对立的是阴影,光被物体  遮挡住了便形成了阴影。根据光照的效果不同,THREE.js 中抽象除了几种不同的光源。     聚光灯(THREE.SpotLight)     平行光源(THREE.DirectionalLight)     环境光源(THREE.AmbientLight)     半球光源(THREE.HemisphereLight)     点光源(THREE.PointLight)     聚光灯(SpotLight) 聚光灯像某个方向进行照射的光源,其光照范围呈圆锥状。 构造函数 SpotLight(color, intensity,distance, angle, penumbra, decay); color :光的颜色 intensity :光的强度 distance :光能照射的最远的距离,按照光的强度按照距离呈线性衰减。 angle :照射的中心点到圆锥上边距的夹角 decay :光线衰减的速率 除了构造函数中的几个属性之外,SpotLight 还有一个很重要的属性target ,点光源聚焦的地方  ,该属性值是一个Object3D 的实例,将target 的值设置为一个运动中的物体可以让点光源跟随物体的运动而运动。 THREE.js 中只有聚光灯(SpotLight) 和平行光源(DirectionalLight) 可以产生阴影,这里看看如何让聚光灯产生阴影。  1>. 告诉renderer 需要渲染阴影 var renderer = new THREE.WEBGLRenderer(); renderer.shadowMapEnabled = true; or renderer.shadowMap.enabled = true; 2>. 告诉THREE.js 哪些物体会投射阴影, 哪些物体会接收阴影 cubeMesh.castShadow = true; //cubeMesh 会在其他的物体上面投射阴影 floorMesh.receiveShadow = true; //floorMesh 会接收其他物体在其上投射的阴影 3>. 添加聚光灯 var spotLight = new THREE.SpotLight(); spotLight.angle = Math.PI / 8; spotLight.exponent = 30; spotLight.position = new THREE.Vector3(40, 60, -50); scene.add(spotLight); 4>. 设置阴影相关的属性 spotLight.castShadow = true; spotLight.shadow.camera.near = 500; spotLight.shadow.camera.far = 4000; spotLight.shadow.camera.fov = 30; near, far, fov 设置投影的区域 5>. 设置阴影贴图大小 spotLight.shadow.mapSize.width = 1024; spotLight.shadow.mapSize.height = 1024; 设置阴影贴图大小,如果发现阴影的边界呈块状,说明阴影贴图太小了,需要设置更大的值 总结实例: <!DOCTYPE html>   <html>   <head>     <title>Example 03.04 - Directional Light</title>     <script type="text/javascript" src="../libs/three.js"></script>     <script type="text/javascript" src="../libs/jquery-1.9.0.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">   // once everything is loaded, we run our Three.js stuff. $(function () {     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.setClearColorHex(0xEEEEEE, 1.0);     renderer.setSize(window.innerWidth, window.innerHeight);     renderer.shadowMapEnabled = true;     // create the ground plane     var planeGeometry = new THREE.PlaneGeometry(600, 200, 20, 20);     var planeMaterial = new THREE.MeshLambertMaterial({color: 0xffffff});     var plane = new THREE.Mesh(planeGeometry, planeMaterial);     plane.receiveShadow = true;     // rotate and position the plane     plane.rotation.x = -0.5 * Math.PI;     plane.position.x = 15     plane.position.y = -5     plane.position.z = 0     // add the plane to the scene     scene.add(plane);     // create a cube     var cubeGeometry = new THREE.CubeGeometry(4, 4, 4);     var cubeMaterial = new THREE.MeshLambertMaterial({color: 0xff3333});     var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);     cube.castShadow = true;     // position the cube     cube.position.x = -4;     cube.position.y = 3;     cube.position.z = 0;     // add the cube to the scene     scene.add(cube);     var sphereGeometry = new THREE.SphereGeometry(4, 20, 20);     var sphereMaterial = new THREE.MeshLambertMaterial({color: 0x7777ff});     var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);     // position the sphere     sphere.position.x = 20;     sphere.position.y = 0;     sphere.position.z = 2;     sphere.castShadow = true;     // add the sphere to the scene     scene.add(sphere);     // position and point the camera to the center of the scene     camera.position.x = -35;     camera.position.y = 30;     camera.position.z = 25;     camera.lookAt(new THREE.Vector3(10, 0, 0));     // add subtle ambient lighting     var ambiColor = "#1c1c1c";     var ambientLight = new THREE.AmbientLight(ambiColor);     scene.add(ambientLight);     var target = new THREE.Object3D();     target.position = new THREE.Vector3(5, 0, 0);     var pointColor = "#ff5808";     var directionalLight = new THREE.DirectionalLight(pointColor);     directionalLight.position.set(-40, 60, -10);     directionalLight.castShadow = true;     directionalLight.shadowCameraNear = 2;     directionalLight.shadowCameraFar = 200;     directionalLight.shadowCameraLeft = -50;     directionalLight.shadowCameraRight = 50;     directionalLight.shadowCameraTop = 50;     directionalLight.shadowCameraBottom = -50;       directionalLight.distance = 0;     directionalLight.intensity = 0.5;     directionalLight.shadowMapHeight = 1024;     directionalLight.shadowMapWidth = 1024;     scene.add(directionalLight);     // add a small sphere simulating the pointlight     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, 20, 3);     scene.add(sphereLightMesh);     // add the output of the renderer to the html element     $("#WebGL-output").append(renderer.domElement);     // call the render function     var step = 0;     // used to determine the switch point for the light animation     var invert = 1;     var phase = 0;     var controls = new function () {         this.rotationSpeed = 0.03;         this.bouncingSpeed = 0.03;         this.ambientColor = ambiColor;         this.pointColor = pointColor;         this.intensity = 0.5;         this.distance = 0;         this.exponent = 30;         this.angle = 0.1;         this.debug = false;         this.castShadow = true;         this.onlyShadow = false;         this.target = "Plane";     }     var gui = new dat.GUI();     gui.addColor(controls, 'ambientColor').onChange(function (e) {         ambientLight.color = new THREE.Color(e);     });     gui.addColor(controls, 'pointColor').onChange(function (e) {         directionalLight.color = new THREE.Color(e);     });     gui.add(controls, 'intensity', 0, 5).onChange(function (e) {         directionalLight.intensity = e;     });     gui.add(controls, 'distance', 0, 200).onChange(function (e) {         directionalLight.distance = e;     });     gui.add(controls, 'debug').onChange(function (e) {         directionalLight.shadowCameraVisible = e;     });     gui.add(controls, 'castShadow').onChange(function (e) {         directionalLight.castShadow = e;     });     gui.add(controls, 'onlyShadow').onChange(function (e) {         directionalLight.onlyShadow = e;     });     gui.add(controls, 'target', ['Plane', 'Sphere', 'Cube']).onChange(function (e) {         console.log(e);         switch (e) {             case "Plane":                 directionalLight.target = plane;                 break;             case "Sphere":                 directionalLight.target = sphere;                 break;             case "Cube":                 directionalLight.target = cube;                 break;         }     });     render();     function render() {         stats.update();         // rotate the cube around its axes         cube.rotation.x += controls.rotationSpeed;         cube.rotation.y += controls.rotationSpeed;         cube.rotation.z += controls.rotationSpeed;         // bounce the sphere up and down         step += controls.bouncingSpeed;         sphere.position.x = 20 + ( 10 * (Math.cos(step)));         sphere.position.y = 2 + ( 10 * Math.abs(Math.sin(step)));         sphereLightMesh.position.z = -8;         sphereLightMesh.position.y = +(27 * (Math.sin(step / 3)));         sphereLightMesh.position.x = 10 + (26 * (Math.cos(step / 3)));         directionalLight.position = sphereLightMesh.position;         // 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';         $("#Stats-output").append(stats.domElement);         return stats;     } }); </script> </body> </html>
转载请注明原文地址: https://www.6miu.com/read-39372.html

最新回复(0)