Mapping 106: Shaders

# What are Shaders?

Shaders are what give your textures/surfaces properties.

They define the properties of a surface in-game in **how it functions** and **how it appears.** We will focus on an overview of both areas and try to break down how they can bring life to your textures and more function.

Regardless of if you set up a shader for any texture used in your map, Netradiant will automatically creates and applies a few shader properties to it, to insure it at least has lighting properties (lightmap).

Using shaders it is possible to:

* Change how it **functions**:
	+ Make surfaces/volumes behave in certain ways in-game (water, lava, nonsolid, etc..)
		- We went over this previously with surfaceparms in Mapping 104: System Brushes
* Change how it **appears**:
	+ Blend multiple textures together in many different ways
	+ Create surface sprites (useful for grass etc.)
	+ Create blended terrain
	+ Create scrolling, rotating textures.
	+ Make textures **glow** in-game
	+ Provide lighting to your map (light-emitting shaders)
	+ Combinations of the above

*To really understand what a shader is, you need to spend a good chunk of time studying* **The Shader Manual.** However, this is a lot of information not easily digested by a new mapper, so this guide has broken down and organized most of these concepts.

## How to work with Shaders

Your first time opening or viewing a shader might feel overwhelming, especially if you have no programmer experience. Shaders are text files that the compiler or engine will read to change aspects of your surfaces. These .shader text assets are found within the game's /shaders directory (some other quake games put this within /scripts).

There are a few ways to open and edit a .shader file. While they *can* be opened or created by any ol' text editor, though we suggest using Sublime with this neat Shader syntax highlighter so that you can see the different parameters and format color-coded (to help prevent against a typo or mistake in syntax). This should help you avoid typos or accidentally missing a closing bracket in your shader.

Netradiant-custom also has a very neat tool recently added as of 2023:

* Shift+Left click on a texture in your texture browser
* The shader will pop up in a text editor within Netradiant-custom
* If that .shader file is not within a .pk3, you will actually be able to edit and save it! Good for quick edits.

### base/shaders/shaderlist.txt

To make NetRadiant recognize and load in a shaders, you **must** add the name of your .shader files to `shaderlist.txt` within `base/maps` and refresh your texture browser. The shaderlist.txt is a very simple file – a simple list of shader filenames loaded up into your texture browser. Neglecting this step leads to your shaders being ignored by the editor and compiler, resulting in improper rendering, missing textures and ignored parameters which are important to your compile.

### Parsing

Whenever a shader is parsed in Netradiant, its first found instance is what is used. This is the opposite of how the JAMP engine parses. Whichever .pk3 is loaded last (which may happen to have a .shader) is what the game uses.

Let's assume you have the same shader in each of these folders or .pk3 listed below. Which one gets loaded?

Assuming in preferences you have Game - > custom JA Modification / MBII set, this is how your compiler prioritizes which shader is being used.

Compiler and editor loading priority (1 being priority, anything else could be overwritten):

1. mb2/folders
2. base/folders
3. mb2/a.pk3
4. mb2/z.pk3
5. base/z.pk3

Game priority (1 being what is loaded last and thusly overwriting anything past it):

1. mb2/z.pk3
2. mb2/a.pk3
3. base/z.pk3
4. mb2/folders
5. base/folders

Remember that shader files with identical names will overwrite each other, so you need to know this order! For Netradiant, folders get priority before pk3s, wheras the opposite is true for the game engine. If you alter a shader in base/shaders and wonder why NetRadiant doesn't render it correctly, add a .pk3 which overwrites that update or temporarily remove it from your .pk3 file as well! Netradiant can open up .pk3s and edit shaders within it's shader editor, so just keep that in mind. It's pretty easy to edit the wrong shader if you aren't paying attention.

Ok, now that we get the basics of how to edit and where things go, let's learn how it works.

## Understanding each Directive

It's very important as a mapper to understand the format/syntax of shaders and understand where to put the various directives. There are 5 different types of directives possible for your shader. Each of these have their own page, after reading this page is is recommended to read up on them all (each of these directives are links you can click on) to understand what each directive does so you can determine for yourself what kind of shader you would like to make.

#### Radiant Editor Directives

Radiant editor directives change the appearance of the shader in the map editor only. It has no effect on the shader in game.

#### General Directives

A shader may contain general directives, which affects the shader's appearance globally (affects the entire shader), and changes the physical attributes of the surface that uses the shader. These attributes can affect the player. These parameters are executed at runtime, that is, in order to see the changes one does not need to re-compile the map.

##### Global Directives

These two directives types control various aspects of lighting, shading, and surface properties, they go further than just visual appeal to influence gameplay mechanics, lighting interactions, optimization and sounds. These parameters all go **before** the the first stage of your shader and affect the shader globally. Unlike the other shader directives, these must be compiled in order to function.

##### Q3Map Directives (q3map\_)

These directives are used by the compiler to change the physical nature of the shader's surface and are also global.

Put briefly, these directives offer you control to:

* Illuminate and Control Light
* Optimize Models
* Create and control Fog/Skybox/Terrain
* Adjust Surface Properties and Appearances
* Change aspects of your lightmap
* Optimize surfaces

#### Q3Map Surface Parameter Directives (surfaceparms)

These tell the compiler about the physical nature of the shader's surface. To give a few examples, these params allow for things such as:

* Changing the surface into liquid
* Making a surface slippery or stopping fall damage
* Changing the sound of footsteps on this surface
* Hiding or blocking light

#### Stage Specific Shader Directives

The shader may contain one or more "stages". Each stage consists of an opening and closing bracket along with the contents of the stage (indented). The stage will contain a texture map specification which specifies the source image, and various other stages specific shader directives that modifies the appearance of the source image. Stage specific directives are processed by the in-game renderer. They are appearance changes only and have no effect on game play or game mechanics. Changes to any of these attributes will take effect as soon as the game goes to another level or vid\_restarts (type command "/vid\_restart" in the game console).

We'll be getting into understanding stages more in the next chapter, so don't worry too much if this is confusing.

Easy way to remember think about stages are as if each stage is a new layer of properties or texture for your shader.

## Shader Syntax

.shader files consists of a series of surface attribute and rendering instructions formatted similarly to the C programming language within braces: { and }.. Keeping the proper format is important or else the shader may break or cause issues with other shaders getting loaded in. A single .shader file can also contain multiple shaders for more than one surface. It is common for maps to have all of their shaders in one .shader file and it is a good way to save space.

Basic shader syntax is *super* important, so let's make sure we have a good understanding of how that works. People with programming experience will be able to pick up on this quickly, but for those with none, I will try to break things down simply. When you are creating a shader, consider the examples below. This is your basic template for any shader.

##### Skeleton of a shader:

```
directory/nameofshader
{
 // Global Variables (General Directives)
 // Q3Map2 Global Directives,
 // Q3Map2 Surface Parameter Directives,
 // Quake Editor Radiant Directives

 // Stage 1
 {
 // Stage Directives
 // usually your lightmap is mapped here
 }

 // Stage 2 (optional)
 {
 // More Stage Directives (more appearance parameters)
 // usually your texture is mapped here
 }

 // Stage 3 (optional)
 {
 // Further stage directives, e.g., blending of another texture on top
 }
}

```

is your basic format, generally speaking this is what a shader needs:

1. The name of the shader
2. opening bracket {
3. Any Quake editor directives
4. Any global or general directives (what it does)
	1. Before the first shader stage is where you place any of your Global Directives. This is where you would set stuff like lighting, surfaceparms and more.
	2. *Most* global or general directives will require a recompile in order to see their effect.
5. Stage
	1. Opening stage bracket {
	2. Stage (think of this like a layer to your shader) is required if you want it to have a lightmap or any visual properties other than default
	3. Closing stage bracket }
		* The stage (or stages) will contain a texture map or lightmap specification which specifies the source image, and various other stages specific shader directives that modifies the appearance of the source image.
		* Stages do not require your map to be recompiled to see any change.
		* Changes to any of these attributes will take effect as soon as the game goes to another level or vid\_restarts (type command "/vid\_restart" in the game console).
	4. Additional bracketed shader stage if desired
	5. Closing shader bracket }

You can have a max of 8 stages per shader. There are a lot of ways to use these stages to add visual modifiers to your base texture. It is quite modular. You can also also load a shader into ShaderEd, which is provided in the SDK. This helps provide a bit of visualization to what's going on in the shader script. It's a bit of a confusing program at first, so it is recommended to use it after you have learned most of the directives on this wiki before. Let's flesh out that skeleton example a bit more:

#### Slightly more fleshed out Shader template:

```
File path of shader

{//Opening brace
 //Shader properties (there is a lot you can put in here)
 //This is where you would put Global, Editor or General Parameters
 {//Opening brace to Stage 1, note the indent
 map <File path of texture>
 rgbGen FUNCTION
 }//closing bracket for Stage 1

 { //starting bracket for Stage 2
 map <file path of texture>
 blendFunc FUNCTION
 rgbGen FUNCTION
 } //Closing bracket for Stage 2} and so-on-and-so forth depending on how many stages your shader has.
}

```
Note that in this example, that the directives for map, rgbGen and blendFunc are listed. These directives are some of the most commonly used directives, so get used to seeing those and make sure you learn what they do.

## Shader examples:

### Example 1 (the default shader)

For the game engine, textures are only images with a default shader. The game renderer process the generic texture and put it into a generic shader. Here is the default shader structure which Q3map2 uses to compile a generic texture:

```
textures/firstshader/floor
{
 {
 map $lightmap
 rgbGen identity
 }
 {
 map textures/firstshader/floor.tga
 blendFunc GL\_DST\_COLOR GL\_ZERO
 rgbGen identity
 }
}

```

The first line is the shader name for the engine and is usually and similar to a texture name (relative path with filename but without extension).

The first stage establishes that this surface should have a lightmap and also establishes RGB identity.

In line 8, "textures/firstshader/floor.tga" establishes what texture is to be used for this shader (tga or jpg are suggested formats, avoid .png).

Again, this is just default. This is the shader properties Netradiant applies to any texture which does not already have a shader. As you can see, by default, Q3map will set a lightmap and basic color/rgb identities for any texture getting compiled. If you are to create a new shader, you need to be aware of these 'defaults'.

#### Example 2 (a shader with a glow)

We are going to combine these two textures together, using the blend.jpg as a way to give the texture a sense of illumination (dynamic light)

Largelamplight.jpg

Largelamplight.blend.jpg

```
textures/mymapname/largelamplight //Defines when to load if selected from texture menu
{

 qer\_editorimage textures/mymapname/largelamplight.jpg //image displayed in radiant

 q3map\_lightimage textures/mymapname/largelamplight.blend.jpg //emitting pattern

 surfaceparm nomarks //This makes sure no shotmarks cover the lamp

 q3map\_surfacelight 1250 //This is the setting that makes the texture emit light

 { //STAGE 1

 map textures/mymapname/largelamplight.jpg //Texture displayed in map

 }

 { //STAGE 2

 map $lightmap //maps lightmap in

 blendfunc filter //filters the dark parts

 }

 {//STAGE 3

 map textures/mymapname/largelamplight.blend.jpg //Overlay source, kinda

 blendfunc add //Adds previous image ignoring the darker parts.

 }

} //IMPORTANT NOTE: TWO ENDING BRACKETS, one closes the last stage, the other closes the shader!

```

* The main difference in this shader vs the default is that this has a 3rd stage for a second image to overlay on top of the first, as well as this shader will emit light onto the map.

#### Example 2 (lava)

Here is another example of a shader:

```
textures/liquids/lava-example
{
 deformVertexes wave sin 0 3 0 0.1
 q3map\_tessSize 64
 surfaceparm lava
 qer\_editorimage textures/common/lava.tga
 {
 map textures/common/lava.tga
 }
}

```

* Line 1 is the shader name and what is references in Netradiant
* Line 2 is the starting bracket of the first stage.
* Line 3 is a general directive which gives the lava have that warpy liquid feel.
* Line 4 is a q3map directive. It must be compiled to work.
* Line 5 is a surface parameter keyword. These keywords tell the behavior of a surface of the shader to the compiler.
* Line 6 is an editor-specific keyword. These keywords tell the behavior of a shader to the map editor.
* Line 8 is a Stage-specific keyword. The only purpose of this stage is to map the texture to the shader.
* Line 9 closes the bracket of the stage
* Line 10 closes the brackets of the shader.

## Create your first shader

Now that we've gotten some understanding (hopefully) of how all this works, let's create our own.

#### 1) Write the first line of your shader

Open up Sublime, download and install this so that you can see proper shader format to make your life not a living nightmare.[1]

1. Line 1 of our shader is going to be the 'name directory' of our shader. Let's name it:
	* textures/firstshader/floorshader
2. Save your text file as a .shader in your base/shaders folder. Name it something non-generic so it doesn't overwrite an already existing shader in JA
	* The shader name doesn't need to match the texture's filename. It just needs to be unique, meaning no other shaders in the game should have this same directory name you are making (e.g. "mapnameliquids.shader" would be better than "liquids.shader").

#### 2) Save your texture in base/textures/somewhere

* Wait a second, we don't have a textures/firstshader/floor texture, that doesn't exist! But if we direct this shader (and appropriately format it) to an existing texture, suddenly this shader will show up in that directory and we will see the referenced texture. Or if the shader exists but the texture does not, you will see a missing shader error as your tiled image.    Where we place this texture will correspond with how it is written in our shader. Let's just save this texture in base/textures/firstshader/floor.jpg
	+ To better order your textures it's a good idea to sort them in a subfolder of the textures folder.
	+ You can drop this in a .pk3 if you want, but your engine should be able to re-load the shader if it's in base/textures/firstshader as floor.jpg

#### 3) Finish writing your first shader

```
textures/firstshader/floor
{
 {
 map $lightmap
 rgbGen identity
 }
 {
 map textures/firstshader/floor
 blendFunc GL\_DST\_COLOR GL\_ZERO
 }
}

```
We name the shader (folder) after the base map filename `firstshader.map` and `firstshader.bsp`. - this kind of naming structure helps to keep things organized.
Let's try adding a surfaceparm to spice it up a bit:

```
textures/firstshader/floor
{
 surfaceparm nodamage
 {
 map $lightmap
 rgbGen identity
 }
 {
 map textures/firstshader/floor.tga
 blendFunc GL\_DST\_COLOR GL\_ZERO
 }
}

```
The first actual change to our vanilla shader will be no falling damage if a player lands on the ground (surface with the new shader). If you wanted to add a different surfaceparm, simply take a look at the list below or check the shader manual for more info.

### 5) Save

Once you finish your shader, save it and refresh your textures in Netradiant (or restart) and this shader should appear in the directory you set as it's 'name' (in this case it should appear in firstshader/floor).

To refresh your shaders in Netradiant-custom, simply click this icon in the top left of your texture browser (bottom right window by default):

### 6) Compile and check to see if your first shader was properly compiled!

If your shader properly loaded in Netradiant-custom and you compiled your map correctly, you should be able to load up your map and test to see if the floor shader blocks fall damage or not. This is just one of many different shader possibilities.

You can download the example map for this tutorial here:

*Special thanks to q3df.org for this basic shader tutorial. I simply converted a few lines here and there to fit jamp engine standards.*

## Tips

* Most "surfaceparm" changes require to recompile the map in order to be effective (e.g. surfaceparm water), but some may be interpreted by the game directly, without a map recompile (e.g. surfaceparm nomarks).
	+ Usually, their order is not a problem... but in some cases, the different *order* of the "surfaceparm" keywords may cause some slightly different behaviors. If you are troubleshooting your shader, in a few cases changing the order of your surfaceparm keywords may fix an unexpected behavior.
* While you *have to* include your additional .shader files in the PK3 of your map when you will release it, you *should NOT* include your shaderlist.txt. If you wish, you may mention in its "readme file" that if someone will want to recompile your map, he should add the included shader files to his own shaderlist.txt.

##### Note: Documenting With Comments

Anything after double forward slashes '//' means it is 'commented out' and will not be a part of the shader code.

Adding comments to shaders is highly useful, especially for testing or collaborating with fellow designers. Shader comments are ignored, serving as notes or temporary removal of directives for testing purposes.

##### Mapper See, Mapper Do

Imitation is the sincerest form of flattery, right? One of the best way to understand shaders is checking the map file's .shader file. Do a little bit of research and reconnaissance by going through maps which have shader properties you like or are curious about and looking closely at their .shader files.

The easiest method of finding a particular texture would be to import the .bsp of the map you are curious about and then find the name of that particular texture by ctrl+clicking it. From there you would open up the .shader file of that map and search for that texture directory name in the .shader. Once you have found the shader within MBII or JKA assets, you can now look up how it is doing things by cross-referencing those properties with the shader manual!

On to the next chapter on shaders: Mapping 106: Q3Map Global Directives

## Assignment:

Using the above knowledge, the updated Shader Manual and Rich Diesel's tutorial series, create 5 unique shaders that you can try in your map:

Before you do so, look through these pages:

* Radiant Editor Directives
* General Directives
* Q3Map Directives (q3map\_)
* Q3Map Surface Parameter Directives (surfaceparms)
* Stage Specific Shader Directives

Look at this tutorial for further visual shader knowledge.

* A transparent surface with a green tint that a player can walk through
* A surface which gives off light that is invisible to a player (and can be walked-through)
* A see-through surface (like a grate), with one part transparent and one part non-transparent (.tga with Alpha Channels)
* A surface with dynamic glow
* Create a liquid
	+ DarthNorman created a nice tutorial on a good water shader, with good explanations per line
* Run ShaderEd from the JKA SDK to get a more visual sense of all the possibilities you can do with your shaders!

More resources:

* Learn how to create a custom skybox
* Learn how to create layered shaders
* Learn how to create falling leaves
* Learn how to create terrain and have your terrain blend
* Advanced water shaders / terrain blending