HowTo:IntroToShaders

From VsWiki
Revision as of 01:50, 5 September 2007 by chuck_starchaser (talk | contribs) (Introduction to Shaders, and what they mean to the modelling and texturing pipeline)
Jump to: navigation, search

Introduction to Shaders, and what they mean to the modelling and texturing pipeline

I'm going to expand on this and write a whole bunch of wiki how-to's; this is a first overview. As of this writing, the default shaders aren't finalized yet, and the changes that are coming affect the way the textures need to be packed.

However, you CAN start working on bumpmaps and normalmaps (and shininess maps) right now, if you want. There will be off-line tools provided to convert texture packs from the current set, namely...

* Diffuse texture
* Specular texture
* Glow texture
* Damage texture,  plus the new
* Normal map
* Shininess map (the current shader expecting it in the alpha channel of the specular texture)

...to the most likely new packing arrangement of:

* Texture 0: Diffuse texture (may have 0, 1, or 8 bits of alpha)
* Texture 1: Specular texture (plus shininess in alpha)
* Texture 2: Glow texture(plus normalmap dU in alpha)
* Texture 3: Damage texture (plus normalmap dV in alpha)
* Texture 4: Auxiliary texture (Bump, concavities, plus ambient occlusion in alpha) 

This is very technical; read at your peril:

In more detail, Texture 4 would have the heighth map (bump map) in the green channel, and two "concavities" in the red and blue channels. Well, not concavities, at all, but I didn't know a better term... This is what I mean:

Suppose you plant a normal at a point on a ship's surface, normalmap considered. Now, suppose this normal is a solid pole with two sticks that pivot at the base and can open up at the top, like a V, symmetrically, like the handles of a wine bottle cork extractor. So, open the sticks like a V until one stick or the other touches any other part of the ship. Write down the angle. Now turn the pole 90 degrees and take another measurement. The two planes of rotation should align with the texture's x and y axes (i.e.: in "tangent space"). These two angle measurements get recorded to red and blue, by an off-line tool yet to be programmed.

At runtime, the shader establishes the direction of the eye vector in texture coordinates (x,y), or (u,v), ignoring tangent space z; and uses these values to interpolate a value between the red and blue channels (the two angles measured off-line). Presumably that would approach the actual V angle at the plane normal to the surface that intersects the eye, if we were to measure it. Now we simply compare the eye-to-normal angle to 1/2 of the V angle, and, VOILA!: If it is less, we paint the environment map (multiplied by surface specular value); if it's more, then we know that the specular reflection is occluded, so we don't paint (or paint with a dark color, like 0.25 times the ship's average color, multiplied by local specular color). This should achieve specular self-occlusion.

End of very technical.

In fact, there may be several such tools, for variations in types and numbers of input textures. And I have a prototype of one such tool, the "nodulizer":

nodulizer.png

The nodulizer is really a Blender3D .blend file. You throw it into a folder where you want to convert a set of textures, rename the textures to what the nodulizer expects, or else edit the input nodes for them (on the left), adjust the scaling factor with that input node at the bottom left corner, and press the Use Nodes button in the menu bar below. The scaling factor is there in case you have large (2k by 2k or 4k x 4k originals, and want to produce 1k outputs; otherwise make the scaling factor 1.0. Needless to say, you need to have Blender installed, then you can just double- -click on nodulizer.blend.

You can download the nodulizer beta here: nodulizer.7z Just don't use it yet; the shader that uses this packing is still in the works; but you can play with it, see what it does.

There may also be a command line tool to do the same thing; not decided yet, but the advantage of using Blender's "nodes" and "noodles" is that the tool can be easily customized, specialized, tweaked, expanded... So, IF there may be a command line version, it will probably only be provided for a default repacking, for those who can't use Blender due to their religion :D


But, getting back to basics, the question most often asked: what's the difference between bump- and normalmaps?

Bump map

A bump map is a gray scale image where the brightness represents height above the surface, and darkness represents depth. 50% gray means at surface level.

The problem with bumpmaps is they take a lot of processing in the gpu (videocard) to be really good to use; and that they are quintessentially non-mipmap-able. So normalmaps soon took over.


Normalmap

Normal maps encode simply the angle of the surface. At each point on the surface, if you think of a normal vector to it, how much it is moved to left or to right from the straight UP position is called the dU. How much it is moved forwards or back from straight up is the dV. And how high it is, is the z. And the length of the normal vector is normalized to 1. What does that mean? 255, of course. :D Well, the way colors are represented in rgb is 8-bits unsigned, going from 0 to 255. On the other hand, you could think of that as a fractional number i.e.: going from 0/256 to 255/256, which is almost 1. In OpenGl it is customary to work with 0-0.994 representation.

In a tangent space normal map, normals are specified relateive to the surface (as opposed to older normal maps where x y and z were specified in global coords). So, since, on average, a surface is flat, z is usually close to 1. z goes in the blue channel, so normal maps, when you open them in Gimp look very blue. Red gets the dU, but transposed, as the dU could be positive or negative. 50% red means zero. Same with green and dV. So where a surface is flat, the normal map color is red = 0.5, green = 0.5, blue = 1.0

And you produce them with xNormal, and/or with the Gimp plugin from nvidia. The plugin takes a grayscale bumpmap and computes a normal map. xNormal takes a fine mesh and a coarse mesh, and makes a normal map that, when applied to the coarse mesh, makes it appear like the fine mesh.

Dual Joe nowadays swears by denormgen; --says it's easier to use than xnormal, runs on Linux, and can stack normalmaps. I haven't tried it yet.

What do they look like?

Bumpmap:

bump.jpg

Normal map:

final_norm.jpg

The above normal map is actually a combination of subtle normal corrections computed using xNormal, from a 100k+ polygon mesh, and the result of making a normal map out of the bumpmap above, using Gimp's normal map plugin from Nvidia. That plugin has a choice in the Conversion drop box, called "Normalize Only". Very useful when you're blending normal maps, because normal maps get corrupted by blending ops, and you need to renormalize them, afterwards. Also, if you want to increase the strength of a normal map, you can dim down a bit the blue channel in Gimp, then renormalize.


Shininess Map

"Shininess" is a bad name for a good thing to model, a fundamental property of materials, which can make a glass cockpit look glossy, and make metal look "shiny" without looking "glossy". (Just goes to show what a bad name "shininess" is... Metal looks "shinier" although less glossy, by having a lower shininess than glass. Why couldn't they call it "gloss", for Pete's sake?)

Here's shininess at work in my current beta shader:

shinycockpit.jpg

shot.jpg

Hard to appreciate with a still picture... The metal does reflect the environment, but the reflections are so blurred you can barely notice them. Don't confuse "shininess" with "specular color". Totally different animals.

Shininess describes how "UN-blurred" reflections are. A high shininess (200 or so) reflects images sharp and clear. With a shininess of 100 you begin to notice blurriness. With a shininess of 20, the reflected environment is so blurred it looks almost like half way between specularity or plain diffuse color.

Unlike specular color, shininess is a monochrome (gray scale) parameter. For the ship in the shader screen-shot above, this is what the specular texture looks like:

specular512.jpg

And this is what the shininess texture looks like:

shininess512.jpg

Notice that specular color of the cockpit is pinkish or purplish. Yes, it looks green, but that's because there's a bit of green light I put in the glow map, to make it look like someone lives there; but the specular reflections are actually tinted purple. But anyhow, what I wanted to call your attention to is that the specular strength of the cockpit is not much greater than that of the metal, and in fact it should be less, or rather, the metal should be brighter in specular. I'll fix that. But the cockpit will still look glossier than the metal --i.e.: won't blur the reflections.

And what makes the cockpit look "glossy" is the white color in the shininess map, versus gray for the metal.

Texture packing

As of this writing, it goes like I wrote at the beginning of the file:

* Texture 0: Diffuse texture (may have 0, 1, or 8 bits of alpha)
* Texture 1: Specular texture (plus shininess in alpha)
* Texture 2: Glow texture (plus ambient occlusion in alpha)
* Texture 3: Damage texture (plus normalmap dU in alpha)
* Texture 4: Bump and concavity (plus normalmap dV in alpha)

I overwrote the above several times in the past few hours, so to say that it is in flux would be an understatement. Anyways, stay tuned.

Miscellanea

A new release of the vs engine may automatically initialize the ambient and specular color in the systems' xml files (i.e.: obtain them from averaging the color of their associated background textures). This will be a Good Thing (TM)! Where would you suppose ambient light comes from, if not from the background? So, if we're in a blue nebula, it makes no sense for ambient light to be red. But the chances of it being blue, if left to modders, is about <math>2^(-24)</math>, or one in 65 million. So, with this change, it will be right automatically.

This subject is not complete without discussing ambient occlusion baking and the glow map; but this is too experimental at the moment. Suffice it to say that if I succeed, we'll never use gl ambient light, but will use the glow map to emulate ambient illumination, with self-occlusion baked in, and modulated by the color and intensity of the background. (EDIT: After this writing it was decided to separate ambient occlusion from static illumination and glows, and throw it into the alpha channel. This will a) give ambient occlusion a lot more precision and resolution when compressed to dds with dxt5, and will make the job of the shader a lot easier, and avoid the hassle of forcing artists to use only saturated colors for external lights.)

Also: "detail textures": No need to complicate this post with it too much, but... Detail textures are basically tiling textures, typically 256x256, that map multiple times over the same UV map as the regular textures do, typically 16x16 times, "adding detail" as you get closer to an object (ship or station).

There will be two:

* Texture 5: Diffuse detail (color in rgb, detail normal map dU in alpha)
* Texture 6: Spec detail (luma in red and blue, shininess in green, normal dV in alpha)

(The above is tentative and subject to change.) The reason you don't need to worry about it is that there will be default detail textures that will apply generally to all ships and stations and planets, unless you supply your own detail textures and specify them in the .bfxm. The default ones will simply be some kind of Perlin noise, barely noticeable, just enough to hide "pixelation" artifacts when you get close to a ship or station; --no more.