« Draw From Your Head | Main | Lighting a Sphere »

July 22, 2005

Wave Generating Mel Script Shader

hypnoDisk.gif
Make some waves with this custom Maya shader which uses a MEL script to generate concentric spherical waves of animated light and darkness. It's a 3D texture, so it will flow over any objects you create. The waves emanate from a Maya locator.

Step 1
Make some objects. Give them a Lambert shader.

In the example above, the plane is 20 x 20 units in the xz-plane.

Step 2
Make a Maya locator. The locator will serve to control the 3D texture. Why a locator? Just to demonstrate how to use one in this way.

Step 3
Into the hypershade drop the following nodes: a samplerInfo node, and a vectorProduct node. Set the vectorProduct node to do a point-matrix multiply.

Step 4
For the point input of the vectorProduct, use the pointObj output of the samplerInfo node. For the matrix input to the vectorProduct, use the worldInverseMatrix of the locator.

This should have the effect of expressing points on your object in the coordinate system of the locator.

waveGenHypershade.jpg

You'll be able to move the wave source around by moving the locator around.

Step 5
Into the script editor place the following MEL script.


float $currentPt[3];

$cPt[0]=vectorProduct1.outputX;
$cPt[1]=vectorProduct1.outputY;
$cPt[2]=vectorProduct1.outputZ;

float $waveSpeed = time * -0.99;
float $waveDist;
float $scalePeriod = 20;

$waveDist = sqrt($cPt[0]*$cPt[0]+$cPt[1]*$cPt[1]+$cPt[2]*$cPt[2]);
$waveDist += $waveSpeed;


$scalePeriod += .02 * noise($waveDist);

float $waveColor[3];

$waveColor[0] = sin($waveDist * $scalePeriod);
$waveColor[1] = sin($waveDist * $scalePeriod);
$waveColor[2] = sin($waveDist * $scalePeriod);

lambert2.colorR = $waveColor[0]*.5+.5;
lambert2.colorG = $waveColor[1]*.5+.5;
lambert2.colorB = $waveColor[2]*.5+.5;

noisyWaves.jpg
Do you see the bold .02 scaling the noise function in the MEL script above? Increase the .02 to something more like 2.0, and you'll see random bunching in the waves.

Adjust to taste.

You are getting very sleepy. Verrr-rr-ry sleepy.

Posted by digital artform at July 22, 2005 11:59 PM

Comments

Very nice. I wonder if it might be possible to turn that expression into a series of utility nodes...

Posted by: Chris at July 25, 2005 08:56 AM

How would you do the sine function? I'm not sure I follow, but I'd like to.

Posted by: Joseph Francis at July 27, 2005 08:51 AM

I'm still fairly new to Maya-I've followed this word for word and all I get is "Invalid use of Maya object 'Lambert2_colorB'" after executing the script. Isn't there something missing in this procedure?
Thanks, Bob

Posted by: Robert at August 16, 2005 09:15 AM

It's possible I left something out.

Without looking, I'd guess your node names are out of synch with the ones specified. Every time you make a new Lambert, for example, the number after the name increases. You need to make sure the node names you use are correct for your situation.

...also I'm wondering why there is an underscore _ instead of a dot . in your error message. Could be the reason for the problem.

Posted by: Joseph Francis at August 16, 2005 09:44 AM

Very nice work. I'm a little new to mel scripting as well. I receive the same error as Robert did. I loaded the error for you to look at.

// Error: $cPt[0]=vectorProduct1.outputX;
//
// Error: Invalid use of Maya object "vectorProduct1.outputX". //
// Error: $cPt[1]=vectorProduct1.outputY;
//
// Error: Invalid use of Maya object "vectorProduct1.outputY". //
// Error: $cPt[2]=vectorProduct1.outputZ;
//
// Error: Invalid use of Maya object "vectorProduct1.outputZ". //
// Error: float $waveSpeed = time * -0.99;
//
// Error: Invalid use of Maya object "time". //
// Error: $waveDist = sqrt($cPt[0]*$cPt[0]+$cPt[1]*$cPt[1]+$cPt[2]*$cPt[2]);
//
// Error: "$cPt" is an undeclared variable. //
// Error: $waveDist = sqrt($cPt[0]*$cPt[0]+$cPt[1]*$cPt[1]+$cPt[2]*$cPt[2]);
//
// Error: "$cPt" is an undeclared variable. //
// Error: $waveDist = sqrt($cPt[0]*$cPt[0]+$cPt[1]*$cPt[1]+$cPt[2]*$cPt[2]);
//
// Error: "$cPt" is an undeclared variable. //
// Error: $waveDist = sqrt($cPt[0]*$cPt[0]+$cPt[1]*$cPt[1]+$cPt[2]*$cPt[2]);
//
// Error: "$cPt" is an undeclared variable. //
// Error: $waveDist = sqrt($cPt[0]*$cPt[0]+$cPt[1]*$cPt[1]+$cPt[2]*$cPt[2]);
//
// Error: "$cPt" is an undeclared variable. //
// Error: $waveDist = sqrt($cPt[0]*$cPt[0]+$cPt[1]*$cPt[1]+$cPt[2]*$cPt[2]);
//
// Error: "$cPt" is an undeclared variable. //
// Error: lambert5.colorR = $waveColor[0]*.5+.5;
//
// Error: Invalid use of Maya object "lambert5.colorR". //
// Error: lambert5.colorB = $waveColor[1]*.5+.5;
//
// Error: Invalid use of Maya object "lambert5.colorB". //
// Error: lambert5.colorG = $waveColor[2]*.5+.5; //
// Error: Invalid use of Maya object "lambert5.colorG". //

Posted by: austen at October 28, 2005 03:48 PM

i almost have this working, however if i use more than one object the pattern doesn't work seemlessly across the objects-- each one has it's own pattern of lines-- they aren't connected as in the example on this page.

i tried parenting the surfaces to the locator, but that didn't help either.

any ideas?

thanks, _j

Posted by: jh at October 12, 2006 11:15 PM

I haven't looked at this in a long time, but I'd guess that if you freeze transforms on the objects they should live in the same scale again.

Posted by: Joseph Francis at October 12, 2006 11:35 PM

Post a comment




Remember Me?

(you may use HTML tags for style)