PDA

View Full Version : How do you switch materials in the channel Box?


Bladien
03-07-2011, 07:32 PM
Hi there, I'm hoping someone can help me with a problem I'm having. If I have an object (like a sphere in the screen shot) how can I create a material switch attribute in the channel box?

So far I've created an attribute and named it "Materials" and chose Enum as the data type as that allows me to name the variables (e.g. lambert, blinn etc). This shows up in the channel box but doesn't do anything. So how do I assign properties (ie the different materials) to these two variables? I'm assuming that the expression editor can solve this problem but I've been unnsuccesful in my script writing attempts so far. Or maybe it is much easier then that. Any ideas?

Nyro
03-09-2011, 10:46 PM
The following workflow offers a theoretical solution (I say theoretical because, in practice, I for some reason couldn't get it to work properly)

1. Create two (ore more) materials

2. In the Hypergraph, add both shaders to the work area. In the HG's menu, under Options, turn off "Clear before Graphing", under Graph, choose "Output Connections".
You should now see the shaders and the associated shadingGroups.

3. Delete one of the shading groups, keep the other (lets call it 'mainSG'). Delete the incoming connection to the remaining shading group (mainSG).

4. Create a Choice node in the Hypergraph. Under Extra Attributes, select "Add New Item" twice (you now have Input[0] and [1])

5. Open the connection editor, load the first material on the left and the choice node on the right.

6. Connect the material's "outColor" attribute to the Input > Input[0] of the choice node

7. Reload the left column with the second material, connect the outColor to the Input > Input[1] attribute

8. Load the choice node on the left column, load the mainSG on the right. Connect the Output of the choice node to the surfaceShader attribute of mainSG.

9. Connect your custom enum attribute to the Selector attribute on the choice node.

in the MEL commandline, enter

sets -e -fe mainSG yourGeometryName

where you'd replace mainSG with the Shading Group name and "yourGeometryName" with the name of the object that should be assign to the materials.

Basically you should be all set up now. Unfortunately, in my tests, the renderer would still complain about the object not having assigned a surface shader. No idea why. But the theory is sound :)

ginodauri
03-10-2011, 01:04 AM
Actually this is job for choice node , and it would be elegant solution , but choice node has some problems.

So solution that i would use is to connect you shaders to layered texture , output of texture to surface shader.

And change your material in layered texture.

Nyro
03-10-2011, 08:36 AM
Actually this is job for choice node , and it would be elegant solution , but choice node has some problems.

That's quite vague. Could you be more specific?

ginodauri
03-10-2011, 05:29 PM
That's quite vague. Could you be more specific?

I don't know,I tried to pass color attributes of materials in choice node , and get black output.

That i tried with separated channels(RGB) , but get little strange rusults.

Nyro
03-10-2011, 06:56 PM
The choice node usually works as intended, it simply passes one of multiple inputs to the output, without changing anything (regarding type or value, etc.).

ginodauri
03-10-2011, 08:01 PM
I tried this setup several times and it don't work.

Try to do following maybe i'm doing something wrong.

blinn.outcolor > choice.input[0]
lambert.outcolor > choice.input[1]

choice.output > surfaceShader.outColor

Does it work?Maybe problem is not choice node?

Azrail
03-11-2011, 11:35 AM
"The choice node should do, but what if you need more than wo materials.
A quick concept that I can suggest is as follows:
// 1. Create a multi attribute of type message:
addAttr -sn mn -ln materialNames -at message -multi;
// 2. Create an enum attribute that will drive your material selector
// 3. Connect the messages of the shaders you want to assign to the inputs of the 'materialName' attribute, i guess this should be done trough mel, because there is no automated index generation trough the connection editor i.e:
connectAttr -f lambert2.message pPlane1.materialNames[2]
connectAttr -f blinn1.message pPlane1.materialNames[1]
// 4. Create a script job that reacts on changing the Enum attribute, and will connect the shader with the corresponding index to the shading group of the object. You should retrieve the data via 'listConnections', because "Message attributes have no data values".


I can't say if this is the best solution, but it can do the trick

Nyro
03-11-2011, 11:43 AM
Ginodauri, the problem is in fact not the choice node, it is the way you connected it.

The inputs to the choice node are fine, but the output of the choice node needs to be connected to the surfaceShader attribute of a ShadingGroup (which, under the hood, is just a regular Set whose members are to receive the surfaceShader (material) connected to the corresponding attribute).

Edit:

Regarding Nikolay's method: sure, something like that should work too, but I can't say I'm a big fan of using scriptJobs. They clutter the scene, they require scriptNode's in order to be saved along with the scene (or else you'll have to run it everytime you reopen the scene).

Also, the surfaceShader, volumeShader and displacementShader attributes of the shadingGroup are untyped, you can plug in anything into those attributes.

ginodauri
03-11-2011, 12:52 PM
Ginodauri, the problem is in fact not the choice node, it is the way you connected it.

The inputs to the choice node are fine, but the output of the choice node needs to be connected to the surfaceShader attribute of a ShadingGroup (which, under the hood, is just a regular Set whose members are to receive the surfaceShader (material) connected to the corresponding attribute).


Can you post exactly what are your connections because it did;t work for me.

I tried it again and it working when you separate your rgb channels , but it works only with maya software , mental ray renders black


Edit:
Problem was surface shader , when connection is to lambert.incandesence attribute it is ok.

ginodauri
03-11-2011, 01:37 PM
Here is solution:

http://forums.cgsociety.org/attachment.php?attachmentid=160235

It still needs to make separate RGB choice nodes but it works , for now :)

Nyro
03-11-2011, 01:54 PM
It seems you are confusing the material/shader with the shadingGroup.

What I meant was to connect Material1.outColor, Material2.outcolor etc. to the inputs of the choice node, and connect Choice1.output to a ShadingGroup.surfaceShader.

ShadingGroup nodes are Set nodes that are created automatically with each Material (e.g, when creating a Lambert, you get something like Lambert2SG as a ShadingGroup). The Shadinggroup is responsible for keeping track which objects get assigned a specific shader. If Lambert2.outColor is connected to Lambert2SG.surfaceShader, then all Objects (and polygons) that are members of Lambert2SG will be assigned the Lambert1 material.

When you drag and drop a shader onto an object, then that object automaticallly becomes a member of the corresponding ShadingGroup.
Say you create a Sphere (Sphere1) and assign to it the Lambert3 material. Then the following connection will be made:

pSphereShape1.instObjGroups[0] -> Lambert3SG.dagSetMembers[0]

lambert3.outColor -> lambert3SG.surfaceShader


Upon creating an object, that object automatically is assigned to the default Shader, which is lambert1, so you will automatically have the following connection:

pSphereShape1.instObjGroups[0] -> initialShadingGroup.dagSetMembers[0]

Disconnect an object from its shadingGroup and you will see in the viewport the object is no longer visible (actually, you'll just see its wireframe, because the faces are no longer shaded).

Can you post exactly what are your connections because it did;t work for me.

I did post quite the detailed process of all connections that need to be made:
http://forums.cgsociety.org/showpost.php?p=6901213&postcount=2

ginodauri
03-11-2011, 02:06 PM
Ok i understand what you mean , but choice node is not shader and can't ne assigned to shader input of shading group.

Nyro
03-11-2011, 02:16 PM
sure it can. Choice node output doesn't have its own type. The type is defined by what is plugged into the input[] attributes. It just passes through one or the other, based on selector. If you pass in the outColor of the shader (which usually goes into surfaceShader attribute anyway), then why would there be a problem?

Also, the surfaceShader, volumeShader and displacementShader attributes of the shadingGroup are untyped, you can plug in anything into those attributes (won't work with anything, but will not throw an error).

ginodauri
03-11-2011, 02:23 PM
Ok now you are saying different thing.

You sad

"""What I meant was to connect Material1.outColor, Material2.outcolor etc. to the inputs of the choice node, and connect Choice1.output to a ShadingGroup.surfaceShader."""
"""

Maybe it is misunderstanding.

But choice node output can't be directly connected to shading group.surfaceShader(it throws error)

Nyro
03-11-2011, 02:41 PM
Yes it can. :curious:

Look at the attached image for proof.

It would seriously help if you could poste the error message you're receiving here instead of simply claiming "it can't be done".

ginodauri
03-11-2011, 02:51 PM
It can be connected ,but error message:

From mr:
// Error: (Mayatomr.Shader) : initialShadingGroup: no shader assigned in material

maya software:

// Warning: line 0: Mesh shape pSphereShape1 has no valid surface shader. Not tessellated. //

i don't know , maybe you are talking about "teoretical" connection , but does this work in rendee?

Nyro
03-11-2011, 03:34 PM
My dear friend, you should really start reading what I write.

My very first post featured this as the very first line:

The following workflow offers a theoretical solution (I say theoretical because, in practice, I for some reason couldn't get it to work properly)

I'm aware that rendering throws an error. But I'm sure that the setup is sound, so all I would need to do is find the culprit, which I haven't really done yet because the OP hasn't showed up once and I'm not about to waste my time fixing a problem that has arisen from a solution which nobody is here to appreciate in the first place.

ginodauri
03-11-2011, 05:19 PM
Ok this will be my last post in this thread.

You obviously write solution to problem and don't explore does it work or not.

The reason why it don't work is because choice node is not shader and shading group don't accept choice node output because is not shader.(connection is made but it is not valid)

Or maybe you would tell that choice node is shader?

Nyro
03-11-2011, 08:20 PM
I'm honestly sorry, but this is the first time I will be totally frank on this forum: are you being wilfully dense?

The choice node is NOT a shader, the choice node is NOT anything. A lambert material is only a shader by virtue of taking the correct input, doing some sensibel stuff with it and passing out the right sort of information to its output so the shadingGroup can work with that. Same can be said for *any* node.

I'll state this for the third time: the choice node doesn't do anything with the data it receives, it simply acts as a switch to decide which of multiple incoming datastreams gets output and thus passed along down the node stream. It doesn't tamper with said data at all, it doesn't care what sort of data comes in, it simply spits that data back out unmodified.

If a lambert.outColor attribute is connected to a shadingGroup.surfaceShader attribute, then inserting a choice node inbetween the two won't change a thing, because the outColor will still be connected to the surfaceShader.

Here's an example that may be easier to grasp:

A car only runs with Diesel. There are two hoses lying around, through one flows Diesel, through the other normal Gasoline. You would obviously connect the Diesel hose to the tank of the car, right?
Now imagine someone wants to make a single hose that spits out the correct fuel type depending on the car. So he grabs both hoses, connects them inside a hydraulic apparatus that pumps the content of one of both, but not the other hoses into a new, single pipe, which then gets inserted into a car tank.
That Apparatus is neither Diesel or Gasoline, for all it cares you could plug the udder of a cow into it and it would pump MILK and pass that along. Obviously, the car won't run with milk, but the apparatus doesn't care nor will it magically stop being MILK, or DIESEL, just because it ran through the apparatus.

Let's give that apparatus a name: CHOICE NODE.

Do you understand now why I am perplexed as to why my solution only works in theory but not in practice? A material is by default connected via outColor to a shadingGroup. Inserting a choice node shouldn't make a difference and yet Maya throws an error. I don't know why and frankly I don't care because I don't have a need for this and the original poster (OP) hasn't showed up at all. If the OP needed further assistance I'd be willing to sit down and invest my spare time to find the root of the problem, which I'm sure will be something trivial. But he obviously doesn't, so I won't. End of story.

merlino3d
06-03-2011, 05:14 PM
Well, i'm trying to do something similar:
i add an attribute of enum type to a controller to make it change the texture for a rig
make an input for every file/texture outColor to the choice node
connect the output of the choice node to the lambert.color

no way it works ... :(
Any solution with the choice node or any other?
I've tried also with the Layered Texture changing the alpha of the inputs, but i can't set driven key to the file's alpha ... mmmmmmmm

P.S.: solved with "use image sequence" an setting driven key there. But that force me to rename my textures, loosing the description ... so i'll appreciate any other way that maintain the texture's name as is :)

isoparmB
06-04-2011, 10:12 AM
There are some possible solutions for this.

One would be to use a layeredShader instead of a layeredTexture and connect both of your shaders there. You could probably set up an enum attribute which is setDrivenKeyed to the alpha of the top shader, so that switching the enum attributes value would toggle this to reveal/conceal the shader underneath.

Another way would be to set up an enum attribute which toggles the surfaceShader connections of the shadingGroup to which your geometry are assigned to (from material A to material B). This is what you really want to toggle: you don't want to change what's connected to the material, the quickest way would be to just change what shader is assigned to each sahdingGroup. This would be done via an expression which performs mel commands (not normally recommended, I know, as this will break if your object's names change via referencing or name conflicts. doing a shadingGroup1.surfaceShader = shader.outColor won't work because you can only connect float, int or bool attributes this way. ). To get this to work for multiple references or be safe from name space conflicts, though I remember having to set up an expression to get it to have id attributes so each instance of an asset in a scene could identify itself and only connect and disconnect nodes for that asset (and not for any other copies of that asset in the scene): link (http://forums.cgsociety.org/showthread.php?f=89&t=466696).

Or a quick and dirty way would be to just use render layers and have different materials assigned in different layers for your master file. Just remember to disable/enable which layer renders based on what you need.

rapsalands
06-04-2011, 07:04 PM
were u all looking for this.............
http://www.youtube.com/watch?v=HoPrCPzYxh0

merlino3d
06-10-2011, 03:25 AM
Hi isoparmB,
thanks for the reply. Actually i prefer do this work in the hypershade, so i'll do a try with the layeredShader changing the alpha for every material connected and making a driven key. My doubt now is if that way at the render time this trick will eat a lot of ram, but i'll discover this week end with some time to test it! (i don't know if it charges the texture in the ram even if the alpha of a material is set to 0)

CGTalk Moderation
06-10-2011, 03:25 AM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.