New approach for node setups, and more competent skin mat

Works in progress and technical screen shots.

Moderator: joepal

New approach for node setups, and more competent skin mat

Postby joepal » Thu Jul 04, 2019 9:58 am

Having grown increasingly frustrated with the complexity of the material setup for the importer in the makehuman plugin for blender (MPFB), I've rewritten large parts of it to instead use json templates to setup node groups. This is currently how the default definition file looks:

Code: Select all
{
  "groups": {

  },
  "nodes" : {
    "output": {
      "type": "ShaderNodeOutputMaterial",
      "label": "Material output",
      "location": [350, 100],
      "group": "",
      "values": {},
      "create": true
    },
    "principled": {
      "type": "ShaderNodeBsdfPrincipled",
      "label": "Principled",
      "location": [0, 100],
      "group": "",
      "values": {
        "Base Color": [0.8, 0.8, 0.8, 1.0]
      },
      "create": true
    },
    "diffuseTexture": {
      "type": "ShaderNodeTexImage",
      "label": "diffuseTexture",
      "location": [-400, 100],
      "group": "",
      "values": {},
      "imageData": {
        "path": "",
        "colorspace_settings_name": "sRGB"
      },
      "create": false
    },
    "normalMapTexture": {
      "type": "ShaderNodeTexImage",
      "label": "normal map texture",
      "location": [-600, -500],
      "group": "",
      "values": {},
      "imageData": {
        "path": "",
        "colorspace_settings_name": "Non-Color"
      },
      "create": false
    },
    "bumpMapTexture": {
      "type": "ShaderNodeTexImage",
      "label": "normal map texture",
      "location": [-600, -200],
      "group": "",
      "values": {},
      "imageData": {
        "path": "",
        "colorspace_settings_name": "Non-Color"
      },
      "create": false
    },
    "bumpOrNormal": {
      "type": "ShaderNodeNormalMap",
      "label": "normal map",
      "location": [-300, -300],
      "group": "",
      "values": {
        "Strength": 1.0
      },
      "create": false
    },
    "bumpAndNormal": {
      "type": "ShaderNodeNormalMap",
      "label": "normal map",
      "location": [-300, -300],
      "group": "",
      "values": {
        "Strength": 1.0
      },
      "create": false
    },
    "bumpMap": {
      "type": "ShaderNodeBump",
      "label": "bump map",
      "location": [-100, -300],
      "group": "",
      "values": {
        "Strength": 0.5
      },
      "create": false
    }
  },
  "connections" : [
    {
      "outputNode": "principled",
      "outputSocket": "BSDF",
      "inputNode": "output",
      "inputSocket": "Surface"
    },
    {
      "outputNode": "diffuseTexture",
      "outputSocket": "Color",
      "inputNode": "principled",
      "inputSocket": "Base Color"
    },
    {
      "outputNode": "diffuseTexture",
      "outputSocket": "Alpha",
      "inputNode": "principled",
      "inputSocket": "Alpha"
    },
    {
      "outputNode": "normalMapTexture",
      "outputSocket": "Color",
      "inputNode": "bumpOrNormal",
      "inputSocket": "Color"
    },
    {
      "outputNode": "normalMapTexture",
      "outputSocket": "Color",
      "inputNode": "bumpAndNormal",
      "inputSocket": "Color"
    },
    {
      "outputNode": "bumpOrNormal",
      "outputSocket": "Normal",
      "inputNode": "principled",
      "inputSocket": "Normal"
    },
    {
      "outputNode": "bumpMapTexture",
      "outputSocket": "Color",
      "inputNode": "bumpMap",
      "inputSocket": "Height"
    },
    {
      "outputNode": "bumpAndNormal",
      "outputSocket": "Normal",
      "inputNode": "bumpMap",
      "inputSocket": "Normal"
    },
    {
      "outputNode": "bumpMap",
      "outputSocket": "Normal",
      "inputNode": "principled",
      "inputSocket": "Normal"
    }
  ]
}


This will produce this node setup (for Punkduck's sport bra) :

nodes_sport_bra.png


(thanks btw Aranuvir, for doing away with the ugly transparency/mix node setup... this approach is much cleaner)

While being at it, I have also started working on a more competent skin node setup. The added benefit of having rewritten the material setup to use json files, is that I can now simply provide a separate json file for this setup, rather than rewriting the code:

Code: Select all
{
  "groups": {
    "skinGroup": {
      "label": "Skin",
      "inputs": {
        "colorMixIn": {
          "type": "NodeSocketColor",
          "value": [1.0, 0.2, 0.2, 1.0]
        },
        "colorMixInStrength": {
          "type": "NodeSocketFloat",
          "value": 0.05
        },
        "Roughness": {
          "type": "NodeSocketFloat",
          "value": 0.5
        },
        "Brightness": {
          "type": "NodeSocketFloat",
          "value": 0.0
        },
        "Contrast": {
          "type": "NodeSocketFloat",
          "value": 0.0
        },
        "Clearcoat": {
          "type": "NodeSocketFloat",
          "value": 0.2
        },
        "Clearcoat Roughness": {
          "type": "NodeSocketFloat",
          "value": 0.3
        }
      },
      "outputs": {
        "shaderOutput": {
          "type": "NodeSocketShader"
        }
      },
      "location": [0, 100],
      "create": true
    }
  },
  "nodes" : {
    "skinGroupInputs": {
      "type": "NodeGroupInput",
      "label": "Skin input",
      "location": [-800, -100],
      "group": "skinGroup",
      "values": {},
      "create": true
    },
    "skinGroupOutputs": {
      "type": "NodeGroupOutput",
      "label": "Skin output",
      "location": [600, 100],
      "group": "skinGroup",
      "values": {},
      "create": true
    },
    "output": {
      "type": "ShaderNodeOutputMaterial",
      "label": "Material output",
      "location": [350, 100],
      "group": "",
      "values": {},
      "create": true
    },
    "principled": {
      "type": "ShaderNodeBsdfPrincipled",
      "label": "Principled",
      "location": [0, 100],
      "group": "skinGroup",
      "values": {
        "Base Color": [0.8, 0.8, 0.8, 1.0]
      },
      "create": true
    },

    "diffuseTexture": {
      "type": "ShaderNodeTexImage",
      "label": "diffuseTexture",
      "location": [-800, 300],
      "group": "skinGroup",
      "values": {},
      "imageData": {
        "path": "",
        "colorspace_settings_name": "sRGB"
      },
      "create": false
    },
    "normalMapTexture": {
      "type": "ShaderNodeTexImage",
      "label": "normal map texture",
      "location": [-600, -500],
      "group": "skinGroup",
      "values": {},
      "imageData": {
        "path": "",
        "colorspace_settings_name": "Non-Color"
      },
      "create": false
    },
    "bumpMapTexture": {
      "type": "ShaderNodeTexImage",
      "label": "normal map texture",
      "location": [-600, -200],
      "group": "skinGroup",
      "values": {},
      "imageData": {
        "path": "",
        "colorspace_settings_name": "Non-Color"
      },
      "create": false
    },
    "bumpOrNormal": {
      "type": "ShaderNodeNormalMap",
      "label": "normal map",
      "location": [-300, -300],
      "group": "skinGroup",
      "values": {
        "Strength": 1.0
      },
      "create": false
    },
    "bumpAndNormal": {
      "type": "ShaderNodeNormalMap",
      "label": "normal map",
      "location": [-300, -300],
      "group": "skinGroup",
      "values": {
        "Strength": 1.0
      },
      "create": false
    },
    "bumpMap": {
      "type": "ShaderNodeBump",
      "label": "bump map",
      "location": [-100, -300],
      "group": "skinGroup",
      "values": {},
      "create": false
    },
    "colorMix": {
      "type": "ShaderNodeMixRGB",
      "label": "Color mix",
      "location": [-500, 200],
      "group": "skinGroup",
      "values": {},
      "create": true
    },
    "brightContrast": {
      "type": "ShaderNodeBrightContrast",
      "label": "Brightness and Contrast",
      "location": [-300, 100],
      "group": "skinGroup",
      "values": {},
      "create": true
    }

  },
  "connections" : [
    {
      "outputNode": "principled",
      "outputSocket": "BSDF",
      "inputNode": "skinGroupOutputs",
      "inputSocket": "shaderOutput"
    },
    {
      "outputNode": "skinGroup",
      "outputSocket": "shaderOutput",
      "inputNode": "output",
      "inputSocket": "Surface"
    },
    {
      "outputNode": "diffuseTexture",
      "outputSocket": "Color",
      "inputNode": "colorMix",
      "inputSocket": "Color1"
    },
    {
      "outputNode": "skinGroupInputs",
      "outputSocket": "colorMixIn",
      "inputNode": "colorMix",
      "inputSocket": "Color2"
    },
    {
      "outputNode": "skinGroupInputs",
      "outputSocket": "colorMixInStrength",
      "inputNode": "colorMix",
      "inputSocket": "Fac"
    },
    {
      "outputNode": "colorMix",
      "outputSocket": "Color",
      "inputNode": "brightContrast",
      "inputSocket": "Color"
    },
    {
      "outputNode": "brightContrast",
      "outputSocket": "Color",
      "inputNode": "principled",
      "inputSocket": "Base Color"
    },
    {
      "outputNode": "skinGroupInputs",
      "outputSocket": "Brightness",
      "inputNode": "brightContrast",
      "inputSocket": "Bright"
    },
    {
      "outputNode": "skinGroupInputs",
      "outputSocket": "Contrast",
      "inputNode": "brightContrast",
      "inputSocket": "Contrast"
    },
    {
      "outputNode": "skinGroupInputs",
      "outputSocket": "Roughness",
      "inputNode": "principled",
      "inputSocket": "Roughness"
    },
    {
      "outputNode": "skinGroupInputs",
      "outputSocket": "Clearcoat Roughness",
      "inputNode": "principled",
      "inputSocket": "Clearcoat Roughness"
    },
    {
      "outputNode": "skinGroupInputs",
      "outputSocket": "Clearcoat",
      "inputNode": "principled",
      "inputSocket": "Clearcoat"
    },
    {
      "outputNode": "diffuseTexture",
      "outputSocket": "Alpha",
      "inputNode": "principled",
      "inputSocket": "Alpha"
    },
    {
      "outputNode": "normalMapTexture",
      "outputSocket": "Color",
      "inputNode": "bumpOrNormal",
      "inputSocket": "Color"
    },
    {
      "outputNode": "bumpOrNormal",
      "outputSocket": "Normal",
      "inputNode": "principled",
      "inputSocket": "Normal"
    }
  ]
}


This will create a node group with convenience inputs:

nodes_group.png


Which internally currently looks like this:

nodes_group1.png


In the longer run I plan on adding support for a generated bump map for skin pores etc, but for now it at least makes it easy to vary skin tone and shininess of imported characters even when they come from the same skin material.

Downside is that I pretty much assume this won't work in blender 2.79, it's 2.80 only.

For now all these changes reside in a feature branch: https://github.com/makehumancommunity/m ... node_setup, but unless someone points out an obvious flaw, I'll probably merge this to master soon.
Joel Palmius (LinkedIn)
MakeHuman Infrastructure Manager
http://www.palmius.com/joel
joepal
 
Posts: 4455
Joined: Wed Jun 04, 2008 11:20 am

Re: New approach for node setups, and more competent skin ma

Postby joepal » Thu Jul 04, 2019 3:01 pm

All three characters have the same skin here, but I have varied the brightness and skin color mixin parameters. Personally, I'm thinking this is pretty convenient...

nodes_skintone.png
Joel Palmius (LinkedIn)
MakeHuman Infrastructure Manager
http://www.palmius.com/joel
joepal
 
Posts: 4455
Joined: Wed Jun 04, 2008 11:20 am

Re: New approach for node setups, and more competent skin ma

Postby RobBaer » Fri Jul 05, 2019 4:03 pm

Without having time to play, this looks like a nice approach. "Everything nodes" is the latest Bender mantra.

Theoretically, this won't affect .dae and .fbx exporters/importers?
User avatar
RobBaer
 
Posts: 1204
Joined: Sat Jul 13, 2013 3:30 pm
Location: Kirksville, MO USA

Re: New approach for node setups, and more competent skin ma

Postby jcpalmer » Sat Jul 06, 2019 5:13 pm

Representing this as data is probably a good idea from both a design & flexiblity standpoint. I know my exporters (JSON & inline Javascript) bound for BabylonJS right now are probably gonna choke, on this though. I have also looked at the source for glTF exporter, & think it will not work. I realize Rob was not referring to downstream of Blender when he commented, but coming up with something really custom will be trouble unless it just going to be used in Blender.

Seems some of this node group is just holding values for principled, seems like just assigning the principled node would have both the same effect, yet make it much easier for downstream.

I am also wondering about the use of principled's subsurface color for skin. I can export sub-surface & BabylonJS uses it (don't think glTF has it yet). I ignore it when the color is the default red. Had to also ignore it because you are setting it to white by also checking that subsurface > 0. White is terrible, I am not sure why you are changing it. Given that I did some tests of other objects, & think it might be useful for skin. I have not gotten around to putting in playing with subsurface in my PBR export tester (see my topic in this sub-forum), but here is a side-by-side snapshot I did while adding subsurface to the exporter.
gus_pbr.JPG

The cookie is a little thin & this is shown in an environment texture with a very bright sun from the back right. Certain areas kind of look like sun burn. If I get a chance, I'll see if doing something on skin seems near equivalent. Please keep this off the master branch for a while.
jcpalmer
 
Posts: 115
Joined: Tue Dec 16, 2014 4:14 pm

Re: New approach for node setups, and more competent skin ma

Postby joepal » Sun Jul 07, 2019 1:26 pm

Seeing these comments I realize I have been very unclear regarding what these changes are. To make things clearer:

  • All this is blender only
  • All changes are in the blender side of the importer, basically in this code file of the MPFB: https://github.com/makehumancommunity/m ... aterial.py
  • None of this touches anything in the makehuman codebase.
  • No changes have been done to how materials are handled in makehuman, nor are such changes planned. At least not now.

The goal is primarily to refactor the code that sets up materials in blender when running the blender importer in MPFB, largely because that code was messy and difficult to extend. The materials are still created from the same material info (basically the hashed MHMAT file) that comes from makehuman, same as before.

A secondary goal is to open up for a few optional extras in blender when it comes to setting up nodes for skin materials specifically. If not using this option, you'll get the same rather simple diffusetex/normalmap/principled as you've gotten before. With the extras you'll currently also get nodes set up for mixing in a secondary color and adjusting brightness/contrast for the diffuse texture. Planned is to also set up a procedural bump for skin pores.

Had to also ignore it because you are setting it to white by also checking that subsurface > 0. White is terrible, I am not sure why you are changing it.


I was not aware that I did. As far as I know, I have not set anything related to SSS in MPFB. Grepping for "sss" and "subsurface" in the code, I find nothing related to sss either:

Code: Select all
15:20:17 [joepal@ligur makehuman-plugin-for-blender]$ grep -i -r sss *
blender_source/MH_Community/kinect_sensor/to_kinect2.py:        self.processSide(armature, meshes, True )
blender_source/MH_Community/kinect_sensor/to_kinect2.py:        self.processSide(armature, meshes, False)
blender_source/MH_Community/kinect_sensor/to_kinect2.py:    def processSide(self, armature, meshes, isLeft):

15:20:21 [joepal@ligur makehuman-plugin-for-blender]$ grep -i -r subs *
blender_source/MH_Community/mh_sync/import_body_binary.py:                faceSubSet = self.faceVertIndexes[first:last]
blender_source/MH_Community/mh_sync/import_body_binary.py:                verts.extend(list(set(itertools.chain.from_iterable(faceSubSet))))
blender_source/MH_Community/mh_sync/import_body_binary.py:            subdiv = self.obj.modifiers.new("Subdivision", 'SUBSURF')
blender_source/MH_Community/mh_sync/import_body_binary.py:                subdiv = proxy.obj.modifiers.new("Subdivision", 'SUBSURF')
blender_source/MH_Community/kinect_sensor/kinect2_runtime.py:        # This test is only performed once.  Subsequent calls just echo first test, so can be used in UI polling
Joel Palmius (LinkedIn)
MakeHuman Infrastructure Manager
http://www.palmius.com/joel
joepal
 
Posts: 4455
Joined: Wed Jun 04, 2008 11:20 am

Re: New approach for node setups, and more competent skin ma

Postby jcpalmer » Mon Jul 08, 2019 8:37 pm

After more checking, this was a 2.80 transition change, I seemed to have strattled. In 2.79, the default was a shade of red. It did not change to white in 2.80 until very recently. It is still in my screen shots of how I am mapping for export.
Principled_mapping_PBR.jpg


Subsurface where I export to is not implemented the same as it is in Blender, but I have just mapped the Subsurface property > 0 as the sole switch as to whether to export or not. I set the value == to the amount of transparency. I also got really good results. Here is a pastie red head, using subsurface & turning roughness all the way up on the hair.
redhead_pbr.JPG

If subsurface works at all like here, this might be another option, which will also might be easier to export. As long as I have an option to not get a node group, I am fine.
jcpalmer
 
Posts: 115
Joined: Tue Dec 16, 2014 4:14 pm

Re: New approach for node setups, and more competent skin ma

Postby joepal » Tue Jul 30, 2019 9:52 am

Continuing work on the optional enhanced skin blender material, I have now added a procedural texture for skin pores. The effect is subtle, but in the first image you have the default skin (with no pores), and in the second image you have the enhanced skin (with pores).

newSkinMat-default.png


newSkinMat-enhanced.png


The effect is most visble if you click on the second image and look on the breast side in the lower left corner of the image, or on the shoulders.

Control of the pores is done via group inputs:

newSkinMat-settings.png
newSkinMat-settings.png (15.79 KiB) Viewed 16917 times


All this is still in a feature branch: https://github.com/makehumancommunity/m ... node_setup
Joel Palmius (LinkedIn)
MakeHuman Infrastructure Manager
http://www.palmius.com/joel
joepal
 
Posts: 4455
Joined: Wed Jun 04, 2008 11:20 am

Re: New approach for node setups, and more competent skin ma

Postby joepal » Sun Aug 04, 2019 11:16 am

I've now pushed this to master on github, and made a rebuild. I haven't tested the 2.79 zip properly, as moving onwards I don't think it makes much sense to support anything other than 2.80.

You can get the new version of the plugin here: https://github.com/makehumancommunity/m ... stribution
Joel Palmius (LinkedIn)
MakeHuman Infrastructure Manager
http://www.palmius.com/joel
joepal
 
Posts: 4455
Joined: Wed Jun 04, 2008 11:20 am

Re: New approach for node setups, and more competent skin ma

Postby ecke101 » Sun Aug 04, 2019 10:51 pm

Looks nice! I have an idea for new eyes + shaders, but I don't know if it would be possible to get it to work with MakeHuman.
Basically I modelled the cornea with a glass shader and the rest with a standard Principled BSDF.
Also made the pupil a hole and added a shape key to change the size.
As you can see it looks much better especially from the side than the standard eyes.
You can also change hue and saturation to get other eyecolors from the same texture.

mh-neweye1.JPG


Green eye with small pupil, shader nodes for everything but the cornea
mh-neweye2.JPG


Blue eye with big pupil, shader nodes for the cornea
mh-neweye3.JPG
ecke101
 
Posts: 21
Joined: Thu May 09, 2019 6:59 pm

Re: New approach for node setups, and more competent skin ma

Postby joepal » Mon Aug 05, 2019 8:15 am

Yeah, eyes is next on my list of things that could be improved.

However, I'm hesitant to override geometry that comes from MH. If there is an alternate mesh for eyes, it fits better as an asset in the asset repo.

In the longer run, I think we'll have to improve material handling of assets too. Maybe it'd be possible to include hints for node setups together with the normal MHMAT file. Specifying a glass shader for eyes could be an example where this might be relevant.
Joel Palmius (LinkedIn)
MakeHuman Infrastructure Manager
http://www.palmius.com/joel
joepal
 
Posts: 4455
Joined: Wed Jun 04, 2008 11:20 am

Next

Return to WIP (Work In Progress)

Who is online

Users browsing this forum: No registered users and 1 guest