Skip to main content

A little substance helper

Substance is an amazing tool, i think this can be considered a fact by now. At least i had a lot of fun tinkering around with substance designer since version 4 and so far it only improved in the right ways. Even the sour acquisition from adobe doesn't really stop my enthusiasm.

A little annoyance though is the boilerplate nodes you usually create before even you can start to experiment. Setup color nodes for metalness and roughness as well as the normal node plus creating a height output, etc... Nothing horrifying, but yea, it's annoying.

img

Hence i created a little node that takes care of most of this i call "Quick Height to Textures". It takes a color and a height map and outputs all the rest. Additional parameters for metalness, roughness and ambient occlusion add more variety. Again, nothing amazing, but it shortens the setup time to the juicy experimentation phase.

img

Download

Maya: OBJ is not FBX!

Not that that would be a surprise. But even with things that should be standard Maya finds ways to fuck things up. If you export an object as FBX from Maya, it exports the material with it. If you export the same object as  an OBJ-file, the .MTL-file (which has the material definitions) uses the shading group names as references! And of course, those have no direct relevance to the material name... Why, Maya, why?

"Bad UI"-Quicky #1

Because it's better to enable the "ignore" of a setting than have the setting itself actually enable something...

badui_maya_outliner

What's wrong with "Show in Outliner" and "Use Outliner Color"...? This happens when people don't think before implementing stuff.

Another funky maya quirk!

I'm trying to write a function that selects all top level objects that have a child object. In maya that's tricky. First we need to filter out top level objects

{obj for obj in ls(transforms=True) if obj.firstParent2()==None}

This works okay. But figuring out wether it has children is a tough call in maya, because: Group objects are transforms without shape nodesShape nodes are the first child of transform nodesHence when you check a node, you cannot simply ask how many childs it has. If you filter for nodes with one or more children, you're basically get all meshes, cameras, lights and so on. If you filter for two or more, you don't get groups with only one child. Anyhow you need a lot of filtering for what should be a really small issue.

Maya scripting crap - The 3rd

I stumbled over some more marvels of maya scripting. This time it's about user interface layout. You see, sometimes you don't know the parent of a certain UI, so you have to ask maya. And how do you do that?

form = cmds.setParent(q=True)

Yes. You're pretending to set the parent, but actually get the parent! All because of that "clever" way of calling command in query mode. You hardly can get less python-codex than this.

Also there is a command called "iconTextScrollList". And it has nothing to do with icons. Nothing. Nada. Niente. How crude must the development of this program been that these kinds of errors/lazinesses happened...?

Installation routine programming in python for a 3d graphic artist workflow or how i made maya my bitch - Part 1

Every 3D artist who works with maya uses scripts. You'd be an idiot if you don't, as the base functionality of maya most often is not sufficient for every 3D modeling, rigging or animating task. But when you're in a bigger team (10 people) with a company-specific workflow, it's highly inefficient (or simply impossible) to work without a dedicated toolchain.

I wasn't sure whether i bit off too much to chew when i went on to set up the base for the toolchain at my company. My python skills and my understanding of maya's architecture sure improved over the last two years, but i felt nowhere near the level of security and control i felt with maxscript. But dang, i'd feel like the old man that i am if i would let myself scare away of that challenge!

The worldly conditions for the toolchain are pretty hefty:

  1. The target is an in-house engine and probably one of the most ill-conceived ones i've seen in my 15-year-life as a game artist. The story goes the management of this former purely 2D-focused company perceived 3D as a short-lived trend and the architecture of the engine reflects that. Add to that 3D-inexperienced coders and artists and you get an idea of the monster that i made myself a mission to tame.
  2. I'm only here for about 2 years now, but the company is far older (>20 years). Hence loads of structures are in place that i won't be able to change, no matter how much (or little) sense they make. The workflow for installing scripts was the old "copy it from the network in your script folder"-approach. Hence every artist has a different version of tools (if at all). Also due to loads of projects running pretty much parallel, every artist has different downloaded scripts that might tamper with the prefs. And ordering of new software is a painful chain of convincing superiors and waiting sometimes months for delivery. It's pretty much the wild west of 3D graphics and i'm only the deputy sheriff at best. At least i might not get shot...?
  3. Some programmers see artists more as a necessary evil, which over here seems to be grown over decades out of standard coder-artist communication differences. Creating tools for them is seen as an annoying distraction from their actual work. The philosophy "an engine is only as good as its tools to create content" is even in times of Unity3D and Unreal hardly widespread. Hence the in-house tools aren't more than a handful of buggy and unintuitive MEL-scripts. At the same time it seems the engine coders are overly protective of those hacky scripts. Conclusively i won't get rid of those scripts in the short run and will have to incorporate them in a safe way, until we manage to generate a more partner-like atmosphere.
  4. "Usability" is unknown or at best a futuristic concept around here. A script doesn't work? Well, obviously the user made a mistake! The general tools approach here boggles my mind to the point that i actually question whether the year is really 2017. As far as i understand it's a result of the company atmosphere, which is often more interested in holding somebody accountable than to actually fix a problem. And as long as "usability" is not a measurable value, it's easy to shift the blame for inefficiency between artists and coders.
  5. On the shaky plus side is the fact that projects here take "only" around 6 months and due to the inefficiency of the tools and the feedback loop, it's easy for me to make loads of iterations and tests in various workload-conditions on the tools.

So far so scary, lets research what we got on the technical side!

  1. MEL is a horrible scripting language. Its style clearly resembles a UNIX shell. I wouldn't want to code a toolchain as batch-files and as such i won't even consider using MEL.
  2. This only leaves python, which thankfully is the quasi-standard nowadays for technical artists. But which implementation to choose? With the quality of python there comes the quantity of options: Maya Python, PyMel, Maya Python API 1.0, 2.0, PySide, ... We don't want to over-engineer the codebase, as i seem to be the most python-adept around here (not a huge bar to jump though) and don't have or want to have the sole control over the toolchain. I really want to encourage collaboration with this one and further a sorta "band of brothers"-approach between the tools guys. Shit might hit the fan and i don't need pointy fingers then.

This background evaluation concludes Part one. Lets see when i get to the next one.

More Maya Scripting crap

My favourite target to complain about maya is the questionable transform node - shape node duality. This creates so many problems and i haven't really found a moment where it actually solves one. My limited knowledge of computer- and programming language design tells me that it was implemented to easier adress transform components in C or C++.

Nevertheless this system creates some unique behaviours of commands. The LS command for example doesn't know or care which transform is connected to a light shape node for example. Hence you can't ask it "Give me all light transform nodes", even though it has a "transform"-parameter. So we have this command:

ls( lights=True, transforms=True )

which returns all light shape nodes and all transform nodes of a scene. The parameters create the union of two different sets. In contrast this command:

ls( sl=True, dag=True, transforms=True )

returns all nodes that are selected, part of the hierachy and transforms. The parameters create the intersection of three sets.

Gamerz... ARG!

Wow, i'm embarrassed for calling myself a gamer since the whole shitshow around "No Mans Sky". 

Crying on internet boards for weeks about how a product is not what it was advertised as, that at least sorta sounds to me like "not having all too much of a life". I'm pretty sure at the time he said those things he thought he could make them work. In that regard you can call it a "broken promise". And yes, if you're butthurt enough, you might equate a "broken promise" with a "lie"... It's still a rather petty way to distract from the fact you paid for a product without knowing anything about it. But yea, call the people that like it "apologists", way to go doublestandard there. This shitcampaign is so out of proportion by now, it's beyond ridiculous. The "He just wanted to make a quick buck"-argument is just pure and utter evil. I work in the gambling industry and i know what "making a quick buck with idiots" really looks like. Konami took a dump on gamers and is big in gambling now. Does any gamer care? No. A guy tried to make a game that was far beyond the scope of an 8-person-team and failed, yes, that's the target for all your hate.

Just sad.

MEL is crap. Maya Python is crap. And even PyMEL is crap!

Yes, PyMel is crap. It's the best crap you get in Maya, but it's still crap. Take a look:

pm.autoKeyframe(state=True)

This SETS a value. And this

pm.autoKeyframe(query=True,state=True)

RETURNS a value. Finally this

pm.autoKeyframe.state()

delivers an ERROR. This is not how you're supposed to use Python ffs!!!

Also the "sets"-command is an abomination in Maya python. Actually, it's already in MEL, but at least it sorta follows the idiotic MEL-logic. In python it just batshit crazy. To remove an object from a set, you do this:

cmds.sets( myObject, remove=mySet )

Yes. You tell the "sets"-command to remove the mySet from myObject to actually remove myObject from mySet... head explodes... Oh yea, in pyMel it seems to not accept it's own objects anymore... I give up.

Photoshop 8-bit dither workflow

I recently watched the GDC presentation from the great Mark Ferrari. That guy does amazing things with 8-bit palettes. But a little thing struck me. When talking about his dithering techniques he stated that he hasn't found a better way to dither than either paint single pixels or use pre-defined dither masks with the "hue/satuaration"-adjustment. Very tedious! So i went out to find a better way and i might have found one.

The dithering technique i'm showing here is far from perfect and will need some handwork, but it's a great point to start from. Also it's non-destructive, dynamic and highly configureable. As such i think it's a great tool to have in any game artists toolbox.

To understand how it works you should have a good understanding of adjustment layers, precisely "posterize", "gradient map" and "pattern". And here we go:

Create dither pattern

Start with an empty image, white background. We only need a 4x4 pixel pattern with the colors black, white, 66% gray (#a8a8a8) and 33% gray (#545454) setup in this layout:

pattern

Select it, define a new pattern (Edit => Define Pattern) and call it "Dither" or something similar. This will define the dither style.

Create some black/white image to dither

We will change the colors later on, so the source image is best set to grayscale. I'm using just a demo image here, but you can use whatever you want: Shapes, paintings, etc.

img

Dither Setup

Now the magic starts. First add a pattern layer with our dither pattern right above the image and set it to something around 18% opacity.

img

Then add a posterize layer above that:

img

That already creates a nice black and white dither effect:

img

Finally we need to set a color, which can be easily done with a gradient map layer:

img

By defining a gradient, we're now able to create all kinds of dithered color variants.

imgimgimgimg

This technique is pretty versatile, as all the layers react dynamically to whatever they are superimposed on.

imgimgimg

Also, by changing the opacity of the dither pattern layer, the amount of dithering can be manipulated:

imgimgimg

And by setting the levels of the posterize layer, it's possible to add more or less color levels:

imgimg

It might also be interesting to experiment with other dithering patterns:

img

All in all this is a great technique to get a quick dithering idea. To finish up you'll still have to go in and pixel a little, but i'm positive this will spare you a lot of time. Thanks for reading and have fun creating art!