News Design Artwork Photos Articles
Creative Commons All use of my digital work is covered by this Creative Commons Deed.
Please do not use any of my work for commercial purposes, thank you.
 Spot the Difference   File Size: 5.63Mb
Spot the Difference One of the primary effects used in the map Edge of Forever was to trigger shaders between different states. It was an essential component of the environmental immersion because it gave valuable feedback to the player.

The trigger shader commands were a late additions to the Quake III code base and are available in patch 1.32b. Most Quake III entities can use these additional key / pairs but a good example are the target_relay / target_delay entities.
Click on the above image for a larger version
 The Bare Minimum    
The Bare Minimum In order for triggered shaders to work, the following things must be setup:

Entity The triggered shader is done via a new key / pair which has to exist on an entity and be triggered to work. The new key / pair can be setup on most existing entities, including triggers. (trigger_multiple)

Textures The source and target texture to be swapped.

Shaders The textures need to be setup as shaders and the full path used with the new key/pair on the entity.

Click on the above image for a larger version
 Nuts and Bolts    
The new triggered shader key / pair:
Source Shader = targetShaderName
Target Shader = targetShaderNewName

- The source shader name always points to the same shader name regardless of how many times it changes.

- The shader name always contains the full path to where it is defined.
- The triggered shader affects all relevant surfaces throughout the map at once.

- If the target shader is not loaded before the swap there is a FPS delay.
- If too many shaders are changed at once the client will crash with an overflow error.

- Triggered shaders should have a similar amount of layers, otherwise a FPS delay.
 Light Corruption    
Lightmap Problems When triggering shaders there is a chance that the lightmap can become too bright / dark or even corrupted. This can happen to any triggered shader that has a lightmap stage.

The image to the left has four panel lights and the triggered shaders on the far left have corrupted lightmaps. This will be noticeable when the shader is triggered for the first time and then will remain afterwards regardless of how many times it is changed.
Click on the above image for a larger version
 Splitting Hairs    
To prevent the lightmap from being corrupted when the shader is triggered, the original shader should be split into two parts. The first part is the background texture plus lightmap and the second part is the triggered effect.

The example shaders below show how the split would happen for a single stage light switch effect. The tricky part is creating an 'off state' shader, but using the rbgGen const function the vertex colours can be set to zero (black) and are then rendered 'invisible' to the player.
The Background + Lightmap shader with the triggered effect removed
01
02
03
04
05
06
07
08
09
10
11
12
textures/switch_tut/switch_background { qer_editorimage textures/switch_tut/switch_border.tga { map $lightmap rgbGen identity } { map textures/switch_tut/switch_border.tga blendFunc GL_DST_COLOR GL_ZERO } }


The OFF triggered shader effect using rbgGen to create a 'transparent like' surface in-game
01
02
03
04
05
06
07
08
09
10
11
12
13
textures/switch_tut/switch_off { qer_editorimage textures/switch_tut/switch_editor_off.tga surfaceparm trans surfaceparm nonsolid surfaceparm nomarks polygonOffset { map textures/switch_tut/switch_black.tga blendFunc GL_ONE GL_ONE rgbGen const ( 0 0 0 ) } }


The ON triggered shader effect using polygonOffset to draw over the top of the background
01
02
03
04
05
06
07
08
09
10
11
12
13
textures/switch_tut/switch_on { qer_editorimage textures/switch_tut/switch_editor_on.tga surfaceparm trans surfaceparm nonsolid surfaceparm nomarks polygonOffset { map textures/switch_tut/switch_blend.tga blendfunc GL_ONE GL_ONE rgbGen wave sin .8 .3 0 0.25 } }


Every triggered shader needs a base shader to work from. This is setup to be 'off' by default
01
02
03
04
05
06
07
08
09
10
11
12
13
textures/switch_tut/zswitch_03 { qer_editorimage textures/switch_tut/switch_editor_off.tga surfaceparm trans surfaceparm nonsolid surfaceparm nomarks polygonOffset { map textures/switch_tut/switch_black.tga blendFunc GL_ONE GL_ONE rgbGen const ( 0 0 0 ) } }

 Shader Stacking    
Shader Stacking With the new shader setup and the various parts (background + lightmap and effect) split up, the triggered shader will now only affect what is needed and leave the rest alone.

The two shaders (background and effect) should be setup on top of each other. Either using a detail brush or a simple (3x3) patch so that both surfaces can coexist with each other and not be removed by the compiler.

The target texture should exist somewhere else in the map so that when the source texture is triggered, it will not be loaded from disk but memory. Create a small room somewhere in the map that the player cannot reach for storing triggered textures.
Click on the above image for a larger version
 The Overload Switch    
The Overload Switch Each time a triggerable shader is activated the change is transmitted to all clients. (Q3 is based on client/server architecture) This 'update packet' is a fixed size and if it fills up quicker than the engine can transmit, the game will crash.

To see what the engine is transmitting use the console command 'developer 1' and activate a triggerable shader. As you can see on the console, the full shader path is used for both source and target strings which can quickly overwhelm the engine.
Click on the above image for a larger version
The ideal solution is to stagger (use wait keys) all triggerable shaders as much as possible. It is very likely that if too much is happening at once, the player will not notice anyway. Try to keep the number of synchronized changes to a minimum so that the engine has enough time to keep up.

Prev Page Articles Page
Mememe
Articles 
Level Design -
GameDev Advice -
Creating Terrain -
Terrain Blending -
Rockwall Corridors -
Rockwall Detail -
2 Point Clipping -
Phong Shading -
3D Puzzle Scripting -
Triggerable Shaders -
RTCW Scripting -
Scripted Doors -
Basic Lift -
Advanced Lift -
Cooking -
Apple Crumble -
This site has been cobbled together by Simon O'Callaghan
Contact Information: Simon O'Callaghan
All content is Copyright © 2000-2024
Hosted by ApisNetwork