Объемный туман из компьютерной игры Tomb Raider 4 (Fog Bulb)

volume fog dx9

Загрузить исходный код для Visual Stduio 2005 и DirectX 9 June 2010 SDK ЗДЕСЬ.

Тот же принцип объемного тумана из TR4 реализованный на Visual Stduio 2019 и DirectX 12 ЗДЕСЬ.

Алгоритм программы следующий (для Visual Stduio 2005 и DirectX 9 June 2010 SDK).

  1. Есть исходные данные - позиция наблюдателя (камеры), есть вершины треугольников сцены (сама сцена на экране), и так же сфера, размещенная на этой сцене. Каждая вершина треугольников сцены имеет формат - координаты x,y,z, зеркальная составляющая цвета вершины, текстурные координаты.
  2. На следующем этапе есть цикл в котором мы перебираем все вершины сцены (функция Update). В этом цикле мы проводим вектор от позиции камеры до вершины (каждого треугольника сцены). И проверяем- пересекает этот вектор сферу на сцене или нет. Если пересекает есть две точки пересечения - вход вектора в сферу и выход из сферы. Мы берем эти две координаты и узнает между ними расстояние. Это расстояние принимается за интенсивность тумана - пересечение вектора ближе к краю сферы дает меньшую интенсивность тумана, пересечение ближе к центру сферы дает большую интенсивность тумана, так как расстояние между точками перечечения разное.
  3. В этом же цикле когда мы перебираем все вершины, и узнали интенсивность тумана, эту интенсивность записываем как альфа- составляющую зеркального цвета вершины, rgb компоненты зеркального цвета не имеют значения, могут быть ноль.
  4. Теперь можно перейти к рисованию сцены с туманом - устанавливаем renderstate cullmode, если нет нормалей в вершинах (у нас нет) устанавливаем render state lighting false, и теперь самое главное: D3DRS_FOGENABLE -> true, устанавливаем цвет тумана D3DRS_FOGCOLOR, устанавливаем Fog End и Fog Start, и самое важное устанавливаем D3DRS_RANGEFOGENABLE -> true.
  5. Вызываем функцию DrawPrimitive() для отрисовки сцены.

	m_pD3DDevice->SetRenderState(D3DRS_FOGENABLE, TRUE);

	DWORD fog_colr = D3DCOLOR_ARGB(0xFF, 0, 223, 191);
	m_pD3DDevice->SetRenderState(D3DRS_FOGCOLOR, fog_colr);

	float m_fFogStart = 1024.0f * 12.0f;
	float m_fFogEnd = 1024.0f * 20.0f;

	m_pD3DDevice->SetRenderState(D3DRS_FOGSTART, *(DWORD *)(&m_fFogStart));
	m_pD3DDevice->SetRenderState(D3DRS_FOGEND,   *(DWORD *)(&m_fFogEnd));

	m_pD3DDevice->SetRenderState(D3DRS_RANGEFOGENABLE, TRUE);