提交 2f4e3023 编写于 作者: S SUNAG 提交者: Mr.doob

node material r5 + mirror nodes example (#8886)

上级 761e4fb1
......@@ -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",
......
......@@ -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 = [
......
......@@ -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 ) ) );
}
......
......@@ -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;
};
......
......@@ -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;
......
......@@ -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 );
}
......
......@@ -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;
......
......@@ -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';
......
......@@ -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;
};
......
......@@ -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 );
......
......@@ -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 );
......
......@@ -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;
}
......
......@@ -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 );
};
......@@ -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 );
......
/**
* @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;
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 );
}
};
......@@ -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 );
......
......@@ -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" ],
......
......@@ -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" ]
);
......
......@@ -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 );
};
......
......@@ -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 );
};
......@@ -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 {
......
<!DOCTYPE html>
<html lang="en">
<head>
<title>WebGL NodeMaterial</title>
<title>three.js webgl - node material</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
......@@ -1299,7 +1299,7 @@
}, true );
addGui( 'hardBody', colorB.value.getHex(), function( val ) {
addGui( 'rigidBody', colorB.value.getHex(), function( val ) {
colorB.value.setHex( val );
......
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - mirror with 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: #888888;
font-family:Monospace;
font-size:13px;
background-color: #000;
margin: 0px;
overflow: hidden;
}
#info {
position: absolute;
top: 0px;
width: 200px;
left: calc(50% - 100px);
text-align: center;
}
a {
color: #00f;
}
</style>
</head>
<body>
<div id="container"></div>
<div id="info"><a href="http://threejs.org" target="_blank">three.js</a> - mirror
</div>
<script src="../build/three.js"></script>
<script src="js/Mirror.js"></script>
<script src="js/controls/OrbitControls.js"></script>
<!-- NodeLibrary -->
<script src="js/nodes/GLNode.js"></script>
<script src="js/nodes/RawNode.js"></script>
<script src="js/nodes/TempNode.js"></script>
<script src="js/nodes/InputNode.js"></script>
<script src="js/nodes/ConstNode.js"></script>
<script src="js/nodes/FunctionNode.js"></script>
<script src="js/nodes/FunctionCallNode.js"></script>
<script src="js/nodes/BuilderNode.js"></script>
<script src="js/nodes/NodeLib.js"></script>
<script src="js/nodes/NodeMaterial.js"></script>
<!-- Accessors -->
<script src="js/nodes/accessors/PositionNode.js"></script>
<script src="js/nodes/accessors/NormalNode.js"></script>
<script src="js/nodes/accessors/UVNode.js"></script>
<script src="js/nodes/accessors/ScreenUVNode.js"></script>
<script src="js/nodes/accessors/ColorsNode.js"></script>
<script src="js/nodes/accessors/CameraNode.js"></script>
<script src="js/nodes/accessors/ReflectNode.js"></script>
<script src="js/nodes/accessors/LightNode.js"></script>
<!-- Inputs -->
<script src="js/nodes/inputs/IntNode.js"></script>
<script src="js/nodes/inputs/FloatNode.js"></script>
<script src="js/nodes/inputs/ColorNode.js"></script>
<script src="js/nodes/inputs/Vector2Node.js"></script>
<script src="js/nodes/inputs/Vector3Node.js"></script>
<script src="js/nodes/inputs/Vector4Node.js"></script>
<script src="js/nodes/inputs/TextureNode.js"></script>
<script src="js/nodes/inputs/CubeTextureNode.js"></script>
<script src="js/nodes/inputs/Matrix4Node.js"></script>
<script src="js/nodes/inputs/MirrorNode.js"></script>
<!-- Math -->
<script src="js/nodes/math/Math1Node.js"></script>
<script src="js/nodes/math/Math2Node.js"></script>
<script src="js/nodes/math/Math3Node.js"></script>
<script src="js/nodes/math/OperatorNode.js"></script>
<!-- Utils -->
<script src="js/nodes/utils/SwitchNode.js"></script>
<script src="js/nodes/utils/JoinNode.js"></script>
<script src="js/nodes/utils/TimerNode.js"></script>
<script src="js/nodes/utils/RoughnessToBlinnExponentNode.js"></script>
<script src="js/nodes/utils/VelocityNode.js"></script>
<script src="js/nodes/utils/LuminanceNode.js"></script>
<script src="js/nodes/utils/ColorAdjustmentNode.js"></script>
<script src="js/nodes/utils/NoiseNode.js"></script>
<script src="js/nodes/utils/ResolutionNode.js"></script>
<!-- Phong Material -->
<script src="js/nodes/materials/PhongNode.js"></script>
<script src="js/nodes/materials/PhongNodeMaterial.js"></script>
<script>
// scene size
var WIDTH = window.innerWidth;
var HEIGHT = window.innerHeight;
// camera
var VIEW_ANGLE = 45;
var ASPECT = WIDTH / HEIGHT;
var NEAR = 1;
var FAR = 500;
var decalNormal = new THREE.TextureLoader().load( 'textures/decal/decal-normal.jpg' );
var decalDiffuse = new THREE.TextureLoader().load( 'textures/decal/decal-diffuse.png' );
decalDiffuse.wrapS = decalDiffuse.wrapT = THREE.RepeatWrapping;
var camera, scene, renderer;
var cameraControls;
var groundMirror;
var sphereGroup, smallSphere;
var groundMirrorMaterial;
function init() {
// renderer
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( WIDTH, HEIGHT );
// scene
scene = new THREE.Scene();
// camera
camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
camera.position.set( 0, 75, 160 );
cameraControls = new THREE.OrbitControls(camera, renderer.domElement);
cameraControls.target.set( 0, 40, 0);
cameraControls.maxDistance = 400;
cameraControls.minDistance = 10;
cameraControls.update();
var container = document.getElementById( 'container' );
container.appendChild( renderer.domElement );
}
function fillScene() {
var planeGeo = new THREE.PlaneBufferGeometry( 100.1, 100.1 );
// MIRROR planes
groundMirror = new THREE.Mirror( renderer, camera, { clipBias: 0.003, textureWidth: WIDTH, textureHeight: HEIGHT, color: 0x777777 } );
var mask = new THREE.SwitchNode( new THREE.TextureNode( decalDiffuse ), 'w' );
var maskFlip = new THREE.Math1Node( mask, THREE.Math1Node.INVERT );
var mirror = new THREE.MirrorNode( groundMirror );
var normal = new THREE.TextureNode( decalNormal );
var normalXY = new THREE.SwitchNode( normal, 'xy' );
var normalXYFlip = new THREE.Math1Node(
normalXY,
THREE.Math1Node.INVERT
);
var offsetNormal = new THREE.OperatorNode(
normalXYFlip,
new THREE.FloatNode( .5 ),
THREE.OperatorNode.SUB
);
mirror.offset = new THREE.OperatorNode(
offsetNormal, // normal
new THREE.FloatNode( 6 ),// scale
THREE.OperatorNode.MUL
);
var clr = new THREE.Math3Node(
mirror,
new THREE.ColorNode( 0xFFFFFF ),
mask,
THREE.Math3Node.MIX
);
groundMirrorMaterial = new THREE.PhongNodeMaterial();
groundMirrorMaterial.environment = mirror;
groundMirrorMaterial.environmentAlpha = mask;
groundMirrorMaterial.normal = normal;
//groundMirrorMaterial.normalScale = new THREE.FloatNode( 1 );
groundMirrorMaterial.build();
var mirrorMesh = new THREE.Mesh( planeGeo, groundMirrorMaterial );
mirrorMesh.add( groundMirror );
mirrorMesh.rotateX( - Math.PI / 2 );
scene.add( mirrorMesh );
sphereGroup = new THREE.Object3D();
scene.add( sphereGroup );
var geometry = new THREE.CylinderGeometry( 0.1, 15 * Math.cos( Math.PI / 180 * 30 ), 0.1, 24, 1 );
var material = new THREE.MeshPhongMaterial( { color: 0xffffff, emissive: 0x444444 } );
var sphereCap = new THREE.Mesh( geometry, material );
sphereCap.position.y = -15 * Math.sin( Math.PI / 180 * 30 ) - 0.05;
sphereCap.rotateX(-Math.PI);
var geometry = new THREE.SphereGeometry( 15, 24, 24, Math.PI / 2, Math.PI * 2, 0, Math.PI / 180 * 120 );
var halfSphere = new THREE.Mesh( geometry, material );
halfSphere.add( sphereCap );
halfSphere.rotateX( - Math.PI / 180 * 135 );
halfSphere.rotateZ( - Math.PI / 180 * 20 );
halfSphere.position.y = 7.5 + 15 * Math.sin( Math.PI / 180 * 30 );
sphereGroup.add( halfSphere );
var geometry = new THREE.IcosahedronGeometry( 5, 0 );
var material = new THREE.MeshPhongMaterial( { color: 0xffffff, emissive: 0x333333, shading: THREE.FlatShading } );
smallSphere = new THREE.Mesh( geometry, material );
scene.add(smallSphere);
// walls
var planeTop = new THREE.Mesh( planeGeo, new THREE.MeshPhongMaterial( { color: 0xffffff } ) );
planeTop.position.y = 100;
planeTop.rotateX( Math.PI / 2 );
scene.add( planeTop );
var planeBack = new THREE.Mesh( planeGeo, new THREE.MeshPhongMaterial( { color: 0xffffff } ) );
planeBack.position.z = -50;
planeBack.position.y = 50;
scene.add( planeBack );
var planeFront = new THREE.Mesh( planeGeo, new THREE.MeshPhongMaterial( { color: 0x7f7fff } ) );
planeFront.position.z = 50;
planeFront.position.y = 50;
planeFront.rotateY( Math.PI );
scene.add( planeFront );
var planeRight = new THREE.Mesh( planeGeo, new THREE.MeshPhongMaterial( { color: 0x00ff00 } ) );
planeRight.position.x = 50;
planeRight.position.y = 50;
planeRight.rotateY( - Math.PI / 2 );
scene.add( planeRight );
var planeLeft = new THREE.Mesh( planeGeo, new THREE.MeshPhongMaterial( { color: 0xff0000 } ) );
planeLeft.position.x = -50;
planeLeft.position.y = 50;
planeLeft.rotateY( Math.PI / 2 );
scene.add( planeLeft );
// lights
var mainLight = new THREE.PointLight( 0xcccccc, 1.5, 250 );
mainLight.position.y = 60;
scene.add( mainLight );
var greenLight = new THREE.PointLight( 0x00ff00, 0.25, 1000 );
greenLight.position.set( 550, 50, 0 );
scene.add( greenLight );
var redLight = new THREE.PointLight( 0xff0000, 0.25, 1000 );
redLight.position.set( - 550, 50, 0 );
scene.add( redLight );
var blueLight = new THREE.PointLight( 0x7f7fff, 0.25, 1000 );
blueLight.position.set( 0, 50, 550 );
scene.add( blueLight );
}
function render() {
// render (update) the mirrors
groundMirrorMaterial.visible = false;
groundMirror.render();
groundMirrorMaterial.visible = true;
renderer.render(scene, camera);
}
function update() {
requestAnimationFrame( update );
var timer = Date.now() * 0.01;
sphereGroup.rotation.y -= 0.002;
smallSphere.position.set(
Math.cos( timer * 0.1 ) * 30,
Math.abs( Math.cos( timer * 0.2 ) ) * 20 + 5,
Math.sin( timer * 0.1 ) * 30
);
smallSphere.rotation.y = ( Math.PI / 2 ) - timer * 0.1;
smallSphere.rotation.z = timer * 0.8;
cameraControls.update();
render();
}
init();
fillScene();
update();
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - postprocessing</title>
<title>three.js webgl - postprocessing with 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>
......@@ -414,9 +414,6 @@
var scale = new THREE.FloatNode( 128 );
var fade = new THREE.FloatNode( 1 );
var uv = new THREE.UVNode();
var tex = new THREE.TextureNode( lensflare2 );
var mask = new THREE.Math1Node( new THREE.SwitchNode( tex, 'x' ), THREE.Math1Node.INVERT );
var blocks = new THREE.OperatorNode(
uv,
......@@ -435,22 +432,14 @@
THREE.OperatorNode.DIV
);
var maskAlpha = new THREE.OperatorNode(
mask,
fade,
THREE.OperatorNode.MUL
);
var fadeCoord = new THREE.Math3Node(
var fadeScreen = new THREE.Math3Node(
uv,
coord,
maskAlpha,
fade,
THREE.Math3Node.MIX
);
var screen = new THREE.ScreenNode( fadeCoord );
nodepass.value = screen;
nodepass.value = new THREE.ScreenNode( fadeScreen );
// GUI
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册