# Shader Script .SHD

by Christoph Kubisch

## Content

- Definition
- Example
- Techniques
- Renderflag
- Stages
- Commands
- History

## Definition

A shader allows multiple texture effects on a single surface. That can be blending different textures or complex operations such as Cg or Vertex/Fragment programs.
The shader defines how textures should be blend, while a MTL-Material sets the textures to be used, however the shader can have hardwired textures and special textures.

It is made of several stages, you should try to limit the amount of stages cause it will take a lot performance.

All commands are case sensitive and closed by ; !
<id> ranges from 0 to 7
<vector4> is (float,float,float,float)
<bool> is 1 = true, 0 = false

The header is necessary
current version:
luxinia_Shader_v300

### Branching

You can do branching with following commands. Enclose the branches in curly brackets { }

- IF:<condition string>
- ELSEIF:<condition string>
- ELSE

The condition string can be set from luxinia API with resource.condition.
You can also negate a statement with !<condition string>.
Be aware that the parser is not fully rock solid, so at best use COMMAND{<newline> <what><newline> }<newline> , when problems occur.

Content

## Example

     luxinia_Shader_v300
    Technique:VID_LOWDETAIL{
    	Texture{
    		TEX "TEX_0"
    	}
    }
    Technique:VID_CG_TEX4{
    	RenderFlag{
    		#comment blah
    		lit;
    		nocull;
    	}
    	GpuProgram{
    		BASE 0 "gpuprogs/test.cg" "unlit";
    		SKIN 0 "gpuprogs/test.cg" "skin_unlit";
    		BASE 1 "gpuprogs/test.cg" "lit1";
    		SKIN 1 "gpuprogs/test.cg" "skin_lit1";

    		VCG;

    		param	"angle"	0 VID_VALUE (45.0,0.0,0.0,1.0);
    		tangents;
    	}
    	GpuProgram{
    		BASE 0 "gpuprogs/test_pixel.cg" "main";
    		FCG;
    		param	"color"	0 VID_LIGHTCOLOR (0.0,0.0,0.0,0.0);
    	}
    	Color{
    		RGBA "Color:0";
    	}
    	Texture{
    		TEX "Texture:1";
    	}
    	Texture{
    		ATTENUATE;
    	}
    	Texture{
    		NORMALIZE;
    	}
    }
    Technique:VID_DEFAULT{
    	RenderFlag{
    		#comment blah
    		lit;
    		nocull;
    	}
    	Color{
    		RGBA "Color:0";
    	}
    	Texture{
    		VTEX "Texture:0";
    	}
    	IF:DOSIMPLEANI{
    		Texture{
    			TEX "textures/fx/aniso.jpg";
    			blendmode	VID_ADD;
    		}
    	}
    }

Content

## Technique

you can specify techniques if the same shader should look different depending on hardware capabilities, if no technique is specified VID_DEFAULT is assumed.
If a technique is defined there also must be a VID_DEFAULT technique. The first technique that is valid for the system's hardware will be used, so you should put the "highest detail" ones above default in. If there is any VID_LOWDETAIL must come first.

following techniques are defined:

- basic techniques:
  - VID_DEFAULT
    always works on all hardware (blendmode VID_NORMAL might not)
  - VID_LOWDETAIL
    is used when user set engine details to low.

- higher techniques in ascending priority:
  - VID_ARB_TEXCOMB
    requires ARB texture_env_combine, crossbar (or NV combine4), dot3 and cubemaps.
  - VID_ARB_V
    requires ARB vertex programs and combiners
  - VID_CG
    requires Cg support (vertex and fragment)
  - VID_ARB_VF
    requires ARB vertex program and fragment program
  - VID_CG_SM3_TEX8
    requires Cg support and shader model 3 along with 8 texture coords

- _TEX4
  means it also needs 4 texture coords
- _TEX8
  means it also needs 8 texture coords (only for VID_ARB_VF)

Content

## RenderFlag

These are independent from stages and used for all surfaces assigned, so be careful.
They are "or'ed" to the object's renderflags.

- nocolorarray;
  turns of color array (often required when you want Color Stages)
- sunlit;
  surface is shaded by sunlights
- unlit;
  surface is not shaded by lights (forces lights off)
- nocull;
  turns backface culling off
- nodepthmask;
  wont write into depthmask (ie. no depth information stored)
- nodepthtest;
  wont do depth testing (ie. always on top when drawn)
- alphamask;
  quick for: alphafunc GL_GREATER (0.0)
- alphaTEX "filename.ext" <texchannel uint>;
  when a shader uses alphatesting and projectors are applied
  this texture's alpha will be used as mask for all. Alternatively it can be stored for baking processes.
  Same mechanism as for the other TEX commands at Texture is used.
  If shader compilation creates problems, use newpass mechanism and manually define combiners to preserve the alpha you need.
  - texchannel
    optionally you can define which texcoord channel to use 0-3. See texcoord command below.
- normals;
  means the program needs normals as pervertex attrib

- alphafunc <enum func> (<float ref>);
  - func
    to cap transparency of an object, same as in OGL
    GL_NEVER, GL_ALWAYS, GL_LESS, GL_GREATER, GL_LEQUAL, GL_GEQUAL, GL_EQUAL, GL_NOTEQUAL
- layer <enum layer>;
  to move surfaces in certain draw layers. This allows control over when things are drawn.
  - layer
    in the order they are drawn
    VID_FRONT_TO_BACK
    VID_LAYER_0
    ...
    VID_LAYER_13
    VID_BACK_TO_FRONT
    FRONT_TO_BACK/BACK_TO_FRONT sort the Z-Depth according to their name. Normally you would put things like trees (alphatest) in VID_FRONT_TO_BACK and transparent surfaces in VID_BACK_TO_FRONT

Content

## Stages

There are 4 different types of stages. All stages are processed in the same order, it is written in the shader file.
Limits: VID_SHADER_STAGES = 16 (tex or gpu) MAX_COLORSTAGES = 1
Beyond the limit will be ignored

### NewPass

A new pass is started from here on.
Be warned that once you start using NewPass no automatic shader compilation will be done. This is why you must make sure, that the stages after and before newpass can actually be processed within a single pass. This means on Techniques with 2 Texture units you must not use more than 2 TextureStages?.

The advantage is that you can use a lot more blendmodes/combiners for texturing. You can also define your own with the lua api.

### Color

just a simple color, overrides vertexcolors of surface

- RGBA "Color:n";
  n is id in material

for most "models" you will need to use "nocolorarray" renderflag to actually see an effect of the values specified here

### Texture

a single texturemap:

- TEX "filename.ext";
  - TEX : RGB/RGBA
  - TEXALPHA : ALPHA
  - V??? : auto sets vertexcolored flag
- TEX/VTEX "Texture:n";
  n is id in Material
- System needs cubemap support:
  - TEXPROJ: RGB/RGBA with cubemap using given texture as +Z
  - TEXDOTZ: INTENSITY/RGB/RGBA with cubemap using given 1d texture as dot(vector,+z), -1 is left and +1 is right.
  - TEXCUBE: 6 textures separated by comma make this texture
    "pos_x.jpg,neg_x.jpg,pos_y.jpg,neg_y.jpg,pos_z.jpg,neg_z.jpg"
    or a single .dds file "cubemap.dds"
- User Textures
  - if the name string looks like "USER_TEX(name)" then the engine will lookup
    user-created textures or registered textures with this name.
- Special Textures
  - LIGHTMAP;
    the lightmap for the instance of current model
    there cannot be more than a single LIGHTMAP texture stage
- For higher Techniques:
  - ATTENUATE3D;
    a 3d texture with radial square falloff
  - NORMALIZE;
    a normalization cubemap
  - SKYBOX;
    the skybox cubemap
  - SPECULAR;
    specular cubemap lighting, intensity = (MAX (0,(texcoord dot (0,0,1)))^8
  - DIFFUSE;
    diffuse cubemap lighting, intensity = MAX(0,texcoord dot (0,0,1))

### GpuProgram

only allowed in higher techniques
using multiple GpuPrograms? per pass is not allowed, if you want to use more than one pair of GpuPrograms? (vertex/fragment) you need to use NewPass? mechanism.
Also, GpuPrograms? of a pass must come next to each other.

- BASE <int lightnum> "filename.ext" "entryname"
  - lightnum
    is not needed but can be specified from 0 to 4

For Vertex Processing

- SKIN <int lightnum> "filename.ext" "entryname"
  optional with skinning support, same vertex programtype as the basic one. To really allow gpu skinning all vertex stages must specifcy a skin program.

And all programs within shader must be of same type.

For Fragment Processing

- FOGGED <int lightnum> "filename.ext" "entryname"
  optional, used when fog state is set

- <enum type>;
  - type
    VPROG ARB_VERTEX_PROGRAM (very common)
    VCG Cg Shader (very common)
    FPROG ARB_FRAGMENT_PROGRAM (4th gen. T&L)
    FCG Cg Shader (4th gen. T&L or restricted 3rd gen. Nvidia)
    FFIXED Fragment Fixed Function Pipeline (ie the blendmodes specified in the Color/Tex Stages) unbind previous bound shaders

#### Notes:

- Skinning
  - program.env[0..VID_BONESLAST] (ARB_prog) or "bonesmatrices" (Cg)
    matrices can contain up to VID_BONESMAX float4s saved as float4x3 matrices
    - VID_BONESMAX = 3* ((max. program parameters) - system_hwbonesparams) (set in config.env)
    - VID_BONESLAST = VID_BONESMAX - 1

  - vertex.attrib6 = {index0, weight0, index1, weight1}

- Billboard
  - program.local[1..32] (ARB_prog) or "bbvertexoffsets" (Cg)
    vertex offsets in Cg stored as 32 float4s
  - program.local[33..64] (ARB_prog) or "bbtexoffsets" (Cg)
    texture offsets in Cg stored as 32 float2s
  - program.local[0] (ARB_prog) or "bbtexwidth" (Cg)
    texturewidth is stored in Cg as 1 float2 (texwidth,1)
  - program.local[65..67] (ARB_prog) or "bbglobalaxis" (Cg)
    global axis for aligned particles is stored in Cg as 3 float4s

  - vertex.tex0 = { Index, Size, texnum, 1 }
  - vertex.attrib[6] = { cos, -sin , age/life , speed }

Content

## Commands

After the stage specific commands there is multiple possibilities to change the stage

### blendmode <mode enum>;

to blend fragments on top of each other, enums start with VID_...
RESULT = the fragment produced after blend
TEX = current fragment, normally a texture but could as well be a plain color
PREV = the previous fragment drawn (the one "below" TEX)

- Replacement mode
  just overwrites previous fragment
  RESULT = (TEX)
  - VID_REPLACE
- Modulation mode
  multiplies fragments
  RESULT = (PREV) * (TEX)
  - VID_MODULATE
- Decal modes
  A decal is drawn ontop of another surface and replaces the pixel below based on the alpha value used (think of a transparent sticker):
  RESULT = (PREV) * ( 1-ALPHA) + (TEX) * (ALPHA)
  - VID_DECAL
    ALPHA = TEX.ALPHA
  - VID_DECAL_PREV
    ALPHA = PREV.ALPHA
  - VID_DECAL_VERTEX
    ALPHA = VERTEXCOLOR.ALPHA
  - VID_DECAL_CONST
    ALPHA = TEXCONSTANT.ALPHA (provided by texconst)
- Additive modes
  The fragments are summed together:
  RESULT = (PREV) + (TEX) * FACTOR
  - VID_ADD
    FACTOR = 1
  - VID_AMODADD
    FACTOR = TEX.ALPHA
  - VID_AMODADD_PREV
    FACTOR = PREV.ALPHA
  - VID_AMODADD_VERTEX
    FACTOR = VERTEXCOLOR.ALPHA
  - VID_AMODADD_CONST
    FACTOR = CONSTANT.ALPHA (provided by texconst)

- Special modes:

  - VID_NORMAL
    takes the texture as normal map and does a "normal lighting pass" after all previous passes. This results always in n+1 passes. As it requires more extensions it might be ignored if system is not capable of doing it

- only in VID_ARB_V and higher techniques:
  - VID_AMODADD_CONSTMOD
    RESULT = (PREV) + (TEX) * FACTOR
    FACTOR = CONSTANT.ALPHA * TEX.ALPHA
  - VID_DECAL_CONSTMOD
    RESULT = (PREV) * ( 1-ALPHA) + (TEX) * (ALPHA)
    ALPHA = CONSTANT.ALPHA * TEX.ALPHA

- Advanced:
  - internal modes:
    the compiler normally turns the basic modes above and generates other modes so that it uses least passes possible.
    In manual compile mode those might be useful. All combiners are listed in the "vid_texcombiners.txt" file

  - custom modes:
    You can program your own texture combiners with the luxinia api and store them with your custom names (e.g. COMBINER_SPECIAL_ALPHA).
    See texturecombiner class for details

  - alphamode <mode enum>;
    controls alpha separate from color blend. Only allowed in manual compiling (newpass mechanism)
    All combiners are listed in the "vid_texcombiners.txt" file.

- Notes:
  - VID_REPLACE
    is default when the first blend is not a effect will mostly need multiple passes when drawn
  - _PREV
    is not allowed in first stage and will be changed to VID_DECAL

### generic flags:

- blendinvertalpha;
  inverts the alpha used in AMODADD and DECAL blendmodes

### texture flags

- texture coordinate generation modes
  - spheremap;
    turns the texcoord mapping into sphere mapped
  - screenmap;
    screen mapped texture generation
  - reflectmap;
    reflection mapped texture generation
  - worldlinmap;
    world linear mapped texture generation
    planes and coordinates are set with the texgenplane command
  - objlinmap;
    object linear mapped texture generation
    planes and coordinates are set with the texgenplane command
  - normalmap;
    normal mapped texture generation
  - skyreflectmap;
    special mode that uses reflection and skybox tracking, ideally for regular reflections
  - sunreflectmap;
    special mode that uses reflection and suntracking, mostly for specular reflections
  - sunnormalmap;
    special mode that uses normal and suntracking, mostly for custom lighting

- vertexcolored;
  the current texture will be modulated with vertex colors (when first stage is a color stage set to REPLACE, and the second stage is texture stage set to MODULATE, then it is the same as texture stage set to REPLACE with "vertexcolored" on) auto-set when VTEX is used

- rgbscale2;
  result of texture blending operation is scaled by 2 (should only be used in newpass mechanism)
- rgbscale4;
  result of texture blending operation is scaled by 2 (should only be used in newpass mechanism)
- alphascale2;
  result of texture blending operation is scaled by 2 (should only be used in newpass mechanism)
- alphascale4;
  result of texture blending operation is scaled by 4 (should only be used in newpass mechanism)
- lightmapscale;
  when LIGHTMAP is used we will use the lightmap texture's lightmapscale property.

### texture functions

- texcoord <uint channel>;
  channel 0 is default, 1 is lightmap (vertex32lm). 2,3(2d) and 4(4d) can exist if vertex64 is used
- texclamp (<X bool>,<Y bool>,<Z bool>);
  texture clamping (to edge) enabled for given axis. By default all are off and therefore set to repeat.
  Only applied to new loaded textures
- texgenplane <axis uint> <vector4 plane>
  sets the texgen plane for each axis (0 = X, 1 = Y,...) for world/objlinmap. Be aware that only following axis combinations are legal:
  - XY,XYW,XYZ,XYZW
- param...;
  see functions below at GpuProgram, only VID_VALUE, VID_LIGHTCOLOR, VID_LIGHTDIR, VID_CAMDIR are supported and passed as TEXCONST

### GpuProgram flags

- tangents;
  means the program needs tangents as pervertex attrib
  tangents are stored in vertex.attrib[7]
- normals;
  means the program needs normals as pervertex attrib

### GpuProgram functions:

- param "<name>" <uint id> <enum type> (<x float>,<y float>,<z float>,<w float>);
  - name
    variable name
  - id
    id number for ARB_PROGRAMs
  - type
    what type of variable
    - VID_VALUE generic value, ie the 4 flaots the user passes
    - VID_CAMPOS camera position, in objectspace
    - VID_CAMDIR camera view direction
    - VID_CAMUP camera up vector
    - VID_FOGCOLOR fog color
    - VID_LIGHTPOSx light x position in objectspace, x from 0 to 3
    - VID_LIGHTDIRx light x direction in objectspace,
    - VID_LIGHTCOLORx light x color
    - VID_LIGHTRANGEx (range,1/range,range/2,range*range)
    - VID_RANDOM result is (rand1*range,rand2*range,rand3*range,range)
      rand are random numbers [0,1] that are fixed with the drawnode
      range is given by user <w>
    - VID_TIME time values result is(time*scale,sin(time*scale),cos(time*scale),scale)
      time is in milliseconds,scale is given by user <w>
    - VID_FOGCOLOR fog color
    - VID_TEXCONSTx texture constant id, x from 0 to 7. Stage's color as in material is used.

  - (x,y,z,w)
    the vector, will be overwritten when type is not VID_VALUE
    some special types will keep the <w float> as function value

### NewPass flags:

- colorpass;
  renders without setting a new color untextured the model again.

### NewPass functions:

- alphafunc
  see RenderFlag

Content

## History

1st Draft 17.4.2004
This is just a basic idea about functionality. Shaders may change on implentation if too complex to a more rigid system with a hardcoded set of FX

2nd Draft 28.4.2004
moved stageflags to renderflags, moved alpha/blend to renderflag as well, this is easier to work with in OGL, but needs a new system for texture blending which needs to be done soon (mainly combine)

3rd Draft 1.5.2004
texture blending and combining is now set.

4th Draft 10.5.2004
added a new custom texmode called VID_COLORDECAL, removed GL_SUBTRACT cause it brings us in trouble with older systems. CBF to do workaround.

5th Draft 12.5.2004
okay texcombine is removed, instead there are fixed effect types possible for the combining of texlayers. depending on hardware I will create the proper texcombiners/multipass renders.

6th Draft 2.6.2004
it will stay as is, although multiple textures per shader may not work well on all hardware until a "brute force" rendering pipeline is part of the engine.

7th Draft 7.6.2004
added reflectmap,eyelinmap as texture coord generation mode

8th Draft 31.7.2004
blendfunc is not valid for all passes just the first pass (first tex + color) also added LITMODADD and ADDMOD modes

9th Draft 13.8.2004
added LITDECAL_VERTEX and DECAL_VERTEX modes

10th Draft 30.8.2004
added BUMP mode

11th Draft 2.8.2004
added SPECBUMP mode

12th Draft 27.9.2004
changed BUMP to NORMAL and SPECBUMP to SPECNORMAL

13th Draft 15.10.2004
LIT renamed to COLOR

14th Draft 18.10.2004
ALPHA as texture mode to upload greyscales added nocolorarray renderflag

15th Draft 20.10.2004
blendfunc taken out, heavy reorganisation of blends now part of every stage as blendmode

16th Draft 1.11.2004
added LowDetail? stage

17th Draft 6.12.2004
addded GPUProgram? and FXShader? stage, the latter is not implemented at all and the first doesnt allow DXPSA yet

18th Draft 10.12.2004
layer renderflag added, to allow user to mark certain surfaces to be rendered at certain times. allows Zsort, Glow, Haze, Top layer (thats also the order in which they are drawn) removed DXPSA gpuprog type

19th Draft 19.12.2004
modifers need a name to be accessible from gamecode

20th Draft 22.12.2004
added techniques and shaders "values" need to be put in () vectors separated by , special Textures allowed in higher techniques (skybox, normalize...) gpuprogram parameters will soon allow special values (campos, camdir..) to be auto linked with

21th Draft 29.12.2004
name is a unique identifier of the stage to allow easier access to stages from gamescript LIGHTMAP added

22nd Draft 23.2.2005
split shader into "shader/material" so that shader only contains info how textures are blend

23rd Draft 15.3.2005
added "skin" versions for vertex programs

24th Draft 31.3.2005
added "texcoord" to allow use of different texcoord channels

25th Draft 16.7.2005
added "lit" versions for gpu programs and entrynames

26th Draft 23.7.2005
added new Techniques for better hardware, also added new automatic shader parameters

27th Draft 6.1.2006
the NewPass? Stage is introduced to allow manual 'compiling'

28th Draft 27.5.2006
added .dds support

29th Draft 20.6.2006
sunreflectmap and sunnormalmap
added TEXDOTZ for special cubemaps

30th Draft 2.7.2006
lit renamed to sunlit
added alphaTEX

31st Draft 28.7.2006:
texture clamping and texgenplane added.
eyelinmap renamed to worldlinmap, objlinmap added as well.

32nd Draft 1.8.2006:
all combiners (alpha/color) are now accessible. alphamode was added
33rd Draft 10.8.2006:
added "preprocessor" branching

34th Draft 2.9.2006:
param for regular stages

35th Draft 25.12.2006:
param for regular stages got support for lightcolor/lightdir

36th Draft 31.1.2007:
normals; flag also added to RenderFlag?

Content