:Ночное Видение
Серия Программирование окружающей обстановки Выскажите свои мысли — Помогите нам воплотить больше идей |
---|
Переключение карт и передача данных | Оптимизация | Процедурные текстуры | Прицелы и винтовки | Специальные эффекты | Транспорт | Многопоточный код | Файлы сохранений игры | Ночное видение | Небоевое оснащение | Динамическое появление оружия | Динамическое появление оружия (подробно) |
Ночное видение это вещь, в работоспособности которой многие люди сомневались, но это уже реализовано в NightFall моде.
Кратко
Этот пример очень ранней попытки (это работает), и, кроме того, один из многих способов заставить Режим Ночного Видения работать в своём моде.
Установка ConVar
Откройте файл src/cl_dll/view_scene.cpp, и добавьте код ниже до конца ifdef
//-----------------------------------------------------------------------------
// Предварительное кэширование необходимых материалов
//-----------------------------------------------------------------------------
#ifdef HL2_CLIENT_DLL
Найдите строку 170 (чтобы перейти к номеру строки быстро, нажмите ctrl+g)
//Предварительное кэширование Ночного Видения
CLIENTEFFECT_MATERIAL( "HUDoverlays/nightvision" )
Теперь перейдите к концу страницы (ctrl+end) и добавьте этот класс
//nightfall - amckern - [email protected]
//NightVision
static void ScreenOver_f( void )
{
IMaterial *pMaterial = materials->FindMaterial( "HUDoverlays/nightvision", TEXTURE_GROUP_OTHER, true );
//Эту текстуру мы будем использовать для 'effect' - никогда не используйте доб на материальных файлов
{
static bool bDisplayed = false;
if( bDisplayed )
{
// turn it off
view->SetScreenOverlayMaterial( NULL );
// Deactivate the 'light'
cvar->FindVar("mat_fullbright")->SetValue(0);
CLocalPlayerFilter filter;
C_BaseEntity::EmitSound( filter, 0, "Nightfall.NightVisOff" );
//play the off sound
}
else
{
// turn it on
view->SetScreenOverlayMaterial( pMaterial );
//this is the HUDoverlays/nightvision texture we made a pointer to above
// Activate the 'light'
cvar->FindVar("mat_fullbright")->SetValue(1);
CLocalPlayerFilter filter;
C_BaseEntity::EmitSound( filter, 0, "Nightfall.NightVisOn" );
//On we go - play a sound to let the player know that the NV is on
}
bDisplayed = !bDisplayed;
//check if fullbright has been disabled, or enabled
if (cvar->FindVar("mat_fullbright")->GetInt() == 1)//is it on?
cvar->FindVar("mat_fullbright")->SetValue(0);//well turn it off.
}
}
static ConCommand r_screenover( "r_screenover", ScreenOver_f );
Итак, что мы сделали здесь установлено логическое значение cvar (on/off) что позволяет или запрещает эффект ночного видения. Если вы читайте комментарии, вы будете понять что каждая часть сделала.
Этот раздел был отредактирован держит Fullbright обманом чита, чтобы остановить людей, используя его - код был обновлен от поставляемых в комментариях.
Это может показаться странным, чтобы иметь функцию выключения первой, но вы не хотим, чтобы игрок чтобы бегать в игре с ночным видением оказалось на от времени они заспавнились.
Звук
Nightfall.NightVisOn / Nightfall.NightVisOff
Этот код называет на файле скрипте nightfall_engine_sounds.txt что в свою очередь, прекэширован в game_sounds_manifest.txt вот так
"precache_file" "scripts/nightfall_engine_sounds.txt"
Звуки прекэшированы с PrecacheScript("Nightfall.NightVisOn"); в player.cpp функции прекэширования, только в том случае, если вам интересно, почему игра зависает, когда вы идете использовать звуковой эффект.
Вы можете всегда использовать direct звук события, как engine->ClientCmd( "play your_effect_sound.wav\n"); если вы не знаете как сделать soundscript звук. Недостатком этого является то, что игра всегда будет зависать в то время как это загружает звуковой файл для первого раза, и от того, что понимать, здесь никоим образом прекэшировать звуковой файл directly в коде.
Ночное видение с шейдерами
Создание ночного видения с shader требует 5 вещей, HLSL пиксель и вершина шейдер файлов, C++ шейдер файл, материал использует шейдер и шаг в триггер материал из игры. Эти предположения вам надо настроить и знать как компилировать шейдеры как показанный здесь . Credit goes to wraiyth для него удивительно полезные туториалы на HLSL.
Пиксель шейдера:
#include "common_ps_fxc.h"
const HALF Brightness : register (c0); //this is a variable to set how bright the NV will be.
sampler BaseTextureSampler : register( s0 ); //a sampler to get the texture this shader will be used on (in this case it will be a frame buffer)
HALF4 main(float2 iTexCoord : TEXCOORD0) : COLOR //out main function
{
float4 vAdd = float4(0.1,0.1,0.1,0); // just a float4 for use later
float4 cColor = tex2D(BaseTextureSampler,iTexCoord); //this takes our sampler and turns the rgba into floats between 0 and 1
cColor += tex2D(BaseTextureSampler, iTexCoord.xy + 0.001); // these 3 lines blur the image slightly
cColor += tex2D(BaseTextureSampler, iTexCoord.xy + 0.002);
cColor += tex2D(BaseTextureSampler, iTexCoord.xy + 0.003);
if (((cColor.r + cColor.g + cColor.b)/3) < 0.9) // if the pixel is bright leave it bright
{
cColor = cColor / 4; //otherwise set it to an average color of the 4 images we just added together
}
float4 cTempColor = cColor; //a new float4 cTempColor for use later
float4 cFinal = cTempColor + vAdd; //adds the floats together
cFinal.g = (cTempColor.r + cTempColor.g + cTempColor.b)/3; // sets green the the average of rgb
cFinal.r = 0; //removes red and blue colors
cFinal.b = 0;
return cFinal * Brightness; // brighten the final image and return it
}
Сохраните это как post_nightvision_ps20.fxc.
Затем вершинного шейдера:
#include "common_vs_fxc.h"
void main( in float4 iPosition : POSITION, in float2 iTexCoord : TEXCOORD0, out float4 oPosition : POSITION, out float2 oTexCoord : TEXCOORD0)
{
oPosition=iPosition;
oTexCoord=iTexCoord;
}
Сохранить как PassThrough_vs20.fxc и компилируйте 2 шейдера.
Дальше C++ файл:
#include "BaseVSShader.h"
#include "post_nightvision_ps20.inc"
#include "PassThrough_vs20.inc" //files generated by compiling the fxc files
BEGIN_VS_SHADER( Post_NightVision, "Help for Post_NightVision" ) //Begin the shader
BEGIN_SHADER_PARAMS
SHADER_PARAM(NVLEVEL, SHADER_PARAM_TYPE_FLOAT, "1.0", "")
//This is our shader parameter taken from the material file called NVLEVEL, write "$nvlevel" 10 for example in the .vmt
END_SHADER_PARAMS
SHADER_INIT_PARAMS() //called after parameters have been initialized
{
}
SHADER_FALLBACK //doesn't fallback to anything (I know this works on dx9, hasn't been tested on others)
{
return 0;
}
bool NeedsFullFrameBufferTexture( IMaterialVar **params ) const //does this need the full screen? in our case yes
{
return true;
}
SHADER_INIT //initializes the shader
{
}
SHADER_DRAW
{
SHADOW_STATE
{
pShaderShadow->EnableTexture( SHADER_TEXTURE_STAGE0, true ); //enables SHADER_TEXTURE_STAGE0
pShaderShadow->EnableDepthWrites( false ); //depth writes aren't needed
int fmt = VERTEX_POSITION;
pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0, 0 ); //sets the vertex format for the .fxc
pShaderShadow->SetVertexShader( "PassThrough_vs20", 0 ); //set the vertex shader
pShaderShadow->SetPixelShader( "post_nightvision_ps20" ); //set the pixel shader
DefaultFog();
}
DYNAMIC_STATE
{
float Scale = params[NVLEVEL]->GetFloatValue(); // get the value of NVLEVEL and turn it to a float
float vScale[4] = {Scale, Scale, Scale, 1}; //new float using NVLEVEL values
pShaderAPI->SetPixelShaderConstant(0, vScale); //set the first shader variable to our float
pShaderAPI->BindFBTexture( SHADER_TEXTURE_STAGE0 ); //set the shader texture to our frame buffer
}
Draw(); //draw the shader
}
END_SHADER
Добавьте это в game_shader_generic_sample проект (или без разницы другой вы используете) и компилируйте это.
Сейчас создайте материал в вашем моде materials папке все что надо это .vmt файл:
"Post_NightVision"
{
"$basetexture" "_rt_FullFrameFB"
"$nvlevel" 10 //can be whatever value you want
}
Сейчас откройте view_scene.cpp в client проекте в вашем моде и добавьте следующий код внизу:
//-----------------------------------------------------------------------------
// NightVision
//-----------------------------------------------------------------------------
static void NightVision_f ( void )
{
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); //get the local player
const Vector *vOrigin = &pPlayer->GetAbsOrigin(); //get the local players origin
static bool bDisplayed; //static bool
if ( bDisplayed )
{
view->SetScreenOverlayMaterial( null ); //set screenoverlay to nothing
CLocalPlayerFilter filter;
pPlayer->EmitSound(filter, 0, "TestMod.NightVisionOff", vOrigin); //and play sound
}
else
{
IMaterial *pMaterial = materials->FindMaterial( "NightVision", TEXTURE_GROUP_OTHER, true); //set pMaterial to our texture
view->SetScreenOverlayMaterial( pMaterial ); //and overlay it on the screen
CLocalPlayerFilter filter;
pPlayer->EmitSound(filter, 0, "TestMod.NightVisionOn", vOrigin); //and play a sound
}
bDisplayed = !bDisplayed; // flip flop the bool
}
//night vision console command
static ConCommand r_nightvision( "r_nightvision", NightVision_f ); // console command to trigger the function, bind it by typing bind n r_nightvision.
Компилируйте это и вы должны иметь полностью рабочую затенения приводом ночного видения, настроить его по своему желанию. Вы также можете прекэшировать звуки и материал как пояснялось ранее.