未验证 提交 9b26302c 编写于 作者: M Mr.doob 提交者: GitHub

Merge pull request #14427 from sunag/dev-nodematerial-r7

NodeMaterial - r7 (2)
......@@ -209,6 +209,7 @@ var files = {
"webgl_panorama_equirectangular",
"webgl_performance",
"webgl_performance_doublesided",
"webgl_performance_nodes",
"webgl_performance_static",
"webgl_physics_cloth",
"webgl_physics_convex_break",
......@@ -232,6 +233,7 @@ var files = {
"webgl_postprocessing_ssaa",
"webgl_postprocessing_ssaa_unbiased",
"webgl_postprocessing_nodes",
"webgl_postprocessing_nodes_pass",
"webgl_postprocessing_outline",
"webgl_postprocessing_pixel",
"webgl_postprocessing_procedural",
......
......@@ -2,7 +2,7 @@
// core
export { GLNode } from './core/GLNode.js';
export { Node } from './core/Node.js';
export { TempNode } from './core/TempNode.js';
export { InputNode } from './core/InputNode.js';
export { ConstNode } from './core/ConstNode.js';
......@@ -10,6 +10,7 @@ export { VarNode } from './core/VarNode.js';
export { StructNode } from './core/StructNode.js';
export { AttributeNode } from './core/AttributeNode.js';
export { FunctionNode } from './core/FunctionNode.js';
export { ExpressionNode } from './core/ExpressionNode.js';
export { FunctionCallNode } from './core/FunctionCallNode.js';
export { NodeLib } from './core/NodeLib.js';
export { NodeUtils } from './core/NodeUtils.js';
......@@ -32,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
......@@ -51,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
......@@ -78,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
......@@ -103,4 +108,5 @@ export { MeshStandardNodeMaterial } from './materials/MeshStandardNodeMaterial.j
// postprocessing
export { NodePostProcessing } from './postprocessing/NodePostProcessing.js';
//export { NodePass } from './postprocessing/NodePass.js';
......@@ -2,7 +2,7 @@ import {
// core
GLNode,
Node,
TempNode,
InputNode,
ConstNode,
......@@ -10,6 +10,7 @@ import {
StructNode,
AttributeNode,
FunctionNode,
ExpressionNode,
FunctionCallNode,
NodeLib,
NodeUtils,
......@@ -32,6 +33,7 @@ import {
ScreenNode,
ReflectorNode,
PropertyNode,
RTTNode,
// accessors
......@@ -51,10 +53,12 @@ import {
Math2Node,
Math3Node,
OperatorNode,
CondNode,
// procedural
NoiseNode,
CheckerNode,
// bsdfs
......@@ -78,6 +82,7 @@ import {
VelocityNode,
UVTransformNode,
MaxMIPLevelNode,
ColorSpaceNode,
// effects
......@@ -99,13 +104,17 @@ import {
SpriteNodeMaterial,
PhongNodeMaterial,
StandardNodeMaterial,
MeshStandardNodeMaterial
MeshStandardNodeMaterial,
// post-processing
NodePostProcessing
} from './Nodes.js';
// core
THREE.GLNode = GLNode;
THREE.Node = Node;
THREE.TempNode = TempNode;
THREE.InputNode = InputNode;
THREE.ConstNode = ConstNode;
......@@ -113,6 +122,7 @@ THREE.VarNode = VarNode;
THREE.StructNode = StructNode;
THREE.AttributeNode = AttributeNode;
THREE.FunctionNode = FunctionNode;
THREE.ExpressionNode = ExpressionNode;
THREE.FunctionCallNode = FunctionCallNode;
THREE.NodeLib = NodeLib;
THREE.NodeUtils = NodeUtils;
......@@ -135,6 +145,7 @@ THREE.CubeTextureNode = CubeTextureNode;
THREE.ScreenNode = ScreenNode;
THREE.ReflectorNode = ReflectorNode;
THREE.PropertyNode = PropertyNode;
THREE.RTTNode = RTTNode;
// accessors
......@@ -154,10 +165,12 @@ THREE.Math1Node = Math1Node;
THREE.Math2Node = Math2Node;
THREE.Math3Node = Math3Node;
THREE.OperatorNode = OperatorNode;
THREE.CondNode = CondNode;
// procedural
THREE.NoiseNode = NoiseNode;
THREE.CheckerNode = CheckerNode;
// bsdfs
......@@ -181,6 +194,7 @@ THREE.TimerNode = TimerNode;
THREE.VelocityNode = VelocityNode;
THREE.UVTransformNode = UVTransformNode;
THREE.MaxMIPLevelNode = MaxMIPLevelNode;
THREE.ColorSpaceNode = ColorSpaceNode;
// effects
......@@ -203,3 +217,7 @@ THREE.SpriteNodeMaterial = SpriteNodeMaterial;
THREE.PhongNodeMaterial = PhongNodeMaterial;
THREE.StandardNodeMaterial = StandardNodeMaterial;
THREE.MeshStandardNodeMaterial = MeshStandardNodeMaterial;
// post-processing
THREE.NodePostProcessing = NodePostProcessing;
......@@ -14,9 +14,9 @@ function CameraNode( scope, camera ) {
this.setScope( scope || CameraNode.POSITION );
this.setCamera( camera );
};
}
CameraNode.Nodes = (function() {
CameraNode.Nodes = ( function () {
var depthColor = new FunctionNode( [
"float depthColor( float mNear, float mFar ) {",
......@@ -40,7 +40,7 @@ CameraNode.Nodes = (function() {
depthColor: depthColor
};
})();
} )();
CameraNode.POSITION = 'position';
CameraNode.DEPTH = 'depth';
......
......@@ -3,7 +3,6 @@
*/
import { TempNode } from '../core/TempNode.js';
import { NodeLib } from '../core/NodeLib.js';
var vertexDict = [ 'color', 'color2' ],
fragmentDict = [ 'vColor', 'vColor2' ];
......@@ -14,7 +13,7 @@ function ColorsNode( index ) {
this.index = index || 0;
};
}
ColorsNode.prototype = Object.create( TempNode.prototype );
ColorsNode.prototype.constructor = ColorsNode;
......
......@@ -10,7 +10,7 @@ function LightNode( scope ) {
this.scope = scope || LightNode.TOTAL;
};
}
LightNode.TOTAL = 'total';
......@@ -22,13 +22,13 @@ LightNode.prototype.generate = function ( builder, output ) {
if ( builder.isCache( 'light' ) ) {
return builder.format( 'reflectedLight.directDiffuse', this.getType( builder ), output );
return builder.format( 'reflectedLight.directDiffuse', this.type, output );
} else {
console.warn( "THREE.LightNode is only compatible in \"light\" channel." );
return builder.format( 'vec3( 0.0 )', this.getType( builder ), output );
return builder.format( 'vec3( 0.0 )', this.type, output );
}
......
......@@ -11,7 +11,7 @@ function NormalNode( scope ) {
this.scope = scope || NormalNode.LOCAL;
};
}
NormalNode.LOCAL = 'local';
NormalNode.WORLD = 'world';
......@@ -45,7 +45,7 @@ NormalNode.prototype.generate = function ( builder, output ) {
builder.requires.normal = true;
result = builder.isShader( 'vertex' ) ? 'normal' : 'vObjectNormal';
result = 'normal';
break;
......
......@@ -11,7 +11,7 @@ function PositionNode( scope ) {
this.scope = scope || PositionNode.LOCAL;
};
}
PositionNode.LOCAL = 'local';
PositionNode.WORLD = 'world';
......@@ -22,7 +22,7 @@ PositionNode.prototype = Object.create( TempNode.prototype );
PositionNode.prototype.constructor = PositionNode;
PositionNode.prototype.nodeType = "Position";
PositionNode.prototype.getType = function ( builder ) {
PositionNode.prototype.getType = function ( ) {
switch ( this.scope ) {
......
......@@ -10,7 +10,7 @@ function ReflectNode( scope ) {
this.scope = scope || ReflectNode.CUBE;
};
}
ReflectNode.CUBE = 'cube';
ReflectNode.SPHERE = 'sphere';
......@@ -72,7 +72,7 @@ ReflectNode.prototype.generate = function ( builder, output ) {
}
return builder.format( result, this.getType( this.type ), output );
return builder.format( result, this.getType( builder ), output );
} else {
......
......@@ -4,13 +4,11 @@
import { Vector2Node } from '../inputs/Vector2Node.js';
function ResolutionNode( renderer ) {
function ResolutionNode() {
Vector2Node.call( this );
this.renderer = renderer;
};
}
ResolutionNode.prototype = Object.create( Vector2Node.prototype );
ResolutionNode.prototype.constructor = ResolutionNode;
......@@ -18,12 +16,20 @@ ResolutionNode.prototype.nodeType = "Resolution";
ResolutionNode.prototype.updateFrame = function ( frame ) {
var size = this.renderer.getSize(),
pixelRatio = this.renderer.getPixelRatio();
if ( frame.renderer ) {
var size = frame.renderer.getSize(),
pixelRatio = frame.renderer.getPixelRatio();
this.x = size.width * pixelRatio;
this.y = size.height * pixelRatio;
} else {
console.warn( "ResolutionNode need a renderer in NodeFrame" );
}
};
ResolutionNode.prototype.copy = function ( source ) {
......
......@@ -3,14 +3,15 @@
*/
import { TempNode } from '../core/TempNode.js';
import { ResolutionNode } from './ResolutionNode.js';
function ScreenUVNode( resolution ) {
TempNode.call( this, 'v2' );
this.resolution = resolution;
this.resolution = resolution || new ResolutionNode();
};
}
ScreenUVNode.prototype = Object.create( TempNode.prototype );
ScreenUVNode.prototype.constructor = ScreenUVNode;
......
......@@ -14,7 +14,7 @@ function UVNode( index ) {
this.index = index || 0;
};
}
UVNode.prototype = Object.create( TempNode.prototype );
UVNode.prototype.constructor = UVNode;
......
......@@ -11,7 +11,7 @@ function BlinnExponentToRoughnessNode( blinnExponent ) {
this.blinnExponent = blinnExponent || new BlinnShininessExponentNode();
};
}
BlinnExponentToRoughnessNode.prototype = Object.create( TempNode.prototype );
BlinnExponentToRoughnessNode.prototype.constructor = BlinnExponentToRoughnessNode;
......
......@@ -8,7 +8,7 @@ function BlinnShininessExponentNode() {
TempNode.call( this, 'f' );
};
}
BlinnShininessExponentNode.prototype = Object.create( TempNode.prototype );
BlinnShininessExponentNode.prototype.constructor = BlinnShininessExponentNode;
......
......@@ -16,9 +16,9 @@ function RoughnessToBlinnExponentNode( texture ) {
this.maxMIPLevel = new MaxMIPLevelNode( texture );
this.blinnShininessExponent = new BlinnShininessExponentNode();
};
}
RoughnessToBlinnExponentNode.Nodes = (function() {
RoughnessToBlinnExponentNode.Nodes = ( function () {
var getSpecularMIPLevel = new FunctionNode( [
// taken from here: http://casual-effects.blogspot.ca/2011/08/plausible-environment-lighting-in-two.html
......@@ -27,10 +27,11 @@ RoughnessToBlinnExponentNode.Nodes = (function() {
// float envMapWidth = pow( 2.0, maxMIPLevelScalar );
// float desiredMIPLevel = log2( envMapWidth * sqrt( 3.0 ) ) - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );
" float desiredMIPLevel = maxMIPLevelScalar - 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );",
" float desiredMIPLevel = maxMIPLevelScalar + 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );",
// clamp to allowable LOD ranges.
" return clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );",
"}"
].join( "\n" ) );
......@@ -38,7 +39,7 @@ RoughnessToBlinnExponentNode.Nodes = (function() {
getSpecularMIPLevel: getSpecularMIPLevel
};
})();
} )();
RoughnessToBlinnExponentNode.prototype = Object.create( TempNode.prototype );
RoughnessToBlinnExponentNode.prototype.constructor = RoughnessToBlinnExponentNode;
......
......@@ -2,17 +2,17 @@
* @author sunag / http://www.sunag.com.br/
*/
import { GLNode } from './GLNode.js';
import { Node } from './Node.js';
function AttributeNode( name, type ) {
GLNode.call( this, type );
Node.call( this, type );
this.name = name;
};
}
AttributeNode.prototype = Object.create( GLNode.prototype );
AttributeNode.prototype = Object.create( Node.prototype );
AttributeNode.prototype.constructor = AttributeNode;
AttributeNode.prototype.nodeType = "Attribute";
......@@ -45,7 +45,7 @@ AttributeNode.prototype.generate = function ( builder, output ) {
AttributeNode.prototype.copy = function ( source ) {
GLNode.prototype.copy.call( this, source );
Node.prototype.copy.call( this, source );
this.type = source.type;
......
......@@ -4,13 +4,15 @@
import { TempNode } from './TempNode.js';
var declarationRegexp = /^([a-z_0-9]+)\s([a-z_0-9]+)\s?\=?\s?(.*?)(\;|$)/i;
function ConstNode( src, useDefine ) {
TempNode.call( this );
this.eval( src || ConstNode.PI, useDefine );
};
}
ConstNode.PI = 'PI';
ConstNode.PI2 = 'PI2';
......@@ -19,8 +21,6 @@ ConstNode.RECIPROCAL_PI2 = 'RECIPROCAL_PI2';
ConstNode.LOG2 = 'LOG2';
ConstNode.EPSILON = 'EPSILON';
ConstNode.rDeclaration = /^([a-z_0-9]+)\s([a-z_0-9]+)\s?\=?\s?(.*?)(\;|$)/i;
ConstNode.prototype = Object.create( TempNode.prototype );
ConstNode.prototype.constructor = ConstNode;
ConstNode.prototype.nodeType = "Const";
......@@ -37,9 +37,9 @@ ConstNode.prototype.eval = function ( src, useDefine ) {
var name, type, value = "";
var match = this.src.match( ConstNode.rDeclaration );
var match = this.src.match( declarationRegexp );
this.useDefine = useDefine || this.src.charAt(0) === '#';
this.useDefine = useDefine || this.src.charAt( 0 ) === '#';
if ( match && match.length > 1 ) {
......@@ -74,7 +74,7 @@ ConstNode.prototype.build = function ( builder, output ) {
return 'const ' + this.type + ' ' + this.name + ' = ' + this.value + ';';
} else if (this.useDefine) {
} else if ( this.useDefine ) {
return this.src;
......
/**
* @author sunag / http://www.sunag.com.br/
*/
import { FunctionNode } from './FunctionNode.js';
function ExpressionNode( src, type, keywords, extensions, includes ) {
FunctionNode.call( this, src, includes, extensions, keywords, type );
}
ExpressionNode.prototype = Object.create( FunctionNode.prototype );
ExpressionNode.prototype.constructor = ExpressionNode;
ExpressionNode.prototype.nodeType = "Expression";
export { ExpressionNode };
......@@ -10,7 +10,7 @@ function FunctionCallNode( func, inputs ) {
this.setFunction( func, inputs );
};
}
FunctionCallNode.prototype = Object.create( TempNode.prototype );
FunctionCallNode.prototype.constructor = FunctionCallNode;
......
......@@ -6,32 +6,25 @@
import { TempNode } from './TempNode.js';
import { NodeLib } from './NodeLib.js';
function FunctionNode( src, includesOrType, extensionsOrKeywords, keywordsOrExtensions, includes ) {
var declarationRegexp = /^([a-z_0-9]+)\s([a-z_0-9]+)\s*\((.*?)\)/i,
propertiesRegexp = /[a-z_0-9]+/ig;
this.isMethod = typeof includesOrType !== "string";
this.useKeywords = true;
function FunctionNode( src, includes, extensions, keywords, type ) {
TempNode.call( this, this.isMethod ? null : includesOrType );
this.isMethod = type === undefined;
if ( this.isMethod ) {
this.eval( src, includesOrType, extensionsOrKeywords, keywordsOrExtensions );
} else {
TempNode.call( this, type );
this.eval( src, includes, keywordsOrExtensions, extensionsOrKeywords );
}
};
this.eval( src, includes, extensions, keywords );
FunctionNode.rDeclaration = /^([a-z_0-9]+)\s([a-z_0-9]+)\s*\((.*?)\)/i;
FunctionNode.rProperties = /[a-z_0-9]+/ig;
}
FunctionNode.prototype = Object.create( TempNode.prototype );
FunctionNode.prototype.constructor = FunctionNode;
FunctionNode.prototype.nodeType = "Function";
FunctionNode.prototype.useKeywords = true;
FunctionNode.prototype.isShared = function ( builder, output ) {
return ! this.isMethod;
......@@ -50,11 +43,14 @@ FunctionNode.prototype.getInputByName = function ( name ) {
while ( i -- ) {
if ( this.inputs[ i ].name === name )
if ( this.inputs[ i ].name === name ) {
return this.inputs[ i ];
}
}
};
FunctionNode.prototype.getIncludeByName = function ( name ) {
......@@ -63,11 +59,14 @@ FunctionNode.prototype.getIncludeByName = function ( name ) {
while ( i -- ) {
if ( this.includes[ i ].name === name )
if ( this.includes[ i ].name === name ) {
return this.includes[ i ];
}
}
};
FunctionNode.prototype.generate = function ( builder, output ) {
......@@ -86,7 +85,7 @@ FunctionNode.prototype.generate = function ( builder, output ) {
}
while ( match = FunctionNode.rProperties.exec( this.src ) ) {
while ( match = propertiesRegexp.exec( this.src ) ) {
var prop = match[ 0 ],
isGlobal = this.isMethod ? ! this.getInputByName( prop ) : true,
......@@ -156,7 +155,7 @@ FunctionNode.prototype.eval = function ( src, includes, extensions, keywords ) {
if ( this.isMethod ) {
var match = this.src.match( FunctionNode.rDeclaration );
var match = this.src.match( declarationRegexp );
this.inputs = [];
......@@ -165,7 +164,7 @@ FunctionNode.prototype.eval = function ( src, includes, extensions, keywords ) {
this.type = match[ 1 ];
this.name = match[ 2 ];
var inputs = match[ 3 ].match( FunctionNode.rProperties );
var inputs = match[ 3 ].match( propertiesRegexp );
if ( inputs ) {
......
......@@ -13,7 +13,7 @@ function InputNode( type, params ) {
this.readonly = false;
};
}
InputNode.prototype = Object.create( TempNode.prototype );
InputNode.prototype.constructor = InputNode;
......
......@@ -2,7 +2,7 @@
* @author sunag / http://www.sunag.com.br/
*/
function GLNode( type ) {
function Node( type ) {
this.uuid = THREE.Math.generateUUID();
......@@ -12,11 +12,11 @@ function GLNode( type ) {
this.userData = {};
};
}
GLNode.prototype = {
Node.prototype = {
constructor: GLNode,
constructor: Node,
isNode: true,
......@@ -26,12 +26,12 @@ GLNode.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.clearVertexNodeCode();
builder.clearFragmentNodeCode();
builder.removeCache().removeSlot();
builder.removeFlow();
builder.parsing = false;
......@@ -51,11 +51,11 @@ GLNode.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 @@ GLNode.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 ) {
......@@ -100,7 +104,7 @@ GLNode.prototype = {
},
setName: function( name ) {
setName: function ( name ) {
this.name = name;
......@@ -108,7 +112,7 @@ GLNode.prototype = {
},
getName: function( builder ) {
getName: function ( builder ) {
return this.name;
......@@ -173,4 +177,4 @@ GLNode.prototype = {
};
export { GLNode };
export { Node };
......@@ -40,8 +40,9 @@ var elements = NodeUtils.elements,
function NodeBuilder() {
this.caches = [];
this.slots = [];
this.caches = [];
this.contexts = [];
this.keywords = {};
......@@ -63,7 +64,7 @@ function NodeBuilder() {
this.attributes = {};
this.prefixCode = [
"#ifdef GL_EXT_shader_texture_lod",
"#ifdef TEXTURE_LOD_EXT",
" #define texCube(a, b) textureCube(a, b)",
" #define texCubeBias(a, b, c) textureCubeLodEXT(a, b, c)",
......@@ -81,7 +82,8 @@ function NodeBuilder() {
"#endif",
"#include <packing>"
"#include <packing>",
"#include <common>"
].join( "\n" );
......@@ -140,15 +142,13 @@ function NodeBuilder() {
this.parsing = false;
this.optimize = true;
this.update();
};
}
NodeBuilder.prototype = {
constructor: NodeBuilder,
build: function( vertex, fragment ) {
build: function ( vertex, fragment ) {
this.buildShader( 'vertex', vertex );
this.buildShader( 'fragment', fragment );
......@@ -224,13 +224,13 @@ NodeBuilder.prototype = {
},
buildShader: function( shader, node ) {
buildShader: function ( shader, node ) {
this.resultCode[shader] = node.build( this.setShader( shader ), 'v4' );
this.resultCode[ shader ] = node.build( this.setShader( shader ), 'v4' );
},
setMaterial: function( material, renderer ) {
setMaterial: function ( material, renderer ) {
this.material = material;
this.renderer = renderer;
......@@ -238,44 +238,75 @@ NodeBuilder.prototype = {
this.requires.lights = material.lights;
this.requires.fog = material.fog;
this.mergeDefines( material.defines );
return this;
},
addCache: function ( name, context ) {
addFlow: function ( slot, cache, context ) {
this.caches.push( {
name: name || '',
context: context || {}
} );
return this.addSlot( slot ).addCache( cache ).addContext( context );
return this.update();
},
removeFlow: function () {
return this.removeSlot().removeCache().removeContext();
},
addCache: function ( name ) {
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;
},
addContext: function ( context ) {
this.context = Object.assign( {}, this.context, context );
this.contexts.push( this.context );
return this.update();
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;
},
......@@ -294,7 +325,7 @@ NodeBuilder.prototype = {
addCode: function ( code, shader ) {
this.code[shader || this.shader] += code + '\n';
this.code[ shader || this.shader ] += code + '\n';
},
......@@ -313,7 +344,7 @@ NodeBuilder.prototype = {
addNodeCode: function ( code, shader ) {
this.nodeCode[shader || this.shader] += code + '\n';
this.nodeCode[ shader || this.shader ] += code + '\n';
},
......@@ -321,9 +352,9 @@ NodeBuilder.prototype = {
shader = shader || this.shader;
var code = this.nodeCode[shader];
var code = this.nodeCode[ shader ];
this.nodeCode[shader] = '';
this.nodeCode[ shader ] = '';
return code;
......@@ -355,7 +386,7 @@ NodeBuilder.prototype = {
addFinalCode: function ( code, shader ) {
this.finalCode[shader || this.shader] += code + '\n';
this.finalCode[ shader || this.shader ] += code + '\n';
},
......@@ -374,7 +405,7 @@ NodeBuilder.prototype = {
addParsCode: function ( code, shader ) {
this.parsCode[shader || this.shader] += code + '\n';
this.parsCode[ shader || this.shader ] += code + '\n';
},
......@@ -389,42 +420,13 @@ NodeBuilder.prototype = {
isCache: function ( name ) {
var i = this.caches.length;
while ( i -- ) {
if ( this.caches[ i ].name === name ) return true;
}
return false;
return this.caches.indexOf( name ) !== - 1;
},
isSlot: function ( name ) {
var i = this.slots.length;
while ( i -- ) {
if ( this.slots[ i ].name === name ) return true;
}
return false;
},
update: function () {
var cache = this.caches[ this.caches.length - 1 ];
var slot = this.slots[ this.slots.length - 1 ];
this.slot = slot ? slot.name : '';
this.cache = cache ? cache.name : '';
this.context = cache ? cache.context : {};
return this;
return this.slots.indexOf( name ) !== - 1;
},
......@@ -444,7 +446,7 @@ NodeBuilder.prototype = {
shader = shader || 'varying';
var vars = this.getVars(shader),
var vars = this.getVars( shader ),
data = vars[ uuid ];
if ( ! data ) {
......@@ -486,18 +488,18 @@ NodeBuilder.prototype = {
},
getCode: function( shader ) {
getCode: function ( shader ) {
return [
this.prefixCode,
this.parsCode[ shader ],
this.getVarListCode( this.getVars('varying'), 'varying' ),
this.getVarListCode( this.inputs.uniforms[shader], 'uniform' ),
this.getVarListCode( this.getVars( 'varying' ), 'varying' ),
this.getVarListCode( this.inputs.uniforms[ shader ], 'uniform' ),
this.getIncludesCode( 'consts', shader ),
this.getIncludesCode( 'structs', shader ),
this.getIncludesCode( 'functions', shader ),
'void main() {',
this.getVarListCode( this.getVars(shader) ),
this.getVarListCode( this.getVars( shader ) ),
this.code[ shader ],
this.resultCode[ shader ],
this.finalCode[ shader ],
......@@ -514,7 +516,7 @@ NodeBuilder.prototype = {
for ( var i = 0, l = vars.length; i < l; ++ i ) {
var nVar = vars[i],
var nVar = vars[ i ],
type = nVar.type,
name = nVar.name;
......@@ -555,15 +557,15 @@ 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
} );
uniforms.list.push( uniform );
uniforms[shader].push( uniform );
uniforms[shader][ uniform.name ] = uniform;
uniforms[ shader ].push( uniform );
uniforms[ shader ][ uniform.name ] = uniform;
this.uniforms[ uniform.name ] = uniform;
......@@ -589,6 +591,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;
......@@ -605,7 +614,7 @@ NodeBuilder.prototype = {
var includes = includesStruct[ this.shader ] = includesStruct[ this.shader ] || [];
if (node) {
if ( node ) {
var included = includes[ node.name ];
......@@ -650,7 +659,7 @@ NodeBuilder.prototype = {
} else {
throw new Error("Include not found.");
throw new Error( "Include not found." );
}
......@@ -670,7 +679,7 @@ NodeBuilder.prototype = {
getIncludes: function ( type, shader ) {
return this.includes[type][shader || this.shader];
return this.includes[ type ][ shader || this.shader ];
},
......@@ -731,13 +740,13 @@ NodeBuilder.prototype = {
},
findNode: function() {
findNode: function () {
for(var i = 0; i < arguments.length; i++) {
for ( var i = 0; i < arguments.length; i ++ ) {
var nodeCandidate = arguments[i];
var nodeCandidate = arguments[ i ];
if (nodeCandidate !== undefined && nodeCandidate.isNode) {
if ( nodeCandidate !== undefined && nodeCandidate.isNode ) {
return nodeCandidate;
......@@ -747,21 +756,21 @@ NodeBuilder.prototype = {
},
resolve: function() {
resolve: function () {
for(var i = 0; i < arguments.length; i++) {
for ( var i = 0; i < arguments.length; i ++ ) {
var nodeCandidate = arguments[i];
var nodeCandidate = arguments[ i ];
if (nodeCandidate !== undefined) {
if ( nodeCandidate !== undefined ) {
if (nodeCandidate.isNode) {
if ( nodeCandidate.isNode ) {
return nodeCandidate;
} else if (nodeCandidate.isTexture) {
} else if ( nodeCandidate.isTexture ) {
switch( nodeCandidate.mapping ) {
switch ( nodeCandidate.mapping ) {
case THREE.CubeReflectionMapping:
case THREE.CubeRefractionMapping:
......@@ -783,15 +792,15 @@ NodeBuilder.prototype = {
}
} else if (nodeCandidate.isVector2) {
} else if ( nodeCandidate.isVector2 ) {
return new Vector2Node( nodeCandidate );
} else if (nodeCandidate.isVector3) {
} else if ( nodeCandidate.isVector3 ) {
return new Vector3Node( nodeCandidate );
} else if (nodeCandidate.isVector4) {
} else if ( nodeCandidate.isVector4 ) {
return new Vector4Node( nodeCandidate );
......@@ -805,34 +814,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 +897,34 @@ NodeBuilder.prototype = {
},
mergeUniform: function ( uniforms ) {
mergeDefines: function ( defines ) {
for ( var name in uniforms ) {
for ( var name in defines ) {
this.uniforms[ name ] = uniforms[ name ];
this.defines[ name ] = defines[ name ];
}
},
getTexelDecodingFunctionFromTexture: function( code, texture ) {
var gammaOverrideLinear = this.getTextureEncodingFromMap( texture, this.context.gamma && ( this.renderer ? this.renderer.gammaInput : false ) )
return this.getTexelDecodingFunction( code, gammaOverrideLinear );
return this.defines;
},
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 ) {
mergeUniform: function ( uniforms ) {
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 ];
}
},
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 );
}
return this.uniforms;
},
getTextureEncodingFromMap: function ( map, gammaOverrideLinear ) {
gammaOverrideLinear = gammaOverrideLinear !== undefined ? gammaOverrideLinear : this.context.gamma && ( this.renderer ? this.renderer.gammaInput : false );
var encoding;
if ( ! map ) {
......
......@@ -6,9 +6,9 @@ function NodeFrame( time ) {
this.time = time !== undefined ? time : 0;
this.frameId = 0;
this.id = 0;
};
}
NodeFrame.prototype = {
......@@ -16,7 +16,7 @@ NodeFrame.prototype = {
update: function ( delta ) {
++this.frameId;
++ this.id;
this.time += delta;
this.delta = delta;
......@@ -25,13 +25,29 @@ NodeFrame.prototype = {
},
setRenderer: function ( renderer ) {
this.renderer = renderer;
return this;
},
setRenderTexture: function ( renderTexture ) {
this.renderTexture = renderTexture;
return this;
},
updateNode: function ( node ) {
if ( node.frameId === this.frameId ) return this;
if ( node.frameId === this.id ) return this;
node.updateFrame( this );
node.frameId = this.frameId;
node.frameId = this.id;
return this;
......
......@@ -11,7 +11,7 @@ function NodeUniform( params ) {
this.node = params.node;
this.needsUpdate = params.needsUpdate;
};
}
Object.defineProperties( NodeUniform.prototype, {
......
......@@ -57,8 +57,8 @@ var NodeUtils = {
for ( var i = 0; i < list.length; ++ i ) {
var data = list[ i ].split( "." ),
property = data[0],
subProperty = data[1];
property = data[ 0 ],
subProperty = data[ 1 ];
shortcuts[ property ] = applyShortcut( proxy, property, subProperty );
......
......@@ -3,18 +3,17 @@
*/
import { TempNode } from './TempNode.js';
import { FunctionNode } from './FunctionNode.js';
var declarationRegexp = /^struct\s*([a-z_0-9]+)\s*{\s*((.|\n)*?)}/img,
propertiesRegexp = /\s*(\w*?)\s*(\w*?)(\=|\;)/img;
function StructNode( src ) {
TempNode.call( this);
TempNode.call( this );
this.eval( src );
};
StructNode.rDeclaration = /^struct\s*([a-z_0-9]+)\s*{\s*((.|\n)*?)}/img;
StructNode.rProperties = /\s*(\w*?)\s*(\w*?)(\=|\;)/img;
}
StructNode.prototype = Object.create( TempNode.prototype );
StructNode.prototype.constructor = StructNode;
......@@ -32,11 +31,14 @@ StructNode.prototype.getInputByName = function ( name ) {
while ( i -- ) {
if ( this.inputs[ i ].name === name )
if ( this.inputs[ i ].name === name ) {
return this.inputs[ i ];
}
}
};
StructNode.prototype.generate = function ( builder, output ) {
......@@ -47,7 +49,7 @@ StructNode.prototype.generate = function ( builder, output ) {
} else {
return builder.format( "(" + src + ")", this.getType( builder ), output );
return builder.format( '( ' + src + ' )', this.getType( builder ), output );
}
......@@ -59,24 +61,22 @@ StructNode.prototype.eval = function ( src ) {
this.inputs = [];
var declaration = StructNode.rDeclaration.exec( this.src );
if (declaration) {
var declaration = declarationRegexp.exec( this.src );
var properties = declaration[2], matchType, matchName;
if ( declaration ) {
while ( matchType = FunctionNode.rProperties.exec( properties ) ) {
var properties = declaration[ 2 ], match;
matchName = FunctionNode.rProperties.exec( properties )[0];
while ( match = propertiesRegexp.exec( properties ) ) {
this.inputs.push( {
name: matchName,
type: matchType
type: match[ 1 ],
name: match[ 2 ]
} );
}
this.name = declaration[1];
this.name = declaration[ 1 ];
} else {
......
......@@ -3,20 +3,20 @@
* @author sunag / http://www.sunag.com.br/
*/
import { GLNode } from './GLNode.js';
import { Node } from './Node.js';
function TempNode( type, params ) {
GLNode.call( this, type );
Node.call( this, type );
params = params || {};
this.shared = params.shared !== undefined ? params.shared : true;
this.unique = params.unique !== undefined ? params.unique : false;
};
}
TempNode.prototype = Object.create( GLNode.prototype );
TempNode.prototype = Object.create( Node.prototype );
TempNode.prototype.constructor = TempNode;
TempNode.prototype.build = function ( builder, output, uuid, ns ) {
......@@ -35,36 +35,36 @@ TempNode.prototype.build = function ( builder, output, uuid, ns ) {
uuid = builder.getUuid( uuid || this.getUuid(), ! isUnique );
var data = builder.getNodeData( uuid );
var data = builder.getNodeData( uuid ),
type = data.output || this.getType( builder );
if ( builder.parsing ) {
if ( data.deps || 0 > 0 ) {
if ( ( data.deps || 0 ) > 0 ) {
this.appendDepsNode( builder, data, output );
return this.generate( builder, type, uuid );
return this.generate( builder, output, uuid );
}
return GLNode.prototype.build.call( this, builder, output, uuid );
return Node.prototype.build.call( this, builder, output, uuid );
} else if ( isUnique ) {
data.name = data.name || GLNode.prototype.build.call( this, builder, output, uuid );
data.name = data.name || Node.prototype.build.call( this, builder, output, uuid );
return data.name;
} else if ( ! builder.optimize || data.deps == 1 ) {
} else if ( ! this.isShared( builder, type ) || ( ! builder.optimize || data.deps == 1 ) ) {
return GLNode.prototype.build.call( this, builder, output, uuid );
return Node.prototype.build.call( this, builder, output, uuid );
}
uuid = this.getUuid( false );
var name = this.getTemp( builder, uuid ),
type = data.output || this.getType( builder );
var name = this.getTemp( builder, uuid );
if ( name ) {
......@@ -84,7 +84,7 @@ TempNode.prototype.build = function ( builder, output, uuid, ns ) {
}
return GLNode.prototype.build.call( this, builder, output, uuid );
return Node.prototype.build.call( this, builder, output, uuid );
};
......@@ -114,7 +114,7 @@ TempNode.prototype.getTemp = function ( builder, uuid ) {
uuid = uuid || this.uuid;
var tempVar = builder.getVars()[uuid]
var tempVar = builder.getVars()[ uuid ];
return tempVar ? tempVar.name : undefined;
......
......@@ -2,17 +2,17 @@
* @author sunag / http://www.sunag.com.br/
*/
import { GLNode } from './GLNode.js';
import { Node } from './Node.js';
function VarNode( type, value ) {
GLNode.call( this, type );
Node.call( this, type );
this.value = value;
};
}
VarNode.prototype = Object.create( GLNode.prototype );
VarNode.prototype = Object.create( Node.prototype );
VarNode.prototype.constructor = VarNode;
VarNode.prototype.nodeType = "Var";
......@@ -38,7 +38,7 @@ VarNode.prototype.generate = function ( builder, output ) {
VarNode.prototype.copy = function ( source ) {
GLNode.prototype.copy.call( this, source );
Node.prototype.copy.call( this, source );
this.type = source.type;
this.value = source.value;
......
......@@ -24,9 +24,9 @@ function BlurNode( value, uv, radius, size ) {
this.horizontal = new FloatNode( 1 / 64 );
this.vertical = new FloatNode( 1 / 64 );
};
}
BlurNode.Nodes = (function() {
BlurNode.Nodes = ( function () {
var blurX = new FunctionNode( [
"vec4 blurX( sampler2D texture, vec2 uv, float s ) {",
......@@ -40,7 +40,7 @@ BlurNode.Nodes = (function() {
" sum += texture2D( texture, vec2( uv.x + 2.0 * s, uv.y ) ) * 0.12245;",
" sum += texture2D( texture, vec2( uv.x + 3.0 * s, uv.y ) ) * 0.0918;",
" sum += texture2D( texture, vec2( uv.x + 4.0 * s, uv.y ) ) * 0.051;",
" return sum;",
" return sum * .667;",
"}"
].join( "\n" ) );
......@@ -56,7 +56,7 @@ BlurNode.Nodes = (function() {
" sum += texture2D( texture, vec2( uv.x, uv.y + 2.0 * s ) ) * 0.12245;",
" sum += texture2D( texture, vec2( uv.x, uv.y + 3.0 * s ) ) * 0.0918;",
" sum += texture2D( texture, vec2( uv.x, uv.y + 4.0 * s ) ) * 0.051;",
" return sum;",
" return sum * .667;",
"}"
].join( "\n" ) );
......@@ -65,7 +65,7 @@ BlurNode.Nodes = (function() {
blurY: blurY
};
})();
} )();
BlurNode.prototype = Object.create( TempNode.prototype );
......@@ -111,7 +111,7 @@ BlurNode.prototype.generate = function ( builder, output ) {
}
if ( blurCode.length == 2 ) code = '( ' + blurCode.join( ' + ' ) + '/ 2.0 )';
if ( blurCode.length == 2 ) code = '( ' + blurCode.join( ' + ' ) + ' / 2.0 )';
else if ( blurCode.length ) code = '( ' + blurCode[ 0 ] + ' )';
else code = 'vec4( 0.0 )';
......
......@@ -15,9 +15,9 @@ function ColorAdjustmentNode( rgb, adjustment, method ) {
this.method = method || ColorAdjustmentNode.SATURATION;
};
}
ColorAdjustmentNode.Nodes = (function() {
ColorAdjustmentNode.Nodes = ( function () {
var hue = new FunctionNode( [
"vec3 hue(vec3 rgb, float adjustment) {",
......@@ -66,7 +66,7 @@ ColorAdjustmentNode.Nodes = (function() {
vibrance: vibrance
};
})();
} )();
ColorAdjustmentNode.SATURATION = 'saturation';
ColorAdjustmentNode.HUE = 'hue';
......@@ -99,7 +99,7 @@ ColorAdjustmentNode.prototype.generate = function ( builder, output ) {
}
var method = builder.include( ColorAdjustmentNode.Nodes[this.method] );
var method = builder.include( ColorAdjustmentNode.Nodes[ this.method ] );
return builder.format( method + '( ' + rgb + ', ' + adjustment + ' )', this.getType( builder ), output );
......
......@@ -12,9 +12,9 @@ function LuminanceNode( rgb ) {
this.rgb = rgb;
};
}
LuminanceNode.Nodes = (function() {
LuminanceNode.Nodes = ( function () {
var LUMA = new ConstNode( "vec3 LUMA vec3( 0.2125, 0.7154, 0.0721 )" );
......@@ -32,7 +32,7 @@ LuminanceNode.Nodes = (function() {
luminance: luminance
};
})();
} )();
LuminanceNode.prototype = Object.create( TempNode.prototype );
LuminanceNode.prototype.constructor = LuminanceNode;
......
......@@ -11,7 +11,7 @@ function ColorNode( color, g, b ) {
this.value = color instanceof THREE.Color ? color : new THREE.Color( color || 0, g, b );
};
}
ColorNode.prototype = Object.create( InputNode.prototype );
ColorNode.prototype.constructor = ColorNode;
......
......@@ -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 ) {
......@@ -13,7 +14,7 @@ function CubeTextureNode( value, uv, bias ) {
this.uv = uv || new ReflectNode();
this.bias = bias;
};
}
CubeTextureNode.prototype = Object.create( InputNode.prototype );
CubeTextureNode.prototype.constructor = CubeTextureNode;
......@@ -48,7 +49,14 @@ 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 );
......
......@@ -10,7 +10,7 @@ function FloatNode( value ) {
this.value = value || 0;
};
}
FloatNode.prototype = Object.create( InputNode.prototype );
FloatNode.prototype.constructor = FloatNode;
......
......@@ -10,7 +10,7 @@ function IntNode( value ) {
this.value = Math.floor( value || 0 );
};
}
IntNode.prototype = Object.create( InputNode.prototype );
IntNode.prototype.constructor = IntNode;
......
......@@ -10,7 +10,7 @@ function Matrix3Node( matrix ) {
this.value = matrix || new THREE.Matrix3();
};
}
Matrix3Node.prototype = Object.create( InputNode.prototype );
Matrix3Node.prototype.constructor = Matrix3Node;
......@@ -20,7 +20,7 @@ Object.defineProperties( Matrix3Node.prototype, {
elements: {
set: function (val) {
set: function ( val ) {
this.value.elements = val;
......
......@@ -10,7 +10,7 @@ function Matrix4Node( matrix ) {
this.value = matrix || new THREE.Matrix4();
};
}
Matrix4Node.prototype = Object.create( InputNode.prototype );
Matrix4Node.prototype.constructor = Matrix4Node;
......@@ -20,7 +20,7 @@ Object.defineProperties( Matrix4Node.prototype, {
elements: {
set: function (val) {
set: function ( val ) {
this.value.elements = val;
......
......@@ -11,7 +11,7 @@ function PropertyNode( object, property, type ) {
this.object = object;
this.property = property;
};
}
PropertyNode.prototype = Object.create( InputNode.prototype );
PropertyNode.prototype.constructor = PropertyNode;
......
/**
* @author sunag / http://www.sunag.com.br/
*/
import { NodeMaterial } from '../materials/NodeMaterial.js';
import { TextureNode } from './TextureNode.js';
function RTTNode( width, height, input, options ) {
options = options || {};
this.input = input;
this.clear = options.clear !== undefined ? options.clear : true;
this.renderTarget = new THREE.WebGLRenderTarget( width, height, options );
this.material = new 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 );
this.render = true;
TextureNode.call( this, this.renderTarget.texture );
}
RTTNode.prototype = Object.create( TextureNode.prototype );
RTTNode.prototype.constructor = RTTNode;
RTTNode.prototype.nodeType = "RTT";
RTTNode.prototype.build = function ( builder, output, uuid ) {
var rttBuilder = new THREE.NodeBuilder();
rttBuilder.nodes = builder.nodes;
rttBuilder.updaters = builder.updaters;
this.material.fragment.value = this.input;
this.material.build( { builder: rttBuilder } );
return TextureNode.prototype.build.call( this, builder, output, uuid );
};
RTTNode.prototype.updateFramesaveTo = function ( frame ) {
this.saveTo.render = false;
if ( this.saveTo !== this.saveToCurrent ) {
if ( this.saveToMaterial ) this.saveToMaterial.dispose();
var material = new NodeMaterial();
material.fragment.value = this;
material.build();
var scene = new THREE.Scene();
var quad = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), material );
quad.frustumCulled = false; // Avoid getting clipped
scene.add( quad );
this.saveToScene = scene;
this.saveToMaterial = material;
}
this.saveToCurrent = this.saveTo;
frame.renderer.render( this.saveToScene, this.camera, this.saveTo.renderTarget, this.saveTo.clear );
};
RTTNode.prototype.updateFrame = function ( frame ) {
if ( frame.renderer ) {
// from the second frame
if ( this.saveTo && this.saveTo.render === false ) {
this.updateFramesaveTo( frame );
}
if ( this.render ) {
if ( this.material.uniforms.renderTexture ) {
this.material.uniforms.renderTexture.value = frame.renderTexture;
}
frame.renderer.render( this.scene, this.camera, this.renderTarget, this.clear );
}
// first frame
if ( this.saveTo && this.saveTo.render === true ) {
this.updateFramesaveTo( frame );
}
} else {
console.warn( "RTTNode need a renderer in NodeFrame" );
}
};
RTTNode.prototype.copy = function ( source ) {
TextureNode.prototype.copy.call( this, source );
this.saveTo = source.saveTo;
};
RTTNode.prototype.toJSON = function ( meta ) {
var data = this.getJSONNode( meta );
if ( ! data ) {
data = THREE.TextureNode.prototype.toJSON.call( this, meta );
if ( this.saveTo ) data.saveTo = this.saveTo.toJSON( meta ).uuid;
}
return data;
};
export { RTTNode };
......@@ -14,7 +14,7 @@ function ReflectorNode( mirror ) {
if ( mirror ) this.setMirror( mirror );
};
}
ReflectorNode.prototype = Object.create( TempNode.prototype );
ReflectorNode.prototype.constructor = ReflectorNode;
......
......@@ -9,7 +9,7 @@ function ScreenNode( uv ) {
TextureNode.call( this, undefined, uv );
};
}
ScreenNode.prototype = Object.create( TextureNode.prototype );
ScreenNode.prototype.constructor = ScreenNode;
......
......@@ -3,8 +3,8 @@
*/
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 ) {
......@@ -15,7 +15,7 @@ function TextureNode( value, uv, bias, project ) {
this.bias = bias;
this.project = project !== undefined ? project : false;
};
}
TextureNode.prototype = Object.create( InputNode.prototype );
TextureNode.prototype.constructor = TextureNode;
......@@ -53,7 +53,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 );
......
......@@ -11,7 +11,7 @@ function Vector2Node( x, y ) {
this.value = x instanceof THREE.Vector2 ? x : new THREE.Vector2( x, y );
};
}
Vector2Node.prototype = Object.create( InputNode.prototype );
Vector2Node.prototype.constructor = Vector2Node;
......
......@@ -11,7 +11,7 @@ function Vector3Node( x, y, z ) {
this.value = x instanceof THREE.Vector3 ? x : new THREE.Vector3( x, y, z );
};
}
Vector3Node.prototype = Object.create( InputNode.prototype );
Vector3Node.prototype.constructor = Vector3Node;
......
......@@ -11,7 +11,7 @@ function Vector4Node( x, y, z, w ) {
this.value = x instanceof THREE.Vector4 ? x : new THREE.Vector4( x, y, z, w );
};
}
Vector4Node.prototype = Object.create( InputNode.prototype );
Vector4Node.prototype.constructor = Vector4Node;
......
......@@ -14,7 +14,7 @@ function MeshStandardNodeMaterial() {
this.type = "MeshStandardNodeMaterial";
};
}
MeshStandardNodeMaterial.prototype = Object.create( NodeMaterial.prototype );
MeshStandardNodeMaterial.prototype.constructor = MeshStandardNodeMaterial;
......
......@@ -11,16 +11,12 @@ 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 ) );
this.updaters = [];
};
}
NodeMaterial.prototype = Object.create( THREE.ShaderMaterial.prototype );
NodeMaterial.prototype.constructor = NodeMaterial;
......@@ -75,8 +71,8 @@ NodeMaterial.prototype.build = function ( params ) {
builder.setMaterial( this, params.renderer );
builder.build( this.vertex, this.fragment );
this.vertexShader = builder.getCode('vertex');
this.fragmentShader = builder.getCode('fragment');
this.vertexShader = builder.getCode( 'vertex' );
this.fragmentShader = builder.getCode( 'fragment' );
this.defines = builder.defines;
this.uniforms = builder.uniforms;
......@@ -98,15 +94,15 @@ NodeMaterial.prototype.copy = function ( source ) {
var uuid = this.uuid;
for (var name in source) {
for ( var name in source ) {
this[name] = source[name];
this[ name ] = source[ name ];
}
this.uuid = uuid;
if ( source.userData !== undefined) {
if ( source.userData !== undefined ) {
this.userData = JSON.parse( JSON.stringify( source.userData ) );
......
......@@ -14,7 +14,7 @@ function PhongNodeMaterial() {
this.type = "PhongNodeMaterial";
};
}
PhongNodeMaterial.prototype = Object.create( NodeMaterial.prototype );
PhongNodeMaterial.prototype.constructor = PhongNodeMaterial;
......@@ -32,7 +32,7 @@ NodeUtils.addShortcuts( PhongNodeMaterial.prototype, 'fragment', [
'ao',
'environment',
'environmentAlpha',
'transform'
'position'
] );
export { PhongNodeMaterial };
......@@ -14,7 +14,7 @@ function SpriteNodeMaterial() {
this.type = "SpriteNodeMaterial";
};
}
SpriteNodeMaterial.prototype = Object.create( NodeMaterial.prototype );
SpriteNodeMaterial.prototype.constructor = SpriteNodeMaterial;
......@@ -22,7 +22,7 @@ SpriteNodeMaterial.prototype.constructor = SpriteNodeMaterial;
NodeUtils.addShortcuts( SpriteNodeMaterial.prototype, 'fragment', [
'color',
'alpha',
'transform',
'position',
'spherical'
] );
......
......@@ -14,7 +14,7 @@ function StandardNodeMaterial() {
this.type = "StandardNodeMaterial";
};
}
StandardNodeMaterial.prototype = Object.create( NodeMaterial.prototype );
StandardNodeMaterial.prototype.constructor = StandardNodeMaterial;
......@@ -34,7 +34,7 @@ NodeUtils.addShortcuts( StandardNodeMaterial.prototype, 'fragment', [
'shadow',
'ao',
'environment',
'transform'
'position'
] );
export { StandardNodeMaterial };
......@@ -26,7 +26,7 @@ function MeshStandardNode() {
normalScale: new PropertyNode( this.properties, 'normalScale', 'v2' )
};
};
}
MeshStandardNode.prototype = Object.create( StandardNode.prototype );
MeshStandardNode.prototype.constructor = MeshStandardNode;
......@@ -37,7 +37,7 @@ MeshStandardNode.prototype.build = function ( builder ) {
var props = this.properties,
inputs = this.inputs;
if ( builder.isShader('fragment') ) {
if ( builder.isShader( 'fragment' ) ) {
// slots
// * color
......@@ -73,7 +73,11 @@ 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 );
} else {
this.normal = undefined;
}
......@@ -98,7 +102,7 @@ MeshStandardNode.prototype.toJSON = function ( meta ) {
data = this.createJSONNode( meta );
console.warn(".toJSON not implemented in", this);
console.warn( ".toJSON not implemented in", this );
}
......
......@@ -2,21 +2,21 @@
* @author sunag / http://www.sunag.com.br/
*/
import { GLNode } from '../../core/GLNode.js';
import { Node } from '../../core/Node.js';
import { ColorNode } from '../../inputs/ColorNode.js';
import { FloatNode } from '../../inputs/FloatNode.js';
function PhongNode() {
GLNode.call( this );
Node.call( this );
this.color = new ColorNode( 0xEEEEEE );
this.specular = new ColorNode( 0x111111 );
this.shininess = new FloatNode( 30 );
};
}
PhongNode.prototype = Object.create( GLNode.prototype );
PhongNode.prototype = Object.create( Node.prototype );
PhongNode.prototype.constructor = PhongNode;
PhongNode.prototype.nodeType = "Phong";
......@@ -25,18 +25,17 @@ PhongNode.prototype.build = function ( builder ) {
var code;
builder.define( 'PHONG' );
builder.define( 'ALPHATEST', '0.0' );
builder.requires.lights = true;
if ( builder.isShader( 'vertex' ) ) {
var transform = this.transform ? this.transform.parseAndBuildCode( builder, 'v3', { cache: 'transform' } ) : undefined;
var position = this.position ? this.position.parseAndBuildCode( builder, 'v3', { cache: 'position' } ) : undefined;
builder.mergeUniform( THREE.UniformsUtils.merge( [
THREE.UniformsLib[ "fog" ],
THREE.UniformsLib[ "lights" ]
THREE.UniformsLib.fog,
THREE.UniformsLib.lights
] ) );
......@@ -49,13 +48,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 +64,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 );",
......@@ -74,11 +73,11 @@ PhongNode.prototype.build = function ( builder ) {
"#include <begin_vertex>"
];
if ( transform ) {
if ( position ) {
output.push(
transform.code,
transform.result ? "transformed = " + transform.result + ";" : ''
position.code,
position.result ? "transformed = " + position.result + ";" : ''
);
}
......@@ -89,11 +88,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" );
......@@ -109,7 +110,6 @@ PhongNode.prototype.build = function ( builder ) {
if ( this.alpha ) this.alpha.parse( builder );
if ( this.normal ) this.normal.parse( builder );
if ( this.normalScale && this.normal ) this.normalScale.parse( builder );
if ( this.light ) this.light.parse( builder, { cache: 'light' } );
......@@ -130,7 +130,6 @@ PhongNode.prototype.build = function ( builder ) {
var alpha = this.alpha ? this.alpha.buildCode( builder, 'f' ) : undefined;
var normal = this.normal ? this.normal.buildCode( builder, 'v3' ) : undefined;
var normalScale = this.normalScale && this.normal ? this.normalScale.buildCode( builder, 'v2' ) : undefined;
var light = this.light ? this.light.buildCode( builder, 'v3', { cache: 'light' } ) : undefined;
......@@ -145,7 +144,6 @@ PhongNode.prototype.build = function ( builder ) {
builder.requires.transparent = alpha != undefined;
builder.addParsCode( [
"#include <common>",
"#include <fog_pars_fragment>",
"#include <bsdfs>",
"#include <lights_pars_begin>",
......@@ -180,7 +178,11 @@ PhongNode.prototype.build = function ( builder ) {
output.push(
alpha.code,
'if ( ' + alpha.result + ' <= ALPHATEST ) discard;'
'#ifdef ALPHATEST',
'if ( ' + alpha.result + ' <= ALPHATEST ) discard;',
'#endif'
);
}
......@@ -281,7 +283,7 @@ PhongNode.prototype.build = function ( builder ) {
}
}
/*
/*
switch( builder.material.combine ) {
case THREE.ENVMAP_BLENDING_MULTIPLY:
......@@ -321,11 +323,11 @@ PhongNode.prototype.build = function ( builder ) {
PhongNode.prototype.copy = function ( source ) {
GLNode.prototype.copy.call( this, source );
Node.prototype.copy.call( this, source );
// vertex
if ( source.transform ) this.transform = source.transform;
if ( source.position ) this.position = source.position;
// fragment
......@@ -360,7 +362,7 @@ PhongNode.prototype.toJSON = function ( meta ) {
// vertex
if ( this.transform ) data.transform = this.transform.toJSON( meta ).uuid;
if ( this.position ) data.position = this.position.toJSON( meta ).uuid;
// fragment
......
......@@ -2,17 +2,17 @@
* @author sunag / http://www.sunag.com.br/
*/
import { GLNode } from '../../core/GLNode.js';
import { Node } from '../../core/Node.js';
function RawNode( value ) {
GLNode.call( this, 'v4' );
Node.call( this, 'v4' );
this.value = value;
};
}
RawNode.prototype = Object.create( GLNode.prototype );
RawNode.prototype = Object.create( Node.prototype );
RawNode.prototype.constructor = RawNode;
RawNode.prototype.nodeType = "Raw";
......@@ -37,7 +37,7 @@ RawNode.prototype.generate = function ( builder ) {
RawNode.prototype.copy = function ( source ) {
GLNode.prototype.copy.call( this, source );
Node.prototype.copy.call( this, source );
this.value = source.value;
......
......@@ -2,19 +2,19 @@
* @author sunag / http://www.sunag.com.br/
*/
import { GLNode } from '../../core/GLNode.js';
import { Node } from '../../core/Node.js';
import { ColorNode } from '../../inputs/ColorNode.js';
function SpriteNode() {
GLNode.call( this );
Node.call( this );
this.color = new ColorNode( 0xEEEEEE );
this.spherical = true;
};
}
SpriteNode.prototype = Object.create( GLNode.prototype );
SpriteNode.prototype = Object.create( Node.prototype );
SpriteNode.prototype.constructor = SpriteNode;
SpriteNode.prototype.nodeType = "Sprite";
......@@ -25,29 +25,32 @@ SpriteNode.prototype.build = function ( builder ) {
builder.define( 'SPRITE' );
builder.requires.lights = false;
builder.requires.transparent = this.alpha != undefined;
builder.requires.transparent = this.alpha !== undefined;
if ( builder.isShader( 'vertex' ) ) {
var transform = this.transform ? this.transform.parseAndBuildCode( builder, 'v3', { cache: 'transform' } ) : undefined;
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 <fog_pars_vertex>",
"#include <logdepthbuf_pars_vertex>",
"#include <clipping_planes_pars_vertex>"
].join( "\n" ) );
output = [
"#include <clipping_planes_fragment>",
"#include <begin_vertex>"
];
if ( transform ) {
if ( position ) {
output.push(
transform.code,
transform.result ? "transformed = " + transform.result + ";" : ''
position.code,
position.result ? "transformed = " + position.result + ";" : ''
);
}
......@@ -98,43 +101,64 @@ SpriteNode.prototype.build = function ( builder ) {
'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 <fog_pars_fragment>",
"#include <logdepthbuf_pars_fragment>",
"#include <clipping_planes_pars_fragment>"
].join( "\n" ) );
// parse all nodes to reuse generate codes
builder.addCode( [
"#include <clipping_planes_fragment>",
"#include <logdepthbuf_fragment>"
].join( "\n" ) );
this.color.parse( builder, { slot: 'color' } );
// parse all nodes to reuse generate codes
if ( this.alpha ) this.alpha.parse( builder );
// build code
this.color.parse( builder, { slot: 'color' } );
var color = this.color.buildCode( builder, 'c', { slot: 'color' } );
var alpha = this.alpha ? this.alpha.buildCode( builder, 'f' ) : undefined;
// build code
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,
'#ifdef ALPHATEST',
'if ( ' + alpha.result + ' <= ALPHATEST ) discard;',
'#endif',
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>"
);
}
......@@ -144,17 +168,17 @@ SpriteNode.prototype.build = function ( builder ) {
SpriteNode.prototype.copy = function ( source ) {
GLNode.prototype.copy.call( this, source );
Node.prototype.copy.call( this, source );
// vertex
if ( source.transform ) this.transform = source.transform;
if ( source.position ) this.position = source.position;
// fragment
this.color = source.color;
if ( source.spherical !== undefined ) this.spherical = source.transform;
if ( source.spherical !== undefined ) this.spherical = source.spherical;
if ( source.alpha ) this.alpha = source.alpha;
......@@ -170,7 +194,7 @@ SpriteNode.prototype.toJSON = function ( meta ) {
// vertex
if ( this.transform ) data.transform = this.transform.toJSON( meta ).uuid;
if ( this.position ) data.position = this.position.toJSON( meta ).uuid;
// fragment
......
......@@ -2,22 +2,22 @@
* @author sunag / http://www.sunag.com.br/
*/
import { GLNode } from '../../core/GLNode.js';
import { Node } from '../../core/Node.js';
import { ColorNode } from '../../inputs/ColorNode.js';
import { FloatNode } from '../../inputs/FloatNode.js';
import { RoughnessToBlinnExponentNode } from '../../bsdfs/RoughnessToBlinnExponentNode.js';
function StandardNode() {
GLNode.call( this );
Node.call( this );
this.color = new ColorNode( 0xEEEEEE );
this.roughness = new FloatNode( 0.5 );
this.metalness = new FloatNode( 0.5 );
};
}
StandardNode.prototype = Object.create( GLNode.prototype );
StandardNode.prototype = Object.create( Node.prototype );
StandardNode.prototype.constructor = StandardNode;
StandardNode.prototype.nodeType = "Standard";
......@@ -26,7 +26,6 @@ StandardNode.prototype.build = function ( builder ) {
var code;
builder.define( this.clearCoat || this.clearCoatRoughness ? 'PHYSICAL' : 'STANDARD' );
builder.define( 'ALPHATEST', '0.0' );
builder.requires.lights = true;
......@@ -34,12 +33,12 @@ StandardNode.prototype.build = function ( builder ) {
if ( builder.isShader( 'vertex' ) ) {
var transform = this.transform ? this.transform.parseAndBuildCode( builder, 'v3', { cache: 'transform' } ) : undefined;
var position = this.position ? this.position.parseAndBuildCode( builder, 'v3', { cache: 'position' } ) : undefined;
builder.mergeUniform( THREE.UniformsUtils.merge( [
THREE.UniformsLib[ "fog" ],
THREE.UniformsLib[ "lights" ]
THREE.UniformsLib.fog,
THREE.UniformsLib.lights
] ) );
......@@ -52,13 +51,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 +67,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
......@@ -81,11 +77,11 @@ StandardNode.prototype.build = function ( builder ) {
"#include <begin_vertex>"
];
if ( transform ) {
if ( position ) {
output.push(
transform.code,
transform.result ? "transformed = " + transform.result + ";" : ''
position.code,
position.result ? "transformed = " + position.result + ";" : ''
);
}
......@@ -96,6 +92,7 @@ StandardNode.prototype.build = function ( builder ) {
"#include <project_vertex>",
"#include <fog_vertex>",
"#include <logdepthbuf_vertex>",
"#include <clipping_planes_vertex>",
" vViewPosition = - mvPosition.xyz;",
......@@ -127,7 +124,6 @@ StandardNode.prototype.build = function ( builder ) {
if ( this.alpha ) this.alpha.parse( builder );
if ( this.normal ) this.normal.parse( builder );
if ( this.normalScale && this.normal ) this.normalScale.parse( builder );
if ( this.clearCoat ) this.clearCoat.parse( builder );
if ( this.clearCoatRoughness ) this.clearCoatRoughness.parse( builder );
......@@ -152,7 +148,6 @@ StandardNode.prototype.build = function ( builder ) {
var alpha = this.alpha ? this.alpha.buildCode( builder, 'f' ) : undefined;
var normal = this.normal ? this.normal.buildCode( builder, 'v3' ) : undefined;
var normalScale = this.normalScale && this.normal ? this.normalScale.buildCode( builder, 'v2' ) : undefined;
var clearCoat = this.clearCoat ? this.clearCoat.buildCode( builder, 'f' ) : undefined;
var clearCoatRoughness = this.clearCoatRoughness ? this.clearCoatRoughness.buildCode( builder, 'f' ) : undefined;
......@@ -182,7 +177,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 +188,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 );",
......@@ -217,7 +214,11 @@ StandardNode.prototype.build = function ( builder ) {
output.push(
alpha.code,
'if ( ' + alpha.result + ' <= ALPHATEST ) discard;'
'#ifdef ALPHATEST',
'if ( ' + alpha.result + ' <= ALPHATEST ) discard;',
'#endif'
);
}
......@@ -374,7 +375,6 @@ StandardNode.prototype.build = function ( builder ) {
}
output.push(
"#include <premultiplied_alpha_fragment>",
"#include <tonemapping_fragment>",
"#include <encodings_fragment>",
"#include <fog_fragment>",
......@@ -392,11 +392,11 @@ StandardNode.prototype.build = function ( builder ) {
StandardNode.prototype.copy = function ( source ) {
GLNode.prototype.copy.call( this, source );
Node.prototype.copy.call( this, source );
// vertex
if ( source.transform ) this.transform = source.transform;
if ( source.position ) this.position = source.position;
// fragment
......@@ -435,7 +435,7 @@ StandardNode.prototype.toJSON = function ( meta ) {
// vertex
if ( this.transform ) data.transform = this.transform.toJSON( meta ).uuid;
if ( this.position ) data.position = this.position.toJSON( meta ).uuid;
// fragment
......
/**
* @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.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 };
......@@ -10,9 +10,9 @@ function Math1Node( a, method ) {
this.a = a;
this.method = method || Math1Node.SIN;
this.method = method;
};
}
Math1Node.RAD = 'radians';
Math1Node.DEG = 'degrees';
......
......@@ -11,9 +11,9 @@ function Math2Node( a, b, method ) {
this.a = a;
this.b = b;
this.method = method || Math2Node.DISTANCE;
this.method = method;
};
}
Math2Node.MIN = 'min';
Math2Node.MAX = 'max';
......
......@@ -12,9 +12,9 @@ function Math3Node( a, b, c, method ) {
this.b = b;
this.c = c;
this.method = method || Math3Node.MIX;
this.method = method;
};
}
Math3Node.MIX = 'mix';
Math3Node.REFRACT = 'refract';
......
......@@ -10,9 +10,9 @@ function OperatorNode( a, b, op ) {
this.a = a;
this.b = b;
this.op = op || OperatorNode.ADD;
this.op = op;
};
}
OperatorNode.ADD = '+';
OperatorNode.SUB = '-';
......@@ -52,7 +52,7 @@ OperatorNode.prototype.generate = function ( builder, output ) {
var a = this.a.build( builder, type ),
b = this.b.build( builder, type );
return builder.format( '( ' + a + ' ' + this.op + ' '+ b + ' )', type, output );
return builder.format( '( ' + a + ' ' + this.op + ' ' + b + ' )', type, output );
};
......
......@@ -17,9 +17,9 @@ function BumpMapNode( value, scale ) {
this.toNormalMap = false;
};
}
BumpMapNode.Nodes = (function() {
BumpMapNode.Nodes = ( function () {
var dHdxy_fwd = new FunctionNode( [
......@@ -91,7 +91,7 @@ BumpMapNode.Nodes = (function() {
bumpToNormal: bumpToNormal
};
})();
} )();
BumpMapNode.prototype = Object.create( TempNode.prototype );
BumpMapNode.prototype.constructor = BumpMapNode;
......@@ -114,7 +114,7 @@ BumpMapNode.prototype.generate = function ( builder, output ) {
var derivativeHeight = builder.include( BumpMapNode.Nodes.dHdxy_fwd ),
perturbNormalArb = builder.include( BumpMapNode.Nodes.perturbNormalArb );
this.normal = this.normal || new NormalNode( NormalNode.VIEW );
this.normal = this.normal || new NormalNode();
this.position = this.position || new PositionNode( PositionNode.VIEW );
var derivativeHeightCode = derivativeHeight + '( ' + this.value.build( builder, 'sampler2D' ) + ', ' +
......
......@@ -16,9 +16,9 @@ function NormalMapNode( value, scale ) {
this.value = value;
this.scale = scale || new Vector2Node( 1, 1 );
};
}
NormalMapNode.Nodes = (function() {
NormalMapNode.Nodes = ( function () {
var perturbNormal2Arb = new FunctionNode( [
......@@ -56,7 +56,7 @@ NormalMapNode.Nodes = (function() {
perturbNormal2Arb: perturbNormal2Arb
};
})();
} )();
NormalMapNode.prototype = Object.create( TempNode.prototype );
NormalMapNode.prototype.constructor = NormalMapNode;
......@@ -68,7 +68,7 @@ NormalMapNode.prototype.generate = function ( builder, output ) {
var perturbNormal2Arb = builder.include( NormalMapNode.Nodes.perturbNormal2Arb );
this.normal = this.normal || new NormalNode( NormalNode.VIEW );
this.normal = this.normal || new NormalNode();
this.position = this.position || new PositionNode( PositionNode.VIEW );
this.uv = this.uv || new UVNode();
......
......@@ -12,7 +12,7 @@ function TextureCubeNode( value, uv ) {
this.value = value;
this.uv = uv || new TextureCubeUVNode();
};
}
TextureCubeNode.prototype = Object.create( TempNode.prototype );
TextureCubeNode.prototype.constructor = TextureCubeNode;
......
......@@ -16,19 +16,19 @@ function TextureCubeUVNode( uv, textureSize, blinnExponentToRoughness ) {
this.uv = uv || new ReflectNode( ReflectNode.VECTOR );
this.textureSize = textureSize || new FloatNode( 1024 );
this.blinnExponentToRoughness = this.blinnExponentToRoughness || new BlinnExponentToRoughnessNode();
this.blinnExponentToRoughness = blinnExponentToRoughness || new BlinnExponentToRoughnessNode();
};
}
TextureCubeUVNode.Nodes = (function() {
TextureCubeUVNode.Nodes = ( function () {
var TextureCubeUVData = new StructNode([
var TextureCubeUVData = new StructNode( [
"struct TextureCubeUVData {",
" vec2 uv_10;",
" vec2 uv_20;",
" float t;",
"}"
].join( "\n" ));
].join( "\n" ) );
var getFaceFromDirection = new FunctionNode( [
"int getFaceFromDirection(vec3 direction) {",
......@@ -162,7 +162,7 @@ TextureCubeUVNode.Nodes = (function() {
textureCubeUV: textureCubeUV
};
})();
} )();
TextureCubeUVNode.prototype = Object.create( TempNode.prototype );
TextureCubeUVNode.prototype.constructor = TextureCubeUVNode;
......
......@@ -2,9 +2,7 @@
* @author sunag / http://www.sunag.com.br/
*/
import { NodeUtils } from '../core/NodeUtils.js';
import { NodeMaterial } from '../materials/NodeMaterial.js';
import { RawNode } from '../materials/nodes/RawNode.js';
import { ScreenNode } from '../inputs/ScreenNode.js';
function NodePass() {
......@@ -18,32 +16,30 @@ function NodePass() {
this.textureID = 'renderTexture';
this.fragment = new RawNode( new ScreenNode() );
this.input = new ScreenNode();
this.node = new NodeMaterial();
this.node.fragment = this.fragment;
this.material = new NodeMaterial();
this.needsUpdate = true;
};
}
NodePass.prototype = Object.create( THREE.ShaderPass.prototype );
NodePass.prototype.constructor = NodePass;
NodeUtils.addShortcuts( NodePass.prototype, 'fragment', [ 'value' ] );
NodePass.prototype.render = function () {
if ( this.needsUpdate ) {
this.node.dispose();
this.material.dispose();
this.material.fragment.value = this.input;
this.needsUpdate = false;
}
this.uniforms = this.node.uniforms;
this.material = this.node;
this.uniforms = this.material.uniforms;
THREE.ShaderPass.prototype.render.apply( this, arguments );
......@@ -51,7 +47,7 @@ NodePass.prototype.render = function () {
NodePass.prototype.copy = function ( source ) {
this.value = source.value;
this.input = source.input;
};
......@@ -82,7 +78,7 @@ NodePass.prototype.toJSON = function ( meta ) {
if ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData;
data.value = this.value.toJSON( meta ).uuid;
data.input = this.input.toJSON( meta ).uuid;
}
......
/**
* @author sunag / http://www.sunag.com.br/
*/
import { NodeMaterial } from '../materials/NodeMaterial.js';
import { ScreenNode } from '../inputs/ScreenNode.js';
function NodePostProcessing( renderer, renderTarget ) {
if ( renderTarget === undefined ) {
var parameters = {
minFilter: THREE.LinearFilter,
magFilter: THREE.LinearFilter,
format: THREE.RGBAFormat,
stencilBuffer: false
};
var size = renderer.getDrawingBufferSize();
renderTarget = new THREE.WebGLRenderTarget( size.width, size.height, parameters );
}
this.renderer = renderer;
this.renderTarget = renderTarget;
this.output = new ScreenNode();
this.material = new 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 );
this.needsUpdate = true;
}
NodePostProcessing.prototype = {
constructor: NodePostProcessing,
render: function ( scene, camera, frame ) {
if ( this.needsUpdate ) {
this.material.dispose();
this.material.fragment.value = this.output;
this.material.build();
if ( this.material.uniforms.renderTexture ) {
this.material.uniforms.renderTexture.value = this.renderTarget.texture;
}
this.needsUpdate = false;
}
frame.setRenderer( this.renderer )
.setRenderTexture( this.renderTarget.texture );
this.renderer.render( scene, camera, this.renderTarget );
frame.updateNode( this.material );
this.renderer.render( this.scene, this.camera );
},
setSize: function ( width, height ) {
this.renderTarget.setSize( width, height );
this.renderer.setSize( width, height );
},
copy: function ( source ) {
this.output = source.output;
},
toJSON: function ( meta ) {
var isRootObject = ( meta === undefined || typeof meta === 'string' );
if ( isRootObject ) {
meta = {
nodes: {}
};
}
if ( meta && ! meta.post ) meta.post = {};
if ( ! meta.post[ this.uuid ] ) {
var data = {};
data.uuid = this.uuid;
data.type = "NodePostProcessing";
meta.post[ this.uuid ] = data;
if ( this.name !== "" ) data.name = this.name;
if ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData;
data.output = this.output.toJSON( meta ).uuid;
}
meta.post = this.uuid;
return meta;
}
};
export { NodePostProcessing };
/**
* @author sunag / http://www.sunag.com.br/
*/
import { TempNode } from '../core/TempNode.js';
import { FunctionNode } from '../core/FunctionNode.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 };
......@@ -12,13 +12,13 @@ function NoiseNode( uv ) {
this.uv = uv || new UVNode();
};
}
NoiseNode.prototype = Object.create( TempNode.prototype );
NoiseNode.prototype.constructor = NoiseNode;
NoiseNode.prototype.nodeType = "Noise";
NoiseNode.Nodes = (function() {
NoiseNode.Nodes = ( function () {
var snoise = new FunctionNode( [
"float snoise(vec2 co) {",
......@@ -32,7 +32,7 @@ NoiseNode.Nodes = (function() {
snoise: snoise
};
})();
} )();
NoiseNode.prototype.generate = function ( builder, output ) {
......
......@@ -2,18 +2,18 @@
* @author sunag / http://www.sunag.com.br/
*/
import { GLNode } from '../core/GLNode.js';
import { Node } from '../core/Node.js';
function BypassNode( code, value ) {
GLNode.call( this );
Node.call( this );
this.code = code;
this.value = value;
};
}
BypassNode.prototype = Object.create( GLNode.prototype );
BypassNode.prototype = Object.create( Node.prototype );
BypassNode.prototype.constructor = BypassNode;
BypassNode.prototype.nodeType = "Bypass";
......@@ -23,7 +23,7 @@ BypassNode.prototype.getType = function ( builder ) {
return this.value.getType( builder );
} else if (builder.isShader( 'fragment' )) {
} else if ( builder.isShader( 'fragment' ) ) {
return 'f';
......@@ -41,7 +41,7 @@ BypassNode.prototype.generate = function ( builder, output ) {
if ( builder.isShader( 'vertex' ) ) {
if (this.value) {
if ( this.value ) {
return this.value.build( builder, output );
......@@ -57,7 +57,7 @@ BypassNode.prototype.generate = function ( builder, output ) {
BypassNode.prototype.copy = function ( source ) {
GLNode.prototype.copy.call( this, source );
Node.prototype.copy.call( this, source );
this.code = source.code;
this.value = source.value;
......@@ -74,7 +74,7 @@ BypassNode.prototype.toJSON = function ( meta ) {
data.code = this.code.toJSON( meta ).uuid;
if (this.value) data.value = this.value.toJSON( meta ).uuid;
if ( this.value ) data.value = this.value.toJSON( meta ).uuid;
}
......
/**
* @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 };
......@@ -16,7 +16,7 @@ function JoinNode( x, y, z, w ) {
this.z = z;
this.w = w;
};
}
JoinNode.prototype = Object.create( TempNode.prototype );
JoinNode.prototype.constructor = JoinNode;
......
......@@ -12,7 +12,7 @@ function MaxMIPLevelNode( texture ) {
this.maxMIPLevel = 0;
};
}
MaxMIPLevelNode.prototype = Object.create( FloatNode.prototype );
MaxMIPLevelNode.prototype.constructor = MaxMIPLevelNode;
......@@ -26,9 +26,9 @@ Object.defineProperties( MaxMIPLevelNode.prototype, {
if ( this.maxMIPLevel === 0 ) {
var image = this.texture.value.image ? this.texture.value.image[0] : undefined;
var image = this.texture.value.image ? this.texture.value.image[ 0 ] : undefined;
this.maxMIPLevel = image !== undefined ? ( Math.log( Math.max( image.width, image.height ) ) + 1 ) * Math.LOG2E : 0;
this.maxMIPLevel = image !== undefined ? Math.log( Math.max( image.width, image.height ) ) * Math.LOG2E : 0;
}
......
......@@ -2,18 +2,18 @@
* @author sunag / http://www.sunag.com.br/
*/
import { GLNode } from '../core/GLNode.js';
import { Node } from '../core/Node.js';
function SwitchNode( node, components ) {
GLNode.call( this );
Node.call( this );
this.node = node;
this.components = components || 'x';
};
}
SwitchNode.prototype = Object.create( GLNode.prototype );
SwitchNode.prototype = Object.create( Node.prototype );
SwitchNode.prototype.constructor = SwitchNode;
SwitchNode.prototype.nodeType = "Switch";
......@@ -75,7 +75,7 @@ SwitchNode.prototype.generate = function ( builder, output ) {
SwitchNode.prototype.copy = function ( source ) {
GLNode.prototype.copy.call( this, source );
Node.prototype.copy.call( this, source );
this.node = source.node;
this.components = source.components;
......
......@@ -5,16 +5,16 @@
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;
};
}
TimerNode.GLOBAL = 'global';
TimerNode.LOCAL = 'local';
......@@ -26,6 +26,8 @@ TimerNode.prototype.nodeType = "Timer";
TimerNode.prototype.isReadonly = function () {
// never use TimerNode as readonly but aways as "uniform"
return false;
};
......@@ -33,6 +35,7 @@ TimerNode.prototype.isReadonly = function () {
TimerNode.prototype.isUnique = function () {
// share TimerNode "uniform" input if is used on more time with others TimerNode
return this.timeScale && ( this.scope === TimerNode.GLOBAL || this.scope === TimerNode.DELTA );
};
......@@ -41,7 +44,7 @@ TimerNode.prototype.updateFrame = function ( frame ) {
var scale = this.timeScale ? this.scale : 1;
switch( this.scope ) {
switch ( this.scope ) {
case TimerNode.LOCAL:
......@@ -70,7 +73,7 @@ TimerNode.prototype.copy = function ( source ) {
this.scope = source.scope;
this.scale = source.scale;
this.useTimeScale = source.useTimeScale;
this.timeScale = source.timeScale;
};
......@@ -85,7 +88,7 @@ TimerNode.prototype.toJSON = function ( meta ) {
data.scope = this.scope;
data.scale = this.scale;
data.useTimeScale = this.useTimeScale;
data.timeScale = this.timeScale;
}
......
......@@ -2,29 +2,29 @@
* @author sunag / http://www.sunag.com.br/
*/
import { FunctionNode } from '../core/FunctionNode.js';
import { ExpressionNode } from '../core/ExpressionNode.js';
import { Matrix3Node } from '../inputs/Matrix3Node.js';
import { UVNode } from '../accessors/UVNode.js';
function UVTransformNode( uv, transform ) {
function UVTransformNode( uv, position ) {
FunctionNode.call( this, "( uvTransform * vec3( uvNode, 1 ) ).xy", "vec2" );
ExpressionNode.call( this, "( uvTransform * vec3( uvNode, 1 ) ).xy", "vec2" );
this.uv = uv || new UVNode();
this.transform = transform || new Matrix3Node();
this.position = position || new Matrix3Node();
};
}
UVTransformNode.prototype = Object.create( FunctionNode.prototype );
UVTransformNode.prototype = Object.create( ExpressionNode.prototype );
UVTransformNode.prototype.constructor = UVTransformNode;
UVTransformNode.prototype.nodeType = "UVTransform";
UVTransformNode.prototype.generate = function ( builder, output ) {
this.keywords[ "uvNode" ] = this.uv;
this.keywords[ "uvTransform" ] = this.transform;
this.keywords[ "uvTransform" ] = this.position;
return FunctionNode.prototype.generate.call( this, builder, output );
return ExpressionNode.prototype.generate.call( this, builder, output );
};
......@@ -33,16 +33,16 @@ UVTransformNode.prototype.setUvTransform = function ( tx, ty, sx, sy, rotation,
cx = cx !== undefined ? cx : .5;
cy = cy !== undefined ? cy : .5;
this.transform.value.setUvTransform( tx, ty, sx, sy, rotation, cx, cy );
this.position.value.setUvTransform( tx, ty, sx, sy, rotation, cx, cy );
};
UVTransformNode.prototype.copy = function ( source ) {
FunctionNode.prototype.copy.call( this, source );
ExpressionNode.prototype.copy.call( this, source );
this.uv = source.uv;
this.transform = source.transform;
this.position = source.position;
};
......@@ -55,7 +55,7 @@ UVTransformNode.prototype.toJSON = function ( meta ) {
data = this.createJSONNode( meta );
data.uv = this.uv.toJSON( meta ).uuid;
data.transform = this.transform.toJSON( meta ).uuid;
data.position = this.position.toJSON( meta ).uuid;
}
......
......@@ -15,7 +15,7 @@ function VelocityNode( target, params ) {
this.setTarget( target );
this.setParams( params );
};
}
VelocityNode.prototype = Object.create( Vector3Node.prototype );
VelocityNode.prototype.constructor = VelocityNode;
......
{"nodes":{"A9543A4D-4036-4AB3-AEF1-0AE10CFDD4A6":{"uuid":"A9543A4D-4036-4AB3-AEF1-0AE10CFDD4A6","nodeType":"Phong","transform":"A298C150-1E98-425D-8552-CF4690C3238E","color":"DCD2B815-345D-4600-BAFD-BE26925C60E6","specular":"DCD2B815-345D-4600-BAFD-BE26925C60E6","shininess":"5E1EEAA6-F057-4D5F-8607-E9F8265D2B0A","emissive":"BF320EA1-F523-4314-9B87-07E33F39CC6C"},"A298C150-1E98-425D-8552-CF4690C3238E":{"uuid":"A298C150-1E98-425D-8552-CF4690C3238E","nodeType":"Operator","a":"6449FE7E-56E7-490E-9CA9-9F5E9A540AFD","b":"09ECA9C2-8B78-422B-B3DA-2194BCBC5FCA","op":"+"},"6449FE7E-56E7-490E-9CA9-9F5E9A540AFD":{"uuid":"6449FE7E-56E7-490E-9CA9-9F5E9A540AFD","nodeType":"Position","scope":"local"},"09ECA9C2-8B78-422B-B3DA-2194BCBC5FCA":{"uuid":"09ECA9C2-8B78-422B-B3DA-2194BCBC5FCA","nodeType":"Operator","a":"C4573235-0C78-460A-BB35-E41470304BD5","b":"1FF6B149-BCA7-4F37-91E9-8AFA8770F084","op":"*"},"C4573235-0C78-460A-BB35-E41470304BD5":{"uuid":"C4573235-0C78-460A-BB35-E41470304BD5","nodeType":"Operator","a":"0E355E3B-23AB-4225-9477-312295B18436","b":"ABD03824-B7F8-46A4-9006-03FBA06618A9","op":"*"},"0E355E3B-23AB-4225-9477-312295B18436":{"uuid":"0E355E3B-23AB-4225-9477-312295B18436","nodeType":"Normal","scope":"local"},"ABD03824-B7F8-46A4-9006-03FBA06618A9":{"uuid":"ABD03824-B7F8-46A4-9006-03FBA06618A9","nodeType":"Switch","node":"43D31AB8-1DD6-46BE-8969-0668FAB513E2","components":"w"},"43D31AB8-1DD6-46BE-8969-0668FAB513E2":{"uuid":"43D31AB8-1DD6-46BE-8969-0668FAB513E2","nodeType":"Texture","value":"cloud","uv":"273D729E-E18D-47AE-8299-F069FDB6C43A","project":false},"273D729E-E18D-47AE-8299-F069FDB6C43A":{"uuid":"273D729E-E18D-47AE-8299-F069FDB6C43A","nodeType":"Operator","a":"C46D2A54-57A8-4649-AF9B-09D011AF3BFD","b":"C43B8DA9-AFF5-4690-B2EA-3EED061C0662","op":"+"},"C46D2A54-57A8-4649-AF9B-09D011AF3BFD":{"uuid":"C46D2A54-57A8-4649-AF9B-09D011AF3BFD","nodeType":"Operator","a":"F81EC887-A160-455B-B1DE-A0FA2B7FAC36","b":"801913CD-EC7A-47BE-A54C-3D86020B0847","op":"*"},"F81EC887-A160-455B-B1DE-A0FA2B7FAC36":{"uuid":"F81EC887-A160-455B-B1DE-A0FA2B7FAC36","nodeType":"Timer","name":"time","scope":"global","scale":1,"useTimeScale":false},"801913CD-EC7A-47BE-A54C-3D86020B0847":{"uuid":"801913CD-EC7A-47BE-A54C-3D86020B0847","nodeType":"Float","name":"speed","value":0.2},"C43B8DA9-AFF5-4690-B2EA-3EED061C0662":{"uuid":"C43B8DA9-AFF5-4690-B2EA-3EED061C0662","nodeType":"UV","index":0},"1FF6B149-BCA7-4F37-91E9-8AFA8770F084":{"uuid":"1FF6B149-BCA7-4F37-91E9-8AFA8770F084","nodeType":"Float","value":2},"DCD2B815-345D-4600-BAFD-BE26925C60E6":{"uuid":"DCD2B815-345D-4600-BAFD-BE26925C60E6","nodeType":"Color","r":0,"g":0,"b":0},"5E1EEAA6-F057-4D5F-8607-E9F8265D2B0A":{"uuid":"5E1EEAA6-F057-4D5F-8607-E9F8265D2B0A","nodeType":"Float","value":30},"BF320EA1-F523-4314-9B87-07E33F39CC6C":{"uuid":"BF320EA1-F523-4314-9B87-07E33F39CC6C","nodeType":"Math3","a":"F9EA5DC0-2BC8-4C38-A480-1DA3D0680AAE","b":"65010573-EE24-42A3-B32C-3945F3CF2E93","c":"ABD03824-B7F8-46A4-9006-03FBA06618A9","method":"mix"},"F9EA5DC0-2BC8-4C38-A480-1DA3D0680AAE":{"uuid":"F9EA5DC0-2BC8-4C38-A480-1DA3D0680AAE","nodeType":"Color","r":0,"g":0.32941176470588235,"b":0.8745098039215686},"65010573-EE24-42A3-B32C-3945F3CF2E93":{"uuid":"65010573-EE24-42A3-B32C-3945F3CF2E93","nodeType":"Color","r":1,"g":1,"b":1}},"materials":{"BCB86F69-822F-4F9C-838B-70F657904D05":{"uuid":"BCB86F69-822F-4F9C-838B-70F657904D05","type":"PhongNodeMaterial","fog":false,"lights":true,"vertex":"A9543A4D-4036-4AB3-AEF1-0AE10CFDD4A6","fragment":"A9543A4D-4036-4AB3-AEF1-0AE10CFDD4A6"}},"material":"BCB86F69-822F-4F9C-838B-70F657904D05"}
\ No newline at end of file
{"nodes":{"A9543A4D-4036-4AB3-AEF1-0AE10CFDD4A6":{"uuid":"A9543A4D-4036-4AB3-AEF1-0AE10CFDD4A6","nodeType":"Phong","position":"A298C150-1E98-425D-8552-CF4690C3238E","color":"DCD2B815-345D-4600-BAFD-BE26925C60E6","specular":"DCD2B815-345D-4600-BAFD-BE26925C60E6","shininess":"5E1EEAA6-F057-4D5F-8607-E9F8265D2B0A","emissive":"BF320EA1-F523-4314-9B87-07E33F39CC6C"},"A298C150-1E98-425D-8552-CF4690C3238E":{"uuid":"A298C150-1E98-425D-8552-CF4690C3238E","nodeType":"Operator","a":"6449FE7E-56E7-490E-9CA9-9F5E9A540AFD","b":"09ECA9C2-8B78-422B-B3DA-2194BCBC5FCA","op":"+"},"6449FE7E-56E7-490E-9CA9-9F5E9A540AFD":{"uuid":"6449FE7E-56E7-490E-9CA9-9F5E9A540AFD","nodeType":"Position","scope":"local"},"09ECA9C2-8B78-422B-B3DA-2194BCBC5FCA":{"uuid":"09ECA9C2-8B78-422B-B3DA-2194BCBC5FCA","nodeType":"Operator","a":"C4573235-0C78-460A-BB35-E41470304BD5","b":"1FF6B149-BCA7-4F37-91E9-8AFA8770F084","op":"*"},"C4573235-0C78-460A-BB35-E41470304BD5":{"uuid":"C4573235-0C78-460A-BB35-E41470304BD5","nodeType":"Operator","a":"0E355E3B-23AB-4225-9477-312295B18436","b":"ABD03824-B7F8-46A4-9006-03FBA06618A9","op":"*"},"0E355E3B-23AB-4225-9477-312295B18436":{"uuid":"0E355E3B-23AB-4225-9477-312295B18436","nodeType":"Normal","scope":"local"},"ABD03824-B7F8-46A4-9006-03FBA06618A9":{"uuid":"ABD03824-B7F8-46A4-9006-03FBA06618A9","nodeType":"Switch","node":"43D31AB8-1DD6-46BE-8969-0668FAB513E2","components":"w"},"43D31AB8-1DD6-46BE-8969-0668FAB513E2":{"uuid":"43D31AB8-1DD6-46BE-8969-0668FAB513E2","nodeType":"Texture","value":"cloud","uv":"273D729E-E18D-47AE-8299-F069FDB6C43A","project":false},"273D729E-E18D-47AE-8299-F069FDB6C43A":{"uuid":"273D729E-E18D-47AE-8299-F069FDB6C43A","nodeType":"Operator","a":"C46D2A54-57A8-4649-AF9B-09D011AF3BFD","b":"C43B8DA9-AFF5-4690-B2EA-3EED061C0662","op":"+"},"C46D2A54-57A8-4649-AF9B-09D011AF3BFD":{"uuid":"C46D2A54-57A8-4649-AF9B-09D011AF3BFD","nodeType":"Operator","a":"F81EC887-A160-455B-B1DE-A0FA2B7FAC36","b":"801913CD-EC7A-47BE-A54C-3D86020B0847","op":"*"},"F81EC887-A160-455B-B1DE-A0FA2B7FAC36":{"uuid":"F81EC887-A160-455B-B1DE-A0FA2B7FAC36","nodeType":"Timer","name":"time","scope":"global","scale":1,"useTimeScale":false},"801913CD-EC7A-47BE-A54C-3D86020B0847":{"uuid":"801913CD-EC7A-47BE-A54C-3D86020B0847","nodeType":"Float","name":"speed","value":0.2},"C43B8DA9-AFF5-4690-B2EA-3EED061C0662":{"uuid":"C43B8DA9-AFF5-4690-B2EA-3EED061C0662","nodeType":"UV","index":0},"1FF6B149-BCA7-4F37-91E9-8AFA8770F084":{"uuid":"1FF6B149-BCA7-4F37-91E9-8AFA8770F084","nodeType":"Float","value":2},"DCD2B815-345D-4600-BAFD-BE26925C60E6":{"uuid":"DCD2B815-345D-4600-BAFD-BE26925C60E6","nodeType":"Color","r":0,"g":0,"b":0},"5E1EEAA6-F057-4D5F-8607-E9F8265D2B0A":{"uuid":"5E1EEAA6-F057-4D5F-8607-E9F8265D2B0A","nodeType":"Float","value":30},"BF320EA1-F523-4314-9B87-07E33F39CC6C":{"uuid":"BF320EA1-F523-4314-9B87-07E33F39CC6C","nodeType":"Math3","a":"F9EA5DC0-2BC8-4C38-A480-1DA3D0680AAE","b":"65010573-EE24-42A3-B32C-3945F3CF2E93","c":"ABD03824-B7F8-46A4-9006-03FBA06618A9","method":"mix"},"F9EA5DC0-2BC8-4C38-A480-1DA3D0680AAE":{"uuid":"F9EA5DC0-2BC8-4C38-A480-1DA3D0680AAE","nodeType":"Color","r":0,"g":0.32941176470588235,"b":0.8745098039215686},"65010573-EE24-42A3-B32C-3945F3CF2E93":{"uuid":"65010573-EE24-42A3-B32C-3945F3CF2E93","nodeType":"Color","r":1,"g":1,"b":1}},"materials":{"BCB86F69-822F-4F9C-838B-70F657904D05":{"uuid":"BCB86F69-822F-4F9C-838B-70F657904D05","type":"PhongNodeMaterial","fog":false,"lights":true,"vertex":"A9543A4D-4036-4AB3-AEF1-0AE10CFDD4A6","fragment":"A9543A4D-4036-4AB3-AEF1-0AE10CFDD4A6"}},"material":"BCB86F69-822F-4F9C-838B-70F657904D05"}
\ No newline at end of file
{"nodes":{"6BB91CE5-93BA-41BF-88C6-8D03721D4790":{"uuid":"6BB91CE5-93BA-41BF-88C6-8D03721D4790","nodeType":"Phong","transform":"39ED31F8-337B-49A4-9DBE-B43B1F5D180B","color":"1628C697-A4FC-4F02-9746-1CFAC6C6E85B","specular":"D730CA9D-A641-4289-BEF8-348CDD7218B6","shininess":"73E26FEC-C8C2-4E9E-8A4A-209A88156348"},"39ED31F8-337B-49A4-9DBE-B43B1F5D180B":{"uuid":"39ED31F8-337B-49A4-9DBE-B43B1F5D180B","nodeType":"Operator","a":"28F9F474-E77F-4373-BA46-D39F8588A56B","b":"B792813E-FC18-4440-8256-E4030E9D7E3A","op":"+"},"28F9F474-E77F-4373-BA46-D39F8588A56B":{"uuid":"28F9F474-E77F-4373-BA46-D39F8588A56B","nodeType":"Position","scope":"local"},"B792813E-FC18-4440-8256-E4030E9D7E3A":{"uuid":"B792813E-FC18-4440-8256-E4030E9D7E3A","nodeType":"Join","inputs":{"x":"F84376EF-6595-4A0F-AE1C-C183AE4D6392","y":"B7A4178E-D407-4444-9633-741A8C2DAD09","z":"F5785794-4DB6-47F6-AAB6-78DFC896B782"}},"F84376EF-6595-4A0F-AE1C-C183AE4D6392":{"uuid":"F84376EF-6595-4A0F-AE1C-C183AE4D6392","nodeType":"Float","value":0},"B7A4178E-D407-4444-9633-741A8C2DAD09":{"uuid":"B7A4178E-D407-4444-9633-741A8C2DAD09","nodeType":"Operator","a":"526B9B70-CBA1-47E4-9CEF-0CE5A9C4F041","b":"0A80D285-164D-4857-B8B9-30CE5CEC6931","op":"*"},"526B9B70-CBA1-47E4-9CEF-0CE5A9C4F041":{"uuid":"526B9B70-CBA1-47E4-9CEF-0CE5A9C4F041","nodeType":"Switch","node":"575F9E64-5B6D-4A95-9522-3A27919165BF","components":"x"},"575F9E64-5B6D-4A95-9522-3A27919165BF":{"uuid":"575F9E64-5B6D-4A95-9522-3A27919165BF","nodeType":"Math1","a":"4EF09677-828F-4164-BE18-2E8E87A3E969","method":"sin"},"4EF09677-828F-4164-BE18-2E8E87A3E969":{"uuid":"4EF09677-828F-4164-BE18-2E8E87A3E969","nodeType":"Operator","a":"DA817C54-9793-4850-9B90-A087050C6335","b":"CE06CC57-FAFF-4EF7-A0E3-1D71ED0A4EFD","op":"+"},"DA817C54-9793-4850-9B90-A087050C6335":{"uuid":"DA817C54-9793-4850-9B90-A087050C6335","nodeType":"Operator","a":"87304A41-2F18-4A98-92F1-9869F01786D3","b":"ECE889D2-A244-49EF-9ECF-BB685CD84828","op":"*"},"87304A41-2F18-4A98-92F1-9869F01786D3":{"uuid":"87304A41-2F18-4A98-92F1-9869F01786D3","nodeType":"Position","scope":"local"},"ECE889D2-A244-49EF-9ECF-BB685CD84828":{"uuid":"ECE889D2-A244-49EF-9ECF-BB685CD84828","nodeType":"Float","value":0.4},"CE06CC57-FAFF-4EF7-A0E3-1D71ED0A4EFD":{"uuid":"CE06CC57-FAFF-4EF7-A0E3-1D71ED0A4EFD","nodeType":"Operator","a":"D035D8DE-7C30-4372-A5E5-9A03169CFA96","b":"2090FF81-9723-4F1F-BF10-2F223F879DA5","op":"*"},"D035D8DE-7C30-4372-A5E5-9A03169CFA96":{"uuid":"D035D8DE-7C30-4372-A5E5-9A03169CFA96","nodeType":"Timer","name":"time","scope":"global","scale":1,"useTimeScale":false},"2090FF81-9723-4F1F-BF10-2F223F879DA5":{"uuid":"2090FF81-9723-4F1F-BF10-2F223F879DA5","nodeType":"Float","name":"speed","value":5},"0A80D285-164D-4857-B8B9-30CE5CEC6931":{"uuid":"0A80D285-164D-4857-B8B9-30CE5CEC6931","nodeType":"Float","value":1},"F5785794-4DB6-47F6-AAB6-78DFC896B782":{"uuid":"F5785794-4DB6-47F6-AAB6-78DFC896B782","nodeType":"Float","value":0},"1628C697-A4FC-4F02-9746-1CFAC6C6E85B":{"uuid":"1628C697-A4FC-4F02-9746-1CFAC6C6E85B","nodeType":"Math3","a":"48DEB7D7-83ED-4679-BB0B-45A11052AA5F","b":"8C0EACD5-DEA2-431B-B083-06FB93DB7D2A","c":"526B9B70-CBA1-47E4-9CEF-0CE5A9C4F041","method":"mix"},"48DEB7D7-83ED-4679-BB0B-45A11052AA5F":{"uuid":"48DEB7D7-83ED-4679-BB0B-45A11052AA5F","nodeType":"Color","r":0,"g":0.32941176470588235,"b":0.8745098039215686},"8C0EACD5-DEA2-431B-B083-06FB93DB7D2A":{"uuid":"8C0EACD5-DEA2-431B-B083-06FB93DB7D2A","nodeType":"Color","r":1,"g":1,"b":1},"D730CA9D-A641-4289-BEF8-348CDD7218B6":{"uuid":"D730CA9D-A641-4289-BEF8-348CDD7218B6","nodeType":"Color","r":0.06666666666666667,"g":0.06666666666666667,"b":0.06666666666666667},"73E26FEC-C8C2-4E9E-8A4A-209A88156348":{"uuid":"73E26FEC-C8C2-4E9E-8A4A-209A88156348","nodeType":"Float","value":30}},"materials":{"7DCC94F3-82FE-4A67-B5DB-8ACE85789BAA":{"uuid":"7DCC94F3-82FE-4A67-B5DB-8ACE85789BAA","type":"PhongNodeMaterial","fog":false,"lights":true,"vertex":"6BB91CE5-93BA-41BF-88C6-8D03721D4790","fragment":"6BB91CE5-93BA-41BF-88C6-8D03721D4790"}},"material":"7DCC94F3-82FE-4A67-B5DB-8ACE85789BAA"}
\ No newline at end of file
{"nodes":{"6BB91CE5-93BA-41BF-88C6-8D03721D4790":{"uuid":"6BB91CE5-93BA-41BF-88C6-8D03721D4790","nodeType":"Phong","position":"39ED31F8-337B-49A4-9DBE-B43B1F5D180B","color":"1628C697-A4FC-4F02-9746-1CFAC6C6E85B","specular":"D730CA9D-A641-4289-BEF8-348CDD7218B6","shininess":"73E26FEC-C8C2-4E9E-8A4A-209A88156348"},"39ED31F8-337B-49A4-9DBE-B43B1F5D180B":{"uuid":"39ED31F8-337B-49A4-9DBE-B43B1F5D180B","nodeType":"Operator","a":"28F9F474-E77F-4373-BA46-D39F8588A56B","b":"B792813E-FC18-4440-8256-E4030E9D7E3A","op":"+"},"28F9F474-E77F-4373-BA46-D39F8588A56B":{"uuid":"28F9F474-E77F-4373-BA46-D39F8588A56B","nodeType":"Position","scope":"local"},"B792813E-FC18-4440-8256-E4030E9D7E3A":{"uuid":"B792813E-FC18-4440-8256-E4030E9D7E3A","nodeType":"Join","inputs":{"x":"F84376EF-6595-4A0F-AE1C-C183AE4D6392","y":"B7A4178E-D407-4444-9633-741A8C2DAD09","z":"F5785794-4DB6-47F6-AAB6-78DFC896B782"}},"F84376EF-6595-4A0F-AE1C-C183AE4D6392":{"uuid":"F84376EF-6595-4A0F-AE1C-C183AE4D6392","nodeType":"Float","value":0},"B7A4178E-D407-4444-9633-741A8C2DAD09":{"uuid":"B7A4178E-D407-4444-9633-741A8C2DAD09","nodeType":"Operator","a":"526B9B70-CBA1-47E4-9CEF-0CE5A9C4F041","b":"0A80D285-164D-4857-B8B9-30CE5CEC6931","op":"*"},"526B9B70-CBA1-47E4-9CEF-0CE5A9C4F041":{"uuid":"526B9B70-CBA1-47E4-9CEF-0CE5A9C4F041","nodeType":"Switch","node":"575F9E64-5B6D-4A95-9522-3A27919165BF","components":"x"},"575F9E64-5B6D-4A95-9522-3A27919165BF":{"uuid":"575F9E64-5B6D-4A95-9522-3A27919165BF","nodeType":"Math1","a":"4EF09677-828F-4164-BE18-2E8E87A3E969","method":"sin"},"4EF09677-828F-4164-BE18-2E8E87A3E969":{"uuid":"4EF09677-828F-4164-BE18-2E8E87A3E969","nodeType":"Operator","a":"DA817C54-9793-4850-9B90-A087050C6335","b":"CE06CC57-FAFF-4EF7-A0E3-1D71ED0A4EFD","op":"+"},"DA817C54-9793-4850-9B90-A087050C6335":{"uuid":"DA817C54-9793-4850-9B90-A087050C6335","nodeType":"Operator","a":"87304A41-2F18-4A98-92F1-9869F01786D3","b":"ECE889D2-A244-49EF-9ECF-BB685CD84828","op":"*"},"87304A41-2F18-4A98-92F1-9869F01786D3":{"uuid":"87304A41-2F18-4A98-92F1-9869F01786D3","nodeType":"Position","scope":"local"},"ECE889D2-A244-49EF-9ECF-BB685CD84828":{"uuid":"ECE889D2-A244-49EF-9ECF-BB685CD84828","nodeType":"Float","value":0.4},"CE06CC57-FAFF-4EF7-A0E3-1D71ED0A4EFD":{"uuid":"CE06CC57-FAFF-4EF7-A0E3-1D71ED0A4EFD","nodeType":"Operator","a":"D035D8DE-7C30-4372-A5E5-9A03169CFA96","b":"2090FF81-9723-4F1F-BF10-2F223F879DA5","op":"*"},"D035D8DE-7C30-4372-A5E5-9A03169CFA96":{"uuid":"D035D8DE-7C30-4372-A5E5-9A03169CFA96","nodeType":"Timer","name":"time","scope":"global","scale":1,"useTimeScale":false},"2090FF81-9723-4F1F-BF10-2F223F879DA5":{"uuid":"2090FF81-9723-4F1F-BF10-2F223F879DA5","nodeType":"Float","name":"speed","value":5},"0A80D285-164D-4857-B8B9-30CE5CEC6931":{"uuid":"0A80D285-164D-4857-B8B9-30CE5CEC6931","nodeType":"Float","value":1},"F5785794-4DB6-47F6-AAB6-78DFC896B782":{"uuid":"F5785794-4DB6-47F6-AAB6-78DFC896B782","nodeType":"Float","value":0},"1628C697-A4FC-4F02-9746-1CFAC6C6E85B":{"uuid":"1628C697-A4FC-4F02-9746-1CFAC6C6E85B","nodeType":"Math3","a":"48DEB7D7-83ED-4679-BB0B-45A11052AA5F","b":"8C0EACD5-DEA2-431B-B083-06FB93DB7D2A","c":"526B9B70-CBA1-47E4-9CEF-0CE5A9C4F041","method":"mix"},"48DEB7D7-83ED-4679-BB0B-45A11052AA5F":{"uuid":"48DEB7D7-83ED-4679-BB0B-45A11052AA5F","nodeType":"Color","r":0,"g":0.32941176470588235,"b":0.8745098039215686},"8C0EACD5-DEA2-431B-B083-06FB93DB7D2A":{"uuid":"8C0EACD5-DEA2-431B-B083-06FB93DB7D2A","nodeType":"Color","r":1,"g":1,"b":1},"D730CA9D-A641-4289-BEF8-348CDD7218B6":{"uuid":"D730CA9D-A641-4289-BEF8-348CDD7218B6","nodeType":"Color","r":0.06666666666666667,"g":0.06666666666666667,"b":0.06666666666666667},"73E26FEC-C8C2-4E9E-8A4A-209A88156348":{"uuid":"73E26FEC-C8C2-4E9E-8A4A-209A88156348","nodeType":"Float","value":30}},"materials":{"7DCC94F3-82FE-4A67-B5DB-8ACE85789BAA":{"uuid":"7DCC94F3-82FE-4A67-B5DB-8ACE85789BAA","type":"PhongNodeMaterial","fog":false,"lights":true,"vertex":"6BB91CE5-93BA-41BF-88C6-8D03721D4790","fragment":"6BB91CE5-93BA-41BF-88C6-8D03721D4790"}},"material":"7DCC94F3-82FE-4A67-B5DB-8ACE85789BAA"}
\ No newline at end of file
......@@ -207,10 +207,10 @@
mtl.emissive = cos;
var transformer = new THREE.FunctionNode( "position + 0.0 * " + Math.random(), "vec3", [ ]);
var transformer = new THREE.ExpressionNode( "position + 0.0 * " + Math.random(), "vec3", [ ]);
mtl.transform = transformer;
// build shader
// build shader ( ignore auto build )
mtl.build();
// set material
......
......@@ -53,7 +53,7 @@
var controls;
var move = false;
var rtTexture, rtMaterial;
var gui, guiElements = [];
var gui;
var library = {};
var serialized = false;
var textures = {
......@@ -61,11 +61,12 @@
grass: { url: 'textures/terrain/grasslight-big.jpg' },
grassNormal: { url: 'textures/terrain/grasslight-big-nm.jpg' },
decalDiffuse: { url: 'textures/decal/decal-diffuse.png' },
decalNormal: { url: 'textures/decal/decal-normal.jpg' },
cloud: { url: 'textures/lava/cloud.png' },
spherical: { url: 'textures/envmap.png' }
};
var param = { example: new URL(window.location.href).searchParams.get('e') || 'mesh-standard' };
var param = { example: new URL( window.location.href ).searchParams.get( 'e' ) || 'mesh-standard' };
function getTexture( name ) {
......@@ -185,9 +186,14 @@
'adv / soft-body': 'soft-body',
'adv / wave': 'wave',
'adv / triangle-blur': 'triangle-blur',
'adv / render-to-texture': 'rtt',
'adv / temporal-blur': 'temporal-blur',
'adv / conditional': 'conditional',
'adv / expression': 'expression',
'adv / sss': 'sss',
'adv / translucent': 'translucent',
'node / position': 'node-position',
'node / normal': 'node-normal',
'misc / smoke': 'smoke',
'misc / firefly': 'firefly',
'misc / reserved-keywords': 'reserved-keywords',
......@@ -221,7 +227,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 () {
......@@ -291,7 +297,7 @@
//mtl.light = // input/output light (vec3)
//mtl.environment = // reflection/refraction (vec3)
//mtl.environmentAlpha = // environment alpha (float)
//mtl.transform = // vertex transformation (vec3)
//mtl.position = // vertex local position (vec3)
var mask = new THREE.SwitchNode( new THREE.TextureNode( getTexture( "decalDiffuse" ) ), 'w' );
......@@ -322,7 +328,7 @@
//mtl.light = // custom-light (vec3)
//mtl.ao = // ambient occlusion (float)
//mtl.environment = // reflection/refraction (vec3)
//mtl.transform = // vertex transformation (vec3)
//mtl.position = // vertex local position (vec3)
var mask = new THREE.SwitchNode( new THREE.TextureNode( getTexture( "decalDiffuse" ) ), 'w' );
......@@ -405,22 +411,25 @@
// MATERIAL
var sataturation = new THREE.FloatNode( 1 );
var sataturation = new THREE.FloatNode( 1 ),
useNodeMaterial = true,
useMap = true,
useNormals = true;
function updateMaterial( useNodeMaterial ) {
function updateMaterial() {
var oldMaterial = mtl;
if (oldMaterial) oldMaterial.dispose();
if ( oldMaterial ) oldMaterial.dispose();
mtl = useNodeMaterial ? new THREE.MeshStandardNodeMaterial() : new THREE.MeshStandardMaterial();
// default syntax ( backward-compatible )
mtl.map = getTexture( "brick" );
mtl.map = useMap ? getTexture( "brick" ) : undefined;
mtl.normalMap = getTexture( "grassNormal" );
mtl.normalScale = new THREE.Vector2( .3, -.3 );
mtl.normalMap = useNormals ? getTexture( "decalNormal" ) : undefined;
mtl.normalScale = oldMaterial ? oldMaterial.normalScale : new THREE.Vector2( .5, .5 );
mtl.envMap = cubemap;
......@@ -429,7 +438,7 @@
// extended syntax ( only for NodeMaterial )
if (useNodeMaterial) {
if ( useNodeMaterial && useMap ) {
mtl.map = new THREE.ColorAdjustmentNode(
new THREE.TextureNode( mtl.map ),
......@@ -441,19 +450,22 @@
// apply material
mtl.side = THREE.DoubleSide;
mtl.needsUpdate = true;
mesh.material = mtl;
}
updateMaterial( true );
updateMaterial();
// GUI
addGui( 'use node material', true, function ( val ) {
addGui( 'use node material', useNodeMaterial, function ( val ) {
updateMaterial( val );
useNodeMaterial = val;
updateMaterial();
} );
......@@ -469,12 +481,40 @@
}, false, 0, 1 );
addGui( 'normalX', mtl.normalScale.x, function ( val ) {
mtl.normalScale.x = val;
}, false, - 1, 1 );
addGui( 'normalY', mtl.normalScale.y, function ( val ) {
mtl.normalScale.y = val;
}, false, - 1, 1 );
addGui( 'sat. (node)', sataturation.value, function ( val ) {
sataturation.value = val;
}, false, 0, 2 );
addGui( 'colors', useMap, function ( val ) {
useMap = val;
updateMaterial();
}, false );
addGui( 'normals', useNormals, function ( val ) {
useNormals = val;
updateMaterial();
}, false );
break;
case 'physical':
......@@ -497,7 +537,7 @@
//mtl.light = // custom-light (vec3)
//mtl.ao = // ambient occlusion (float)
//mtl.environment = // reflection/refraction (vec3)
//mtl.transform = // vertex transformation (vec3)
//mtl.position = // vertex local position (vec3)
var mask = new THREE.SwitchNode( new THREE.TextureNode( getTexture( "decalDiffuse" ) ), 'w' );
......@@ -671,7 +711,7 @@
);
mtl.color = color;
mtl.transform = blend;
mtl.position = blend;
// GUI
......@@ -726,7 +766,7 @@
var color = new THREE.ColorNode( 0xFFFFFF );
var viewZ = new THREE.Math2Node(
new THREE.NormalNode( THREE.NormalNode.VIEW ),
new THREE.NormalNode(),
new THREE.Vector3Node( 0, 0, - intensity ),
THREE.Math2Node.DOT
);
......@@ -1007,7 +1047,7 @@
var color = new THREE.CubeTextureNode( cubemap );
var viewZ = new THREE.Math2Node(
new THREE.NormalNode( THREE.NormalNode.VIEW ),
new THREE.NormalNode(),
new THREE.Vector3Node( 0, 0, - 1 ),
THREE.Math2Node.DOT
);
......@@ -1250,7 +1290,7 @@
mtl.color = mtl.specular = new THREE.ColorNode( 0 );
mtl.emissive = color;
mtl.transform = blend;
mtl.position = blend;
// GUI
......@@ -1605,7 +1645,7 @@
);
mtl.color = colors;
mtl.transform = softPosition;
mtl.position = softPosition;
// GUI
......@@ -1652,7 +1692,7 @@
var fur = new THREE.FloatNode( .5 );
var posDirection = new THREE.Math1Node( new THREE.PositionNode( THREE.PositionNode.VIEW ), THREE.Math1Node.NORMALIZE );
var norDirection = new THREE.Math1Node( new THREE.NormalNode( THREE.NormalNode.VIEW ), THREE.Math1Node.NORMALIZE );
var norDirection = new THREE.Math1Node( new THREE.NormalNode(), THREE.Math1Node.NORMALIZE );
var viewZ = new THREE.Math2Node(
posDirection,
......@@ -1836,7 +1876,7 @@
// LINE
var posDirection = new THREE.Math1Node( new THREE.PositionNode( THREE.PositionNode.VIEW ), THREE.Math1Node.NORMALIZE );
var norDirection = new THREE.Math1Node( new THREE.NormalNode( THREE.NormalNode.VIEW ), THREE.Math1Node.NORMALIZE );
var norDirection = new THREE.Math1Node( new THREE.NormalNode(), THREE.Math1Node.NORMALIZE );
var viewZ = new THREE.Math2Node(
posDirection,
......@@ -1867,7 +1907,7 @@
// APPLY
mtl.color = color;
mtl.light = new THREE.LightNode();
mtl.light = posCelLight;
mtl.shininess = new THREE.FloatNode( 0 );
mtl.environment = lineColor;
......@@ -1942,11 +1982,11 @@
var speed = new THREE.FloatNode( .5 );
mtl.color = new THREE.FunctionNode( "myCustomUv + (sin(time*speed)*.5) + (position * .05)", "vec3" );
mtl.color = new THREE.ExpressionNode( "myCustomUv + (sin(time*speed)*.5) + (position * .05)", "vec3" );
mtl.color.keywords[ "speed" ] = speed;
mtl.transform = new THREE.FunctionNode( "mod(time*speed,1.0) < 0.5 ? position + (worldNormal*(1.0+sin(time*speed*1.0))*3.0) : position + sin( position.x * sin(time*speed*2.0))", "vec3" );
mtl.transform.keywords[ "speed" ] = speed;
mtl.position = new THREE.ExpressionNode( "mod(time*speed,1.0) < 0.5 ? position + (worldNormal*(1.0+sin(time*speed*1.0))*3.0) : position + sin( position.x * sin(time*speed*2.0))", "vec3" );
mtl.position.keywords[ "speed" ] = speed;
// add global keyword ( variable or const )
THREE.NodeLib.addKeyword( 'myCustomUv', function ( builder ) {
......@@ -2001,6 +2041,56 @@
break;
case 'node-position':
// MATERIAL
var node = new THREE.PositionNode();
mtl = new THREE.PhongNodeMaterial();
mtl.color = node;
// GUI
addGui( 'scope', {
local: THREE.PositionNode.LOCAL,
world: THREE.PositionNode.WORLD,
view: THREE.PositionNode.VIEW
}, function ( val ) {
node.scope = val;
mtl.needsUpdate = true;
} );
break;
case 'node-normal':
// MATERIAL
var node = new THREE.NormalNode();
mtl = new THREE.PhongNodeMaterial();
mtl.color = node;
// GUI
addGui( 'scope', {
local: THREE.NormalNode.LOCAL,
world: THREE.NormalNode.WORLD,
view: THREE.NormalNode.VIEW
}, function ( val ) {
node.scope = val;
mtl.needsUpdate = true;
} );
break;
case 'varying':
// MATERIAL
......@@ -2010,16 +2100,16 @@
var varying = new THREE.VarNode( "vec3" );
varying.value = new THREE.NormalNode( THREE.NormalNode.VIEW );
// using BypassNode the NormalNode not apply the value in .transform slot
// using BypassNode the NormalNode not apply the value in .position slot
// but set the NormalNode value in VarNode
// it can be useful to send values between vertex to fragment shader
// without affect vertex shader
mtl.transform = new THREE.BypassNode( varying );
mtl.position = new THREE.BypassNode( varying );
mtl.color = varying;
// you can also set a independent value in .transform slot using BypassNode
// such this expression using FunctionNode
mtl.transform.value = new THREE.FunctionNode("position * ( .1 + abs( sin( time ) ) )", "vec3");
// you can also set a independent value in .position slot using BypassNode
// such this expression using ExpressionNode
mtl.position.value = new THREE.ExpressionNode( "position * ( .1 + abs( sin( time ) ) )", "vec3" );
break;
......@@ -2045,12 +2135,12 @@
// add keyword
setMyVar.keywords[ "myVar" ] = varying;
var transform = new THREE.FunctionNode( "setMyVar( position * .1 )", "vec3" );
transform.includes = [ setMyVar ];
transform.keywords[ "tex" ] = new THREE.TextureNode( getTexture( "brick" ) );
var position = new THREE.ExpressionNode( "setMyVar( position * .1 )", "vec3" );
position.includes = [ setMyVar ];
position.keywords[ "tex" ] = new THREE.TextureNode( getTexture( "brick" ) );
// use BypassNode to "void" functions
mtl.transform = new THREE.BypassNode( transform );
mtl.position = new THREE.BypassNode( position );
// FRAGMENT
......@@ -2070,6 +2160,150 @@
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 'temporal-blur':
// MATERIAL
mtl = new THREE.PhongNodeMaterial();
var texture = new THREE.TextureNode( getTexture( "brick" ) );
var rttStore = new THREE.RTTNode( 512, 512, texture );
var blur = new THREE.BlurNode( rttStore );
var timer = new THREE.TimerNode( .01, THREE.TimerNode.LOCAL );
var color = new THREE.Math3Node(
rttStore,
blur,
new THREE.FloatNode( .6 ),
THREE.Math3Node.MIX
);
blur.horizontal = blur.vertical = timer;
var rttSave = new THREE.RTTNode( 512, 512, color );
rttSave.saveTo = rttStore;
mtl.color = rttSave;
// GUI
addGui( 'click to reset', false, function ( val ) {
// render a single time
rttStore.render = true;
// reset time blur
timer.value = 0;
} );
break;
case 'readonly':
// MATERIAL
......@@ -2250,7 +2484,7 @@
mtl = new THREE.StandardNodeMaterial();
var backSideDepth = new THREE.TextureNode( rtTexture.texture, new THREE.ScreenUVNode( new THREE.ResolutionNode( renderer ) ) );
var backSideDepth = new THREE.TextureNode( rtTexture.texture, new THREE.ScreenUVNode() );
var difference = new THREE.OperatorNode(
objectDepth,
......@@ -2352,6 +2586,9 @@
}
// set material
mtl.side = THREE.DoubleSide;
mesh.material = mtl;
}
......@@ -2369,14 +2606,14 @@
}
document.getElementById( 'serialize' ).addEventListener('click', function () {
document.getElementById( 'serialize' ).addEventListener( 'click', function () {
if ( serialized ) reset();
else serialize();
serialized = ! serialized;
});
} );
function reset() {
......@@ -2446,7 +2683,7 @@
// update material animation and/or gpu calcs (pre-renderer)
frame.update( delta );
frame.update( delta ).setRenderer( renderer );
if ( mesh.material instanceof THREE.NodeMaterial ) {
......
......@@ -138,7 +138,7 @@
var blurMirror = new THREE.BlurNode( mirror );
blurMirror.size = new THREE.Vector2( WIDTH, HEIGHT );
blurMirror.uv = new THREE.FunctionNode( "projCoord.xyz / projCoord.q", "vec3" );
blurMirror.uv = new THREE.ExpressionNode( "projCoord.xyz / projCoord.q", "vec3" );
blurMirror.uv.keywords[ "projCoord" ] = new THREE.OperatorNode( mirror.offset, mirror.uv, THREE.OperatorNode.ADD );
blurMirror.radius.x = blurMirror.radius.y = 0;
......@@ -155,7 +155,7 @@
//groundMirrorMaterial.normalScale = new THREE.FloatNode( 1 );
// test serialization
/*
/*
var library = {};
library[ groundMirror.uuid ] = groundMirror;
library[ decalDiffuse.uuid ] = decalDiffuse;
......@@ -165,7 +165,7 @@
var json = groundMirrorMaterial.toJSON();
groundMirrorMaterial = new THREE.NodeMaterialLoader( null, library ).parse( json );
*/
*/
//--
var mirrorMesh = new THREE.Mesh( planeGeo, groundMirrorMaterial );
......@@ -279,7 +279,6 @@
fillScene();
update();
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - performance [nodes]</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
color: #fff;
font-family:Monospace;
font-size:13px;
margin: 0px;
text-align:center;
overflow: hidden;
}
#info {
color: #999;
position: absolute;
top: 10px;
width: 100%;
text-align: center;
display:block;
}
.white {
color: white;
}
b { color: #ccc; }
a { color: white }
</style>
</head>
<body>
<script src="../build/three.js"></script>
<script src="js/libs/stats.min.js"></script>
<div id="info">
<a href="http://threejs.org" target="_blank">three.js</a><span class="white"> - NodeMaterial Performance</span></br>
<br>
<b>Node Material System</b>
<br>
<div>
Standard<b>Node</b>Material |
<span id="node" class="white">None</span>
</div>
<div>
MeshStandard<b>Node</b>Material |
<span id="nodeBased" class="white">None</span>
</div>
<br>
<b>Current Material System</b>
<br>
<div>
MeshStandardMaterial |
<span id="default" class="white">None</span>
</div>
<br>
<a id="bench" href="javascript:void(0);">Click to benchmark</a>
</div>
<script type="module">
import './js/nodes/THREE.Nodes.js';
var container, stats;
var camera, scene, renderer;
var geometry;
var meshes = [];
var mouseX = 0, mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
init();
animate();
function createScene( MaterialClass, count ) {
count = count !== undefined ? count : 70;
var i = 0;
for ( i = 0; i < meshes.length; i ++ ) {
meshes[ i ].material.dispose();
scene.remove( meshes[ i ] );
}
meshes = [];
for ( i = 0; i < 70; i ++ ) {
var material = new MaterialClass(),
color = 0xFFFFFF * Math.random();
if ( material.color.isNode ) material.color.value.setHex( color );
else material.color.setHex( color );
// prevent share code
material.defines.UUID = material.uuid;
var mesh = new THREE.Mesh( geometry, material );
mesh.position.x = Math.random() * 1000 - 500;
mesh.position.y = Math.random() * 1000 - 500;
mesh.position.z = Math.random() * 1000 - 500;
mesh.rotation.x = Math.random() * 2 * Math.PI;
mesh.rotation.y = Math.random() * 2 * Math.PI;
mesh.scale.x = mesh.scale.y = mesh.scale.z = Math.random() * 50 + 100;
mesh.matrixAutoUpdate = false;
mesh.updateMatrix();
scene.add( mesh );
meshes.push( mesh );
}
}
function benchmark() {
var time, benchmarkTime;
// Stabilizes CPU
createScene( THREE.MeshStandardMaterial, 10 );
render();
// Standard *Node* Material
time = performance.now();
createScene( THREE.StandardNodeMaterial );
render();
benchmarkTime = ( performance.now() - time ) / 1000;
document.getElementById( 'node' ).textContent = benchmarkTime.toFixed( 3 ) + " seconds";
// Mesh Standard *Node* Material
time = performance.now();
createScene( THREE.MeshStandardNodeMaterial );
render();
benchmarkTime = ( performance.now() - time ) / 1000;
document.getElementById( 'nodeBased' ).textContent = benchmarkTime.toFixed( 3 ) + " seconds";
// Mesh Standard Material
time = performance.now();
createScene( THREE.MeshStandardMaterial );
render();
benchmarkTime = ( performance.now() - time ) / 1000;
document.getElementById( 'default' ).textContent = benchmarkTime.toFixed( 3 ) + " seconds";
}
document.getElementById( 'bench' ).addEventListener( 'click', function () {
if ( geometry ) {
benchmark();
}
} );
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.z = 3200;
scene = new THREE.Scene();
scene.add( new THREE.PointLight( 0xFFFFFF ) );
//scene.background = new THREE.Color( 0xffffff );
var loader = new THREE.BufferGeometryLoader();
loader.load( 'models/json/suzanne_buffergeometry.json', function ( geo ) {
geo.computeVertexNormals();
geometry = geo;
} );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
//renderer.sortObjects = false;
container.appendChild( renderer.domElement );
stats = new Stats();
container.appendChild( stats.dom );
//
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function onDocumentMouseMove( event ) {
mouseX = ( event.clientX - windowHalfX ) * 10;
mouseY = ( event.clientY - windowHalfY ) * 10;
}
//
function animate() {
requestAnimationFrame( animate );
render();
stats.update();
}
function render() {
camera.position.x += ( mouseX - camera.position.x ) * .05;
camera.position.y += ( - mouseY - camera.position.y ) * .05;
camera.lookAt( scene.position );
renderer.render( scene, camera );
}
</script>
</body>
</html>
......@@ -34,27 +34,19 @@
<script src="../build/three.js"></script>
<script src="js/libs/dat.gui.min.js"></script>
<script src="js/shaders/CopyShader.js"></script>
<script src="js/postprocessing/EffectComposer.js"></script>
<script src="js/postprocessing/RenderPass.js"></script>
<script src="js/postprocessing/MaskPass.js"></script>
<script src="js/postprocessing/ShaderPass.js"></script>
<script type="module">
import './js/nodes/THREE.Nodes.js';
import { NodePass } from './js/nodes/postprocessing/NodePass.js';
import './js/loaders/NodeMaterialLoader.js';
var camera, scene, renderer, composer;
var object, light, nodepass;
var gui, guiElements = [];
var camera, scene, renderer;
var object, light, nodepost;
var gui;
var clock = new THREE.Clock();
var frame = new THREE.NodeFrame();
var param = { example: 'color-adjustment' };
var param = { example: new URL( window.location.href ).searchParams.get( 'e' ) || 'color-adjustment' };
var textureLoader = new THREE.TextureLoader();
......@@ -79,6 +71,7 @@
'basic / fade': 'fade',
'basic / invert': 'invert',
'basic / blur': 'blur',
'adv / motion-blur': 'motion-blur',
'adv / saturation': 'saturation',
'adv / refraction': 'refraction',
'adv / mosaic': 'mosaic'
......@@ -108,7 +101,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 () {
......@@ -140,6 +133,8 @@
case 'color-adjustment':
// POST
var screen = new THREE.ScreenNode();
var hue = new THREE.FloatNode();
......@@ -154,7 +149,7 @@
var brightnessNode = new THREE.ColorAdjustmentNode( vibranceNode, brightness, THREE.ColorAdjustmentNode.BRIGHTNESS );
var contrastNode = new THREE.ColorAdjustmentNode( brightnessNode, contrast, THREE.ColorAdjustmentNode.CONTRAST );
nodepass.value = contrastNode;
nodepost.output = contrastNode;
// GUI
......@@ -192,7 +187,7 @@
case 'fade':
// PASS
// POST
var color = new THREE.ColorNode( 0xFFFFFF );
var percent = new THREE.FloatNode( .5 );
......@@ -204,7 +199,7 @@
THREE.Math3Node.MIX
);
nodepass.value = fade;
nodepost.output = fade;
// GUI
......@@ -224,7 +219,7 @@
case 'invert':
// PASS
// POST
var alpha = new THREE.FloatNode( 1 );
......@@ -238,7 +233,7 @@
THREE.Math3Node.MIX
);
nodepass.value = fade;
nodepost.output = fade;
// GUI
......@@ -252,7 +247,7 @@
case 'blends':
// PASS
// POST
var multiply = new THREE.OperatorNode(
new THREE.ScreenNode(),
......@@ -260,7 +255,7 @@
THREE.OperatorNode.ADD
);
nodepass.value = multiply;
nodepost.output = multiply;
// GUI
......@@ -273,7 +268,7 @@
multiply.op = val;
nodepass.needsUpdate = true;
nodepost.needsUpdate = true;
} );
......@@ -298,7 +293,7 @@
saturation.inputs.rgb = screen;
saturation.inputs.adjustment = sat;
nodepass.value = saturation;
nodepost.output = saturation;
// GUI
......@@ -312,7 +307,7 @@
case 'refraction':
// PASS
// POST
var normal = new THREE.TextureNode( decalNormal );
var normalXY = new THREE.SwitchNode( normal, 'xy' );
......@@ -351,7 +346,7 @@
var screen = new THREE.ScreenNode( offsetCoord );
nodepass.value = screen;
nodepost.output = screen;
// GUI
......@@ -365,15 +360,39 @@
offsetNormal.a = val ? normalXYFlip : normalXY;
nodepass.needsUpdate = true;
nodepost.needsUpdate = true;
} );
break;
case 'motion-blur':
// POST
var size = renderer.getDrawingBufferSize();
var screen = new THREE.ScreenNode();
var previousFrame = new THREE.RTTNode( size.width, size.height, screen );
var motionBlur = new THREE.Math3Node(
previousFrame,
screen,
new THREE.FloatNode( .5 ),
THREE.Math3Node.MIX
);
var currentFrame = new THREE.RTTNode( size.width, size.height, motionBlur );
currentFrame.saveTo = previousFrame;
nodepost.output = currentFrame;
break;
case 'mosaic':
// PASS
// POST
var scale = new THREE.FloatNode( 128 );
var fade = new THREE.FloatNode( 1 );
......@@ -403,7 +422,7 @@
THREE.Math3Node.MIX
);
nodepass.value = new THREE.ScreenNode( fadeScreen );
nodepost.output = new THREE.ScreenNode( fadeScreen );
// GUI
......@@ -423,7 +442,7 @@
fadeScreen.c = val ? new THREE.TextureNode( lensflare2 ) : fade;
nodepass.needsUpdate = true;
nodepost.needsUpdate = true;
} );
......@@ -431,14 +450,14 @@
case 'blur':
// PASS
// POST
var size = renderer.getDrawingBufferSize();
var blurScreen = new THREE.BlurNode( new THREE.ScreenNode() );
blurScreen.size = new THREE.Vector2( size.width, size.height );
nodepass.value = blurScreen;
nodepost.output = blurScreen;
// GUI
......@@ -458,18 +477,19 @@
}
nodepass.needsUpdate = true;
nodepost.needsUpdate = true;
// test serialization
/*
/*
var library = {};
library[ lensflare2.uuid ] = lensflare2;
library[ decalNormal.uuid ] = decalNormal;
var json = nodepass.toJSON();
var json = nodepost.toJSON();
nodepost.output = new THREE.NodeMaterialLoader( null, library ).parse( json ).value;
*/
nodepass.value = new THREE.NodeMaterialLoader( null, library ).parse( json ).value;
*/
}
function init() {
......@@ -479,6 +499,8 @@
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
nodepost = new THREE.NodePostProcessing( renderer );
//
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
......@@ -510,16 +532,6 @@
light.position.set( 1, 1, 1 );
scene.add( light );
// postprocessing
composer = new THREE.EffectComposer( renderer );
composer.addPass( new THREE.RenderPass( scene, camera ) );
nodepass = new NodePass();
nodepass.renderToScreen = true;
composer.addPass( nodepass );
//
updateMaterial();
......@@ -533,8 +545,7 @@
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
composer.setSize( window.innerWidth, window.innerHeight );
nodepost.setSize( window.innerWidth, window.innerHeight );
}
......@@ -547,12 +558,13 @@
object.rotation.x += 0.005;
object.rotation.y += 0.01;
frame.update( delta ).updateNode( nodepass.node );
frame.update( delta );
composer.render();
nodepost.render( scene, camera, frame );
}
</script>
</body>
......
此差异已折叠。
......@@ -48,7 +48,7 @@
var renderer, scene, camera, clock = new THREE.Clock(), fov = 50;
var frame = new THREE.NodeFrame();
var plane, sprite1, sprite2, sprite3;
var sprite1, sprite2, sprite3;
var walkingManTexture, walkingManTextureURL;
var library = {};
var controls;
......@@ -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,22 +134,22 @@
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.transform = new THREE.OperatorNode(
sprite2.material.position = new THREE.OperatorNode(
new THREE.OperatorNode(
new THREE.Math1Node( new THREE.TimerNode( 3 ), THREE.Math1Node.SIN ), // 3 is speed (time scale)
new THREE.Vector2Node( .3, 0 ), // horizontal scale (position)
......@@ -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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册