Adverti horiz upsell
Internal Variables in a Simple Color Suppression Macro
Internal Variables in a Simple Color Suppression Macro
mplec, added 2005-09-17 22:22:33 UTC 29,276 views  Rating:
(3 ratings)
Page 1 of 4

In the service of building a trivial color suppression macro, this tutorial illustrates two really important concepts in Shake: thinking in parallel, which will influence the overall design of the macro, and variable dependencies in macros, which will come into play when we get into the implementation details.

Many artists make the mistake of thinking about what they're doing in Shake on the level of individual pixels and end up writing expressions on ColorX/LayerX/WarpX nodes in order to build up effects that vary based on input pixel values. Unfortunately, by their very nature as general-purpose tools these nodes are nowhere near as efficient as their special purpose cousins like Add or Mult. Thinking of operating in parallel, as if on the image as a whole, every pixel at once, rather than on individual pixels, can lead you to build much more efficient processing trees. Unfortunately, many of us get in the habit of thinking serially and trying to specify pixel-by-pixel what we want Shake to do. For example, to suppress the level of green in a pixel to the level of blue in it, we might use a ColorX node with the gExpr parameter set to

(g > b) ? b : g

which means, "if green is greater than blue, use blue, otherwise use green". This would indeed give us the result we're after: green values unchanged where they don't exceed blue, and clipped at blue otherwise. We could also implement it more simply as just

min(g, b)

The output is again the blue values where green exceeds blue and green values where green is less than blue.

Unfortunately both of these require use of ColorX. The whole thing would work a bit faster if we could find a way to do it with built-in nodes optimized for their particular tasks rather than ColorX. In this case, we could reorder the channels so that the two inputs to the Min node were the green and blue channels separately and the output was copied back into the green channel of the original image, giving us exactly the same result as the expression on ColorX did but gaining the efficiency of the optimized Min node. What about all this extra work to reorder the channels around the Min? On the surface this seems counterproductive, using four nodes rather than one, but Shake's built-in nodes are highly optimized and we also get the benefit of caching between nodes. In the long run, and particularly for complex operations and adjusting in the UI, the result is much more efficient than executing an arbitrary function for each pixel. For a one-off, this may not be worth the effort, but for something you might use over and over or turn into a macro, the efficiencies can add up to big improvements in overall render times.