Wave Generating Mel Script Shader

| 7 Comments

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.

7 Comments

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

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

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

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.

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". //

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

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.

Leave a comment

About this Entry

This page contains a single entry by published on July 22, 2005 11:59 PM.

Draw From Your Head was the previous entry in this blog.

Lighting a Sphere is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.