当前位置: 代码迷 >> JavaScript >> three.js javascript 3d 超级发动机
  详细解决方案

three.js javascript 3d 超级发动机

热度:760   发布时间:2013-03-06 16:20:31.0
three.js javascript 3d 超级引擎 !

apiurl:http://mrdoob.github.com/three.js/docs/56/

?

?

?

博客一:

?

【three.js详解之一】入门篇

?

?

开场白

webGL可以让我们在canvas上实现3D效果。而three.js是一款webGL框架,由于其易用性被广泛应用。如果你要学习webGL,抛弃那些复杂的原生接口从这款框架入手是一个不错的选择。

博主目前也在学习three.js,发现相关资料非常稀少,甚至官方的api文档也非常粗糙,很多效果需要自己慢慢敲代码摸索。所以我写这个教程的目的一是自己总结,二是与大家分享。

本篇是系列教程的第一篇:入门篇。在这篇文章中,我将以一个简单的demo为例,阐述three.js的基本配置方法。学完这篇文章,你将学会如何在浏览器中绘制一个立体图形!

准备工作

在写代码之前,你首先要去下最新的three.js框架包,在你的页面里引入three.js,当然文件包里面也有不少的demo便于大家学习;

chrome是目前支持webGL最好的浏览器,Firefow居其次,国内的遨游、猎豹经测试也可以运行。

从实例开始入门!

首先我们搭建html,如下:

复制代码
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>lesson1-by-shawn.xie</title>
        <!--引入Three.js-->
        <script src="Three.js"></script>
        <style type="text/css">
            div#canvas-frame{
                  border: none;
                  cursor: move;
                  width: 1400px;
                  height: 600px;
                  background-color: #EEEEEE;
                }
        </style>
    </head>

    <body>
        <!--盛放canvas的容器-->
        <div id="container"></div>
    </body>
</html>
复制代码

准备和画布框大小一致的领域用于WebGL绘制。 具体来说:

(1) body 标签中添加 id 为「canvas3d」的 div 元素。

(2) style 标签中指定 「canvas3d」的CSS样式。

需要注意的是,我们并不需要写一个<canvas>标签,我们只需要定义好盛放canvas的div就可以,canvas是three.js动态生成的!

下面我们开始写脚本,我们将通过以下五步构建一个简单的立体模型,这也是three.js的基本步骤:

1.设置three.js渲染器

三维空间里的物体映射到二维平面的过程被称为三维渲染。 一般来说我们都把进行渲染操作的软件叫做渲染器。 具体来说要进行下面这些处理。

(0) 声明全局变量(对象);

(1) 获取画布「canvas-frame」的高宽;

(2) 生成渲染器对象(属性:抗锯齿效果为设置有效);

(3) 指定渲染器的高宽(和画布框大小一致);

(4) 追加 【canvas】 元素到 【canvas3d】 元素中;

(5) 设置渲染器的清除色(clearColor)。

?

复制代码
//开启Three.js渲染器
var renderer;//声明全局变量(对象)
function initThree() {
   width = document.getElementById('canvas3d').clientWidth;//获取画布「canvas3d」的宽
   height = document.getElementById('canvas3d').clientHeight;//获取画布「canvas3d」的高
   renderer=new THREE.WebGLRenderer({antialias:true});//生成渲染器对象(属性:抗锯齿效果为设置有效)
   renderer.setSize(width, height );//指定渲染器的高宽(和画布框大小一致)
   document.getElementById('canvas3d').appendChild(renderer.domElement);//追加 【canvas】 元素到 【canvas3d】 元素中。
   renderer.setClearColorHex(0xFFFFFF, 1.0);//设置canvas背景色(clearColor)
}
复制代码

?

2.设置摄像机camera

OpenGL(WebGL)中、三维空间中的物体投影到二维空间的方式中,存在透视投影和正投影两种相机。 透视投影就是、从视点开始越近的物体越大、远处的物体绘制的较小的一种方式、和日常生活中我们看物体的方式是一致的。 正投影就是不管物体和视点距离,都按照统一的大小进行绘制、在建筑和设计等领域需要从各个角度来绘制物体,因此这种投影被广泛应用。在 Three.js 也能够指定透视投影和正投影两种方式的相机。 本文按照以下的步骤设置透视投影方式。

(0) 声明全局的变量(对象);

(1) 设置透视投影的相机;

(2) 设置相机的位置坐标;

(3) 设置相机的上为「z」轴方向;

(4) 设置视野的中心坐标。

复制代码
         //设置相机
              var camera;
              function initCamera() { 
                camera = new THREE.PerspectiveCamera( 45, width / height , 1 , 5000 );//设置透视投影的相机,默认情况下相机的上方向为Y轴,右方向为X轴,沿着Z轴朝里(视野角:fov 纵横比:aspect 相机离视体积最近的距离:near 相机离视体积最远的距离:far)
                camera.position.x = 0;//设置相机的位置坐标
                camera.position.y = 50;//设置相机的位置坐标
                camera.position.z = 100;//设置相机的位置坐标
                camera.up.x = 0;//设置相机的上为「x」轴方向
                camera.up.y = 1;//设置相机的上为「y」轴方向
                camera.up.z = 0;//设置相机的上为「z」轴方向
                camera.lookAt( {x:0, y:0, z:0 } );//设置视野的中心坐标
              }
复制代码

?

3.设置场景scene

场景就是一个三维空间。 用 [Scene] 类声明一个叫 [scene] 的对象。

        //设置场景
              var scene;
              function initScene() {   
                scene = new THREE.Scene();
              }

?

4.设置光源light

OpenGL(WebGL)的三维空间中,存在点光源和聚光灯两种类型。 而且,作为点光源的一种特例还存在平行光源(无线远光源)。另外,作为光源的参数还可以进行 [环境光] 等设置。 作为对应, Three.js中可以设置 [点光源(Point Light)] [聚光灯(Spot Light)] [平行光源(Direction Light)],和 [环境光(Ambient Light)]。 和OpenGL一样、在一个场景中可以设置多个光源。 基本上,都是环境光和其他几种光源进行组合。 如果不设置环境光,那么光线照射不到的面会变得过于黑暗。 本文中首先按照下面的步骤设置平行光源,在这之后还会追加环境光。

(0) 声明全局变量(对象)

(1) 设置平行光源

(2) 设置光源向量

(3) 追加光源到场景

这里我们用「DirectionalLight」类声明一个叫 [light] 的对象来代表平行光源

复制代码
         //设置光源
              var light;
              function initLight() { 
                light = new THREE.DirectionalLight(0xff0000, 1.0, 0);//设置平行光源
                light.position.set( 200, 200, 200 );//设置光源向量
                scene.add(light);// 追加光源到场景
              }
复制代码

?

5.设置物体object

?? 这里,我们声明一个球模型

复制代码
         //设置物体
              var sphere;
              function initObject(){  
                sphere = new THREE.Mesh(
                     new THREE.SphereGeometry(20,20),                //width,height,depth
                     new THREE.MeshLambertMaterial({color: 0xff0000}) //材质设定
                );
                scene.add(sphere);
                sphere.position.set(0,0,0);
              }
复制代码

最后,我们写一个主函数执行以上五步:

复制代码
        //执行
              function threeStart() {
                initThree();
                initCamera();
                initScene();   
                initLight();
                initObject();
                renderer.clear(); 
                renderer.render(scene, camera);
              }
复制代码

这时,测试以上程序,你会发现浏览器窗口中出现了你绘制的球形模型:

总结

以上就是three.js的入门内容,我们核心的五步就是:

1.设置three.js渲染器

2.设置摄像机camera

3.设置场景scene

4.设置光源light

5.设置物体object

可能其中有些设置你还不太清楚,没关系,后面几篇文章会对以上五个主要步骤进行详细的讲解,敬请期待~~


本例完整代码:

复制代码
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>lesson1-by-shawn.xie</title>
        <!--引入Three.js-->
        <script src="Three.js"></script>
        <script type="text/javascript">
            //开启Three.js渲染器
             var renderer;//声明全局变量(对象)
             function initThree() {
                width = document.getElementById('canvas3d').clientWidth;//获取画布「canvas3d」的宽
                height = document.getElementById('canvas3d').clientHeight;//获取画布「canvas3d」的高
                renderer=new THREE.WebGLRenderer({antialias:true});//生成渲染器对象(属性:抗锯齿效果为设置有效)
                renderer.setSize(width, height );//指定渲染器的高宽(和画布框大小一致)
                document.getElementById('canvas3d').appendChild(renderer.domElement);//追加 【canvas】 元素到 【canvas3d】 元素中。
                renderer.setClearColorHex(0xFFFFFF, 1.0);//设置canvas背景色(clearColor)
              }
               //设置相机
              var camera;
              function initCamera() { 
                camera = new THREE.PerspectiveCamera( 45, width / height , 1 , 5000 );//设置透视投影的相机,默认情况下相机的上方向为Y轴,右方向为X轴,沿着Z轴朝里(视野角:fov 纵横比:aspect 相机离视体积最近的距离:near 相机离视体积最远的距离:far)
                camera.position.x = 0;//设置相机的位置坐标
                camera.position.y = 50;//设置相机的位置坐标
                camera.position.z = 100;//设置相机的位置坐标
                camera.up.x = 0;//设置相机的上为「x」轴方向
                camera.up.y = 1;//设置相机的上为「y」轴方向
                camera.up.z = 0;//设置相机的上为「z」轴方向
                camera.lookAt( {x:0, y:0, z:0 } );//设置视野的中心坐标
              }
               //设置场景
              var scene;
              function initScene() {   
                scene = new THREE.Scene();
              }

              //设置光源
              var light;
              function initLight() { 
                light = new THREE.DirectionalLight(0xff0000, 1.0, 0);//设置平行光源
                light.position.set( 200, 200, 200 );//设置光源向量
                scene.add(light);// 追加光源到场景
              }
               //设置物体
              var sphere;
              function initObject(){  
                sphere = new THREE.Mesh(
                     new THREE.SphereGeometry(20,20),                //width,height,depth
                     new THREE.MeshLambertMaterial({color: 0xff0000}) //材质设定
                );
                scene.add(sphere);
                sphere.position.set(0,0,0);
              }
              //执行
              function threeStart() {
                initThree();
                initCamera();
                initScene();   
                initLight();
                initObject();
                renderer.clear(); 
                renderer.render(scene, camera);
              }
        </script>
        <style type="text/css">
            div#canvas3d{
                  border: none;
                  cursor: move;
                  width: 1400px;
                  height: 600px;
                  background-color: #EEEEEE;
                }
        </style>
    </head>

    <body onload='threeStart();'>
        <!--盛放canvas的容器-->
        <div id="canvas3d"></div>
    </body>
</html>
复制代码

?

?

?

博客二:

如何学习Three.JS 3D引擎

发布时间:2011-11-29 作者:小想 来源:未知?我要评论

我已经用Three.js做了些小实验,这是一个比较伟大的引擎,你只需要为浏览器的不支持而头疼。你可以用它来创建摄像机(cameras),对象,(objects),光照(lights),材质(materials)等等。你还可以选…

?我已经用Three.js做了些小实验,这是一个比较伟大的引擎,你只需要为浏览器的不支持而头疼。你可以用它来创建摄像机(cameras),对象,(objects),?光照(lights),?材质(materials)?等等。你还可以选择渲染器,Three.js提供了多种渲染方式,如果你想让你的网页支持HTML5你也可以选择使用canvas来渲染,也可以使用WebGL或者SVG来进行渲染。Threejs是开源框架,你如果感兴趣你也可以参与开发。但是现在我只是用这个引擎,也只是把它当作一种小工具。在这里我也给大家演示一下如何学习ThreeJS的基础知识。

???对于ThreeJS的粉丝这是一片很基础的文章,但是对于新手这将很快的使你了解ThreeJS,通常你需要结合大量的实例来分析demo才可以明白。如果你有问题可以直接在mrdoob的论坛上发布,?asking questions via GitHub.他会给你做出回答和解决的。如果你有很深奥和着急的问题你也可以发邮件给他们?Mr. doob和AlteredQualia?都会帮组你的。

?

1:基础

??首先我假设你是个有一定基础的3D开发者,并且你可以熟练的掌握和合理的运用javascript语法。如果你没有上述两点那么你需要学习学习,也许你会觉得非常的有趣的。不过javascript确实有点混乱,容易被人头疼。

在我们目前的3D世界当中至少包括以下几点基础的东西,我会给大家一一介绍。

?一:?一个场景

二:?一个渲染器

三:?一个摄像机

四:?一个对象或者至少两个材质

当然你也可以做很多的东西,很多非常疯狂的东西,只要很有足够的想象力,那么就开始你的3D开发,做出很多很炫的WebGL作品吧。

2:?支持

?开发WebGL需要浏览器的大力支持,google的chrome是我在做demo的时候常用的浏览器,个人感觉还是不错的。支持webgl的渲染并且在javascript上速度还是不错的还有一些潜在的javascript引擎。Chrome全部支持canvas,webgl,svg这一块。火狐个人觉得排名第二那么google就肯定第一了,并且是火狐4的版本。火狐的javascript引擎似乎还是比google的chrome慢些,但是在渲染的支持上还是很强的。Opear和Safari也支持webgl,但是他们当前的版本只支持canvas渲染,IE9也只支持canvas渲染,到目前为止还没有听到微软说全面支持webgl的消息,担忧啊。

3:设置场景(Scene)

这一步我想你肯定已经选好了一个可以渲染WebGL的浏览器了,并且选好了你要使用的渲染方式了canvas,因为canvas还是比较标准些。Canvas不只是支持WebGL,还有更多的支持。不过,WebGL运行在你cpu的图形卡上,这样就意味着你的cpu可以专心的做别的事,而不需要为webgl渲染而担心,这就叫做硬件加速渲染。

?无论你选择什么样的渲染机制,但是你需要记住的就是javascript需要很好的优化性能,因为3D对于浏览器来说还是很大的渲染,所以在你的javascript代码中尽量减少浏览器的压力,优化优化再优化你的javascript代码。

?那么这样的话,你可以下载you have downloadedThreeJS的多有js文件在你的电脑中,那么先看看如何着手建立一个Threejs的场景,看下面代码行:

JavaScript Code复制内容到剪贴板
  1. //?set?the?scene?size??
  2. var?WIDTH?=?400,??
  3. ????HEIGHT?=?300;??
  4. ??
  5. //?设置相机的属性s??
  6. var?VIEW_ANGLE?=?45,??
  7. ????ASPECT?=?WIDTH?/?HEIGHT,??
  8. ????NEAR?=?0.1,??
  9. ????FAR?=?10000;??
  10. ??
  11. //?得到dom的元素??
  12. //?-?假设我们有jquery的开发经验??
  13. var?$container?=?$('#container');??
  14. ??
  15. //?创建一个WebGL的渲染器和摄像机和一个场景??
  16. ??
  17. var?renderer?=?new?THREE.WebGLRenderer();??
  18. var?camera?=?new?THREE.Camera(??VIEW_ANGLE,??
  19. ????????????????????????????????ASPECT,??
  20. ????????????????????????????????NEAR,??
  21. ????????????????????????????????FAR??);??
  22. var?scene?=?new?THREE.Scene();??
  23. ??
  24. //?摄像机从?0,0,0开始?,因此默认原点,需要时回滚??
  25. ??
  26. //设置摄像机z坐标位置距离原点向外300??
  27. camera.position.z?=?300;??
  28. ??
  29. //?开始渲染??
  30. renderer.setSize(WIDTH,?HEIGHT);??
  31. ??
  32. //?加载dom的元素??
  33. $container.append(renderer.domElement);??

看起来挺简单的,不是很难。

4:做一个网格模型

???现在我们有一个场景,一个摄像机,一个渲染器,但是我们需要画一个实体。实际上Three.js可以加载很多格式的3D文件,你的模型文件可以来自Blender,Maya,Chinema4D,3DMax等等。现在我们要做的是一个网格的元素,相对比较基础的东西(球体)Spheres, (飞机)Planes,(立方体) Cubes?,?(圆柱体)Cylinders。Three.js创建这些物体会非常的容易。

JavaScript Code复制内容到剪贴板
  1. //定义球体??
  2. var?radius?=?50,?segments?=?16,?rings?=?16;??
  3. ??
  4. //?创建一个新的网格球体几何学?-??
  5. //?在下一节我们将要涉及到sphereMaterial???
  6. var?sphere?=?new?THREE.Mesh(??
  7. ???new?Sphere(radius,?segments,?rings),??
  8. ???sphereMaterial);??
  9. ??
  10. //?添加球体到场景??
  11. scene.addChild(sphere);??

好了!但是我们的这个球体没有材质。在代码中我们使用了一个变量sphereMaterial,但是我们还没有对他进行定义。首先我们需要做的是对球体的材质进行描述。

5:材质(Materials)

?毫无疑问这在Three.Js中是很重要的一部分,因为Three.js可以让你很方便的实现你的网格效果。

???1:不发光

???2:发光

???3:多面

还有很多很多,现在我只介绍这些,剩下的由你自己去发现。但是你必须写在WebGL的着色器上,着色器是一个很庞大的东西,但是你可以使用GLSL(OpenGL的着色语言)。这就需要你用数学来实现模拟的灯光,这样会很复杂。但是多亏了Three.js,你可以不需要在做那样的数学计算了,如果你想写关于阴影的那么你可以使用MeshShaderMaterial来实现,所以这是一个很活泛的设置。

JavaScript Code复制内容到剪贴板
  1. //?创建一个球体的材质??
  2. var?sphereMaterial?=?new?THREE.MeshLambertMaterial(??
  3. {??
  4. ????color:?0xCC0000??
  5. });??

你也可以创建一个其他的材质,除了颜色,比如平滑或者环境的地图。你可以看看这个页面check out the Wiki page,看看你还可以创建什么材质,实际上任何一个引擎都会提供给你的。

6:灯(Lights)

如果你按照上面的实现,那么你现在可以看到一个空色的圆球。但是我们现在有材质却没有光,Three.js默认的是全环境的光,那么我们需要把这些光修理的好点。

JavaScript Code复制内容到剪贴板
  1. //?创建一个光的源点??
  2. var?pointLight?=?new?THREE.PointLight(?0xFFFFFF?);??
  3. ??
  4. //?设置光源点位置??
  5. pointLight.position.x?=?10;??
  6. pointLight.position.y?=?50;??
  7. pointLight.position.z?=?130;??
  8. ??
  9. //?添加到场景??
  10. scene.addLight(pointLight);??

7:循环渲染

现在我们大概算是有一些渲染了,但是我们需要这样做:

JavaScript Code复制内容到剪贴板
  1. //?绘画!??
  2. renderer.render(scene,?camera);??

我们渲染但不一定只是一次,所以如果你想循环渲染,那么你就需要好好的利用requestAnimationFrame这个js类,这是在浏览器中处理动画迄今为止最先进的js代码,但是到目前为止还不是完全支持,所以推介你看看?Paul Irish's shim.。

JavaScript Code复制内容到剪贴板
  1. //?设置回滚时间??
  2. window.requestAnimFrame?=?(function(){??
  3. ??return??window.requestAnimationFrame???????||??
  4. ??????????window.webkitRequestAnimationFrame?||??
  5. ??????????window.mozRequestAnimationFrame????||??
  6. ??????????window.oRequestAnimationFrame??????||??
  7. ??????????window.msRequestAnimationFrame?????||??
  8. ??????????function(/*?function?*/?callback,?/*?DOMElement?*/?element){??
  9. ????????????window.setTimeout(callback,?1000?/?60);??
  10. ??????????};??
  11. })();??
  12. ??
  13. //?插入setInterval(render,?16)?....??
  14. (function?animloop(){??
  15. ??render();??
  16. ??requestAnimFrame(animloop,?element);??
  17. })();??

代码:

JavaScript Code复制内容到剪贴板
  1. //?requestAnim?shim?layer?by?Paul?Irish??
  2. ????window.requestAnimFrame?=?(function(){??
  3. ??????return??window.requestAnimationFrame???????||??
  4. ??????????????window.webkitRequestAnimationFrame?||??
  5. ??????????????window.mozRequestAnimationFrame????||??
  6. ??????????????window.oRequestAnimationFrame??????||??
  7. ??????????????window.msRequestAnimationFrame?????||??
  8. ??????????????function(/*?function?*/?callback,?/*?DOMElement?*/?element){??
  9. ????????????????window.setTimeout(callback,?1000?/?60);??
  10. ??????????????};??
  11. ????})();??
  12. ???
  13. ???
  14. //?example?code?from?mr?doob?:?http://mrdoob.com/lab/javascript/requestanimationframe/??
  15. ???
  16. var?canvas,?context;??
  17. ???
  18. init();??
  19. animate();??
  20. ???
  21. function?init()?{??
  22. ???
  23. ????canvas?=?document.createElement(?'canvas'?);??
  24. ????canvas.width?=?256;??
  25. ????canvas.height?=?256;??
  26. ???
  27. ????context?=?canvas.getContext(?'2d'?);??
  28. ???
  29. ????document.body.appendChild(?canvas?);??
  30. ???
  31. }??
  32. ???
  33. function?animate()?{??
  34. ????requestAnimFrame(?animate?);??
  35. ????draw();??
  36. ???
  37. }??
  38. ???
  39. function?draw()?{??
  40. ???
  41. ????var?time?=?new?Date().getTime()?*?0.002;??
  42. ????var?x?=?Math.sin(?time?)?*?96?+?128;??
  43. ????var?y?=?Math.cos(?time?*?0.9?)?*?96?+?128;??
  44. ???
  45. ????context.fillStyle?=?'rgb(245,245,245)';??
  46. ????context.fillRect(?0,?0,?255,?255?);??
  47. ???
  48. ????context.fillStyle?=?'rgb(255,0,0)';??
  49. ????context.beginPath();??
  50. ????context.arc(?x,?y,?10,?0,?Math.PI?*?2,?true?);??
  51. ????context.closePath();??
  52. ????context.fill();??
  53. ???
  54. }??

8常见的对象的特性

如果你花时间看代码的话,你会看到很多Three.js继承的Object3D的对象,这是一个很基础的对象,包含很多非常有用的特征,位置,旋转,大小的信息。特别的是我们的网格也是继承与Object3D,他加了自己的一些特性:材质和几何。

你想知道为什么我会说到这里,那么你想画一个球体在你的web上什么都不做吗?这些特征的存在值得你去研究,因为他们允许你去操作潜在的材质和网格划分。

JavaScript Code复制内容到剪贴板
  1. //?几何球面??
  2. sphere.geometry??
  3. ??
  4. //?包含顶点和面??
  5. sphere.geometry.vertices?//?数组??
  6. sphere.geometry.faces?//?以数组形式??
  7. ??
  8. //?位置??
  9. sphere.position?//?包括x,y,z三个属性??
  10. sphere.rotation?//?包括x,y,z三个属性??
  11. sphere.scale?//?包括x,y,z三个属性??

9:一个小的更改

?在顶点这里我们需要做个更改,你尝试更改你的顶点数据,但是你会发现你的渲染一点没有改变,这是为什么呢?因为Three.js是一向很复杂的优化,你只需要更换其中的一个方法就可以,

JavaScript Code复制内容到剪贴板
  1. //?改变顶点??
  2. sphere.geometry.__dirtyVertices?=?true;??
  3. ??
  4. //?改变法线??
  5. sphere.geometry.__dirtyNormals?=?true;??

其实还有很多,但是这两个是我发现最重要的,你会发现只改变这个就省去很多不必要的计算。

结论:

我想你已经大致了解这个关于Three.js的简单介绍了,你可以自己动手尝试做些实例了,你会发现3D在网页中也是非常有趣的。Three.js为你解决了很多头疼的问题,你就可以做出很酷的效果了。

??????你可以看看这里wrapped up the source code?的文章,对你会有很大的帮组的

  相关解决方案