Главная Новости Статьи Книги Обзоры Проекты Обо мне
Поиск:

меню
главная
новости
статьи
книги
обзоры
проекты
обо мне
 

 
GodRays



Объемный свет.

Что еще можно добавить в нашу сцену? Ну конечно же объемный свет. Этот эффект является аналогом шафтов, но имеет другое название – God Rays
Для реализации потребуется внедрение пост-процесса, т.к. этот эффект реализован в 2Д. Что нам понадобится для этого? Во первых текстура сцены натянутой на квад. Этого я объяснять не буду – примеров море. Далее когда мы отрисовываем облака, делаем второй проход – рисуя облака в отдельную текстуру. Только шейдер сильно изменяется – нам нужна только альфа облака. На черном фоне. Сам смысл – получить изображение кадра из камеры наблюдателя, который изначально черный, отрисовываем облака белым цветом.

В результате получим примерно вот такую текстуру :

Чтобы повысить быстродействие программы – данная текстура должна быть меньше основного разрешения. Если разрешение равно 1024*768 – то текстура может быть 512*384 – без потери качества.

Что делать с этой текстурой? Выводим ее на финальную сцену таким шейдером :


PS_INPUT VS( VS_INPUT input )
{
PS_INPUT output = (PS_INPUT)0;
output.Pos=input.Pos;
output.Tex=input.Tex;
return output;
}

 

half Density = 2.0f;
half Weight = 0.95f;
half Decay = 0.95f;
half Exposition = 0.1f;

//GLightPos - вектор света !
int numSamples = 64;

float4 PS( PS_INPUT input) : SV_Target
{
float4 shaft = ShaftMap.Sample( samLinear, input.Tex );

half4 screenPos = mul(GLightPos*2000, WorldViewProjection);
half2 ssPos = screenPos.xy / screenPos.w * float2(0.5,-0.5) + 0.5;

half2 oriTexCoord = input.Tex;
half2 texCoord = input.Tex;
half2 deltaTexCoord = (texCoord - ssPos);
deltaTexCoord *= 1.0f / numSamples * Density;
half3 color = ShaftMap.Sample( samLinear, texCoord).xyz;
half illuminationDecay = 1.0f;
for (int i=0; i < numSamples; i++)
{

texCoord -= deltaTexCoord;
half3 sample = ShaftMap.Sample( samLinear, texCoord).xyz;
sample *= illuminationDecay * Weight;
color += sample;
illuminationDecay *= Decay;
}
half amount = dot(mul(-GLightPos,View), half3(0.0f,0.0f,-1.f));

float3 V1 = normalize(CamDir.xyz);
float A = saturate(max(dot(GLightPos,V1),0));
half4 sampleFrame = ColorMap.Sample( samLinear, oriTexCoord);

//Шафты только днем, закат они порят...
if (GLightPos.y<0.1) {A=lerp(A/2,A,GLightPos.y*(1/0.1));}

float4 colframe = saturate(A-0.2) * (half4((1-color) * Exposition, 1))/2.5 + sampleFrame;
return float4(colframe.xyz,1);

}

Что делает шейдер? По вершинному – можно сказать одно – мы рисуем в экранных координатах – т.е. пост-процесс. В пиксельном шейдере, ShaftMap – это тексель нашей текстуры шафтов. ColorMap – тексель тексуры сцены. Сначала мы переводим источник света в экранные координаты. Матрица WorldViewProjection – считается так:

D3DXMatrixIdentity(&PWVP);
D3DXMatrixTranslation(&PWVP,LightDirection.x*1000,LightDirection.y*1000, LightDirection.z*1000);
D3DXMatrixMultiply(&PWVP,&PWVP,&mView);
D3DXMatrixMultiply(&PWVP,&PWVP,&mProj);

ShaftR_WorldViewProjection->SetMatrix( ( float* )&PWVP );

Далее шейдер получает значение точки и её затемнения – трассируя по вектору солнце-тексель. Вообще-то шейдер практически совпадает с шейдером облаков.
После, цвета инвертируются – ведь шафты – это затенение, а у нас текстура белая.
Вот результат :

 

 

 

Copyright CSS PSV 2009 Kherson
Hosted by uCoz