搜索
首页web前端js教程使用three.js做出的3D效果图?

使用three.js做出的3D效果图?

May 26, 2018 pm 02:45 PM
3dmaxjavascript

       使用three.js可以方便的让我们在网页中做出各种不同的3D效果。如果希望2D绘图内容,建议使用canvas来进行。但很多小伙伴不清楚到底如何为我们绘制和导入的图形添加阴影效果,更是不清楚到底如何导入我们已经制作好的3dmax资源。所以这篇教程将简要介绍如何将我们用3dmax制作好的资源导入进来,以及如何为我们导入的资源,包括所有自己绘制的图形添加阴影。也有很多小伙伴表示根本记不住这些八股文一般的代码。其实,每次需要编写代码的时候参考官方案例即可,不必背诵代码。如果编的多,那自然就记住了。如果编的少,我们也没有必要付出大把时间背诵这些我们很少使用的代码。

       首先,先介绍如何导入3dmax的资源。这里注意,经过我自己的测试,如果直接从本地打开文件的方式打开编写的网页,谷歌、IE等浏览器将无法显示我们自己加载的资源,原因是由于本地打开文件后是file协议,所以浏览器会因为安全性问题阻止我们加载本地资源。而火狐浏览器却可以正常打开。所以建议大家调试时使用火狐浏览器,或者使用tomcat、apache等先建立一个本地服务器,通过域名来访问自己编写的网页。不推荐修改浏览器的安全性设置。

       我们先用3dmax制作一个图形,这里选择其自带的茶壶。用3dmax制作茶壶的教程网上实在太多,所以这里不再赘述,请不会的小伙伴搜索教程即可,几步即可搞定。        当然,制作好了之后不要忘记导出。我们需要将其导出成为一个mtl文件和一个obj文件。这一步操作大多制作茶壶的教程也都有,同样是点点鼠标就行。至于材质等,我们这里不多考虑,毕竟学习要从简单开始。

       导出如上图的两个文件之后,我们就可以参考官方的代码导入我们自己的素材了。

       首先,我们除了three.js文件之外,还需要引入个三源文件。一个是OBJLoader.js,一个是MTLLoader.js,一个是DDSLoader.js。这些是官方提供的加载我们本地资源的库文件,可以从官网下载。    这个网址既是官方案例。我们需要的文件也可以在这里下载到。

       以下代码便是将素材导入的代码,我们除了像官方那样导入文件之外,还加入了阴影效果。


 1 var onError = function ( xhr ) { }; 
 2                 THREE.Loader.Handlers.add( /\.dds$/i, new THREE.DDSLoader() ); 
 3                 var mtlLoader = new THREE.MTLLoader(); 
 4                 mtlLoader.setPath( './' );       //设置我们需要加载的mtl文件路径 
 5                 mtlLoader.load( 'lyn.mtl', function( material ) {      //这里加载我们需要的文件名   
 6                     material.preload(); 
 7                     var objLoader = new THREE.OBJLoader(); 
 8                     objLoader.setMaterials( material );      //材质,也可自定义 
 9                     objLoader.setPath( './' );               //设置要加载的obj文件的路径
 10                     objLoader.load( 'lyn.obj', function ( object ) {           //加载obj文件
 11                         object.position.z = 1;         //这里设置我们的素材相对于原来的大小以及旋转缩放等
 12                         object.position.y = -0.5;
 13                         object.scale.x = 0.2;
 14                         object.scale.y = 0.2;
 15                         object.scale.z = 0.2;
 16                         object1 = object;               //这里是对素材设置阴影的操作
 17                         for(var k in object.children){  //由于我们的素材并不是看上去的一个整体,所以需要进行迭代
 18                                                         //对其中的所有孩子都设置接收阴影以及投射阴影
 19                                                         //才能看到阴影效果
 20                             object.children[k].castShadow = true;   //设置该对象可以产生阴影
 21                             object.children[k].receiveShadow = true;  //设置该对象可以接收阴影
 22                         }
 23                         scene.add( object1 );
 24                         
 25                     }, onProgress, onError );
 26                 });

       上述的代码除了设置阴影以及调整大小之外,都是八股文,需要的时候复制粘贴即可,如果经常从事这方面开发,才建议检查源代码的实现。有时我们会发现,即便导入后,我们也无法看到素材。我们需要考虑以下几方面问题。第一方面,我们是否将我们的3dmax素材做的太大或者太小。太大的话,我们只能看到素材的一部分,造成一种看不到的假象。太小,又会看不清楚或者无法显示。这种问题就需要各位根据我们摄像机的视距等来调整了。还有一种问题,就是由于我们没有为我们的素材设置材质,而且我们的代码中没有添加光源,导致只显示黑漆漆的一片。所以,如果要看到这个素材,我们还需要添加光照。

      以下是添加聚光灯光源的代码,因为聚光灯光源可以聚焦,我们演示会方便一些。小伙伴们也可以自己动手尝试其他光源。记住,我们需要的是点光源或者平行光等光源。环境光是无法生成阴影的。但如果希望周围显示的更加清楚,我们也可以同时添加点光源和环境光,只是环境光的光强需要弱一些,避免环境光过强影响阴影的正常显示。

function SpotLight(){
                light = new THREE.SpotLight( '#ffffff' ,1);
                light.castShadow = true;
                light.distance = 50; 
                light.angle = 0.6; 
                light.decay = 2;
                light.penumbra = 0.2;          
                light.position.set( 3, 2, 1 );
                light.shadow.camera.near = 1;
                light.shadow.camera.far = 3;
                light.shadow.camera.visible = true;            
                light.shadow.mapSize.width = 1024;
                light.shadow.mapSize.height = 1024;                                    
                light.target = sp;
                scene.add(light);
            }

     我们还需要一个地板,将阴影投射到我们的地板上,这样才能看到阴影。而之前我们讲到过receiveShadow这个属性。假设我们创建了一个添加了材质的图形sp。我们需要使用sp.receiveShadow=true来让其可以接收阴影。如果设置为false,会出现什么情况呢?

并没有生成阴影。那如果我们设置为true,会是什么样呢?

       可以看到,已经生成了阴影。所以,如果我们要让一个物体可以产生阴影,需要设置castShadow这个属性为true,而生成了阴影,总需要投射到某个物体上,才能被观察到。所以,接收投影需要将receiveShadow这个属性设置为true。

       完整的效果如下

       以下是完整代码。其中库文件以及3dmax的素材文件这里不提供,需要自己生成或者自己下载。也可以只学习阴影的生成方法。代码编写略仓促,不过除了各种事件的控制等,其他方面应该还是比较清晰的。欢迎批评之争。

1 <!DOCTYPE html>  
2 <html>  
3     <head>  
4         <style>  
5             html,  
6             body {  
7                 width: 100%;  
8                 height: 100%;  
9             } 
10              
11             body { 
12                 margin: 0; 
13             } 
14              
15             canvas { 
16                 width: 100%; 
17                 height: 100% 
18             } 
19         </style> 
20     </head> 
21     <body> 
22  
23         <script src="js/three.min.js?1.1.11"></script>        
24         <script src="js/jquery-1.12.4.js?1.1.11"></script> 
25         <script src="js/OBJLoader.js?1.1.11"></script> 
26         <script src="js/MTLLoader.js?1.1.11"></script> 
27         <script src="js/DDSLoader.js?1.1.11"></script>       
28         <script> 
29             var scene = new THREE.Scene(); 
30             var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 2000); 
31             camera.position.z = 6; 
32             camera.position.y = 1; 
33             camera.position.x = 2; 
34             camera.lookAt(new THREE.Vector3(0, 0, 0)); 
35  
36             var other = new THREE.Object3D(); 
37             other.add(camera);           
38             scene.add(other); 
39  
40             var renderer = new THREE.WebGLRenderer(); 
41             renderer.setSize(window.innerWidth, window.innerHeight); 
42             document.body.appendChild(renderer.domElement); 
43  
44             var geometry = new THREE.BoxGeometry(1,1,1); 
45             var material = new THREE.MeshPhongMaterial({ 
46                 color : &#39;#2194ce&#39;, 
47                 specular : &#39;#111111&#39;, 
48                 specular : 
10                                               
49             }); 
50             var sp = new THREE.Mesh(geometry,material); 
51             sp.position.z = -0.5; 
52  
53             var geometry = new THREE.ConeGeometry( 0.5, 1, 6 ); 
54             var material2 = new THREE.MeshPhongMaterial({ 
55                 color : &#39;#2194ce&#39;, 
56                 specular : &#39;#ffffff&#39;, 
57                 shininess : 100               
58             }); 
59             var sp2 = new THREE.Mesh(geometry,material2); 
60             sp2.position.x = -2.5; 
61             sp2.position.z = -1;   
62  
63             var ball = new THREE.SphereGeometry( 0.5, 32, 32 ); 
64             var material3 = new THREE.MeshPhongMaterial({ 
65                 color : &#39;#2194ce&#39;, 
66                 specular : &#39;#111111&#39;, 
67                 shininess : 100               
68             });      
69             var myBall = new THREE.Mesh(ball,material3); 
70             myBall.position.z = 1; 
71             myBall.position.x = -1; 
72             myBall.position.y = -1; 
73             myBall.castShadow = true; 
74             myBall.receiveShadow = true;   
75  
76             var light2 = new THREE.SpotLight( &#39;#ffffff&#39; ,1); 
77             light2.castShadow = true; 
78             light2.distance = 50; 
79             light2.angle = 0.3; 
80             light2.decay = 2; 
81             light2.penumbra = 0.2;          
82             light2.position.set( -2, 5, -2 ); 
83             light2.shadow.camera.near = 1; 
84             light2.shadow.camera.far = 3; 
85             light2.shadow.camera.visible = true;            
86             light2.shadow.mapSize.width = 1024; 
87             light2.shadow.mapSize.height = 1024;                                    
88             light2.target = sp; 
89             scene.add(light2); 
90             lightHelper2 = new THREE.SpotLightHelper(light2); 
91             scene.add(lightHelper2); 
92  
93             renderer.shadowMap.enabled = true; 
94              
95             var matFloor = new THREE.MeshPhongMaterial( { color:0x808080 } );            
96             var geoFloor = new THREE.BoxGeometry( 200, 0.1, 200 ); 
97             var mshFloor = new THREE.Mesh( geoFloor, matFloor ); 
98             var ambient = new THREE.AmbientLight( 0x111111); 
99             var lightHelper;        
100 
101             var light;
102             SpotLight();
103             lightHelper = new THREE.SpotLightHelper( light );
104 
105             sp.castShadow = true;
106             sp.receiveShadow = true;
107             sp2.castShadow = true;
108             sp2.receiveShadow = true;
109             mshFloor.castShadow = true;
110             mshFloor.receiveShadow = true;
111             mshFloor.position.set( 0, -2, 0 );
112            
113 
114             scene.add( mshFloor );
115             scene.add(sp);
116             scene.add(sp2);
117             scene.add(myBall);
118             scene.add( light );
119             scene.add(ambient);
120             scene.add(lightHelper);            
121            // 0.9854        
122             
123             //聚光灯光源
124            function SpotLight(){
125                 light = new THREE.SpotLight( &#39;#ffffff&#39; ,1);
126                 light.castShadow = true;
127                 light.distance = 50; 
128                 light.angle = 0.6; 
129                 light.decay = 2;
130                 light.penumbra = 0.2;          
131                 light.position.set( 3, 2, 1 );
132                 light.shadow.camera.near = 1;
133                 light.shadow.camera.far = 3;
134                 light.shadow.camera.visible = true;            
135                 light.shadow.mapSize.width = 1024;
136                 light.shadow.mapSize.height = 1024;                                    
137                 light.target = sp;
138                 scene.add(light);
139             }
140 
141             //点光源
142             function PointLight(){
143                 light = new THREE.PointLight(&#39;#ffffff&#39;,1,50,2);
144                     light.castShadow = true;
145                     light.position.set( 3, 2, 1 );           
146                     light.shadow.mapSize.width = 1024;
147                     light.shadow.mapSize.height = 1024;  
148                     scene.add(light);                    
149             }
150 
151             //平行光
152             function DirectLight(){
153                 light = new THREE.DirectionalLight(&#39;#ffffff&#39;,1);
154                     light.castShadow = true;
155                     light.position.set( 3, 2, 1 ); 
156                     light.decay = 2;
157                     light.penumbra = 0.2;          
158                     light.shadow.mapSize.width = 1024;
159                     light.shadow.mapSize.height = 1024;  
160                     scene.add(light); 
161             }
162 
163             var onProgress = function ( xhr ) {
164                     if ( xhr.lengthComputable ) {
165                         var percentComplete = xhr.loaded / xhr.total * 100;
166                         console.log( Math.round(percentComplete, 2) + &#39;% downloaded&#39; );
167                     }
168                 };
169 
170                 var onError = function ( xhr ) { };
171                 THREE.Loader.Handlers.add( /\.dds$/i, new THREE.DDSLoader() );
172                 var mtlLoader = new THREE.MTLLoader();
173                 mtlLoader.setPath( &#39;./&#39; );       //设置我们需要加载的mtl文件路径
174                 mtlLoader.load( &#39;lyn.mtl&#39;, function( material ) {      //这里加载我们需要的文件名  
175                     material.preload();176                     var objLoader = new THREE.OBJLoader();
177                     objLoader.setMaterials( material );      //材质,也可自定义
178                     objLoader.setPath( &#39;./&#39; );               //设置要加载的obj文件的路径
179                     objLoader.load( &#39;lyn.obj&#39;, function ( object ) {           //加载obj文件
180                         object.position.z = 1;         //这里设置我们的素材相对于原来的大小以及旋转缩放等
181                         object.position.y = -0.5;
182                         object.scale.x = 0.2;
183                         object.scale.y = 0.2;
184                         object.scale.z = 0.2;
185                         object1 = object;               //这里是对素材设置阴影的操作
186                         for(var k in object.children){  //由于我们的素材并不是看上去的一个整体,所以需要进行迭代
187                                                         //对其中的所有孩子都设置接收阴影以及投射阴影
188                                                         //才能看到阴影效果
189                             object.children[k].castShadow = true;   //设置该对象可以产生阴影
190                             object.children[k].receiveShadow = true;  //设置该对象可以接收阴影
191                         }
192                         scene.add( object1 );
193                         
194                     }, onProgress, onError );
195                 });
196 
197 
198             var render = function() {
199                 requestAnimationFrame(render);
200                 lightHelper.update();
201                                       
202                 other.rotation.y += 0.01;
203                 sp2.rotation.x += 0.01;
204 
205                 renderer.render(scene, camera);
206             }
207             
208             render();
209             
210             //设置场景不停旋转
211             var tmp = 0;
212             var timer = setInterval(function(){
213                 if(tmp == 0){
214                     var route = (5 - light.position.y) / 50;
215                     light.position.y += route;
216                     if(route <= 0.001){
217                         tmp = 1;
218                     }
219                 }else{
220                     var route = (light.position.y - 1) / 50;
221                     light.position.y -= route;
222                     if(route <= 0.001){
223                         tmp = 0;
224                     }
225                 }
226             },15);
227 
228            //设置图中的立方体可以旋转
229             var left = false;
230             var right = false;
231             var boxLeft = false;
232             var boxRight = false;
233             var boxUp = false;
234             var boxDown = false;
235             var object1 = &#39;&#39;;                        
236             setInterval(function(){                
237                 if(left){                                                            
238                     object1.rotation.y -= 0.02;                  
239                 }else if(right){                                        
240                     object1.rotation.y += 0.02;            
241                 }else if(boxLeft){
242                     sp.rotation.y -= 0.02;
243                 }else if(boxRight){
244                     sp.rotation.y += 0.02;
245                 }else if(boxUp){246                     sp.rotation.x -= 0.02;
247                 }else if(boxDown){248                     sp.rotation.x += 0.02;
249                 }
250             },25);
251 
252             document.onkeydown = function(ev){
253                 var ev = ev || event;
254                 if(ev.keyCode == 65)
255                     left = true;
256                 else if(ev.keyCode == 68)
257                     right = true;   
258                 else if(ev.keyCode == 37)
259                     boxLeft = true;
260                 else if(ev.keyCode == 38)
261                     boxUp = true;
262                 else if(ev.keyCode == 39)
263                     boxRight = true;
264                 else if(ev.keyCode == 40)
265                     boxDown = true; 
266                 else if(ev.keyCode == 80){
267                     scene.remove(light);
268                     PointLight();
269                 }else if(ev.keyCode == 83){
270                     scene.remove(light);
271                     SpotLight();
272                 }else if(ev.keyCode == 17){
273                     scene.remove(light);
274                     DirectLight();
275                 }else if(ev.keyCode == 90){
276                     if(light.intensity < 10)
277                         light.intensity += 1;
278                 }else if(ev.keyCode == 88){
279                     if(light.intensity > 0)
280                         light.intensity -= 1;
281                 }else if(ev.keyCode == 67){
282                     scene.remove(sp);
283                     geometry = new THREE.BoxGeometry(1,1,1);
284                     material = new THREE.MeshPhongMaterial({
285                         color : &#39;#A44A32&#39;,
286                         specular : &#39;#ffffff&#39;,
287                         specular : 100                                               
288                     });
289                     var sp = new THREE.Mesh(geometry,material);
290                     sp.position.z = -0.5;
291                     scene.add(sp);
292                 }else if(ev.keyCode == 86){
293                     scene.remove(sp);
294                     geometry = new THREE.BoxGeometry(1,1,1);
295                     material = new THREE.MeshPhongMaterial({
296                         color : &#39;#2194ce&#39;,
297                         specular : &#39;#111111&#39;,
298                         specular : 100                                               
299                     });
300                     var sp = new THREE.Mesh(geometry,material);
301                     sp.position.z = -0.5;
302                     scene.add(sp);
303                 }     
304             }
305 
306             document.onkeyup = function(ev){
307                 var ev = ev || event;
308                 if(ev.keyCode == 65)
309                     left = false;
310                 else if(ev.keyCode == 68)
311                     right = false;
312                 else if(ev.keyCode == 37)
313                     boxLeft = false;
314                 else if(ev.keyCode == 38)
315                     boxUp = false;
316                 else if(ev.keyCode == 39)
317                     boxRight = false;
318                 else if(ev.keyCode == 40)
319                     boxDown = false; 
320             }
321 
322 
323         </script>
324     </body>
325 </html>


以上是使用three.js做出的3D效果图?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
使用Next.js(后端集成)构建多租户SaaS应用程序使用Next.js(后端集成)构建多租户SaaS应用程序Apr 11, 2025 am 08:23 AM

我使用您的日常技术工具构建了功能性的多租户SaaS应用程序(一个Edtech应用程序),您可以做同样的事情。 首先,什么是多租户SaaS应用程序? 多租户SaaS应用程序可让您从唱歌中为多个客户提供服务

如何使用Next.js(前端集成)构建多租户SaaS应用程序如何使用Next.js(前端集成)构建多租户SaaS应用程序Apr 11, 2025 am 08:22 AM

本文展示了与许可证确保的后端的前端集成,并使用Next.js构建功能性Edtech SaaS应用程序。 前端获取用户权限以控制UI的可见性并确保API要求遵守角色库

JavaScript:探索网络语言的多功能性JavaScript:探索网络语言的多功能性Apr 11, 2025 am 12:01 AM

JavaScript是现代Web开发的核心语言,因其多样性和灵活性而广泛应用。1)前端开发:通过DOM操作和现代框架(如React、Vue.js、Angular)构建动态网页和单页面应用。2)服务器端开发:Node.js利用非阻塞I/O模型处理高并发和实时应用。3)移动和桌面应用开发:通过ReactNative和Electron实现跨平台开发,提高开发效率。

JavaScript的演变:当前的趋势和未来前景JavaScript的演变:当前的趋势和未来前景Apr 10, 2025 am 09:33 AM

JavaScript的最新趋势包括TypeScript的崛起、现代框架和库的流行以及WebAssembly的应用。未来前景涵盖更强大的类型系统、服务器端JavaScript的发展、人工智能和机器学习的扩展以及物联网和边缘计算的潜力。

神秘的JavaScript:它的作用以及为什么重要神秘的JavaScript:它的作用以及为什么重要Apr 09, 2025 am 12:07 AM

JavaScript是现代Web开发的基石,它的主要功能包括事件驱动编程、动态内容生成和异步编程。1)事件驱动编程允许网页根据用户操作动态变化。2)动态内容生成使得页面内容可以根据条件调整。3)异步编程确保用户界面不被阻塞。JavaScript广泛应用于网页交互、单页面应用和服务器端开发,极大地提升了用户体验和跨平台开发的灵活性。

Python还是JavaScript更好?Python还是JavaScript更好?Apr 06, 2025 am 12:14 AM

Python更适合数据科学和机器学习,JavaScript更适合前端和全栈开发。 1.Python以简洁语法和丰富库生态着称,适用于数据分析和Web开发。 2.JavaScript是前端开发核心,Node.js支持服务器端编程,适用于全栈开发。

如何安装JavaScript?如何安装JavaScript?Apr 05, 2025 am 12:16 AM

JavaScript不需要安装,因为它已内置于现代浏览器中。你只需文本编辑器和浏览器即可开始使用。1)在浏览器环境中,通过标签嵌入HTML文件中运行。2)在Node.js环境中,下载并安装Node.js后,通过命令行运行JavaScript文件。

在Quartz中如何在任务开始前发送通知?在Quartz中如何在任务开始前发送通知?Apr 04, 2025 pm 09:24 PM

如何在Quartz中提前发送任务通知在使用Quartz定时器进行任务调度时,任务的执行时间是由cron表达式设定的。现�...

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
3 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。

EditPlus 中文破解版

EditPlus 中文破解版

体积小,语法高亮,不支持代码提示功能

Dreamweaver Mac版

Dreamweaver Mac版

视觉化网页开发工具

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境