$detailblendfactor is not respected by UnlitGeneric material shader

Author: chaoraceCreated Jul 19, 2026Updated Jul 24, 2026

Currently, most of the $detailblendmode options work with the UnlitGeneric shader except for one serious problem: $detailblendfactor is permanently stuck at 0 regardless of what's programmed into the VMT.

The issue stems from the fact that UnlitGeneric and VertexLitGeneric both rely on the same helper code to set $detailblendfactor: https://github.com/ValveSoftware/source-sdk-2013/blob/88fa198fba3fb85d46d4c95018254693fdc3af0a/src/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.cpp#L1214

As you can see above, $selfillumtint and $detailblendfactor share the same register, with the first three channels being utilized by $selfillumtint and the final channel being utilized by $detailblendfactor. This is a problem because $selfillumtint is hardcoded to -1 in the UnlitGeneric shader, which in turn causes the write for BOTH components of the register's channels to be skipped

It looks to me like full funtionality of $detailblendmode in UnlitGeneric can be restored by simply guarding against this -1 condition and instead writing white to the $selfillumtint channels rather than the current behavior of discarding everything. The shader never actually accesses those channels, so it seems completely safe to do so:

if ( info.m_nSelfIllumTint != -1 )
{
      pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant_W( 4, info.m_nSelfIllumTint, fBlendFac
}
else
{
      pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant4( 4, 1.0f, 1.0f, 1.0f, fBlendFactor );
}

This fix would be extremely nice to have for usecases like mine (drawing abstract 3D visualizations from VScript). Visualizations like these can greatly benefit from utilizing smooth two-texture blend effects, but currently that's impossible without the extremely undesirable world lighting that VertexLitGeneric imposes.

Source: ValveSoftware/source-sdk-2013