Forum: Blender


Subject: Blender Python Shader (Cycles) Automation

RobynsVeil opened this issue on Oct 18, 2015 · 32 posts


RobynsVeil posted Sun, 25 October 2015 at 6:29 AM

Not sure if anyone wants to play with this, but here goes. This is very much a proof-of-concept thing this far in, nothing more. I won't talk to suitability or anything else: just having a wee bit of fun. Here is the code:

# FullSkin024.py
# 
# Copyright (c) 25-Oct-2015, Robyn Hahn
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ***** END GPL LICENCE BLOCK *****

bl_info = {
    "name": "Simple skin shader for Poser Figures",
    "author": "Robyn Hahn",
    "version": (0, 2, 4),
    "blender": (2, 76, 0),
    "location": "-= Not a real addon For Blender, yet =-",
    "description": "Generates a simple Cycles shader for a Poser figure",
    "warning": "early development",
    "wiki_url": "http://0.0.0.1",
    "category": "Simple Material Script"}

import bpy
import os.path

"""
These are the items you change:
path     ... the fully-qualified path to your texture files like C:MyDirMyTex
curr_obj ... the name of your imported V4 figure   
clr files... colour maps 
bmp files... bump maps
"""
path = '/home/robyn/Documents/Blender/Projects/AllTextures/AllSkin/textures/'
curr_obj = bpy.data.objects['V4']
clrLimbs = 'Syri_Limbs.jpg'
bmpLimbs = 'Syri_LimbsB.jpg'
clrTorso = 'Syri_Torso.jpg'
bmpTorso = 'Syri_TorsoB.jpg'
clr_Face = 'Syri_Face.jpg'
bmp_Face = 'Syri_FaceB.jpg'



# sets renderer to Cycles
if bpy.context.scene.render.engine == 'BLENDER_RENDER':
    bpy.context.scene.render.engine = 'CYCLES'


# class builds mat-specific node set (shader)
class buildShader():
    def __init__(self, cObj, cRegion, ImgClr, ImgBum=None):
        self.selObj = cObj
        self.Region = cRegion
        self.ImgCol = ImgClr
        self.ImgBmp = ImgBum

        self.selObj.select = True
        
        self.selMats = self.selObj.active_material
        self.selMats.use_nodes = True
        
        self.treeNodes = self.selMats.node_tree
        self.nodeLinks = self.treeNodes.links
        
        self.makeSkin()
    
    def makeSkin(self):
        # clears existing nodes, if any
        for n in self.treeNodes.nodes:
            self.treeNodes.nodes.remove(n)
            
        # create nodes: Texture Coordinate and Mapping
        shaTcd = self.treeNodes.nodes.new('ShaderNodeTexCoord')
        shaMap = self.treeNodes.nodes.new('ShaderNodeMapping')
        
        # create node: Colour Image Texture
        ImgCol = self.treeNodes.nodes.new('ShaderNodeTexImage')    
        ImgCol.image = self.ImgCol
        ImgCol.color_space = 'COLOR'
        
        # create node: Bump Image Texture
        ImgBmp = self.treeNodes.nodes.new('ShaderNodeTexImage')    
        ImgBmp.image = self.ImgBmp
        ImgBmp.color_space = 'NONE'


        # create nodes: Diffuse, set second input [1] roughness to .15
        shaDif = self.treeNodes.nodes.new('ShaderNodeBsdfDiffuse')
        shaDif.inputs[1].default_value = .15
        
        # create node: Translucent
        shaTrn = self.treeNodes.nodes.new('ShaderNodeBsdfTranslucent')
        shaTrn.inputs[0].default_value = [.8, .22, .06, 1]
        
        # create node: Glossy
        shaGls = self.treeNodes.nodes.new('ShaderNodeBsdfGlossy')
        shaGls.inputs[1].default_value = .12

        # create node: Mix-RGB
        clrMix = self.treeNodes.nodes.new('ShaderNodeMixRGB')
        clrMix.inputs[0].default_value = .1
        clrMix.inputs[2].default_value = [.5, .35, .275, 1]

        mathMl = self.treeNodes.nodes.new('ShaderNodeMath')
        mathMl.operation = 'MULTIPLY'
        mathMl.inputs[1].default_value = .01

        shaMx3 = self.treeNodes.nodes.new('ShaderNodeMixShader')
        shaMx2 = self.treeNodes.nodes.new('ShaderNodeMixShader')
        shaMx1 = self.treeNodes.nodes.new('ShaderNodeMixShader')
        
        # create node: Material Output (sort-of like PoserSurface)
        shaOut = self.treeNodes.nodes.new('ShaderNodeOutputMaterial')

        # Set node locations, roughly
        shaTcd.location = -850, 300
        shaMap.location = -600, 300
        ImgCol.location = -200, 400
        ImgBmp.location = -200, 200
        shaDif.location = 0, 400
        shaTrn.location = 0, 200
        clrMix.location = 0, 100
        shaMx3.location = 200, 400
        shaMx2.location = 400, 400
        shaGls.location = 400, 100
        shaMx1.location = 600, 400
        mathMl.location = 600, 100
        shaOut.location = 800, 300

        # Link nodes: tex cood and mapping
        self.nodeLinks.new(shaTcd.outputs[2], shaMap.inputs[0])
        self.nodeLinks.new(shaMap.outputs[0], ImgCol.inputs[0])
        self.nodeLinks.new(shaMap.outputs[0], ImgBmp.inputs[0])
        # Link nodes: clr and bmp
        self.nodeLinks.new(ImgCol.outputs[0], shaDif.inputs[0])
        self.nodeLinks.new(ImgCol.outputs[0], clrMix.inputs[1])
        self.nodeLinks.new(ImgBmp.outputs[0], mathMl.inputs[0])
        # Mixing colorMap and Translucent ( reddish )
        self.nodeLinks.new(shaDif.outputs[0], shaMx3.inputs[1])
        self.nodeLinks.new(shaTrn.outputs[0], shaMx3.inputs[2])
        shaMx3.inputs[0].default_value = .065
        # Mixing ClrMap/Translu and ClrMix ( beige )
        self.nodeLinks.new(shaMx3.outputs[0], shaMx2.inputs[1])
        self.nodeLinks.new(clrMix.outputs[0], shaMx2.inputs[2])
        shaMx2.inputs[0].default_value = .05
        # Mixing ClrMap/Transl/ClrMix and Glossy
        self.nodeLinks.new(shaMx2.outputs[0], shaMx1.inputs[1])
        self.nodeLinks.new(shaGls.outputs[0], shaMx1.inputs[2])
        shaMx1.inputs[0].default_value = .05
        
        # Output
        self.nodeLinks.new(shaMx1.outputs[0], shaOut.inputs[0])
        self.nodeLinks.new(mathMl.outputs[0], shaOut.inputs[2])
        
        return self.selMats
        

# make sure your figure is selected and nothing else
# bpy.ops.object.select_all(action='DESELECT')
bpy.context.object.active_material_index = 0

path = '/home/robyn/Documents/Blender/Projects/AllTextures/AllSkin/textures/'
curr_obj = bpy.data.objects['V4']

"""So far, this will set the skin shader for any limbs materials"""
for i in range(27):
    bPasteTex = False 
    curr_obj.active_material_index = i
    matName = curr_obj.active_material.name
    matType = matName[0:1]
    if matType == '3':
        img_Clr = clrLimbs
        img_Bmp = bmpLimbs
        bPasteTex = True
    if matType == '2':
        img_Clr = clrTorso
        img_Bmp = bmpTorso
        bPasteTex = True
    if matType == '1':
        img_Clr = clr_Face
        img_Bmp = bmp_Face
        bPasteTex = True

    if bPasteTex:
        ImgColour = path + img_Clr
        ImgBump = path + img_Bmp
        imgC = bpy.data.images.load(filepath = ImgColour)
        imgB = bpy.data.images.load(filepath = ImgBump)

        newMat = buildShader(curr_obj, 'Skin', imgC, imgB)

At this point, this simple script paints V4 with your favourite skin textures and a shader of sorts. If you want to manually play with the code, you can tweak the values.

Here are the steps to take to make this work:

-- Save the content of the above script to a plain-text editor file, call it whatever you want.
         (I call mine 'FullSkin024.py', because it's Python code, version .24.)
-- Open Blender (getting rid of the default cube and that)
-- File -> Import -> Wavefront (obj) ... navigate to your Vicky, select her OBJ (not her MTL), then chose the following Import settings:
---- Untick Smooth Groups and untick Lines and everything in Split By
---- Tick Keep Vert Order and tick Poly Groups
-- Import OBJ
-- Click on her in the scene, then hit [S] (for scale), 10
-- Select Scripting from the Scene Selector (next to 'Help') - usually says 'Default' by default 😉
-- In the Text Editor section, select Open and navigate to the code file (the one I call 'FullSkin024.py')
-- Scroll down to line 44 and make changes to:
---- path
---- name of your Vickie - whatever she's called in Outliner
---- the names of your V4 texture (colour) and bump files for the face, torso and limbs
-- Run the script

I'll sit over here in Oz with my fingers crossed hoping it will work for you. 😅

If this actually works, you can save the script with the changes you put in.

If anyone actually tries this, please let me know if it worked or if you ran into dramas or whatever. 🙂

Monterey/Mint21.x/Win10 - Blender3.x - PP11.3(cm) - Musescore3.6.2

Wir sind gewohnt, daß die Menschen verhöhnen was sie nicht verstehen
[it is clear that humans have contempt for that which they do not understand] 

Metaphor of Chooks