diff --git a/Chapter2/2.4.1.html b/Chapter2/2.4.1.html
index c9d7328..7282e91 100644
--- a/Chapter2/2.4.1.html
+++ b/Chapter2/2.4.1.html
@@ -13,7 +13,7 @@
// camera
// canvas size is 400x300
- var camera = new THREE.PerspectiveCamera(45, 400 / 300, 1, 10);
+ var camera = new THREE.PerspectiveCamera(60, 400 / 300, 1, 10);
camera.position.set(0, 0, 5);
scene.add(camera);
diff --git a/Chapter3/3.1.1.html b/Chapter3/3.1.1.html
index b3e9223..71d5d4e 100644
--- a/Chapter3/3.1.1.html
+++ b/Chapter3/3.1.1.html
@@ -26,15 +26,15 @@
});
drawCube(scene, material);
- //drawPlane(scene, material);
- //drawSphere(scene, material);
- //drawCircle(scene, material);
- //drawCylinder(scene, material);
- //drawTetra(scene, material);
- //drawOcta(scene, material);
- //drawIcosa(scene, material);
- //drawTorus(scene, material);
- //drawTorusKnot(scene, material);
+ // drawPlane(scene, material);
+ // drawSphere(scene, material);
+ // drawCircle(scene, material);
+ // drawCylinder(scene, material);
+ // drawTetra(scene, material);
+ // drawOcta(scene, material);
+ // drawIcosa(scene, material);
+ // drawTorus(scene, material);
+ // drawTorusKnot(scene, material);
// render
renderer.render(scene, camera);
@@ -51,12 +51,17 @@
}
function drawSphere(scene, material) {
- var sphere = new THREE.Mesh(new THREE.SphereGeometry(3, 8, 6,
- Math.PI / 6, Math.PI / 3), material);
- //var sphere = new THREE.Mesh(new THREE.SphereGeometry(3, 8, 6,
- // 0, Math.PI * 2, Math.PI / 6, Math.PI / 2), material);
- //var sphere = new THREE.Mesh(new THREE.SphereGeometry(3, 8, 6,
- // Math.PI / 2, Math.PI, Math.PI / 6, Math.PI / 2), material);
+ var sphere = new THREE.Mesh(new THREE.SphereGeometry(3, 8, 6), material);
+ // var sphere = new THREE.Mesh(new THREE.SphereGeometry(3, 8, 6,
+ // 0, Math.PI * 2, Math.PI / 6, Math.PI / 2), material);
+ // var sphere = new THREE.Mesh(new THREE.SphereGeometry(3, 8, 6,
+ // Math.PI / 2, Math.PI, Math.PI / 6, Math.PI / 2), material);
+ // var sphere = new THREE.Mesh(new THREE.SphereGeometry(3, 8, 6,
+ // Math.PI / 6, Math.PI / 3), material);
+ // var sphere = new THREE.Mesh(new THREE.SphereGeometry(3, 8, 6,
+ // 0, Math.PI * 2, Math.PI / 6, Math.PI / 3), material);
+ // var sphere = new THREE.Mesh(new THREE.SphereGeometry(3, 8, 6,
+ // Math.PI / 2, Math.PI, Math.PI / 6, Math.PI / 2), material);
scene.add(sphere);
}
@@ -67,8 +72,8 @@
function drawCylinder(scene, material) {
var cylinder = new THREE.Mesh(new THREE.CylinderGeometry(2, 2, 4, 18, 3), material);
- //var cylinder = new THREE.Mesh(new THREE.CylinderGeometry(2, 3, 4, 18, 3), material);
- //var cylinder = new THREE.Mesh(new THREE.CylinderGeometry(2, 3, 4, 18, 3, true), material);
+ // var cylinder = new THREE.Mesh(new THREE.CylinderGeometry(2, 3, 4, 18, 3), material);
+ // var cylinder = new THREE.Mesh(new THREE.CylinderGeometry(2, 3, 4, 18, 3, true), material);
scene.add(cylinder);
}
@@ -88,7 +93,9 @@
}
function drawTorus(scene, material) {
- var torus = new THREE.Mesh(new THREE.TorusGeometry(3, 1, 4, 8, Math.PI / 3 * 2), material);
+ var torus = new THREE.Mesh(new THREE.TorusGeometry(3, 1, 4, 8), material);
+ // var torus = new THREE.Mesh(new THREE.TorusGeometry(3, 1, 12, 18), material);
+ // var torus = new THREE.Mesh(new THREE.TorusGeometry(3, 1, 4, 8, Math.PI / 3 * 2), material);
scene.add(torus);
}
@@ -106,7 +113,7 @@
// x-axis
var xGeo = new THREE.Geometry();
xGeo.vertices.push(new THREE.Vector3(0, 0, 0));
- xGeo.vertices.push(new THREE.Vector3(1, 0, 0));
+ xGeo.vertices.push(new THREE.Vector3(3, 0, 0));
var xMat = new THREE.LineBasicMaterial({
color: 0xff0000
});
@@ -116,7 +123,7 @@
// y-axis
var yGeo = new THREE.Geometry();
yGeo.vertices.push(new THREE.Vector3(0, 0, 0));
- yGeo.vertices.push(new THREE.Vector3(0, 1, 0));
+ yGeo.vertices.push(new THREE.Vector3(0, 3, 0));
var yMat = new THREE.LineBasicMaterial({
color: 0x00ff00
});
@@ -126,7 +133,7 @@
// z-axis
var zGeo = new THREE.Geometry();
zGeo.vertices.push(new THREE.Vector3(0, 0, 0));
- zGeo.vertices.push(new THREE.Vector3(0, 0, 1));
+ zGeo.vertices.push(new THREE.Vector3(0, 0, 3));
var zMat = new THREE.LineBasicMaterial({
color: 0x00ccff
});
diff --git a/Chapter3/3.2.1.html b/Chapter3/3.2.1.html
index 0ccd4fd..2225a7e 100644
--- a/Chapter3/3.2.1.html
+++ b/Chapter3/3.2.1.html
@@ -2,8 +2,7 @@
-
-
+
-
+
+
+
+
+
+
+
+
+
+
diff --git a/index.html b/index.html
index 6665c30..5ba2d0f 100644
--- a/index.html
+++ b/index.html
@@ -5,7 +5,7 @@
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-38205696-1']);
_gaq.push(['_trackPageview']);
-
+
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
@@ -19,7 +19,7 @@
-
+
@@ -31,21 +31,21 @@
《Three.js 入门指南》书例代码
目录
第 1 章 概述
-
阅读原文
+
阅读原文
例 1.1.1
运行代码 | 查看代码
例 1.2.1
运行代码 | 查看代码
第 2 章 照相机
-
阅读原文
+
阅读原文
例 2.3.1
运行代码 | 查看代码
例 2.4.1
运行代码 | 查看代码
第 3 章 几何形状
-
阅读原文
+
阅读原文
例 3.1.1
运行代码 | 查看代码
例 3.2.1
@@ -54,7 +54,7 @@
例 3.3.1
运行代码 | 查看代码
第 4 章 材质
-
阅读原文
+
阅读原文
例 4.1.1
运行代码 | 查看代码
例 4.2.1
@@ -71,7 +71,7 @@
例 4.5.3
运行代码 | 查看代码
第 5 章 网格
-
阅读原文
+
阅读原文
例 5.1.1
运行代码 | 查看代码
例 5.2.1
@@ -80,7 +80,7 @@
例 5.2.2
运行代码 | 查看代码
第 6 章 动画
-
阅读原文
+
阅读原文
例 6.1.1
运行代码 | 查看代码
例 6.1.2
@@ -93,7 +93,7 @@
例 6.3.1
运行代码 | 查看代码
第 7 章 外部模型
-
阅读原文
+
阅读原文
例 7.2.1
运行代码 | 查看代码
例 7.3.1
@@ -102,7 +102,7 @@
例 7.3.2
运行代码 | 查看代码
第 8 章 光与影
-
阅读原文
+
阅读原文
例 8.1.1
运行代码 | 查看代码
例 8.1.2
@@ -119,7 +119,7 @@
例 8.5.1
运行代码 | 查看代码
第 9 章 着色器
-
阅读原文
+
阅读原文
例 9.3.1
运行代码 | 查看代码
例 9.3.2
@@ -158,7 +158,7 @@
关于作者
-
+
(0,0,1,1,0,0)
+ optimize: function() {
- var inverse = new THREE.Matrix4();
+ var times = this.times,
+ values = this.values,
+ stride = this.getValueSize(),
- inverse.getInverse( this.bones[ b ].skinMatrix );
+ writeIndex = 1;
- this.boneInverses.push( inverse );
+ for( var i = 1, n = times.length - 1; i <= n; ++ i ) {
- }
+ var keep = false;
- }
+ var time = times[ i ];
+ var timeNext = times[ i + 1 ];
- // flatten bone matrices to array
+ // remove adjacent keyframes scheduled at the same time
- for ( var b = 0, bl = this.bones.length; b < bl; b ++ ) {
+ if ( time !== timeNext && ( i !== 1 || time !== time[ 0 ] ) ) {
- // compute the offset between the current and the original transform;
+ // remove unnecessary keyframes same as their neighbors
+ var offset = i * stride,
+ offsetP = offset - stride,
+ offsetN = offset + stride;
- // TODO: we could get rid of this multiplication step if the skinMatrix
- // was already representing the offset; however, this requires some
- // major changes to the animation system
+ for ( var j = 0; j !== stride; ++ j ) {
- offsetMatrix.multiplyMatrices( this.bones[ b ].skinMatrix, this.boneInverses[ b ] );
- offsetMatrix.flattenToArrayOffset( this.boneMatrices, b * 16 );
+ var value = values[ offset + j ];
- }
+ if ( value !== values[ offsetP + j ] ||
+ value !== values[ offsetN + j ] ) {
- if ( this.useVertexTexture ) {
+ keep = true;
+ break;
- this.boneTexture.needsUpdate = true;
+ }
- }
+ }
- };
+ }
-}();
+ // in-place compaction
-THREE.SkinnedMesh.prototype.pose = function () {
+ if ( keep ) {
- this.updateMatrixWorld( true );
+ if ( i !== writeIndex ) {
- this.normalizeSkinWeights();
+ times[ writeIndex ] = times[ i ];
-};
+ var readOffset = i * stride,
+ writeOffset = writeIndex * stride;
-THREE.SkinnedMesh.prototype.normalizeSkinWeights = function () {
+ for ( var j = 0; j !== stride; ++ j ) {
- if ( this.geometry instanceof THREE.Geometry ) {
+ values[ writeOffset + j ] = values[ readOffset + j ];
- for ( var i = 0; i < this.geometry.skinIndices.length; i ++ ) {
+ }
- var sw = this.geometry.skinWeights[ i ];
- var scale = 1.0 / sw.lengthManhattan();
+ }
- if ( scale !== Infinity ) {
+ ++ writeIndex;
- sw.multiplyScalar( scale );
+ }
- } else {
+ }
- sw.set( 1 ); // this will be normalized by the shader anyway
+ if ( writeIndex !== times.length ) {
- }
+ this.times = THREE.AnimationUtils.arraySlice( times, 0, writeIndex );
+ this.values = THREE.AnimationUtils.arraySlice( values, 0, writeIndex * stride );
}
- } else {
-
- // skinning weights assumed to be normalized for THREE.BufferGeometry
+ return this;
}
};
-THREE.SkinnedMesh.prototype.clone = function ( object ) {
-
- if ( object === undefined ) {
-
- object = new THREE.SkinnedMesh( this.geometry, this.material, this.useVertexTexture );
-
- }
+// Static methods:
- THREE.Mesh.prototype.clone.call( this, object );
+Object.assign( THREE.KeyframeTrack, {
- return object;
+ // Serialization (in static context, because of constructor invocation
+ // and automatic invocation of .toJSON):
-};
+ parse: function( json ) {
-/**
- * @author alteredq / http://alteredqualia.com/
- */
+ if( json.type === undefined ) {
-THREE.MorphAnimMesh = function ( geometry, material ) {
+ throw new Error( "track type undefined, can not parse" );
- THREE.Mesh.call( this, geometry, material );
+ }
- // API
+ var trackType = THREE.KeyframeTrack._getTrackTypeForValueTypeName( json.type );
- this.duration = 1000; // milliseconds
- this.mirroredLoop = false;
- this.time = 0;
+ if ( json.times === undefined ) {
- // internals
+ var times = [], values = [];
- this.lastKeyframe = 0;
- this.currentKeyframe = 0;
+ THREE.AnimationUtils.flattenJSON( json.keys, times, values, 'value' );
- this.direction = 1;
- this.directionBackwards = false;
+ json.times = times;
+ json.values = values;
- this.setFrameRange( 0, this.geometry.morphTargets.length - 1 );
+ }
-};
+ // derived classes can define a static parse method
+ if ( trackType.parse !== undefined ) {
-THREE.MorphAnimMesh.prototype = Object.create( THREE.Mesh.prototype );
+ return trackType.parse( json );
-THREE.MorphAnimMesh.prototype.setFrameRange = function ( start, end ) {
+ } else {
- this.startKeyframe = start;
- this.endKeyframe = end;
+ // by default, we asssume a constructor compatible with the base
+ return new trackType(
+ json.name, json.times, json.values, json.interpolation );
- this.length = this.endKeyframe - this.startKeyframe + 1;
+ }
-};
+ },
-THREE.MorphAnimMesh.prototype.setDirectionForward = function () {
+ toJSON: function( track ) {
- this.direction = 1;
- this.directionBackwards = false;
+ var trackType = track.constructor;
-};
+ var json;
-THREE.MorphAnimMesh.prototype.setDirectionBackward = function () {
+ // derived classes can define a static toJSON method
+ if ( trackType.toJSON !== undefined ) {
- this.direction = -1;
- this.directionBackwards = true;
+ json = trackType.toJSON( track );
-};
+ } else {
-THREE.MorphAnimMesh.prototype.parseAnimations = function () {
+ // by default, we assume the data can be serialized as-is
+ json = {
- var geometry = this.geometry;
+ 'name': track.name,
+ 'times': THREE.AnimationUtils.convertArray( track.times, Array ),
+ 'values': THREE.AnimationUtils.convertArray( track.values, Array )
- if ( ! geometry.animations ) geometry.animations = {};
+ };
- var firstAnimation, animations = geometry.animations;
+ var interpolation = track.getInterpolation();
- var pattern = /([a-z]+)(\d+)/;
+ if ( interpolation !== track.DefaultInterpolation ) {
- for ( var i = 0, il = geometry.morphTargets.length; i < il; i ++ ) {
+ json.interpolation = interpolation;
- var morph = geometry.morphTargets[ i ];
- var parts = morph.name.match( pattern );
+ }
- if ( parts && parts.length > 1 ) {
+ }
- var label = parts[ 1 ];
- var num = parts[ 2 ];
+ json.type = track.ValueTypeName; // mandatory
- if ( ! animations[ label ] ) animations[ label ] = { start: Infinity, end: -Infinity };
+ return json;
- var animation = animations[ label ];
+ },
- if ( i < animation.start ) animation.start = i;
- if ( i > animation.end ) animation.end = i;
+ _getTrackTypeForValueTypeName: function( typeName ) {
- if ( ! firstAnimation ) firstAnimation = label;
+ switch( typeName.toLowerCase() ) {
- }
+ case "scalar":
+ case "double":
+ case "float":
+ case "number":
+ case "integer":
- }
+ return THREE.NumberKeyframeTrack;
- geometry.firstAnimation = firstAnimation;
+ case "vector":
+ case "vector2":
+ case "vector3":
+ case "vector4":
-};
+ return THREE.VectorKeyframeTrack;
-THREE.MorphAnimMesh.prototype.setAnimationLabel = function ( label, start, end ) {
+ case "color":
- if ( ! this.geometry.animations ) this.geometry.animations = {};
+ return THREE.ColorKeyframeTrack;
- this.geometry.animations[ label ] = { start: start, end: end };
+ case "quaternion":
-};
+ return THREE.QuaternionKeyframeTrack;
-THREE.MorphAnimMesh.prototype.playAnimation = function ( label, fps ) {
+ case "bool":
+ case "boolean":
- var animation = this.geometry.animations[ label ];
+ return THREE.BooleanKeyframeTrack;
- if ( animation ) {
+ case "string":
- this.setFrameRange( animation.start, animation.end );
- this.duration = 1000 * ( ( animation.end - animation.start ) / fps );
- this.time = 0;
+ return THREE.StringKeyframeTrack;
- } else {
+ }
- console.warn( "animation[" + label + "] undefined" );
+ throw new Error( "Unsupported typeName: " + typeName );
}
-};
+} );
-THREE.MorphAnimMesh.prototype.updateAnimation = function ( delta ) {
+// File:src/animation/PropertyBinding.js
- var frameTime = this.duration / this.length;
+/**
+ *
+ * A reference to a real property in the scene graph.
+ *
+ *
+ * @author Ben Houston / http://clara.io/
+ * @author David Sarno / http://lighthaus.us/
+ * @author tschw
+ */
- this.time += this.direction * delta;
+THREE.PropertyBinding = function ( rootNode, path, parsedPath ) {
- if ( this.mirroredLoop ) {
+ this.path = path;
+ this.parsedPath = parsedPath ||
+ THREE.PropertyBinding.parseTrackName( path );
- if ( this.time > this.duration || this.time < 0 ) {
+ this.node = THREE.PropertyBinding.findNode(
+ rootNode, this.parsedPath.nodeName ) || rootNode;
- this.direction *= -1;
+ this.rootNode = rootNode;
- if ( this.time > this.duration ) {
+};
- this.time = this.duration;
- this.directionBackwards = true;
+THREE.PropertyBinding.prototype = {
- }
+ constructor: THREE.PropertyBinding,
- if ( this.time < 0 ) {
+ getValue: function getValue_unbound( targetArray, offset ) {
- this.time = 0;
- this.directionBackwards = false;
+ this.bind();
+ this.getValue( targetArray, offset );
- }
+ // Note: This class uses a State pattern on a per-method basis:
+ // 'bind' sets 'this.getValue' / 'setValue' and shadows the
+ // prototype version of these methods with one that represents
+ // the bound state. When the property is not found, the methods
+ // become no-ops.
- }
+ },
- } else {
+ setValue: function getValue_unbound( sourceArray, offset ) {
- this.time = this.time % this.duration;
+ this.bind();
+ this.setValue( sourceArray, offset );
- if ( this.time < 0 ) this.time += this.duration;
+ },
- }
+ // create getter / setter pair for a property in the scene graph
+ bind: function() {
- var keyframe = this.startKeyframe + THREE.Math.clamp( Math.floor( this.time / frameTime ), 0, this.length - 1 );
+ var targetObject = this.node,
+ parsedPath = this.parsedPath,
- if ( keyframe !== this.currentKeyframe ) {
+ objectName = parsedPath.objectName,
+ propertyName = parsedPath.propertyName,
+ propertyIndex = parsedPath.propertyIndex;
- this.morphTargetInfluences[ this.lastKeyframe ] = 0;
- this.morphTargetInfluences[ this.currentKeyframe ] = 1;
+ if ( ! targetObject ) {
- this.morphTargetInfluences[ keyframe ] = 0;
+ targetObject = THREE.PropertyBinding.findNode(
+ this.rootNode, parsedPath.nodeName ) || this.rootNode;
- this.lastKeyframe = this.currentKeyframe;
- this.currentKeyframe = keyframe;
+ this.node = targetObject;
- }
+ }
- var mix = ( this.time % frameTime ) / frameTime;
+ // set fail state so we can just 'return' on error
+ this.getValue = this._getValue_unavailable;
+ this.setValue = this._setValue_unavailable;
- if ( this.directionBackwards ) {
+ // ensure there is a value node
+ if ( ! targetObject ) {
- mix = 1 - mix;
+ console.error( " trying to update node for track: " + this.path + " but it wasn't found." );
+ return;
- }
+ }
- this.morphTargetInfluences[ this.currentKeyframe ] = mix;
- this.morphTargetInfluences[ this.lastKeyframe ] = 1 - mix;
+ if ( objectName ) {
-};
+ var objectIndex = parsedPath.objectIndex;
-THREE.MorphAnimMesh.prototype.clone = function ( object ) {
+ // special cases were we need to reach deeper into the hierarchy to get the face materials....
+ switch ( objectName ) {
- if ( object === undefined ) object = new THREE.MorphAnimMesh( this.geometry, this.material );
+ case 'materials':
- object.duration = this.duration;
- object.mirroredLoop = this.mirroredLoop;
- object.time = this.time;
+ if ( ! targetObject.material ) {
- object.lastKeyframe = this.lastKeyframe;
- object.currentKeyframe = this.currentKeyframe;
+ console.error( ' can not bind to material as node does not have a material', this );
+ return;
- object.direction = this.direction;
- object.directionBackwards = this.directionBackwards;
+ }
- THREE.Mesh.prototype.clone.call( this, object );
+ if ( ! targetObject.material.materials ) {
- return object;
+ console.error( ' can not bind to material.materials as node.material does not have a materials array', this );
+ return;
-};
+ }
-/**
- * @author alteredq / http://alteredqualia.com/
- */
+ targetObject = targetObject.material.materials;
-THREE.Ribbon = function ( geometry, material ) {
+ break;
- THREE.Object3D.call( this );
+ case 'bones':
- this.geometry = geometry;
- this.material = material;
+ if ( ! targetObject.skeleton ) {
-};
+ console.error( ' can not bind to bones as node does not have a skeleton', this );
+ return;
-THREE.Ribbon.prototype = Object.create( THREE.Object3D.prototype );
+ }
-THREE.Ribbon.prototype.clone = function ( object ) {
+ // potential future optimization: skip this if propertyIndex is already an integer
+ // and convert the integer string to a true integer.
- if ( object === undefined ) object = new THREE.Ribbon( this.geometry, this.material );
+ targetObject = targetObject.skeleton.bones;
- THREE.Object3D.prototype.clone.call( this, object );
+ // support resolving morphTarget names into indices.
+ for ( var i = 0; i < targetObject.length; i ++ ) {
- return object;
+ if ( targetObject[ i ].name === objectIndex ) {
-};
+ objectIndex = i;
+ break;
-/**
- * @author mikael emtinger / http://gomo.se/
- * @author alteredq / http://alteredqualia.com/
- * @author mrdoob / http://mrdoob.com/
- */
+ }
-THREE.LOD = function () {
+ }
- THREE.Object3D.call( this );
+ break;
- this.objects = [];
+ default:
-};
+ if ( targetObject[ objectName ] === undefined ) {
+ console.error( ' can not bind to objectName of node, undefined', this );
+ return;
-THREE.LOD.prototype = Object.create( THREE.Object3D.prototype );
+ }
-THREE.LOD.prototype.addLevel = function ( object, distance ) {
+ targetObject = targetObject[ objectName ];
- if ( distance === undefined ) distance = 0;
+ }
- distance = Math.abs( distance );
- for ( var l = 0; l < this.objects.length; l ++ ) {
+ if ( objectIndex !== undefined ) {
- if ( distance < this.objects[ l ].distance ) {
+ if ( targetObject[ objectIndex ] === undefined ) {
- break;
+ console.error( " trying to bind to objectIndex of objectName, but is undefined:", this, targetObject );
+ return;
- }
+ }
- }
+ targetObject = targetObject[ objectIndex ];
- this.objects.splice( l, 0, { distance: distance, object: object } );
- this.add( object );
+ }
-};
+ }
-THREE.LOD.prototype.getObjectForDistance = function ( distance ) {
+ // resolve property
+ var nodeProperty = targetObject[ propertyName ];
- for ( var i = 1, l = this.objects.length; i < l; i ++ ) {
+ if ( nodeProperty === undefined ) {
- if ( distance < this.objects[ i ].distance ) {
+ var nodeName = parsedPath.nodeName;
- break;
+ console.error( " trying to update property for track: " + nodeName +
+ '.' + propertyName + " but it wasn't found.", targetObject );
+ return;
}
- }
-
- return this.objects[ i - 1 ].object;
+ // determine versioning scheme
+ var versioning = this.Versioning.None;
-};
+ if ( targetObject.needsUpdate !== undefined ) { // material
-THREE.LOD.prototype.update = function () {
+ versioning = this.Versioning.NeedsUpdate;
+ this.targetObject = targetObject;
- var v1 = new THREE.Vector3();
- var v2 = new THREE.Vector3();
+ } else if ( targetObject.matrixWorldNeedsUpdate !== undefined ) { // node transform
- return function ( camera ) {
+ versioning = this.Versioning.MatrixWorldNeedsUpdate;
+ this.targetObject = targetObject;
- if ( this.objects.length > 1 ) {
+ }
- v1.getPositionFromMatrix( camera.matrixWorld );
- v2.getPositionFromMatrix( this.matrixWorld );
+ // determine how the property gets bound
+ var bindingType = this.BindingType.Direct;
- var distance = v1.distanceTo( v2 );
+ if ( propertyIndex !== undefined ) {
+ // access a sub element of the property array (only primitives are supported right now)
- this.objects[ 0 ].object.visible = true;
+ if ( propertyName === "morphTargetInfluences" ) {
+ // potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer.
- for ( var i = 1, l = this.objects.length; i < l; i ++ ) {
+ // support resolving morphTarget names into indices.
+ if ( ! targetObject.geometry ) {
- if ( distance >= this.objects[ i ].distance ) {
+ console.error( ' can not bind to morphTargetInfluences becasuse node does not have a geometry', this );
+ return;
- this.objects[ i - 1 ].object.visible = false;
- this.objects[ i ].object.visible = true;
+ }
- } else {
+ if ( ! targetObject.geometry.morphTargets ) {
- break;
+ console.error( ' can not bind to morphTargetInfluences becasuse node does not have a geometry.morphTargets', this );
+ return;
}
- }
+ for ( var i = 0; i < this.node.geometry.morphTargets.length; i ++ ) {
+
+ if ( targetObject.geometry.morphTargets[ i ].name === propertyIndex ) {
- for( ; i < l; i ++ ) {
+ propertyIndex = i;
+ break;
+
+ }
- this.objects[ i ].object.visible = false;
+ }
}
- }
+ bindingType = this.BindingType.ArrayElement;
- };
+ this.resolvedProperty = nodeProperty;
+ this.propertyIndex = propertyIndex;
-}();
+ } else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) {
+ // must use copy for Object3D.Euler/Quaternion
-THREE.LOD.prototype.clone = function () {
+ bindingType = this.BindingType.HasFromToArray;
- // TODO
+ this.resolvedProperty = nodeProperty;
-};
+ } else if ( nodeProperty.length !== undefined ) {
-/**
- * @author mikael emtinger / http://gomo.se/
- * @author alteredq / http://alteredqualia.com/
- */
+ bindingType = this.BindingType.EntireArray;
-THREE.Sprite = function ( material ) {
+ this.resolvedProperty = nodeProperty;
- THREE.Object3D.call( this );
+ } else {
- this.material = ( material !== undefined ) ? material : new THREE.SpriteMaterial();
+ this.propertyName = propertyName;
- this.rotation3d = this.rotation;
- this.rotation = 0;
+ }
-};
+ // select getter / setter
+ this.getValue = this.GetterByBindingType[ bindingType ];
+ this.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ];
-THREE.Sprite.prototype = Object.create( THREE.Object3D.prototype );
+ },
-/*
- * Custom update matrix
- */
+ unbind: function() {
-THREE.Sprite.prototype.updateMatrix = function () {
+ this.node = null;
- this.rotation3d.set( 0, 0, this.rotation, this.rotation3d.order );
- this.quaternion.setFromEuler( this.rotation3d );
- this.matrix.compose( this.position, this.quaternion, this.scale );
+ // back to the prototype version of getValue / setValue
+ // note: avoiding to mutate the shape of 'this' via 'delete'
+ this.getValue = this._getValue_unbound;
+ this.setValue = this._setValue_unbound;
- this.matrixWorldNeedsUpdate = true;
+ }
};
-THREE.Sprite.prototype.clone = function ( object ) {
+Object.assign( THREE.PropertyBinding.prototype, { // prototype, continued
- if ( object === undefined ) object = new THREE.Sprite( this.material );
+ // these are used to "bind" a nonexistent property
+ _getValue_unavailable: function() {},
+ _setValue_unavailable: function() {},
- THREE.Object3D.prototype.clone.call( this, object );
+ // initial state of these methods that calls 'bind'
+ _getValue_unbound: THREE.PropertyBinding.prototype.getValue,
+ _setValue_unbound: THREE.PropertyBinding.prototype.setValue,
- return object;
+ BindingType: {
+ Direct: 0,
+ EntireArray: 1,
+ ArrayElement: 2,
+ HasFromToArray: 3
+ },
-};
+ Versioning: {
+ None: 0,
+ NeedsUpdate: 1,
+ MatrixWorldNeedsUpdate: 2
+ },
+ GetterByBindingType: [
-/**
- * @author mrdoob / http://mrdoob.com/
- */
+ function getValue_direct( buffer, offset ) {
-THREE.Scene = function () {
+ buffer[ offset ] = this.node[ this.propertyName ];
- THREE.Object3D.call( this );
+ },
- this.fog = null;
- this.overrideMaterial = null;
+ function getValue_array( buffer, offset ) {
- this.autoUpdate = true; // checked by the renderer
- this.matrixAutoUpdate = false;
+ var source = this.resolvedProperty;
- this.__objects = [];
- this.__lights = [];
+ for ( var i = 0, n = source.length; i !== n; ++ i ) {
- this.__objectsAdded = [];
- this.__objectsRemoved = [];
+ buffer[ offset ++ ] = source[ i ];
-};
+ }
-THREE.Scene.prototype = Object.create( THREE.Object3D.prototype );
+ },
-THREE.Scene.prototype.__addObject = function ( object ) {
+ function getValue_arrayElement( buffer, offset ) {
- if ( object instanceof THREE.Light ) {
+ buffer[ offset ] = this.resolvedProperty[ this.propertyIndex ];
- if ( this.__lights.indexOf( object ) === - 1 ) {
+ },
+
+ function getValue_toArray( buffer, offset ) {
- this.__lights.push( object );
+ this.resolvedProperty.toArray( buffer, offset );
}
- if ( object.target && object.target.parent === undefined ) {
+ ],
- this.add( object.target );
+ SetterByBindingTypeAndVersioning: [
- }
+ [
+ // Direct
+
+ function setValue_direct( buffer, offset ) {
- } else if ( !( object instanceof THREE.Camera || object instanceof THREE.Bone ) ) {
+ this.node[ this.propertyName ] = buffer[ offset ];
- if ( this.__objects.indexOf( object ) === - 1 ) {
+ },
- this.__objects.push( object );
- this.__objectsAdded.push( object );
+ function setValue_direct_setNeedsUpdate( buffer, offset ) {
- // check if previously removed
+ this.node[ this.propertyName ] = buffer[ offset ];
+ this.targetObject.needsUpdate = true;
- var i = this.__objectsRemoved.indexOf( object );
+ },
- if ( i !== -1 ) {
+ function setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) {
- this.__objectsRemoved.splice( i, 1 );
+ this.node[ this.propertyName ] = buffer[ offset ];
+ this.targetObject.matrixWorldNeedsUpdate = true;
}
- }
+ ], [
- }
+ // EntireArray
- for ( var c = 0; c < object.children.length; c ++ ) {
+ function setValue_array( buffer, offset ) {
- this.__addObject( object.children[ c ] );
+ var dest = this.resolvedProperty;
- }
+ for ( var i = 0, n = dest.length; i !== n; ++ i ) {
-};
+ dest[ i ] = buffer[ offset ++ ];
-THREE.Scene.prototype.__removeObject = function ( object ) {
+ }
- if ( object instanceof THREE.Light ) {
+ },
- var i = this.__lights.indexOf( object );
+ function setValue_array_setNeedsUpdate( buffer, offset ) {
- if ( i !== -1 ) {
+ var dest = this.resolvedProperty;
- this.__lights.splice( i, 1 );
+ for ( var i = 0, n = dest.length; i !== n; ++ i ) {
- }
+ dest[ i ] = buffer[ offset ++ ];
+
+ }
- } else if ( !( object instanceof THREE.Camera ) ) {
+ this.targetObject.needsUpdate = true;
- var i = this.__objects.indexOf( object );
+ },
- if( i !== -1 ) {
+ function setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) {
- this.__objects.splice( i, 1 );
- this.__objectsRemoved.push( object );
+ var dest = this.resolvedProperty;
- // check if previously added
+ for ( var i = 0, n = dest.length; i !== n; ++ i ) {
- var ai = this.__objectsAdded.indexOf( object );
+ dest[ i ] = buffer[ offset ++ ];
- if ( ai !== -1 ) {
+ }
- this.__objectsAdded.splice( ai, 1 );
+ this.targetObject.matrixWorldNeedsUpdate = true;
}
- }
-
- }
+ ], [
- for ( var c = 0; c < object.children.length; c ++ ) {
+ // ArrayElement
- this.__removeObject( object.children[ c ] );
+ function setValue_arrayElement( buffer, offset ) {
- }
+ this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
-};
+ },
-THREE.Scene.prototype.clone = function ( object ) {
+ function setValue_arrayElement_setNeedsUpdate( buffer, offset ) {
- if ( object === undefined ) object = new THREE.Scene();
+ this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
+ this.targetObject.needsUpdate = true;
- THREE.Object3D.prototype.clone.call(this, object);
+ },
- if ( this.fog !== null ) object.fog = this.fog.clone();
- if ( this.overrideMaterial !== null ) object.overrideMaterial = this.overrideMaterial.clone();
+ function setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) {
- object.autoUpdate = this.autoUpdate;
- object.matrixAutoUpdate = this.matrixAutoUpdate;
+ this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
+ this.targetObject.matrixWorldNeedsUpdate = true;
- return object;
+ }
-};
+ ], [
-/**
- * @author mrdoob / http://mrdoob.com/
- * @author alteredq / http://alteredqualia.com/
- */
+ // HasToFromArray
-THREE.Fog = function ( hex, near, far ) {
+ function setValue_fromArray( buffer, offset ) {
- this.name = '';
+ this.resolvedProperty.fromArray( buffer, offset );
- this.color = new THREE.Color( hex );
+ },
- this.near = ( near !== undefined ) ? near : 1;
- this.far = ( far !== undefined ) ? far : 1000;
+ function setValue_fromArray_setNeedsUpdate( buffer, offset ) {
-};
+ this.resolvedProperty.fromArray( buffer, offset );
+ this.targetObject.needsUpdate = true;
-THREE.Fog.prototype.clone = function () {
+ },
- return new THREE.Fog( this.color.getHex(), this.near, this.far );
+ function setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) {
-};
+ this.resolvedProperty.fromArray( buffer, offset );
+ this.targetObject.matrixWorldNeedsUpdate = true;
-/**
- * @author mrdoob / http://mrdoob.com/
- * @author alteredq / http://alteredqualia.com/
- */
+ }
-THREE.FogExp2 = function ( hex, density ) {
+ ]
- this.name = '';
+ ]
- this.color = new THREE.Color( hex );
- this.density = ( density !== undefined ) ? density : 0.00025;
+} );
-};
+THREE.PropertyBinding.Composite =
+ function( targetGroup, path, optionalParsedPath ) {
-THREE.FogExp2.prototype.clone = function () {
+ var parsedPath = optionalParsedPath ||
+ THREE.PropertyBinding.parseTrackName( path );
- return new THREE.FogExp2( this.color.getHex(), this.density );
+ this._targetGroup = targetGroup;
+ this._bindings = targetGroup.subscribe_( path, parsedPath );
};
-/**
- * @author mrdoob / http://mrdoob.com/
- */
+THREE.PropertyBinding.Composite.prototype = {
-THREE.CanvasRenderer = function ( parameters ) {
+ constructor: THREE.PropertyBinding.Composite,
- console.log( 'THREE.CanvasRenderer', THREE.REVISION );
+ getValue: function( array, offset ) {
- var smoothstep = THREE.Math.smoothstep;
+ this.bind(); // bind all binding
- parameters = parameters || {};
+ var firstValidIndex = this._targetGroup.nCachedObjects_,
+ binding = this._bindings[ firstValidIndex ];
- var _this = this,
- _renderData, _elements, _lights,
- _projector = new THREE.Projector(),
+ // and only call .getValue on the first
+ if ( binding !== undefined ) binding.getValue( array, offset );
- _canvas = parameters.canvas !== undefined
- ? parameters.canvas
- : document.createElement( 'canvas' ),
+ },
- _canvasWidth, _canvasHeight, _canvasWidthHalf, _canvasHeightHalf,
- _context = _canvas.getContext( '2d' ),
+ setValue: function( array, offset ) {
- _clearColor = new THREE.Color( 0x000000 ),
- _clearAlpha = 0,
+ var bindings = this._bindings;
- _contextGlobalAlpha = 1,
- _contextGlobalCompositeOperation = 0,
- _contextStrokeStyle = null,
- _contextFillStyle = null,
- _contextLineWidth = null,
- _contextLineCap = null,
- _contextLineJoin = null,
- _contextDashSize = null,
- _contextGapSize = 0,
+ for ( var i = this._targetGroup.nCachedObjects_,
+ n = bindings.length; i !== n; ++ i ) {
- _camera,
+ bindings[ i ].setValue( array, offset );
- _v1, _v2, _v3, _v4,
- _v5 = new THREE.RenderableVertex(),
- _v6 = new THREE.RenderableVertex(),
+ }
- _v1x, _v1y, _v2x, _v2y, _v3x, _v3y,
- _v4x, _v4y, _v5x, _v5y, _v6x, _v6y,
+ },
- _color = new THREE.Color(),
- _color1 = new THREE.Color(),
- _color2 = new THREE.Color(),
- _color3 = new THREE.Color(),
- _color4 = new THREE.Color(),
+ bind: function() {
- _diffuseColor = new THREE.Color(),
- _emissiveColor = new THREE.Color(),
+ var bindings = this._bindings;
- _lightColor = new THREE.Color(),
+ for ( var i = this._targetGroup.nCachedObjects_,
+ n = bindings.length; i !== n; ++ i ) {
- _patterns = {}, _imagedatas = {},
+ bindings[ i ].bind();
- _near, _far,
+ }
- _image, _uvs,
- _uv1x, _uv1y, _uv2x, _uv2y, _uv3x, _uv3y,
+ },
- _clipBox = new THREE.Box2(),
- _clearBox = new THREE.Box2(),
- _elemBox = new THREE.Box2(),
+ unbind: function() {
- _ambientLight = new THREE.Color(),
- _directionalLights = new THREE.Color(),
- _pointLights = new THREE.Color(),
+ var bindings = this._bindings;
- _vector3 = new THREE.Vector3(), // Needed for PointLight
+ for ( var i = this._targetGroup.nCachedObjects_,
+ n = bindings.length; i !== n; ++ i ) {
- _pixelMap, _pixelMapContext, _pixelMapImage, _pixelMapData,
- _gradientMap, _gradientMapContext, _gradientMapQuality = 16;
+ bindings[ i ].unbind();
- _pixelMap = document.createElement( 'canvas' );
- _pixelMap.width = _pixelMap.height = 2;
+ }
- _pixelMapContext = _pixelMap.getContext( '2d' );
- _pixelMapContext.fillStyle = 'rgba(0,0,0,1)';
- _pixelMapContext.fillRect( 0, 0, 2, 2 );
+ }
- _pixelMapImage = _pixelMapContext.getImageData( 0, 0, 2, 2 );
- _pixelMapData = _pixelMapImage.data;
+};
- _gradientMap = document.createElement( 'canvas' );
- _gradientMap.width = _gradientMap.height = _gradientMapQuality;
+THREE.PropertyBinding.create = function( root, path, parsedPath ) {
- _gradientMapContext = _gradientMap.getContext( '2d' );
- _gradientMapContext.translate( - _gradientMapQuality / 2, - _gradientMapQuality / 2 );
- _gradientMapContext.scale( _gradientMapQuality, _gradientMapQuality );
+ if ( ! ( root instanceof THREE.AnimationObjectGroup ) ) {
- _gradientMapQuality --; // Fix UVs
+ return new THREE.PropertyBinding( root, path, parsedPath );
- // dash+gap fallbacks for Firefox and everything else
+ } else {
- if ( _context.setLineDash === undefined ) {
+ return new THREE.PropertyBinding.Composite( root, path, parsedPath );
- if ( _context.mozDash !== undefined ) {
+ }
- _context.setLineDash = function ( values ) {
+};
- _context.mozDash = values[ 0 ] !== null ? values : null;
+THREE.PropertyBinding.parseTrackName = function( trackName ) {
- }
+ // matches strings in the form of:
+ // nodeName.property
+ // nodeName.property[accessor]
+ // nodeName.material.property[accessor]
+ // uuid.property[accessor]
+ // uuid.objectName[objectIndex].propertyName[propertyIndex]
+ // parentName/nodeName.property
+ // parentName/parentName/nodeName.property[index]
+ // .bone[Armature.DEF_cog].position
+ // created and tested via https://regex101.com/#javascript
- } else {
+ var re = /^(([\w]+\/)*)([\w-\d]+)?(\.([\w]+)(\[([\w\d\[\]\_.:\- ]+)\])?)?(\.([\w.]+)(\[([\w\d\[\]\_. ]+)\])?)$/;
+ var matches = re.exec( trackName );
- _context.setLineDash = function () {}
+ if ( ! matches ) {
- }
+ throw new Error( "cannot parse trackName at all: " + trackName );
}
- this.domElement = _canvas;
+ if ( matches.index === re.lastIndex ) {
- this.devicePixelRatio = parameters.devicePixelRatio !== undefined
- ? parameters.devicePixelRatio
- : window.devicePixelRatio !== undefined
- ? window.devicePixelRatio
- : 1;
+ re.lastIndex++;
- this.autoClear = true;
- this.sortObjects = true;
- this.sortElements = true;
-
- this.info = {
+ }
- render: {
+ var results = {
+ // directoryName: matches[ 1 ], // (tschw) currently unused
+ nodeName: matches[ 3 ], // allowed to be null, specified root node.
+ objectName: matches[ 5 ],
+ objectIndex: matches[ 7 ],
+ propertyName: matches[ 9 ],
+ propertyIndex: matches[ 11 ] // allowed to be null, specifies that the whole property is set.
+ };
- vertices: 0,
- faces: 0
+ if ( results.propertyName === null || results.propertyName.length === 0 ) {
- }
+ throw new Error( "can not parse propertyName from trackName: " + trackName );
}
- // WebGLRenderer compatibility
-
- this.supportsVertexTextures = function () {};
- this.setFaceCulling = function () {};
+ return results;
- this.setSize = function ( width, height, updateStyle ) {
+};
- _canvasWidth = width * this.devicePixelRatio;
- _canvasHeight = height * this.devicePixelRatio;
+THREE.PropertyBinding.findNode = function( root, nodeName ) {
- _canvasWidthHalf = Math.floor( _canvasWidth / 2 );
- _canvasHeightHalf = Math.floor( _canvasHeight / 2 );
+ if ( ! nodeName || nodeName === "" || nodeName === "root" || nodeName === "." || nodeName === -1 || nodeName === root.name || nodeName === root.uuid ) {
- _canvas.width = _canvasWidth;
- _canvas.height = _canvasHeight;
+ return root;
- if ( this.devicePixelRatio !== 1 && updateStyle !== false ) {
+ }
- _canvas.style.width = width + 'px';
- _canvas.style.height = height + 'px';
+ // search into skeleton bones.
+ if ( root.skeleton ) {
- }
+ var searchSkeleton = function( skeleton ) {
- _clipBox.set(
- new THREE.Vector2( - _canvasWidthHalf, - _canvasHeightHalf ),
- new THREE.Vector2( _canvasWidthHalf, _canvasHeightHalf )
- );
+ for( var i = 0; i < skeleton.bones.length; i ++ ) {
- _clearBox.set(
- new THREE.Vector2( - _canvasWidthHalf, - _canvasHeightHalf ),
- new THREE.Vector2( _canvasWidthHalf, _canvasHeightHalf )
- );
+ var bone = skeleton.bones[ i ];
- _contextGlobalAlpha = 1;
- _contextGlobalCompositeOperation = 0;
- _contextStrokeStyle = null;
- _contextFillStyle = null;
- _contextLineWidth = null;
- _contextLineCap = null;
- _contextLineJoin = null;
+ if ( bone.name === nodeName ) {
- };
+ return bone;
- this.setClearColor = function ( color, alpha ) {
+ }
+ }
- _clearColor.set( color );
- _clearAlpha = alpha !== undefined ? alpha : 1;
+ return null;
- _clearBox.set(
- new THREE.Vector2( - _canvasWidthHalf, - _canvasHeightHalf ),
- new THREE.Vector2( _canvasWidthHalf, _canvasHeightHalf )
- );
+ };
- };
+ var bone = searchSkeleton( root.skeleton );
- this.setClearColorHex = function ( hex, alpha ) {
+ if ( bone ) {
- console.warn( 'DEPRECATED: .setClearColorHex() is being removed. Use .setClearColor() instead.' );
- this.setClearColor( hex, alpha );
+ return bone;
- };
+ }
+ }
- this.getMaxAnisotropy = function () {
+ // search into node subtree.
+ if ( root.children ) {
- return 0;
+ var searchNodeSubtree = function( children ) {
- };
+ for( var i = 0; i < children.length; i ++ ) {
- this.clear = function () {
+ var childNode = children[ i ];
- _context.setTransform( 1, 0, 0, - 1, _canvasWidthHalf, _canvasHeightHalf );
+ if ( childNode.name === nodeName || childNode.uuid === nodeName ) {
- if ( _clearBox.empty() === false ) {
+ return childNode;
- _clearBox.intersect( _clipBox );
- _clearBox.expandByScalar( 2 );
+ }
- if ( _clearAlpha < 1 ) {
+ var result = searchNodeSubtree( childNode.children );
- _context.clearRect(
- _clearBox.min.x | 0,
- _clearBox.min.y | 0,
- ( _clearBox.max.x - _clearBox.min.x ) | 0,
- ( _clearBox.max.y - _clearBox.min.y ) | 0
- );
+ if ( result ) return result;
}
- if ( _clearAlpha > 0 ) {
-
- setBlending( THREE.NormalBlending );
- setOpacity( 1 );
+ return null;
- setFillStyle( 'rgba(' + Math.floor( _clearColor.r * 255 ) + ',' + Math.floor( _clearColor.g * 255 ) + ',' + Math.floor( _clearColor.b * 255 ) + ',' + _clearAlpha + ')' );
+ };
- _context.fillRect(
- _clearBox.min.x | 0,
- _clearBox.min.y | 0,
- ( _clearBox.max.x - _clearBox.min.x ) | 0,
- ( _clearBox.max.y - _clearBox.min.y ) | 0
- );
+ var subTreeNode = searchNodeSubtree( root.children );
- }
+ if ( subTreeNode ) {
- _clearBox.makeEmpty();
+ return subTreeNode;
}
+ }
- };
+ return null;
- this.render = function ( scene, camera ) {
+};
- if ( camera instanceof THREE.Camera === false ) {
+// File:src/animation/PropertyMixer.js
- console.error( 'THREE.CanvasRenderer.render: camera is not an instance of THREE.Camera.' );
- return;
+/**
+ *
+ * Buffered scene graph property that allows weighted accumulation.
+ *
+ *
+ * @author Ben Houston / http://clara.io/
+ * @author David Sarno / http://lighthaus.us/
+ * @author tschw
+ */
- }
+THREE.PropertyMixer = function ( binding, typeName, valueSize ) {
- if ( this.autoClear === true ) this.clear();
+ this.binding = binding;
+ this.valueSize = valueSize;
- _context.setTransform( 1, 0, 0, - 1, _canvasWidthHalf, _canvasHeightHalf );
+ var bufferType = Float64Array,
+ mixFunction;
- _this.info.render.vertices = 0;
- _this.info.render.faces = 0;
+ switch ( typeName ) {
- _renderData = _projector.projectScene( scene, camera, this.sortObjects, this.sortElements );
- _elements = _renderData.elements;
- _lights = _renderData.lights;
- _camera = camera;
+ case 'quaternion': mixFunction = this._slerp; break;
- /* DEBUG
- setFillStyle( 'rgba( 0, 255, 255, 0.5 )' );
- _context.fillRect( _clipBox.min.x, _clipBox.min.y, _clipBox.max.x - _clipBox.min.x, _clipBox.max.y - _clipBox.min.y );
- */
+ case 'string':
+ case 'bool':
- calculateLights();
+ bufferType = Array, mixFunction = this._select; break;
- for ( var e = 0, el = _elements.length; e < el; e++ ) {
+ default: mixFunction = this._lerp;
+
+ }
- var element = _elements[ e ];
+ this.buffer = new bufferType( valueSize * 4 );
+ // layout: [ incoming | accu0 | accu1 | orig ]
+ //
+ // interpolators can use .buffer as their .result
+ // the data then goes to 'incoming'
+ //
+ // 'accu0' and 'accu1' are used frame-interleaved for
+ // the cumulative result and are compared to detect
+ // changes
+ //
+ // 'orig' stores the original state of the property
- var material = element.material;
+ this._mixBufferRegion = mixFunction;
- if ( material === undefined || material.visible === false ) continue;
+ this.cumulativeWeight = 0;
- _elemBox.makeEmpty();
+ this.useCount = 0;
+ this.referenceCount = 0;
- if ( element instanceof THREE.RenderableParticle ) {
+};
- _v1 = element;
- _v1.x *= _canvasWidthHalf; _v1.y *= _canvasHeightHalf;
+THREE.PropertyMixer.prototype = {
- renderParticle( _v1, element, material );
+ constructor: THREE.PropertyMixer,
- } else if ( element instanceof THREE.RenderableLine ) {
+ // accumulate data in the 'incoming' region into 'accu'
+ accumulate: function( accuIndex, weight ) {
- _v1 = element.v1; _v2 = element.v2;
+ // note: happily accumulating nothing when weight = 0, the caller knows
+ // the weight and shouldn't have made the call in the first place
- _v1.positionScreen.x *= _canvasWidthHalf; _v1.positionScreen.y *= _canvasHeightHalf;
- _v2.positionScreen.x *= _canvasWidthHalf; _v2.positionScreen.y *= _canvasHeightHalf;
+ var buffer = this.buffer,
+ stride = this.valueSize,
+ offset = accuIndex * stride + stride,
- _elemBox.setFromPoints( [
- _v1.positionScreen,
- _v2.positionScreen
- ] );
+ currentWeight = this.cumulativeWeight;
- if ( _clipBox.isIntersectionBox( _elemBox ) === true ) {
+ if ( currentWeight === 0 ) {
- renderLine( _v1, _v2, element, material );
+ // accuN := incoming * weight
- }
+ for ( var i = 0; i !== stride; ++ i ) {
- } else if ( element instanceof THREE.RenderableFace3 ) {
+ buffer[ offset + i ] = buffer[ i ];
- _v1 = element.v1; _v2 = element.v2; _v3 = element.v3;
+ }
- if ( _v1.positionScreen.z < -1 || _v1.positionScreen.z > 1 ) continue;
- if ( _v2.positionScreen.z < -1 || _v2.positionScreen.z > 1 ) continue;
- if ( _v3.positionScreen.z < -1 || _v3.positionScreen.z > 1 ) continue;
+ currentWeight = weight;
- _v1.positionScreen.x *= _canvasWidthHalf; _v1.positionScreen.y *= _canvasHeightHalf;
- _v2.positionScreen.x *= _canvasWidthHalf; _v2.positionScreen.y *= _canvasHeightHalf;
- _v3.positionScreen.x *= _canvasWidthHalf; _v3.positionScreen.y *= _canvasHeightHalf;
+ } else {
- if ( material.overdraw > 0 ) {
+ // accuN := accuN + incoming * weight
- expand( _v1.positionScreen, _v2.positionScreen, material.overdraw );
- expand( _v2.positionScreen, _v3.positionScreen, material.overdraw );
- expand( _v3.positionScreen, _v1.positionScreen, material.overdraw );
+ currentWeight += weight;
+ var mix = weight / currentWeight;
+ this._mixBufferRegion( buffer, offset, 0, mix, stride );
- }
+ }
- _elemBox.setFromPoints( [
- _v1.positionScreen,
- _v2.positionScreen,
- _v3.positionScreen
- ] );
+ this.cumulativeWeight = currentWeight;
- if ( _clipBox.isIntersectionBox( _elemBox ) === true ) {
+ },
- renderFace3( _v1, _v2, _v3, 0, 1, 2, element, material );
+ // apply the state of 'accu' to the binding when accus differ
+ apply: function( accuIndex ) {
- }
+ var stride = this.valueSize,
+ buffer = this.buffer,
+ offset = accuIndex * stride + stride,
- }
+ weight = this.cumulativeWeight,
- /* DEBUG
- setLineWidth( 1 );
- setStrokeStyle( 'rgba( 0, 255, 0, 0.5 )' );
- _context.strokeRect( _elemBox.min.x, _elemBox.min.y, _elemBox.max.x - _elemBox.min.x, _elemBox.max.y - _elemBox.min.y );
- */
+ binding = this.binding;
- _clearBox.union( _elemBox );
+ this.cumulativeWeight = 0;
- }
+ if ( weight < 1 ) {
- /* DEBUG
- setLineWidth( 1 );
- setStrokeStyle( 'rgba( 255, 0, 0, 0.5 )' );
- _context.strokeRect( _clearBox.min.x, _clearBox.min.y, _clearBox.max.x - _clearBox.min.x, _clearBox.max.y - _clearBox.min.y );
- */
+ // accuN := accuN + original * ( 1 - cumulativeWeight )
- _context.setTransform( 1, 0, 0, 1, 0, 0 );
+ var originalValueOffset = stride * 3;
- };
+ this._mixBufferRegion(
+ buffer, offset, originalValueOffset, 1 - weight, stride );
- //
+ }
- function calculateLights() {
+ for ( var i = stride, e = stride + stride; i !== e; ++ i ) {
- _ambientLight.setRGB( 0, 0, 0 );
- _directionalLights.setRGB( 0, 0, 0 );
- _pointLights.setRGB( 0, 0, 0 );
+ if ( buffer[ i ] !== buffer[ i + stride ] ) {
- for ( var l = 0, ll = _lights.length; l < ll; l ++ ) {
+ // value has changed -> update scene graph
- var light = _lights[ l ];
- var lightColor = light.color;
+ binding.setValue( buffer, offset );
+ break;
- if ( light instanceof THREE.AmbientLight ) {
+ }
- _ambientLight.add( lightColor );
+ }
- } else if ( light instanceof THREE.DirectionalLight ) {
+ },
- // for particles
+ // remember the state of the bound property and copy it to both accus
+ saveOriginalState: function() {
- _directionalLights.add( lightColor );
+ var binding = this.binding;
- } else if ( light instanceof THREE.PointLight ) {
+ var buffer = this.buffer,
+ stride = this.valueSize,
- // for particles
+ originalValueOffset = stride * 3;
- _pointLights.add( lightColor );
+ binding.getValue( buffer, originalValueOffset );
- }
+ // accu[0..1] := orig -- initially detect changes against the original
+ for ( var i = stride, e = originalValueOffset; i !== e; ++ i ) {
+
+ buffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ];
}
- }
+ this.cumulativeWeight = 0;
+
+ },
- function calculateLight( position, normal, color ) {
+ // apply the state previously taken via 'saveOriginalState' to the binding
+ restoreOriginalState: function() {
- for ( var l = 0, ll = _lights.length; l < ll; l ++ ) {
+ var originalValueOffset = this.valueSize * 3;
+ this.binding.setValue( this.buffer, originalValueOffset );
- var light = _lights[ l ];
+ },
- _lightColor.copy( light.color );
- if ( light instanceof THREE.DirectionalLight ) {
+ // mix functions
- var lightPosition = _vector3.getPositionFromMatrix( light.matrixWorld ).normalize();
+ _select: function( buffer, dstOffset, srcOffset, t, stride ) {
- var amount = normal.dot( lightPosition );
+ if ( t >= 0.5 ) {
- if ( amount <= 0 ) continue;
+ for ( var i = 0; i !== stride; ++ i ) {
- amount *= light.intensity;
+ buffer[ dstOffset + i ] = buffer[ srcOffset + i ];
- color.add( _lightColor.multiplyScalar( amount ) );
+ }
- } else if ( light instanceof THREE.PointLight ) {
+ }
- var lightPosition = _vector3.getPositionFromMatrix( light.matrixWorld );
+ },
- var amount = normal.dot( _vector3.subVectors( lightPosition, position ).normalize() );
+ _slerp: function( buffer, dstOffset, srcOffset, t, stride ) {
- if ( amount <= 0 ) continue;
+ THREE.Quaternion.slerpFlat( buffer, dstOffset,
+ buffer, dstOffset, buffer, srcOffset, t );
- amount *= light.distance == 0 ? 1 : 1 - Math.min( position.distanceTo( lightPosition ) / light.distance, 1 );
+ },
- if ( amount == 0 ) continue;
+ _lerp: function( buffer, dstOffset, srcOffset, t, stride ) {
- amount *= light.intensity;
+ var s = 1 - t;
- color.add( _lightColor.multiplyScalar( amount ) );
+ for ( var i = 0; i !== stride; ++ i ) {
- }
+ var j = dstOffset + i;
+
+ buffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t;
}
}
- function renderParticle( v1, element, material ) {
+};
- setOpacity( material.opacity );
- setBlending( material.blending );
+// File:src/animation/tracks/BooleanKeyframeTrack.js
- var width, height, scaleX, scaleY,
- bitmap, bitmapWidth, bitmapHeight;
+/**
+ *
+ * A Track of Boolean keyframe values.
+ *
+ *
+ * @author Ben Houston / http://clara.io/
+ * @author David Sarno / http://lighthaus.us/
+ * @author tschw
+ */
- if ( material instanceof THREE.ParticleBasicMaterial ) {
+THREE.BooleanKeyframeTrack = function ( name, times, values ) {
- if ( material.map === null ) {
+ THREE.KeyframeTrack.call( this, name, times, values );
- scaleX = element.object.scale.x;
- scaleY = element.object.scale.y;
+};
- // TODO: Be able to disable this
+THREE.BooleanKeyframeTrack.prototype =
+ Object.assign( Object.create( THREE.KeyframeTrack.prototype ), {
- scaleX *= element.scale.x * _canvasWidthHalf;
- scaleY *= element.scale.y * _canvasHeightHalf;
+ constructor: THREE.BooleanKeyframeTrack,
- _elemBox.min.set( v1.x - scaleX, v1.y - scaleY );
- _elemBox.max.set( v1.x + scaleX, v1.y + scaleY );
+ ValueTypeName: 'bool',
+ ValueBufferType: Array,
- if ( _clipBox.isIntersectionBox( _elemBox ) === false ) {
+ DefaultInterpolation: THREE.InterpolateDiscrete,
- _elemBox.makeEmpty();
- return;
+ InterpolantFactoryMethodLinear: undefined,
+ InterpolantFactoryMethodSmooth: undefined
- }
+ // Note: Actually this track could have a optimized / compressed
+ // representation of a single value and a custom interpolant that
+ // computes "firstValue ^ isOdd( index )".
- setFillStyle( material.color.getStyle() );
+} );
- _context.save();
- _context.translate( v1.x, v1.y );
- _context.rotate( - element.rotation );
- _context.scale( scaleX, scaleY );
- _context.fillRect( -1, -1, 2, 2 );
- _context.restore();
+// File:src/animation/tracks/ColorKeyframeTrack.js
- } else {
+/**
+ *
+ * A Track of keyframe values that represent color.
+ *
+ *
+ * @author Ben Houston / http://clara.io/
+ * @author David Sarno / http://lighthaus.us/
+ * @author tschw
+ */
- bitmap = material.map.image;
- bitmapWidth = bitmap.width >> 1;
- bitmapHeight = bitmap.height >> 1;
+THREE.ColorKeyframeTrack = function ( name, times, values, interpolation ) {
- scaleX = element.scale.x * _canvasWidthHalf;
- scaleY = element.scale.y * _canvasHeightHalf;
+ THREE.KeyframeTrack.call( this, name, times, values, interpolation );
- width = scaleX * bitmapWidth;
- height = scaleY * bitmapHeight;
+};
- // TODO: Rotations break this...
+THREE.ColorKeyframeTrack.prototype =
+ Object.assign( Object.create( THREE.KeyframeTrack.prototype ), {
- _elemBox.min.set( v1.x - width, v1.y - height );
- _elemBox.max.set( v1.x + width, v1.y + height );
+ constructor: THREE.ColorKeyframeTrack,
- if ( _clipBox.isIntersectionBox( _elemBox ) === false ) {
+ ValueTypeName: 'color'
- _elemBox.makeEmpty();
- return;
+ // ValueBufferType is inherited
- }
+ // DefaultInterpolation is inherited
- _context.save();
- _context.translate( v1.x, v1.y );
- _context.rotate( - element.rotation );
- _context.scale( scaleX, - scaleY );
- _context.translate( - bitmapWidth, - bitmapHeight );
- _context.drawImage( bitmap, 0, 0 );
- _context.restore();
+ // Note: Very basic implementation and nothing special yet.
+ // However, this is the place for color space parameterization.
- }
+} );
- /* DEBUG
- setStrokeStyle( 'rgb(255,255,0)' );
- _context.beginPath();
- _context.moveTo( v1.x - 10, v1.y );
- _context.lineTo( v1.x + 10, v1.y );
- _context.moveTo( v1.x, v1.y - 10 );
- _context.lineTo( v1.x, v1.y + 10 );
- _context.stroke();
- */
+// File:src/animation/tracks/NumberKeyframeTrack.js
- } else if ( material instanceof THREE.ParticleCanvasMaterial ) {
+/**
+ *
+ * A Track of numeric keyframe values.
+ *
+ * @author Ben Houston / http://clara.io/
+ * @author David Sarno / http://lighthaus.us/
+ * @author tschw
+ */
- width = element.scale.x * _canvasWidthHalf;
- height = element.scale.y * _canvasHeightHalf;
+THREE.NumberKeyframeTrack = function ( name, times, values, interpolation ) {
- _elemBox.min.set( v1.x - width, v1.y - height );
- _elemBox.max.set( v1.x + width, v1.y + height );
+ THREE.KeyframeTrack.call( this, name, times, values, interpolation );
- if ( _clipBox.isIntersectionBox( _elemBox ) === false ) {
+};
- _elemBox.makeEmpty();
- return;
+THREE.NumberKeyframeTrack.prototype =
+ Object.assign( Object.create( THREE.KeyframeTrack.prototype ), {
- }
+ constructor: THREE.NumberKeyframeTrack,
- setStrokeStyle( material.color.getStyle() );
- setFillStyle( material.color.getStyle() );
+ ValueTypeName: 'number',
- _context.save();
- _context.translate( v1.x, v1.y );
- _context.rotate( - element.rotation );
- _context.scale( width, height );
+ // ValueBufferType is inherited
- material.program( _context );
+ // DefaultInterpolation is inherited
- _context.restore();
+} );
- }
+// File:src/animation/tracks/QuaternionKeyframeTrack.js
- }
+/**
+ *
+ * A Track of quaternion keyframe values.
+ *
+ * @author Ben Houston / http://clara.io/
+ * @author David Sarno / http://lighthaus.us/
+ * @author tschw
+ */
- function renderLine( v1, v2, element, material ) {
+THREE.QuaternionKeyframeTrack = function ( name, times, values, interpolation ) {
- setOpacity( material.opacity );
- setBlending( material.blending );
+ THREE.KeyframeTrack.call( this, name, times, values, interpolation );
- _context.beginPath();
- _context.moveTo( v1.positionScreen.x, v1.positionScreen.y );
- _context.lineTo( v2.positionScreen.x, v2.positionScreen.y );
+};
- if ( material instanceof THREE.LineBasicMaterial ) {
+THREE.QuaternionKeyframeTrack.prototype =
+ Object.assign( Object.create( THREE.KeyframeTrack.prototype ), {
- setLineWidth( material.linewidth );
- setLineCap( material.linecap );
- setLineJoin( material.linejoin );
+ constructor: THREE.QuaternionKeyframeTrack,
- if ( material.vertexColors !== THREE.VertexColors ) {
+ ValueTypeName: 'quaternion',
- setStrokeStyle( material.color.getStyle() );
+ // ValueBufferType is inherited
- } else {
+ DefaultInterpolation: THREE.InterpolateLinear,
- var colorStyle1 = element.vertexColors[0].getStyle();
- var colorStyle2 = element.vertexColors[1].getStyle();
+ InterpolantFactoryMethodLinear: function( result ) {
- if ( colorStyle1 === colorStyle2 ) {
+ return new THREE.QuaternionLinearInterpolant(
+ this.times, this.values, this.getValueSize(), result );
- setStrokeStyle( colorStyle1 );
+ },
- } else {
+ InterpolantFactoryMethodSmooth: undefined // not yet implemented
- try {
+} );
- var grad = _context.createLinearGradient(
- v1.positionScreen.x,
- v1.positionScreen.y,
- v2.positionScreen.x,
- v2.positionScreen.y
- );
- grad.addColorStop( 0, colorStyle1 );
- grad.addColorStop( 1, colorStyle2 );
+// File:src/animation/tracks/StringKeyframeTrack.js
- } catch ( exception ) {
+/**
+ *
+ * A Track that interpolates Strings
+ *
+ *
+ * @author Ben Houston / http://clara.io/
+ * @author David Sarno / http://lighthaus.us/
+ * @author tschw
+ */
- grad = colorStyle1;
+THREE.StringKeyframeTrack = function ( name, times, values, interpolation ) {
- }
+ THREE.KeyframeTrack.call( this, name, times, values, interpolation );
- setStrokeStyle( grad );
+};
- }
+THREE.StringKeyframeTrack.prototype =
+ Object.assign( Object.create( THREE.KeyframeTrack.prototype ), {
- }
+ constructor: THREE.StringKeyframeTrack,
- _context.stroke();
- _elemBox.expandByScalar( material.linewidth * 2 );
+ ValueTypeName: 'string',
+ ValueBufferType: Array,
- } else if ( material instanceof THREE.LineDashedMaterial ) {
+ DefaultInterpolation: THREE.InterpolateDiscrete,
- setLineWidth( material.linewidth );
- setLineCap( material.linecap );
- setLineJoin( material.linejoin );
- setStrokeStyle( material.color.getStyle() );
- setDashAndGap( material.dashSize, material.gapSize );
+ InterpolantFactoryMethodLinear: undefined,
- _context.stroke();
+ InterpolantFactoryMethodSmooth: undefined
- _elemBox.expandByScalar( material.linewidth * 2 );
+} );
- setDashAndGap( null, null );
+// File:src/animation/tracks/VectorKeyframeTrack.js
- }
+/**
+ *
+ * A Track of vectored keyframe values.
+ *
+ *
+ * @author Ben Houston / http://clara.io/
+ * @author David Sarno / http://lighthaus.us/
+ * @author tschw
+ */
- }
+THREE.VectorKeyframeTrack = function ( name, times, values, interpolation ) {
- function renderFace3( v1, v2, v3, uv1, uv2, uv3, element, material ) {
+ THREE.KeyframeTrack.call( this, name, times, values, interpolation );
- _this.info.render.vertices += 3;
- _this.info.render.faces ++;
+};
- setOpacity( material.opacity );
- setBlending( material.blending );
+THREE.VectorKeyframeTrack.prototype =
+ Object.assign( Object.create( THREE.KeyframeTrack.prototype ), {
- _v1x = v1.positionScreen.x; _v1y = v1.positionScreen.y;
- _v2x = v2.positionScreen.x; _v2y = v2.positionScreen.y;
- _v3x = v3.positionScreen.x; _v3y = v3.positionScreen.y;
+ constructor: THREE.VectorKeyframeTrack,
- drawTriangle( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y );
+ ValueTypeName: 'vector'
- if ( ( material instanceof THREE.MeshLambertMaterial || material instanceof THREE.MeshPhongMaterial ) && material.map === null ) {
+ // ValueBufferType is inherited
- _diffuseColor.copy( material.color );
- _emissiveColor.copy( material.emissive );
+ // DefaultInterpolation is inherited
- if ( material.vertexColors === THREE.FaceColors ) {
+} );
- _diffuseColor.multiply( element.color );
+// File:src/audio/Audio.js
- }
+/**
+ * @author mrdoob / http://mrdoob.com/
+ * @author Reece Aaron Lecrivain / http://reecenotes.com/
+ */
- if ( material.wireframe === false && material.shading == THREE.SmoothShading && element.vertexNormalsLength == 3 ) {
+THREE.Audio = function ( listener ) {
- _color1.copy( _ambientLight );
- _color2.copy( _ambientLight );
- _color3.copy( _ambientLight );
+ THREE.Object3D.call( this );
- calculateLight( element.v1.positionWorld, element.vertexNormalsModel[ 0 ], _color1 );
- calculateLight( element.v2.positionWorld, element.vertexNormalsModel[ 1 ], _color2 );
- calculateLight( element.v3.positionWorld, element.vertexNormalsModel[ 2 ], _color3 );
+ this.type = 'Audio';
- _color1.multiply( _diffuseColor ).add( _emissiveColor );
- _color2.multiply( _diffuseColor ).add( _emissiveColor );
- _color3.multiply( _diffuseColor ).add( _emissiveColor );
- _color4.addColors( _color2, _color3 ).multiplyScalar( 0.5 );
+ this.context = listener.context;
+ this.source = this.context.createBufferSource();
+ this.source.onended = this.onEnded.bind( this );
- _image = getGradientTexture( _color1, _color2, _color3, _color4 );
+ this.gain = this.context.createGain();
+ this.gain.connect( listener.getInput() );
- clipImage( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, 0, 0, 1, 0, 0, 1, _image );
+ this.autoplay = false;
- } else {
+ this.startTime = 0;
+ this.playbackRate = 1;
+ this.isPlaying = false;
+ this.hasPlaybackControl = true;
+ this.sourceType = 'empty';
- _color.copy( _ambientLight );
+ this.filters = [];
- calculateLight( element.centroidModel, element.normalModel, _color );
+};
- _color.multiply( _diffuseColor ).add( _emissiveColor );
+THREE.Audio.prototype = Object.assign( Object.create( THREE.Object3D.prototype ), {
- material.wireframe === true
- ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin )
- : fillPath( _color );
+ constructor: THREE.Audio,
- }
+ getOutput: function () {
- } else if ( material instanceof THREE.MeshBasicMaterial || material instanceof THREE.MeshLambertMaterial || material instanceof THREE.MeshPhongMaterial ) {
+ return this.gain;
- if ( material.map !== null ) {
+ },
- if ( material.map.mapping instanceof THREE.UVMapping ) {
+ setNodeSource: function ( audioNode ) {
- _uvs = element.uvs[ 0 ];
- 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 );
+ this.hasPlaybackControl = false;
+ this.sourceType = 'audioNode';
+ this.source = audioNode;
+ this.connect();
- }
+ return this;
+
+ },
+ setBuffer: function ( audioBuffer ) {
- } else if ( material.envMap !== null ) {
+ this.source.buffer = audioBuffer;
+ this.sourceType = 'buffer';
- if ( material.envMap.mapping instanceof THREE.SphericalReflectionMapping ) {
+ if ( this.autoplay ) this.play();
- _vector3.copy( element.vertexNormalsModelView[ uv1 ] );
- _uv1x = 0.5 * _vector3.x + 0.5;
- _uv1y = 0.5 * _vector3.y + 0.5;
+ return this;
- _vector3.copy( element.vertexNormalsModelView[ uv2 ] );
- _uv2x = 0.5 * _vector3.x + 0.5;
- _uv2y = 0.5 * _vector3.y + 0.5;
+ },
- _vector3.copy( element.vertexNormalsModelView[ uv3 ] );
- _uv3x = 0.5 * _vector3.x + 0.5;
- _uv3y = 0.5 * _vector3.y + 0.5;
+ play: function () {
- patternPath( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _uv1x, _uv1y, _uv2x, _uv2y, _uv3x, _uv3y, material.envMap );
+ if ( this.isPlaying === true ) {
- }/* else if ( material.envMap.mapping == THREE.SphericalRefractionMapping ) {
+ console.warn( 'THREE.Audio: Audio is already playing.' );
+ return;
+ }
+ if ( this.hasPlaybackControl === false ) {
- }*/
+ console.warn( 'THREE.Audio: this Audio has no playback control.' );
+ return;
+ }
- } else {
+ var source = this.context.createBufferSource();
- _color.copy( material.color );
+ source.buffer = this.source.buffer;
+ source.loop = this.source.loop;
+ source.onended = this.source.onended;
+ source.start( 0, this.startTime );
+ source.playbackRate.value = this.playbackRate;
- if ( material.vertexColors === THREE.FaceColors ) {
+ this.isPlaying = true;
- _color.multiply( element.color );
+ this.source = source;
- }
+ return this.connect();
- material.wireframe === true
- ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin )
- : fillPath( _color );
+ },
- }
+ pause: function () {
- } else if ( material instanceof THREE.MeshDepthMaterial ) {
+ if ( this.hasPlaybackControl === false ) {
- _near = _camera.near;
- _far = _camera.far;
+ console.warn( 'THREE.Audio: this Audio has no playback control.' );
+ return;
- _color1.r = _color1.g = _color1.b = 1 - smoothstep( v1.positionScreen.z * v1.positionScreen.w, _near, _far );
- _color2.r = _color2.g = _color2.b = 1 - smoothstep( v2.positionScreen.z * v2.positionScreen.w, _near, _far );
- _color3.r = _color3.g = _color3.b = 1 - smoothstep( v3.positionScreen.z * v3.positionScreen.w, _near, _far );
- _color4.addColors( _color2, _color3 ).multiplyScalar( 0.5 );
+ }
- _image = getGradientTexture( _color1, _color2, _color3, _color4 );
+ this.source.stop();
+ this.startTime = this.context.currentTime;
+ this.isPlaying = false;
- clipImage( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, 0, 0, 1, 0, 0, 1, _image );
+ return this;
- } else if ( material instanceof THREE.MeshNormalMaterial ) {
+ },
- var normal;
+ stop: function () {
- if ( material.shading == THREE.FlatShading ) {
+ if ( this.hasPlaybackControl === false ) {
- normal = element.normalModelView;
+ console.warn( 'THREE.Audio: this Audio has no playback control.' );
+ return;
- _color.setRGB( normal.x, normal.y, normal.z ).multiplyScalar( 0.5 ).addScalar( 0.5 );
+ }
- material.wireframe === true
- ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin )
- : fillPath( _color );
+ this.source.stop();
+ this.startTime = 0;
+ this.isPlaying = false;
- } else if ( material.shading == THREE.SmoothShading ) {
+ return this;
- normal = element.vertexNormalsModelView[ uv1 ];
- _color1.setRGB( normal.x, normal.y, normal.z ).multiplyScalar( 0.5 ).addScalar( 0.5 );
+ },
- normal = element.vertexNormalsModelView[ uv2 ];
- _color2.setRGB( normal.x, normal.y, normal.z ).multiplyScalar( 0.5 ).addScalar( 0.5 );
+ connect: function () {
- normal = element.vertexNormalsModelView[ uv3 ];
- _color3.setRGB( normal.x, normal.y, normal.z ).multiplyScalar( 0.5 ).addScalar( 0.5 );
+ if ( this.filters.length > 0 ) {
- _color4.addColors( _color2, _color3 ).multiplyScalar( 0.5 );
+ this.source.connect( this.filters[ 0 ] );
- _image = getGradientTexture( _color1, _color2, _color3, _color4 );
+ for ( var i = 1, l = this.filters.length; i < l; i ++ ) {
- clipImage( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, 0, 0, 1, 0, 0, 1, _image );
+ this.filters[ i - 1 ].connect( this.filters[ i ] );
}
- }
+ this.filters[ this.filters.length - 1 ].connect( this.getOutput() );
- }
+ } else {
- //
+ this.source.connect( this.getOutput() );
- function drawTriangle( x0, y0, x1, y1, x2, y2 ) {
+ }
- _context.beginPath();
- _context.moveTo( x0, y0 );
- _context.lineTo( x1, y1 );
- _context.lineTo( x2, y2 );
- _context.closePath();
+ return this;
- }
+ },
- function strokePath( color, linewidth, linecap, linejoin ) {
+ disconnect: function () {
- setLineWidth( linewidth );
- setLineCap( linecap );
- setLineJoin( linejoin );
- setStrokeStyle( color.getStyle() );
+ if ( this.filters.length > 0 ) {
- _context.stroke();
+ this.source.disconnect( this.filters[ 0 ] );
- _elemBox.expandByScalar( linewidth * 2 );
+ for ( var i = 1, l = this.filters.length; i < l; i ++ ) {
- }
+ this.filters[ i - 1 ].disconnect( this.filters[ i ] );
- function fillPath( color ) {
+ }
- setFillStyle( color.getStyle() );
- _context.fill();
+ this.filters[ this.filters.length - 1 ].disconnect( this.getOutput() );
- }
+ } else {
- function patternPath( x0, y0, x1, y1, x2, y2, u0, v0, u1, v1, u2, v2, texture ) {
+ this.source.disconnect( this.getOutput() );
- if ( texture instanceof THREE.DataTexture || texture.image === undefined || texture.image.width == 0 ) return;
+ }
- if ( texture.needsUpdate === true ) {
+ return this;
- var repeatX = texture.wrapS == THREE.RepeatWrapping;
- var repeatY = texture.wrapT == THREE.RepeatWrapping;
+ },
- _patterns[ texture.id ] = _context.createPattern(
- texture.image, repeatX === true && repeatY === true
- ? 'repeat'
- : repeatX === true && repeatY === false
- ? 'repeat-x'
- : repeatX === false && repeatY === true
- ? 'repeat-y'
- : 'no-repeat'
- );
+ getFilters: function () {
- texture.needsUpdate = false;
+ return this.filters;
- }
+ },
- _patterns[ texture.id ] === undefined
- ? setFillStyle( 'rgba(0,0,0,1)' )
- : setFillStyle( _patterns[ texture.id ] );
+ setFilters: function ( value ) {
- // http://extremelysatisfactorytotalitarianism.com/blog/?p=2120
+ if ( ! value ) value = [];
- var a, b, c, d, e, f, det, idet,
- offsetX = texture.offset.x / texture.repeat.x,
- offsetY = texture.offset.y / texture.repeat.y,
- width = texture.image.width * texture.repeat.x,
- height = texture.image.height * texture.repeat.y;
+ if ( this.isPlaying === true ) {
- u0 = ( u0 + offsetX ) * width;
- v0 = ( 1.0 - v0 + offsetY ) * height;
+ this.disconnect();
+ this.filters = value;
+ this.connect();
- u1 = ( u1 + offsetX ) * width;
- v1 = ( 1.0 - v1 + offsetY ) * height;
+ } else {
- u2 = ( u2 + offsetX ) * width;
- v2 = ( 1.0 - v2 + offsetY ) * height;
+ this.filters = value;
- x1 -= x0; y1 -= y0;
- x2 -= x0; y2 -= y0;
+ }
- u1 -= u0; v1 -= v0;
- u2 -= u0; v2 -= v0;
+ return this;
- det = u1 * v2 - u2 * v1;
+ },
- if ( det === 0 ) {
+ getFilter: function () {
- if ( _imagedatas[ texture.id ] === undefined ) {
+ return this.getFilters()[ 0 ];
- var canvas = document.createElement( 'canvas' )
- canvas.width = texture.image.width;
- canvas.height = texture.image.height;
+ },
- var context = canvas.getContext( '2d' );
- context.drawImage( texture.image, 0, 0 );
+ setFilter: function ( filter ) {
- _imagedatas[ texture.id ] = context.getImageData( 0, 0, texture.image.width, texture.image.height ).data;
+ return this.setFilters( filter ? [ filter ] : [] );
- }
+ },
- var data = _imagedatas[ texture.id ];
- var index = ( Math.floor( u0 ) + Math.floor( v0 ) * texture.image.width ) * 4;
+ setPlaybackRate: function ( value ) {
- _color.setRGB( data[ index ] / 255, data[ index + 1 ] / 255, data[ index + 2 ] / 255 );
- fillPath( _color );
+ if ( this.hasPlaybackControl === false ) {
+ console.warn( 'THREE.Audio: this Audio has no playback control.' );
return;
}
- idet = 1 / det;
-
- a = ( v2 * x1 - v1 * x2 ) * idet;
- b = ( v2 * y1 - v1 * y2 ) * idet;
- c = ( u1 * x2 - u2 * x1 ) * idet;
- d = ( u1 * y2 - u2 * y1 ) * idet;
+ this.playbackRate = value;
- e = x0 - a * u0 - c * v0;
- f = y0 - b * u0 - d * v0;
+ if ( this.isPlaying === true ) {
- _context.save();
- _context.transform( a, b, c, d, e, f );
- _context.fill();
- _context.restore();
+ this.source.playbackRate.value = this.playbackRate;
- }
-
- function clipImage( x0, y0, x1, y1, x2, y2, u0, v0, u1, v1, u2, v2, image ) {
+ }
- // http://extremelysatisfactorytotalitarianism.com/blog/?p=2120
+ return this;
- var a, b, c, d, e, f, det, idet,
- width = image.width - 1,
- height = image.height - 1;
+ },
- u0 *= width; v0 *= height;
- u1 *= width; v1 *= height;
- u2 *= width; v2 *= height;
+ getPlaybackRate: function () {
- x1 -= x0; y1 -= y0;
- x2 -= x0; y2 -= y0;
+ return this.playbackRate;
- u1 -= u0; v1 -= v0;
- u2 -= u0; v2 -= v0;
+ },
- det = u1 * v2 - u2 * v1;
+ onEnded: function () {
- idet = 1 / det;
+ this.isPlaying = false;
- a = ( v2 * x1 - v1 * x2 ) * idet;
- b = ( v2 * y1 - v1 * y2 ) * idet;
- c = ( u1 * x2 - u2 * x1 ) * idet;
- d = ( u1 * y2 - u2 * y1 ) * idet;
+ },
- e = x0 - a * u0 - c * v0;
- f = y0 - b * u0 - d * v0;
+ getLoop: function () {
- _context.save();
- _context.transform( a, b, c, d, e, f );
- _context.clip();
- _context.drawImage( image, 0, 0 );
- _context.restore();
+ if ( this.hasPlaybackControl === false ) {
- }
+ console.warn( 'THREE.Audio: this Audio has no playback control.' );
+ return false;
- function getGradientTexture( color1, color2, color3, color4 ) {
+ }
- // http://mrdoob.com/blog/post/710
+ return this.source.loop;
- _pixelMapData[ 0 ] = ( color1.r * 255 ) | 0;
- _pixelMapData[ 1 ] = ( color1.g * 255 ) | 0;
- _pixelMapData[ 2 ] = ( color1.b * 255 ) | 0;
+ },
- _pixelMapData[ 4 ] = ( color2.r * 255 ) | 0;
- _pixelMapData[ 5 ] = ( color2.g * 255 ) | 0;
- _pixelMapData[ 6 ] = ( color2.b * 255 ) | 0;
+ setLoop: function ( value ) {
- _pixelMapData[ 8 ] = ( color3.r * 255 ) | 0;
- _pixelMapData[ 9 ] = ( color3.g * 255 ) | 0;
- _pixelMapData[ 10 ] = ( color3.b * 255 ) | 0;
+ if ( this.hasPlaybackControl === false ) {
- _pixelMapData[ 12 ] = ( color4.r * 255 ) | 0;
- _pixelMapData[ 13 ] = ( color4.g * 255 ) | 0;
- _pixelMapData[ 14 ] = ( color4.b * 255 ) | 0;
+ console.warn( 'THREE.Audio: this Audio has no playback control.' );
+ return;
- _pixelMapContext.putImageData( _pixelMapImage, 0, 0 );
- _gradientMapContext.drawImage( _pixelMap, 0, 0 );
+ }
- return _gradientMap;
+ this.source.loop = value;
- }
+ },
- // Hide anti-alias gaps
+ getVolume: function () {
- function expand( v1, v2, pixels ) {
+ return this.gain.gain.value;
- var x = v2.x - v1.x, y = v2.y - v1.y,
- det = x * x + y * y, idet;
+ },
- if ( det === 0 ) return;
- idet = pixels / Math.sqrt( det );
+ setVolume: function ( value ) {
- x *= idet; y *= idet;
+ this.gain.gain.value = value;
- v2.x += x; v2.y += y;
- v1.x -= x; v1.y -= y;
+ return this;
}
- // Context cached methods.
+} );
+
+// File:src/audio/AudioAnalyser.js
- function setOpacity( value ) {
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
- if ( _contextGlobalAlpha !== value ) {
+THREE.AudioAnalyser = function ( audio, fftSize ) {
- _context.globalAlpha = value;
- _contextGlobalAlpha = value;
+ this.analyser = audio.context.createAnalyser();
+ this.analyser.fftSize = fftSize !== undefined ? fftSize : 2048;
- }
+ this.data = new Uint8Array( this.analyser.frequencyBinCount );
- }
+ audio.getOutput().connect( this.analyser );
- function setBlending( value ) {
+};
- if ( _contextGlobalCompositeOperation !== value ) {
+Object.assign( THREE.AudioAnalyser.prototype, {
- if ( value === THREE.NormalBlending ) {
+ getFrequencyData: function () {
- _context.globalCompositeOperation = 'source-over';
+ this.analyser.getByteFrequencyData( this.data );
- } else if ( value === THREE.AdditiveBlending ) {
+ return this.data;
- _context.globalCompositeOperation = 'lighter';
+ },
- } else if ( value === THREE.SubtractiveBlending ) {
+ getAverageFrequency: function () {
- _context.globalCompositeOperation = 'darker';
+ var value = 0, data = this.getFrequencyData();
- }
+ for ( var i = 0; i < data.length; i ++ ) {
- _contextGlobalCompositeOperation = value;
+ value += data[ i ];
}
+ return value / data.length;
+
}
- function setLineWidth( value ) {
+} );
- if ( _contextLineWidth !== value ) {
+// File:src/audio/AudioContext.js
- _context.lineWidth = value;
- _contextLineWidth = value;
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
- }
+Object.defineProperty( THREE, 'AudioContext', {
- }
+ get: ( function () {
- function setLineCap( value ) {
+ var context;
- // "butt", "round", "square"
+ return function get() {
- if ( _contextLineCap !== value ) {
+ if ( context === undefined ) {
- _context.lineCap = value;
- _contextLineCap = value;
+ context = new ( window.AudioContext || window.webkitAudioContext )();
- }
+ }
- }
+ return context;
- function setLineJoin( value ) {
+ };
- // "round", "bevel", "miter"
+ } )()
- if ( _contextLineJoin !== value ) {
+} );
- _context.lineJoin = value;
- _contextLineJoin = value;
+// File:src/audio/PositionalAudio.js
- }
-
- }
-
- function setStrokeStyle( value ) {
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
- if ( _contextStrokeStyle !== value ) {
+THREE.PositionalAudio = function ( listener ) {
- _context.strokeStyle = value;
- _contextStrokeStyle = value;
+ THREE.Audio.call( this, listener );
- }
+ this.panner = this.context.createPanner();
+ this.panner.connect( this.gain );
- }
+};
- function setFillStyle( value ) {
+THREE.PositionalAudio.prototype = Object.assign( Object.create( THREE.Audio.prototype ), {
- if ( _contextFillStyle !== value ) {
+ constructor: THREE.PositionalAudio,
- _context.fillStyle = value;
- _contextFillStyle = value;
+ getOutput: function () {
- }
+ return this.panner;
- }
+ },
- function setDashAndGap( dashSizeValue, gapSizeValue ) {
+ getRefDistance: function () {
- if ( _contextDashSize !== dashSizeValue || _contextGapSize !== gapSizeValue ) {
+ return this.panner.refDistance;
- _context.setLineDash( [ dashSizeValue, gapSizeValue ] );
- _contextDashSize = dashSizeValue;
- _contextGapSize = gapSizeValue;
+ },
- }
+ setRefDistance: function ( value ) {
- }
+ this.panner.refDistance = value;
-};
+ },
-/**
- * @author alteredq / http://alteredqualia.com/
- * @author mrdoob / http://mrdoob.com/
- * @author mikael emtinger / http://gomo.se/
- */
+ getRolloffFactor: function () {
-THREE.ShaderChunk = {
+ return this.panner.rolloffFactor;
- // FOG
+ },
- fog_pars_fragment: [
+ setRolloffFactor: function ( value ) {
- "#ifdef USE_FOG",
+ this.panner.rolloffFactor = value;
- "uniform vec3 fogColor;",
+ },
- "#ifdef FOG_EXP2",
+ getDistanceModel: function () {
- "uniform float fogDensity;",
+ return this.panner.distanceModel;
- "#else",
+ },
- "uniform float fogNear;",
- "uniform float fogFar;",
+ setDistanceModel: function ( value ) {
- "#endif",
+ this.panner.distanceModel = value;
- "#endif"
+ },
- ].join("\n"),
+ getMaxDistance: function () {
- fog_fragment: [
+ return this.panner.maxDistance;
- "#ifdef USE_FOG",
+ },
- "float depth = gl_FragCoord.z / gl_FragCoord.w;",
+ setMaxDistance: function ( value ) {
- "#ifdef FOG_EXP2",
+ this.panner.maxDistance = value;
- "const float LOG2 = 1.442695;",
- "float fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );",
- "fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );",
+ },
- "#else",
+ updateMatrixWorld: ( function () {
- "float fogFactor = smoothstep( fogNear, fogFar, depth );",
+ var position = new THREE.Vector3();
- "#endif",
+ return function updateMatrixWorld( force ) {
- "gl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );",
+ THREE.Object3D.prototype.updateMatrixWorld.call( this, force );
- "#endif"
+ position.setFromMatrixPosition( this.matrixWorld );
- ].join("\n"),
+ this.panner.setPosition( position.x, position.y, position.z );
- // ENVIRONMENT MAP
+ };
- envmap_pars_fragment: [
+ } )()
- "#ifdef USE_ENVMAP",
- "uniform float reflectivity;",
- "uniform samplerCube envMap;",
- "uniform float flipEnvMap;",
- "uniform int combine;",
+} );
- "#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )",
+// File:src/audio/AudioListener.js
- "uniform bool useRefract;",
- "uniform float refractionRatio;",
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
- "#else",
+THREE.AudioListener = function () {
- "varying vec3 vReflect;",
+ THREE.Object3D.call( this );
- "#endif",
+ this.type = 'AudioListener';
- "#endif"
+ this.context = THREE.AudioContext;
- ].join("\n"),
+ this.gain = this.context.createGain();
+ this.gain.connect( this.context.destination );
- envmap_fragment: [
+ this.filter = null;
- "#ifdef USE_ENVMAP",
+};
- "vec3 reflectVec;",
+THREE.AudioListener.prototype = Object.assign( Object.create( THREE.Object3D.prototype ), {
- "#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )",
+ constructor: THREE.AudioListener,
- "vec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );",
+ getInput: function () {
- "if ( useRefract ) {",
+ return this.gain;
- "reflectVec = refract( cameraToVertex, normal, refractionRatio );",
+ },
- "} else { ",
+ removeFilter: function ( ) {
- "reflectVec = reflect( cameraToVertex, normal );",
+ if ( this.filter !== null ) {
- "}",
+ this.gain.disconnect( this.filter );
+ this.filter.disconnect( this.context.destination );
+ this.gain.connect( this.context.destination );
+ this.filter = null;
- "#else",
+ }
- "reflectVec = vReflect;",
+ },
- "#endif",
+ getFilter: function () {
- "#ifdef DOUBLE_SIDED",
+ return this.filter;
- "float flipNormal = ( -1.0 + 2.0 * float( gl_FrontFacing ) );",
- "vec4 cubeColor = textureCube( envMap, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );",
+ },
- "#else",
+ setFilter: function ( value ) {
- "vec4 cubeColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );",
+ if ( this.filter !== null ) {
- "#endif",
+ this.gain.disconnect( this.filter );
+ this.filter.disconnect( this.context.destination );
- "#ifdef GAMMA_INPUT",
+ } else {
- "cubeColor.xyz *= cubeColor.xyz;",
+ this.gain.disconnect( this.context.destination );
- "#endif",
+ }
- "if ( combine == 1 ) {",
+ this.filter = value;
+ this.gain.connect( this.filter );
+ this.filter.connect( this.context.destination );
- "gl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularStrength * reflectivity );",
+ },
- "} else if ( combine == 2 ) {",
+ getMasterVolume: function () {
- "gl_FragColor.xyz += cubeColor.xyz * specularStrength * reflectivity;",
+ return this.gain.gain.value;
- "} else {",
+ },
- "gl_FragColor.xyz = mix( gl_FragColor.xyz, gl_FragColor.xyz * cubeColor.xyz, specularStrength * reflectivity );",
+ setMasterVolume: function ( value ) {
- "}",
+ this.gain.gain.value = value;
- "#endif"
+ },
- ].join("\n"),
+ updateMatrixWorld: ( function () {
- envmap_pars_vertex: [
+ var position = new THREE.Vector3();
+ var quaternion = new THREE.Quaternion();
+ var scale = new THREE.Vector3();
- "#if defined( USE_ENVMAP ) && ! defined( USE_BUMPMAP ) && ! defined( USE_NORMALMAP )",
+ var orientation = new THREE.Vector3();
- "varying vec3 vReflect;",
+ return function updateMatrixWorld( force ) {
- "uniform float refractionRatio;",
- "uniform bool useRefract;",
+ THREE.Object3D.prototype.updateMatrixWorld.call( this, force );
- "#endif"
+ var listener = this.context.listener;
+ var up = this.up;
- ].join("\n"),
+ this.matrixWorld.decompose( position, quaternion, scale );
- worldpos_vertex : [
+ orientation.set( 0, 0, - 1 ).applyQuaternion( quaternion );
- "#if defined( USE_ENVMAP ) || defined( PHONG ) || defined( LAMBERT ) || defined ( USE_SHADOWMAP )",
+ listener.setPosition( position.x, position.y, position.z );
+ listener.setOrientation( orientation.x, orientation.y, orientation.z, up.x, up.y, up.z );
- "#ifdef USE_SKINNING",
+ };
- "vec4 worldPosition = modelMatrix * skinned;",
+ } )()
- "#endif",
+} );
- "#if defined( USE_MORPHTARGETS ) && ! defined( USE_SKINNING )",
+// File:src/cameras/Camera.js
- "vec4 worldPosition = modelMatrix * vec4( morphed, 1.0 );",
+/**
+ * @author mrdoob / http://mrdoob.com/
+ * @author mikael emtinger / http://gomo.se/
+ * @author WestLangley / http://github.com/WestLangley
+*/
- "#endif",
+THREE.Camera = function () {
- "#if ! defined( USE_MORPHTARGETS ) && ! defined( USE_SKINNING )",
+ THREE.Object3D.call( this );
- "vec4 worldPosition = modelMatrix * vec4( position, 1.0 );",
+ this.type = 'Camera';
- "#endif",
+ this.matrixWorldInverse = new THREE.Matrix4();
+ this.projectionMatrix = new THREE.Matrix4();
- "#endif"
+};
- ].join("\n"),
+THREE.Camera.prototype = Object.create( THREE.Object3D.prototype );
+THREE.Camera.prototype.constructor = THREE.Camera;
- envmap_vertex : [
+THREE.Camera.prototype.getWorldDirection = function () {
- "#if defined( USE_ENVMAP ) && ! defined( USE_BUMPMAP ) && ! defined( USE_NORMALMAP )",
+ var quaternion = new THREE.Quaternion();
- "vec3 worldNormal = mat3( modelMatrix[ 0 ].xyz, modelMatrix[ 1 ].xyz, modelMatrix[ 2 ].xyz ) * objectNormal;",
- "worldNormal = normalize( worldNormal );",
+ return function getWorldDirection( optionalTarget ) {
- "vec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );",
+ var result = optionalTarget || new THREE.Vector3();
- "if ( useRefract ) {",
+ this.getWorldQuaternion( quaternion );
- "vReflect = refract( cameraToVertex, worldNormal, refractionRatio );",
+ return result.set( 0, 0, - 1 ).applyQuaternion( quaternion );
- "} else {",
+ };
- "vReflect = reflect( cameraToVertex, worldNormal );",
+}();
- "}",
+THREE.Camera.prototype.lookAt = function () {
- "#endif"
+ // This routine does not support cameras with rotated and/or translated parent(s)
- ].join("\n"),
+ var m1 = new THREE.Matrix4();
- // COLOR MAP (particles)
+ return function lookAt( vector ) {
- map_particle_pars_fragment: [
+ m1.lookAt( this.position, vector, this.up );
- "#ifdef USE_MAP",
+ this.quaternion.setFromRotationMatrix( m1 );
- "uniform sampler2D map;",
+ };
- "#endif"
+}();
- ].join("\n"),
+THREE.Camera.prototype.clone = function () {
+ return new this.constructor().copy( this );
- map_particle_fragment: [
+};
- "#ifdef USE_MAP",
+THREE.Camera.prototype.copy = function ( source ) {
- "gl_FragColor = gl_FragColor * texture2D( map, vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y ) );",
+ THREE.Object3D.prototype.copy.call( this, source );
- "#endif"
+ this.matrixWorldInverse.copy( source.matrixWorldInverse );
+ this.projectionMatrix.copy( source.projectionMatrix );
- ].join("\n"),
+ return this;
- // COLOR MAP (triangles)
+};
- map_pars_vertex: [
+// File:src/cameras/CubeCamera.js
- "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP )",
+/**
+ * Camera for rendering cube maps
+ * - renders scene into axis-aligned cube
+ *
+ * @author alteredq / http://alteredqualia.com/
+ */
- "varying vec2 vUv;",
- "uniform vec4 offsetRepeat;",
+THREE.CubeCamera = function ( near, far, cubeResolution ) {
- "#endif"
+ THREE.Object3D.call( this );
- ].join("\n"),
+ this.type = 'CubeCamera';
- map_pars_fragment: [
+ var fov = 90, aspect = 1;
- "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP )",
+ var cameraPX = new THREE.PerspectiveCamera( fov, aspect, near, far );
+ cameraPX.up.set( 0, - 1, 0 );
+ cameraPX.lookAt( new THREE.Vector3( 1, 0, 0 ) );
+ this.add( cameraPX );
- "varying vec2 vUv;",
+ var cameraNX = new THREE.PerspectiveCamera( fov, aspect, near, far );
+ cameraNX.up.set( 0, - 1, 0 );
+ cameraNX.lookAt( new THREE.Vector3( - 1, 0, 0 ) );
+ this.add( cameraNX );
- "#endif",
+ var cameraPY = new THREE.PerspectiveCamera( fov, aspect, near, far );
+ cameraPY.up.set( 0, 0, 1 );
+ cameraPY.lookAt( new THREE.Vector3( 0, 1, 0 ) );
+ this.add( cameraPY );
- "#ifdef USE_MAP",
+ var cameraNY = new THREE.PerspectiveCamera( fov, aspect, near, far );
+ cameraNY.up.set( 0, 0, - 1 );
+ cameraNY.lookAt( new THREE.Vector3( 0, - 1, 0 ) );
+ this.add( cameraNY );
- "uniform sampler2D map;",
+ var cameraPZ = new THREE.PerspectiveCamera( fov, aspect, near, far );
+ cameraPZ.up.set( 0, - 1, 0 );
+ cameraPZ.lookAt( new THREE.Vector3( 0, 0, 1 ) );
+ this.add( cameraPZ );
- "#endif"
+ var cameraNZ = new THREE.PerspectiveCamera( fov, aspect, near, far );
+ cameraNZ.up.set( 0, - 1, 0 );
+ cameraNZ.lookAt( new THREE.Vector3( 0, 0, - 1 ) );
+ this.add( cameraNZ );
- ].join("\n"),
+ var options = { format: THREE.RGBFormat, magFilter: THREE.LinearFilter, minFilter: THREE.LinearFilter };
- map_vertex: [
+ this.renderTarget = new THREE.WebGLRenderTargetCube( cubeResolution, cubeResolution, options );
- "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP )",
+ this.updateCubeMap = function ( renderer, scene ) {
- "vUv = uv * offsetRepeat.zw + offsetRepeat.xy;",
+ if ( this.parent === null ) this.updateMatrixWorld();
- "#endif"
+ var renderTarget = this.renderTarget;
+ var generateMipmaps = renderTarget.texture.generateMipmaps;
- ].join("\n"),
+ renderTarget.texture.generateMipmaps = false;
- map_fragment: [
+ renderTarget.activeCubeFace = 0;
+ renderer.render( scene, cameraPX, renderTarget );
- "#ifdef USE_MAP",
+ renderTarget.activeCubeFace = 1;
+ renderer.render( scene, cameraNX, renderTarget );
- "vec4 texelColor = texture2D( map, vUv );",
+ renderTarget.activeCubeFace = 2;
+ renderer.render( scene, cameraPY, renderTarget );
- "#ifdef GAMMA_INPUT",
+ renderTarget.activeCubeFace = 3;
+ renderer.render( scene, cameraNY, renderTarget );
- "texelColor.xyz *= texelColor.xyz;",
+ renderTarget.activeCubeFace = 4;
+ renderer.render( scene, cameraPZ, renderTarget );
- "#endif",
+ renderTarget.texture.generateMipmaps = generateMipmaps;
- "gl_FragColor = gl_FragColor * texelColor;",
+ renderTarget.activeCubeFace = 5;
+ renderer.render( scene, cameraNZ, renderTarget );
- "#endif"
+ renderer.setRenderTarget( null );
- ].join("\n"),
+ };
- // LIGHT MAP
+};
- lightmap_pars_fragment: [
+THREE.CubeCamera.prototype = Object.create( THREE.Object3D.prototype );
+THREE.CubeCamera.prototype.constructor = THREE.CubeCamera;
- "#ifdef USE_LIGHTMAP",
+// File:src/cameras/OrthographicCamera.js
- "varying vec2 vUv2;",
- "uniform sampler2D lightMap;",
+/**
+ * @author alteredq / http://alteredqualia.com/
+ * @author arose / http://github.com/arose
+ */
- "#endif"
+THREE.OrthographicCamera = function ( left, right, top, bottom, near, far ) {
- ].join("\n"),
+ THREE.Camera.call( this );
- lightmap_pars_vertex: [
+ this.type = 'OrthographicCamera';
- "#ifdef USE_LIGHTMAP",
+ this.zoom = 1;
+ this.view = null;
- "varying vec2 vUv2;",
+ this.left = left;
+ this.right = right;
+ this.top = top;
+ this.bottom = bottom;
- "#endif"
+ this.near = ( near !== undefined ) ? near : 0.1;
+ this.far = ( far !== undefined ) ? far : 2000;
- ].join("\n"),
+ this.updateProjectionMatrix();
- lightmap_fragment: [
+};
- "#ifdef USE_LIGHTMAP",
+THREE.OrthographicCamera.prototype = Object.assign( Object.create( THREE.Camera.prototype ), {
- "gl_FragColor = gl_FragColor * texture2D( lightMap, vUv2 );",
+ constructor: THREE.OrthographicCamera,
- "#endif"
+ copy: function ( source ) {
- ].join("\n"),
+ THREE.Camera.prototype.copy.call( this, source );
- lightmap_vertex: [
+ this.left = source.left;
+ this.right = source.right;
+ this.top = source.top;
+ this.bottom = source.bottom;
+ this.near = source.near;
+ this.far = source.far;
- "#ifdef USE_LIGHTMAP",
+ this.zoom = source.zoom;
+ this.view = source.view === null ? null : Object.assign( {}, source.view );
- "vUv2 = uv2;",
+ return this;
- "#endif"
+ },
- ].join("\n"),
+ setViewOffset: function( fullWidth, fullHeight, x, y, width, height ) {
- // BUMP MAP
+ this.view = {
+ fullWidth: fullWidth,
+ fullHeight: fullHeight,
+ offsetX: x,
+ offsetY: y,
+ width: width,
+ height: height
+ };
- bumpmap_pars_fragment: [
+ this.updateProjectionMatrix();
- "#ifdef USE_BUMPMAP",
+ },
- "uniform sampler2D bumpMap;",
- "uniform float bumpScale;",
+ clearViewOffset: function() {
- // Derivative maps - bump mapping unparametrized surfaces by Morten Mikkelsen
- // http://mmikkelsen3d.blogspot.sk/2011/07/derivative-maps.html
+ this.view = null;
+ this.updateProjectionMatrix();
- // Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2)
+ },
- "vec2 dHdxy_fwd() {",
+ updateProjectionMatrix: function () {
- "vec2 dSTdx = dFdx( vUv );",
- "vec2 dSTdy = dFdy( vUv );",
+ var dx = ( this.right - this.left ) / ( 2 * this.zoom );
+ var dy = ( this.top - this.bottom ) / ( 2 * this.zoom );
+ var cx = ( this.right + this.left ) / 2;
+ var cy = ( this.top + this.bottom ) / 2;
- "float Hll = bumpScale * texture2D( bumpMap, vUv ).x;",
- "float dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;",
- "float dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;",
+ var left = cx - dx;
+ var right = cx + dx;
+ var top = cy + dy;
+ var bottom = cy - dy;
- "return vec2( dBx, dBy );",
+ if ( this.view !== null ) {
- "}",
+ var zoomW = this.zoom / ( this.view.width / this.view.fullWidth );
+ var zoomH = this.zoom / ( this.view.height / this.view.fullHeight );
+ var scaleW = ( this.right - this.left ) / this.view.width;
+ var scaleH = ( this.top - this.bottom ) / this.view.height;
- "vec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {",
+ left += scaleW * ( this.view.offsetX / zoomW );
+ right = left + scaleW * ( this.view.width / zoomW );
+ top -= scaleH * ( this.view.offsetY / zoomH );
+ bottom = top - scaleH * ( this.view.height / zoomH );
- "vec3 vSigmaX = dFdx( surf_pos );",
- "vec3 vSigmaY = dFdy( surf_pos );",
- "vec3 vN = surf_norm;", // normalized
+ }
- "vec3 R1 = cross( vSigmaY, vN );",
- "vec3 R2 = cross( vN, vSigmaX );",
+ this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far );
- "float fDet = dot( vSigmaX, R1 );",
+ },
- "vec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );",
- "return normalize( abs( fDet ) * surf_norm - vGrad );",
+ toJSON: function ( meta ) {
- "}",
+ var data = THREE.Object3D.prototype.toJSON.call( this, meta );
- "#endif"
+ data.object.zoom = this.zoom;
+ data.object.left = this.left;
+ data.object.right = this.right;
+ data.object.top = this.top;
+ data.object.bottom = this.bottom;
+ data.object.near = this.near;
+ data.object.far = this.far;
- ].join("\n"),
+ if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
- // NORMAL MAP
+ return data;
- normalmap_pars_fragment: [
+ }
- "#ifdef USE_NORMALMAP",
+} );
- "uniform sampler2D normalMap;",
- "uniform vec2 normalScale;",
+// File:src/cameras/PerspectiveCamera.js
- // Per-Pixel Tangent Space Normal Mapping
- // http://hacksoflife.blogspot.ch/2009/11/per-pixel-tangent-space-normal-mapping.html
+/**
+ * @author mrdoob / http://mrdoob.com/
+ * @author greggman / http://games.greggman.com/
+ * @author zz85 / http://www.lab4games.net/zz85/blog
+ * @author tschw
+ */
- "vec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {",
+THREE.PerspectiveCamera = function ( fov, aspect, near, far ) {
- "vec3 q0 = dFdx( eye_pos.xyz );",
- "vec3 q1 = dFdy( eye_pos.xyz );",
- "vec2 st0 = dFdx( vUv.st );",
- "vec2 st1 = dFdy( vUv.st );",
+ THREE.Camera.call( this );
- "vec3 S = normalize( q0 * st1.t - q1 * st0.t );",
- "vec3 T = normalize( -q0 * st1.s + q1 * st0.s );",
- "vec3 N = normalize( surf_norm );",
+ this.type = 'PerspectiveCamera';
- "vec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;",
- "mapN.xy = normalScale * mapN.xy;",
- "mat3 tsn = mat3( S, T, N );",
- "return normalize( tsn * mapN );",
+ this.fov = fov !== undefined ? fov : 50;
+ this.zoom = 1;
- "}",
+ this.near = near !== undefined ? near : 0.1;
+ this.far = far !== undefined ? far : 2000;
+ this.focus = 10;
- "#endif"
+ this.aspect = aspect !== undefined ? aspect : 1;
+ this.view = null;
- ].join("\n"),
+ this.filmGauge = 35; // width of the film (default in millimeters)
+ this.filmOffset = 0; // horizontal film offset (same unit as gauge)
- // SPECULAR MAP
+ this.updateProjectionMatrix();
- specularmap_pars_fragment: [
+};
- "#ifdef USE_SPECULARMAP",
+THREE.PerspectiveCamera.prototype = Object.assign( Object.create( THREE.Camera.prototype ), {
- "uniform sampler2D specularMap;",
+ constructor: THREE.PerspectiveCamera,
- "#endif"
+ copy: function ( source ) {
- ].join("\n"),
+ THREE.Camera.prototype.copy.call( this, source );
- specularmap_fragment: [
+ this.fov = source.fov;
+ this.zoom = source.zoom;
- "float specularStrength;",
+ this.near = source.near;
+ this.far = source.far;
+ this.focus = source.focus;
- "#ifdef USE_SPECULARMAP",
+ this.aspect = source.aspect;
+ this.view = source.view === null ? null : Object.assign( {}, source.view );
- "vec4 texelSpecular = texture2D( specularMap, vUv );",
- "specularStrength = texelSpecular.r;",
+ this.filmGauge = source.filmGauge;
+ this.filmOffset = source.filmOffset;
- "#else",
+ return this;
- "specularStrength = 1.0;",
+ },
- "#endif"
+ /**
+ * Sets the FOV by focal length in respect to the current .filmGauge.
+ *
+ * The default film gauge is 35, so that the focal length can be specified for
+ * a 35mm (full frame) camera.
+ *
+ * Values for focal length and film gauge must have the same unit.
+ */
+ setFocalLength: function ( focalLength ) {
- ].join("\n"),
+ // see http://www.bobatkins.com/photography/technical/field_of_view.html
+ var vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;
- // LIGHTS LAMBERT
+ this.fov = THREE.Math.RAD2DEG * 2 * Math.atan( vExtentSlope );
+ this.updateProjectionMatrix();
- lights_lambert_pars_vertex: [
+ },
- "uniform vec3 ambient;",
- "uniform vec3 diffuse;",
- "uniform vec3 emissive;",
+ /**
+ * Calculates the focal length from the current .fov and .filmGauge.
+ */
+ getFocalLength: function () {
- "uniform vec3 ambientLightColor;",
+ var vExtentSlope = Math.tan( THREE.Math.DEG2RAD * 0.5 * this.fov );
- "#if MAX_DIR_LIGHTS > 0",
+ return 0.5 * this.getFilmHeight() / vExtentSlope;
- "uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];",
- "uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];",
+ },
- "#endif",
+ getEffectiveFOV: function () {
- "#if MAX_HEMI_LIGHTS > 0",
+ return THREE.Math.RAD2DEG * 2 * Math.atan(
+ Math.tan( THREE.Math.DEG2RAD * 0.5 * this.fov ) / this.zoom );
- "uniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];",
- "uniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];",
- "uniform vec3 hemisphereLightDirection[ MAX_HEMI_LIGHTS ];",
+ },
- "#endif",
+ getFilmWidth: function () {
- "#if MAX_POINT_LIGHTS > 0",
+ // film not completely covered in portrait format (aspect < 1)
+ return this.filmGauge * Math.min( this.aspect, 1 );
- "uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];",
- "uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
- "uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
+ },
- "#endif",
+ getFilmHeight: function () {
- "#if MAX_SPOT_LIGHTS > 0",
+ // film not completely covered in landscape format (aspect > 1)
+ return this.filmGauge / Math.max( this.aspect, 1 );
- "uniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];",
- "uniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];",
- "uniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];",
- "uniform float spotLightDistance[ MAX_SPOT_LIGHTS ];",
- "uniform float spotLightAngleCos[ MAX_SPOT_LIGHTS ];",
- "uniform float spotLightExponent[ MAX_SPOT_LIGHTS ];",
+ },
- "#endif",
+ /**
+ * Sets an offset in a larger frustum. This is useful for multi-window or
+ * multi-monitor/multi-machine setups.
+ *
+ * For example, if you have 3x2 monitors and each monitor is 1920x1080 and
+ * the monitors are in grid like this
+ *
+ * +---+---+---+
+ * | A | B | C |
+ * +---+---+---+
+ * | D | E | F |
+ * +---+---+---+
+ *
+ * then for each monitor you would call it like this
+ *
+ * var w = 1920;
+ * var h = 1080;
+ * var fullWidth = w * 3;
+ * var fullHeight = h * 2;
+ *
+ * --A--
+ * camera.setOffset( fullWidth, fullHeight, w * 0, h * 0, w, h );
+ * --B--
+ * camera.setOffset( fullWidth, fullHeight, w * 1, h * 0, w, h );
+ * --C--
+ * camera.setOffset( fullWidth, fullHeight, w * 2, h * 0, w, h );
+ * --D--
+ * camera.setOffset( fullWidth, fullHeight, w * 0, h * 1, w, h );
+ * --E--
+ * camera.setOffset( fullWidth, fullHeight, w * 1, h * 1, w, h );
+ * --F--
+ * camera.setOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );
+ *
+ * Note there is no reason monitors have to be the same size or in a grid.
+ */
+ setViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) {
- "#ifdef WRAP_AROUND",
+ this.aspect = fullWidth / fullHeight;
- "uniform vec3 wrapRGB;",
+ this.view = {
+ fullWidth: fullWidth,
+ fullHeight: fullHeight,
+ offsetX: x,
+ offsetY: y,
+ width: width,
+ height: height
+ };
- "#endif"
+ this.updateProjectionMatrix();
- ].join("\n"),
+ },
- lights_lambert_vertex: [
+ clearViewOffset: function() {
- "vLightFront = vec3( 0.0 );",
+ this.view = null;
+ this.updateProjectionMatrix();
- "#ifdef DOUBLE_SIDED",
+ },
- "vLightBack = vec3( 0.0 );",
+ updateProjectionMatrix: function () {
- "#endif",
+ var near = this.near,
+ top = near * Math.tan(
+ THREE.Math.DEG2RAD * 0.5 * this.fov ) / this.zoom,
+ height = 2 * top,
+ width = this.aspect * height,
+ left = - 0.5 * width,
+ view = this.view;
- "transformedNormal = normalize( transformedNormal );",
+ if ( view !== null ) {
- "#if MAX_DIR_LIGHTS > 0",
+ var fullWidth = view.fullWidth,
+ fullHeight = view.fullHeight;
- "for( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {",
+ left += view.offsetX * width / fullWidth;
+ top -= view.offsetY * height / fullHeight;
+ width *= view.width / fullWidth;
+ height *= view.height / fullHeight;
- "vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );",
- "vec3 dirVector = normalize( lDirection.xyz );",
+ }
- "float dotProduct = dot( transformedNormal, dirVector );",
- "vec3 directionalLightWeighting = vec3( max( dotProduct, 0.0 ) );",
+ var skew = this.filmOffset;
+ if ( skew !== 0 ) left += near * skew / this.getFilmWidth();
- "#ifdef DOUBLE_SIDED",
+ this.projectionMatrix.makeFrustum(
+ left, left + width, top - height, top, near, this.far );
- "vec3 directionalLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );",
+ },
- "#ifdef WRAP_AROUND",
+ toJSON: function ( meta ) {
- "vec3 directionalLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );",
+ var data = THREE.Object3D.prototype.toJSON.call( this, meta );
- "#endif",
+ data.object.fov = this.fov;
+ data.object.zoom = this.zoom;
- "#endif",
+ data.object.near = this.near;
+ data.object.far = this.far;
+ data.object.focus = this.focus;
- "#ifdef WRAP_AROUND",
+ data.object.aspect = this.aspect;
- "vec3 directionalLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );",
- "directionalLightWeighting = mix( directionalLightWeighting, directionalLightWeightingHalf, wrapRGB );",
+ if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
- "#ifdef DOUBLE_SIDED",
+ data.object.filmGauge = this.filmGauge;
+ data.object.filmOffset = this.filmOffset;
- "directionalLightWeightingBack = mix( directionalLightWeightingBack, directionalLightWeightingHalfBack, wrapRGB );",
+ return data;
- "#endif",
+ }
- "#endif",
+} );
- "vLightFront += directionalLightColor[ i ] * directionalLightWeighting;",
+// File:src/cameras/StereoCamera.js
- "#ifdef DOUBLE_SIDED",
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
- "vLightBack += directionalLightColor[ i ] * directionalLightWeightingBack;",
+THREE.StereoCamera = function () {
- "#endif",
+ this.type = 'StereoCamera';
- "}",
+ this.aspect = 1;
- "#endif",
+ this.cameraL = new THREE.PerspectiveCamera();
+ this.cameraL.layers.enable( 1 );
+ this.cameraL.matrixAutoUpdate = false;
- "#if MAX_POINT_LIGHTS > 0",
+ this.cameraR = new THREE.PerspectiveCamera();
+ this.cameraR.layers.enable( 2 );
+ this.cameraR.matrixAutoUpdate = false;
- "for( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
+};
- "vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
- "vec3 lVector = lPosition.xyz - mvPosition.xyz;",
+Object.assign( THREE.StereoCamera.prototype, {
- "float lDistance = 1.0;",
- "if ( pointLightDistance[ i ] > 0.0 )",
- "lDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );",
+ update: ( function () {
- "lVector = normalize( lVector );",
- "float dotProduct = dot( transformedNormal, lVector );",
+ var focus, fov, aspect, near, far;
- "vec3 pointLightWeighting = vec3( max( dotProduct, 0.0 ) );",
+ var eyeRight = new THREE.Matrix4();
+ var eyeLeft = new THREE.Matrix4();
- "#ifdef DOUBLE_SIDED",
+ return function update( camera ) {
- "vec3 pointLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );",
+ var needsUpdate = focus !== camera.focus || fov !== camera.fov ||
+ aspect !== camera.aspect * this.aspect || near !== camera.near ||
+ far !== camera.far;
- "#ifdef WRAP_AROUND",
+ if ( needsUpdate ) {
- "vec3 pointLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );",
+ focus = camera.focus;
+ fov = camera.fov;
+ aspect = camera.aspect * this.aspect;
+ near = camera.near;
+ far = camera.far;
- "#endif",
+ // Off-axis stereoscopic effect based on
+ // http://paulbourke.net/stereographics/stereorender/
- "#endif",
+ var projectionMatrix = camera.projectionMatrix.clone();
+ var eyeSep = 0.064 / 2;
+ var eyeSepOnProjection = eyeSep * near / focus;
+ var ymax = near * Math.tan( THREE.Math.DEG2RAD * fov * 0.5 );
+ var xmin, xmax;
- "#ifdef WRAP_AROUND",
+ // translate xOffset
- "vec3 pointLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );",
- "pointLightWeighting = mix( pointLightWeighting, pointLightWeightingHalf, wrapRGB );",
+ eyeLeft.elements[ 12 ] = - eyeSep;
+ eyeRight.elements[ 12 ] = eyeSep;
- "#ifdef DOUBLE_SIDED",
+ // for left eye
- "pointLightWeightingBack = mix( pointLightWeightingBack, pointLightWeightingHalfBack, wrapRGB );",
+ xmin = - ymax * aspect + eyeSepOnProjection;
+ xmax = ymax * aspect + eyeSepOnProjection;
- "#endif",
+ projectionMatrix.elements[ 0 ] = 2 * near / ( xmax - xmin );
+ projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
- "#endif",
+ this.cameraL.projectionMatrix.copy( projectionMatrix );
- "vLightFront += pointLightColor[ i ] * pointLightWeighting * lDistance;",
+ // for right eye
- "#ifdef DOUBLE_SIDED",
+ xmin = - ymax * aspect - eyeSepOnProjection;
+ xmax = ymax * aspect - eyeSepOnProjection;
- "vLightBack += pointLightColor[ i ] * pointLightWeightingBack * lDistance;",
+ projectionMatrix.elements[ 0 ] = 2 * near / ( xmax - xmin );
+ projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
- "#endif",
+ this.cameraR.projectionMatrix.copy( projectionMatrix );
- "}",
+ }
- "#endif",
+ this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( eyeLeft );
+ this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( eyeRight );
- "#if MAX_SPOT_LIGHTS > 0",
+ };
- "for( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {",
+ } )()
- "vec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );",
- "vec3 lVector = lPosition.xyz - mvPosition.xyz;",
+} );
- "float spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - worldPosition.xyz ) );",
+// File:src/lights/Light.js
- "if ( spotEffect > spotLightAngleCos[ i ] ) {",
+/**
+ * @author mrdoob / http://mrdoob.com/
+ * @author alteredq / http://alteredqualia.com/
+ */
- "spotEffect = max( pow( spotEffect, spotLightExponent[ i ] ), 0.0 );",
+THREE.Light = function ( color, intensity ) {
- "float lDistance = 1.0;",
- "if ( spotLightDistance[ i ] > 0.0 )",
- "lDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );",
+ THREE.Object3D.call( this );
- "lVector = normalize( lVector );",
+ this.type = 'Light';
- "float dotProduct = dot( transformedNormal, lVector );",
- "vec3 spotLightWeighting = vec3( max( dotProduct, 0.0 ) );",
+ this.color = new THREE.Color( color );
+ this.intensity = intensity !== undefined ? intensity : 1;
- "#ifdef DOUBLE_SIDED",
+ this.receiveShadow = undefined;
- "vec3 spotLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );",
+};
- "#ifdef WRAP_AROUND",
+THREE.Light.prototype = Object.assign( Object.create( THREE.Object3D.prototype ), {
- "vec3 spotLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );",
+ constructor: THREE.Light,
- "#endif",
+ copy: function ( source ) {
- "#endif",
+ THREE.Object3D.prototype.copy.call( this, source );
- "#ifdef WRAP_AROUND",
+ this.color.copy( source.color );
+ this.intensity = source.intensity;
- "vec3 spotLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );",
- "spotLightWeighting = mix( spotLightWeighting, spotLightWeightingHalf, wrapRGB );",
+ return this;
- "#ifdef DOUBLE_SIDED",
+ },
- "spotLightWeightingBack = mix( spotLightWeightingBack, spotLightWeightingHalfBack, wrapRGB );",
+ toJSON: function ( meta ) {
- "#endif",
+ var data = THREE.Object3D.prototype.toJSON.call( this, meta );
- "#endif",
+ data.object.color = this.color.getHex();
+ data.object.intensity = this.intensity;
- "vLightFront += spotLightColor[ i ] * spotLightWeighting * lDistance * spotEffect;",
+ if ( this.groundColor !== undefined ) data.object.groundColor = this.groundColor.getHex();
- "#ifdef DOUBLE_SIDED",
+ if ( this.distance !== undefined ) data.object.distance = this.distance;
+ if ( this.angle !== undefined ) data.object.angle = this.angle;
+ if ( this.decay !== undefined ) data.object.decay = this.decay;
+ if ( this.penumbra !== undefined ) data.object.penumbra = this.penumbra;
- "vLightBack += spotLightColor[ i ] * spotLightWeightingBack * lDistance * spotEffect;",
+ return data;
- "#endif",
+ }
- "}",
+} );
- "}",
+// File:src/lights/LightShadow.js
- "#endif",
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
- "#if MAX_HEMI_LIGHTS > 0",
+THREE.LightShadow = function ( camera ) {
- "for( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {",
+ this.camera = camera;
- "vec4 lDirection = viewMatrix * vec4( hemisphereLightDirection[ i ], 0.0 );",
- "vec3 lVector = normalize( lDirection.xyz );",
+ this.bias = 0;
+ this.radius = 1;
- "float dotProduct = dot( transformedNormal, lVector );",
+ this.mapSize = new THREE.Vector2( 512, 512 );
- "float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;",
- "float hemiDiffuseWeightBack = -0.5 * dotProduct + 0.5;",
+ this.map = null;
+ this.matrix = new THREE.Matrix4();
- "vLightFront += mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );",
+};
- "#ifdef DOUBLE_SIDED",
+Object.assign( THREE.LightShadow.prototype, {
- "vLightBack += mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeightBack );",
+ copy: function ( source ) {
- "#endif",
+ this.camera = source.camera.clone();
- "}",
+ this.bias = source.bias;
+ this.radius = source.radius;
- "#endif",
+ this.mapSize.copy( source.mapSize );
- "vLightFront = vLightFront * diffuse + ambient * ambientLightColor + emissive;",
+ return this;
- "#ifdef DOUBLE_SIDED",
+ },
- "vLightBack = vLightBack * diffuse + ambient * ambientLightColor + emissive;",
+ clone: function () {
- "#endif"
+ return new this.constructor().copy( this );
- ].join("\n"),
+ }
- // LIGHTS PHONG
+} );
- lights_phong_pars_vertex: [
+// File:src/lights/AmbientLight.js
- "#ifndef PHONG_PER_PIXEL",
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
- "#if MAX_POINT_LIGHTS > 0",
+THREE.AmbientLight = function ( color, intensity ) {
- "uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
- "uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
+ THREE.Light.call( this, color, intensity );
- "varying vec4 vPointLight[ MAX_POINT_LIGHTS ];",
+ this.type = 'AmbientLight';
- "#endif",
+ this.castShadow = undefined;
- "#if MAX_SPOT_LIGHTS > 0",
+};
- "uniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];",
- "uniform float spotLightDistance[ MAX_SPOT_LIGHTS ];",
+THREE.AmbientLight.prototype = Object.assign( Object.create( THREE.Light.prototype ), {
- "varying vec4 vSpotLight[ MAX_SPOT_LIGHTS ];",
+ constructor: THREE.AmbientLight
- "#endif",
+} );
- "#endif",
+// File:src/lights/DirectionalLight.js
- "#if MAX_SPOT_LIGHTS > 0 || defined( USE_BUMPMAP )",
+/**
+ * @author mrdoob / http://mrdoob.com/
+ * @author alteredq / http://alteredqualia.com/
+ */
- "varying vec3 vWorldPosition;",
+THREE.DirectionalLight = function ( color, intensity ) {
- "#endif"
+ THREE.Light.call( this, color, intensity );
- ].join("\n"),
+ this.type = 'DirectionalLight';
+ this.position.copy( THREE.Object3D.DefaultUp );
+ this.updateMatrix();
- lights_phong_vertex: [
+ this.target = new THREE.Object3D();
- "#ifndef PHONG_PER_PIXEL",
+ this.shadow = new THREE.DirectionalLightShadow();
- "#if MAX_POINT_LIGHTS > 0",
+};
- "for( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
+THREE.DirectionalLight.prototype = Object.assign( Object.create( THREE.Light.prototype ), {
- "vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
- "vec3 lVector = lPosition.xyz - mvPosition.xyz;",
+ constructor: THREE.DirectionalLight,
- "float lDistance = 1.0;",
- "if ( pointLightDistance[ i ] > 0.0 )",
- "lDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );",
+ copy: function ( source ) {
- "vPointLight[ i ] = vec4( lVector, lDistance );",
+ THREE.Light.prototype.copy.call( this, source );
- "}",
+ this.target = source.target.clone();
- "#endif",
+ this.shadow = source.shadow.clone();
- "#if MAX_SPOT_LIGHTS > 0",
+ return this;
- "for( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {",
+ }
- "vec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );",
- "vec3 lVector = lPosition.xyz - mvPosition.xyz;",
+} );
- "float lDistance = 1.0;",
- "if ( spotLightDistance[ i ] > 0.0 )",
- "lDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );",
+// File:src/lights/DirectionalLightShadow.js
- "vSpotLight[ i ] = vec4( lVector, lDistance );",
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
- "}",
+THREE.DirectionalLightShadow = function ( light ) {
- "#endif",
+ THREE.LightShadow.call( this, new THREE.OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) );
- "#endif",
+};
- "#if MAX_SPOT_LIGHTS > 0 || defined( USE_BUMPMAP )",
+THREE.DirectionalLightShadow.prototype = Object.assign( Object.create( THREE.LightShadow.prototype ), {
- "vWorldPosition = worldPosition.xyz;",
+ constructor: THREE.DirectionalLightShadow
- "#endif"
+} );
- ].join("\n"),
+// File:src/lights/HemisphereLight.js
- lights_phong_pars_fragment: [
+/**
+ * @author alteredq / http://alteredqualia.com/
+ */
- "uniform vec3 ambientLightColor;",
+THREE.HemisphereLight = function ( skyColor, groundColor, intensity ) {
- "#if MAX_DIR_LIGHTS > 0",
+ THREE.Light.call( this, skyColor, intensity );
- "uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];",
- "uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];",
+ this.type = 'HemisphereLight';
- "#endif",
+ this.castShadow = undefined;
- "#if MAX_HEMI_LIGHTS > 0",
+ this.position.copy( THREE.Object3D.DefaultUp );
+ this.updateMatrix();
- "uniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];",
- "uniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];",
- "uniform vec3 hemisphereLightDirection[ MAX_HEMI_LIGHTS ];",
+ this.groundColor = new THREE.Color( groundColor );
- "#endif",
+};
- "#if MAX_POINT_LIGHTS > 0",
+THREE.HemisphereLight.prototype = Object.assign( Object.create( THREE.Light.prototype ), {
- "uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];",
+ constructor: THREE.HemisphereLight,
- "#ifdef PHONG_PER_PIXEL",
+ copy: function ( source ) {
- "uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
- "uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
+ THREE.Light.prototype.copy.call( this, source );
- "#else",
+ this.groundColor.copy( source.groundColor );
- "varying vec4 vPointLight[ MAX_POINT_LIGHTS ];",
+ return this;
- "#endif",
+ }
- "#endif",
+} );
- "#if MAX_SPOT_LIGHTS > 0",
+// File:src/lights/PointLight.js
- "uniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];",
- "uniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];",
- "uniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];",
- "uniform float spotLightAngleCos[ MAX_SPOT_LIGHTS ];",
- "uniform float spotLightExponent[ MAX_SPOT_LIGHTS ];",
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
- "#ifdef PHONG_PER_PIXEL",
- "uniform float spotLightDistance[ MAX_SPOT_LIGHTS ];",
+THREE.PointLight = function ( color, intensity, distance, decay ) {
- "#else",
+ THREE.Light.call( this, color, intensity );
- "varying vec4 vSpotLight[ MAX_SPOT_LIGHTS ];",
+ this.type = 'PointLight';
- "#endif",
+ Object.defineProperty( this, 'power', {
+ get: function () {
+ // intensity = power per solid angle.
+ // ref: equation (15) from http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf
+ return this.intensity * 4 * Math.PI;
- "#endif",
+ },
+ set: function ( power ) {
+ // intensity = power per solid angle.
+ // ref: equation (15) from http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf
+ this.intensity = power / ( 4 * Math.PI );
+ }
+ } );
- "#if MAX_SPOT_LIGHTS > 0 || defined( USE_BUMPMAP )",
+ this.distance = ( distance !== undefined ) ? distance : 0;
+ this.decay = ( decay !== undefined ) ? decay : 1; // for physically correct lights, should be 2.
- "varying vec3 vWorldPosition;",
+ this.shadow = new THREE.LightShadow( new THREE.PerspectiveCamera( 90, 1, 0.5, 500 ) );
- "#endif",
+};
- "#ifdef WRAP_AROUND",
+THREE.PointLight.prototype = Object.assign( Object.create( THREE.Light.prototype ), {
- "uniform vec3 wrapRGB;",
+ constructor: THREE.PointLight,
- "#endif",
+ copy: function ( source ) {
- "varying vec3 vViewPosition;",
- "varying vec3 vNormal;"
+ THREE.Light.prototype.copy.call( this, source );
- ].join("\n"),
+ this.distance = source.distance;
+ this.decay = source.decay;
- lights_phong_fragment: [
+ this.shadow = source.shadow.clone();
- "vec3 normal = normalize( vNormal );",
- "vec3 viewPosition = normalize( vViewPosition );",
+ return this;
- "#ifdef DOUBLE_SIDED",
+ }
- "normal = normal * ( -1.0 + 2.0 * float( gl_FrontFacing ) );",
+} );
- "#endif",
+// File:src/lights/SpotLight.js
- "#ifdef USE_NORMALMAP",
+/**
+ * @author alteredq / http://alteredqualia.com/
+ */
- "normal = perturbNormal2Arb( -vViewPosition, normal );",
+THREE.SpotLight = function ( color, intensity, distance, angle, penumbra, decay ) {
- "#elif defined( USE_BUMPMAP )",
+ THREE.Light.call( this, color, intensity );
- "normal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );",
+ this.type = 'SpotLight';
- "#endif",
+ this.position.copy( THREE.Object3D.DefaultUp );
+ this.updateMatrix();
- "#if MAX_POINT_LIGHTS > 0",
+ this.target = new THREE.Object3D();
- "vec3 pointDiffuse = vec3( 0.0 );",
- "vec3 pointSpecular = vec3( 0.0 );",
+ Object.defineProperty( this, 'power', {
+ get: function () {
+ // intensity = power per solid angle.
+ // ref: equation (17) from http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf
+ return this.intensity * Math.PI;
+ },
+ set: function ( power ) {
+ // intensity = power per solid angle.
+ // ref: equation (17) from http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf
+ this.intensity = power / Math.PI;
+ }
+ } );
- "for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
+ this.distance = ( distance !== undefined ) ? distance : 0;
+ this.angle = ( angle !== undefined ) ? angle : Math.PI / 3;
+ this.penumbra = ( penumbra !== undefined ) ? penumbra : 0;
+ this.decay = ( decay !== undefined ) ? decay : 1; // for physically correct lights, should be 2.
- "#ifdef PHONG_PER_PIXEL",
+ this.shadow = new THREE.SpotLightShadow();
- "vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
- "vec3 lVector = lPosition.xyz + vViewPosition.xyz;",
+};
- "float lDistance = 1.0;",
- "if ( pointLightDistance[ i ] > 0.0 )",
- "lDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );",
+THREE.SpotLight.prototype = Object.assign( Object.create( THREE.Light.prototype ), {
- "lVector = normalize( lVector );",
+ constructor: THREE.SpotLight,
- "#else",
+ copy: function ( source ) {
- "vec3 lVector = normalize( vPointLight[ i ].xyz );",
- "float lDistance = vPointLight[ i ].w;",
+ THREE.Light.prototype.copy.call( this, source );
- "#endif",
+ this.distance = source.distance;
+ this.angle = source.angle;
+ this.penumbra = source.penumbra;
+ this.decay = source.decay;
- // diffuse
+ this.target = source.target.clone();
- "float dotProduct = dot( normal, lVector );",
+ this.shadow = source.shadow.clone();
- "#ifdef WRAP_AROUND",
+ return this;
- "float pointDiffuseWeightFull = max( dotProduct, 0.0 );",
- "float pointDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );",
+ }
- "vec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );",
+} );
- "#else",
+// File:src/lights/SpotLightShadow.js
- "float pointDiffuseWeight = max( dotProduct, 0.0 );",
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
- "#endif",
+THREE.SpotLightShadow = function () {
- "pointDiffuse += diffuse * pointLightColor[ i ] * pointDiffuseWeight * lDistance;",
+ THREE.LightShadow.call( this, new THREE.PerspectiveCamera( 50, 1, 0.5, 500 ) );
- // specular
+};
- "vec3 pointHalfVector = normalize( lVector + viewPosition );",
- "float pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );",
- "float pointSpecularWeight = specularStrength * max( pow( pointDotNormalHalf, shininess ), 0.0 );",
+THREE.SpotLightShadow.prototype = Object.assign( Object.create( THREE.LightShadow.prototype ), {
- "#ifdef PHYSICALLY_BASED_SHADING",
+ constructor: THREE.SpotLightShadow,
- // 2.0 => 2.0001 is hack to work around ANGLE bug
+ update: function ( light ) {
- "float specularNormalization = ( shininess + 2.0001 ) / 8.0;",
+ var fov = THREE.Math.RAD2DEG * 2 * light.angle;
+ var aspect = this.mapSize.width / this.mapSize.height;
+ var far = light.distance || 500;
- "vec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, pointHalfVector ), 5.0 );",
- "pointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance * specularNormalization;",
+ var camera = this.camera;
- "#else",
+ if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) {
- "pointSpecular += specular * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance;",
+ camera.fov = fov;
+ camera.aspect = aspect;
+ camera.far = far;
+ camera.updateProjectionMatrix();
- "#endif",
+ }
- "}",
+ }
- "#endif",
+} );
- "#if MAX_SPOT_LIGHTS > 0",
+// File:src/loaders/AudioLoader.js
- "vec3 spotDiffuse = vec3( 0.0 );",
- "vec3 spotSpecular = vec3( 0.0 );",
+/**
+ * @author Reece Aaron Lecrivain / http://reecenotes.com/
+ */
- "for ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {",
+THREE.AudioLoader = function ( manager ) {
- "#ifdef PHONG_PER_PIXEL",
+ this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
- "vec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );",
- "vec3 lVector = lPosition.xyz + vViewPosition.xyz;",
+};
- "float lDistance = 1.0;",
- "if ( spotLightDistance[ i ] > 0.0 )",
- "lDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );",
+Object.assign( THREE.AudioLoader.prototype, {
- "lVector = normalize( lVector );",
+ load: function ( url, onLoad, onProgress, onError ) {
- "#else",
+ var loader = new THREE.XHRLoader( this.manager );
+ loader.setResponseType( 'arraybuffer' );
+ loader.load( url, function ( buffer ) {
- "vec3 lVector = normalize( vSpotLight[ i ].xyz );",
- "float lDistance = vSpotLight[ i ].w;",
+ var context = THREE.AudioContext;
- "#endif",
+ context.decodeAudioData( buffer, function ( audioBuffer ) {
- "float spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - vWorldPosition ) );",
+ onLoad( audioBuffer );
- "if ( spotEffect > spotLightAngleCos[ i ] ) {",
+ } );
- "spotEffect = max( pow( spotEffect, spotLightExponent[ i ] ), 0.0 );",
+ }, onProgress, onError );
- // diffuse
+ }
- "float dotProduct = dot( normal, lVector );",
+} );
- "#ifdef WRAP_AROUND",
+// File:src/loaders/Cache.js
- "float spotDiffuseWeightFull = max( dotProduct, 0.0 );",
- "float spotDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );",
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
- "vec3 spotDiffuseWeight = mix( vec3 ( spotDiffuseWeightFull ), vec3( spotDiffuseWeightHalf ), wrapRGB );",
+THREE.Cache = {
- "#else",
+ enabled: false,
- "float spotDiffuseWeight = max( dotProduct, 0.0 );",
+ files: {},
- "#endif",
+ add: function ( key, file ) {
- "spotDiffuse += diffuse * spotLightColor[ i ] * spotDiffuseWeight * lDistance * spotEffect;",
+ if ( this.enabled === false ) return;
- // specular
+ // console.log( 'THREE.Cache', 'Adding key:', key );
- "vec3 spotHalfVector = normalize( lVector + viewPosition );",
- "float spotDotNormalHalf = max( dot( normal, spotHalfVector ), 0.0 );",
- "float spotSpecularWeight = specularStrength * max( pow( spotDotNormalHalf, shininess ), 0.0 );",
+ this.files[ key ] = file;
- "#ifdef PHYSICALLY_BASED_SHADING",
+ },
- // 2.0 => 2.0001 is hack to work around ANGLE bug
+ get: function ( key ) {
- "float specularNormalization = ( shininess + 2.0001 ) / 8.0;",
+ if ( this.enabled === false ) return;
- "vec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, spotHalfVector ), 5.0 );",
- "spotSpecular += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * specularNormalization * spotEffect;",
+ // console.log( 'THREE.Cache', 'Checking key:', key );
- "#else",
+ return this.files[ key ];
- "spotSpecular += specular * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * spotEffect;",
+ },
- "#endif",
+ remove: function ( key ) {
- "}",
+ delete this.files[ key ];
- "}",
+ },
- "#endif",
+ clear: function () {
- "#if MAX_DIR_LIGHTS > 0",
+ this.files = {};
- "vec3 dirDiffuse = vec3( 0.0 );",
- "vec3 dirSpecular = vec3( 0.0 );" ,
+ }
- "for( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {",
+};
- "vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );",
- "vec3 dirVector = normalize( lDirection.xyz );",
+// File:src/loaders/Loader.js
- // diffuse
+/**
+ * @author alteredq / http://alteredqualia.com/
+ */
- "float dotProduct = dot( normal, dirVector );",
+THREE.Loader = function () {
- "#ifdef WRAP_AROUND",
+ this.onLoadStart = function () {};
+ this.onLoadProgress = function () {};
+ this.onLoadComplete = function () {};
- "float dirDiffuseWeightFull = max( dotProduct, 0.0 );",
- "float dirDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );",
+};
- "vec3 dirDiffuseWeight = mix( vec3( dirDiffuseWeightFull ), vec3( dirDiffuseWeightHalf ), wrapRGB );",
+THREE.Loader.prototype = {
- "#else",
+ constructor: THREE.Loader,
- "float dirDiffuseWeight = max( dotProduct, 0.0 );",
+ crossOrigin: undefined,
- "#endif",
+ extractUrlBase: function ( url ) {
- "dirDiffuse += diffuse * directionalLightColor[ i ] * dirDiffuseWeight;",
+ var parts = url.split( '/' );
- // specular
+ if ( parts.length === 1 ) return './';
- "vec3 dirHalfVector = normalize( dirVector + viewPosition );",
- "float dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );",
- "float dirSpecularWeight = specularStrength * max( pow( dirDotNormalHalf, shininess ), 0.0 );",
+ parts.pop();
- "#ifdef PHYSICALLY_BASED_SHADING",
+ return parts.join( '/' ) + '/';
- /*
- // fresnel term from skin shader
- "const float F0 = 0.128;",
+ },
- "float base = 1.0 - dot( viewPosition, dirHalfVector );",
- "float exponential = pow( base, 5.0 );",
+ initMaterials: function ( materials, texturePath, crossOrigin ) {
- "float fresnel = exponential + F0 * ( 1.0 - exponential );",
- */
+ var array = [];
- /*
- // fresnel term from fresnel shader
- "const float mFresnelBias = 0.08;",
- "const float mFresnelScale = 0.3;",
- "const float mFresnelPower = 5.0;",
+ for ( var i = 0; i < materials.length; ++ i ) {
- "float fresnel = mFresnelBias + mFresnelScale * pow( 1.0 + dot( normalize( -viewPosition ), normal ), mFresnelPower );",
- */
+ array[ i ] = this.createMaterial( materials[ i ], texturePath, crossOrigin );
- // 2.0 => 2.0001 is hack to work around ANGLE bug
+ }
- "float specularNormalization = ( shininess + 2.0001 ) / 8.0;",
+ return array;
- //"dirSpecular += specular * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization * fresnel;",
+ },
- "vec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( dirVector, dirHalfVector ), 5.0 );",
- "dirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;",
+ createMaterial: ( function () {
- "#else",
+ var color, textureLoader, materialLoader;
- "dirSpecular += specular * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight;",
+ return function createMaterial( m, texturePath, crossOrigin ) {
- "#endif",
+ if ( color === undefined ) color = new THREE.Color();
+ if ( textureLoader === undefined ) textureLoader = new THREE.TextureLoader();
+ if ( materialLoader === undefined ) materialLoader = new THREE.MaterialLoader();
- "}",
+ // convert from old material format
- "#endif",
+ var textures = {};
- "#if MAX_HEMI_LIGHTS > 0",
+ function loadTexture( path, repeat, offset, wrap, anisotropy ) {
- "vec3 hemiDiffuse = vec3( 0.0 );",
- "vec3 hemiSpecular = vec3( 0.0 );" ,
+ var fullPath = texturePath + path;
+ var loader = THREE.Loader.Handlers.get( fullPath );
- "for( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {",
+ var texture;
- "vec4 lDirection = viewMatrix * vec4( hemisphereLightDirection[ i ], 0.0 );",
- "vec3 lVector = normalize( lDirection.xyz );",
+ if ( loader !== null ) {
- // diffuse
+ texture = loader.load( fullPath );
- "float dotProduct = dot( normal, lVector );",
- "float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;",
+ } else {
- "vec3 hemiColor = mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );",
+ textureLoader.setCrossOrigin( crossOrigin );
+ texture = textureLoader.load( fullPath );
- "hemiDiffuse += diffuse * hemiColor;",
+ }
- // specular (sky light)
+ if ( repeat !== undefined ) {
- "vec3 hemiHalfVectorSky = normalize( lVector + viewPosition );",
- "float hemiDotNormalHalfSky = 0.5 * dot( normal, hemiHalfVectorSky ) + 0.5;",
- "float hemiSpecularWeightSky = specularStrength * max( pow( hemiDotNormalHalfSky, shininess ), 0.0 );",
+ texture.repeat.fromArray( repeat );
- // specular (ground light)
+ if ( repeat[ 0 ] !== 1 ) texture.wrapS = THREE.RepeatWrapping;
+ if ( repeat[ 1 ] !== 1 ) texture.wrapT = THREE.RepeatWrapping;
- "vec3 lVectorGround = -lVector;",
+ }
- "vec3 hemiHalfVectorGround = normalize( lVectorGround + viewPosition );",
- "float hemiDotNormalHalfGround = 0.5 * dot( normal, hemiHalfVectorGround ) + 0.5;",
- "float hemiSpecularWeightGround = specularStrength * max( pow( hemiDotNormalHalfGround, shininess ), 0.0 );",
+ if ( offset !== undefined ) {
- "#ifdef PHYSICALLY_BASED_SHADING",
+ texture.offset.fromArray( offset );
- "float dotProductGround = dot( normal, lVectorGround );",
+ }
- // 2.0 => 2.0001 is hack to work around ANGLE bug
+ if ( wrap !== undefined ) {
- "float specularNormalization = ( shininess + 2.0001 ) / 8.0;",
+ if ( wrap[ 0 ] === 'repeat' ) texture.wrapS = THREE.RepeatWrapping;
+ if ( wrap[ 0 ] === 'mirror' ) texture.wrapS = THREE.MirroredRepeatWrapping;
- "vec3 schlickSky = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, hemiHalfVectorSky ), 5.0 );",
- "vec3 schlickGround = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVectorGround, hemiHalfVectorGround ), 5.0 );",
- "hemiSpecular += hemiColor * specularNormalization * ( schlickSky * hemiSpecularWeightSky * max( dotProduct, 0.0 ) + schlickGround * hemiSpecularWeightGround * max( dotProductGround, 0.0 ) );",
+ if ( wrap[ 1 ] === 'repeat' ) texture.wrapT = THREE.RepeatWrapping;
+ if ( wrap[ 1 ] === 'mirror' ) texture.wrapT = THREE.MirroredRepeatWrapping;
- "#else",
+ }
- "hemiSpecular += specular * hemiColor * ( hemiSpecularWeightSky + hemiSpecularWeightGround ) * hemiDiffuseWeight;",
+ if ( anisotropy !== undefined ) {
- "#endif",
+ texture.anisotropy = anisotropy;
- "}",
+ }
- "#endif",
+ var uuid = THREE.Math.generateUUID();
- "vec3 totalDiffuse = vec3( 0.0 );",
- "vec3 totalSpecular = vec3( 0.0 );",
+ textures[ uuid ] = texture;
- "#if MAX_DIR_LIGHTS > 0",
+ return uuid;
- "totalDiffuse += dirDiffuse;",
- "totalSpecular += dirSpecular;",
+ }
- "#endif",
+ //
- "#if MAX_HEMI_LIGHTS > 0",
+ var json = {
+ uuid: THREE.Math.generateUUID(),
+ type: 'MeshLambertMaterial'
+ };
- "totalDiffuse += hemiDiffuse;",
- "totalSpecular += hemiSpecular;",
+ for ( var name in m ) {
- "#endif",
+ var value = m[ name ];
- "#if MAX_POINT_LIGHTS > 0",
+ switch ( name ) {
+ case 'DbgColor':
+ case 'DbgIndex':
+ case 'opticalDensity':
+ case 'illumination':
+ break;
+ case 'DbgName':
+ json.name = value;
+ break;
+ case 'blending':
+ json.blending = THREE[ value ];
+ break;
+ case 'colorAmbient':
+ case 'mapAmbient':
+ console.warn( 'THREE.Loader.createMaterial:', name, 'is no longer supported.' );
+ break;
+ case 'colorDiffuse':
+ json.color = color.fromArray( value ).getHex();
+ break;
+ case 'colorSpecular':
+ json.specular = color.fromArray( value ).getHex();
+ break;
+ case 'colorEmissive':
+ json.emissive = color.fromArray( value ).getHex();
+ break;
+ case 'specularCoef':
+ json.shininess = value;
+ break;
+ case 'shading':
+ if ( value.toLowerCase() === 'basic' ) json.type = 'MeshBasicMaterial';
+ if ( value.toLowerCase() === 'phong' ) json.type = 'MeshPhongMaterial';
+ if ( value.toLowerCase() === 'standard' ) json.type = 'MeshStandardMaterial';
+ break;
+ case 'mapDiffuse':
+ json.map = loadTexture( value, m.mapDiffuseRepeat, m.mapDiffuseOffset, m.mapDiffuseWrap, m.mapDiffuseAnisotropy );
+ break;
+ case 'mapDiffuseRepeat':
+ case 'mapDiffuseOffset':
+ case 'mapDiffuseWrap':
+ case 'mapDiffuseAnisotropy':
+ break;
+ case 'mapEmissive':
+ json.emissiveMap = loadTexture( value, m.mapEmissiveRepeat, m.mapEmissiveOffset, m.mapEmissiveWrap, m.mapEmissiveAnisotropy );
+ break;
+ case 'mapEmissiveRepeat':
+ case 'mapEmissiveOffset':
+ case 'mapEmissiveWrap':
+ case 'mapEmissiveAnisotropy':
+ break;
+ case 'mapLight':
+ json.lightMap = loadTexture( value, m.mapLightRepeat, m.mapLightOffset, m.mapLightWrap, m.mapLightAnisotropy );
+ break;
+ case 'mapLightRepeat':
+ case 'mapLightOffset':
+ case 'mapLightWrap':
+ case 'mapLightAnisotropy':
+ break;
+ case 'mapAO':
+ json.aoMap = loadTexture( value, m.mapAORepeat, m.mapAOOffset, m.mapAOWrap, m.mapAOAnisotropy );
+ break;
+ case 'mapAORepeat':
+ case 'mapAOOffset':
+ case 'mapAOWrap':
+ case 'mapAOAnisotropy':
+ break;
+ case 'mapBump':
+ json.bumpMap = loadTexture( value, m.mapBumpRepeat, m.mapBumpOffset, m.mapBumpWrap, m.mapBumpAnisotropy );
+ break;
+ case 'mapBumpScale':
+ json.bumpScale = value;
+ break;
+ case 'mapBumpRepeat':
+ case 'mapBumpOffset':
+ case 'mapBumpWrap':
+ case 'mapBumpAnisotropy':
+ break;
+ case 'mapNormal':
+ json.normalMap = loadTexture( value, m.mapNormalRepeat, m.mapNormalOffset, m.mapNormalWrap, m.mapNormalAnisotropy );
+ break;
+ case 'mapNormalFactor':
+ json.normalScale = [ value, value ];
+ break;
+ case 'mapNormalRepeat':
+ case 'mapNormalOffset':
+ case 'mapNormalWrap':
+ case 'mapNormalAnisotropy':
+ break;
+ case 'mapSpecular':
+ json.specularMap = loadTexture( value, m.mapSpecularRepeat, m.mapSpecularOffset, m.mapSpecularWrap, m.mapSpecularAnisotropy );
+ break;
+ case 'mapSpecularRepeat':
+ case 'mapSpecularOffset':
+ case 'mapSpecularWrap':
+ case 'mapSpecularAnisotropy':
+ break;
+ case 'mapMetalness':
+ json.metalnessMap = loadTexture( value, m.mapMetalnessRepeat, m.mapMetalnessOffset, m.mapMetalnessWrap, m.mapMetalnessAnisotropy );
+ break;
+ case 'mapMetalnessRepeat':
+ case 'mapMetalnessOffset':
+ case 'mapMetalnessWrap':
+ case 'mapMetalnessAnisotropy':
+ break;
+ case 'mapRoughness':
+ json.roughnessMap = loadTexture( value, m.mapRoughnessRepeat, m.mapRoughnessOffset, m.mapRoughnessWrap, m.mapRoughnessAnisotropy );
+ break;
+ case 'mapRoughnessRepeat':
+ case 'mapRoughnessOffset':
+ case 'mapRoughnessWrap':
+ case 'mapRoughnessAnisotropy':
+ break;
+ case 'mapAlpha':
+ json.alphaMap = loadTexture( value, m.mapAlphaRepeat, m.mapAlphaOffset, m.mapAlphaWrap, m.mapAlphaAnisotropy );
+ break;
+ case 'mapAlphaRepeat':
+ case 'mapAlphaOffset':
+ case 'mapAlphaWrap':
+ case 'mapAlphaAnisotropy':
+ break;
+ case 'flipSided':
+ json.side = THREE.BackSide;
+ break;
+ case 'doubleSided':
+ json.side = THREE.DoubleSide;
+ break;
+ case 'transparency':
+ console.warn( 'THREE.Loader.createMaterial: transparency has been renamed to opacity' );
+ json.opacity = value;
+ break;
+ case 'depthTest':
+ case 'depthWrite':
+ case 'colorWrite':
+ case 'opacity':
+ case 'reflectivity':
+ case 'transparent':
+ case 'visible':
+ case 'wireframe':
+ json[ name ] = value;
+ break;
+ case 'vertexColors':
+ if ( value === true ) json.vertexColors = THREE.VertexColors;
+ if ( value === 'face' ) json.vertexColors = THREE.FaceColors;
+ break;
+ default:
+ console.error( 'THREE.Loader.createMaterial: Unsupported', name, value );
+ break;
+ }
- "totalDiffuse += pointDiffuse;",
- "totalSpecular += pointSpecular;",
+ }
- "#endif",
+ if ( json.type === 'MeshBasicMaterial' ) delete json.emissive;
+ if ( json.type !== 'MeshPhongMaterial' ) delete json.specular;
- "#if MAX_SPOT_LIGHTS > 0",
+ if ( json.opacity < 1 ) json.transparent = true;
- "totalDiffuse += spotDiffuse;",
- "totalSpecular += spotSpecular;",
+ materialLoader.setTextures( textures );
- "#endif",
+ return materialLoader.parse( json );
- "#ifdef METAL",
+ };
- "gl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient + totalSpecular );",
+ } )()
- "#else",
+};
- "gl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient ) + totalSpecular;",
+THREE.Loader.Handlers = {
- "#endif"
+ handlers: [],
- ].join("\n"),
+ add: function ( regex, loader ) {
- // VERTEX COLORS
+ this.handlers.push( regex, loader );
- color_pars_fragment: [
+ },
- "#ifdef USE_COLOR",
+ get: function ( file ) {
- "varying vec3 vColor;",
+ var handlers = this.handlers;
- "#endif"
+ for ( var i = 0, l = handlers.length; i < l; i += 2 ) {
- ].join("\n"),
+ var regex = handlers[ i ];
+ var loader = handlers[ i + 1 ];
+ if ( regex.test( file ) ) {
- color_fragment: [
+ return loader;
- "#ifdef USE_COLOR",
+ }
- "gl_FragColor = gl_FragColor * vec4( vColor, opacity );",
+ }
- "#endif"
+ return null;
- ].join("\n"),
+ }
- color_pars_vertex: [
+};
- "#ifdef USE_COLOR",
+// File:src/loaders/XHRLoader.js
- "varying vec3 vColor;",
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
- "#endif"
+THREE.XHRLoader = function ( manager ) {
- ].join("\n"),
+ this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
+};
- color_vertex: [
+Object.assign( THREE.XHRLoader.prototype, {
- "#ifdef USE_COLOR",
+ load: function ( url, onLoad, onProgress, onError ) {
- "#ifdef GAMMA_INPUT",
+ if ( this.path !== undefined ) url = this.path + url;
- "vColor = color * color;",
+ var scope = this;
- "#else",
+ var cached = THREE.Cache.get( url );
- "vColor = color;",
+ if ( cached !== undefined ) {
- "#endif",
+ scope.manager.itemStart( url );
- "#endif"
+ setTimeout( function () {
- ].join("\n"),
+ if ( onLoad ) onLoad( cached );
- // SKINNING
+ scope.manager.itemEnd( url );
- skinning_pars_vertex: [
+ }, 0 );
- "#ifdef USE_SKINNING",
+ return cached;
- "#ifdef BONE_TEXTURE",
+ }
- "uniform sampler2D boneTexture;",
+ var request = new XMLHttpRequest();
+ request.overrideMimeType( 'text/plain' );
+ request.open( 'GET', url, true );
- "mat4 getBoneMatrix( const in float i ) {",
+ request.addEventListener( 'load', function ( event ) {
- "float j = i * 4.0;",
- "float x = mod( j, N_BONE_PIXEL_X );",
- "float y = floor( j / N_BONE_PIXEL_X );",
+ var response = event.target.response;
- "const float dx = 1.0 / N_BONE_PIXEL_X;",
- "const float dy = 1.0 / N_BONE_PIXEL_Y;",
+ THREE.Cache.add( url, response );
- "y = dy * ( y + 0.5 );",
+ if ( this.status === 200 ) {
- "vec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );",
- "vec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );",
- "vec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );",
- "vec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );",
+ if ( onLoad ) onLoad( response );
- "mat4 bone = mat4( v1, v2, v3, v4 );",
+ scope.manager.itemEnd( url );
- "return bone;",
+ } else if ( this.status === 0 ) {
- "}",
+ // Some browsers return HTTP Status 0 when using non-http protocol
+ // e.g. 'file://' or 'data://'. Handle as success.
- "#else",
+ console.warn( 'THREE.XHRLoader: HTTP Status 0 received.' );
- "uniform mat4 boneGlobalMatrices[ MAX_BONES ];",
+ if ( onLoad ) onLoad( response );
- "mat4 getBoneMatrix( const in float i ) {",
+ scope.manager.itemEnd( url );
- "mat4 bone = boneGlobalMatrices[ int(i) ];",
- "return bone;",
+ } else {
- "}",
+ if ( onError ) onError( event );
- "#endif",
+ scope.manager.itemError( url );
- "#endif"
+ }
- ].join("\n"),
+ }, false );
- skinbase_vertex: [
+ if ( onProgress !== undefined ) {
- "#ifdef USE_SKINNING",
+ request.addEventListener( 'progress', function ( event ) {
- "mat4 boneMatX = getBoneMatrix( skinIndex.x );",
- "mat4 boneMatY = getBoneMatrix( skinIndex.y );",
+ onProgress( event );
- "#endif"
+ }, false );
- ].join("\n"),
+ }
- skinning_vertex: [
+ request.addEventListener( 'error', function ( event ) {
- "#ifdef USE_SKINNING",
+ if ( onError ) onError( event );
- "#ifdef USE_MORPHTARGETS",
+ scope.manager.itemError( url );
- "vec4 skinVertex = vec4( morphed, 1.0 );",
+ }, false );
- "#else",
+ if ( this.responseType !== undefined ) request.responseType = this.responseType;
+ if ( this.withCredentials !== undefined ) request.withCredentials = this.withCredentials;
- "vec4 skinVertex = vec4( position, 1.0 );",
+ request.send( null );
- "#endif",
+ scope.manager.itemStart( url );
- "vec4 skinned = boneMatX * skinVertex * skinWeight.x;",
- "skinned += boneMatY * skinVertex * skinWeight.y;",
+ return request;
- "#endif"
+ },
- ].join("\n"),
+ setPath: function ( value ) {
- // MORPHING
+ this.path = value;
+ return this;
- morphtarget_pars_vertex: [
+ },
- "#ifdef USE_MORPHTARGETS",
+ setResponseType: function ( value ) {
- "#ifndef USE_MORPHNORMALS",
+ this.responseType = value;
+ return this;
- "uniform float morphTargetInfluences[ 8 ];",
+ },
- "#else",
+ setWithCredentials: function ( value ) {
- "uniform float morphTargetInfluences[ 4 ];",
+ this.withCredentials = value;
+ return this;
- "#endif",
+ }
- "#endif"
+} );
- ].join("\n"),
+// File:src/loaders/FontLoader.js
- morphtarget_vertex: [
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
- "#ifdef USE_MORPHTARGETS",
+THREE.FontLoader = function ( manager ) {
- "vec3 morphed = vec3( 0.0 );",
- "morphed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];",
- "morphed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];",
- "morphed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];",
- "morphed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];",
+ this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
- "#ifndef USE_MORPHNORMALS",
+};
- "morphed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];",
- "morphed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];",
- "morphed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];",
- "morphed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];",
+Object.assign( THREE.FontLoader.prototype, {
- "#endif",
+ load: function ( url, onLoad, onProgress, onError ) {
- "morphed += position;",
+ var scope = this;
- "#endif"
+ var loader = new THREE.XHRLoader( this.manager );
+ loader.load( url, function ( text ) {
- ].join("\n"),
+ var json;
- default_vertex : [
+ try {
- "vec4 mvPosition;",
+ json = JSON.parse( text );
- "#ifdef USE_SKINNING",
+ } catch ( e ) {
- "mvPosition = modelViewMatrix * skinned;",
+ console.warn( 'THREE.FontLoader: typeface.js support is being deprecated. Use typeface.json instead.' );
+ json = JSON.parse( text.substring( 65, text.length - 2 ) );
- "#endif",
+ }
- "#if !defined( USE_SKINNING ) && defined( USE_MORPHTARGETS )",
+ var font = scope.parse( json );
- "mvPosition = modelViewMatrix * vec4( morphed, 1.0 );",
+ if ( onLoad ) onLoad( font );
- "#endif",
+ }, onProgress, onError );
- "#if !defined( USE_SKINNING ) && ! defined( USE_MORPHTARGETS )",
+ },
- "mvPosition = modelViewMatrix * vec4( position, 1.0 );",
+ parse: function ( json ) {
- "#endif",
+ return new THREE.Font( json );
- "gl_Position = projectionMatrix * mvPosition;"
+ }
- ].join("\n"),
+} );
- morphnormal_vertex: [
+// File:src/loaders/ImageLoader.js
- "#ifdef USE_MORPHNORMALS",
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
- "vec3 morphedNormal = vec3( 0.0 );",
+THREE.ImageLoader = function ( manager ) {
- "morphedNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];",
- "morphedNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];",
- "morphedNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];",
- "morphedNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];",
+ this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
- "morphedNormal += normal;",
+};
- "#endif"
+Object.assign( THREE.ImageLoader.prototype, {
- ].join("\n"),
+ load: function ( url, onLoad, onProgress, onError ) {
- skinnormal_vertex: [
+ var scope = this;
- "#ifdef USE_SKINNING",
+ var image = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'img' );
+ image.onload = function () {
- "mat4 skinMatrix = skinWeight.x * boneMatX;",
- "skinMatrix += skinWeight.y * boneMatY;",
+ URL.revokeObjectURL( image.src );
- "#ifdef USE_MORPHNORMALS",
+ if ( onLoad ) onLoad( image );
- "vec4 skinnedNormal = skinMatrix * vec4( morphedNormal, 0.0 );",
+ scope.manager.itemEnd( url );
- "#else",
+ };
- "vec4 skinnedNormal = skinMatrix * vec4( normal, 0.0 );",
+ if ( url.indexOf( 'data:' ) === 0 ) {
- "#endif",
+ image.src = url;
- "#endif"
+ } else {
- ].join("\n"),
+ var loader = new THREE.XHRLoader();
+ loader.setPath( this.path );
+ loader.setResponseType( 'blob' );
+ loader.load( url, function ( blob ) {
- defaultnormal_vertex: [
+ image.src = URL.createObjectURL( blob );
- "vec3 objectNormal;",
+ }, onProgress, onError );
- "#ifdef USE_SKINNING",
+ }
- "objectNormal = skinnedNormal.xyz;",
+ scope.manager.itemStart( url );
- "#endif",
+ return image;
- "#if !defined( USE_SKINNING ) && defined( USE_MORPHNORMALS )",
+ },
- "objectNormal = morphedNormal;",
+ setCrossOrigin: function ( value ) {
- "#endif",
+ this.crossOrigin = value;
+ return this;
- "#if !defined( USE_SKINNING ) && ! defined( USE_MORPHNORMALS )",
+ },
- "objectNormal = normal;",
+ setPath: function ( value ) {
- "#endif",
+ this.path = value;
+ return this;
- "#ifdef FLIP_SIDED",
+ }
- "objectNormal = -objectNormal;",
+} );
- "#endif",
+// File:src/loaders/JSONLoader.js
- "vec3 transformedNormal = normalMatrix * objectNormal;"
+/**
+ * @author mrdoob / http://mrdoob.com/
+ * @author alteredq / http://alteredqualia.com/
+ */
- ].join("\n"),
+THREE.JSONLoader = function ( manager ) {
- // SHADOW MAP
+ if ( typeof manager === 'boolean' ) {
- // based on SpiderGL shadow map and Fabien Sanglard's GLSL shadow mapping examples
- // http://spidergl.org/example.php?id=6
- // http://fabiensanglard.net/shadowmapping
+ console.warn( 'THREE.JSONLoader: showStatus parameter has been removed from constructor.' );
+ manager = undefined;
- shadowmap_pars_fragment: [
+ }
- "#ifdef USE_SHADOWMAP",
+ this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
- "uniform sampler2D shadowMap[ MAX_SHADOWS ];",
- "uniform vec2 shadowMapSize[ MAX_SHADOWS ];",
+ this.withCredentials = false;
- "uniform float shadowDarkness[ MAX_SHADOWS ];",
- "uniform float shadowBias[ MAX_SHADOWS ];",
+};
- "varying vec4 vShadowCoord[ MAX_SHADOWS ];",
+Object.assign( THREE.JSONLoader.prototype, {
- "float unpackDepth( const in vec4 rgba_depth ) {",
+ load: function( url, onLoad, onProgress, onError ) {
- "const vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );",
- "float depth = dot( rgba_depth, bit_shift );",
- "return depth;",
+ var scope = this;
- "}",
+ var texturePath = this.texturePath && ( typeof this.texturePath === "string" ) ? this.texturePath : THREE.Loader.prototype.extractUrlBase( url );
- "#endif"
+ var loader = new THREE.XHRLoader( this.manager );
+ loader.setWithCredentials( this.withCredentials );
+ loader.load( url, function ( text ) {
- ].join("\n"),
+ var json = JSON.parse( text );
+ var metadata = json.metadata;
- shadowmap_fragment: [
+ if ( metadata !== undefined ) {
- "#ifdef USE_SHADOWMAP",
+ var type = metadata.type;
- "#ifdef SHADOWMAP_DEBUG",
+ if ( type !== undefined ) {
- "vec3 frustumColors[3];",
- "frustumColors[0] = vec3( 1.0, 0.5, 0.0 );",
- "frustumColors[1] = vec3( 0.0, 1.0, 0.8 );",
- "frustumColors[2] = vec3( 0.0, 0.5, 1.0 );",
+ if ( type.toLowerCase() === 'object' ) {
- "#endif",
+ console.error( 'THREE.JSONLoader: ' + url + ' should be loaded with THREE.ObjectLoader instead.' );
+ return;
- "#ifdef SHADOWMAP_CASCADE",
+ }
- "int inFrustumCount = 0;",
+ if ( type.toLowerCase() === 'scene' ) {
- "#endif",
+ console.error( 'THREE.JSONLoader: ' + url + ' should be loaded with THREE.SceneLoader instead.' );
+ return;
- "float fDepth;",
- "vec3 shadowColor = vec3( 1.0 );",
+ }
- "for( int i = 0; i < MAX_SHADOWS; i ++ ) {",
+ }
- "vec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;",
+ }
- // "if ( something && something )" breaks ATI OpenGL shader compiler
- // "if ( all( something, something ) )" using this instead
+ var object = scope.parse( json, texturePath );
+ onLoad( object.geometry, object.materials );
- "bvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );",
- "bool inFrustum = all( inFrustumVec );",
+ }, onProgress, onError );
- // don't shadow pixels outside of light frustum
- // use just first frustum (for cascades)
- // don't shadow pixels behind far plane of light frustum
+ },
- "#ifdef SHADOWMAP_CASCADE",
+ setTexturePath: function ( value ) {
- "inFrustumCount += int( inFrustum );",
- "bvec3 frustumTestVec = bvec3( inFrustum, inFrustumCount == 1, shadowCoord.z <= 1.0 );",
+ this.texturePath = value;
- "#else",
+ },
- "bvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );",
+ parse: function ( json, texturePath ) {
- "#endif",
+ var geometry = new THREE.Geometry(),
+ scale = ( json.scale !== undefined ) ? 1.0 / json.scale : 1.0;
- "bool frustumTest = all( frustumTestVec );",
+ parseModel( scale );
- "if ( frustumTest ) {",
+ parseSkin();
+ parseMorphing( scale );
+ parseAnimations();
- "shadowCoord.z += shadowBias[ i ];",
+ geometry.computeFaceNormals();
+ geometry.computeBoundingSphere();
- "#if defined( SHADOWMAP_TYPE_PCF )",
+ function parseModel( scale ) {
- // Percentage-close filtering
- // (9 pixel kernel)
- // http://fabiensanglard.net/shadowmappingPCF/
+ function isBitSet( value, position ) {
- "float shadow = 0.0;",
+ return value & ( 1 << position );
- /*
- // nested loops breaks shader compiler / validator on some ATI cards when using OpenGL
- // must enroll loop manually
+ }
- "for ( float y = -1.25; y <= 1.25; y += 1.25 )",
- "for ( float x = -1.25; x <= 1.25; x += 1.25 ) {",
+ var i, j, fi,
- "vec4 rgbaDepth = texture2D( shadowMap[ i ], vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy );",
+ offset, zLength,
- // doesn't seem to produce any noticeable visual difference compared to simple "texture2D" lookup
- //"vec4 rgbaDepth = texture2DProj( shadowMap[ i ], vec4( vShadowCoord[ i ].w * ( vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy ), 0.05, vShadowCoord[ i ].w ) );",
+ colorIndex, normalIndex, uvIndex, materialIndex,
- "float fDepth = unpackDepth( rgbaDepth );",
+ type,
+ isQuad,
+ hasMaterial,
+ hasFaceVertexUv,
+ hasFaceNormal, hasFaceVertexNormal,
+ hasFaceColor, hasFaceVertexColor,
- "if ( fDepth < shadowCoord.z )",
- "shadow += 1.0;",
+ vertex, face, faceA, faceB, hex, normal,
- "}",
+ uvLayer, uv, u, v,
- "shadow /= 9.0;",
+ faces = json.faces,
+ vertices = json.vertices,
+ normals = json.normals,
+ colors = json.colors,
- */
+ nUvLayers = 0;
- "const float shadowDelta = 1.0 / 9.0;",
+ if ( json.uvs !== undefined ) {
- "float xPixelOffset = 1.0 / shadowMapSize[ i ].x;",
- "float yPixelOffset = 1.0 / shadowMapSize[ i ].y;",
+ // disregard empty arrays
- "float dx0 = -1.25 * xPixelOffset;",
- "float dy0 = -1.25 * yPixelOffset;",
- "float dx1 = 1.25 * xPixelOffset;",
- "float dy1 = 1.25 * yPixelOffset;",
+ for ( i = 0; i < json.uvs.length; i ++ ) {
- "fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );",
- "if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
+ if ( json.uvs[ i ].length ) nUvLayers ++;
- "fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );",
- "if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
+ }
- "fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );",
- "if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
+ for ( i = 0; i < nUvLayers; i ++ ) {
- "fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );",
- "if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
+ geometry.faceVertexUvs[ i ] = [];
- "fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );",
- "if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
+ }
- "fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );",
- "if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
+ }
- "fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );",
- "if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
+ offset = 0;
+ zLength = vertices.length;
- "fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );",
- "if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
+ while ( offset < zLength ) {
- "fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );",
- "if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
+ vertex = new THREE.Vector3();
- "shadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );",
+ vertex.x = vertices[ offset ++ ] * scale;
+ vertex.y = vertices[ offset ++ ] * scale;
+ vertex.z = vertices[ offset ++ ] * scale;
- "#elif defined( SHADOWMAP_TYPE_PCF_SOFT )",
+ geometry.vertices.push( vertex );
- // Percentage-close filtering
- // (9 pixel kernel)
- // http://fabiensanglard.net/shadowmappingPCF/
+ }
- "float shadow = 0.0;",
+ offset = 0;
+ zLength = faces.length;
- "float xPixelOffset = 1.0 / shadowMapSize[ i ].x;",
- "float yPixelOffset = 1.0 / shadowMapSize[ i ].y;",
+ while ( offset < zLength ) {
- "float dx0 = -1.0 * xPixelOffset;",
- "float dy0 = -1.0 * yPixelOffset;",
- "float dx1 = 1.0 * xPixelOffset;",
- "float dy1 = 1.0 * yPixelOffset;",
+ type = faces[ offset ++ ];
- "mat3 shadowKernel;",
- "mat3 depthKernel;",
- "depthKernel[0][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );",
- "depthKernel[0][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );",
- "depthKernel[0][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );",
- "depthKernel[1][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );",
- "depthKernel[1][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );",
- "depthKernel[1][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );",
- "depthKernel[2][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );",
- "depthKernel[2][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );",
- "depthKernel[2][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );",
+ isQuad = isBitSet( type, 0 );
+ hasMaterial = isBitSet( type, 1 );
+ hasFaceVertexUv = isBitSet( type, 3 );
+ hasFaceNormal = isBitSet( type, 4 );
+ hasFaceVertexNormal = isBitSet( type, 5 );
+ hasFaceColor = isBitSet( type, 6 );
+ hasFaceVertexColor = isBitSet( type, 7 );
- "vec3 shadowZ = vec3( shadowCoord.z );",
- "shadowKernel[0] = vec3(lessThan(depthKernel[0], shadowZ ));",
- "shadowKernel[0] *= vec3(0.25);",
-
- "shadowKernel[1] = vec3(lessThan(depthKernel[1], shadowZ ));",
- "shadowKernel[1] *= vec3(0.25);",
+ // console.log("type", type, "bits", isQuad, hasMaterial, hasFaceVertexUv, hasFaceNormal, hasFaceVertexNormal, hasFaceColor, hasFaceVertexColor);
- "shadowKernel[2] = vec3(lessThan(depthKernel[2], shadowZ ));",
- "shadowKernel[2] *= vec3(0.25);",
+ if ( isQuad ) {
- "vec2 fractionalCoord = 1.0 - fract( shadowCoord.xy * shadowMapSize[i].xy );",
+ faceA = new THREE.Face3();
+ faceA.a = faces[ offset ];
+ faceA.b = faces[ offset + 1 ];
+ faceA.c = faces[ offset + 3 ];
- "shadowKernel[0] = mix( shadowKernel[1], shadowKernel[0], fractionalCoord.x );",
- "shadowKernel[1] = mix( shadowKernel[2], shadowKernel[1], fractionalCoord.x );",
+ faceB = new THREE.Face3();
+ faceB.a = faces[ offset + 1 ];
+ faceB.b = faces[ offset + 2 ];
+ faceB.c = faces[ offset + 3 ];
- "vec4 shadowValues;",
- "shadowValues.x = mix( shadowKernel[0][1], shadowKernel[0][0], fractionalCoord.y );",
- "shadowValues.y = mix( shadowKernel[0][2], shadowKernel[0][1], fractionalCoord.y );",
- "shadowValues.z = mix( shadowKernel[1][1], shadowKernel[1][0], fractionalCoord.y );",
- "shadowValues.w = mix( shadowKernel[1][2], shadowKernel[1][1], fractionalCoord.y );",
+ offset += 4;
- "shadow = dot( shadowValues, vec4( 1.0 ) );",
+ if ( hasMaterial ) {
- "shadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );",
+ materialIndex = faces[ offset ++ ];
+ faceA.materialIndex = materialIndex;
+ faceB.materialIndex = materialIndex;
- "#else",
+ }
- "vec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );",
- "float fDepth = unpackDepth( rgbaDepth );",
+ // to get face <=> uv index correspondence
- "if ( fDepth < shadowCoord.z )",
+ fi = geometry.faces.length;
- // spot with multiple shadows is darker
+ if ( hasFaceVertexUv ) {
- "shadowColor = shadowColor * vec3( 1.0 - shadowDarkness[ i ] );",
+ for ( i = 0; i < nUvLayers; i ++ ) {
- // spot with multiple shadows has the same color as single shadow spot
+ uvLayer = json.uvs[ i ];
- //"shadowColor = min( shadowColor, vec3( shadowDarkness[ i ] ) );",
+ geometry.faceVertexUvs[ i ][ fi ] = [];
+ geometry.faceVertexUvs[ i ][ fi + 1 ] = [];
- "#endif",
+ for ( j = 0; j < 4; j ++ ) {
- "}",
+ uvIndex = faces[ offset ++ ];
+ u = uvLayer[ uvIndex * 2 ];
+ v = uvLayer[ uvIndex * 2 + 1 ];
- "#ifdef SHADOWMAP_DEBUG",
+ uv = new THREE.Vector2( u, v );
- "#ifdef SHADOWMAP_CASCADE",
+ if ( j !== 2 ) geometry.faceVertexUvs[ i ][ fi ].push( uv );
+ if ( j !== 0 ) geometry.faceVertexUvs[ i ][ fi + 1 ].push( uv );
- "if ( inFrustum && inFrustumCount == 1 ) gl_FragColor.xyz *= frustumColors[ i ];",
+ }
- "#else",
+ }
- "if ( inFrustum ) gl_FragColor.xyz *= frustumColors[ i ];",
+ }
- "#endif",
+ if ( hasFaceNormal ) {
- "#endif",
+ normalIndex = faces[ offset ++ ] * 3;
- "}",
+ faceA.normal.set(
+ normals[ normalIndex ++ ],
+ normals[ normalIndex ++ ],
+ normals[ normalIndex ]
+ );
- "#ifdef GAMMA_OUTPUT",
+ faceB.normal.copy( faceA.normal );
- "shadowColor *= shadowColor;",
+ }
- "#endif",
+ if ( hasFaceVertexNormal ) {
- "gl_FragColor.xyz = gl_FragColor.xyz * shadowColor;",
+ for ( i = 0; i < 4; i ++ ) {
- "#endif"
+ normalIndex = faces[ offset ++ ] * 3;
- ].join("\n"),
+ normal = new THREE.Vector3(
+ normals[ normalIndex ++ ],
+ normals[ normalIndex ++ ],
+ normals[ normalIndex ]
+ );
- shadowmap_pars_vertex: [
- "#ifdef USE_SHADOWMAP",
+ if ( i !== 2 ) faceA.vertexNormals.push( normal );
+ if ( i !== 0 ) faceB.vertexNormals.push( normal );
- "varying vec4 vShadowCoord[ MAX_SHADOWS ];",
- "uniform mat4 shadowMatrix[ MAX_SHADOWS ];",
+ }
- "#endif"
+ }
- ].join("\n"),
- shadowmap_vertex: [
+ if ( hasFaceColor ) {
- "#ifdef USE_SHADOWMAP",
+ colorIndex = faces[ offset ++ ];
+ hex = colors[ colorIndex ];
- "for( int i = 0; i < MAX_SHADOWS; i ++ ) {",
+ faceA.color.setHex( hex );
+ faceB.color.setHex( hex );
- "vShadowCoord[ i ] = shadowMatrix[ i ] * worldPosition;",
+ }
- "}",
- "#endif"
+ if ( hasFaceVertexColor ) {
- ].join("\n"),
+ for ( i = 0; i < 4; i ++ ) {
- // ALPHATEST
+ colorIndex = faces[ offset ++ ];
+ hex = colors[ colorIndex ];
- alphatest_fragment: [
+ if ( i !== 2 ) faceA.vertexColors.push( new THREE.Color( hex ) );
+ if ( i !== 0 ) faceB.vertexColors.push( new THREE.Color( hex ) );
- "#ifdef ALPHATEST",
+ }
- "if ( gl_FragColor.a < ALPHATEST ) discard;",
+ }
- "#endif"
+ geometry.faces.push( faceA );
+ geometry.faces.push( faceB );
- ].join("\n"),
+ } else {
- // LINEAR SPACE
+ face = new THREE.Face3();
+ face.a = faces[ offset ++ ];
+ face.b = faces[ offset ++ ];
+ face.c = faces[ offset ++ ];
- linear_to_gamma_fragment: [
+ if ( hasMaterial ) {
- "#ifdef GAMMA_OUTPUT",
+ materialIndex = faces[ offset ++ ];
+ face.materialIndex = materialIndex;
- "gl_FragColor.xyz = sqrt( gl_FragColor.xyz );",
+ }
- "#endif"
+ // to get face <=> uv index correspondence
- ].join("\n")
+ fi = geometry.faces.length;
+ if ( hasFaceVertexUv ) {
-};
+ for ( i = 0; i < nUvLayers; i ++ ) {
-THREE.UniformsUtils = {
+ uvLayer = json.uvs[ i ];
- merge: function ( uniforms ) {
+ geometry.faceVertexUvs[ i ][ fi ] = [];
- var u, p, tmp, merged = {};
+ for ( j = 0; j < 3; j ++ ) {
- for ( u = 0; u < uniforms.length; u ++ ) {
+ uvIndex = faces[ offset ++ ];
- tmp = this.clone( uniforms[ u ] );
+ u = uvLayer[ uvIndex * 2 ];
+ v = uvLayer[ uvIndex * 2 + 1 ];
- for ( p in tmp ) {
+ uv = new THREE.Vector2( u, v );
- merged[ p ] = tmp[ p ];
+ geometry.faceVertexUvs[ i ][ fi ].push( uv );
- }
+ }
- }
+ }
- return merged;
+ }
- },
+ if ( hasFaceNormal ) {
- clone: function ( uniforms_src ) {
+ normalIndex = faces[ offset ++ ] * 3;
- var u, p, parameter, parameter_src, uniforms_dst = {};
+ face.normal.set(
+ normals[ normalIndex ++ ],
+ normals[ normalIndex ++ ],
+ normals[ normalIndex ]
+ );
- for ( u in uniforms_src ) {
+ }
- uniforms_dst[ u ] = {};
+ if ( hasFaceVertexNormal ) {
- for ( p in uniforms_src[ u ] ) {
+ for ( i = 0; i < 3; i ++ ) {
- parameter_src = uniforms_src[ u ][ p ];
+ normalIndex = faces[ offset ++ ] * 3;
- if ( parameter_src instanceof THREE.Color ||
- parameter_src instanceof THREE.Vector2 ||
- parameter_src instanceof THREE.Vector3 ||
- parameter_src instanceof THREE.Vector4 ||
- parameter_src instanceof THREE.Matrix4 ||
- parameter_src instanceof THREE.Texture ) {
+ normal = new THREE.Vector3(
+ normals[ normalIndex ++ ],
+ normals[ normalIndex ++ ],
+ normals[ normalIndex ]
+ );
- uniforms_dst[ u ][ p ] = parameter_src.clone();
+ face.vertexNormals.push( normal );
- } else if ( parameter_src instanceof Array ) {
+ }
- uniforms_dst[ u ][ p ] = parameter_src.slice();
+ }
- } else {
- uniforms_dst[ u ][ p ] = parameter_src;
+ if ( hasFaceColor ) {
- }
+ colorIndex = faces[ offset ++ ];
+ face.color.setHex( colors[ colorIndex ] );
- }
+ }
- }
- return uniforms_dst;
+ if ( hasFaceVertexColor ) {
- }
+ for ( i = 0; i < 3; i ++ ) {
-};
+ colorIndex = faces[ offset ++ ];
+ face.vertexColors.push( new THREE.Color( colors[ colorIndex ] ) );
-THREE.UniformsLib = {
+ }
- common: {
+ }
- "diffuse" : { type: "c", value: new THREE.Color( 0xeeeeee ) },
- "opacity" : { type: "f", value: 1.0 },
+ geometry.faces.push( face );
- "map" : { type: "t", value: null },
- "offsetRepeat" : { type: "v4", value: new THREE.Vector4( 0, 0, 1, 1 ) },
+ }
- "lightMap" : { type: "t", value: null },
- "specularMap" : { type: "t", value: null },
+ }
- "envMap" : { type: "t", value: null },
- "flipEnvMap" : { type: "f", value: -1 },
- "useRefract" : { type: "i", value: 0 },
- "reflectivity" : { type: "f", value: 1.0 },
- "refractionRatio" : { type: "f", value: 0.98 },
- "combine" : { type: "i", value: 0 },
+ }
- "morphTargetInfluences" : { type: "f", value: 0 }
+ function parseSkin() {
- },
+ var influencesPerVertex = ( json.influencesPerVertex !== undefined ) ? json.influencesPerVertex : 2;
- bump: {
+ if ( json.skinWeights ) {
- "bumpMap" : { type: "t", value: null },
- "bumpScale" : { type: "f", value: 1 }
+ for ( var i = 0, l = json.skinWeights.length; i < l; i += influencesPerVertex ) {
- },
+ var x = json.skinWeights[ i ];
+ var y = ( influencesPerVertex > 1 ) ? json.skinWeights[ i + 1 ] : 0;
+ var z = ( influencesPerVertex > 2 ) ? json.skinWeights[ i + 2 ] : 0;
+ var w = ( influencesPerVertex > 3 ) ? json.skinWeights[ i + 3 ] : 0;
- normalmap: {
+ geometry.skinWeights.push( new THREE.Vector4( x, y, z, w ) );
- "normalMap" : { type: "t", value: null },
- "normalScale" : { type: "v2", value: new THREE.Vector2( 1, 1 ) }
- },
-
- fog : {
+ }
- "fogDensity" : { type: "f", value: 0.00025 },
- "fogNear" : { type: "f", value: 1 },
- "fogFar" : { type: "f", value: 2000 },
- "fogColor" : { type: "c", value: new THREE.Color( 0xffffff ) }
+ }
- },
+ if ( json.skinIndices ) {
- lights: {
+ for ( var i = 0, l = json.skinIndices.length; i < l; i += influencesPerVertex ) {
- "ambientLightColor" : { type: "fv", value: [] },
+ var a = json.skinIndices[ i ];
+ var b = ( influencesPerVertex > 1 ) ? json.skinIndices[ i + 1 ] : 0;
+ var c = ( influencesPerVertex > 2 ) ? json.skinIndices[ i + 2 ] : 0;
+ var d = ( influencesPerVertex > 3 ) ? json.skinIndices[ i + 3 ] : 0;
- "directionalLightDirection" : { type: "fv", value: [] },
- "directionalLightColor" : { type: "fv", value: [] },
+ geometry.skinIndices.push( new THREE.Vector4( a, b, c, d ) );
- "hemisphereLightDirection" : { type: "fv", value: [] },
- "hemisphereLightSkyColor" : { type: "fv", value: [] },
- "hemisphereLightGroundColor" : { type: "fv", value: [] },
+ }
- "pointLightColor" : { type: "fv", value: [] },
- "pointLightPosition" : { type: "fv", value: [] },
- "pointLightDistance" : { type: "fv1", value: [] },
+ }
- "spotLightColor" : { type: "fv", value: [] },
- "spotLightPosition" : { type: "fv", value: [] },
- "spotLightDirection" : { type: "fv", value: [] },
- "spotLightDistance" : { type: "fv1", value: [] },
- "spotLightAngleCos" : { type: "fv1", value: [] },
- "spotLightExponent" : { type: "fv1", value: [] }
+ geometry.bones = json.bones;
- },
+ if ( geometry.bones && geometry.bones.length > 0 && ( geometry.skinWeights.length !== geometry.skinIndices.length || geometry.skinIndices.length !== geometry.vertices.length ) ) {
- particle: {
+ console.warn( 'When skinning, number of vertices (' + geometry.vertices.length + '), skinIndices (' +
+ geometry.skinIndices.length + '), and skinWeights (' + geometry.skinWeights.length + ') should match.' );
- "psColor" : { type: "c", value: new THREE.Color( 0xeeeeee ) },
- "opacity" : { type: "f", value: 1.0 },
- "size" : { type: "f", value: 1.0 },
- "scale" : { type: "f", value: 1.0 },
- "map" : { type: "t", value: null },
+ }
- "fogDensity" : { type: "f", value: 0.00025 },
- "fogNear" : { type: "f", value: 1 },
- "fogFar" : { type: "f", value: 2000 },
- "fogColor" : { type: "c", value: new THREE.Color( 0xffffff ) }
+ }
- },
+ function parseMorphing( scale ) {
- shadowmap: {
+ if ( json.morphTargets !== undefined ) {
- "shadowMap": { type: "tv", value: [] },
- "shadowMapSize": { type: "v2v", value: [] },
+ for ( var i = 0, l = json.morphTargets.length; i < l; i ++ ) {
- "shadowBias" : { type: "fv1", value: [] },
- "shadowDarkness": { type: "fv1", value: [] },
+ geometry.morphTargets[ i ] = {};
+ geometry.morphTargets[ i ].name = json.morphTargets[ i ].name;
+ geometry.morphTargets[ i ].vertices = [];
- "shadowMatrix" : { type: "m4v", value: [] }
+ var dstVertices = geometry.morphTargets[ i ].vertices;
+ var srcVertices = json.morphTargets[ i ].vertices;
- }
+ for ( var v = 0, vl = srcVertices.length; v < vl; v += 3 ) {
-};
+ var vertex = new THREE.Vector3();
+ vertex.x = srcVertices[ v ] * scale;
+ vertex.y = srcVertices[ v + 1 ] * scale;
+ vertex.z = srcVertices[ v + 2 ] * scale;
-THREE.ShaderLib = {
+ dstVertices.push( vertex );
- 'basic': {
+ }
- uniforms: THREE.UniformsUtils.merge( [
+ }
- THREE.UniformsLib[ "common" ],
- THREE.UniformsLib[ "fog" ],
- THREE.UniformsLib[ "shadowmap" ]
+ }
- ] ),
+ if ( json.morphColors !== undefined && json.morphColors.length > 0 ) {
- vertexShader: [
+ console.warn( 'THREE.JSONLoader: "morphColors" no longer supported. Using them as face colors.' );
- THREE.ShaderChunk[ "map_pars_vertex" ],
- THREE.ShaderChunk[ "lightmap_pars_vertex" ],
- THREE.ShaderChunk[ "envmap_pars_vertex" ],
- THREE.ShaderChunk[ "color_pars_vertex" ],
- THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
- THREE.ShaderChunk[ "skinning_pars_vertex" ],
- THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
+ var faces = geometry.faces;
+ var morphColors = json.morphColors[ 0 ].colors;
- "void main() {",
+ for ( var i = 0, l = faces.length; i < l; i ++ ) {
- THREE.ShaderChunk[ "map_vertex" ],
- THREE.ShaderChunk[ "lightmap_vertex" ],
- THREE.ShaderChunk[ "color_vertex" ],
- THREE.ShaderChunk[ "skinbase_vertex" ],
+ faces[ i ].color.fromArray( morphColors, i * 3 );
- "#ifdef USE_ENVMAP",
+ }
- THREE.ShaderChunk[ "morphnormal_vertex" ],
- THREE.ShaderChunk[ "skinnormal_vertex" ],
- THREE.ShaderChunk[ "defaultnormal_vertex" ],
+ }
- "#endif",
+ }
- THREE.ShaderChunk[ "morphtarget_vertex" ],
- THREE.ShaderChunk[ "skinning_vertex" ],
- THREE.ShaderChunk[ "default_vertex" ],
+ function parseAnimations() {
- THREE.ShaderChunk[ "worldpos_vertex" ],
- THREE.ShaderChunk[ "envmap_vertex" ],
- THREE.ShaderChunk[ "shadowmap_vertex" ],
+ var outputAnimations = [];
- "}"
+ // parse old style Bone/Hierarchy animations
+ var animations = [];
- ].join("\n"),
+ if ( json.animation !== undefined ) {
- fragmentShader: [
+ animations.push( json.animation );
- "uniform vec3 diffuse;",
- "uniform float opacity;",
+ }
- THREE.ShaderChunk[ "color_pars_fragment" ],
- THREE.ShaderChunk[ "map_pars_fragment" ],
- THREE.ShaderChunk[ "lightmap_pars_fragment" ],
- THREE.ShaderChunk[ "envmap_pars_fragment" ],
- THREE.ShaderChunk[ "fog_pars_fragment" ],
- THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
- THREE.ShaderChunk[ "specularmap_pars_fragment" ],
+ if ( json.animations !== undefined ) {
- "void main() {",
+ if ( json.animations.length ) {
- "gl_FragColor = vec4( diffuse, opacity );",
+ animations = animations.concat( json.animations );
- THREE.ShaderChunk[ "map_fragment" ],
- THREE.ShaderChunk[ "alphatest_fragment" ],
- THREE.ShaderChunk[ "specularmap_fragment" ],
- THREE.ShaderChunk[ "lightmap_fragment" ],
- THREE.ShaderChunk[ "color_fragment" ],
- THREE.ShaderChunk[ "envmap_fragment" ],
- THREE.ShaderChunk[ "shadowmap_fragment" ],
+ } else {
- THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
+ animations.push( json.animations );
- THREE.ShaderChunk[ "fog_fragment" ],
+ }
- "}"
+ }
- ].join("\n")
+ for ( var i = 0; i < animations.length; i ++ ) {
- },
+ var clip = THREE.AnimationClip.parseAnimation( animations[ i ], geometry.bones );
+ if ( clip ) outputAnimations.push( clip );
- 'lambert': {
+ }
- uniforms: THREE.UniformsUtils.merge( [
+ // parse implicit morph animations
+ if ( geometry.morphTargets ) {
- THREE.UniformsLib[ "common" ],
- THREE.UniformsLib[ "fog" ],
- THREE.UniformsLib[ "lights" ],
- THREE.UniformsLib[ "shadowmap" ],
+ // TODO: Figure out what an appropraite FPS is for morph target animations -- defaulting to 10, but really it is completely arbitrary.
+ var morphAnimationClips = THREE.AnimationClip.CreateClipsFromMorphTargetSequences( geometry.morphTargets, 10 );
+ outputAnimations = outputAnimations.concat( morphAnimationClips );
- {
- "ambient" : { type: "c", value: new THREE.Color( 0xffffff ) },
- "emissive" : { type: "c", value: new THREE.Color( 0x000000 ) },
- "wrapRGB" : { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) }
}
- ] ),
+ if ( outputAnimations.length > 0 ) geometry.animations = outputAnimations;
- vertexShader: [
+ }
- "#define LAMBERT",
+ if ( json.materials === undefined || json.materials.length === 0 ) {
- "varying vec3 vLightFront;",
+ return { geometry: geometry };
- "#ifdef DOUBLE_SIDED",
+ } else {
- "varying vec3 vLightBack;",
+ var materials = THREE.Loader.prototype.initMaterials( json.materials, texturePath, this.crossOrigin );
- "#endif",
+ return { geometry: geometry, materials: materials };
- THREE.ShaderChunk[ "map_pars_vertex" ],
- THREE.ShaderChunk[ "lightmap_pars_vertex" ],
- THREE.ShaderChunk[ "envmap_pars_vertex" ],
- THREE.ShaderChunk[ "lights_lambert_pars_vertex" ],
- THREE.ShaderChunk[ "color_pars_vertex" ],
- THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
- THREE.ShaderChunk[ "skinning_pars_vertex" ],
- THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
+ }
- "void main() {",
+ }
- THREE.ShaderChunk[ "map_vertex" ],
- THREE.ShaderChunk[ "lightmap_vertex" ],
- THREE.ShaderChunk[ "color_vertex" ],
+} );
- THREE.ShaderChunk[ "morphnormal_vertex" ],
- THREE.ShaderChunk[ "skinbase_vertex" ],
- THREE.ShaderChunk[ "skinnormal_vertex" ],
- THREE.ShaderChunk[ "defaultnormal_vertex" ],
+// File:src/loaders/LoadingManager.js
- THREE.ShaderChunk[ "morphtarget_vertex" ],
- THREE.ShaderChunk[ "skinning_vertex" ],
- THREE.ShaderChunk[ "default_vertex" ],
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
- THREE.ShaderChunk[ "worldpos_vertex" ],
- THREE.ShaderChunk[ "envmap_vertex" ],
- THREE.ShaderChunk[ "lights_lambert_vertex" ],
- THREE.ShaderChunk[ "shadowmap_vertex" ],
+THREE.LoadingManager = function ( onLoad, onProgress, onError ) {
- "}"
+ var scope = this;
- ].join("\n"),
+ var isLoading = false, itemsLoaded = 0, itemsTotal = 0;
- fragmentShader: [
+ this.onStart = undefined;
+ this.onLoad = onLoad;
+ this.onProgress = onProgress;
+ this.onError = onError;
- "uniform float opacity;",
+ this.itemStart = function ( url ) {
- "varying vec3 vLightFront;",
+ itemsTotal ++;
- "#ifdef DOUBLE_SIDED",
+ if ( isLoading === false ) {
- "varying vec3 vLightBack;",
+ if ( scope.onStart !== undefined ) {
- "#endif",
+ scope.onStart( url, itemsLoaded, itemsTotal );
- THREE.ShaderChunk[ "color_pars_fragment" ],
- THREE.ShaderChunk[ "map_pars_fragment" ],
- THREE.ShaderChunk[ "lightmap_pars_fragment" ],
- THREE.ShaderChunk[ "envmap_pars_fragment" ],
- THREE.ShaderChunk[ "fog_pars_fragment" ],
- THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
- THREE.ShaderChunk[ "specularmap_pars_fragment" ],
+ }
- "void main() {",
+ }
- "gl_FragColor = vec4( vec3 ( 1.0 ), opacity );",
+ isLoading = true;
- THREE.ShaderChunk[ "map_fragment" ],
- THREE.ShaderChunk[ "alphatest_fragment" ],
- THREE.ShaderChunk[ "specularmap_fragment" ],
+ };
- "#ifdef DOUBLE_SIDED",
+ this.itemEnd = function ( url ) {
- //"float isFront = float( gl_FrontFacing );",
- //"gl_FragColor.xyz *= isFront * vLightFront + ( 1.0 - isFront ) * vLightBack;",
+ itemsLoaded ++;
- "if ( gl_FrontFacing )",
- "gl_FragColor.xyz *= vLightFront;",
- "else",
- "gl_FragColor.xyz *= vLightBack;",
+ if ( scope.onProgress !== undefined ) {
- "#else",
+ scope.onProgress( url, itemsLoaded, itemsTotal );
- "gl_FragColor.xyz *= vLightFront;",
+ }
- "#endif",
+ if ( itemsLoaded === itemsTotal ) {
- THREE.ShaderChunk[ "lightmap_fragment" ],
- THREE.ShaderChunk[ "color_fragment" ],
- THREE.ShaderChunk[ "envmap_fragment" ],
- THREE.ShaderChunk[ "shadowmap_fragment" ],
+ isLoading = false;
- THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
+ if ( scope.onLoad !== undefined ) {
- THREE.ShaderChunk[ "fog_fragment" ],
+ scope.onLoad();
- "}"
+ }
- ].join("\n")
+ }
- },
+ };
- 'phong': {
+ this.itemError = function ( url ) {
- uniforms: THREE.UniformsUtils.merge( [
+ if ( scope.onError !== undefined ) {
- THREE.UniformsLib[ "common" ],
- THREE.UniformsLib[ "bump" ],
- THREE.UniformsLib[ "normalmap" ],
- THREE.UniformsLib[ "fog" ],
- THREE.UniformsLib[ "lights" ],
- THREE.UniformsLib[ "shadowmap" ],
+ scope.onError( url );
- {
- "ambient" : { type: "c", value: new THREE.Color( 0xffffff ) },
- "emissive" : { type: "c", value: new THREE.Color( 0x000000 ) },
- "specular" : { type: "c", value: new THREE.Color( 0x111111 ) },
- "shininess": { type: "f", value: 30 },
- "wrapRGB" : { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) }
- }
+ }
- ] ),
+ };
- vertexShader: [
+};
- "#define PHONG",
+THREE.DefaultLoadingManager = new THREE.LoadingManager();
- "varying vec3 vViewPosition;",
- "varying vec3 vNormal;",
+// File:src/loaders/BufferGeometryLoader.js
- THREE.ShaderChunk[ "map_pars_vertex" ],
- THREE.ShaderChunk[ "lightmap_pars_vertex" ],
- THREE.ShaderChunk[ "envmap_pars_vertex" ],
- THREE.ShaderChunk[ "lights_phong_pars_vertex" ],
- THREE.ShaderChunk[ "color_pars_vertex" ],
- THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
- THREE.ShaderChunk[ "skinning_pars_vertex" ],
- THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
- "void main() {",
+THREE.BufferGeometryLoader = function ( manager ) {
- THREE.ShaderChunk[ "map_vertex" ],
- THREE.ShaderChunk[ "lightmap_vertex" ],
- THREE.ShaderChunk[ "color_vertex" ],
+ this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
- THREE.ShaderChunk[ "morphnormal_vertex" ],
- THREE.ShaderChunk[ "skinbase_vertex" ],
- THREE.ShaderChunk[ "skinnormal_vertex" ],
- THREE.ShaderChunk[ "defaultnormal_vertex" ],
+};
- "vNormal = normalize( transformedNormal );",
+Object.assign( THREE.BufferGeometryLoader.prototype, {
- THREE.ShaderChunk[ "morphtarget_vertex" ],
- THREE.ShaderChunk[ "skinning_vertex" ],
- THREE.ShaderChunk[ "default_vertex" ],
+ load: function ( url, onLoad, onProgress, onError ) {
- "vViewPosition = -mvPosition.xyz;",
+ var scope = this;
- THREE.ShaderChunk[ "worldpos_vertex" ],
- THREE.ShaderChunk[ "envmap_vertex" ],
- THREE.ShaderChunk[ "lights_phong_vertex" ],
- THREE.ShaderChunk[ "shadowmap_vertex" ],
+ var loader = new THREE.XHRLoader( scope.manager );
+ loader.load( url, function ( text ) {
- "}"
+ onLoad( scope.parse( JSON.parse( text ) ) );
- ].join("\n"),
+ }, onProgress, onError );
- fragmentShader: [
+ },
- "uniform vec3 diffuse;",
- "uniform float opacity;",
+ parse: function ( json ) {
- "uniform vec3 ambient;",
- "uniform vec3 emissive;",
- "uniform vec3 specular;",
- "uniform float shininess;",
+ var geometry = new THREE.BufferGeometry();
- THREE.ShaderChunk[ "color_pars_fragment" ],
- THREE.ShaderChunk[ "map_pars_fragment" ],
- THREE.ShaderChunk[ "lightmap_pars_fragment" ],
- THREE.ShaderChunk[ "envmap_pars_fragment" ],
- THREE.ShaderChunk[ "fog_pars_fragment" ],
- THREE.ShaderChunk[ "lights_phong_pars_fragment" ],
- THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
- THREE.ShaderChunk[ "bumpmap_pars_fragment" ],
- THREE.ShaderChunk[ "normalmap_pars_fragment" ],
- THREE.ShaderChunk[ "specularmap_pars_fragment" ],
+ var index = json.data.index;
+
+ var TYPED_ARRAYS = {
+ 'Int8Array': Int8Array,
+ 'Uint8Array': Uint8Array,
+ 'Uint8ClampedArray': Uint8ClampedArray,
+ 'Int16Array': Int16Array,
+ 'Uint16Array': Uint16Array,
+ 'Int32Array': Int32Array,
+ 'Uint32Array': Uint32Array,
+ 'Float32Array': Float32Array,
+ 'Float64Array': Float64Array
+ };
- "void main() {",
+ if ( index !== undefined ) {
- "gl_FragColor = vec4( vec3 ( 1.0 ), opacity );",
+ var typedArray = new TYPED_ARRAYS[ index.type ]( index.array );
+ geometry.setIndex( new THREE.BufferAttribute( typedArray, 1 ) );
- THREE.ShaderChunk[ "map_fragment" ],
- THREE.ShaderChunk[ "alphatest_fragment" ],
- THREE.ShaderChunk[ "specularmap_fragment" ],
+ }
- THREE.ShaderChunk[ "lights_phong_fragment" ],
+ var attributes = json.data.attributes;
- THREE.ShaderChunk[ "lightmap_fragment" ],
- THREE.ShaderChunk[ "color_fragment" ],
- THREE.ShaderChunk[ "envmap_fragment" ],
- THREE.ShaderChunk[ "shadowmap_fragment" ],
+ for ( var key in attributes ) {
- THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
+ var attribute = attributes[ key ];
+ var typedArray = new TYPED_ARRAYS[ attribute.type ]( attribute.array );
- THREE.ShaderChunk[ "fog_fragment" ],
+ geometry.addAttribute( key, new THREE.BufferAttribute( typedArray, attribute.itemSize, attribute.normalized ) );
- "}"
+ }
- ].join("\n")
+ var groups = json.data.groups || json.data.drawcalls || json.data.offsets;
- },
+ if ( groups !== undefined ) {
- 'particle_basic': {
+ for ( var i = 0, n = groups.length; i !== n; ++ i ) {
- uniforms: THREE.UniformsUtils.merge( [
+ var group = groups[ i ];
- THREE.UniformsLib[ "particle" ],
- THREE.UniformsLib[ "shadowmap" ]
+ geometry.addGroup( group.start, group.count, group.materialIndex );
- ] ),
+ }
- vertexShader: [
+ }
- "uniform float size;",
- "uniform float scale;",
+ var boundingSphere = json.data.boundingSphere;
- THREE.ShaderChunk[ "color_pars_vertex" ],
- THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
+ if ( boundingSphere !== undefined ) {
- "void main() {",
+ var center = new THREE.Vector3();
- THREE.ShaderChunk[ "color_vertex" ],
+ if ( boundingSphere.center !== undefined ) {
- "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
+ center.fromArray( boundingSphere.center );
- "#ifdef USE_SIZEATTENUATION",
- "gl_PointSize = size * ( scale / length( mvPosition.xyz ) );",
- "#else",
- "gl_PointSize = size;",
- "#endif",
+ }
- "gl_Position = projectionMatrix * mvPosition;",
+ geometry.boundingSphere = new THREE.Sphere( center, boundingSphere.radius );
- THREE.ShaderChunk[ "worldpos_vertex" ],
- THREE.ShaderChunk[ "shadowmap_vertex" ],
+ }
- "}"
+ return geometry;
- ].join("\n"),
+ }
- fragmentShader: [
+} );
- "uniform vec3 psColor;",
- "uniform float opacity;",
+// File:src/loaders/MaterialLoader.js
- THREE.ShaderChunk[ "color_pars_fragment" ],
- THREE.ShaderChunk[ "map_particle_pars_fragment" ],
- THREE.ShaderChunk[ "fog_pars_fragment" ],
- THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
- "void main() {",
+THREE.MaterialLoader = function ( manager ) {
- "gl_FragColor = vec4( psColor, opacity );",
+ this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
+ this.textures = {};
- THREE.ShaderChunk[ "map_particle_fragment" ],
- THREE.ShaderChunk[ "alphatest_fragment" ],
- THREE.ShaderChunk[ "color_fragment" ],
- THREE.ShaderChunk[ "shadowmap_fragment" ],
- THREE.ShaderChunk[ "fog_fragment" ],
+};
- "}"
+Object.assign( THREE.MaterialLoader.prototype, {
- ].join("\n")
+ load: function ( url, onLoad, onProgress, onError ) {
- },
+ var scope = this;
- 'dashed': {
+ var loader = new THREE.XHRLoader( scope.manager );
+ loader.load( url, function ( text ) {
- uniforms: THREE.UniformsUtils.merge( [
+ onLoad( scope.parse( JSON.parse( text ) ) );
- THREE.UniformsLib[ "common" ],
- THREE.UniformsLib[ "fog" ],
+ }, onProgress, onError );
- {
- "scale": { type: "f", value: 1 },
- "dashSize": { type: "f", value: 1 },
- "totalSize": { type: "f", value: 2 }
- }
+ },
- ] ),
+ setTextures: function ( value ) {
- vertexShader: [
+ this.textures = value;
- "uniform float scale;",
- "attribute float lineDistance;",
+ },
- "varying float vLineDistance;",
+ getTexture: function ( name ) {
- THREE.ShaderChunk[ "color_pars_vertex" ],
+ var textures = this.textures;
- "void main() {",
+ if ( textures[ name ] === undefined ) {
- THREE.ShaderChunk[ "color_vertex" ],
+ console.warn( 'THREE.MaterialLoader: Undefined texture', name );
- "vLineDistance = scale * lineDistance;",
+ }
- "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
- "gl_Position = projectionMatrix * mvPosition;",
+ return textures[ name ];
- "}"
+ },
- ].join("\n"),
+ parse: function ( json ) {
- fragmentShader: [
+ var material = new THREE[ json.type ];
- "uniform vec3 diffuse;",
- "uniform float opacity;",
+ if ( json.uuid !== undefined ) material.uuid = json.uuid;
+ if ( json.name !== undefined ) material.name = json.name;
+ if ( json.color !== undefined ) material.color.setHex( json.color );
+ if ( json.roughness !== undefined ) material.roughness = json.roughness;
+ if ( json.metalness !== undefined ) material.metalness = json.metalness;
+ if ( json.emissive !== undefined ) material.emissive.setHex( json.emissive );
+ if ( json.specular !== undefined ) material.specular.setHex( json.specular );
+ if ( json.shininess !== undefined ) material.shininess = json.shininess;
+ if ( json.uniforms !== undefined ) material.uniforms = json.uniforms;
+ if ( json.vertexShader !== undefined ) material.vertexShader = json.vertexShader;
+ if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader;
+ if ( json.vertexColors !== undefined ) material.vertexColors = json.vertexColors;
+ if ( json.shading !== undefined ) material.shading = json.shading;
+ if ( json.blending !== undefined ) material.blending = json.blending;
+ if ( json.side !== undefined ) material.side = json.side;
+ if ( json.opacity !== undefined ) material.opacity = json.opacity;
+ if ( json.transparent !== undefined ) material.transparent = json.transparent;
+ if ( json.alphaTest !== undefined ) material.alphaTest = json.alphaTest;
+ if ( json.depthTest !== undefined ) material.depthTest = json.depthTest;
+ if ( json.depthWrite !== undefined ) material.depthWrite = json.depthWrite;
+ if ( json.colorWrite !== undefined ) material.colorWrite = json.colorWrite;
+ if ( json.wireframe !== undefined ) material.wireframe = json.wireframe;
+ if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth;
- "uniform float dashSize;",
- "uniform float totalSize;",
+ // for PointsMaterial
+ if ( json.size !== undefined ) material.size = json.size;
+ if ( json.sizeAttenuation !== undefined ) material.sizeAttenuation = json.sizeAttenuation;
- "varying float vLineDistance;",
+ // maps
- THREE.ShaderChunk[ "color_pars_fragment" ],
- THREE.ShaderChunk[ "fog_pars_fragment" ],
+ if ( json.map !== undefined ) material.map = this.getTexture( json.map );
- "void main() {",
+ if ( json.alphaMap !== undefined ) {
- "if ( mod( vLineDistance, totalSize ) > dashSize ) {",
+ material.alphaMap = this.getTexture( json.alphaMap );
+ material.transparent = true;
- "discard;",
+ }
- "}",
+ if ( json.bumpMap !== undefined ) material.bumpMap = this.getTexture( json.bumpMap );
+ if ( json.bumpScale !== undefined ) material.bumpScale = json.bumpScale;
- "gl_FragColor = vec4( diffuse, opacity );",
+ if ( json.normalMap !== undefined ) material.normalMap = this.getTexture( json.normalMap );
+ if ( json.normalScale !== undefined ) {
- THREE.ShaderChunk[ "color_fragment" ],
- THREE.ShaderChunk[ "fog_fragment" ],
+ var normalScale = json.normalScale;
- "}"
+ if ( Array.isArray( normalScale ) === false ) {
- ].join("\n")
+ // Blender exporter used to export a scalar. See #7459
- },
+ normalScale = [ normalScale, normalScale ];
- 'depth': {
+ }
- uniforms: {
+ material.normalScale = new THREE.Vector2().fromArray( normalScale );
- "mNear": { type: "f", value: 1.0 },
- "mFar" : { type: "f", value: 2000.0 },
- "opacity" : { type: "f", value: 1.0 }
+ }
- },
+ if ( json.displacementMap !== undefined ) material.displacementMap = this.getTexture( json.displacementMap );
+ if ( json.displacementScale !== undefined ) material.displacementScale = json.displacementScale;
+ if ( json.displacementBias !== undefined ) material.displacementBias = json.displacementBias;
- vertexShader: [
+ if ( json.roughnessMap !== undefined ) material.roughnessMap = this.getTexture( json.roughnessMap );
+ if ( json.metalnessMap !== undefined ) material.metalnessMap = this.getTexture( json.metalnessMap );
- "void main() {",
+ if ( json.emissiveMap !== undefined ) material.emissiveMap = this.getTexture( json.emissiveMap );
+ if ( json.emissiveIntensity !== undefined ) material.emissiveIntensity = json.emissiveIntensity;
- "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
+ if ( json.specularMap !== undefined ) material.specularMap = this.getTexture( json.specularMap );
- "}"
+ if ( json.envMap !== undefined ) {
- ].join("\n"),
+ material.envMap = this.getTexture( json.envMap );
+ material.combine = THREE.MultiplyOperation;
- fragmentShader: [
+ }
- "uniform float mNear;",
- "uniform float mFar;",
- "uniform float opacity;",
+ if ( json.reflectivity !== undefined ) material.reflectivity = json.reflectivity;
- "void main() {",
+ if ( json.lightMap !== undefined ) material.lightMap = this.getTexture( json.lightMap );
+ if ( json.lightMapIntensity !== undefined ) material.lightMapIntensity = json.lightMapIntensity;
- "float depth = gl_FragCoord.z / gl_FragCoord.w;",
- "float color = 1.0 - smoothstep( mNear, mFar, depth );",
- "gl_FragColor = vec4( vec3( color ), opacity );",
+ if ( json.aoMap !== undefined ) material.aoMap = this.getTexture( json.aoMap );
+ if ( json.aoMapIntensity !== undefined ) material.aoMapIntensity = json.aoMapIntensity;
- "}"
+ // MultiMaterial
- ].join("\n")
+ if ( json.materials !== undefined ) {
- },
+ for ( var i = 0, l = json.materials.length; i < l; i ++ ) {
- 'normal': {
+ material.materials.push( this.parse( json.materials[ i ] ) );
- uniforms: {
+ }
- "opacity" : { type: "f", value: 1.0 }
+ }
- },
+ return material;
- vertexShader: [
+ }
- "varying vec3 vNormal;",
+} );
- THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
+// File:src/loaders/ObjectLoader.js
- "void main() {",
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
- "vNormal = normalize( normalMatrix * normal );",
+THREE.ObjectLoader = function ( manager ) {
- THREE.ShaderChunk[ "morphtarget_vertex" ],
- THREE.ShaderChunk[ "default_vertex" ],
+ this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
+ this.texturePath = '';
- "}"
+};
- ].join("\n"),
+Object.assign( THREE.ObjectLoader.prototype, {
- fragmentShader: [
+ load: function ( url, onLoad, onProgress, onError ) {
- "uniform float opacity;",
- "varying vec3 vNormal;",
+ if ( this.texturePath === '' ) {
- "void main() {",
+ this.texturePath = url.substring( 0, url.lastIndexOf( '/' ) + 1 );
- "gl_FragColor = vec4( 0.5 * normalize( vNormal ) + 0.5, opacity );",
+ }
- "}"
+ var scope = this;
- ].join("\n")
+ var loader = new THREE.XHRLoader( scope.manager );
+ loader.load( url, function ( text ) {
- },
+ scope.parse( JSON.parse( text ), onLoad );
- /* -------------------------------------------------------------------------
- // Normal map shader
- // - Blinn-Phong
- // - normal + diffuse + specular + AO + displacement + reflection + shadow maps
- // - point and directional lights (use with "lights: true" material option)
- ------------------------------------------------------------------------- */
+ }, onProgress, onError );
- 'normalmap' : {
+ },
- uniforms: THREE.UniformsUtils.merge( [
+ setTexturePath: function ( value ) {
- THREE.UniformsLib[ "fog" ],
- THREE.UniformsLib[ "lights" ],
- THREE.UniformsLib[ "shadowmap" ],
+ this.texturePath = value;
- {
+ },
- "enableAO" : { type: "i", value: 0 },
- "enableDiffuse" : { type: "i", value: 0 },
- "enableSpecular" : { type: "i", value: 0 },
- "enableReflection": { type: "i", value: 0 },
- "enableDisplacement": { type: "i", value: 0 },
+ setCrossOrigin: function ( value ) {
- "tDisplacement": { type: "t", value: null }, // must go first as this is vertex texture
- "tDiffuse" : { type: "t", value: null },
- "tCube" : { type: "t", value: null },
- "tNormal" : { type: "t", value: null },
- "tSpecular" : { type: "t", value: null },
- "tAO" : { type: "t", value: null },
+ this.crossOrigin = value;
- "uNormalScale": { type: "v2", value: new THREE.Vector2( 1, 1 ) },
+ },
- "uDisplacementBias": { type: "f", value: 0.0 },
- "uDisplacementScale": { type: "f", value: 1.0 },
+ parse: function ( json, onLoad ) {
- "uDiffuseColor": { type: "c", value: new THREE.Color( 0xffffff ) },
- "uSpecularColor": { type: "c", value: new THREE.Color( 0x111111 ) },
- "uAmbientColor": { type: "c", value: new THREE.Color( 0xffffff ) },
- "uShininess": { type: "f", value: 30 },
- "uOpacity": { type: "f", value: 1 },
+ var geometries = this.parseGeometries( json.geometries );
- "useRefract": { type: "i", value: 0 },
- "uRefractionRatio": { type: "f", value: 0.98 },
- "uReflectivity": { type: "f", value: 0.5 },
+ var images = this.parseImages( json.images, function () {
- "uOffset" : { type: "v2", value: new THREE.Vector2( 0, 0 ) },
- "uRepeat" : { type: "v2", value: new THREE.Vector2( 1, 1 ) },
+ if ( onLoad !== undefined ) onLoad( object );
- "wrapRGB" : { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) }
+ } );
- }
+ var textures = this.parseTextures( json.textures, images );
+ var materials = this.parseMaterials( json.materials, textures );
- ] ),
+ var object = this.parseObject( json.object, geometries, materials );
- fragmentShader: [
+ if ( json.animations ) {
- "uniform vec3 uAmbientColor;",
- "uniform vec3 uDiffuseColor;",
- "uniform vec3 uSpecularColor;",
- "uniform float uShininess;",
- "uniform float uOpacity;",
+ object.animations = this.parseAnimations( json.animations );
- "uniform bool enableDiffuse;",
- "uniform bool enableSpecular;",
- "uniform bool enableAO;",
- "uniform bool enableReflection;",
+ }
- "uniform sampler2D tDiffuse;",
- "uniform sampler2D tNormal;",
- "uniform sampler2D tSpecular;",
- "uniform sampler2D tAO;",
+ if ( json.images === undefined || json.images.length === 0 ) {
- "uniform samplerCube tCube;",
+ if ( onLoad !== undefined ) onLoad( object );
- "uniform vec2 uNormalScale;",
+ }
- "uniform bool useRefract;",
- "uniform float uRefractionRatio;",
- "uniform float uReflectivity;",
+ return object;
- "varying vec3 vTangent;",
- "varying vec3 vBinormal;",
- "varying vec3 vNormal;",
- "varying vec2 vUv;",
+ },
- "uniform vec3 ambientLightColor;",
+ parseGeometries: function ( json ) {
- "#if MAX_DIR_LIGHTS > 0",
+ var geometries = {};
- "uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];",
- "uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];",
+ if ( json !== undefined ) {
- "#endif",
+ var geometryLoader = new THREE.JSONLoader();
+ var bufferGeometryLoader = new THREE.BufferGeometryLoader();
- "#if MAX_HEMI_LIGHTS > 0",
+ for ( var i = 0, l = json.length; i < l; i ++ ) {
- "uniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];",
- "uniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];",
- "uniform vec3 hemisphereLightDirection[ MAX_HEMI_LIGHTS ];",
+ var geometry;
+ var data = json[ i ];
- "#endif",
+ switch ( data.type ) {
- "#if MAX_POINT_LIGHTS > 0",
+ case 'PlaneGeometry':
+ case 'PlaneBufferGeometry':
- "uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];",
- "uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
- "uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
+ geometry = new THREE[ data.type ](
+ data.width,
+ data.height,
+ data.widthSegments,
+ data.heightSegments
+ );
- "#endif",
+ break;
- "#if MAX_SPOT_LIGHTS > 0",
+ case 'BoxGeometry':
+ case 'BoxBufferGeometry':
+ case 'CubeGeometry': // backwards compatible
- "uniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];",
- "uniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];",
- "uniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];",
- "uniform float spotLightAngleCos[ MAX_SPOT_LIGHTS ];",
- "uniform float spotLightExponent[ MAX_SPOT_LIGHTS ];",
- "uniform float spotLightDistance[ MAX_SPOT_LIGHTS ];",
+ geometry = new THREE[ data.type ](
+ data.width,
+ data.height,
+ data.depth,
+ data.widthSegments,
+ data.heightSegments,
+ data.depthSegments
+ );
- "#endif",
+ break;
- "#ifdef WRAP_AROUND",
+ case 'CircleGeometry':
+ case 'CircleBufferGeometry':
- "uniform vec3 wrapRGB;",
+ geometry = new THREE[ data.type ](
+ data.radius,
+ data.segments,
+ data.thetaStart,
+ data.thetaLength
+ );
- "#endif",
+ break;
- "varying vec3 vWorldPosition;",
- "varying vec3 vViewPosition;",
+ case 'CylinderGeometry':
+ case 'CylinderBufferGeometry':
- THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
- THREE.ShaderChunk[ "fog_pars_fragment" ],
+ geometry = new THREE[ data.type ](
+ data.radiusTop,
+ data.radiusBottom,
+ data.height,
+ data.radialSegments,
+ data.heightSegments,
+ data.openEnded,
+ data.thetaStart,
+ data.thetaLength
+ );
- "void main() {",
+ break;
- "gl_FragColor = vec4( vec3( 1.0 ), uOpacity );",
+ case 'ConeGeometry':
+ case 'ConeBufferGeometry':
- "vec3 specularTex = vec3( 1.0 );",
+ geometry = new THREE [ data.type ](
+ data.radius,
+ data.height,
+ data.radialSegments,
+ data.heightSegments,
+ data.openEnded,
+ data.thetaStart,
+ data.thetaLength
+ );
- "vec3 normalTex = texture2D( tNormal, vUv ).xyz * 2.0 - 1.0;",
- "normalTex.xy *= uNormalScale;",
- "normalTex = normalize( normalTex );",
+ break;
- "if( enableDiffuse ) {",
+ case 'SphereGeometry':
+ case 'SphereBufferGeometry':
- "#ifdef GAMMA_INPUT",
+ geometry = new THREE[ data.type ](
+ data.radius,
+ data.widthSegments,
+ data.heightSegments,
+ data.phiStart,
+ data.phiLength,
+ data.thetaStart,
+ data.thetaLength
+ );
- "vec4 texelColor = texture2D( tDiffuse, vUv );",
- "texelColor.xyz *= texelColor.xyz;",
+ break;
- "gl_FragColor = gl_FragColor * texelColor;",
+ case 'DodecahedronGeometry':
+ case 'IcosahedronGeometry':
+ case 'OctahedronGeometry':
+ case 'TetrahedronGeometry':
- "#else",
+ geometry = new THREE[ data.type ](
+ data.radius,
+ data.detail
+ );
- "gl_FragColor = gl_FragColor * texture2D( tDiffuse, vUv );",
+ break;
- "#endif",
+ case 'RingGeometry':
+ case 'RingBufferGeometry':
- "}",
+ geometry = new THREE[ data.type ](
+ data.innerRadius,
+ data.outerRadius,
+ data.thetaSegments,
+ data.phiSegments,
+ data.thetaStart,
+ data.thetaLength
+ );
- "if( enableAO ) {",
+ break;
- "#ifdef GAMMA_INPUT",
+ case 'TorusGeometry':
+ case 'TorusBufferGeometry':
- "vec4 aoColor = texture2D( tAO, vUv );",
- "aoColor.xyz *= aoColor.xyz;",
+ geometry = new THREE[ data.type ](
+ data.radius,
+ data.tube,
+ data.radialSegments,
+ data.tubularSegments,
+ data.arc
+ );
- "gl_FragColor.xyz = gl_FragColor.xyz * aoColor.xyz;",
+ break;
- "#else",
+ case 'TorusKnotGeometry':
+ case 'TorusKnotBufferGeometry':
- "gl_FragColor.xyz = gl_FragColor.xyz * texture2D( tAO, vUv ).xyz;",
-
- "#endif",
-
- "}",
-
- "if( enableSpecular )",
- "specularTex = texture2D( tSpecular, vUv ).xyz;",
-
- "mat3 tsb = mat3( normalize( vTangent ), normalize( vBinormal ), normalize( vNormal ) );",
- "vec3 finalNormal = tsb * normalTex;",
+ geometry = new THREE[ data.type ](
+ data.radius,
+ data.tube,
+ data.tubularSegments,
+ data.radialSegments,
+ data.p,
+ data.q
+ );
- "#ifdef FLIP_SIDED",
+ break;
- "finalNormal = -finalNormal;",
+ case 'LatheGeometry':
+ case 'LatheBufferGeometry':
- "#endif",
+ geometry = new THREE[ data.type ](
+ data.points,
+ data.segments,
+ data.phiStart,
+ data.phiLength
+ );
- "vec3 normal = normalize( finalNormal );",
- "vec3 viewPosition = normalize( vViewPosition );",
+ break;
- // point lights
+ case 'BufferGeometry':
- "#if MAX_POINT_LIGHTS > 0",
+ geometry = bufferGeometryLoader.parse( data );
- "vec3 pointDiffuse = vec3( 0.0 );",
- "vec3 pointSpecular = vec3( 0.0 );",
+ break;
- "for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
+ case 'Geometry':
- "vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
- "vec3 pointVector = lPosition.xyz + vViewPosition.xyz;",
+ geometry = geometryLoader.parse( data.data, this.texturePath ).geometry;
- "float pointDistance = 1.0;",
- "if ( pointLightDistance[ i ] > 0.0 )",
- "pointDistance = 1.0 - min( ( length( pointVector ) / pointLightDistance[ i ] ), 1.0 );",
+ break;
- "pointVector = normalize( pointVector );",
+ default:
- // diffuse
+ console.warn( 'THREE.ObjectLoader: Unsupported geometry type "' + data.type + '"' );
- "#ifdef WRAP_AROUND",
+ continue;
- "float pointDiffuseWeightFull = max( dot( normal, pointVector ), 0.0 );",
- "float pointDiffuseWeightHalf = max( 0.5 * dot( normal, pointVector ) + 0.5, 0.0 );",
+ }
- "vec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );",
+ geometry.uuid = data.uuid;
- "#else",
+ if ( data.name !== undefined ) geometry.name = data.name;
- "float pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );",
+ geometries[ data.uuid ] = geometry;
- "#endif",
+ }
- "pointDiffuse += pointDistance * pointLightColor[ i ] * uDiffuseColor * pointDiffuseWeight;",
+ }
- // specular
+ return geometries;
- "vec3 pointHalfVector = normalize( pointVector + viewPosition );",
- "float pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );",
- "float pointSpecularWeight = specularTex.r * max( pow( pointDotNormalHalf, uShininess ), 0.0 );",
+ },
- "#ifdef PHYSICALLY_BASED_SHADING",
+ parseMaterials: function ( json, textures ) {
- // 2.0 => 2.0001 is hack to work around ANGLE bug
+ var materials = {};
- "float specularNormalization = ( uShininess + 2.0001 ) / 8.0;",
+ if ( json !== undefined ) {
- "vec3 schlick = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( pointVector, pointHalfVector ), 5.0 );",
- "pointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * pointDistance * specularNormalization;",
+ var loader = new THREE.MaterialLoader();
+ loader.setTextures( textures );
- "#else",
+ for ( var i = 0, l = json.length; i < l; i ++ ) {
- "pointSpecular += pointDistance * pointLightColor[ i ] * uSpecularColor * pointSpecularWeight * pointDiffuseWeight;",
+ var material = loader.parse( json[ i ] );
+ materials[ material.uuid ] = material;
- "#endif",
+ }
- "}",
+ }
- "#endif",
+ return materials;
- // spot lights
+ },
- "#if MAX_SPOT_LIGHTS > 0",
+ parseAnimations: function ( json ) {
- "vec3 spotDiffuse = vec3( 0.0 );",
- "vec3 spotSpecular = vec3( 0.0 );",
+ var animations = [];
- "for ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {",
+ for ( var i = 0; i < json.length; i ++ ) {
- "vec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );",
- "vec3 spotVector = lPosition.xyz + vViewPosition.xyz;",
+ var clip = THREE.AnimationClip.parse( json[ i ] );
- "float spotDistance = 1.0;",
- "if ( spotLightDistance[ i ] > 0.0 )",
- "spotDistance = 1.0 - min( ( length( spotVector ) / spotLightDistance[ i ] ), 1.0 );",
+ animations.push( clip );
- "spotVector = normalize( spotVector );",
+ }
- "float spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - vWorldPosition ) );",
+ return animations;
- "if ( spotEffect > spotLightAngleCos[ i ] ) {",
+ },
- "spotEffect = max( pow( spotEffect, spotLightExponent[ i ] ), 0.0 );",
+ parseImages: function ( json, onLoad ) {
- // diffuse
+ var scope = this;
+ var images = {};
- "#ifdef WRAP_AROUND",
+ function loadImage( url ) {
- "float spotDiffuseWeightFull = max( dot( normal, spotVector ), 0.0 );",
- "float spotDiffuseWeightHalf = max( 0.5 * dot( normal, spotVector ) + 0.5, 0.0 );",
+ scope.manager.itemStart( url );
- "vec3 spotDiffuseWeight = mix( vec3 ( spotDiffuseWeightFull ), vec3( spotDiffuseWeightHalf ), wrapRGB );",
+ return loader.load( url, function () {
- "#else",
+ scope.manager.itemEnd( url );
- "float spotDiffuseWeight = max( dot( normal, spotVector ), 0.0 );",
+ } );
- "#endif",
+ }
- "spotDiffuse += spotDistance * spotLightColor[ i ] * uDiffuseColor * spotDiffuseWeight * spotEffect;",
+ if ( json !== undefined && json.length > 0 ) {
- // specular
+ var manager = new THREE.LoadingManager( onLoad );
- "vec3 spotHalfVector = normalize( spotVector + viewPosition );",
- "float spotDotNormalHalf = max( dot( normal, spotHalfVector ), 0.0 );",
- "float spotSpecularWeight = specularTex.r * max( pow( spotDotNormalHalf, uShininess ), 0.0 );",
+ var loader = new THREE.ImageLoader( manager );
+ loader.setCrossOrigin( this.crossOrigin );
- "#ifdef PHYSICALLY_BASED_SHADING",
+ for ( var i = 0, l = json.length; i < l; i ++ ) {
- // 2.0 => 2.0001 is hack to work around ANGLE bug
+ var image = json[ i ];
+ var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( image.url ) ? image.url : scope.texturePath + image.url;
- "float specularNormalization = ( uShininess + 2.0001 ) / 8.0;",
+ images[ image.uuid ] = loadImage( path );
- "vec3 schlick = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( spotVector, spotHalfVector ), 5.0 );",
- "spotSpecular += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * spotDistance * specularNormalization * spotEffect;",
+ }
- "#else",
+ }
- "spotSpecular += spotDistance * spotLightColor[ i ] * uSpecularColor * spotSpecularWeight * spotDiffuseWeight * spotEffect;",
+ return images;
- "#endif",
+ },
- "}",
+ parseTextures: function ( json, images ) {
- "}",
+ function parseConstant( value ) {
- "#endif",
+ if ( typeof( value ) === 'number' ) return value;
- // directional lights
+ console.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value );
- "#if MAX_DIR_LIGHTS > 0",
+ return THREE[ value ];
- "vec3 dirDiffuse = vec3( 0.0 );",
- "vec3 dirSpecular = vec3( 0.0 );",
+ }
- "for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {",
+ var textures = {};
- "vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );",
- "vec3 dirVector = normalize( lDirection.xyz );",
+ if ( json !== undefined ) {
- // diffuse
+ for ( var i = 0, l = json.length; i < l; i ++ ) {
- "#ifdef WRAP_AROUND",
+ var data = json[ i ];
- "float directionalLightWeightingFull = max( dot( normal, dirVector ), 0.0 );",
- "float directionalLightWeightingHalf = max( 0.5 * dot( normal, dirVector ) + 0.5, 0.0 );",
+ if ( data.image === undefined ) {
- "vec3 dirDiffuseWeight = mix( vec3( directionalLightWeightingFull ), vec3( directionalLightWeightingHalf ), wrapRGB );",
+ console.warn( 'THREE.ObjectLoader: No "image" specified for', data.uuid );
- "#else",
+ }
- "float dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );",
+ if ( images[ data.image ] === undefined ) {
- "#endif",
+ console.warn( 'THREE.ObjectLoader: Undefined image', data.image );
- "dirDiffuse += directionalLightColor[ i ] * uDiffuseColor * dirDiffuseWeight;",
+ }
- // specular
+ var texture = new THREE.Texture( images[ data.image ] );
+ texture.needsUpdate = true;
- "vec3 dirHalfVector = normalize( dirVector + viewPosition );",
- "float dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );",
- "float dirSpecularWeight = specularTex.r * max( pow( dirDotNormalHalf, uShininess ), 0.0 );",
+ texture.uuid = data.uuid;
- "#ifdef PHYSICALLY_BASED_SHADING",
+ if ( data.name !== undefined ) texture.name = data.name;
- // 2.0 => 2.0001 is hack to work around ANGLE bug
+ if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping );
- "float specularNormalization = ( uShininess + 2.0001 ) / 8.0;",
+ if ( data.offset !== undefined ) texture.offset.fromArray( data.offset );
+ if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat );
+ if ( data.wrap !== undefined ) {
- "vec3 schlick = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( dirVector, dirHalfVector ), 5.0 );",
- "dirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;",
+ texture.wrapS = parseConstant( data.wrap[ 0 ] );
+ texture.wrapT = parseConstant( data.wrap[ 1 ] );
- "#else",
+ }
- "dirSpecular += directionalLightColor[ i ] * uSpecularColor * dirSpecularWeight * dirDiffuseWeight;",
+ if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter );
+ if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter );
+ if ( data.anisotropy !== undefined ) texture.anisotropy = data.anisotropy;
- "#endif",
+ if ( data.flipY !== undefined ) texture.flipY = data.flipY;
- "}",
+ textures[ data.uuid ] = texture;
- "#endif",
+ }
- // hemisphere lights
+ }
- "#if MAX_HEMI_LIGHTS > 0",
+ return textures;
- "vec3 hemiDiffuse = vec3( 0.0 );",
- "vec3 hemiSpecular = vec3( 0.0 );" ,
+ },
- "for( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {",
+ parseObject: function () {
- "vec4 lDirection = viewMatrix * vec4( hemisphereLightDirection[ i ], 0.0 );",
- "vec3 lVector = normalize( lDirection.xyz );",
+ var matrix = new THREE.Matrix4();
- // diffuse
+ return function parseObject( data, geometries, materials ) {
- "float dotProduct = dot( normal, lVector );",
- "float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;",
+ var object;
- "vec3 hemiColor = mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );",
+ function getGeometry( name ) {
- "hemiDiffuse += uDiffuseColor * hemiColor;",
+ if ( geometries[ name ] === undefined ) {
- // specular (sky light)
+ console.warn( 'THREE.ObjectLoader: Undefined geometry', name );
+ }
- "vec3 hemiHalfVectorSky = normalize( lVector + viewPosition );",
- "float hemiDotNormalHalfSky = 0.5 * dot( normal, hemiHalfVectorSky ) + 0.5;",
- "float hemiSpecularWeightSky = specularTex.r * max( pow( hemiDotNormalHalfSky, uShininess ), 0.0 );",
+ return geometries[ name ];
- // specular (ground light)
+ }
- "vec3 lVectorGround = -lVector;",
+ function getMaterial( name ) {
- "vec3 hemiHalfVectorGround = normalize( lVectorGround + viewPosition );",
- "float hemiDotNormalHalfGround = 0.5 * dot( normal, hemiHalfVectorGround ) + 0.5;",
- "float hemiSpecularWeightGround = specularTex.r * max( pow( hemiDotNormalHalfGround, uShininess ), 0.0 );",
+ if ( name === undefined ) return undefined;
- "#ifdef PHYSICALLY_BASED_SHADING",
+ if ( materials[ name ] === undefined ) {
- "float dotProductGround = dot( normal, lVectorGround );",
+ console.warn( 'THREE.ObjectLoader: Undefined material', name );
- // 2.0 => 2.0001 is hack to work around ANGLE bug
+ }
- "float specularNormalization = ( uShininess + 2.0001 ) / 8.0;",
+ return materials[ name ];
- "vec3 schlickSky = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( lVector, hemiHalfVectorSky ), 5.0 );",
- "vec3 schlickGround = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( lVectorGround, hemiHalfVectorGround ), 5.0 );",
- "hemiSpecular += hemiColor * specularNormalization * ( schlickSky * hemiSpecularWeightSky * max( dotProduct, 0.0 ) + schlickGround * hemiSpecularWeightGround * max( dotProductGround, 0.0 ) );",
+ }
- "#else",
+ switch ( data.type ) {
- "hemiSpecular += uSpecularColor * hemiColor * ( hemiSpecularWeightSky + hemiSpecularWeightGround ) * hemiDiffuseWeight;",
+ case 'Scene':
- "#endif",
+ object = new THREE.Scene();
- "}",
+ break;
- "#endif",
+ case 'PerspectiveCamera':
- // all lights contribution summation
+ object = new THREE.PerspectiveCamera( data.fov, data.aspect, data.near, data.far );
- "vec3 totalDiffuse = vec3( 0.0 );",
- "vec3 totalSpecular = vec3( 0.0 );",
+ if ( data.focus !== undefined ) object.focus = data.focus;
+ if ( data.zoom !== undefined ) object.zoom = data.zoom;
+ if ( data.filmGauge !== undefined ) object.filmGauge = data.filmGauge;
+ if ( data.filmOffset !== undefined ) object.filmOffset = data.filmOffset;
+ if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
- "#if MAX_DIR_LIGHTS > 0",
+ break;
- "totalDiffuse += dirDiffuse;",
- "totalSpecular += dirSpecular;",
+ case 'OrthographicCamera':
- "#endif",
+ object = new THREE.OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far );
- "#if MAX_HEMI_LIGHTS > 0",
+ break;
- "totalDiffuse += hemiDiffuse;",
- "totalSpecular += hemiSpecular;",
+ case 'AmbientLight':
- "#endif",
+ object = new THREE.AmbientLight( data.color, data.intensity );
- "#if MAX_POINT_LIGHTS > 0",
+ break;
- "totalDiffuse += pointDiffuse;",
- "totalSpecular += pointSpecular;",
+ case 'DirectionalLight':
- "#endif",
+ object = new THREE.DirectionalLight( data.color, data.intensity );
- "#if MAX_SPOT_LIGHTS > 0",
+ break;
- "totalDiffuse += spotDiffuse;",
- "totalSpecular += spotSpecular;",
+ case 'PointLight':
- "#endif",
+ object = new THREE.PointLight( data.color, data.intensity, data.distance, data.decay );
- "#ifdef METAL",
+ break;
- "gl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * uAmbientColor + totalSpecular );",
+ case 'SpotLight':
- "#else",
+ object = new THREE.SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay );
- "gl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * uAmbientColor ) + totalSpecular;",
+ break;
- "#endif",
+ case 'HemisphereLight':
- "if ( enableReflection ) {",
+ object = new THREE.HemisphereLight( data.color, data.groundColor, data.intensity );
- "vec3 vReflect;",
- "vec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );",
+ break;
- "if ( useRefract ) {",
+ case 'Mesh':
- "vReflect = refract( cameraToVertex, normal, uRefractionRatio );",
+ var geometry = getGeometry( data.geometry );
+ var material = getMaterial( data.material );
- "} else {",
+ if ( geometry.bones && geometry.bones.length > 0 ) {
- "vReflect = reflect( cameraToVertex, normal );",
+ object = new THREE.SkinnedMesh( geometry, material );
- "}",
+ } else {
- "vec4 cubeColor = textureCube( tCube, vec3( -vReflect.x, vReflect.yz ) );",
+ object = new THREE.Mesh( geometry, material );
- "#ifdef GAMMA_INPUT",
+ }
- "cubeColor.xyz *= cubeColor.xyz;",
+ break;
- "#endif",
+ case 'LOD':
- "gl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularTex.r * uReflectivity );",
+ object = new THREE.LOD();
- "}",
+ break;
- THREE.ShaderChunk[ "shadowmap_fragment" ],
- THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
- THREE.ShaderChunk[ "fog_fragment" ],
+ case 'Line':
- "}"
+ object = new THREE.Line( getGeometry( data.geometry ), getMaterial( data.material ), data.mode );
- ].join("\n"),
+ break;
- vertexShader: [
+ case 'PointCloud':
+ case 'Points':
- "attribute vec4 tangent;",
+ object = new THREE.Points( getGeometry( data.geometry ), getMaterial( data.material ) );
- "uniform vec2 uOffset;",
- "uniform vec2 uRepeat;",
+ break;
- "uniform bool enableDisplacement;",
+ case 'Sprite':
- "#ifdef VERTEX_TEXTURES",
+ object = new THREE.Sprite( getMaterial( data.material ) );
- "uniform sampler2D tDisplacement;",
- "uniform float uDisplacementScale;",
- "uniform float uDisplacementBias;",
+ break;
- "#endif",
+ case 'Group':
- "varying vec3 vTangent;",
- "varying vec3 vBinormal;",
- "varying vec3 vNormal;",
- "varying vec2 vUv;",
+ object = new THREE.Group();
- "varying vec3 vWorldPosition;",
- "varying vec3 vViewPosition;",
+ break;
- THREE.ShaderChunk[ "skinning_pars_vertex" ],
- THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
+ default:
- "void main() {",
+ object = new THREE.Object3D();
- THREE.ShaderChunk[ "skinbase_vertex" ],
- THREE.ShaderChunk[ "skinnormal_vertex" ],
+ }
- // normal, tangent and binormal vectors
+ object.uuid = data.uuid;
- "#ifdef USE_SKINNING",
+ if ( data.name !== undefined ) object.name = data.name;
+ if ( data.matrix !== undefined ) {
- "vNormal = normalize( normalMatrix * skinnedNormal.xyz );",
+ matrix.fromArray( data.matrix );
+ matrix.decompose( object.position, object.quaternion, object.scale );
- "vec4 skinnedTangent = skinMatrix * vec4( tangent.xyz, 0.0 );",
- "vTangent = normalize( normalMatrix * skinnedTangent.xyz );",
+ } else {
- "#else",
+ if ( data.position !== undefined ) object.position.fromArray( data.position );
+ if ( data.rotation !== undefined ) object.rotation.fromArray( data.rotation );
+ if ( data.scale !== undefined ) object.scale.fromArray( data.scale );
- "vNormal = normalize( normalMatrix * normal );",
- "vTangent = normalize( normalMatrix * tangent.xyz );",
+ }
- "#endif",
+ if ( data.castShadow !== undefined ) object.castShadow = data.castShadow;
+ if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow;
- "vBinormal = normalize( cross( vNormal, vTangent ) * tangent.w );",
+ if ( data.visible !== undefined ) object.visible = data.visible;
+ if ( data.userData !== undefined ) object.userData = data.userData;
- "vUv = uv * uRepeat + uOffset;",
+ if ( data.children !== undefined ) {
- // displacement mapping
+ for ( var child in data.children ) {
- "vec3 displacedPosition;",
+ object.add( this.parseObject( data.children[ child ], geometries, materials ) );
- "#ifdef VERTEX_TEXTURES",
+ }
- "if ( enableDisplacement ) {",
+ }
- "vec3 dv = texture2D( tDisplacement, uv ).xyz;",
- "float df = uDisplacementScale * dv.x + uDisplacementBias;",
- "displacedPosition = position + normalize( normal ) * df;",
+ if ( data.type === 'LOD' ) {
- "} else {",
+ var levels = data.levels;
- "#ifdef USE_SKINNING",
+ for ( var l = 0; l < levels.length; l ++ ) {
- "vec4 skinVertex = vec4( position, 1.0 );",
+ var level = levels[ l ];
+ var child = object.getObjectByProperty( 'uuid', level.object );
- "vec4 skinned = boneMatX * skinVertex * skinWeight.x;",
- "skinned += boneMatY * skinVertex * skinWeight.y;",
+ if ( child !== undefined ) {
- "displacedPosition = skinned.xyz;",
+ object.addLevel( child, level.distance );
- "#else",
+ }
- "displacedPosition = position;",
+ }
- "#endif",
+ }
- "}",
+ return object;
- "#else",
+ };
- "#ifdef USE_SKINNING",
+ }()
- "vec4 skinVertex = vec4( position, 1.0 );",
+} );
- "vec4 skinned = boneMatX * skinVertex * skinWeight.x;",
- "skinned += boneMatY * skinVertex * skinWeight.y;",
+// File:src/loaders/TextureLoader.js
- "displacedPosition = skinned.xyz;",
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
- "#else",
+THREE.TextureLoader = function ( manager ) {
- "displacedPosition = position;",
+ this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
- "#endif",
+};
- "#endif",
+Object.assign( THREE.TextureLoader.prototype, {
- //
+ load: function ( url, onLoad, onProgress, onError ) {
- "vec4 mvPosition = modelViewMatrix * vec4( displacedPosition, 1.0 );",
- "vec4 worldPosition = modelMatrix * vec4( displacedPosition, 1.0 );",
+ var texture = new THREE.Texture();
- "gl_Position = projectionMatrix * mvPosition;",
+ var loader = new THREE.ImageLoader( this.manager );
+ loader.setCrossOrigin( this.crossOrigin );
+ loader.setPath( this.path );
+ loader.load( url, function ( image ) {
- //
+ // JPEGs can't have an alpha channel, so memory can be saved by storing them as RGB.
+ var isJPEG = url.search( /\.(jpg|jpeg)$/ ) > 0 || url.search( /^data\:image\/jpeg/ ) === 0;
- "vWorldPosition = worldPosition.xyz;",
- "vViewPosition = -mvPosition.xyz;",
+ texture.format = isJPEG ? THREE.RGBFormat : THREE.RGBAFormat;
+ texture.image = image;
+ texture.needsUpdate = true;
- // shadows
+ if ( onLoad !== undefined ) {
- "#ifdef USE_SHADOWMAP",
+ onLoad( texture );
- "for( int i = 0; i < MAX_SHADOWS; i ++ ) {",
+ }
- "vShadowCoord[ i ] = shadowMatrix[ i ] * worldPosition;",
+ }, onProgress, onError );
- "}",
+ return texture;
- "#endif",
+ },
- "}"
+ setCrossOrigin: function ( value ) {
- ].join("\n")
+ this.crossOrigin = value;
+ return this;
},
- /* -------------------------------------------------------------------------
- // Cube map shader
- ------------------------------------------------------------------------- */
-
- 'cube': {
-
- uniforms: { "tCube": { type: "t", value: null },
- "tFlip": { type: "f", value: -1 } },
+ setPath: function ( value ) {
- vertexShader: [
+ this.path = value;
+ return this;
- "varying vec3 vWorldPosition;",
+ }
- "void main() {",
+} );
- "vec4 worldPosition = modelMatrix * vec4( position, 1.0 );",
- "vWorldPosition = worldPosition.xyz;",
+// File:src/loaders/CubeTextureLoader.js
- "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
- "}"
+THREE.CubeTextureLoader = function ( manager ) {
- ].join("\n"),
+ this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
- fragmentShader: [
+};
- "uniform samplerCube tCube;",
- "uniform float tFlip;",
+Object.assign( THREE.CubeTextureLoader.prototype, {
- "varying vec3 vWorldPosition;",
+ load: function ( urls, onLoad, onProgress, onError ) {
- "void main() {",
+ var texture = new THREE.CubeTexture();
- "gl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );",
+ var loader = new THREE.ImageLoader( this.manager );
+ loader.setCrossOrigin( this.crossOrigin );
+ loader.setPath( this.path );
- "}"
+ var loaded = 0;
- ].join("\n")
+ function loadTexture( i ) {
- },
+ loader.load( urls[ i ], function ( image ) {
- // Depth encoding into RGBA texture
- // based on SpiderGL shadow map example
- // http://spidergl.org/example.php?id=6
- // originally from
- // http://www.gamedev.net/topic/442138-packing-a-float-into-a-a8r8g8b8-texture-shader/page__whichpage__1%25EF%25BF%25BD
- // see also here:
- // http://aras-p.info/blog/2009/07/30/encoding-floats-to-rgba-the-final/
+ texture.images[ i ] = image;
- 'depthRGBA': {
+ loaded ++;
- uniforms: {},
+ if ( loaded === 6 ) {
- vertexShader: [
+ texture.needsUpdate = true;
- THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
- THREE.ShaderChunk[ "skinning_pars_vertex" ],
+ if ( onLoad ) onLoad( texture );
- "void main() {",
+ }
- THREE.ShaderChunk[ "skinbase_vertex" ],
- THREE.ShaderChunk[ "morphtarget_vertex" ],
- THREE.ShaderChunk[ "skinning_vertex" ],
- THREE.ShaderChunk[ "default_vertex" ],
+ }, undefined, onError );
- "}"
+ }
- ].join("\n"),
+ for ( var i = 0; i < urls.length; ++ i ) {
- fragmentShader: [
+ loadTexture( i );
- "vec4 pack_depth( const in float depth ) {",
+ }
- "const vec4 bit_shift = vec4( 256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0 );",
- "const vec4 bit_mask = vec4( 0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0 );",
- "vec4 res = fract( depth * bit_shift );",
- "res -= res.xxyz * bit_mask;",
- "return res;",
+ return texture;
- "}",
+ },
- "void main() {",
+ setCrossOrigin: function ( value ) {
- "gl_FragData[ 0 ] = pack_depth( gl_FragCoord.z );",
+ this.crossOrigin = value;
+ return this;
- //"gl_FragData[ 0 ] = pack_depth( gl_FragCoord.z / gl_FragCoord.w );",
- //"float z = ( ( gl_FragCoord.z / gl_FragCoord.w ) - 3.0 ) / ( 4000.0 - 3.0 );",
- //"gl_FragData[ 0 ] = pack_depth( z );",
- //"gl_FragData[ 0 ] = vec4( z, z, z, 1.0 );",
+ },
- "}"
+ setPath: function ( value ) {
- ].join("\n")
+ this.path = value;
+ return this;
}
-};
+} );
+
+// File:src/loaders/BinaryTextureLoader.js
/**
- * @author supereggbert / http://www.paulbrunt.co.uk/
- * @author mrdoob / http://mrdoob.com/
- * @author alteredq / http://alteredqualia.com/
- * @author szimek / https://github.com/szimek/
+ * @author Nikos M. / https://github.com/foo123/
+ *
+ * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...)
*/
-THREE.WebGLRenderer = function ( parameters ) {
+THREE.DataTextureLoader = THREE.BinaryTextureLoader = function ( manager ) {
- console.log( 'THREE.WebGLRenderer', THREE.REVISION );
+ this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
- parameters = parameters || {};
+ // override in sub classes
+ this._parser = null;
- var _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElement( 'canvas' ),
+};
- _precision = parameters.precision !== undefined ? parameters.precision : 'highp',
+Object.assign( THREE.BinaryTextureLoader.prototype, {
- _alpha = parameters.alpha !== undefined ? parameters.alpha : true,
- _premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true,
- _antialias = parameters.antialias !== undefined ? parameters.antialias : false,
- _stencil = parameters.stencil !== undefined ? parameters.stencil : true,
- _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false,
+ load: function ( url, onLoad, onProgress, onError ) {
- _clearColor = new THREE.Color( 0x000000 ),
- _clearAlpha = 0;
+ var scope = this;
- if ( parameters.clearColor !== undefined ) {
+ var texture = new THREE.DataTexture();
- console.warn( 'DEPRECATED: clearColor in WebGLRenderer constructor parameters is being removed. Use .setClearColor() instead.' );
- _clearColor.setHex( parameters.clearColor );
+ var loader = new THREE.XHRLoader( this.manager );
+ loader.setResponseType( 'arraybuffer' );
- }
+ loader.load( url, function ( buffer ) {
- if ( parameters.clearAlpha !== undefined ) {
+ var texData = scope._parser( buffer );
- console.warn( 'DEPRECATED: clearAlpha in WebGLRenderer constructor parameters is being removed. Use .setClearColor() instead.' );
- _clearAlpha = parameters.clearAlpha;
+ if ( ! texData ) return;
- }
+ if ( undefined !== texData.image ) {
- // public properties
+ texture.image = texData.image;
- this.domElement = _canvas;
- this.context = null;
- this.devicePixelRatio = parameters.devicePixelRatio !== undefined
- ? parameters.devicePixelRatio
- : window.devicePixelRatio !== undefined
- ? window.devicePixelRatio
- : 1;
+ } else if ( undefined !== texData.data ) {
- // clearing
+ texture.image.width = texData.width;
+ texture.image.height = texData.height;
+ texture.image.data = texData.data;
- this.autoClear = true;
- this.autoClearColor = true;
- this.autoClearDepth = true;
- this.autoClearStencil = true;
+ }
- // scene graph
+ texture.wrapS = undefined !== texData.wrapS ? texData.wrapS : THREE.ClampToEdgeWrapping;
+ texture.wrapT = undefined !== texData.wrapT ? texData.wrapT : THREE.ClampToEdgeWrapping;
- this.sortObjects = true;
- this.autoUpdateObjects = true;
+ texture.magFilter = undefined !== texData.magFilter ? texData.magFilter : THREE.LinearFilter;
+ texture.minFilter = undefined !== texData.minFilter ? texData.minFilter : THREE.LinearMipMapLinearFilter;
- // physically based shading
+ texture.anisotropy = undefined !== texData.anisotropy ? texData.anisotropy : 1;
- this.gammaInput = false;
- this.gammaOutput = false;
- this.physicallyBasedShading = false;
+ if ( undefined !== texData.format ) {
- // shadow map
+ texture.format = texData.format;
- this.shadowMapEnabled = false;
- this.shadowMapAutoUpdate = true;
- this.shadowMapType = THREE.PCFShadowMap;
- this.shadowMapCullFace = THREE.CullFaceFront;
- this.shadowMapDebug = false;
- this.shadowMapCascade = false;
+ }
+ if ( undefined !== texData.type ) {
- // morphs
+ texture.type = texData.type;
- this.maxMorphTargets = 8;
- this.maxMorphNormals = 4;
+ }
- // flags
+ if ( undefined !== texData.mipmaps ) {
- this.autoScaleCubemaps = true;
+ texture.mipmaps = texData.mipmaps;
- // custom render plugins
+ }
- this.renderPluginsPre = [];
- this.renderPluginsPost = [];
+ if ( 1 === texData.mipmapCount ) {
- // info
+ texture.minFilter = THREE.LinearFilter;
- this.info = {
+ }
- memory: {
+ texture.needsUpdate = true;
- programs: 0,
- geometries: 0,
- textures: 0
+ if ( onLoad ) onLoad( texture, texData );
- },
+ }, onProgress, onError );
- render: {
- calls: 0,
- vertices: 0,
- faces: 0,
- points: 0
+ return texture;
- }
+ }
- };
+} );
- // internal properties
+// File:src/loaders/CompressedTextureLoader.js
- var _this = this,
+/**
+ * @author mrdoob / http://mrdoob.com/
+ *
+ * Abstract Base class to block based textures loader (dds, pvr, ...)
+ */
- _programs = [],
- _programs_counter = 0,
+THREE.CompressedTextureLoader = function ( manager ) {
- // internal state cache
+ this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
- _currentProgram = null,
- _currentFramebuffer = null,
- _currentMaterialId = -1,
- _currentGeometryGroupHash = null,
- _currentCamera = null,
- _geometryGroupCounter = 0,
+ // override in sub classes
+ this._parser = null;
- _usedTextureUnits = 0,
+};
- // GL state cache
+Object.assign( THREE.CompressedTextureLoader.prototype, {
- _oldDoubleSided = -1,
- _oldFlipSided = -1,
+ load: function ( url, onLoad, onProgress, onError ) {
- _oldBlending = -1,
+ var scope = this;
- _oldBlendEquation = -1,
- _oldBlendSrc = -1,
- _oldBlendDst = -1,
+ var images = [];
- _oldDepthTest = -1,
- _oldDepthWrite = -1,
+ var texture = new THREE.CompressedTexture();
+ texture.image = images;
- _oldPolygonOffset = null,
- _oldPolygonOffsetFactor = null,
- _oldPolygonOffsetUnits = null,
+ var loader = new THREE.XHRLoader( this.manager );
+ loader.setPath( this.path );
+ loader.setResponseType( 'arraybuffer' );
- _oldLineWidth = null,
+ function loadTexture( i ) {
- _viewportX = 0,
- _viewportY = 0,
- _viewportWidth = 0,
- _viewportHeight = 0,
- _currentWidth = 0,
- _currentHeight = 0,
+ loader.load( url[ i ], function ( buffer ) {
- _enabledAttributes = {},
+ var texDatas = scope._parser( buffer, true );
- // frustum
+ images[ i ] = {
+ width: texDatas.width,
+ height: texDatas.height,
+ format: texDatas.format,
+ mipmaps: texDatas.mipmaps
+ };
- _frustum = new THREE.Frustum(),
+ loaded += 1;
- // camera matrices cache
+ if ( loaded === 6 ) {
- _projScreenMatrix = new THREE.Matrix4(),
- _projScreenMatrixPS = new THREE.Matrix4(),
+ if ( texDatas.mipmapCount === 1 )
+ texture.minFilter = THREE.LinearFilter;
- _vector3 = new THREE.Vector3(),
-
- // light arrays cache
-
- _direction = new THREE.Vector3(),
-
- _lightsNeedUpdate = true,
-
- _lights = {
-
- ambient: [ 0, 0, 0 ],
- directional: { length: 0, colors: new Array(), positions: new Array() },
- point: { length: 0, colors: new Array(), positions: new Array(), distances: new Array() },
- spot: { length: 0, colors: new Array(), positions: new Array(), distances: new Array(), directions: new Array(), anglesCos: new Array(), exponents: new Array() },
- hemi: { length: 0, skyColors: new Array(), groundColors: new Array(), positions: new Array() }
-
- };
-
- // initialize
-
- var _gl;
-
- var _glExtensionTextureFloat;
- var _glExtensionTextureFloatLinear;
- var _glExtensionStandardDerivatives;
- var _glExtensionTextureFilterAnisotropic;
- var _glExtensionCompressedTextureS3TC;
-
- initGL();
-
- setDefaultGLState();
-
- this.context = _gl;
-
- // GPU capabilities
-
- var _maxTextures = _gl.getParameter( _gl.MAX_TEXTURE_IMAGE_UNITS );
- var _maxVertexTextures = _gl.getParameter( _gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS );
- var _maxTextureSize = _gl.getParameter( _gl.MAX_TEXTURE_SIZE );
- var _maxCubemapSize = _gl.getParameter( _gl.MAX_CUBE_MAP_TEXTURE_SIZE );
-
- var _maxAnisotropy = _glExtensionTextureFilterAnisotropic ? _gl.getParameter( _glExtensionTextureFilterAnisotropic.MAX_TEXTURE_MAX_ANISOTROPY_EXT ) : 0;
-
- var _supportsVertexTextures = ( _maxVertexTextures > 0 );
- var _supportsBoneTextures = _supportsVertexTextures && _glExtensionTextureFloat;
-
- var _compressedTextureFormats = _glExtensionCompressedTextureS3TC ? _gl.getParameter( _gl.COMPRESSED_TEXTURE_FORMATS ) : [];
-
- //
+ texture.format = texDatas.format;
+ texture.needsUpdate = true;
- var _vertexShaderPrecisionHighpFloat = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.HIGH_FLOAT );
- var _vertexShaderPrecisionMediumpFloat = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.MEDIUM_FLOAT );
- var _vertexShaderPrecisionLowpFloat = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.LOW_FLOAT );
+ if ( onLoad ) onLoad( texture );
- var _fragmentShaderPrecisionHighpFloat = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.HIGH_FLOAT );
- var _fragmentShaderPrecisionMediumpFloat = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.MEDIUM_FLOAT );
- var _fragmentShaderPrecisionLowpFloat = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.LOW_FLOAT );
+ }
- var _vertexShaderPrecisionHighpInt = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.HIGH_INT );
- var _vertexShaderPrecisionMediumpInt = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.MEDIUM_INT );
- var _vertexShaderPrecisionLowpInt = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.LOW_INT );
+ }, onProgress, onError );
- var _fragmentShaderPrecisionHighpInt = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.HIGH_INT );
- var _fragmentShaderPrecisionMediumpInt = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.MEDIUM_INT );
- var _fragmentShaderPrecisionLowpInt = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.LOW_INT );
+ }
- // clamp precision to maximum available
+ if ( Array.isArray( url ) ) {
- var highpAvailable = _vertexShaderPrecisionHighpFloat.precision > 0 && _fragmentShaderPrecisionHighpFloat.precision > 0;
- var mediumpAvailable = _vertexShaderPrecisionMediumpFloat.precision > 0 && _fragmentShaderPrecisionMediumpFloat.precision > 0;
+ var loaded = 0;
- if ( _precision === "highp" && ! highpAvailable ) {
+ for ( var i = 0, il = url.length; i < il; ++ i ) {
- if ( mediumpAvailable ) {
+ loadTexture( i );
- _precision = "mediump";
- console.warn( "WebGLRenderer: highp not supported, using mediump" );
+ }
} else {
- _precision = "lowp";
- console.warn( "WebGLRenderer: highp and mediump not supported, using lowp" );
-
- }
-
- }
+ // compressed cubemap texture stored in a single DDS file
- if ( _precision === "mediump" && ! mediumpAvailable ) {
+ loader.load( url, function ( buffer ) {
- _precision = "lowp";
- console.warn( "WebGLRenderer: mediump not supported, using lowp" );
+ var texDatas = scope._parser( buffer, true );
- }
+ if ( texDatas.isCubemap ) {
- // API
+ var faces = texDatas.mipmaps.length / texDatas.mipmapCount;
- this.getContext = function () {
+ for ( var f = 0; f < faces; f ++ ) {
- return _gl;
+ images[ f ] = { mipmaps : [] };
- };
+ for ( var i = 0; i < texDatas.mipmapCount; i ++ ) {
- this.supportsVertexTextures = function () {
+ images[ f ].mipmaps.push( texDatas.mipmaps[ f * texDatas.mipmapCount + i ] );
+ images[ f ].format = texDatas.format;
+ images[ f ].width = texDatas.width;
+ images[ f ].height = texDatas.height;
- return _supportsVertexTextures;
+ }
- };
+ }
- this.supportsFloatTextures = function () {
+ } else {
- return _glExtensionTextureFloat;
+ texture.image.width = texDatas.width;
+ texture.image.height = texDatas.height;
+ texture.mipmaps = texDatas.mipmaps;
- };
+ }
- this.supportsStandardDerivatives = function () {
+ if ( texDatas.mipmapCount === 1 ) {
- return _glExtensionStandardDerivatives;
+ texture.minFilter = THREE.LinearFilter;
- };
+ }
- this.supportsCompressedTextureS3TC = function () {
+ texture.format = texDatas.format;
+ texture.needsUpdate = true;
- return _glExtensionCompressedTextureS3TC;
+ if ( onLoad ) onLoad( texture );
- };
+ }, onProgress, onError );
- this.getMaxAnisotropy = function () {
+ }
- return _maxAnisotropy;
+ return texture;
- };
+ },
- this.getPrecision = function () {
+ setPath: function ( value ) {
- return _precision;
+ this.path = value;
+ return this;
- };
+ }
- this.setSize = function ( width, height, updateStyle ) {
+} );
- _canvas.width = width * this.devicePixelRatio;
- _canvas.height = height * this.devicePixelRatio;
+// File:src/materials/Material.js
- if ( this.devicePixelRatio !== 1 && updateStyle !== false ) {
+/**
+ * @author mrdoob / http://mrdoob.com/
+ * @author alteredq / http://alteredqualia.com/
+ */
- _canvas.style.width = width + 'px';
- _canvas.style.height = height + 'px';
+THREE.Material = function () {
- }
+ Object.defineProperty( this, 'id', { value: THREE.MaterialIdCount ++ } );
- this.setViewport( 0, 0, _canvas.width, _canvas.height );
+ this.uuid = THREE.Math.generateUUID();
- };
+ this.name = '';
+ this.type = 'Material';
- this.setViewport = function ( x, y, width, height ) {
+ this.fog = true;
+ this.lights = true;
- _viewportX = x !== undefined ? x : 0;
- _viewportY = y !== undefined ? y : 0;
+ this.blending = THREE.NormalBlending;
+ this.side = THREE.FrontSide;
+ this.shading = THREE.SmoothShading; // THREE.FlatShading, THREE.SmoothShading
+ this.vertexColors = THREE.NoColors; // THREE.NoColors, THREE.VertexColors, THREE.FaceColors
- _viewportWidth = width !== undefined ? width : _canvas.width;
- _viewportHeight = height !== undefined ? height : _canvas.height;
+ this.opacity = 1;
+ this.transparent = false;
- _gl.viewport( _viewportX, _viewportY, _viewportWidth, _viewportHeight );
+ this.blendSrc = THREE.SrcAlphaFactor;
+ this.blendDst = THREE.OneMinusSrcAlphaFactor;
+ this.blendEquation = THREE.AddEquation;
+ this.blendSrcAlpha = null;
+ this.blendDstAlpha = null;
+ this.blendEquationAlpha = null;
- };
+ this.depthFunc = THREE.LessEqualDepth;
+ this.depthTest = true;
+ this.depthWrite = true;
- this.setScissor = function ( x, y, width, height ) {
+ this.clippingPlanes = null;
+ this.clipShadows = false;
- _gl.scissor( x, y, width, height );
+ this.colorWrite = true;
- };
+ this.precision = null; // override the renderer's default precision for this material
- this.enableScissorTest = function ( enable ) {
+ this.polygonOffset = false;
+ this.polygonOffsetFactor = 0;
+ this.polygonOffsetUnits = 0;
- enable ? _gl.enable( _gl.SCISSOR_TEST ) : _gl.disable( _gl.SCISSOR_TEST );
+ this.alphaTest = 0;
+ this.premultipliedAlpha = false;
- };
+ this.overdraw = 0; // Overdrawn pixels (typically between 0 and 1) for fixing antialiasing gaps in CanvasRenderer
- // Clearing
+ this.visible = true;
- this.setClearColor = function ( color, alpha ) {
+ this._needsUpdate = true;
- _clearColor.set( color );
- _clearAlpha = alpha !== undefined ? alpha : 1;
+};
- _gl.clearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
+THREE.Material.prototype = {
- };
+ constructor: THREE.Material,
- this.setClearColorHex = function ( hex, alpha ) {
+ get needsUpdate() {
- console.warn( 'DEPRECATED: .setClearColorHex() is being removed. Use .setClearColor() instead.' );
- this.setClearColor( hex, alpha );
+ return this._needsUpdate;
- };
+ },
- this.getClearColor = function () {
+ set needsUpdate( value ) {
- return _clearColor;
+ if ( value === true ) this.update();
+ this._needsUpdate = value;
- };
+ },
- this.getClearAlpha = function () {
+ setValues: function ( values ) {
- return _clearAlpha;
+ if ( values === undefined ) return;
- };
+ for ( var key in values ) {
- this.clear = function ( color, depth, stencil ) {
+ var newValue = values[ key ];
- var bits = 0;
+ if ( newValue === undefined ) {
- if ( color === undefined || color ) bits |= _gl.COLOR_BUFFER_BIT;
- if ( depth === undefined || depth ) bits |= _gl.DEPTH_BUFFER_BIT;
- if ( stencil === undefined || stencil ) bits |= _gl.STENCIL_BUFFER_BIT;
+ console.warn( "THREE.Material: '" + key + "' parameter is undefined." );
+ continue;
- _gl.clear( bits );
+ }
- };
+ var currentValue = this[ key ];
- this.clearTarget = function ( renderTarget, color, depth, stencil ) {
+ if ( currentValue === undefined ) {
- this.setRenderTarget( renderTarget );
- this.clear( color, depth, stencil );
+ console.warn( "THREE." + this.type + ": '" + key + "' is not a property of this material." );
+ continue;
- };
+ }
- // Plugins
+ if ( currentValue instanceof THREE.Color ) {
- this.addPostPlugin = function ( plugin ) {
+ currentValue.set( newValue );
- plugin.init( this );
- this.renderPluginsPost.push( plugin );
+ } else if ( currentValue instanceof THREE.Vector3 && newValue instanceof THREE.Vector3 ) {
- };
+ currentValue.copy( newValue );
- this.addPrePlugin = function ( plugin ) {
+ } else if ( key === 'overdraw' ) {
- plugin.init( this );
- this.renderPluginsPre.push( plugin );
+ // ensure overdraw is backwards-compatible with legacy boolean type
+ this[ key ] = Number( newValue );
- };
+ } else {
- // Rendering
+ this[ key ] = newValue;
- this.updateShadowMap = function ( scene, camera ) {
+ }
- _currentProgram = null;
- _oldBlending = -1;
- _oldDepthTest = -1;
- _oldDepthWrite = -1;
- _currentGeometryGroupHash = -1;
- _currentMaterialId = -1;
- _lightsNeedUpdate = true;
- _oldDoubleSided = -1;
- _oldFlipSided = -1;
+ }
- this.shadowMapPlugin.update( scene, camera );
+ },
- };
+ toJSON: function ( meta ) {
- // Internal functions
+ var isRoot = meta === undefined;
- // Buffer allocation
+ if ( isRoot ) {
- function createParticleBuffers ( geometry ) {
+ meta = {
+ textures: {},
+ images: {}
+ };
- geometry.__webglVertexBuffer = _gl.createBuffer();
- geometry.__webglColorBuffer = _gl.createBuffer();
+ }
- _this.info.memory.geometries ++;
+ var data = {
+ metadata: {
+ version: 4.4,
+ type: 'Material',
+ generator: 'Material.toJSON'
+ }
+ };
- };
+ // standard Material serialization
+ data.uuid = this.uuid;
+ data.type = this.type;
- function createLineBuffers ( geometry ) {
+ if ( this.name !== '' ) data.name = this.name;
- geometry.__webglVertexBuffer = _gl.createBuffer();
- geometry.__webglColorBuffer = _gl.createBuffer();
- geometry.__webglLineDistanceBuffer = _gl.createBuffer();
+ if ( this.color instanceof THREE.Color ) data.color = this.color.getHex();
- _this.info.memory.geometries ++;
+ if ( this.roughness !== undefined ) data.roughness = this.roughness;
+ if ( this.metalness !== undefined ) data.metalness = this.metalness;
- };
+ if ( this.emissive instanceof THREE.Color ) data.emissive = this.emissive.getHex();
+ if ( this.specular instanceof THREE.Color ) data.specular = this.specular.getHex();
+ if ( this.shininess !== undefined ) data.shininess = this.shininess;
- function createRibbonBuffers ( geometry ) {
+ if ( this.map instanceof THREE.Texture ) data.map = this.map.toJSON( meta ).uuid;
+ if ( this.alphaMap instanceof THREE.Texture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid;
+ if ( this.lightMap instanceof THREE.Texture ) data.lightMap = this.lightMap.toJSON( meta ).uuid;
+ if ( this.bumpMap instanceof THREE.Texture ) {
- geometry.__webglVertexBuffer = _gl.createBuffer();
- geometry.__webglColorBuffer = _gl.createBuffer();
- geometry.__webglNormalBuffer = _gl.createBuffer();
+ data.bumpMap = this.bumpMap.toJSON( meta ).uuid;
+ data.bumpScale = this.bumpScale;
- _this.info.memory.geometries ++;
+ }
+ if ( this.normalMap instanceof THREE.Texture ) {
- };
+ data.normalMap = this.normalMap.toJSON( meta ).uuid;
+ data.normalScale = this.normalScale.toArray();
- function createMeshBuffers ( geometryGroup ) {
+ }
+ if ( this.displacementMap instanceof THREE.Texture ) {
- geometryGroup.__webglVertexBuffer = _gl.createBuffer();
- geometryGroup.__webglNormalBuffer = _gl.createBuffer();
- geometryGroup.__webglTangentBuffer = _gl.createBuffer();
- geometryGroup.__webglColorBuffer = _gl.createBuffer();
- geometryGroup.__webglUVBuffer = _gl.createBuffer();
- geometryGroup.__webglUV2Buffer = _gl.createBuffer();
+ data.displacementMap = this.displacementMap.toJSON( meta ).uuid;
+ data.displacementScale = this.displacementScale;
+ data.displacementBias = this.displacementBias;
- geometryGroup.__webglSkinIndicesBuffer = _gl.createBuffer();
- geometryGroup.__webglSkinWeightsBuffer = _gl.createBuffer();
+ }
+ if ( this.roughnessMap instanceof THREE.Texture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid;
+ if ( this.metalnessMap instanceof THREE.Texture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid;
- geometryGroup.__webglFaceBuffer = _gl.createBuffer();
- geometryGroup.__webglLineBuffer = _gl.createBuffer();
+ if ( this.emissiveMap instanceof THREE.Texture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid;
+ if ( this.specularMap instanceof THREE.Texture ) data.specularMap = this.specularMap.toJSON( meta ).uuid;
- var m, ml;
+ if ( this.envMap instanceof THREE.Texture ) {
- if ( geometryGroup.numMorphTargets ) {
+ data.envMap = this.envMap.toJSON( meta ).uuid;
+ data.reflectivity = this.reflectivity; // Scale behind envMap
- geometryGroup.__webglMorphTargetsBuffers = [];
+ }
- for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
+ if ( this.size !== undefined ) data.size = this.size;
+ if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation;
- geometryGroup.__webglMorphTargetsBuffers.push( _gl.createBuffer() );
+ if ( this.blending !== THREE.NormalBlending ) data.blending = this.blending;
+ if ( this.shading !== THREE.SmoothShading ) data.shading = this.shading;
+ if ( this.side !== THREE.FrontSide ) data.side = this.side;
+ if ( this.vertexColors !== THREE.NoColors ) data.vertexColors = this.vertexColors;
- }
+ if ( this.opacity < 1 ) data.opacity = this.opacity;
+ if ( this.transparent === true ) data.transparent = this.transparent;
+ if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest;
+ if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha;
+ if ( this.wireframe === true ) data.wireframe = this.wireframe;
+ if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth;
- }
+ // TODO: Copied from Object3D.toJSON
- if ( geometryGroup.numMorphNormals ) {
+ function extractFromCache ( cache ) {
- geometryGroup.__webglMorphNormalsBuffers = [];
+ var values = [];
- for ( m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) {
+ for ( var key in cache ) {
- geometryGroup.__webglMorphNormalsBuffers.push( _gl.createBuffer() );
+ var data = cache[ key ];
+ delete data.metadata;
+ values.push( data );
}
+ return values;
+
}
- _this.info.memory.geometries ++;
+ if ( isRoot ) {
- };
+ var textures = extractFromCache( meta.textures );
+ var images = extractFromCache( meta.images );
- // Events
+ if ( textures.length > 0 ) data.textures = textures;
+ if ( images.length > 0 ) data.images = images;
- var onGeometryDispose = function ( event ) {
+ }
- var geometry = event.target;
+ return data;
- geometry.removeEventListener( 'dispose', onGeometryDispose );
+ },
- deallocateGeometry( geometry );
+ clone: function () {
- };
+ return new this.constructor().copy( this );
- var onTextureDispose = function ( event ) {
+ },
- var texture = event.target;
+ copy: function ( source ) {
- texture.removeEventListener( 'dispose', onTextureDispose );
+ this.name = source.name;
- deallocateTexture( texture );
+ this.fog = source.fog;
+ this.lights = source.lights;
- _this.info.memory.textures --;
+ this.blending = source.blending;
+ this.side = source.side;
+ this.shading = source.shading;
+ this.vertexColors = source.vertexColors;
+ this.opacity = source.opacity;
+ this.transparent = source.transparent;
- };
+ this.blendSrc = source.blendSrc;
+ this.blendDst = source.blendDst;
+ this.blendEquation = source.blendEquation;
+ this.blendSrcAlpha = source.blendSrcAlpha;
+ this.blendDstAlpha = source.blendDstAlpha;
+ this.blendEquationAlpha = source.blendEquationAlpha;
- var onRenderTargetDispose = function ( event ) {
+ this.depthFunc = source.depthFunc;
+ this.depthTest = source.depthTest;
+ this.depthWrite = source.depthWrite;
- var renderTarget = event.target;
+ this.colorWrite = source.colorWrite;
- renderTarget.removeEventListener( 'dispose', onRenderTargetDispose );
+ this.precision = source.precision;
- deallocateRenderTarget( renderTarget );
+ this.polygonOffset = source.polygonOffset;
+ this.polygonOffsetFactor = source.polygonOffsetFactor;
+ this.polygonOffsetUnits = source.polygonOffsetUnits;
- _this.info.memory.textures --;
+ this.alphaTest = source.alphaTest;
- };
+ this.premultipliedAlpha = source.premultipliedAlpha;
- var onMaterialDispose = function ( event ) {
+ this.overdraw = source.overdraw;
- var material = event.target;
+ this.visible = source.visible;
+ this.clipShadows = source.clipShadows;
- material.removeEventListener( 'dispose', onMaterialDispose );
+ var srcPlanes = source.clippingPlanes,
+ dstPlanes = null;
- deallocateMaterial( material );
+ if ( srcPlanes !== null ) {
- };
+ var n = srcPlanes.length;
+ dstPlanes = new Array( n );
- // Buffer deallocation
+ for ( var i = 0; i !== n; ++ i )
+ dstPlanes[ i ] = srcPlanes[ i ].clone();
- var deleteBuffers = function ( geometry ) {
+ }
- if ( geometry.__webglVertexBuffer !== undefined ) _gl.deleteBuffer( geometry.__webglVertexBuffer );
- if ( geometry.__webglNormalBuffer !== undefined ) _gl.deleteBuffer( geometry.__webglNormalBuffer );
- if ( geometry.__webglTangentBuffer !== undefined ) _gl.deleteBuffer( geometry.__webglTangentBuffer );
- if ( geometry.__webglColorBuffer !== undefined ) _gl.deleteBuffer( geometry.__webglColorBuffer );
- if ( geometry.__webglUVBuffer !== undefined ) _gl.deleteBuffer( geometry.__webglUVBuffer );
- if ( geometry.__webglUV2Buffer !== undefined ) _gl.deleteBuffer( geometry.__webglUV2Buffer );
+ this.clippingPlanes = dstPlanes;
- if ( geometry.__webglSkinIndicesBuffer !== undefined ) _gl.deleteBuffer( geometry.__webglSkinIndicesBuffer );
- if ( geometry.__webglSkinWeightsBuffer !== undefined ) _gl.deleteBuffer( geometry.__webglSkinWeightsBuffer );
+ return this;
- if ( geometry.__webglFaceBuffer !== undefined ) _gl.deleteBuffer( geometry.__webglFaceBuffer );
- if ( geometry.__webglLineBuffer !== undefined ) _gl.deleteBuffer( geometry.__webglLineBuffer );
+ },
- if ( geometry.__webglLineDistanceBuffer !== undefined ) _gl.deleteBuffer( geometry.__webglLineDistanceBuffer );
- // custom attributes
+ update: function () {
- if ( geometry.__webglCustomAttributesList !== undefined ) {
+ this.dispatchEvent( { type: 'update' } );
- for ( var id in geometry.__webglCustomAttributesList ) {
+ },
- _gl.deleteBuffer( geometry.__webglCustomAttributesList[ id ].buffer );
+ dispose: function () {
- }
+ this.dispatchEvent( { type: 'dispose' } );
- }
+ }
- _this.info.memory.geometries --;
+};
- };
+Object.assign( THREE.Material.prototype, THREE.EventDispatcher.prototype );
- var deallocateGeometry = function ( geometry ) {
+THREE.MaterialIdCount = 0;
- geometry.__webglInit = undefined;
+// File:src/materials/LineBasicMaterial.js
- if ( geometry instanceof THREE.BufferGeometry ) {
+/**
+ * @author mrdoob / http://mrdoob.com/
+ * @author alteredq / http://alteredqualia.com/
+ *
+ * parameters = {
+ * color: ,
+ * opacity: ,
+ *
+ * linewidth: ,
+ * linecap: "round",
+ * linejoin: "round"
+ * }
+ */
- var attributes = geometry.attributes;
+THREE.LineBasicMaterial = function ( parameters ) {
- for ( var key in attributes ) {
+ THREE.Material.call( this );
- if ( attributes[ key ].buffer !== undefined ) {
+ this.type = 'LineBasicMaterial';
- _gl.deleteBuffer( attributes[ key ].buffer );
-
- }
+ this.color = new THREE.Color( 0xffffff );
- }
+ this.linewidth = 1;
+ this.linecap = 'round';
+ this.linejoin = 'round';
- _this.info.memory.geometries --;
+ this.lights = false;
- } else {
+ this.setValues( parameters );
- if ( geometry.geometryGroups !== undefined ) {
+};
- for ( var g in geometry.geometryGroups ) {
+THREE.LineBasicMaterial.prototype = Object.create( THREE.Material.prototype );
+THREE.LineBasicMaterial.prototype.constructor = THREE.LineBasicMaterial;
- var geometryGroup = geometry.geometryGroups[ g ];
+THREE.LineBasicMaterial.prototype.copy = function ( source ) {
- if ( geometryGroup.numMorphTargets !== undefined ) {
+ THREE.Material.prototype.copy.call( this, source );
- for ( var m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
+ this.color.copy( source.color );
- _gl.deleteBuffer( geometryGroup.__webglMorphTargetsBuffers[ m ] );
+ this.linewidth = source.linewidth;
+ this.linecap = source.linecap;
+ this.linejoin = source.linejoin;
- }
+ return this;
- }
+};
- if ( geometryGroup.numMorphNormals !== undefined ) {
+// File:src/materials/LineDashedMaterial.js
- for ( var m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) {
+/**
+ * @author alteredq / http://alteredqualia.com/
+ *
+ * parameters = {
+ * color: ,
+ * opacity: ,
+ *
+ * linewidth: ,
+ *
+ * scale: ,
+ * dashSize: ,
+ * gapSize:
+ * }
+ */
- _gl.deleteBuffer( geometryGroup.__webglMorphNormalsBuffers[ m ] );
+THREE.LineDashedMaterial = function ( parameters ) {
- }
+ THREE.Material.call( this );
- }
+ this.type = 'LineDashedMaterial';
- deleteBuffers( geometryGroup );
+ this.color = new THREE.Color( 0xffffff );
- }
+ this.linewidth = 1;
- } else {
+ this.scale = 1;
+ this.dashSize = 3;
+ this.gapSize = 1;
- deleteBuffers( geometry );
+ this.lights = false;
- }
+ this.setValues( parameters );
- }
+};
- };
+THREE.LineDashedMaterial.prototype = Object.create( THREE.Material.prototype );
+THREE.LineDashedMaterial.prototype.constructor = THREE.LineDashedMaterial;
- var deallocateTexture = function ( texture ) {
+THREE.LineDashedMaterial.prototype.copy = function ( source ) {
- if ( texture.image && texture.image.__webglTextureCube ) {
+ THREE.Material.prototype.copy.call( this, source );
- // cube texture
+ this.color.copy( source.color );
- _gl.deleteTexture( texture.image.__webglTextureCube );
+ this.linewidth = source.linewidth;
- } else {
+ this.scale = source.scale;
+ this.dashSize = source.dashSize;
+ this.gapSize = source.gapSize;
- // 2D texture
+ return this;
- if ( ! texture.__webglInit ) return;
+};
- texture.__webglInit = false;
- _gl.deleteTexture( texture.__webglTexture );
+// File:src/materials/MeshBasicMaterial.js
- }
+/**
+ * @author mrdoob / http://mrdoob.com/
+ * @author alteredq / http://alteredqualia.com/
+ *
+ * parameters = {
+ * color: ,
+ * opacity: ,
+ * map: new THREE.Texture( ),
+ *
+ * aoMap: new THREE.Texture( ),
+ * aoMapIntensity:
+ *
+ * specularMap: new THREE.Texture( ),
+ *
+ * alphaMap: new THREE.Texture( ),
+ *
+ * envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ),
+ * combine: THREE.Multiply,
+ * reflectivity: ,
+ * refractionRatio: ,
+ *
+ * shading: THREE.SmoothShading,
+ * depthTest: ,
+ * depthWrite: ,
+ *
+ * wireframe: ,
+ * wireframeLinewidth: ,
+ *
+ * skinning: ,
+ * morphTargets:
+ * }
+ */
- };
+THREE.MeshBasicMaterial = function ( parameters ) {
- var deallocateRenderTarget = function ( renderTarget ) {
+ THREE.Material.call( this );
- if ( !renderTarget || ! renderTarget.__webglTexture ) return;
+ this.type = 'MeshBasicMaterial';
- _gl.deleteTexture( renderTarget.__webglTexture );
+ this.color = new THREE.Color( 0xffffff ); // emissive
- if ( renderTarget instanceof THREE.WebGLRenderTargetCube ) {
+ this.map = null;
- for ( var i = 0; i < 6; i ++ ) {
+ this.aoMap = null;
+ this.aoMapIntensity = 1.0;
- _gl.deleteFramebuffer( renderTarget.__webglFramebuffer[ i ] );
- _gl.deleteRenderbuffer( renderTarget.__webglRenderbuffer[ i ] );
+ this.specularMap = null;
- }
+ this.alphaMap = null;
- } else {
+ this.envMap = null;
+ this.combine = THREE.MultiplyOperation;
+ this.reflectivity = 1;
+ this.refractionRatio = 0.98;
- _gl.deleteFramebuffer( renderTarget.__webglFramebuffer );
- _gl.deleteRenderbuffer( renderTarget.__webglRenderbuffer );
+ this.wireframe = false;
+ this.wireframeLinewidth = 1;
+ this.wireframeLinecap = 'round';
+ this.wireframeLinejoin = 'round';
- }
+ this.skinning = false;
+ this.morphTargets = false;
- };
+ this.lights = false;
- var deallocateMaterial = function ( material ) {
+ this.setValues( parameters );
- var program = material.program;
+};
- if ( program === undefined ) return;
+THREE.MeshBasicMaterial.prototype = Object.create( THREE.Material.prototype );
+THREE.MeshBasicMaterial.prototype.constructor = THREE.MeshBasicMaterial;
- material.program = undefined;
+THREE.MeshBasicMaterial.prototype.copy = function ( source ) {
- // only deallocate GL program if this was the last use of shared program
- // assumed there is only single copy of any program in the _programs list
- // (that's how it's constructed)
+ THREE.Material.prototype.copy.call( this, source );
- var i, il, programInfo;
- var deleteProgram = false;
+ this.color.copy( source.color );
- for ( i = 0, il = _programs.length; i < il; i ++ ) {
+ this.map = source.map;
- programInfo = _programs[ i ];
+ this.aoMap = source.aoMap;
+ this.aoMapIntensity = source.aoMapIntensity;
- if ( programInfo.program === program ) {
+ this.specularMap = source.specularMap;
- programInfo.usedTimes --;
+ this.alphaMap = source.alphaMap;
- if ( programInfo.usedTimes === 0 ) {
+ this.envMap = source.envMap;
+ this.combine = source.combine;
+ this.reflectivity = source.reflectivity;
+ this.refractionRatio = source.refractionRatio;
- deleteProgram = true;
+ this.wireframe = source.wireframe;
+ this.wireframeLinewidth = source.wireframeLinewidth;
+ this.wireframeLinecap = source.wireframeLinecap;
+ this.wireframeLinejoin = source.wireframeLinejoin;
- }
+ this.skinning = source.skinning;
+ this.morphTargets = source.morphTargets;
- break;
+ return this;
- }
+};
- }
+// File:src/materials/MeshDepthMaterial.js
- if ( deleteProgram === true ) {
+/**
+ * @author mrdoob / http://mrdoob.com/
+ * @author alteredq / http://alteredqualia.com/
+ * @author bhouston / https://clara.io
+ * @author WestLangley / http://github.com/WestLangley
+ *
+ * parameters = {
+ *
+ * opacity: ,
+ *
+ * map: new THREE.Texture( ),
+ *
+ * alphaMap: new THREE.Texture( ),
+ *
+ * displacementMap: new THREE.Texture( ),
+ * displacementScale: ,
+ * displacementBias: ,
+ *
+ * wireframe: ,
+ * wireframeLinewidth:
+ * }
+ */
- // avoid using array.splice, this is costlier than creating new array from scratch
+THREE.MeshDepthMaterial = function ( parameters ) {
- var newPrograms = [];
+ THREE.Material.call( this );
- for ( i = 0, il = _programs.length; i < il; i ++ ) {
+ this.type = 'MeshDepthMaterial';
- programInfo = _programs[ i ];
+ this.depthPacking = THREE.BasicDepthPacking;
- if ( programInfo.program !== program ) {
+ this.skinning = false;
+ this.morphTargets = false;
- newPrograms.push( programInfo );
+ this.map = null;
- }
+ this.alphaMap = null;
- }
+ this.displacementMap = null;
+ this.displacementScale = 1;
+ this.displacementBias = 0;
- _programs = newPrograms;
+ this.wireframe = false;
+ this.wireframeLinewidth = 1;
- _gl.deleteProgram( program );
+ this.fog = false;
+ this.lights = false;
- _this.info.memory.programs --;
+ this.setValues( parameters );
- }
+};
- };
+THREE.MeshDepthMaterial.prototype = Object.create( THREE.Material.prototype );
+THREE.MeshDepthMaterial.prototype.constructor = THREE.MeshDepthMaterial;
- // Buffer initialization
+THREE.MeshDepthMaterial.prototype.copy = function ( source ) {
- function initCustomAttributes ( geometry, object ) {
+ THREE.Material.prototype.copy.call( this, source );
- var nvertices = geometry.vertices.length;
+ this.depthPacking = source.depthPacking;
- var material = object.material;
+ this.skinning = source.skinning;
+ this.morphTargets = source.morphTargets;
- if ( material.attributes ) {
+ this.map = source.map;
- if ( geometry.__webglCustomAttributesList === undefined ) {
+ this.alphaMap = source.alphaMap;
- geometry.__webglCustomAttributesList = [];
+ this.displacementMap = source.displacementMap;
+ this.displacementScale = source.displacementScale;
+ this.displacementBias = source.displacementBias;
- }
+ this.wireframe = source.wireframe;
+ this.wireframeLinewidth = source.wireframeLinewidth;
- for ( var a in material.attributes ) {
+ return this;
- var attribute = material.attributes[ a ];
+};
- if ( !attribute.__webglInitialized || attribute.createUniqueBuffers ) {
+// File:src/materials/MeshLambertMaterial.js
- attribute.__webglInitialized = true;
+/**
+ * @author mrdoob / http://mrdoob.com/
+ * @author alteredq / http://alteredqualia.com/
+ *
+ * parameters = {
+ * color: ,
+ * opacity: ,
+ *
+ * map: new THREE.Texture( ),
+ *
+ * lightMap: new THREE.Texture( ),
+ * lightMapIntensity:
+ *
+ * aoMap: new THREE.Texture( ),
+ * aoMapIntensity:
+ *
+ * emissive: ,
+ * emissiveIntensity:
+ * emissiveMap: new THREE.Texture( ),
+ *
+ * specularMap: new THREE.Texture( ),
+ *
+ * alphaMap: new THREE.Texture( ),
+ *
+ * envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ),
+ * combine: THREE.Multiply,
+ * reflectivity: ,
+ * refractionRatio: ,
+ *
+ * wireframe: ,
+ * wireframeLinewidth: ,
+ *
+ * skinning: ,
+ * morphTargets: ,
+ * morphNormals:
+ * }
+ */
- var size = 1; // "f" and "i"
+THREE.MeshLambertMaterial = function ( parameters ) {
- if ( attribute.type === "v2" ) size = 2;
- else if ( attribute.type === "v3" ) size = 3;
- else if ( attribute.type === "v4" ) size = 4;
- else if ( attribute.type === "c" ) size = 3;
+ THREE.Material.call( this );
- attribute.size = size;
+ this.type = 'MeshLambertMaterial';
- attribute.array = new Float32Array( nvertices * size );
+ this.color = new THREE.Color( 0xffffff ); // diffuse
- attribute.buffer = _gl.createBuffer();
- attribute.buffer.belongsToAttribute = a;
+ this.map = null;
- attribute.needsUpdate = true;
+ this.lightMap = null;
+ this.lightMapIntensity = 1.0;
- }
+ this.aoMap = null;
+ this.aoMapIntensity = 1.0;
- geometry.__webglCustomAttributesList.push( attribute );
+ this.emissive = new THREE.Color( 0x000000 );
+ this.emissiveIntensity = 1.0;
+ this.emissiveMap = null;
- }
+ this.specularMap = null;
- }
+ this.alphaMap = null;
- };
+ this.envMap = null;
+ this.combine = THREE.MultiplyOperation;
+ this.reflectivity = 1;
+ this.refractionRatio = 0.98;
- function initParticleBuffers ( geometry, object ) {
+ this.wireframe = false;
+ this.wireframeLinewidth = 1;
+ this.wireframeLinecap = 'round';
+ this.wireframeLinejoin = 'round';
- var nvertices = geometry.vertices.length;
+ this.skinning = false;
+ this.morphTargets = false;
+ this.morphNormals = false;
- geometry.__vertexArray = new Float32Array( nvertices * 3 );
- geometry.__colorArray = new Float32Array( nvertices * 3 );
+ this.setValues( parameters );
- geometry.__sortArray = [];
+};
- geometry.__webglParticleCount = nvertices;
+THREE.MeshLambertMaterial.prototype = Object.create( THREE.Material.prototype );
+THREE.MeshLambertMaterial.prototype.constructor = THREE.MeshLambertMaterial;
- initCustomAttributes ( geometry, object );
+THREE.MeshLambertMaterial.prototype.copy = function ( source ) {
- };
+ THREE.Material.prototype.copy.call( this, source );
- function initLineBuffers ( geometry, object ) {
+ this.color.copy( source.color );
- var nvertices = geometry.vertices.length;
+ this.map = source.map;
- geometry.__vertexArray = new Float32Array( nvertices * 3 );
- geometry.__colorArray = new Float32Array( nvertices * 3 );
- geometry.__lineDistanceArray = new Float32Array( nvertices * 1 );
+ this.lightMap = source.lightMap;
+ this.lightMapIntensity = source.lightMapIntensity;
- geometry.__webglLineCount = nvertices;
+ this.aoMap = source.aoMap;
+ this.aoMapIntensity = source.aoMapIntensity;
- initCustomAttributes ( geometry, object );
+ this.emissive.copy( source.emissive );
+ this.emissiveMap = source.emissiveMap;
+ this.emissiveIntensity = source.emissiveIntensity;
- };
+ this.specularMap = source.specularMap;
- function initRibbonBuffers ( geometry, object ) {
+ this.alphaMap = source.alphaMap;
- var nvertices = geometry.vertices.length;
+ this.envMap = source.envMap;
+ this.combine = source.combine;
+ this.reflectivity = source.reflectivity;
+ this.refractionRatio = source.refractionRatio;
- geometry.__vertexArray = new Float32Array( nvertices * 3 );
- geometry.__colorArray = new Float32Array( nvertices * 3 );
- geometry.__normalArray = new Float32Array( nvertices * 3 );
+ this.wireframe = source.wireframe;
+ this.wireframeLinewidth = source.wireframeLinewidth;
+ this.wireframeLinecap = source.wireframeLinecap;
+ this.wireframeLinejoin = source.wireframeLinejoin;
- geometry.__webglVertexCount = nvertices;
+ this.skinning = source.skinning;
+ this.morphTargets = source.morphTargets;
+ this.morphNormals = source.morphNormals;
- initCustomAttributes ( geometry, object );
+ return this;
- };
+};
- function initMeshBuffers ( geometryGroup, object ) {
+// File:src/materials/MeshNormalMaterial.js
- var geometry = object.geometry,
- faces3 = geometryGroup.faces3,
+/**
+ * @author mrdoob / http://mrdoob.com/
+ *
+ * parameters = {
+ * opacity: ,
+ *
+ * wireframe: ,
+ * wireframeLinewidth:
+ * }
+ */
- nvertices = faces3.length * 3,
- ntris = faces3.length * 1,
- nlines = faces3.length * 3,
+THREE.MeshNormalMaterial = function ( parameters ) {
- material = getBufferMaterial( object, geometryGroup ),
+ THREE.Material.call( this, parameters );
- uvType = bufferGuessUVType( material ),
- normalType = bufferGuessNormalType( material ),
- vertexColorType = bufferGuessVertexColorType( material );
+ this.type = 'MeshNormalMaterial';
- // console.log( "uvType", uvType, "normalType", normalType, "vertexColorType", vertexColorType, object, geometryGroup, material );
+ this.wireframe = false;
+ this.wireframeLinewidth = 1;
- geometryGroup.__vertexArray = new Float32Array( nvertices * 3 );
+ this.fog = false;
+ this.lights = false;
+ this.morphTargets = false;
- if ( normalType ) {
+ this.setValues( parameters );
- geometryGroup.__normalArray = new Float32Array( nvertices * 3 );
+};
- }
+THREE.MeshNormalMaterial.prototype = Object.create( THREE.Material.prototype );
+THREE.MeshNormalMaterial.prototype.constructor = THREE.MeshNormalMaterial;
- if ( geometry.hasTangents ) {
+THREE.MeshNormalMaterial.prototype.copy = function ( source ) {
- geometryGroup.__tangentArray = new Float32Array( nvertices * 4 );
+ THREE.Material.prototype.copy.call( this, source );
- }
+ this.wireframe = source.wireframe;
+ this.wireframeLinewidth = source.wireframeLinewidth;
- if ( vertexColorType ) {
+ return this;
- geometryGroup.__colorArray = new Float32Array( nvertices * 3 );
+};
- }
+// File:src/materials/MeshPhongMaterial.js
- if ( uvType ) {
+/**
+ * @author mrdoob / http://mrdoob.com/
+ * @author alteredq / http://alteredqualia.com/
+ *
+ * parameters = {
+ * color: ,
+ * specular: ,
+ * shininess: ,
+ * opacity: ,
+ *
+ * map: new THREE.Texture( ),
+ *
+ * lightMap: new THREE.Texture( ),
+ * lightMapIntensity:
+ *
+ * aoMap: new THREE.Texture( ),
+ * aoMapIntensity:
+ *
+ * emissive: ,
+ * emissiveIntensity:
+ * emissiveMap: new THREE.Texture( ),
+ *
+ * bumpMap: new THREE.Texture( ),
+ * bumpScale: ,
+ *
+ * normalMap: new THREE.Texture( ),
+ * normalScale: ,
+ *
+ * displacementMap: new THREE.Texture( ),
+ * displacementScale: ,
+ * displacementBias: ,
+ *
+ * specularMap: new THREE.Texture( ),
+ *
+ * alphaMap: new THREE.Texture( ),
+ *
+ * envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ),
+ * combine: THREE.Multiply,
+ * reflectivity: ,
+ * refractionRatio: ,
+ *
+ * wireframe: ,
+ * wireframeLinewidth: ,
+ *
+ * skinning: ,
+ * morphTargets: ,
+ * morphNormals:
+ * }
+ */
- if ( geometry.faceVertexUvs.length > 0 ) {
+THREE.MeshPhongMaterial = function ( parameters ) {
- geometryGroup.__uvArray = new Float32Array( nvertices * 2 );
+ THREE.Material.call( this );
- }
+ this.type = 'MeshPhongMaterial';
- if ( geometry.faceVertexUvs.length > 1 ) {
+ this.color = new THREE.Color( 0xffffff ); // diffuse
+ this.specular = new THREE.Color( 0x111111 );
+ this.shininess = 30;
- geometryGroup.__uv2Array = new Float32Array( nvertices * 2 );
+ this.map = null;
- }
+ this.lightMap = null;
+ this.lightMapIntensity = 1.0;
- }
+ this.aoMap = null;
+ this.aoMapIntensity = 1.0;
- if ( object.geometry.skinWeights.length && object.geometry.skinIndices.length ) {
+ this.emissive = new THREE.Color( 0x000000 );
+ this.emissiveIntensity = 1.0;
+ this.emissiveMap = null;
- geometryGroup.__skinIndexArray = new Float32Array( nvertices * 4 );
- geometryGroup.__skinWeightArray = new Float32Array( nvertices * 4 );
+ this.bumpMap = null;
+ this.bumpScale = 1;
- }
+ this.normalMap = null;
+ this.normalScale = new THREE.Vector2( 1, 1 );
- geometryGroup.__faceArray = new Uint16Array( ntris * 3 );
- geometryGroup.__lineArray = new Uint16Array( nlines * 2 );
+ this.displacementMap = null;
+ this.displacementScale = 1;
+ this.displacementBias = 0;
- var m, ml;
+ this.specularMap = null;
- if ( geometryGroup.numMorphTargets ) {
+ this.alphaMap = null;
- geometryGroup.__morphTargetsArrays = [];
+ this.envMap = null;
+ this.combine = THREE.MultiplyOperation;
+ this.reflectivity = 1;
+ this.refractionRatio = 0.98;
- for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
+ this.wireframe = false;
+ this.wireframeLinewidth = 1;
+ this.wireframeLinecap = 'round';
+ this.wireframeLinejoin = 'round';
- geometryGroup.__morphTargetsArrays.push( new Float32Array( nvertices * 3 ) );
+ this.skinning = false;
+ this.morphTargets = false;
+ this.morphNormals = false;
- }
+ this.setValues( parameters );
- }
+};
- if ( geometryGroup.numMorphNormals ) {
+THREE.MeshPhongMaterial.prototype = Object.create( THREE.Material.prototype );
+THREE.MeshPhongMaterial.prototype.constructor = THREE.MeshPhongMaterial;
- geometryGroup.__morphNormalsArrays = [];
+THREE.MeshPhongMaterial.prototype.copy = function ( source ) {
- for ( m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) {
+ THREE.Material.prototype.copy.call( this, source );
- geometryGroup.__morphNormalsArrays.push( new Float32Array( nvertices * 3 ) );
+ this.color.copy( source.color );
+ this.specular.copy( source.specular );
+ this.shininess = source.shininess;
- }
+ this.map = source.map;
- }
+ this.lightMap = source.lightMap;
+ this.lightMapIntensity = source.lightMapIntensity;
- geometryGroup.__webglFaceCount = ntris * 3;
- geometryGroup.__webglLineCount = nlines * 2;
+ this.aoMap = source.aoMap;
+ this.aoMapIntensity = source.aoMapIntensity;
+ this.emissive.copy( source.emissive );
+ this.emissiveMap = source.emissiveMap;
+ this.emissiveIntensity = source.emissiveIntensity;
- // custom attributes
+ this.bumpMap = source.bumpMap;
+ this.bumpScale = source.bumpScale;
- if ( material.attributes ) {
+ this.normalMap = source.normalMap;
+ this.normalScale.copy( source.normalScale );
- if ( geometryGroup.__webglCustomAttributesList === undefined ) {
+ this.displacementMap = source.displacementMap;
+ this.displacementScale = source.displacementScale;
+ this.displacementBias = source.displacementBias;
- geometryGroup.__webglCustomAttributesList = [];
+ this.specularMap = source.specularMap;
- }
+ this.alphaMap = source.alphaMap;
- for ( var a in material.attributes ) {
+ this.envMap = source.envMap;
+ this.combine = source.combine;
+ this.reflectivity = source.reflectivity;
+ this.refractionRatio = source.refractionRatio;
- // Do a shallow copy of the attribute object so different geometryGroup chunks use different
- // attribute buffers which are correctly indexed in the setMeshBuffers function
+ this.wireframe = source.wireframe;
+ this.wireframeLinewidth = source.wireframeLinewidth;
+ this.wireframeLinecap = source.wireframeLinecap;
+ this.wireframeLinejoin = source.wireframeLinejoin;
- var originalAttribute = material.attributes[ a ];
+ this.skinning = source.skinning;
+ this.morphTargets = source.morphTargets;
+ this.morphNormals = source.morphNormals;
- var attribute = {};
+ return this;
- for ( var property in originalAttribute ) {
-
- attribute[ property ] = originalAttribute[ property ];
+};
- }
+// File:src/materials/MeshStandardMaterial.js
- if ( !attribute.__webglInitialized || attribute.createUniqueBuffers ) {
+/**
+ * @author WestLangley / http://github.com/WestLangley
+ *
+ * parameters = {
+ * color: ,
+ * roughness: ,
+ * metalness: ,
+ * opacity: ,
+ *
+ * map: new THREE.Texture( ),
+ *
+ * lightMap: new THREE.Texture( ),
+ * lightMapIntensity:
+ *
+ * aoMap: new THREE.Texture( ),
+ * aoMapIntensity:
+ *
+ * emissive: ,
+ * emissiveIntensity:
+ * emissiveMap: new THREE.Texture( ),
+ *
+ * bumpMap: new THREE.Texture( ),
+ * bumpScale: ,
+ *
+ * normalMap: new THREE.Texture( ),
+ * normalScale: ,
+ *
+ * displacementMap: new THREE.Texture( ),
+ * displacementScale: ,
+ * displacementBias: ,
+ *
+ * roughnessMap: new THREE.Texture( ),
+ *
+ * metalnessMap: new THREE.Texture( ),
+ *
+ * alphaMap: new THREE.Texture( ),
+ *
+ * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
+ * envMapIntensity:
+ *
+ * refractionRatio: ,
+ *
+ * wireframe: ,
+ * wireframeLinewidth: ,
+ *
+ * skinning: ,
+ * morphTargets: ,
+ * morphNormals:
+ * }
+ */
- attribute.__webglInitialized = true;
+THREE.MeshStandardMaterial = function ( parameters ) {
- var size = 1; // "f" and "i"
+ THREE.Material.call( this );
- if( attribute.type === "v2" ) size = 2;
- else if( attribute.type === "v3" ) size = 3;
- else if( attribute.type === "v4" ) size = 4;
- else if( attribute.type === "c" ) size = 3;
+ this.defines = { 'STANDARD': '' };
- attribute.size = size;
+ this.type = 'MeshStandardMaterial';
- attribute.array = new Float32Array( nvertices * size );
+ this.color = new THREE.Color( 0xffffff ); // diffuse
+ this.roughness = 0.5;
+ this.metalness = 0.5;
- attribute.buffer = _gl.createBuffer();
- attribute.buffer.belongsToAttribute = a;
+ this.map = null;
- originalAttribute.needsUpdate = true;
- attribute.__original = originalAttribute;
+ this.lightMap = null;
+ this.lightMapIntensity = 1.0;
- }
+ this.aoMap = null;
+ this.aoMapIntensity = 1.0;
- geometryGroup.__webglCustomAttributesList.push( attribute );
+ this.emissive = new THREE.Color( 0x000000 );
+ this.emissiveIntensity = 1.0;
+ this.emissiveMap = null;
- }
+ this.bumpMap = null;
+ this.bumpScale = 1;
- }
+ this.normalMap = null;
+ this.normalScale = new THREE.Vector2( 1, 1 );
- geometryGroup.__inittedArrays = true;
+ this.displacementMap = null;
+ this.displacementScale = 1;
+ this.displacementBias = 0;
- };
+ this.roughnessMap = null;
- function getBufferMaterial( object, geometryGroup ) {
+ this.metalnessMap = null;
- return object.material instanceof THREE.MeshFaceMaterial
- ? object.material.materials[ geometryGroup.materialIndex ]
- : object.material;
+ this.alphaMap = null;
- };
+ this.envMap = null;
+ this.envMapIntensity = 1.0;
- function materialNeedsSmoothNormals ( material ) {
+ this.refractionRatio = 0.98;
- return material && material.shading !== undefined && material.shading === THREE.SmoothShading;
+ this.wireframe = false;
+ this.wireframeLinewidth = 1;
+ this.wireframeLinecap = 'round';
+ this.wireframeLinejoin = 'round';
- };
+ this.skinning = false;
+ this.morphTargets = false;
+ this.morphNormals = false;
- function bufferGuessNormalType ( material ) {
+ this.setValues( parameters );
- // only MeshBasicMaterial and MeshDepthMaterial don't need normals
+};
- if ( ( material instanceof THREE.MeshBasicMaterial && !material.envMap ) || material instanceof THREE.MeshDepthMaterial ) {
+THREE.MeshStandardMaterial.prototype = Object.create( THREE.Material.prototype );
+THREE.MeshStandardMaterial.prototype.constructor = THREE.MeshStandardMaterial;
- return false;
+THREE.MeshStandardMaterial.prototype.copy = function ( source ) {
- }
+ THREE.Material.prototype.copy.call( this, source );
- if ( materialNeedsSmoothNormals( material ) ) {
+ this.defines = { 'STANDARD': '' };
- return THREE.SmoothShading;
+ this.color.copy( source.color );
+ this.roughness = source.roughness;
+ this.metalness = source.metalness;
- } else {
+ this.map = source.map;
- return THREE.FlatShading;
+ this.lightMap = source.lightMap;
+ this.lightMapIntensity = source.lightMapIntensity;
- }
+ this.aoMap = source.aoMap;
+ this.aoMapIntensity = source.aoMapIntensity;
- };
+ this.emissive.copy( source.emissive );
+ this.emissiveMap = source.emissiveMap;
+ this.emissiveIntensity = source.emissiveIntensity;
- function bufferGuessVertexColorType( material ) {
+ this.bumpMap = source.bumpMap;
+ this.bumpScale = source.bumpScale;
- if ( material.vertexColors ) {
+ this.normalMap = source.normalMap;
+ this.normalScale.copy( source.normalScale );
- return material.vertexColors;
+ this.displacementMap = source.displacementMap;
+ this.displacementScale = source.displacementScale;
+ this.displacementBias = source.displacementBias;
- }
+ this.roughnessMap = source.roughnessMap;
- return false;
+ this.metalnessMap = source.metalnessMap;
- };
+ this.alphaMap = source.alphaMap;
- function bufferGuessUVType( material ) {
+ this.envMap = source.envMap;
+ this.envMapIntensity = source.envMapIntensity;
- // material must use some texture to require uvs
+ this.refractionRatio = source.refractionRatio;
- if ( material.map ||
- material.lightMap ||
- material.bumpMap ||
- material.normalMap ||
- material.specularMap ||
- material instanceof THREE.ShaderMaterial ) {
+ this.wireframe = source.wireframe;
+ this.wireframeLinewidth = source.wireframeLinewidth;
+ this.wireframeLinecap = source.wireframeLinecap;
+ this.wireframeLinejoin = source.wireframeLinejoin;
- return true;
+ this.skinning = source.skinning;
+ this.morphTargets = source.morphTargets;
+ this.morphNormals = source.morphNormals;
- }
+ return this;
- return false;
+};
- };
+// File:src/materials/MeshPhysicalMaterial.js
- //
+/**
+ * @author WestLangley / http://github.com/WestLangley
+ *
+ * parameters = {
+ * reflectivity:
+ * }
+ */
- function initDirectBuffers( geometry ) {
+THREE.MeshPhysicalMaterial = function ( parameters ) {
- var a, attribute, type;
+ THREE.MeshStandardMaterial.call( this );
- for ( a in geometry.attributes ) {
+ this.defines = { 'PHYSICAL': '' };
- if ( a === "index" ) {
+ this.type = 'MeshPhysicalMaterial';
- type = _gl.ELEMENT_ARRAY_BUFFER;
+ this.reflectivity = 0.5; // maps to F0 = 0.04
- } else {
+ this.clearCoat = 0.0;
+ this.clearCoatRoughness = 0.0;
- type = _gl.ARRAY_BUFFER;
+ this.setValues( parameters );
- }
+};
- attribute = geometry.attributes[ a ];
+THREE.MeshPhysicalMaterial.prototype = Object.create( THREE.MeshStandardMaterial.prototype );
+THREE.MeshPhysicalMaterial.prototype.constructor = THREE.MeshPhysicalMaterial;
- if ( attribute.numItems === undefined ) {
+THREE.MeshPhysicalMaterial.prototype.copy = function ( source ) {
- attribute.numItems = attribute.array.length;
+ THREE.MeshStandardMaterial.prototype.copy.call( this, source );
- }
+ this.defines = { 'PHYSICAL': '' };
- attribute.buffer = _gl.createBuffer();
+ this.reflectivity = source.reflectivity;
- _gl.bindBuffer( type, attribute.buffer );
- _gl.bufferData( type, attribute.array, _gl.STATIC_DRAW );
+ this.clearCoat = source.clearCoat;
+ this.clearCoatRoughness = source.clearCoatRoughness;
- }
+ return this;
- };
+};
- // Buffer setting
+// File:src/materials/MultiMaterial.js
- function setParticleBuffers ( geometry, hint, object ) {
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
- var v, c, vertex, offset, index, color,
+THREE.MultiMaterial = function ( materials ) {
- vertices = geometry.vertices,
- vl = vertices.length,
+ this.uuid = THREE.Math.generateUUID();
- colors = geometry.colors,
- cl = colors.length,
+ this.type = 'MultiMaterial';
- vertexArray = geometry.__vertexArray,
- colorArray = geometry.__colorArray,
+ this.materials = materials instanceof Array ? materials : [];
- sortArray = geometry.__sortArray,
+ this.visible = true;
- dirtyVertices = geometry.verticesNeedUpdate,
- dirtyElements = geometry.elementsNeedUpdate,
- dirtyColors = geometry.colorsNeedUpdate,
+};
- customAttributes = geometry.__webglCustomAttributesList,
- i, il,
- a, ca, cal, value,
- customAttribute;
+THREE.MultiMaterial.prototype = {
- if ( object.sortParticles ) {
+ constructor: THREE.MultiMaterial,
- _projScreenMatrixPS.copy( _projScreenMatrix );
- _projScreenMatrixPS.multiply( object.matrixWorld );
+ toJSON: function ( meta ) {
- for ( v = 0; v < vl; v ++ ) {
+ var output = {
+ metadata: {
+ version: 4.2,
+ type: 'material',
+ generator: 'MaterialExporter'
+ },
+ uuid: this.uuid,
+ type: this.type,
+ materials: []
+ };
- vertex = vertices[ v ];
+ var materials = this.materials;
- _vector3.copy( vertex );
- _vector3.applyProjection( _projScreenMatrixPS );
+ for ( var i = 0, l = materials.length; i < l; i ++ ) {
- sortArray[ v ] = [ _vector3.z, v ];
+ var material = materials[ i ].toJSON( meta );
+ delete material.metadata;
- }
+ output.materials.push( material );
- sortArray.sort( numericalSort );
+ }
- for ( v = 0; v < vl; v ++ ) {
+ output.visible = this.visible;
- vertex = vertices[ sortArray[v][1] ];
+ return output;
- offset = v * 3;
+ },
- vertexArray[ offset ] = vertex.x;
- vertexArray[ offset + 1 ] = vertex.y;
- vertexArray[ offset + 2 ] = vertex.z;
+ clone: function () {
- }
+ var material = new this.constructor();
- for ( c = 0; c < cl; c ++ ) {
+ for ( var i = 0; i < this.materials.length; i ++ ) {
- offset = c * 3;
+ material.materials.push( this.materials[ i ].clone() );
- color = colors[ sortArray[c][1] ];
+ }
- colorArray[ offset ] = color.r;
- colorArray[ offset + 1 ] = color.g;
- colorArray[ offset + 2 ] = color.b;
+ material.visible = this.visible;
- }
+ return material;
- if ( customAttributes ) {
+ }
- for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
+};
- customAttribute = customAttributes[ i ];
+// File:src/materials/PointsMaterial.js
- if ( ! ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) ) continue;
+/**
+ * @author mrdoob / http://mrdoob.com/
+ * @author alteredq / http://alteredqualia.com/
+ *
+ * parameters = {
+ * color: ,
+ * opacity: ,
+ * map: new THREE.Texture( ),
+ *
+ * size: ,
+ * sizeAttenuation:
+ * }
+ */
- offset = 0;
+THREE.PointsMaterial = function ( parameters ) {
- cal = customAttribute.value.length;
+ THREE.Material.call( this );
- if ( customAttribute.size === 1 ) {
+ this.type = 'PointsMaterial';
- for ( ca = 0; ca < cal; ca ++ ) {
+ this.color = new THREE.Color( 0xffffff );
- index = sortArray[ ca ][ 1 ];
+ this.map = null;
- customAttribute.array[ ca ] = customAttribute.value[ index ];
+ this.size = 1;
+ this.sizeAttenuation = true;
- }
+ this.lights = false;
- } else if ( customAttribute.size === 2 ) {
+ this.setValues( parameters );
- for ( ca = 0; ca < cal; ca ++ ) {
+};
- index = sortArray[ ca ][ 1 ];
+THREE.PointsMaterial.prototype = Object.create( THREE.Material.prototype );
+THREE.PointsMaterial.prototype.constructor = THREE.PointsMaterial;
- value = customAttribute.value[ index ];
+THREE.PointsMaterial.prototype.copy = function ( source ) {
- customAttribute.array[ offset ] = value.x;
- customAttribute.array[ offset + 1 ] = value.y;
+ THREE.Material.prototype.copy.call( this, source );
- offset += 2;
+ this.color.copy( source.color );
- }
+ this.map = source.map;
- } else if ( customAttribute.size === 3 ) {
+ this.size = source.size;
+ this.sizeAttenuation = source.sizeAttenuation;
- if ( customAttribute.type === "c" ) {
+ return this;
- for ( ca = 0; ca < cal; ca ++ ) {
+};
- index = sortArray[ ca ][ 1 ];
+// File:src/materials/ShaderMaterial.js
- value = customAttribute.value[ index ];
+/**
+ * @author alteredq / http://alteredqualia.com/
+ *
+ * parameters = {
+ * defines: { "label" : "value" },
+ * uniforms: { "parameter1": { value: 1.0 }, "parameter2": { value2: 2 } },
+ *
+ * fragmentShader: ,
+ * vertexShader: ,
+ *
+ * wireframe: ,
+ * wireframeLinewidth: ,
+ *
+ * lights: ,
+ *
+ * skinning: ,
+ * morphTargets: ,
+ * morphNormals:
+ * }
+ */
- customAttribute.array[ offset ] = value.r;
- customAttribute.array[ offset + 1 ] = value.g;
- customAttribute.array[ offset + 2 ] = value.b;
+THREE.ShaderMaterial = function ( parameters ) {
- offset += 3;
+ THREE.Material.call( this );
- }
+ this.type = 'ShaderMaterial';
- } else {
+ this.defines = {};
+ this.uniforms = {};
- for ( ca = 0; ca < cal; ca ++ ) {
+ this.vertexShader = 'void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}';
+ this.fragmentShader = 'void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}';
- index = sortArray[ ca ][ 1 ];
+ this.linewidth = 1;
- value = customAttribute.value[ index ];
+ this.wireframe = false;
+ this.wireframeLinewidth = 1;
- customAttribute.array[ offset ] = value.x;
- customAttribute.array[ offset + 1 ] = value.y;
- customAttribute.array[ offset + 2 ] = value.z;
+ this.fog = false; // set to use scene fog
+ this.lights = false; // set to use scene lights
+ this.clipping = false; // set to use user-defined clipping planes
- offset += 3;
+ this.skinning = false; // set to use skinning attribute streams
+ this.morphTargets = false; // set to use morph targets
+ this.morphNormals = false; // set to use morph normals
- }
+ this.extensions = {
+ derivatives: false, // set to use derivatives
+ fragDepth: false, // set to use fragment depth values
+ drawBuffers: false, // set to use draw buffers
+ shaderTextureLOD: false // set to use shader texture LOD
+ };
- }
+ // When rendered geometry doesn't include these attributes but the material does,
+ // use these default values in WebGL. This avoids errors when buffer data is missing.
+ this.defaultAttributeValues = {
+ 'color': [ 1, 1, 1 ],
+ 'uv': [ 0, 0 ],
+ 'uv2': [ 0, 0 ]
+ };
- } else if ( customAttribute.size === 4 ) {
+ this.index0AttributeName = undefined;
- for ( ca = 0; ca < cal; ca ++ ) {
+ if ( parameters !== undefined ) {
- index = sortArray[ ca ][ 1 ];
+ if ( parameters.attributes !== undefined ) {
- value = customAttribute.value[ index ];
+ console.error( 'THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.' );
- customAttribute.array[ offset ] = value.x;
- customAttribute.array[ offset + 1 ] = value.y;
- customAttribute.array[ offset + 2 ] = value.z;
- customAttribute.array[ offset + 3 ] = value.w;
+ }
- offset += 4;
+ this.setValues( parameters );
- }
+ }
- }
+};
- }
+THREE.ShaderMaterial.prototype = Object.create( THREE.Material.prototype );
+THREE.ShaderMaterial.prototype.constructor = THREE.ShaderMaterial;
- }
+THREE.ShaderMaterial.prototype.copy = function ( source ) {
- } else {
+ THREE.Material.prototype.copy.call( this, source );
- if ( dirtyVertices ) {
+ this.fragmentShader = source.fragmentShader;
+ this.vertexShader = source.vertexShader;
- for ( v = 0; v < vl; v ++ ) {
+ this.uniforms = THREE.UniformsUtils.clone( source.uniforms );
- vertex = vertices[ v ];
+ this.defines = source.defines;
- offset = v * 3;
+ this.wireframe = source.wireframe;
+ this.wireframeLinewidth = source.wireframeLinewidth;
- vertexArray[ offset ] = vertex.x;
- vertexArray[ offset + 1 ] = vertex.y;
- vertexArray[ offset + 2 ] = vertex.z;
+ this.lights = source.lights;
+ this.clipping = source.clipping;
- }
+ this.skinning = source.skinning;
- }
+ this.morphTargets = source.morphTargets;
+ this.morphNormals = source.morphNormals;
- if ( dirtyColors ) {
+ this.extensions = source.extensions;
- for ( c = 0; c < cl; c ++ ) {
+ return this;
- color = colors[ c ];
+};
- offset = c * 3;
+THREE.ShaderMaterial.prototype.toJSON = function ( meta ) {
- colorArray[ offset ] = color.r;
- colorArray[ offset + 1 ] = color.g;
- colorArray[ offset + 2 ] = color.b;
+ var data = THREE.Material.prototype.toJSON.call( this, meta );
- }
+ data.uniforms = this.uniforms;
+ data.vertexShader = this.vertexShader;
+ data.fragmentShader = this.fragmentShader;
- }
+ return data;
- if ( customAttributes ) {
+};
- for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
+// File:src/materials/RawShaderMaterial.js
- customAttribute = customAttributes[ i ];
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
- if ( customAttribute.needsUpdate &&
- ( customAttribute.boundTo === undefined ||
- customAttribute.boundTo === "vertices") ) {
+THREE.RawShaderMaterial = function ( parameters ) {
- cal = customAttribute.value.length;
+ THREE.ShaderMaterial.call( this, parameters );
- offset = 0;
+ this.type = 'RawShaderMaterial';
- if ( customAttribute.size === 1 ) {
+};
- for ( ca = 0; ca < cal; ca ++ ) {
+THREE.RawShaderMaterial.prototype = Object.create( THREE.ShaderMaterial.prototype );
+THREE.RawShaderMaterial.prototype.constructor = THREE.RawShaderMaterial;
- customAttribute.array[ ca ] = customAttribute.value[ ca ];
+// File:src/materials/SpriteMaterial.js
- }
+/**
+ * @author alteredq / http://alteredqualia.com/
+ *
+ * parameters = {
+ * color: ,
+ * opacity: ,
+ * map: new THREE.Texture( ),
+ *
+ * uvOffset: new THREE.Vector2(),
+ * uvScale: new THREE.Vector2()
+ * }
+ */
- } else if ( customAttribute.size === 2 ) {
+THREE.SpriteMaterial = function ( parameters ) {
- for ( ca = 0; ca < cal; ca ++ ) {
+ THREE.Material.call( this );
- value = customAttribute.value[ ca ];
+ this.type = 'SpriteMaterial';
- customAttribute.array[ offset ] = value.x;
- customAttribute.array[ offset + 1 ] = value.y;
+ this.color = new THREE.Color( 0xffffff );
+ this.map = null;
- offset += 2;
+ this.rotation = 0;
- }
+ this.fog = false;
+ this.lights = false;
- } else if ( customAttribute.size === 3 ) {
+ this.setValues( parameters );
- if ( customAttribute.type === "c" ) {
+};
- for ( ca = 0; ca < cal; ca ++ ) {
+THREE.SpriteMaterial.prototype = Object.create( THREE.Material.prototype );
+THREE.SpriteMaterial.prototype.constructor = THREE.SpriteMaterial;
- value = customAttribute.value[ ca ];
+THREE.SpriteMaterial.prototype.copy = function ( source ) {
- customAttribute.array[ offset ] = value.r;
- customAttribute.array[ offset + 1 ] = value.g;
- customAttribute.array[ offset + 2 ] = value.b;
+ THREE.Material.prototype.copy.call( this, source );
- offset += 3;
+ this.color.copy( source.color );
+ this.map = source.map;
- }
+ this.rotation = source.rotation;
- } else {
+ return this;
- for ( ca = 0; ca < cal; ca ++ ) {
+};
- value = customAttribute.value[ ca ];
+// File:src/materials/ShadowMaterial.js
- customAttribute.array[ offset ] = value.x;
- customAttribute.array[ offset + 1 ] = value.y;
- customAttribute.array[ offset + 2 ] = value.z;
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
- offset += 3;
+THREE.ShadowMaterial = function () {
- }
+ THREE.ShaderMaterial.call( this, {
+ uniforms: THREE.UniformsUtils.merge( [
+ THREE.UniformsLib[ "lights" ],
+ {
+ opacity: { value: 1.0 }
+ }
+ ] ),
+ vertexShader: THREE.ShaderChunk[ 'shadow_vert' ],
+ fragmentShader: THREE.ShaderChunk[ 'shadow_frag' ]
+ } );
- }
+ this.lights = true;
+ this.transparent = true;
- } else if ( customAttribute.size === 4 ) {
+ Object.defineProperties( this, {
+ opacity: {
+ enumerable: true,
+ get: function () {
+ return this.uniforms.opacity.value;
+ },
+ set: function ( value ) {
+ this.uniforms.opacity.value = value;
+ }
+ }
+ } );
- for ( ca = 0; ca < cal; ca ++ ) {
+};
- value = customAttribute.value[ ca ];
+THREE.ShadowMaterial.prototype = Object.create( THREE.ShaderMaterial.prototype );
+THREE.ShadowMaterial.prototype.constructor = THREE.ShadowMaterial;
- customAttribute.array[ offset ] = value.x;
- customAttribute.array[ offset + 1 ] = value.y;
- customAttribute.array[ offset + 2 ] = value.z;
- customAttribute.array[ offset + 3 ] = value.w;
+// File:src/textures/Texture.js
- offset += 4;
+/**
+ * @author mrdoob / http://mrdoob.com/
+ * @author alteredq / http://alteredqualia.com/
+ * @author szimek / https://github.com/szimek/
+ */
- }
+THREE.Texture = function ( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {
- }
+ Object.defineProperty( this, 'id', { value: THREE.TextureIdCount ++ } );
- }
+ this.uuid = THREE.Math.generateUUID();
- }
+ this.name = '';
+ this.sourceFile = '';
- }
+ this.image = image !== undefined ? image : THREE.Texture.DEFAULT_IMAGE;
+ this.mipmaps = [];
- }
+ this.mapping = mapping !== undefined ? mapping : THREE.Texture.DEFAULT_MAPPING;
- if ( dirtyVertices || object.sortParticles ) {
+ this.wrapS = wrapS !== undefined ? wrapS : THREE.ClampToEdgeWrapping;
+ this.wrapT = wrapT !== undefined ? wrapT : THREE.ClampToEdgeWrapping;
- _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglVertexBuffer );
- _gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint );
+ this.magFilter = magFilter !== undefined ? magFilter : THREE.LinearFilter;
+ this.minFilter = minFilter !== undefined ? minFilter : THREE.LinearMipMapLinearFilter;
- }
+ this.anisotropy = anisotropy !== undefined ? anisotropy : 1;
- if ( dirtyColors || object.sortParticles ) {
+ this.format = format !== undefined ? format : THREE.RGBAFormat;
+ this.type = type !== undefined ? type : THREE.UnsignedByteType;
- _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglColorBuffer );
- _gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint );
+ this.offset = new THREE.Vector2( 0, 0 );
+ this.repeat = new THREE.Vector2( 1, 1 );
- }
+ this.generateMipmaps = true;
+ this.premultiplyAlpha = false;
+ this.flipY = true;
+ this.unpackAlignment = 4; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)
- if ( customAttributes ) {
- for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
+ // Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap.
+ //
+ // Also changing the encoding after already used by a Material will not automatically make the Material
+ // update. You need to explicitly call Material.needsUpdate to trigger it to recompile.
+ this.encoding = encoding !== undefined ? encoding : THREE.LinearEncoding;
- customAttribute = customAttributes[ i ];
+ this.version = 0;
+ this.onUpdate = null;
- if ( customAttribute.needsUpdate || object.sortParticles ) {
+};
- _gl.bindBuffer( _gl.ARRAY_BUFFER, customAttribute.buffer );
- _gl.bufferData( _gl.ARRAY_BUFFER, customAttribute.array, hint );
+THREE.Texture.DEFAULT_IMAGE = undefined;
+THREE.Texture.DEFAULT_MAPPING = THREE.UVMapping;
- }
+THREE.Texture.prototype = {
- }
+ constructor: THREE.Texture,
- }
+ set needsUpdate( value ) {
+ if ( value === true ) this.version ++;
- };
+ },
- function setLineBuffers ( geometry, hint ) {
+ clone: function () {
- var v, c, d, vertex, offset, color,
+ return new this.constructor().copy( this );
- vertices = geometry.vertices,
- colors = geometry.colors,
- lineDistances = geometry.lineDistances,
+ },
- vl = vertices.length,
- cl = colors.length,
- dl = lineDistances.length,
+ copy: function ( source ) {
- vertexArray = geometry.__vertexArray,
- colorArray = geometry.__colorArray,
- lineDistanceArray = geometry.__lineDistanceArray,
+ this.image = source.image;
+ this.mipmaps = source.mipmaps.slice( 0 );
- dirtyVertices = geometry.verticesNeedUpdate,
- dirtyColors = geometry.colorsNeedUpdate,
- dirtyLineDistances = geometry.lineDistancesNeedUpdate,
+ this.mapping = source.mapping;
- customAttributes = geometry.__webglCustomAttributesList,
+ this.wrapS = source.wrapS;
+ this.wrapT = source.wrapT;
- i, il,
- a, ca, cal, value,
- customAttribute;
+ this.magFilter = source.magFilter;
+ this.minFilter = source.minFilter;
- if ( dirtyVertices ) {
+ this.anisotropy = source.anisotropy;
- for ( v = 0; v < vl; v ++ ) {
+ this.format = source.format;
+ this.type = source.type;
- vertex = vertices[ v ];
+ this.offset.copy( source.offset );
+ this.repeat.copy( source.repeat );
- offset = v * 3;
+ this.generateMipmaps = source.generateMipmaps;
+ this.premultiplyAlpha = source.premultiplyAlpha;
+ this.flipY = source.flipY;
+ this.unpackAlignment = source.unpackAlignment;
+ this.encoding = source.encoding;
- vertexArray[ offset ] = vertex.x;
- vertexArray[ offset + 1 ] = vertex.y;
- vertexArray[ offset + 2 ] = vertex.z;
+ return this;
- }
+ },
+
+ toJSON: function ( meta ) {
- _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglVertexBuffer );
- _gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint );
+ if ( meta.textures[ this.uuid ] !== undefined ) {
+
+ return meta.textures[ this.uuid ];
}
- if ( dirtyColors ) {
+ function getDataURL( image ) {
+
+ var canvas;
- for ( c = 0; c < cl; c ++ ) {
+ if ( image.toDataURL !== undefined ) {
- color = colors[ c ];
+ canvas = image;
- offset = c * 3;
+ } else {
- colorArray[ offset ] = color.r;
- colorArray[ offset + 1 ] = color.g;
- colorArray[ offset + 2 ] = color.b;
+ canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
+ canvas.width = image.width;
+ canvas.height = image.height;
- }
+ canvas.getContext( '2d' ).drawImage( image, 0, 0, image.width, image.height );
- _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglColorBuffer );
- _gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint );
+ }
- }
+ if ( canvas.width > 2048 || canvas.height > 2048 ) {
- if ( dirtyLineDistances ) {
+ return canvas.toDataURL( 'image/jpeg', 0.6 );
- for ( d = 0; d < dl; d ++ ) {
+ } else {
- lineDistanceArray[ d ] = lineDistances[ d ];
+ return canvas.toDataURL( 'image/png' );
}
- _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglLineDistanceBuffer );
- _gl.bufferData( _gl.ARRAY_BUFFER, lineDistanceArray, hint );
-
}
- if ( customAttributes ) {
+ var output = {
+ metadata: {
+ version: 4.4,
+ type: 'Texture',
+ generator: 'Texture.toJSON'
+ },
- for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
+ uuid: this.uuid,
+ name: this.name,
- customAttribute = customAttributes[ i ];
+ mapping: this.mapping,
- if ( customAttribute.needsUpdate &&
- ( customAttribute.boundTo === undefined ||
- customAttribute.boundTo === "vertices" ) ) {
+ repeat: [ this.repeat.x, this.repeat.y ],
+ offset: [ this.offset.x, this.offset.y ],
+ wrap: [ this.wrapS, this.wrapT ],
- offset = 0;
+ minFilter: this.minFilter,
+ magFilter: this.magFilter,
+ anisotropy: this.anisotropy,
- cal = customAttribute.value.length;
-
- if ( customAttribute.size === 1 ) {
+ flipY: this.flipY
+ };
- for ( ca = 0; ca < cal; ca ++ ) {
+ if ( this.image !== undefined ) {
- customAttribute.array[ ca ] = customAttribute.value[ ca ];
+ // TODO: Move to THREE.Image
- }
+ var image = this.image;
- } else if ( customAttribute.size === 2 ) {
+ if ( image.uuid === undefined ) {
- for ( ca = 0; ca < cal; ca ++ ) {
+ image.uuid = THREE.Math.generateUUID(); // UGH
- value = customAttribute.value[ ca ];
+ }
- customAttribute.array[ offset ] = value.x;
- customAttribute.array[ offset + 1 ] = value.y;
+ if ( meta.images[ image.uuid ] === undefined ) {
- offset += 2;
+ meta.images[ image.uuid ] = {
+ uuid: image.uuid,
+ url: getDataURL( image )
+ };
- }
+ }
- } else if ( customAttribute.size === 3 ) {
+ output.image = image.uuid;
- if ( customAttribute.type === "c" ) {
+ }
- for ( ca = 0; ca < cal; ca ++ ) {
+ meta.textures[ this.uuid ] = output;
- value = customAttribute.value[ ca ];
+ return output;
- customAttribute.array[ offset ] = value.r;
- customAttribute.array[ offset + 1 ] = value.g;
- customAttribute.array[ offset + 2 ] = value.b;
+ },
- offset += 3;
+ dispose: function () {
- }
+ this.dispatchEvent( { type: 'dispose' } );
- } else {
+ },
- for ( ca = 0; ca < cal; ca ++ ) {
+ transformUv: function ( uv ) {
- value = customAttribute.value[ ca ];
+ if ( this.mapping !== THREE.UVMapping ) return;
- customAttribute.array[ offset ] = value.x;
- customAttribute.array[ offset + 1 ] = value.y;
- customAttribute.array[ offset + 2 ] = value.z;
+ uv.multiply( this.repeat );
+ uv.add( this.offset );
- offset += 3;
+ if ( uv.x < 0 || uv.x > 1 ) {
- }
+ switch ( this.wrapS ) {
- }
+ case THREE.RepeatWrapping:
- } else if ( customAttribute.size === 4 ) {
+ uv.x = uv.x - Math.floor( uv.x );
+ break;
- for ( ca = 0; ca < cal; ca ++ ) {
+ case THREE.ClampToEdgeWrapping:
- value = customAttribute.value[ ca ];
+ uv.x = uv.x < 0 ? 0 : 1;
+ break;
- customAttribute.array[ offset ] = value.x;
- customAttribute.array[ offset + 1 ] = value.y;
- customAttribute.array[ offset + 2 ] = value.z;
- customAttribute.array[ offset + 3 ] = value.w;
+ case THREE.MirroredRepeatWrapping:
- offset += 4;
+ if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) {
- }
+ uv.x = Math.ceil( uv.x ) - uv.x;
- }
+ } else {
- _gl.bindBuffer( _gl.ARRAY_BUFFER, customAttribute.buffer );
- _gl.bufferData( _gl.ARRAY_BUFFER, customAttribute.array, hint );
+ uv.x = uv.x - Math.floor( uv.x );
- }
+ }
+ break;
}
}
- };
+ if ( uv.y < 0 || uv.y > 1 ) {
- function setRibbonBuffers ( geometry, hint ) {
+ switch ( this.wrapT ) {
- var v, c, n, vertex, offset, color, normal,
+ case THREE.RepeatWrapping:
- i, il, ca, cal, customAttribute, value,
+ uv.y = uv.y - Math.floor( uv.y );
+ break;
- vertices = geometry.vertices,
- colors = geometry.colors,
- normals = geometry.normals,
+ case THREE.ClampToEdgeWrapping:
- vl = vertices.length,
- cl = colors.length,
- nl = normals.length,
+ uv.y = uv.y < 0 ? 0 : 1;
+ break;
- vertexArray = geometry.__vertexArray,
- colorArray = geometry.__colorArray,
- normalArray = geometry.__normalArray,
+ case THREE.MirroredRepeatWrapping:
- dirtyVertices = geometry.verticesNeedUpdate,
- dirtyColors = geometry.colorsNeedUpdate,
- dirtyNormals = geometry.normalsNeedUpdate,
+ if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) {
- customAttributes = geometry.__webglCustomAttributesList;
+ uv.y = Math.ceil( uv.y ) - uv.y;
- if ( dirtyVertices ) {
+ } else {
- for ( v = 0; v < vl; v ++ ) {
+ uv.y = uv.y - Math.floor( uv.y );
- vertex = vertices[ v ];
+ }
+ break;
- offset = v * 3;
+ }
- vertexArray[ offset ] = vertex.x;
- vertexArray[ offset + 1 ] = vertex.y;
- vertexArray[ offset + 2 ] = vertex.z;
+ }
- }
+ if ( this.flipY ) {
- _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglVertexBuffer );
- _gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint );
+ uv.y = 1 - uv.y;
}
- if ( dirtyColors ) {
+ }
+
+};
+
+Object.assign( THREE.Texture.prototype, THREE.EventDispatcher.prototype );
- for ( c = 0; c < cl; c ++ ) {
+THREE.TextureIdCount = 0;
- color = colors[ c ];
+// File:src/textures/DepthTexture.js
- offset = c * 3;
+/**
+ * @author Matt DesLauriers / @mattdesl
+ */
- colorArray[ offset ] = color.r;
- colorArray[ offset + 1 ] = color.g;
- colorArray[ offset + 2 ] = color.b;
+THREE.DepthTexture = function ( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy ) {
- }
+ THREE.Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, THREE.DepthFormat, type, anisotropy );
- _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglColorBuffer );
- _gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint );
+ this.image = { width: width, height: height };
- }
+ this.type = type !== undefined ? type : THREE.UnsignedShortType;
- if ( dirtyNormals ) {
+ this.magFilter = magFilter !== undefined ? magFilter : THREE.NearestFilter;
+ this.minFilter = minFilter !== undefined ? minFilter : THREE.NearestFilter;
- for ( n = 0; n < nl; n ++ ) {
+ this.flipY = false;
+ this.generateMipmaps = false;
- normal = normals[ n ];
+};
- offset = n * 3;
+THREE.DepthTexture.prototype = Object.create( THREE.Texture.prototype );
+THREE.DepthTexture.prototype.constructor = THREE.DepthTexture;
- normalArray[ offset ] = normal.x;
- normalArray[ offset + 1 ] = normal.y;
- normalArray[ offset + 2 ] = normal.z;
+// File:src/textures/CanvasTexture.js
- }
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
- _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglNormalBuffer );
- _gl.bufferData( _gl.ARRAY_BUFFER, normalArray, hint );
+THREE.CanvasTexture = function ( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
- }
+ THREE.Texture.call( this, canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
- if ( customAttributes ) {
+ this.needsUpdate = true;
- for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
+};
- customAttribute = customAttributes[ i ];
+THREE.CanvasTexture.prototype = Object.create( THREE.Texture.prototype );
+THREE.CanvasTexture.prototype.constructor = THREE.CanvasTexture;
- if ( customAttribute.needsUpdate &&
- ( customAttribute.boundTo === undefined ||
- customAttribute.boundTo === "vertices" ) ) {
+// File:src/textures/CubeTexture.js
- offset = 0;
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
- cal = customAttribute.value.length;
+THREE.CubeTexture = function ( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {
- if ( customAttribute.size === 1 ) {
+ images = images !== undefined ? images : [];
+ mapping = mapping !== undefined ? mapping : THREE.CubeReflectionMapping;
- for ( ca = 0; ca < cal; ca ++ ) {
+ THREE.Texture.call( this, images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
- customAttribute.array[ ca ] = customAttribute.value[ ca ];
+ this.flipY = false;
- }
+};
- } else if ( customAttribute.size === 2 ) {
+THREE.CubeTexture.prototype = Object.create( THREE.Texture.prototype );
+THREE.CubeTexture.prototype.constructor = THREE.CubeTexture;
- for ( ca = 0; ca < cal; ca ++ ) {
+Object.defineProperty( THREE.CubeTexture.prototype, 'images', {
- value = customAttribute.value[ ca ];
+ get: function () {
- customAttribute.array[ offset ] = value.x;
- customAttribute.array[ offset + 1 ] = value.y;
+ return this.image;
- offset += 2;
+ },
- }
+ set: function ( value ) {
- } else if ( customAttribute.size === 3 ) {
+ this.image = value;
- if ( customAttribute.type === "c" ) {
+ }
- for ( ca = 0; ca < cal; ca ++ ) {
+} );
- value = customAttribute.value[ ca ];
+// File:src/textures/CompressedTexture.js
- customAttribute.array[ offset ] = value.r;
- customAttribute.array[ offset + 1 ] = value.g;
- customAttribute.array[ offset + 2 ] = value.b;
+/**
+ * @author alteredq / http://alteredqualia.com/
+ */
- offset += 3;
+THREE.CompressedTexture = function ( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {
- }
+ THREE.Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
- } else {
+ this.image = { width: width, height: height };
+ this.mipmaps = mipmaps;
- for ( ca = 0; ca < cal; ca ++ ) {
+ // no flipping for cube textures
+ // (also flipping doesn't work for compressed textures )
- value = customAttribute.value[ ca ];
+ this.flipY = false;
- customAttribute.array[ offset ] = value.x;
- customAttribute.array[ offset + 1 ] = value.y;
- customAttribute.array[ offset + 2 ] = value.z;
+ // can't generate mipmaps for compressed textures
+ // mips must be embedded in DDS files
- offset += 3;
+ this.generateMipmaps = false;
- }
+};
- }
+THREE.CompressedTexture.prototype = Object.create( THREE.Texture.prototype );
+THREE.CompressedTexture.prototype.constructor = THREE.CompressedTexture;
- } else if ( customAttribute.size === 4 ) {
+// File:src/textures/DataTexture.js
- for ( ca = 0; ca < cal; ca ++ ) {
+/**
+ * @author alteredq / http://alteredqualia.com/
+ */
- value = customAttribute.value[ ca ];
+THREE.DataTexture = function ( data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {
- customAttribute.array[ offset ] = value.x;
- customAttribute.array[ offset + 1 ] = value.y;
- customAttribute.array[ offset + 2 ] = value.z;
- customAttribute.array[ offset + 3 ] = value.w;
+ THREE.Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
- offset += 4;
+ this.image = { data: data, width: width, height: height };
- }
+ this.magFilter = magFilter !== undefined ? magFilter : THREE.NearestFilter;
+ this.minFilter = minFilter !== undefined ? minFilter : THREE.NearestFilter;
- }
+ this.flipY = false;
+ this.generateMipmaps = false;
- _gl.bindBuffer( _gl.ARRAY_BUFFER, customAttribute.buffer );
- _gl.bufferData( _gl.ARRAY_BUFFER, customAttribute.array, hint );
+};
- }
+THREE.DataTexture.prototype = Object.create( THREE.Texture.prototype );
+THREE.DataTexture.prototype.constructor = THREE.DataTexture;
- }
+// File:src/textures/VideoTexture.js
- }
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
- };
+THREE.VideoTexture = function ( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
- function setMeshBuffers( geometryGroup, object, hint, dispose, material ) {
+ THREE.Texture.call( this, video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
- if ( ! geometryGroup.__inittedArrays ) {
+ this.generateMipmaps = false;
- return;
+ var scope = this;
- }
+ function update() {
- var normalType = bufferGuessNormalType( material ),
- vertexColorType = bufferGuessVertexColorType( material ),
- uvType = bufferGuessUVType( material ),
+ requestAnimationFrame( update );
- needsSmoothNormals = ( normalType === THREE.SmoothShading );
+ if ( video.readyState >= video.HAVE_CURRENT_DATA ) {
- var f, fl, fi, face,
- vertexNormals, faceNormal, normal,
- vertexColors, faceColor,
- vertexTangents,
- uv, uv2, v1, v2, v3, v4, t1, t2, t3, t4, n1, n2, n3, n4,
- c1, c2, c3, c4,
- sw1, sw2, sw3, sw4,
- si1, si2, si3, si4,
- sa1, sa2, sa3, sa4,
- sb1, sb2, sb3, sb4,
- m, ml, i, il,
- vn, uvi, uv2i,
- vk, vkl, vka,
- nka, chf, faceVertexNormals,
- a,
+ scope.needsUpdate = true;
- vertexIndex = 0,
+ }
- offset = 0,
- offset_uv = 0,
- offset_uv2 = 0,
- offset_face = 0,
- offset_normal = 0,
- offset_tangent = 0,
- offset_line = 0,
- offset_color = 0,
- offset_skin = 0,
- offset_morphTarget = 0,
- offset_custom = 0,
- offset_customSrc = 0,
+ }
- value,
+ update();
- vertexArray = geometryGroup.__vertexArray,
- uvArray = geometryGroup.__uvArray,
- uv2Array = geometryGroup.__uv2Array,
- normalArray = geometryGroup.__normalArray,
- tangentArray = geometryGroup.__tangentArray,
- colorArray = geometryGroup.__colorArray,
+};
- skinIndexArray = geometryGroup.__skinIndexArray,
- skinWeightArray = geometryGroup.__skinWeightArray,
+THREE.VideoTexture.prototype = Object.create( THREE.Texture.prototype );
+THREE.VideoTexture.prototype.constructor = THREE.VideoTexture;
- morphTargetsArrays = geometryGroup.__morphTargetsArrays,
- morphNormalsArrays = geometryGroup.__morphNormalsArrays,
+// File:src/objects/Group.js
- customAttributes = geometryGroup.__webglCustomAttributesList,
- customAttribute,
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
- faceArray = geometryGroup.__faceArray,
- lineArray = geometryGroup.__lineArray,
+THREE.Group = function () {
- geometry = object.geometry, // this is shared for all chunks
+ THREE.Object3D.call( this );
- dirtyVertices = geometry.verticesNeedUpdate,
- dirtyElements = geometry.elementsNeedUpdate,
- dirtyUvs = geometry.uvsNeedUpdate,
- dirtyNormals = geometry.normalsNeedUpdate,
- dirtyTangents = geometry.tangentsNeedUpdate,
- dirtyColors = geometry.colorsNeedUpdate,
- dirtyMorphTargets = geometry.morphTargetsNeedUpdate,
+ this.type = 'Group';
- vertices = geometry.vertices,
- chunk_faces3 = geometryGroup.faces3,
- obj_faces = geometry.faces,
+};
- obj_uvs = geometry.faceVertexUvs[ 0 ],
- obj_uvs2 = geometry.faceVertexUvs[ 1 ],
+THREE.Group.prototype = Object.assign( Object.create( THREE.Object3D.prototype ), {
- obj_colors = geometry.colors,
+ constructor: THREE.Group
- obj_skinIndices = geometry.skinIndices,
- obj_skinWeights = geometry.skinWeights,
+} );
- morphTargets = geometry.morphTargets,
- morphNormals = geometry.morphNormals;
+// File:src/objects/Points.js
- if ( dirtyVertices ) {
+/**
+ * @author alteredq / http://alteredqualia.com/
+ */
- for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+THREE.Points = function ( geometry, material ) {
- face = obj_faces[ chunk_faces3[ f ] ];
+ THREE.Object3D.call( this );
- v1 = vertices[ face.a ];
- v2 = vertices[ face.b ];
- v3 = vertices[ face.c ];
+ this.type = 'Points';
- vertexArray[ offset ] = v1.x;
- vertexArray[ offset + 1 ] = v1.y;
- vertexArray[ offset + 2 ] = v1.z;
+ this.geometry = geometry !== undefined ? geometry : new THREE.BufferGeometry();
+ this.material = material !== undefined ? material : new THREE.PointsMaterial( { color: Math.random() * 0xffffff } );
- vertexArray[ offset + 3 ] = v2.x;
- vertexArray[ offset + 4 ] = v2.y;
- vertexArray[ offset + 5 ] = v2.z;
+};
- vertexArray[ offset + 6 ] = v3.x;
- vertexArray[ offset + 7 ] = v3.y;
- vertexArray[ offset + 8 ] = v3.z;
+THREE.Points.prototype = Object.assign( Object.create( THREE.Object3D.prototype ), {
- offset += 9;
+ constructor: THREE.Points,
- }
+ raycast: ( function () {
- _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglVertexBuffer );
- _gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint );
+ var inverseMatrix = new THREE.Matrix4();
+ var ray = new THREE.Ray();
+ var sphere = new THREE.Sphere();
- }
+ return function raycast( raycaster, intersects ) {
- if ( dirtyMorphTargets ) {
+ var object = this;
+ var geometry = this.geometry;
+ var matrixWorld = this.matrixWorld;
+ var threshold = raycaster.params.Points.threshold;
- for ( vk = 0, vkl = morphTargets.length; vk < vkl; vk ++ ) {
+ // Checking boundingSphere distance to ray
- offset_morphTarget = 0;
+ if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
- for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+ sphere.copy( geometry.boundingSphere );
+ sphere.applyMatrix4( matrixWorld );
- chf = chunk_faces3[ f ];
- face = obj_faces[ chf ];
+ if ( raycaster.ray.intersectsSphere( sphere ) === false ) return;
- // morph positions
+ //
- v1 = morphTargets[ vk ].vertices[ face.a ];
- v2 = morphTargets[ vk ].vertices[ face.b ];
- v3 = morphTargets[ vk ].vertices[ face.c ];
+ inverseMatrix.getInverse( matrixWorld );
+ ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );
- vka = morphTargetsArrays[ vk ];
+ var localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
+ var localThresholdSq = localThreshold * localThreshold;
+ var position = new THREE.Vector3();
- vka[ offset_morphTarget ] = v1.x;
- vka[ offset_morphTarget + 1 ] = v1.y;
- vka[ offset_morphTarget + 2 ] = v1.z;
+ function testPoint( point, index ) {
- vka[ offset_morphTarget + 3 ] = v2.x;
- vka[ offset_morphTarget + 4 ] = v2.y;
- vka[ offset_morphTarget + 5 ] = v2.z;
+ var rayPointDistanceSq = ray.distanceSqToPoint( point );
- vka[ offset_morphTarget + 6 ] = v3.x;
- vka[ offset_morphTarget + 7 ] = v3.y;
- vka[ offset_morphTarget + 8 ] = v3.z;
+ if ( rayPointDistanceSq < localThresholdSq ) {
- // morph normals
+ var intersectPoint = ray.closestPointToPoint( point );
+ intersectPoint.applyMatrix4( matrixWorld );
- if ( material.morphNormals ) {
+ var distance = raycaster.ray.origin.distanceTo( intersectPoint );
- if ( needsSmoothNormals ) {
+ if ( distance < raycaster.near || distance > raycaster.far ) return;
- faceVertexNormals = morphNormals[ vk ].vertexNormals[ chf ];
+ intersects.push( {
- n1 = faceVertexNormals.a;
- n2 = faceVertexNormals.b;
- n3 = faceVertexNormals.c;
+ distance: distance,
+ distanceToRay: Math.sqrt( rayPointDistanceSq ),
+ point: intersectPoint.clone(),
+ index: index,
+ face: null,
+ object: object
- } else {
+ } );
- n1 = morphNormals[ vk ].faceNormals[ chf ];
- n2 = n1;
- n3 = n1;
+ }
- }
+ }
- nka = morphNormalsArrays[ vk ];
+ if ( geometry instanceof THREE.BufferGeometry ) {
- nka[ offset_morphTarget ] = n1.x;
- nka[ offset_morphTarget + 1 ] = n1.y;
- nka[ offset_morphTarget + 2 ] = n1.z;
+ var index = geometry.index;
+ var attributes = geometry.attributes;
+ var positions = attributes.position.array;
- nka[ offset_morphTarget + 3 ] = n2.x;
- nka[ offset_morphTarget + 4 ] = n2.y;
- nka[ offset_morphTarget + 5 ] = n2.z;
+ if ( index !== null ) {
- nka[ offset_morphTarget + 6 ] = n3.x;
- nka[ offset_morphTarget + 7 ] = n3.y;
- nka[ offset_morphTarget + 8 ] = n3.z;
+ var indices = index.array;
- }
+ for ( var i = 0, il = indices.length; i < il; i ++ ) {
- //
+ var a = indices[ i ];
- offset_morphTarget += 9;
+ position.fromArray( positions, a * 3 );
- }
+ testPoint( position, a );
- _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ vk ] );
- _gl.bufferData( _gl.ARRAY_BUFFER, morphTargetsArrays[ vk ], hint );
+ }
- if ( material.morphNormals ) {
+ } else {
- _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphNormalsBuffers[ vk ] );
- _gl.bufferData( _gl.ARRAY_BUFFER, morphNormalsArrays[ vk ], hint );
+ for ( var i = 0, l = positions.length / 3; i < l; i ++ ) {
- }
+ position.fromArray( positions, i * 3 );
- }
+ testPoint( position, i );
- }
+ }
- if ( obj_skinWeights.length ) {
+ }
- for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+ } else {
- face = obj_faces[ chunk_faces3[ f ] ];
+ var vertices = geometry.vertices;
- // weights
+ for ( var i = 0, l = vertices.length; i < l; i ++ ) {
- sw1 = obj_skinWeights[ face.a ];
- sw2 = obj_skinWeights[ face.b ];
- sw3 = obj_skinWeights[ face.c ];
+ testPoint( vertices[ i ], i );
- skinWeightArray[ offset_skin ] = sw1.x;
- skinWeightArray[ offset_skin + 1 ] = sw1.y;
- skinWeightArray[ offset_skin + 2 ] = sw1.z;
- skinWeightArray[ offset_skin + 3 ] = sw1.w;
+ }
- skinWeightArray[ offset_skin + 4 ] = sw2.x;
- skinWeightArray[ offset_skin + 5 ] = sw2.y;
- skinWeightArray[ offset_skin + 6 ] = sw2.z;
- skinWeightArray[ offset_skin + 7 ] = sw2.w;
+ }
- skinWeightArray[ offset_skin + 8 ] = sw3.x;
- skinWeightArray[ offset_skin + 9 ] = sw3.y;
- skinWeightArray[ offset_skin + 10 ] = sw3.z;
- skinWeightArray[ offset_skin + 11 ] = sw3.w;
+ };
- // indices
+ }() ),
- si1 = obj_skinIndices[ face.a ];
- si2 = obj_skinIndices[ face.b ];
- si3 = obj_skinIndices[ face.c ];
+ clone: function () {
- skinIndexArray[ offset_skin ] = si1.x;
- skinIndexArray[ offset_skin + 1 ] = si1.y;
- skinIndexArray[ offset_skin + 2 ] = si1.z;
- skinIndexArray[ offset_skin + 3 ] = si1.w;
+ return new this.constructor( this.geometry, this.material ).copy( this );
- skinIndexArray[ offset_skin + 4 ] = si2.x;
- skinIndexArray[ offset_skin + 5 ] = si2.y;
- skinIndexArray[ offset_skin + 6 ] = si2.z;
- skinIndexArray[ offset_skin + 7 ] = si2.w;
+ }
- skinIndexArray[ offset_skin + 8 ] = si3.x;
- skinIndexArray[ offset_skin + 9 ] = si3.y;
- skinIndexArray[ offset_skin + 10 ] = si3.z;
- skinIndexArray[ offset_skin + 11 ] = si3.w;
+} );
- offset_skin += 12;
+// File:src/objects/Line.js
- }
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
- if ( offset_skin > 0 ) {
+THREE.Line = function ( geometry, material, mode ) {
- _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinIndicesBuffer );
- _gl.bufferData( _gl.ARRAY_BUFFER, skinIndexArray, hint );
+ if ( mode === 1 ) {
- _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinWeightsBuffer );
- _gl.bufferData( _gl.ARRAY_BUFFER, skinWeightArray, hint );
+ console.warn( 'THREE.Line: parameter THREE.LinePieces no longer supported. Created THREE.LineSegments instead.' );
+ return new THREE.LineSegments( geometry, material );
- }
+ }
- }
+ THREE.Object3D.call( this );
- if ( dirtyColors && vertexColorType ) {
+ this.type = 'Line';
- for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+ this.geometry = geometry !== undefined ? geometry : new THREE.BufferGeometry();
+ this.material = material !== undefined ? material : new THREE.LineBasicMaterial( { color: Math.random() * 0xffffff } );
- face = obj_faces[ chunk_faces3[ f ] ];
+};
- vertexColors = face.vertexColors;
- faceColor = face.color;
+THREE.Line.prototype = Object.assign( Object.create( THREE.Object3D.prototype ), {
- if ( vertexColors.length === 3 && vertexColorType === THREE.VertexColors ) {
+ constructor: THREE.Line,
- c1 = vertexColors[ 0 ];
- c2 = vertexColors[ 1 ];
- c3 = vertexColors[ 2 ];
+ raycast: ( function () {
- } else {
+ var inverseMatrix = new THREE.Matrix4();
+ var ray = new THREE.Ray();
+ var sphere = new THREE.Sphere();
- c1 = faceColor;
- c2 = faceColor;
- c3 = faceColor;
+ return function raycast( raycaster, intersects ) {
- }
+ var precision = raycaster.linePrecision;
+ var precisionSq = precision * precision;
- colorArray[ offset_color ] = c1.r;
- colorArray[ offset_color + 1 ] = c1.g;
- colorArray[ offset_color + 2 ] = c1.b;
+ var geometry = this.geometry;
+ var matrixWorld = this.matrixWorld;
- colorArray[ offset_color + 3 ] = c2.r;
- colorArray[ offset_color + 4 ] = c2.g;
- colorArray[ offset_color + 5 ] = c2.b;
+ // Checking boundingSphere distance to ray
- colorArray[ offset_color + 6 ] = c3.r;
- colorArray[ offset_color + 7 ] = c3.g;
- colorArray[ offset_color + 8 ] = c3.b;
+ if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
- offset_color += 9;
+ sphere.copy( geometry.boundingSphere );
+ sphere.applyMatrix4( matrixWorld );
- }
+ if ( raycaster.ray.intersectsSphere( sphere ) === false ) return;
- if ( offset_color > 0 ) {
+ //
- _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglColorBuffer );
- _gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint );
+ inverseMatrix.getInverse( matrixWorld );
+ ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );
- }
+ var vStart = new THREE.Vector3();
+ var vEnd = new THREE.Vector3();
+ var interSegment = new THREE.Vector3();
+ var interRay = new THREE.Vector3();
+ var step = this instanceof THREE.LineSegments ? 2 : 1;
- }
+ if ( geometry instanceof THREE.BufferGeometry ) {
- if ( dirtyTangents && geometry.hasTangents ) {
+ var index = geometry.index;
+ var attributes = geometry.attributes;
+ var positions = attributes.position.array;
- for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+ if ( index !== null ) {
- face = obj_faces[ chunk_faces3[ f ] ];
+ var indices = index.array;
- vertexTangents = face.vertexTangents;
+ for ( var i = 0, l = indices.length - 1; i < l; i += step ) {
- t1 = vertexTangents[ 0 ];
- t2 = vertexTangents[ 1 ];
- t3 = vertexTangents[ 2 ];
+ var a = indices[ i ];
+ var b = indices[ i + 1 ];
- tangentArray[ offset_tangent ] = t1.x;
- tangentArray[ offset_tangent + 1 ] = t1.y;
- tangentArray[ offset_tangent + 2 ] = t1.z;
- tangentArray[ offset_tangent + 3 ] = t1.w;
+ vStart.fromArray( positions, a * 3 );
+ vEnd.fromArray( positions, b * 3 );
- tangentArray[ offset_tangent + 4 ] = t2.x;
- tangentArray[ offset_tangent + 5 ] = t2.y;
- tangentArray[ offset_tangent + 6 ] = t2.z;
- tangentArray[ offset_tangent + 7 ] = t2.w;
+ var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
- tangentArray[ offset_tangent + 8 ] = t3.x;
- tangentArray[ offset_tangent + 9 ] = t3.y;
- tangentArray[ offset_tangent + 10 ] = t3.z;
- tangentArray[ offset_tangent + 11 ] = t3.w;
+ if ( distSq > precisionSq ) continue;
- offset_tangent += 12;
+ interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
- }
+ var distance = raycaster.ray.origin.distanceTo( interRay );
- _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglTangentBuffer );
- _gl.bufferData( _gl.ARRAY_BUFFER, tangentArray, hint );
+ if ( distance < raycaster.near || distance > raycaster.far ) continue;
- }
+ intersects.push( {
- if ( dirtyNormals && normalType ) {
+ distance: distance,
+ // What do we want? intersection point on the ray or on the segment??
+ // point: raycaster.ray.at( distance ),
+ point: interSegment.clone().applyMatrix4( this.matrixWorld ),
+ index: i,
+ face: null,
+ faceIndex: null,
+ object: this
- for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+ } );
- face = obj_faces[ chunk_faces3[ f ] ];
+ }
- vertexNormals = face.vertexNormals;
- faceNormal = face.normal;
+ } else {
- if ( vertexNormals.length === 3 && needsSmoothNormals ) {
+ for ( var i = 0, l = positions.length / 3 - 1; i < l; i += step ) {
- for ( i = 0; i < 3; i ++ ) {
+ vStart.fromArray( positions, 3 * i );
+ vEnd.fromArray( positions, 3 * i + 3 );
- vn = vertexNormals[ i ];
+ var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
- normalArray[ offset_normal ] = vn.x;
- normalArray[ offset_normal + 1 ] = vn.y;
- normalArray[ offset_normal + 2 ] = vn.z;
+ if ( distSq > precisionSq ) continue;
- offset_normal += 3;
+ interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
- }
+ var distance = raycaster.ray.origin.distanceTo( interRay );
- } else {
+ if ( distance < raycaster.near || distance > raycaster.far ) continue;
- for ( i = 0; i < 3; i ++ ) {
+ intersects.push( {
- normalArray[ offset_normal ] = faceNormal.x;
- normalArray[ offset_normal + 1 ] = faceNormal.y;
- normalArray[ offset_normal + 2 ] = faceNormal.z;
+ distance: distance,
+ // What do we want? intersection point on the ray or on the segment??
+ // point: raycaster.ray.at( distance ),
+ point: interSegment.clone().applyMatrix4( this.matrixWorld ),
+ index: i,
+ face: null,
+ faceIndex: null,
+ object: this
- offset_normal += 3;
+ } );
}
}
- }
-
- _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglNormalBuffer );
- _gl.bufferData( _gl.ARRAY_BUFFER, normalArray, hint );
+ } else if ( geometry instanceof THREE.Geometry ) {
- }
+ var vertices = geometry.vertices;
+ var nbVertices = vertices.length;
- if ( dirtyUvs && obj_uvs && uvType ) {
+ for ( var i = 0; i < nbVertices - 1; i += step ) {
- for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+ var distSq = ray.distanceSqToSegment( vertices[ i ], vertices[ i + 1 ], interRay, interSegment );
- fi = chunk_faces3[ f ];
+ if ( distSq > precisionSq ) continue;
- uv = obj_uvs[ fi ];
+ interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
- if ( uv === undefined ) continue;
+ var distance = raycaster.ray.origin.distanceTo( interRay );
- for ( i = 0; i < 3; i ++ ) {
+ if ( distance < raycaster.near || distance > raycaster.far ) continue;
- uvi = uv[ i ];
+ intersects.push( {
- uvArray[ offset_uv ] = uvi.x;
- uvArray[ offset_uv + 1 ] = uvi.y;
+ distance: distance,
+ // What do we want? intersection point on the ray or on the segment??
+ // point: raycaster.ray.at( distance ),
+ point: interSegment.clone().applyMatrix4( this.matrixWorld ),
+ index: i,
+ face: null,
+ faceIndex: null,
+ object: this
- offset_uv += 2;
+ } );
}
}
- if ( offset_uv > 0 ) {
+ };
- _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUVBuffer );
- _gl.bufferData( _gl.ARRAY_BUFFER, uvArray, hint );
+ }() ),
- }
+ clone: function () {
- }
+ return new this.constructor( this.geometry, this.material ).copy( this );
- if ( dirtyUvs && obj_uvs2 && uvType ) {
+ }
- for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+} );
- fi = chunk_faces3[ f ];
+// File:src/objects/LineSegments.js
- uv2 = obj_uvs2[ fi ];
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
- if ( uv2 === undefined ) continue;
+THREE.LineSegments = function ( geometry, material ) {
- for ( i = 0; i < 3; i ++ ) {
+ THREE.Line.call( this, geometry, material );
- uv2i = uv2[ i ];
+ this.type = 'LineSegments';
- uv2Array[ offset_uv2 ] = uv2i.x;
- uv2Array[ offset_uv2 + 1 ] = uv2i.y;
+};
- offset_uv2 += 2;
+THREE.LineSegments.prototype = Object.assign( Object.create( THREE.Line.prototype ), {
- }
+ constructor: THREE.LineSegments
- }
+} );
- if ( offset_uv2 > 0 ) {
+// File:src/objects/Mesh.js
- _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUV2Buffer );
- _gl.bufferData( _gl.ARRAY_BUFFER, uv2Array, hint );
+/**
+ * @author mrdoob / http://mrdoob.com/
+ * @author alteredq / http://alteredqualia.com/
+ * @author mikael emtinger / http://gomo.se/
+ * @author jonobr1 / http://jonobr1.com/
+ */
- }
+THREE.Mesh = function ( geometry, material ) {
- }
+ THREE.Object3D.call( this );
- if ( dirtyElements ) {
+ this.type = 'Mesh';
- for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+ this.geometry = geometry !== undefined ? geometry : new THREE.BufferGeometry();
+ this.material = material !== undefined ? material : new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff } );
- faceArray[ offset_face ] = vertexIndex;
- faceArray[ offset_face + 1 ] = vertexIndex + 1;
- faceArray[ offset_face + 2 ] = vertexIndex + 2;
+ this.drawMode = THREE.TrianglesDrawMode;
- offset_face += 3;
+ this.updateMorphTargets();
- lineArray[ offset_line ] = vertexIndex;
- lineArray[ offset_line + 1 ] = vertexIndex + 1;
+};
- lineArray[ offset_line + 2 ] = vertexIndex;
- lineArray[ offset_line + 3 ] = vertexIndex + 2;
+THREE.Mesh.prototype = Object.assign( Object.create( THREE.Object3D.prototype ), {
- lineArray[ offset_line + 4 ] = vertexIndex + 1;
- lineArray[ offset_line + 5 ] = vertexIndex + 2;
+ constructor: THREE.Mesh,
- offset_line += 6;
+ setDrawMode: function ( value ) {
- vertexIndex += 3;
+ this.drawMode = value;
- }
+ },
- _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglFaceBuffer );
- _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, faceArray, hint );
+ copy: function ( source ) {
- _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglLineBuffer );
- _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, lineArray, hint );
+ THREE.Object3D.prototype.copy.call( this, source );
- }
+ this.drawMode = source.drawMode;
- if ( customAttributes ) {
+ return this;
- for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
+ },
- customAttribute = customAttributes[ i ];
+ updateMorphTargets: function () {
- if ( ! customAttribute.__original.needsUpdate ) continue;
+ if ( this.geometry.morphTargets !== undefined && this.geometry.morphTargets.length > 0 ) {
- offset_custom = 0;
- offset_customSrc = 0;
+ this.morphTargetBase = - 1;
+ this.morphTargetInfluences = [];
+ this.morphTargetDictionary = {};
- if ( customAttribute.size === 1 ) {
+ for ( var m = 0, ml = this.geometry.morphTargets.length; m < ml; m ++ ) {
- if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
+ this.morphTargetInfluences.push( 0 );
+ this.morphTargetDictionary[ this.geometry.morphTargets[ m ].name ] = m;
- for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+ }
- face = obj_faces[ chunk_faces3[ f ] ];
+ }
- customAttribute.array[ offset_custom ] = customAttribute.value[ face.a ];
- customAttribute.array[ offset_custom + 1 ] = customAttribute.value[ face.b ];
- customAttribute.array[ offset_custom + 2 ] = customAttribute.value[ face.c ];
+ },
- offset_custom += 3;
+ getMorphTargetIndexByName: function ( name ) {
- }
+ if ( this.morphTargetDictionary[ name ] !== undefined ) {
- } else if ( customAttribute.boundTo === "faces" ) {
+ return this.morphTargetDictionary[ name ];
- for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+ }
- value = customAttribute.value[ chunk_faces3[ f ] ];
+ console.warn( 'THREE.Mesh.getMorphTargetIndexByName: morph target ' + name + ' does not exist. Returning 0.' );
- customAttribute.array[ offset_custom ] = value;
- customAttribute.array[ offset_custom + 1 ] = value;
- customAttribute.array[ offset_custom + 2 ] = value;
+ return 0;
- offset_custom += 3;
+ },
- }
+ raycast: ( function () {
- }
+ var inverseMatrix = new THREE.Matrix4();
+ var ray = new THREE.Ray();
+ var sphere = new THREE.Sphere();
- } else if ( customAttribute.size === 2 ) {
+ var vA = new THREE.Vector3();
+ var vB = new THREE.Vector3();
+ var vC = new THREE.Vector3();
- if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
+ var tempA = new THREE.Vector3();
+ var tempB = new THREE.Vector3();
+ var tempC = new THREE.Vector3();
- for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+ var uvA = new THREE.Vector2();
+ var uvB = new THREE.Vector2();
+ var uvC = new THREE.Vector2();
- face = obj_faces[ chunk_faces3[ f ] ];
+ var barycoord = new THREE.Vector3();
- v1 = customAttribute.value[ face.a ];
- v2 = customAttribute.value[ face.b ];
- v3 = customAttribute.value[ face.c ];
+ var intersectionPoint = new THREE.Vector3();
+ var intersectionPointWorld = new THREE.Vector3();
- customAttribute.array[ offset_custom ] = v1.x;
- customAttribute.array[ offset_custom + 1 ] = v1.y;
+ function uvIntersection( point, p1, p2, p3, uv1, uv2, uv3 ) {
- customAttribute.array[ offset_custom + 2 ] = v2.x;
- customAttribute.array[ offset_custom + 3 ] = v2.y;
+ THREE.Triangle.barycoordFromPoint( point, p1, p2, p3, barycoord );
- customAttribute.array[ offset_custom + 4 ] = v3.x;
- customAttribute.array[ offset_custom + 5 ] = v3.y;
+ uv1.multiplyScalar( barycoord.x );
+ uv2.multiplyScalar( barycoord.y );
+ uv3.multiplyScalar( barycoord.z );
- offset_custom += 6;
+ uv1.add( uv2 ).add( uv3 );
- }
+ return uv1.clone();
- } else if ( customAttribute.boundTo === "faces" ) {
-
- for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
- value = customAttribute.value[ chunk_faces3[ f ] ];
+ }
- v1 = value;
- v2 = value;
- v3 = value;
+ function checkIntersection( object, raycaster, ray, pA, pB, pC, point ) {
- customAttribute.array[ offset_custom ] = v1.x;
- customAttribute.array[ offset_custom + 1 ] = v1.y;
+ var intersect;
+ var material = object.material;
- customAttribute.array[ offset_custom + 2 ] = v2.x;
- customAttribute.array[ offset_custom + 3 ] = v2.y;
+ if ( material.side === THREE.BackSide ) {
- customAttribute.array[ offset_custom + 4 ] = v3.x;
- customAttribute.array[ offset_custom + 5 ] = v3.y;
+ intersect = ray.intersectTriangle( pC, pB, pA, true, point );
- offset_custom += 6;
+ } else {
- }
+ intersect = ray.intersectTriangle( pA, pB, pC, material.side !== THREE.DoubleSide, point );
- }
+ }
- } else if ( customAttribute.size === 3 ) {
+ if ( intersect === null ) return null;
- var pp;
+ intersectionPointWorld.copy( point );
+ intersectionPointWorld.applyMatrix4( object.matrixWorld );
- if ( customAttribute.type === "c" ) {
+ var distance = raycaster.ray.origin.distanceTo( intersectionPointWorld );
- pp = [ "r", "g", "b" ];
+ if ( distance < raycaster.near || distance > raycaster.far ) return null;
- } else {
+ return {
+ distance: distance,
+ point: intersectionPointWorld.clone(),
+ object: object
+ };
- pp = [ "x", "y", "z" ];
+ }
- }
+ function checkBufferGeometryIntersection( object, raycaster, ray, positions, uvs, a, b, c ) {
- if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
+ vA.fromArray( positions, a * 3 );
+ vB.fromArray( positions, b * 3 );
+ vC.fromArray( positions, c * 3 );
- for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+ var intersection = checkIntersection( object, raycaster, ray, vA, vB, vC, intersectionPoint );
- face = obj_faces[ chunk_faces3[ f ] ];
+ if ( intersection ) {
- v1 = customAttribute.value[ face.a ];
- v2 = customAttribute.value[ face.b ];
- v3 = customAttribute.value[ face.c ];
+ if ( uvs ) {
- customAttribute.array[ offset_custom ] = v1[ pp[ 0 ] ];
- customAttribute.array[ offset_custom + 1 ] = v1[ pp[ 1 ] ];
- customAttribute.array[ offset_custom + 2 ] = v1[ pp[ 2 ] ];
+ uvA.fromArray( uvs, a * 2 );
+ uvB.fromArray( uvs, b * 2 );
+ uvC.fromArray( uvs, c * 2 );
- customAttribute.array[ offset_custom + 3 ] = v2[ pp[ 0 ] ];
- customAttribute.array[ offset_custom + 4 ] = v2[ pp[ 1 ] ];
- customAttribute.array[ offset_custom + 5 ] = v2[ pp[ 2 ] ];
+ intersection.uv = uvIntersection( intersectionPoint, vA, vB, vC, uvA, uvB, uvC );
- customAttribute.array[ offset_custom + 6 ] = v3[ pp[ 0 ] ];
- customAttribute.array[ offset_custom + 7 ] = v3[ pp[ 1 ] ];
- customAttribute.array[ offset_custom + 8 ] = v3[ pp[ 2 ] ];
+ }
- offset_custom += 9;
+ intersection.face = new THREE.Face3( a, b, c, THREE.Triangle.normal( vA, vB, vC ) );
+ intersection.faceIndex = a;
- }
+ }
- } else if ( customAttribute.boundTo === "faces" ) {
+ return intersection;
- for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+ }
- value = customAttribute.value[ chunk_faces3[ f ] ];
+ return function raycast( raycaster, intersects ) {
- v1 = value;
- v2 = value;
- v3 = value;
+ var geometry = this.geometry;
+ var material = this.material;
+ var matrixWorld = this.matrixWorld;
- customAttribute.array[ offset_custom ] = v1[ pp[ 0 ] ];
- customAttribute.array[ offset_custom + 1 ] = v1[ pp[ 1 ] ];
- customAttribute.array[ offset_custom + 2 ] = v1[ pp[ 2 ] ];
+ if ( material === undefined ) return;
- customAttribute.array[ offset_custom + 3 ] = v2[ pp[ 0 ] ];
- customAttribute.array[ offset_custom + 4 ] = v2[ pp[ 1 ] ];
- customAttribute.array[ offset_custom + 5 ] = v2[ pp[ 2 ] ];
+ // Checking boundingSphere distance to ray
- customAttribute.array[ offset_custom + 6 ] = v3[ pp[ 0 ] ];
- customAttribute.array[ offset_custom + 7 ] = v3[ pp[ 1 ] ];
- customAttribute.array[ offset_custom + 8 ] = v3[ pp[ 2 ] ];
+ if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
- offset_custom += 9;
+ sphere.copy( geometry.boundingSphere );
+ sphere.applyMatrix4( matrixWorld );
- }
+ if ( raycaster.ray.intersectsSphere( sphere ) === false ) return;
- } else if ( customAttribute.boundTo === "faceVertices" ) {
+ //
- for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+ inverseMatrix.getInverse( matrixWorld );
+ ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );
- value = customAttribute.value[ chunk_faces3[ f ] ];
+ // Check boundingBox before continuing
- v1 = value[ 0 ];
- v2 = value[ 1 ];
- v3 = value[ 2 ];
+ if ( geometry.boundingBox !== null ) {
- customAttribute.array[ offset_custom ] = v1[ pp[ 0 ] ];
- customAttribute.array[ offset_custom + 1 ] = v1[ pp[ 1 ] ];
- customAttribute.array[ offset_custom + 2 ] = v1[ pp[ 2 ] ];
+ if ( ray.intersectsBox( geometry.boundingBox ) === false ) return;
- customAttribute.array[ offset_custom + 3 ] = v2[ pp[ 0 ] ];
- customAttribute.array[ offset_custom + 4 ] = v2[ pp[ 1 ] ];
- customAttribute.array[ offset_custom + 5 ] = v2[ pp[ 2 ] ];
+ }
- customAttribute.array[ offset_custom + 6 ] = v3[ pp[ 0 ] ];
- customAttribute.array[ offset_custom + 7 ] = v3[ pp[ 1 ] ];
- customAttribute.array[ offset_custom + 8 ] = v3[ pp[ 2 ] ];
+ var uvs, intersection;
- offset_custom += 9;
+ if ( geometry instanceof THREE.BufferGeometry ) {
- }
+ var a, b, c;
+ var index = geometry.index;
+ var attributes = geometry.attributes;
+ var positions = attributes.position.array;
- }
+ if ( attributes.uv !== undefined ) {
- } else if ( customAttribute.size === 4 ) {
+ uvs = attributes.uv.array;
- if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
+ }
- for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+ if ( index !== null ) {
- face = obj_faces[ chunk_faces3[ f ] ];
+ var indices = index.array;
- v1 = customAttribute.value[ face.a ];
- v2 = customAttribute.value[ face.b ];
- v3 = customAttribute.value[ face.c ];
+ for ( var i = 0, l = indices.length; i < l; i += 3 ) {
- customAttribute.array[ offset_custom ] = v1.x;
- customAttribute.array[ offset_custom + 1 ] = v1.y;
- customAttribute.array[ offset_custom + 2 ] = v1.z;
- customAttribute.array[ offset_custom + 3 ] = v1.w;
+ a = indices[ i ];
+ b = indices[ i + 1 ];
+ c = indices[ i + 2 ];
- customAttribute.array[ offset_custom + 4 ] = v2.x;
- customAttribute.array[ offset_custom + 5 ] = v2.y;
- customAttribute.array[ offset_custom + 6 ] = v2.z;
- customAttribute.array[ offset_custom + 7 ] = v2.w;
+ intersection = checkBufferGeometryIntersection( this, raycaster, ray, positions, uvs, a, b, c );
- customAttribute.array[ offset_custom + 8 ] = v3.x;
- customAttribute.array[ offset_custom + 9 ] = v3.y;
- customAttribute.array[ offset_custom + 10 ] = v3.z;
- customAttribute.array[ offset_custom + 11 ] = v3.w;
+ if ( intersection ) {
- offset_custom += 12;
+ intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indices buffer semantics
+ intersects.push( intersection );
}
- } else if ( customAttribute.boundTo === "faces" ) {
+ }
- for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+ } else {
- value = customAttribute.value[ chunk_faces3[ f ] ];
- v1 = value;
- v2 = value;
- v3 = value;
+ for ( var i = 0, l = positions.length; i < l; i += 9 ) {
- customAttribute.array[ offset_custom ] = v1.x;
- customAttribute.array[ offset_custom + 1 ] = v1.y;
- customAttribute.array[ offset_custom + 2 ] = v1.z;
- customAttribute.array[ offset_custom + 3 ] = v1.w;
+ a = i / 3;
+ b = a + 1;
+ c = a + 2;
- customAttribute.array[ offset_custom + 4 ] = v2.x;
- customAttribute.array[ offset_custom + 5 ] = v2.y;
- customAttribute.array[ offset_custom + 6 ] = v2.z;
- customAttribute.array[ offset_custom + 7 ] = v2.w;
+ intersection = checkBufferGeometryIntersection( this, raycaster, ray, positions, uvs, a, b, c );
- customAttribute.array[ offset_custom + 8 ] = v3.x;
- customAttribute.array[ offset_custom + 9 ] = v3.y;
- customAttribute.array[ offset_custom + 10 ] = v3.z;
- customAttribute.array[ offset_custom + 11 ] = v3.w;
+ if ( intersection ) {
- offset_custom += 12;
+ intersection.index = a; // triangle number in positions buffer semantics
+ intersects.push( intersection );
}
- } else if ( customAttribute.boundTo === "faceVertices" ) {
+ }
- for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+ }
- value = customAttribute.value[ chunk_faces3[ f ] ];
+ } else if ( geometry instanceof THREE.Geometry ) {
- v1 = value[ 0 ];
- v2 = value[ 1 ];
- v3 = value[ 2 ];
+ var fvA, fvB, fvC;
+ var isFaceMaterial = material instanceof THREE.MultiMaterial;
+ var materials = isFaceMaterial === true ? material.materials : null;
- customAttribute.array[ offset_custom ] = v1.x;
- customAttribute.array[ offset_custom + 1 ] = v1.y;
- customAttribute.array[ offset_custom + 2 ] = v1.z;
- customAttribute.array[ offset_custom + 3 ] = v1.w;
+ var vertices = geometry.vertices;
+ var faces = geometry.faces;
+ var faceVertexUvs = geometry.faceVertexUvs[ 0 ];
+ if ( faceVertexUvs.length > 0 ) uvs = faceVertexUvs;
- customAttribute.array[ offset_custom + 4 ] = v2.x;
- customAttribute.array[ offset_custom + 5 ] = v2.y;
- customAttribute.array[ offset_custom + 6 ] = v2.z;
- customAttribute.array[ offset_custom + 7 ] = v2.w;
+ for ( var f = 0, fl = faces.length; f < fl; f ++ ) {
- customAttribute.array[ offset_custom + 8 ] = v3.x;
- customAttribute.array[ offset_custom + 9 ] = v3.y;
- customAttribute.array[ offset_custom + 10 ] = v3.z;
- customAttribute.array[ offset_custom + 11 ] = v3.w;
+ var face = faces[ f ];
+ var faceMaterial = isFaceMaterial === true ? materials[ face.materialIndex ] : material;
- offset_custom += 12;
+ if ( faceMaterial === undefined ) continue;
- }
+ fvA = vertices[ face.a ];
+ fvB = vertices[ face.b ];
+ fvC = vertices[ face.c ];
- }
+ if ( faceMaterial.morphTargets === true ) {
- }
+ var morphTargets = geometry.morphTargets;
+ var morphInfluences = this.morphTargetInfluences;
- _gl.bindBuffer( _gl.ARRAY_BUFFER, customAttribute.buffer );
- _gl.bufferData( _gl.ARRAY_BUFFER, customAttribute.array, hint );
+ vA.set( 0, 0, 0 );
+ vB.set( 0, 0, 0 );
+ vC.set( 0, 0, 0 );
- }
+ for ( var t = 0, tl = morphTargets.length; t < tl; t ++ ) {
- }
+ var influence = morphInfluences[ t ];
- if ( dispose ) {
+ if ( influence === 0 ) continue;
- delete geometryGroup.__inittedArrays;
- delete geometryGroup.__colorArray;
- delete geometryGroup.__normalArray;
- delete geometryGroup.__tangentArray;
- delete geometryGroup.__uvArray;
- delete geometryGroup.__uv2Array;
- delete geometryGroup.__faceArray;
- delete geometryGroup.__vertexArray;
- delete geometryGroup.__lineArray;
- delete geometryGroup.__skinIndexArray;
- delete geometryGroup.__skinWeightArray;
+ var targets = morphTargets[ t ].vertices;
- }
+ vA.addScaledVector( tempA.subVectors( targets[ face.a ], fvA ), influence );
+ vB.addScaledVector( tempB.subVectors( targets[ face.b ], fvB ), influence );
+ vC.addScaledVector( tempC.subVectors( targets[ face.c ], fvC ), influence );
- };
+ }
- function setDirectBuffers ( geometry, hint, dispose ) {
+ vA.add( fvA );
+ vB.add( fvB );
+ vC.add( fvC );
- var attributes = geometry.attributes;
+ fvA = vA;
+ fvB = vB;
+ fvC = vC;
- var attributeName, attributeItem;
+ }
- for ( attributeName in attributes ) {
+ intersection = checkIntersection( this, raycaster, ray, fvA, fvB, fvC, intersectionPoint );
- attributeItem = attributes[ attributeName ];
+ if ( intersection ) {
- if ( attributeItem.needsUpdate ) {
+ if ( uvs ) {
- if ( attributeName === 'index' ) {
+ var uvs_f = uvs[ f ];
+ uvA.copy( uvs_f[ 0 ] );
+ uvB.copy( uvs_f[ 1 ] );
+ uvC.copy( uvs_f[ 2 ] );
- _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, attributeItem.buffer );
- _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, attributeItem.array, hint );
+ intersection.uv = uvIntersection( intersectionPoint, fvA, fvB, fvC, uvA, uvB, uvC );
- } else {
+ }
- _gl.bindBuffer( _gl.ARRAY_BUFFER, attributeItem.buffer );
- _gl.bufferData( _gl.ARRAY_BUFFER, attributeItem.array, hint );
+ intersection.face = face;
+ intersection.faceIndex = f;
+ intersects.push( intersection );
- }
+ }
- attributeItem.needsUpdate = false;
+ }
}
- if ( dispose && ! attributeItem.dynamic ) {
+ };
- attributeItem.array = null;
+ }() ),
- }
+ clone: function () {
- }
+ return new this.constructor( this.geometry, this.material ).copy( this );
- };
+ }
- // Buffer rendering
+} );
- this.renderBufferImmediate = function ( object, program, material ) {
+// File:src/objects/Bone.js
- if ( object.hasPositions && ! object.__webglVertexBuffer ) object.__webglVertexBuffer = _gl.createBuffer();
- if ( object.hasNormals && ! object.__webglNormalBuffer ) object.__webglNormalBuffer = _gl.createBuffer();
- if ( object.hasUvs && ! object.__webglUvBuffer ) object.__webglUvBuffer = _gl.createBuffer();
- if ( object.hasColors && ! object.__webglColorBuffer ) object.__webglColorBuffer = _gl.createBuffer();
+/**
+ * @author mikael emtinger / http://gomo.se/
+ * @author alteredq / http://alteredqualia.com/
+ * @author ikerr / http://verold.com
+ */
- if ( object.hasPositions ) {
+THREE.Bone = function ( skin ) {
- _gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglVertexBuffer );
- _gl.bufferData( _gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW );
- _gl.enableVertexAttribArray( program.attributes.position );
- _gl.vertexAttribPointer( program.attributes.position, 3, _gl.FLOAT, false, 0, 0 );
+ THREE.Object3D.call( this );
- }
+ this.type = 'Bone';
- if ( object.hasNormals ) {
+ this.skin = skin;
- _gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglNormalBuffer );
+};
- if ( material.shading === THREE.FlatShading ) {
+THREE.Bone.prototype = Object.assign( Object.create( THREE.Object3D.prototype ), {
- var nx, ny, nz,
- nax, nbx, ncx, nay, nby, ncy, naz, nbz, ncz,
- normalArray,
- i, il = object.count * 3;
+ constructor: THREE.Bone,
- for( i = 0; i < il; i += 9 ) {
+ copy: function ( source ) {
- normalArray = object.normalArray;
+ THREE.Object3D.prototype.copy.call( this, source );
- nax = normalArray[ i ];
- nay = normalArray[ i + 1 ];
- naz = normalArray[ i + 2 ];
+ this.skin = source.skin;
- nbx = normalArray[ i + 3 ];
- nby = normalArray[ i + 4 ];
- nbz = normalArray[ i + 5 ];
+ return this;
- ncx = normalArray[ i + 6 ];
- ncy = normalArray[ i + 7 ];
- ncz = normalArray[ i + 8 ];
+ }
- nx = ( nax + nbx + ncx ) / 3;
- ny = ( nay + nby + ncy ) / 3;
- nz = ( naz + nbz + ncz ) / 3;
+} );
- normalArray[ i ] = nx;
- normalArray[ i + 1 ] = ny;
- normalArray[ i + 2 ] = nz;
+// File:src/objects/Skeleton.js
- normalArray[ i + 3 ] = nx;
- normalArray[ i + 4 ] = ny;
- normalArray[ i + 5 ] = nz;
+/**
+ * @author mikael emtinger / http://gomo.se/
+ * @author alteredq / http://alteredqualia.com/
+ * @author michael guerrero / http://realitymeltdown.com
+ * @author ikerr / http://verold.com
+ */
- normalArray[ i + 6 ] = nx;
- normalArray[ i + 7 ] = ny;
- normalArray[ i + 8 ] = nz;
+THREE.Skeleton = function ( bones, boneInverses, useVertexTexture ) {
- }
+ this.useVertexTexture = useVertexTexture !== undefined ? useVertexTexture : true;
- }
+ this.identityMatrix = new THREE.Matrix4();
- _gl.bufferData( _gl.ARRAY_BUFFER, object.normalArray, _gl.DYNAMIC_DRAW );
- _gl.enableVertexAttribArray( program.attributes.normal );
- _gl.vertexAttribPointer( program.attributes.normal, 3, _gl.FLOAT, false, 0, 0 );
+ // copy the bone array
- }
+ bones = bones || [];
- if ( object.hasUvs && material.map ) {
+ this.bones = bones.slice( 0 );
- _gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglUvBuffer );
- _gl.bufferData( _gl.ARRAY_BUFFER, object.uvArray, _gl.DYNAMIC_DRAW );
- _gl.enableVertexAttribArray( program.attributes.uv );
- _gl.vertexAttribPointer( program.attributes.uv, 2, _gl.FLOAT, false, 0, 0 );
+ // create a bone texture or an array of floats
- }
+ if ( this.useVertexTexture ) {
- if ( object.hasColors && material.vertexColors !== THREE.NoColors ) {
+ // layout (1 matrix = 4 pixels)
+ // RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
+ // with 8x8 pixel texture max 16 bones * 4 pixels = (8 * 8)
+ // 16x16 pixel texture max 64 bones * 4 pixels = (16 * 16)
+ // 32x32 pixel texture max 256 bones * 4 pixels = (32 * 32)
+ // 64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64)
- _gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglColorBuffer );
- _gl.bufferData( _gl.ARRAY_BUFFER, object.colorArray, _gl.DYNAMIC_DRAW );
- _gl.enableVertexAttribArray( program.attributes.color );
- _gl.vertexAttribPointer( program.attributes.color, 3, _gl.FLOAT, false, 0, 0 );
- }
+ var size = Math.sqrt( this.bones.length * 4 ); // 4 pixels needed for 1 matrix
+ size = THREE.Math.nextPowerOfTwo( Math.ceil( size ) );
+ size = Math.max( size, 4 );
- _gl.drawArrays( _gl.TRIANGLES, 0, object.count );
+ this.boneTextureWidth = size;
+ this.boneTextureHeight = size;
- object.count = 0;
+ this.boneMatrices = new Float32Array( this.boneTextureWidth * this.boneTextureHeight * 4 ); // 4 floats per RGBA pixel
+ this.boneTexture = new THREE.DataTexture( this.boneMatrices, this.boneTextureWidth, this.boneTextureHeight, THREE.RGBAFormat, THREE.FloatType );
- };
+ } else {
- this.renderBufferDirect = function ( camera, lights, fog, material, geometry, object ) {
+ this.boneMatrices = new Float32Array( 16 * this.bones.length );
- if ( material.visible === false ) return;
+ }
- var linewidth, a, attribute;
- var attributeItem, attributeName, attributePointer, attributeSize;
+ // use the supplied bone inverses or calculate the inverses
- var program = setProgram( camera, lights, fog, material, object );
+ if ( boneInverses === undefined ) {
- var programAttributes = program.attributes;
- var geometryAttributes = geometry.attributes;
+ this.calculateInverses();
- var updateBuffers = false,
- wireframeBit = material.wireframe ? 1 : 0,
- geometryHash = ( geometry.id * 0xffffff ) + ( program.id * 2 ) + wireframeBit;
+ } else {
- if ( geometryHash !== _currentGeometryGroupHash ) {
+ if ( this.bones.length === boneInverses.length ) {
- _currentGeometryGroupHash = geometryHash;
- updateBuffers = true;
+ this.boneInverses = boneInverses.slice( 0 );
- }
+ } else {
- if ( updateBuffers ) {
+ console.warn( 'THREE.Skeleton bonInverses is the wrong length.' );
- disableAttributes();
+ this.boneInverses = [];
- }
+ for ( var b = 0, bl = this.bones.length; b < bl; b ++ ) {
- // render mesh
+ this.boneInverses.push( new THREE.Matrix4() );
- if ( object instanceof THREE.Mesh ) {
+ }
- var index = geometryAttributes[ "index" ];
+ }
- // indexed triangles
+ }
- if ( index ) {
+};
- var offsets = geometry.offsets;
+Object.assign( THREE.Skeleton.prototype, {
- // if there is more than 1 chunk
- // must set attribute pointers to use new offsets for each chunk
- // even if geometry and materials didn't change
+ calculateInverses: function () {
- if ( offsets.length > 1 ) updateBuffers = true;
+ this.boneInverses = [];
- for ( var i = 0, il = offsets.length; i < il; i ++ ) {
+ for ( var b = 0, bl = this.bones.length; b < bl; b ++ ) {
+
+ var inverse = new THREE.Matrix4();
- var startIndex = offsets[ i ].index;
+ if ( this.bones[ b ] ) {
- if ( updateBuffers ) {
+ inverse.getInverse( this.bones[ b ].matrixWorld );
+
+ }
- for ( attributeName in programAttributes ) {
+ this.boneInverses.push( inverse );
- attributePointer = programAttributes[ attributeName ];
- attributeItem = geometryAttributes[ attributeName ];
+ }
- if ( attributePointer >= 0 ) {
+ },
- if ( attributeItem ) {
+ pose: function () {
- attributeSize = attributeItem.itemSize;
- _gl.bindBuffer( _gl.ARRAY_BUFFER, attributeItem.buffer );
- enableAttribute( attributePointer );
- _gl.vertexAttribPointer( attributePointer, attributeSize, _gl.FLOAT, false, 0, startIndex * attributeSize * 4 ); // 4 bytes per Float32
+ var bone;
- } else if ( material.defaultAttributeValues ) {
+ // recover the bind-time world matrices
- if ( material.defaultAttributeValues[ attributeName ].length === 2 ) {
+ for ( var b = 0, bl = this.bones.length; b < bl; b ++ ) {
- _gl.vertexAttrib2fv( attributePointer, material.defaultAttributeValues[ attributeName ] );
+ bone = this.bones[ b ];
- } else if ( material.defaultAttributeValues[ attributeName ].length === 3 ) {
+ if ( bone ) {
- _gl.vertexAttrib3fv( attributePointer, material.defaultAttributeValues[ attributeName ] );
+ bone.matrixWorld.getInverse( this.boneInverses[ b ] );
- }
+ }
- }
+ }
- }
+ // compute the local matrices, positions, rotations and scales
- }
+ for ( var b = 0, bl = this.bones.length; b < bl; b ++ ) {
- // indices
+ bone = this.bones[ b ];
- _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, index.buffer );
+ if ( bone ) {
- }
+ if ( bone.parent instanceof THREE.Bone ) {
- // render indexed triangles
+ bone.matrix.getInverse( bone.parent.matrixWorld );
+ bone.matrix.multiply( bone.matrixWorld );
- _gl.drawElements( _gl.TRIANGLES, offsets[ i ].count, _gl.UNSIGNED_SHORT, offsets[ i ].start * 2 ); // 2 bytes per Uint16
+ } else {
- _this.info.render.calls ++;
- _this.info.render.vertices += offsets[ i ].count; // not really true, here vertices can be shared
- _this.info.render.faces += offsets[ i ].count / 3;
+ bone.matrix.copy( bone.matrixWorld );
}
- // non-indexed triangles
+ bone.matrix.decompose( bone.position, bone.quaternion, bone.scale );
- } else {
+ }
+
+ }
- if ( updateBuffers ) {
+ },
- for ( attributeName in programAttributes ) {
+ update: ( function () {
- if ( attributeName === 'index') continue;
+ var offsetMatrix = new THREE.Matrix4();
- attributePointer = programAttributes[ attributeName ];
- attributeItem = geometryAttributes[ attributeName ];
-
- if ( attributePointer >= 0 ) {
+ return function update() {
- if ( attributeItem ) {
+ // flatten bone matrices to array
- attributeSize = attributeItem.itemSize;
- _gl.bindBuffer( _gl.ARRAY_BUFFER, attributeItem.buffer );
- enableAttribute( attributePointer );
- _gl.vertexAttribPointer( attributePointer, attributeSize, _gl.FLOAT, false, 0, 0 );
+ for ( var b = 0, bl = this.bones.length; b < bl; b ++ ) {
- } else if ( material.defaultAttributeValues && material.defaultAttributeValues[ attributeName ] ) {
+ // compute the offset between the current and the original transform
- if ( material.defaultAttributeValues[ attributeName ].length === 2 ) {
+ var matrix = this.bones[ b ] ? this.bones[ b ].matrixWorld : this.identityMatrix;
- _gl.vertexAttrib2fv( attributePointer, material.defaultAttributeValues[ attributeName ] );
+ offsetMatrix.multiplyMatrices( matrix, this.boneInverses[ b ] );
+ offsetMatrix.toArray( this.boneMatrices, b * 16 );
- } else if ( material.defaultAttributeValues[ attributeName ].length === 3 ) {
+ }
- _gl.vertexAttrib3fv( attributePointer, material.defaultAttributeValues[ attributeName ] );
+ if ( this.useVertexTexture ) {
- }
+ this.boneTexture.needsUpdate = true;
- }
+ }
- }
+ };
- }
+ } )(),
- }
+ clone: function () {
- var position = geometry.attributes[ "position" ];
+ return new THREE.Skeleton( this.bones, this.boneInverses, this.useVertexTexture );
- // render non-indexed triangles
+ }
- _gl.drawArrays( _gl.TRIANGLES, 0, position.numItems / 3 );
+} );
- _this.info.render.calls ++;
- _this.info.render.vertices += position.numItems / 3;
- _this.info.render.faces += position.numItems / 3 / 3;
+// File:src/objects/SkinnedMesh.js
- }
+/**
+ * @author mikael emtinger / http://gomo.se/
+ * @author alteredq / http://alteredqualia.com/
+ * @author ikerr / http://verold.com
+ */
- // render particles
+THREE.SkinnedMesh = function ( geometry, material, useVertexTexture ) {
- } else if ( object instanceof THREE.ParticleSystem ) {
+ THREE.Mesh.call( this, geometry, material );
- if ( updateBuffers ) {
+ this.type = 'SkinnedMesh';
- for ( attributeName in programAttributes ) {
+ this.bindMode = "attached";
+ this.bindMatrix = new THREE.Matrix4();
+ this.bindMatrixInverse = new THREE.Matrix4();
- attributePointer = programAttributes[ attributeName ];
- attributeItem = geometryAttributes[ attributeName ];
-
- if ( attributePointer >= 0 ) {
+ // init bones
- if ( attributeItem ) {
+ // TODO: remove bone creation as there is no reason (other than
+ // convenience) for THREE.SkinnedMesh to do this.
- attributeSize = attributeItem.itemSize;
- _gl.bindBuffer( _gl.ARRAY_BUFFER, attributeItem.buffer );
- enableAttribute( attributePointer );
- _gl.vertexAttribPointer( attributePointer, attributeSize, _gl.FLOAT, false, 0, 0 );
+ var bones = [];
- } else if ( material.defaultAttributeValues && material.defaultAttributeValues[ attributeName ] ) {
+ if ( this.geometry && this.geometry.bones !== undefined ) {
- if ( material.defaultAttributeValues[ attributeName ].length === 2 ) {
+ var bone, gbone;
- _gl.vertexAttrib2fv( attributePointer, material.defaultAttributeValues[ attributeName ] );
+ for ( var b = 0, bl = this.geometry.bones.length; b < bl; ++ b ) {
- } else if ( material.defaultAttributeValues[ attributeName ].length === 3 ) {
+ gbone = this.geometry.bones[ b ];
- _gl.vertexAttrib3fv( attributePointer, material.defaultAttributeValues[ attributeName ] );
+ bone = new THREE.Bone( this );
+ bones.push( bone );
- }
+ bone.name = gbone.name;
+ bone.position.fromArray( gbone.pos );
+ bone.quaternion.fromArray( gbone.rotq );
+ if ( gbone.scl !== undefined ) bone.scale.fromArray( gbone.scl );
- }
+ }
- }
+ for ( var b = 0, bl = this.geometry.bones.length; b < bl; ++ b ) {
- }
+ gbone = this.geometry.bones[ b ];
- var position = geometryAttributes[ "position" ];
+ if ( gbone.parent !== - 1 && gbone.parent !== null &&
+ bones[ gbone.parent ] !== undefined ) {
- // render particles
+ bones[ gbone.parent ].add( bones[ b ] );
- _gl.drawArrays( _gl.POINTS, 0, position.numItems / 3 );
+ } else {
- _this.info.render.calls ++;
- _this.info.render.points += position.numItems / 3;
+ this.add( bones[ b ] );
}
- } else if ( object instanceof THREE.Line ) {
-
- if ( updateBuffers ) {
+ }
- for ( attributeName in programAttributes ) {
+ }
- attributePointer = programAttributes[ attributeName ];
- attributeItem = geometryAttributes[ attributeName ];
-
- if ( attributePointer >= 0 ) {
+ this.normalizeSkinWeights();
- if ( attributeItem ) {
+ this.updateMatrixWorld( true );
+ this.bind( new THREE.Skeleton( bones, undefined, useVertexTexture ), this.matrixWorld );
- attributeSize = attributeItem.itemSize;
- _gl.bindBuffer( _gl.ARRAY_BUFFER, attributeItem.buffer );
- enableAttribute( attributePointer );
- _gl.vertexAttribPointer( attributePointer, attributeSize, _gl.FLOAT, false, 0, 0 );
+};
- } else if ( material.defaultAttributeValues && material.defaultAttributeValues[ attributeName ] ) {
- if ( material.defaultAttributeValues[ attributeName ].length === 2 ) {
+THREE.SkinnedMesh.prototype = Object.assign( Object.create( THREE.Mesh.prototype ), {
- _gl.vertexAttrib2fv( attributePointer, material.defaultAttributeValues[ attributeName ] );
+ constructor: THREE.SkinnedMesh,
- } else if ( material.defaultAttributeValues[ attributeName ].length === 3 ) {
+ bind: function( skeleton, bindMatrix ) {
- _gl.vertexAttrib3fv( attributePointer, material.defaultAttributeValues[ attributeName ] );
+ this.skeleton = skeleton;
- }
+ if ( bindMatrix === undefined ) {
- }
+ this.updateMatrixWorld( true );
- }
+ this.skeleton.calculateInverses();
- }
+ bindMatrix = this.matrixWorld;
- // render lines
+ }
- var primitives = ( object.type === THREE.LineStrip ) ? _gl.LINE_STRIP : _gl.LINES;
+ this.bindMatrix.copy( bindMatrix );
+ this.bindMatrixInverse.getInverse( bindMatrix );
- setLineWidth( material.linewidth );
+ },
- var position = geometryAttributes[ "position" ];
+ pose: function () {
- _gl.drawArrays( primitives, 0, position.numItems / 3 );
+ this.skeleton.pose();
- _this.info.render.calls ++;
- _this.info.render.points += position.numItems;
+ },
- }
+ normalizeSkinWeights: function () {
- }
+ if ( this.geometry instanceof THREE.Geometry ) {
- };
+ for ( var i = 0; i < this.geometry.skinWeights.length; i ++ ) {
- this.renderBuffer = function ( camera, lights, fog, material, geometryGroup, object ) {
+ var sw = this.geometry.skinWeights[ i ];
- if ( material.visible === false ) return;
+ var scale = 1.0 / sw.lengthManhattan();
- var linewidth, a, attribute, i, il;
+ if ( scale !== Infinity ) {
- var program = setProgram( camera, lights, fog, material, object );
+ sw.multiplyScalar( scale );
- var attributes = program.attributes;
+ } else {
- var updateBuffers = false,
- wireframeBit = material.wireframe ? 1 : 0,
- geometryGroupHash = ( geometryGroup.id * 0xffffff ) + ( program.id * 2 ) + wireframeBit;
+ sw.set( 1, 0, 0, 0 ); // do something reasonable
- if ( geometryGroupHash !== _currentGeometryGroupHash ) {
+ }
- _currentGeometryGroupHash = geometryGroupHash;
- updateBuffers = true;
+ }
- }
+ } else if ( this.geometry instanceof THREE.BufferGeometry ) {
- if ( updateBuffers ) {
+ var vec = new THREE.Vector4();
- disableAttributes();
+ var skinWeight = this.geometry.attributes.skinWeight;
- }
+ for ( var i = 0; i < skinWeight.count; i ++ ) {
- // vertices
+ vec.x = skinWeight.getX( i );
+ vec.y = skinWeight.getY( i );
+ vec.z = skinWeight.getZ( i );
+ vec.w = skinWeight.getW( i );
- if ( !material.morphTargets && attributes.position >= 0 ) {
+ var scale = 1.0 / vec.lengthManhattan();
- if ( updateBuffers ) {
+ if ( scale !== Infinity ) {
- _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglVertexBuffer );
- enableAttribute( attributes.position );
- _gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 );
+ vec.multiplyScalar( scale );
- }
+ } else {
- } else {
+ vec.set( 1, 0, 0, 0 ); // do something reasonable
- if ( object.morphTargetBase ) {
+ }
- setupMorphTargets( material, geometryGroup, object );
+ skinWeight.setXYZW( i, vec.x, vec.y, vec.z, vec.w );
}
}
+ },
- if ( updateBuffers ) {
-
- // custom attributes
-
- // Use the per-geometryGroup custom attribute arrays which are setup in initMeshBuffers
-
- if ( geometryGroup.__webglCustomAttributesList ) {
+ updateMatrixWorld: function( force ) {
- for ( i = 0, il = geometryGroup.__webglCustomAttributesList.length; i < il; i ++ ) {
+ THREE.Mesh.prototype.updateMatrixWorld.call( this, true );
- attribute = geometryGroup.__webglCustomAttributesList[ i ];
+ if ( this.bindMode === "attached" ) {
- if ( attributes[ attribute.buffer.belongsToAttribute ] >= 0 ) {
+ this.bindMatrixInverse.getInverse( this.matrixWorld );
- _gl.bindBuffer( _gl.ARRAY_BUFFER, attribute.buffer );
- enableAttribute( attributes[ attribute.buffer.belongsToAttribute ] );
- _gl.vertexAttribPointer( attributes[ attribute.buffer.belongsToAttribute ], attribute.size, _gl.FLOAT, false, 0, 0 );
+ } else if ( this.bindMode === "detached" ) {
- }
+ this.bindMatrixInverse.getInverse( this.bindMatrix );
- }
+ } else {
- }
+ console.warn( 'THREE.SkinnedMesh unrecognized bindMode: ' + this.bindMode );
+ }
- // colors
+ },
- if ( attributes.color >= 0 ) {
+ clone: function() {
- if ( object.geometry.colors.length > 0 || object.geometry.faces.length > 0 ) {
+ return new this.constructor( this.geometry, this.material, this.skeleton.useVertexTexture ).copy( this );
- _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglColorBuffer );
- enableAttribute( attributes.color );
- _gl.vertexAttribPointer( attributes.color, 3, _gl.FLOAT, false, 0, 0 );
+ }
- } else if ( material.defaultAttributeValues ) {
+} );
+// File:src/objects/LOD.js
- _gl.vertexAttrib3fv( attributes.color, material.defaultAttributeValues.color );
+/**
+ * @author mikael emtinger / http://gomo.se/
+ * @author alteredq / http://alteredqualia.com/
+ * @author mrdoob / http://mrdoob.com/
+ */
- }
+THREE.LOD = function () {
- }
+ THREE.Object3D.call( this );
- // normals
+ this.type = 'LOD';
- if ( attributes.normal >= 0 ) {
+ Object.defineProperties( this, {
+ levels: {
+ enumerable: true,
+ value: []
+ }
+ } );
- _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglNormalBuffer );
- enableAttribute( attributes.normal );
- _gl.vertexAttribPointer( attributes.normal, 3, _gl.FLOAT, false, 0, 0 );
+};
- }
- // tangents
+THREE.LOD.prototype = Object.assign( Object.create( THREE.Object3D.prototype ), {
- if ( attributes.tangent >= 0 ) {
+ constructor: THREE.LOD,
- _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglTangentBuffer );
- enableAttribute( attributes.tangent );
- _gl.vertexAttribPointer( attributes.tangent, 4, _gl.FLOAT, false, 0, 0 );
+ copy: function ( source ) {
- }
+ THREE.Object3D.prototype.copy.call( this, source, false );
- // uvs
+ var levels = source.levels;
- if ( attributes.uv >= 0 ) {
+ for ( var i = 0, l = levels.length; i < l; i ++ ) {
- if ( object.geometry.faceVertexUvs[0] ) {
+ var level = levels[ i ];
- _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUVBuffer );
- enableAttribute( attributes.uv );
- _gl.vertexAttribPointer( attributes.uv, 2, _gl.FLOAT, false, 0, 0 );
+ this.addLevel( level.object.clone(), level.distance );
- } else if ( material.defaultAttributeValues ) {
+ }
+ return this;
- _gl.vertexAttrib2fv( attributes.uv, material.defaultAttributeValues.uv );
+ },
- }
+ addLevel: function ( object, distance ) {
- }
+ if ( distance === undefined ) distance = 0;
- if ( attributes.uv2 >= 0 ) {
+ distance = Math.abs( distance );
- if ( object.geometry.faceVertexUvs[1] ) {
+ var levels = this.levels;
- _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUV2Buffer );
- enableAttribute( attributes.uv2 );
- _gl.vertexAttribPointer( attributes.uv2, 2, _gl.FLOAT, false, 0, 0 );
+ for ( var l = 0; l < levels.length; l ++ ) {
- } else if ( material.defaultAttributeValues ) {
+ if ( distance < levels[ l ].distance ) {
+ break;
- _gl.vertexAttrib2fv( attributes.uv2, material.defaultAttributeValues.uv2 );
+ }
- }
+ }
- }
+ levels.splice( l, 0, { distance: distance, object: object } );
- if ( material.skinning &&
- attributes.skinIndex >= 0 && attributes.skinWeight >= 0 ) {
+ this.add( object );
- _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinIndicesBuffer );
- enableAttribute( attributes.skinIndex );
- _gl.vertexAttribPointer( attributes.skinIndex, 4, _gl.FLOAT, false, 0, 0 );
+ },
- _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinWeightsBuffer );
- enableAttribute( attributes.skinWeight );
- _gl.vertexAttribPointer( attributes.skinWeight, 4, _gl.FLOAT, false, 0, 0 );
+ getObjectForDistance: function ( distance ) {
- }
+ var levels = this.levels;
- // line distances
+ for ( var i = 1, l = levels.length; i < l; i ++ ) {
- if ( attributes.lineDistance >= 0 ) {
+ if ( distance < levels[ i ].distance ) {
- _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglLineDistanceBuffer );
- enableAttribute( attributes.lineDistance );
- _gl.vertexAttribPointer( attributes.lineDistance, 1, _gl.FLOAT, false, 0, 0 );
+ break;
}
}
- // render mesh
+ return levels[ i - 1 ].object;
- if ( object instanceof THREE.Mesh ) {
+ },
+
+ raycast: ( function () {
- // wireframe
+ var matrixPosition = new THREE.Vector3();
- if ( material.wireframe ) {
+ return function raycast( raycaster, intersects ) {
- setLineWidth( material.wireframeLinewidth );
+ matrixPosition.setFromMatrixPosition( this.matrixWorld );
- if ( updateBuffers ) _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglLineBuffer );
- _gl.drawElements( _gl.LINES, geometryGroup.__webglLineCount, _gl.UNSIGNED_SHORT, 0 );
+ var distance = raycaster.ray.origin.distanceTo( matrixPosition );
- // triangles
+ this.getObjectForDistance( distance ).raycast( raycaster, intersects );
- } else {
+ };
- if ( updateBuffers ) _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglFaceBuffer );
- _gl.drawElements( _gl.TRIANGLES, geometryGroup.__webglFaceCount, _gl.UNSIGNED_SHORT, 0 );
+ }() ),
- }
+ update: function () {
- _this.info.render.calls ++;
- _this.info.render.vertices += geometryGroup.__webglFaceCount;
- _this.info.render.faces += geometryGroup.__webglFaceCount / 3;
+ var v1 = new THREE.Vector3();
+ var v2 = new THREE.Vector3();
- // render lines
+ return function update( camera ) {
- } else if ( object instanceof THREE.Line ) {
+ var levels = this.levels;
- var primitives = ( object.type === THREE.LineStrip ) ? _gl.LINE_STRIP : _gl.LINES;
+ if ( levels.length > 1 ) {
- setLineWidth( material.linewidth );
+ v1.setFromMatrixPosition( camera.matrixWorld );
+ v2.setFromMatrixPosition( this.matrixWorld );
- _gl.drawArrays( primitives, 0, geometryGroup.__webglLineCount );
+ var distance = v1.distanceTo( v2 );
- _this.info.render.calls ++;
+ levels[ 0 ].object.visible = true;
- // render particles
+ for ( var i = 1, l = levels.length; i < l; i ++ ) {
- } else if ( object instanceof THREE.ParticleSystem ) {
+ if ( distance >= levels[ i ].distance ) {
- _gl.drawArrays( _gl.POINTS, 0, geometryGroup.__webglParticleCount );
+ levels[ i - 1 ].object.visible = false;
+ levels[ i ].object.visible = true;
- _this.info.render.calls ++;
- _this.info.render.points += geometryGroup.__webglParticleCount;
+ } else {
- // render ribbon
+ break;
- } else if ( object instanceof THREE.Ribbon ) {
+ }
- _gl.drawArrays( _gl.TRIANGLE_STRIP, 0, geometryGroup.__webglVertexCount );
+ }
- _this.info.render.calls ++;
+ for ( ; i < l; i ++ ) {
- }
+ levels[ i ].object.visible = false;
- };
+ }
- function enableAttribute( attribute ) {
+ }
- if ( ! _enabledAttributes[ attribute ] ) {
+ };
- _gl.enableVertexAttribArray( attribute );
- _enabledAttributes[ attribute ] = true;
+ }(),
- }
+ toJSON: function ( meta ) {
- };
+ var data = THREE.Object3D.prototype.toJSON.call( this, meta );
- function disableAttributes() {
+ data.object.levels = [];
- for ( var attribute in _enabledAttributes ) {
+ var levels = this.levels;
- if ( _enabledAttributes[ attribute ] ) {
+ for ( var i = 0, l = levels.length; i < l; i ++ ) {
- _gl.disableVertexAttribArray( attribute );
- _enabledAttributes[ attribute ] = false;
+ var level = levels[ i ];
- }
+ data.object.levels.push( {
+ object: level.object.uuid,
+ distance: level.distance
+ } );
}
- };
-
- function setupMorphTargets ( material, geometryGroup, object ) {
+ return data;
- // set base
+ }
- var attributes = material.program.attributes;
+} );
- if ( object.morphTargetBase !== -1 && attributes.position >= 0 ) {
+// File:src/objects/Sprite.js
- _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ object.morphTargetBase ] );
- enableAttribute( attributes.position );
- _gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 );
+/**
+ * @author mikael emtinger / http://gomo.se/
+ * @author alteredq / http://alteredqualia.com/
+ */
- } else if ( attributes.position >= 0 ) {
+THREE.Sprite = function ( material ) {
- _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglVertexBuffer );
- enableAttribute( attributes.position );
- _gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 );
+ THREE.Object3D.call( this );
- }
+ this.type = 'Sprite';
- if ( object.morphTargetForcedOrder.length ) {
+ this.material = ( material !== undefined ) ? material : new THREE.SpriteMaterial();
- // set forced order
+};
- var m = 0;
- var order = object.morphTargetForcedOrder;
- var influences = object.morphTargetInfluences;
+THREE.Sprite.prototype = Object.assign( Object.create( THREE.Object3D.prototype ), {
- while ( m < material.numSupportedMorphTargets && m < order.length ) {
+ constructor: THREE.Sprite,
- if ( attributes[ "morphTarget" + m ] >= 0 ) {
+ raycast: ( function () {
- _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ order[ m ] ] );
- enableAttribute( attributes[ "morphTarget" + m ] );
- _gl.vertexAttribPointer( attributes[ "morphTarget" + m ], 3, _gl.FLOAT, false, 0, 0 );
+ var matrixPosition = new THREE.Vector3();
- }
+ return function raycast( raycaster, intersects ) {
- if ( attributes[ "morphNormal" + m ] >= 0 && material.morphNormals ) {
+ matrixPosition.setFromMatrixPosition( this.matrixWorld );
- _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphNormalsBuffers[ order[ m ] ] );
- enableAttribute( attributes[ "morphNormal" + m ] );
- _gl.vertexAttribPointer( attributes[ "morphNormal" + m ], 3, _gl.FLOAT, false, 0, 0 );
+ var distanceSq = raycaster.ray.distanceSqToPoint( matrixPosition );
+ var guessSizeSq = this.scale.x * this.scale.y / 4;
- }
+ if ( distanceSq > guessSizeSq ) {
- object.__webglMorphTargetInfluences[ m ] = influences[ order[ m ] ];
+ return;
- m ++;
}
- } else {
+ intersects.push( {
- // find the most influencing
+ distance: Math.sqrt( distanceSq ),
+ point: this.position,
+ face: null,
+ object: this
- var influence, activeInfluenceIndices = [];
- var influences = object.morphTargetInfluences;
- var i, il = influences.length;
+ } );
- for ( i = 0; i < il; i ++ ) {
+ };
- influence = influences[ i ];
+ }() ),
- if ( influence > 0 ) {
+ clone: function () {
- activeInfluenceIndices.push( [ influence, i ] );
+ return new this.constructor( this.material ).copy( this );
- }
+ }
- }
+} );
- if ( activeInfluenceIndices.length > material.numSupportedMorphTargets ) {
+// File:src/objects/LensFlare.js
- activeInfluenceIndices.sort( numericalSort );
- activeInfluenceIndices.length = material.numSupportedMorphTargets;
+/**
+ * @author mikael emtinger / http://gomo.se/
+ * @author alteredq / http://alteredqualia.com/
+ */
- } else if ( activeInfluenceIndices.length > material.numSupportedMorphNormals ) {
+THREE.LensFlare = function ( texture, size, distance, blending, color ) {
- activeInfluenceIndices.sort( numericalSort );
+ THREE.Object3D.call( this );
- } else if ( activeInfluenceIndices.length === 0 ) {
+ this.lensFlares = [];
- activeInfluenceIndices.push( [ 0, 0 ] );
+ this.positionScreen = new THREE.Vector3();
+ this.customUpdateCallback = undefined;
- };
+ if ( texture !== undefined ) {
- var influenceIndex, m = 0;
+ this.add( texture, size, distance, blending, color );
- while ( m < material.numSupportedMorphTargets ) {
+ }
- if ( activeInfluenceIndices[ m ] ) {
+};
- influenceIndex = activeInfluenceIndices[ m ][ 1 ];
+THREE.LensFlare.prototype = Object.assign( Object.create( THREE.Object3D.prototype ), {
- if ( attributes[ "morphTarget" + m ] >= 0 ) {
+ constructor: THREE.LensFlare,
- _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ influenceIndex ] );
- enableAttribute( attributes[ "morphTarget" + m ] );
- _gl.vertexAttribPointer( attributes[ "morphTarget" + m ], 3, _gl.FLOAT, false, 0, 0 );
+ copy: function ( source ) {
- }
+ THREE.Object3D.prototype.copy.call( this, source );
- if ( attributes[ "morphNormal" + m ] >= 0 && material.morphNormals ) {
+ this.positionScreen.copy( source.positionScreen );
+ this.customUpdateCallback = source.customUpdateCallback;
- _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphNormalsBuffers[ influenceIndex ] );
- enableAttribute( attributes[ "morphNormal" + m ] );
- _gl.vertexAttribPointer( attributes[ "morphNormal" + m ], 3, _gl.FLOAT, false, 0, 0 );
+ for ( var i = 0, l = source.lensFlares.length; i < l; i ++ ) {
+ this.lensFlares.push( source.lensFlares[ i ] );
- }
+ }
- object.__webglMorphTargetInfluences[ m ] = influences[ influenceIndex ];
+ return this;
- } else {
+ },
- /*
- _gl.vertexAttribPointer( attributes[ "morphTarget" + m ], 3, _gl.FLOAT, false, 0, 0 );
+ add: function ( texture, size, distance, blending, color, opacity ) {
- if ( material.morphNormals ) {
+ if ( size === undefined ) size = - 1;
+ if ( distance === undefined ) distance = 0;
+ if ( opacity === undefined ) opacity = 1;
+ if ( color === undefined ) color = new THREE.Color( 0xffffff );
+ if ( blending === undefined ) blending = THREE.NormalBlending;
- _gl.vertexAttribPointer( attributes[ "morphNormal" + m ], 3, _gl.FLOAT, false, 0, 0 );
+ distance = Math.min( distance, Math.max( 0, distance ) );
- }
- */
+ this.lensFlares.push( {
+ texture: texture, // THREE.Texture
+ size: size, // size in pixels (-1 = use texture.width)
+ distance: distance, // distance (0-1) from light source (0=at light source)
+ x: 0, y: 0, z: 0, // screen position (-1 => 1) z = 0 is in front z = 1 is back
+ scale: 1, // scale
+ rotation: 0, // rotation
+ opacity: opacity, // opacity
+ color: color, // color
+ blending: blending // blending
+ } );
- object.__webglMorphTargetInfluences[ m ] = 0;
+ },
- }
+ /*
+ * Update lens flares update positions on all flares based on the screen position
+ * Set myLensFlare.customUpdateCallback to alter the flares in your project specific way.
+ */
- m ++;
+ updateLensFlares: function () {
- }
+ var f, fl = this.lensFlares.length;
+ var flare;
+ var vecX = - this.positionScreen.x * 2;
+ var vecY = - this.positionScreen.y * 2;
- }
+ for ( f = 0; f < fl; f ++ ) {
- // load updated influences uniform
+ flare = this.lensFlares[ f ];
- if ( material.program.uniforms.morphTargetInfluences !== null ) {
+ flare.x = this.positionScreen.x + vecX * flare.distance;
+ flare.y = this.positionScreen.y + vecY * flare.distance;
- _gl.uniform1fv( material.program.uniforms.morphTargetInfluences, object.__webglMorphTargetInfluences );
+ flare.wantedRotation = flare.x * Math.PI * 0.25;
+ flare.rotation += ( flare.wantedRotation - flare.rotation ) * 0.25;
}
- };
-
- // Sorting
-
- function painterSortStable ( a, b ) {
-
- if ( a.z !== b.z ) {
-
- return b.z - a.z;
-
- } else {
+ }
- return a.id - b.id;
+} );
- }
+// File:src/scenes/Scene.js
- };
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
- function numericalSort ( a, b ) {
+THREE.Scene = function () {
- return b[ 0 ] - a[ 0 ];
+ THREE.Object3D.call( this );
- };
+ this.type = 'Scene';
+ this.background = null;
+ this.fog = null;
+ this.overrideMaterial = null;
- // Rendering
+ this.autoUpdate = true; // checked by the renderer
- this.render = function ( scene, camera, renderTarget, forceClear ) {
+};
- if ( camera instanceof THREE.Camera === false ) {
+THREE.Scene.prototype = Object.create( THREE.Object3D.prototype );
+THREE.Scene.prototype.constructor = THREE.Scene;
- console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' );
- return;
+THREE.Scene.prototype.copy = function ( source, recursive ) {
- }
+ THREE.Object3D.prototype.copy.call( this, source, recursive );
- var i, il,
+ if ( source.background !== null ) this.background = source.background.clone();
+ if ( source.fog !== null ) this.fog = source.fog.clone();
+ if ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone();
- webglObject, object,
- renderList,
+ this.autoUpdate = source.autoUpdate;
+ this.matrixAutoUpdate = source.matrixAutoUpdate;
- lights = scene.__lights,
- fog = scene.fog;
+ return this;
- // reset caching for this frame
+};
- _currentMaterialId = -1;
- _lightsNeedUpdate = true;
+// File:src/scenes/Fog.js
- // update scene graph
+/**
+ * @author mrdoob / http://mrdoob.com/
+ * @author alteredq / http://alteredqualia.com/
+ */
- if ( scene.autoUpdate === true ) scene.updateMatrixWorld();
+THREE.Fog = function ( color, near, far ) {
- // update camera matrices and frustum
+ this.name = '';
- if ( camera.parent === undefined ) camera.updateMatrixWorld();
+ this.color = new THREE.Color( color );
- camera.matrixWorldInverse.getInverse( camera.matrixWorld );
+ this.near = ( near !== undefined ) ? near : 1;
+ this.far = ( far !== undefined ) ? far : 1000;
- _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
- _frustum.setFromMatrix( _projScreenMatrix );
+};
- // update WebGL objects
+THREE.Fog.prototype.clone = function () {
- if ( this.autoUpdateObjects ) this.initWebGLObjects( scene );
+ return new THREE.Fog( this.color.getHex(), this.near, this.far );
- // custom render plugins (pre pass)
+};
- renderPlugins( this.renderPluginsPre, scene, camera );
+// File:src/scenes/FogExp2.js
- //
+/**
+ * @author mrdoob / http://mrdoob.com/
+ * @author alteredq / http://alteredqualia.com/
+ */
- _this.info.render.calls = 0;
- _this.info.render.vertices = 0;
- _this.info.render.faces = 0;
- _this.info.render.points = 0;
+THREE.FogExp2 = function ( color, density ) {
- this.setRenderTarget( renderTarget );
+ this.name = '';
- if ( this.autoClear || forceClear ) {
+ this.color = new THREE.Color( color );
+ this.density = ( density !== undefined ) ? density : 0.00025;
- this.clear( this.autoClearColor, this.autoClearDepth, this.autoClearStencil );
+};
- }
+THREE.FogExp2.prototype.clone = function () {
- // set matrices for regular objects (frustum culled)
+ return new THREE.FogExp2( this.color.getHex(), this.density );
- renderList = scene.__webglObjects;
+};
- for ( i = 0, il = renderList.length; i < il; i ++ ) {
+// File:src/renderers/shaders/ShaderChunk.js
- webglObject = renderList[ i ];
- object = webglObject.object;
+THREE.ShaderChunk = {};
- webglObject.id = i;
- webglObject.render = false;
+// File:src/renderers/shaders/ShaderChunk/alphamap_fragment.glsl
- if ( object.visible ) {
+THREE.ShaderChunk[ 'alphamap_fragment' ] = "#ifdef USE_ALPHAMAP\n diffuseColor.a *= texture2D( alphaMap, vUv ).g;\n#endif\n";
- if ( ! ( object instanceof THREE.Mesh || object instanceof THREE.ParticleSystem ) || ! ( object.frustumCulled ) || _frustum.intersectsObject( object ) ) {
+// File:src/renderers/shaders/ShaderChunk/alphamap_pars_fragment.glsl
- setupMatrices( object, camera );
+THREE.ShaderChunk[ 'alphamap_pars_fragment' ] = "#ifdef USE_ALPHAMAP\n uniform sampler2D alphaMap;\n#endif\n";
- unrollBufferMaterial( webglObject );
+// File:src/renderers/shaders/ShaderChunk/alphatest_fragment.glsl
- webglObject.render = true;
+THREE.ShaderChunk[ 'alphatest_fragment' ] = "#ifdef ALPHATEST\n if ( diffuseColor.a < ALPHATEST ) discard;\n#endif\n";
- if ( this.sortObjects === true ) {
+// File:src/renderers/shaders/ShaderChunk/aomap_fragment.glsl
- if ( object.renderDepth !== null ) {
+THREE.ShaderChunk[ 'aomap_fragment' ] = "#ifdef USE_AOMAP\n float ambientOcclusion = ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0;\n reflectedLight.indirectDiffuse *= ambientOcclusion;\n #if defined( USE_ENVMAP ) && defined( PHYSICAL )\n float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n reflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.specularRoughness );\n #endif\n#endif\n";
- webglObject.z = object.renderDepth;
+// File:src/renderers/shaders/ShaderChunk/aomap_pars_fragment.glsl
- } else {
+THREE.ShaderChunk[ 'aomap_pars_fragment' ] = "#ifdef USE_AOMAP\n uniform sampler2D aoMap;\n uniform float aoMapIntensity;\n#endif";
- _vector3.getPositionFromMatrix( object.matrixWorld );
- _vector3.applyProjection( _projScreenMatrix );
+// File:src/renderers/shaders/ShaderChunk/begin_vertex.glsl
- webglObject.z = _vector3.z;
+THREE.ShaderChunk[ 'begin_vertex' ] = "\nvec3 transformed = vec3( position );\n";
- }
+// File:src/renderers/shaders/ShaderChunk/beginnormal_vertex.glsl
- }
+THREE.ShaderChunk[ 'beginnormal_vertex' ] = "\nvec3 objectNormal = vec3( normal );\n";
- }
+// File:src/renderers/shaders/ShaderChunk/bsdfs.glsl
- }
+THREE.ShaderChunk[ 'bsdfs' ] = "bool testLightInRange( const in float lightDistance, const in float cutoffDistance ) {\n return any( bvec2( cutoffDistance == 0.0, lightDistance < cutoffDistance ) );\n}\nfloat punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n if( decayExponent > 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n float distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n float maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n return distanceFalloff * maxDistanceCutoffFactor;\n#else\n return pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n }\n return 1.0;\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n return RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n float fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n return ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n float a2 = pow2( alpha );\n float gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n float gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n return 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n float a2 = pow2( alpha );\n float gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n float gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n return 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n float a2 = pow2( alpha );\n float denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n return RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n float alpha = pow2( roughness );\n vec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n float dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n float dotNH = saturate( dot( geometry.normal, halfDir ) );\n float dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n vec3 F = F_Schlick( specularColor, dotLH );\n float G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n float D = D_GGX( alpha, dotNH );\n return F * ( G * D );\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n const vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n const vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n vec4 r = roughness * c0 + c1;\n float a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n vec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n return specularColor * AB.x + AB.y;\n}\nfloat G_BlinnPhong_Implicit( ) {\n return 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n return RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n vec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n float dotNH = saturate( dot( geometry.normal, halfDir ) );\n float dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n vec3 F = F_Schlick( specularColor, dotLH );\n float G = G_BlinnPhong_Implicit( );\n float D = D_BlinnPhong( shininess, dotNH );\n return F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n return ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n return sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n";
- }
+// File:src/renderers/shaders/ShaderChunk/bumpmap_pars_fragment.glsl
- if ( this.sortObjects ) {
+THREE.ShaderChunk[ 'bumpmap_pars_fragment' ] = "#ifdef USE_BUMPMAP\n uniform sampler2D bumpMap;\n uniform float bumpScale;\n vec2 dHdxy_fwd() {\n vec2 dSTdx = dFdx( vUv );\n vec2 dSTdy = dFdy( vUv );\n float Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n float dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n float dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n return vec2( dBx, dBy );\n }\n vec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n vec3 vSigmaX = dFdx( surf_pos );\n vec3 vSigmaY = dFdy( surf_pos );\n vec3 vN = surf_norm;\n vec3 R1 = cross( vSigmaY, vN );\n vec3 R2 = cross( vN, vSigmaX );\n float fDet = dot( vSigmaX, R1 );\n vec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n return normalize( abs( fDet ) * surf_norm - vGrad );\n }\n#endif\n";
- renderList.sort( painterSortStable );
+// File:src/renderers/shaders/ShaderChunk/clipping_planes_fragment.glsl
- }
+THREE.ShaderChunk[ 'clipping_planes_fragment' ] = "#if NUM_CLIPPING_PLANES > 0\n for ( int i = 0; i < NUM_CLIPPING_PLANES; ++ i ) {\n vec4 plane = clippingPlanes[ i ];\n if ( dot( vViewPosition, plane.xyz ) > plane.w ) discard;\n }\n#endif\n";
- // set matrices for immediate objects
+// File:src/renderers/shaders/ShaderChunk/clipping_planes_pars_fragment.glsl
- renderList = scene.__webglObjectsImmediate;
+THREE.ShaderChunk[ 'clipping_planes_pars_fragment' ] = "#if NUM_CLIPPING_PLANES > 0\n #if ! defined( PHYSICAL ) && ! defined( PHONG )\n varying vec3 vViewPosition;\n #endif\n uniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif\n";
- for ( i = 0, il = renderList.length; i < il; i ++ ) {
+// File:src/renderers/shaders/ShaderChunk/clipping_planes_pars_vertex.glsl
- webglObject = renderList[ i ];
- object = webglObject.object;
+THREE.ShaderChunk[ 'clipping_planes_pars_vertex' ] = "#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n varying vec3 vViewPosition;\n#endif\n";
- if ( object.visible ) {
+// File:src/renderers/shaders/ShaderChunk/clipping_planes_vertex.glsl
- setupMatrices( object, camera );
+THREE.ShaderChunk[ 'clipping_planes_vertex' ] = "#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n vViewPosition = - mvPosition.xyz;\n#endif\n";
- unrollImmediateBufferMaterial( webglObject );
+// File:src/renderers/shaders/ShaderChunk/color_fragment.glsl
- }
+THREE.ShaderChunk[ 'color_fragment' ] = "#ifdef USE_COLOR\n diffuseColor.rgb *= vColor;\n#endif";
- }
+// File:src/renderers/shaders/ShaderChunk/color_pars_fragment.glsl
- if ( scene.overrideMaterial ) {
+THREE.ShaderChunk[ 'color_pars_fragment' ] = "#ifdef USE_COLOR\n varying vec3 vColor;\n#endif\n";
- var material = scene.overrideMaterial;
+// File:src/renderers/shaders/ShaderChunk/color_pars_vertex.glsl
- this.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
- this.setDepthTest( material.depthTest );
- this.setDepthWrite( material.depthWrite );
- setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
+THREE.ShaderChunk[ 'color_pars_vertex' ] = "#ifdef USE_COLOR\n varying vec3 vColor;\n#endif";
- renderObjects( scene.__webglObjects, false, "", camera, lights, fog, true, material );
- renderObjectsImmediate( scene.__webglObjectsImmediate, "", camera, lights, fog, false, material );
+// File:src/renderers/shaders/ShaderChunk/color_vertex.glsl
- } else {
+THREE.ShaderChunk[ 'color_vertex' ] = "#ifdef USE_COLOR\n vColor.xyz = color.xyz;\n#endif";
- var material = null;
+// File:src/renderers/shaders/ShaderChunk/common.glsl
- // opaque pass (front-to-back order)
+THREE.ShaderChunk[ 'common' ] = "#define PI 3.14159265359\n#define PI2 6.28318530718\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n const highp float a = 12.9898, b = 78.233, c = 43758.5453;\n highp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n return fract(sin(sn) * c);\n}\nstruct IncidentLight {\n vec3 color;\n vec3 direction;\n bool visible;\n};\nstruct ReflectedLight {\n vec3 directDiffuse;\n vec3 directSpecular;\n vec3 indirectDiffuse;\n vec3 indirectSpecular;\n};\nstruct GeometricContext {\n vec3 position;\n vec3 normal;\n vec3 viewDir;\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n return normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n float distance = dot( planeNormal, point - pointOnPlane );\n return - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n return sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n return lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\n";
- this.setBlending( THREE.NoBlending );
+// File:src/renderers/shaders/ShaderChunk/cube_uv_reflection_fragment.glsl
- renderObjects( scene.__webglObjects, true, "opaque", camera, lights, fog, false, material );
- renderObjectsImmediate( scene.__webglObjectsImmediate, "opaque", camera, lights, fog, false, material );
+THREE.ShaderChunk[ 'cube_uv_reflection_fragment' ] = "#ifdef ENVMAP_TYPE_CUBE_UV\n#define cubeUV_textureSize (1024.0)\nint getFaceFromDirection(vec3 direction) {\n vec3 absDirection = abs(direction);\n int face = -1;\n if( absDirection.x > absDirection.z ) {\n if(absDirection.x > absDirection.y )\n face = direction.x > 0.0 ? 0 : 3;\n else\n face = direction.y > 0.0 ? 1 : 4;\n }\n else {\n if(absDirection.z > absDirection.y )\n face = direction.z > 0.0 ? 2 : 5;\n else\n face = direction.y > 0.0 ? 1 : 4;\n }\n return face;\n}\n#define cubeUV_maxLods1 (log2(cubeUV_textureSize*0.25) - 1.0)\n#define cubeUV_rangeClamp (exp2((6.0 - 1.0) * 2.0))\nvec2 MipLevelInfo( vec3 vec, float roughnessLevel, float roughness ) {\n float scale = exp2(cubeUV_maxLods1 - roughnessLevel);\n float dxRoughness = dFdx(roughness);\n float dyRoughness = dFdy(roughness);\n vec3 dx = dFdx( vec * scale * dxRoughness );\n vec3 dy = dFdy( vec * scale * dyRoughness );\n float d = max( dot( dx, dx ), dot( dy, dy ) );\n d = clamp(d, 1.0, cubeUV_rangeClamp);\n float mipLevel = 0.5 * log2(d);\n return vec2(floor(mipLevel), fract(mipLevel));\n}\n#define cubeUV_maxLods2 (log2(cubeUV_textureSize*0.25) - 2.0)\n#define cubeUV_rcpTextureSize (1.0 / cubeUV_textureSize)\nvec2 getCubeUV(vec3 direction, float roughnessLevel, float mipLevel) {\n mipLevel = roughnessLevel > cubeUV_maxLods2 - 3.0 ? 0.0 : mipLevel;\n float a = 16.0 * cubeUV_rcpTextureSize;\n vec2 exp2_packed = exp2( vec2( roughnessLevel, mipLevel ) );\n vec2 rcp_exp2_packed = vec2( 1.0 ) / exp2_packed;\n float powScale = exp2_packed.x * exp2_packed.y;\n float scale = rcp_exp2_packed.x * rcp_exp2_packed.y * 0.25;\n float mipOffset = 0.75*(1.0 - rcp_exp2_packed.y) * rcp_exp2_packed.x;\n bool bRes = mipLevel == 0.0;\n scale = bRes && (scale < a) ? a : scale;\n vec3 r;\n vec2 offset;\n int face = getFaceFromDirection(direction);\n float rcpPowScale = 1.0 / powScale;\n if( face == 0) {\n r = vec3(direction.x, -direction.z, direction.y);\n offset = vec2(0.0+mipOffset,0.75 * rcpPowScale);\n offset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n }\n else if( face == 1) {\n r = vec3(direction.y, direction.x, direction.z);\n offset = vec2(scale+mipOffset, 0.75 * rcpPowScale);\n offset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n }\n else if( face == 2) {\n r = vec3(direction.z, direction.x, direction.y);\n offset = vec2(2.0*scale+mipOffset, 0.75 * rcpPowScale);\n offset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n }\n else if( face == 3) {\n r = vec3(direction.x, direction.z, direction.y);\n offset = vec2(0.0+mipOffset,0.5 * rcpPowScale);\n offset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n }\n else if( face == 4) {\n r = vec3(direction.y, direction.x, -direction.z);\n offset = vec2(scale+mipOffset, 0.5 * rcpPowScale);\n offset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n }\n else {\n r = vec3(direction.z, -direction.x, direction.y);\n offset = vec2(2.0*scale+mipOffset, 0.5 * rcpPowScale);\n offset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n }\n r = normalize(r);\n float texelOffset = 0.5 * cubeUV_rcpTextureSize;\n vec2 s = ( r.yz / abs( r.x ) + vec2( 1.0 ) ) * 0.5;\n vec2 base = offset + vec2( texelOffset );\n return base + s * ( scale - 2.0 * texelOffset );\n}\n#define cubeUV_maxLods3 (log2(cubeUV_textureSize*0.25) - 3.0)\nvec4 textureCubeUV(vec3 reflectedDirection, float roughness ) {\n float roughnessVal = roughness* cubeUV_maxLods3;\n float r1 = floor(roughnessVal);\n float r2 = r1 + 1.0;\n float t = fract(roughnessVal);\n vec2 mipInfo = MipLevelInfo(reflectedDirection, r1, roughness);\n float s = mipInfo.y;\n float level0 = mipInfo.x;\n float level1 = level0 + 1.0;\n level1 = level1 > 5.0 ? 5.0 : level1;\n level0 += min( floor( s + 0.5 ), 5.0 );\n vec2 uv_10 = getCubeUV(reflectedDirection, r1, level0);\n vec4 color10 = envMapTexelToLinear(texture2D(envMap, uv_10));\n vec2 uv_20 = getCubeUV(reflectedDirection, r2, level0);\n vec4 color20 = envMapTexelToLinear(texture2D(envMap, uv_20));\n vec4 result = mix(color10, color20, t);\n return vec4(result.rgb, 1.0);\n}\n#endif\n";
- // transparent pass (back-to-front order)
+// File:src/renderers/shaders/ShaderChunk/defaultnormal_vertex.glsl
- renderObjects( scene.__webglObjects, false, "transparent", camera, lights, fog, true, material );
- renderObjectsImmediate( scene.__webglObjectsImmediate, "transparent", camera, lights, fog, true, material );
+THREE.ShaderChunk[ 'defaultnormal_vertex' ] = "#ifdef FLIP_SIDED\n objectNormal = -objectNormal;\n#endif\nvec3 transformedNormal = normalMatrix * objectNormal;\n";
- }
+// File:src/renderers/shaders/ShaderChunk/displacementmap_vertex.glsl
- // custom render plugins (post pass)
+THREE.ShaderChunk[ 'displacementmap_vertex' ] = "#ifdef USE_DISPLACEMENTMAP\n transformed += normal * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );\n#endif\n";
- renderPlugins( this.renderPluginsPost, scene, camera );
+// File:src/renderers/shaders/ShaderChunk/displacementmap_pars_vertex.glsl
+THREE.ShaderChunk[ 'displacementmap_pars_vertex' ] = "#ifdef USE_DISPLACEMENTMAP\n uniform sampler2D displacementMap;\n uniform float displacementScale;\n uniform float displacementBias;\n#endif\n";
- // Generate mipmap if we're using any kind of mipmap filtering
+// File:src/renderers/shaders/ShaderChunk/emissivemap_fragment.glsl
- if ( renderTarget && renderTarget.generateMipmaps && renderTarget.minFilter !== THREE.NearestFilter && renderTarget.minFilter !== THREE.LinearFilter ) {
+THREE.ShaderChunk[ 'emissivemap_fragment' ] = "#ifdef USE_EMISSIVEMAP\n vec4 emissiveColor = texture2D( emissiveMap, vUv );\n emissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n totalEmissiveRadiance *= emissiveColor.rgb;\n#endif\n";
- updateRenderTargetMipmap( renderTarget );
+// File:src/renderers/shaders/ShaderChunk/emissivemap_pars_fragment.glsl
- }
+THREE.ShaderChunk[ 'emissivemap_pars_fragment' ] = "#ifdef USE_EMISSIVEMAP\n uniform sampler2D emissiveMap;\n#endif\n";
- // Ensure depth buffer writing is enabled so it can be cleared on next render
+// File:src/renderers/shaders/ShaderChunk/encodings_pars_fragment.glsl
- this.setDepthTest( true );
- this.setDepthWrite( true );
+THREE.ShaderChunk[ 'encodings_pars_fragment' ] = "\nvec4 LinearToLinear( in vec4 value ) {\n return value;\n}\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n return vec4( pow( value.xyz, vec3( gammaFactor ) ), value.w );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n return vec4( pow( value.xyz, vec3( 1.0 / gammaFactor ) ), value.w );\n}\nvec4 sRGBToLinear( in vec4 value ) {\n return vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.w );\n}\nvec4 LinearTosRGB( in vec4 value ) {\n return vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.w );\n}\nvec4 RGBEToLinear( in vec4 value ) {\n return vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}\nvec4 LinearToRGBE( in vec4 value ) {\n float maxComponent = max( max( value.r, value.g ), value.b );\n float fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n return vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n}\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n return vec4( value.xyz * value.w * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n float maxRGB = max( value.x, max( value.g, value.b ) );\n float M = clamp( maxRGB / maxRange, 0.0, 1.0 );\n M = ceil( M * 255.0 ) / 255.0;\n return vec4( value.rgb / ( M * maxRange ), M );\n}\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n return vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n float maxRGB = max( value.x, max( value.g, value.b ) );\n float D = max( maxRange / maxRGB, 1.0 );\n D = min( floor( D ) / 255.0, 1.0 );\n return vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value ) {\n vec3 Xp_Y_XYZp = value.rgb * cLogLuvM;\n Xp_Y_XYZp = max(Xp_Y_XYZp, vec3(1e-6, 1e-6, 1e-6));\n vec4 vResult;\n vResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n float Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n vResult.w = fract(Le);\n vResult.z = (Le - (floor(vResult.w*255.0))/255.0)/255.0;\n return vResult;\n}\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n float Le = value.z * 255.0 + value.w;\n vec3 Xp_Y_XYZp;\n Xp_Y_XYZp.y = exp2((Le - 127.0) / 2.0);\n Xp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n Xp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n vec3 vRGB = Xp_Y_XYZp.rgb * cLogLuvInverseM;\n return vec4( max(vRGB, 0.0), 1.0 );\n}\n";
- // _gl.finish();
+// File:src/renderers/shaders/ShaderChunk/encodings_fragment.glsl
- };
+THREE.ShaderChunk[ 'encodings_fragment' ] = " gl_FragColor = linearToOutputTexel( gl_FragColor );\n";
- function renderPlugins( plugins, scene, camera ) {
+// File:src/renderers/shaders/ShaderChunk/envmap_fragment.glsl
- if ( ! plugins.length ) return;
+THREE.ShaderChunk[ 'envmap_fragment' ] = "#ifdef USE_ENVMAP\n #if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n vec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\n vec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n #ifdef ENVMAP_MODE_REFLECTION\n vec3 reflectVec = reflect( cameraToVertex, worldNormal );\n #else\n vec3 reflectVec = refract( cameraToVertex, worldNormal, refractionRatio );\n #endif\n #else\n vec3 reflectVec = vReflect;\n #endif\n #ifdef ENVMAP_TYPE_CUBE\n vec4 envColor = textureCube( envMap, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n #elif defined( ENVMAP_TYPE_EQUIREC )\n vec2 sampleUV;\n sampleUV.y = saturate( flipNormal * reflectVec.y * 0.5 + 0.5 );\n sampleUV.x = atan( flipNormal * reflectVec.z, flipNormal * reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n vec4 envColor = texture2D( envMap, sampleUV );\n #elif defined( ENVMAP_TYPE_SPHERE )\n vec3 reflectView = flipNormal * normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0, 0.0, 1.0 ) );\n vec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );\n #endif\n envColor = envMapTexelToLinear( envColor );\n #ifdef ENVMAP_BLENDING_MULTIPLY\n outgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n #elif defined( ENVMAP_BLENDING_MIX )\n outgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n #elif defined( ENVMAP_BLENDING_ADD )\n outgoingLight += envColor.xyz * specularStrength * reflectivity;\n #endif\n#endif\n";
- for ( var i = 0, il = plugins.length; i < il; i ++ ) {
+// File:src/renderers/shaders/ShaderChunk/envmap_pars_fragment.glsl
- // reset state for plugin (to start from clean slate)
+THREE.ShaderChunk[ 'envmap_pars_fragment' ] = "#if defined( USE_ENVMAP ) || defined( PHYSICAL )\n uniform float reflectivity;\n uniform float envMapIntenstiy;\n#endif\n#ifdef USE_ENVMAP\n #if ! defined( PHYSICAL ) && ( defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) )\n varying vec3 vWorldPosition;\n #endif\n #ifdef ENVMAP_TYPE_CUBE\n uniform samplerCube envMap;\n #else\n uniform sampler2D envMap;\n #endif\n uniform float flipEnvMap;\n #if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( PHYSICAL )\n uniform float refractionRatio;\n #else\n varying vec3 vReflect;\n #endif\n#endif\n";
- _currentProgram = null;
- _currentCamera = null;
+// File:src/renderers/shaders/ShaderChunk/envmap_pars_vertex.glsl
- _oldBlending = -1;
- _oldDepthTest = -1;
- _oldDepthWrite = -1;
- _oldDoubleSided = -1;
- _oldFlipSided = -1;
- _currentGeometryGroupHash = -1;
- _currentMaterialId = -1;
+THREE.ShaderChunk[ 'envmap_pars_vertex' ] = "#ifdef USE_ENVMAP\n #if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n varying vec3 vWorldPosition;\n #else\n varying vec3 vReflect;\n uniform float refractionRatio;\n #endif\n#endif\n";
- _lightsNeedUpdate = true;
+// File:src/renderers/shaders/ShaderChunk/envmap_vertex.glsl
- plugins[ i ].render( scene, camera, _currentWidth, _currentHeight );
+THREE.ShaderChunk[ 'envmap_vertex' ] = "#ifdef USE_ENVMAP\n #if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n vWorldPosition = worldPosition.xyz;\n #else\n vec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n vec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n #ifdef ENVMAP_MODE_REFLECTION\n vReflect = reflect( cameraToVertex, worldNormal );\n #else\n vReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n #endif\n #endif\n#endif\n";
- // reset state after plugin (anything could have changed)
+// File:src/renderers/shaders/ShaderChunk/fog_fragment.glsl
- _currentProgram = null;
- _currentCamera = null;
+THREE.ShaderChunk[ 'fog_fragment' ] = "#ifdef USE_FOG\n #ifdef USE_LOGDEPTHBUF_EXT\n float depth = gl_FragDepthEXT / gl_FragCoord.w;\n #else\n float depth = gl_FragCoord.z / gl_FragCoord.w;\n #endif\n #ifdef FOG_EXP2\n float fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * depth * depth * LOG2 ) );\n #else\n float fogFactor = smoothstep( fogNear, fogFar, depth );\n #endif\n gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif\n";
- _oldBlending = -1;
- _oldDepthTest = -1;
- _oldDepthWrite = -1;
- _oldDoubleSided = -1;
- _oldFlipSided = -1;
- _currentGeometryGroupHash = -1;
- _currentMaterialId = -1;
+// File:src/renderers/shaders/ShaderChunk/fog_pars_fragment.glsl
- _lightsNeedUpdate = true;
+THREE.ShaderChunk[ 'fog_pars_fragment' ] = "#ifdef USE_FOG\n uniform vec3 fogColor;\n #ifdef FOG_EXP2\n uniform float fogDensity;\n #else\n uniform float fogNear;\n uniform float fogFar;\n #endif\n#endif";
- }
+// File:src/renderers/shaders/ShaderChunk/lightmap_fragment.glsl
- };
+THREE.ShaderChunk[ 'lightmap_fragment' ] = "#ifdef USE_LIGHTMAP\n reflectedLight.indirectDiffuse += PI * texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n#endif\n";
- function renderObjects ( renderList, reverse, materialType, camera, lights, fog, useBlending, overrideMaterial ) {
+// File:src/renderers/shaders/ShaderChunk/lightmap_pars_fragment.glsl
- var webglObject, object, buffer, material, start, end, delta;
+THREE.ShaderChunk[ 'lightmap_pars_fragment' ] = "#ifdef USE_LIGHTMAP\n uniform sampler2D lightMap;\n uniform float lightMapIntensity;\n#endif";
- if ( reverse ) {
+// File:src/renderers/shaders/ShaderChunk/lights_lambert_vertex.glsl
- start = renderList.length - 1;
- end = -1;
- delta = -1;
+THREE.ShaderChunk[ 'lights_lambert_vertex' ] = "vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n vLightBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\n#if NUM_POINT_LIGHTS > 0\n for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n getPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n dotNL = dot( geometry.normal, directLight.direction );\n directLightColor_Diffuse = PI * directLight.color;\n vLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n #ifdef DOUBLE_SIDED\n vLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n #endif\n }\n#endif\n#if NUM_SPOT_LIGHTS > 0\n for ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n getSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n dotNL = dot( geometry.normal, directLight.direction );\n directLightColor_Diffuse = PI * directLight.color;\n vLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n #ifdef DOUBLE_SIDED\n vLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n #endif\n }\n#endif\n#if NUM_DIR_LIGHTS > 0\n for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n getDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n dotNL = dot( geometry.normal, directLight.direction );\n directLightColor_Diffuse = PI * directLight.color;\n vLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n #ifdef DOUBLE_SIDED\n vLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n #endif\n }\n#endif\n#if NUM_HEMI_LIGHTS > 0\n for ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n vLightFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n #ifdef DOUBLE_SIDED\n vLightBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n #endif\n }\n#endif\n";
- } else {
+// File:src/renderers/shaders/ShaderChunk/lights_pars.glsl
- start = 0;
- end = renderList.length;
- delta = 1;
- }
+THREE.ShaderChunk[ 'lights_pars' ] = "uniform vec3 ambientLightColor;\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n vec3 irradiance = ambientLightColor;\n #ifndef PHYSICALLY_CORRECT_LIGHTS\n irradiance *= PI;\n #endif\n return irradiance;\n}\n#if NUM_DIR_LIGHTS > 0\n struct DirectionalLight {\n vec3 direction;\n vec3 color;\n int shadow;\n float shadowBias;\n float shadowRadius;\n vec2 shadowMapSize;\n };\n uniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n void getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n directLight.color = directionalLight.color;\n directLight.direction = directionalLight.direction;\n directLight.visible = true;\n }\n#endif\n#if NUM_POINT_LIGHTS > 0\n struct PointLight {\n vec3 position;\n vec3 color;\n float distance;\n float decay;\n int shadow;\n float shadowBias;\n float shadowRadius;\n vec2 shadowMapSize;\n };\n uniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n void getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n vec3 lVector = pointLight.position - geometry.position;\n directLight.direction = normalize( lVector );\n float lightDistance = length( lVector );\n if ( testLightInRange( lightDistance, pointLight.distance ) ) {\n directLight.color = pointLight.color;\n directLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n directLight.visible = true;\n } else {\n directLight.color = vec3( 0.0 );\n directLight.visible = false;\n }\n }\n#endif\n#if NUM_SPOT_LIGHTS > 0\n struct SpotLight {\n vec3 position;\n vec3 direction;\n vec3 color;\n float distance;\n float decay;\n float coneCos;\n float penumbraCos;\n int shadow;\n float shadowBias;\n float shadowRadius;\n vec2 shadowMapSize;\n };\n uniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n void getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n vec3 lVector = spotLight.position - geometry.position;\n directLight.direction = normalize( lVector );\n float lightDistance = length( lVector );\n float angleCos = dot( directLight.direction, spotLight.direction );\n if ( all( bvec2( angleCos > spotLight.coneCos, testLightInRange( lightDistance, spotLight.distance ) ) ) ) {\n float spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n directLight.color = spotLight.color;\n directLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n directLight.visible = true;\n } else {\n directLight.color = vec3( 0.0 );\n directLight.visible = false;\n }\n }\n#endif\n#if NUM_HEMI_LIGHTS > 0\n struct HemisphereLight {\n vec3 direction;\n vec3 skyColor;\n vec3 groundColor;\n };\n uniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n vec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {\n float dotNL = dot( geometry.normal, hemiLight.direction );\n float hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n vec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n #ifndef PHYSICALLY_CORRECT_LIGHTS\n irradiance *= PI;\n #endif\n return irradiance;\n }\n#endif\n#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n vec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n #include \n vec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n #ifdef ENVMAP_TYPE_CUBE\n vec3 queryVec = flipNormal * vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n #ifdef TEXTURE_LOD_EXT\n vec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n #else\n vec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n #endif\n envMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n #elif defined( ENVMAP_TYPE_CUBE_UV )\n vec3 queryVec = flipNormal * vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n vec4 envMapColor = textureCubeUV( queryVec, 1.0 );\n #else\n vec4 envMapColor = vec4( 0.0 );\n #endif\n return PI * envMapColor.rgb * envMapIntensity;\n }\n float getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {\n float maxMIPLevelScalar = float( maxMIPLevel );\n float desiredMIPLevel = maxMIPLevelScalar - 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );\n return clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n }\n vec3 getLightProbeIndirectRadiance( const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {\n #ifdef ENVMAP_MODE_REFLECTION\n vec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );\n #else\n vec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );\n #endif\n #include \n reflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n float specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );\n #ifdef ENVMAP_TYPE_CUBE\n vec3 queryReflectVec = flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n #ifdef TEXTURE_LOD_EXT\n vec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n #else\n vec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n #endif\n envMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n #elif defined( ENVMAP_TYPE_CUBE_UV )\n vec3 queryReflectVec = flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n vec4 envMapColor = textureCubeUV(queryReflectVec, BlinnExponentToGGXRoughness(blinnShininessExponent));\n #elif defined( ENVMAP_TYPE_EQUIREC )\n vec2 sampleUV;\n sampleUV.y = saturate( flipNormal * reflectVec.y * 0.5 + 0.5 );\n sampleUV.x = atan( flipNormal * reflectVec.z, flipNormal * reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n #ifdef TEXTURE_LOD_EXT\n vec4 envMapColor = texture2DLodEXT( envMap, sampleUV, specularMIPLevel );\n #else\n vec4 envMapColor = texture2D( envMap, sampleUV, specularMIPLevel );\n #endif\n envMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n #elif defined( ENVMAP_TYPE_SPHERE )\n vec3 reflectView = flipNormal * normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) );\n #ifdef TEXTURE_LOD_EXT\n vec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n #else\n vec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n #endif\n envMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n #endif\n return envMapColor.rgb * envMapIntensity;\n }\n#endif\n";
- for ( var i = start; i !== end; i += delta ) {
+// File:src/renderers/shaders/ShaderChunk/lights_phong_fragment.glsl
- webglObject = renderList[ i ];
+THREE.ShaderChunk[ 'lights_phong_fragment' ] = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;\n";
- if ( webglObject.render ) {
+// File:src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl
- object = webglObject.object;
- buffer = webglObject.buffer;
+THREE.ShaderChunk[ 'lights_phong_pars_fragment' ] = "varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n varying vec3 vNormal;\n#endif\nstruct BlinnPhongMaterial {\n vec3 diffuseColor;\n vec3 specularColor;\n float specularShininess;\n float specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n float dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n vec3 irradiance = dotNL * directLight.color;\n #ifndef PHYSICALLY_CORRECT_LIGHTS\n irradiance *= PI;\n #endif\n reflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n reflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n reflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n#define RE_Direct RE_Direct_BlinnPhong\n#define RE_IndirectDiffuse RE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material ) (0)\n";
- if ( overrideMaterial ) {
+// File:src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl
- material = overrideMaterial;
+THREE.ShaderChunk[ 'lights_physical_fragment' ] = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nmaterial.specularRoughness = clamp( roughnessFactor, 0.04, 1.0 );\n#ifdef STANDARD\n material.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\n#else\n material.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\n material.clearCoat = saturate( clearCoat ); material.clearCoatRoughness = clamp( clearCoatRoughness, 0.04, 1.0 );\n#endif\n";
- } else {
+// File:src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl
- material = webglObject[ materialType ];
+THREE.ShaderChunk[ 'lights_physical_pars_fragment' ] = "struct PhysicalMaterial {\n vec3 diffuseColor;\n float specularRoughness;\n vec3 specularColor;\n #ifndef STANDARD\n float clearCoat;\n float clearCoatRoughness;\n #endif\n};\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\nfloat clearCoatDHRApprox( const in float roughness, const in float dotNL ) {\n return DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\n}\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n float dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n vec3 irradiance = dotNL * directLight.color;\n #ifndef PHYSICALLY_CORRECT_LIGHTS\n irradiance *= PI;\n #endif\n #ifndef STANDARD\n float clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n #else\n float clearCoatDHR = 0.0;\n #endif\n reflectedLight.directSpecular += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness );\n reflectedLight.directDiffuse += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n #ifndef STANDARD\n reflectedLight.directSpecular += irradiance * material.clearCoat * BRDF_Specular_GGX( directLight, geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n #endif\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n reflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 clearCoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n #ifndef STANDARD\n float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n float dotNL = dotNV;\n float clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n #else\n float clearCoatDHR = 0.0;\n #endif\n reflectedLight.indirectSpecular += ( 1.0 - clearCoatDHR ) * radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );\n #ifndef STANDARD\n reflectedLight.indirectSpecular += clearCoatRadiance * material.clearCoat * BRDF_Specular_GGX_Environment( geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n #endif\n}\n#define RE_Direct RE_Direct_Physical\n#define RE_IndirectDiffuse RE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular RE_IndirectSpecular_Physical\n#define Material_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.specularRoughness )\n#define Material_ClearCoat_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.clearCoatRoughness )\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n return saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}\n";
- if ( ! material ) continue;
+// File:src/renderers/shaders/ShaderChunk/lights_template.glsl
- if ( useBlending ) _this.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
+THREE.ShaderChunk[ 'lights_template' ] = "\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = normalize( vViewPosition );\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n PointLight pointLight;\n for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n pointLight = pointLights[ i ];\n getPointDirectLightIrradiance( pointLight, geometry, directLight );\n #ifdef USE_SHADOWMAP\n directLight.color *= all( bvec2( pointLight.shadow, directLight.visible ) ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ] ) : 1.0;\n #endif\n RE_Direct( directLight, geometry, material, reflectedLight );\n }\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n SpotLight spotLight;\n for ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n spotLight = spotLights[ i ];\n getSpotDirectLightIrradiance( spotLight, geometry, directLight );\n #ifdef USE_SHADOWMAP\n directLight.color *= all( bvec2( spotLight.shadow, directLight.visible ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n #endif\n RE_Direct( directLight, geometry, material, reflectedLight );\n }\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n DirectionalLight directionalLight;\n for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n directionalLight = directionalLights[ i ];\n getDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n #ifdef USE_SHADOWMAP\n directLight.color *= all( bvec2( directionalLight.shadow, directLight.visible ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n #endif\n RE_Direct( directLight, geometry, material, reflectedLight );\n }\n#endif\n#if defined( RE_IndirectDiffuse )\n vec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n #ifdef USE_LIGHTMAP\n vec3 lightMapIrradiance = texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n #ifndef PHYSICALLY_CORRECT_LIGHTS\n lightMapIrradiance *= PI;\n #endif\n irradiance += lightMapIrradiance;\n #endif\n #if ( NUM_HEMI_LIGHTS > 0 )\n for ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n irradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n }\n #endif\n #if defined( USE_ENVMAP ) && defined( PHYSICAL ) && defined( ENVMAP_TYPE_CUBE_UV )\n irradiance += getLightProbeIndirectIrradiance( geometry, 8 );\n #endif\n RE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n vec3 radiance = getLightProbeIndirectRadiance( geometry, Material_BlinnShininessExponent( material ), 8 );\n #ifndef STANDARD\n vec3 clearCoatRadiance = getLightProbeIndirectRadiance( geometry, Material_ClearCoat_BlinnShininessExponent( material ), 8 );\n #else\n vec3 clearCoatRadiance = vec3( 0.0 );\n #endif\n \n RE_IndirectSpecular( radiance, clearCoatRadiance, geometry, material, reflectedLight );\n#endif\n";
- _this.setDepthTest( material.depthTest );
- _this.setDepthWrite( material.depthWrite );
- setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
+// File:src/renderers/shaders/ShaderChunk/logdepthbuf_fragment.glsl
- }
+THREE.ShaderChunk[ 'logdepthbuf_fragment' ] = "#if defined(USE_LOGDEPTHBUF) && defined(USE_LOGDEPTHBUF_EXT)\n gl_FragDepthEXT = log2(vFragDepth) * logDepthBufFC * 0.5;\n#endif";
- _this.setMaterialFaces( material );
+// File:src/renderers/shaders/ShaderChunk/logdepthbuf_pars_fragment.glsl
- if ( buffer instanceof THREE.BufferGeometry ) {
+THREE.ShaderChunk[ 'logdepthbuf_pars_fragment' ] = "#ifdef USE_LOGDEPTHBUF\n uniform float logDepthBufFC;\n #ifdef USE_LOGDEPTHBUF_EXT\n varying float vFragDepth;\n #endif\n#endif\n";
- _this.renderBufferDirect( camera, lights, fog, material, buffer, object );
+// File:src/renderers/shaders/ShaderChunk/logdepthbuf_pars_vertex.glsl
- } else {
+THREE.ShaderChunk[ 'logdepthbuf_pars_vertex' ] = "#ifdef USE_LOGDEPTHBUF\n #ifdef USE_LOGDEPTHBUF_EXT\n varying float vFragDepth;\n #endif\n uniform float logDepthBufFC;\n#endif";
- _this.renderBuffer( camera, lights, fog, material, buffer, object );
+// File:src/renderers/shaders/ShaderChunk/logdepthbuf_vertex.glsl
- }
+THREE.ShaderChunk[ 'logdepthbuf_vertex' ] = "#ifdef USE_LOGDEPTHBUF\n gl_Position.z = log2(max( EPSILON, gl_Position.w + 1.0 )) * logDepthBufFC;\n #ifdef USE_LOGDEPTHBUF_EXT\n vFragDepth = 1.0 + gl_Position.w;\n #else\n gl_Position.z = (gl_Position.z - 1.0) * gl_Position.w;\n #endif\n#endif\n";
- }
+// File:src/renderers/shaders/ShaderChunk/map_fragment.glsl
- }
+THREE.ShaderChunk[ 'map_fragment' ] = "#ifdef USE_MAP\n vec4 texelColor = texture2D( map, vUv );\n texelColor = mapTexelToLinear( texelColor );\n diffuseColor *= texelColor;\n#endif\n";
- };
+// File:src/renderers/shaders/ShaderChunk/map_pars_fragment.glsl
- function renderObjectsImmediate ( renderList, materialType, camera, lights, fog, useBlending, overrideMaterial ) {
+THREE.ShaderChunk[ 'map_pars_fragment' ] = "#ifdef USE_MAP\n uniform sampler2D map;\n#endif\n";
- var webglObject, object, material, program;
+// File:src/renderers/shaders/ShaderChunk/map_particle_fragment.glsl
- for ( var i = 0, il = renderList.length; i < il; i ++ ) {
+THREE.ShaderChunk[ 'map_particle_fragment' ] = "#ifdef USE_MAP\n vec4 mapTexel = texture2D( map, vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y ) * offsetRepeat.zw + offsetRepeat.xy );\n diffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n";
- webglObject = renderList[ i ];
- object = webglObject.object;
+// File:src/renderers/shaders/ShaderChunk/map_particle_pars_fragment.glsl
- if ( object.visible ) {
+THREE.ShaderChunk[ 'map_particle_pars_fragment' ] = "#ifdef USE_MAP\n uniform vec4 offsetRepeat;\n uniform sampler2D map;\n#endif\n";
- if ( overrideMaterial ) {
+// File:src/renderers/shaders/ShaderChunk/metalnessmap_fragment.glsl
- material = overrideMaterial;
+THREE.ShaderChunk[ 'metalnessmap_fragment' ] = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n vec4 texelMetalness = texture2D( metalnessMap, vUv );\n metalnessFactor *= texelMetalness.r;\n#endif\n";
- } else {
+// File:src/renderers/shaders/ShaderChunk/metalnessmap_pars_fragment.glsl
- material = webglObject[ materialType ];
+THREE.ShaderChunk[ 'metalnessmap_pars_fragment' ] = "#ifdef USE_METALNESSMAP\n uniform sampler2D metalnessMap;\n#endif";
- if ( ! material ) continue;
+// File:src/renderers/shaders/ShaderChunk/morphnormal_vertex.glsl
- if ( useBlending ) _this.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
+THREE.ShaderChunk[ 'morphnormal_vertex' ] = "#ifdef USE_MORPHNORMALS\n objectNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\n objectNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\n objectNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\n objectNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\n#endif\n";
- _this.setDepthTest( material.depthTest );
- _this.setDepthWrite( material.depthWrite );
- setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
+// File:src/renderers/shaders/ShaderChunk/morphtarget_pars_vertex.glsl
- }
+THREE.ShaderChunk[ 'morphtarget_pars_vertex' ] = "#ifdef USE_MORPHTARGETS\n #ifndef USE_MORPHNORMALS\n uniform float morphTargetInfluences[ 8 ];\n #else\n uniform float morphTargetInfluences[ 4 ];\n #endif\n#endif";
- _this.renderImmediateObject( camera, lights, fog, material, object );
+// File:src/renderers/shaders/ShaderChunk/morphtarget_vertex.glsl
- }
+THREE.ShaderChunk[ 'morphtarget_vertex' ] = "#ifdef USE_MORPHTARGETS\n transformed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\n transformed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\n transformed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\n transformed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n #ifndef USE_MORPHNORMALS\n transformed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\n transformed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\n transformed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\n transformed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n #endif\n#endif\n";
- }
+// File:src/renderers/shaders/ShaderChunk/normal_flip.glsl
- };
+THREE.ShaderChunk[ 'normal_flip' ] = "#ifdef DOUBLE_SIDED\n float flipNormal = ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n#else\n float flipNormal = 1.0;\n#endif\n";
- this.renderImmediateObject = function ( camera, lights, fog, material, object ) {
+// File:src/renderers/shaders/ShaderChunk/normal_fragment.glsl
- var program = setProgram( camera, lights, fog, material, object );
+THREE.ShaderChunk[ 'normal_fragment' ] = "#ifdef FLAT_SHADED\n vec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n vec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n vec3 normal = normalize( cross( fdx, fdy ) );\n#else\n vec3 normal = normalize( vNormal ) * flipNormal;\n#endif\n#ifdef USE_NORMALMAP\n normal = perturbNormal2Arb( -vViewPosition, normal );\n#elif defined( USE_BUMPMAP )\n normal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif\n";
- _currentGeometryGroupHash = -1;
+// File:src/renderers/shaders/ShaderChunk/normalmap_pars_fragment.glsl
- _this.setMaterialFaces( material );
+THREE.ShaderChunk[ 'normalmap_pars_fragment' ] = "#ifdef USE_NORMALMAP\n uniform sampler2D normalMap;\n uniform vec2 normalScale;\n vec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n vec3 q0 = dFdx( eye_pos.xyz );\n vec3 q1 = dFdy( eye_pos.xyz );\n vec2 st0 = dFdx( vUv.st );\n vec2 st1 = dFdy( vUv.st );\n vec3 S = normalize( q0 * st1.t - q1 * st0.t );\n vec3 T = normalize( -q0 * st1.s + q1 * st0.s );\n vec3 N = normalize( surf_norm );\n vec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n mapN.xy = normalScale * mapN.xy;\n mat3 tsn = mat3( S, T, N );\n return normalize( tsn * mapN );\n }\n#endif\n";
- if ( object.immediateRenderCallback ) {
+// File:src/renderers/shaders/ShaderChunk/packing.glsl
- object.immediateRenderCallback( program, _gl, _frustum );
+THREE.ShaderChunk[ 'packing' ] = "vec3 packNormalToRGB( const in vec3 normal ) {\n return normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n return 1.0 - 2.0 * rgb.xyz;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n vec4 r = vec4( fract( v * PackFactors ), v );\n r.yzw -= r.xyz * ShiftRight8; return r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n return dot( v, UnpackFactors );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n return ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n return linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n return (( near + viewZ ) * far ) / (( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n return ( near * far ) / ( ( far - near ) * invClipZ - far );\n}\n";
- } else {
+// File:src/renderers/shaders/ShaderChunk/premultiplied_alpha_fragment.glsl
- object.render( function( object ) { _this.renderBufferImmediate( object, program, material ); } );
+THREE.ShaderChunk[ 'premultiplied_alpha_fragment' ] = "#ifdef PREMULTIPLIED_ALPHA\n gl_FragColor.rgb *= gl_FragColor.a;\n#endif\n";
- }
+// File:src/renderers/shaders/ShaderChunk/project_vertex.glsl
- };
+THREE.ShaderChunk[ 'project_vertex' ] = "#ifdef USE_SKINNING\n vec4 mvPosition = modelViewMatrix * skinned;\n#else\n vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\n#endif\ngl_Position = projectionMatrix * mvPosition;\n";
- function unrollImmediateBufferMaterial ( globject ) {
+// File:src/renderers/shaders/ShaderChunk/roughnessmap_fragment.glsl
- var object = globject.object,
- material = object.material;
+THREE.ShaderChunk[ 'roughnessmap_fragment' ] = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n vec4 texelRoughness = texture2D( roughnessMap, vUv );\n roughnessFactor *= texelRoughness.r;\n#endif\n";
- if ( material.transparent ) {
+// File:src/renderers/shaders/ShaderChunk/roughnessmap_pars_fragment.glsl
- globject.transparent = material;
- globject.opaque = null;
+THREE.ShaderChunk[ 'roughnessmap_pars_fragment' ] = "#ifdef USE_ROUGHNESSMAP\n uniform sampler2D roughnessMap;\n#endif";
- } else {
+// File:src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl
- globject.opaque = material;
- globject.transparent = null;
+THREE.ShaderChunk[ 'shadowmap_pars_fragment' ] = "#ifdef USE_SHADOWMAP\n #if NUM_DIR_LIGHTS > 0\n uniform sampler2D directionalShadowMap[ NUM_DIR_LIGHTS ];\n varying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n #endif\n #if NUM_SPOT_LIGHTS > 0\n uniform sampler2D spotShadowMap[ NUM_SPOT_LIGHTS ];\n varying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n #endif\n #if NUM_POINT_LIGHTS > 0\n uniform sampler2D pointShadowMap[ NUM_POINT_LIGHTS ];\n varying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n #endif\n float texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n return step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n }\n float texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {\n const vec2 offset = vec2( 0.0, 1.0 );\n vec2 texelSize = vec2( 1.0 ) / size;\n vec2 centroidUV = floor( uv * size + 0.5 ) / size;\n float lb = texture2DCompare( depths, centroidUV + texelSize * offset.xx, compare );\n float lt = texture2DCompare( depths, centroidUV + texelSize * offset.xy, compare );\n float rb = texture2DCompare( depths, centroidUV + texelSize * offset.yx, compare );\n float rt = texture2DCompare( depths, centroidUV + texelSize * offset.yy, compare );\n vec2 f = fract( uv * size + 0.5 );\n float a = mix( lb, lt, f.y );\n float b = mix( rb, rt, f.y );\n float c = mix( a, b, f.x );\n return c;\n }\n float getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n shadowCoord.xyz /= shadowCoord.w;\n shadowCoord.z += shadowBias;\n bvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n bool inFrustum = all( inFrustumVec );\n bvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n bool frustumTest = all( frustumTestVec );\n if ( frustumTest ) {\n #if defined( SHADOWMAP_TYPE_PCF )\n vec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n float dx0 = - texelSize.x * shadowRadius;\n float dy0 = - texelSize.y * shadowRadius;\n float dx1 = + texelSize.x * shadowRadius;\n float dy1 = + texelSize.y * shadowRadius;\n return (\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n ) * ( 1.0 / 9.0 );\n #elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n vec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n float dx0 = - texelSize.x * shadowRadius;\n float dy0 = - texelSize.y * shadowRadius;\n float dx1 = + texelSize.x * shadowRadius;\n float dy1 = + texelSize.y * shadowRadius;\n return (\n texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy, shadowCoord.z ) +\n texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n ) * ( 1.0 / 9.0 );\n #else\n return texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n #endif\n }\n return 1.0;\n }\n vec2 cubeToUV( vec3 v, float texelSizeY ) {\n vec3 absV = abs( v );\n float scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n absV *= scaleToCube;\n v *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n vec2 planar = v.xy;\n float almostATexel = 1.5 * texelSizeY;\n float almostOne = 1.0 - almostATexel;\n if ( absV.z >= almostOne ) {\n if ( v.z > 0.0 )\n planar.x = 4.0 - v.x;\n } else if ( absV.x >= almostOne ) {\n float signX = sign( v.x );\n planar.x = v.z * signX + 2.0 * signX;\n } else if ( absV.y >= almostOne ) {\n float signY = sign( v.y );\n planar.x = v.x + 2.0 * signY + 2.0;\n planar.y = v.z * signY - 2.0;\n }\n return vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n }\n float getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n vec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n vec3 lightToPosition = shadowCoord.xyz;\n vec3 bd3D = normalize( lightToPosition );\n float dp = ( length( lightToPosition ) - shadowBias ) / 1000.0;\n #if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT )\n vec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n return (\n texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n ) * ( 1.0 / 9.0 );\n #else\n return texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n #endif\n }\n#endif\n";
- }
+// File:src/renderers/shaders/ShaderChunk/shadowmap_pars_vertex.glsl
- };
+THREE.ShaderChunk[ 'shadowmap_pars_vertex' ] = "#ifdef USE_SHADOWMAP\n #if NUM_DIR_LIGHTS > 0\n uniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHTS ];\n varying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n #endif\n #if NUM_SPOT_LIGHTS > 0\n uniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHTS ];\n varying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n #endif\n #if NUM_POINT_LIGHTS > 0\n uniform mat4 pointShadowMatrix[ NUM_POINT_LIGHTS ];\n varying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n #endif\n#endif\n";
- function unrollBufferMaterial ( globject ) {
+// File:src/renderers/shaders/ShaderChunk/shadowmap_vertex.glsl
- var object = globject.object,
- buffer = globject.buffer,
- material, materialIndex, meshMaterial;
+THREE.ShaderChunk[ 'shadowmap_vertex' ] = "#ifdef USE_SHADOWMAP\n #if NUM_DIR_LIGHTS > 0\n for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n vDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;\n }\n #endif\n #if NUM_SPOT_LIGHTS > 0\n for ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n vSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;\n }\n #endif\n #if NUM_POINT_LIGHTS > 0\n for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n vPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;\n }\n #endif\n#endif\n";
- meshMaterial = object.material;
+// File:src/renderers/shaders/ShaderChunk/shadowmask_pars_fragment.glsl
- if ( meshMaterial instanceof THREE.MeshFaceMaterial ) {
+THREE.ShaderChunk[ 'shadowmask_pars_fragment' ] = "float getShadowMask() {\n float shadow = 1.0;\n #ifdef USE_SHADOWMAP\n #if NUM_DIR_LIGHTS > 0\n DirectionalLight directionalLight;\n for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n directionalLight = directionalLights[ i ];\n shadow *= bool( directionalLight.shadow ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n }\n #endif\n #if NUM_SPOT_LIGHTS > 0\n SpotLight spotLight;\n for ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n spotLight = spotLights[ i ];\n shadow *= bool( spotLight.shadow ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n }\n #endif\n #if NUM_POINT_LIGHTS > 0\n PointLight pointLight;\n for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n pointLight = pointLights[ i ];\n shadow *= bool( pointLight.shadow ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ] ) : 1.0;\n }\n #endif\n #endif\n return shadow;\n}\n";
- materialIndex = buffer.materialIndex;
+// File:src/renderers/shaders/ShaderChunk/skinbase_vertex.glsl
- material = meshMaterial.materials[ materialIndex ];
+THREE.ShaderChunk[ 'skinbase_vertex' ] = "#ifdef USE_SKINNING\n mat4 boneMatX = getBoneMatrix( skinIndex.x );\n mat4 boneMatY = getBoneMatrix( skinIndex.y );\n mat4 boneMatZ = getBoneMatrix( skinIndex.z );\n mat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif";
- if ( material.transparent ) {
+// File:src/renderers/shaders/ShaderChunk/skinning_pars_vertex.glsl
- globject.transparent = material;
- globject.opaque = null;
+THREE.ShaderChunk[ 'skinning_pars_vertex' ] = "#ifdef USE_SKINNING\n uniform mat4 bindMatrix;\n uniform mat4 bindMatrixInverse;\n #ifdef BONE_TEXTURE\n uniform sampler2D boneTexture;\n uniform int boneTextureWidth;\n uniform int boneTextureHeight;\n mat4 getBoneMatrix( const in float i ) {\n float j = i * 4.0;\n float x = mod( j, float( boneTextureWidth ) );\n float y = floor( j / float( boneTextureWidth ) );\n float dx = 1.0 / float( boneTextureWidth );\n float dy = 1.0 / float( boneTextureHeight );\n y = dy * ( y + 0.5 );\n vec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n vec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n vec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n vec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n mat4 bone = mat4( v1, v2, v3, v4 );\n return bone;\n }\n #else\n uniform mat4 boneMatrices[ MAX_BONES ];\n mat4 getBoneMatrix( const in float i ) {\n mat4 bone = boneMatrices[ int(i) ];\n return bone;\n }\n #endif\n#endif\n";
- } else {
+// File:src/renderers/shaders/ShaderChunk/skinning_vertex.glsl
- globject.opaque = material;
- globject.transparent = null;
+THREE.ShaderChunk[ 'skinning_vertex' ] = "#ifdef USE_SKINNING\n vec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n vec4 skinned = vec4( 0.0 );\n skinned += boneMatX * skinVertex * skinWeight.x;\n skinned += boneMatY * skinVertex * skinWeight.y;\n skinned += boneMatZ * skinVertex * skinWeight.z;\n skinned += boneMatW * skinVertex * skinWeight.w;\n skinned = bindMatrixInverse * skinned;\n#endif\n";
- }
+// File:src/renderers/shaders/ShaderChunk/skinnormal_vertex.glsl
- } else {
+THREE.ShaderChunk[ 'skinnormal_vertex' ] = "#ifdef USE_SKINNING\n mat4 skinMatrix = mat4( 0.0 );\n skinMatrix += skinWeight.x * boneMatX;\n skinMatrix += skinWeight.y * boneMatY;\n skinMatrix += skinWeight.z * boneMatZ;\n skinMatrix += skinWeight.w * boneMatW;\n skinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n objectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n#endif\n";
- material = meshMaterial;
+// File:src/renderers/shaders/ShaderChunk/specularmap_fragment.glsl
- if ( material ) {
+THREE.ShaderChunk[ 'specularmap_fragment' ] = "float specularStrength;\n#ifdef USE_SPECULARMAP\n vec4 texelSpecular = texture2D( specularMap, vUv );\n specularStrength = texelSpecular.r;\n#else\n specularStrength = 1.0;\n#endif";
- if ( material.transparent ) {
+// File:src/renderers/shaders/ShaderChunk/specularmap_pars_fragment.glsl
- globject.transparent = material;
- globject.opaque = null;
+THREE.ShaderChunk[ 'specularmap_pars_fragment' ] = "#ifdef USE_SPECULARMAP\n uniform sampler2D specularMap;\n#endif";
- } else {
+// File:src/renderers/shaders/ShaderChunk/tonemapping_fragment.glsl
- globject.opaque = material;
- globject.transparent = null;
+THREE.ShaderChunk[ 'tonemapping_fragment' ] = "#if defined( TONE_MAPPING )\n gl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif\n";
- }
+// File:src/renderers/shaders/ShaderChunk/tonemapping_pars_fragment.glsl
- }
+THREE.ShaderChunk[ 'tonemapping_pars_fragment' ] = "#define saturate(a) clamp( a, 0.0, 1.0 )\nuniform float toneMappingExposure;\nuniform float toneMappingWhitePoint;\nvec3 LinearToneMapping( vec3 color ) {\n return toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n color *= toneMappingExposure;\n return saturate( color / ( vec3( 1.0 ) + color ) );\n}\n#define Uncharted2Helper( x ) max( ( ( x * ( 0.15 * x + 0.10 * 0.50 ) + 0.20 * 0.02 ) / ( x * ( 0.15 * x + 0.50 ) + 0.20 * 0.30 ) ) - 0.02 / 0.30, vec3( 0.0 ) )\nvec3 Uncharted2ToneMapping( vec3 color ) {\n color *= toneMappingExposure;\n return saturate( Uncharted2Helper( color ) / Uncharted2Helper( vec3( toneMappingWhitePoint ) ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n color *= toneMappingExposure;\n color = max( vec3( 0.0 ), color - 0.004 );\n return pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\n";
- }
+// File:src/renderers/shaders/ShaderChunk/uv2_pars_fragment.glsl
- };
+THREE.ShaderChunk[ 'uv2_pars_fragment' ] = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n varying vec2 vUv2;\n#endif";
- // Geometry splitting
+// File:src/renderers/shaders/ShaderChunk/uv2_pars_vertex.glsl
- function sortFacesByMaterial ( geometry, material ) {
+THREE.ShaderChunk[ 'uv2_pars_vertex' ] = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n attribute vec2 uv2;\n varying vec2 vUv2;\n#endif";
- var f, fl, face, materialIndex, vertices,
- groupHash, hash_map = {};
+// File:src/renderers/shaders/ShaderChunk/uv2_vertex.glsl
- var numMorphTargets = geometry.morphTargets.length;
- var numMorphNormals = geometry.morphNormals.length;
+THREE.ShaderChunk[ 'uv2_vertex' ] = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n vUv2 = uv2;\n#endif";
- var usesFaceMaterial = material instanceof THREE.MeshFaceMaterial;
+// File:src/renderers/shaders/ShaderChunk/uv_pars_fragment.glsl
- geometry.geometryGroups = {};
+THREE.ShaderChunk[ 'uv_pars_fragment' ] = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n varying vec2 vUv;\n#endif";
- for ( f = 0, fl = geometry.faces.length; f < fl; f ++ ) {
+// File:src/renderers/shaders/ShaderChunk/uv_pars_vertex.glsl
- face = geometry.faces[ f ];
- materialIndex = usesFaceMaterial ? face.materialIndex : 0;
+THREE.ShaderChunk[ 'uv_pars_vertex' ] = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n varying vec2 vUv;\n uniform vec4 offsetRepeat;\n#endif\n";
- if ( hash_map[ materialIndex ] === undefined ) {
+// File:src/renderers/shaders/ShaderChunk/uv_vertex.glsl
- hash_map[ materialIndex ] = { 'hash': materialIndex, 'counter': 0 };
+THREE.ShaderChunk[ 'uv_vertex' ] = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n vUv = uv * offsetRepeat.zw + offsetRepeat.xy;\n#endif";
- }
+// File:src/renderers/shaders/ShaderChunk/worldpos_vertex.glsl
- groupHash = hash_map[ materialIndex ].hash + '_' + hash_map[ materialIndex ].counter;
+THREE.ShaderChunk[ 'worldpos_vertex' ] = "#if defined( USE_ENVMAP ) || defined( PHONG ) || defined( PHYSICAL ) || defined( LAMBERT ) || defined ( USE_SHADOWMAP )\n #ifdef USE_SKINNING\n vec4 worldPosition = modelMatrix * skinned;\n #else\n vec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\n #endif\n#endif\n";
- if ( geometry.geometryGroups[ groupHash ] === undefined ) {
+// File:src/renderers/shaders/UniformsUtils.js
- geometry.geometryGroups[ groupHash ] = { 'faces3': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };
+/**
+ * Uniform Utilities
+ */
- }
+THREE.UniformsUtils = {
- vertices = 3;
+ merge: function ( uniforms ) {
- if ( geometry.geometryGroups[ groupHash ].vertices + vertices > 65535 ) {
+ var merged = {};
- hash_map[ materialIndex ].counter += 1;
- groupHash = hash_map[ materialIndex ].hash + '_' + hash_map[ materialIndex ].counter;
+ for ( var u = 0; u < uniforms.length; u ++ ) {
- if ( geometry.geometryGroups[ groupHash ] === undefined ) {
+ var tmp = this.clone( uniforms[ u ] );
- geometry.geometryGroups[ groupHash ] = { 'faces3': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };
+ for ( var p in tmp ) {
- }
+ merged[ p ] = tmp[ p ];
}
- geometry.geometryGroups[ groupHash ].faces3.push( f );
- geometry.geometryGroups[ groupHash ].vertices += vertices;
-
}
- geometry.geometryGroupsList = [];
+ return merged;
- for ( var g in geometry.geometryGroups ) {
+ },
- geometry.geometryGroups[ g ].id = _geometryGroupCounter ++;
+ clone: function ( uniforms_src ) {
- geometry.geometryGroupsList.push( geometry.geometryGroups[ g ] );
+ var uniforms_dst = {};
- }
+ for ( var u in uniforms_src ) {
- };
+ uniforms_dst[ u ] = {};
- // Objects refresh
+ for ( var p in uniforms_src[ u ] ) {
- this.initWebGLObjects = function ( scene ) {
+ var parameter_src = uniforms_src[ u ][ p ];
- if ( !scene.__webglObjects ) {
+ if ( parameter_src instanceof THREE.Color ||
+ parameter_src instanceof THREE.Vector2 ||
+ parameter_src instanceof THREE.Vector3 ||
+ parameter_src instanceof THREE.Vector4 ||
+ parameter_src instanceof THREE.Matrix3 ||
+ parameter_src instanceof THREE.Matrix4 ||
+ parameter_src instanceof THREE.Texture ) {
- scene.__webglObjects = [];
- scene.__webglObjectsImmediate = [];
- scene.__webglSprites = [];
- scene.__webglFlares = [];
+ uniforms_dst[ u ][ p ] = parameter_src.clone();
- }
+ } else if ( Array.isArray( parameter_src ) ) {
- while ( scene.__objectsAdded.length ) {
+ uniforms_dst[ u ][ p ] = parameter_src.slice();
- addObject( scene.__objectsAdded[ 0 ], scene );
- scene.__objectsAdded.splice( 0, 1 );
+ } else {
- }
+ uniforms_dst[ u ][ p ] = parameter_src;
- while ( scene.__objectsRemoved.length ) {
+ }
- removeObject( scene.__objectsRemoved[ 0 ], scene );
- scene.__objectsRemoved.splice( 0, 1 );
+ }
}
- // update must be called after objects adding / removal
+ return uniforms_dst;
- for ( var o = 0, ol = scene.__webglObjects.length; o < ol; o ++ ) {
+ }
- var object = scene.__webglObjects[ o ].object;
+};
- // TODO: Remove this hack (WebGLRenderer refactoring)
+// File:src/renderers/shaders/UniformsLib.js
- if ( object.__webglInit === undefined ) {
+/**
+ * Uniforms library for shared webgl shaders
+ */
- if ( object.__webglActive !== undefined ) {
+THREE.UniformsLib = {
- removeObject( object, scene );
+ common: {
- }
+ "diffuse": { value: new THREE.Color( 0xeeeeee ) },
+ "opacity": { value: 1.0 },
- addObject( object, scene );
+ "map": { value: null },
+ "offsetRepeat": { value: new THREE.Vector4( 0, 0, 1, 1 ) },
- }
+ "specularMap": { value: null },
+ "alphaMap": { value: null },
- updateObject( object );
+ "envMap": { value: null },
+ "flipEnvMap": { value: - 1 },
+ "reflectivity": { value: 1.0 },
+ "refractionRatio": { value: 0.98 }
- }
+ },
- };
+ aomap: {
- // Objects adding
+ "aoMap": { value: null },
+ "aoMapIntensity": { value: 1 }
- function addObject( object, scene ) {
+ },
- var g, geometry, material, geometryGroup;
+ lightmap: {
- if ( object.__webglInit === undefined ) {
+ "lightMap": { value: null },
+ "lightMapIntensity": { value: 1 }
- object.__webglInit = true;
+ },
- object._modelViewMatrix = new THREE.Matrix4();
- object._normalMatrix = new THREE.Matrix3();
+ emissivemap: {
- if ( object.geometry !== undefined && object.geometry.__webglInit === undefined ) {
+ "emissiveMap": { value: null }
- object.geometry.__webglInit = true;
- object.geometry.addEventListener( 'dispose', onGeometryDispose );
+ },
- }
+ bumpmap: {
- geometry = object.geometry;
+ "bumpMap": { value: null },
+ "bumpScale": { value: 1 }
- if ( geometry === undefined ) {
+ },
- // fail silently for now
+ normalmap: {
- } else if ( geometry instanceof THREE.BufferGeometry ) {
+ "normalMap": { value: null },
+ "normalScale": { value: new THREE.Vector2( 1, 1 ) }
- initDirectBuffers( geometry );
+ },
- } else if ( object instanceof THREE.Mesh ) {
+ displacementmap: {
- material = object.material;
+ "displacementMap": { value: null },
+ "displacementScale": { value: 1 },
+ "displacementBias": { value: 0 }
- if ( geometry.geometryGroups === undefined ) {
+ },
- sortFacesByMaterial( geometry, material );
+ roughnessmap: {
- }
+ "roughnessMap": { value: null }
- // create separate VBOs per geometry chunk
+ },
- for ( g in geometry.geometryGroups ) {
+ metalnessmap: {
- geometryGroup = geometry.geometryGroups[ g ];
+ "metalnessMap": { value: null }
- // initialise VBO on the first access
+ },
- if ( ! geometryGroup.__webglVertexBuffer ) {
+ fog: {
- createMeshBuffers( geometryGroup );
- initMeshBuffers( geometryGroup, object );
+ "fogDensity": { value: 0.00025 },
+ "fogNear": { value: 1 },
+ "fogFar": { value: 2000 },
+ "fogColor": { value: new THREE.Color( 0xffffff ) }
- geometry.verticesNeedUpdate = true;
- geometry.morphTargetsNeedUpdate = true;
- geometry.elementsNeedUpdate = true;
- geometry.uvsNeedUpdate = true;
- geometry.normalsNeedUpdate = true;
- geometry.tangentsNeedUpdate = true;
- geometry.colorsNeedUpdate = true;
+ },
- }
+ lights: {
- }
+ "ambientLightColor": { value: [] },
- } else if ( object instanceof THREE.Ribbon ) {
+ "directionalLights": { value: [], properties: {
+ "direction": {},
+ "color": {},
- if ( ! geometry.__webglVertexBuffer ) {
+ "shadow": {},
+ "shadowBias": {},
+ "shadowRadius": {},
+ "shadowMapSize": {}
+ } },
- createRibbonBuffers( geometry );
- initRibbonBuffers( geometry, object );
+ "directionalShadowMap": { value: [] },
+ "directionalShadowMatrix": { value: [] },
- geometry.verticesNeedUpdate = true;
- geometry.colorsNeedUpdate = true;
- geometry.normalsNeedUpdate = true;
+ "spotLights": { value: [], properties: {
+ "color": {},
+ "position": {},
+ "direction": {},
+ "distance": {},
+ "coneCos": {},
+ "penumbraCos": {},
+ "decay": {},
- }
+ "shadow": {},
+ "shadowBias": {},
+ "shadowRadius": {},
+ "shadowMapSize": {}
+ } },
- } else if ( object instanceof THREE.Line ) {
+ "spotShadowMap": { value: [] },
+ "spotShadowMatrix": { value: [] },
- if ( ! geometry.__webglVertexBuffer ) {
+ "pointLights": { value: [], properties: {
+ "color": {},
+ "position": {},
+ "decay": {},
+ "distance": {},
- createLineBuffers( geometry );
- initLineBuffers( geometry, object );
+ "shadow": {},
+ "shadowBias": {},
+ "shadowRadius": {},
+ "shadowMapSize": {}
+ } },
- geometry.verticesNeedUpdate = true;
- geometry.colorsNeedUpdate = true;
- geometry.lineDistancesNeedUpdate = true;
+ "pointShadowMap": { value: [] },
+ "pointShadowMatrix": { value: [] },
- }
+ "hemisphereLights": { value: [], properties: {
+ "direction": {},
+ "skyColor": {},
+ "groundColor": {}
+ } }
- } else if ( object instanceof THREE.ParticleSystem ) {
+ },
- if ( ! geometry.__webglVertexBuffer ) {
+ points: {
- createParticleBuffers( geometry );
- initParticleBuffers( geometry, object );
+ "diffuse": { value: new THREE.Color( 0xeeeeee ) },
+ "opacity": { value: 1.0 },
+ "size": { value: 1.0 },
+ "scale": { value: 1.0 },
+ "map": { value: null },
+ "offsetRepeat": { value: new THREE.Vector4( 0, 0, 1, 1 ) }
- geometry.verticesNeedUpdate = true;
- geometry.colorsNeedUpdate = true;
+ }
- }
+};
- }
+// File:src/renderers/shaders/ShaderLib/cube_frag.glsl
- }
+THREE.ShaderChunk[ 'cube_frag' ] = "uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldPosition;\n#include \nvoid main() {\n gl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );\n gl_FragColor.a *= opacity;\n}\n";
- if ( object.__webglActive === undefined ) {
+// File:src/renderers/shaders/ShaderLib/cube_vert.glsl
- if ( object instanceof THREE.Mesh ) {
+THREE.ShaderChunk[ 'cube_vert' ] = "varying vec3 vWorldPosition;\n#include \nvoid main() {\n vWorldPosition = transformDirection( position, modelMatrix );\n #include \n #include \n}\n";
- geometry = object.geometry;
+// File:src/renderers/shaders/ShaderLib/depth_frag.glsl
- if ( geometry instanceof THREE.BufferGeometry ) {
+THREE.ShaderChunk[ 'depth_frag' ] = "#if DEPTH_PACKING == 3200\n uniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n vec4 diffuseColor = vec4( 1.0 );\n #if DEPTH_PACKING == 3200\n diffuseColor.a = opacity;\n #endif\n #include \n #include \n #include \n #include \n #if DEPTH_PACKING == 3200\n gl_FragColor = vec4( vec3( gl_FragCoord.z ), opacity );\n #elif DEPTH_PACKING == 3201\n gl_FragColor = packDepthToRGBA( gl_FragCoord.z );\n #endif\n}\n";
- addBuffer( scene.__webglObjects, geometry, object );
+// File:src/renderers/shaders/ShaderLib/depth_vert.glsl
- } else if ( geometry instanceof THREE.Geometry ) {
+THREE.ShaderChunk[ 'depth_vert' ] = "#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n}\n";
- for ( g in geometry.geometryGroups ) {
+// File:src/renderers/shaders/ShaderLib/distanceRGBA_frag.glsl
- geometryGroup = geometry.geometryGroups[ g ];
+THREE.ShaderChunk[ 'distanceRGBA_frag' ] = "uniform vec3 lightPos;\nvarying vec4 vWorldPosition;\n#include \n#include \n#include \nvoid main () {\n #include \n gl_FragColor = packDepthToRGBA( length( vWorldPosition.xyz - lightPos.xyz ) / 1000.0 );\n}\n";
- addBuffer( scene.__webglObjects, geometryGroup, object );
+// File:src/renderers/shaders/ShaderLib/distanceRGBA_vert.glsl
- }
+THREE.ShaderChunk[ 'distanceRGBA_vert' ] = "varying vec4 vWorldPosition;\n#include \n#include \n#include \n#include \nvoid main() {\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n vWorldPosition = worldPosition;\n}\n";
- }
+// File:src/renderers/shaders/ShaderLib/equirect_frag.glsl
- } else if ( object instanceof THREE.Ribbon ||
- object instanceof THREE.Line ||
- object instanceof THREE.ParticleSystem ) {
+THREE.ShaderChunk[ 'equirect_frag' ] = "uniform sampler2D tEquirect;\nuniform float tFlip;\nvarying vec3 vWorldPosition;\n#include \nvoid main() {\n vec3 direction = normalize( vWorldPosition );\n vec2 sampleUV;\n sampleUV.y = saturate( tFlip * direction.y * -0.5 + 0.5 );\n sampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;\n gl_FragColor = texture2D( tEquirect, sampleUV );\n}\n";
- geometry = object.geometry;
- addBuffer( scene.__webglObjects, geometry, object );
+// File:src/renderers/shaders/ShaderLib/equirect_vert.glsl
- } else if ( object instanceof THREE.ImmediateRenderObject || object.immediateRenderCallback ) {
+THREE.ShaderChunk[ 'equirect_vert' ] = "varying vec3 vWorldPosition;\n#include \nvoid main() {\n vWorldPosition = transformDirection( position, modelMatrix );\n #include \n #include \n}\n";
- addBufferImmediate( scene.__webglObjectsImmediate, object );
+// File:src/renderers/shaders/ShaderLib/linedashed_frag.glsl
- } else if ( object instanceof THREE.Sprite ) {
+THREE.ShaderChunk[ 'linedashed_frag' ] = "uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n if ( mod( vLineDistance, totalSize ) > dashSize ) {\n discard;\n }\n vec3 outgoingLight = vec3( 0.0 );\n vec4 diffuseColor = vec4( diffuse, opacity );\n #include \n #include \n outgoingLight = diffuseColor.rgb;\n gl_FragColor = vec4( outgoingLight, diffuseColor.a );\n #include \n #include \n #include \n #include \n}\n";
- scene.__webglSprites.push( object );
+// File:src/renderers/shaders/ShaderLib/linedashed_vert.glsl
- } else if ( object instanceof THREE.LensFlare ) {
+THREE.ShaderChunk[ 'linedashed_vert' ] = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \nvoid main() {\n #include \n vLineDistance = scale * lineDistance;\n vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n gl_Position = projectionMatrix * mvPosition;\n #include \n #include \n}\n";
- scene.__webglFlares.push( object );
+// File:src/renderers/shaders/ShaderLib/meshbasic_frag.glsl
- }
+THREE.ShaderChunk[ 'meshbasic_frag' ] = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n varying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n vec4 diffuseColor = vec4( diffuse, opacity );\n #include \n #include \n #include \n #include \n #include \n #include \n ReflectedLight reflectedLight;\n reflectedLight.directDiffuse = vec3( 0.0 );\n reflectedLight.directSpecular = vec3( 0.0 );\n reflectedLight.indirectDiffuse = diffuseColor.rgb;\n reflectedLight.indirectSpecular = vec3( 0.0 );\n #include \n vec3 outgoingLight = reflectedLight.indirectDiffuse;\n #include \n #include \n gl_FragColor = vec4( outgoingLight, diffuseColor.a );\n #include \n #include \n #include \n #include \n}\n";
- object.__webglActive = true;
+// File:src/renderers/shaders/ShaderLib/meshbasic_vert.glsl
- }
+THREE.ShaderChunk[ 'meshbasic_vert' ] = "#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n #include \n #include \n #include \n #ifdef USE_ENVMAP\n #include \n #include \n #include \n #include \n #endif\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n}\n";
- };
+// File:src/renderers/shaders/ShaderLib/meshlambert_frag.glsl
- function addBuffer( objlist, buffer, object ) {
+THREE.ShaderChunk[ 'meshlambert_frag' ] = "uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n varying vec3 vLightBack;\n#endif\n#include