提交 1599e1ac 编写于 作者: S SUNAG

mrdoob approves

上级 1e26eb05
......@@ -3,122 +3,122 @@
*/
THREE.BuilderNode = function( material ) {
this.material = material;
this.require = {};
this.isVerify = false;
this.cache = '';
};
THREE.BuilderNode.prototype = {
constructor: THREE.BuilderNode,
include : function ( func ) {
include : function( func ) {
this.material.include( this.shader, func );
},
getFormatConstructor : function ( len ) {
return THREE.BuilderNode.constructors[len-1];
getFormatConstructor : function( len ) {
return THREE.BuilderNode.constructors[ len - 1 ];
},
getFormat : function ( format ) {
return format.replace('c','v3').replace(/fv1|iv1/, 'v1');
getFormat : function( format ) {
return format.replace( 'c', 'v3' ).replace( /fv1|iv1/, 'v1' );
},
getFormatLength : function ( format ) {
return parseInt( this.getFormat(format).substr(1) );
getFormatLength : function( format ) {
return parseInt( this.getFormat( format ).substr( 1 ) );
},
getFormatByLength : function ( len ) {
if (len == 1) return 'fv1';
getFormatByLength : function( len ) {
if ( len == 1 ) return 'fv1';
return 'v' + len;
},
format : function ( code, from, to ) {
var format = this.getFormat(from + '=' + to);
format : function( code, from, to ) {
var format = this.getFormat( from + '=' + to );
switch ( format ) {
case 'v1=v2': return 'vec2(' + code + ')';
case 'v1=v3': return 'vec3(' + code + ')';
case 'v1=v4': return 'vec4(' + code + ')';
case 'v2=v1': return code + '.x';
case 'v2=v3': return 'vec3(' + code + ',0.0)';
case 'v2=v4': return 'vec4(' + code + ',0.0,0.0)';
case 'v3=v1': return code + '.x';
case 'v3=v2': return code + '.xy';
case 'v3=v4': return 'vec4(' + code + ',0.0)';
case 'v4=v1': return code + '.x';
case 'v4=v2': return code + '.xy';
case 'v4=v3': return code + '.xyz';
}
return code;
},
getType : function ( format ) {
getType : function( format ) {
return THREE.BuilderNode.type[ format ];
},
getUuid : function ( uuid, useCache ) {
getUuid : function( uuid, useCache ) {
useCache = useCache !== undefined ? useCache : true;
if (useCache && this.cache) uuid = this.cache + '-' + uuid;
if ( useCache && this.cache ) uuid = this.cache + '-' + uuid;
return uuid;
},
setCache : function ( name ) {
setCache : function( name ) {
this.cache = name || '';
return this;
},
getElementByIndex : function ( index ) {
getElementByIndex : function( index ) {
return THREE.BuilderNode.elements[ index ];
},
getElementIndex : function ( elm ) {
getElementIndex : function( elm ) {
return THREE.BuilderNode.elements.indexOf( elm );
},
isShader : function ( shader ) {
isShader : function( shader ) {
return this.shader == shader || this.isVerify;
},
setShader : function ( shader ) {
setShader : function( shader ) {
this.shader = shader;
return this;
}
......@@ -132,15 +132,15 @@ THREE.BuilderNode.type = {
};
THREE.BuilderNode.constructors = [
'',
'vec2',
'vec3',
'',
'vec2',
'vec3',
'vec4'
];
THREE.BuilderNode.elements = [
'x',
'y',
'z',
'x',
'y',
'z',
'w'
];
\ No newline at end of file
];
......@@ -2,37 +2,37 @@
* @author sunag / http://www.sunag.com.br/
*/
THREE.ConstNode = function(name, useDefine) {
THREE.ConstNode = function( name, useDefine ) {
name = name || THREE.ConstNode.PI;
var rDeclaration = /^([a-z_0-9]+)\s([a-z_0-9]+)\s?\=(.*?)\;/i;
var type = 'fv1';
var match = name.match( rDeclaration );
if (match && match.length > 1) {
type = match[1];
name = match[2];
if (useDefine) {
this.src = '#define ' + name + ' ' + match[3];
if ( match && match.length > 1 ) {
type = match[ 1 ];
name = match[ 2 ];
if ( useDefine ) {
this.src = '#define ' + name + ' ' + match[ 3 ];
}
else {
this.src = 'const ' + type + ' ' + name + ' = ' + match[3] + ';';
this.src = 'const ' + type + ' ' + name + ' = ' + match[ 3 ] + ';';
}
}
this.name = name;
THREE.TempNode.call( this, type );
};
THREE.ConstNode.prototype = Object.create( THREE.TempNode.prototype );
......@@ -46,7 +46,7 @@ THREE.ConstNode.LOG2 = 'LOG2';
THREE.ConstNode.EPSILON = 'EPSILON';
THREE.ConstNode.prototype.generate = function( builder, output ) {
return builder.format( this.name, this.getType( builder ), output );
};
\ No newline at end of file
};
......@@ -3,58 +3,58 @@
*/
THREE.FunctionCallNode = function( value ) {
THREE.TempNode.call( this );
this.setFunction( value );
};
THREE.FunctionCallNode.prototype = Object.create( THREE.TempNode.prototype );
THREE.FunctionCallNode.prototype.constructor = THREE.FunctionCallNode;
THREE.FunctionCallNode.prototype.setFunction = function(val) {
THREE.FunctionCallNode.prototype.setFunction = function( val ) {
this.input = [];
this.value = val;
};
THREE.FunctionCallNode.prototype.getFunction = function() {
return this.value;
};
THREE.FunctionCallNode.prototype.getType = function( builder ) {
return this.value.getType( builder );
};
THREE.FunctionCallNode.prototype.generate = function( builder, output ) {
var material = builder.material;
var type = this.getType( builder );
var func = this.value;
builder.include( func );
var code = func.name + '(';
var params = [];
for(var i = 0; i < func.input.length; i++) {
var inpt = func.input[i];
var param = this.input[i] || this.input[inpt.name];
for ( var i = 0; i < func.input.length; i ++ ) {
var inpt = func.input[ i ];
var param = this.input[ i ] || this.input[ inpt.name ];
params.push( param.build( builder, builder.getType( inpt.type ) ) );
}
code += params.join(',') + ')';
code += params.join( ',' ) + ')';
return builder.format( code, type, output );
};
......@@ -4,21 +4,21 @@
*/
THREE.FunctionNode = function( src, includes, extensions ) {
THREE.GLNode.call( this );
this.parse( src || '', includes, extensions );
};
THREE.FunctionNode.prototype = Object.create( THREE.GLNode.prototype );
THREE.FunctionNode.prototype.constructor = THREE.FunctionNode;
THREE.FunctionNode.prototype.parseReference = function( name ) {
switch(name) {
switch ( name ) {
case 'uv': return new THREE.UVNode().name;
case 'uv2': return new THREE.UVNode(1).name;
case 'uv2': return new THREE.UVNode( 1 ).name;
case 'position': return new THREE.PositionNode().name;
case 'worldPosition': return new THREE.PositionNode( THREE.PositionNode.WORLD ).name;
case 'normal': return new THREE.NormalNode().name;
......@@ -26,9 +26,9 @@ THREE.FunctionNode.prototype.parseReference = function( name ) {
case 'viewPosition': return new THREE.PositionNode( THREE.NormalNode.VIEW ).name;
case 'viewNormal': return new THREE.NormalNode( THREE.NormalNode.VIEW ).name;
}
return name;
};
THREE.FunctionNode.prototype.getTypeNode = function( builder, type ) {
......@@ -38,120 +38,122 @@ THREE.FunctionNode.prototype.getTypeNode = function( builder, type ) {
};
THREE.FunctionNode.prototype.getInputByName = function( name ) {
var i = this.input.length;
while(i--) {
if (this.input[i].name === name)
return this.input[i];
while ( i -- ) {
if ( this.input[ i ].name === name )
return this.input[ i ];
}
};
THREE.FunctionNode.prototype.getType = function( builder ) {
return this.getTypeNode( builder, this.type );
};
THREE.FunctionNode.prototype.getInclude = function( name ) {
var i = this.includes.length;
while(i--) {
if (this.includes[i].name === name)
return this.includes[i];
while ( i -- ) {
if ( this.includes[ i ].name === name )
return this.includes[ i ];
}
return undefined;
};
THREE.FunctionNode.prototype.parse = function( src, includes, extensions ) {
var rDeclaration = /^([a-z_0-9]+)\s([a-z_0-9]+)\s?\((.*?)\)/i;
var rProperties = /[a-z_0-9]+/ig;
this.includes = includes || [];
this.extensions = extensions || {};
var match = src.match( rDeclaration );
this.input = [];
if (match && match.length == 4) {
this.type = match[1];
this.name = match[2];
var inputs = match[3].match( rProperties );
if (inputs) {
if ( match && match.length == 4 ) {
this.type = match[ 1 ];
this.name = match[ 2 ];
var inputs = match[ 3 ].match( rProperties );
if ( inputs ) {
var i = 0;
while(i < inputs.length) {
var qualifier = inputs[i++];
while ( i < inputs.length ) {
var qualifier = inputs[ i ++ ];
var type, name;
if (qualifier == 'in' || qualifier == 'out' || qualifier == 'inout') {
type = inputs[i++];
if ( qualifier == 'in' || qualifier == 'out' || qualifier == 'inout' ) {
type = inputs[ i ++ ];
}
else {
type = qualifier;
qualifier = '';
}
name = inputs[i++];
this.input.push({
name = inputs[ i ++ ];
this.input.push( {
name : name,
type : type,
qualifier : qualifier
});
} );
}
}
var match, offset = 0;
while (match = rProperties.exec(src)) {
var prop = match[0];
while ( match = rProperties.exec( src ) ) {
var prop = match[ 0 ];
var reference = this.parseReference( prop );
if (prop != reference) {
src = src.substring( 0, match.index + offset ) + reference + src.substring( match.index + prop.length + offset );
if ( prop != reference ) {
src = src.substring( 0, match.index + offset ) + reference + src.substring( match.index + prop.length + offset );
offset += reference.length - prop.length;
}
if (this.getInclude(reference) === undefined && THREE.LibNode.contains(reference)) {
this.includes.push( THREE.LibNode.get(reference) );
if ( this.getInclude( reference ) === undefined && THREE.LibNode.contains( reference ) ) {
this.includes.push( THREE.LibNode.get( reference ) );
}
}
this.src = src;
}
else {
this.type = '';
this.name = '';
}
};
\ No newline at end of file
};
......@@ -3,66 +3,66 @@
*/
THREE.GLNode = function( type ) {
this.uuid = THREE.Math.generateUUID();
this.allow = {};
this.requestUpdate = false;
this.type = type;
};
THREE.GLNode.prototype.verify = function( builder ) {
builder.isVerify = true;
var material = builder.material;
this.build( builder, 'v4' );
material.clearVertexNode();
material.clearFragmentNode();
builder.setCache(); // reset cache
builder.isVerify = false;
};
THREE.GLNode.prototype.verifyAndBuildCode = function( builder, output, cache ) {
this.verify( builder.setCache(cache) );
return this.buildCode( builder.setCache(cache), output );
this.verify( builder.setCache( cache ) );
return this.buildCode( builder.setCache( cache ), output );
};
THREE.GLNode.prototype.buildCode = function( builder, output, uuid ) {
var material = builder.material;
var data = { result : this.build( builder, output, uuid ) };
if (builder.isShader('vertex')) data.code = material.clearVertexNode();
if ( builder.isShader( 'vertex' ) ) data.code = material.clearVertexNode();
else data.code = material.clearFragmentNode();
builder.setCache(); // reset cache
return data;
};
THREE.GLNode.prototype.verifyDepsNode = function( builder, data, output ) {
data.deps = (data.deps || 0) + 1;
data.deps = ( data.deps || 0 ) + 1;
var outputLen = builder.getFormatLength( output );
if (outputLen > data.outputMax || this.getType( builder )) {
if ( outputLen > data.outputMax || this.getType( builder ) ) {
data.outputMax = outputLen;
data.output = output;
}
};
......@@ -71,24 +71,28 @@ THREE.GLNode.prototype.build = function( builder, output, uuid ) {
var material = builder.material;
var data = material.getDataNode( uuid || this.uuid );
if (builder.isShader('verify')) this.verifyDepsNode( builder, data, output );
if (this.allow[builder.shader] === false) {
if ( builder.isShader( 'verify' ) ) this.verifyDepsNode( builder, data, output );
if ( this.allow[ builder.shader ] === false ) {
throw new Error( 'Shader ' + shader + ' is not compatible with this node.' );
}
if (this.requestUpdate && !data.requestUpdate) {
if ( this.requestUpdate && ! data.requestUpdate ) {
material.requestUpdate.push( this );
data.requestUpdate = true;
}
return this.generate( builder, output, uuid );
};
THREE.GLNode.prototype.getType = function( builder ) {
return this.type;
};
\ No newline at end of file
};
......@@ -2,10 +2,10 @@
* @author sunag / http://www.sunag.com.br/
*/
THREE.InputNode = function(type, params) {
THREE.InputNode = function( type, params ) {
THREE.TempNode.call( this, type, params );
};
THREE.InputNode.prototype = Object.create( THREE.TempNode.prototype );
......@@ -17,28 +17,30 @@ THREE.InputNode.prototype.generate = function( builder, output, uuid, type ) {
uuid = builder.getUuid( uuid || this.uuid );
type = type || this.type;
var data = material.getDataNode( uuid );
if (builder.isShader('vertex')) {
if (!data.vertex) {
if ( builder.isShader( 'vertex' ) ) {
if ( ! data.vertex ) {
data.vertex = material.getVertexUniform( this.value, type );
}
return builder.format( data.vertex.name, type, output );
}
else {
if (!data.fragment) {
if ( ! data.fragment ) {
data.fragment = material.getFragmentUniform( this.value, type );
}
return builder.format( data.fragment.name, type, output );
}
};
\ No newline at end of file
};
......@@ -3,18 +3,26 @@
*/
THREE.LibNode = {
nodes:{},
add:function(node) {
this.nodes[node.name] = node;
nodes: {},
add: function( node ) {
this.nodes[ node.name ] = node;
},
remove:function(node) {
delete this.nodes[node.name];
remove: function( node ) {
delete this.nodes[ node.name ];
},
get:function(name) {
return this.nodes[name];
get: function( name ) {
return this.nodes[ name ];
},
contains:function(name) {
return this.nodes[name] != undefined;
contains: function( name ) {
return this.nodes[ name ] != undefined;
}
};
......@@ -22,13 +30,13 @@ THREE.LibNode = {
// Luma
//
THREE.LibNode.add(new THREE.ConstNode("vec3 LUMA = vec3(0.2125, 0.7154, 0.0721);") );
THREE.LibNode.add( new THREE.ConstNode( "vec3 LUMA = vec3(0.2125, 0.7154, 0.0721);" ) );
//
// DepthColor
//
THREE.LibNode.add(new THREE.FunctionNode([
THREE.LibNode.add( new THREE.FunctionNode( [
"float depthcolor( float mNear, float mFar ) {",
"#ifdef USE_LOGDEPTHBUF_EXT",
......@@ -36,16 +44,16 @@ THREE.LibNode.add(new THREE.FunctionNode([
"#else",
"float depth = gl_FragCoord.z / gl_FragCoord.w;",
"#endif",
"return 1.0 - smoothstep( mNear, mFar, depth );",
"}"
].join( "\n" )));
].join( "\n" ) ) );
//
// NormalMap
//
THREE.LibNode.add(new THREE.FunctionNode([
THREE.LibNode.add( new THREE.FunctionNode( [
// Per-Pixel Tangent Space Normal Mapping
// http://hacksoflife.blogspot.ch/2009/11/per-pixel-tangent-space-normal-mapping.html
"vec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 map, vec2 mUv, float scale ) {",
......@@ -61,27 +69,27 @@ THREE.LibNode.add(new THREE.FunctionNode([
"mat3 tsn = mat3( S, T, N );",
"return normalize( tsn * mapN );",
"}"
].join( "\n" ), null, {derivatives:true}));
].join( "\n" ), null, { derivatives: true } ) );
//
// Saturation
//
THREE.LibNode.add(new THREE.FunctionNode([
THREE.LibNode.add( new THREE.FunctionNode( [
// Algorithm from Chapter 16 of OpenGL Shading Language
"vec3 saturation_rgb(vec3 rgb, float adjustment) {",
"vec3 intensity = vec3(dot(rgb, LUMA));",
"return mix(intensity, rgb, adjustment);",
"}"
].join( "\n" )));
].join( "\n" ) ) );
//
// Luminance
//
THREE.LibNode.add(new THREE.FunctionNode([
THREE.LibNode.add( new THREE.FunctionNode( [
// Algorithm from Chapter 10 of Graphics Shaders.
"float luminance_rgb(vec3 rgb) {",
"return dot(rgb, LUMA);",
"}"
].join( "\n" )));
\ No newline at end of file
].join( "\n" ) ) );
......@@ -3,12 +3,12 @@
*/
THREE.NodeMaterial = function( vertex, fragment ) {
THREE.ShaderMaterial.call( this );
this.vertex = vertex || new THREE.RawNode( new THREE.PositionNode( THREE.PositionNode.PROJECTION ) );
this.fragment = fragment || new THREE.RawNode( new THREE.ColorNode( 0xFF0000 ) );
};
THREE.NodeMaterial.prototype = Object.create( THREE.ShaderMaterial.prototype );
......@@ -27,168 +27,176 @@ THREE.NodeMaterial.Type = {
};
THREE.NodeMaterial.GetShortcuts = function( prop, name ) {
return {
get: function () { return this[prop][name]; },
set: function ( val ) { this[prop][name] = val; }
get: function() {
return this[ prop ][ name ];
},
set: function( val ) {
this[ prop ][ name ] = val;
}
};
};
THREE.NodeMaterial.Shortcuts = function( proto, prop, list ) {
var shortcuts = {};
for(var i = 0; i < list.length; ++i) {
var name = list[i];
shortcuts[name] = this.GetShortcuts( prop, name );
for ( var i = 0; i < list.length; ++ i ) {
var name = list[ i ];
shortcuts[ name ] = this.GetShortcuts( prop, name );
}
Object.defineProperties( proto, shortcuts );
};
THREE.NodeMaterial.prototype.updateAnimation = function( delta ) {
for(var i = 0; i < this.requestUpdate.length; ++i) {
this.requestUpdate[i].updateAnimation( delta );
for ( var i = 0; i < this.requestUpdate.length; ++ i ) {
this.requestUpdate[ i ].updateAnimation( delta );
}
};
THREE.NodeMaterial.prototype.build = function() {
var vertex, fragment;
this.defines = {};
this.uniforms = {};
this.nodeData = {};
this.uniforms = {};
this.nodeData = {};
this.vertexUniform = [];
this.fragmentUniform = [];
this.vertexTemps = [];
this.fragmentTemps = [];
this.uniformList = [];
this.consts = [];
this.functions = [];
this.requestUpdate = [];
this.requestAttrib = {
uv:[],
color:[]
uv: [],
color: []
};
this.needsColor = false;
this.needsLight = false;
this.needsPosition = false;
this.needsTransparent = false;
this.vertexPars = '';
this.fragmentPars = '';
this.vertexCode = '';
this.fragmentCode = '';
this.vertexNode = '';
this.fragmentNode = '';
var builder = new THREE.BuilderNode(this);
vertex = this.vertex.build( builder.setShader('vertex'), 'v4' );
fragment = this.fragment.build( builder.setShader('fragment'), 'v4' );
if (this.requestAttrib.uv[0]) {
var builder = new THREE.BuilderNode( this );
vertex = this.vertex.build( builder.setShader( 'vertex' ), 'v4' );
fragment = this.fragment.build( builder.setShader( 'fragment' ), 'v4' );
if ( this.requestAttrib.uv[ 0 ] ) {
this.addVertexPars( 'varying vec2 vUv;' );
this.addFragmentPars( 'varying vec2 vUv;' );
this.addVertexCode( 'vUv = uv;' );
}
if (this.requestAttrib.uv[1]) {
if ( this.requestAttrib.uv[ 1 ] ) {
this.addVertexPars( 'varying vec2 vUv2; attribute vec2 uv2;' );
this.addFragmentPars( 'varying vec2 vUv2;' );
this.addVertexCode( 'vUv2 = uv2;' );
}
if (this.requestAttrib.color[0]) {
if ( this.requestAttrib.color[ 0 ] ) {
this.addVertexPars( 'varying vec4 vColor; attribute vec4 color;' );
this.addFragmentPars( 'varying vec4 vColor;' );
this.addVertexCode( 'vColor = color;' );
}
if (this.requestAttrib.color[1]) {
if ( this.requestAttrib.color[ 1 ] ) {
this.addVertexPars( 'varying vec4 vColor2; attribute vec4 color2;' );
this.addFragmentPars( 'varying vec4 vColor2;' );
this.addVertexCode( 'vColor2 = color2;' );
}
if (this.requestAttrib.position) {
if ( this.requestAttrib.position ) {
this.addVertexPars( 'varying vec3 vPosition;' );
this.addFragmentPars( 'varying vec3 vPosition;' );
this.addVertexCode( 'vPosition = transformed;' );
}
if (this.requestAttrib.worldPosition) {
if ( this.requestAttrib.worldPosition ) {
// for future update replace from the native "varying vec3 vWorldPosition" for optimization
this.addVertexPars( 'varying vec3 vWPosition;' );
this.addFragmentPars( 'varying vec3 vWPosition;' );
this.addVertexCode( 'vWPosition = worldPosition.xyz;' );
}
if (this.requestAttrib.normal) {
if ( this.requestAttrib.normal ) {
this.addVertexPars( 'varying vec3 vObjectNormal;' );
this.addFragmentPars( 'varying vec3 vObjectNormal;' );
this.addVertexCode( 'vObjectNormal = normal;' );
}
if (this.requestAttrib.worldNormal) {
if ( this.requestAttrib.worldNormal ) {
this.addVertexPars( 'varying vec3 vWNormal;' );
this.addFragmentPars( 'varying vec3 vWNormal;' );
this.addVertexCode( 'vWNormal = ( modelMatrix * vec4( objectNormal, 0.0 ) ).xyz;' );
}
this.lights = this.needsLight;
this.transparent = this.needsTransparent;
this.vertexShader = [
this.vertexPars,
this.getCodePars( this.vertexUniform, 'uniform' ),
this.getIncludes(this.consts['vertex']),
this.getIncludes(this.functions['vertex']),
this.getIncludes( this.consts[ 'vertex' ] ),
this.getIncludes( this.functions[ 'vertex' ] ),
'void main(){',
this.getCodePars( this.vertexTemps ),
vertex,
......@@ -199,115 +207,120 @@ THREE.NodeMaterial.prototype.build = function() {
this.fragmentShader = [
this.fragmentPars,
this.getCodePars( this.fragmentUniform, 'uniform' ),
this.getIncludes(this.consts['fragment']),
this.getIncludes(this.functions['fragment']),
this.getIncludes( this.consts[ 'fragment' ] ),
this.getIncludes( this.functions[ 'fragment' ] ),
'void main(){',
this.getCodePars( this.fragmentTemps ),
this.fragmentCode,
fragment,
'}'
].join( "\n" );
this.needsUpdate = true;
this.dispose(); // force update
return this;
};
THREE.NodeMaterial.prototype.define = function(name, value) {
THREE.NodeMaterial.prototype.define = function( name, value ) {
this.defines[name] = value == undefined ? 1 : value;
this.defines[ name ] = value == undefined ? 1 : value;
};
THREE.NodeMaterial.prototype.isDefined = function(name) {
THREE.NodeMaterial.prototype.isDefined = function( name ) {
return this.defines[name] != undefined;
return this.defines[ name ] != undefined;
};
THREE.NodeMaterial.prototype.mergeUniform = function( uniforms ) {
for (var name in uniforms) {
for ( var name in uniforms ) {
this.uniforms[ name ] = uniforms[ name ];
}
};
THREE.NodeMaterial.prototype.createUniform = function( value, type, needsUpdate ) {
var index = this.uniformList.length;
var uniform = {
type : type,
value : value,
needsUpdate : needsUpdate,
name : 'nVu' + index
};
this.uniformList.push(uniform);
this.uniformList.push( uniform );
return uniform;
};
THREE.NodeMaterial.prototype.getVertexTemp = function( uuid, type ) {
if (!this.vertexTemps[ uuid ]) {
if ( ! this.vertexTemps[ uuid ] ) {
var index = this.vertexTemps.length,
name = 'nVt' + index,
data = { name : name, type : type };
this.vertexTemps.push( data );
this.vertexTemps[uuid] = data;
this.vertexTemps[ uuid ] = data;
}
return this.vertexTemps[uuid];
return this.vertexTemps[ uuid ];
};
THREE.NodeMaterial.prototype.getIncludes = function( incs ) {
function sortByPosition(a, b){
function sortByPosition( a, b ) {
return b.deps - a.deps;
}
return function( incs ) {
if (!incs) return '';
if ( ! incs ) return '';
var code = '';
var incs = incs.sort(sortByPosition);
for(var i = 0; i < incs.length; i++) {
code += incs[i].node.src + '\n';
var incs = incs.sort( sortByPosition );
for ( var i = 0; i < incs.length; i ++ ) {
code += incs[ i ].node.src + '\n';
}
return code;
}
}();
THREE.NodeMaterial.prototype.getFragmentTemp = function( uuid, type ) {
if (!this.fragmentTemps[ uuid ]) {
if ( ! this.fragmentTemps[ uuid ] ) {
var index = this.fragmentTemps.length,
name = 'nVt' + index,
data = { name : name, type : type };
this.fragmentTemps.push( data );
this.fragmentTemps[uuid] = data;
this.fragmentTemps[ uuid ] = data;
}
return this.fragmentTemps[uuid];
return this.fragmentTemps[ uuid ];
};
THREE.NodeMaterial.prototype.addVertexPars = function( code ) {
......@@ -343,9 +356,9 @@ THREE.NodeMaterial.prototype.addVertexNode = function( code ) {
THREE.NodeMaterial.prototype.clearVertexNode = function() {
var code = this.fragmentNode;
this.fragmentNode = '';
return code;
};
......@@ -359,9 +372,9 @@ THREE.NodeMaterial.prototype.addFragmentNode = function( code ) {
THREE.NodeMaterial.prototype.clearFragmentNode = function() {
var code = this.fragmentNode;
this.fragmentNode = '';
return code;
};
......@@ -371,20 +384,21 @@ THREE.NodeMaterial.prototype.getCodePars = function( pars, prefix ) {
prefix = prefix || '';
var code = '';
for (var i = 0, l = pars.length; i < l; ++i) {
var parsType = pars[i].type;
var parsName = pars[i].name;
var parsValue = pars[i].value;
if (parsType == 't' && parsValue instanceof THREE.CubeTexture) parsType = 'tc';
for ( var i = 0, l = pars.length; i < l; ++ i ) {
var parsType = pars[ i ].type;
var parsName = pars[ i ].name;
var parsValue = pars[ i ].value;
if ( parsType == 't' && parsValue instanceof THREE.CubeTexture ) parsType = 'tc';
var type = THREE.NodeMaterial.Type[ parsType ];
if (type == undefined) throw new Error( "Node pars " + parsType + " not found." );
if ( type == undefined ) throw new Error( "Node pars " + parsType + " not found." );
code += prefix + ' ' + type + ' ' + parsName + ';\n';
}
return code;
......@@ -394,12 +408,12 @@ THREE.NodeMaterial.prototype.getCodePars = function( pars, prefix ) {
THREE.NodeMaterial.prototype.getVertexUniform = function( value, type, needsUpdate ) {
var uniform = this.createUniform( value, type, needsUpdate );
this.vertexUniform.push(uniform);
this.vertexUniform[uniform.name] = uniform;
this.vertexUniform.push( uniform );
this.vertexUniform[ uniform.name ] = uniform;
this.uniforms[ uniform.name ] = uniform;
return uniform;
};
......@@ -407,61 +421,61 @@ THREE.NodeMaterial.prototype.getVertexUniform = function( value, type, needsUpda
THREE.NodeMaterial.prototype.getFragmentUniform = function( value, type, needsUpdate ) {
var uniform = this.createUniform( value, type, needsUpdate );
this.fragmentUniform.push(uniform);
this.fragmentUniform[uniform.name] = uniform;
this.fragmentUniform.push( uniform );
this.fragmentUniform[ uniform.name ] = uniform;
this.uniforms[ uniform.name ] = uniform;
return uniform;
};
THREE.NodeMaterial.prototype.getDataNode = function( uuid ) {
return this.nodeData[uuid] = this.nodeData[uuid] || {};
return this.nodeData[ uuid ] = this.nodeData[ uuid ] || {};
};
THREE.NodeMaterial.prototype.include = function( shader, node ) {
var includes;
node = typeof node === 'string' ? THREE.LibNode.get(node) : node;
if (node instanceof THREE.FunctionNode) {
for (var i = 0; i < node.includes.length; i++) {
this.include( shader, node.includes[i] );
node = typeof node === 'string' ? THREE.LibNode.get( node ) : node;
if ( node instanceof THREE.FunctionNode ) {
for ( var i = 0; i < node.includes.length; i ++ ) {
this.include( shader, node.includes[ i ] );
}
includes = this.functions[shader] = this.functions[shader] || [];
includes = this.functions[ shader ] = this.functions[ shader ] || [];
}
else if (node instanceof THREE.ConstNode) {
includes = this.consts[shader] = this.consts[shader] || [];
else if ( node instanceof THREE.ConstNode ) {
includes = this.consts[ shader ] = this.consts[ shader ] || [];
}
if (includes[node.name] === undefined) {
for (var ext in node.extensions) {
this.extensions[ext] = true;
if ( includes[ node.name ] === undefined ) {
for ( var ext in node.extensions ) {
this.extensions[ ext ] = true;
}
includes[node.name] = {
includes[ node.name ] = {
node : node,
deps : 1
};
includes.push(includes[node.name]);
includes.push( includes[ node.name ] );
}
else ++includes[node.name].deps;
else ++ includes[ node.name ].deps;
};
\ No newline at end of file
};
......@@ -3,35 +3,35 @@
*/
THREE.RawNode = function( value ) {
THREE.GLNode.call( this, 'v4' );
this.value = value;
};
THREE.RawNode.prototype = Object.create( THREE.GLNode.prototype );
THREE.RawNode.prototype.constructor = THREE.RawNode;
THREE.GLNode.prototype.generate = function( builder ) {
var material = builder.material;
var data = this.value.verifyAndBuildCode( builder, this.type );
var code = data.code + '\n';
if (builder.shader == 'vertex') {
if ( builder.shader == 'vertex' ) {
code += 'gl_Position = ' + data.result + ';';
}
else {
code += 'gl_FragColor = ' + data.result + ';';
}
return code;
};
\ No newline at end of file
};
......@@ -4,113 +4,115 @@
*/
THREE.TempNode = function( type, params ) {
THREE.GLNode.call( this, type );
params = params || {};
this.shared = params.shared !== undefined ? params.shared : true;
this.unique = params.unique !== undefined ? params.unique : false;
};
THREE.TempNode.prototype = Object.create( THREE.GLNode.prototype );
THREE.TempNode.prototype.constructor = THREE.TempNode;
THREE.TempNode.prototype.build = function( builder, output, uuid ) {
var material = builder.material;
if (this.isShared()) {
if ( this.isShared() ) {
var isUnique = this.isUnique();
if (isUnique && this.constructor.uuid === undefined) {
if ( isUnique && this.constructor.uuid === undefined ) {
this.constructor.uuid = THREE.Math.generateUUID();
}
uuid = builder.getUuid( uuid || this.constructor.uuid || this.uuid, !isUnique );
uuid = builder.getUuid( uuid || this.constructor.uuid || this.uuid, ! isUnique );
var data = material.getDataNode( uuid );
if (builder.isShader('verify')) {
if (data.deps || 0 > 0) {
if ( builder.isShader( 'verify' ) ) {
if ( data.deps || 0 > 0 ) {
this.verifyDepsNode( builder, data, output );
return '';
}
return THREE.GLNode.prototype.build.call( this, builder, output, uuid );
}
else if (data.deps == 1) {
else if ( data.deps == 1 ) {
return THREE.GLNode.prototype.build.call( this, builder, output, uuid );
}
var name = this.getTemp( builder, uuid );
var type = data.output || this.getType( builder );
if (name) {
if ( name ) {
return builder.format( name, type, output );
}
else {
name = THREE.TempNode.prototype.generate.call( this, builder, output, uuid, data.output );
var code = this.generate( builder, type, uuid );
if (builder.isShader('vertex')) material.addVertexNode(name + '=' + code + ';');
else material.addFragmentNode(name + '=' + code + ';');
if ( builder.isShader( 'vertex' ) ) material.addVertexNode( name + '=' + code + ';' );
else material.addFragmentNode( name + '=' + code + ';' );
return builder.format( name, type, output );
}
}
else {
return builder.format( this.generate( builder, this.getType( builder ), uuid ), type, output );
}
};
THREE.TempNode.prototype.isShared = function() {
return this.shared;
};
THREE.TempNode.prototype.isUnique = function() {
return this.unique;
};
THREE.TempNode.prototype.getTemp = function( builder, uuid ) {
uuid = uuid || this.uuid;
var material = builder.material;
if (builder.isShader('vertex') && material.vertexTemps[ uuid ]) return material.vertexTemps[ uuid ].name;
else if (material.fragmentTemps[ uuid ]) return material.fragmentTemps[ uuid ].name;
if ( builder.isShader( 'vertex' ) && material.vertexTemps[ uuid ] ) return material.vertexTemps[ uuid ].name;
else if ( material.fragmentTemps[ uuid ] ) return material.fragmentTemps[ uuid ].name;
};
THREE.TempNode.prototype.generate = function( builder, output, uuid, type ) {
if (!this.isShared()) console.error("THREE.TempNode is not shared!");
if ( ! this.isShared() ) console.error( "THREE.TempNode is not shared!" );
uuid = uuid || this.uuid;
if (builder.isShader('vertex')) return builder.material.getVertexTemp( uuid, type || this.getType( builder ) ).name;
if ( builder.isShader( 'vertex' ) ) return builder.material.getVertexTemp( uuid, type || this.getType( builder ) ).name;
else return builder.material.getFragmentTemp( uuid, type || this.getType( builder ) ).name;
};
\ No newline at end of file
};
......@@ -3,25 +3,25 @@
*/
THREE.CameraNode = function( scope, camera ) {
THREE.TempNode.call( this, 'v3' );
this.scope = scope || THREE.CameraNode.POSITION;
this.camera = camera;
switch(scope) {
switch ( scope ) {
case THREE.CameraNode.DEPTH:
this.near = new THREE.FloatNode( camera ? camera.near : 1);
this.far = new THREE.FloatNode(camera ? camera.far : 1200);
this.near = new THREE.FloatNode( camera ? camera.near : 1 );
this.far = new THREE.FloatNode( camera ? camera.far : 1200 );
break;
}
this.requestUpdate = this.camera !== undefined;
};
THREE.CameraNode.prototype = Object.create( THREE.TempNode.prototype );
......@@ -31,76 +31,76 @@ THREE.CameraNode.POSITION = 'position';
THREE.CameraNode.DEPTH = 'depth';
THREE.CameraNode.prototype.getType = function( builder ) {
switch(this.scope) {
switch ( this.scope ) {
case THREE.CameraNode.DEPTH:
return 'fv1';
}
return this.type;
};
THREE.CameraNode.prototype.isUnique = function( builder ) {
switch(this.scope) {
switch ( this.scope ) {
case THREE.CameraNode.DEPTH:
return true;
}
return false;
};
THREE.CameraNode.prototype.isShared = function( builder ) {
switch(this.scope) {
switch ( this.scope ) {
case THREE.CameraNode.POSITION:
return false;
}
return true;
};
THREE.CameraNode.prototype.generate = function( builder, output ) {
var material = builder.material;
var result;
switch (this.scope) {
switch ( this.scope ) {
case THREE.CameraNode.POSITION:
result = 'cameraPosition';
break;
case THREE.CameraNode.DEPTH:
builder.include('depthcolor');
builder.include( 'depthcolor' );
result = 'depthcolor(' + this.near.build( builder, 'fv1' ) + ',' + this.far.build( builder, 'fv1' ) + ')';
break;
}
return builder.format( result, this.getType( builder ), output );
};
THREE.CameraNode.prototype.updateAnimation = function( delta ) {
switch(this.scope) {
switch ( this.scope ) {
case THREE.CameraNode.DEPTH:
this.near.number = camera.near;
this.far.number = camera.far;
break;
}
};
\ No newline at end of file
};
......@@ -3,29 +3,29 @@
*/
THREE.ColorsNode = function( index ) {
THREE.TempNode.call( this, 'v4', {share:false} );
THREE.TempNode.call( this, 'v4', { share: false } );
this.index = index || 0;
};
THREE.ColorsNode.prototype = Object.create( THREE.TempNode.prototype );
THREE.ColorsNode.prototype.constructor = THREE.ColorsNode;
THREE.ColorsNode.vertexDict = ['color', 'color2'];
THREE.ColorsNode.fragmentDict = ['vColor', 'vColor2'];
THREE.ColorsNode.vertexDict = [ 'color', 'color2' ];
THREE.ColorsNode.fragmentDict = [ 'vColor', 'vColor2' ];
THREE.ColorsNode.prototype.generate = function( builder, output ) {
var material = builder.material;
var result;
material.requestAttrib.color[this.index] = true;
if (builder.isShader('vertex')) result = THREE.ColorsNode.vertexDict[this.index];
else result = THREE.ColorsNode.fragmentDict[this.index];
material.requestAttrib.color[ this.index ] = true;
if ( builder.isShader( 'vertex' ) ) result = THREE.ColorsNode.vertexDict[ this.index ];
else result = THREE.ColorsNode.fragmentDict[ this.index ];
return builder.format( result, this.getType( builder ), output );
};
......@@ -3,11 +3,11 @@
*/
THREE.NormalNode = function( scope ) {
THREE.TempNode.call( this, 'v3' );
this.scope = scope || THREE.NormalNode.LOCAL;
};
THREE.NormalNode.prototype = Object.create( THREE.TempNode.prototype );
......@@ -18,49 +18,49 @@ THREE.NormalNode.WORLD = 'world';
THREE.NormalNode.VIEW = 'view';
THREE.NormalNode.prototype.isShared = function( builder ) {
switch(this.method) {
switch ( this.method ) {
case THREE.NormalNode.WORLD:
return true;
}
return false;
};
THREE.NormalNode.prototype.generate = function( builder, output ) {
var material = builder.material;
var result;
switch (this.scope) {
switch ( this.scope ) {
case THREE.NormalNode.LOCAL:
material.requestAttrib.normal = true;
if (builder.isShader('vertex')) result = 'normal';
if ( builder.isShader( 'vertex' ) ) result = 'normal';
else result = 'vObjectNormal';
break;
case THREE.NormalNode.WORLD:
material.requestAttrib.worldNormal = true;
if (builder.isShader('vertex')) result = '( modelMatrix * vec4( objectNormal, 0.0 ) ).xyz';
if ( builder.isShader( 'vertex' ) ) result = '( modelMatrix * vec4( objectNormal, 0.0 ) ).xyz';
else result = 'vWNormal';
break;
case THREE.NormalNode.VIEW:
result = 'vNormal';
break;
}
return builder.format( result, this.getType( builder ), output );
};
......@@ -3,11 +3,11 @@
*/
THREE.PositionNode = function( scope ) {
THREE.TempNode.call( this, 'v3' );
this.scope = scope || THREE.PositionNode.LOCAL;
};
THREE.PositionNode.prototype = Object.create( THREE.TempNode.prototype );
......@@ -19,69 +19,69 @@ THREE.PositionNode.VIEW = 'view';
THREE.PositionNode.PROJECTION = 'projection';
THREE.PositionNode.prototype.getType = function( builder ) {
switch(this.method) {
switch ( this.method ) {
case THREE.PositionNode.PROJECTION:
return 'v4';
}
return this.type;
};
THREE.PositionNode.prototype.isShared = function( builder ) {
switch(this.method) {
switch ( this.method ) {
case THREE.PositionNode.LOCAL:
case THREE.PositionNode.WORLD:
return false;
}
return true;
};
THREE.PositionNode.prototype.generate = function( builder, output ) {
var material = builder.material;
var result;
switch (this.scope) {
switch ( this.scope ) {
case THREE.PositionNode.LOCAL:
material.requestAttrib.position = true;
if (builder.isShader('vertex')) result = 'transformed';
if ( builder.isShader( 'vertex' ) ) result = 'transformed';
else result = 'vPosition';
break;
case THREE.PositionNode.WORLD:
material.requestAttrib.worldPosition = true;
if (builder.isShader('vertex')) result = 'vWPosition';
if ( builder.isShader( 'vertex' ) ) result = 'vWPosition';
else result = 'vWPosition';
break;
case THREE.PositionNode.VIEW:
if (builder.isShader('vertex')) result = '-mvPosition.xyz';
if ( builder.isShader( 'vertex' ) ) result = '-mvPosition.xyz';
else result = 'vViewPosition';
break;
case THREE.PositionNode.PROJECTION:
if (builder.isShader('vertex')) result = '(projectionMatrix * modelViewMatrix * vec4( position, 1.0 ))';
if ( builder.isShader( 'vertex' ) ) result = '(projectionMatrix * modelViewMatrix * vec4( position, 1.0 ))';
else result = 'vec4( 0.0 )';
break;
}
return builder.format( result, this.getType( builder ), output );
};
\ No newline at end of file
};
......@@ -3,37 +3,37 @@
*/
THREE.ReflectNode = function() {
THREE.TempNode.call( this, 'v3', {unique:true} );
THREE.TempNode.call( this, 'v3', { unique: true } );
this.worldPosition = new THREE.PositionNode( THREE.PositionNode.WORLD );
};
THREE.ReflectNode.prototype = Object.create( THREE.TempNode.prototype );
THREE.ReflectNode.prototype.constructor = THREE.ReflectNode;
THREE.ReflectNode.prototype.generate = function( builder, output ) {
var material = builder.material;
if (builder.isShader('fragment')) {
if ( builder.isShader( 'fragment' ) ) {
material.addFragmentNode( [
'vec3 cameraToVertex = normalize( ' + this.worldPosition.build( builder, 'v3' ) + ' - cameraPosition );',
'vec3 cameraToVertex = normalize( ' + this.worldPosition.build( builder, 'v3' ) + ' - cameraPosition );',
'vec3 worldNormal = inverseTransformDirection( normal, viewMatrix );',
'vec3 vReflect = reflect( cameraToVertex, worldNormal );'
].join( "\n" ) );
return builder.format( 'vReflect', this.type, output );
}
else {
console.warn("THREE.ReflectNode is not compatible with " + builder.shader + " shader");
console.warn( "THREE.ReflectNode is not compatible with " + builder.shader + " shader" );
return builder.format( 'vec3( 0.0 )', this.type, output );
}
};
\ No newline at end of file
};
......@@ -3,29 +3,29 @@
*/
THREE.UVNode = function( index ) {
THREE.TempNode.call( this, 'v2', {shared:false} );
THREE.TempNode.call( this, 'v2', { shared: false } );
this.index = index || 0;
};
THREE.UVNode.prototype = Object.create( THREE.TempNode.prototype );
THREE.UVNode.prototype.constructor = THREE.UVNode;
THREE.UVNode.vertexDict = ['uv', 'uv2'];
THREE.UVNode.fragmentDict = ['vUv', 'vUv2'];
THREE.UVNode.vertexDict = [ 'uv', 'uv2' ];
THREE.UVNode.fragmentDict = [ 'vUv', 'vUv2' ];
THREE.UVNode.prototype.generate = function( builder, output ) {
var material = builder.material;
var result;
material.requestAttrib.uv[this.index] = true;
if (builder.isShader('vertex')) result = THREE.UVNode.vertexDict[this.index];
else result = THREE.UVNode.fragmentDict[this.index];
material.requestAttrib.uv[ this.index ] = true;
if ( builder.isShader( 'vertex' ) ) result = THREE.UVNode.vertexDict[ this.index ];
else result = THREE.UVNode.fragmentDict[ this.index ];
return builder.format( result, this.getType( builder ), output );
};
......@@ -3,38 +3,38 @@
*/
THREE.VelocityNode = function( target, params ) {
THREE.Vector3Node.call( this );
this.requestUpdate = true;
this.target = target;
this.position = this.target.position.clone();
this.velocity = new THREE.Vector3();
this.moment = new THREE.Vector3();
this.params = params || {};
};
THREE.VelocityNode.prototype = Object.create( THREE.Vector3Node.prototype );
THREE.VelocityNode.prototype.constructor = THREE.VelocityNode;
THREE.VelocityNode.prototype.updateAnimation = function( delta ) {
this.velocity.subVectors( this.target.position, this.position );
this.position.copy( this.target.position );
switch(this.params.type) {
switch ( this.params.type ) {
case "elastic":
delta *= this.params.fps || 60;
var spring = Math.pow( this.params.spring, delta );
var friction = Math.pow( this.params.friction, delta );
// spring
this.moment.x += this.velocity.x * spring;
this.moment.y += this.velocity.y * spring;
......@@ -46,14 +46,14 @@ THREE.VelocityNode.prototype.updateAnimation = function( delta ) {
this.moment.z *= friction;
this.value.copy( this.moment );
break;
default:
this.value.copy( this.velocity );
break;
}
};
\ No newline at end of file
};
......@@ -3,14 +3,14 @@
*/
THREE.ColorNode = function( color ) {
THREE.InputNode.call( this, 'c', {share:false} );
THREE.InputNode.call( this, 'c', { share: false } );
this.value = new THREE.Color( color || 0 );
};
THREE.ColorNode.prototype = Object.create( THREE.InputNode.prototype );
THREE.ColorNode.prototype.constructor = THREE.ColorNode;
THREE.NodeMaterial.Shortcuts( THREE.ColorNode.prototype, 'value', [ 'r', 'g', 'b' ] );
\ No newline at end of file
THREE.NodeMaterial.Shortcuts( THREE.ColorNode.prototype, 'value', [ 'r', 'g', 'b' ] );
......@@ -3,13 +3,13 @@
*/
THREE.CubeTextureNode = function( value, coord, bias ) {
THREE.InputNode.call( this, 'v4' );
this.value = value;
this.coord = coord || new THREE.ReflectNode();
this.bias = bias;
};
THREE.CubeTextureNode.prototype = Object.create( THREE.InputNode.prototype );
......@@ -20,18 +20,18 @@ THREE.CubeTextureNode.prototype.generate = function( builder, output ) {
var cubetex = THREE.InputNode.prototype.generate.call( this, builder, output, this.value.uuid, 't' );
var coord = this.coord.build( builder, 'v3' );
var bias = this.bias ? this.bias.build( builder, 'fv1' ) : undefined;;
if (bias == undefined && builder.require.cubeTextureBias) {
if ( bias == undefined && builder.require.cubeTextureBias ) {
bias = builder.require.cubeTextureBias.build( builder, 'fv1' );
}
var code;
if (bias) code = 'textureCube(' + cubetex + ',' + coord + ',' + bias + ')';
if ( bias ) code = 'textureCube(' + cubetex + ',' + coord + ',' + bias + ')';
else code = 'textureCube(' + cubetex + ',' + coord + ')';
return builder.format(code, this.type, output );
};
\ No newline at end of file
return builder.format( code, this.type, output );
};
......@@ -3,11 +3,11 @@
*/
THREE.FloatNode = function( value ) {
THREE.InputNode.call( this, 'fv1', {share:false} );
THREE.InputNode.call( this, 'fv1', { share: false } );
this.value = [ value || 0 ];
};
THREE.FloatNode.prototype = Object.create( THREE.InputNode.prototype );
......@@ -15,7 +15,15 @@ THREE.FloatNode.prototype.constructor = THREE.FloatNode;
Object.defineProperties( THREE.FloatNode.prototype, {
number: {
get: function () { return this.value[0]; },
set: function ( val ) { this.value[0] = val; }
get: function() {
return this.value[ 0 ];
},
set: function( val ) {
this.value[ 0 ] = val;
}
}
});
\ No newline at end of file
} );
......@@ -3,11 +3,11 @@
*/
THREE.IntNode = function( value ) {
THREE.InputNode.call( this, 'fv1', {share:false} );
this.value = [ Math.floor(value || 0) ];
THREE.InputNode.call( this, 'fv1', { share: false } );
this.value = [ Math.floor( value || 0 ) ];
};
THREE.IntNode.prototype = Object.create( THREE.InputNode.prototype );
......@@ -15,7 +15,15 @@ THREE.IntNode.prototype.constructor = THREE.IntNode;
Object.defineProperties( THREE.IntNode.prototype, {
number: {
get: function () { return this.value[0]; },
set: function ( val ) { this.value[0] = Math.floor(val); }
get: function() {
return this.value[ 0 ];
},
set: function( val ) {
this.value[ 0 ] = Math.floor( val );
}
}
});
} );
......@@ -3,13 +3,13 @@
*/
THREE.TextureNode = function( value, coord, bias ) {
THREE.InputNode.call( this, 'v4' );
this.value = value;
this.coord = coord || new THREE.UVNode();
this.bias = bias;
};
THREE.TextureNode.prototype = Object.create( THREE.InputNode.prototype );
......@@ -20,12 +20,12 @@ THREE.TextureNode.prototype.generate = function( builder, output ) {
var tex = THREE.InputNode.prototype.generate.call( this, builder, output, this.value.uuid, 't' );
var coord = this.coord.build( builder, 'v2' );
var bias = this.bias ? this.bias.build( builder, 'fv1' ) : undefined;
var code;
if (bias) code = 'texture2D(' + tex + ',' + coord + ',' + bias + ')';
if ( bias ) code = 'texture2D(' + tex + ',' + coord + ',' + bias + ')';
else code = 'texture2D(' + tex + ',' + coord + ')';
return builder.format(code, this.type, output );
return builder.format( code, this.type, output );
};
......@@ -3,14 +3,14 @@
*/
THREE.Vector2Node = function( x, y ) {
THREE.InputNode.call( this, 'v2', {share:false} );
THREE.InputNode.call( this, 'v2', { share: false } );
this.value = new THREE.Vector2( x, y );
};
THREE.Vector2Node.prototype = Object.create( THREE.InputNode.prototype );
THREE.Vector2Node.prototype.constructor = THREE.Vector2Node;
THREE.NodeMaterial.Shortcuts( THREE.Vector2Node.prototype, 'value', [ 'x', 'y' ] );
\ No newline at end of file
THREE.NodeMaterial.Shortcuts( THREE.Vector2Node.prototype, 'value', [ 'x', 'y' ] );
......@@ -3,15 +3,15 @@
*/
THREE.Vector3Node = function( x, y, z ) {
THREE.InputNode.call( this, 'v3', {share:false} );
THREE.InputNode.call( this, 'v3', { share: false } );
this.type = 'v3';
this.value = new THREE.Vector3( x, y, z );
};
THREE.Vector3Node.prototype = Object.create( THREE.InputNode.prototype );
THREE.Vector3Node.prototype.constructor = THREE.Vector3Node;
THREE.NodeMaterial.Shortcuts( THREE.Vector3Node.prototype, 'value', [ 'x', 'y', 'z' ] );
\ No newline at end of file
THREE.NodeMaterial.Shortcuts( THREE.Vector3Node.prototype, 'value', [ 'x', 'y', 'z' ] );
......@@ -3,14 +3,14 @@
*/
THREE.Vector4Node = function( x, y, z, w ) {
THREE.InputNode.call( this, 'v4', {share:false} );
THREE.InputNode.call( this, 'v4', { share: false } );
this.value = new THREE.Vector4( x, y, z, w );
};
THREE.Vector4Node.prototype = Object.create( THREE.InputNode.prototype );
THREE.Vector4Node.prototype.constructor = THREE.Vector4Node;
THREE.NodeMaterial.Shortcuts( THREE.Vector4Node.prototype, 'value', [ 'x', 'y', 'z', 'w' ] );
\ No newline at end of file
THREE.NodeMaterial.Shortcuts( THREE.Vector4Node.prototype, 'value', [ 'x', 'y', 'z', 'w' ] );
......@@ -3,32 +3,32 @@
*/
THREE.PhongNode = function() {
THREE.GLNode.call( this );
this.color = new THREE.ColorNode( 0xEEEEEE );
this.specular = new THREE.ColorNode( 0x111111 );
this.shininess = new THREE.FloatNode( 30 );
};
THREE.PhongNode.prototype = Object.create( THREE.GLNode.prototype );
THREE.PhongNode.prototype.constructor = THREE.PhongNode;
THREE.PhongNode.prototype.build = function( builder ) {
var material = builder.material;
var code;
material.define( 'PHONG' );
material.define( 'ALPHATEST', '0.0' );
material.needsLight = true;
if (builder.isShader('vertex')) {
if ( builder.isShader( 'vertex' ) ) {
var transform = this.transform ? this.transform.verifyAndBuildCode( builder, 'v3' ) : undefined;
material.mergeUniform( THREE.UniformsUtils.merge( [
THREE.UniformsLib[ "fog" ],
......@@ -36,7 +36,7 @@ THREE.PhongNode.prototype.build = function( builder ) {
THREE.UniformsLib[ "shadowmap" ]
] ) );
material.addVertexPars( [
"varying vec3 vViewPosition;",
......@@ -54,7 +54,7 @@ THREE.PhongNode.prototype.build = function( builder ) {
THREE.ShaderChunk[ "logdepthbuf_pars_vertex" ]
].join( "\n" ) );
var output = [
THREE.ShaderChunk[ "beginnormal_vertex" ],
THREE.ShaderChunk[ "morphnormal_vertex" ],
......@@ -70,12 +70,14 @@ THREE.PhongNode.prototype.build = function( builder ) {
THREE.ShaderChunk[ "begin_vertex" ]
];
if ( transform ) {
output.push( transform.code );
output.push( "transformed = " + transform.result + ";" );
}
output.push(
THREE.ShaderChunk[ "morphtarget_vertex" ],
THREE.ShaderChunk[ "skinning_vertex" ],
......@@ -88,52 +90,52 @@ THREE.PhongNode.prototype.build = function( builder ) {
THREE.ShaderChunk[ "lights_phong_vertex" ],
THREE.ShaderChunk[ "shadowmap_vertex" ]
);
code = output.join( "\n" );
}
else {
// verify all nodes to reuse generate codes
this.color.verify( builder );
this.specular.verify( builder );
this.shininess.verify( builder );
if (this.alpha) this.alpha.verify( builder );
if (this.ao) this.ao.verify( builder );
if (this.ambient) this.ambient.verify( builder );
if (this.shadow) this.shadow.verify( builder );
if (this.emissive) this.emissive.verify( builder );
if (this.normal) this.normal.verify( builder );
if (this.normalScale && this.normal) this.normalScale.verify( builder );
if (this.environment) this.environment.verify( builder );
if (this.reflectivity && this.environment) this.reflectivity.verify( builder );
if ( this.alpha ) this.alpha.verify( builder );
if ( this.ao ) this.ao.verify( builder );
if ( this.ambient ) this.ambient.verify( builder );
if ( this.shadow ) this.shadow.verify( builder );
if ( this.emissive ) this.emissive.verify( builder );
if ( this.normal ) this.normal.verify( builder );
if ( this.normalScale && this.normal ) this.normalScale.verify( builder );
if ( this.environment ) this.environment.verify( builder );
if ( this.reflectivity && this.environment ) this.reflectivity.verify( builder );
// build code
var color = this.color.buildCode( builder, 'v4' );
var specular = this.specular.buildCode( builder, 'c' );
var shininess = this.shininess.buildCode( builder, 'fv1' );
var alpha = this.alpha ? this.alpha.buildCode( builder, 'fv1' ) : undefined;
var ao = this.ao ? this.ao.buildCode( builder, 'c' ) : undefined;
var ambient = this.ambient ? this.ambient.buildCode( builder, 'c' ) : undefined;
var shadow = this.shadow ? this.shadow.buildCode( builder, 'c' ) : undefined;
var emissive = this.emissive ? this.emissive.buildCode( builder, 'c' ) : undefined;
var normal = this.normal ? this.normal.buildCode( builder, 'v3' ) : undefined;
var normalScale = this.normalScale && this.normal ? this.normalScale.buildCode( builder, 'fv1' ) : undefined;
var environment = this.environment ? this.environment.buildCode( builder.setCache('env'), 'c' ) : undefined;
var environment = this.environment ? this.environment.buildCode( builder.setCache( 'env' ), 'c' ) : undefined;
var reflectivity = this.reflectivity && this.environment ? this.reflectivity.buildCode( builder, 'fv1' ) : undefined;
material.needsTransparent = alpha != undefined;
material.addFragmentPars( [
THREE.ShaderChunk[ "common" ],
THREE.ShaderChunk[ "fog_pars_fragment" ],
......@@ -143,115 +145,130 @@ THREE.PhongNode.prototype.build = function( builder ) {
THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
THREE.ShaderChunk[ "logdepthbuf_pars_fragment" ]
].join( "\n" ) );
var output = [
// prevent undeclared normal
THREE.ShaderChunk[ "normal_fragment" ],
color.code,
" vec4 diffuseColor = " + color.result + ";",
" ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );",
THREE.ShaderChunk[ "logdepthbuf_fragment" ],
specular.code,
" vec3 specular = " + specular.result + ";",
shininess.code,
" float shininess = max(0.0001," + shininess.result + ");",
" float specularStrength = 1.0;" // Ignored in MaterialNode ( replace to specular )
];
if (alpha) {
output.push(
];
if ( alpha ) {
output.push(
alpha.code,
'if ( ' + alpha.result + ' <= ALPHATEST ) discard;'
);
}
if (normal) {
if ( normal ) {
builder.include( 'perturbNormal2Arb' );
output.push(normal.code);
if (normalScale) output.push(normalScale.code);
output.push( normal.code );
if ( normalScale ) output.push( normalScale.code );
output.push(
'normal = perturbNormal2Arb(-vViewPosition,normal,' +
normal.result + ',' +
new THREE.UVNode().build( builder, 'v2' ) + ',' +
(normalScale ? normalScale.result : '1.0') + ');'
( normalScale ? normalScale.result : '1.0' ) + ');'
);
}
output.push(
THREE.ShaderChunk[ "shadowmap_fragment" ],
// accumulation
THREE.ShaderChunk[ "lights_phong_fragment" ],
THREE.ShaderChunk[ "lights_template" ]
);
if (ao) {
if ( ao ) {
output.push( ao.code );
output.push( "reflectedLight.indirectDiffuse *= " + ao.result + ";" );
}
if (ambient) {
if ( ambient ) {
output.push( ambient.code );
output.push( "reflectedLight.indirectDiffuse += " + ambient.result + ";" );
}
if (shadow) {
if ( shadow ) {
output.push( shadow.code );
output.push( "reflectedLight.directDiffuse *= " + shadow.result + ";" );
output.push( "reflectedLight.directSpecular *= " + shadow.result + ";" );
}
if (emissive) {
if ( emissive ) {
output.push( emissive.code );
output.push( "reflectedLight.directDiffuse += " + emissive.result + ";" );
}
output.push("vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular;");
if (environment) {
output.push( "vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular;" );
if ( environment ) {
output.push( environment.code );
if (reflectivity) {
if ( reflectivity ) {
output.push( reflectivity.code );
output.push( "outgoingLight = mix(" + 'outgoingLight' + "," + environment.result + "," + reflectivity.result + ");" );
}
else {
output.push( "outgoingLight = " + environment.result + ";" );
}
}
output.push(
THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
THREE.ShaderChunk[ "fog_fragment" ]
);
if (alpha) {
if ( alpha ) {
output.push( "gl_FragColor = vec4( outgoingLight, " + alpha.result + " );" );
}
else {
output.push( "gl_FragColor = vec4( outgoingLight, 1.0 );" );
}
code = output.join( "\n" );
}
return code;
};
\ No newline at end of file
};
......@@ -3,15 +3,15 @@
*/
THREE.PhongNodeMaterial = function() {
this.node = new THREE.PhongNode();
THREE.NodeMaterial.call( this, this.node, this.node );
};
THREE.PhongNodeMaterial.prototype = Object.create( THREE.NodeMaterial.prototype );
THREE.PhongNodeMaterial.prototype.constructor = THREE.PhongNodeMaterial;
THREE.NodeMaterial.Shortcuts( THREE.PhongNodeMaterial.prototype, 'node',
[ 'color', 'alpha', 'specular', 'shininess', 'normal', 'normalScale', 'emissive', 'ambient', 'shadow', 'ao', 'environment', 'reflectivity', 'transform' ] );
\ No newline at end of file
THREE.NodeMaterial.Shortcuts( THREE.PhongNodeMaterial.prototype, 'node',
[ 'color', 'alpha', 'specular', 'shininess', 'normal', 'normalScale', 'emissive', 'ambient', 'shadow', 'ao', 'environment', 'reflectivity', 'transform' ] );
......@@ -3,32 +3,32 @@
*/
THREE.StandardNode = function() {
THREE.GLNode.call( this );
this.color = new THREE.ColorNode( 0xEEEEEE );
this.roughness = new THREE.FloatNode( 0.5 );
this.metalness = new THREE.FloatNode( 0.5 );
};
THREE.StandardNode.prototype = Object.create( THREE.GLNode.prototype );
THREE.StandardNode.prototype.constructor = THREE.StandardNode;
THREE.StandardNode.prototype.build = function( builder ) {
var material = builder.material;
var code;
material.define( 'STANDARD' );
material.define( 'ALPHATEST', '0.0' );
material.needsLight = true;
if (builder.isShader('vertex')) {
if ( builder.isShader( 'vertex' ) ) {
var transform = this.transform ? this.transform.verifyAndBuildCode( builder, 'v3' ) : undefined;
material.mergeUniform( THREE.UniformsUtils.merge( [
THREE.UniformsLib[ "fog" ],
......@@ -36,7 +36,7 @@ THREE.StandardNode.prototype.build = function( builder ) {
THREE.UniformsLib[ "shadowmap" ]
] ) );
material.addVertexPars( [
"varying vec3 vViewPosition;",
......@@ -54,7 +54,7 @@ THREE.StandardNode.prototype.build = function( builder ) {
THREE.ShaderChunk[ "logdepthbuf_pars_vertex" ]
].join( "\n" ) );
var output = [
THREE.ShaderChunk[ "beginnormal_vertex" ],
THREE.ShaderChunk[ "morphnormal_vertex" ],
......@@ -70,12 +70,14 @@ THREE.StandardNode.prototype.build = function( builder ) {
THREE.ShaderChunk[ "begin_vertex" ]
];
if ( transform ) {
output.push( transform.code );
output.push( "transformed = " + transform.result + ";" );
}
output.push(
THREE.ShaderChunk[ "morphtarget_vertex" ],
THREE.ShaderChunk[ "skinning_vertex" ],
......@@ -88,66 +90,66 @@ THREE.StandardNode.prototype.build = function( builder ) {
THREE.ShaderChunk[ "lights_phong_vertex" ],
THREE.ShaderChunk[ "shadowmap_vertex" ]
);
code = output.join( "\n" );
}
else {
// CubeMap blur effect (PBR)
builder.require.cubeTextureBias = builder.require.cubeTextureBias || new THREE.RoughnessToBlinnExponentNode();
// verify all nodes to reuse generate codes
this.color.verify( builder );
this.roughness.verify( builder );
this.metalness.verify( builder );
if (this.alpha) this.alpha.verify( builder );
if (this.ao) this.ao.verify( builder );
if (this.ambient) this.ambient.verify( builder );
if (this.shadow) this.shadow.verify( builder );
if (this.emissive) this.emissive.verify( builder );
if (this.normal) this.normal.verify( builder );
if (this.normalScale && this.normal) this.normalScale.verify( builder );
if (this.environment) this.environment.verify( builder.setCache('env') ); // isolate environment from others inputs ( see TextureNode, CubeTextureNode )
if (this.reflectivity && this.environment) this.reflectivity.verify( builder );
if ( this.alpha ) this.alpha.verify( builder );
if ( this.ao ) this.ao.verify( builder );
if ( this.ambient ) this.ambient.verify( builder );
if ( this.shadow ) this.shadow.verify( builder );
if ( this.emissive ) this.emissive.verify( builder );
if ( this.normal ) this.normal.verify( builder );
if ( this.normalScale && this.normal ) this.normalScale.verify( builder );
if ( this.environment ) this.environment.verify( builder.setCache( 'env' ) ); // isolate environment from others inputs ( see TextureNode, CubeTextureNode )
if ( this.reflectivity && this.environment ) this.reflectivity.verify( builder );
// build code
var color = this.color.buildCode( builder, 'v4' );
var roughness = this.roughness.buildCode( builder, 'fv1' );
var metalness = this.metalness.buildCode( builder, 'fv1' );
var alpha = this.alpha ? this.alpha.buildCode( builder, 'fv1' ) : undefined;
var ao = this.ao ? this.ao.buildCode( builder, 'c' ) : undefined;
var ambient = this.ambient ? this.ambient.buildCode( builder, 'c' ) : undefined;
var shadow = this.shadow ? this.shadow.buildCode( builder, 'c' ) : undefined;
var emissive = this.emissive ? this.emissive.buildCode( builder, 'c' ) : undefined;
var normal = this.normal ? this.normal.buildCode( builder, 'v3' ) : undefined;
var normalScale = this.normalScale && this.normal ? this.normalScale.buildCode( builder, 'fv1' ) : undefined;
var environment = this.environment ? this.environment.buildCode( builder.setCache('env'), 'c' ) : undefined;
var environment = this.environment ? this.environment.buildCode( builder.setCache( 'env' ), 'c' ) : undefined;
var reflectivity = this.reflectivity && this.environment ? this.reflectivity.buildCode( builder, 'fv1' ) : undefined;
material.needsTransparent = alpha != undefined;
material.addFragmentPars( [
"varying vec3 vViewPosition;",
"#ifndef FLAT_SHADED",
" varying vec3 vNormal;",
"#endif",
THREE.ShaderChunk[ "common" ],
THREE.ShaderChunk[ "fog_pars_fragment" ],
THREE.ShaderChunk[ "bsdfs" ],
......@@ -156,113 +158,129 @@ THREE.StandardNode.prototype.build = function( builder ) {
THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
THREE.ShaderChunk[ "logdepthbuf_pars_fragment" ],
].join( "\n" ) );
var output = [
// prevent undeclared normal
THREE.ShaderChunk[ "normal_fragment" ],
// prevent undeclared material
" StandardMaterial material;",
color.code,
" vec4 diffuseColor = " + color.result + ";",
" ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );",
THREE.ShaderChunk[ "logdepthbuf_fragment" ],
roughness.code,
" float roughnessFactor = " + roughness.result + ";",
metalness.code,
" float metalnessFactor = " + metalness.result + ";"
];
if (alpha) {
output.push(
];
if ( alpha ) {
output.push(
alpha.code,
'if ( ' + alpha.result + ' <= ALPHATEST ) discard;'
);
}
if (normal) {
if ( normal ) {
builder.include( 'perturbNormal2Arb' );
output.push(normal.code);
if (normalScale) output.push(normalScale.code);
output.push( normal.code );
if ( normalScale ) output.push( normalScale.code );
output.push(
'normal = perturbNormal2Arb(-vViewPosition,normal,' +
normal.result + ',' +
new THREE.UVNode().build( builder, 'v2' ) + ',' +
(normalScale ? normalScale.result : '1.0') + ');'
( normalScale ? normalScale.result : '1.0' ) + ');'
);
}
output.push(
THREE.ShaderChunk[ "shadowmap_fragment" ],
// accumulation
'material.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );',
'material.specularRoughness = clamp( roughnessFactor, 0.001, 1.0 );', // disney's remapping of [ 0, 1 ] roughness to [ 0.001, 1 ]
'material.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );',
THREE.ShaderChunk[ "lights_template" ]
);
if (ao) {
if ( ao ) {
output.push( ao.code );
output.push( "reflectedLight.indirectDiffuse *= " + ao.result + ";" );
}
if (ambient) {
if ( ambient ) {
output.push( ambient.code );
output.push( "reflectedLight.indirectDiffuse += " + ambient.result + ";" );
}
if (shadow) {
if ( shadow ) {
output.push( shadow.code );
output.push( "reflectedLight.directDiffuse *= " + shadow.result + ";" );
output.push( "reflectedLight.directSpecular *= " + shadow.result + ";" );
}
if (emissive) {
if ( emissive ) {
output.push( emissive.code );
output.push( "reflectedLight.directDiffuse += " + emissive.result + ";" );
}
if (environment) {
if ( environment ) {
output.push( environment.code );
output.push( "RE_IndirectSpecular(" + environment.result + ", geometry, material, reflectedLight );" );
}
if (reflectivity) {
if ( reflectivity ) {
output.push( reflectivity.code );
output.push( "reflectedLight.indirectSpecular *= " + reflectivity.result + ";" );
}
output.push("vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular;");
output.push( "vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular;" );
output.push(
THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
THREE.ShaderChunk[ "fog_fragment" ]
);
if (alpha) {
if ( alpha ) {
output.push( "gl_FragColor = vec4( outgoingLight, " + alpha.result + " );" );
}
else {
output.push( "gl_FragColor = vec4( outgoingLight, 1.0 );" );
}
code = output.join( "\n" );
}
return code;
};
\ No newline at end of file
};
......@@ -3,15 +3,15 @@
*/
THREE.StandardNodeMaterial = function() {
this.node = new THREE.StandardNode();
THREE.NodeMaterial.call( this, this.node, this.node );
};
THREE.StandardNodeMaterial.prototype = Object.create( THREE.NodeMaterial.prototype );
THREE.StandardNodeMaterial.prototype.constructor = THREE.StandardNodeMaterial;
THREE.NodeMaterial.Shortcuts( THREE.StandardNodeMaterial.prototype, 'node',
[ 'color', 'alpha', 'roughness', 'metalness', 'normal', 'normalScale', 'emissive', 'ambient', 'shadow', 'ao', 'environment', 'reflectivity', 'transform' ] );
\ No newline at end of file
THREE.NodeMaterial.Shortcuts( THREE.StandardNodeMaterial.prototype, 'node',
[ 'color', 'alpha', 'roughness', 'metalness', 'normal', 'normalScale', 'emissive', 'ambient', 'shadow', 'ao', 'environment', 'reflectivity', 'transform' ] );
......@@ -3,13 +3,13 @@
*/
THREE.Math1Node = function( a, method ) {
THREE.TempNode.call( this );
this.a = a;
this.method = method || THREE.Math1Node.SIN;
};
THREE.Math1Node.prototype = Object.create( THREE.TempNode.prototype );
......@@ -40,39 +40,39 @@ THREE.Math1Node.NEGATE = 'negate';
THREE.Math1Node.INVERT = 'invert';
THREE.Math1Node.prototype.getType = function( builder ) {
switch(this.method) {
switch ( this.method ) {
case THREE.Math1Node.DISTANCE:
return 'fv1';
}
return this.a.getType( builder );
};
THREE.Math1Node.prototype.generate = function( builder, output ) {
var material = builder.material;
var type = this.getType( builder );
var result = this.a.build( builder, type );
switch(this.method) {
switch ( this.method ) {
case THREE.Math1Node.NEGATE:
result = '(-' + result + ')';
break;
case THREE.Math1Node.INVERT:
result = '(1.0-' + result + ')';
break;
default:
result = this.method + '(' + result + ')';
break;
}
return builder.format( result, type, output );
};
\ No newline at end of file
};
......@@ -3,14 +3,14 @@
*/
THREE.Math2Node = function( a, b, method ) {
THREE.TempNode.call( this );
this.a = a;
this.b = b;
this.method = method || THREE.Math2Node.DISTANCE;
};
THREE.Math2Node.prototype = Object.create( THREE.TempNode.prototype );
......@@ -27,67 +27,70 @@ THREE.Math2Node.CROSS = 'cross';
THREE.Math2Node.POW = 'pow';
THREE.Math2Node.prototype.getInputType = function( builder ) {
// use the greater length vector
if (builder.getFormatLength( this.b.getType( builder ) ) > builder.getFormatLength( this.a.getType( builder ) )) {
if ( builder.getFormatLength( this.b.getType( builder ) ) > builder.getFormatLength( this.a.getType( builder ) ) ) {
return this.b.getType( builder );
}
return this.a.getType( builder );
};
THREE.Math2Node.prototype.getType = function( builder ) {
switch(this.method) {
switch ( this.method ) {
case THREE.Math2Node.DISTANCE:
case THREE.Math2Node.DOT:
return 'fv1';
case THREE.Math2Node.CROSS:
return 'v3';
}
return this.getInputType( builder );
};
THREE.Math2Node.prototype.generate = function( builder, output ) {
var material = builder.material;
var type = this.getInputType( builder );
var a, b,
var a, b,
al = builder.getFormatLength( this.a.getType( builder ) ),
bl = builder.getFormatLength( this.b.getType( builder ) );
// optimzer
switch(this.method) {
switch ( this.method ) {
case THREE.Math2Node.CROSS:
a = this.a.build( builder, 'v3' );
b = this.b.build( builder, 'v3' );
break;
case THREE.Math2Node.STEP:
a = this.a.build( builder, al == 1 ? 'fv1' : type );
b = this.b.build( builder, type );
break;
case THREE.Math2Node.MIN:
case THREE.Math2Node.MAX:
case THREE.Math2Node.MODULO:
a = this.a.build( builder, type );
b = this.b.build( builder, bl == 1 ? 'fv1' : type );
break;
default:
a = this.a.build( builder, type );
b = this.b.build( builder, type );
break;
}
return builder.format( this.method + '(' + a + ',' + b + ')', this.getType( builder ), output );
};
\ No newline at end of file
};
......@@ -3,15 +3,15 @@
*/
THREE.Math3Node = function( a, b, c, method ) {
THREE.TempNode.call( this );
this.a = a;
this.b = b;
this.c = c;
this.method = method || THREE.Math3Node.MIX;
};
THREE.Math3Node.prototype = Object.create( THREE.TempNode.prototype );
......@@ -23,58 +23,62 @@ THREE.Math3Node.SMOOTHSTEP = 'smoothstep';
THREE.Math3Node.FACEFORWARD = 'faceforward';
THREE.Math3Node.prototype.getType = function( builder ) {
var a = builder.getFormatLength( this.a.getType( builder ) );
var b = builder.getFormatLength( this.b.getType( builder ) );
var c = builder.getFormatLength( this.c.getType( builder ) );
if (a > b) {
if (a > c) return this.a.getType( builder );
if ( a > b ) {
if ( a > c ) return this.a.getType( builder );
return this.c.getType( builder );
}
}
else {
if (b > c) return this.b.getType( builder );
if ( b > c ) return this.b.getType( builder );
return this.c.getType( builder );
}
};
THREE.Math3Node.prototype.generate = function( builder, output ) {
var material = builder.material;
var type = this.getType( builder );
var a, b, c,
al = builder.getFormatLength( this.a.getType( builder ) ),
bl = builder.getFormatLength( this.b.getType( builder ) ),
cl = builder.getFormatLength( this.c.getType( builder ) )
// optimzer
switch(this.method) {
switch ( this.method ) {
case THREE.Math3Node.REFRACT:
a = this.a.build( builder, type );
b = this.b.build( builder, type );
c = this.c.build( builder, 'fv1' );
break;
case THREE.Math3Node.MIX:
case THREE.Math3Node.SMOOTHSTEP:
a = this.a.build( builder, type );
b = this.b.build( builder, type );
c = this.c.build( builder, cl == 1 ? 'fv1' : type );
break;
default:
a = this.a.build( builder, type );
b = this.b.build( builder, type );
c = this.c.build( builder, type );
break;
}
return builder.format( this.method + '(' + a + ',' + b + ',' + c + ')', type, output );
};
\ No newline at end of file
};
/**
* @author sunag / http://www.sunag.com.br/
*/
THREE.OperatorNode = function( a, b, op ) {
THREE.TempNode.call( this );
this.op = op || THREE.OperatorNode.ADD;
this.a = a;
this.b = b;
};
THREE.OperatorNode.prototype = Object.create( THREE.TempNode.prototype );
......@@ -22,24 +22,26 @@ THREE.OperatorNode.MUL = '*';
THREE.OperatorNode.DIV = '/';
THREE.OperatorNode.prototype.getType = function( builder ) {
// use the greater length vector
if (builder.getFormatLength( this.b.getType( builder ) ) > builder.getFormatLength( this.a.getType( builder ) )) {
if ( builder.getFormatLength( this.b.getType( builder ) ) > builder.getFormatLength( this.a.getType( builder ) ) ) {
return this.b.getType( builder );
}
return this.a.getType( builder );
};
THREE.OperatorNode.prototype.generate = function( builder, output ) {
var material = builder.material;
var data = material.getDataNode( this.uuid );
var a = this.a.build( builder, output );
var b = this.b.build( builder, output );
return '(' + a + this.op + b + ')';
};
\ No newline at end of file
};
......@@ -3,63 +3,67 @@
*/
THREE.JoinNode = function( x, y, z, w ) {
THREE.GLNode.call( this, 'fv1' );
this.x = x;
this.y = y;
this.z = z;
this.w = w;
};
THREE.JoinNode.prototype = Object.create( THREE.GLNode.prototype );
THREE.JoinNode.prototype.constructor = THREE.JoinNode;
THREE.JoinNode.inputs = ['x','y','z','w'];
THREE.JoinNode.inputs = [ 'x', 'y', 'z', 'w' ];
THREE.JoinNode.prototype.getNumElements = function() {
var inputs = THREE.JoinNode.inputs;
var i = inputs.length;
while (i--) {
if ( this[ inputs[i] ] !== undefined ) {
++i;
while ( i -- ) {
if ( this[ inputs[ i ] ] !== undefined ) {
++ i;
break;
}
}
return Math.max(i, 2);
return Math.max( i, 2 );
};
THREE.JoinNode.prototype.getType = function( builder ) {
return builder.getFormatByLength( this.getNumElements() );
};
THREE.JoinNode.prototype.generate = function( builder, output ) {
var material = builder.material;
var type = this.getType( builder );
var length = this.getNumElements();
var inputs = THREE.JoinNode.inputs;
var outputs = [];
for(var i = 0; i < length; i++) {
var elm = this[inputs[i]];
for ( var i = 0; i < length; i ++ ) {
var elm = this[ inputs[ i ]];
outputs.push( elm ? elm.build( builder, 'fv1' ) : '0.' );
}
var code = builder.getFormatConstructor(length) + '(' + outputs.join(',') + ')';
var code = builder.getFormatConstructor( length ) + '(' + outputs.join( ',' ) + ')';
return builder.format( code, type, output );
};
\ No newline at end of file
};
......@@ -3,42 +3,42 @@
*/
THREE.RoughnessToBlinnExponentNode = function() {
THREE.TempNode.call( this, 'fv1', {unique:true} );
THREE.TempNode.call( this, 'fv1', { unique: true } );
};
THREE.RoughnessToBlinnExponentNode.prototype = Object.create( THREE.TempNode.prototype );
THREE.RoughnessToBlinnExponentNode.prototype.constructor = THREE.RoughnessToBlinnExponentNode;
THREE.RoughnessToBlinnExponentNode.prototype.generate = function( builder, output ) {
var material = builder.material;
if (builder.isShader('fragment')) {
if (material.isDefined('STANDARD')) {
material.addFragmentNode('float specularMIPLevel = GGXRoughnessToBlinnExponent( 1.0 - material.specularRoughness );');
if ( builder.isShader( 'fragment' ) ) {
if ( material.isDefined( 'STANDARD' ) ) {
material.addFragmentNode( 'float specularMIPLevel = GGXRoughnessToBlinnExponent( 1.0 - material.specularRoughness );' );
}
else {
console.warn("THREE.RoughnessToBlinnExponentNode is compatible with StandardMaterial only");
material.addFragmentNode('float specularMIPLevel = 0.0;');
console.warn( "THREE.RoughnessToBlinnExponentNode is compatible with StandardMaterial only" );
material.addFragmentNode( 'float specularMIPLevel = 0.0;' );
}
return builder.format( 'specularMIPLevel', this.type, output );
}
else {
console.warn("THREE.RoughnessToBlinnExponentNode is not compatible with " + builder.shader + " shader");
console.warn( "THREE.RoughnessToBlinnExponentNode is not compatible with " + builder.shader + " shader" );
return builder.format( '0.0', this.type, output );
}
};
\ No newline at end of file
};
......@@ -3,64 +3,66 @@
*/
THREE.SwitchNode = function( a, component ) {
THREE.GLNode.call( this, 'fv1' );
this.component = component || 'x';
this.a = a;
};
THREE.SwitchNode.prototype = Object.create( THREE.GLNode.prototype );
THREE.SwitchNode.prototype.constructor = THREE.SwitchNode;
THREE.SwitchNode.prototype.getType = function( builder ) {
return builder.getFormatByLength( this.component.length );
};
THREE.SwitchNode.prototype.generate = function( builder, output ) {
var type = this.a.getType( builder );
var inputLength = builder.getFormatLength( type ) - 1;
var a = this.a.build( builder, type );
var outputLength = 0;
var i, len = this.component.length;
// get max length
for (i = 0; i < len; i++) {
outputLength = Math.max( outputLength, builder.getElementIndex( this.component.charAt(i) ) );
for ( i = 0; i < len; i ++ ) {
outputLength = Math.max( outputLength, builder.getElementIndex( this.component.charAt( i ) ) );
}
if (outputLength > inputLength) outputLength = inputLength;
if ( outputLength > inputLength ) outputLength = inputLength;
// build switch
a += '.';
for (i = 0; i < len; i++) {
var elm = this.component.charAt(i);
var idx = builder.getElementIndex( this.component.charAt(i) );
if (idx > outputLength) idx = outputLength;
if (builder.getElementByIndex( idx ) == undefined) {
for ( i = 0; i < len; i ++ ) {
var elm = this.component.charAt( i );
var idx = builder.getElementIndex( this.component.charAt( i ) );
if ( idx > outputLength ) idx = outputLength;
if ( builder.getElementByIndex( idx ) == undefined ) {
console.log( builder.getElementByIndex( idx ) );
}
a += builder.getElementByIndex( idx );
}
return builder.format( a, this.type, output );
};
\ No newline at end of file
};
......@@ -3,18 +3,18 @@
*/
THREE.TimeNode = function( value ) {
THREE.FloatNode.call( this, value );
this.requestUpdate = true;
};
THREE.TimeNode.prototype = Object.create( THREE.FloatNode.prototype );
THREE.TimeNode.prototype.constructor = THREE.TimeNode;
THREE.TimeNode.prototype.updateAnimation = function( delta ) {
this.number += delta;
};
\ No newline at end of file
};
......@@ -99,23 +99,23 @@
var controls;
var move = false;
var gui, guiElements = [];
var param = { example: 'standard' };
var brick = new THREE.TextureLoader().load( 'textures/brick_diffuse.jpg' );
var grass = new THREE.TextureLoader().load( 'textures/terrain/grasslight-big.jpg' );
var grassNormal = new THREE.TextureLoader().load( 'textures/terrain/grasslight-big-nm.jpg' );
var decalDiffuse = new THREE.TextureLoader().load( 'textures/decal/decal-diffuse.png' );
decalDiffuse.wrapS = decalDiffuse.wrapT = THREE.RepeatWrapping;
var decalNormal = new THREE.TextureLoader().load( 'textures/decal/decal-normal.jpg' );
var cloud = new THREE.TextureLoader().load( 'textures/lava/cloud.png' );
cloud.wrapS = cloud.wrapT = THREE.RepeatWrapping;
var cubemap = function() {
var path = "textures/cube/Park2/";
var format = '.jpg';
var urls = [
......@@ -123,14 +123,14 @@
path + 'posy' + format, path + 'negy' + format,
path + 'posz' + format, path + 'negz' + format
];
var textureCube = new THREE.CubeTextureLoader().load( urls );
textureCube.format = THREE.RGBFormat;
return textureCube;
}()
window.addEventListener( 'load', init );
function init() {
......@@ -144,7 +144,7 @@
camera = new THREE.PerspectiveCamera( fov, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.x = 50;
camera.position.z = -50;
camera.position.z = - 50;
camera.position.y = 30;
camera.target = new THREE.Vector3();
......@@ -159,34 +159,34 @@
scene.add( light );
var light = new THREE.DirectionalLight( 0xccccff, 1 );
light.position.set( -1, 0.75, -0.5 );
light.position.set( - 1, 0.75, - 0.5 );
scene.add( light );
teapot = new THREE.TeapotBufferGeometry( 15, 18 );
mesh = new THREE.Mesh( teapot );
scene.add( mesh );
window.addEventListener( 'resize', onWindowResize, false );
updateMaterial();
onWindowResize();
animate();
}
function clearGui() {
if (gui) gui.destroy();
if ( gui ) gui.destroy();
gui = new dat.GUI();
var example = gui.add( param, 'example', {
var example = gui.add( param, 'example', {
'basic / standard (PBR)': 'standard',
'basic / phong': 'phong',
'basic / layers': 'layers',
'basic / rim': 'rim',
'basic / rim': 'rim',
'adv / fresnel': 'fresnel',
'adv / saturation': 'saturation',
'adv / top-bottom': 'top-bottom',
......@@ -197,64 +197,64 @@
'adv / wave': 'wave',
'misc / smoke' : 'smoke',
'misc / firefly' : 'firefly'
} ).onFinishChange(function() {
} ).onFinishChange( function() {
updateMaterial();
} );
gui.open();
}
function addGui( name, value, callback, isColor, min, max ) {
var node;
param[name] = value;
if (isColor) {
node = gui.addColor( param, name ).onChange(function() {
callback( param[name] );
param[ name ] = value;
if ( isColor ) {
node = gui.addColor( param, name ).onChange( function() {
callback( param[ name ] );
} );
}
else {
node = gui.add( param, name, min, max ).onChange(function() {
callback( param[name] );
node = gui.add( param, name, min, max ).onChange( function() {
callback( param[ name ] );
} );
}
return node;
}
function updateMaterial() {
move = false;
if (mesh.material) mesh.material.dispose();
if ( mesh.material ) mesh.material.dispose();
var name = param.example;
var mtl;
var mtl;
clearGui();
switch( name ) {
switch ( name ) {
case 'phong':
// MATERIAL
mtl = new THREE.PhongNodeMaterial();
//mtl.color = // albedo color
//mtl.alpha = // opacity (0 at 1)
//mtl.specular = // specular color
......@@ -268,25 +268,25 @@
//mtl.environment = // reflection map (CubeMap recommended)
//mtl.reflectivity = // environment intensity
//mtl.transform = // vertex transformation
var mask = new THREE.SwitchNode(new THREE.TextureNode(decalDiffuse), 'w');
mtl.color = new THREE.TextureNode(grass);
mtl.specular = new THREE.FloatNode(.5);
mtl.shininess = new THREE.FloatNode(15);
mtl.environment = new THREE.CubeTextureNode(cubemap);
var mask = new THREE.SwitchNode( new THREE.TextureNode( decalDiffuse ), 'w' );
mtl.color = new THREE.TextureNode( grass );
mtl.specular = new THREE.FloatNode( .5 );
mtl.shininess = new THREE.FloatNode( 15 );
mtl.environment = new THREE.CubeTextureNode( cubemap );
mtl.reflectivity = mask;
mtl.normal = new THREE.TextureNode(grassNormal);
mtl.normalScale = new THREE.Math1Node( mask, THREE.Math1Node.INVERT );
mtl.normal = new THREE.TextureNode( grassNormal );
mtl.normalScale = new THREE.Math1Node( mask, THREE.Math1Node.INVERT );
break;
case 'standard':
// MATERIAL
mtl = new THREE.StandardNodeMaterial();
//mtl.color = // albedo color
//mtl.alpha = // opacity (0 at 1)
//mtl.roughness = // roughness (float)
......@@ -300,680 +300,680 @@
//mtl.environment = // reflection map (CubeMap recommended)
//mtl.reflectivity = // environment intensity
//mtl.transform = // vertex transformation
var mask = new THREE.SwitchNode(new THREE.TextureNode(decalDiffuse), 'w');
var normalScale = new THREE.FloatNode(.3);
var roughnessA = new THREE.FloatNode(.5);
var metalnessA = new THREE.FloatNode(.5);
var roughnessB = new THREE.FloatNode(0);
var metalnessB = new THREE.FloatNode(1);
var mask = new THREE.SwitchNode( new THREE.TextureNode( decalDiffuse ), 'w' );
var normalScale = new THREE.FloatNode( .3 );
var roughnessA = new THREE.FloatNode( .5 );
var metalnessA = new THREE.FloatNode( .5 );
var roughnessB = new THREE.FloatNode( 0 );
var metalnessB = new THREE.FloatNode( 1 );
var roughness = new THREE.Math3Node(
roughnessA,
roughnessB,
mask,
THREE.Math3Node.MIX
);
);
var metalness = new THREE.Math3Node(
metalnessA,
metalnessB,
mask,
THREE.Math3Node.MIX
);
var normalMask = new THREE.OperatorNode(
new THREE.Math1Node( mask, THREE.Math1Node.INVERT ),
normalScale,
THREE.OperatorNode.MUL
);
mtl.color = new THREE.ColorNode(0xFFFFFF);
mtl.color = new THREE.ColorNode( 0xFFFFFF );
mtl.roughness = roughness;
mtl.metalness = metalness;
mtl.environment = new THREE.CubeTextureNode(cubemap);
mtl.normal = new THREE.TextureNode(grassNormal);
mtl.environment = new THREE.CubeTextureNode( cubemap );
mtl.normal = new THREE.TextureNode( grassNormal );
mtl.normalScale = normalMask;
// GUI
addGui( 'color', mtl.color.value.getHex(), function( val ) {
mtl.color.value.setHex( val );
}, true );
addGui( 'roughnessA', roughnessA.number, function( val ) {
roughnessA.number = val;
}, false, 0, 1 );
addGui( 'metalnessA', metalnessA.number, function( val ) {
metalnessA.number = val;
}, false, 0, 1 );
addGui( 'roughnessB', roughnessB.number, function( val ) {
roughnessB.number = val;
}, false, 0, 1 );
addGui( 'metalnessB', metalnessB.number, function( val ) {
metalnessB.number = val;
}, false, 0, 1 );
addGui( 'normalScale', normalScale.number, function( val ) {
normalScale.number = val;
}, false, 0, 1 );
break;
case 'wave':
// MATERIAL
mtl = new THREE.PhongNodeMaterial();
var time = new THREE.TimeNode();
var speed = new THREE.FloatNode(5);
var scale = new THREE.FloatNode(1);
var worldScale = new THREE.FloatNode(.4);
var colorA = new THREE.ColorNode(0xFFFFFF);
var colorB = new THREE.ColorNode(0x0054df);
var speed = new THREE.FloatNode( 5 );
var scale = new THREE.FloatNode( 1 );
var worldScale = new THREE.FloatNode( .4 );
var colorA = new THREE.ColorNode( 0xFFFFFF );
var colorB = new THREE.ColorNode( 0x0054df );
var uv = new THREE.UVNode();
var timeScale = new THREE.OperatorNode(
time,
speed,
THREE.OperatorNode.MUL
);
var worldScl = new THREE.OperatorNode(
new THREE.PositionNode(),
worldScale,
THREE.OperatorNode.MUL
);
var posContinuous = new THREE.OperatorNode(
worldScl,
timeScale,
THREE.OperatorNode.ADD
);
var wave = new THREE.Math1Node(posContinuous, THREE.Math1Node.SIN);
wave = new THREE.SwitchNode(wave, 'x');
var wave = new THREE.Math1Node( posContinuous, THREE.Math1Node.SIN );
wave = new THREE.SwitchNode( wave, 'x' );
var waveScale = new THREE.OperatorNode(
wave,
scale,
THREE.OperatorNode.MUL
);
var displaceY = new THREE.JoinNode(
new THREE.FloatNode(),
waveScale,
new THREE.FloatNode()
);
var displace = new THREE.OperatorNode(
new THREE.NormalNode(),
displaceY,
THREE.OperatorNode.MUL
);
var blend = new THREE.OperatorNode(
new THREE.PositionNode(),
displaceY,
THREE.OperatorNode.ADD
);
var color = new THREE.Math3Node(
colorB,
colorA,
wave,
THREE.Math3Node.MIX
);
mtl.color = color;
mtl.transform = blend;
// GUI
addGui( 'speed', speed.number, function( val ) {
speed.number = val;
}, false, 0, 10 );
addGui( 'scale', scale.number, function( val ) {
scale.number = val;
}, false, 0, 3 );
addGui( 'worldScale', worldScale.number, function( val ) {
worldScale.number = val;
}, false, 0, 1 );
addGui( 'colorA', colorA.value.getHex(), function( val ) {
colorA.value.setHex( val );
}, true );
addGui( 'colorB', colorB.value.getHex(), function( val ) {
colorB.value.setHex( val );
}, true );
addGui( 'useNormals', false, function( val ) {
blend.b = val ? displace : displaceY;
mtl.build();
} );
break;
case 'rim':
// MATERIAL
mtl = new THREE.PhongNodeMaterial();
var intensity = 1.3;
var power = new THREE.FloatNode(3);
var color = new THREE.ColorNode(0xFFFFFF);
var power = new THREE.FloatNode( 3 );
var color = new THREE.ColorNode( 0xFFFFFF );
var viewZ = new THREE.Math2Node(
new THREE.NormalNode( THREE.NormalNode.VIEW ),
new THREE.Vector3Node(0, 0, -intensity),
new THREE.NormalNode( THREE.NormalNode.VIEW ),
new THREE.Vector3Node( 0, 0, - intensity ),
THREE.Math2Node.DOT
);
var rim = new THREE.OperatorNode(
viewZ,
new THREE.FloatNode(intensity),
new THREE.FloatNode( intensity ),
THREE.OperatorNode.ADD
);
var rimPower = new THREE.Math2Node(
rim,
power,
rim,
power,
THREE.Math2Node.POW
);
var rimColor = new THREE.OperatorNode(
rimPower,
color,
THREE.OperatorNode.MUL
);
mtl.color = new THREE.ColorNode(0x111111);
mtl.emissive = rimColor;
mtl.color = new THREE.ColorNode( 0x111111 );
mtl.emissive = rimColor;
// GUI
addGui( 'color', color.value.getHex(), function( val ) {
color.value.setHex( val );
}, true );
addGui( 'intensity', intensity, function( val ) {
intensity = val;
viewZ.b.z = -intensity;
viewZ.b.z = - intensity;
rim.b.number = intensity;
}, false, 0, 3 );
addGui( 'power', power.number, function( val ) {
power.number = val;
}, false, 0, 6 );
addGui( 'xray', false, function( val ) {
if (val) {
mtl.emissive = color;
mtl.alpha = rimPower;
if ( val ) {
mtl.emissive = color;
mtl.alpha = rimPower;
mtl.blending = THREE.AdditiveBlending;
mtl.depthWrite = false;
}
else {
mtl.emissive = rimColor;
mtl.emissive = rimColor;
mtl.alpha = null;
mtl.blending = THREE.NormalBlending;
mtl.depthWrite = true;
}
mtl.build();
} );
break;
case 'fresnel':
// MATERIAL
mtl = new THREE.PhongNodeMaterial();
var reflectance = new THREE.FloatNode(1.3);
var power = new THREE.FloatNode(1);
var color = new THREE.CubeTextureNode(cubemap);
var reflectance = new THREE.FloatNode( 1.3 );
var power = new THREE.FloatNode( 1 );
var color = new THREE.CubeTextureNode( cubemap );
var viewZ = new THREE.Math2Node(
new THREE.NormalNode( THREE.NormalNode.VIEW ),
new THREE.Vector3Node(0, 0, -1),
new THREE.NormalNode( THREE.NormalNode.VIEW ),
new THREE.Vector3Node( 0, 0, - 1 ),
THREE.Math2Node.DOT
);
var theta = new THREE.OperatorNode(
viewZ,
new THREE.FloatNode(1),
new THREE.FloatNode( 1 ),
THREE.OperatorNode.ADD
);
var thetaPower = new THREE.Math2Node(
theta,
power,
theta,
power,
THREE.Math2Node.POW
);
var fresnel = new THREE.OperatorNode(
reflectance,
thetaPower,
THREE.OperatorNode.MUL
);
mtl.color = new THREE.ColorNode(0x3399FF);
mtl.color = new THREE.ColorNode( 0x3399FF );
mtl.environment = color;
mtl.reflectivity = new THREE.Math1Node( fresnel, THREE.Math1Node.SAT );
// GUI
addGui( 'reflectance', reflectance.number, function( val ) {
reflectance.number = val;
}, false, 0, 3 );
addGui( 'power', power.number, function( val ) {
power.number = val;
}, false, 0, 5 );
break;
case 'layers':
// MATERIAL
mtl = new THREE.PhongNodeMaterial();
var tex1 = new THREE.TextureNode(grass);
var tex2 = new THREE.TextureNode(brick);
var offset = new THREE.FloatNode(0);
var scale = new THREE.FloatNode(1);
var tex1 = new THREE.TextureNode( grass );
var tex2 = new THREE.TextureNode( brick );
var offset = new THREE.FloatNode( 0 );
var scale = new THREE.FloatNode( 1 );
var uv = new THREE.UVNode();
var uvOffset = new THREE.OperatorNode(
offset,
uv,
THREE.OperatorNode.ADD
);
var uvScale = new THREE.OperatorNode(
uvOffset,
scale,
THREE.OperatorNode.MUL
);
var mask = new THREE.TextureNode(decalDiffuse, uvScale);
var maskAlphaChannel = new THREE.SwitchNode(mask, 'w');
var mask = new THREE.TextureNode( decalDiffuse, uvScale );
var maskAlphaChannel = new THREE.SwitchNode( mask, 'w' );
var blend = new THREE.Math3Node(
tex1,
tex2,
maskAlphaChannel,
THREE.Math3Node.MIX
);
mtl.color = blend;
// GUI
addGui( 'offset', offset.number, function( val ) {
offset.number = val;
}, false, 0, 1 );
addGui( 'scale', scale.number, function( val ) {
scale.number = val;
}, false, 0, 10 );
break;
case 'saturation':
// MATERIAL
mtl = new THREE.StandardNodeMaterial();
var tex = new THREE.TextureNode(brick);
var sat = new THREE.FloatNode(0);
var satrgb = new THREE.FunctionNode([
var tex = new THREE.TextureNode( brick );
var sat = new THREE.FloatNode( 0 );
var satrgb = new THREE.FunctionNode( [
"vec3 satrgb(vec3 rgb, float adjustment) {",
//"const vec3 W = vec3(0.2125, 0.7154, 0.0721);", // LUMA
"vec3 intensity = vec3(dot(rgb, LUMA));",
"return mix(intensity, rgb, adjustment);",
"}"
].join( "\n" ));
var saturation = new THREE.FunctionCallNode(satrgb);
].join( "\n" ) );
var saturation = new THREE.FunctionCallNode( satrgb );
saturation.input.rgb = tex;
saturation.input.adjustment = sat;
// or try
//saturation.input[0] = tex;
//saturation.input[1] = sat;
mtl.color = saturation;
mtl.environment = new THREE.CubeTextureNode(cubemap); // optional
mtl.environment = new THREE.CubeTextureNode( cubemap ); // optional
// GUI
addGui( 'saturation', sat.number, function( val ) {
sat.number = val;
}, false, 0, 2 );
break;
case 'top-bottom':
// MATERIAL
mtl = new THREE.PhongNodeMaterial();
var top = new THREE.TextureNode(grass);
var bottom = new THREE.TextureNode(brick);
var top = new THREE.TextureNode( grass );
var bottom = new THREE.TextureNode( brick );
var normal = new THREE.NormalNode( THREE.NormalNode.WORLD );
var normalY = new THREE.SwitchNode(normal, 'y');
var hard = new THREE.FloatNode(9);
var offset = new THREE.FloatNode(-2.5);
var normalY = new THREE.SwitchNode( normal, 'y' );
var hard = new THREE.FloatNode( 9 );
var offset = new THREE.FloatNode( - 2.5 );
var hardClamp = new THREE.OperatorNode(
normalY,
hard,
THREE.OperatorNode.MUL
);
var offsetClamp = new THREE.OperatorNode(
hardClamp,
offset,
THREE.OperatorNode.ADD
);
var clamp0at1 = new THREE.Math1Node( offsetClamp, THREE.Math1Node.SAT );
var blend = new THREE.Math3Node(top,bottom,clamp0at1,THREE.Math3Node.MIX);
var blend = new THREE.Math3Node( top, bottom, clamp0at1, THREE.Math3Node.MIX );
mtl.color = blend;
// GUI
addGui( 'hard', hard.number, function( val ) {
hard.number = val;
}, false, 0, 20 );
addGui( 'offset', offset.number, function( val ) {
offset.number = val;
}, false, -10, 10 );
}, false, - 10, 10 );
break;
case 'displace':
// MATERIAL
mtl = new THREE.PhongNodeMaterial();
var time = new THREE.TimeNode();
var scale = new THREE.FloatNode(2);
var speed = new THREE.FloatNode(.2);
var colorA = new THREE.ColorNode(0xFFFFFF);
var colorB = new THREE.ColorNode(0x0054df);
var scale = new THREE.FloatNode( 2 );
var speed = new THREE.FloatNode( .2 );
var colorA = new THREE.ColorNode( 0xFFFFFF );
var colorB = new THREE.ColorNode( 0x0054df );
var uv = new THREE.UVNode();
var timeScl = new THREE.OperatorNode(
time,
speed,
THREE.OperatorNode.MUL
);
var displaceOffset = new THREE.OperatorNode(
timeScl,
uv,
THREE.OperatorNode.ADD
);
var tex = new THREE.TextureNode(cloud, displaceOffset);
var texArea = new THREE.SwitchNode(tex, 'w');
var tex = new THREE.TextureNode( cloud, displaceOffset );
var texArea = new THREE.SwitchNode( tex, 'w' );
var displace = new THREE.OperatorNode(
new THREE.NormalNode(),
texArea,
THREE.OperatorNode.MUL
);
var displaceScale = new THREE.OperatorNode(
displace,
scale,
THREE.OperatorNode.MUL
);
var blend = new THREE.OperatorNode(
new THREE.PositionNode(),
displaceScale,
THREE.OperatorNode.ADD
);
var color = new THREE.Math3Node(
colorB,
colorA,
texArea,
THREE.Math3Node.MIX
);
mtl.color = mtl.specular = new THREE.ColorNode(0);
mtl.color = mtl.specular = new THREE.ColorNode( 0 );
mtl.emissive = color;
mtl.transform = blend;
// GUI
addGui( 'speed', speed.number, function( val ) {
speed.number = val;
}, false, 0, 1 );
addGui( 'scale', scale.number, function( val ) {
scale.number = val;
}, false, 0, 10 );
addGui( 'colorA', colorA.value.getHex(), function( val ) {
colorA.value.setHex( val );
}, true );
addGui( 'colorB', colorB.value.getHex(), function( val ) {
colorB.value.setHex( val );
}, true );
break;
case 'smoke':
// MATERIAL
mtl = new THREE.PhongNodeMaterial();
var time = new THREE.TimeNode();
var uv = new THREE.UVNode();
var timeSpeedA = new THREE.OperatorNode(
time,
new THREE.Vector2Node(0.3, 0.1),
new THREE.Vector2Node( 0.3, 0.1 ),
THREE.OperatorNode.MUL
);
var timeSpeedB = new THREE.OperatorNode(
time,
new THREE.Vector2Node(0.15, 0.4),
new THREE.Vector2Node( 0.15, 0.4 ),
THREE.OperatorNode.MUL
);
var uvOffsetA = new THREE.OperatorNode(
timeSpeedA,
uv,
THREE.OperatorNode.ADD
);
var uvOffsetB = new THREE.OperatorNode(
timeSpeedB,
uv,
THREE.OperatorNode.ADD
);
var cloudA = new THREE.TextureNode(cloud, uvOffsetA);
var cloudB = new THREE.TextureNode(cloud, uvOffsetB);
var cloudA = new THREE.TextureNode( cloud, uvOffsetA );
var cloudB = new THREE.TextureNode( cloud, uvOffsetB );
var clouds = new THREE.OperatorNode(
cloudA,
cloudB,
THREE.OperatorNode.ADD
);
mtl.environment = new THREE.ColorNode(0xFFFFFF);
mtl.environment = new THREE.ColorNode( 0xFFFFFF );
mtl.alpha = clouds;
// GUI
addGui( 'color', mtl.environment.value.getHex(), function( val ) {
mtl.environment.value.setHex( val );
}, true );
break;
case 'camera-depth':
// MATERIAL
var colorA = new THREE.ColorNode(0xFFFFFF);
var colorB = new THREE.ColorNode(0x0054df);
var colorA = new THREE.ColorNode( 0xFFFFFF );
var colorB = new THREE.ColorNode( 0x0054df );
var depth = new THREE.CameraNode( THREE.CameraNode.DEPTH );
depth.near.number = 1;
depth.far.number = 200;
var colors = new THREE.Math3Node(
colorB,
colorA,
depth,
THREE.Math3Node.MIX
);
mtl = new THREE.PhongNodeMaterial();
mtl.color = colors;
// GUI
addGui( 'near', depth.near.number, function( val ) {
depth.near.number = val;
}, false, 1, 1200 );
addGui( 'far', depth.far.number, function( val ) {
depth.far.number = val;
}, false, 1, 1200 );
addGui( 'nearColor', colorA.value.getHex(), function( val ) {
colorA.value.setHex( val );
}, true );
addGui( 'farColor', colorB.value.getHex(), function( val ) {
colorB.value.setHex( val );
}, true );
break;
case 'caustic':
// MATERIAL
mtl = new THREE.StandardNodeMaterial();
var hash2 = new THREE.FunctionNode([
var hash2 = new THREE.FunctionNode( [
"vec2 hash2(vec2 p) {",
"return fract(sin(vec2(dot(p, vec2(123.4, 748.6)), dot(p, vec2(547.3, 659.3))))*5232.85324);",
"}"
].join( "\n" ));
var voronoi = new THREE.FunctionNode([
].join( "\n" ) );
var voronoi = new THREE.FunctionNode( [
// Based off of iq's described here: http://www.iquilezles.org/www/articles/voronoili
"float voronoi(vec2 p, in float time) {",
"vec2 n = floor(p);",
......@@ -995,9 +995,9 @@
"}",
"return md;",
"}"
].join( "\n" ), [hash2]); // define hash2 as dependencies
var voronoiLayers = new THREE.FunctionNode([
].join( "\n" ), [ hash2 ] ); // define hash2 as dependencies
var voronoiLayers = new THREE.FunctionNode( [
// based on https://www.shadertoy.com/view/4tXSDf
"float voronoiLayers(vec2 p, in float time) {",
"float v = 0.0;",
......@@ -1009,267 +1009,267 @@
"}",
"return v;",
"}"
].join( "\n" ), [voronoi]); // define voronoi as dependencies
].join( "\n" ), [ voronoi ] ); // define voronoi as dependencies
var time = new THREE.TimeNode();
var timeScale = new THREE.FloatNode(2);
var alpha = new THREE.FloatNode(1);
var scale = new THREE.FloatNode(.1);
var intensity = new THREE.FloatNode(1.5);
var color = new THREE.ColorNode(0xFFFFFF);
var colorA = new THREE.ColorNode(0xFFFFFF);
var colorB = new THREE.ColorNode(0x0054df);
var timeScale = new THREE.FloatNode( 2 );
var alpha = new THREE.FloatNode( 1 );
var scale = new THREE.FloatNode( .1 );
var intensity = new THREE.FloatNode( 1.5 );
var color = new THREE.ColorNode( 0xFFFFFF );
var colorA = new THREE.ColorNode( 0xFFFFFF );
var colorB = new THREE.ColorNode( 0x0054df );
var worldPos = new THREE.PositionNode( THREE.PositionNode.WORLD );
var worldPosTop = new THREE.SwitchNode(worldPos, 'xz');
var worldPosTop = new THREE.SwitchNode( worldPos, 'xz' );
var pos = new THREE.PositionNode( THREE.PositionNode.WORLD );
var posNorm = new THREE.Math1Node(pos, THREE.Math1Node.NORMALIZE);
var mask = new THREE.SwitchNode(posNorm, 'y');
var posNorm = new THREE.Math1Node( pos, THREE.Math1Node.NORMALIZE );
var mask = new THREE.SwitchNode( posNorm, 'y' );
// clamp0at1
mask = new THREE.Math1Node( mask, THREE.Math1Node.SAT );
var timeOffset = new THREE.OperatorNode(
time,
timeScale,
THREE.OperatorNode.MUL
);
);
var uvPos = new THREE.OperatorNode(
worldPosTop,
scale,
THREE.OperatorNode.MUL
);
var voronoi = new THREE.FunctionCallNode(voronoiLayers);
);
var voronoi = new THREE.FunctionCallNode( voronoiLayers );
voronoi.input.p = uvPos;
voronoi.input.time = timeOffset;
var maskCaustic = new THREE.OperatorNode(
alpha,
mask,
THREE.OperatorNode.MUL
);
);
var voronoiIntensity = new THREE.OperatorNode(
voronoi,
intensity,
THREE.OperatorNode.MUL
);
);
var voronoiColors = new THREE.Math3Node(
colorB,
colorA,
new THREE.Math1Node( voronoiIntensity, THREE.Math1Node.SAT ), // mix needs clamp
THREE.Math3Node.MIX
);
var caustic = new THREE.Math3Node(
color,
voronoiColors,
maskCaustic,
THREE.Math3Node.MIX
);
var causticLights = new THREE.OperatorNode(
voronoiIntensity,
maskCaustic,
THREE.OperatorNode.MUL
);
mtl.color = caustic;
mtl.ambient = causticLights;
// GUI
addGui( 'timeScale', timeScale.number, function( val ) {
timeScale.number = val;
}, false, 0, 5 );
addGui( 'intensity', intensity.number, function( val ) {
intensity.number = val;
}, false, 0, 3 );
addGui( 'scale', scale.number, function( val ) {
scale.number = val;
}, false, 0, 1 );
addGui( 'alpha', alpha.number, function( val ) {
alpha.number = val;
}, false, 0, 1 );
addGui( 'color', color.value.getHex(), function( val ) {
color.value.setHex( val );
}, true );
addGui( 'colorA', colorA.value.getHex(), function( val ) {
colorA.value.setHex( val );
}, true );
addGui( 'colorB', colorB.value.getHex(), function( val ) {
colorB.value.setHex( val );
}, true );
break;
case 'soft-body':
// MATERIAL
move = true;
mtl = new THREE.StandardNodeMaterial();
var scale = new THREE.FloatNode(2);
var colorA = new THREE.ColorNode(0xFF6633);
var colorB = new THREE.ColorNode(0x3366FF);
var scale = new THREE.FloatNode( 2 );
var colorA = new THREE.ColorNode( 0xFF6633 );
var colorB = new THREE.ColorNode( 0x3366FF );
var pos = new THREE.PositionNode();
var posNorm = new THREE.Math1Node(pos, THREE.Math1Node.NORMALIZE);
var mask = new THREE.SwitchNode(posNorm, 'y');
var posNorm = new THREE.Math1Node( pos, THREE.Math1Node.NORMALIZE );
var mask = new THREE.SwitchNode( posNorm, 'y' );
var velocity = new THREE.VelocityNode( mesh, {
type:'elastic',
spring:.8,
friction:.9
type: 'elastic',
spring: .8,
friction: .9
} );
var velocityArea = new THREE.OperatorNode(
mask,
scale,
THREE.OperatorNode.MUL
);
var softVelocity = new THREE.OperatorNode(
velocity,
velocityArea,
THREE.OperatorNode.MUL
);
var softPosition = new THREE.OperatorNode(
new THREE.PositionNode(),
softVelocity,
THREE.OperatorNode.ADD
);
var colors = new THREE.Math3Node(
colorB,
colorA,
mask,
THREE.Math3Node.MIX
);
mtl.color = colors;
mtl.transform = softPosition;
// GUI
addGui( 'spring', velocity.params.spring, function( val ) {
velocity.params.spring = val;
}, false, 0, .9 );
addGui( 'friction', velocity.params.friction, function( val ) {
velocity.params.friction = val;
}, false, 0, .9 );
addGui( 'scale', scale.number, function( val ) {
scale.number = val;
}, false, 0, 3 );
addGui( 'softBody', colorA.value.getHex(), function( val ) {
colorA.value.setHex( val );
}, true );
addGui( 'hardBody', colorB.value.getHex(), function( val ) {
colorB.value.setHex( val );
}, true );
break;
case 'firefly':
// MATERIAL
mtl = new THREE.PhongNodeMaterial();
var time = new THREE.TimeNode();
var speed = new THREE.FloatNode(.5);
var color = new THREE.ColorNode(0x98ff00);
var speed = new THREE.FloatNode( .5 );
var color = new THREE.ColorNode( 0x98ff00 );
var timeSpeed = new THREE.OperatorNode(
time,
speed,
THREE.OperatorNode.MUL
);
var sinCycleInSecs = new THREE.OperatorNode(
timeSpeed,
timeSpeed,
new THREE.ConstNode( THREE.ConstNode.PI2 ),
THREE.OperatorNode.MUL
);
var cycle = new THREE.Math1Node(sinCycleInSecs, THREE.Math1Node.SIN);
var cycle = new THREE.Math1Node( sinCycleInSecs, THREE.Math1Node.SIN );
var cycleColor = new THREE.OperatorNode(
cycle,
color,
THREE.OperatorNode.MUL
);
var cos = new THREE.Math1Node(cycleColor, THREE.Math1Node.SIN);
mtl.color = new THREE.ColorNode(0);
var cos = new THREE.Math1Node( cycleColor, THREE.Math1Node.SIN );
mtl.color = new THREE.ColorNode( 0 );
mtl.emissive = cos;
// GUI
addGui( 'speed', speed.number, function( val ) {
speed.number = val;
}, false, 0, 3 );
break;
}
// build shader
mtl.build();
// set material
mesh.material = mtl;
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
......@@ -1282,28 +1282,28 @@
function animate() {
var delta = clock.getDelta();
if (move) {
if ( move ) {
var time = Date.now() * 0.005;
mesh.position.z = Math.cos( time ) * 10;
mesh.position.y = Math.sin( time ) * 10;
}
else {
mesh.position.z = mesh.position.y = 0;
}
//mesh.rotation.z += .01;
// update material animation and/or gpu calcs (pre-renderer)
mesh.material.updateAnimation( delta );
renderer.render( scene, camera );
requestAnimationFrame( animate );
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册