Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 62 additions & 56 deletions examples/js/loaders/GLTFLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -1182,15 +1182,12 @@ THREE.GLTFLoader = ( function () {
*/
function createDefaultMaterial() {

return new THREE.MeshStandardMaterial( {
color: 0xFFFFFF,
emissive: 0x000000,
metalness: 1,
roughness: 1,
transparent: false,
depthTest: true,
side: THREE.FrontSide
} );
var material = new THREE.StandardNodeMaterial();
material.color.value.setHex( 0xFFFFFF );
material.emissive.value.setHex( 0x000000 );
material.metalness.value = 1.0;
material.roughness.value = 1.0;
return material;

}

Expand Down Expand Up @@ -2074,11 +2071,35 @@ THREE.GLTFLoader = ( function () {
* @param {number} textureIndex
* @return {Promise}
*/
GLTFParser.prototype.assignTexture = function ( materialParams, textureName, textureIndex ) {
GLTFParser.prototype.assignTexture = function ( material, textureName, textureIndex, textureComponent ) {

return this.getDependency( 'texture', textureIndex ).then( function ( texture ) {

materialParams[ textureName ] = texture;
var factorNode = material[ textureName ];
var textureNode = new THREE.TextureNode( texture );

// baseColorTexture and emissiveTexture use sRGB encoding.
if ( textureName === 'color' || textureName === 'emissive' ) {

textureNode.value.encoding = THREE.sRGBEncoding;

}

if ( textureComponent !== undefined ) {

textureNode = new THREE.SwitchNode( textureNode, textureComponent );

}

if ( factorNode === undefined ) {

material[ textureName ] = textureNode;

} else {

material[ textureName ] = new THREE.OperatorNode( factorNode, textureNode, THREE.OperatorNode.MUL );

}

} );

Expand All @@ -2096,6 +2117,7 @@ THREE.GLTFLoader = ( function () {
var extensions = this.extensions;
var materialDef = this.json.materials[ materialIndex ];

var material;
var materialType;
var materialParams = {};
var materialExtensions = materialDef.extensions || {};
Expand All @@ -2119,135 +2141,119 @@ THREE.GLTFLoader = ( function () {
// Specification:
// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#metallic-roughness-material

materialType = THREE.MeshStandardMaterial;
material = new THREE.StandardNodeMaterial();

var metallicRoughness = materialDef.pbrMetallicRoughness || {};

materialParams.color = new THREE.Color( 1.0, 1.0, 1.0 );
materialParams.opacity = 1.0;
material.color = new THREE.ColorNode( 0xFFFFFF );
material.alpha = new THREE.FloatNode( 1.0 );

if ( Array.isArray( metallicRoughness.baseColorFactor ) ) {

var array = metallicRoughness.baseColorFactor;

materialParams.color.fromArray( array );
materialParams.opacity = array[ 3 ];
material.color.value.fromArray( array );
material.alpha.value = array[ 3 ];

}

if ( metallicRoughness.baseColorTexture !== undefined ) {

pending.push( parser.assignTexture( materialParams, 'map', metallicRoughness.baseColorTexture.index ) );
pending.push( parser.assignTexture( material, 'color', metallicRoughness.baseColorTexture.index ) );

}

materialParams.metalness = metallicRoughness.metallicFactor !== undefined ? metallicRoughness.metallicFactor : 1.0;
materialParams.roughness = metallicRoughness.roughnessFactor !== undefined ? metallicRoughness.roughnessFactor : 1.0;
material.metalness.value = metallicRoughness.metallicFactor !== undefined ? metallicRoughness.metallicFactor : 1.0;
material.roughness.value = metallicRoughness.roughnessFactor !== undefined ? metallicRoughness.roughnessFactor : 1.

if ( metallicRoughness.metallicRoughnessTexture !== undefined ) {

var textureIndex = metallicRoughness.metallicRoughnessTexture.index;
pending.push( parser.assignTexture( materialParams, 'metalnessMap', textureIndex ) );
pending.push( parser.assignTexture( materialParams, 'roughnessMap', textureIndex ) );
pending.push( parser.assignTexture( material, 'metalness', textureIndex, 'z' ) );
pending.push( parser.assignTexture( material, 'roughness', textureIndex, 'y' ) );

}

}

if ( materialDef.doubleSided === true ) {

materialParams.side = THREE.DoubleSide;
material.side = THREE.DoubleSide;

}

var alphaMode = materialDef.alphaMode || ALPHA_MODES.OPAQUE;

if ( alphaMode === ALPHA_MODES.BLEND ) {

materialParams.transparent = true;
material.transparent = true;

} else {

materialParams.transparent = false;
material.transparent = false;

if ( alphaMode === ALPHA_MODES.MASK ) {

materialParams.alphaTest = materialDef.alphaCutoff !== undefined ? materialDef.alphaCutoff : 0.5;
material.alphaTest = materialDef.alphaCutoff !== undefined ? materialDef.alphaCutoff : 0.5;

}

}

if ( materialDef.normalTexture !== undefined && materialType !== THREE.MeshBasicMaterial) {

pending.push( parser.assignTexture( materialParams, 'normalMap', materialDef.normalTexture.index ) );
pending.push( parser.assignTexture( material, 'normal', materialDef.normalTexture.index ) );

materialParams.normalScale = new THREE.Vector2( 1, 1 );
// Normal map textures use OpenGL conventions:
// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#materialnormaltexture
material.normalScale = new THREE.Vector2Node( 1.0, -1.0 );

if ( materialDef.normalTexture.scale !== undefined ) {

materialParams.normalScale.set( materialDef.normalTexture.scale, materialDef.normalTexture.scale );
material.normalScale.value.multiplyScalar( materialDef.normalTexture.scale );

}

}

if ( materialDef.occlusionTexture !== undefined && materialType !== THREE.MeshBasicMaterial) {

pending.push( parser.assignTexture( materialParams, 'aoMap', materialDef.occlusionTexture.index ) );
material.ao = new THREE.FloatNode( 1.0 );

if ( materialDef.occlusionTexture.strength !== undefined ) {

materialParams.aoMapIntensity = materialDef.occlusionTexture.strength;
material.ao.value = materialDef.occlusionTexture.strength;

}

pending.push( parser.assignTexture( material, 'ao', materialDef.occlusionTexture.index, 'x' ) );

}

material.emissive = new THREE.ColorNode( 0x000000 );

if ( materialDef.emissiveFactor !== undefined && materialType !== THREE.MeshBasicMaterial) {

materialParams.emissive = new THREE.Color().fromArray( materialDef.emissiveFactor );
material.emissive.value.fromArray( materialDef.emissiveFactor );

}

if ( materialDef.emissiveTexture !== undefined && materialType !== THREE.MeshBasicMaterial) {

pending.push( parser.assignTexture( materialParams, 'emissiveMap', materialDef.emissiveTexture.index ) );
pending.push( parser.assignTexture( material, 'emissive', materialDef.emissiveTexture.index ) );

}

return Promise.all( pending ).then( function () {

var material;

if ( materialType === THREE.ShaderMaterial ) {

material = extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ].createMaterial( materialParams );

} else {

material = new materialType( materialParams );

}

if ( materialDef.name !== undefined ) material.name = materialDef.name;

// Normal map textures use OpenGL conventions:
// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#materialnormaltexture
if ( material.normalScale ) {

material.normalScale.y = - material.normalScale.y;

}

// emissiveTexture and baseColorTexture use sRGB encoding.
if ( material.map ) material.map.encoding = THREE.sRGBEncoding;
if ( material.emissiveMap ) material.emissiveMap.encoding = THREE.sRGBEncoding;

if ( materialDef.extras ) material.userData = materialDef.extras;

if ( materialDef.extensions ) addUnknownExtensionsToUserData( extensions, material, materialDef );

material.build();

return material;

} );
Expand Down
6 changes: 4 additions & 2 deletions examples/js/nodes/NodeLib.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,10 @@ THREE.NodeLib.add( new THREE.FunctionNode( [
" vec3 q1 = dFdy( eye_pos );",
" vec2 st0 = dFdx( mUv.st );",
" vec2 st1 = dFdy( mUv.st );",
" vec3 S = normalize( q0 * st1.t - q1 * st0.t );",
" vec3 T = normalize( -q0 * st1.s + q1 * st0.s );",
" float factor = sign( st1.t * st0.s - st0.t * st1.s );",
" factor *= float( gl_FrontFacing ) * 2.0 - 1.0;",
" vec3 S = normalize( ( q0 * st1.t - q1 * st0.t ) * factor );",
" vec3 T = normalize( ( -q0 * st1.s + q1 * st0.s ) * factor );",
" vec3 N = normalize( surf_norm );",
" vec3 mapN = map * 2.0 - 1.0;",
" mapN.xy = scale * mapN.xy;",
Expand Down
8 changes: 5 additions & 3 deletions examples/js/nodes/inputs/TextureNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,19 @@ THREE.TextureNode.prototype.generate = function ( builder, output ) {
if ( bias ) code = method + '(' + tex + ',' + coord + ',' + bias + ')';
else code = method + '(' + tex + ',' + coord + ')';

// TODO: This is a hack, but WebGLProgram does not know enough about
// node materials to infer correct colorspace.
if ( builder.isSlot( 'color' ) ) {

code = 'mapTexelToLinear(' + code + ')';
code = 'sRGBToLinear(' + code + ')';

} else if ( builder.isSlot( 'emissive' ) ) {

code = 'emissiveMapTexelToLinear(' + code + ')';
code = 'sRGBToLinear(' + code + ')';

} else if ( builder.isSlot( 'environment' ) ) {

code = 'envMapTexelToLinear(' + code + ')';
code = 'sRGBToLinear(' + code + ')';

}

Expand Down
74 changes: 73 additions & 1 deletion examples/webgl_loader_gltf.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,72 @@
<script src="js/controls/OrbitControls.js"></script>
<script src="js/loaders/GLTFLoader.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/VarNode.js"></script>
<script src="js/nodes/FunctionNode.js"></script>
<script src="js/nodes/FunctionCallNode.js"></script>
<script src="js/nodes/AttributeNode.js"></script>
<script src="js/nodes/NodeUniform.js"></script>
<script src="js/nodes/NodeBuilder.js"></script>
<script src="js/nodes/NodeLib.js"></script>
<script src="js/nodes/NodeFrame.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/Matrix3Node.js"></script>
<script src="js/nodes/inputs/Matrix4Node.js"></script>
<script src="js/nodes/inputs/CubeTextureNode.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>
<script src="js/nodes/utils/BumpNode.js"></script>
<script src="js/nodes/utils/BlurNode.js"></script>
<script src="js/nodes/utils/UVTransformNode.js"></script>

<!-- Phong Material -->
<script src="js/nodes/materials/PhongNode.js"></script>
<script src="js/nodes/materials/PhongNodeMaterial.js"></script>

<!-- Standard Material -->
<script src="js/nodes/materials/StandardNode.js"></script>
<script src="js/nodes/materials/StandardNodeMaterial.js"></script>

<script src="js/Detector.js"></script>
<script src="js/libs/stats.min.js"></script>

Expand Down Expand Up @@ -89,14 +155,20 @@

if ( child.isMesh ) {

child.material.envMap = envMap;
child.material.environment = new THREE.CubeTextureNode( envMap );

child.material.build();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A visual node editor that would generate the GLSL would expose "inputs". Rather than having node( type input) after compiling it should just be type input, if that makes sense? It feels weird to have to rebuild it, but this is basically in lieu of needsUpdate?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I don't think I quite follow your question, but yes, .build() is analogous to .needsUpdate here.


}

} );

scene.add( gltf.scene );

}, undefined, function ( e ) {

console.error( e );

} );

renderer = new THREE.WebGLRenderer( { antialias: true } );
Expand Down