NightVision Tutorial: Difference between revisions
(New Page - YAY!) |
mNo edit summary |
||
| Line 15: | Line 15: | ||
Open the file '''src/cl_dll/view_scene.cpp''', and jump to the end (ctrl+end) | Open the file '''src/cl_dll/view_scene.cpp''', and jump to the end (ctrl+end) | ||
<pre> | |||
//nightfall - amckern - amckern@yahoo.com | //nightfall - amckern - amckern@yahoo.com | ||
//NightVision | //NightVision | ||
| Line 46: | Line 47: | ||
static ConCommand r_screenover( "r_screenover", ScreenOver_f ); | static ConCommand r_screenover( "r_screenover", ScreenOver_f ); | ||
</pre> | |||
This is the function we will use to get a pointer to the render target. The '256' numbers are meaningless, they get overridden by [[RT_SIZE_FULL_FRAME_BUFFER]] which forces the texture to be the size of the frame buffer. | This is the function we will use to get a pointer to the render target. The '256' numbers are meaningless, they get overridden by [[RT_SIZE_FULL_FRAME_BUFFER]] which forces the texture to be the size of the frame buffer. | ||
Revision as of 07:48, 9 November 2005
Adding Nightvision To your Source Single Player Mod
Here's something that is part of Nightfall nightfall, and many people have been stumpled on - Night Vision.
Summary
Before i start, this is only one, and a very early attempt (It works), of one way to get the Night Vision Mode to work with your mod.
Before i start, i would like to credit Gnolfo from hl2coding.com and user:ts2do
Seting up the convar, and the Meat and Spuds
Open the file src/cl_dll/view_scene.cpp, and jump to the end (ctrl+end)
//nightfall - amckern - amckern@yahoo.com
//NightVision
static void ScreenOver_f( void )
{
IMaterial *pMaterial = materials->FindMaterial( "HUDoverlays/nightvision", TEXTURE_GROUP_OTHER, true );
{
static bool bDisplayed = false;
if( bDisplayed )
{
// turn it off
view->SetScreenOverlayMaterial( NULL );
engine->ClientCmd( "mat_fullbright 0\n" );//turn full bright off again
CLocalPlayerFilter filter;
C_BaseEntity::EmitSound( filter, 0, "Nightfall.NightVisOff" );
}
else
{
// turn it on
view->SetScreenOverlayMaterial( pMaterial );
engine->ClientCmd( "mat_fullbright 1\n" );//light up the world
CLocalPlayerFilter filter;
C_BaseEntity::EmitSound( filter, 0, "Nightfall.NightVisOn" );
}
bDisplayed = !bDisplayed;
}
}
static ConCommand r_screenover( "r_screenover", ScreenOver_f );
This is the function we will use to get a pointer to the render target. The '256' numbers are meaningless, they get overridden by RT_SIZE_FULL_FRAME_BUFFER which forces the texture to be the size of the frame buffer.
So now in the file src/cl_dll/rendertexture.h add:
ITexture *GetMoBlurTex0( void );
This will allow us to use this function.
Rendering the Motion Blur
First of all lets add some console commands that we're going to use. I make this console commands because people will want to change them in Garry's Mod. This code can go pretty much anywhere that it can be seen from CViewRender::RenderView( const CViewSetup &view, bool drawViewModel ) in view_scene.cpp.
// To toggle the blur on and off
ConVar pp_motionblur("pp_motionblur", "1", 0, "Motion Blur");
// The amount of alpha to use when adding the FB to our custom buffer
ConVar pp_motionblur_addalpha("pp_motionblur_addalpha", "0.1", 0, "Motion Blur Alpha");
// The amount of alpha to use when adding our custom buffer to the FB
ConVar pp_motionblur_drawalpha("pp_motionblur_drawalpha", "1", 0, "Motion Blur Draw Alpha");
// Delay to add between capturing the FB
ConVar pp_motionblur_time("pp_motionblur_time", "0.05", 0, "The amount of time to wait until updating the FB");
All pretty self explanatory.
void CViewRender::DoMotionBlur( void )
{
if ( pp_motionblur.GetInt() == 0 ) return;
static float fNextDrawTime = 0.0f;
bool found;
IMaterialVar* mv = NULL;
IMaterial *pMatScreen = NULL;
ITexture *pMoBlur = NULL;
ITexture *pOriginalTexture = NULL;
// Get the front buffer material
pMatScreen = materials->FindMaterial( "frontbuffer", TEXTURE_GROUP_OTHER, true );
// Get our custom render target
pMoBlur = GetMoBlurTex0();
// Store the current render target
ITexture *pOriginalRenderTarget = materials->GetRenderTarget();
// Set the camera up so we can draw the overlay
int oldX, oldY, oldW, oldH;
materials->GetViewport( oldX, oldY, oldW, oldH );
materials->MatrixMode( MATERIAL_PROJECTION );
materials->PushMatrix();
materials->LoadIdentity();
materials->MatrixMode( MATERIAL_VIEW );
materials->PushMatrix();
materials->LoadIdentity();
if( gpGlobals->curtime >= fNextDrawTime )
{
UpdateScreenEffectTexture( 0 );
// Set the alpha to whatever our console variable is
mv = pMatScreen->FindVar( "$alpha", &found, false );
if (found)
{
if ( fNextDrawTime == 0 )
{
mv->SetFloatValue( 1.0f );
}
else
{
mv->SetFloatValue( pp_motionblur_addalpha.GetFloat() );
}
}
materials->SetRenderTarget( pMoBlur );
materials->DrawScreenSpaceQuad( pMatScreen );
// Set the next draw time according to the convar
fNextDrawTime = gpGlobals->curtime + pp_motionblur_time.GetFloat();
}
// Set the alpha
mv = pMatScreen->FindVar( "$alpha", &found, false );
if (found)
{
mv->SetFloatValue( pp_motionblur_drawalpha.GetFloat() );
}
// Set the texture to our buffer
mv = pMatScreen->FindVar( "$basetexture", &found, false );
if (found)
{
pOriginalTexture = mv->GetTextureValue();
mv->SetTextureValue( pMoBlur );
}
// Pretend we were never here, set everything back
materials->SetRenderTarget( pOriginalRenderTarget );
materials->DrawScreenSpaceQuad( pMatScreen );
// Set our texture back to _rt_FullFrameFB
if (found)
{
mv->SetTextureValue( pOriginalTexture );
}
materials->DepthRange( 0.0f, 1.0f );
materials->MatrixMode( MATERIAL_PROJECTION );
materials->PopMatrix();
materials->MatrixMode( MATERIAL_VIEW );
materials->PopMatrix();
}
I hope that all makes sense.
Now in the CViewRender::RenderView( const CViewSetup &view, bool drawViewModel ) function which is located in view_scene.cpp, add this:
DoMotionBlur();
Just before
// Draw the 2D graphics
Lastly Add the line:
void CViewRender::DoMotionBlur( void );
Before the end in the viewrender.h file.
Single Player
If your working on a Single Player Mod, you may have found that the front buffer wont update on a map change, or player death, this is because when you change the map, the gpGlobals->curtime variable resets to 0.0 seconds, but your fNextDrawTime retains its value.
So when the blur performs the check:
if ( fNextDrawTime < gpGlobals->curtime )
It will not return true until gpGlobals->curtime catches up - so if you played for 30 mins on the last map, the blur will start working 30 minutes into the new map. To do this you need to reset your fNextDrawTime on a map change by using the hack below, or don't use this check at all.
if ( fNextDrawTime - gpGlobals->curtime > 1.0f)
{
fNextDrawTime = 0.0f;
}
This code sits above this line
if( gpGlobals->curtime >= fNextDrawTime )
Material Files
That should do it. You need to add a material file called frontbuffer.vmt in your materials folder - although you could probably use an existing one. Here's what mine looks like:
"UnlitGeneric" { "$basetexture" "_rt_FullFrameFB" "$ignorez" 1 }
Finished
I chose this tutorial to do because it covered a few things that people continually ask me about. I hope it helps someone.
Garry Newman