Maison  >  Article  >  interface Web  >  Des rendus 3D réalisés avec three.js ?

Des rendus 3D réalisés avec three.js ?

零下一度
零下一度original
2018-05-26 14:45:463696parcourir

L'utilisation de three.js peut facilement nous permettre de créer divers effets 3D sur des pages Web. Si vous souhaitez dessiner du contenu en 2D, il est recommandé d'utiliser un canevas. Mais beaucoup d’amis ne savent pas comment ajouter des effets d’ombre aux graphiques que nous dessinons et importons, et ils ne savent même pas comment importer les ressources 3dmax que nous avons déjà produites. Ce tutoriel présentera donc brièvement comment importer les ressources que nous avons créées avec 3dmax et comment ajouter des ombres aux ressources que nous avons importées, y compris tous les graphiques dessinés par nous-mêmes. Il y a aussi de nombreux amis qui disent qu'ils ne se souviennent pas du tout de ces codes ressemblant à un essai en huit parties. En fait, chaque fois que vous avez besoin d'écrire du code, vous pouvez simplement vous référer au cas officiel au lieu de mémoriser le code. Si vous inventez beaucoup, vous vous en souviendrez naturellement. Si nous compilons moins, nous n’aurons pas besoin de passer beaucoup de temps à mémoriser ces codes que nous utilisons rarement.

Tout d’abord, présentons comment importer des ressources 3dmax. Notez ici qu'après mes propres tests, si la page Web écrite est ouverte directement à partir du fichier local, les navigateurs tels que Google et IE ne pourront pas afficher les ressources que nous avons chargées. La raison en est que le protocole de fichier est utilisé après l'ouverture du fichier. fichier localement, donc la navigation sur le serveur nous empêchera de charger les ressources locales en raison de problèmes de sécurité. Le navigateur Firefox peut être ouvert normalement. Par conséquent, il est recommandé d'utiliser Firefox lors du débogage, ou d'utiliser Tomcat, Apache, etc. pour configurer d'abord un serveur local et accéder aux pages Web que vous avez écrites via le nom de domaine. Il n'est pas recommandé de modifier les paramètres de sécurité du navigateur.

On utilise d'abord 3dmax pour créer un graphique, ici on choisit sa propre théière. Il y a trop de tutoriels sur la fabrication de théières à l'aide de 3dmax sur Internet, je n'entrerai donc pas dans les détails ici. Les amis qui ne savent pas comment le faire peuvent simplement rechercher des tutoriels et vous pourrez le faire en quelques étapes. Bien sûr, n’oubliez pas de l’exporter après l’avoir réalisé. Nous devons l'exporter dans un fichier mtl et un fichier obj. Cette étape est également disponible dans la plupart des tutoriels de fabrication de théières, et elle ne nécessite également que quelques clics de souris. Quant au matériel, etc., nous n’y penserons pas beaucoup ici. Après tout, l’apprentissage doit commencer simplement.

Après avoir exporté les deux fichiers comme indiqué ci-dessus, nous pouvons nous référer au code officiel pour importer nos propres matériaux.

Tout d'abord, en plus du fichier three.js, nous devons également introduire un fichier à trois sources. L’un est OBJLoader.js, l’autre MTLLoader.js et l’autre DDSLoader.js. Il s'agit de fichiers de bibliothèque officiellement fournis pour charger nos ressources locales et peuvent être téléchargés à partir du site officiel. Ce site Web est un cas officiel. Les fichiers dont nous avons besoin peuvent également être téléchargés ici.

Le code suivant est le code pour importer le matériel En plus d'importer le fichier comme la méthode officielle, nous avons également ajouté un effet d'ombre.


 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                 });

À l'exception du réglage de l'ombre et de l'ajustement de la taille, le code ci-dessus est entièrement écrit à huit pattes. Vous pouvez le copier et le coller si vous en avez souvent besoin. s'engager dans le développement dans ce domaine, il est uniquement recommandé de vérifier le code source de l'implémentation. Parfois, nous constatons que même après l’importation, nous ne pouvons pas voir le matériel. Nous devons considérer les aspects suivants. Le premier aspect est de savoir si nos matériaux 3dmax sont trop grands ou trop petits. S’il est trop grand, nous ne pouvons voir qu’une partie de la matière, créant ainsi l’illusion d’être invisible. S'il est trop petit, il ne sera pas clairement visible ou ne pourra pas être affiché. Ce genre de problème nécessite de l'ajuster en fonction de la distance de visualisation de notre caméra. Un autre problème est que, comme nous n'avons pas défini de matériau pour notre matériau et que nous n'avons pas ajouté de source de lumière à notre code, seule une zone sombre était affichée. Donc, si nous voulons voir ce matériau, nous devons également ajouter de l’éclairage.

Ce qui suit est le code pour ajouter une source de lumière spot. Étant donné que la source de lumière spot peut être focalisée, il nous sera plus pratique de la démontrer. Les amis peuvent également essayer eux-mêmes d’autres sources de lumière. N'oubliez pas que nous avons besoin d'une source de lumière telle qu'une source de lumière ponctuelle ou une source de lumière directionnelle. La lumière ambiante ne peut pas générer d'ombres. Mais si nous voulons que l'environnement soit affiché plus clairement, nous pouvons également ajouter des sources de lumière ponctuelles et de la lumière ambiante en même temps, mais l'intensité de la lumière ambiante doit être plus faible pour éviter qu'une lumière ambiante excessive n'affecte l'affichage normal des ombres.

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);
            }

Nous avons également besoin d'un sol pour projeter l'ombre sur notre sol afin que nous puissions voir l'ombre. Nous avons déjà parlé de l’attribut recevoirShadow. Disons que nous créons une forme sp à laquelle un matériau est ajouté. Nous devons utiliser sp.receiveShadow=true pour lui permettre de recevoir des ombres. Que se passe-t-il s'il est défini sur false ?

ne génère pas d'ombres. Alors, que se passerait-il si nous le définissons sur vrai ?

       可以看到,已经生成了阴影。所以,如果我们要让一个物体可以产生阴影,需要设置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>


Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn