Selaa lähdekoodia

optimize + CondNode + RTTNode + CheckerNode + ColorSpaceNode

sunag 7 vuotta sitten
vanhempi
commit
cf0a010815

+ 4 - 0
examples/js/nodes/Nodes.js

@@ -33,6 +33,7 @@ export { CubeTextureNode } from './inputs/CubeTextureNode.js';
 export { ScreenNode } from './inputs/ScreenNode.js';
 export { ReflectorNode } from './inputs/ReflectorNode.js';
 export { PropertyNode } from './inputs/PropertyNode.js';
+export { RTTNode } from './inputs/RTTNode.js';
 
 // accessors
 
@@ -52,10 +53,12 @@ export { Math1Node } from './math/Math1Node.js';
 export { Math2Node } from './math/Math2Node.js';
 export { Math3Node } from './math/Math3Node.js';
 export { OperatorNode } from './math/OperatorNode.js';
+export { CondNode } from './math/CondNode.js';
 
 // procedural
 
 export { NoiseNode } from './procedural/NoiseNode.js';
+export { CheckerNode } from './procedural/CheckerNode.js';
 
 // bsdfs
 
@@ -79,6 +82,7 @@ export { TimerNode } from './utils/TimerNode.js';
 export { VelocityNode } from './utils/VelocityNode.js';
 export { UVTransformNode } from './utils/UVTransformNode.js';
 export { MaxMIPLevelNode } from './utils/MaxMIPLevelNode.js';
+export { ColorSpaceNode } from './utils/ColorSpaceNode.js';
 
 // effects
 

+ 8 - 0
examples/js/nodes/THREE.Nodes.js

@@ -33,6 +33,7 @@ import {
 	ScreenNode,
 	ReflectorNode,
 	PropertyNode,
+	RTTNode,
 	
 	// accessors
 	
@@ -52,10 +53,12 @@ import {
 	Math2Node,
 	Math3Node,
 	OperatorNode,
+	CondNode,
 	
 	// procedural
 	
 	NoiseNode,
+	CheckerNode,
 	
 	// bsdfs
 	
@@ -79,6 +82,7 @@ import {
 	VelocityNode,
 	UVTransformNode,
 	MaxMIPLevelNode,
+	ColorSpaceNode,
 	
 	// effects
 	
@@ -137,6 +141,7 @@ THREE.CubeTextureNode = CubeTextureNode;
 THREE.ScreenNode = ScreenNode;
 THREE.ReflectorNode = ReflectorNode;
 THREE.PropertyNode = PropertyNode;
+THREE.RTTNode = RTTNode;
 
 // accessors
 
@@ -156,10 +161,12 @@ THREE.Math1Node = Math1Node;
 THREE.Math2Node = Math2Node;
 THREE.Math3Node = Math3Node;
 THREE.OperatorNode = OperatorNode;
+THREE.CondNode = CondNode;
 
 // procedural
 
 THREE.NoiseNode = NoiseNode;
+THREE.CheckerNode = CheckerNode;
 
 // bsdfs
 
@@ -183,6 +190,7 @@ THREE.TimerNode = TimerNode;
 THREE.VelocityNode = VelocityNode;
 THREE.UVTransformNode = UVTransformNode;
 THREE.MaxMIPLevelNode = MaxMIPLevelNode;
+THREE.ColorSpaceNode = ColorSpaceNode;
 
 // effects
 

+ 9 - 5
examples/js/nodes/core/Node.js

@@ -26,12 +26,12 @@ Node.prototype = {
 
 		builder.parsing = true;
 
-		this.build( builder.addCache( settings.cache, settings.requires ).addSlot( settings.slot ), 'v4' );
+		this.build( builder.addFlow( settings.slot, settings.cache, settings.context ), 'v4' );
 
 		builder.clearVertexNodeCode()
 		builder.clearFragmentNodeCode();
 
-		builder.removeCache().removeSlot();
+		builder.removeFlow();
 
 		builder.parsing = false;
 
@@ -51,11 +51,11 @@ Node.prototype = {
 
 		settings = settings || {};
 
-		var data = { result: this.build( builder.addCache( settings.cache, settings.context ).addSlot( settings.slot ), output ) };
+		var data = { result: this.build( builder.addFlow( settings.slot, settings.cache, settings.context ), output ) };
 
 		data.code = builder.clearNodeCode();
 
-		builder.removeCache().removeSlot();
+		builder.removeFlow();
 
 		return data;
 	
@@ -67,7 +67,11 @@ Node.prototype = {
 
 		var data = builder.getNodeData( uuid || this );
 
-		if ( builder.parsing ) this.appendDepsNode( builder, data, output );
+		if ( builder.parsing ) {
+			
+			this.appendDepsNode( builder, data, output );
+			
+		}
 
 		if ( builder.nodes.indexOf( this ) === - 1 ) {
 

+ 89 - 108
examples/js/nodes/core/NodeBuilder.js

@@ -39,9 +39,10 @@ var elements = NodeUtils.elements,
 	};
  
 function NodeBuilder() {
-
-	this.caches = [];
+	
 	this.slots = [];
+	this.caches = [];
+	this.contexts = [];
 
 	this.keywords = {};
 	
@@ -238,44 +239,75 @@ NodeBuilder.prototype = {
 		this.requires.lights = material.lights;
 		this.requires.fog = material.fog;
 		
+		this.mergeDefines( material.defines );
+		
 		return this;
 		
 	},
 	
-	addCache: function ( name, context ) {
-
-		this.caches.push( {
-			name: name || '',
-			context: context || {}
-		} );
+	addFlow: function ( slot, cache, context ) {
+		
+		return this.addSlot( slot ).addCache( cache ).addContext( context );
+		
+	},
+	
+	removeFlow: function () {
+		
+		return this.removeSlot().removeCache().removeContext();
+		
+	},
+	
+	addCache: function ( name ) {
 
-		return this.update();
+		this.cache = name || '';
+		this.caches.push( this.cache );
+		
+		return this;
 
 	},
 
 	removeCache: function () {
 
 		this.caches.pop();
+		this.cache = this.caches[ this.caches.length - 1 ] || '';
+
+		return this;
+
+	},
 
-		return this.update();
+	addContext: function ( context ) {
+
+		this.context = context || {};
+		this.contexts.push( this.context );
+
+		return this;
 
 	},
 
+	removeContext: function () {
+
+		this.contexts.pop();
+		this.context = this.contexts[ this.contexts.length - 1 ] || {};
+
+		return this;
+
+	},
+	
 	addSlot: function ( name ) {
 
-		this.slots.push( {
-			name: name || ''
-		} );
+		this.slot = name || '';
+		this.slots.push( this.slot );
 
-		return this.update();
+		return this;
 
 	},
 
 	removeSlot: function () {
 
 		this.slots.pop();
+		this.slot = this.slots[ this.slots.length - 1 ] || {};
 
-		return this.update();
+		return this;
 
 	},
 
@@ -555,7 +587,7 @@ NodeBuilder.prototype = {
 
 		var uniform = new NodeUniform( {
 			type: type,
-			name: ns ? ns : 'nVu' + index + '_' + THREE.Math.generateUUID().substr(0, 8),
+			name: ns ? ns : 'nVu' + index,
 			node: node,
 			needsUpdate: needsUpdate
 		} );
@@ -589,6 +621,13 @@ NodeBuilder.prototype = {
 
 		node = typeof node === 'string' ? NodeLib.get( node ) : node;
 
+		if (this.context.include === false) {
+			
+			return node.name;
+			
+		} 
+		
+		
 		if ( node instanceof FunctionNode ) {
 
 			includesStruct = this.includes.functions;
@@ -805,34 +844,34 @@ NodeBuilder.prototype = {
 
 	format: function ( code, from, to ) {
 
-		var typeToType = this.colorToVector( to + ' = ' + from );
+		var typeToType = this.colorToVector( to + ' <- ' + from );
 
 		switch ( typeToType ) {
 
-			case 'f = v2': return code + '.x';
-			case 'f = v3': return code + '.x';
-			case 'f = v4': return code + '.x';
-			case 'f = i': return 'float( ' + code + ' )';
+			case 'f <- v2': return code + '.x';
+			case 'f <- v3': return code + '.x';
+			case 'f <- v4': return code + '.x';
+			case 'f <- i': return 'float( ' + code + ' )';
 
-			case 'v2 = f': return 'vec2( ' + code + ' )';
-			case 'v2 = v3': return code + '.xy';
-			case 'v2 = v4': return code + '.xy';
-			case 'v2 = i': return 'vec2( float( ' + code + ' ) )';
+			case 'v2 <- f': return 'vec2( ' + code + ' )';
+			case 'v2 <- v3': return code + '.xy';
+			case 'v2 <- v4': return code + '.xy';
+			case 'v2 <- i': return 'vec2( float( ' + code + ' ) )';
 
-			case 'v3 = f': return 'vec3( ' + code + ' )';
-			case 'v3 = v2': return 'vec3( ' + code + ', 0.0 )';
-			case 'v3 = v4': return code + '.xyz';
-			case 'v3 = i': return 'vec2( float( ' + code + ' ) )';
+			case 'v3 <- f': return 'vec3( ' + code + ' )';
+			case 'v3 <- v2': return 'vec3( ' + code + ', 0.0 )';
+			case 'v3 <- v4': return code + '.xyz';
+			case 'v3 <- i': return 'vec2( float( ' + code + ' ) )';
 
-			case 'v4 = f': return 'vec4( ' + code + ' )';
-			case 'v4 = v2': return 'vec4( ' + code + ', 0.0, 1.0 )';
-			case 'v4 = v3': return 'vec4( ' + code + ', 1.0 )';
-			case 'v4 = i': return 'vec4( float( ' + code + ' ) )';
+			case 'v4 <- f': return 'vec4( ' + code + ' )';
+			case 'v4 <- v2': return 'vec4( ' + code + ', 0.0, 1.0 )';
+			case 'v4 <- v3': return 'vec4( ' + code + ', 1.0 )';
+			case 'v4 <- i': return 'vec4( float( ' + code + ' ) )';
 
-			case 'i = f': return 'int( ' + code + ' )';
-			case 'i = v2': return 'int( ' + code + '.x )';
-			case 'i = v3': return 'int( ' + code + '.x )';
-			case 'i = v4': return 'int( ' + code + '.x )';
+			case 'i <- f': return 'int( ' + code + ' )';
+			case 'i <- v2': return 'int( ' + code + '.x )';
+			case 'i <- v3': return 'int( ' + code + '.x )';
+			case 'i <- v4': return 'int( ' + code + '.x )';
 
 		}
 
@@ -888,92 +927,34 @@ NodeBuilder.prototype = {
 
 	},
 	
-	mergeUniform: function ( uniforms ) {
+	mergeDefines: function ( defines ) {
 
-		for ( var name in uniforms ) {
+		for ( var name in defines ) {
 
-			this.uniforms[ name ] = uniforms[ name ];
-
-		}
-
-	},
-
-	getTexelDecodingFunctionFromTexture: function( code, texture ) {
-
-		var gammaOverrideLinear = this.getTextureEncodingFromMap( texture, this.context.gamma && ( this.renderer ? this.renderer.gammaInput : false ) )
-
-		return this.getTexelDecodingFunction( code, gammaOverrideLinear );
-
-	},
-
-	getTexelDecodingFunction: function( value, encoding ) {
-
-		var components = this.getEncodingComponents( encoding );
-
-		return components[ 0 ] + 'ToLinear' + components[ 1 ].replace( 'value', value );
-
-	},
-
-	getTexelEncodingFunction: function( value, encoding ) {
-
-		var components = this.getEncodingComponents( encoding );
-
-		return 'LinearTo' + components[ 0 ] + components[ 1 ].replace( 'value', value );
-
-	},
-
-	getEncodingComponents: function( encoding ) {
-
-		switch ( encoding ) {
-
-			case THREE.LinearEncoding:
-				return [ 'Linear', '( value )' ];
-			case THREE.sRGBEncoding:
-				return [ 'sRGB', '( value )' ];
-			case THREE.RGBEEncoding:
-				return [ 'RGBE', '( value )' ];
-			case THREE.RGBM7Encoding:
-				return [ 'RGBM', '( value, 7.0 )' ];
-			case THREE.RGBM16Encoding:
-				return [ 'RGBM', '( value, 16.0 )' ];
-			case THREE.RGBDEncoding:
-				return [ 'RGBD', '( value, 256.0 )' ];
-			case THREE.GammaEncoding:
-				return [ 'Gamma', '( value, float( GAMMA_FACTOR ) )' ];
-			default:
-				throw new Error( 'unsupported encoding: ' + encoding );
+			this.defines[ name ] = defines[ name ];
 
 		}
+		
+		return this.defines;
 
 	},
+	
+	mergeUniform: function ( uniforms ) {
 
-	getEncodingComponents: function( encoding ) {
-
-		switch ( encoding ) {
+		for ( var name in uniforms ) {
 
-			case THREE.LinearEncoding:
-				return [ 'Linear', '( value )' ];
-			case THREE.sRGBEncoding:
-				return [ 'sRGB', '( value )' ];
-			case THREE.RGBEEncoding:
-				return [ 'RGBE', '( value )' ];
-			case THREE.RGBM7Encoding:
-				return [ 'RGBM', '( value, 7.0 )' ];
-			case THREE.RGBM16Encoding:
-				return [ 'RGBM', '( value, 16.0 )' ];
-			case THREE.RGBDEncoding:
-				return [ 'RGBD', '( value, 256.0 )' ];
-			case THREE.GammaEncoding:
-				return [ 'Gamma', '( value, float( GAMMA_FACTOR ) )' ];
-			default:
-				throw new Error( 'unsupported encoding: ' + encoding );
+			this.uniforms[ name ] = uniforms[ name ];
 
 		}
+		
+		return this.uniforms;
 
 	},
 	
 	getTextureEncodingFromMap: function ( map, gammaOverrideLinear ) {
 
+		gammaOverrideLinear = gammaOverrideLinear !== undefined ? gammaOverrideLinear : this.context.gamma && ( this.renderer ? this.renderer.gammaInput : false );
+	
 		var encoding;
 
 		if ( ! map ) {

+ 8 - 0
examples/js/nodes/core/NodeFrame.js

@@ -25,6 +25,14 @@ NodeFrame.prototype = {
 
 	},
 	
+	setRenderer: function( renderer ) {
+		
+		this.renderer = renderer;
+		
+		return this;
+		
+	},
+	
 	updateNode: function ( node ) {
 
 		if ( node.frameId === this.frameId ) return this;

+ 9 - 1
examples/js/nodes/inputs/CubeTextureNode.js

@@ -4,6 +4,7 @@
 
 import { InputNode } from '../core/InputNode.js';
 import { ReflectNode } from '../accessors/ReflectNode.js';
+import { ColorSpaceNode } from '../utils/ColorSpaceNode.js';
 
 function CubeTextureNode( value, uv, bias ) {
 
@@ -48,8 +49,15 @@ CubeTextureNode.prototype.generate = function ( builder, output ) {
 	if ( bias ) code = 'texCubeBias( ' + cubetex + ', ' + uv + ', ' + bias + ' )';
 	else code = 'texCube( ' + cubetex + ', ' + uv + ' )';
 
-	code = builder.getTexelDecodingFunctionFromTexture( code, this.value );
+	// add this context to replace ColorSpaceNode.input to code
+	
+	builder.addContext( { input: code, encoding: builder.getTextureEncodingFromMap( this.value ), include: builder.isShader('vertex') } )
 
+	this.colorSpace = this.colorSpace || new ColorSpaceNode( this );	
+	code = this.colorSpace.build( builder, this.type );
+	
+	builder.removeContext();
+	
 	return builder.format( code, this.type, output );
 
 };

+ 55 - 0
examples/js/nodes/inputs/RTTNode.js

@@ -0,0 +1,55 @@
+/**
+ * @author sunag / http://www.sunag.com.br/
+ */
+
+import { InputNode } from '../core/InputNode.js';
+import { NodeMaterial } from '../materials/NodeMaterial.js';
+import { TextureNode } from './TextureNode.js';
+
+function RTTNode( width, height, node, options ) {
+
+	this.node = node;
+	
+	this.clear = true;
+	
+	this.rtt = new THREE.WebGLRenderTarget( width, height, options );
+	
+	this.material = new THREE.NodeMaterial();
+	
+	this.camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
+	this.scene = new THREE.Scene();
+
+	this.quad = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), this.material );
+	this.quad.frustumCulled = false; // Avoid getting clipped
+	this.scene.add( this.quad );
+
+	TextureNode.call( this, this.rtt.texture );
+
+};
+
+RTTNode.prototype = Object.create( TextureNode.prototype );
+RTTNode.prototype.constructor = RTTNode;
+RTTNode.prototype.nodeType = "RTT";
+
+RTTNode.prototype.generate = function ( builder, output ) {
+	
+	this.material.fragment.value = this.node;
+	
+	return TextureNode.prototype.generate.call( this, builder, output );
+};
+
+RTTNode.prototype.updateFrame = function ( frame ) {
+	
+	if ( frame.renderer ) {
+		
+		frame.renderer.render( this.scene, this.camera, this.rtt, this.clear );
+		
+	} else {
+		
+		console.warn("RTTNode need a renderer in NodeFrame")
+		
+	}
+	
+};
+
+export { RTTNode };

+ 9 - 1
examples/js/nodes/inputs/TextureNode.js

@@ -5,6 +5,7 @@
 import { InputNode } from '../core/InputNode.js';
 import { NodeBuilder } from '../core/NodeBuilder.js';
 import { UVNode } from '../accessors/UVNode.js';
+import { ColorSpaceNode } from '../utils/ColorSpaceNode.js';
 
 function TextureNode( value, uv, bias, project ) {
 
@@ -53,7 +54,14 @@ TextureNode.prototype.generate = function ( builder, output ) {
 	if ( bias ) code = method + '( ' + tex + ', ' + uv + ', ' + bias + ' )';
 	else code = method + '( ' + tex + ', ' + uv + ' )';
 
-	code = builder.getTexelDecodingFunctionFromTexture( code, this.value );
+	// add this context to replace ColorSpaceNode.input to code
+	
+	builder.addContext( { input: code, encoding: builder.getTextureEncodingFromMap( this.value ), include: builder.isShader('vertex') } )
+
+	this.colorSpace = this.colorSpace || new ColorSpaceNode( this );	
+	code = this.colorSpace.build( builder, this.type );
+	
+	builder.removeContext();
 
 	return builder.format( code, this.type, output );
 

+ 0 - 4
examples/js/nodes/materials/NodeMaterial.js

@@ -11,10 +11,6 @@ function NodeMaterial( vertex, fragment ) {
 
 	THREE.ShaderMaterial.call( this );
 
-	// prevent code share conflict, remove in future
-	
-	this.defines.UUID = this.uuid;
-
 	this.vertex = vertex || new RawNode( new PositionNode( PositionNode.PROJECTION ) );
 	this.fragment = fragment || new RawNode( new ColorNode( 0xFF0000 ) );
 

+ 1 - 1
examples/js/nodes/materials/nodes/MeshStandardNode.js

@@ -73,7 +73,7 @@ MeshStandardNode.prototype.build = function ( builder ) {
 		if ( props.normalMap ) {
 			
 			this.normal = new NormalMapNode( builder.resolve( props.normalMap ) );
-			this.normal.scale = builder.findNode( props.normalScale, inputs.normalScale )
+			this.normal.scale = builder.findNode( props.normalScale, inputs.normalScale );
 
 		}
 

+ 9 - 6
examples/js/nodes/materials/nodes/PhongNode.js

@@ -35,8 +35,8 @@ PhongNode.prototype.build = function ( builder ) {
 
 		builder.mergeUniform( THREE.UniformsUtils.merge( [
 
-			THREE.UniformsLib[ "fog" ],
-			THREE.UniformsLib[ "lights" ]
+			THREE.UniformsLib.fog,
+			THREE.UniformsLib.lights
 
 		] ) );
 
@@ -50,12 +50,13 @@ PhongNode.prototype.build = function ( builder ) {
 			"#endif",
 
 			"#include <common>",
-			"#include <encodings_pars_fragment>", // encoding functions
+			//"#include <encodings_pars_fragment>", // encoding functions
 			"#include <fog_pars_vertex>",
 			"#include <morphtarget_pars_vertex>",
 			"#include <skinning_pars_vertex>",
 			"#include <shadowmap_pars_vertex>",
-			"#include <logdepthbuf_pars_vertex>"
+			"#include <logdepthbuf_pars_vertex>",
+			"#include <clipping_planes_pars_vertex>"
 		].join( "\n" ) );
 
 		var output = [
@@ -65,7 +66,7 @@ PhongNode.prototype.build = function ( builder ) {
 			"#include <skinnormal_vertex>",
 			"#include <defaultnormal_vertex>",
 
-			"#ifndef FLAT_SHADED", // Normal computed with derivatives when FLAT_SHADED
+			"#ifndef FLAT_SHADED", // normal computed with derivatives when FLAT_SHADED
 
 			"	vNormal = normalize( transformedNormal );",
 
@@ -89,11 +90,13 @@ PhongNode.prototype.build = function ( builder ) {
 			"	#include <project_vertex>",
 			"	#include <fog_vertex>",
 			"	#include <logdepthbuf_vertex>",
+			"	#include <clipping_planes_vertex>",
 
 			"	vViewPosition = - mvPosition.xyz;",
 
 			"	#include <worldpos_vertex>",
-			"	#include <shadowmap_vertex>"
+			"	#include <shadowmap_vertex>",
+			"	#include <fog_vertex>"
 		);
 
 		code = output.join( "\n" );

+ 43 - 20
examples/js/nodes/materials/nodes/SpriteNode.js

@@ -23,26 +23,31 @@ SpriteNode.prototype.build = function ( builder ) {
 	var output, code;
 
 	builder.define( 'SPRITE' );
+	builder.define( 'ALPHATEST', '0.0' );
 
 	builder.requires.lights = false;
-	builder.requires.transparent = this.alpha != undefined;
+	builder.requires.transparent = this.alpha !== undefined;
 
 	if ( builder.isShader( 'vertex' ) ) {
 
 		var position = this.position ? this.position.parseAndBuildCode( builder, 'v3', { cache: 'position' } ) : undefined;
 
 		builder.mergeUniform( THREE.UniformsUtils.merge( [
-			THREE.UniformsLib[ "fog" ]
+			THREE.UniformsLib.fog
 		] ) );
 
 		builder.addParsCode( [
-			"#include <fog_pars_vertex>"
+			"#include <common>",
+			"#include <fog_pars_vertex>",
+			"#include <logdepthbuf_pars_vertex>",
+			"#include <clipping_planes_pars_vertex>"
 		].join( "\n" ) );
 
 		output = [
+			"#include <clipping_planes_fragment>",
 			"#include <begin_vertex>"
 		];
-
+		
 		if ( position ) {
 
 			output.push(
@@ -51,7 +56,7 @@ SpriteNode.prototype.build = function ( builder ) {
 			);
 
 		}
-
+		
 		output.push(
 			"#include <project_vertex>",
 			"#include <fog_vertex>",
@@ -80,7 +85,7 @@ SpriteNode.prototype.build = function ( builder ) {
 			'modelViewMtx[0][1] = 0.0;',
 			'modelViewMtx[0][2] = 0.0;'
 		);
-
+		
 		if ( this.spherical ) {
 
 			output.push(
@@ -91,50 +96,68 @@ SpriteNode.prototype.build = function ( builder ) {
 			);
 
 		}
-
+		
 		output.push(
 			// Thrid colunm.
 			'modelViewMtx[2][0] = 0.0;',
 			'modelViewMtx[2][1] = 0.0;',
 			'modelViewMtx[2][2] = 1.0;',
 
-			// apply
-			'gl_Position = projectionMatrix * modelViewMtx * modelMtx * vec4( transformed, 1.0 );'
+			"gl_Position = projectionMatrix * modelViewMtx * modelMtx * vec4( transformed, 1.0 );",
+			
+			"#include <logdepthbuf_vertex>",
+			"#include <clipping_planes_vertex>",
+			"#include <fog_vertex>"
 		);
 
 	} else {
 
 		builder.addParsCode( [
+			"#include <common>",
 			"#include <fog_pars_fragment>",
+			"#include <logdepthbuf_pars_fragment>",
+			"#include <clipping_planes_pars_fragment>"
 		].join( "\n" ) );
 
+		builder.addCode( [
+			"#include <clipping_planes_fragment>",
+			"#include <logdepthbuf_fragment>"
+		].join( "\n" ) );
+		
 		// parse all nodes to reuse generate codes
 
-		this.color.parse( builder, { slot: 'color' } );
-
 		if ( this.alpha ) this.alpha.parse( builder );
+		
+		this.color.parse( builder, { slot: 'color' } );
 
 		// build code
 
-		var color = this.color.buildCode( builder, 'c', { slot: 'color' } );
-		var alpha = this.alpha ? this.alpha.buildCode( builder, 'f' ) : undefined;
-
-		output = [ color.code ];
+		var alpha = this.alpha ? this.alpha.buildCode( builder, 'f' ) : undefined,
+			color = this.color.buildCode( builder, 'c', { slot: 'color' } );
 
 		if ( alpha ) {
 
-			output.push(
+			output = [
 				alpha.code,
+				'if ( ' + alpha.result + ' <= ALPHATEST ) discard;',
+				color.code,
 				"gl_FragColor = vec4( " + color.result + ", " + alpha.result + " );"
-			);
+			];
 
 		} else {
 
-			output.push( "gl_FragColor = vec4( " + color.result + ", 1.0 );" );
+			output = [
+				color.code,
+				"gl_FragColor = vec4( " + color.result + ", 1.0 );"
+			];
 
 		}
 
-		output.push( "#include <fog_fragment>" );
+		output.push( 
+			"#include <tonemapping_fragment>",
+			"#include <encodings_fragment>",
+			"#include <fog_fragment>" 
+		);
 
 	}
 
@@ -154,7 +177,7 @@ SpriteNode.prototype.copy = function ( source ) {
 	
 	this.color = source.color;
 	
-	if ( source.spherical !== undefined ) this.spherical = source.position;
+	if ( source.spherical !== undefined ) this.spherical = source.spherical;
 	
 	if ( source.alpha ) this.alpha = source.alpha;
 

+ 11 - 10
examples/js/nodes/materials/nodes/StandardNode.js

@@ -38,8 +38,8 @@ StandardNode.prototype.build = function ( builder ) {
 
 		builder.mergeUniform( THREE.UniformsUtils.merge( [
 
-			THREE.UniformsLib[ "fog" ],
-			THREE.UniformsLib[ "lights" ]
+			THREE.UniformsLib.fog,
+			THREE.UniformsLib.lights
 
 		] ) );
 
@@ -53,12 +53,13 @@ StandardNode.prototype.build = function ( builder ) {
 			"#endif",
 
 			"#include <common>",
-			"#include <encodings_pars_fragment>", // encoding functions
+			//"#include <encodings_pars_fragment>", // encoding functions
 			"#include <fog_pars_vertex>",
 			"#include <morphtarget_pars_vertex>",
 			"#include <skinning_pars_vertex>",
 			"#include <shadowmap_pars_vertex>",
-			"#include <logdepthbuf_pars_vertex>"
+			"#include <logdepthbuf_pars_vertex>",
+			"#include <clipping_planes_pars_vertex>"
 
 		].join( "\n" ) );
 
@@ -68,9 +69,6 @@ StandardNode.prototype.build = function ( builder ) {
 			"#include <skinbase_vertex>",
 			"#include <skinnormal_vertex>",
 			"#include <defaultnormal_vertex>",
-			"#include <logdepthbuf_pars_vertex>",
-			"#include <logdepthbuf_pars_vertex>",
-			"#include <logdepthbuf_pars_vertex>",
 
 			"#ifndef FLAT_SHADED", // Normal computed with derivatives when FLAT_SHADED
 
@@ -96,6 +94,7 @@ StandardNode.prototype.build = function ( builder ) {
 			"#include <project_vertex>",
 			"#include <fog_vertex>",
 			"#include <logdepthbuf_vertex>",
+			"#include <clipping_planes_vertex>",
 
 			"	vViewPosition = - mvPosition.xyz;",
 
@@ -183,6 +182,7 @@ StandardNode.prototype.build = function ( builder ) {
 			"#endif",
 
 			"#include <common>",
+			"#include <dithering_pars_fragment>",
 			"#include <fog_pars_fragment>",
 			"#include <bsdfs>",
 			"#include <lights_pars_begin>",
@@ -193,10 +193,12 @@ StandardNode.prototype.build = function ( builder ) {
 		].join( "\n" ) );
 
 		var output = [
-			// prevent undeclared normal
+			"#include <clipping_planes_fragment>",
+		
+			// add before: prevent undeclared normal
 			"	#include <normal_fragment_begin>",
 
-			// prevent undeclared material
+			// add before: prevent undeclared material
 			"	PhysicalMaterial material;",
 			"	material.diffuseColor = vec3( 1.0 );",
 
@@ -374,7 +376,6 @@ StandardNode.prototype.build = function ( builder ) {
 		}
 
 		output.push(
-			"#include <premultiplied_alpha_fragment>",
 			"#include <tonemapping_fragment>",
 			"#include <encodings_fragment>",
 			"#include <fog_fragment>",

+ 107 - 0
examples/js/nodes/math/CondNode.js

@@ -0,0 +1,107 @@
+/**
+ * @author sunag / http://www.sunag.com.br/
+ */
+ 
+import { TempNode } from '../core/TempNode.js';
+
+function CondNode( a, b, ifNode, elseNode, op ) {
+
+	TempNode.call( this );
+
+	this.a = a;
+	this.b = b;
+	
+	this.ifNode = ifNode;
+	this.elseNode = elseNode;
+
+	this.op = op || CondNode.EQUAL;
+
+};
+
+CondNode.EQUAL = '==';
+CondNode.NOT_EQUAL = '!=';
+CondNode.GREATER = '>';
+CondNode.GREATER_EQUAL = '>=';
+CondNode.LESS = '<';
+CondNode.LESS_EQUAL = '<=';
+
+CondNode.prototype = Object.create( TempNode.prototype );
+CondNode.prototype.constructor = CondNode;
+CondNode.prototype.nodeType = "Cond";
+
+CondNode.prototype.getType = function ( builder ) {
+
+	if ( builder.getTypeLength( this.elseNode.getType( builder ) ) > builder.getTypeLength( this.ifNode.getType( builder ) ) ) {
+
+		return this.elseNode.getType( builder );
+
+	}
+
+	return this.ifNode.getType( builder );
+
+};
+
+CondNode.prototype.getCondType = function ( builder ) {
+
+	if ( builder.getTypeLength( this.b.getType( builder ) ) > builder.getTypeLength( this.a.getType( builder ) ) ) {
+
+		return this.b.getType( builder );
+
+	}
+
+	return this.a.getType( builder );
+
+};
+
+CondNode.prototype.generate = function ( builder, output ) {
+
+	var type = this.getType( builder ),
+		condType = this.getCondType( builder ),
+		a = this.a.build( builder, condType ),
+		b = this.b.build( builder, condType ),
+		ifNode = this.ifNode.build( builder, type ),
+		elseNode = this.elseNode.build( builder, type );
+	
+	var code = '( ' + [ a, this.op, b, '?', ifNode, ':', elseNode ].join(' ') + ' )';
+
+	return builder.format( code, this.getType( builder ), output );
+
+};
+
+CondNode.prototype.copy = function ( source ) {
+			
+	TempNode.prototype.copy.call( this, source );
+	
+	this.a = source.a;
+	this.b = source.b;
+	
+	this.ifNode = source.ifNode;
+	this.elseNode = source.elseNode;
+	
+	this.op = source.op;
+	
+};
+
+CondNode.prototype.toJSON = function ( meta ) {
+
+	var data = this.getJSONNode( meta );
+
+	if ( ! data ) {
+
+		data = this.createJSONNode( meta );
+
+		data.a = this.a.toJSON( meta ).uuid;
+		data.b = this.b.toJSON( meta ).uuid;
+		
+		data.ifNode = this.ifNode.toJSON( meta ).uuid;
+		data.elseNode = this.elseNode.toJSON( meta ).uuid;
+
+		data.op = this.op;
+
+	}
+
+	return data;
+
+};
+
+export { CondNode };

+ 76 - 0
examples/js/nodes/procedural/CheckerNode.js

@@ -0,0 +1,76 @@
+/**
+ * @author sunag / http://www.sunag.com.br/
+ */
+
+import { TempNode } from '../core/TempNode.js';
+import { FunctionNode } from '../core/FunctionNode.js';
+import { FloatNode } from '../inputs/FloatNode.js';
+import { UVNode } from '../accessors/UVNode.js';
+
+function CheckerNode( uv ) {
+
+	TempNode.call( this, 'f' );
+
+	this.uv = uv || new UVNode();
+
+};
+
+CheckerNode.prototype = Object.create( TempNode.prototype );
+CheckerNode.prototype.constructor = CheckerNode;
+CheckerNode.prototype.nodeType = "Noise";
+
+CheckerNode.Nodes = (function() {
+	
+	// https://github.com/mattdesl/glsl-checker/blob/master/index.glsl
+	
+	var checker = new FunctionNode( [
+		"float checker( vec2 uv ) {",
+		
+		"	float cx = floor( uv.x );",
+		"	float cy = floor( uv.y ); ",
+		"	float result = mod( cx + cy, 2.0 );",
+
+		"	return sign( result );",
+		
+		"}"
+	].join( "\n" ) );
+
+	return {
+		checker: checker
+	};
+	
+})();
+
+CheckerNode.prototype.generate = function ( builder, output ) {
+
+	var snoise = builder.include( CheckerNode.Nodes.checker );
+
+	return builder.format( snoise + '( ' + this.uv.build( builder, 'v2' ) + ' )', this.getType( builder ), output );
+
+};
+
+CheckerNode.prototype.copy = function ( source ) {
+			
+	TempNode.prototype.copy.call( this, source );
+	
+	this.uv = source.uv;
+	
+};
+
+CheckerNode.prototype.toJSON = function ( meta ) {
+
+	var data = this.getJSONNode( meta );
+
+	if ( ! data ) {
+
+		data = this.createJSONNode( meta );
+
+		data.uv = this.uv.toJSON( meta ).uuid;
+
+	}
+
+	return data;
+
+};
+
+export { CheckerNode };

+ 297 - 0
examples/js/nodes/utils/ColorSpaceNode.js

@@ -0,0 +1,297 @@
+/**
+ * @author sunag / http://www.sunag.com.br/
+ */
+
+import { TempNode } from '../core/TempNode.js';
+import { ConstNode } from '../core/ConstNode.js';
+import { FunctionNode } from '../core/FunctionNode.js';
+
+function ColorSpaceNode( input, method ) {
+
+	TempNode.call( this, 'v4' );
+
+	this.input = input;
+
+	this.method = method || ColorSpaceNode.LINEAR;
+
+};
+
+ColorSpaceNode.Nodes = (function() {
+	
+	// For a discussion of what this is, please read this: http://lousodrome.net/blog/light/2013/05/26/gamma-correct-and-hdr-rendering-in-a-32-bits-buffer/
+
+	var LinearToLinear = new FunctionNode( [
+		"vec4 LinearToLinear( in vec4 value ) {",
+		
+		"	return value;",
+
+		"}"
+	].join( "\n" ) );
+	
+	var GammaToLinear = new FunctionNode( [
+		"vec4 GammaToLinear( in vec4 value, in float gammaFactor ) {",
+		
+		"	return vec4( pow( value.xyz, vec3( gammaFactor ) ), value.w );",
+		
+		"}"
+	].join( "\n" ));
+	
+	var LinearToGamma = new FunctionNode( [
+		"vec4 LinearToGamma( in vec4 value, in float gammaFactor ) {",
+		
+		"	return vec4( pow( value.xyz, vec3( 1.0 / gammaFactor ) ), value.w );",
+		
+		"}"
+	].join( "\n" ));
+	
+	var sRGBToLinear = new FunctionNode( [
+		"vec4 sRGBToLinear( in vec4 value ) {",
+		
+		"	return vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.w );",
+		
+		"}"
+	].join( "\n" ));
+	
+	var LinearTosRGB = new FunctionNode( [
+		"vec4 LinearTosRGB( in vec4 value ) {",
+		
+		"	return vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.w );",
+		
+		"}"
+	].join( "\n" ));
+	
+	var RGBEToLinear = new FunctionNode( [
+		"vec4 RGBEToLinear( in vec4 value ) {",
+		
+		"	return vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );",
+		
+		"}"
+	].join( "\n" ));
+	
+	var LinearToRGBE = new FunctionNode( [
+		"vec4 LinearToRGBE( in vec4 value ) {",
+		
+		"	float maxComponent = max( max( value.r, value.g ), value.b );",
+		"	float fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );",
+		"	return vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );",
+		//  return vec4( value.brg, ( 3.0 + 128.0 ) / 256.0 );
+		
+		"}"
+	].join( "\n" ));
+	
+	// reference: http://iwasbeingirony.blogspot.ca/2010/06/difference-between-rgbm-and-rgbd.html
+	
+	var RGBMToLinear = new FunctionNode( [
+		"vec3 RGBMToLinear( in vec4 value, in float maxRange ) {",
+		
+		"	return vec4( value.xyz * value.w * maxRange, 1.0 );",
+		
+		"}"
+	].join( "\n" ) );
+	
+	var LinearToRGBM = new FunctionNode( [
+		"vec3 LinearToRGBM( in vec4 value, in float maxRange ) {",
+		
+		"	float maxRGB = max( value.x, max( value.g, value.b ) );",
+		"	float M      = clamp( maxRGB / maxRange, 0.0, 1.0 );",
+		"	M            = ceil( M * 255.0 ) / 255.0;",
+		"	return vec4( value.rgb / ( M * maxRange ), M );",
+		
+		"}"
+	].join( "\n" ) );
+	
+	// reference: http://iwasbeingirony.blogspot.ca/2010/06/difference-between-rgbm-and-rgbd.html
+	
+	var RGBDToLinear = new FunctionNode( [
+		"vec3 RGBDToLinear( in vec4 value, in float maxRange ) {",
+		
+		"	return vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );",
+		
+		"}"
+	].join( "\n" ) );
+	
+	
+	var LinearToRGBD = new FunctionNode( [
+		"vec3 LinearToRGBD( in vec4 value, in float maxRange ) {",
+		
+		"	float maxRGB = max( value.x, max( value.g, value.b ) );",
+		"	float D      = max( maxRange / maxRGB, 1.0 );",
+		"	D            = min( floor( D ) / 255.0, 1.0 );",
+		"	return vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );",
+		
+		"}"
+	].join( "\n" ) );
+	
+	// LogLuv reference: http://graphicrants.blogspot.ca/2009/04/rgbm-color-encoding.html
+
+	// M matrix, for encoding
+	
+	var cLogLuvM = new ConstNode("const mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );");
+	
+	var LinearToLogLuv = new FunctionNode( [
+		"vec4 LinearToLogLuv( in vec4 value ) {",
+		
+		"	vec3 Xp_Y_XYZp = value.rgb * cLogLuvM;",
+		"	Xp_Y_XYZp = max(Xp_Y_XYZp, vec3(1e-6, 1e-6, 1e-6));",
+		"	vec4 vResult;",
+		"	vResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;",
+		"	float Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;",
+		"	vResult.w = fract(Le);",
+		"	vResult.z = (Le - (floor(vResult.w*255.0))/255.0)/255.0;",
+		"	return vResult;",
+		
+		"}"
+	].join( "\n" ), [ cLogLuvM ] );
+	
+	// Inverse M matrix, for decoding
+	
+	var cLogLuvInverseM = new ConstNode("const mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );");
+	
+	var LogLuvToLinear = new FunctionNode( [
+		"vec4 LogLuvToLinear( in vec4 value ) {",
+		
+		"	float Le = value.z * 255.0 + value.w;",
+		"	vec3 Xp_Y_XYZp;",
+		"	Xp_Y_XYZp.y = exp2((Le - 127.0) / 2.0);",
+		"	Xp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;",
+		"	Xp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;",
+		"	vec3 vRGB = Xp_Y_XYZp.rgb * cLogLuvInverseM;",
+		"	return vec4( max(vRGB, 0.0), 1.0 );",
+		
+		"}"
+	].join( "\n" ), [ cLogLuvInverseM ] );
+	
+	return {
+		LinearToLinear: LinearToLinear,
+		GammaToLinear: GammaToLinear,
+		LinearToGamma: LinearToGamma,
+		sRGBToLinear: sRGBToLinear,
+		LinearTosRGB: LinearTosRGB,
+		RGBEToLinear: RGBEToLinear,
+		LinearToRGBE: LinearToRGBE,
+		RGBMToLinear: RGBMToLinear,
+		LinearToRGBM: LinearToRGBM,
+		RGBDToLinear: RGBDToLinear,
+		LinearToRGBD: LinearToRGBD,
+		cLogLuvM: cLogLuvM,
+		LinearToLogLuv: LinearToLogLuv,
+		cLogLuvInverseM: cLogLuvInverseM,
+		LogLuvToLinear: LogLuvToLinear
+	};
+	
+})();
+
+ColorSpaceNode.LINEAR_TO_LINEAR = 'LinearToLinear';
+
+ColorSpaceNode.GAMMA_TO_LINEAR = 'GammaToLinear';
+ColorSpaceNode.LINEAR_TO_GAMMA = 'LinearToGamma';
+
+ColorSpaceNode.SRGB_TO_LINEAR = 'sRGBToLinear';
+ColorSpaceNode.LINEAR_TO_SRGB = 'LinearTosRGB';
+
+ColorSpaceNode.RGBE_TO_LINEAR = 'RGBEToLinear';
+ColorSpaceNode.LINEAR_TO_RGBE = 'LinearToRGBE';
+
+ColorSpaceNode.RGBM_TO_LINEAR = 'RGBMToLinear';
+ColorSpaceNode.LINEAR_TO_RGBM = 'LinearToRGBM';
+
+ColorSpaceNode.RGBD_TO_LINEAR = 'RGBDToLinear';
+ColorSpaceNode.LINEAR_TO_RGBD = 'LinearToRGBD';
+
+ColorSpaceNode.LINEAR_TO_LOG_LUV = 'LinearToLogLuv';
+ColorSpaceNode.LOG_LUV_TO_LINEAR = 'LogLuvToLinear';
+
+ColorSpaceNode.prototype = Object.create( TempNode.prototype );
+ColorSpaceNode.prototype.constructor = ColorSpaceNode;
+ColorSpaceNode.prototype.nodeType = "ColorAdjustment";
+
+ColorSpaceNode.prototype.generate = function ( builder, output ) {
+
+	var input = builder.context.input || this.input.build( builder, 'v4' ),
+		encodingMethod = builder.context.encoding !== undefined ? this.getEncodingMethod( builder.context.encoding ) : [ this.method ],
+		factor = this.factor ? this.factor.build( builder, 'f' ) : encodingMethod[1];
+	
+	var method = builder.include( ColorSpaceNode.Nodes[encodingMethod[0]] );
+	
+	if (factor) {
+		
+		return builder.format( method + '( ' + input + ', ' + factor + ' )', this.getType( builder ), output );
+		
+	} else {
+		
+		return builder.format( method + '( ' + input + ' )', this.getType( builder ), output );
+		
+	}
+
+};
+
+ColorSpaceNode.prototype.getDecodingMethod = function( encoding ) {
+
+	var components = this.getEncodingComponents( encoding );
+
+	components[ 0 ] += 'ToLinear';
+	
+	return components;
+
+};
+
+ColorSpaceNode.prototype.getEncodingMethod = function( encoding ) {
+
+	var components = this.getEncodingComponents( encoding );
+
+	components[ 0 ] = 'LinearTo' + components[ 0 ];
+	
+	return components;
+
+};
+
+ColorSpaceNode.prototype.getEncodingComponents = function( encoding ) {
+
+	switch ( encoding ) {
+
+		case THREE.LinearEncoding:
+			return [ 'Linear' ];
+		case THREE.sRGBEncoding:
+			return [ 'sRGB' ];
+		case THREE.RGBEEncoding:
+			return [ 'RGBE' ];
+		case THREE.RGBM7Encoding:
+			return [ 'RGBM', '7.0' ];
+		case THREE.RGBM16Encoding:
+			return [ 'RGBM', '16.0' ];
+		case THREE.RGBDEncoding:
+			return [ 'RGBD', '256.0' ];
+		case THREE.GammaEncoding:
+			return [ 'Gamma', 'float( GAMMA_FACTOR )' ];
+
+	}
+
+};
+
+ColorSpaceNode.prototype.copy = function ( source ) {
+			
+	TempNode.prototype.copy.call( this, source );
+	
+	this.input = source.input;
+	this.method = source.method;
+
+};
+
+ColorSpaceNode.prototype.toJSON = function ( meta ) {
+
+	var data = this.getJSONNode( meta );
+
+	if ( ! data ) {
+
+		data = this.createJSONNode( meta );
+
+		data.input = this.input.toJSON( meta ).uuid;
+		data.method = this.method;
+
+	}
+
+	return data;
+
+};
+
+export { ColorSpaceNode };

+ 4 - 4
examples/js/nodes/utils/TimerNode.js

@@ -5,14 +5,14 @@
 import { FloatNode } from '../inputs/FloatNode.js';
 import { NodeLib } from '../core/NodeLib.js';
  
-function TimerNode( scale, scope, useTimeScale ) {
+function TimerNode( scale, scope, timeScale ) {
 
 	FloatNode.call( this );
 
 	this.scale = scale !== undefined ? scale : 1;
 	this.scope = scope || TimerNode.GLOBAL;
 
-	this.useTimeScale = useTimeScale !== undefined ? useTimeScale : this.scale !== 1;
+	this.timeScale = timeScale !== undefined ? timeScale : this.scale !== 1;
 
 };
 
@@ -73,7 +73,7 @@ TimerNode.prototype.copy = function ( source ) {
 	this.scope = source.scope;
 	this.scale = source.scale;
 	
-	this.useTimeScale = source.useTimeScale;
+	this.timeScale = source.timeScale;
 	
 };
 
@@ -88,7 +88,7 @@ TimerNode.prototype.toJSON = function ( meta ) {
 		data.scope = this.scope;
 		data.scale = this.scale;
 		
-		data.useTimeScale = this.useTimeScale;
+		data.timeScale = this.timeScale;
 
 	}
 

+ 105 - 1
examples/webgl_materials_nodes.html

@@ -185,6 +185,8 @@
 				'adv / soft-body': 'soft-body',
 				'adv / wave': 'wave',
 				'adv / triangle-blur': 'triangle-blur',
+				'adv / render-to-texture': 'rtt',
+				'adv / conditional': 'conditional',
 				'adv / expression': 'expression',
 				'adv / sss': 'sss',
 				'adv / translucent': 'translucent',
@@ -221,7 +223,7 @@
 
 			} else if ( typeof value == 'object' ) {
 
-				param.blend = value[ Object.keys( value )[ 0 ] ];
+				param[ name ] = value[ Object.keys( value )[ 0 ] ];
 
 				node = gui.add( param, name, value ).onChange( function () {
 
@@ -2070,6 +2072,107 @@
 
 					break;	
 				
+				case 'conditional':
+
+					// MATERIAL
+
+					mtl = new THREE.PhongNodeMaterial();
+
+					var a = new THREE.FloatNode( 0 ),
+						b = new THREE.FloatNode( 0 ),
+						ifNode = new THREE.ColorNode( 0x0000FF ),
+						elseNode = new THREE.ColorNode( 0xFF0000 );
+					
+					var cond = new THREE.CondNode( a, b, ifNode, elseNode, THREE.CondNode.EQUAL );
+					
+					mtl.color = cond;
+
+					// GUI
+					
+					addGui( 'a', a.value, function ( val ) {
+
+						a.value = val;
+
+					}, false, 0, 1 );
+					
+					addGui( 'b', b.value, function ( val ) {
+
+						b.value = val;
+
+					}, false, 0, 1 );
+					
+					addGui( 'a condition b', {
+						EQUAL: THREE.CondNode.EQUAL,
+						NOT_EQUAL: THREE.CondNode.NOT_EQUAL,
+						GREATER: THREE.CondNode.GREATER,
+						GREATER_EQUAL: THREE.CondNode.GREATER_EQUAL,
+						LESS: THREE.CondNode.LESS,
+						LESS_EQUAL: THREE.CondNode.LESS_EQUAL
+					}, function ( val ) {
+
+						cond.op = val;
+						
+						mtl.needsUpdate = true;
+
+					} );
+					
+					addGui( 'if color', ifNode.value.getHex(), function ( val ) {
+
+						ifNode.value.setHex( val );
+
+					}, true );
+
+					addGui( 'else color', elseNode.value.getHex(), function ( val ) {
+
+						elseNode.value.setHex( val );
+
+					}, true );
+					
+					break;
+				
+				case 'rtt':
+
+					// MATERIAL
+
+					mtl = new THREE.PhongNodeMaterial();
+
+					var uvTransform = new THREE.UVTransformNode(),
+						checker = new THREE.CheckerNode( uvTransform );
+					
+					uvTransform.setUvTransform( 0, 0, 2, 2, 0 );
+					
+					var rtt = new THREE.RTTNode( 512, 512, checker ),
+						bumpMap = new THREE.BumpMapNode( rtt );
+					
+					bumpMap.scale.value = .1;
+					
+					mtl.color = checker;
+					mtl.normal = bumpMap;
+					
+					// GUI
+					
+					addGui( 'bump', bumpMap.scale.value, function ( val ) {
+
+						bumpMap.scale.value = val;
+
+					}, false, - .5, .5 );
+					
+					addGui( 'scale', 2, function ( val ) {
+
+						uvTransform.setUvTransform( 0, 0, val, val, 0 );
+
+					}, false, 0, 8 );
+					
+					addGui( 'ignoreColor', false, function ( val ) {
+
+						mtl.color = val ? new THREE.ColorNode( 0xFFFFFF ) : checker;
+
+						mtl.needsUpdate = true;
+
+					} );
+					
+					break;
+				
 				case 'readonly':
 
 					// MATERIAL
@@ -2447,6 +2550,7 @@
 			// update material animation and/or gpu calcs (pre-renderer)
 			
 			frame.update( delta );
+			frame.setRenderer( renderer );
 			
 			if ( mesh.material instanceof THREE.NodeMaterial ) {
 			

+ 1 - 1
examples/webgl_postprocessing_nodes.html

@@ -108,7 +108,7 @@
 
 				} else if ( typeof value == 'object' ) {
 
-					param.blend = value[ Object.keys( value )[ 0 ] ];
+					param[ name ] = value[ Object.keys( value )[ 0 ] ];
 
 					node = gui.add( param, name, value ).onChange( function () {
 

+ 5 - 8
examples/webgl_sprites_nodes.html

@@ -81,9 +81,6 @@
 			// SpriteNode
 			//
 
-			// use scale to adjuste the real sprite size
-			plane = new THREE.PlaneBufferGeometry( 1, 1 );
-
 			// https://openclipart.org/detail/239883/walking-man-sprite-sheet
 			walkingManTextureURL = "textures/WalkingManSpriteSheet.png";
 
@@ -137,20 +134,20 @@
 			var spriteWidth = 20,
 				spriteHeight = 20;
 
-			scene.add( sprite1 = new THREE.Mesh( plane, new THREE.SpriteNodeMaterial() ) );
+			scene.add( sprite1 = new THREE.Sprite( new THREE.SpriteNodeMaterial() ) );
 			sprite1.scale.x = spriteWidth;
 			sprite1.scale.y = spriteHeight;
 			sprite1.material.color = new THREE.TextureNode( walkingManTexture );
 			sprite1.material.color.uv = createHorizontalSpriteSheetNode( 8, 10 );
 
-			scene.add( sprite2 = new THREE.Mesh( plane, new THREE.SpriteNodeMaterial() ) );
+			scene.add( sprite2 = new THREE.Sprite( new THREE.SpriteNodeMaterial() ) );
 			sprite2.position.x = 30;
 			sprite2.scale.x = spriteWidth;
 			sprite2.scale.y = spriteHeight;
 			sprite2.material.color = new THREE.TextureNode( walkingManTexture );
 			sprite2.material.color.uv = createHorizontalSpriteSheetNode( 8, 30 );
 			sprite2.material.color = new THREE.Math1Node( sprite2.material.color, THREE.Math1Node.INVERT );
-			sprite2.material.spherical = false; // look at camera horizontally only, very used to vegetation
+			sprite2.material.spherical = false; // look at camera horizontally only, very used in vegetation
 			// horizontal zigzag sprite
 			sprite2.material.position = new THREE.OperatorNode(
 				new THREE.OperatorNode(
@@ -172,13 +169,13 @@
 				"}"
 			].join( "\n" ) );
 
-			scene.add( sprite3 = new THREE.Mesh( plane, new THREE.SpriteNodeMaterial() ) );
+			scene.add( sprite3 = new THREE.Sprite( new THREE.SpriteNodeMaterial() ) );
 			sprite3.position.x = - 30;
 			sprite3.scale.x = spriteWidth;
 			sprite3.scale.y = spriteHeight;
 			sprite3.material.color = new THREE.TextureNode( walkingManTexture );
 			sprite3.material.color.uv = new THREE.FunctionCallNode( sineWaveFunction, {
-				"uv": createHorizontalSpriteSheetNode( 8, 0 ),
+				"uv": createHorizontalSpriteSheetNode( 8, 10 ),
 				"phase": new THREE.TimerNode()
 			} );
 			sprite3.material.fog = true;