Shaders


Dranore and 343's Introduction to Shaders!

Did you ever notice the sheer massive number of models in the game? Impressive, isn't it? Making ALL of those models? Well... it's not quite as much work as it would seem thanks to a little thing called Shaders! "What is a shader?" you say? Well, we'll explain. The word “Shader” just means “all the surface information”. Texture, colour, special lighting information, opacity, all those and more can be defined by shaders. In the context of Anachronox, shaders can define reflection maps, opacity, special effects, etc. But in the CG Industry, shaders can do MUCH more. See http://www.renderman.org/RMR/ for more. If you unpack models.dat, you will find lots... and lots... and lots of models. The models themselves are *.MD2 files. These are the files that contain the geometry and animations for any given model. Then you have *.MDA files. These are shader files. MDAs allow you to create multiple skins on any given model, as well as creating special effects! By using ONE model with many skin variants, it's possible to populate a level with hundreds of unique characters, while keeping a very low “model loading” footprint.

Well, what else is it useful for other than lowering model count and special effects? Another neat aspect of the shaders is that they can be controlled with APE! For example, you know how Boots has that black eye at the beginning of the game? Did you notice that it's suddenly disappears? Well, this was done with shaders! Once Boots learns how to "Beat" from Whack-Master Jack, his black eye disappears! Cool huh? You could do any change of appearance you like this way! Well... as long as it only has to do with the skin.

NOTE from 343: The fact that his eyes (and the other main character's eyes) blink isn't the credit of the shader. That's just an Animated texture, which the shader treats as a normal bitmap. Joey wrote a GREAT HTML intro to animated textures… It should be somewhere.

Since this is an intro, 343 and I will break it down for you. Let's take a look at PAL-18. He's got some cool stuff happening on him! To see how this cool stuff is done, there are a few steps involved. First thing ya need to do is extract your "models.dat." <<343 to Dranore: Might wanna explain this process, including URLs for DATExtract… might be nice. >> Inside you'll find a "models" folder and then in the "pal" sub-directory, you will find "PAL.MDA." If we open this file in ParticleMan, you'll see some shiny surfaces on his face and chest plate. This shininess is defined by a few lines of code in the .mda file. So open it up in a text editor, or just follow along here, as we go over WHY this fella looks the way he does. Oh, yeah. Shader files are written in code that can be edited and written in Notepad! No special tools needed! As a matter of fact, Joey (with his Robot Brain) made MOST of his Anox files readable in plain text. Besides .mda (shader files), also see .apd (particles), .atd (animated textures), and .s files (PLANET scripts). So once we crack the file open in Notepad, we'll see the following: MDA1 basemodel models\PAL\pal.md2 profile { skin { pass { map "models/PAL/pal_OPM.tga" alphafunc ge128 depthwrite 1 } pass { map "models\PAL\pal_shin" uvgen sphere blendmode add depthfunc equal cull front } pass { map "models\PAL\pal_opm.tga" blendmode none depthfunc less cull front } } } profile FLAT { skin { pass { map "models/PAL/pal.tga" } } } Cool, got it! Great! Go home you're done.

=)

Now let's examine this file a few lines at a time.

Okay:

MDA1
basemodel models\PAL\pal.md2

Now, ALL MDA files begin with the four letter designation "MDA1". That's effectively a header that lets Anox know that a model file will follow. We don't think it should be anything other than MDA1.

The "Basemodel" line calls the .md2 that the shader will use. So in this case, it is calling the basic PAL-18 model file. Ok, now the next part requires an understanding of one of the most basic concepts of programming: The Bracket. Brackets are used to encapsulate and organize bits of code, and it is no different in shader files! Now, there are three different sub-divisions of a shader. The first is:

profile
{

A “Profile” is the WHOLE shader of an object, and contains bitmap, shader, and effects. Models can have as many profiles as you want, although each have a four letter designator. If the first profile DOESN'T have a designator, it is understood to be DFLT. The four letter designator is always in caps. HMA.mda has 35 different profiles, each of which is a different skin. Profiles are dictated in the Entity.dat, and remember that there are ways to switch profiles based on game events. (Remember how Boots loses his black eye once he learns how to fight?). Once you've started a profile, and named it, you open a bracket. The entire profile will follow, and be capped by a closing bracket once you're done. Also (as stated above), the model has ONE memory footprint. It's Really cheap to duplicate the model a hundered times with a hundred profiles. Doing that helps the engine think it's dealing with one model, and helps the player think they're dealing with a hundered! If you check out Entity.dat, you'll notice that entries dictate which profile they'll use. Look for !DFLT, or Any Four letter all-caps combo preceeded by an exclamation point.

Once Profile's been declared, we move on to:

skin
{

“Skin” is designated under Profile because sometimes a model will use Multiple bitmaps. When a model is skinned, sometimes groups of polys will be seperated into what is called Surfaces. Each Surface uses a separate skin, but a Model only uses one Profile (which can Contain multiple skins) at a time. Skins don't have names the way profiles do (remember the four letter all-caps thingy?), since they're simply done in sequence. After declaring “Skin”, you open ANOTHER set of brackets, which you'll close at the end of the skin. Some models (the ones with more than one surface) use multiple skins. For example, Rho's got a separate bitmap for her glasses.

Okay. Now lets look at these: pass { map "models/PAL/pal_OPM.tga" alphafunc ge128 depthwrite 1 } pass { map "models\PAL\pal_shin" uvgen sphere blendmode add depthfunc equal cull front } pass { map "models\PAL\pal_opm.tga" blendmode none depthfunc less cull front PAL here uses what's called a "multi-pass" shader, which means that the model is actually DRAWN multiple times by the card. Since the DFLT profile for PAL uses three passes (count 'em!), he's drawn three times, tripling his polycount. USE THIS CAREFULLY. Now, since PAL has 3 passes, you might be asking: "How does it know WHERE to apply the shader, and furthermore WHY have more than one skin?" Well, since he's already been skinned, bitmaps already know how to apply to his surface, but in order to make some areas shiny and some areas NOT shiny, We need some Clever masking. Don't worry. we'll explain all when we go over the three passes. Moving on, if you'll look closely, there are TWO bitmaps being used.

map "models/PAL/pal_OPM.tga"

map "models\PAL\pal_shin"

map "models\PAL\pal_OPM.tga"

These Bitmaps are "Pal_OPM.tga" and "Pal_shin.tga". (note how Pal_shin doesn't have the extension. It's because Extensions don't matter. No two images can have the same name, but Anox will pick it up if it's a useable image file named Pal_shin. Pal_shin.tga would work just as well as Pal_shin.jpg). Now we'll explain what's happening when the computer draws PAL.mda, and it's pretty messed up, so it may be hard to follow. Bear with us!

PASS ONE:
Draw the entire bitmap onto PAL, but every pixel with a value greater than 128 in the alpha channel (lighter than middle grey) is COMPLETELY Transparent.

PASS TWO:
Draw the Shiny bitmap, but Spherical map it (so that it looks like a reflection), and additive blend it (so it's transparent and lightening what's behind it). Don't draw over anything.

PASS THREE:
Draw the entire bitmap, as before, but only draw UNDER everything.

THIS way, The entire skin draws, but by careful use of the Alpha channel, we "mask out" the area that we want Reflective. It's not a smooth mask (it uses "cookie cutter" alpha, where there's not a smooth gradation of opacity. It's either transparent or it's not), but it's a COOL-ASS Trick.

Now we'll explain how it does all this. ;)

Pass one:

map "models/PAL/pal_OPM.tga"

"map," calls the bitmap, and the bitmap name is in quotes. Pretty straightforward.

alphafunc ge128

"alphafunc," this means Alpha Function. It's the Cookie Cutter Alpha trick. "ge128" Means "Greater than 128" or Lighter than Middle Grey, in the alpha channel. THIS is how the game knows to only show PAL-18's chest plate and face as shiny. This process cuts a hole through the image to show the layers beneath it.

depthwrite 1

"Depthwrite" confuses us. It means that it writes to the Z-Buffer, but we don't know WHY you'd do that. But it's important, or something. (in truth, you don't have to understand ANY of why this works. Just cut and paste, rename things to appy to YOUR model/bitmaps, and if your alpha channel works, you're golden!)

That's pass one, now onto pass two!

map "models\PAL\pal_shin"

We know what “map” means.

uvgen sphere

This tells it "Disregard the UV's, and UV map the image with a Spherical map". It's good for that reflective look, since the mapping disregards the orientation of the model. If stuff has reflections on it in Anachronox, this is how they're applied.

blendmode add

Blending mode. In this case, it's additive. The bitmap will only lighten whatever's behind it. Used for a _LOT_ for Energy effects. When used, the black parts of a bitmap will be invisible (since black doesn't lighten anything), and white parts are opaque (since you can't get lighter than white).

depthfunc equal

We can't explain this precisely, but it basically says for this to draw. We mean, you're not drawing behind or in front of anything. You just draw. The Depth is neither Greater nor Lesser.

cull front

Culling basically means, "Do not draw." We assume "cull front" culls the front faces and only draws the back faces, but that doesn't seem right somehow. (BTW Cull Disable draws 2-sided polygons, because by default Anox draws one-sided polygons. Disable ALL culling, and NOTHING is culled. Hence, you see both sides of the polygons. Useful.).

That's pass two! Almost done! Pass three:

map "models\PAL\pal_opm.tga"

Same as before.

blendmode none

Unless we're mistaken, this Forces the bitmap to use the Alpha channel AS an Alpha channel. If you DIDN'T force the Alpha channel to be the Alpha channel, it wouldn't show up. See, when you put an image in a Shader, it ONLY takes the image and uses it. You need to explicitly force the alpha, if you want to use it as Alpha. Otherwise, you could use the Alpha channel to mask stuff out (see above), etc. In this case we've got an alpha channel masking out everything that isn't the face or chest plate. Otherwise, the layer above would apply (additively) to the entire surface.

depthfunc less

Depthfunc Less is the same as Depthfunc ge. Only the opposite. Basically, Draw Behind stuff.

cull front

Same as before...

} } } These are the Closing brackets that close off Pass, Skin, and Profile, respectavely.

That's it for the DFLT profile! Now there is the "FLAT" profile! This one is simple! profile FLAT { skin { pass { map "models/PAL/pal.tga" } } } All this does is create a new profile with the designation "FLAT." Then it creates a skin. Then it generates a pass. This pass displays PAL's skin without any effects on it. And that's it! See! That didn't hurt too much? Did it?

Well, that about wraps up our intro to shaders! Hope this helped you understand how Anachronox works just a little bit better! As of right now, there is no list for all of the commands possible for use with shaders. Though, one may magically appear in the future. (provided that Archmage Liaw has nothing better to do) This is an introduction, so don't expect too much. ;) More later!

NOTE from 343: Now, before this tutorial ends, I thought it was important to add something about teenage lesbians. So here we go. See, those words alone call to mind a miasma of torrid, pornographic imagery, but the truth of the matter is that Adolescence is a complicated and difficult time for Anyone, let alone sexual minorities. In today's society, SO much Emphasis is placed on Gender Identity and Gender roles. We're expected to WANT to fall in love with someone of the opposite sex, and when that doesn't happen, a lot of discomfort and stress can result. Just remember that teenage lesbians are trying to get a richer understanding of who they are as a person, and how they fit into the greater scheme of society and the world. Support them, and let them know you care and are willing to listen. For more information, see http://www.smyal.org/

/343 no longer allowed to edit any documents at two in the morning EVAR again.