Author Topic: HowTo: Using emitters to give the illusion of self-randomizing textures  (Read 512 times)

Legacy_OldTimeRadio

  • Hero Member
  • *****
  • Posts: 2307
  • Karma: +0/-0


               Below are some pictures of c_yinnkeep.mdl with texture variations to make him look a little more interesting and unique.  He's a non-dynamic model with TGA (not PLT) textures, supermodeled into a_ba.mdl for his animations.  He's one of about 50 stock NPC appearances in the Toolset and if you've seen him once you've probably seen him 10,000 times.  Like the rest of the NPC appearances, he gets used again and again along with the rest of them to populate towns, cities, etc.  And he and they always look exactly the same.  ':crying:'

But as I said, I've made some texture variations to help him look a bit more unique.  How many different models would it take to get this number of variations in-game?
'Posted'Posted
'Posted'Posted
'Posted'Posted

What if I said that you were looking at just one model? One model which randomizes itself, or more accurately, randomizes certain details which make us believe it is unique.  And all without using dynamic parts, creating extra models or spending time editing 2DA files.

How it's done and why it works: Emitters can have animated textures on them.  Animated textures are stored as individual frames, one after the other, on a big sheet called a "sprite sheet".  Here's an example of a sprite sheet.  Normally, the grid of frames in a sprite sheet are played one after the other to give the illusion of one continuous movement of a thing, like the red smoke in my example.

 But that's not the only way a sprite sheet can be used.  One can also put different images in each one of the grid frames and set up the emitter in such a way as to cause it to pick just a single frame's texture from a sprite sheet and use that without displaying others: A random texture picker!

Using the random texture as a decal to overlay a model's main texture gives the illusion of variation- especially when a given model contains more than one random texture picking emitter.  With this method, certain models like NPC's, horde creatures or placeables can be made to look more unique without the overhead of actually using entirely different textures for each variation and all the extra models that go with it.

Here is an image showing a randomly generated inkeep and the sprite sheets which act as the pool of potential textures:
'Posted

Some decal emitters were used more than once.  There are 4 freckle emitters, for instance, one for each quadrant of his face.  Each freckle emitter has a 25% chance of displaying. As you can see, we hit the payoff on two of the freckle emitters this time.

This method is best used in these circumstances:
* Any time you have a bunch of the same model around and you don't want them to all look the same
* Any time you'd like for texture changes to give the impression of a more dynamic world.

Limitations:
* Limited to a flat plane
* Different players in the same world see different variations on the same objects
* Can only be used to benefit in certain circumstances.  Using in the wrong circumstance can confuse players.
* Model will randomize itself on creation or if it is unloaded then reloaded by the engine, such as walking out of range and then back into range of the object- about 35-45 meters.  Or exiting and then re-entering the same area.

Also, since animated textures must be in TGA format (and so, uncompressed), we need to be careful not to make our sprite sheets too large or they'll eat up an unreasonable amount of memory. On the flip side, working for us is the fact that NWN will cache textures which have already been loaded by another model so the graphics memory "cost" of loading an uncompressed TGA will drop the more models on the screen draw from the same texture file.  Like getting a discount for buying in bulk.

Introduction to the effect in the Toolset:
Download this archive and uncompress it into your override directory.  Go into the toolset, search for and select an Armoire and while holding down shift, start placing them.  You should wind up with something that looks like this:
'Posted
In the upper left hand corner of that picture you can see the sprite sheet used as the texture pool.  Really simple stuff, when it comes right down to it.  Instead of those four numbers, it could just as easily be different flowers.  Or sheets of paper on a mage's worktable or a store clerk's counter.

It could also be attached to a model like our innkeep for instance.  Along with his example textures, one could also add random tattoos, patches to indicate worn clothing, rings, beltbuckles or anything else which is eye-catching and substantially changes how the model is perceived by the players.  Typical horde creatures like skeletons or kobolds could be randomized like this as well, breaking up the cookie-cutter look of a lot of encounters.

How to set up the emitter assembly in G/Max:
Our emitter assembly is composed of 3 things: A Dummy node and an Emitter and a helper Plane which will be attached to it.  The Plane acts as a proxy for the virtual emitter surface and when we're happy with the size of the helper Plane (which usually has one frame from our sprite sheet applied to it), we just copy the information into the Emitter so it has the same size.

First let's go over the settings we'll need to put on our emitter after creating it.  Here is the emitter rollout with the changes one needs to make from a default emitter to achieve this effect, using the data from the 0-3 button demo in the toolset.  I've sliced it into 3 and put the pieces side by side so it doesn't take up so much space:

'Posted
1. Update type Single - The emitter will pick just a single image on creation.
2. Billboard to Local Z - The image will retain the orientation it had when it was created.
3. Start Color - We need to make the start color white or at least light so that we can see our texture.  If the Start Color is black (as it is by default), our decal is going to be black as well, which looks awful.  I like to set my white somewhere between 250 & 255, which is the max.
4. Size X & Size Y - This is the size of the virtual emitter plane we're using to target the texture onto.  It's in meters, not centimeters as you'd expect.  We find the right size for the virtual emitter plane by using the helper plane, then plug in whatever size the helper plane wound up being into these slots.  So if your helper plane winds up being 5.6cm on a side, then you'd plug 0.056 into each of those two spots to get an emitter plane which was the same size.
5. Birthrate & Life Expectancy - We need at least one particle to be born so we put 1 under birthrate.  Because the Update style is set to Single (no. 1, above) it will only generate one particle.  By setting Life Expectancy to -1.0, the particle/decal will last as long as the model it's created from.
6. Texture - This is the texture name for our TGA sprite sheet, without the extension.
7. Grid X & Y - The number of frames we have along the X plane and Y plane in our sprite sheet.
8. Last Frame & Random Playback - Last Frame is the number of the highest frame to play or choose from.  The first frame is frame 0, so the fourth frame would be frame 3.  This means all frames on our sprite sheet are fair game.  Random Playback, when selected, will randomly pick a frame from the pool of frames, as defined by First Frame and Last Frame.

If we're going to be attaching this emitter to the surface of a moving object, like the goatee on our innkeep, we also need to put a check next to Inherit.   After all, we don't want our inkeeper's goatee to fly off his face when he bows or laughs.  This prevents that from happening.
'Posted
Next, create a Dummy and a Plane.  To make the emitter assembly just attach the emitter and the Plane to the Dummy node.  Then, while the emitter is selected, press ALT-A (Align) and click on the Dummy node.  Align the emitter with the Dummy node by checking these settings and then hitting Apply.  Select the Plane, press ALT-A again and select the Dummy again, using the same Alignment settings we did for the emitter.  Finish it off by copying an individual frame from your sprite sheet onto the plane.  When you're done it should look something like this.

I just make one from scratch and then keep cloning it in the scene as I need it, making sure to clone the full assembly.  If I'm moving a new assembly close to where an existing one is, with the assembly's Dummy node selected I just hit ALT-A, select the Dummy of the node I want to movie it to and then along with these settings I also tick X, Y and Z under "Align Orientation (Local)" to help speed the positioning process up. When you're happy with where the assembly is, just unattach the helper Plane from the Dummy node and attach the Dummy node to the geometry it will be overlaying the texture of.  Here's an example of what my face looks like in Max.

Anyway, the concept itself is pretty simple.  It doesn't take a GIMP/Photoshop or GMax pro to do it, either.  Finding the most appropriate place for this effect probably requires the most thought of all.

For instance, I've taken this concept to the extremes with a self-randomizing cloud.  It's made up of dozens of emitters which randomly select from a range within a default cloud sprite sheet.  By changing the range (First Frame & Last Frame in point 8, above, on the Emitter settings rollout) I can either make very wispy clouds (first third), very dense clouds (last third) or clouds which have both dense bits and puffy wisps by selecting a range in the middle.  The sprite sheet I used for a proof-of-concept was very large (1024x1024) and so the recording is choppy, but you can see the result of a few "randomized medium cloud" placeables here.  Downloadable here, just unpack to override directory and place an Armoire.

In my free time recently I've been playing around with NWN as an old side-scrolling dungeon crawl type game.  By using this effect for decals on dungeon walls, I'm hoping to break up the "sameness" of a level without having to resort to creating and destroying any more placeables than I have to.  I'm interested to see what other uses people can think up for the effect.

'<img'>
               
               

               


                     Modifié par OldTimeRadio, 24 juin 2011 - 06:14 .
                     
                  


            

Legacy_Zwerkules

  • Hero Member
  • *****
  • Posts: 1997
  • Karma: +0/-0
HowTo: Using emitters to give the illusion of self-randomizing textures
« Reply #1 on: June 21, 2011, 08:44:47 pm »


               Wow! I don't know what to say. This is amazing!
               
               

               
            

Legacy_s e n

  • Hero Member
  • *****
  • Posts: 654
  • Karma: +0/-0
HowTo: Using emitters to give the illusion of self-randomizing textures
« Reply #2 on: June 21, 2011, 08:52:08 pm »


               still, those textures will pierce through fog and wont render through semi transparent meshes '<img'>
time has come to find a solution to the nasty emitter BUG!!!
wonderful tutorial '<img'>
               
               

               
            

Legacy__six

  • Hero Member
  • *****
  • Posts: 1436
  • Karma: +0/-0
HowTo: Using emitters to give the illusion of self-randomizing textures
« Reply #3 on: June 21, 2011, 09:58:15 pm »


               

OldTimeRadio wrote...

Like the rest of the NPC appearances, he gets used again and again along with the rest of them to populate towns, cities, etc.


Only if you're really lazy ':bandit:'

Curious as to how long it took to set up that one particular model. I mean, your margin of error for getting things right on faces is gonna be 1cm max, and since you have to playtest every change you make...

Still, it's a very interesting use of emitters. I'm not sure how much practical use there is in it, but it certainly sounds truly awesome.
               
               

               


                     Modifié par _six, 21 juin 2011 - 09:02 .
                     
                  


            

Legacy_Rubies

  • Hero Member
  • *****
  • Posts: 508
  • Karma: +0/-0
HowTo: Using emitters to give the illusion of self-randomizing textures
« Reply #4 on: June 21, 2011, 10:56:41 pm »


               I totally have a bunch of ideas on how to use this, it sounds really nice! ':kissing:'
               
               

               


                     Modifié par Rubies, 21 juin 2011 - 09:56 .
                     
                  


            

Legacy_OldTimeRadio

  • Hero Member
  • *****
  • Posts: 2307
  • Karma: +0/-0
HowTo: Using emitters to give the illusion of self-randomizing textures
« Reply #5 on: June 21, 2011, 11:16:08 pm »


               @Zwerkules:

It's a fun effect when the situation is such that none of the limitations get in your way.  I had the idea a few years ago to use the same effect as an above-the-head die roller until I figured out that no two people would probably see the same result, and then just shelved it until it occurred to me to use it like this.

@S e n:

This probably won't work, but every played with Render Order in an attempt to remedy that effect?  The necklace on c_yinnkeep is an emitter plane and so is the medallion which appears over it.  I had problems with the medallion part appearing correctly (it would sort of flash on and off depending on viewing distance and angle), until I realized it was a render order.  I think I increased the render order of the medallion to be one higher than the render order of the necklace and suddenly everything worked.  I remember a guy named...Doyleyboy (?) a million years ago posted some issues like the ones you're talking about.  Lord Rosenkrantz might have posted something similar, both possibly in regards to alpha on grass against a sky, I think.  If that's the case, I dunno, I haven't tried tackling that.

@_Six:

I know exactly what you're talking about.  I did the c_yinnkeep model just to show off one avenue you could go down with the effect but about halfway through doing the eyes (that was the first thing I did on him) I started thinking about that 1cm...uh...I guess "auto-snap" aspect in the game engine and wasn't sure it would work because of that.  For using this effect as a decal on, say, a treasure chest or whatever, you're not going to have to worry about those kinds of tolerances but for his face (and I've zoomed in closer to c_yinkeep's face than any player will ever see them) you can see there doesn't appear to be any of that 1-cm snapping.

And I think I just realized why that it is: Everybody else's copy of NWMax (unless they've modded it) actually does some rounding-down when saving out models.  If you load up Estelindis's beautiful necklace models and then turn right around and export them they'll be trashed.  At least that's what happened to me using NWMax Plus- I don't think MDA changed that bit from default NWMax.  I hunted up the bit in the NWMax MaxScript which was responsible for this and disabled it: Problem solved.  I wasn't aware that such a rounding-off was automatically taking place.  That was a few weeks before I wound up playing with this idea and so the change was still in there.

So the actual set up process didn't take the time you would naturally think it did.  I don't recall having to go through any sort of trial and error with the placement as a result of any kind of 1cm engine snap like I believe you're thinking of.  As long as I had a sample frame on my helper plane I could just Align the emitter assembly to my head and then drag it out from there until most or all of the plane was showing and that was it.  I am starting to think the reason why it was probably so easy was a result of modifying that rounding behavior in NWMax export but it didn't occur to me at the time.  I know the BioWare export script documentation talks about a 1cm snap but that appears to be specifically in regards to static meshes.

I think the bit I modified in aurora_fn_export.ms to get Estelindis's necklaces to export properly was the following:

for i = 1 to mesh.numverts do (
   
        local v, x, y, z
        --local round, round_result
       
        v = getvert mesh i
       
        --    We round to the nearest centimeter before converting to meters.
        --    MAXscript doesn't have a round function, so we make our own.
       
        --if (g_RoundOffVertices == true) then (
        --
        --    v = nx_roundp3 v
        --   
        --)

I think there's a variable I could have set somewhere instead of just commenting it out but I tend to butcher up my NWMax/Plus installations as I do various projects.
               
               

               


                     Modifié par OldTimeRadio, 21 juin 2011 - 10:47 .
                     
                  


            

Legacy_OldTimeRadio

  • Hero Member
  • *****
  • Posts: 2307
  • Karma: +0/-0
HowTo: Using emitters to give the illusion of self-randomizing textures
« Reply #6 on: June 21, 2011, 11:27:41 pm »


               

Rubies wrote...
I totally have a bunch of ideas on how to use this, it sounds really nice! ':kissing:'

Cool!  The ones I think may pay off the most (given the limitations) are clutter or foliage related, and anything that can be used to make horde creatures look more unique.  So, say, give a stock gnoll some random eyecolors and armor scuffs or (and I've played with this one myself) putting crack decals on skeletons so they don't all look the same.

Again, the process definitely has limitations but it was a fun little discovery!
               
               

               
            

Legacy_Frith5

  • Hero Member
  • *****
  • Posts: 595
  • Karma: +0/-0
HowTo: Using emitters to give the illusion of self-randomizing textures
« Reply #7 on: June 22, 2011, 01:33:20 am »


               Wow, it sounds very promising for some applications.  One could perhaps create the semblance of a crowd by having the same few(er) NPCs walking around, and changing their looks when out of perception. Would look like the streets were busier than they really are, I think. Could work good for 'windows' too,  or 'paintings' I bet.
Nice post, OTR.

JFK
               
               

               
            

Legacy_s e n

  • Hero Member
  • *****
  • Posts: 654
  • Karma: +0/-0
HowTo: Using emitters to give the illusion of self-randomizing textures
« Reply #8 on: June 22, 2011, 01:45:08 pm »


               render order wont work due its just an on/off switch. its so frustrating working with emitters wich you can use to very improve old nwn and dealing with this major bug! i wonder why no one at bioware ever fixed it... i'll try send a mail to lord Rosenkrantz if i manage to find his address.
atm i think i tried everything possible and a lot of impossible to fix it, but sadly wi thout effort
my main idea was to have a box mesh covering the emitter based tree, and setting such mesh in a way so the engine can render it internally but transparent (or almost) on the output (monitor) : so to bypass the bug, but i failed. now i have some floating idea about shaders, disabled environmental mapping in conjunction with transparencies, play again and more with txi setting etc etc. im not sure we'll ever manage to solve this, if only we could access the engine code, that would be probably a couple lines of settings
               
               

               
            

Legacy_Estelindis

  • Hero Member
  • *****
  • Posts: 935
  • Karma: +0/-0
HowTo: Using emitters to give the illusion of self-randomizing textures
« Reply #9 on: June 23, 2011, 03:05:25 pm »


               I like this idea!  I tend to populate my areas with unique-looking dynamic NPCs, but I know they're much more of a CPU load than non-dynamic ones.  This could be a great way to save some juice!  Plus, being TGA-based, there's the possibility of transparency for hair.  '<img'>

OldTimeRadio wrote...

If you load up Estelindis's beautiful necklace models and then turn right around and export them they'll be trashed.

I thought I saw some nasty effects on a few reskins of the necklaces that others posted here and there, but I couldn't understand what was happening.  Thank you for looking into this and posting a solution!
               
               

               
            

Legacy_ShadowM

  • Hero Member
  • *****
  • Posts: 1373
  • Karma: +0/-0
HowTo: Using emitters to give the illusion of self-randomizing textures
« Reply #10 on: June 24, 2011, 02:42:03 am »


               I was doing a lot of similar stuff back in the day, but was told in the old DLA forums to watch out not to use too many emitters because it could affect performance. I eased on emitters after that, but never really tested it limits or effect. So if someone could do a good performance test with emitters I be very happy '<img'> Thanks for the info OldTimeRadio , mine stuff was mainly with emitter clouds, tornadoes, waves etc.. not with body parts. OldTimeRadio do you want me to put this in the tutorial topic?
               
               

               
            

Legacy_OldTimeRadio

  • Hero Member
  • *****
  • Posts: 2307
  • Karma: +0/-0
HowTo: Using emitters to give the illusion of self-randomizing textures
« Reply #11 on: June 24, 2011, 07:11:44 am »


               Yeah please do, ShadowM!  I thank you.  '<img'>

If you find it useful, here are the self-randomizing clouds I reference in the demo and the video.  Maybe they'll help spawn some more ideas.  The sprite sheet needs to be downsized but I included the individual frames if you (or anyone else) wanted to try your hand at seeing what you can come up with.  Loosely based on an excellent idea from Niniane Wang and her paper is worth a read if that stuff is your thing.

@Estelindis - My pleasure!  You are the first person whose content I've actually had to rewrite a bit of NWMax to deal with, heh heh.
               
               

               


                     Modifié par OldTimeRadio, 24 juin 2011 - 06:12 .
                     
                  


            

Legacy_Borden Haelven

  • Hero Member
  • *****
  • Posts: 681
  • Karma: +0/-0
HowTo: Using emitters to give the illusion of self-randomizing textures
« Reply #12 on: June 24, 2011, 12:24:00 pm »


               This has sparked a few ideas... Thanks OTR.
               
               

               


                     Modifié par Borden Haelven, 24 juin 2011 - 11:35 .