Home > Article > Web Front-end > 3D renderings made using three.js?
Using three.js can easily allow us to create various 3D effects in web pages. If you want to draw content in 2D, it is recommended to use canvas. But many friends don’t know exactly how to add shadow effects to the graphics we draw and import, and they don’t even know how to import the 3dmax resources we have already produced. So this tutorial will briefly introduce how to import the resources we made with 3dmax, and how to add shadows to the resources we imported, including all graphics drawn by ourselves. There are also many friends who say that they cannot remember these eight-part essay-like codes at all. In fact, every time you need to write code, you can just refer to the official case instead of memorizing the code. If you make up a lot, you will naturally remember it. If we compile less, we don't need to spend a lot of time memorizing these codes that we rarely use.
First, let’s introduce how to import 3dmax resources. Note here that after my own testing, if the written webpage is opened directly from the local file, browsers such as Google and IE will not be able to display the resources we have loaded. The reason is that the file protocol is used after opening the file locally, so browsing The server will prevent us from loading local resources due to security issues. The Firefox browser can be opened normally. Therefore, it is recommended that you use Firefox when debugging, or use tomcat, apache, etc. to set up a local server first and access the web pages you wrote through the domain name. It is not recommended to modify browser security settings.
We first use 3dmax to create a graphic, and here we choose its own teapot. There are too many tutorials on making teapots using 3dmax on the Internet, so I won’t go into details here. Friends who don’t know how to do it can just search for tutorials and you can get it done in a few steps. Of course, don’t forget to export it after making it. We need to export it into an mtl file and an obj file. This step is also available in most tutorials for making teapots, and it also requires just a few clicks of the mouse. As for materials, etc., we won’t think much about it here. After all, learning should start simple.
After exporting the two files as shown above, we can refer to the official code to import our own materials.
First, in addition to the three.js file, we also need to introduce a three source file. One is OBJLoader.js, one is MTLLoader.js, and one is DDSLoader.js. These are officially provided library files for loading our local resources and can be downloaded from the official website. This website is an official case. The files we need can also be downloaded here.
The following code is the code to import the material. In addition to importing the file like the official method, we also added a shadow effect.
# The above code. In addition to setting the shadow and adjusting the size, it is all eight -shaped text. Copy and paste when you need it. If you often engage in this development, it is recommended. Check the source code for implementation. Sometimes we find that even after importing, we cannot see the material. We need to consider the following aspects. The first aspect is whether we make our 3dmax material too big or too small. If it is too large, we can only see part of the material, creating an illusion of being invisible. If it is too small, it will not be visible clearly or cannot be displayed. This kind of problem requires you to adjust it according to the viewing distance of our camera. Another problem is that because we did not set a material for our material, and we did not add a light source to our code, only a dark patch was displayed. So, if we want to see this material, we also need to add lighting.
The following is the code for adding a spotlight light source. Because the spotlight light source can be focused, it will be more convenient for us to demonstrate. Friends can also try other light sources by themselves. Remember, what we need is a light source such as a point light source or a directional light source. Ambient light cannot generate shadows. But if we want the surroundings to be displayed more clearly, we can also add point light sources and ambient light at the same time, but the intensity of the ambient light needs to be weaker to avoid excessive ambient light affecting the normal display of shadows.
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 });
We also need a floor to cast the shadow onto our floor so we can see the shadow. We talked about the receiveShadow attribute before. Let's say we create a shape sp that has a material added to it. We need to use sp.receiveShadow=true to allow it to receive shadows. What happens if it is set to false?
No shadow is generated. So what would happen if we set it to 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 : '#2194ce', 47 specular : '#111111', 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 : '#2194ce', 56 specular : '#ffffff', 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 : '#2194ce', 66 specular : '#111111', 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( '#ffffff' ,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( '#ffffff' ,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('#ffffff',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('#ffffff',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) + '% downloaded' ); 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( './' ); //设置我们需要加载的mtl文件路径 174 mtlLoader.load( 'lyn.mtl', function( material ) { //这里加载我们需要的文件名 175 material.preload();176 var objLoader = new THREE.OBJLoader(); 177 objLoader.setMaterials( material ); //材质,也可自定义 178 objLoader.setPath( './' ); //设置要加载的obj文件的路径 179 objLoader.load( 'lyn.obj', 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 = ''; 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 : '#A44A32', 286 specular : '#ffffff', 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 : '#2194ce', 297 specular : '#111111', 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>
The above is the detailed content of 3D renderings made using three.js?. For more information, please follow other related articles on the PHP Chinese website!