View Full Version : Generate a texture map from particle data?

08 August 2008, 02:21 AM
Hi guys, me again.

I've got a whole tonne of particles being shot at a polygon object. When they collide, a new particle is emmitted with a goalU and goalV of the spot where they struck.

What I would like to do, and I don't know if it's possible, is on every frame to make a texture with a spot on it, corresponding to each particles goalU and goalV, and then save this file out for processing.

Ultimately I'm going to be blurring these maps a little bit, and applying them back to the model as a transparency map. The ide being that when a particle strikes, it sticks, and that spot of the model becomes opaque.

I don't even know if this is possible, but thanks so much for your time :)

08 August 2008, 09:21 AM
There's a couple of ways around it, probably more. One way to do it, involving the Maya Software renderer, could be this...

Create a samplerInfo node.
Create a ramp (delete the attached place2dTexture node, if any).
Create a shader, a Lambert is fine.

Make the ramp go from black in the bottom to white in the top. Also, setting the ramps "interpolation" to "Exponential Up" might give a smoother result.
Connect the outColor of the ramp to ie. the incandescence of the Lambert.

Assign the Lambert to the geometry that the particles should have effect on (in your case the surface they stick to).

Then enter this as an expression - but NOT as a particle type of expression (like runtime before dynamics and that sort of thing), just ordinary per frame type of expression.
As usual adjust for the specific names of the nodes you have in your case.

vector $samplePoint = <<(samplerInfo1.pointWorldX),(samplerInfo1.pointWorldY),(samplerInfo1.pointWorldZ)>>;

float $allParticlePositions[] = `getAttr particle2.position`;
int $numberOfParticles = size($allParticlePositions)/3;;

float $sum = 0;
for($i=0; $i<$numberOfParticles; $i++) {
int $xComp = $i*3;
int $yComp = ($i*3)+1;
int $zComp = ($i*3)+2;
vector $particlePos = <<($allParticlePositions[$xComp]),($allParticlePositions[$yComp]),($allParticlePositions[$zComp])>>;
float $distance = mag($particlePos - $samplePoint);
$sum += 1-smoothstep(0.1,0.2,$distance);

ramp1.vCoord = clamp(0,1,$sum);

The expression looks at all particle positions (in this case for particle2) and finds the distance from the particle to the point being renderered (getting the point from the samplerInfo), and pipes a result into the ramp V coordinate.

Try rendering, using Maya Software renderer, and you should see bright spots where the particles are sitting on or very close to the surface. Alternately turn off primary visibility for the particles so they don't cover up the spots.

in the expression, what controls the radius of the spots is this:
So for a bigger effect you could set those numbers higher.
Example: smoothstep(0,5,$distance) will result in bigger and "softer" spots.
smoothstep(0.49,0.5,$distance) will result in smaller and very "hard" spots.

Next, to get this effect out as a texture file, you need to do some baking.
Again based on Maya Software renderer, the feature found in the Hypershade window menu Edit > Convert to File Texture (Maya Software) will get you there.
Only, from the menu it doesn't support baking for multiple frames in one go, so a script will help here:

//Select a surface and select a corresponding shader.
//Then call the procedure texBakeMaya with an argument for texture resolution,
//example: texBakeMaya 512
//The resolution will be used for both height and width of the resulting texture files,
//which are named "texBake.#.tga" and output to the "sourceImages" directory of the current project directory.
//The script will bake a texture for each frame of your playback range.

global proc texBakeMaya(int $resolution){

int $playbackMin = `playbackOptions -query -minTime`;
int $playbackMax = `playbackOptions -query -maxTime`;

for($i = $playbackMin; $i <= $playbackMax; $i++) {
currentTime $i;
string $fileName = ("texBake." + $i + ".tga");
string $fileNodeName[] = `convertSolidTx -antiAlias 0 -bm 1 -fts 1 -sp 0 -sh 0 -alpha 0 -doubleSided 0 -componentRange 0 -resolutionX $resolution -resolutionY $resolution -fileImageName $fileName -fileFormat "tga" -name "texBakeFile"`;
delete $fileNodeName[0];

Put the script into a text editor and save it as texBakeMaya.mel to your maya scripts directory. Restart maya, select the surface and add-select the shader made earlier, and in you MEL command line type: texBakeMaya 512
and hit enter. (The number is the pixel size of the resulting file texture. You may set it as you like).
Maya will now bake a texture for each frame of your playback range for the surface based on the assigned shader. The files will be output as .tga files in your sourceImages directory of your currect project directory. They will be named something like "texBake.#.tga"

And there you go.

There's a packaged example scene here, including expressions and script:

textureFromParticles (

Cheers, C

08 August 2008, 09:30 AM
... looks like CGTalk made a mess of a bit of the code in the first expression...

just remove spaces from (samplerInfo1.pointWorl dY)

08 August 2008, 10:17 AM
Wow, you are absolutely my hero!!

I'm really so amazed that you took SO much time out to help me with this, I'm getting all misty eyed over here :D

It's a bit late for me tonight, but I know enough about stuff to be able to read that and know it will do exactly what I want, and I'm so excited to see this in action. I tried hard to find a soluteion, and a colleague told me it couldn't be done, but I should be using "wetmaps" in realflow. Now, that's all good and well, but realflow cant import particles from Maya (not officially anyway) and I really dont have time to learn a whole packageand redo my simulation.

You're a life saver!

When I'm done I'll upload my results if you're interested?

Thanks again

08 August 2008, 11:44 AM
Well, your question coincided with a personal interest of mine, so no worries. Dry your eyes ;-)
And yeah, seeing the results would be great!

Cheers, C

CGTalk Moderation
08 August 2008, 11:44 AM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.