К сожалению всё руки не доходят посмотреть тот движок, хотя я заметил там несколько классных фич которые надо бы перенять.
Вот мой код:
/*
================================================================================
rc2d::FogCompute
================================================================================
*/
auto rc::rc2d::FogCompute( Pyramid::Vector3f& outColor, const Pyramid::Vector3f& inColor, float rayLen ) const noexcept ->void {
if ( rayLen > desc.fogMaxClamp ) {
rayLen = desc.fogMaxClamp;
} else if ( rayLen < desc.fogMinClamp ) {
rayLen = desc.fogMinClamp;
}
float fogValue = ( rayLen - desc.fogMinClamp ) / ( desc.fogMaxClamp - desc.fogMinClamp );
fogValue *= desc.fogFactor;
outColor = inColor + ( desc.fogColor * fogValue );
outColor.Saturate();
}
Сразу замечу что представление цвета я храню в 3д векторе типа float и уже непосредственно при записи в пиксел я конвертирую в uint32. В твоём случае (для возможности игры на mmx и более старых машинах) так лучше не делать.
outColor - результирующий цвет.
inColor - исходный цвет.
rayLen - длина луча до стены (или пола/потолка).
Первая часть функции это условия чтобы регулировать на каком расстоянии туман начинается и на каком он достигает своего максимального значения ( desc.fogMinClamp и desc.fogMaxClamp соответственно ).
Между этими значениями происходит линейная интерполяция, которая осуществляется в следующей строке кода и записывается в fogValue. Результат будет в диапазоне 0.0f - 1.0f.
Затем идет домножение на desc.fogFactor чтобы нормализованное значение изменить таким образом в соответствии с решением задуманным дизайнером.
Дальше мы умножаем на desc.fogColor чтобы задать цвет туману и прибавляем результат цвета к исходному inColor цвету пиксела.
Затем функция Saturate просто обрезает (не нормализует) значения вектора в диапазон [0.0f; 1.0f] - это аналогично функции saturate или clamp( x, 0.0f, 1.0f ) из HLSL.