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 – представляет глубину, или расстояние от видового вектора до начала появления тумана. Вот простенький шейдер для линейного тумана:
Стоит уделить внимание строчке:
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
Права на документ принадлежат автору, указывайте ссылку при цитировании
Последнее обновление: 13 июня 2009