GLDEFS

From ZDoom Wiki
Jump to: navigation, search
Center Warning: This feature does not work in ZDoom but in its OpenGL children ports.

GLDEFS lumps allow to define several effects that are supported only by the OpenGL hardware renderer used in GZDoom and Skulltag. Outside of ZDoom-derived source ports, GLBoom+ supports some features of the lump (notably, skybox definitions) and features its own extensions, documented DoomWikiLogoIcon.pngon the Doom wiki.

Because ZDoomGL did it so, a number of game-specific aliases are supported as well as GLDEFS:

DOOMDEFS (for Doom)
HTICDEFS (for Heretic)
HEXNDEFS (for Hexen)
STRFDEFS (for Strife)

When playing a game, the content of the lumps that do not correspond to that game are ignored. However, given the absence of actor name conflicts between these games, using one of these aliases is rather pointless. Further, this system is not extended to games whose support was more recently added to ZDoom, such as Chex Quest.

You can use #include statements in any of these lumps. For example, you could find this in a pk3 file:

#include actors/monsters.gl
#include actors/missiles.gl
#include actors/decorations.gl

Or, the same organization but in a wad file:

#include MONSLITE
#include MISLLITE
#include DECOLITE

Dynamic lights

GLDEFS allow to define dynamic lights, similar to the DynamicLight actors, that are bound to chosen states of chosen actors. They are created and destroyed automatically when needed and follow their bound actor on the map.

Dynamic light definitions

A dynamic light in defined in this manner:

<lighttype> <LIGHTNAME>
{
    ...
}
  • lighttype: The type of light. This can be "PointLight", "FlickerLight", "FlickerLight2", "PulseLight" or "SectorLight".
  • LIGHTNAME: The name of the light (to be used later when binding it to objects/frames).

Inside the brackets you define the light properties. These differ for the different types of lights. Properties between [square brackets] are optional. Here are examples of each type:

pointlight POINT
{
    color <RED> <GREEN> <BLUE>
    size <SIZE>
    [offset <X> <Y> <Z>]
    [subtractive <SUB>]
    [attenuate <ATT>]
    [dontlightself <DLS>]
}
  • RED, GREEN and BLUE: Color components (each between 0.0 and 1.0).
  • SIZE: Size of the light, in map units.
  • X, Y and Z: The offset for the light in map units. This is relative to a thing's sprite, not the world, so the Y axis is height and the Z axis is depth. Defaults to 0,0,0.
  • SUB: Either 1 or 0. Subtractive lights 'darken' the area around them rather than light them.
  • ATT: Either 1 or 0. Attenuated lights illuminate surfaces depending on surface angle — surfaces that are not facing the light will get progressively less illuminated.
  • DLS: Either 1 or 0. If dontlightself is set to 1, the dynamic light will not affect the sprites to which it is bound.


pulselight PULSE
{
    color <RED> <GREEN> <BLUE>
    size <SIZE>
    secondarySize <SECSIZE>
    interval <INTERVAL>
    [offset <X> <Y> <Z>]
    [subtractive <SUB>]
    [attenuate <ATT>]
    [dontlightself <DLS>]
} 
  • SECSIZE: The size to 'pulse' to. In the same units as SIZE. This value must be greater than SIZE.
  • INTERVAL: The time it takes to complete a full pulse (in seconds).
flickerlight FLICKER
{
    color <RED> <GREEN> <BLUE>
    size <SIZE>
    secondarySize <SECSIZE>
    chance <CHANCE>
    [offset <X> <Y> <Z>]
    [subtractive <SUB>]
    [attenuate <ATT>]
    [dontlightself <DLS>]
}
  • SECSIZE: The second size to flicker (will alternate between SIZE and SECSIZE). SECSIZE must be greater than SIZE.
  • CHANCE: The chance, each frame, that it will flicker to the second size. The value ranges from 0.0 (never) and 1.0 (always).
flickerlight2 FLICKER2
{
    color <RED> <GREEN> <BLUE>
    size <SIZE>
    secondarySize <SECSIZE>
    interval <INTERVAL>
    [offset <X> <Z> <Y>]
    [subtractive <SUB>]
    [attenuate <ATT>]
    [dontlightself <DLS>]
}
  • SIZE and SECSIZE: Lower and upper bounds for the size (the light will pick a random value between the two). SECSIZE must be greater than SIZE.
  • INTERVAL: The time between 'flickering' to a new random size. Same as for pulselight, but 0.1 is one second, not 1.0.

The sectorlight takes its intensity from the light level of the sector it's in.

sectorlight SECLIGHT
{
    color <RED> <GREEN> <BLUE>
    scale <SCALE>
    [offset <X> <Z> <Y>]
    [subtractive <SUB>]
    [attenuate <ATT>]
    [dontlightself <DLS>]
}
  • SCALE: How much of the containing sector's intensity to use (between 0.0 and 1.0)

Dynamic light binding

Once dynamic lights are defined, they must be bound to actors. There are two possible methods to do so; the binding can be done directly in the actors' DECORATE code, or in the GLDEFS lump. The most important difference is that bindings made in DECORATE code are preserved through inheritance, whereas bindings made in GLDEFS are applied only to the actor itself and not its descendants. For the first method, see the actor states article. The GLDEFS method follows.

object [CLASSNAME]
{
    frame [SPRITENAME]
    {
         light [LIGHTNAME]
         ...
    }
    ...
}
  • CLASSNAME: An actor class. A full list of these can be found at the ZDoom wiki.
  • SPRITENAME: The first few characters of the sprite name. This can be either a sprite name (four characters) or a frame name (five characters). For example, "MISL" will bind the light to all frames (used by that object) using a "MISL" sprite; whereas "MISLA" will bind the light specifically to the "MISLA" frame.
  • LIGHTNAME: The name of a previously defined light (see above). It is possible to bind multiple lights to a single object, however only at most two lights will be used on a given frame: the one bound for this object to this frame in particular, and the one bound to the sprite. If several lights are bound for the same object to the same sprite or frame, only the last binding applies.

Example

pointlight BLURSPHERE1
{
    color 1.0 0.0 0.0
    size 40
    offset 0 16 0
}

pointlight BLURSPHERE2
{
    color 0.0 0.0 1.0
    size 32
    offset 0 16 0
}

pointlight BLURSPHERE3
{
    color 0.0 0.0 1.0
    size 24
    offset 0 16 0
} 

pointlight BLURSPHERE4
{
    color 0.0 0.0 1.0
    size 16
    offset 0 16 0
}

pointlight BLURSPHERE5
{
    color 0.0 0.0 1.0
    size 8
    offset 0 16 0
} 

object BlurSphere
{
    frame PINS { light BLURSPHERE1 }
    frame PINSA { light BLURSPHERE2 }
    frame PINSB { light BLURSPHERE3 }
    frame PINSC { light BLURSPHERE4 }
    frame PINSD { light BLURSPHERE5 }
}

This binds the light BLURSPHERE1 to all of the BlurSphere's frames (PINS*) for the red sphere, and extra lights on top of it (BLURSPHERE2-5 to PINSA-D) for the animated blue blob in the middle.

Skybox definitions

Note: GZDoom is also able to parse the Vavoom SKYBOXES lump. See here for more information.


The GLDEFS lump can also be used to define skyboxes similar to those used in Quake II, made from a textured cube. The textures must be specially polarized so that the skybox will not appear to be a cube when seen in the game. A skybox is defined with the skybox <name> line, and followed by a list of textures within bracket. The given name can then be used as a texture name for the sky in MAPINFO.

There are two options, a six-texture skybox and a three-texture skybox.

If the skybox has six square graphics, one for each face of the cube, you must specify all six of them in order: North, East, South, West, Top, Bottom.

Skybox MYSKY6 [fliptop]
{
  MYSKY6_N
  MYSKY6_E
  MYSKY6_S
  MYSKY6_W
  MYSKY6_T
  MYSKY6_B
}

If the skybox has only three square graphics, there must be one for the four walls and one each for the top and the bottom. The order is similar: Wall, Top, Bottom.

Skybox MYSKY3 [fliptop]
{
  MYSKY3_W
  MYSKY3_T
  MYSKY3_B
}

Note that this feature was accidentally implemented with a non-standard skybox graphic as reference so the top face was inadvertently flipped. To use skyboxes made for games like Quake 2, Quake 3 or Half-Life you either need to flip the top image yourself or use the fliptop keyword.

The bottom picture must be aligned with the north picture so that it fits right just under it. The top picture must likewise be aligned so that it fits right just above the north picture, but after that it must be mirrored horizontally and rotated 180°. Skyboxes made for other games may not fit these specifications unless you use the fliptop keyword.

Brightmaps

Another feature of the GLDEFS lump is to define brightmaps that can be used to alter the brightness of given pixels within an otherwise static image. Brightmaps can be defined for sprites, flats and textures, but not for patches. This can be used, for example, to make back-lit computer screens, an enemy whose eyes glow in the dark, or to light up only the weapon part of an image when an enemy fires, rather than lighting the whole enemy.

To create a brightmap, first an image must be created that defines the base brightness of each pixel in the image. Black represents 0 brightness (no change) while white represents full-bright. Normal light is grayscaled, but it is possible to use color in order to tint the light. Note that this is the minimum light level the pixel will show at; if the area the monster is standing in is not completely pitch-black, the pixels will be lit to the ambient surrounding light level. Therefore, an enemy standing in an area with full brightness (such as a sector with a light level of 255) will be completely unaffected by his associated brightmap.

Once the image is created, the following definition needs to be added to the GLDEFS lump to link each sprite image to its brightmap:

brightmap <flat|sprite|texture> <IMAGE>
{
   map <BRIGHTMAP>
   [iwad]
   [thiswad]
   [disablefullbright]
}

One of the keywords flat, sprite or texture must be used. <IMAGE> is the name of the graphic within the WAD. Examples are PLAYF1 or BAL1A0. Whenever this graphic is displayed in the game, the specified <BRIGHTMAP> will be applied. <BRIGHTMAP> can be a lump name (for a WAD file), or a complete path to the image in a PK3 file.

If the iwad keyword is present within the definition, then the brightmap will not be applied if the image is replaced by a loaded PWAD. This is useful so that if the user is loading a PWAD that replaces a given enemy, the brightmap doesn't end up trying to apply itself to a graphic which no longer represents the same thing, possibly resulting in an incorrectly-lit enemy or decoration. In general, you don't need to worry about adding this keyword if you're creating brightmaps for your custom creations.

The thiswad keyword acts as the iwad keyword, but only for sprites contained in the same file as the definitions. It can be used if you expect your mod to have its custom graphics overridden by another mod; making it mostly useful for autoloaded sprite packs. If both iwad and thiswad are given to the same definition, it will be applied if the sprite is either from the iwad or from the wad.

The disablefullbright keyword causes the renderer to ignore the bright keyword applied to a frame within DECORATE. This can allow a user to override fullbright sprites that would otherwise nullify the effects of a brightmap. It's useful for player modifications because you can create an enemy which uses bright frames for its attacks, which will be seen by players who do not opt to allow brightmaps, or whose hardware doesn't support it. For everyone else, the brightmaps will override these bright frames.

All brightmap images in the brightmaps/auto directory are automatically assigned to the same-named texture. This removes the need to do individual assignments for those brightmaps.

Glowing flats

Floor and ceiling textures can be made to glow. This effect works well for materials such as lava, computer screens, lamps, and so on. While the effect can be added to both flats and textures, it will only work when said flats and textures are applied on a floor or ceiling; if applied to a wall they will simply not glow.

The syntax is of this form:

Glow
{
	Flats
	{
		flat name
		flat name
		flat name
		...
	}
	Walls
	{
		texture name
		texture name
		texture name
		...
	}
	Texture "flat name", color[, glow height] [, fullbright]
}

Use a Flats block to define a list of flats that have to glow. The glow will use default settings: the glow height is 64, the color is averaged from the mapped picture, and the flat is set to be fullbright. Use a Walls block in the same way, but for textures. Despite the "walls" moniker, keep in mind that they do not work if actually set on a wall; only on floors and ceilings.

Use a Texture entry to define the parameters yourself. Contrarily to "Flats" and "Walls", "Texture" is not a block and only define the glow for a single texture. The color parameter must be either a RGB hex triplet, such as C010A8, or one of the recognized X11R6 color name, such as SlateGray1 or PowderBlue. Optionally, a glow height parameter can be given to set how high the glow goes, this must be an integer. Optionally as well, the definition can be finished with the fullbright keyword. If this keyword is not given, the affected texture will not be set to be fullbright.

Hardware shaders

Graficon.gif Warning: This feature is GZDoom specific, and is not compatible with ZDoom!
To see all of GZDoom's specific features, see GZDoom features.

Custom hardware fragment (ie pixel) GLSL shaders can be written and applied to sprites, flates, and textures. This requires a two step process.

The first step is to write a complying shader function. Each fragment shader requires a single function, Process, to be correctly defined. The function returns a vec4 that corresponds to the color your pixel should be. The function takes in a single vec4 parameter called color. This value has already had lighting and fog applied to it, and consequently should be multiplied in to your result.

This function must be saved in your archive as a text lump. The following example is how GZDoom implements the warping graphics feature:

uniform float timer;
vec4 Process(vec4 color)
{
  vec2 texCoord = gl_TexCoord[0].st;
  const float pi = 3.14159265358979323846;
  vec2 offset = vec2(0,0);
  offset.y = sin(pi * 2.0 * (texCoord.x + timer * 0.125)) * 0.1;
  offset.x = sin(pi * 2.0 * (texCoord.y + timer * 0.125)) * 0.1;
  texCoord += offset;
  return getTexel(texCoord) * color;
}

While warped graphics would not normally allow you to apply a fragment shader to them (being implemented internally via a compliant Process function), extending this shader and applying it to your textures independently of ANIMDEFS will allow you to create advanced warp effects.

The second step to implementing custom fragment shaders is to define a HardwareShader entry in GLDEFS. Only one shader can be defined per valid graphic. A definition takes the following form:

HardwareShader [Type] <LumpName>
{
	Shader "<File>"
	Speed <Value>
}

[Type] is an optional and is one of either Flat, Sprite, Texture. This is useful to prevent ambiguity if the same name is used by several graphics of different kinds. <LumpName> corresponds to the graphic to which it is applied. <File> corresponds to the text lump containing your Process function. <Value> is a floating point value that defines a multiplier to be applied to the timer uniform.

Advanced shader topics

In GLSL, there are three basic data input types: attribute, uniform, and varying. uniform and varying data types are the only types available to custom fragment shaders. uniform values are constants set by GZDoom; while varying values are those that have been processed by the vertex shader. It is recommended that you do not use these variables unless you are experienced in GLSL.

The following uniform variables are always available to your shaders:

  • int fogenabled
  • vec4 fogcolor
  • vec3 dlightcolor
  • vec3 camerapos
  • float desaturation_factor
  • vec4 topglowcolor
  • vec4 bottomglowcolor
  • int texturemode
  • sampler2D tex
  • float timer
If you wish to use the timer uniform, you must define it yourself at the top of your shader file.

If the DYNLIGHT define is defined, the following uniform variables available:

  • ivec3 lightrange
  • vec4 lights[256]
Only if MAXLIGHTS128 is not defined
  • vec4 lights[128]
Only if MAXLIGHTS128 is defined

The following varying variables are always available to your shaders:

  • float lightlevel
  • vec2 glowdist
  • vec4 pixelpos
  • vec4 fogparm

The X and Y coordinates are between 0.0 and 1.0. If you want to have the dimension of the image in texel, you can use the textureSize function, in this way:

ivec2 texSize = textureSize(tex, 0);

In this line, ivec2 corresponds to a 2D vector of integers, texSize is the name of the variable (you can use a different one if you want), tex is the name of the texture sampler, and 0 specifies we want its maximum dimensions (not those of a mipmap level). The image dimensions will then be available as texSize.x and texSize.y.

External links