前言:首先先推荐一篇博客,关于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动态生成的。

<!DOCTYPE html>
<html>
<head>
<title>01.01 - WebGLRenderer - Skeleton</title>
<script src="../libs/three.js"></script>
<style> #canvas3d{
width:800px;
height:450px;
margin:100px auto;
}
</style>
</head>
<body>
<div id="canvas3d"></div>
</body>
</html>

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

<script>
var renderer; //渲染器
var scene;   //场景
var camera; //相机
var light;   //光源
var cube; //物体
</script>

 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:间隔的长度

 

three.js初探,立体几何入手(一)的更多相关文章

  1. Node.js初探之GET方式传输

    Node.js初探之GET方式传输 例子:form用GET方法向后台传东西 html文件: <form action="http://localhost:8080/aaa" ...

  2. vue.js初探

    前言 入手2016最火前端框架之一vue.js.大概从网上找了些资料看了下vue.js,从网上的资料来看只能惊叹其发展速度太快,让我意外的是其作者是华人的前提下作品这么受欢迎. 网上的博客和教程各种组 ...

  3. Node.js 初探

    概念 Node.js 是构建在Chrome javascript runtime之上的平台,能够很容易的构建快速的,可伸缩性的网络应用程序.Node.js使用事件驱动,非阻塞I/O 模式,这使它能够更 ...

  4. 后端视角下的前端框架之Vue.js初探

    背景 作为常年搞后端的自己来说,除了多年前学习的一点关于HTML的皮毛,对现在的前端技术栈可谓是一窍不通.但是因为最近在做的内部业务全链路监控系统,负责前端的同事做到一半去搞别的项目了,为了把项目落地 ...

  5. Node.js系列之node.js初探

    官方介绍:Node.js is a platform built on Chrome's JavaScript runtime for easily building fast, scalable n ...

  6. [转]backbone.js 初探

    本文转自:http://weakfi.iteye.com/blog/1391990 什么是backbone backbone不是脊椎骨,而是帮助开发重量级的javascript应用的框架. 主要提供了 ...

  7. angular.js初探

    2015年7月27日 22:26:35 星期一 用在我论坛里的小栗子: 先列出来一级回帖, 点击帖子前边的"查看回复"按钮无刷新的去请求该帖子的所有回复 首先要引用js文件, 我这 ...

  8. Parallel.js初探续集

    @author mrbean 例子均来源于github parallel.js 昨天写的第一篇今天一看居然有50+的阅读量了,感觉很激动啊,但是也有点害怕毕竟这只是自己笔记性质的一点东西,所以赶紧拿起 ...

  9. Parallel.js初探

    今天闲着看了一下Parallel.js.这个库暂时貌似还没有什么中文的介绍(可能暂时用的人都不多吧).所以就只能上github找它得源码和介绍看看了.貌似它的代码也不多,以后可以深入研究一下. 先简单 ...

随机推荐

  1. webpack4.0.1安装问题和webpack.config.js的配置变化

    The CLI moved into a separate package: webpack-cli. Please install 'webpack-cli' in addition to webp ...

  2. studio-3t 配置文件位置

    换电脑了,原来的studio-3t的配置 在 C:\Users\用户名\.3T. 将这个目录下的所有文件拷贝到 新电脑里的 相同文件夹,覆盖即可

  3. 【Mac】-NO.161.Mac.1 -【MacOS Error running 'Tomcat 8.5.371': Cannot run program Permission denied】

    Style:Mac Series:Java Since:2018-09-10 End:2018-09-10 Total Hours:1 Degree Of Diffculty:5 Degree Of ...

  4. PyCharm更换sublime类似主题

    1. 下载jar主题包 下载地址:https://github.com/spasserby/PyCharm-monokai 2.导入pycharm设置 导入方法:file-->Import Se ...

  5. jenkins centos slave起不来报错The SSH key presented by the remote host does not match the key saved in the Known Hosts file against this host. Connections to this host will be denied until the two keys mat

    场景:我的centos-204是一台centos的机器,本来用https://www.cnblogs.com/zndxall/p/8297356.html 的centos slave方式搭建ok的,一 ...

  6. ESP8266 RTOS SDK烧写环境构建

    简介 esptool是一个Python软件程序,适用于ESP8266等一系列芯片的烧写,灵活高效. 环境构建 在官网下载安装最新2.7版python (linux和os x一般会自带python2.7 ...

  7. 训练集(train set),验证集(validation set)和测试集(test set)

    把数据集分为三部分,分别为:训练集(train set),验证集(validation set)和测试集(test set). 具体比例有各种说法.待补充 测试集是为了测模型泛化能力,不能在训练的时候 ...

  8. 并发编程实战1-chap1-2-斗者6星

    一.线程安全性 1.线程安全关注点:对共享的和可变的状态的访问 2.JAVA同步机制:synchronized.volatile.显示锁.原子变量 3.无状态对象一定是线程安全的:不包含任何域,也不包 ...

  9. ShowWindow 隐藏、显示、最大化、最小化窗口

    #include <Windows.h> #include <tchar.h> int WINAPI _tWinMain(HINSTANCE hInstance, HINSTA ...

  10. HTML5的优点与缺点?

    优点:a.网络标准统一.HTML5本身是由W3C推荐出来的. b.多设备.跨平台 c.即时更新,提高可用性和改进用户的友好体验: d.有几个新的标签,这将有助于开发人员定义重要的内容: e.可以给站点 ...