three.js学习3_相机相关

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>

 

posted @ 2020-09-16 20:36  随遇丿而安  阅读(148)  评论(2编辑  收藏