123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569 |
- /**
- * @author sunag / http://www.sunag.com.br/
- */
- THREE.NodeMaterial = function( vertex, fragment ) {
- THREE.ShaderMaterial.call( this );
- this.vertex = vertex || new THREE.RawNode( new THREE.PositionNode( THREE.PositionNode.PROJECTION ) );
- this.fragment = fragment || new THREE.RawNode( new THREE.ColorNode( 0xFF0000 ) );
- };
- THREE.NodeMaterial.types = {
- t : 'sampler2D',
- tc : 'samplerCube',
- bv1 : 'bool',
- iv1 : 'int',
- fv1 : 'float',
- c : 'vec3',
- v2 : 'vec2',
- v3 : 'vec3',
- v4 : 'vec4',
- m4 : 'mat4'
- };
- THREE.NodeMaterial.addShortcuts = function( proto, prop, list ) {
- function applyShortcut( prop, name ) {
- return {
- get: function() {
- return this[ prop ][ name ];
- },
- set: function( val ) {
- this[ prop ][ name ] = val;
- }
- };
- }
- return ( function() {
- var shortcuts = {};
- for ( var i = 0; i < list.length; ++ i ) {
- var name = list[ i ];
- shortcuts[ name ] = applyShortcut( prop, name );
- }
- Object.defineProperties( proto, shortcuts );
- } )();
- };
- THREE.NodeMaterial.prototype = Object.create( THREE.ShaderMaterial.prototype );
- THREE.NodeMaterial.prototype.constructor = THREE.NodeMaterial;
- THREE.NodeMaterial.prototype.updateFrame = function( delta ) {
- for ( var i = 0; i < this.requestUpdate.length; ++ i ) {
- this.requestUpdate[ i ].updateFrame( delta );
- }
- };
- THREE.NodeMaterial.prototype.build = function() {
- var vertex, fragment;
- this.defines = {};
- this.uniforms = {};
- this.attributes = {};
- this.extensions = {};
- this.nodeData = {};
- this.vertexUniform = [];
- this.fragmentUniform = [];
- this.vars = [];
- this.vertexTemps = [];
- this.fragmentTemps = [];
- this.uniformList = [];
- this.consts = [];
- this.functions = [];
- this.requestUpdate = [];
- this.requestAttribs = {
- uv: [],
- color: []
- };
- this.vertexPars = '';
- this.fragmentPars = '';
- this.vertexCode = '';
- this.fragmentCode = '';
- this.vertexNode = '';
- this.fragmentNode = '';
- this.prefixCode = [
- "#ifdef GL_EXT_shader_texture_lod",
- " #define texCube(a, b) textureCube(a, b)",
- " #define texCubeBias(a, b, c) textureCubeLodEXT(a, b, c)",
- " #define tex2D(a, b) texture2D(a, b)",
- " #define tex2DBias(a, b, c) texture2DLodEXT(a, b, c)",
- "#else",
- " #define texCube(a, b) textureCube(a, b)",
- " #define texCubeBias(a, b, c) textureCube(a, b, c)",
- " #define tex2D(a, b) texture2D(a, b)",
- " #define tex2DBias(a, b, c) texture2D(a, b, c)",
- "#endif",
- "#include <packing>"
- ].join( "\n" );
- var builder = new THREE.NodeBuilder( this );
- vertex = this.vertex.build( builder.setShader( 'vertex' ), 'v4' );
- fragment = this.fragment.build( builder.setShader( 'fragment' ), 'v4' );
- if ( this.requestAttribs.uv[ 0 ] ) {
- this.addVertexPars( 'varying vec2 vUv;' );
- this.addFragmentPars( 'varying vec2 vUv;' );
- this.addVertexCode( 'vUv = uv;' );
- }
- if ( this.requestAttribs.uv[ 1 ] ) {
- this.addVertexPars( 'varying vec2 vUv2; attribute vec2 uv2;' );
- this.addFragmentPars( 'varying vec2 vUv2;' );
- this.addVertexCode( 'vUv2 = uv2;' );
- }
- if ( this.requestAttribs.color[ 0 ] ) {
- this.addVertexPars( 'varying vec4 vColor; attribute vec4 color;' );
- this.addFragmentPars( 'varying vec4 vColor;' );
- this.addVertexCode( 'vColor = color;' );
- }
- if ( this.requestAttribs.color[ 1 ] ) {
- this.addVertexPars( 'varying vec4 vColor2; attribute vec4 color2;' );
- this.addFragmentPars( 'varying vec4 vColor2;' );
- this.addVertexCode( 'vColor2 = color2;' );
- }
- if ( this.requestAttribs.position ) {
- this.addVertexPars( 'varying vec3 vPosition;' );
- this.addFragmentPars( 'varying vec3 vPosition;' );
- this.addVertexCode( 'vPosition = transformed;' );
- }
- if ( this.requestAttribs.worldPosition ) {
- // for future update replace from the native "varying vec3 vWorldPosition" for optimization
- this.addVertexPars( 'varying vec3 vWPosition;' );
- this.addFragmentPars( 'varying vec3 vWPosition;' );
- this.addVertexCode( 'vWPosition = worldPosition.xyz;' );
- }
- if ( this.requestAttribs.normal ) {
- this.addVertexPars( 'varying vec3 vObjectNormal;' );
- this.addFragmentPars( 'varying vec3 vObjectNormal;' );
- this.addVertexCode( 'vObjectNormal = normal;' );
- }
- if ( this.requestAttribs.worldNormal ) {
- this.addVertexPars( 'varying vec3 vWNormal;' );
- this.addFragmentPars( 'varying vec3 vWNormal;' );
- this.addVertexCode( 'vWNormal = ( modelMatrix * vec4( objectNormal, 0.0 ) ).xyz;' );
- }
- this.lights = this.requestAttribs.light;
- this.transparent = this.requestAttribs.transparent || this.blending > THREE.NormalBlending;
- this.vertexShader = [
- this.prefixCode,
- this.vertexPars,
- this.getCodePars( this.vertexUniform, 'uniform' ),
- this.getIncludes( this.consts[ 'vertex' ] ),
- this.getIncludes( this.functions[ 'vertex' ] ),
- 'void main(){',
- this.getCodePars( this.vertexTemps ),
- vertex,
- this.vertexCode,
- '}'
- ].join( "\n" );
- this.fragmentShader = [
- this.prefixCode,
- this.fragmentPars,
- this.getCodePars( this.fragmentUniform, 'uniform' ),
- this.getIncludes( this.consts[ 'fragment' ] ),
- this.getIncludes( this.functions[ 'fragment' ] ),
- 'void main(){',
- this.getCodePars( this.fragmentTemps ),
- this.fragmentCode,
- fragment,
- '}'
- ].join( "\n" );
- this.needsUpdate = true;
- this.dispose(); // force update
- return this;
- };
- THREE.NodeMaterial.prototype.define = function( name, value ) {
- this.defines[ name ] = value == undefined ? 1 : value;
- };
- THREE.NodeMaterial.prototype.isDefined = function( name ) {
- return this.defines[ name ] != undefined;
- };
- THREE.NodeMaterial.prototype.mergeUniform = function( uniforms ) {
- for ( var name in uniforms ) {
- this.uniforms[ name ] = uniforms[ name ];
- }
- };
- THREE.NodeMaterial.prototype.createUniform = function( type, value, ns, needsUpdate ) {
- var index = this.uniformList.length;
- var uniform = {
- type : type,
- value : value,
- name : ns ? ns : 'nVu' + index,
- needsUpdate : needsUpdate
- };
- this.uniformList.push( uniform );
- return uniform;
- };
- THREE.NodeMaterial.prototype.getVertexTemp = function( uuid, type, ns ) {
- var data = this.vertexTemps[ uuid ];
- if ( ! data ) {
- var index = this.vertexTemps.length,
- name = ns ? ns : 'nVt' + index;
- data = { name : name, type : type };
- this.vertexTemps.push( data );
- this.vertexTemps[ uuid ] = data;
- }
- return data;
- };
- THREE.NodeMaterial.prototype.getFragmentTemp = function( uuid, type, ns ) {
- var data = this.fragmentTemps[ uuid ];
- if ( ! data ) {
- var index = this.fragmentTemps.length,
- name = ns ? ns : 'nVt' + index;
- data = { name : name, type : type };
- this.fragmentTemps.push( data );
- this.fragmentTemps[ uuid ] = data;
- }
- return data;
- };
- THREE.NodeMaterial.prototype.getVar = function( uuid, type, ns ) {
- var data = this.vars[ uuid ];
- if ( ! data ) {
- var index = this.vars.length,
- name = ns ? ns : 'nVv' + index;
- data = { name : name, type : type };
- this.vars.push( data );
- this.vars[ uuid ] = data;
- this.addVertexPars( 'varying ' + type + ' ' + name + ';' );
- this.addFragmentPars( 'varying ' + type + ' ' + name + ';' );
- }
- return data;
- };
- THREE.NodeMaterial.prototype.getAttribute = function( name, type ) {
- if ( ! this.attributes[ name ] ) {
- var varying = this.getVar( name, type );
- this.addVertexPars( 'attribute ' + type + ' ' + name + ';' );
- this.addVertexCode( varying.name + ' = ' + name + ';' );
- this.attributes[ name ] = { varying : varying, name : name, type : type };
- }
- return this.attributes[ name ];
- };
- THREE.NodeMaterial.prototype.getIncludes = function() {
- function sortByPosition( a, b ) {
- return a.deps.length - b.deps.length;
- }
- return function( incs ) {
- if ( ! incs ) return '';
- var code = '', incs = incs.sort( sortByPosition );
- for ( var i = 0; i < incs.length; i ++ ) {
- if ( incs[ i ].src ) code += incs[ i ].src + '\n';
- }
- return code;
- }
- }();
- THREE.NodeMaterial.prototype.addVertexPars = function( code ) {
- this.vertexPars += code + '\n';
- };
- THREE.NodeMaterial.prototype.addFragmentPars = function( code ) {
- this.fragmentPars += code + '\n';
- };
- THREE.NodeMaterial.prototype.addVertexCode = function( code ) {
- this.vertexCode += code + '\n';
- };
- THREE.NodeMaterial.prototype.addFragmentCode = function( code ) {
- this.fragmentCode += code + '\n';
- };
- THREE.NodeMaterial.prototype.addVertexNode = function( code ) {
- this.vertexNode += code + '\n';
- };
- THREE.NodeMaterial.prototype.clearVertexNode = function() {
- var code = this.vertexNode;
- this.vertexNode = '';
- return code;
- };
- THREE.NodeMaterial.prototype.addFragmentNode = function( code ) {
- this.fragmentNode += code + '\n';
- };
- THREE.NodeMaterial.prototype.clearFragmentNode = function() {
- var code = this.fragmentNode;
- this.fragmentNode = '';
- return code;
- };
- THREE.NodeMaterial.prototype.getCodePars = function( pars, prefix ) {
- prefix = prefix || '';
- var code = '';
- for ( var i = 0, l = pars.length; i < l; ++ i ) {
- var parsType = pars[ i ].type;
- var parsName = pars[ i ].name;
- var parsValue = pars[ i ].value;
- if ( parsType == 't' && parsValue instanceof THREE.CubeTexture ) parsType = 'tc';
- var type = THREE.NodeMaterial.types[ parsType ];
- if ( type == undefined ) throw new Error( "Node pars " + parsType + " not found." );
- code += prefix + ' ' + type + ' ' + parsName + ';\n';
- }
- return code;
- };
- THREE.NodeMaterial.prototype.createVertexUniform = function( type, value, ns, needsUpdate ) {
- var uniform = this.createUniform( type, value, ns, needsUpdate );
- this.vertexUniform.push( uniform );
- this.vertexUniform[ uniform.name ] = uniform;
- this.uniforms[ uniform.name ] = uniform;
- return uniform;
- };
- THREE.NodeMaterial.prototype.createFragmentUniform = function( type, value, ns, needsUpdate ) {
- var uniform = this.createUniform( type, value, ns, needsUpdate );
- this.fragmentUniform.push( uniform );
- this.fragmentUniform[ uniform.name ] = uniform;
- this.uniforms[ uniform.name ] = uniform;
- return uniform;
- };
- THREE.NodeMaterial.prototype.getDataNode = function( uuid ) {
- return this.nodeData[ uuid ] = this.nodeData[ uuid ] || {};
- };
- THREE.NodeMaterial.prototype.include = function( builder, node, parent, source ) {
- var includes;
- node = typeof node === 'string' ? THREE.NodeLib.get( node ) : node;
- if ( node instanceof THREE.FunctionNode ) {
- includes = this.functions[ builder.shader ] = this.functions[ builder.shader ] || [];
- } else if ( node instanceof THREE.ConstNode ) {
- includes = this.consts[ builder.shader ] = this.consts[ builder.shader ] || [];
- }
- var included = includes[ node.name ];
- if ( ! included ) {
- included = includes[ node.name ] = {
- node : node,
- deps : []
- };
- includes.push( included );
- included.src = node.build( builder, 'source' );
- }
- if ( node instanceof THREE.FunctionNode && parent && includes[ parent.name ] && includes[ parent.name ].deps.indexOf( node ) == - 1 ) {
- includes[ parent.name ].deps.push( node );
- if ( node.includes && node.includes.length ) {
- var i = 0;
- do {
- this.include( builder, node.includes[ i ++ ], parent );
- } while ( i < node.includes.length );
- }
- }
- if ( source ) {
- included.src = source;
- }
- };
|