three.js學習3_相機相關

隨遇丿而安發表於2020-09-16

Three.Camera

Camera是所有相機的抽象基類, 在構建新攝像機時,應始終繼承此類. 常見的相機有兩種型別: PerspectiveCamera(透視攝像機)或者 OrthographicCamera(正交攝像機)。

Camera子型別有ArrayCamera, CubeCamera, OrthographicCamera, PerspectiveCamera, StereoCamera, 這些相機中, 我認為比較有趣的是CubeCamera, 它包含6個PerspectiveCameras(透視攝像機)的立方攝像機, 拍出來的照片可以作為貼圖使用, 先看看它的效果吧 !

1. CubeCamera

整個環境成為了球的表面, 這個功能是不是很容易擴充套件呢. 將環境放在任意物體上, 還十分炫酷

步驟

1. 建立cubeCamera

1     //cubeCamera
2     cubeCamera = new THREE.CubeCamera(1, 10000, 128);
3     scene.add(cubeCamera);

說明: CubeCamera( near : Number, far : Number, cubeResolution : Number )

near -- 遠剪下面的距離
far -- 近剪下面的距離
cubeResolution -- 設定立方體邊緣的長度

2. 建立物體表面材質並將cubeCamera照出的環境作為材質的貼圖

1     material = new THREE.MeshBasicMaterial( {
2       envMap: cubeCamera.renderTarget.texture
3     } );

3. 建立物體, 將第二步的材質賦予物體

1     let sphere = new THREE.Mesh( new THREE.IcosahedronBufferGeometry( 20, 3 ), material );
2     scene.add( sphere );

4. 更新材質貼圖內容

1     cubeCamera.update( renderer, scene );

那麼, 帶有環境的物體就做好了, 是不是很想試一試呀! 

2. perspectiveCamera

這一投影模式被用來模擬人眼所看到的景象,它是3D場景的渲染中使用得最普遍的投影模式。

使用時需要注意: 在PerspectiveCamera大多數屬性發生改變之後,需要呼叫.updateProjectionMatrix來使得這些改變生效。

相機的使用步驟都十分類似, 第一步, 寫建構函式, 第二步, 改變位置, 第三步, 新增至場景, 第四步, 改變相機位置.

對於perspectiveCamera, 它的特點是像人眼, 距離越遠, 物體越小, 它與OrthographicCamera最大的區別就在於此, OrthographicCamera看到的物體無論距離多遠, 物體看上去的大小一樣.

使用流程

1     //1.建立相機
2     camera = new THREE.PerspectiveCamera(30, window.innerWidth / window.innerHeight, 0.1, 1000);
3     //2.新增相機至場景
4     scene.add(camera);
5     //3.改變相機位置
6     camera.position.set( 100, 50, 150);
7     //4.改變相機朝向
8     camera.lookAt(scene.position);

PerspectiveCamera( fov : Number, aspect : Number, near : Number, far : Number )

fov — 攝像機視錐體垂直視野角度
aspect — 攝像機視錐體長寬比
near — 攝像機視錐體近端面
far — 攝像機視錐體遠端面

注意點: renderer.render(scene, camera);

在渲染時, 引數選中的camera就相當於眼睛了, 選中哪個哪個就是眼睛. 

效果如第一張圖片所示, 看到的是透視相機拍出來的

3. OrthographicCamera

注意它的建構函式就行, 其他與PerspectiveCamera類似

OrthographicCamera( left : Number, right : Number, top : Number, bottom : Number, near : Number, far : Number )

left — 攝像機視錐體左側面。
right — 攝像機視錐體右側面。
top — 攝像機視錐體上側面。
bottom — 攝像機視錐體下側面。
near — 攝像機視錐體近端面。
far — 攝像機視錐體遠端面。

4. ArrayCamera與StereoCamera

這兩種我還沒使用過, 這裡就簡單描述下, 後面用到了再補充

ArrayCamera 用於更加高效地使用一組已經預定義的攝像機來渲染一個場景。這將能夠更好地提升VR場景的渲染效能。
一個 ArrayCamera 的例項中總是包含著一組子攝像機,應當為每一個子攝像機定義viewport(邊界)這個屬性,這一屬性決定了由該子攝像機所渲染的視口區域的大小。

雙透視攝像機(立體相機)常被用於建立3D Anaglyph(3D立體影像)或者Parallax Barrier(視差效果)。

5. 總結

相機想使用不難, 如何靈活運用相機達到想要的效果就比較難了

6. 程式碼

  1 <!DOCTYPE html>
  2 <html lang="en">
  3 <head>
  4   <meta charset="UTF-8">
  5   <title>Title</title>
  6   <style>
  7     body {
  8       margin: 0;
  9       overflow: hidden;
 10     }
 11   </style>
 12 
 13 </head>
 14 <body>
 15 <script src="/js/three.js"></script>
 16 <script src="/js/OrbitControls.js"></script>
 17 <script src="/js/libs/stats.min.js"></script>
 18 <script src="/js/libs/inflate.min.js"></script>
 19 <script src="/js/loaders/FBXLoader.js"></script>
 20 <script src="/js/exporters/GLTFExporter.js"></script>
 21 <script>
 22   let renderer, scene, camera, light, cubeCamera;
 23 
 24   let container, stats;
 25 
 26   init();
 27   animation();
 28 
 29   function init() {
 30     //container
 31     container = document.createElement("div");
 32     document.body.appendChild(container);
 33 
 34     //status
 35     stats = new Stats();
 36     container.appendChild(stats.domElement);
 37 
 38     //renderer
 39     renderer = new THREE.WebGLRenderer({
 40       antialias: true
 41     });
 42     renderer.setSize(window.innerWidth, window.innerHeight);
 43     renderer.setClearColor(0xffffff);
 44     container.appendChild(renderer.domElement);
 45 
 46     //scene
 47     scene = new THREE.Scene();
 48     scene.background = new THREE.Color( 0xcce0ff );
 49     scene.fog = new THREE.Fog( 0xcce0ff, 500, 10000 );
 50 
 51     //3_相機
 52     camera = new THREE.PerspectiveCamera(30, window.innerWidth / window.innerHeight);
 53     scene.add(camera);
 54     camera.position.set( 100, 50, 150);
 55     camera.lookAt(scene.position);
 56 
 57     //cubeCamera
 58     cubeCamera = new THREE.CubeCamera(1, 10000, 128);
 59     scene.add(cubeCamera);
 60 
 61     material = new THREE.MeshBasicMaterial( {
 62       envMap: cubeCamera.renderTarget.texture
 63     } );
 64 
 65     //
 66     let sphere = new THREE.Mesh( new THREE.IcosahedronBufferGeometry( 20, 3 ), material );
 67     scene.add( sphere );
 68     let geometry = new THREE.BoxGeometry( 1, 1, 1 );
 69     let meterial2 = new THREE.MeshBasicMaterial( {
 70       vertexColors: THREE.VertexColors,
 71       // wireframe: true
 72     });
 73     let cube = new THREE.Mesh(
 74         geometry,
 75         meterial2
 76     );
 77     geometry.faces.forEach(face => {
 78       // 設定三角面face三個頂點的顏色
 79       face.vertexColors = [
 80         new THREE.Color(0xffff00),
 81         new THREE.Color(0x0000ff),
 82         new THREE.Color(0x00ff00),
 83       ]
 84     });
 85     scene.add(cube);
 86 
 87     // light
 88     scene.add( new THREE.AmbientLight( 0x666666 ) );
 89 
 90     light = new THREE.DirectionalLight( 0xdfebff, 1 );
 91     light.position.set( 50, 200, 100 );
 92     light.position.multiplyScalar( 1.3 );
 93 
 94     light.castShadow = true;
 95 
 96     light.shadow.mapSize.width = 1024;
 97     light.shadow.mapSize.height = 1024;
 98 
 99     let d = 300;
100     light.shadow.camera.left = - d;
101     light.shadow.camera.right = d;
102     light.shadow.camera.top = d;
103     light.shadow.camera.bottom = - d;
104 
105     light.shadow.camera.far = 1000;
106 
107     scene.add( light );
108 
109     // ground
110     var loader = new THREE.TextureLoader();
111     var groundTexture = loader.load( '/textures/terrain/grasslight-big.jpg' );
112     groundTexture.wrapS = groundTexture.wrapT = THREE.RepeatWrapping;
113     groundTexture.repeat.set( 25, 25 );
114     groundTexture.anisotropy = 16;
115 
116     var groundMaterial = new THREE.MeshLambertMaterial( { map: groundTexture } );
117 
118     var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 20000, 20000 ), groundMaterial );
119     mesh.position.y = - 250;
120     mesh.rotation.x = - Math.PI / 2;
121     mesh.receiveShadow = true;
122     scene.add( mesh );
123 
124     //輔助工具
125     // scene.add(new THREE.AxesHelper(20));
126 
127     // controls
128     var controls = new THREE.OrbitControls( camera, renderer.domElement );
129     // controls.maxPolarAngle = Math.PI * 0.5;
130     // controls.minDistance = 1000;
131     // controls.maxDistance = 5000;
132 
133 
134   }
135 
136   function animation(){
137     stats.update();
138     cubeCamera.update( renderer, scene );
139     render();
140     requestAnimationFrame(animation);
141   }
142 
143   function render() {
144 
145     renderer.render(scene, camera);
146 
147   }
148 </script>
149 </body>
150 </html>

 

相關文章