diff --git a/examples/files.js b/examples/files.js index 3306af8a42affcc280d2628ad6ac8330aad071e1..0a5bb30efde6d9aa999b61a9aa3c4185e53c3690 100644 --- a/examples/files.js +++ b/examples/files.js @@ -152,6 +152,7 @@ var files = { "webgl_materials_video", "webgl_materials_wireframe", "webgl_mirror", + "webgl_mirror_nodes", "webgl_modifier_subdivision", "webgl_modifier_tessellation", "webgl_morphnormals", diff --git a/examples/js/nodes/BuilderNode.js b/examples/js/nodes/BuilderNode.js index f836cbea2727722aff0de790bcc049bfd39eb263..a44e8d20ab1a7cc6c7fda1fb96efa10f63d17512 100644 --- a/examples/js/nodes/BuilderNode.js +++ b/examples/js/nodes/BuilderNode.js @@ -7,7 +7,9 @@ THREE.BuilderNode = function( material ) { this.material = material; this.caches = []; - this.isVerify = false; + + this.parsing = false; + this.optimize = true; this.addCache(); @@ -90,7 +92,13 @@ THREE.BuilderNode.prototype = { getFormatName : function( format ) { - return format.replace( 'c', 'v3' ).replace( /fv1|iv1/, 'v1' ); + return format.replace( /c/g, 'v3' ).replace( /fv1|iv1/g, 'v1' ); + + }, + + isFormatMatrix : function( format ) { + + return /^m/.test( format ); }, @@ -119,11 +127,11 @@ THREE.BuilderNode.prototype = { case 'v2=v1': return code + '.x'; case 'v2=v3': return 'vec3(' + code + ',0.0)'; - case 'v2=v4': return 'vec4(' + code + ',0.0,0.0)'; + case 'v2=v4': return 'vec4(' + code + ',0.0,1.0)'; case 'v3=v1': return code + '.x'; case 'v3=v2': return code + '.xy'; - case 'v3=v4': return 'vec4(' + code + ',0.0)'; + case 'v3=v4': return 'vec4(' + code + ',1.0)'; case 'v4=v1': return code + '.x'; case 'v4=v2': return code + '.xy'; @@ -134,7 +142,7 @@ THREE.BuilderNode.prototype = { }, - getType : function( format ) { + getTypeByFormat : function( format ) { return THREE.BuilderNode.type[ format ]; @@ -164,7 +172,7 @@ THREE.BuilderNode.prototype = { isShader : function( shader ) { - return this.shader == shader || this.isVerify; + return this.shader == shader; }, @@ -181,7 +189,8 @@ THREE.BuilderNode.type = { 'float' : 'fv1', vec2 : 'v2', vec3 : 'v3', - vec4 : 'v4' + vec4 : 'v4', + mat4 : 'v4' }; THREE.BuilderNode.constructors = [ diff --git a/examples/js/nodes/FunctionCallNode.js b/examples/js/nodes/FunctionCallNode.js index 21a20dc7cf70a5d256b1f50f4fce51dbec0792a3..d2d84ca0fdd5cd39e6cfecfa195dec2b7cc00d93 100644 --- a/examples/js/nodes/FunctionCallNode.js +++ b/examples/js/nodes/FunctionCallNode.js @@ -49,7 +49,7 @@ THREE.FunctionCallNode.prototype.generate = function( builder, output ) { var inpt = func.inputs[ i ]; var param = this.inputs[ i ] || this.inputs[ inpt.name ]; - params.push( param.build( builder, builder.getType( inpt.type ) ) ); + params.push( param.build( builder, builder.getTypeByFormat( inpt.type ) ) ); } diff --git a/examples/js/nodes/FunctionNode.js b/examples/js/nodes/FunctionNode.js index c2671a1f44afde2f10e953e9e490c904890dfa9d..c45b23f70653806717877e7572d2357497ff8e1c 100644 --- a/examples/js/nodes/FunctionNode.js +++ b/examples/js/nodes/FunctionNode.js @@ -33,7 +33,7 @@ THREE.FunctionNode.prototype.parseReference = function( name ) { THREE.FunctionNode.prototype.getTypeNode = function( builder, type ) { - return builder.getType( type ) || type; + return builder.getTypeByFormat( type ) || type; }; diff --git a/examples/js/nodes/GLNode.js b/examples/js/nodes/GLNode.js index dc53231b7a2734bf2091aec1d637205769adc79e..cec18dc26eedc29a0eac6138baab50b5c145d422 100644 --- a/examples/js/nodes/GLNode.js +++ b/examples/js/nodes/GLNode.js @@ -13,9 +13,9 @@ THREE.GLNode = function( type ) { }; -THREE.GLNode.prototype.verify = function( builder, cache, requires ) { +THREE.GLNode.prototype.parse = function( builder, cache, requires ) { - builder.isVerify = true; + builder.parsing = true; var material = builder.material; @@ -26,13 +26,13 @@ THREE.GLNode.prototype.verify = function( builder, cache, requires ) { builder.removeCache(); - builder.isVerify = false; + builder.parsing = false; }; -THREE.GLNode.prototype.verifyAndBuildCode = function( builder, output, cache, requires ) { +THREE.GLNode.prototype.parseAndBuildCode = function( builder, output, cache, requires ) { - this.verify( builder, cache, requires ); + this.parse( builder, cache, requires ); return this.buildCode( builder, output, cache, requires ); @@ -53,27 +53,12 @@ THREE.GLNode.prototype.buildCode = function( builder, output, cache, requires ) }; -THREE.GLNode.prototype.verifyDepsNode = function( builder, data, output ) { - - data.deps = ( data.deps || 0 ) + 1; - - var outputLen = builder.getFormatLength( output ); - - if ( outputLen > data.outputMax || this.getType( builder ) ) { - - data.outputMax = outputLen; - data.output = output; - - } - -}; - THREE.GLNode.prototype.build = function( builder, output, uuid ) { var material = builder.material; var data = material.getDataNode( uuid || this.uuid ); - if ( builder.isShader( 'verify' ) ) this.verifyDepsNode( builder, data, output ); + if ( builder.parsing ) this.appendDepsNode( builder, data, output ); if ( this.allow[ builder.shader ] === false ) { @@ -92,6 +77,21 @@ THREE.GLNode.prototype.build = function( builder, output, uuid ) { }; +THREE.GLNode.prototype.appendDepsNode = function( builder, data, output ) { + + data.deps = ( data.deps || 0 ) + 1; + + var outputLen = builder.getFormatLength( output ); + + if ( outputLen > ( data.outputMax || 0 ) || this.getType( builder ) ) { + + data.outputMax = outputLen; + data.output = output; + + } + +}; + THREE.GLNode.prototype.getType = function( builder ) { return this.type; diff --git a/examples/js/nodes/InputNode.js b/examples/js/nodes/InputNode.js index 0c9186a319dbccc80e9006136c845af14df614b9..d508a8e450edb87783e5e201e50d7797073efc0f 100644 --- a/examples/js/nodes/InputNode.js +++ b/examples/js/nodes/InputNode.js @@ -15,8 +15,8 @@ THREE.InputNode.prototype.generate = function( builder, output, uuid, type, ns, var material = builder.material; - uuid = builder.getUuid( uuid || this.uuid ); - type = type || this.type; + uuid = builder.getUuid( uuid || this.getUuid() ); + type = type || this.getType( builder ); var data = material.getDataNode( uuid ); @@ -24,7 +24,7 @@ THREE.InputNode.prototype.generate = function( builder, output, uuid, type, ns, if ( ! data.vertex ) { - data.vertex = material.getVertexUniform( this.value, type, ns, needsUpdate ); + data.vertex = material.createVertexUniform( type, this.value, ns, needsUpdate ); } @@ -35,7 +35,7 @@ THREE.InputNode.prototype.generate = function( builder, output, uuid, type, ns, if ( ! data.fragment ) { - data.fragment = material.getFragmentUniform( this.value, type, ns, needsUpdate ); + data.fragment = material.createFragmentUniform( type, this.value, ns, needsUpdate ); } diff --git a/examples/js/nodes/NodeMaterial.js b/examples/js/nodes/NodeMaterial.js index 1ffb056fbec74996c54722c666c0447351dc9f1c..d6dc6e3b223cc2ee31285231fd5508ac4f3ac2e0 100644 --- a/examples/js/nodes/NodeMaterial.js +++ b/examples/js/nodes/NodeMaterial.js @@ -20,7 +20,8 @@ THREE.NodeMaterial.types = { c : 'vec3', v2 : 'vec2', v3 : 'vec3', - v4 : 'vec4' + v4 : 'vec4', + m4 : 'mat4' }; THREE.NodeMaterial.addShortcuts = function( proto, prop, list ) { @@ -42,7 +43,7 @@ THREE.NodeMaterial.addShortcuts = function( proto, prop, list ) { }; - return (function() { + return ( function() { var shortcuts = {}; @@ -56,7 +57,7 @@ THREE.NodeMaterial.addShortcuts = function( proto, prop, list ) { Object.defineProperties( proto, shortcuts ); - })(); + } )(); }; @@ -109,6 +110,26 @@ THREE.NodeMaterial.prototype.build = function() { 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" + ].join( "\n" ); + var builder = new THREE.BuilderNode( this ); vertex = this.vertex.build( builder.setShader( 'vertex' ), 'v4' ); @@ -192,6 +213,7 @@ THREE.NodeMaterial.prototype.build = function() { this.transparent = this.requestAttrib.transparent; this.vertexShader = [ + this.prefixCode, this.vertexPars, this.getCodePars( this.vertexUniform, 'uniform' ), this.getIncludes( this.consts[ 'vertex' ] ), @@ -204,6 +226,7 @@ THREE.NodeMaterial.prototype.build = function() { ].join( "\n" ); this.fragmentShader = [ + this.prefixCode, this.fragmentPars, this.getCodePars( this.fragmentUniform, 'uniform' ), this.getIncludes( this.consts[ 'fragment' ] ), @@ -244,7 +267,7 @@ THREE.NodeMaterial.prototype.mergeUniform = function( uniforms ) { }; -THREE.NodeMaterial.prototype.createUniform = function( value, type, ns, needsUpdate ) { +THREE.NodeMaterial.prototype.createUniform = function( type, value, ns, needsUpdate ) { var index = this.uniformList.length; @@ -404,9 +427,9 @@ THREE.NodeMaterial.prototype.getCodePars = function( pars, prefix ) { }; -THREE.NodeMaterial.prototype.getVertexUniform = function( value, type, ns, needsUpdate ) { +THREE.NodeMaterial.prototype.createVertexUniform = function( type, value, ns, needsUpdate ) { - var uniform = this.createUniform( value, type, ns, needsUpdate ); + var uniform = this.createUniform( type, value, ns, needsUpdate ); this.vertexUniform.push( uniform ); this.vertexUniform[ uniform.name ] = uniform; @@ -417,9 +440,9 @@ THREE.NodeMaterial.prototype.getVertexUniform = function( value, type, ns, needs }; -THREE.NodeMaterial.prototype.getFragmentUniform = function( value, type, ns, needsUpdate ) { +THREE.NodeMaterial.prototype.createFragmentUniform = function( type, value, ns, needsUpdate ) { - var uniform = this.createUniform( value, type, ns, needsUpdate ); + var uniform = this.createUniform( type, value, ns, needsUpdate ); this.fragmentUniform.push( uniform ); this.fragmentUniform[ uniform.name ] = uniform; diff --git a/examples/js/nodes/RawNode.js b/examples/js/nodes/RawNode.js index 74d08e6b0802d3b5dd8899770284fff34f119c91..75d5c8820b67b828b865c37de25690fed0d3a18b 100644 --- a/examples/js/nodes/RawNode.js +++ b/examples/js/nodes/RawNode.js @@ -17,7 +17,7 @@ THREE.GLNode.prototype.generate = function( builder ) { var material = builder.material; - var data = this.value.verifyAndBuildCode( builder, this.type ); + var data = this.value.parseAndBuildCode( builder, this.type ); var code = data.code + '\n'; diff --git a/examples/js/nodes/TempNode.js b/examples/js/nodes/TempNode.js index 898d969230ba81ca3b00960cf6c566dd2d87f8be..52dfcf00f83579ec0f452492e2bedc075be72515 100644 --- a/examples/js/nodes/TempNode.js +++ b/examples/js/nodes/TempNode.js @@ -35,24 +35,27 @@ THREE.TempNode.prototype.build = function( builder, output, uuid, ns ) { var data = material.getDataNode( uuid ); - if ( builder.isShader( 'verify' ) ) { + if ( builder.parsing ) { if ( data.deps || 0 > 0 ) { - this.verifyDepsNode( builder, data, output ); - return ''; + this.appendDepsNode( builder, data, output ); + + return this.generate( builder, type, uuid ); } return THREE.GLNode.prototype.build.call( this, builder, output, uuid ); } - else if ( data.deps == 1 ) { + else if ( ! builder.optimize || data.deps == 1 ) { return THREE.GLNode.prototype.build.call( this, builder, output, uuid ); } + uuid = this.getUuid( false ); + var name = this.getTemp( builder, uuid ); var type = data.output || this.getType( builder ); @@ -95,9 +98,13 @@ THREE.TempNode.prototype.isUnique = function() { }; -THREE.TempNode.prototype.getUuid = function() { +THREE.TempNode.prototype.getUuid = function( unique ) { + + var uuid = unique || unique == undefined ? this.constructor.uuid || this.uuid : this.uuid; + + if ( typeof this.scope == "string" ) uuid = this.scope + '-' + uuid; - return this.constructor.uuid || this.uuid; + return uuid; }; diff --git a/examples/js/nodes/accessors/CameraNode.js b/examples/js/nodes/accessors/CameraNode.js index 59905e289387e79967737bdedab876640876923f..bc26caf2b05ab0f9d9fe75a7b449f77607e371fe 100644 --- a/examples/js/nodes/accessors/CameraNode.js +++ b/examples/js/nodes/accessors/CameraNode.js @@ -13,6 +13,7 @@ THREE.CameraNode = function( scope, camera ) { THREE.CameraNode.POSITION = 'position'; THREE.CameraNode.DEPTH = 'depth'; +THREE.CameraNode.TO_VERTEX = 'toVertex'; THREE.CameraNode.prototype = Object.create( THREE.TempNode.prototype ); THREE.CameraNode.prototype.constructor = THREE.CameraNode; @@ -67,6 +68,7 @@ THREE.CameraNode.prototype.isUnique = function( builder ) { switch ( this.scope ) { case THREE.CameraNode.DEPTH: + case THREE.CameraNode.TO_VERTEX: return true; } @@ -106,6 +108,12 @@ THREE.CameraNode.prototype.generate = function( builder, output ) { break; + case THREE.CameraNode.TO_VERTEX: + + result = 'normalize( ' + new THREE.PositionNode( THREE.PositionNode.WORLD ).build( builder, 'v3' ) + ' - cameraPosition )'; + + break; + } return builder.format( result, this.getType( builder ), output ); diff --git a/examples/js/nodes/accessors/LightNode.js b/examples/js/nodes/accessors/LightNode.js index fcb64a96a1d79c33861e9f0d2b262fdd9969083b..4e6708786c5aacd36ee923318118656d5f3f0eea 100644 --- a/examples/js/nodes/accessors/LightNode.js +++ b/examples/js/nodes/accessors/LightNode.js @@ -20,7 +20,7 @@ THREE.LightNode.prototype.generate = function( builder, output ) { } else { - console.warn( "THREE.LightNode is compatible only in \"light\" channel." ); + console.warn( "THREE.LightNode is only compatible in \"light\" channel." ); return builder.format( 'vec3( 0.0 )', this.getType( builder ), output ); diff --git a/examples/js/nodes/accessors/PositionNode.js b/examples/js/nodes/accessors/PositionNode.js index 57acd4141c8b3e2554cfc985c6b719593e8f45b8..215762c7b37c01a490a05a114f7eb955f1a05e82 100644 --- a/examples/js/nodes/accessors/PositionNode.js +++ b/examples/js/nodes/accessors/PositionNode.js @@ -55,7 +55,7 @@ THREE.PositionNode.prototype.generate = function( builder, output ) { if ( builder.isShader( 'vertex' ) ) result = 'transformed'; else result = 'vPosition'; - break; + break; case THREE.PositionNode.WORLD: @@ -64,21 +64,21 @@ THREE.PositionNode.prototype.generate = function( builder, output ) { if ( builder.isShader( 'vertex' ) ) result = 'vWPosition'; else result = 'vWPosition'; - break; + break; case THREE.PositionNode.VIEW: if ( builder.isShader( 'vertex' ) ) result = '-mvPosition.xyz'; else result = 'vViewPosition'; - break; + break; case THREE.PositionNode.PROJECTION: if ( builder.isShader( 'vertex' ) ) result = '(projectionMatrix * modelViewMatrix * vec4( position, 1.0 ))'; else result = 'vec4( 0.0 )'; - break; + break; } diff --git a/examples/js/nodes/accessors/ReflectNode.js b/examples/js/nodes/accessors/ReflectNode.js index 9ab55f1c59091cf9f0720c06f5082b59c53491a9..fa753385c80d8785ff3d89fc32c08858011c76d1 100644 --- a/examples/js/nodes/accessors/ReflectNode.js +++ b/examples/js/nodes/accessors/ReflectNode.js @@ -2,38 +2,67 @@ * @author sunag / http://www.sunag.com.br/ */ -THREE.ReflectNode = function() { +THREE.ReflectNode = function( scope ) { THREE.TempNode.call( this, 'v3', { unique: true } ); - this.worldPosition = new THREE.PositionNode( THREE.PositionNode.WORLD ); + this.scope = scope || THREE.ReflectNode.CUBE; }; +THREE.ReflectNode.CUBE = 'cube'; +THREE.ReflectNode.SPHERE = 'sphere'; +THREE.ReflectNode.VECTOR = 'vector'; + THREE.ReflectNode.prototype = Object.create( THREE.TempNode.prototype ); THREE.ReflectNode.prototype.constructor = THREE.ReflectNode; +THREE.ReflectNode.prototype.getType = function( builder ) { + + switch ( this.scope ) { + case THREE.CameraNode.SPHERE: + return 'v2'; + } + + return this.type; + +}; + THREE.ReflectNode.prototype.generate = function( builder, output ) { - var material = builder.material; + var result; - if ( builder.isShader( 'fragment' ) ) { + switch ( this.scope ) { - material.addFragmentNode( [ - 'vec3 cameraToVertex = normalize( ' + this.worldPosition.build( builder, 'v3' ) + ' - cameraPosition );', - 'vec3 worldNormal = inverseTransformDirection( normal, viewMatrix );', - 'vec3 vReflect = reflect( cameraToVertex, worldNormal );' - ].join( "\n" ) ); + case THREE.ReflectNode.VECTOR: - return builder.format( 'vReflect', this.type, output ); + builder.material.addFragmentNode( 'vec3 reflectVec = inverseTransformDirection( reflect( -geometry.viewDir, geometry.normal ), viewMatrix );' ); - } - else { + result = 'reflectVec'; + + break; - console.warn( "THREE.ReflectNode is not compatible with " + builder.shader + " shader." ); + case THREE.ReflectNode.CUBE: - return builder.format( 'vec3( 0.0 )', this.type, output ); + var reflectVec = new THREE.ReflectNode( THREE.ReflectNode.VECTOR ).build( builder, 'v3' ); + builder.material.addFragmentNode( 'vec3 reflectCubeVec = vec3( -1.0 * ' + reflectVec + '.x, ' + reflectVec + '.yz );' ); + + result = 'reflectCubeVec'; + + break; + + case THREE.ReflectNode.SPHERE: + + var reflectVec = new THREE.ReflectNode( THREE.ReflectNode.VECTOR ).build( builder, 'v3' ); + + builder.material.addFragmentNode( 'vec3 reflectSphereVec = normalize((viewMatrix * vec4(' + reflectVec + ', 0.0 )).xyz + vec3(0.0,0.0,1.0)).xy * 0.5 + 0.5;' ); + + result = 'reflectSphereVec'; + + break; } + return builder.format( result, this.getType( this.type ), output ); + }; diff --git a/examples/js/nodes/inputs/CubeTextureNode.js b/examples/js/nodes/inputs/CubeTextureNode.js index 13408ca0479346e547e1a27f7ec3ea53ae8abb09..3843399b55b9009b574280896efa4a94589543af 100644 --- a/examples/js/nodes/inputs/CubeTextureNode.js +++ b/examples/js/nodes/inputs/CubeTextureNode.js @@ -35,8 +35,8 @@ THREE.CubeTextureNode.prototype.generate = function( builder, output ) { var code; - if ( bias ) code = 'textureCube(' + cubetex + ',' + coord + ',' + bias + ')'; - else code = 'textureCube(' + cubetex + ',' + coord + ')'; + if ( bias ) code = 'texCubeBias(' + cubetex + ',' + coord + ',' + bias + ')'; + else code = 'texCube(' + cubetex + ',' + coord + ')'; return builder.format( code, this.type, output ); diff --git a/examples/js/nodes/inputs/Matrix4Node.js b/examples/js/nodes/inputs/Matrix4Node.js new file mode 100644 index 0000000000000000000000000000000000000000..81fbdd64d57d0b0969a55a2b0d0397be1c690f32 --- /dev/null +++ b/examples/js/nodes/inputs/Matrix4Node.js @@ -0,0 +1,14 @@ +/** + * @author sunag / http://www.sunag.com.br/ + */ + +THREE.Matrix4Node = function( matrix ) { + + THREE.InputNode.call( this, 'm4', { share: false } ); + + this.value = matrix || new THREE.Matrix4(); + +}; + +THREE.Matrix4Node.prototype = Object.create( THREE.InputNode.prototype ); +THREE.Matrix4Node.prototype.constructor = THREE.Matrix4Node; diff --git a/examples/js/nodes/inputs/MirrorNode.js b/examples/js/nodes/inputs/MirrorNode.js new file mode 100644 index 0000000000000000000000000000000000000000..d3c1cd9d268a2a5ef08544bc706fded484114a9a --- /dev/null +++ b/examples/js/nodes/inputs/MirrorNode.js @@ -0,0 +1,43 @@ +THREE.MirrorNode = function( renderer, camera, options ) { + + THREE.TempNode.call( this, 'v4' ); + + this.mirror = renderer instanceof THREE.Mirror ? renderer : new THREE.Mirror( renderer, camera, options ); + + this.textureMatrix = new THREE.Matrix4Node( this.mirror.textureMatrix ); + + this.worldPosition = new THREE.PositionNode( THREE.PositionNode.WORLD ); + + this.coord = new THREE.OperatorNode( this.textureMatrix, this.worldPosition, THREE.OperatorNode.MUL ); + this.coordResult = new THREE.OperatorNode( null, this.coord, THREE.OperatorNode.ADD ); + + this.texture = new THREE.TextureNode( this.mirror.renderTarget.texture, this.coord, null, true ); + +}; + +THREE.MirrorNode.prototype = Object.create( THREE.TempNode.prototype ); +THREE.MirrorNode.prototype.constructor = THREE.MirrorNode; + +THREE.MirrorNode.prototype.generate = function( builder, output ) { + + var material = builder.material; + + if ( builder.isShader( 'fragment' ) ) { + + this.coordResult.a = this.offset; + this.texture.coord = this.offset ? this.coordResult : this.coord; + + var coord = this.texture.build( builder, this.type ); + + return builder.format( coord, this.type, output ); + + } + else { + + console.warn( "THREE.MirrorNode is not compatible with " + builder.shader + " shader." ); + + return builder.format( 'vec4(0.0)', this.type, output ); + + } + +}; diff --git a/examples/js/nodes/inputs/TextureNode.js b/examples/js/nodes/inputs/TextureNode.js index cb2a963fb39aada6531295dfe02fd6468006783b..b8e3fd3fd23edc73421a0d2e8f496b2f4ad08e43 100644 --- a/examples/js/nodes/inputs/TextureNode.js +++ b/examples/js/nodes/inputs/TextureNode.js @@ -2,13 +2,14 @@ * @author sunag / http://www.sunag.com.br/ */ -THREE.TextureNode = function( value, coord, bias ) { +THREE.TextureNode = function( value, coord, bias, project ) { THREE.InputNode.call( this, 'v4' ); this.value = value; this.coord = coord || new THREE.UVNode(); this.bias = bias; + this.project = project !== undefined ? project : false; }; @@ -24,7 +25,7 @@ THREE.TextureNode.prototype.getTexture = function( builder, output ) { THREE.TextureNode.prototype.generate = function( builder, output ) { var tex = this.getTexture( builder, output ); - var coord = this.coord.build( builder, 'v2' ); + var coord = this.coord.build( builder, this.project ? 'v4' : 'v2' ); var bias = this.bias ? this.bias.build( builder, 'fv1' ) : undefined; if ( bias == undefined && builder.requires.bias ) { @@ -33,10 +34,13 @@ THREE.TextureNode.prototype.generate = function( builder, output ) { } - var code; + var method, code; - if ( bias ) code = 'texture2D(' + tex + ',' + coord + ',' + bias + ')'; - else code = 'texture2D(' + tex + ',' + coord + ')'; + if ( this.project ) method = 'texture2DProj'; + else method = bias ? 'tex2DBias' : 'tex2D'; + + if ( bias ) code = method + '(' + tex + ',' + coord + ',' + bias + ')'; + else code = method + '(' + tex + ',' + coord + ')'; return builder.format( code, this.type, output ); diff --git a/examples/js/nodes/materials/PhongNode.js b/examples/js/nodes/materials/PhongNode.js index f11ab7c8963415fa4343d18235dcad02168eefe9..0e7c6ae7a06e1cab978e046cb60ff71a8e1cc4ab 100644 --- a/examples/js/nodes/materials/PhongNode.js +++ b/examples/js/nodes/materials/PhongNode.js @@ -27,11 +27,12 @@ THREE.PhongNode.prototype.build = function( builder ) { if ( builder.isShader( 'vertex' ) ) { - var transform = this.transform ? this.transform.verifyAndBuildCode( builder, 'v3', 'transform' ) : undefined; + var transform = this.transform ? this.transform.parseAndBuildCode( builder, 'v3', 'transform' ) : undefined; material.mergeUniform( THREE.UniformsUtils.merge( [ THREE.UniformsLib[ "fog" ], + THREE.UniformsLib[ "ambient" ], THREE.UniformsLib[ "lights" ] ] ) ); @@ -95,26 +96,26 @@ THREE.PhongNode.prototype.build = function( builder ) { } else { - // verify all nodes to reuse generate codes + // parse all nodes to reuse generate codes - this.color.verify( builder ); - this.specular.verify( builder ); - this.shininess.verify( builder ); + this.color.parse( builder ); + this.specular.parse( builder ); + this.shininess.parse( builder ); - if ( this.alpha ) this.alpha.verify( builder ); + if ( this.alpha ) this.alpha.parse( builder ); - if ( this.light ) this.light.verify( builder, 'light' ); + if ( this.light ) this.light.parse( builder, 'light' ); - if ( this.ao ) this.ao.verify( builder ); - if ( this.ambient ) this.ambient.verify( builder ); - if ( this.shadow ) this.shadow.verify( builder ); - if ( this.emissive ) this.emissive.verify( builder ); + if ( this.ao ) this.ao.parse( builder ); + if ( this.ambient ) this.ambient.parse( builder ); + if ( this.shadow ) this.shadow.parse( builder ); + if ( this.emissive ) this.emissive.parse( builder ); - if ( this.normal ) this.normal.verify( builder ); - if ( this.normalScale && this.normal ) this.normalScale.verify( builder ); + if ( this.normal ) this.normal.parse( builder ); + if ( this.normalScale && this.normal ) this.normalScale.parse( builder ); - if ( this.environment ) this.environment.verify( builder ); - if ( this.environmentAlpha && this.environment ) this.environmentAlpha.verify( builder ); + if ( this.environment ) this.environment.parse( builder ); + if ( this.environmentAlpha && this.environment ) this.environmentAlpha.parse( builder ); // build code @@ -143,6 +144,7 @@ THREE.PhongNode.prototype.build = function( builder ) { THREE.ShaderChunk[ "common" ], THREE.ShaderChunk[ "fog_pars_fragment" ], THREE.ShaderChunk[ "bsdfs" ], + THREE.ShaderChunk[ "ambient_pars" ], THREE.ShaderChunk[ "lights_pars" ], THREE.ShaderChunk[ "lights_phong_pars_fragment" ], THREE.ShaderChunk[ "shadowmap_pars_fragment" ], diff --git a/examples/js/nodes/materials/StandardNode.js b/examples/js/nodes/materials/StandardNode.js index 5d2ca839ee844e6eacb81d189a7bba429e9a989e..dd64635fb6327de46a97511e54b41a1d2f71ae43 100644 --- a/examples/js/nodes/materials/StandardNode.js +++ b/examples/js/nodes/materials/StandardNode.js @@ -20,18 +20,19 @@ THREE.StandardNode.prototype.build = function( builder ) { var material = builder.material; var code; - material.define( 'STANDARD' ); + material.define( 'PHYSICAL' ); material.define( 'ALPHATEST', '0.0' ); material.requestAttrib.light = true; if ( builder.isShader( 'vertex' ) ) { - var transform = this.transform ? this.transform.verifyAndBuildCode( builder, 'v3', 'transform' ) : undefined; + var transform = this.transform ? this.transform.parseAndBuildCode( builder, 'v3', 'transform' ) : undefined; material.mergeUniform( THREE.UniformsUtils.merge( [ THREE.UniformsLib[ "fog" ], + THREE.UniformsLib[ "ambient" ], THREE.UniformsLib[ "lights" ] ] ) ); @@ -95,31 +96,33 @@ THREE.StandardNode.prototype.build = function( builder ) { } else { - // autoblur textures for PBR Material effect + // blur textures for PBR effect var requires = { - bias : new THREE.RoughnessToBlinnExponentNode() + bias : new THREE.RoughnessToBlinnExponentNode(), + offsetU : 0, + offsetV : 0 }; - // verify all nodes to reuse generate codes + // parse all nodes to reuse generate codes - this.color.verify( builder ); - this.roughness.verify( builder ); - this.metalness.verify( builder ); + this.color.parse( builder ); + this.roughness.parse( builder ); + this.metalness.parse( builder ); - if ( this.alpha ) this.alpha.verify( builder ); + if ( this.alpha ) this.alpha.parse( builder ); - if ( this.light ) this.light.verify( builder, 'light' ); + if ( this.light ) this.light.parse( builder, 'light' ); - if ( this.ao ) this.ao.verify( builder ); - if ( this.ambient ) this.ambient.verify( builder ); - if ( this.shadow ) this.shadow.verify( builder ); - if ( this.emissive ) this.emissive.verify( builder ); + if ( this.ao ) this.ao.parse( builder ); + if ( this.ambient ) this.ambient.parse( builder ); + if ( this.shadow ) this.shadow.parse( builder ); + if ( this.emissive ) this.emissive.parse( builder ); - if ( this.normal ) this.normal.verify( builder ); - if ( this.normalScale && this.normal ) this.normalScale.verify( builder ); + if ( this.normal ) this.normal.parse( builder ); + if ( this.normalScale && this.normal ) this.normalScale.parse( builder ); - if ( this.environment ) this.environment.verify( builder, 'env', requires ); // isolate environment from others inputs ( see TextureNode, CubeTextureNode ) + if ( this.environment ) this.environment.parse( builder, 'env', requires ); // isolate environment from others inputs ( see TextureNode, CubeTextureNode ) // build code @@ -127,6 +130,8 @@ THREE.StandardNode.prototype.build = function( builder ) { var roughness = this.roughness.buildCode( builder, 'fv1' ); var metalness = this.metalness.buildCode( builder, 'fv1' ); + var reflectivity = this.reflectivity ? this.reflectivity.buildCode( builder, 'fv1' ) : undefined; + var alpha = this.alpha ? this.alpha.buildCode( builder, 'fv1' ) : undefined; var light = this.light ? this.light.buildCode( builder, 'v3', 'light' ) : undefined; @@ -157,7 +162,7 @@ THREE.StandardNode.prototype.build = function( builder ) { THREE.ShaderChunk[ "fog_pars_fragment" ], THREE.ShaderChunk[ "bsdfs" ], THREE.ShaderChunk[ "lights_pars" ], - THREE.ShaderChunk[ "lights_standard_pars_fragment" ], + THREE.ShaderChunk[ "lights_physical_pars_fragment" ], THREE.ShaderChunk[ "shadowmap_pars_fragment" ], THREE.ShaderChunk[ "logdepthbuf_pars_fragment" ], ].join( "\n" ) ); @@ -167,7 +172,7 @@ THREE.StandardNode.prototype.build = function( builder ) { THREE.ShaderChunk[ "normal_fragment" ], // prevent undeclared material - " StandardMaterial material;", + " PhysicalMaterial material;", " material.diffuseColor = vec3( 1.0 );", color.code, @@ -215,9 +220,25 @@ THREE.StandardNode.prototype.build = function( builder ) { output.push( // accumulation - 'material.specularRoughness = clamp( roughnessFactor, 0.001, 1.0 );', // disney's remapping of [ 0, 1 ] roughness to [ 0.001, 1 ] - 'material.specularColor = mix( vec3( 0.04 ), diffuseColor, metalnessFactor );', + 'material.specularRoughness = clamp( roughnessFactor, 0.04, 1.0 );' // disney's remapping of [ 0, 1 ] roughness to [ 0.001, 1 ] + ); + + if ( reflectivity ) { + + output.push( + 'material.specularColor = mix( vec3( 0.16 * pow2( ' + reflectivity.builder( builder, 'fv1' ) + ' ) ), diffuseColor, metalnessFactor );' + ); + } + else { + + output.push( + 'material.specularColor = mix( vec3( 0.04 ), diffuseColor, metalnessFactor );' + ); + + } + + output.push( THREE.ShaderChunk[ "lights_template" ] ); diff --git a/examples/js/nodes/math/Math3Node.js b/examples/js/nodes/math/Math3Node.js index 78da6d0230362fa2abfa2920ee137d516dae9368..9b6a79694aff170019b54ed3e39b930161906301 100644 --- a/examples/js/nodes/math/Math3Node.js +++ b/examples/js/nodes/math/Math3Node.js @@ -28,19 +28,10 @@ THREE.Math3Node.prototype.getType = function( builder ) { var b = builder.getFormatLength( this.b.getType( builder ) ); var c = builder.getFormatLength( this.c.getType( builder ) ); - if ( a > b ) { - - if ( a > c ) return this.a.getType( builder ); - return this.c.getType( builder ); - - } - else { - - if ( b > c ) return this.b.getType( builder ); - - return this.c.getType( builder ); - - } + if ( a > b && a > c ) return this.a.getType( builder ); + else if ( b > c ) return this.b.getType( builder ); + + return this.c.getType( builder ); }; diff --git a/examples/js/nodes/math/OperatorNode.js b/examples/js/nodes/math/OperatorNode.js index 436408769807d6ea66b5ffa261e14484f1ffb391..05797153396f52b34f5e6053f66e32d90fd67e8b 100644 --- a/examples/js/nodes/math/OperatorNode.js +++ b/examples/js/nodes/math/OperatorNode.js @@ -22,25 +22,35 @@ THREE.OperatorNode.prototype.constructor = THREE.OperatorNode; THREE.OperatorNode.prototype.getType = function( builder ) { + var a = this.a.getType( builder ); + var b = this.b.getType( builder ); + + if ( builder.isFormatMatrix( a ) ) { + + return 'v4'; + + } // use the greater length vector - if ( builder.getFormatLength( this.b.getType( builder ) ) > builder.getFormatLength( this.a.getType( builder ) ) ) { + else if ( builder.getFormatLength( b ) > builder.getFormatLength( a ) ) { - return this.b.getType( builder ); + return b; } - return this.a.getType( builder ); + return a; }; THREE.OperatorNode.prototype.generate = function( builder, output ) { - var material = builder.material; - var data = material.getDataNode( this.uuid ); + var material = builder.material, + data = material.getDataNode( this.uuid ); - var a = this.a.build( builder, output ); - var b = this.b.build( builder, output ); + var type = this.getType( builder ); + + var a = this.a.build( builder, type ); + var b = this.b.build( builder, type ); - return '(' + a + this.op + b + ')'; + return builder.format( '(' + a + this.op + b + ')', type, output ); }; diff --git a/examples/js/nodes/utils/RoughnessToBlinnExponentNode.js b/examples/js/nodes/utils/RoughnessToBlinnExponentNode.js index d4ae8eb7b620cb6a940c53351181b51c946931e9..4ecae2a4f476f7e87ce71939942c74f9da7edc1d 100644 --- a/examples/js/nodes/utils/RoughnessToBlinnExponentNode.js +++ b/examples/js/nodes/utils/RoughnessToBlinnExponentNode.js @@ -4,10 +4,24 @@ THREE.RoughnessToBlinnExponentNode = function() { - THREE.TempNode.call( this, 'fv1', { unique: true } ); + THREE.TempNode.call( this, 'fv1' ); }; +THREE.RoughnessToBlinnExponentNode.getSpecularMIPLevel = new THREE.FunctionNode( [ +// taken from here: http://casual-effects.blogspot.ca/2011/08/plausible-environment-lighting-in-two.html +"float getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {", + + //float envMapWidth = pow( 2.0, maxMIPLevelScalar ); + //float desiredMIPLevel = log2( envMapWidth * sqrt( 3.0 ) ) - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 ); + "float maxMIPLevelScalar = float( maxMIPLevel );", + "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" ) ); + THREE.RoughnessToBlinnExponentNode.prototype = Object.create( THREE.TempNode.prototype ); THREE.RoughnessToBlinnExponentNode.prototype.constructor = THREE.RoughnessToBlinnExponentNode; @@ -17,21 +31,21 @@ THREE.RoughnessToBlinnExponentNode.prototype.generate = function( builder, outpu if ( builder.isShader( 'fragment' ) ) { - if ( material.isDefined( 'STANDARD' ) ) { + if ( material.isDefined( 'PHYSICAL' ) ) { - material.addFragmentNode( 'float specularMIPLevel = GGXRoughnessToBlinnExponent( 1.0 - material.specularRoughness );' ); + builder.include( THREE.RoughnessToBlinnExponentNode.getSpecularMIPLevel ); + + return builder.format( 'getSpecularMIPLevel( Material_BlinnShininessExponent( material ), 8 )', this.type, output ); } else { - console.warn( "THREE.RoughnessToBlinnExponentNode is compatible with StandardMaterial only." ); + console.warn( "THREE.RoughnessToBlinnExponentNode is only compatible with PhysicalMaterial." ); - material.addFragmentNode( 'float specularMIPLevel = 0.0;' ); + return builder.format( '0.0', this.type, output ); } - return builder.format( 'specularMIPLevel', this.type, output ); - } else { diff --git a/examples/webgl_materials_nodes.html b/examples/webgl_materials_nodes.html index 48e72c3ab4834a1d41ce8ec4a1671738b809c608..778ef02114d452c05e26f779d52e9042e8fd3585 100644 --- a/examples/webgl_materials_nodes.html +++ b/examples/webgl_materials_nodes.html @@ -1,7 +1,7 @@ - WebGL NodeMaterial + three.js webgl - node material + + + +
+
three.js - mirror +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/webgl_postprocessing_nodes.html b/examples/webgl_postprocessing_nodes.html index c25c1f786b66335e3c8ec329911a25351c4b04ba..f3d5c61bfe2990dc477c169be80c10b848a42b82 100644 --- a/examples/webgl_postprocessing_nodes.html +++ b/examples/webgl_postprocessing_nodes.html @@ -1,7 +1,7 @@ - three.js webgl - postprocessing + three.js webgl - postprocessing with nodes