

module( "halo", package.seeall )



local matColor	= Material( "model_color" )

local mat_Copy	= Material( "pp/copy" )

local mat_Add	= Material( "pp/add" )

local mat_Sub	= Material( "pp/sub" )

local rt_Stencil	= render.GetBloomTex0()

local rt_Store		= render.GetScreenEffectTexture( 0 )



local List = {}



function Add( ents, color, blurx, blury, passes, add, ignorez )



	if ( add == nil ) then add = true end

	if ( ignorez == nil ) then ignorez = false end



	local t = 

	{

		Ents = ents,

		Color = color,

		Hidden = when_hidden,

		BlurX = blurx or 2,

		BlurY = blury or 2,

		DrawPasses = passes or 1,

		Additive = add,

		IgnoreZ = ignorez

	}

	

	table.insert( List, t )



end



function Render( entry )



	local OldRT = render.GetRenderTarget()

	

	-- Copy what's currently on the screen to another texture

	render.CopyRenderTargetToTexture( rt_Store )

	

	-- Clear the colour and the stencils, not the depth

	if ( entry.Additive ) then			

		render.Clear( 0, 0, 0, 255, false, true )

	else

		render.Clear( 255, 255, 255, 255, false, true )

	end

		

	

	-- FILL STENCIL

	-- Write to the stencil..		

	cam.Start3D( EyePos(), EyeAngles() )

	

		cam.IgnoreZ( entry.IgnoreZ )

		render.OverrideDepthEnable( true, false )									-- Don't write depth

		

		render.SetStencilEnable( true )

		render.SetStencilFailOperation( STENCILOPERATION_KEEP )

		render.SetStencilZFailOperation( STENCILOPERATION_KEEP )

		render.SetStencilPassOperation( STENCILOPERATION_REPLACE )

		render.SetStencilCompareFunction( STENCILCOMPARISONFUNCTION_ALWAYS )

		render.SetStencilWriteMask( 1 )

		render.SetStencilReferenceValue( 1 )

		

		render.SetBlend( 0 ) -- don't render any colour

		

		for k, v in pairs( entry.Ents ) do

		

			if ( !IsValid( v ) ) then continue end

			

			v:DrawModel()



		end

			

	cam.End3D()	

	

	-- FILL COLOUR

	-- Write to the colour buffer

	cam.Start3D( EyePos(), EyeAngles() )



		render.MaterialOverride( matColor )

		cam.IgnoreZ( entry.IgnoreZ )

		

		render.SetStencilEnable( true )

		render.SetStencilWriteMask( 0 )

		render.SetStencilReferenceValue( 0 )

		render.SetStencilTestMask( 1 )

		render.SetStencilFailOperation( STENCILOPERATION_KEEP )

		render.SetStencilPassOperation( STENCILOPERATION_KEEP )

		render.SetStencilZFailOperation( STENCILOPERATION_KEEP )

		render.SetStencilCompareFunction( STENCILCOMPARISONFUNCTION_NOTEQUAL )

		

		for k, v in pairs( entry.Ents ) do

			

			if ( !IsValid( v ) ) then continue end

			

			render.SetColorModulation( entry.Color.r/255, entry.Color.g/255, entry.Color.b/255 )

			render.SetBlend( entry.Color.a/255 )



			v:DrawModel()

			

		end

			

		render.MaterialOverride( nil )

		render.SetStencilEnable( false )



	cam.End3D()

	

	-- BLUR IT

		render.CopyRenderTargetToTexture( rt_Stencil )

		render.OverrideDepthEnable( false, false )

		render.SetStencilEnable( false )

		render.BlurRenderTarget( rt_Stencil, entry.BlurX, entry.BlurY, 1 )

	

	-- Put our scene back

		render.SetRenderTarget( OldRT )

		render.SetColorModulation( 1, 1, 1 )

		render.SetStencilEnable( false )

		render.OverrideDepthEnable( true, false )

		render.SetBlend( 1 )

		mat_Copy:SetTexture( "$basetexture", rt_Store )

		render.SetMaterial( mat_Copy )

		render.DrawScreenQuad()

		

	

	-- DRAW IT TO THE SCEEN



		render.SetStencilEnable( true )

		render.SetStencilWriteMask( 0 )

		render.SetStencilReferenceValue( 0 )

		render.SetStencilTestMask( 1 )

		render.SetStencilFailOperation( STENCILOPERATION_KEEP )

		render.SetStencilPassOperation( STENCILOPERATION_KEEP )

		render.SetStencilZFailOperation( STENCILOPERATION_KEEP )

		render.SetStencilCompareFunction( STENCILCOMPARISONFUNCTION_EQUAL )

		    

		if ( entry.Additive ) then	

			mat_Add:SetTexture( "$basetexture", rt_Stencil )

			render.SetMaterial( mat_Add )

		else

			mat_Sub:SetTexture( "$basetexture", rt_Stencil )

			render.SetMaterial( mat_Sub )

		end

		

		for i=0, entry.DrawPasses do

			render.DrawScreenQuad()

		end

	

	-- PUT EVERYTHING BACK HOW WE FOUND IT



		render.SetStencilWriteMask( 0 )

		render.SetStencilReferenceValue( 0 )

		render.SetStencilTestMask( 0 )

		render.SetStencilEnable( false )

		render.OverrideDepthEnable( false )

		render.SetBlend( 1 )

		

		cam.IgnoreZ( false )



end



hook.Add( "PostDrawEffects", "RenderHalos", function()



	hook.Run( "PreDrawHalos" )



	if ( #List == 0 ) then return end

	

	for k, v in pairs( List ) do

		Render( v )

	end

		

	List = {}

	

end )

