前言:首先先推荐一篇博客,关于webgl原理,讲的非常之通俗易懂了 图解WebGL&Three.js工作原理  webGL可以理解为openGL ES2.0

(webGL2.0 - openGL ES3.0)的javascript绑定。所以实现的语言是javascript和opengl(最常用的跨平台图形库)着色语言,webgl是

HTML5中提出的新技术,是一种3D绘图标准。

three.js是以webgl为基础的库,封装了一些3D渲染需求中重要的工具方法与渲染循环。WebGL门槛相对较高,Three.js对WebGL提供的接

口进行了非常好的封装,简化了很多细节,大大降低了学习成本

我们可能还听说过一个D3.js(Data-Driven Documents),是一个数据可视化的库,技术基础是SVG。兼容性是IE9+,官网(http://d3js.org),

从官网的example中可以看出,它跟3d视图还是不同的。

我们只需要从官网上下载一个three.js,然后用script标签引入即可。

首先注意的一点是,我们在页面上并不需要一个canvas标签,只需要一个盛放canvas的容器就行,canvas是three.js动态生成的。

01.01 - WebGLRenderer - Skeleton

#canvas3d{

width:800px;

height:450px;

margin:100px auto;

}

threejs里最重要的几个元素,如下:

var renderer; //渲染器

var scene;   //场景

var camera; //相机

var light;   //光源

var cube; //物体

1,生成3d渲染器,设置渲染器的宽高和背景色,(通常我们可以直接获取页面上画布的宽高,便于嵌入改动)

renderer = new THREE.WebGLRenderer({antialias:true}); //生成渲染器对象(antialias属性:抗锯齿效果为设置有效)

renderer.setClearColor(0x333333, 1.0);

//renderer.setSize(window.innerWidth, window.innerHeight);

renderer.setSize('800', '450');

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

scene = new THREE.Scene();

3,设置一个摄像机camera,

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

正交投影与透视投影的区别如上图所示,左图是正交投影,物体发出的光平行地投射到屏幕上,远近的方块都是一样大的;右图是透视投影,近大远小,符合我们平时看东西的感觉。

camera坐标系

Three中使用采用常见的右手坐标系定位。

// 四个参数分别代表了摄像机的视角、宽高比、近和远两个视截面。

//设置透视投影的相机,默认情况下相机的上方向为Y轴,右方向为X轴,沿着Z轴朝里(视野角:fov 纵横比:aspect 相机离视体积最近的距离:near 相机离视体积最远的距离:far)

camera = new THREE.PerspectiveCamera(90, window.innerWidth / window.innerHeight, 0.1, 1000);

// position and point the camera to the center of the scene

camera.position.x = 20;

camera.position.y = 18;

camera.position.z = 35;

camera.lookAt(scene.position); //设置视野的中心坐标

4,设置光源light

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

//设置light

light = new THREE.DirectionalLight(0xff0000, 1.0, 0); //设置平行光

light.position.set( 200, 200, 200 ); //设置光源向量

scene.add(light); // 追加光源到场景

5,设置物体 object

在three.js中,我们使用Mesh模型,Mesh的构造函数是这样的:Mesh( geometry, material ) geometry是它的形状,material是它的材质。 三维模型通常用三角形的网格来描述

对于图中的兔子,随着三角形数量的增加,它的表面越来越平滑/准确

我们这里是一个立方体 cube

var cubeGeometry = new THREE.BoxGeometry(20, 10, 15,2,3,1); //设置长宽高 以及对应长宽高的分段,在使用线模式({wireframe:true})进行渲染的时候可以看到效果

var cubeMaterial = new THREE.MeshNormalMaterial({wireframe : true}); //材质

cube = new THREE.Mesh(cubeGeometry, cubeMaterial);

var border = new THREE.EdgesHelper( cube,0xffff00 ); //添加边框

scene.add(cube);

scene.add(border);

6,最后一步,进行渲染

//将渲染器的元素添加到页面中

document.getElementById('canvas3d').appendChild(renderer.domElement);

renderer.render(scene, camera);

完整的代码已经上传到github上: github(three-one)  如果你觉得我写的对你有所帮助的话,请给我个star吧,谢谢

最后的效果图如下:

在上面的学习基础上,我们继续深入的探究一下,如何给3d视图添加动画,纹理等;

1,首先我们在上面的基础上,添加多个立体几何图形

//立方体

var cubeGeometry = new THREE.BoxGeometry(15,15,15,1,1,1);

var cubeMaterial = new THREE.MeshNormalMaterial({wireframe : true}); //材质

cube = new THREE.Mesh(cubeGeometry, cubeMaterial);

var border = new THREE.EdgesHelper( cube,0xffff00 ); //添加边框

scene.add(cube);

scene.add(border);

//圆柱体

var cylinderGeometry = new THREE.CylinderGeometry(8, 8,10,30,30);

var cylinderMaterial = new THREE.MeshNormalMaterial();

var cylinder = new THREE.Mesh(cylinderGeometry,cylinderMaterial);

cylinder.position.x = -10;

cylinder.position.y = -5;

cylinder.position.z = 25;

cylinder.castShadow = true;

scene.add(cylinder);

//球体

var sphereGeometry = new THREE.SphereGeometry(7, 25, 25);

var sphereMaterial = new THREE.MeshLambertMaterial({color: 0x7777ff});

var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);

// position the sphere

sphere.position.x = 0;

sphere.position.y = 0;

sphere.position.z = 0;

sphere.castShadow = true;

// add the sphere to the scene

scene.add(sphere);

//圆环

var torusGeometry = new THREE.TorusGeometry(10,3,20,20);

var torusMaterial = new THREE.MeshBasicMaterial();

var tours = new THREE.Mesh(torusGeometry,torusMaterial);

tours.position.x = 10;

tours.position.y = -10;

tours.position.z = -40;

tours.castShadow = true;

scene.add(tours);我们通过position属性

调整立体几何在scene中的位置(x,y,z)

创建几何体时有一点强调的是,对于参数的设置,例如创建圆环的时候,

THREE.TorusGeometry(10,3,20,20)

我们第三四个参数分割比的值越大,立体几何中拼凑的平面图形就越多,立体几何就越圆滑,就是上一篇博客中兔子的那个原理。

2,添加动画

我们要针对每个几何体添加不同的动画,所以就需要为每个几何体添加一个name属性来指定,比如:

cube.name = 'cube';

cylinder.name = 'cylinder';

然后在render函数中,用getObjectByName获取到对应的几何体,用setInterval的思想原理,通过requestAnimationFrame函数使得几何体动起来

scene.getObjectByName('cube').rotation.x += control.rotationSpeed;

scene.getObjectByName('cube').scale.set(control.scale, control.scale, control.scale);

scene.getObjectByName('cylinder').rotation.z += control.rotationSpeed2;

scene.getObjectByName('tours').rotation.z += 0.05;

requestAnimationFrame(render);

3,stats性能插件

stats.js用于对JavaScript进行性能检测。

我们创建一个createStats的函数,然后在init初始化中调用它

function createStats() {

var stats = new Stats();

stats.setMode(0);

stats.domElement.style.position = 'absolute';

stats.domElement.style.left = '0px';

stats.domElement.style.top = '5px';

return stats;

}

需要特别注意的一点是,我们需要在render函数中不断的更新stats显示

stats.update();

dat.gui.js用于创建菜单栏,可以用来控制场景中的各个参数来调试场景。

function addControls(controlObject){

var gui = new dat.GUI();

gui.add(controlObject,'rotationSpeed',-0.1,0.1);

gui.add(controlObject, 'scale', 0.01, 2);

gui.add(controlObject, 'rotationSpeed2', -0.1, 0.1);

}

创建addControls函数,然后在init初始化函数中设置默认值,并调用这个函数

control = new function (){

this.rotationSpeed = 0.005;

this.scale = 1;

this.rotationSpeed2 = 0.05;

}

addControls(control);

4,添加纹理

这个首先注意的就是图片应该是异步获取的,所以你可以放在本地的apache中,也可以自己用nodejs非常方便的搭建一个服务器,不然的话,他就会报错,跨域了。

var texture = new THREE.ImageUtils.loadTexture("http://10.1.26.29:84/Brick-2399.jpg");

torusMaterial.map = texture;

最后的效果图如下:

完整的代码:github(threejs-two)  如果你觉得我写的对你有帮助的话,请给我个star吧,谢谢,我会继续更新下去的

5,最后,从完整的代码中,我们可以看出,关于材质,我们也是调用了不同的函数,这里总结一下材质

材质种类:

MeshBasicMaterial:为几何体赋予一种简单的颜色,或者显示几何体的线框

MeshDepthMaterial:根据网格到相机的距离,该材质决定如何给网格染色

MeshNormalMaterial:根据物体表面的法向量计算颜色

MeshFaceMaterial:这是一种容器,可以在该容器中为物体的各个表面上设置不同的颜色

MeshLambertMaterial:考虑光照的影响,可以创建颜色暗淡,不光亮的物体

MeshPhongMaterial:考虑光照的影响,可以创建光亮的物体

ShaderMaterial:使用自定义的着色器程序,直接控制顶点的放置方式,以及像素的着色方式。

LineBasicMaterial:可以用于THREE.Line几何体,从而创建着色的直线

LineDashedMaterial:类似与基础材质,但可以创建虚线效果

(1)MeshBasicMaterial:不考虑光照的影响。

属性:

color

wireframe

wireframeLinewidth

wireframeLinecap:线段端点如何显示。可选值有:butt(平)、round、square。默认是round。WebGLRenderer对象不支持该属性。

wireframeLinejoin:线段连接点如何显示。可选值有:round、bevel(斜角)、miter(尖角)。默认是round。WebGLRenderer对象不支持属性。

shading:着色模式。可选值:THREE.SmoothShading、THREE.FlatShading。

vertexColors:为每个顶点定义不同的颜色。在CanvasRenderer对象中不起作用。

fog:指示当前是否会受全局雾化效果设置的影响。

两种设置属性的方式:

//1.构造函数

var meshMaterial = new THREE.MeshBasicMaterial({color:0xffccff});

//2属性

meshMaterial.visible = false;

(2)MeshDepthMaterial

使用这种材质的物体,其外观不是由光照或某个材质属性决定的;而是由物体到相机的距离决定的。可以将这种材质与其他材质相结合,从而很容易创建逐渐消失的效果。

只有两个控制线框的属性:

wireframe

wireframeLinewidth

可以通过设置相机的near和far的值,来控制创建中使用这种材质的物体的消失速度。如果near和fat之间的差值越大,那么物体远离相机时,只会稍微消失一点;反之,物体消失的效果非常明显。

var cubeMaterial = new THREE.MeshDepthMaterial();

var colorMaterial = new THREE.MeshBasicMaterial({color:0x00ff00,transparent:true,blending:THREE.MultiplyBlending});

var cube = new THREE.SceneUtils.createMultiMaterialObject(cubeGeometry,[colorMaterial,cubeMaterial]);

cube.children[1].scale.set(0.99,0.99,0.99);//避免渲染遮挡而造成的闪烁

(3)MeshNormalMaterial

法向量的作用: 决定光的发射方向、在计算光照、阴影时提供信息、为物体表面上色。法向量所指的方向决定每个面从MeshNormalMaterial材质获取的颜色。

属性:

wireframe

wireframeLinewidth

shading

for(var f = 0 , f1 = sphere.geometry.faces.length; f < f1 ; f++){

var face = spere.geometry.faces[f];

var arrow = new THREE.ArrowHelper(face.normal,face.centroid,2,0x3333ff);

spere.add(arrow);

}

在球体的每个面上添加了一个长度为2,颜色为0x3333ff的箭头

(4)MeshFaceMaterial

可以为几何体的每一个面指定不同的材质。

假设有一个正方体,可以为每个面指定不同的颜色。

var matArray = [];

matArray.push(new THREE.MeshBasicMaterial({color:0x00ff00}));

matArray.push(new THREE.MeshBasicMaterial({color:0x00ff00}));

matArray.push(new THREE.MeshBasicMaterial({color:0x00ff00}));

matArray.push(new THREE.MeshBasicMaterial({color:0x00ff00}));

matArray.push(new THREE.MeshBasicMaterial({color:0x00ff00}));

matArray.push(new THREE.MeshBasicMaterial({color:0x00ff00}));

var faceMaterial = new THREE.MeshFaceMaterial(matArray);

var cubeGeometry = new THREE.CubeGeometry(3,3,3);

var cube = new THREE.Mesh(cubeGeometry,faceMaterial);

(5)MeshLambertMaterial

对光源有反应。

基本属性:

color、opacity、shading、blending、depthTest、depthWrite、wireframe、wireframeLineWith、wirefLinecap、wireframeLinejoin、vertexColors、fog。

独特属性:

ambient:和AmbientLight光源一起使用。该颜色会与AmbientLight光源的颜色相乘。默认是白色。

emissive:该材质发射的属性。不像是光源,只是一种纯粹的、不受其他光照影响的颜色。默认是黑色。

(6)MeshPhongMaterial

基本属性:

color、opacity、shading、blending、depthTest、depthWrite、wireframe、wireframeLineWith、wirefLinecap、wireframeLinejoin、vertexColors、fog。

独特属性:

ambient

emissive

specular:指定该材质的光亮程度及其高光部分的颜色。如果将他设置成跟color属性相同的颜色,将会得到一种更加类似金属的材质。如果设置为灰色,材质将变得更像塑料。

shininess:指定高光部分的亮度。默认是30.

(7)ShaderMaterial

属性:

wireframe

wireframeLinewidth

shading

vertexColor

fog:指示当前是否会受全局雾化效果设置的影响。

独特属性:

fragmentShader:定义每个传入的像素的颜色。

vertexShader:允许你修改每一个传入的顶点的位置

uniforms:该属性可以向你的着色器发送消息。将同样的信息发送到每一个顶点和片段。

defines:该属性可以转换为vertexShader和fragmentShader里的#define代码。该属性可以用来设置着色器程序里的一些全局变量。

attributes:该属性可以修改每个顶点和片段。常用来传递位置数据和法向量相关的数据。如果要用这个属性,辣么你要为几何体中的所有顶点提供信息。

lights:定义光照数据是否传递给着色器。默认是false。

独特属性:

fragmentShader:定义每个传入的像素的颜色。

vertexShader:允许你修改每一个传入的顶点的位置

uniforms:该属性可以向你的着色器发送消息。将同样的信息发送到每一个顶点和片段。

defines:该属性可以转换为vertexShader和fragmentShader里的#define代码。该属性可以用来设置着色器程序里的一些全局变量。

attributes:该属性可以修改每个顶点和片段。常用来传递位置数据和法向量相关的数据。如果要用这个属性,辣么你要为几何体中的所有顶点提供信息。

lights:定义光照数据是否传递给着色器。默认是false。

(8)LineBasicMaterial

基本属性:

color

lineWidth

LineCap:butt、round、square。默认是round。WebGLRenderer不支持该属性。

LineJoin:round、bevel(斜切)、miter(尖角)。默认是round。WebGLRenderer不支持该属性。

vertexColors:该属性值设置为 THREE.VertexColors值时,就可以为每个顶点指定一种颜色。

fog:指定当前物体是否受全局雾化效果的影响。

(9)LineDashedMaterial

和LineBasicMaterial有着一样的属性,但是有几个额外的属性,可以用来定义短划线长度和短划线中间空格长度的属性。

独特属性:

scale:缩放dashSize和gapSize。如果scale<1,则dashSize和gapSize就会增大。

dashSize:短线划的长度

gapSize:间隔的长度

threejs 三面体_three.js初探,立体几何入手(一)相关推荐

  1. threejs 三面体_Three.js 自定义了一个几何体

    几何体本质: 立方体几何体BoxGeometry本质上就是一系列的顶点构成,只是Threejs的APIBoxGeometry把顶点的生成细节封装了,用户可以直接使用. 比如一个立方体网格模型,有6个面 ...

  2. threejs 形状几何体_Three.js模型几何体面积、体积计算

    Three.js模型几何体面积.体积计算 在工作中通过Three.js开发项目的时候,一些特定的情况下你可能需要计算一个三维模型的表面积或者体积,比如在3D打印的Web项目中,你需要计算一个三维模型的 ...

  3. threejs 三面体_如何在Three.js中构造空心圆柱体

    I'm having difficulties constructing a hollow cylinder in Three.js. Should I go and construct it usi ...

  4. threejs球体旋转与场景旋转_three.js实现围绕某物体旋转

    话不多说,请看代码: 可以拖动右上角观察变化 Document // 1.设置three.js渲染器 var renderer; function initThree(){ width = docum ...

  5. threejs 绘制球体_Three.js 第一篇:绘制一个静态的3D球体

    第一篇就画一个球体吧 首先我们知道Three.js其实是一个3D的JS引擎,其中的强大之处就在于这个JS框架并不是依托于JQUERY来写的.那么,我们在写这一篇绘制3D球体的文章的时候,应该注意哪些地 ...

  6. threejs 绘制球体_Three.js基础探寻四——立方体、平面与球体

    前面简单介绍了 1.立方体 虽然这一形状的名字叫立方体(CubeGeometry),但它其实是长方体,也就是长宽高可以设置为不同的值.其构造函数是: THREE.CubeGeometry(width, ...

  7. threejs 纹理流动_Three.js纹理(一)

    一.概念 3D世界的纹理由图片组成.将纹理以一定的规则映射到几何体上,一般是三角形上,那么这个几何体就有纹理皮肤了. 那么在threejs中,或者任何3D引擎中,纹理应该怎么来实现呢?首先应该有一个纹 ...

  8. threejs 加载两个场景_three.js 场景切换

    用6个面组成的立方体作为场景图,发现会出现变形的现象,css3DRenderer 不会变形,但是不方便增加文字,最后采用scene的背景作为场景,背景是用cubeTextureLoader()加载的. ...

  9. threejs 三面体_ThreeJS学习6_几何体相关(BufferGeometry)

    ThreeJS学习6_几何体相关(BufferGeometry) 使用 BufferGeometry 可以有效减少向 GPU 传输几何体相关数据所需的开销 可以自定义顶点位置, 面片索引, 法向量, ...

最新文章

  1. mysql vip_MySQL高可用集群的VIP切换
  2. coreData使用
  3. hdu 5501(贪心+01背包)
  4. 人工智障学习笔记——机器学习(5)朴素贝叶斯
  5. 浦发银行出现:部件'InstallCertListAx.ocx'或其附件之一不能正确注册:一个文件丢失 解决...
  6. 框架升级后某个类型所在程序集发生转移,应用还能正常运行吗?
  7. JavaScript之判断用户登录信息
  8. 毕业设计(五)---spring学习笔记(3)之-dataSource,sessionFactory,hibernateTemplate,事务 的简单配置。...
  9. 客户端动态化系列之——URLRoute
  10. 今日,寒露。读王羲之与陶渊明的魏晋风流。 文/光剑
  11. 初学Linux的简单命令(一)
  12. Pr 视频效果:过渡、透视、通道
  13. EtherCAT总线伺服速度控制功能块(H5U PLC)
  14. 中医药天池大数据竞赛——中医文献问题生成挑战(三)
  15. Element表格序号问题
  16. 电脑开启wifi热点
  17. 分享两个线+标注的SLD样式
  18. 微信聊天软件测试用例设计,微信页面测试用例_20140819
  19. 带你读懂——频率响应与采样频率之间的关系
  20. 快来让你的网页色彩绚丽--linear-gradient与radial-gradient

热门文章

  1. 硬件工程师需要学习那些本领
  2. 转吕建伟 我们的管理:部门管理
  3. vcpkg安装msys2
  4. WorkNC轻松几步导入刀柄轮廓
  5. 10.Windchill -- 客制化生命周期状态和角色
  6. 隐私保护与数据利用的冲突,如何避免成为透明人
  7. 安装WIN7的系统后鼠标键盘动不了怎么回事????
  8. 小程序开发(一)| 简介
  9. 工作感悟——工作伙伴或者搭档(1)
  10. Pregel:一个大规模图计算系统