M2/Rendering
WIP
Blending Modes
All clients dating back to at least Wrath of the Lich King follow the state table below. The table is up to date with all blending modes present in the 7.1.0.22996 retail client. Not all blending modes are used, especially in older clients.
Wrath of the Lich King and Cataclysm do not use separate alpha blending. Legion does use separate alpha blending. It's currently unknown if Mists of Pandaria or Warlords of Draenor use separate alpha blending.
Blend_BlendAdd was added after Cataclysm.
Blend function enums are for OpenGL, but each has a Direct3D equivalent. Most pairings should be obvious, except: in Direct3D, CONSTANT_ALPHA is BLEND_FACTOR and ONE_MINUS_CONSTANT_ALPHA is INV_BLEND_FACTOR.
M2Material Blending Mode to blendStateIdx
In Wrath of the Lich King (and possibly newer clients), the blendStateIdx column does not directly match the M2Material blending_mode value present in M2 files. The value is translated through the following mapping table: { 0, 1, 2, 10, 3, 4, 5 }
Blend State Table
blendStateIdx | Mode | Blending Enabled | Src Color | Dest Color | Src Alpha | Dest Alpha |
---|---|---|---|---|---|---|
0 | Blend_Opaque | Disabled | ONE | ZERO | ONE | ZERO |
1 | Blend_AlphaKey | Disabled | ONE | ZERO | ONE | ZERO |
2 | Blend_Alpha | Enabled | SRC_ALPHA | ONE_MINUS_SRC_ALPHA | ONE | ONE_MINUS_SRC_ALPHA |
3 | Blend_Add | Enabled | SRC_ALPHA | ONE | ZERO | ONE |
4 | Blend_Mod | Enabled | DST_COLOR | ZERO | DST_ALPHA | ZERO |
5 | Blend_Mod2x | Enabled | DST_COLOR | SRC_COLOR | DST_ALPHA | SRC_ALPHA |
6 | Blend_ModAdd | Enabled | DST_COLOR | ONE | DST_ALPHA | ONE |
7 | Blend_InvSrcAlphaAdd | Enabled | ONE_MINUS_SRC_ALPHA | ONE | ONE_MINUS_SRC_ALPHA | ONE |
8 | Blend_InvSrcAlphaOpaque | Enabled | ONE_MINUS_SRC_ALPHA | ZERO | ONE_MINUS_SRC_ALPHA | ZERO |
9 | Blend_SrcAlphaOpaque | Enabled | SRC_ALPHA | ZERO | SRC_ALPHA | ZERO |
10 | Blend_NoAlphaAdd | Enabled | ONE | ONE | ZERO | ONE |
11 | Blend_ConstantAlpha | Enabled | CONSTANT_ALPHA | ONE_MINUS_CONSTANT_ALPHA | CONSTANT_ALPHA | ONE_MINUS_CONSTANT_ALPHA |
12 | Blend_Screen | Enabled | ONE_MINUS_DST_COLOR | ONE | ONE | ZERO |
13 | Blend_BlendAdd | Enabled | ONE | ONE_MINUS_SRC_ALPHA | ONE | ONE_MINUS_SRC_ALPHA |
Credits: Deamon, for unearthing blending mode names and laying out the original table; relaxok, for checking D3D state at runtime; schlumpf, for the initial reversing work; fallenoak, for mapping Deamon's table to OpenGL enums and verifying values across several expansion clients.
Fog Modes
Because blending modes adjust how color is applied during a draw call, fog color often has to be modified accordingly. The client maps blending modes to fog modes using s_fogModeList.
M2Material flag 0x02 causes fog mode 0 (disabled) to always be selected, regardless of blending mode.
In certain cases (possibly when the mesh or the camera is underwater), s_blendDisableUWFog may force fog mode 0 (disabled) to be selected based on blending mode. As of Mists of Pandaria, it appears this applies to Blend_Add and Blend_NoAlphaAdd.
The following fog modes were taken from Mists of Pandaria (build 15662).
Fog Mode | Action | Blending Modes |
---|---|---|
0 | Disable fog logic in shader | - |
1 | Use fog color (without changes) | Blend_Opaque, Blend_AlphaKey, Blend_Alpha |
2 | Override fog color to 0x000000 (black) | Blend_Add, possibly: Blend_NoAlphaAdd |
3 | Override fog color to 0xFFFFFF (white) | Blend_Mod |
4 | Override fog color to 0x808080 (half white) | Blend_Mod2x |
5 | ? submerged camera related; use ViewSettings::s_fogInfo 2 or 3 | - |
6 | ? liquid plane related; use ViewSettings::s_fogInfo 3 or use CM2Lighting fog | - |
Lighting Modes
Similar to fog modes above, blending modes also impact lighting. The client maps blending modes to lighting modes using s_shadedList.
M2Material flag 0x01 always causes lighting mode 0 (disabled) to be selected.
The following lighting modes were taken from Mists of Pandaria (build 15662).
Lighting Mode | Action | Blending Modes |
---|---|---|
0 | Disable lighting logic in shader, including local lights | Blend_Mod, Blend_Mod2x |
1 | Enable lighting logic in shader | Blend_Opaque, Blend_AlphaKey, Blend_Alpha, Blend_Add, possibly: Blend_NoAlphaAdd |
M2Elements
An M2 is rendered as a series of M2Elements, which are constructed at runtime in CM2SceneRender::BeginDraw()
Element Alpha
For a given M2Element, whole-element alpha is calculated by multiplying the following things together:
- batch->color.alpha is the M2Batch animated color track alpha value (if present)
- batch->textureWeight is the M2Batch animated texture weight track value (if present)
- m2->alpha is overall model opacity, which can be manipulated by things like distance fading and similar effects; default: 1.0
element->alpha = batch->color.alpha * batch->textureWeight * m2->alpha;
Alpha Testing
Alpha testing is enabled for most or all M2Elements being rendered. The alpha comparison function is always D3DCMP_GREATEREQUAL, which discards pixels with alpha values lower than the provided alphaRef.
For Blend_AlphaKey blending, the alphaRef value starts at a baseline, and is multiplied by the M2Element->alpha. See the M2Element alpha section above for more details.
For all other blending modes (ie !(Blend_AlphaKey), the alphaRef value is constant.
Blending Mode | alphaRef | |
---|---|---|
!(Blend_AlphaKey) | All | 1.0 / 255.0 (constant) |
Blend_AlphaKey | >= Cata | (128.0 / 255.0) * element->alpha |
<= WotLK | (224.0 / 255.0) * element->alpha |