NightVision Tutorial: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
mNo edit summary
mNo edit summary
Line 1: Line 1:
[[Category:Programming]]
[[Category:Programming]]
[[Category:Tutorials]]
[[Category:Tutorials]]
[[Image:garry_motionblur.jpg|thumb]]
== Adding Nightvision To your Source Single Player Mod ==
== 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.
Here's something that is part of Nightfall [[nightfall]], and many people have been stumpled on - Night Vision.
Line 9: Line 8:
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, 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]]
Before i start, i would like to credit Gnolfo from www.hl2coding.com and [[user:ts2do]]


== Seting up the convar, and the Meat and Spuds ==
== Seting up the convar, The Meat and The Spuds ==


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)
Line 19: Line 18:
//NightVision
//NightVision
static void ScreenOver_f( void )
static void ScreenOver_f( void )
//rename ScreenOver to what ever you wish, maybe cl_nightvis
{
{
IMaterial *pMaterial = materials->FindMaterial( "HUDoverlays/nightvision", TEXTURE_GROUP_OTHER, true );
IMaterial *pMaterial = materials->FindMaterial( "HUDoverlays/nightvision", TEXTURE_GROUP_OTHER, true );
//This is the texture we are going to use for the 'effect' - never use an ext on material files


{
{
Line 28: Line 29:
{
{
// turn it off
// turn it off
            view->SetScreenOverlayMaterial( NULL );
view->SetScreenOverlayMaterial( NULL );
engine->ClientCmd( "mat_fullbright 0\n" );//turn full bright off again
engine->ClientCmd( "mat_fullbright 0\n" );//turn full bright off again
CLocalPlayerFilter filter;
CLocalPlayerFilter filter;
C_BaseEntity::EmitSound( filter, 0, "Nightfall.NightVisOff" );
C_BaseEntity::EmitSound( filter, 0, "Nightfall.NightVisOff" );
//play the off sound
}
}
else
else
Line 37: Line 39:
// turn it on
// turn it on
view->SetScreenOverlayMaterial( pMaterial );
view->SetScreenOverlayMaterial( pMaterial );
//this is the HUDoverlays/nightvision texture we made a pointer to above
engine->ClientCmd( "mat_fullbright 1\n" );//light up the world
engine->ClientCmd( "mat_fullbright 1\n" );//light up the world
CLocalPlayerFilter filter;
CLocalPlayerFilter filter;
C_BaseEntity::EmitSound( filter, 0, "Nightfall.NightVisOn" );
C_BaseEntity::EmitSound( filter, 0, "Nightfall.NightVisOn" );
//On we go - play a sound to let the player know that the NV is on
}
}
Line 49: Line 53:
</pre>
</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.
So what we have done here is set a bool cvar (on/off) that either enables, or disables the night vision effect. if you read the comments, you will under stand what each part is doing.


So now in the file '''src/cl_dll/rendertexture.h''' add:
<pre>Nightfall.NightVisOn</pre> is
 
  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:
 
<pre>
void CViewRender::DoMotionBlur( void );
</pre>
 
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.
 
<pre>
if ( fNextDrawTime - gpGlobals->curtime > 1.0f)
{
  fNextDrawTime = 0.0f;
}
</pre>
 
This code sits above this line
 
<pre>if( gpGlobals->curtime >= fNextDrawTime ) </pre>
 
== 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

Revision as of 07:56, 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 www.hl2coding.com and user:ts2do

Seting up the convar, The Meat and The 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 )
//rename ScreenOver to what ever you wish, maybe cl_nightvis
{
	IMaterial *pMaterial = materials->FindMaterial( "HUDoverlays/nightvision", TEXTURE_GROUP_OTHER, true );
//This is the texture we are going to use for the 'effect' - never use an ext on material files

	{
		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" );
			//play the off sound
		}
		else
		{
			// turn it on
			view->SetScreenOverlayMaterial( pMaterial );
			//this is the HUDoverlays/nightvision texture we made a pointer to above
			engine->ClientCmd( "mat_fullbright 1\n" );//light up the world
			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;
	}
}

static ConCommand r_screenover( "r_screenover", ScreenOver_f );

So what we have done here is set a bool cvar (on/off) that either enables, or disables the night vision effect. if you read the comments, you will under stand what each part is doing.

Nightfall.NightVisOn

is