Vision Nocturna/ru

From Valve Developer Community
Jump to: navigation, search

Ночное видение это вещь, в работоспособности которой многие люди сомневались, но это уже реализовано в 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.

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