Программирование игр
/ GameDev.ru / Программирование / Термины / Fog (Туман)

Fog (Туман)

Окружающий туман - эффект, который используется во всех играх, поскольку позволяет придать объектам или сцене реалистичность, а также "почувствовать" глубину сцены. Кроме того, он позволяет скрыть ненужную геометрию.

Описание
Линейный туман
Экспоненциальный (квадратичный) туман
Ссылки

Описание

Эффект тумана зависит от трех основных компонент:
1. Цвет тумана (C).
2. Плотность (g).
3. Расстояние (d).

В сцене с туманом, интенсивность света, которая достигает камеры пользователя, зависит от трех компонент:
1. Поглощение - величина, которая регулирует перекрытие световой интенсивности частиц вдоль трассируемого луча.
2. Рассеивание - это выбивание лучей из луча, который идет к глазу.
3. Рассеивание внутрь - это попадание (из-за рассеивания) других лучей в луч, который идет к глазу.
Эти три компоненты обобщают и характеризуют одним коэффициентом g, т.е. плотностью.

Поскольку объекты находящиеся в дали должны больше поддаваться эффекту тумана, ввели коэффициент d, т.е. расстояние. Окончательный цвет вершины получают интерполированием цвета тумана и текущем цветом: Lerp(Cfog, Ccurrent, f)

Где f - влияние тумана на цвет вершины, т.е. при 0 - цвет вершины будет цветом тумана (это случай когда геометрия находится вдали от зрителя), а при 1 - наоборот соответственно.

Вычислять Cfinal надо только в том случае, если вы используете пиксельный шейдер:

float4 Cf;
sampler BaseTexture;

struct PS_INPUT
{
      float2  texcoord :   TEXCOORD0;
      float  f:         TEXCOORD1;
};
float4 main(PS_INPUT Input): COLOR
{
      float4 Ccur = tex2D(BaseTexture, Input.texcoord);
      return lerp(Cf, Ccur * Input.Diffuse, Input.f);
}

Иначе это сделает за нас direct3d9 установкой следующих стейтов:

mRenderDevice->SetRenderState(D3DRS_FOGCOLOR, color);
mRenderDevice->SetRenderState(D3DRS_FOGENABLE, TRUE);
Draw();
mRenderDevice->SetRenderState(D3DRS_FOGENABLE, FALSE);

или с помощью OpenGL:

glEnable( GL_FOG );
glFogi( GL_FOG_COLOR, color);
Draw();
glDisable( GL_FOG );

Линейный туман


Самый простой из всех видов.

Основное уравнение:
f = (Zfogend – d)/(Zfogend – Zfogstart)
В таком случае частицы тумана распределяются равномерно от точки Zfogstart и до точки Zfogend. d – представляет глубину, или расстояние от видового вектора до начала появления тумана. Вот простенький шейдер для линейного тумана:

float2 mFog; //x – начало тумана, y – конец тумана.
float4x4 matWorldViewProj;
float4x4 matView;

VS_OUTPUT main(VS_INPUT Input)
{
VS_OUTPUT Out = (VS_OUTPUT) 0;

float4 d = mul(Input.Position, matWorldView);

float f = (mFog.x - d.z)/(mFog.x - mFog.y);
//Результат переводится в диапазон [0..1] для правильности //вычислений по основной формуле расчета тумана.
Out.Fog = clamp(f, 0.0f, 1.0f);

Out.Position = mul(Input.Position, matWorldViewProj);
Out.Tex0.xy = Input.Tex0.xy;
//Диффузионный цвет необходим для смешивания, как основной цвет //вершины.
Out.Diffuse = Input.Diffuse;

return Out;
};

Стоит уделить внимание строчке:

float4 d = mul(Input.Position, matView);

В ней мы получаем вершину в пространстве камеры, и затем берем z координату этого вектора, что бы получить расстояние d. Это более грубый и дешевый способ расчета расстояния.

Второй способ состоит в вычислении расстояния между позицией вершины и видовым вектором:

float d = distance(Position_in_world_space, View_Vector);
Что более дорого для вычисления.

Экспоненциальный (квадратичный) туман


В этом случае, плотность тумана более быстро и плавно уменьшается чем в случае с линейным туманом, поэтому эффект отлично приближен к реальному эффекту.

Представьте, что луч можно разбить на множество отрезков, где каждый отрезок имеет свою единичную длину. С каждым продвижением этого луча, интенсивность отрезка уменьшается на коэффициент g, в свою очередь следующий отрезок также будет сокращен на g и т.д. Поэтому такое поведение легко смоделировать с помощью экспоненциальной функции.

Основное уравнение для экспоненциального тумана:
f = exp(-d*g)
для экспоненциального квадратичного тумана:
f = exp(-(d*g)*(d*g) )

Вершинный шейдер:

float g; //плотность.
float4x4 matWorldViewProj;
float4x4 matWorld;
float4 viewvec;
bool expfog;

VS_OUTPUT main(const VS_INPUT Input)
{
VS_OUTPUT Out = (VS_OUTPUT) 0;
//Используем второй способ расчета d:
float dist = distance(mul(Input.Position, matWorld), viewvec);
//Добавлен флаг expfog, что бы шейдер заново не переписывать.
if(expfog)
{
//Экспоненциальный туман:
float f = exp(-dist *g);
}
else
{
//Экспоненциальный квадратичный туман:
float f = exp(-(dist * g) *(dist * g));
}
//Результат переводится в диапазон [0..1] для правильности //вычислений по основной формуле расчета тумана.
Out.Fog = clamp(f, 0.0f, 1.0f);
//Диффузионный цвет необходим для смешивания, как основной цвет //вершины.
Out.Diffuse = Input.Diffuse;
//
Out.Position = mul(Input.Position, matWorldViewProj);
Out.Tex0.xy = Input.Tex0.xy;
return Out;
};

Ссылки


http://www.gamedev.net/reference/articles/article677.asp

Что такое Fog (Туман)?

29 июля 2005

Категории: fog

Комментарии [5] |

Права на документ принадлежат автору, указывайте ссылку при цитировании
Последнее обновление: 13 июня 2009

2001—2010 © GameDev.ru — Разработка игр