Skinning Tutorial #3 - Shaders
Throwing shade (╯°□°)╯︵ ┻━┻
Prerequisites:
What this will cover:
- What a shader is
- Basic structure and making one
- Spec shader
- Glow shader
- Transparent Textures
- Putting it all together
- Closing notes
What is a shader?
Put simply, it is a set of instructions that tell game what to do with your texture. How it behaves, any effects it has, etc. By using shaders you can make skins far more interesting by applying various effects to give it the desired look.
How do I make a shader?
Shaders can be made with text editors or ShaderEd from the SDK. For this tutorial we'll be using notepad as that is generally all you'll need once you get the hang of it.
So, first off you'll want to have a skin (or at least a texture) made so it's ready to get the shader.
In your base folder where you've been working on your skin, make a folder called "shaders" (without quotation marks). In this folder make a new .txt file. The name doesn't matter (as long as it doesn't clash with any of the base shaders) but typically you'd choose the name of the skin. What's important is changing the file extension from .txt to .shader, otherwise it won't work.
Open your shader in notepad and work can properly begin! (You can assign the extension .shader to be opened by notepad, Google how if you're unsure.)
The typical format of a shader (from top to bottom) is as follows:
- File path of texture
- Opening brace {
- Opening brace {
- map <File path of texture>
- blendFunc FUNCTION
- rgbGen FUNCTION
- Closing brace }
- Closing brace }
Now, you'll be asking yourself "wth have I just read?" It is best shown with an example following the exact format as above:
models/players/artsExample/rebel_pilot_torso
{
{
map models/players/artsExample/rebel_pilot_torso
blendFunc GL_ONE GL_ZERO
rgbGen lightingDiffuse
}
}
Now I'll explain in turn what each line means and what is happening:
models/players/artsExample/rebel_pilot_torso
This is the texture we want to apply the shader to. The game needs to know where it is. File extension (.jpg, .tga, .png, etc) isn't needed.
{
Tells the game that anything after the brace is a shader for the texture just referenced.
{
Tells the game this is the start of a "stage". Each stage within your shader is telling the game what to do with your texture. For instance, one stage could tell the game to make parts of a texture transparent, the next tells the game to add glow on top. Each different "effect" is divided into separate stages.
map models/players/artsExample/rebel_pilot_torso
This is telling the game I want to map (use) this texture for the first "effect".
I've split the next line up a bit.
blendFunc
Short for blend function. This tells the game how the texture should be mixed; how the pixels on it should behave with what is 'behind' it. A shader usually has multiple stages, in each stage an image is mapped, so you get 'layers' of images stacked on top of each other. BlendFunc tells the game how that particular texture should be mixed with the others below.
GL_ONE GL_ZERO
The simplest of blendFunc's. Tells the game to render the texture as-is. More on other blendFunc's later.
Again, I've split up the next line.
rgbGen
This is stuff to do with colour (hence RGB). You can use rgbGen if you want to make a texture pulsate/fade/animated or have customisable RGB (char_color_ commands).
lightingDiffuse
Tells the game to make it react normal in light. This is what you'll be using mostly.
}
End of the stage.
}
End of the shader.
Some small notes on the above:
- You may find people omit a blendFunc or rgbGen from their shaders. This will result in the default behavior of GL_ONE GL_ZERO and lightingDiffuse respectively.
- blendFunc and rgbGen are two examples of "stage specific keywords" i.e. can only be used within a stage. More on this later.
- The shader shown above won't make the skin appear any differently in game as it uses the default behaviour for any texture (default blendFunc and rgbGen values). Time to change that!
Spec shader:
Probably the most common shader used is specular (or spec) i.e. shine. Everything in real life will shine: It's light reflecting off a surface. A spec shader will make a texture react to lighting more vigorously than a texture without. To be more precise, the game will map a separate texture for its shine (called a spec map) which will be shown to various degrees of opacity depending on the lighting conditions the model is in.
So, here is how to make one (continuing from previous example)!
models/players/artsExample/rebel_pilot_torso
{
{
map models/players/artsExample/rebel_pilot_torso
blendFunc GL_ONE GL_ZERO
rgbGen lightingDiffuse
}
{
map models/players/artsExample/rebel_pilot_torso_spec
blendFunc GL_SRC_ALPHA GL_ONE
alphaGen lightingSpecular
}
}
You'll notice that this shader has two stages, this is important. The game needs to first of all map the original texture, otherwise the game will be mapping the specular texture onto... Nothing. It follows the same format as before but this time the texture being mapped is our spec (named etc_spec).
Secondly, there is a different blendFunc being used, GL_SRC_ALPHA GL_ONE, there is no rgbGen and there is an alphaGen, lightingSpecular.
I'm not going to explain what the blendFunc and alphaGen are doing here, you can do further background reading in the Shader Manual (link at bottom) if you really want. This is just showing what a spec shader will look like.
I'll now explain briefly how to make a specular map texture, but it is down to personal preference and what the base texture is (e.g. metal will typically be very shiny, but something like matte black paint will have far less of a shine to it).
The main thing to remember is darker parts of the spec map = less visable in game (if the spec map was completely black, they'd be no shine at all) and white = more shine! You shouldn't generally have large parts of a texture completely black, keep a bit of detail visible.
How to make a basic spec map:
- Open your texture in a graphics program.
- Increase levels/contrast.
- Either tone down the saturation or make it completely greyscale. Shouldn't be more saturated than before.
Example:
Diffuse:
Specular:
As you can see, I didn't want the jumpsuit to have much shine but I wanted the padding to have more. Lets see how it looks in game!
Comparison below in another part of the map, with and without the spec shader respectfully:
So you have now learned to make a basic spec shader, as simple as it may be it makes a HUGE difference to the skin.
Glow shader:
Make your skin shine brighter than my future.
How to make a glow shader:
models/players/artsExample/rebel_pilot_torso
{
{
map models/players/artsExample/rebel_pilot_torso
blendFunc GL_ONE GL_ZERO
rgbGen lightingDiffuse
}
{
map models/players/artsExample/rebel_pilot_torso_glow
blendFunc GL_ONE GL_ONE
glow
}
}
GL_ONE GL_ONE makes darker pixels more transparent. If the texture was a simple white => black gradient going from left => right, then in game it would be completely opaque (and show up as white) on the far left and gradually fades to complete transparency on the right.
With this in mind, you'll want your glow map to be completely black except the areas you want to glow. These bits should be extremely vibrant so they stand out in game.
I've stuck with the same skin as before and I'll be making the clan logo glow. Below is the glow map I have made for it:
And here is how it looks in game (no spec shader):
Neat huh? It's worth noting that due to a lack of gpu on my computer (:<) you don't see the full glow effect, just a bright looking texture (but it does work, trust me!)
Transparency shader:
Yes, a shader is required for a texture to be transparent in game.
A few things you'll need to know first about transparency:
- Also called alpha (or an alpha channel). If your texture has no alpha channel then it cannot be transparent. You can Google how to add alpha channels and make images transparent.
- Once you have alpha on your image and an area is transparent, you've pretty much done the hard work, but the .shader is equally important.
- If you load your texture in game and it doesn't have the correct shader, it'll be as if you have no alpha channel and anything you have made transparent will be shown.
An example of this transparency issue is the rebel pilot I've been using throughout. You'll notice the base rebel pilot has a semi transparent visor while mine doesn't.
This is due to the base pilot having a conventional transparency shader, which looks something like this:
models/players/artsExample/googles
{
{
map models/players/artsExample/googles
blendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
depthWrite
rgbGen lightingDiffuse
}
}
You can also use blendFunc blend (exactly the same). Don't forget depthWrite, otherwise strange artefcats can occur.
That's it! The above method is for conventional transparency but you can also use alphaFunc, like so:
models/players/artsExample/googles
{
{
map models/players/artsExample/googles
blendFunc GL_ONE GL_ZERO
rgbGen lightingDiffuse
alphaFunc GE128
}
}
alphaFunc can use the following values; GT0, LT128, GE128 (Greater than 0, Less than 128, Greater than or equal to 128). These apply to the value of the pixel in the alpha channel. A fully black pixel (denoting full transparency) has value 0, while white (fully opaque) is 255. Shades of grey (so partially transparent) are any values in between.
alphaFunc cannot be used if your texture requires varying levels of transparency - either has to be visible or not. Because of this, I recommend sticking with the blendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA.
blendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA:
alphaFunc GT0:
alphaFunc LT128:
alphaFunc GE128:
As you can see, results are quite mixed. Stick with the blendFunc method as it's rare that you'll have to use alphaFunc.
Now putting it all together!
Thoughout this adventure, Mr. artsExample has gone a long way. We've given him a shiny spec, a glowing logo and fixed his googles so he is no longer blind. Putting all the shaders together now is dead easy! You still use the one .shader file, don't need a separate one for each shader your skin uses.
models/players/artsExample/googles
{
{
map models/players/artsExample/googles
blendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
depthWrite
rgbGen lightingDiffuse
}
}
models/players/artsExample/rebel_pilot_torso
{
{
map models/players/artsExample/rebel_pilot_torso
blendFunc GL_ONE GL_ZERO
rgbGen lightingDiffuse
}
{
map models/players/artsExample/rebel_pilot_torso_spec
blendFunc GL_SRC_ALPHA GL_ONE
alphaGen lightingSpecular
}
{
map models/players/artsExample/rebel_pilot_torso_glow
blendFunc GL_ONE GL_ONE
glow
}
}
And here he is in game:
But there's a LITTLE bit more...
Remember how I mentioned stage specific keywords? As the name implies, they are specific to stages. You can also get general shader keywords. These apply to the whole shader for that texture as opposed to an individual stage.
The only one you'll probably use is cull disable, but there are others which you can experiment with, such as deformVertexes. Read the manual if you're interested in what these do and how to make them.
cull disable (can also use cull twosided) makes a texture appear on both sides of its surface. Some textures (most commonly skirts) will only show the texture on one side - when you look through the other side you see right through it as if nothing was there. cull disable fixes this.
General shader keywords go between the first and second opening braces of the shader, like so:
models/players/artsExample/rebel_pilot_torso
{
cull disable
{
map models/players/artsExample/rebel_pilot_torso
blendFunc GL_ONE GL_ZERO
rgbGen lightingDiffuse
}
{
map models/players/etc...
(This texture doesn't need it, it's just there to domonstrate where it goes in the shader.)
And that's it! This has covered the basics of making shaders and some common examples of them. Get creating!
Some final tips to remember:
- The majority of the time when making a shader you'll copypasta it from another skin you know has it, even if it's spec or glow. I usually do this if I can't be bothered writing from scratch as it saves a ton of typing.
- Experiment, experiment, experiment... Mess around with blendFunc's, see what happens if you swap x and y stages around, etc. This is how you will learn and understand what does what and get better at making you're own shaders!
- Shaders is all about problem solving and logical thinking: You'll ONLY get better with practice.
- If you roll a turd in glitter... You've still got a turd.
Q3A Shader Manual:
www.heppler.com/shader
tl;dr: Learn yourself by looking at the shaders of other skins. It's what I did.
Recommended Comments
There are no comments to display.
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now