├── README.md
├── areaLight.html
├── basicTexture.html
├── card.html
├── dynamic.html
├── images
├── basicTexture.gif
├── bathroom-normal.jpg
├── bathroom.jpg
├── brick-wall.jpg
├── darker_wood.jpg
├── dmngp.gif
├── dynamic.gif
├── floor-wood.jpg
├── lineMaterial.gif
├── meshMaterial.gif
├── metal-floor-normal.jpg
├── metal-floor.jpg
├── metal-rust.jpg
├── negx.jpg
├── negy.jpg
├── negz.jpg
├── normalMap.gif
├── plaster-diffuse.jpg
├── plaster-normal.jpg
├── plaster.jpg
├── pointCloud.gif
├── posx.jpg
├── posy.jpg
├── posz.jpg
├── raindrop.png
├── rainyScene.gif
├── snowflake1.png
├── snowflake2.png
├── snowflake3.png
├── snowflake4.png
├── snowflake5.png
├── snowyScene.gif
├── stone-bump.jpg
├── stone.jpg
├── textGeometry.jpg
├── weave-bump.jpg
├── weave.jpg
└── wood-2.jpg
├── libs
├── CanvasRenderer.js
├── CopyShader.js
├── EffectComposer.js
├── FXAAShader.js
├── MaskPass.js
├── OrbitControls.js
├── Projector.js
├── RenderPass.js
├── ShaderDeferred.js
├── ShaderPass.js
├── WebGLDeferredRenderer.js
├── ammo.js
├── chroma.js
├── dat.gui.js
├── fonts
│ ├── bitstream_vera_sans_mono_roman.typeface.js
│ ├── helvetiker_bold.typeface.js
│ └── helvetiker_regular.typeface.js
├── physi.js
├── physijs_worker.js
├── stats.js
└── three.js
├── lineMaterial.html
├── meshMaterial.html
├── normalMap.html
├── pointCloud.html
├── rainyScene.html
├── snowyScene.html
└── textGeometry.html
/README.md:
--------------------------------------------------------------------------------
1 | # ThreejsLab
2 |
3 | 记录自己学习的一个过程。
4 |
5 | 所有项目均使用了2个开发环境用的测试辅助库:
6 | * stats.js性能监视器来监视3d性能,详见各个demo左上角(它的介绍在 )
7 | * GUI库( dat.gui.js ),详见各个demo右上角,用户可进行控制操作( )
8 |
9 | ## Demo:
10 | (所有demo页右上角有`GUI渲染控制器`,可通过调节它来控制页面的3d效果变化)
11 |
12 |
13 | 1、[平面光3d光源](http://imzouyang.com/project/threejs/areaLight.html)(该页面右上角各GUI参数可控制3d变化)
14 | * 该光源:属于复杂光源、使用它可以定义一个发光的矩形、此光源不再Three.js标准库中,而在它的扩展库中,它不能再使用渲染器WebGLRenderer对象了,而是使用渲染器WebGLDeferredRenderer,俗称延迟渲染器(使用此渲染器还需引入其他js,详见demo,才能使用延迟渲染器),该渲染器专门处理复杂光源。
15 |
16 |
17 | 2、[几何体及网格](http://imzouyang.com/project/threejs/meshMaterial.html)
18 | * 注释:Mesh几何体为groundGeom;通过MeshNormalMaterial作为几何体材质展示旋转色变(MeshNormalMaterial :通过计算法向颜色来决定每个面颜色的材质)。
19 | 
20 |
21 |
22 | 3、[gosper曲线](http://imzouyang.com/project/threejs/lineMaterial.html)
23 | * gosper(),该函数返回的是一个gosper曲线。wiki有相关介绍:( )
24 | 
25 |
26 |
27 | 4、[创建三维文本](http://imzouyang.com/project/threejs/textGeometry.html)
28 | * 实例化new THREE.TextGeometry(),并操作相关属性即可
29 | 
30 |
31 |
32 | 5、[创建粒子材质](http://imzouyang.com/project/threejs/pointCloud.html)
33 | * 实例化new THREE.ParticleBasicMaterial(),创建粒子材质,该材质有9个可控属性
34 | 
35 |
36 |
37 | 6、[创建下雨3d动画](http://imzouyang.com/project/threejs/rainyScene.html)
38 | * 使用ParticleBasicMaterial的map属性来加载外部图片;并使用 THREE.AdditiveBlending融合模式,此模式会在画新像素时,背景像素的颜色会被添加到新像素上
39 | 
40 |
41 |
42 | 7、[创建下雪3d动画](http://imzouyang.com/project/threejs/snowyScene.html)
43 | 
44 |
45 |
46 | 8、[基础材质应用](http://imzouyang.com/project/threejs/basicTexture.html)
47 | * 使用THREE.ImageUtils.loadTexture 来加载一个外部图片
48 | * threejs内有2种材质对光源产生反应:MeshLamberMaterial 和 MeshPhongMaterial,MeshPhongMaterial一般用于创建光亮表面
49 | 
50 |
51 |
52 | 9、[基础材质应用2](http://imzouyang.com/project/threejs/normalMap.html)
53 | * 使用THREE.UniformsUtils的clone方法
54 | * 创建立方体BoxGeometry
55 | 
56 |
57 |
58 | 10、[构建真实动态3d场景](http://imzouyang.com/project/threejs/dynamic.html)
59 | * 拖动(滚动)鼠标可360度查看全景,整个场景是由6张jpg图片够成。
60 | 
61 |
62 |
63 |
64 | # 以下是一些记录:
65 | 1、Three.js本质上是Webgl,如果你的浏览器不支持Webgl,那么肯定你就不能完整的运行Three.js。支持Webgl的浏览器很多,例如Chrome、FireFox、360安 全浏览器6.0等,而IE浏览器对Webgl标准的支持就不太好。
66 |
67 | 2、在Three.js中,要渲染物体到网页中,我们需要3个组件:场景(scene)、相机(camera)和渲染器(renderer)。有了这三样东西,才能将物体渲染到网页中去。
68 | ```javascript
69 | var scene = new THREE.Scene(); // 场景
70 |
71 | var camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);// 透视相机
72 |
73 | var renderer = new THREE.WebGLRenderer(); // 渲染器
74 |
75 | renderer.setSize(window.innerWidth, window.innerHeight); // 设置渲染器的大小为窗口的内宽度,也就是内容区的宽度
76 | document.body.appendChild(renderer.domElement);
77 | ```
78 |
79 | 3、场景与相机
80 | * 1)场景只有一种,用THREE.Scene来表示,通过new THREE.Scene();
81 | * 2)相机有2种,决定了场景中那个角度的景色会显示出来。
82 | * 透视投影相机:THREE.PerspectiveCamera
83 | * 正投影相机:THREE.OrthographicCamera ( left, right, top, bottom, near, far ) 里面的参数分别代表各个面与相机镜头中心点的垂直距离。
84 |
85 | 4、Threejs使用的是右手坐标系,这源于opengl默认情况下,也是右手坐标系。
86 |
87 | 5、和three.js紧密结合的动画引擎是Tween.js,可以在这里下载 https://github.com/sole
88 | ```
89 | 1)引入js
90 | 2)构建对象:
91 | function initTween()
92 | {
93 | new TWEEN.Tween( mesh.position)
94 | .to( { x: -400 }, 3000 ).repeat( Infinity ).start();
95 | }
96 | TWEEN.Tween的构造函数接受的是要改变属性的对象,这里传入的是mesh的位置。
97 | Tween的任何一个函数返回的都是自身,所以可以用串联的方式直接调用各个函数。
98 | to函数,接受两个参数:
99 | 第一个参数是一个集合,里面存放的键值对,键x表示mesh.position的x属性,值-400表示,动画结束的时候需要移动到的位置。
100 | 第二个参数,是完成动画需要的时间,这里是3000ms。
101 | repeat( Infinity )表示重复无穷次,也可以接受一个整形数值,例如5次。
102 | Start表示开始动画,默认情况下是匀速的将mesh.position.x移动到-400的位置。
103 | 3)渲染函数中执行:TWEEN.update();
104 | ```
105 |
106 | 6、Threejs中的各种光源:
107 | * 光源基类 THREE.Light ( hex )
108 | ```
109 | 参数hex,接受一个16进制的颜色值。例如要定义一种红色的光源,我们可以这样来定义:
110 | var redLight = new THREE.Light(0xFF0000);
111 | ```
112 | * 由基类派生出来的其他种类光源
113 |
114 | 7、环境光
115 | 是经过多次反射而来的光称为环境光,无法确定其最初的方向。环境光是一种无处不在的光。环境光源放出的光线被认为来自任何方向。因此,当你仅为场景指定环境光时,所有的物体无论法向量如何,都将表现为同样的明暗程度。 (这是因为,反射光可以从各个方向进入您的眼睛)
116 | 构造函数 : THREE.AmbientLight( hex )
117 | var light = new THREE.AmbientLight( 0xff0000 );
118 | scene.add( light );
119 |
120 | 8、聚光灯
121 | 构造:THREE.SpotLight( hex, intensity, distance, angle, exponent )
122 | 这种光源的光线从一个锥体中射出,在被照射的物体上产生聚光的效果。
123 | 使用这种光源需要指定光的射出方向以及锥体的顶角α。
124 |
125 |
126 | 9、方向光(平行光)
127 | * 它是一组没有衰减的平行的光线,类似太阳光的效果。
128 | * THREE.DirectionalLight = function ( hex, intensity )
129 |
130 | 10、点光源
131 | * 点光源的特点是发光部分为一个小圆面,近似一个点
132 | * 是理想化为质点的向四面八方发出光线的光源。点光源是抽象化了的物理概念,为了把物理问题的研究简单化。就像平时说的光滑平面,质点,无空气阻力一样,点光源在现实中也是不存在的,指的是从一个点向周围空间均匀发光的光源。
133 | * 点光源不会产生投影,原因是光源是朝所有方向发出,计算阴影对GPU来说,负担太重。
134 |
135 | ### 省略一大坨
136 | ```
137 | 更多详细笔记,如有需要的童鞋可以私信我邮箱
138 | ```
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
--------------------------------------------------------------------------------
/areaLight.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Area Light
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
203 |
204 |
--------------------------------------------------------------------------------
/basicTexture.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 基础textures
7 |
8 |
9 |
10 |
11 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
118 |
119 |
--------------------------------------------------------------------------------
/card.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 | Physijs
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
--------------------------------------------------------------------------------
/dynamic.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | dynamic
5 |
6 |
7 |
8 |
14 |
15 |
142 |
143 |
144 |
--------------------------------------------------------------------------------
/images/basicTexture.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/basicTexture.gif
--------------------------------------------------------------------------------
/images/bathroom-normal.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/bathroom-normal.jpg
--------------------------------------------------------------------------------
/images/bathroom.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/bathroom.jpg
--------------------------------------------------------------------------------
/images/brick-wall.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/brick-wall.jpg
--------------------------------------------------------------------------------
/images/darker_wood.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/darker_wood.jpg
--------------------------------------------------------------------------------
/images/dmngp.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/dmngp.gif
--------------------------------------------------------------------------------
/images/dynamic.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/dynamic.gif
--------------------------------------------------------------------------------
/images/floor-wood.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/floor-wood.jpg
--------------------------------------------------------------------------------
/images/lineMaterial.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/lineMaterial.gif
--------------------------------------------------------------------------------
/images/meshMaterial.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/meshMaterial.gif
--------------------------------------------------------------------------------
/images/metal-floor-normal.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/metal-floor-normal.jpg
--------------------------------------------------------------------------------
/images/metal-floor.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/metal-floor.jpg
--------------------------------------------------------------------------------
/images/metal-rust.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/metal-rust.jpg
--------------------------------------------------------------------------------
/images/negx.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/negx.jpg
--------------------------------------------------------------------------------
/images/negy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/negy.jpg
--------------------------------------------------------------------------------
/images/negz.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/negz.jpg
--------------------------------------------------------------------------------
/images/normalMap.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/normalMap.gif
--------------------------------------------------------------------------------
/images/plaster-diffuse.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/plaster-diffuse.jpg
--------------------------------------------------------------------------------
/images/plaster-normal.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/plaster-normal.jpg
--------------------------------------------------------------------------------
/images/plaster.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/plaster.jpg
--------------------------------------------------------------------------------
/images/pointCloud.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/pointCloud.gif
--------------------------------------------------------------------------------
/images/posx.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/posx.jpg
--------------------------------------------------------------------------------
/images/posy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/posy.jpg
--------------------------------------------------------------------------------
/images/posz.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/posz.jpg
--------------------------------------------------------------------------------
/images/raindrop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/raindrop.png
--------------------------------------------------------------------------------
/images/rainyScene.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/rainyScene.gif
--------------------------------------------------------------------------------
/images/snowflake1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/snowflake1.png
--------------------------------------------------------------------------------
/images/snowflake2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/snowflake2.png
--------------------------------------------------------------------------------
/images/snowflake3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/snowflake3.png
--------------------------------------------------------------------------------
/images/snowflake4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/snowflake4.png
--------------------------------------------------------------------------------
/images/snowflake5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/snowflake5.png
--------------------------------------------------------------------------------
/images/snowyScene.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/snowyScene.gif
--------------------------------------------------------------------------------
/images/stone-bump.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/stone-bump.jpg
--------------------------------------------------------------------------------
/images/stone.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/stone.jpg
--------------------------------------------------------------------------------
/images/textGeometry.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/textGeometry.jpg
--------------------------------------------------------------------------------
/images/weave-bump.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/weave-bump.jpg
--------------------------------------------------------------------------------
/images/weave.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/weave.jpg
--------------------------------------------------------------------------------
/images/wood-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouyang1230/ThreejsLab/b4c9ecf87f2695c201e72d3cc9af7ecf662ec499/images/wood-2.jpg
--------------------------------------------------------------------------------
/libs/CanvasRenderer.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author mrdoob / http://mrdoob.com/
3 | */
4 |
5 | THREE.SpriteCanvasMaterial = function ( parameters ) {
6 |
7 | THREE.Material.call( this );
8 |
9 | this.type = 'SpriteCanvasMaterial';
10 |
11 | this.color = new THREE.Color( 0xffffff );
12 | this.program = function ( context, color ) {};
13 |
14 | this.setValues( parameters );
15 |
16 | };
17 |
18 | THREE.SpriteCanvasMaterial.prototype = Object.create( THREE.Material.prototype );
19 |
20 | THREE.SpriteCanvasMaterial.prototype.clone = function () {
21 |
22 | var material = new THREE.SpriteCanvasMaterial();
23 |
24 | THREE.Material.prototype.clone.call( this, material );
25 |
26 | material.color.copy( this.color );
27 | material.program = this.program;
28 |
29 | return material;
30 |
31 | };
32 |
33 | //
34 |
35 | THREE.CanvasRenderer = function ( parameters ) {
36 |
37 | console.log( 'THREE.CanvasRenderer', THREE.REVISION );
38 |
39 | var smoothstep = THREE.Math.smoothstep;
40 |
41 | parameters = parameters || {};
42 |
43 | var _this = this,
44 | _renderData, _elements, _lights,
45 | _projector = new THREE.Projector(),
46 |
47 | _canvas = parameters.canvas !== undefined
48 | ? parameters.canvas
49 | : document.createElement( 'canvas' ),
50 |
51 | _canvasWidth = _canvas.width,
52 | _canvasHeight = _canvas.height,
53 | _canvasWidthHalf = Math.floor( _canvasWidth / 2 ),
54 | _canvasHeightHalf = Math.floor( _canvasHeight / 2 ),
55 |
56 | _viewportX = 0,
57 | _viewportY = 0,
58 | _viewportWidth = _canvasWidth,
59 | _viewportHeight = _canvasHeight,
60 |
61 | _context = _canvas.getContext( '2d', {
62 | alpha: parameters.alpha === true
63 | } ),
64 |
65 | _clearColor = new THREE.Color( 0x000000 ),
66 | _clearAlpha = 0,
67 |
68 | _contextGlobalAlpha = 1,
69 | _contextGlobalCompositeOperation = 0,
70 | _contextStrokeStyle = null,
71 | _contextFillStyle = null,
72 | _contextLineWidth = null,
73 | _contextLineCap = null,
74 | _contextLineJoin = null,
75 | _contextLineDash = [],
76 |
77 | _camera,
78 |
79 | _v1, _v2, _v3, _v4,
80 | _v5 = new THREE.RenderableVertex(),
81 | _v6 = new THREE.RenderableVertex(),
82 |
83 | _v1x, _v1y, _v2x, _v2y, _v3x, _v3y,
84 | _v4x, _v4y, _v5x, _v5y, _v6x, _v6y,
85 |
86 | _color = new THREE.Color(),
87 | _color1 = new THREE.Color(),
88 | _color2 = new THREE.Color(),
89 | _color3 = new THREE.Color(),
90 | _color4 = new THREE.Color(),
91 |
92 | _diffuseColor = new THREE.Color(),
93 | _emissiveColor = new THREE.Color(),
94 |
95 | _lightColor = new THREE.Color(),
96 |
97 | _patterns = {},
98 |
99 | _image, _uvs,
100 | _uv1x, _uv1y, _uv2x, _uv2y, _uv3x, _uv3y,
101 |
102 | _clipBox = new THREE.Box2(),
103 | _clearBox = new THREE.Box2(),
104 | _elemBox = new THREE.Box2(),
105 |
106 | _ambientLight = new THREE.Color(),
107 | _directionalLights = new THREE.Color(),
108 | _pointLights = new THREE.Color(),
109 |
110 | _vector3 = new THREE.Vector3(), // Needed for PointLight
111 | _centroid = new THREE.Vector3(),
112 | _normal = new THREE.Vector3(),
113 | _normalViewMatrix = new THREE.Matrix3();
114 |
115 | // dash+gap fallbacks for Firefox and everything else
116 |
117 | if ( _context.setLineDash === undefined ) {
118 |
119 | _context.setLineDash = function () {}
120 |
121 | }
122 |
123 | this.domElement = _canvas;
124 |
125 | this.devicePixelRatio = parameters.devicePixelRatio !== undefined
126 | ? parameters.devicePixelRatio
127 | : self.devicePixelRatio !== undefined
128 | ? self.devicePixelRatio
129 | : 1;
130 |
131 | this.autoClear = true;
132 | this.sortObjects = true;
133 | this.sortElements = true;
134 |
135 | this.info = {
136 |
137 | render: {
138 |
139 | vertices: 0,
140 | faces: 0
141 |
142 | }
143 |
144 | }
145 |
146 | // WebGLRenderer compatibility
147 |
148 | this.supportsVertexTextures = function () {};
149 | this.setFaceCulling = function () {};
150 |
151 | this.setSize = function ( width, height, updateStyle ) {
152 |
153 | _canvasWidth = width * this.devicePixelRatio;
154 | _canvasHeight = height * this.devicePixelRatio;
155 |
156 | _canvas.width = _canvasWidth;
157 | _canvas.height = _canvasHeight;
158 |
159 | _canvasWidthHalf = Math.floor( _canvasWidth / 2 );
160 | _canvasHeightHalf = Math.floor( _canvasHeight / 2 );
161 |
162 | if ( updateStyle !== false ) {
163 |
164 | _canvas.style.width = width + 'px';
165 | _canvas.style.height = height + 'px';
166 |
167 | }
168 |
169 | _clipBox.min.set( -_canvasWidthHalf, -_canvasHeightHalf ),
170 | _clipBox.max.set( _canvasWidthHalf, _canvasHeightHalf );
171 |
172 | _clearBox.min.set( - _canvasWidthHalf, - _canvasHeightHalf );
173 | _clearBox.max.set( _canvasWidthHalf, _canvasHeightHalf );
174 |
175 | _contextGlobalAlpha = 1;
176 | _contextGlobalCompositeOperation = 0;
177 | _contextStrokeStyle = null;
178 | _contextFillStyle = null;
179 | _contextLineWidth = null;
180 | _contextLineCap = null;
181 | _contextLineJoin = null;
182 |
183 | this.setViewport( 0, 0, width, height );
184 |
185 | };
186 |
187 | this.setViewport = function ( x, y, width, height ) {
188 |
189 | _viewportX = x * this.devicePixelRatio;
190 | _viewportY = y * this.devicePixelRatio;
191 |
192 | _viewportWidth = width * this.devicePixelRatio;
193 | _viewportHeight = height * this.devicePixelRatio;
194 |
195 | };
196 |
197 | this.setScissor = function () {};
198 | this.enableScissorTest = function () {};
199 |
200 | this.setClearColor = function ( color, alpha ) {
201 |
202 | _clearColor.set( color );
203 | _clearAlpha = alpha !== undefined ? alpha : 1;
204 |
205 | _clearBox.min.set( - _canvasWidthHalf, - _canvasHeightHalf );
206 | _clearBox.max.set( _canvasWidthHalf, _canvasHeightHalf );
207 |
208 | };
209 |
210 | this.setClearColorHex = function ( hex, alpha ) {
211 |
212 | console.warn( 'THREE.CanvasRenderer: .setClearColorHex() is being removed. Use .setClearColor() instead.' );
213 | this.setClearColor( hex, alpha );
214 |
215 | };
216 |
217 | this.getClearColor = function () {
218 |
219 | return _clearColor;
220 |
221 | };
222 |
223 | this.getClearAlpha = function () {
224 |
225 | return _clearAlpha;
226 |
227 | };
228 |
229 | this.getMaxAnisotropy = function () {
230 |
231 | return 0;
232 |
233 | };
234 |
235 | this.clear = function () {
236 |
237 | if ( _clearBox.empty() === false ) {
238 |
239 | _clearBox.intersect( _clipBox );
240 | _clearBox.expandByScalar( 2 );
241 |
242 | _clearBox.min.x = _clearBox.min.x + _canvasWidthHalf;
243 | _clearBox.min.y = - _clearBox.min.y + _canvasHeightHalf;
244 | _clearBox.max.x = _clearBox.max.x + _canvasWidthHalf;
245 | _clearBox.max.y = - _clearBox.max.y + _canvasHeightHalf;
246 |
247 | if ( _clearAlpha < 1 ) {
248 |
249 | _context.clearRect(
250 | _clearBox.min.x | 0,
251 | _clearBox.min.y | 0,
252 | ( _clearBox.max.x - _clearBox.min.x ) | 0,
253 | ( _clearBox.max.y - _clearBox.min.y ) | 0
254 | );
255 |
256 | }
257 |
258 | if ( _clearAlpha > 0 ) {
259 |
260 | setBlending( THREE.NormalBlending );
261 | setOpacity( 1 );
262 |
263 | setFillStyle( 'rgba(' + Math.floor( _clearColor.r * 255 ) + ',' + Math.floor( _clearColor.g * 255 ) + ',' + Math.floor( _clearColor.b * 255 ) + ',' + _clearAlpha + ')' );
264 |
265 | _context.fillRect(
266 | _clearBox.min.x | 0,
267 | _clearBox.min.y | 0,
268 | ( _clearBox.max.x - _clearBox.min.x ) | 0,
269 | ( _clearBox.max.y - _clearBox.min.y ) | 0
270 | );
271 |
272 | }
273 |
274 | _clearBox.makeEmpty();
275 |
276 | }
277 |
278 | };
279 |
280 | // compatibility
281 |
282 | this.clearColor = function () {};
283 | this.clearDepth = function () {};
284 | this.clearStencil = function () {};
285 |
286 | this.render = function ( scene, camera ) {
287 |
288 | if ( camera instanceof THREE.Camera === false ) {
289 |
290 | console.error( 'THREE.CanvasRenderer.render: camera is not an instance of THREE.Camera.' );
291 | return;
292 |
293 | }
294 |
295 | if ( this.autoClear === true ) this.clear();
296 |
297 | _this.info.render.vertices = 0;
298 | _this.info.render.faces = 0;
299 |
300 | _context.setTransform( _viewportWidth / _canvasWidth, 0, 0, - _viewportHeight / _canvasHeight, _viewportX, _canvasHeight - _viewportY );
301 | _context.translate( _canvasWidthHalf, _canvasHeightHalf );
302 |
303 | _renderData = _projector.projectScene( scene, camera, this.sortObjects, this.sortElements );
304 | _elements = _renderData.elements;
305 | _lights = _renderData.lights;
306 | _camera = camera;
307 |
308 | _normalViewMatrix.getNormalMatrix( camera.matrixWorldInverse );
309 |
310 | /* DEBUG
311 | setFillStyle( 'rgba( 0, 255, 255, 0.5 )' );
312 | _context.fillRect( _clipBox.min.x, _clipBox.min.y, _clipBox.max.x - _clipBox.min.x, _clipBox.max.y - _clipBox.min.y );
313 | */
314 |
315 | calculateLights();
316 |
317 | for ( var e = 0, el = _elements.length; e < el; e ++ ) {
318 |
319 | var element = _elements[ e ];
320 |
321 | var material = element.material;
322 |
323 | if ( material === undefined || material.opacity === 0 ) continue;
324 |
325 | _elemBox.makeEmpty();
326 |
327 | if ( element instanceof THREE.RenderableSprite ) {
328 |
329 | _v1 = element;
330 | _v1.x *= _canvasWidthHalf; _v1.y *= _canvasHeightHalf;
331 |
332 | renderSprite( _v1, element, material );
333 |
334 | } else if ( element instanceof THREE.RenderableLine ) {
335 |
336 | _v1 = element.v1; _v2 = element.v2;
337 |
338 | _v1.positionScreen.x *= _canvasWidthHalf; _v1.positionScreen.y *= _canvasHeightHalf;
339 | _v2.positionScreen.x *= _canvasWidthHalf; _v2.positionScreen.y *= _canvasHeightHalf;
340 |
341 | _elemBox.setFromPoints( [
342 | _v1.positionScreen,
343 | _v2.positionScreen
344 | ] );
345 |
346 | if ( _clipBox.isIntersectionBox( _elemBox ) === true ) {
347 |
348 | renderLine( _v1, _v2, element, material );
349 |
350 | }
351 |
352 | } else if ( element instanceof THREE.RenderableFace ) {
353 |
354 | _v1 = element.v1; _v2 = element.v2; _v3 = element.v3;
355 |
356 | if ( _v1.positionScreen.z < - 1 || _v1.positionScreen.z > 1 ) continue;
357 | if ( _v2.positionScreen.z < - 1 || _v2.positionScreen.z > 1 ) continue;
358 | if ( _v3.positionScreen.z < - 1 || _v3.positionScreen.z > 1 ) continue;
359 |
360 | _v1.positionScreen.x *= _canvasWidthHalf; _v1.positionScreen.y *= _canvasHeightHalf;
361 | _v2.positionScreen.x *= _canvasWidthHalf; _v2.positionScreen.y *= _canvasHeightHalf;
362 | _v3.positionScreen.x *= _canvasWidthHalf; _v3.positionScreen.y *= _canvasHeightHalf;
363 |
364 | if ( material.overdraw > 0 ) {
365 |
366 | expand( _v1.positionScreen, _v2.positionScreen, material.overdraw );
367 | expand( _v2.positionScreen, _v3.positionScreen, material.overdraw );
368 | expand( _v3.positionScreen, _v1.positionScreen, material.overdraw );
369 |
370 | }
371 |
372 | _elemBox.setFromPoints( [
373 | _v1.positionScreen,
374 | _v2.positionScreen,
375 | _v3.positionScreen
376 | ] );
377 |
378 | if ( _clipBox.isIntersectionBox( _elemBox ) === true ) {
379 |
380 | renderFace3( _v1, _v2, _v3, 0, 1, 2, element, material );
381 |
382 | }
383 |
384 | }
385 |
386 | /* DEBUG
387 | setLineWidth( 1 );
388 | setStrokeStyle( 'rgba( 0, 255, 0, 0.5 )' );
389 | _context.strokeRect( _elemBox.min.x, _elemBox.min.y, _elemBox.max.x - _elemBox.min.x, _elemBox.max.y - _elemBox.min.y );
390 | */
391 |
392 | _clearBox.union( _elemBox );
393 |
394 | }
395 |
396 | /* DEBUG
397 | setLineWidth( 1 );
398 | setStrokeStyle( 'rgba( 255, 0, 0, 0.5 )' );
399 | _context.strokeRect( _clearBox.min.x, _clearBox.min.y, _clearBox.max.x - _clearBox.min.x, _clearBox.max.y - _clearBox.min.y );
400 | */
401 |
402 | _context.setTransform( 1, 0, 0, 1, 0, 0 );
403 |
404 | };
405 |
406 | //
407 |
408 | function calculateLights() {
409 |
410 | _ambientLight.setRGB( 0, 0, 0 );
411 | _directionalLights.setRGB( 0, 0, 0 );
412 | _pointLights.setRGB( 0, 0, 0 );
413 |
414 | for ( var l = 0, ll = _lights.length; l < ll; l ++ ) {
415 |
416 | var light = _lights[ l ];
417 | var lightColor = light.color;
418 |
419 | if ( light instanceof THREE.AmbientLight ) {
420 |
421 | _ambientLight.add( lightColor );
422 |
423 | } else if ( light instanceof THREE.DirectionalLight ) {
424 |
425 | // for sprites
426 |
427 | _directionalLights.add( lightColor );
428 |
429 | } else if ( light instanceof THREE.PointLight ) {
430 |
431 | // for sprites
432 |
433 | _pointLights.add( lightColor );
434 |
435 | }
436 |
437 | }
438 |
439 | }
440 |
441 | function calculateLight( position, normal, color ) {
442 |
443 | for ( var l = 0, ll = _lights.length; l < ll; l ++ ) {
444 |
445 | var light = _lights[ l ];
446 |
447 | _lightColor.copy( light.color );
448 |
449 | if ( light instanceof THREE.DirectionalLight ) {
450 |
451 | var lightPosition = _vector3.setFromMatrixPosition( light.matrixWorld ).normalize();
452 |
453 | var amount = normal.dot( lightPosition );
454 |
455 | if ( amount <= 0 ) continue;
456 |
457 | amount *= light.intensity;
458 |
459 | color.add( _lightColor.multiplyScalar( amount ) );
460 |
461 | } else if ( light instanceof THREE.PointLight ) {
462 |
463 | var lightPosition = _vector3.setFromMatrixPosition( light.matrixWorld );
464 |
465 | var amount = normal.dot( _vector3.subVectors( lightPosition, position ).normalize() );
466 |
467 | if ( amount <= 0 ) continue;
468 |
469 | amount *= light.distance == 0 ? 1 : 1 - Math.min( position.distanceTo( lightPosition ) / light.distance, 1 );
470 |
471 | if ( amount == 0 ) continue;
472 |
473 | amount *= light.intensity;
474 |
475 | color.add( _lightColor.multiplyScalar( amount ) );
476 |
477 | }
478 |
479 | }
480 |
481 | }
482 |
483 | function renderSprite( v1, element, material ) {
484 |
485 | setOpacity( material.opacity );
486 | setBlending( material.blending );
487 |
488 | var scaleX = element.scale.x * _canvasWidthHalf;
489 | var scaleY = element.scale.y * _canvasHeightHalf;
490 |
491 | var dist = 0.5 * Math.sqrt( scaleX * scaleX + scaleY * scaleY ); // allow for rotated sprite
492 | _elemBox.min.set( v1.x - dist, v1.y - dist );
493 | _elemBox.max.set( v1.x + dist, v1.y + dist );
494 |
495 | if ( material instanceof THREE.SpriteMaterial ) {
496 |
497 | var texture = material.map;
498 |
499 | if ( texture !== null && texture.image !== undefined ) {
500 |
501 | if ( texture.hasEventListener( 'update', onTextureUpdate ) === false ) {
502 |
503 | if ( texture.image.width > 0 ) {
504 |
505 | textureToPattern( texture );
506 |
507 | }
508 |
509 | texture.addEventListener( 'update', onTextureUpdate );
510 |
511 | }
512 |
513 | var pattern = _patterns[ texture.id ];
514 |
515 | if ( pattern !== undefined ) {
516 |
517 | setFillStyle( pattern );
518 |
519 | } else {
520 |
521 | setFillStyle( 'rgba( 0, 0, 0, 1 )' );
522 |
523 | }
524 |
525 | //
526 |
527 | var bitmap = texture.image;
528 |
529 | var ox = bitmap.width * texture.offset.x;
530 | var oy = bitmap.height * texture.offset.y;
531 |
532 | var sx = bitmap.width * texture.repeat.x;
533 | var sy = bitmap.height * texture.repeat.y;
534 |
535 | var cx = scaleX / sx;
536 | var cy = scaleY / sy;
537 |
538 | _context.save();
539 | _context.translate( v1.x, v1.y );
540 | if ( material.rotation !== 0 ) _context.rotate( material.rotation );
541 | _context.translate( - scaleX / 2, - scaleY / 2 );
542 | _context.scale( cx, cy );
543 | _context.translate( - ox, - oy );
544 | _context.fillRect( ox, oy, sx, sy );
545 | _context.restore();
546 |
547 | } else {
548 |
549 | // no texture
550 |
551 | setFillStyle( material.color.getStyle() );
552 |
553 | _context.save();
554 | _context.translate( v1.x, v1.y );
555 | if ( material.rotation !== 0 ) _context.rotate( material.rotation );
556 | _context.scale( scaleX, - scaleY );
557 | _context.fillRect( - 0.5, - 0.5, 1, 1 );
558 | _context.restore();
559 |
560 | }
561 |
562 | } else if ( material instanceof THREE.SpriteCanvasMaterial ) {
563 |
564 | setStrokeStyle( material.color.getStyle() );
565 | setFillStyle( material.color.getStyle() );
566 |
567 | _context.save();
568 | _context.translate( v1.x, v1.y );
569 | if ( material.rotation !== 0 ) _context.rotate( material.rotation );
570 | _context.scale( scaleX, scaleY );
571 |
572 | material.program( _context );
573 |
574 | _context.restore();
575 |
576 | }
577 |
578 | /* DEBUG
579 | setStrokeStyle( 'rgb(255,255,0)' );
580 | _context.beginPath();
581 | _context.moveTo( v1.x - 10, v1.y );
582 | _context.lineTo( v1.x + 10, v1.y );
583 | _context.moveTo( v1.x, v1.y - 10 );
584 | _context.lineTo( v1.x, v1.y + 10 );
585 | _context.stroke();
586 | */
587 |
588 | }
589 |
590 | function renderLine( v1, v2, element, material ) {
591 |
592 | setOpacity( material.opacity );
593 | setBlending( material.blending );
594 |
595 | _context.beginPath();
596 | _context.moveTo( v1.positionScreen.x, v1.positionScreen.y );
597 | _context.lineTo( v2.positionScreen.x, v2.positionScreen.y );
598 |
599 | if ( material instanceof THREE.LineBasicMaterial ) {
600 |
601 | setLineWidth( material.linewidth );
602 | setLineCap( material.linecap );
603 | setLineJoin( material.linejoin );
604 |
605 | if ( material.vertexColors !== THREE.VertexColors ) {
606 |
607 | setStrokeStyle( material.color.getStyle() );
608 |
609 | } else {
610 |
611 | var colorStyle1 = element.vertexColors[ 0 ].getStyle();
612 | var colorStyle2 = element.vertexColors[ 1 ].getStyle();
613 |
614 | if ( colorStyle1 === colorStyle2 ) {
615 |
616 | setStrokeStyle( colorStyle1 );
617 |
618 | } else {
619 |
620 | try {
621 |
622 | var grad = _context.createLinearGradient(
623 | v1.positionScreen.x,
624 | v1.positionScreen.y,
625 | v2.positionScreen.x,
626 | v2.positionScreen.y
627 | );
628 | grad.addColorStop( 0, colorStyle1 );
629 | grad.addColorStop( 1, colorStyle2 );
630 |
631 | } catch ( exception ) {
632 |
633 | grad = colorStyle1;
634 |
635 | }
636 |
637 | setStrokeStyle( grad );
638 |
639 | }
640 |
641 | }
642 |
643 | _context.stroke();
644 | _elemBox.expandByScalar( material.linewidth * 2 );
645 |
646 | } else if ( material instanceof THREE.LineDashedMaterial ) {
647 |
648 | setLineWidth( material.linewidth );
649 | setLineCap( material.linecap );
650 | setLineJoin( material.linejoin );
651 | setStrokeStyle( material.color.getStyle() );
652 | setLineDash( [ material.dashSize, material.gapSize ] );
653 |
654 | _context.stroke();
655 |
656 | _elemBox.expandByScalar( material.linewidth * 2 );
657 |
658 | setLineDash( [] );
659 |
660 | }
661 |
662 | }
663 |
664 | function renderFace3( v1, v2, v3, uv1, uv2, uv3, element, material ) {
665 |
666 | _this.info.render.vertices += 3;
667 | _this.info.render.faces ++;
668 |
669 | setOpacity( material.opacity );
670 | setBlending( material.blending );
671 |
672 | _v1x = v1.positionScreen.x; _v1y = v1.positionScreen.y;
673 | _v2x = v2.positionScreen.x; _v2y = v2.positionScreen.y;
674 | _v3x = v3.positionScreen.x; _v3y = v3.positionScreen.y;
675 |
676 | drawTriangle( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y );
677 |
678 | if ( ( material instanceof THREE.MeshLambertMaterial || material instanceof THREE.MeshPhongMaterial ) && material.map === null ) {
679 |
680 | _diffuseColor.copy( material.color );
681 | _emissiveColor.copy( material.emissive );
682 |
683 | if ( material.vertexColors === THREE.FaceColors ) {
684 |
685 | _diffuseColor.multiply( element.color );
686 |
687 | }
688 |
689 | _color.copy( _ambientLight );
690 |
691 | _centroid.copy( v1.positionWorld ).add( v2.positionWorld ).add( v3.positionWorld ).divideScalar( 3 );
692 |
693 | calculateLight( _centroid, element.normalModel, _color );
694 |
695 | _color.multiply( _diffuseColor ).add( _emissiveColor );
696 |
697 | material.wireframe === true
698 | ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin )
699 | : fillPath( _color );
700 |
701 | } else if ( material instanceof THREE.MeshBasicMaterial ||
702 | material instanceof THREE.MeshLambertMaterial ||
703 | material instanceof THREE.MeshPhongMaterial ) {
704 |
705 | if ( material.map !== null ) {
706 |
707 | if ( material.map.mapping instanceof THREE.UVMapping ) {
708 |
709 | _uvs = element.uvs;
710 | patternPath( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _uvs[ uv1 ].x, _uvs[ uv1 ].y, _uvs[ uv2 ].x, _uvs[ uv2 ].y, _uvs[ uv3 ].x, _uvs[ uv3 ].y, material.map );
711 |
712 | }
713 |
714 | } else if ( material.envMap !== null ) {
715 |
716 | if ( material.envMap.mapping instanceof THREE.SphericalReflectionMapping ) {
717 |
718 | _normal.copy( element.vertexNormalsModel[ uv1 ] ).applyMatrix3( _normalViewMatrix );
719 | _uv1x = 0.5 * _normal.x + 0.5;
720 | _uv1y = 0.5 * _normal.y + 0.5;
721 |
722 | _normal.copy( element.vertexNormalsModel[ uv2 ] ).applyMatrix3( _normalViewMatrix );
723 | _uv2x = 0.5 * _normal.x + 0.5;
724 | _uv2y = 0.5 * _normal.y + 0.5;
725 |
726 | _normal.copy( element.vertexNormalsModel[ uv3 ] ).applyMatrix3( _normalViewMatrix );
727 | _uv3x = 0.5 * _normal.x + 0.5;
728 | _uv3y = 0.5 * _normal.y + 0.5;
729 |
730 | patternPath( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _uv1x, _uv1y, _uv2x, _uv2y, _uv3x, _uv3y, material.envMap );
731 |
732 | } else if ( material.envMap.mapping instanceof THREE.SphericalRefractionMapping ) {
733 |
734 | _normal.copy( element.vertexNormalsModel[ uv1 ] ).applyMatrix3( _normalViewMatrix );
735 | _uv1x = - 0.5 * _normal.x + 0.5;
736 | _uv1y = - 0.5 * _normal.y + 0.5;
737 |
738 | _normal.copy( element.vertexNormalsModel[ uv2 ] ).applyMatrix3( _normalViewMatrix );
739 | _uv2x = - 0.5 * _normal.x + 0.5;
740 | _uv2y = - 0.5 * _normal.y + 0.5;
741 |
742 | _normal.copy( element.vertexNormalsModel[ uv3 ] ).applyMatrix3( _normalViewMatrix );
743 | _uv3x = - 0.5 * _normal.x + 0.5;
744 | _uv3y = - 0.5 * _normal.y + 0.5;
745 |
746 | patternPath( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _uv1x, _uv1y, _uv2x, _uv2y, _uv3x, _uv3y, material.envMap );
747 |
748 | }
749 |
750 |
751 | } else {
752 |
753 | _color.copy( material.color );
754 |
755 | if ( material.vertexColors === THREE.FaceColors ) {
756 |
757 | _color.multiply( element.color );
758 |
759 | }
760 |
761 | material.wireframe === true
762 | ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin )
763 | : fillPath( _color );
764 |
765 | }
766 |
767 | } else if ( material instanceof THREE.MeshDepthMaterial ) {
768 |
769 | _color.r = _color.g = _color.b = 1 - smoothstep( v1.positionScreen.z * v1.positionScreen.w, _camera.near, _camera.far );
770 |
771 | material.wireframe === true
772 | ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin )
773 | : fillPath( _color );
774 |
775 | } else if ( material instanceof THREE.MeshNormalMaterial ) {
776 |
777 | _normal.copy( element.normalModel ).applyMatrix3( _normalViewMatrix );
778 |
779 | _color.setRGB( _normal.x, _normal.y, _normal.z ).multiplyScalar( 0.5 ).addScalar( 0.5 );
780 |
781 | material.wireframe === true
782 | ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin )
783 | : fillPath( _color );
784 |
785 | } else {
786 |
787 | _color.setRGB( 1, 1, 1 );
788 |
789 | material.wireframe === true
790 | ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin )
791 | : fillPath( _color );
792 |
793 | }
794 |
795 | }
796 |
797 | //
798 |
799 | function drawTriangle( x0, y0, x1, y1, x2, y2 ) {
800 |
801 | _context.beginPath();
802 | _context.moveTo( x0, y0 );
803 | _context.lineTo( x1, y1 );
804 | _context.lineTo( x2, y2 );
805 | _context.closePath();
806 |
807 | }
808 |
809 | function strokePath( color, linewidth, linecap, linejoin ) {
810 |
811 | setLineWidth( linewidth );
812 | setLineCap( linecap );
813 | setLineJoin( linejoin );
814 | setStrokeStyle( color.getStyle() );
815 |
816 | _context.stroke();
817 |
818 | _elemBox.expandByScalar( linewidth * 2 );
819 |
820 | }
821 |
822 | function fillPath( color ) {
823 |
824 | setFillStyle( color.getStyle() );
825 | _context.fill();
826 |
827 | }
828 |
829 | function onTextureUpdate ( event ) {
830 |
831 | textureToPattern( event.target );
832 |
833 | }
834 |
835 | function textureToPattern( texture ) {
836 |
837 | if ( texture instanceof THREE.CompressedTexture ) return;
838 |
839 | var repeatX = texture.wrapS === THREE.RepeatWrapping;
840 | var repeatY = texture.wrapT === THREE.RepeatWrapping;
841 |
842 | var image = texture.image;
843 |
844 | var canvas = document.createElement( 'canvas' );
845 | canvas.width = image.width;
846 | canvas.height = image.height;
847 |
848 | var context = canvas.getContext( '2d' );
849 | context.setTransform( 1, 0, 0, - 1, 0, image.height );
850 | context.drawImage( image, 0, 0 );
851 |
852 | _patterns[ texture.id ] = _context.createPattern(
853 | canvas, repeatX === true && repeatY === true
854 | ? 'repeat'
855 | : repeatX === true && repeatY === false
856 | ? 'repeat-x'
857 | : repeatX === false && repeatY === true
858 | ? 'repeat-y'
859 | : 'no-repeat'
860 | );
861 |
862 | }
863 |
864 | function patternPath( x0, y0, x1, y1, x2, y2, u0, v0, u1, v1, u2, v2, texture ) {
865 |
866 | if ( texture instanceof THREE.DataTexture ) return;
867 |
868 | if ( texture.hasEventListener( 'update', onTextureUpdate ) === false ) {
869 |
870 | if ( texture.image !== undefined && texture.image.width > 0 ) {
871 |
872 | textureToPattern( texture );
873 |
874 | }
875 |
876 | texture.addEventListener( 'update', onTextureUpdate );
877 |
878 | }
879 |
880 | var pattern = _patterns[ texture.id ];
881 |
882 | if ( pattern !== undefined ) {
883 |
884 | setFillStyle( pattern );
885 |
886 | } else {
887 |
888 | setFillStyle( 'rgba(0,0,0,1)' );
889 | _context.fill();
890 |
891 | return;
892 |
893 | }
894 |
895 | // http://extremelysatisfactorytotalitarianism.com/blog/?p=2120
896 |
897 | var a, b, c, d, e, f, det, idet,
898 | offsetX = texture.offset.x / texture.repeat.x,
899 | offsetY = texture.offset.y / texture.repeat.y,
900 | width = texture.image.width * texture.repeat.x,
901 | height = texture.image.height * texture.repeat.y;
902 |
903 | u0 = ( u0 + offsetX ) * width;
904 | v0 = ( v0 + offsetY ) * height;
905 |
906 | u1 = ( u1 + offsetX ) * width;
907 | v1 = ( v1 + offsetY ) * height;
908 |
909 | u2 = ( u2 + offsetX ) * width;
910 | v2 = ( v2 + offsetY ) * height;
911 |
912 | x1 -= x0; y1 -= y0;
913 | x2 -= x0; y2 -= y0;
914 |
915 | u1 -= u0; v1 -= v0;
916 | u2 -= u0; v2 -= v0;
917 |
918 | det = u1 * v2 - u2 * v1;
919 |
920 | if ( det === 0 ) return;
921 |
922 | idet = 1 / det;
923 |
924 | a = ( v2 * x1 - v1 * x2 ) * idet;
925 | b = ( v2 * y1 - v1 * y2 ) * idet;
926 | c = ( u1 * x2 - u2 * x1 ) * idet;
927 | d = ( u1 * y2 - u2 * y1 ) * idet;
928 |
929 | e = x0 - a * u0 - c * v0;
930 | f = y0 - b * u0 - d * v0;
931 |
932 | _context.save();
933 | _context.transform( a, b, c, d, e, f );
934 | _context.fill();
935 | _context.restore();
936 |
937 | }
938 |
939 | function clipImage( x0, y0, x1, y1, x2, y2, u0, v0, u1, v1, u2, v2, image ) {
940 |
941 | // http://extremelysatisfactorytotalitarianism.com/blog/?p=2120
942 |
943 | var a, b, c, d, e, f, det, idet,
944 | width = image.width - 1,
945 | height = image.height - 1;
946 |
947 | u0 *= width; v0 *= height;
948 | u1 *= width; v1 *= height;
949 | u2 *= width; v2 *= height;
950 |
951 | x1 -= x0; y1 -= y0;
952 | x2 -= x0; y2 -= y0;
953 |
954 | u1 -= u0; v1 -= v0;
955 | u2 -= u0; v2 -= v0;
956 |
957 | det = u1 * v2 - u2 * v1;
958 |
959 | idet = 1 / det;
960 |
961 | a = ( v2 * x1 - v1 * x2 ) * idet;
962 | b = ( v2 * y1 - v1 * y2 ) * idet;
963 | c = ( u1 * x2 - u2 * x1 ) * idet;
964 | d = ( u1 * y2 - u2 * y1 ) * idet;
965 |
966 | e = x0 - a * u0 - c * v0;
967 | f = y0 - b * u0 - d * v0;
968 |
969 | _context.save();
970 | _context.transform( a, b, c, d, e, f );
971 | _context.clip();
972 | _context.drawImage( image, 0, 0 );
973 | _context.restore();
974 |
975 | }
976 |
977 | // Hide anti-alias gaps
978 |
979 | function expand( v1, v2, pixels ) {
980 |
981 | var x = v2.x - v1.x, y = v2.y - v1.y,
982 | det = x * x + y * y, idet;
983 |
984 | if ( det === 0 ) return;
985 |
986 | idet = pixels / Math.sqrt( det );
987 |
988 | x *= idet; y *= idet;
989 |
990 | v2.x += x; v2.y += y;
991 | v1.x -= x; v1.y -= y;
992 |
993 | }
994 |
995 | // Context cached methods.
996 |
997 | function setOpacity( value ) {
998 |
999 | if ( _contextGlobalAlpha !== value ) {
1000 |
1001 | _context.globalAlpha = value;
1002 | _contextGlobalAlpha = value;
1003 |
1004 | }
1005 |
1006 | }
1007 |
1008 | function setBlending( value ) {
1009 |
1010 | if ( _contextGlobalCompositeOperation !== value ) {
1011 |
1012 | if ( value === THREE.NormalBlending ) {
1013 |
1014 | _context.globalCompositeOperation = 'source-over';
1015 |
1016 | } else if ( value === THREE.AdditiveBlending ) {
1017 |
1018 | _context.globalCompositeOperation = 'lighter';
1019 |
1020 | } else if ( value === THREE.SubtractiveBlending ) {
1021 |
1022 | _context.globalCompositeOperation = 'darker';
1023 |
1024 | }
1025 |
1026 | _contextGlobalCompositeOperation = value;
1027 |
1028 | }
1029 |
1030 | }
1031 |
1032 | function setLineWidth( value ) {
1033 |
1034 | if ( _contextLineWidth !== value ) {
1035 |
1036 | _context.lineWidth = value;
1037 | _contextLineWidth = value;
1038 |
1039 | }
1040 |
1041 | }
1042 |
1043 | function setLineCap( value ) {
1044 |
1045 | // "butt", "round", "square"
1046 |
1047 | if ( _contextLineCap !== value ) {
1048 |
1049 | _context.lineCap = value;
1050 | _contextLineCap = value;
1051 |
1052 | }
1053 |
1054 | }
1055 |
1056 | function setLineJoin( value ) {
1057 |
1058 | // "round", "bevel", "miter"
1059 |
1060 | if ( _contextLineJoin !== value ) {
1061 |
1062 | _context.lineJoin = value;
1063 | _contextLineJoin = value;
1064 |
1065 | }
1066 |
1067 | }
1068 |
1069 | function setStrokeStyle( value ) {
1070 |
1071 | if ( _contextStrokeStyle !== value ) {
1072 |
1073 | _context.strokeStyle = value;
1074 | _contextStrokeStyle = value;
1075 |
1076 | }
1077 |
1078 | }
1079 |
1080 | function setFillStyle( value ) {
1081 |
1082 | if ( _contextFillStyle !== value ) {
1083 |
1084 | _context.fillStyle = value;
1085 | _contextFillStyle = value;
1086 |
1087 | }
1088 |
1089 | }
1090 |
1091 | function setLineDash( value ) {
1092 |
1093 | if ( _contextLineDash.length !== value.length ) {
1094 |
1095 | _context.setLineDash( value );
1096 | _contextLineDash = value;
1097 |
1098 | }
1099 |
1100 | }
1101 |
1102 | };
1103 |
--------------------------------------------------------------------------------
/libs/CopyShader.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author alteredq / http://alteredqualia.com/
3 | *
4 | * Full-screen textured quad shader
5 | */
6 |
7 | THREE.CopyShader = {
8 |
9 | uniforms: {
10 |
11 | "tDiffuse": { type: "t", value: null },
12 | "opacity": { type: "f", value: 1.0 }
13 |
14 | },
15 |
16 | vertexShader: [
17 |
18 | "varying vec2 vUv;",
19 |
20 | "void main() {",
21 |
22 | "vUv = uv;",
23 | "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
24 |
25 | "}"
26 |
27 | ].join("\n"),
28 |
29 | fragmentShader: [
30 |
31 | "uniform float opacity;",
32 |
33 | "uniform sampler2D tDiffuse;",
34 |
35 | "varying vec2 vUv;",
36 |
37 | "void main() {",
38 |
39 | "vec4 texel = texture2D( tDiffuse, vUv );",
40 | "gl_FragColor = opacity * texel;",
41 |
42 | "}"
43 |
44 | ].join("\n")
45 |
46 | };
47 |
--------------------------------------------------------------------------------
/libs/EffectComposer.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author alteredq / http://alteredqualia.com/
3 | */
4 |
5 | THREE.EffectComposer = function ( renderer, renderTarget ) {
6 |
7 | this.renderer = renderer;
8 |
9 | if ( renderTarget === undefined ) {
10 |
11 | var width = window.innerWidth || 1;
12 | var height = window.innerHeight || 1;
13 | var parameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat, stencilBuffer: false };
14 |
15 | renderTarget = new THREE.WebGLRenderTarget( width, height, parameters );
16 |
17 | }
18 |
19 | this.renderTarget1 = renderTarget;
20 | this.renderTarget2 = renderTarget.clone();
21 |
22 | this.writeBuffer = this.renderTarget1;
23 | this.readBuffer = this.renderTarget2;
24 |
25 | this.passes = [];
26 |
27 | if ( THREE.CopyShader === undefined )
28 | console.error( "THREE.EffectComposer relies on THREE.CopyShader" );
29 |
30 | this.copyPass = new THREE.ShaderPass( THREE.CopyShader );
31 |
32 | };
33 |
34 | THREE.EffectComposer.prototype = {
35 |
36 | swapBuffers: function() {
37 |
38 | var tmp = this.readBuffer;
39 | this.readBuffer = this.writeBuffer;
40 | this.writeBuffer = tmp;
41 |
42 | },
43 |
44 | addPass: function ( pass ) {
45 |
46 | this.passes.push( pass );
47 |
48 | },
49 |
50 | insertPass: function ( pass, index ) {
51 |
52 | this.passes.splice( index, 0, pass );
53 |
54 | },
55 |
56 | render: function ( delta ) {
57 |
58 | this.writeBuffer = this.renderTarget1;
59 | this.readBuffer = this.renderTarget2;
60 |
61 | var maskActive = false;
62 |
63 | var pass, i, il = this.passes.length;
64 |
65 | for ( i = 0; i < il; i ++ ) {
66 |
67 | pass = this.passes[ i ];
68 |
69 | if ( !pass.enabled ) continue;
70 |
71 | pass.render( this.renderer, this.writeBuffer, this.readBuffer, delta, maskActive );
72 |
73 | if ( pass.needsSwap ) {
74 |
75 | if ( maskActive ) {
76 |
77 | var context = this.renderer.context;
78 |
79 | context.stencilFunc( context.NOTEQUAL, 1, 0xffffffff );
80 |
81 | this.copyPass.render( this.renderer, this.writeBuffer, this.readBuffer, delta );
82 |
83 | context.stencilFunc( context.EQUAL, 1, 0xffffffff );
84 |
85 | }
86 |
87 | this.swapBuffers();
88 |
89 | }
90 |
91 | if ( pass instanceof THREE.MaskPass ) {
92 |
93 | maskActive = true;
94 |
95 | } else if ( pass instanceof THREE.ClearMaskPass ) {
96 |
97 | maskActive = false;
98 |
99 | }
100 |
101 | }
102 |
103 | },
104 |
105 | reset: function ( renderTarget ) {
106 |
107 | if ( renderTarget === undefined ) {
108 |
109 | renderTarget = this.renderTarget1.clone();
110 |
111 | renderTarget.width = window.innerWidth;
112 | renderTarget.height = window.innerHeight;
113 |
114 | }
115 |
116 | this.renderTarget1 = renderTarget;
117 | this.renderTarget2 = renderTarget.clone();
118 |
119 | this.writeBuffer = this.renderTarget1;
120 | this.readBuffer = this.renderTarget2;
121 |
122 | },
123 |
124 | setSize: function ( width, height ) {
125 |
126 | var renderTarget = this.renderTarget1.clone();
127 |
128 | renderTarget.width = width;
129 | renderTarget.height = height;
130 |
131 | this.reset( renderTarget );
132 |
133 | }
134 |
135 | };
136 |
137 | // shared ortho camera
138 |
139 | THREE.EffectComposer.camera = new THREE.OrthographicCamera( -1, 1, 1, -1, 0, 1 );
140 |
141 | THREE.EffectComposer.quad = new THREE.Mesh( new THREE.PlaneGeometry( 2, 2 ), null );
142 |
143 | THREE.EffectComposer.scene = new THREE.Scene();
144 | THREE.EffectComposer.scene.add( THREE.EffectComposer.quad );
145 |
--------------------------------------------------------------------------------
/libs/FXAAShader.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author alteredq / http://alteredqualia.com/
3 | * @author davidedc / http://www.sketchpatch.net/
4 | *
5 | * NVIDIA FXAA by Timothy Lottes
6 | * http://timothylottes.blogspot.com/2011/06/fxaa3-source-released.html
7 | * - WebGL port by @supereggbert
8 | * http://www.glge.org/demos/fxaa/
9 | */
10 |
11 | THREE.FXAAShader = {
12 |
13 | uniforms: {
14 |
15 | "tDiffuse": { type: "t", value: null },
16 | "resolution": { type: "v2", value: new THREE.Vector2( 1 / 1024, 1 / 512 ) }
17 |
18 | },
19 |
20 | vertexShader: [
21 |
22 | "varying vec2 vUv;",
23 |
24 | "void main() {",
25 |
26 | "vUv = uv;",
27 | "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
28 |
29 | "}"
30 |
31 | ].join("\n"),
32 |
33 | fragmentShader: [
34 |
35 | "uniform sampler2D tDiffuse;",
36 | "uniform vec2 resolution;",
37 |
38 | "varying vec2 vUv;",
39 |
40 | "#define FXAA_REDUCE_MIN (1.0/128.0)",
41 | "#define FXAA_REDUCE_MUL (1.0/8.0)",
42 | "#define FXAA_SPAN_MAX 8.0",
43 |
44 | "void main() {",
45 |
46 | "vec3 rgbNW = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( -1.0, -1.0 ) ) * resolution ).xyz;",
47 | "vec3 rgbNE = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( 1.0, -1.0 ) ) * resolution ).xyz;",
48 | "vec3 rgbSW = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( -1.0, 1.0 ) ) * resolution ).xyz;",
49 | "vec3 rgbSE = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( 1.0, 1.0 ) ) * resolution ).xyz;",
50 | "vec4 rgbaM = texture2D( tDiffuse, gl_FragCoord.xy * resolution );",
51 | "vec3 rgbM = rgbaM.xyz;",
52 | "float opacity = rgbaM.w;",
53 |
54 | "vec3 luma = vec3( 0.299, 0.587, 0.114 );",
55 |
56 | "float lumaNW = dot( rgbNW, luma );",
57 | "float lumaNE = dot( rgbNE, luma );",
58 | "float lumaSW = dot( rgbSW, luma );",
59 | "float lumaSE = dot( rgbSE, luma );",
60 | "float lumaM = dot( rgbM, luma );",
61 | "float lumaMin = min( lumaM, min( min( lumaNW, lumaNE ), min( lumaSW, lumaSE ) ) );",
62 | "float lumaMax = max( lumaM, max( max( lumaNW, lumaNE) , max( lumaSW, lumaSE ) ) );",
63 |
64 | "vec2 dir;",
65 | "dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));",
66 | "dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));",
67 |
68 | "float dirReduce = max( ( lumaNW + lumaNE + lumaSW + lumaSE ) * ( 0.25 * FXAA_REDUCE_MUL ), FXAA_REDUCE_MIN );",
69 |
70 | "float rcpDirMin = 1.0 / ( min( abs( dir.x ), abs( dir.y ) ) + dirReduce );",
71 | "dir = min( vec2( FXAA_SPAN_MAX, FXAA_SPAN_MAX),",
72 | "max( vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),",
73 | "dir * rcpDirMin)) * resolution;",
74 |
75 | "vec3 rgbA = 0.5 * (",
76 | "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * ( 1.0 / 3.0 - 0.5 ) ).xyz +",
77 | "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * ( 2.0 / 3.0 - 0.5 ) ).xyz );",
78 |
79 | "vec3 rgbB = rgbA * 0.5 + 0.25 * (",
80 | "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * -0.5 ).xyz +",
81 | "texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * 0.5 ).xyz );",
82 |
83 | "float lumaB = dot( rgbB, luma );",
84 |
85 | "if ( ( lumaB < lumaMin ) || ( lumaB > lumaMax ) ) {",
86 |
87 | "gl_FragColor = vec4( rgbA, opacity );",
88 |
89 | "} else {",
90 |
91 | "gl_FragColor = vec4( rgbB, opacity );",
92 |
93 | "}",
94 |
95 | "}"
96 |
97 | ].join("\n")
98 |
99 | };
100 |
--------------------------------------------------------------------------------
/libs/MaskPass.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author alteredq / http://alteredqualia.com/
3 | */
4 |
5 | THREE.MaskPass = function ( scene, camera ) {
6 |
7 | this.scene = scene;
8 | this.camera = camera;
9 |
10 | this.enabled = true;
11 | this.clear = true;
12 | this.needsSwap = false;
13 |
14 | this.inverse = false;
15 |
16 | };
17 |
18 | THREE.MaskPass.prototype = {
19 |
20 | render: function ( renderer, writeBuffer, readBuffer, delta ) {
21 |
22 | var context = renderer.context;
23 |
24 | // don't update color or depth
25 |
26 | context.colorMask( false, false, false, false );
27 | context.depthMask( false );
28 |
29 | // set up stencil
30 |
31 | var writeValue, clearValue;
32 |
33 | if ( this.inverse ) {
34 |
35 | writeValue = 0;
36 | clearValue = 1;
37 |
38 | } else {
39 |
40 | writeValue = 1;
41 | clearValue = 0;
42 |
43 | }
44 |
45 | context.enable( context.STENCIL_TEST );
46 | context.stencilOp( context.REPLACE, context.REPLACE, context.REPLACE );
47 | context.stencilFunc( context.ALWAYS, writeValue, 0xffffffff );
48 | context.clearStencil( clearValue );
49 |
50 | // draw into the stencil buffer
51 |
52 | renderer.render( this.scene, this.camera, readBuffer, this.clear );
53 | renderer.render( this.scene, this.camera, writeBuffer, this.clear );
54 |
55 | // re-enable update of color and depth
56 |
57 | context.colorMask( true, true, true, true );
58 | context.depthMask( true );
59 |
60 | // only render where stencil is set to 1
61 |
62 | context.stencilFunc( context.EQUAL, 1, 0xffffffff ); // draw if == 1
63 | context.stencilOp( context.KEEP, context.KEEP, context.KEEP );
64 |
65 | }
66 |
67 | };
68 |
69 |
70 | THREE.ClearMaskPass = function () {
71 |
72 | this.enabled = true;
73 |
74 | };
75 |
76 | THREE.ClearMaskPass.prototype = {
77 |
78 | render: function ( renderer, writeBuffer, readBuffer, delta ) {
79 |
80 | var context = renderer.context;
81 |
82 | context.disable( context.STENCIL_TEST );
83 |
84 | }
85 |
86 | };
87 |
--------------------------------------------------------------------------------
/libs/OrbitControls.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author qiao / https://github.com/qiao
3 | * @author mrdoob / http://mrdoob.com
4 | * @author alteredq / http://alteredqualia.com/
5 | * @author WestLangley / http://github.com/WestLangley
6 | */
7 |
8 | THREE.OrbitControls = function ( object, domElement ) {
9 |
10 | this.object = object;
11 | this.domElement = ( domElement !== undefined ) ? domElement : document;
12 |
13 | // API
14 |
15 | this.enabled = true;
16 |
17 | this.center = new THREE.Vector3();
18 |
19 | this.userZoom = true;
20 | this.userZoomSpeed = 1.0;
21 |
22 | this.userRotate = true;
23 | this.userRotateSpeed = 1.0;
24 |
25 | this.userPan = true;
26 | this.userPanSpeed = 2.0;
27 |
28 | this.autoRotate = false;
29 | this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60
30 |
31 | this.minPolarAngle = 0; // radians
32 | this.maxPolarAngle = Math.PI; // radians
33 |
34 | this.minDistance = 0;
35 | this.maxDistance = Infinity;
36 |
37 | this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 };
38 |
39 | // internals
40 |
41 | var scope = this;
42 |
43 | var EPS = 0.000001;
44 | var PIXELS_PER_ROUND = 1800;
45 |
46 | var rotateStart = new THREE.Vector2();
47 | var rotateEnd = new THREE.Vector2();
48 | var rotateDelta = new THREE.Vector2();
49 |
50 | var zoomStart = new THREE.Vector2();
51 | var zoomEnd = new THREE.Vector2();
52 | var zoomDelta = new THREE.Vector2();
53 |
54 | var phiDelta = 0;
55 | var thetaDelta = 0;
56 | var scale = 1;
57 |
58 | var lastPosition = new THREE.Vector3();
59 |
60 | var STATE = { NONE: -1, ROTATE: 0, ZOOM: 1, PAN: 2 };
61 | var state = STATE.NONE;
62 |
63 | // events
64 |
65 | var changeEvent = { type: 'change' };
66 |
67 |
68 | this.rotateLeft = function ( angle ) {
69 |
70 | if ( angle === undefined ) {
71 |
72 | angle = getAutoRotationAngle();
73 |
74 | }
75 |
76 | thetaDelta -= angle;
77 |
78 | };
79 |
80 | this.rotateRight = function ( angle ) {
81 |
82 | if ( angle === undefined ) {
83 |
84 | angle = getAutoRotationAngle();
85 |
86 | }
87 |
88 | thetaDelta += angle;
89 |
90 | };
91 |
92 | this.rotateUp = function ( angle ) {
93 |
94 | if ( angle === undefined ) {
95 |
96 | angle = getAutoRotationAngle();
97 |
98 | }
99 |
100 | phiDelta -= angle;
101 |
102 | };
103 |
104 | this.rotateDown = function ( angle ) {
105 |
106 | if ( angle === undefined ) {
107 |
108 | angle = getAutoRotationAngle();
109 |
110 | }
111 |
112 | phiDelta += angle;
113 |
114 | };
115 |
116 | this.zoomIn = function ( zoomScale ) {
117 |
118 | if ( zoomScale === undefined ) {
119 |
120 | zoomScale = getZoomScale();
121 |
122 | }
123 |
124 | scale /= zoomScale;
125 |
126 | };
127 |
128 | this.zoomOut = function ( zoomScale ) {
129 |
130 | if ( zoomScale === undefined ) {
131 |
132 | zoomScale = getZoomScale();
133 |
134 | }
135 |
136 | scale *= zoomScale;
137 |
138 | };
139 |
140 | this.pan = function ( distance ) {
141 |
142 | distance.transformDirection( this.object.matrix );
143 | distance.multiplyScalar( scope.userPanSpeed );
144 |
145 | this.object.position.add( distance );
146 | this.center.add( distance );
147 |
148 | };
149 |
150 | this.update = function () {
151 |
152 | var position = this.object.position;
153 | var offset = position.clone().sub( this.center );
154 |
155 | // angle from z-axis around y-axis
156 |
157 | var theta = Math.atan2( offset.x, offset.z );
158 |
159 | // angle from y-axis
160 |
161 | var phi = Math.atan2( Math.sqrt( offset.x * offset.x + offset.z * offset.z ), offset.y );
162 |
163 | if ( this.autoRotate ) {
164 |
165 | this.rotateLeft( getAutoRotationAngle() );
166 |
167 | }
168 |
169 | theta += thetaDelta;
170 | phi += phiDelta;
171 |
172 | // restrict phi to be between desired limits
173 | phi = Math.max( this.minPolarAngle, Math.min( this.maxPolarAngle, phi ) );
174 |
175 | // restrict phi to be betwee EPS and PI-EPS
176 | phi = Math.max( EPS, Math.min( Math.PI - EPS, phi ) );
177 |
178 | var radius = offset.length() * scale;
179 |
180 | // restrict radius to be between desired limits
181 | radius = Math.max( this.minDistance, Math.min( this.maxDistance, radius ) );
182 |
183 | offset.x = radius * Math.sin( phi ) * Math.sin( theta );
184 | offset.y = radius * Math.cos( phi );
185 | offset.z = radius * Math.sin( phi ) * Math.cos( theta );
186 |
187 | position.copy( this.center ).add( offset );
188 |
189 | this.object.lookAt( this.center );
190 |
191 | thetaDelta = 0;
192 | phiDelta = 0;
193 | scale = 1;
194 |
195 | if ( lastPosition.distanceTo( this.object.position ) > 0 ) {
196 |
197 | this.dispatchEvent( changeEvent );
198 |
199 | lastPosition.copy( this.object.position );
200 |
201 | }
202 |
203 | };
204 |
205 |
206 | function getAutoRotationAngle() {
207 |
208 | return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
209 |
210 | }
211 |
212 | function getZoomScale() {
213 |
214 | return Math.pow( 0.95, scope.userZoomSpeed );
215 |
216 | }
217 |
218 | function onMouseDown( event ) {
219 |
220 | if ( scope.enabled === false ) return;
221 | if ( scope.userRotate === false ) return;
222 |
223 | event.preventDefault();
224 |
225 | if ( event.button === 0 ) {
226 |
227 | state = STATE.ROTATE;
228 |
229 | rotateStart.set( event.clientX, event.clientY );
230 |
231 | } else if ( event.button === 1 ) {
232 |
233 | state = STATE.ZOOM;
234 |
235 | zoomStart.set( event.clientX, event.clientY );
236 |
237 | } else if ( event.button === 2 ) {
238 |
239 | state = STATE.PAN;
240 |
241 | }
242 |
243 | document.addEventListener( 'mousemove', onMouseMove, false );
244 | document.addEventListener( 'mouseup', onMouseUp, false );
245 |
246 | }
247 |
248 | function onMouseMove( event ) {
249 |
250 | if ( scope.enabled === false ) return;
251 |
252 | event.preventDefault();
253 |
254 | if ( state === STATE.ROTATE ) {
255 |
256 | rotateEnd.set( event.clientX, event.clientY );
257 | rotateDelta.subVectors( rotateEnd, rotateStart );
258 |
259 | scope.rotateLeft( 2 * Math.PI * rotateDelta.x / PIXELS_PER_ROUND * scope.userRotateSpeed );
260 | scope.rotateUp( 2 * Math.PI * rotateDelta.y / PIXELS_PER_ROUND * scope.userRotateSpeed );
261 |
262 | rotateStart.copy( rotateEnd );
263 |
264 | } else if ( state === STATE.ZOOM ) {
265 |
266 | zoomEnd.set( event.clientX, event.clientY );
267 | zoomDelta.subVectors( zoomEnd, zoomStart );
268 |
269 | if ( zoomDelta.y > 0 ) {
270 |
271 | scope.zoomIn();
272 |
273 | } else {
274 |
275 | scope.zoomOut();
276 |
277 | }
278 |
279 | zoomStart.copy( zoomEnd );
280 |
281 | } else if ( state === STATE.PAN ) {
282 |
283 | var movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0;
284 | var movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0;
285 |
286 | scope.pan( new THREE.Vector3( - movementX, movementY, 0 ) );
287 |
288 | }
289 |
290 | }
291 |
292 | function onMouseUp( event ) {
293 |
294 | if ( scope.enabled === false ) return;
295 | if ( scope.userRotate === false ) return;
296 |
297 | document.removeEventListener( 'mousemove', onMouseMove, false );
298 | document.removeEventListener( 'mouseup', onMouseUp, false );
299 |
300 | state = STATE.NONE;
301 |
302 | }
303 |
304 | function onMouseWheel( event ) {
305 |
306 | if ( scope.enabled === false ) return;
307 | if ( scope.userZoom === false ) return;
308 |
309 | var delta = 0;
310 |
311 | if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9
312 |
313 | delta = event.wheelDelta;
314 |
315 | } else if ( event.detail ) { // Firefox
316 |
317 | delta = - event.detail;
318 |
319 | }
320 |
321 | if ( delta > 0 ) {
322 |
323 | scope.zoomOut();
324 |
325 | } else {
326 |
327 | scope.zoomIn();
328 |
329 | }
330 |
331 | }
332 |
333 | function onKeyDown( event ) {
334 |
335 | if ( scope.enabled === false ) return;
336 | if ( scope.userPan === false ) return;
337 |
338 | switch ( event.keyCode ) {
339 |
340 | case scope.keys.UP:
341 | scope.pan( new THREE.Vector3( 0, 1, 0 ) );
342 | break;
343 | case scope.keys.BOTTOM:
344 | scope.pan( new THREE.Vector3( 0, - 1, 0 ) );
345 | break;
346 | case scope.keys.LEFT:
347 | scope.pan( new THREE.Vector3( - 1, 0, 0 ) );
348 | break;
349 | case scope.keys.RIGHT:
350 | scope.pan( new THREE.Vector3( 1, 0, 0 ) );
351 | break;
352 | }
353 |
354 | }
355 |
356 | this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
357 | this.domElement.addEventListener( 'mousedown', onMouseDown, false );
358 | this.domElement.addEventListener( 'mousewheel', onMouseWheel, false );
359 | this.domElement.addEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox
360 | this.domElement.addEventListener( 'keydown', onKeyDown, false );
361 |
362 | };
363 |
364 | THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype );
--------------------------------------------------------------------------------
/libs/Projector.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author mrdoob / http://mrdoob.com/
3 | * @author supereggbert / http://www.paulbrunt.co.uk/
4 | * @author julianwa / https://github.com/julianwa
5 | */
6 |
7 | THREE.RenderableObject = function () {
8 |
9 | this.id = 0;
10 |
11 | this.object = null;
12 | this.z = 0;
13 |
14 | };
15 |
16 | //
17 |
18 | THREE.RenderableFace = function () {
19 |
20 | this.id = 0;
21 |
22 | this.v1 = new THREE.RenderableVertex();
23 | this.v2 = new THREE.RenderableVertex();
24 | this.v3 = new THREE.RenderableVertex();
25 |
26 | this.normalModel = new THREE.Vector3();
27 |
28 | this.vertexNormalsModel = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
29 | this.vertexNormalsLength = 0;
30 |
31 | this.color = new THREE.Color();
32 | this.material = null;
33 | this.uvs = [ new THREE.Vector2(), new THREE.Vector2(), new THREE.Vector2() ];
34 |
35 | this.z = 0;
36 |
37 | };
38 |
39 | //
40 |
41 | THREE.RenderableVertex = function () {
42 |
43 | this.position = new THREE.Vector3();
44 | this.positionWorld = new THREE.Vector3();
45 | this.positionScreen = new THREE.Vector4();
46 |
47 | this.visible = true;
48 |
49 | };
50 |
51 | THREE.RenderableVertex.prototype.copy = function ( vertex ) {
52 |
53 | this.positionWorld.copy( vertex.positionWorld );
54 | this.positionScreen.copy( vertex.positionScreen );
55 |
56 | };
57 |
58 | //
59 |
60 | THREE.RenderableLine = function () {
61 |
62 | this.id = 0;
63 |
64 | this.v1 = new THREE.RenderableVertex();
65 | this.v2 = new THREE.RenderableVertex();
66 |
67 | this.vertexColors = [ new THREE.Color(), new THREE.Color() ];
68 | this.material = null;
69 |
70 | this.z = 0;
71 |
72 | };
73 |
74 | //
75 |
76 | THREE.RenderableSprite = function () {
77 |
78 | this.id = 0;
79 |
80 | this.object = null;
81 |
82 | this.x = 0;
83 | this.y = 0;
84 | this.z = 0;
85 |
86 | this.rotation = 0;
87 | this.scale = new THREE.Vector2();
88 |
89 | this.material = null;
90 |
91 | };
92 |
93 | //
94 |
95 | THREE.Projector = function () {
96 |
97 | var _object, _objectCount, _objectPool = [], _objectPoolLength = 0,
98 | _vertex, _vertexCount, _vertexPool = [], _vertexPoolLength = 0,
99 | _face, _faceCount, _facePool = [], _facePoolLength = 0,
100 | _line, _lineCount, _linePool = [], _linePoolLength = 0,
101 | _sprite, _spriteCount, _spritePool = [], _spritePoolLength = 0,
102 |
103 | _renderData = { objects: [], lights: [], elements: [] },
104 |
105 | _vA = new THREE.Vector3(),
106 | _vB = new THREE.Vector3(),
107 | _vC = new THREE.Vector3(),
108 |
109 | _vector3 = new THREE.Vector3(),
110 | _vector4 = new THREE.Vector4(),
111 |
112 | _clipBox = new THREE.Box3( new THREE.Vector3( - 1, - 1, - 1 ), new THREE.Vector3( 1, 1, 1 ) ),
113 | _boundingBox = new THREE.Box3(),
114 | _points3 = new Array( 3 ),
115 | _points4 = new Array( 4 ),
116 |
117 | _viewMatrix = new THREE.Matrix4(),
118 | _viewProjectionMatrix = new THREE.Matrix4(),
119 |
120 | _modelMatrix,
121 | _modelViewProjectionMatrix = new THREE.Matrix4(),
122 |
123 | _normalMatrix = new THREE.Matrix3(),
124 |
125 | _frustum = new THREE.Frustum(),
126 |
127 | _clippedVertex1PositionScreen = new THREE.Vector4(),
128 | _clippedVertex2PositionScreen = new THREE.Vector4();
129 |
130 | //
131 |
132 | this.projectVector = function ( vector, camera ) {
133 |
134 | console.warn( 'THREE.Projector: .projectVector() is now vector.project().' );
135 | vector.project( camera );
136 |
137 | };
138 |
139 | this.unprojectVector = function ( vector, camera ) {
140 |
141 | console.warn( 'THREE.Projector: .unprojectVector() is now vector.unproject().' );
142 | vector.unproject( camera );
143 |
144 | };
145 |
146 | this.pickingRay = function ( vector, camera ) {
147 |
148 | console.error( 'THREE.Projector: .pickingRay() has been removed.' );
149 |
150 | };
151 |
152 | //
153 |
154 | var RenderList = function () {
155 |
156 | var normals = [];
157 | var uvs = [];
158 |
159 | var object = null;
160 | var material = null;
161 |
162 | var normalMatrix = new THREE.Matrix3();
163 |
164 | var setObject = function ( value ) {
165 |
166 | object = value;
167 | material = object.material;
168 |
169 | normalMatrix.getNormalMatrix( object.matrixWorld );
170 |
171 | normals.length = 0;
172 | uvs.length = 0;
173 |
174 | };
175 |
176 | var projectVertex = function ( vertex ) {
177 |
178 | var position = vertex.position;
179 | var positionWorld = vertex.positionWorld;
180 | var positionScreen = vertex.positionScreen;
181 |
182 | positionWorld.copy( position ).applyMatrix4( _modelMatrix );
183 | positionScreen.copy( positionWorld ).applyMatrix4( _viewProjectionMatrix );
184 |
185 | var invW = 1 / positionScreen.w;
186 |
187 | positionScreen.x *= invW;
188 | positionScreen.y *= invW;
189 | positionScreen.z *= invW;
190 |
191 | vertex.visible = positionScreen.x >= - 1 && positionScreen.x <= 1 &&
192 | positionScreen.y >= - 1 && positionScreen.y <= 1 &&
193 | positionScreen.z >= - 1 && positionScreen.z <= 1;
194 |
195 | };
196 |
197 | var pushVertex = function ( x, y, z ) {
198 |
199 | _vertex = getNextVertexInPool();
200 | _vertex.position.set( x, y, z );
201 |
202 | projectVertex( _vertex );
203 |
204 | };
205 |
206 | var pushNormal = function ( x, y, z ) {
207 |
208 | normals.push( x, y, z );
209 |
210 | };
211 |
212 | var pushUv = function ( x, y ) {
213 |
214 | uvs.push( x, y );
215 |
216 | };
217 |
218 | var checkTriangleVisibility = function ( v1, v2, v3 ) {
219 |
220 | if ( v1.visible === true || v2.visible === true || v3.visible === true ) return true;
221 |
222 | _points3[ 0 ] = v1.positionScreen;
223 | _points3[ 1 ] = v2.positionScreen;
224 | _points3[ 2 ] = v3.positionScreen;
225 |
226 | return _clipBox.isIntersectionBox( _boundingBox.setFromPoints( _points3 ) );
227 |
228 | };
229 |
230 | var checkBackfaceCulling = function ( v1, v2, v3 ) {
231 |
232 | return ( ( v3.positionScreen.x - v1.positionScreen.x ) *
233 | ( v2.positionScreen.y - v1.positionScreen.y ) -
234 | ( v3.positionScreen.y - v1.positionScreen.y ) *
235 | ( v2.positionScreen.x - v1.positionScreen.x ) ) < 0;
236 |
237 | };
238 |
239 | var pushLine = function ( a, b ) {
240 |
241 | var v1 = _vertexPool[ a ];
242 | var v2 = _vertexPool[ b ];
243 |
244 | _line = getNextLineInPool();
245 |
246 | _line.id = object.id;
247 | _line.v1.copy( v1 );
248 | _line.v2.copy( v2 );
249 | _line.z = ( v1.positionScreen.z + v2.positionScreen.z ) / 2;
250 |
251 | _line.material = object.material;
252 |
253 | _renderData.elements.push( _line );
254 |
255 | };
256 |
257 | var pushTriangle = function ( a, b, c ) {
258 |
259 | var v1 = _vertexPool[ a ];
260 | var v2 = _vertexPool[ b ];
261 | var v3 = _vertexPool[ c ];
262 |
263 | if ( checkTriangleVisibility( v1, v2, v3 ) === false ) return;
264 |
265 | if ( material.side === THREE.DoubleSide || checkBackfaceCulling( v1, v2, v3 ) === true ) {
266 |
267 | _face = getNextFaceInPool();
268 |
269 | _face.id = object.id;
270 | _face.v1.copy( v1 );
271 | _face.v2.copy( v2 );
272 | _face.v3.copy( v3 );
273 | _face.z = ( v1.positionScreen.z + v2.positionScreen.z + v3.positionScreen.z ) / 3;
274 |
275 | for ( var i = 0; i < 3; i ++ ) {
276 |
277 | var offset = arguments[ i ] * 3;
278 | var normal = _face.vertexNormalsModel[ i ];
279 |
280 | normal.set( normals[ offset ], normals[ offset + 1 ], normals[ offset + 2 ] );
281 | normal.applyMatrix3( normalMatrix ).normalize();
282 |
283 | var offset2 = arguments[ i ] * 2;
284 |
285 | var uv = _face.uvs[ i ];
286 | uv.set( uvs[ offset2 ], uvs[ offset2 + 1 ] );
287 |
288 | }
289 |
290 | _face.vertexNormalsLength = 3;
291 |
292 | _face.material = object.material;
293 |
294 | _renderData.elements.push( _face );
295 |
296 | }
297 |
298 | };
299 |
300 | return {
301 | setObject: setObject,
302 | projectVertex: projectVertex,
303 | checkTriangleVisibility: checkTriangleVisibility,
304 | checkBackfaceCulling: checkBackfaceCulling,
305 | pushVertex: pushVertex,
306 | pushNormal: pushNormal,
307 | pushUv: pushUv,
308 | pushLine: pushLine,
309 | pushTriangle: pushTriangle
310 | }
311 |
312 | };
313 |
314 | var renderList = new RenderList();
315 |
316 | this.projectScene = function ( scene, camera, sortObjects, sortElements ) {
317 |
318 | _faceCount = 0;
319 | _lineCount = 0;
320 | _spriteCount = 0;
321 |
322 | _renderData.elements.length = 0;
323 |
324 | if ( scene.autoUpdate === true ) scene.updateMatrixWorld();
325 | if ( camera.parent === undefined ) camera.updateMatrixWorld();
326 |
327 | _viewMatrix.copy( camera.matrixWorldInverse.getInverse( camera.matrixWorld ) );
328 | _viewProjectionMatrix.multiplyMatrices( camera.projectionMatrix, _viewMatrix );
329 |
330 | _frustum.setFromMatrix( _viewProjectionMatrix );
331 |
332 | //
333 |
334 | _objectCount = 0;
335 |
336 | _renderData.objects.length = 0;
337 | _renderData.lights.length = 0;
338 |
339 | scene.traverseVisible( function ( object ) {
340 |
341 | if ( object instanceof THREE.Light ) {
342 |
343 | _renderData.lights.push( object );
344 |
345 | } else if ( object instanceof THREE.Mesh || object instanceof THREE.Line || object instanceof THREE.Sprite ) {
346 |
347 | if ( object.material.visible === false ) return;
348 |
349 | if ( object.frustumCulled === false || _frustum.intersectsObject( object ) === true ) {
350 |
351 | _object = getNextObjectInPool();
352 | _object.id = object.id;
353 | _object.object = object;
354 |
355 | if ( object.renderDepth !== null ) {
356 |
357 | _object.z = object.renderDepth;
358 |
359 | } else {
360 |
361 | _vector3.setFromMatrixPosition( object.matrixWorld );
362 | _vector3.applyProjection( _viewProjectionMatrix );
363 | _object.z = _vector3.z;
364 |
365 | }
366 |
367 | _renderData.objects.push( _object );
368 |
369 | }
370 |
371 | }
372 |
373 | } );
374 |
375 | if ( sortObjects === true ) {
376 |
377 | _renderData.objects.sort( painterSort );
378 |
379 | }
380 |
381 | //
382 |
383 | for ( var o = 0, ol = _renderData.objects.length; o < ol; o ++ ) {
384 |
385 | var object = _renderData.objects[ o ].object;
386 | var geometry = object.geometry;
387 |
388 | renderList.setObject( object );
389 |
390 | _modelMatrix = object.matrixWorld;
391 |
392 | _vertexCount = 0;
393 |
394 | if ( object instanceof THREE.Mesh ) {
395 |
396 | if ( geometry instanceof THREE.BufferGeometry ) {
397 |
398 | var attributes = geometry.attributes;
399 | var offsets = geometry.offsets;
400 |
401 | if ( attributes.position === undefined ) continue;
402 |
403 | var positions = attributes.position.array;
404 |
405 | for ( var i = 0, l = positions.length; i < l; i += 3 ) {
406 |
407 | renderList.pushVertex( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] );
408 |
409 | }
410 |
411 | if ( attributes.normal !== undefined ) {
412 |
413 | var normals = attributes.normal.array;
414 |
415 | for ( var i = 0, l = normals.length; i < l; i += 3 ) {
416 |
417 | renderList.pushNormal( normals[ i ], normals[ i + 1 ], normals[ i + 2 ] );
418 |
419 | }
420 |
421 | }
422 |
423 | if ( attributes.uv !== undefined ) {
424 |
425 | var uvs = attributes.uv.array;
426 |
427 | for ( var i = 0, l = uvs.length; i < l; i += 2 ) {
428 |
429 | renderList.pushUv( uvs[ i ], uvs[ i + 1 ] );
430 |
431 | }
432 |
433 | }
434 |
435 | if ( attributes.index !== undefined ) {
436 |
437 | var indices = attributes.index.array;
438 |
439 | if ( offsets.length > 0 ) {
440 |
441 | for ( var o = 0; o < offsets.length; o ++ ) {
442 |
443 | var offset = offsets[ o ];
444 | var index = offset.index;
445 |
446 | for ( var i = offset.start, l = offset.start + offset.count; i < l; i += 3 ) {
447 |
448 | renderList.pushTriangle( indices[ i ] + index, indices[ i + 1 ] + index, indices[ i + 2 ] + index );
449 |
450 | }
451 |
452 | }
453 |
454 | } else {
455 |
456 | for ( var i = 0, l = indices.length; i < l; i += 3 ) {
457 |
458 | renderList.pushTriangle( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] );
459 |
460 | }
461 |
462 | }
463 |
464 | } else {
465 |
466 | for ( var i = 0, l = positions.length / 3; i < l; i += 3 ) {
467 |
468 | renderList.pushTriangle( i, i + 1, i + 2 );
469 |
470 | }
471 |
472 | }
473 |
474 | } else if ( geometry instanceof THREE.Geometry ) {
475 |
476 | var vertices = geometry.vertices;
477 | var faces = geometry.faces;
478 | var faceVertexUvs = geometry.faceVertexUvs[ 0 ];
479 |
480 | _normalMatrix.getNormalMatrix( _modelMatrix );
481 |
482 | var isFaceMaterial = object.material instanceof THREE.MeshFaceMaterial;
483 | var objectMaterials = isFaceMaterial === true ? object.material : null;
484 |
485 | for ( var v = 0, vl = vertices.length; v < vl; v ++ ) {
486 |
487 | var vertex = vertices[ v ];
488 | renderList.pushVertex( vertex.x, vertex.y, vertex.z );
489 |
490 | }
491 |
492 | for ( var f = 0, fl = faces.length; f < fl; f ++ ) {
493 |
494 | var face = faces[ f ];
495 |
496 | var material = isFaceMaterial === true
497 | ? objectMaterials.materials[ face.materialIndex ]
498 | : object.material;
499 |
500 | if ( material === undefined ) continue;
501 |
502 | var side = material.side;
503 |
504 | var v1 = _vertexPool[ face.a ];
505 | var v2 = _vertexPool[ face.b ];
506 | var v3 = _vertexPool[ face.c ];
507 |
508 | if ( material.morphTargets === true ) {
509 |
510 | var morphTargets = geometry.morphTargets;
511 | var morphInfluences = object.morphTargetInfluences;
512 |
513 | var v1p = v1.position;
514 | var v2p = v2.position;
515 | var v3p = v3.position;
516 |
517 | _vA.set( 0, 0, 0 );
518 | _vB.set( 0, 0, 0 );
519 | _vC.set( 0, 0, 0 );
520 |
521 | for ( var t = 0, tl = morphTargets.length; t < tl; t ++ ) {
522 |
523 | var influence = morphInfluences[ t ];
524 |
525 | if ( influence === 0 ) continue;
526 |
527 | var targets = morphTargets[ t ].vertices;
528 |
529 | _vA.x += ( targets[ face.a ].x - v1p.x ) * influence;
530 | _vA.y += ( targets[ face.a ].y - v1p.y ) * influence;
531 | _vA.z += ( targets[ face.a ].z - v1p.z ) * influence;
532 |
533 | _vB.x += ( targets[ face.b ].x - v2p.x ) * influence;
534 | _vB.y += ( targets[ face.b ].y - v2p.y ) * influence;
535 | _vB.z += ( targets[ face.b ].z - v2p.z ) * influence;
536 |
537 | _vC.x += ( targets[ face.c ].x - v3p.x ) * influence;
538 | _vC.y += ( targets[ face.c ].y - v3p.y ) * influence;
539 | _vC.z += ( targets[ face.c ].z - v3p.z ) * influence;
540 |
541 | }
542 |
543 | v1.position.add( _vA );
544 | v2.position.add( _vB );
545 | v3.position.add( _vC );
546 |
547 | renderList.projectVertex( v1 );
548 | renderList.projectVertex( v2 );
549 | renderList.projectVertex( v3 );
550 |
551 | }
552 |
553 | if ( renderList.checkTriangleVisibility( v1, v2, v3 ) === false ) continue;
554 |
555 | var visible = renderList.checkBackfaceCulling( v1, v2, v3 );
556 |
557 | if ( side !== THREE.DoubleSide ) {
558 | if ( side === THREE.FrontSide && visible === false ) continue;
559 | if ( side === THREE.BackSide && visible === true ) continue;
560 | }
561 |
562 | _face = getNextFaceInPool();
563 |
564 | _face.id = object.id;
565 | _face.v1.copy( v1 );
566 | _face.v2.copy( v2 );
567 | _face.v3.copy( v3 );
568 |
569 | _face.normalModel.copy( face.normal );
570 |
571 | if ( visible === false && ( side === THREE.BackSide || side === THREE.DoubleSide ) ) {
572 |
573 | _face.normalModel.negate();
574 |
575 | }
576 |
577 | _face.normalModel.applyMatrix3( _normalMatrix ).normalize();
578 |
579 | var faceVertexNormals = face.vertexNormals;
580 |
581 | for ( var n = 0, nl = Math.min( faceVertexNormals.length, 3 ); n < nl; n ++ ) {
582 |
583 | var normalModel = _face.vertexNormalsModel[ n ];
584 | normalModel.copy( faceVertexNormals[ n ] );
585 |
586 | if ( visible === false && ( side === THREE.BackSide || side === THREE.DoubleSide ) ) {
587 |
588 | normalModel.negate();
589 |
590 | }
591 |
592 | normalModel.applyMatrix3( _normalMatrix ).normalize();
593 |
594 | }
595 |
596 | _face.vertexNormalsLength = faceVertexNormals.length;
597 |
598 | var vertexUvs = faceVertexUvs[ f ];
599 |
600 | if ( vertexUvs !== undefined ) {
601 |
602 | for ( var u = 0; u < 3; u ++ ) {
603 |
604 | _face.uvs[ u ].copy( vertexUvs[ u ] );
605 |
606 | }
607 |
608 | }
609 |
610 | _face.color = face.color;
611 | _face.material = material;
612 |
613 | _face.z = ( v1.positionScreen.z + v2.positionScreen.z + v3.positionScreen.z ) / 3;
614 |
615 | _renderData.elements.push( _face );
616 |
617 | }
618 |
619 | }
620 |
621 | } else if ( object instanceof THREE.Line ) {
622 |
623 | if ( geometry instanceof THREE.BufferGeometry ) {
624 |
625 | var attributes = geometry.attributes;
626 |
627 | if ( attributes.position !== undefined ) {
628 |
629 | var positions = attributes.position.array;
630 |
631 | for ( var i = 0, l = positions.length; i < l; i += 3 ) {
632 |
633 | renderList.pushVertex( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] );
634 |
635 | }
636 |
637 | if ( attributes.index !== undefined ) {
638 |
639 | var indices = attributes.index.array;
640 |
641 | for ( var i = 0, l = indices.length; i < l; i += 2 ) {
642 |
643 | renderList.pushLine( indices[ i ], indices[ i + 1 ] );
644 |
645 | }
646 |
647 | } else {
648 |
649 | var step = object.mode === THREE.LinePieces ? 2 : 1;
650 |
651 | for ( var i = 0, l = ( positions.length / 3 ) - 1; i < l; i += step ) {
652 |
653 | renderList.pushLine( i, i + 1 );
654 |
655 | }
656 |
657 | }
658 |
659 | }
660 |
661 | } else if ( geometry instanceof THREE.Geometry ) {
662 |
663 | _modelViewProjectionMatrix.multiplyMatrices( _viewProjectionMatrix, _modelMatrix );
664 |
665 | var vertices = object.geometry.vertices;
666 |
667 | if ( vertices.length === 0 ) continue;
668 |
669 | v1 = getNextVertexInPool();
670 | v1.positionScreen.copy( vertices[ 0 ] ).applyMatrix4( _modelViewProjectionMatrix );
671 |
672 | // Handle LineStrip and LinePieces
673 | var step = object.mode === THREE.LinePieces ? 2 : 1;
674 |
675 | for ( var v = 1, vl = vertices.length; v < vl; v ++ ) {
676 |
677 | v1 = getNextVertexInPool();
678 | v1.positionScreen.copy( vertices[ v ] ).applyMatrix4( _modelViewProjectionMatrix );
679 |
680 | if ( ( v + 1 ) % step > 0 ) continue;
681 |
682 | v2 = _vertexPool[ _vertexCount - 2 ];
683 |
684 | _clippedVertex1PositionScreen.copy( v1.positionScreen );
685 | _clippedVertex2PositionScreen.copy( v2.positionScreen );
686 |
687 | if ( clipLine( _clippedVertex1PositionScreen, _clippedVertex2PositionScreen ) === true ) {
688 |
689 | // Perform the perspective divide
690 | _clippedVertex1PositionScreen.multiplyScalar( 1 / _clippedVertex1PositionScreen.w );
691 | _clippedVertex2PositionScreen.multiplyScalar( 1 / _clippedVertex2PositionScreen.w );
692 |
693 | _line = getNextLineInPool();
694 |
695 | _line.id = object.id;
696 | _line.v1.positionScreen.copy( _clippedVertex1PositionScreen );
697 | _line.v2.positionScreen.copy( _clippedVertex2PositionScreen );
698 |
699 | _line.z = Math.max( _clippedVertex1PositionScreen.z, _clippedVertex2PositionScreen.z );
700 |
701 | _line.material = object.material;
702 |
703 | if ( object.material.vertexColors === THREE.VertexColors ) {
704 |
705 | _line.vertexColors[ 0 ].copy( object.geometry.colors[ v ] );
706 | _line.vertexColors[ 1 ].copy( object.geometry.colors[ v - 1 ] );
707 |
708 | }
709 |
710 | _renderData.elements.push( _line );
711 |
712 | }
713 |
714 | }
715 |
716 | }
717 |
718 | } else if ( object instanceof THREE.Sprite ) {
719 |
720 | _vector4.set( _modelMatrix.elements[ 12 ], _modelMatrix.elements[ 13 ], _modelMatrix.elements[ 14 ], 1 );
721 | _vector4.applyMatrix4( _viewProjectionMatrix );
722 |
723 | var invW = 1 / _vector4.w;
724 |
725 | _vector4.z *= invW;
726 |
727 | if ( _vector4.z >= - 1 && _vector4.z <= 1 ) {
728 |
729 | _sprite = getNextSpriteInPool();
730 | _sprite.id = object.id;
731 | _sprite.x = _vector4.x * invW;
732 | _sprite.y = _vector4.y * invW;
733 | _sprite.z = _vector4.z;
734 | _sprite.object = object;
735 |
736 | _sprite.rotation = object.rotation;
737 |
738 | _sprite.scale.x = object.scale.x * Math.abs( _sprite.x - ( _vector4.x + camera.projectionMatrix.elements[ 0 ] ) / ( _vector4.w + camera.projectionMatrix.elements[ 12 ] ) );
739 | _sprite.scale.y = object.scale.y * Math.abs( _sprite.y - ( _vector4.y + camera.projectionMatrix.elements[ 5 ] ) / ( _vector4.w + camera.projectionMatrix.elements[ 13 ] ) );
740 |
741 | _sprite.material = object.material;
742 |
743 | _renderData.elements.push( _sprite );
744 |
745 | }
746 |
747 | }
748 |
749 | }
750 |
751 | if ( sortElements === true ) {
752 |
753 | _renderData.elements.sort( painterSort );
754 |
755 | }
756 |
757 | return _renderData;
758 |
759 | };
760 |
761 | // Pools
762 |
763 | function getNextObjectInPool() {
764 |
765 | if ( _objectCount === _objectPoolLength ) {
766 |
767 | var object = new THREE.RenderableObject();
768 | _objectPool.push( object );
769 | _objectPoolLength ++;
770 | _objectCount ++;
771 | return object;
772 |
773 | }
774 |
775 | return _objectPool[ _objectCount ++ ];
776 |
777 | }
778 |
779 | function getNextVertexInPool() {
780 |
781 | if ( _vertexCount === _vertexPoolLength ) {
782 |
783 | var vertex = new THREE.RenderableVertex();
784 | _vertexPool.push( vertex );
785 | _vertexPoolLength ++;
786 | _vertexCount ++;
787 | return vertex;
788 |
789 | }
790 |
791 | return _vertexPool[ _vertexCount ++ ];
792 |
793 | }
794 |
795 | function getNextFaceInPool() {
796 |
797 | if ( _faceCount === _facePoolLength ) {
798 |
799 | var face = new THREE.RenderableFace();
800 | _facePool.push( face );
801 | _facePoolLength ++;
802 | _faceCount ++;
803 | return face;
804 |
805 | }
806 |
807 | return _facePool[ _faceCount ++ ];
808 |
809 |
810 | }
811 |
812 | function getNextLineInPool() {
813 |
814 | if ( _lineCount === _linePoolLength ) {
815 |
816 | var line = new THREE.RenderableLine();
817 | _linePool.push( line );
818 | _linePoolLength ++;
819 | _lineCount ++
820 | return line;
821 |
822 | }
823 |
824 | return _linePool[ _lineCount ++ ];
825 |
826 | }
827 |
828 | function getNextSpriteInPool() {
829 |
830 | if ( _spriteCount === _spritePoolLength ) {
831 |
832 | var sprite = new THREE.RenderableSprite();
833 | _spritePool.push( sprite );
834 | _spritePoolLength ++;
835 | _spriteCount ++
836 | return sprite;
837 |
838 | }
839 |
840 | return _spritePool[ _spriteCount ++ ];
841 |
842 | }
843 |
844 | //
845 |
846 | function painterSort( a, b ) {
847 |
848 | if ( a.z !== b.z ) {
849 |
850 | return b.z - a.z;
851 |
852 | } else if ( a.id !== b.id ) {
853 |
854 | return a.id - b.id;
855 |
856 | } else {
857 |
858 | return 0;
859 |
860 | }
861 |
862 | }
863 |
864 | function clipLine( s1, s2 ) {
865 |
866 | var alpha1 = 0, alpha2 = 1,
867 |
868 | // Calculate the boundary coordinate of each vertex for the near and far clip planes,
869 | // Z = -1 and Z = +1, respectively.
870 | bc1near = s1.z + s1.w,
871 | bc2near = s2.z + s2.w,
872 | bc1far = - s1.z + s1.w,
873 | bc2far = - s2.z + s2.w;
874 |
875 | if ( bc1near >= 0 && bc2near >= 0 && bc1far >= 0 && bc2far >= 0 ) {
876 |
877 | // Both vertices lie entirely within all clip planes.
878 | return true;
879 |
880 | } else if ( ( bc1near < 0 && bc2near < 0 ) || ( bc1far < 0 && bc2far < 0 ) ) {
881 |
882 | // Both vertices lie entirely outside one of the clip planes.
883 | return false;
884 |
885 | } else {
886 |
887 | // The line segment spans at least one clip plane.
888 |
889 | if ( bc1near < 0 ) {
890 |
891 | // v1 lies outside the near plane, v2 inside
892 | alpha1 = Math.max( alpha1, bc1near / ( bc1near - bc2near ) );
893 |
894 | } else if ( bc2near < 0 ) {
895 |
896 | // v2 lies outside the near plane, v1 inside
897 | alpha2 = Math.min( alpha2, bc1near / ( bc1near - bc2near ) );
898 |
899 | }
900 |
901 | if ( bc1far < 0 ) {
902 |
903 | // v1 lies outside the far plane, v2 inside
904 | alpha1 = Math.max( alpha1, bc1far / ( bc1far - bc2far ) );
905 |
906 | } else if ( bc2far < 0 ) {
907 |
908 | // v2 lies outside the far plane, v2 inside
909 | alpha2 = Math.min( alpha2, bc1far / ( bc1far - bc2far ) );
910 |
911 | }
912 |
913 | if ( alpha2 < alpha1 ) {
914 |
915 | // The line segment spans two boundaries, but is outside both of them.
916 | // (This can't happen when we're only clipping against just near/far but good
917 | // to leave the check here for future usage if other clip planes are added.)
918 | return false;
919 |
920 | } else {
921 |
922 | // Update the s1 and s2 vertices to match the clipped line segment.
923 | s1.lerp( s2, alpha1 );
924 | s2.lerp( s1, 1 - alpha2 );
925 |
926 | return true;
927 |
928 | }
929 |
930 | }
931 |
932 | }
933 |
934 | };
935 |
--------------------------------------------------------------------------------
/libs/RenderPass.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author alteredq / http://alteredqualia.com/
3 | */
4 |
5 | THREE.RenderPass = function ( scene, camera, overrideMaterial, clearColor, clearAlpha ) {
6 |
7 | this.scene = scene;
8 | this.camera = camera;
9 |
10 | this.overrideMaterial = overrideMaterial;
11 |
12 | this.clearColor = clearColor;
13 | this.clearAlpha = ( clearAlpha !== undefined ) ? clearAlpha : 1;
14 |
15 | this.oldClearColor = new THREE.Color();
16 | this.oldClearAlpha = 1;
17 |
18 | this.enabled = true;
19 | this.clear = true;
20 | this.needsSwap = false;
21 |
22 | };
23 |
24 | THREE.RenderPass.prototype = {
25 |
26 | render: function ( renderer, writeBuffer, readBuffer, delta ) {
27 |
28 | this.scene.overrideMaterial = this.overrideMaterial;
29 |
30 | if ( this.clearColor ) {
31 |
32 | this.oldClearColor.copy( renderer.getClearColor() );
33 | this.oldClearAlpha = renderer.getClearAlpha();
34 |
35 | renderer.setClearColor( this.clearColor, this.clearAlpha );
36 |
37 | }
38 |
39 | renderer.render( this.scene, this.camera, readBuffer, this.clear );
40 |
41 | if ( this.clearColor ) {
42 |
43 | renderer.setClearColor( this.oldClearColor, this.oldClearAlpha );
44 |
45 | }
46 |
47 | this.scene.overrideMaterial = null;
48 |
49 | }
50 |
51 | };
52 |
--------------------------------------------------------------------------------
/libs/ShaderDeferred.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author alteredq / http://alteredqualia.com/
3 | * @author MPanknin / http://www.redplant.de/
4 | * @author benaadams / http://blog.illyriad.co.uk/
5 | *
6 | */
7 |
8 |
9 | THREE.DeferredShaderChunk = {
10 |
11 | // decode float to vec3
12 |
13 | unpackFloat: [
14 |
15 | "vec3 float_to_vec3( float data ) {",
16 |
17 | "vec3 uncompressed;",
18 | "uncompressed.x = fract( data );",
19 | "float zInt = floor( data / 255.0 );",
20 | "uncompressed.z = fract( zInt / 255.0 );",
21 | "uncompressed.y = fract( floor( data - ( zInt * 255.0 ) ) / 255.0 );",
22 | "return uncompressed;",
23 |
24 | "}"
25 |
26 | ].join("\n"),
27 |
28 | computeVertexPositionVS: [
29 |
30 | "vec2 texCoord = gl_FragCoord.xy / vec2( viewWidth, viewHeight );",
31 |
32 | "vec4 normalDepth = texture2D( samplerNormalDepth, texCoord );",
33 | "float z = normalDepth.w;",
34 |
35 | "if ( z == 0.0 ) discard;",
36 |
37 | "vec2 xy = texCoord * 2.0 - 1.0;",
38 |
39 | "vec4 vertexPositionProjected = vec4( xy, z, 1.0 );",
40 | "vec4 vertexPositionVS = matProjInverse * vertexPositionProjected;",
41 | "vertexPositionVS.xyz /= vertexPositionVS.w;",
42 | "vertexPositionVS.w = 1.0;"
43 |
44 | ].join("\n"),
45 |
46 | computeNormal: [
47 |
48 | "vec3 normal = normalDepth.xyz * 2.0 - 1.0;"
49 |
50 | ].join("\n"),
51 |
52 | unpackColorMap: [
53 |
54 | "vec4 colorMap = texture2D( samplerColor, texCoord );",
55 |
56 | "vec3 albedo = float_to_vec3( abs( colorMap.x ) );",
57 | "vec3 specularColor = float_to_vec3( abs( colorMap.y ) );",
58 | "float shininess = abs( colorMap.z );",
59 | "float wrapAround = sign( colorMap.z );",
60 | "float additiveSpecular = sign( colorMap.y );"
61 |
62 | ].join("\n"),
63 |
64 | computeDiffuse: [
65 |
66 | "float dotProduct = dot( normal, lightVector );",
67 | "float diffuseFull = max( dotProduct, 0.0 );",
68 |
69 | "vec3 diffuse;",
70 |
71 | "if ( wrapAround < 0.0 ) {",
72 |
73 | // wrap around lighting
74 |
75 | "float diffuseHalf = max( 0.5 * dotProduct + 0.5, 0.0 );",
76 |
77 | "const vec3 wrapRGB = vec3( 1.0, 1.0, 1.0 );",
78 | "diffuse = mix( vec3( diffuseFull ), vec3( diffuseHalf ), wrapRGB );",
79 |
80 | "} else {",
81 |
82 | // simple lighting
83 |
84 | "diffuse = vec3( diffuseFull );",
85 |
86 | "}"
87 |
88 | ].join("\n"),
89 |
90 | computeSpecular: [
91 |
92 | "vec3 halfVector = normalize( lightVector - normalize( vertexPositionVS.xyz ) );",
93 | "float dotNormalHalf = max( dot( normal, halfVector ), 0.0 );",
94 |
95 | // simple specular
96 |
97 | //"vec3 specular = specularColor * max( pow( dotNormalHalf, shininess ), 0.0 ) * diffuse;",
98 |
99 | // physically based specular
100 |
101 | "float specularNormalization = ( shininess + 2.0001 ) / 8.0;",
102 |
103 | "vec3 schlick = specularColor + vec3( 1.0 - specularColor ) * pow( 1.0 - dot( lightVector, halfVector ), 5.0 );",
104 | "vec3 specular = schlick * max( pow( dotNormalHalf, shininess ), 0.0 ) * diffuse * specularNormalization;"
105 |
106 | ].join("\n"),
107 |
108 | combine: [
109 |
110 | "vec3 light = lightIntensity * lightColor;",
111 | "gl_FragColor = vec4( light * ( albedo * diffuse + specular ), attenuation );"
112 |
113 | ].join("\n")
114 |
115 | };
116 |
117 | THREE.ShaderDeferred = {
118 |
119 | "color" : {
120 |
121 | uniforms: THREE.UniformsUtils.merge( [
122 |
123 | THREE.UniformsLib[ "common" ],
124 | THREE.UniformsLib[ "fog" ],
125 | THREE.UniformsLib[ "shadowmap" ],
126 |
127 | {
128 | "emissive" : { type: "c", value: new THREE.Color( 0x000000 ) },
129 | "specular" : { type: "c", value: new THREE.Color( 0x111111 ) },
130 | "shininess": { type: "f", value: 30 },
131 | "wrapAround": { type: "f", value: 1 },
132 | "additiveSpecular": { type: "f", value: 1 },
133 |
134 | "samplerNormalDepth": { type: "t", value: null },
135 | "viewWidth": { type: "f", value: 800 },
136 | "viewHeight": { type: "f", value: 600 }
137 | }
138 |
139 | ] ),
140 |
141 | fragmentShader : [
142 |
143 | "uniform vec3 diffuse;",
144 | "uniform vec3 specular;",
145 | "uniform vec3 emissive;",
146 | "uniform float shininess;",
147 | "uniform float wrapAround;",
148 | "uniform float additiveSpecular;",
149 |
150 | THREE.ShaderChunk[ "color_pars_fragment" ],
151 | THREE.ShaderChunk[ "map_pars_fragment" ],
152 | THREE.ShaderChunk[ "lightmap_pars_fragment" ],
153 |
154 | "#ifdef USE_ENVMAP",
155 |
156 | "varying vec3 vWorldPosition;",
157 |
158 | "uniform float reflectivity;",
159 | "uniform samplerCube envMap;",
160 | "uniform float flipEnvMap;",
161 | "uniform int combine;",
162 |
163 | "uniform bool useRefract;",
164 | "uniform float refractionRatio;",
165 |
166 | "uniform sampler2D samplerNormalDepth;",
167 | "uniform float viewHeight;",
168 | "uniform float viewWidth;",
169 |
170 | "#endif",
171 |
172 | THREE.ShaderChunk[ "fog_pars_fragment" ],
173 | THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
174 | THREE.ShaderChunk[ "specularmap_pars_fragment" ],
175 |
176 | "const float unit = 255.0/256.0;",
177 |
178 | "float vec3_to_float( vec3 data ) {",
179 |
180 | "highp float compressed = fract( data.x * unit ) + floor( data.y * unit * 255.0 ) + floor( data.z * unit * 255.0 ) * 255.0;",
181 | "return compressed;",
182 |
183 | "}",
184 |
185 | "void main() {",
186 |
187 | "const float opacity = 1.0;",
188 |
189 | "gl_FragColor = vec4( diffuse, opacity );",
190 |
191 | THREE.ShaderChunk[ "map_fragment" ],
192 | THREE.ShaderChunk[ "alphatest_fragment" ],
193 | THREE.ShaderChunk[ "specularmap_fragment" ],
194 | THREE.ShaderChunk[ "lightmap_fragment" ],
195 | THREE.ShaderChunk[ "color_fragment" ],
196 |
197 | "#ifdef USE_ENVMAP",
198 |
199 | "vec2 texCoord = gl_FragCoord.xy / vec2( viewWidth, viewHeight );",
200 | "vec4 normalDepth = texture2D( samplerNormalDepth, texCoord );",
201 | "vec3 normal = normalDepth.xyz * 2.0 - 1.0;",
202 |
203 | "vec3 reflectVec;",
204 |
205 | "vec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );",
206 |
207 | "if ( useRefract ) {",
208 |
209 | "reflectVec = refract( cameraToVertex, normal, refractionRatio );",
210 |
211 | "} else { ",
212 |
213 | "reflectVec = reflect( cameraToVertex, normal );",
214 |
215 | "}",
216 |
217 | "#ifdef DOUBLE_SIDED",
218 |
219 | "float flipNormal = ( -1.0 + 2.0 * float( gl_FrontFacing ) );",
220 | "vec4 cubeColor = textureCube( envMap, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );",
221 |
222 | "#else",
223 |
224 | "vec4 cubeColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );",
225 |
226 | "#endif",
227 |
228 | "#ifdef GAMMA_INPUT",
229 |
230 | "cubeColor.xyz *= cubeColor.xyz;",
231 |
232 | "#endif",
233 |
234 | "if ( combine == 1 ) {",
235 |
236 | "gl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularStrength * reflectivity );",
237 |
238 | "} else if ( combine == 2 ) {",
239 |
240 | "gl_FragColor.xyz += cubeColor.xyz * specularStrength * reflectivity;",
241 |
242 | "} else {",
243 |
244 | "gl_FragColor.xyz = mix( gl_FragColor.xyz, gl_FragColor.xyz * cubeColor.xyz, specularStrength * reflectivity );",
245 |
246 | "}",
247 |
248 | "#endif",
249 |
250 | THREE.ShaderChunk[ "shadowmap_fragment" ],
251 | THREE.ShaderChunk[ "fog_fragment" ],
252 |
253 | //
254 |
255 | "const float compressionScale = 0.999;",
256 |
257 | //
258 |
259 | "vec3 diffuseMapColor;",
260 |
261 | "#ifdef USE_MAP",
262 |
263 | "diffuseMapColor = texelColor.xyz;",
264 |
265 | "#else",
266 |
267 | "diffuseMapColor = vec3( 1.0 );",
268 |
269 | "#endif",
270 |
271 | // diffuse color
272 |
273 | "gl_FragColor.x = vec3_to_float( compressionScale * gl_FragColor.xyz );",
274 |
275 | // specular color
276 |
277 | "if ( additiveSpecular < 0.0 ) {",
278 |
279 | "gl_FragColor.y = vec3_to_float( compressionScale * specular );",
280 |
281 | "} else {",
282 |
283 | "gl_FragColor.y = vec3_to_float( compressionScale * specular * diffuseMapColor );",
284 |
285 | "}",
286 |
287 | "gl_FragColor.y *= additiveSpecular;",
288 |
289 | // shininess
290 |
291 | "gl_FragColor.z = wrapAround * shininess;",
292 |
293 | // emissive color
294 |
295 | "#ifdef USE_COLOR",
296 |
297 | "gl_FragColor.w = vec3_to_float( compressionScale * emissive * diffuseMapColor * vColor );",
298 |
299 | "#else",
300 |
301 | "gl_FragColor.w = vec3_to_float( compressionScale * emissive * diffuseMapColor );",
302 |
303 | "#endif",
304 |
305 | "}"
306 |
307 | ].join("\n"),
308 |
309 | vertexShader : [
310 |
311 | THREE.ShaderChunk[ "map_pars_vertex" ],
312 | THREE.ShaderChunk[ "lightmap_pars_vertex" ],
313 | THREE.ShaderChunk[ "color_pars_vertex" ],
314 | THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
315 | THREE.ShaderChunk[ "skinning_pars_vertex" ],
316 | THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
317 |
318 | "#ifdef USE_ENVMAP",
319 |
320 | "varying vec3 vWorldPosition;",
321 |
322 | "#endif",
323 |
324 | "void main() {",
325 |
326 | THREE.ShaderChunk[ "map_vertex" ],
327 | THREE.ShaderChunk[ "lightmap_vertex" ],
328 | THREE.ShaderChunk[ "color_vertex" ],
329 |
330 | THREE.ShaderChunk[ "skinbase_vertex" ],
331 |
332 | THREE.ShaderChunk[ "morphtarget_vertex" ],
333 | THREE.ShaderChunk[ "skinning_vertex" ],
334 | THREE.ShaderChunk[ "default_vertex" ],
335 |
336 | THREE.ShaderChunk[ "worldpos_vertex" ],
337 | THREE.ShaderChunk[ "shadowmap_vertex" ],
338 |
339 | "#ifdef USE_ENVMAP",
340 |
341 | "vWorldPosition = worldPosition.xyz;",
342 |
343 | "#endif",
344 |
345 | "}"
346 |
347 | ].join("\n")
348 |
349 | },
350 |
351 | "normalDepth" : {
352 |
353 | uniforms: {
354 |
355 | bumpMap: { type: "t", value: null },
356 | bumpScale: { type: "f", value: 1 },
357 | offsetRepeat: { type: "v4", value: new THREE.Vector4( 0, 0, 1, 1 ) }
358 |
359 | },
360 |
361 | fragmentShader : [
362 |
363 | "#ifdef USE_BUMPMAP",
364 |
365 | "#extension GL_OES_standard_derivatives : enable\n",
366 |
367 | "varying vec2 vUv;",
368 | "varying vec3 vViewPosition;",
369 |
370 | THREE.ShaderChunk[ "bumpmap_pars_fragment" ],
371 |
372 | "#endif",
373 |
374 | "varying vec3 normalView;",
375 | "varying vec4 clipPos;",
376 |
377 | "void main() {",
378 |
379 | "vec3 normal = normalize( normalView );",
380 |
381 | "#ifdef USE_BUMPMAP",
382 |
383 | "normal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );",
384 |
385 | "#endif",
386 |
387 | "gl_FragColor.xyz = normal * 0.5 + 0.5;",
388 | "gl_FragColor.w = clipPos.z / clipPos.w;",
389 |
390 | "}"
391 |
392 | ].join("\n"),
393 |
394 | vertexShader : [
395 |
396 | "varying vec3 normalView;",
397 | "varying vec4 clipPos;",
398 |
399 | "#ifdef USE_BUMPMAP",
400 |
401 | "varying vec2 vUv;",
402 | "varying vec3 vViewPosition;",
403 |
404 | "uniform vec4 offsetRepeat;",
405 |
406 | "#endif",
407 |
408 | THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
409 | THREE.ShaderChunk[ "skinning_pars_vertex" ],
410 |
411 | "void main() {",
412 |
413 | THREE.ShaderChunk[ "morphnormal_vertex" ],
414 | THREE.ShaderChunk[ "skinbase_vertex" ],
415 | THREE.ShaderChunk[ "skinnormal_vertex" ],
416 | THREE.ShaderChunk[ "defaultnormal_vertex" ],
417 |
418 | THREE.ShaderChunk[ "morphtarget_vertex" ],
419 | THREE.ShaderChunk[ "skinning_vertex" ],
420 | THREE.ShaderChunk[ "default_vertex" ],
421 |
422 | "normalView = normalize( normalMatrix * objectNormal );",
423 |
424 | "#ifdef USE_BUMPMAP",
425 |
426 | "vUv = uv * offsetRepeat.zw + offsetRepeat.xy;",
427 | "vViewPosition = -mvPosition.xyz;",
428 |
429 | "#endif",
430 |
431 | "clipPos = gl_Position;",
432 |
433 | "}"
434 |
435 | ].join("\n")
436 |
437 | },
438 |
439 | "composite" : {
440 |
441 | uniforms: {
442 |
443 | samplerLight: { type: "t", value: null },
444 | brightness: { type: "f", value: 1 }
445 |
446 | },
447 |
448 | fragmentShader : [
449 |
450 | "varying vec2 texCoord;",
451 | "uniform sampler2D samplerLight;",
452 | "uniform float brightness;",
453 |
454 | // tonemapping operators
455 | // based on John Hable's HLSL snippets
456 | // from http://filmicgames.com/archives/75
457 |
458 | "#ifdef TONEMAP_UNCHARTED",
459 |
460 | "const float A = 0.15;",
461 | "const float B = 0.50;",
462 | "const float C = 0.10;",
463 | "const float D = 0.20;",
464 | "const float E = 0.02;",
465 | "const float F = 0.30;",
466 | "const float W = 11.2;",
467 |
468 | "vec3 Uncharted2Tonemap( vec3 x ) {",
469 |
470 | "return ( ( x * ( A * x + C * B ) + D * E ) / ( x * ( A * x + B ) + D * F ) ) - E / F;",
471 |
472 | "}",
473 |
474 | "#endif",
475 |
476 | "void main() {",
477 |
478 | "vec3 inColor = texture2D( samplerLight, texCoord ).xyz;",
479 | "inColor *= brightness;",
480 |
481 | "vec3 outColor;",
482 |
483 | "#if defined( TONEMAP_SIMPLE )",
484 |
485 | "outColor = sqrt( inColor );",
486 |
487 | "#elif defined( TONEMAP_LINEAR )",
488 |
489 | // simple linear to gamma conversion
490 |
491 | "outColor = pow( inColor, vec3( 1.0 / 2.2 ) );",
492 |
493 | "#elif defined( TONEMAP_REINHARD )",
494 |
495 | // Reinhard operator
496 |
497 | "inColor = inColor / ( 1.0 + inColor );",
498 | "outColor = pow( inColor, vec3( 1.0 / 2.2 ) );",
499 |
500 | "#elif defined( TONEMAP_FILMIC )",
501 |
502 | // filmic operator by Jim Hejl and Richard Burgess-Dawson
503 |
504 | "vec3 x = max( vec3( 0.0 ), inColor - 0.004 );",
505 | "outColor = ( x * ( 6.2 * x + 0.5 ) ) / ( x * ( 6.2 * x + 1.7 ) + 0.06 );",
506 |
507 | "#elif defined( TONEMAP_UNCHARTED )",
508 |
509 | // tonemapping operator from Uncharted 2 by John Hable
510 |
511 | "float ExposureBias = 2.0;",
512 | "vec3 curr = Uncharted2Tonemap( ExposureBias * inColor );",
513 |
514 | "vec3 whiteScale = vec3( 1.0 ) / Uncharted2Tonemap( vec3( W ) );",
515 | "vec3 color = curr * whiteScale;",
516 |
517 | "outColor = pow( color, vec3( 1.0 / 2.2 ) );",
518 |
519 | "#else",
520 |
521 | "outColor = inColor;",
522 |
523 | "#endif",
524 |
525 | "gl_FragColor = vec4( outColor, 1.0 );",
526 |
527 | "}"
528 |
529 | ].join("\n"),
530 |
531 | vertexShader : [
532 |
533 | "varying vec2 texCoord;",
534 |
535 | "void main() {",
536 |
537 | "vec4 pos = vec4( sign( position.xy ), 0.0, 1.0 );",
538 | "texCoord = pos.xy * vec2( 0.5 ) + 0.5;",
539 | "gl_Position = pos;",
540 |
541 | "}"
542 |
543 | ].join("\n")
544 |
545 | },
546 |
547 | "pointLight" : {
548 |
549 | uniforms: {
550 |
551 | samplerNormalDepth: { type: "t", value: null },
552 | samplerColor: { type: "t", value: null },
553 | matProjInverse: { type: "m4", value: new THREE.Matrix4() },
554 | viewWidth: { type: "f", value: 800 },
555 | viewHeight: { type: "f", value: 600 },
556 |
557 | lightPositionVS:{ type: "v3", value: new THREE.Vector3( 0, 0, 0 ) },
558 | lightColor: { type: "c", value: new THREE.Color( 0x000000 ) },
559 | lightIntensity: { type: "f", value: 1.0 },
560 | lightRadius: { type: "f", value: 1.0 }
561 |
562 | },
563 |
564 | fragmentShader : [
565 |
566 | "uniform sampler2D samplerColor;",
567 | "uniform sampler2D samplerNormalDepth;",
568 |
569 | "uniform float lightRadius;",
570 | "uniform float lightIntensity;",
571 | "uniform float viewHeight;",
572 | "uniform float viewWidth;",
573 |
574 | "uniform vec3 lightColor;",
575 | "uniform vec3 lightPositionVS;",
576 |
577 | "uniform mat4 matProjInverse;",
578 |
579 | THREE.DeferredShaderChunk[ "unpackFloat" ],
580 |
581 | "void main() {",
582 |
583 | THREE.DeferredShaderChunk[ "computeVertexPositionVS" ],
584 |
585 | // bail out early when pixel outside of light sphere
586 |
587 | "vec3 lightVector = lightPositionVS - vertexPositionVS.xyz;",
588 | "float distance = length( lightVector );",
589 |
590 | "if ( distance > lightRadius ) discard;",
591 |
592 | THREE.DeferredShaderChunk[ "computeNormal" ],
593 | THREE.DeferredShaderChunk[ "unpackColorMap" ],
594 |
595 | // compute light
596 |
597 | "lightVector = normalize( lightVector );",
598 |
599 | THREE.DeferredShaderChunk[ "computeDiffuse" ],
600 | THREE.DeferredShaderChunk[ "computeSpecular" ],
601 |
602 | // combine
603 |
604 | "float cutoff = 0.3;",
605 | "float denom = distance / lightRadius + 1.0;",
606 | "float attenuation = 1.0 / ( denom * denom );",
607 | "attenuation = ( attenuation - cutoff ) / ( 1.0 - cutoff );",
608 | "attenuation = max( attenuation, 0.0 );",
609 | "attenuation *= attenuation;",
610 |
611 | THREE.DeferredShaderChunk[ "combine" ],
612 |
613 | "}"
614 |
615 | ].join("\n"),
616 |
617 | vertexShader : [
618 |
619 | "void main() { ",
620 |
621 | // sphere proxy needs real position
622 |
623 | "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
624 | "gl_Position = projectionMatrix * mvPosition;",
625 |
626 | "}"
627 |
628 | ].join("\n")
629 |
630 | },
631 |
632 | "spotLight" : {
633 |
634 | uniforms: {
635 |
636 | samplerNormalDepth: { type: "t", value: null },
637 | samplerColor: { type: "t", value: null },
638 | matProjInverse: { type: "m4", value: new THREE.Matrix4() },
639 | viewWidth: { type: "f", value: 800 },
640 | viewHeight: { type: "f", value: 600 },
641 |
642 | lightPositionVS :{ type: "v3", value: new THREE.Vector3( 0, 1, 0 ) },
643 | lightDirectionVS:{ type: "v3", value: new THREE.Vector3( 0, 1, 0 ) },
644 | lightColor: { type: "c", value: new THREE.Color( 0x000000 ) },
645 | lightIntensity: { type: "f", value: 1.0 },
646 | lightDistance: { type: "f", value: 1.0 },
647 | lightAngle: { type: "f", value: 1.0 }
648 |
649 | },
650 |
651 | fragmentShader : [
652 |
653 | "uniform vec3 lightPositionVS;",
654 | "uniform vec3 lightDirectionVS;",
655 |
656 | "uniform sampler2D samplerColor;",
657 | "uniform sampler2D samplerNormalDepth;",
658 |
659 | "uniform float viewHeight;",
660 | "uniform float viewWidth;",
661 |
662 | "uniform float lightAngle;",
663 | "uniform float lightIntensity;",
664 | "uniform vec3 lightColor;",
665 |
666 | "uniform mat4 matProjInverse;",
667 |
668 | THREE.DeferredShaderChunk[ "unpackFloat" ],
669 |
670 | "void main() {",
671 |
672 | THREE.DeferredShaderChunk[ "computeVertexPositionVS" ],
673 | THREE.DeferredShaderChunk[ "computeNormal" ],
674 | THREE.DeferredShaderChunk[ "unpackColorMap" ],
675 |
676 | // compute light
677 |
678 | "vec3 lightVector = normalize( lightPositionVS.xyz - vertexPositionVS.xyz );",
679 |
680 | "float rho = dot( lightDirectionVS, lightVector );",
681 | "float rhoMax = cos( lightAngle * 0.5 );",
682 |
683 | "if ( rho <= rhoMax ) discard;",
684 |
685 | "float theta = rhoMax + 0.0001;",
686 | "float phi = rhoMax + 0.05;",
687 | "float falloff = 4.0;",
688 |
689 | "float spot = 0.0;",
690 |
691 | "if ( rho >= phi ) {",
692 |
693 | "spot = 1.0;",
694 |
695 | "} else if ( rho <= theta ) {",
696 |
697 | "spot = 0.0;",
698 |
699 | "} else { ",
700 |
701 | "spot = pow( ( rho - theta ) / ( phi - theta ), falloff );",
702 |
703 | "}",
704 |
705 | THREE.DeferredShaderChunk[ "computeDiffuse" ],
706 |
707 | "diffuse *= spot;",
708 |
709 | THREE.DeferredShaderChunk[ "computeSpecular" ],
710 |
711 | // combine
712 |
713 | "const float attenuation = 1.0;",
714 |
715 | THREE.DeferredShaderChunk[ "combine" ],
716 |
717 | "}"
718 |
719 | ].join("\n"),
720 |
721 | vertexShader : [
722 |
723 | "void main() { ",
724 |
725 | // full screen quad proxy
726 |
727 | "gl_Position = vec4( sign( position.xy ), 0.0, 1.0 );",
728 |
729 | "}"
730 |
731 | ].join("\n")
732 |
733 | },
734 |
735 | "directionalLight" : {
736 |
737 | uniforms: {
738 |
739 | samplerNormalDepth: { type: "t", value: null },
740 | samplerColor: { type: "t", value: null },
741 | matProjInverse: { type: "m4", value: new THREE.Matrix4() },
742 | viewWidth: { type: "f", value: 800 },
743 | viewHeight: { type: "f", value: 600 },
744 |
745 | lightDirectionVS: { type: "v3", value: new THREE.Vector3( 0, 1, 0 ) },
746 | lightColor: { type: "c", value: new THREE.Color( 0x000000 ) },
747 | lightIntensity: { type: "f", value: 1.0 }
748 |
749 | },
750 |
751 | fragmentShader : [
752 |
753 | "uniform sampler2D samplerColor;",
754 | "uniform sampler2D samplerNormalDepth;",
755 |
756 | "uniform float lightRadius;",
757 | "uniform float lightIntensity;",
758 | "uniform float viewHeight;",
759 | "uniform float viewWidth;",
760 |
761 | "uniform vec3 lightColor;",
762 | "uniform vec3 lightDirectionVS;",
763 |
764 | "uniform mat4 matProjInverse;",
765 |
766 | THREE.DeferredShaderChunk[ "unpackFloat" ],
767 |
768 | "void main() {",
769 |
770 | THREE.DeferredShaderChunk[ "computeVertexPositionVS" ],
771 | THREE.DeferredShaderChunk[ "computeNormal" ],
772 | THREE.DeferredShaderChunk[ "unpackColorMap" ],
773 |
774 | // compute light
775 |
776 | "vec3 lightVector = lightDirectionVS;",
777 |
778 | THREE.DeferredShaderChunk[ "computeDiffuse" ],
779 | THREE.DeferredShaderChunk[ "computeSpecular" ],
780 |
781 | // combine
782 |
783 | "const float attenuation = 1.0;",
784 |
785 | THREE.DeferredShaderChunk[ "combine" ],
786 |
787 | "}"
788 |
789 | ].join("\n"),
790 |
791 | vertexShader : [
792 |
793 | "void main() { ",
794 |
795 | // full screen quad proxy
796 |
797 | "gl_Position = vec4( sign( position.xy ), 0.0, 1.0 );",
798 |
799 | "}"
800 |
801 | ].join("\n")
802 |
803 | },
804 |
805 | "hemisphereLight" : {
806 |
807 | uniforms: {
808 |
809 | samplerNormalDepth: { type: "t", value: null },
810 | samplerColor: { type: "t", value: null },
811 | matProjInverse: { type: "m4", value: new THREE.Matrix4() },
812 | viewWidth: { type: "f", value: 800 },
813 | viewHeight: { type: "f", value: 600 },
814 |
815 | lightDirectionVS: { type: "v3", value: new THREE.Vector3( 0, 1, 0 ) },
816 | lightColorSky: { type: "c", value: new THREE.Color( 0x000000 ) },
817 | lightColorGround: { type: "c", value: new THREE.Color( 0x000000 ) },
818 | lightIntensity: { type: "f", value: 1.0 }
819 |
820 | },
821 |
822 | fragmentShader : [
823 |
824 | "uniform sampler2D samplerColor;",
825 | "uniform sampler2D samplerNormalDepth;",
826 |
827 | "uniform float lightRadius;",
828 | "uniform float lightIntensity;",
829 | "uniform float viewHeight;",
830 | "uniform float viewWidth;",
831 |
832 | "uniform vec3 lightColorSky;",
833 | "uniform vec3 lightColorGround;",
834 | "uniform vec3 lightDirectionVS;",
835 |
836 | "uniform mat4 matProjInverse;",
837 |
838 | THREE.DeferredShaderChunk[ "unpackFloat" ],
839 |
840 | "void main() {",
841 |
842 | THREE.DeferredShaderChunk[ "computeVertexPositionVS" ],
843 | THREE.DeferredShaderChunk[ "computeNormal" ],
844 | THREE.DeferredShaderChunk[ "unpackColorMap" ],
845 |
846 | // compute light
847 |
848 | "vec3 lightVector = lightDirectionVS;",
849 |
850 | // diffuse
851 |
852 | "float dotProduct = dot( normal, lightVector );",
853 | "float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;",
854 |
855 | "vec3 hemiColor = mix( lightColorGround, lightColorSky, hemiDiffuseWeight );",
856 |
857 | "vec3 diffuse = hemiColor;",
858 |
859 | // specular (sky light)
860 |
861 | "vec3 hemiHalfVectorSky = normalize( lightVector - vertexPositionVS.xyz );",
862 | "float hemiDotNormalHalfSky = 0.5 * dot( normal, hemiHalfVectorSky ) + 0.5;",
863 | "float hemiSpecularWeightSky = max( pow( hemiDotNormalHalfSky, shininess ), 0.0 );",
864 |
865 | // specular (ground light)
866 |
867 | "vec3 lVectorGround = -lightVector;",
868 |
869 | "vec3 hemiHalfVectorGround = normalize( lVectorGround - vertexPositionVS.xyz );",
870 | "float hemiDotNormalHalfGround = 0.5 * dot( normal, hemiHalfVectorGround ) + 0.5;",
871 | "float hemiSpecularWeightGround = max( pow( hemiDotNormalHalfGround, shininess ), 0.0 );",
872 |
873 | "float dotProductGround = dot( normal, lVectorGround );",
874 |
875 | "float specularNormalization = ( shininess + 2.0001 ) / 8.0;",
876 |
877 | "vec3 schlickSky = specularColor + vec3( 1.0 - specularColor ) * pow( 1.0 - dot( lightVector, hemiHalfVectorSky ), 5.0 );",
878 | "vec3 schlickGround = specularColor + vec3( 1.0 - specularColor ) * pow( 1.0 - dot( lVectorGround, hemiHalfVectorGround ), 5.0 );",
879 | "vec3 specular = hemiColor * specularNormalization * ( schlickSky * hemiSpecularWeightSky * max( dotProduct, 0.0 ) + schlickGround * hemiSpecularWeightGround * max( dotProductGround, 0.0 ) );",
880 |
881 | // combine
882 |
883 | "gl_FragColor = vec4( lightIntensity * ( albedo * diffuse + specular ), 1.0 );",
884 |
885 | "}"
886 |
887 | ].join("\n"),
888 |
889 | vertexShader : [
890 |
891 | "void main() { ",
892 |
893 | // full screen quad proxy
894 |
895 | "gl_Position = vec4( sign( position.xy ), 0.0, 1.0 );",
896 |
897 | "}"
898 |
899 | ].join("\n")
900 |
901 | },
902 |
903 | "areaLight" : {
904 |
905 | uniforms: {
906 |
907 | samplerNormalDepth: { type: "t", value: null },
908 | samplerColor: { type: "t", value: null },
909 | matProjInverse: { type: "m4", value: new THREE.Matrix4() },
910 | viewWidth: { type: "f", value: 800 },
911 | viewHeight: { type: "f", value: 600 },
912 |
913 | lightPositionVS: { type: "v3", value: new THREE.Vector3( 0, 1, 0 ) },
914 | lightNormalVS: { type: "v3", value: new THREE.Vector3( 0, -1, 0 ) },
915 | lightRightVS: { type: "v3", value: new THREE.Vector3( 1, 0, 0 ) },
916 | lightUpVS: { type: "v3", value: new THREE.Vector3( 1, 0, 0 ) },
917 |
918 | lightColor: { type: "c", value: new THREE.Color( 0x000000 ) },
919 | lightIntensity: { type: "f", value: 1.0 },
920 |
921 | lightWidth: { type: "f", value: 1.0 },
922 | lightHeight: { type: "f", value: 1.0 },
923 |
924 | constantAttenuation: { type: "f", value: 1.5 },
925 | linearAttenuation: { type: "f", value: 0.5 },
926 | quadraticAttenuation: { type: "f", value: 0.1 }
927 |
928 | },
929 |
930 | fragmentShader : [
931 |
932 | "uniform vec3 lightPositionVS;",
933 | "uniform vec3 lightNormalVS;",
934 | "uniform vec3 lightRightVS;",
935 | "uniform vec3 lightUpVS;",
936 |
937 | "uniform sampler2D samplerColor;",
938 | "uniform sampler2D samplerNormalDepth;",
939 |
940 | "uniform float lightWidth;",
941 | "uniform float lightHeight;",
942 |
943 | "uniform float constantAttenuation;",
944 | "uniform float linearAttenuation;",
945 | "uniform float quadraticAttenuation;",
946 |
947 | "uniform float lightIntensity;",
948 | "uniform vec3 lightColor;",
949 |
950 | "uniform float viewHeight;",
951 | "uniform float viewWidth;",
952 |
953 | "uniform mat4 matProjInverse;",
954 |
955 | THREE.DeferredShaderChunk[ "unpackFloat" ],
956 |
957 | "vec3 projectOnPlane( vec3 point, vec3 planeCenter, vec3 planeNorm ) {",
958 |
959 | "return point - dot( point - planeCenter, planeNorm ) * planeNorm;",
960 |
961 | "}",
962 |
963 | "bool sideOfPlane( vec3 point, vec3 planeCenter, vec3 planeNorm ) {",
964 |
965 | "return ( dot( point - planeCenter, planeNorm ) >= 0.0 );",
966 |
967 | "}",
968 |
969 | "vec3 linePlaneIntersect( vec3 lp, vec3 lv, vec3 pc, vec3 pn ) {",
970 |
971 | "return lp + lv * ( dot( pn, pc - lp ) / dot( pn, lv ) );",
972 |
973 | "}",
974 |
975 | "float calculateAttenuation( float dist ) {",
976 |
977 | "return ( 1.0 / ( constantAttenuation + linearAttenuation * dist + quadraticAttenuation * dist * dist ) );",
978 |
979 | "}",
980 |
981 | "void main() {",
982 |
983 | THREE.DeferredShaderChunk[ "computeVertexPositionVS" ],
984 | THREE.DeferredShaderChunk[ "computeNormal" ],
985 | THREE.DeferredShaderChunk[ "unpackColorMap" ],
986 |
987 | "float w = lightWidth;",
988 | "float h = lightHeight;",
989 |
990 | "vec3 proj = projectOnPlane( vertexPositionVS.xyz, lightPositionVS, lightNormalVS );",
991 | "vec3 dir = proj - lightPositionVS;",
992 |
993 | "vec2 diagonal = vec2( dot( dir, lightRightVS ), dot( dir, lightUpVS ) );",
994 | "vec2 nearest2D = vec2( clamp( diagonal.x, -w, w ), clamp( diagonal.y, -h, h ) );",
995 | "vec3 nearestPointInside = vec3( lightPositionVS ) + ( lightRightVS * nearest2D.x + lightUpVS * nearest2D.y );",
996 |
997 | "vec3 lightDir = normalize( nearestPointInside - vertexPositionVS.xyz );",
998 | "float NdotL = max( dot( lightNormalVS, -lightDir ), 0.0 );",
999 | "float NdotL2 = max( dot( normal, lightDir ), 0.0 );",
1000 |
1001 | //"if ( NdotL2 * NdotL > 0.0 && sideOfPlane( vertexPositionVS.xyz, lightPositionVS, lightNormalVS ) ) {",
1002 | "if ( NdotL2 * NdotL > 0.0 ) {",
1003 |
1004 | // diffuse
1005 |
1006 | "vec3 diffuse = vec3( sqrt( NdotL * NdotL2 ) );",
1007 |
1008 | // specular
1009 |
1010 | "vec3 specular = vec3( 0.0 );",
1011 |
1012 | "vec3 R = reflect( normalize( -vertexPositionVS.xyz ), normal );",
1013 | "vec3 E = linePlaneIntersect( vertexPositionVS.xyz, R, vec3( lightPositionVS ), lightNormalVS );",
1014 |
1015 | "float specAngle = dot( R, lightNormalVS );",
1016 |
1017 | "if ( specAngle > 0.0 ) {",
1018 |
1019 | "vec3 dirSpec = E - vec3( lightPositionVS );",
1020 | "vec2 dirSpec2D = vec2( dot( dirSpec, lightRightVS ), dot( dirSpec, lightUpVS ) );",
1021 | "vec2 nearestSpec2D = vec2( clamp( dirSpec2D.x, -w, w ), clamp( dirSpec2D.y, -h, h ) );",
1022 | "float specFactor = 1.0 - clamp( length( nearestSpec2D - dirSpec2D ) * 0.05 * shininess, 0.0, 1.0 );",
1023 | "specular = specularColor * specFactor * specAngle * diffuse;",
1024 |
1025 | "}",
1026 |
1027 | // combine
1028 |
1029 | "float dist = distance( vertexPositionVS.xyz, nearestPointInside );",
1030 | "float attenuation = calculateAttenuation( dist );",
1031 |
1032 | THREE.DeferredShaderChunk[ "combine" ],
1033 |
1034 | "} else {",
1035 |
1036 | "discard;",
1037 |
1038 | "}",
1039 |
1040 | "}"
1041 |
1042 | ].join("\n"),
1043 |
1044 | vertexShader : [
1045 |
1046 | "void main() {",
1047 |
1048 | // full screen quad proxy
1049 |
1050 | "gl_Position = vec4( sign( position.xy ), 0.0, 1.0 );",
1051 |
1052 | "}"
1053 |
1054 | ].join("\n")
1055 |
1056 | },
1057 |
1058 | "emissiveLight" : {
1059 |
1060 | uniforms: {
1061 |
1062 | samplerColor: { type: "t", value: null },
1063 | viewWidth: { type: "f", value: 800 },
1064 | viewHeight: { type: "f", value: 600 },
1065 |
1066 | },
1067 |
1068 | fragmentShader : [
1069 |
1070 | "uniform sampler2D samplerColor;",
1071 |
1072 | "uniform float viewHeight;",
1073 | "uniform float viewWidth;",
1074 |
1075 | THREE.DeferredShaderChunk[ "unpackFloat" ],
1076 |
1077 | "void main() {",
1078 |
1079 | "vec2 texCoord = gl_FragCoord.xy / vec2( viewWidth, viewHeight );",
1080 |
1081 | "vec4 colorMap = texture2D( samplerColor, texCoord );",
1082 | "vec3 emissiveColor = float_to_vec3( abs( colorMap.w ) );",
1083 |
1084 | "gl_FragColor = vec4( emissiveColor, 1.0 );",
1085 |
1086 | "}"
1087 |
1088 | ].join("\n"),
1089 |
1090 | vertexShader : [
1091 |
1092 | "void main() { ",
1093 |
1094 | // full screen quad proxy
1095 |
1096 | "gl_Position = vec4( sign( position.xy ), 0.0, 1.0 );",
1097 |
1098 | "}"
1099 |
1100 | ].join("\n")
1101 |
1102 | }
1103 |
1104 | };
1105 |
--------------------------------------------------------------------------------
/libs/ShaderPass.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author alteredq / http://alteredqualia.com/
3 | */
4 |
5 | THREE.ShaderPass = function ( shader, textureID ) {
6 |
7 | this.textureID = ( textureID !== undefined ) ? textureID : "tDiffuse";
8 |
9 | this.uniforms = THREE.UniformsUtils.clone( shader.uniforms );
10 |
11 | this.material = new THREE.ShaderMaterial( {
12 |
13 | uniforms: this.uniforms,
14 | vertexShader: shader.vertexShader,
15 | fragmentShader: shader.fragmentShader
16 |
17 | } );
18 |
19 | this.renderToScreen = false;
20 |
21 | this.enabled = true;
22 | this.needsSwap = true;
23 | this.clear = false;
24 |
25 | };
26 |
27 | THREE.ShaderPass.prototype = {
28 |
29 | render: function ( renderer, writeBuffer, readBuffer, delta ) {
30 |
31 | if ( this.uniforms[ this.textureID ] ) {
32 |
33 | this.uniforms[ this.textureID ].value = readBuffer;
34 |
35 | }
36 |
37 | THREE.EffectComposer.quad.material = this.material;
38 |
39 | if ( this.renderToScreen ) {
40 |
41 | renderer.render( THREE.EffectComposer.scene, THREE.EffectComposer.camera );
42 |
43 | } else {
44 |
45 | renderer.render( THREE.EffectComposer.scene, THREE.EffectComposer.camera, writeBuffer, this.clear );
46 |
47 | }
48 |
49 | }
50 |
51 | };
52 |
--------------------------------------------------------------------------------
/libs/chroma.js:
--------------------------------------------------------------------------------
1 | (function(){var Color,ColorScale,K,PITHIRD,TWOPI,X,Y,Z,brewer,chroma,clip_rgb,colors,cos,css2rgb,hex2rgb,hsi2rgb,hsl2rgb,hsv2rgb,lab2lch,lab2rgb,lab_xyz,lch2lab,lch2rgb,limit,luminance,luminance_x,rgb2hex,rgb2hsi,rgb2hsl,rgb2hsv,rgb2lab,rgb2lch,rgb_xyz,root,type,unpack,xyz_lab,xyz_rgb,_ref,_ref1,_ref2,_ref3,_ref4,_ref5;root=typeof exports!=="undefined"&&exports!==null?exports:this;chroma=(_ref=root.chroma)!=null?_ref:root.chroma={};if(typeof module!=="undefined"&&module!==null){module.exports=chroma}Color=function(){function Color(x,y,z,m){var me,me_rgb,_ref1;me=this;if(x==null&&y==null&&z==null&&m==null){x=[255,0,255]}if(type(x)==="array"&&x.length===3){if(m==null){m=y}_ref1=x,x=_ref1[0],y=_ref1[1],z=_ref1[2]}if(type(x)==="string"){m="hex"}else{if(m==null){m="rgb"}}if(m==="rgb"){me._rgb=[x,y,z]}else if(m==="hsl"){me._rgb=hsl2rgb(x,y,z)}else if(m==="hsv"){me._rgb=hsv2rgb(x,y,z)}else if(m==="hex"){me._rgb=hex2rgb(x)}else if(m==="lab"){me._rgb=lab2rgb(x,y,z)}else if(m==="lch"){me._rgb=lch2rgb(x,y,z)}else if(m==="hsi"){me._rgb=hsi2rgb(x,y,z)}me_rgb=clip_rgb(me._rgb)}Color.prototype.rgb=function(){return this._rgb};Color.prototype.hex=function(){return rgb2hex(this._rgb)};Color.prototype.toString=function(){return this.hex()};Color.prototype.hsl=function(){return rgb2hsl(this._rgb)};Color.prototype.hsv=function(){return rgb2hsv(this._rgb)};Color.prototype.lab=function(){return rgb2lab(this._rgb)};Color.prototype.lch=function(){return rgb2lch(this._rgb)};Color.prototype.hsi=function(){return rgb2hsi(this._rgb)};Color.prototype.luminance=function(){return luminance(this._rgb)};Color.prototype.name=function(){var h,k;h=this.hex();for(k in chroma.colors){if(h===chroma.colors[k]){return k}}return h};Color.prototype.interpolate=function(f,col,m){var dh,hue,hue0,hue1,lbv,lbv0,lbv1,me,sat,sat0,sat1,xyz0,xyz1;me=this;if(m==null){m="rgb"}if(type(col)==="string"){col=new Color(col)}if(m==="hsl"||m==="hsv"||m==="lch"||m==="hsi"){if(m==="hsl"){xyz0=me.hsl();xyz1=col.hsl()}else if(m==="hsv"){xyz0=me.hsv();xyz1=col.hsv()}else if(m==="hsi"){xyz0=me.hsi();xyz1=col.hsi()}else if(m==="lch"){xyz0=me.lch();xyz1=col.lch()}if(m.substr(0,1)==="h"){hue0=xyz0[0],sat0=xyz0[1],lbv0=xyz0[2];hue1=xyz1[0],sat1=xyz1[1],lbv1=xyz1[2]}else{lbv0=xyz0[0],sat0=xyz0[1],hue0=xyz0[2];lbv1=xyz1[0],sat1=xyz1[1],hue1=xyz1[2]}if(!isNaN(hue0)&&!isNaN(hue1)){if(hue1>hue0&&hue1-hue0>180){dh=hue1-(hue0+360)}else if(hue1180){dh=hue1+360-hue0}else{dh=hue1-hue0}hue=hue0+f*dh}else if(!isNaN(hue0)){hue=hue0;if(lbv1===1||lbv1===0){sat=sat0}}else if(!isNaN(hue1)){hue=hue1;if(lbv0===1||lbv0===0){sat=sat1}}else{hue=void 0}if(sat==null){sat=sat0+f*(sat1-sat0)}lbv=lbv0+f*(lbv1-lbv0);if(m.substr(0,1)==="h"){return new Color(hue,sat,lbv,m)}else{return new Color(lbv,sat,hue,m)}}else if(m==="rgb"){xyz0=me._rgb;xyz1=col._rgb;return new Color(xyz0[0]+f*(xyz1[0]-xyz0[0]),xyz0[1]+f*(xyz1[1]-xyz0[1]),xyz0[2]+f*(xyz1[2]-xyz0[2]),m)}else if(m==="lab"){xyz0=me.lab();xyz1=col.lab();return new Color(xyz0[0]+f*(xyz1[0]-xyz0[0]),xyz0[1]+f*(xyz1[1]-xyz0[1]),xyz0[2]+f*(xyz1[2]-xyz0[2]),m)}else{throw"color mode "+m+" is not supported"}};Color.prototype.darken=function(amount){var lch,me;if(amount==null){amount=20}me=this;lch=me.lch();lch[0]-=amount;return chroma.lch(lch)};Color.prototype.brighten=function(amount){if(amount==null){amount=20}return this.darker(-amount)};Color.prototype.saturate=function(amount){var lch,me;if(amount==null){amount=20}me=this;lch=me.lch();lch[1]+=amount;return chroma.lch(lch)};Color.prototype.desaturate=function(amount){if(amount==null){amount=20}return this.saturate(-amount)};return Color}();hex2rgb=function(hex){var b,g,r,rgb,u;if(hex.match(/^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/)){if(hex.length===4||hex.length===7){hex=hex.substr(1)}if(hex.length===3){hex=hex.split("");hex=hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2]}u=parseInt(hex,16);r=u>>16;g=u>>8&255;b=u&255;return[r,g,b]}if(rgb=css2rgb(hex)){return rgb}throw"unknown color: "+hex};css2rgb=function(css){var hsl,i,m,rgb;if(chroma.colors!=null&&chroma.colors[css]){return hex2rgb(chroma.colors[css])}if(m=css.match(/rgb\(\s*(\-?\d+),\s*(\-?\d+)\s*,\s*(\-?\d+)\s*\)/)){return m.slice(1,4)}if(m=css.match(/rgb\(\s*(\-?\d+)%,\s*(\-?\d+)%\s*,\s*(\-?\d+)%\s*\)/)){rgb=m.slice(1,4);for(i in rgb){rgb[i]=Math.round(rgb[i]*2.55)}return rgb}if(m=css.match(/hsl\(\s*(\-?\d+),\s*(\-?\d+)%\s*,\s*(\-?\d+)%\s*\)/)){hsl=m.slice(1,4);hsl[1]*=.01;hsl[2]*=.01;return hsl2rgb(hsl)}};rgb2hex=function(){var b,g,r,str,u,_ref1;_ref1=unpack(arguments),r=_ref1[0],g=_ref1[1],b=_ref1[2];u=r<<16|g<<8|b;str="000000"+u.toString(16);return"#"+str.substr(str.length-6)};hsv2rgb=function(){var b,f,g,h,i,p,q,r,s,t,v,_ref1,_ref2,_ref3,_ref4,_ref5,_ref6,_ref7;_ref1=unpack(arguments),h=_ref1[0],s=_ref1[1],v=_ref1[2];v*=255;if(s===0){r=g=b=v}else{if(h===360){h=0}if(h>360){h-=360}if(h<0){h+=360}h/=60;i=Math.floor(h);f=h-i;p=v*(1-s);q=v*(1-s*f);t=v*(1-s*(1-f));switch(i){case 0:_ref2=[v,t,p],r=_ref2[0],g=_ref2[1],b=_ref2[2];break;case 1:_ref3=[q,v,p],r=_ref3[0],g=_ref3[1],b=_ref3[2];break;case 2:_ref4=[p,v,t],r=_ref4[0],g=_ref4[1],b=_ref4[2];break;case 3:_ref5=[p,q,v],r=_ref5[0],g=_ref5[1],b=_ref5[2];break;case 4:_ref6=[t,p,v],r=_ref6[0],g=_ref6[1],b=_ref6[2];break;case 5:_ref7=[v,p,q],r=_ref7[0],g=_ref7[1],b=_ref7[2]}}r=Math.round(r);g=Math.round(g);b=Math.round(b);return[r,g,b]};rgb2hsv=function(){var b,delta,g,h,max,min,r,s,v,_ref1;_ref1=unpack(arguments),r=_ref1[0],g=_ref1[1],b=_ref1[2];min=Math.min(r,g,b);max=Math.max(r,g,b);delta=max-min;v=max/255;if(max===0){h=void 0;s=0}else{s=delta/max;if(r===max){h=(g-b)/delta}if(g===max){h=2+(b-r)/delta}if(b===max){h=4+(r-g)/delta}h*=60;if(h<0){h+=360}}return[h,s,v]};hsl2rgb=function(){var b,c,g,h,i,l,r,s,t1,t2,t3,_i,_ref1,_ref2;_ref1=unpack(arguments),h=_ref1[0],s=_ref1[1],l=_ref1[2];if(s===0){r=g=b=l*255}else{t3=[0,0,0];c=[0,0,0];t2=l<.5?l*(1+s):l+s-l*s;t1=2*l-t2;h/=360;t3[0]=h+1/3;t3[1]=h;t3[2]=h-1/3;for(i=_i=0;_i<=2;i=++_i){if(t3[i]<0){t3[i]+=1}if(t3[i]>1){t3[i]-=1}if(6*t3[i]<1){c[i]=t1+(t2-t1)*6*t3[i]}else if(2*t3[i]<1){c[i]=t2}else if(3*t3[i]<2){c[i]=t1+(t2-t1)*(2/3-t3[i])*6}else{c[i]=t1}}_ref2=[Math.round(c[0]*255),Math.round(c[1]*255),Math.round(c[2]*255)],r=_ref2[0],g=_ref2[1],b=_ref2[2]}return[r,g,b]};rgb2hsl=function(r,g,b){var h,l,max,min,s,_ref1;if(r!==void 0&&r.length===3){_ref1=r,r=_ref1[0],g=_ref1[1],b=_ref1[2]}r/=255;g/=255;b/=255;min=Math.min(r,g,b);max=Math.max(r,g,b);l=(max+min)/2;if(max===min){s=0;h=void 0}else{s=l<.5?(max-min)/(max+min):(max-min)/(2-max-min)}if(r===max){h=(g-b)/(max-min)}else if(g===max){h=2+(b-r)/(max-min)}else if(b===max){h=4+(r-g)/(max-min)}h*=60;if(h<0){h+=360}return[h,s,l]};K=18;X=.95047;Y=1;Z=1.08883;lab2rgb=function(l,a,b){var g,r,x,y,z,_ref1,_ref2;if(l!==void 0&&l.length===3){_ref1=l,l=_ref1[0],a=_ref1[1],b=_ref1[2]}if(l!==void 0&&l.length===3){_ref2=l,l=_ref2[0],a=_ref2[1],b=_ref2[2]}y=(l+16)/116;x=y+a/500;z=y-b/200;x=lab_xyz(x)*X;y=lab_xyz(y)*Y;z=lab_xyz(z)*Z;r=xyz_rgb(3.2404542*x-1.5371385*y-.4985314*z);g=xyz_rgb(-.969266*x+1.8760108*y+.041556*z);b=xyz_rgb(.0556434*x-.2040259*y+1.0572252*z);return[limit(r,0,255),limit(g,0,255),limit(b,0,255)]};rgb2lab=function(){var b,g,r,x,y,z,_ref1;_ref1=unpack(arguments),r=_ref1[0],g=_ref1[1],b=_ref1[2];r=rgb_xyz(r);g=rgb_xyz(g);b=rgb_xyz(b);x=xyz_lab((.4124564*r+.3575761*g+.1804375*b)/X);y=xyz_lab((.2126729*r+.7151522*g+.072175*b)/Y);z=xyz_lab((.0193339*r+.119192*g+.9503041*b)/Z);return[116*y-16,500*(x-y),200*(y-z)]};lch2lab=function(){var c,h,l,_ref1;_ref1=unpack(arguments),l=_ref1[0],c=_ref1[1],h=_ref1[2];h=h*Math.PI/180;return[l,Math.cos(h)*c,Math.sin(h)*c]};lch2rgb=function(l,c,h){var L,a,b,g,r,_ref1,_ref2;_ref1=lch2lab(l,c,h),L=_ref1[0],a=_ref1[1],b=_ref1[2];_ref2=lab2rgb(L,a,b),r=_ref2[0],g=_ref2[1],b=_ref2[2];return[limit(r,0,255),limit(g,0,255),limit(b,0,255)]};lab_xyz=function(x){if(x>.206893034){return x*x*x}else{return(x-4/29)/7.787037}};xyz_lab=function(x){if(x>.008856){return Math.pow(x,1/3)}else{return 7.787037*x+4/29}};xyz_rgb=function(r){return Math.round(255*(r<=.00304?12.92*r:1.055*Math.pow(r,1/2.4)-.055))};rgb_xyz=function(r){if((r/=255)<=.04045){return r/12.92}else{return Math.pow((r+.055)/1.055,2.4)}};lab2lch=function(){var a,b,c,h,l,_ref1;_ref1=unpack(arguments),l=_ref1[0],a=_ref1[1],b=_ref1[2];c=Math.sqrt(a*a+b*b);h=Math.atan2(b,a)/Math.PI*180;return[l,c,h]};rgb2lch=function(){var a,b,g,l,r,_ref1,_ref2;_ref1=unpack(arguments),r=_ref1[0],g=_ref1[1],b=_ref1[2];_ref2=rgb2lab(r,g,b),l=_ref2[0],a=_ref2[1],b=_ref2[2];return lab2lch(l,a,b)};rgb2hsi=function(){var TWOPI,b,g,h,i,min,r,s,_ref1;_ref1=unpack(arguments),r=_ref1[0],g=_ref1[1],b=_ref1[2];TWOPI=Math.PI*2;r/=255;g/=255;b/=255;min=Math.min(r,g,b);i=(r+g+b)/3;s=1-min/i;if(s===0){h=0}else{h=(r-g+(r-b))/2;h/=Math.sqrt((r-g)*(r-g)+(r-b)*(g-b));h=Math.acos(h);if(b>g){h=TWOPI-h}h/=TWOPI}return[h*360,s,i]};hsi2rgb=function(h,s,i){var b,g,r,_ref1;_ref1=unpack(arguments),h=_ref1[0],s=_ref1[1],i=_ref1[2];h/=360;if(h<1/3){b=(1-s)/3;r=(1+s*cos(TWOPI*h)/cos(PITHIRD-TWOPI*h))/3;g=1-(b+r)}else if(h<2/3){h-=1/3;r=(1-s)/3;g=(1+s*cos(TWOPI*h)/cos(PITHIRD-TWOPI*h))/3;b=1-(r+g)}else{h-=2/3;g=(1-s)/3;b=(1+s*cos(TWOPI*h)/cos(PITHIRD-TWOPI*h))/3;r=1-(g+b)}r=limit(i*r*3);g=limit(i*g*3);b=limit(i*b*3);return[r*255,g*255,b*255]};clip_rgb=function(rgb){var i;for(i in rgb){if(rgb[i]<0){rgb[i]=0}if(rgb[i]>255){rgb[i]=255}}return rgb};luminance=function(r,g,b){var _ref1;_ref1=unpack(arguments),r=_ref1[0],g=_ref1[1],b=_ref1[2];r=luminance_x(r);g=luminance_x(g);b=luminance_x(b);return.2126*r+.7152*g+.0722*b};luminance_x=function(x){x/=255;if(x<=.03928){return x/12.92}else{return Math.pow((x+.055)/1.055,2.4)}};chroma.Color=Color;chroma.color=function(x,y,z,m){return new Color(x,y,z,m)};chroma.hsl=function(h,s,l){return new Color(h,s,l,"hsl")};chroma.hsv=function(h,s,v){return new Color(h,s,v,"hsv")};chroma.rgb=function(r,g,b){return new Color(r,g,b,"rgb")};chroma.hex=function(x){return new Color(x)};chroma.css=function(x){return new Color(x)};chroma.lab=function(l,a,b){return new Color(l,a,b,"lab")};chroma.lch=function(l,c,h){return new Color(l,c,h,"lch")};chroma.hsi=function(h,s,i){return new Color(h,s,i,"hsi")};chroma.interpolate=function(a,b,f,m){if(a==null||b==null){return"#000"}if(type(a)==="string"){a=new Color(a)}if(type(b)==="string"){b=new Color(b)}return a.interpolate(f,b,m)};chroma.contrast=function(a,b){var l1,l2;if(type(a)==="string"){a=new Color(a)}if(type(b)==="string"){b=new Color(b)}l1=a.luminance();l2=b.luminance();if(l1>l2){return(l1+.05)/(l2+.05)}else{return(l2+.05)/(l1+.05)}};root=typeof exports!=="undefined"&&exports!==null?exports:this;chroma=(_ref1=root.chroma)!=null?_ref1:root.chroma={};Color=chroma.Color;ColorScale=function(){function ColorScale(opts){var me,_ref2,_ref3;if(opts==null){opts={}}me=this;me.range(opts.colors,opts.positions);me._mode=(_ref2=opts.mode)!=null?_ref2:"rgb";me._nacol=chroma.hex((_ref3=opts.nacol)!=null?_ref3:chroma.hex("#ccc"));me.domain([0,1]);me}ColorScale.prototype.range=function(colors,positions){var c,col,me,_i,_j,_ref2,_ref3,_ref4;me=this;if(colors==null){colors=["#ddd","#222"]}if(colors!=null&&type(colors)==="string"&&((_ref2=chroma.brewer)!=null?_ref2[colors]:void 0)!=null){colors=chroma.brewer[colors].slice(0)}for(c=_i=0,_ref3=colors.length-1;0<=_ref3?_i<=_ref3:_i>=_ref3;c=0<=_ref3?++_i:--_i){col=colors[c];if(type(col)==="string"){colors[c]=new Color(col)}}me._colors=colors;if(positions!=null){me._pos=positions}else{me._pos=[];for(c=_j=0,_ref4=colors.length-1;0<=_ref4?_j<=_ref4:_j>=_ref4;c=0<=_ref4?++_j:--_j){me._pos.push(c/(colors.length-1))}}return me};ColorScale.prototype.domain=function(domain){var me;if(domain==null){domain=[]}me=this;me._domain=domain;me._min=domain[0];me._max=domain[domain.length-1];if(domain.length===2){me._numClasses=0}else{me._numClasses=domain.length-1}return me};ColorScale.prototype.get=function(value){var c,f,f0,me;me=this;if(isNaN(value)){return me._nacol}if(me._domain.length>2){c=me.getClass(value);f=c/(me._numClasses-1)}else{f=f0=(value-me._min)/(me._max-me._min);f=Math.min(1,Math.max(0,f))}return me.fColor(f)};ColorScale.prototype.fColor=function(f){var col,cols,i,me,p,_i,_ref2;me=this;cols=me._colors;for(i=_i=0,_ref2=me._pos.length-1;0<=_ref2?_i<=_ref2:_i>=_ref2;i=0<=_ref2?++_i:--_i){p=me._pos[i];if(f<=p){col=cols[i];break}if(f>=p&&i===me._pos.length-1){col=cols[i];break}if(f>p&&f2){n=domain.length-1;i=me.getClass(value);val=domain[i]+(domain[i+1]-domain[i])*.5;minc=domain[0];maxc=domain[n-1];val=me._min+(val-minc)/(maxc-minc)*(me._max-me._min)}return val};ColorScale.prototype.getClass=function(value){var domain,i,n,self;self=this;domain=self._domain;if(domain!=null){n=domain.length-1;i=0;while(i=domain[i]){i++}return i-1}return 0};ColorScale.prototype.validValue=function(value){return!isNaN(value)};return ColorScale}();chroma.ColorScale=ColorScale;chroma.scale=function(colors,positions){var colscale,f,out;colscale=new chroma.ColorScale;colscale.range(colors,positions);out=false;f=function(v){var c;c=colscale.get(v);if(out&&c[out]){return c[out]()}else{return c}};f.domain=function(domain,classes,mode,key){var d;if(mode==null){mode="e"}if(classes!=null){d=chroma.analyze(domain,key);if(classes===0){domain=[d.min,d.max]}else{domain=chroma.limits(d,mode,classes)}}colscale.domain(domain);return f};f.mode=function(_m){colscale._mode=_m;return f};f.range=function(_colors,_pos){colscale.range(_colors,_pos);return f};f.out=function(_o){out=_o;return f};f.getColor=function(val){return f(val)};return f};if((_ref2=chroma.scales)==null){chroma.scales={}}chroma.scales.cool=function(){return chroma.scale([chroma.hsl(180,1,.9),chroma.hsl(250,.7,.4)])};chroma.scales.hot=function(){return chroma.scale(["#000","#f00","#ff0","#fff"],[0,.25,.75,1]).mode("rgb")};chroma.analyze=function(data,key,filter){var add,k,r,val,visit,_i,_len;r={min:Number.MAX_VALUE,max:Number.MAX_VALUE*-1,sum:0,values:[],count:0};if(filter==null){filter=function(){return true}}add=function(val){if(val!=null&&!isNaN(val)){r.values.push(val);r.sum+=val;if(valr.max){r.max=val}r.count+=1}};visit=function(val,k){if(filter(val,k)){if(key!=null&&type(key)==="function"){return add(key(val))}else if(key!=null&&type(key)==="string"||type(key)==="number"){return add(val[key])}else{return add(val)}}};if(type(data)==="array"){for(_i=0,_len=data.length;_i<_len;_i++){val=data[_i];visit(val)}}else{for(k in data){val=data[k];visit(val,k)}}r.domain=[r.min,r.max];r.limits=function(mode,num){return chroma.limits(r,mode,num)};return r};chroma.limits=function(data,mode,num){var assignments,best,centroids,cluster,clusterSizes,dist,i,j,kClusters,limits,max,max_log,min,min_log,mindist,n,nb_iters,newCentroids,p,pb,pr,repeat,sum,tmpKMeansBreaks,value,values,_i,_j,_k,_l,_m,_n,_o,_p,_q,_r,_ref10,_ref11,_ref12,_ref13,_ref14,_ref15,_ref16,_ref17,_ref3,_ref4,_ref5,_ref6,_ref7,_ref8,_ref9,_s,_t,_u,_v,_w;if(mode==null){mode="equal"}if(num==null){num=7}if(data.values==null){data=chroma.analyze(data)}min=data.min;max=data.max;sum=data.sum;values=data.values.sort(function(a,b){return a-b});limits=[];if(mode.substr(0,1)==="c"){limits.push(min);limits.push(max)}if(mode.substr(0,1)==="e"){limits.push(min);for(i=_i=1,_ref3=num-1;1<=_ref3?_i<=_ref3:_i>=_ref3;i=1<=_ref3?++_i:--_i){limits.push(min+i/num*(max-min))}limits.push(max)}else if(mode.substr(0,1)==="l"){if(min<=0){throw"Logarithmic scales are only possible for values > 0"}min_log=Math.LOG10E*Math.log(min);max_log=Math.LOG10E*Math.log(max);limits.push(min);for(i=_j=1,_ref4=num-1;1<=_ref4?_j<=_ref4:_j>=_ref4;i=1<=_ref4?++_j:--_j){limits.push(Math.pow(10,min_log+i/num*(max_log-min_log)))}limits.push(max)}else if(mode.substr(0,1)==="q"){limits.push(min);for(i=_k=1,_ref5=num-1;1<=_ref5?_k<=_ref5:_k>=_ref5;i=1<=_ref5?++_k:--_k){p=values.length*i/num;pb=Math.floor(p);if(pb===p){limits.push(values[pb])}else{pr=p-pb;limits.push(values[pb]*pr+values[pb+1]*(1-pr))}}limits.push(max)}else if(mode.substr(0,1)==="k"){n=values.length;assignments=new Array(n);clusterSizes=new Array(num);repeat=true;nb_iters=0;centroids=null;centroids=[];centroids.push(min);for(i=_l=1,_ref6=num-1;1<=_ref6?_l<=_ref6:_l>=_ref6;i=1<=_ref6?++_l:--_l){centroids.push(min+i/num*(max-min))}centroids.push(max);while(repeat){for(j=_m=0,_ref7=num-1;0<=_ref7?_m<=_ref7:_m>=_ref7;j=0<=_ref7?++_m:--_m){clusterSizes[j]=0}for(i=_n=0,_ref8=n-1;0<=_ref8?_n<=_ref8:_n>=_ref8;i=0<=_ref8?++_n:--_n){value=values[i];mindist=Number.MAX_VALUE;for(j=_o=0,_ref9=num-1;0<=_ref9?_o<=_ref9:_o>=_ref9;j=0<=_ref9?++_o:--_o){dist=Math.abs(centroids[j]-value);if(dist=_ref10;j=0<=_ref10?++_p:--_p){newCentroids[j]=null}for(i=_q=0,_ref11=n-1;0<=_ref11?_q<=_ref11:_q>=_ref11;i=0<=_ref11?++_q:--_q){cluster=assignments[i];if(newCentroids[cluster]===null){newCentroids[cluster]=values[i]}else{newCentroids[cluster]+=values[i]}}for(j=_r=0,_ref12=num-1;0<=_ref12?_r<=_ref12:_r>=_ref12;j=0<=_ref12?++_r:--_r){newCentroids[j]*=1/clusterSizes[j]}repeat=false;for(j=_s=0,_ref13=num-1;0<=_ref13?_s<=_ref13:_s>=_ref13;j=0<=_ref13?++_s:--_s){if(newCentroids[j]!==centroids[i]){repeat=true;break}}centroids=newCentroids;nb_iters++;if(nb_iters>200){repeat=false}}kClusters={};for(j=_t=0,_ref14=num-1;0<=_ref14?_t<=_ref14:_t>=_ref14;j=0<=_ref14?++_t:--_t){kClusters[j]=[]}for(i=_u=0,_ref15=n-1;0<=_ref15?_u<=_ref15:_u>=_ref15;i=0<=_ref15?++_u:--_u){cluster=assignments[i];kClusters[cluster].push(values[i])}tmpKMeansBreaks=[];for(j=_v=0,_ref16=num-1;0<=_ref16?_v<=_ref16:_v>=_ref16;j=0<=_ref16?++_v:--_v){tmpKMeansBreaks.push(kClusters[j][0]);tmpKMeansBreaks.push(kClusters[j][kClusters[j].length-1])}tmpKMeansBreaks=tmpKMeansBreaks.sort(function(a,b){return a-b});limits.push(tmpKMeansBreaks[0]);for(i=_w=1,_ref17=tmpKMeansBreaks.length-1;_w<=_ref17;i=_w+=2){if(!isNaN(tmpKMeansBreaks[i])){limits.push(tmpKMeansBreaks[i])}}}return limits};root=typeof exports!=="undefined"&&exports!==null?exports:this;type=function(){var classToType,name,_i,_len,_ref3;classToType={};_ref3="Boolean Number String Function Array Date RegExp Undefined Null".split(" ");for(_i=0,_len=_ref3.length;_i<_len;_i++){name=_ref3[_i];classToType["[object "+name+"]"]=name.toLowerCase()}return function(obj){var strType;strType=Object.prototype.toString.call(obj);return classToType[strType]||"object"}}();if((_ref3=root.type)==null){root.type=type}Array.max=function(array){return Math.max.apply(Math,array)};Array.min=function(array){return Math.min.apply(Math,array)};limit=function(x,min,max){if(min==null){min=0}if(max==null){max=1}if(xmax){x=max}return x};unpack=function(args){if(args.length===3){return args}else{return args[0]}};TWOPI=Math.PI*2;PITHIRD=Math.PI/3;cos=Math.cos;root=typeof exports!=="undefined"&&exports!==null?exports:this;chroma=(_ref4=root.chroma)!=null?_ref4:root.chroma={};chroma.brewer=brewer={OrRd:["#fff7ec","#fee8c8","#fdd49e","#fdbb84","#fc8d59","#ef6548","#d7301f","#b30000","#7f0000"],PuBu:["#fff7fb","#ece7f2","#d0d1e6","#a6bddb","#74a9cf","#3690c0","#0570b0","#045a8d","#023858"],BuPu:["#f7fcfd","#e0ecf4","#bfd3e6","#9ebcda","#8c96c6","#8c6bb1","#88419d","#810f7c","#4d004b"],Oranges:["#fff5eb","#fee6ce","#fdd0a2","#fdae6b","#fd8d3c","#f16913","#d94801","#a63603","#7f2704"],BuGn:["#f7fcfd","#e5f5f9","#ccece6","#99d8c9","#66c2a4","#41ae76","#238b45","#006d2c","#00441b"],YlOrBr:["#ffffe5","#fff7bc","#fee391","#fec44f","#fe9929","#ec7014","#cc4c02","#993404","#662506"],YlGn:["#ffffe5","#f7fcb9","#d9f0a3","#addd8e","#78c679","#41ab5d","#238443","#006837","#004529"],Reds:["#fff5f0","#fee0d2","#fcbba1","#fc9272","#fb6a4a","#ef3b2c","#cb181d","#a50f15","#67000d"],RdPu:["#fff7f3","#fde0dd","#fcc5c0","#fa9fb5","#f768a1","#dd3497","#ae017e","#7a0177","#49006a"],Greens:["#f7fcf5","#e5f5e0","#c7e9c0","#a1d99b","#74c476","#41ab5d","#238b45","#006d2c","#00441b"],YlGnBu:["#ffffd9","#edf8b1","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#253494","#081d58"],Purples:["#fcfbfd","#efedf5","#dadaeb","#bcbddc","#9e9ac8","#807dba","#6a51a3","#54278f","#3f007d"],GnBu:["#f7fcf0","#e0f3db","#ccebc5","#a8ddb5","#7bccc4","#4eb3d3","#2b8cbe","#0868ac","#084081"],Greys:["#ffffff","#f0f0f0","#d9d9d9","#bdbdbd","#969696","#737373","#525252","#252525","#000000"],YlOrRd:["#ffffcc","#ffeda0","#fed976","#feb24c","#fd8d3c","#fc4e2a","#e31a1c","#bd0026","#800026"],PuRd:["#f7f4f9","#e7e1ef","#d4b9da","#c994c7","#df65b0","#e7298a","#ce1256","#980043","#67001f"],Blues:["#f7fbff","#deebf7","#c6dbef","#9ecae1","#6baed6","#4292c6","#2171b5","#08519c","#08306b"],PuBuGn:["#fff7fb","#ece2f0","#d0d1e6","#a6bddb","#67a9cf","#3690c0","#02818a","#016c59","#014636"],Spectral:["#9e0142","#d53e4f","#f46d43","#fdae61","#fee08b","#ffffbf","#e6f598","#abdda4","#66c2a5","#3288bd","#5e4fa2"],RdYlGn:["#a50026","#d73027","#f46d43","#fdae61","#fee08b","#ffffbf","#d9ef8b","#a6d96a","#66bd63","#1a9850","#006837"],RdBu:["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#f7f7f7","#d1e5f0","#92c5de","#4393c3","#2166ac","#053061"],PiYG:["#8e0152","#c51b7d","#de77ae","#f1b6da","#fde0ef","#f7f7f7","#e6f5d0","#b8e186","#7fbc41","#4d9221","#276419"],PRGn:["#40004b","#762a83","#9970ab","#c2a5cf","#e7d4e8","#f7f7f7","#d9f0d3","#a6dba0","#5aae61","#1b7837","#00441b"],RdYlBu:["#a50026","#d73027","#f46d43","#fdae61","#fee090","#ffffbf","#e0f3f8","#abd9e9","#74add1","#4575b4","#313695"],BrBG:["#543005","#8c510a","#bf812d","#dfc27d","#f6e8c3","#f5f5f5","#c7eae5","#80cdc1","#35978f","#01665e","#003c30"],RdGy:["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#ffffff","#e0e0e0","#bababa","#878787","#4d4d4d","#1a1a1a"],PuOr:["#7f3b08","#b35806","#e08214","#fdb863","#fee0b6","#f7f7f7","#d8daeb","#b2abd2","#8073ac","#542788","#2d004b"],Set2:["#66c2a5","#fc8d62","#8da0cb","#e78ac3","#a6d854","#ffd92f","#e5c494","#b3b3b3"],Accent:["#7fc97f","#beaed4","#fdc086","#ffff99","#386cb0","#f0027f","#bf5b17","#666666"],Set1:["#e41a1c","#377eb8","#4daf4a","#984ea3","#ff7f00","#ffff33","#a65628","#f781bf","#999999"],Set3:["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3","#fdb462","#b3de69","#fccde5","#d9d9d9","#bc80bd","#ccebc5","#ffed6f"],Dark2:["#1b9e77","#d95f02","#7570b3","#e7298a","#66a61e","#e6ab02","#a6761d","#666666"],Paired:["#a6cee3","#1f78b4","#b2df8a","#33a02c","#fb9a99","#e31a1c","#fdbf6f","#ff7f00","#cab2d6","#6a3d9a","#ffff99","#b15928"],Pastel2:["#b3e2cd","#fdcdac","#cbd5e8","#f4cae4","#e6f5c9","#fff2ae","#f1e2cc","#cccccc"],Pastel1:["#fbb4ae","#b3cde3","#ccebc5","#decbe4","#fed9a6","#ffffcc","#e5d8bd","#fddaec","#f2f2f2"]};root=typeof exports!=="undefined"&&exports!==null?exports:this;chroma=(_ref5=root.chroma)!=null?_ref5:root.chroma={};chroma.colors=colors={indigo:"#4b0082",gold:"#ffd700",hotpink:"#ff69b4",firebrick:"#b22222",indianred:"#cd5c5c",yellow:"#ffff00",mistyrose:"#ffe4e1",darkolivegreen:"#556b2f",olive:"#808000",darkseagreen:"#8fbc8f",pink:"#ffc0cb",tomato:"#ff6347",lightcoral:"#f08080",orangered:"#ff4500",navajowhite:"#ffdead",lime:"#00ff00",palegreen:"#98fb98",darkslategrey:"#2f4f4f",greenyellow:"#adff2f",burlywood:"#deb887",seashell:"#fff5ee",mediumspringgreen:"#00fa9a",fuchsia:"#ff00ff",papayawhip:"#ffefd5",blanchedalmond:"#ffebcd",chartreuse:"#7fff00",dimgray:"#696969",black:"#000000",peachpuff:"#ffdab9",springgreen:"#00ff7f",aquamarine:"#7fffd4",white:"#ffffff",orange:"#ffa500",lightsalmon:"#ffa07a",darkslategray:"#2f4f4f",brown:"#a52a2a",ivory:"#fffff0",dodgerblue:"#1e90ff",peru:"#cd853f",lawngreen:"#7cfc00",chocolate:"#d2691e",crimson:"#dc143c",forestgreen:"#228b22",darkgrey:"#a9a9a9",lightseagreen:"#20b2aa",cyan:"#00ffff",mintcream:"#f5fffa",silver:"#c0c0c0",antiquewhite:"#faebd7",mediumorchid:"#ba55d3",skyblue:"#87ceeb",gray:"#808080",darkturquoise:"#00ced1",goldenrod:"#daa520",darkgreen:"#006400",floralwhite:"#fffaf0",darkviolet:"#9400d3",darkgray:"#a9a9a9",moccasin:"#ffe4b5",saddlebrown:"#8b4513",grey:"#808080",darkslateblue:"#483d8b",lightskyblue:"#87cefa",lightpink:"#ffb6c1",mediumvioletred:"#c71585",slategrey:"#708090",red:"#ff0000",deeppink:"#ff1493",limegreen:"#32cd32",darkmagenta:"#8b008b",palegoldenrod:"#eee8aa",plum:"#dda0dd",turquoise:"#40e0d0",lightgrey:"#d3d3d3",lightgoldenrodyellow:"#fafad2",darkgoldenrod:"#b8860b",lavender:"#e6e6fa",maroon:"#800000",yellowgreen:"#9acd32",sandybrown:"#f4a460",thistle:"#d8bfd8",violet:"#ee82ee",navy:"#000080",magenta:"#ff00ff",dimgrey:"#696969",tan:"#d2b48c",rosybrown:"#bc8f8f",olivedrab:"#6b8e23",blue:"#0000ff",lightblue:"#add8e6",ghostwhite:"#f8f8ff",honeydew:"#f0fff0",cornflowerblue:"#6495ed",slateblue:"#6a5acd",linen:"#faf0e6",darkblue:"#00008b",powderblue:"#b0e0e6",seagreen:"#2e8b57",darkkhaki:"#bdb76b",snow:"#fffafa",sienna:"#a0522d",mediumblue:"#0000cd",royalblue:"#4169e1",lightcyan:"#e0ffff",green:"#008000",mediumpurple:"#9370db",midnightblue:"#191970",cornsilk:"#fff8dc",paleturquoise:"#afeeee",bisque:"#ffe4c4",slategray:"#708090",darkcyan:"#008b8b",khaki:"#f0e68c",wheat:"#f5deb3",teal:"#008080",darkorchid:"#9932cc",deepskyblue:"#00bfff",salmon:"#fa8072",darkred:"#8b0000",steelblue:"#4682b4",palevioletred:"#db7093",lightslategray:"#778899",aliceblue:"#f0f8ff",lightslategrey:"#778899",lightgreen:"#90ee90",orchid:"#da70d6",gainsboro:"#dcdcdc",mediumseagreen:"#3cb371",lightgray:"#d3d3d3",mediumturquoise:"#48d1cc",lemonchiffon:"#fffacd",cadetblue:"#5f9ea0",lightyellow:"#ffffe0",lavenderblush:"#fff0f5",coral:"#ff7f50",purple:"#800080",aqua:"#00ffff",whitesmoke:"#f5f5f5",mediumslateblue:"#7b68ee",darkorange:"#ff8c00",mediumaquamarine:"#66cdaa",darksalmon:"#e9967a",beige:"#f5f5dc",blueviolet:"#8a2be2",azure:"#f0ffff",lightsteelblue:"#b0c4de",oldlace:"#fdf5e6"}}).call(this);
--------------------------------------------------------------------------------
/libs/stats.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author mrdoob / http://mrdoob.com/
3 | */
4 |
5 | var Stats = function () {
6 |
7 | var startTime = Date.now(), prevTime = startTime;
8 | var ms = 0, msMin = Infinity, msMax = 0;
9 | var fps = 0, fpsMin = Infinity, fpsMax = 0;
10 | var frames = 0, mode = 0;
11 |
12 | var container = document.createElement( 'div' );
13 | container.id = 'stats';
14 | container.addEventListener( 'mousedown', function ( event ) { event.preventDefault(); setMode( ++ mode % 2 ) }, false );
15 | container.style.cssText = 'width:80px;opacity:0.9;cursor:pointer';
16 |
17 | var fpsDiv = document.createElement( 'div' );
18 | fpsDiv.id = 'fps';
19 | fpsDiv.style.cssText = 'padding:0 0 3px 3px;text-align:left;background-color:#002';
20 | container.appendChild( fpsDiv );
21 |
22 | var fpsText = document.createElement( 'div' );
23 | fpsText.id = 'fpsText';
24 | fpsText.style.cssText = 'color:#0ff;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px';
25 | fpsText.innerHTML = 'FPS';
26 | fpsDiv.appendChild( fpsText );
27 |
28 | var fpsGraph = document.createElement( 'div' );
29 | fpsGraph.id = 'fpsGraph';
30 | fpsGraph.style.cssText = 'position:relative;width:74px;height:30px;background-color:#0ff';
31 | fpsDiv.appendChild( fpsGraph );
32 |
33 | while ( fpsGraph.children.length < 74 ) {
34 |
35 | var bar = document.createElement( 'span' );
36 | bar.style.cssText = 'width:1px;height:30px;float:left;background-color:#113';
37 | fpsGraph.appendChild( bar );
38 |
39 | }
40 |
41 | var msDiv = document.createElement( 'div' );
42 | msDiv.id = 'ms';
43 | msDiv.style.cssText = 'padding:0 0 3px 3px;text-align:left;background-color:#020;display:none';
44 | container.appendChild( msDiv );
45 |
46 | var msText = document.createElement( 'div' );
47 | msText.id = 'msText';
48 | msText.style.cssText = 'color:#0f0;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px';
49 | msText.innerHTML = 'MS';
50 | msDiv.appendChild( msText );
51 |
52 | var msGraph = document.createElement( 'div' );
53 | msGraph.id = 'msGraph';
54 | msGraph.style.cssText = 'position:relative;width:74px;height:30px;background-color:#0f0';
55 | msDiv.appendChild( msGraph );
56 |
57 | while ( msGraph.children.length < 74 ) {
58 |
59 | var bar = document.createElement( 'span' );
60 | bar.style.cssText = 'width:1px;height:30px;float:left;background-color:#131';
61 | msGraph.appendChild( bar );
62 |
63 | }
64 |
65 | var setMode = function ( value ) {
66 |
67 | mode = value;
68 |
69 | switch ( mode ) {
70 |
71 | case 0:
72 | fpsDiv.style.display = 'block';
73 | msDiv.style.display = 'none';
74 | break;
75 | case 1:
76 | fpsDiv.style.display = 'none';
77 | msDiv.style.display = 'block';
78 | break;
79 | }
80 |
81 | }
82 |
83 | var updateGraph = function ( dom, value ) {
84 |
85 | var child = dom.appendChild( dom.firstChild );
86 | child.style.height = value + 'px';
87 |
88 | }
89 |
90 | return {
91 |
92 | REVISION: 11,
93 |
94 | domElement: container,
95 |
96 | setMode: setMode,
97 |
98 | begin: function () {
99 |
100 | startTime = Date.now();
101 |
102 | },
103 |
104 | end: function () {
105 |
106 | var time = Date.now();
107 |
108 | ms = time - startTime;
109 | msMin = Math.min( msMin, ms );
110 | msMax = Math.max( msMax, ms );
111 |
112 | msText.textContent = ms + ' MS (' + msMin + '-' + msMax + ')';
113 | updateGraph( msGraph, Math.min( 30, 30 - ( ms / 200 ) * 30 ) );
114 |
115 | frames ++;
116 |
117 | if ( time > prevTime + 1000 ) {
118 |
119 | fps = Math.round( ( frames * 1000 ) / ( time - prevTime ) );
120 | fpsMin = Math.min( fpsMin, fps );
121 | fpsMax = Math.max( fpsMax, fps );
122 |
123 | fpsText.textContent = fps + ' FPS (' + fpsMin + '-' + fpsMax + ')';
124 | updateGraph( fpsGraph, Math.min( 30, 30 - ( fps / 100 ) * 30 ) );
125 |
126 | prevTime = time;
127 | frames = 0;
128 |
129 | }
130 |
131 | return time;
132 |
133 | },
134 |
135 | update: function () {
136 |
137 | startTime = this.end();
138 |
139 | }
140 |
141 | }
142 |
143 | };
144 |
--------------------------------------------------------------------------------
/lineMaterial.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Linematerial
7 |
8 |
9 |
10 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
227 |
228 |
--------------------------------------------------------------------------------
/meshMaterial.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | meshMaterial
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
277 |
278 |
--------------------------------------------------------------------------------
/normalMap.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | normalMap
7 |
8 |
9 |
10 |
11 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
227 |
228 |
--------------------------------------------------------------------------------
/pointCloud.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | pointCloud
7 |
8 |
9 |
10 |
11 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
142 |
143 |
--------------------------------------------------------------------------------
/rainyScene.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | rainyScene
7 |
8 |
9 |
10 |
11 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
149 |
150 |
--------------------------------------------------------------------------------
/snowyScene.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | snowyScene
7 |
8 |
9 |
10 |
11 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
176 |
177 |
--------------------------------------------------------------------------------
/textGeometry.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Text geometry
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
168 |
169 |
--------------------------------------------------------------------------------