Sun, Nov 24, 4:09 PM CST

Renderosity Forums / Poser - OFFICIAL



Welcome to the Poser - OFFICIAL Forum

Forum Coordinators: RedPhantom

Poser - OFFICIAL F.A.Q (Last Updated: 2024 Nov 24 1:33 pm)



Subject: Tutorial: Creating an EZMat plugin


Snarlygribbly ( ) posted Tue, 05 August 2014 at 9:20 AM · edited Thu, 21 November 2024 at 8:02 PM

This tutorial will show you how to create an EZMat plugin.

It will make a porcelain shader based on Bagginsbill's demo in this thread: Porcelain

To follow this tutorial you will need to have:

  • A copy of EZMat build 97 installed
  • The 'Documentation for plugin authors' download
  • The 'porcelain tutorial' download
  • A decent text editor, i.e. one which does not insert hidden control codes
  • A basic familiarity with Python

All downloads for EZMat are available on my site.

This plugin will not be completely finished by the end, but will be perfectly usable. There will remain scope, though, for you to develop it further if you want.

Pleaase note that for the purposes of this tutorial I am not concerned about the quality of the shader itself - the only aim is to show how to make a working plugin. You are most welcome to make your own improvements and share them with the community, but let's not get too distracted with discussions about how effective the end result is.

Free stuff @ https://poser.cobrablade.net/


Snarlygribbly ( ) posted Tue, 05 August 2014 at 9:30 AM

Having ensured that EZMat is working in your copy of Poser, copy the ez_EZMatTemplate.py file to one of your plugin folders and rename it to ez_Porcelain.py

This is the file we shall be editing for the rest of the tutorial.

Check that you can see the plugin (Called 'Test') in your list of available plugins.

Now, from within the Poser Material Room, select a material of any object in your Poser scene. Any one will do. Apply the Porcelain.mt5 file to the selected material, so that you can see Bagginsbill's shader on it.

You should be able to see the shader showing a couple of differences to the screenshot that BB provided:

  • The nodes are laid out slightly differently
  • The image map node has en replaced with a placeholder, with the image map currently undefined. This is because we need to make the shader generic, so that it works on all materials.

Using the default settings in EZMat's Shader Helper, use the 'Align Nodes' button to make it all look a little tidier (being sure to have the appropriate material selected in EZMat).

Free stuff @ https://poser.cobrablade.net/


Snarlygribbly ( ) posted Tue, 05 August 2014 at 9:36 AM · edited Tue, 05 August 2014 at 9:36 AM

From within the Material Room, and with BB's shader dsiplayed, run the "EZMat Generator.py" script and save the output somewhere convenient with a .txt extension, so that you can easily load it into your text editor.

The 'Porcelain.txt' file in the tutorial archive is a copy of what you should have ended up with.

This text file contains a load of Python code that we can copy and paste into our plugin code. It basically contains all the commands needed to create the node structure you can see on the screen. In the next post I'll show you where to paste it in ez_Porcelain.py

Free stuff @ https://poser.cobrablade.net/


Snarlygribbly ( ) posted Tue, 05 August 2014 at 9:46 AM

Copy all of the text output by the EZMat Generator script.

Open ez_Porcelain.py and delete the last two lines which define the MakeMat method. Paste in the copied code to replace that method.

NB: I use tabs to generate whitespace. This matters in Python. Be sure to have configured your text editor to accept tabs and not convert them to spaces.

Having done this, you will see that your plugin has a new MakeMat method.

Your code should now be the equivalent of that in ez_Porcelain_01.py, which you can use to check that you have done it correctly.

Free stuff @ https://poser.cobrablade.net/


Snarlygribbly ( ) posted Tue, 05 August 2014 at 9:53 AM

We shall now personalise our plugin.

Find the init method of the EZPlugin class (line 8 in ez_Porcelain_01.py)

Give the plugin a new name, new internalname and a description.

To avoid confusion the name should be distinctive so that users do not end up with two plugins with the same name.

The internalname must be unique, to avoid problems when savin presets. I recommend you use a web domain that you own as part of the name, as no-one else should be using that.

See ez_Porcelain_02.py for the entries I have made here.

I have taken the liberty of referencing BB in the names used, to acknowledge that the shader is his work.

Free stuff @ https://poser.cobrablade.net/


Snarlygribbly ( ) posted Tue, 05 August 2014 at 10:07 AM

Ignore ez_Porcelain_03.py :-)

ez_Porcelain_04.py contains the next few changes you should make.

Right at the beginning of the MakeMat method (line 75ish) we add two assignments, to the variables diffusemap and diffusecol.

diffusemap will hold either the imagemap node being used in the shader for Diffuse colour, or None if no diffuse map can be found.

diffusecol will be set to the diffuse colour in the PoserSurface. In fact, we won't be using this - I added it in in case we needed to and never took it out again. Still, leave it in for now as it might prove useful if we do more work on the shader.

The mat.GetMap() and mat.Diffuse_Color() methods are part of the EZMat API, but are as yet undocumented. Work is being done to produce the docs right now :-)

You will notice that the MakeMat signature has also changed, to accommodate an extra parameter, p.

This parameter is passed in the Apply method of the EZPlugin class, as follows:

self.MakeMat(mat, self.pm)

BUT

It should read:

self.MakeMat(mat, self.pm.GetParameter)

Please use the corrected version, which does not appear in the tutorial files until ez_Porcelain_07.py!

You should now have the equivalent of ez_Porcelain_04.py, but with that correction in place.

Free stuff @ https://poser.cobrablade.net/


Snarlygribbly ( ) posted Tue, 05 August 2014 at 10:18 AM

Now find the code which creates the imagemap node and connects it to the HSV node.

In ez_Porcelain_04.py this is on line 138 and 146

Again, the mat.AddNode() and mat.ConnectNodes() methods are part of the undocumented EZMat API.

What we want to do is use the image map that already existed in the shader (if there was one) rather than create a new one. Also, we only want to try and connect it up if it actually exists :-)

Look at ez_Porcelain_05.py to see how these lines have been changed: we check to see if our diffusemap variable is initialised, and if so we use the node that it references and connect it to our shader.

This introduces a bug, though: the mat.RemoveOrphans() method used at or near line 87 gets rid of all the old nodes, but we want to keep the image map one. We'll address this bug soon.

Free stuff @ https://poser.cobrablade.net/


Snarlygribbly ( ) posted Tue, 05 August 2014 at 10:30 AM

Ignoring that little bug for the moment, let's turn our attention to the plugin's user interface (UI).

At line 50 of ez_Porcelain_05.py you can see the variable 'data' assigned with a bunch of nested tuples that define all the controls to be presented to the user.

Those are the default controls though, only there to provide examples of the various controls available. If you check out the equivalent assignemnt in ez_Porcelain_06.py you will see the four controls that I have chosen to implement for this plugin.

Let's look at one of them in more detail.

The first control is defined like this:

('ior',('IOR', 'float', (1.00, 2.00), 1.50, 'Index of Refraction'))

And this is what each bit of the definition means:

'ior' is the name we will use in our code to refer to this control later
'IOR' is the label that the user will see
'float' is the type of value returned by the control, in this case a floating point numerical value
'(1.00, 2.00)' is the minimum and maximum values allowed
'1.50' is the default value
'Index of Refraction' is the tooltip that appears when the mouse is over the control

These controls are managed entirely by EZMat, including the saving of presets etc.

In our code, i.e. using the conventions we have adopted for variable names, we can obtain the value of a control (e.g. the IOR control) thus:

self.pm.GetParameter('ior')

Easy :-)

Free stuff @ https://poser.cobrablade.net/


Snarlygribbly ( ) posted Tue, 05 August 2014 at 10:37 AM

In ez_Porcelain_07.py we finally fix the line:

self.MakeMat(mat, self.pm)

to read:

self.MakeMat(mat, self.pm.GetParameter)

Of course, you will have already done this earlier if you've been following along carefully :-)

In ez_Porcelain_08.py we change the SSS Scale minimum value to 0.200 instead of 1.000, to allow for more flexibility with defining the SSS characterstics.

Finally, in ez_Porcelain_09.py we comment out the mat.RemoveOrphans() line (line 82ish) nd add it to the end of the MakeMat method instead. At that point the imagemap node will have been connected up to the HSV node and therefore no longer be an orphan node, so removing the orphans is now safe

If you have implemented all the code changes described iin this tutorial, you should now have a working plugin :-)

The final version is included in the tutorial archive as 'ez_Porcelain.py'.

Feel free to ask any questions or suggest improvements.

And have fun with EZMat :-)

Free stuff @ https://poser.cobrablade.net/


aRtBee ( ) posted Tue, 05 August 2014 at 11:12 AM

To be included in the Documentation.

- - - - - 

Usually I'm wrong. But to be effective and efficient, I don't need to be correct or accurate.

visit www.aRtBeeWeb.nl (works) or Missing Manuals (tutorials & reviews) - both need an update though


heddheld ( ) posted Tue, 05 August 2014 at 11:25 AM

look forward to trying this ;-)

bit late to the party on EZ stuff (apart from snow machine lol had that for a while)

thank you for all the hard work you put in

and take care of yourself an yours


bagginsbill ( ) posted Tue, 05 August 2014 at 12:56 PM

Nice - thanks.


Renderosity forum reply notifications are wonky. If I read a follow-up in a thread, but I don't myself reply, then notifications no longer happen AT ALL on that thread. So if I seem to be ignoring a question, that's why. (Updated September 23, 2019)


parkdalegardener ( ) posted Wed, 06 August 2014 at 7:07 AM

Thanks snarly. Been waiting for this.



Privacy Notice

This site uses cookies to deliver the best experience. Our own cookies make user accounts and other features possible. Third-party cookies are used to display relevant ads and to analyze how Renderosity is used. By using our site, you acknowledge that you have read and understood our Terms of Service, including our Cookie Policy and our Privacy Policy.