diff --git a/webgl/main.js b/webgl/main.js index 2b9c8a4..deaa191 100644 --- a/webgl/main.js +++ b/webgl/main.js @@ -575,10 +575,12 @@ function addColor(gui, color, name) { return controller; } -function addFloat(gui, parent, path, name) { +function addFloat(gui, parent, path, name, min, max) { + if(min === undefined) { min = 0; } + if(max === undefined) { max = 1; } var c = {}; c[name] = parent[path] - var controller = gui.add(c, name, 0, 1).onChange(function(e) { + var controller = gui.add(c, name, min, max).onChange(function(e) { parent[path] = c[name]; updateRender(); }); @@ -588,29 +590,39 @@ function addFloat(gui, parent, path, name) { function addGuiMaterial(gui, mat, name) { try { var matGui = gui.addFolder('Material ' + name); - function addUniform(uniform, name) { + function addUniformImpl(uniform, name, min, max) { switch(mat.uniforms[uniform].type) { case '3f': addColor(matGui, mat.uniforms[uniform].value, name); break; case 'f': case '1f': - addFloat(matGui, mat.uniforms[uniform], 'value', name); + addFloat(matGui, mat.uniforms[uniform], 'value', name, min, max); break; } } - addUniform('u_baseColor', "baseColor"); - addUniform('u_metallic', 'metallic'); - addUniform('u_subsurface', 'subsurface'); - addUniform('u_specular', 'specular'); - addUniform('u_roughness', 'roughness'); - addUniform('u_specularTint', 'specularTint'); - addUniform('u_anisotropic', 'anisotropic'); - addUniform('u_sheen', 'sheen'); - addUniform('u_sheenTint', 'sheenTint'); - addUniform('u_clearcoat', 'clearcoat'); - addUniform('u_clearcoatGloss', 'clearcoatGloss'); + function addUniform(uniform, name, min, max) { + if(!!mat.uniforms[uniform]) { + addUniformImpl(uniform, name, min, max); + } + max = Math.max(max, 10.0); + for(var i = 1; !!mat.uniforms[uniform + i]; i++) { + addUniformImpl(uniform + i, name + i, min, max); + } + } + + addUniform('u_baseColor', "baseColor", 0, 1); + addUniform('u_metallic', 'metallic', 0, 1); + addUniform('u_subsurface', 'subsurface', 0, 1); + addUniform('u_specular', 'specular', 0, 12.5); + addUniform('u_roughness', 'roughness', 0, 1); + addUniform('u_specularTint', 'specularTint', 0, 1); + addUniform('u_anisotropic', 'anisotropic', 0, 1); + addUniform('u_sheen', 'sheen', 0, 1); + addUniform('u_sheenTint', 'sheenTint', 0, 1); + addUniform('u_clearcoat', 'clearcoat', 0, 4); + addUniform('u_clearcoatGloss', 'clearcoatGloss', 0, 1); } catch(e) { //XXX diff --git a/webgl/materialx.js b/webgl/materialx.js index bd4dc6f..d65be08 100644 --- a/webgl/materialx.js +++ b/webgl/materialx.js @@ -93,6 +93,48 @@ function parse_materialx(mtlx, mtls) { var shader = get_named(shaders, shaderName); var inputs = shader.getElementsByTagName('input'); var shaderInputs = {}; + + function traverse_node(nodeName, opgraph) { + var inNode = get_named(opgraph.children, nodeName); + if(typeof inNode !== 'undefined') { + switch(inNode.tagName) { + case 'image': + { + //XXX: Handling file only here. + var file = get_named(inNode.getElementsByTagName('parameter'), 'file').getAttribute('value'); + var file_prefix = get_file_prefix(inNode); + file = file_prefix + file; + return {type: 'file', value: file}; + } + case 'constant': + { + var type = inNode.getAttribute('type'); + return traverse_node_param(get_named(inNode.getElementsByTagName('parameter'), 'value'), opgraph); + } + case 'multiply': + { + var type = inNode.getAttribute('type'); + var in1 = traverse_node_param(get_named(inNode.getElementsByTagName('parameter'), 'in'), opgraph); + var in2 = traverse_node_param(get_named(inNode.getElementsByTagName('parameter'), 'amount'), opgraph); + return {type: 'multiply', valueType: type, in1: in1, in2: in2}; + } + } + } + } + + function traverse_node_param(param, opgraph) { + if(typeof param !== 'undefined') { + var type = param.getAttribute('type'); + var value = param.getAttribute('value'); + if(type === 'opgraphnode') { + return traverse_node(value, opgraph); + } + else { + return {type: 'value', valueType: type, value: parse_mtlx_value(value, type)}; + } + } + } + outMat.shaderInputs = shaderInputs; outMat.shader = shaderName; for(var j = 0; j < inputs.length; j++) { @@ -111,17 +153,7 @@ function parse_materialx(mtlx, mtls) { var opgraph = get_named(opgraphs, opgraphName); var graphOutput = get_named(opgraph.getElementsByTagName('output'), graphOutputName); var inParam = get_named(graphOutput.getElementsByTagName('parameter'), 'in'); - if(typeof inParam !== 'undefined') { - var inNode = get_named(opgraph.children, inParam.getAttribute('value')); - if(typeof inNode !== 'undefined') { - //XXX: Handling file only here. - var file = get_named(inNode.getElementsByTagName('parameter'), 'file').getAttribute('value'); - var file_prefix = get_file_prefix(inNode); - file = file_prefix + file; - shaderInput.file = file; - shaderInput.input = {type: 'file', value: file}; - } - } + shaderInput.input = traverse_node_param(inParam, opgraph); } } } @@ -179,14 +211,24 @@ function load_materialx_shaders(path, cb, textLoader) { break; case 'value': var channelName = uNamer(); - var uniformType = mtlxTypes[node.valueType].uniformType; - var glsltype = mtlxTypes[node.valueType].glslType; + retType = node.valueType; + var uniformType = mtlxTypes[retType].uniformType; + var glsltype = mtlxTypes[retType].glslType; uniforms[uniPrefix + channelName] = {type: uniformType, value: node.value}; decls.push("uniform " + glsltype + " " + uniPrefix + channelName + ";"); ret = gen_name(); - retType = node.valueType; accessors.push(glsltype + " " + ret + " = " + uniPrefix + channelName + ";"); break; + case 'multiply': + retType = node.valueType; + var glsltype = mtlxTypes[retType].glslType; + var l = add_opgraph_node(node.in1, uNamer, uniforms, decls); + var r = add_opgraph_node(node.in2, uNamer, uniforms, decls); + for(var a in l.accessors) { accessors.push(l.accessors[a]); } + for(var a in r.accessors) { accessors.push(r.accessors[a]); } + ret = gen_name(); + accessors.push(glsltype + " " + ret + " = " + glslconvert(l.ret, l.retType, retType) + " * " + glslconvert(r.ret, r.retType, retType) + ";"); + break; } return {accessors: accessors, ret: ret, retType: retType}; }