在所有渲染层中将所有材质附加到对象[Maya]

时间:2017-01-19 18:14:48

标签: python python-2.7 maya

问题

将所有材质附加到对象而不切换渲染图层;从特定对象的其他渲染层获取材质。

从对象获取材料的代码

# Gets all shaders attached to the current renderLayer for all objects in "group1"
import maya.cmds as cmds

cmds.select("group1")
allChildren = cmds.listRelatives(ad=1)
for eachChild in allChildren:
    # Get the shader groups attached to this particular object
    shaderGroups = cmds.listConnections(cmds.listHistory(eachChild))
    if shaderGroups is not None:
        # Get the material attached to the shader group
        materials = [x for x in cmds.ls(cmds.listConnections(shaderGroups), materials=1)]
print materials

我知道获取放置在其他渲染层中的信息的唯一方法是切换到它们然后运行相同的代码......任何人有任何其他建议吗?

编辑:

cmds.listConnections()cmds.listHistory()以及上面两者的组合似乎提供了渲染层本身,如果附加到我从中获取材料的对象; I.E. - materials = [u'Car_Paint_Material', u'RenderLayer_BluePaint', u'RenderLayer_RedPaint']

编辑#2:

截图!

defaultRenderLayer -> Red material for selected object defaultRenderLayer - >选定对象的红色材料。

layer1             -> Green material for selected object layer1 - >选定对象的绿色素材。

Run above script to get material 运行上面的脚本来获取材料。

Run un-optimized to get object + renderLayer + material 运行un-optimized以获取object + renderLayer +材质。 它可以工作,但它必须切换渲染层才能获得该信息。

我需要一个能够在不切换渲染层的情况下获取上述信息的解决方案。

3 个答案:

答案 0 :(得分:3)

您的方法存在问题

materials = [x for x in cmds.ls(cmds.listConnections(shaderGroups), materials=1)]仅返回所选图层的着色器名称。

解决方案

以下脚本将按以下顺序存储字典中所有图层的所有模型中的所有材料;

meshName : {layerName : shader/MaterialName}

它存储在名为objectList

的字典中

使用具有1203个对象和2个渲染层(+默认渲染层)的场景测试脚本。它在几分之一秒内执行。

meshList = cmds.ls(type='mesh')
shaderList = {}
for mesh in meshList:
    shaderList[mesh]={}

#get render layers
renderLayers = [x for x in cmds.ls(type="renderLayer")]

for eachLayer in renderLayers:
    currentRenderLayerName = eachLayer
    attrib = currentRenderLayerName+'.outAdjustments'
    numberOfConnectedMeshes = len(cmds.getAttr(attrib, multiIndices=True))

    for currentMeshIndex in range(numberOfConnectedMeshes):

        queryConnection = currentRenderLayerName + '.outAdjustments['+str(currentMeshIndex)+']'
        # sometimes if you delete an object, the connection might still be active.
        # validating it with an if condition avoids errors
        if cmds.listConnections(queryConnection+'.outPlug') !=  None:

            # following line should technically return a mesh name, however it returns the transform object name
            currentTransformObject = cmds.listConnections(queryConnection+'.outPlug')[0]
            # following line is important as the 'currentTransformObject' does is the not mesh name.
            # if it does return the mesh object then just change 'currentTransformObject' to 'currentMeshName'
            # and comment out the following line
            currentMeshName = cmds.listRelatives(currentTransformObject)[0]

            currentMeshShadingGroup = cmds.listConnections(queryConnection+'.outValue')[0]
            currentShadingGroupSurfaceShader = cmds.listConnections(currentMeshShadingGroup+'.surfaceShader')

            shaderList[currentMeshName][currentRenderLayerName] = currentShadingGroupSurfaceShader

# If you only have objects on the defaultRenderLayer
# above code ignored those objects.
# following will add them to the shaderList dict
for eachMesh in shaderList:
    if shaderList[eachMesh]=={}:
        currentRenderLayerName  = "defaultRenderLayer"
        materialAppliedToObject = cmds.ls(cmds.listConnections(cmds.listConnections(
                                          cmds.listHistory(cmds.listRelatives(eachMesh, parent=1)))), 
                                          mat=1)[0]
        shaderList[eachMesh][currentRenderLayerName] = materialAppliedToObject 

这在示例场景中返回,其中包含以下三个对象。

shaderList
# Result: 
{
    u'pSphereShape0':
        {
        u'defaultRenderLayer': [u'lambert2'],
        },
    u'pSphereShape1': 
        {
        u'defaultRenderLayer': [u'anisotropic1'], 
        u'layer2': [u'anisotropic3'], 
        u'layer1': [u'anisotropic2']
        }, 
    u'pCubeShape1':
        {
        u'defaultRenderLayer': [u'phong1'], 
        u'layer2': [u'phong3'], 
        u'layer1': [u'phong2']
        },
    u'pConeShape1':
        {
        u'defaultRenderLayer': [u'blinn1'], 
        u'layer2': [u'blinn3'], 
        u'layer1': [u'blinn2']
        }
} # 

使用以下形式

查询给定网格的表面着色器到相应的图层
shaderList['pCubeShape1']['layer2']

# Result: [u'phong3'] 
# notice it returns a list.
# you have to use the index if you need only the name 
#`objectList['pCubeShape1']['layer2'][0]`

如何自定义?

您可以通过直接编辑代码来重新排列dict的顺序,或者更好的选择是您可以查询所选对象或一组对象的着色器列表,并将其以所需顺序存储在新变量中

重要

如果未将对象添加到渲染层,则不会返回相应的着色器信息。

使用

进行测试

Mental Ray / Software / Hardware 2.0 Renderers (如果你们中的任何人成功使用其他渲染器,请加上答案)

答案 1 :(得分:0)

我有一个临时解决方案:

# Gets all shaders attached to the current renderLayer for all objects in "group1"
import maya.cmds as cmds

# Create a dictionary for {"object1": ["material1", "material2"]}
objectToMaterials = {}

# List of renderlayers
renderLayers = [x for x in cmds.ls(type="renderLayer")]

# Pick each renderLayer and switch to it


cmds.select("group1")
allChildren = cmds.listRelatives(ad=1)
for eachChild in allChildren:
    if cmds.objectType(eachChild)=="mesh":
        eachChild = cmds.listRelatives(eachChild, parent=1)
        for eachRenderLayer in renderLayers:
            cmds.editRenderLayerGlobals(crl=eachRenderLayer)
            # Get the shader groups attached to this particular object
            shaderGroups = cmds.listConnections(cmds.listHistory(eachChild))
            if shaderGroups is not None:
                # Get the material attached to the shader group
                materials = [x for x in cmds.ls(cmds.listConnections(shaderGroups), materials=1)]

            objectToMaterials.setdefault(eachChild[0], []).append(eachRenderLayer)
            objectToMaterials.setdefault(eachChild[0], []).append(materials[0])

print(objectToMaterials)

# objectToMaterials = {"object1": ["defaultRenderLayer", "RenderLayer_RedPaint"], ["secondRenderLayer", "RenderLayer_BluePaint"], "object2": ["defaultRenderLayer", "RenderLayer_BluePaint"]}

答案 2 :(得分:0)

# we need a sandbox case   
collection = []
for layer in cmds.ls(type = "renderLayer"):
    members =  cmds.editRenderLayerMembers( layer, query=True)
    for i in members:
        shader_engine = cmds.listConnections(cmds.listHistory(i), type = 'shadingEngine')
        _shaders = cmds.ls(cmds.listConnections(shader_engine), materials= True)
    collection.append(dict(object = members, layer = layer, engine = shader_engine, shaders = _shaders))
print collection

[{'engine': [u'blinn2SG'], 'layer': u'defaultRenderLayer', 'object': [u'pSphere1', u'pSphereShape1', u'pSphere2', u'pSphereShape2'], 'shaders': [u'blinn2']}, {'engine': [u'lambert2SG'], 'layer': u'layer1', 'object': [u'pSphere1'], 'shaders': [u'lambert2']}, {'engine': [u'blinn2SG'], 'layer': u'layer2', 'object': [u'pSphere2'], 'shaders': [u'blinn2']}]