Jump to content

Jedi Academy turned 20 this year! We celebrated in a ton of different ways: mod contest, server event, podcast, etc. Thank you to all who have been a part of this game for the last two decades. Check out the anniversary content!

Read more

Welcome to JKHub

This community is dedicated to the games Star Wars: Jedi Outcast (2002) and Jedi Academy (2003). We host over 3,000 mods created by passionate fans around the world, and thousands of threads of people showcasing their works in progress and asking for assistance. From mods to art to troubleshooting help, we probably have it. If we don't, request or contribute!

Get started

This game turned 20 years old this year, and it is still one of the greatest Star Wars games of all time. If you're new or returning from a long hiatus, here are the basics of getting started with Star Wars Jedi Knight Jedi Academy in 2023.

Read more

Basics of skinning 03: Shaders


Omicron

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:
 

Spoiler

https://jkhub.org/images/4O23uV3.jpg

 

 

Specular:
 

Spoiler

https://jkhub.org/images/pug8HBA.jpg

 

 

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!

Spoiler

spacer.png

Comparison below in another part of the map, with and without the spec shader respectfully:
 

Spoiler

spacer.png

spacer.png

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:

 

Spoiler

https://jkhub.org/images/Wxn7Djq.jpg

 

 

And here is how it looks in game (no spec shader):

Spoiler

spacer.png

spacer.png

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:

Spoiler

e7mmFTK.png

 

alphaFunc GT0:

Spoiler

HRKW0X4.png

alphaFunc LT128:

Spoiler

nhRhmi6.png

alphaFunc GE128:

Spoiler

phNZnfy.png

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:

Spoiler

 

ZtKxPy6.png

 

THbMcq5.png

z5PU2HO.png

 


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.


User Feedback

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 account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...