Добавляем Motion Blur.
Содержание:
1. Введение.
2. Технология.
3. Создание нового Render Target.
4. Основной кодинг.
5. Однопользовательский режим.
6. Файлы материалов.
7. Окончанее.
1. Введение.
В более поздних вегрсиях Гаррис Мода вы могли заметить новый эффект, размытие изображения, при движении объекта (Motion Blur). Метод описываемый в данном туториале не использует шедеров и поэтому будет работать на большинстве видеокарт.
2. Технология.
Этот эффект достигается путем добавления прозрачной версии главного буфера в отдельный буфер, для поледующей прорисовки его поверх глвного, говоря иначе мы записываем в доп. буфер кадр, и с небольшим "опозданием" выводим его полупрозрачную версию на экран. Тот же эффект можно было достигнуть используя только один буфер, но такой метод мение универсален.
3. создание нового Render Target.
Открываем файл src/cl_dll/rendertexture.cpp, и сверху добавляем:
#include "materialsystem/materialsystemutil.h" |
Снизу пишим следующее:
|
Эту функцию мы будем использовать для получения указателя на Render Target. Числа "256" для нас бессмысленны, т.к. они перекрываются RT_SIZE_FULL_FRAME_BUFFER, который заставляет текстуру принимать размер буфера кадров.
Так, теперь идем в файл src/cl_dll/rendertexture.h и добавляем туда:
ITexture *GetMotionBlurTex0( void ); |
Это позволит использовать нашу функцию.
4. Основной кодинг.
Прежде всего давайте добавим консольные команды которые мы собираемся использовать. Я их делаю для удобства настройки Motion Blur прямо в игре. Этот код впринципе универсален, что можно заметить из CViewRender::RenderView( const CViewSetup &view, bool drawViewModel ) находящейся в файле view_scene.cpp
// Включение/Выключение эффекта motion blur ConVar pp_motionblur("pp_motionblur", "1", 0, "Motion Blur"); // Выставление значения Motion Blur Alpha при добавлении буфера кадров (Frame Buffer) в наш буфер. ConVar pp_motionblur_addalpha("pp_motionblur_addalpha", "0.1", 0, "Motion Blur Alpha"); // Выставление значения Motion Blur Alpha при добавление нашего буфера в буфер кадров. ConVar pp_motionblur_drawalpha("pp_motionblur_drawalpha", "1", 0, "Motion Blur Draw Alpha"); // Задержка между захватом и добавлением кадра. Чем меньше время, тем быстрее обновляется кадр. ConVar pp_motionblur_time("pp_motionblur_time", "0.05", 0, "The amount of time to wait until updating the FB"); |
Не буду ничего пояснять, всё прекрасно видно из кода.
void CViewRender::DoMotionBlur( void ) |
|||
if ( pp_motionblur.GetInt() == 0 ) return; static float fNextDrawTime = 0.0f; bool found; // Получение материала из главног буфера // Установка камеры materials->MatrixMode( MATERIAL_PROJECTION ); materials->MatrixMode( MATERIAL_VIEW ); if( gpGlobals->curtime >= fNextDrawTime ) |
|||
UpdateScreenEffectTexture( 0 ); // Установка alpha для любого значения консоли |
|||
if ( fNextDrawTime == 0 ) |
|||
} materials->SetRenderTarget( pMotionBlur ); // установка времяни прорисовки |
|||
} // Установка alpha |
|||
mv->SetFloatValue( pp_motionblur_drawalpha.GetFloat() ); | |||
} // Захват текстуры в наш буфер |
|||
pOriginalTexture = mv->GetTextureValue(); mv->SetTextureValue( pMotionBlur ); |
|||
} materials->SetRenderTarget( pOriginalRenderTarget ); // Sставим текстуру на место |
|||
mv->SetTextureValue( pOriginalTexture ); | |||
} materials->DepthRange( 0.0f, 1.0f ); |
|||
} |
Надеюсь что всё правильно.
Теперь в функции CViewRender::RenderView( const CViewSetup &view, bool drawViewModel ) находящейся в файле view_scene.cpp, добавляем следующую строчку:
DoMotionBlur(); |
Прямо перед:
// Draw the 2D graphics |
Ну и наконец добавляем строчку:
void CViewRender::DoMotionBlur( void ); |
В самаом конце файла viewrender.h
5. Однопользоветельский режим
Если вы работаете над сингл модом, то вы возможно заметели что буфер не обновляется при смене карты или смерти игрока, это происходит потому что при смене карты переменная gpGlobals->curtime принимает значение 0.0 но, fNextDrawTime удерживает её значение.
И так, выполняем проверку:
if ( fNextDrawTime < gpGlobals->curtime )
Если вы играли 30 минут на карте, то после её смены Motion Blur начнет работать 30 минут на новой карте. Теперь обнуляем значение fNextDrawTime с помошью проверки:
if ( fNextDrawTime - gpGlobals->curtime > 1.0f) { |
||
fNextDrawTime = 0.0f; | ||
} |
Данный код находится ниже
if( gpGlobals->curtime >= fNextDrawTime ) |
6. Файлы материалов
Нужно добавить файл материалов с названием frontbuffer.vmt в папку материалов, возможно использование уже существующего. Вот так выглядит мой:
"UnlitGeneric" |
||
"$basetexture" "_rt_FullFrameFB" "$ignorez" |
1 |
|
} |
7. Окончание
Я решил написать этот туториал потому что мне задавалось множество вопросов по этой теме. Надеюсь он кому-нибуть поможет.
Garry Newman.
Материал взят с сайта http://developer.valvesoftware.com
Перевод выполнил Strateg