--[[ | This file was obtained through the combined efforts | of Madbluntz & Plymouth Antiquarian Society. | | Credits: lifestorm, Gregory Wayne Rossel JR., | Maloy, DrPepper10 @ RIP, Atle! | | Visit for more: https://plymouth.thetwilightzone.ru/ --]] -- -- The number of frames to blend -- local pp_fb = CreateClientConVar( "pp_fb", "0", false, false ) -- -- The number of frames to blend -- local pp_fb_frames = CreateClientConVar( "pp_fb_frames", "16", true, false ) -- -- The amount of time the shutter is open. If this is 0.5 then we will blend only -- 50% of the frames. This is normally 0.5. Lowering it will make it more blurry. -- local pp_fb_shutter = CreateClientConVar( "pp_fb_shutter", "0.5", true, false ) local FrameCurves = {} local function FixupCurve( num ) local overflow = num for k, v in pairs( FrameCurves[ num ] ) do overflow = overflow - v end overflow = overflow * math.Rand( 0, 0.5 ) for i=0, num-1 do FrameCurves[ num ][ i ] = FrameCurves[ num ][ i ] + ( overflow / num ) end end local function FrameCurve( f, num ) if ( FrameCurves[ num ] ) then return FrameCurves[ num ][ f ] end local curve = {} for i=0, num-1 do local delta = ( i + 1 ) / num curve[ i ] = math.sin( delta * math.pi ) end FrameCurves[ num ] = curve for i=0, 10 do FixupCurve( num ) end return 1.0 end local texFB = GetRenderTargetEx( "_GMOD_FrameBlend", -1, -1, RT_SIZE_FULL_FRAME_BUFFER, MATERIAL_RT_DEPTH_NONE, 0, 0, IMAGE_FORMAT_DEFAULT ) local matFB = Material( "pp/frame_blend" ) local matFSB = Material( "pp/motionblur" ) local texMB0 = render.GetMoBlurTex0() local texMB1 = render.GetMoBlurTex1() local NumFramesTaken = 0 frame_blend = {} frame_blend.IsActive = function() return pp_fb:GetBool() end frame_blend.IsLastFrame = function() if ( !frame_blend.IsActive() ) then return true end local padding = math.floor( pp_fb_frames:GetInt() * pp_fb_shutter:GetFloat() * 0.5 ) return NumFramesTaken == ( pp_fb_frames:GetInt() - padding - 1 ) end frame_blend.RenderableFrames = function() local padding = math.floor( pp_fb_frames:GetInt() * pp_fb_shutter:GetFloat() * 0.5 ) * 2 return pp_fb_frames:GetInt() - padding end frame_blend.DrawPreview = function() render.Clear( 0, 0, 0, 255, true, true ) matFSB:SetFloat( "$alpha", 1.0 ) matFSB:SetTexture( "$basetexture", texMB1 ) render.SetMaterial( matFSB ) render.DrawScreenQuad() end frame_blend.ShouldSkipFrame = function() if ( pp_fb_shutter:GetFloat() <= 0 ) then return false end if ( pp_fb_shutter:GetFloat() >= 1 ) then return false end local padding = math.floor( pp_fb_frames:GetInt() * pp_fb_shutter:GetFloat() * 0.5 ) if ( NumFramesTaken < padding || NumFramesTaken >= pp_fb_frames:GetInt() - padding ) then return true end return false end frame_blend.CompleteFrame = function() matFSB:SetFloat( "$alpha", 1.0 ) matFSB:SetTexture( "$basetexture", texMB0 ) local OldRT = render.GetRenderTarget() render.SetRenderTarget( texMB1 ) render.SetMaterial( matFSB ) render.DrawScreenQuad() render.SetRenderTarget( OldRT ) render.SetRenderTarget( texMB0 ) render.Clear( 0, 0, 0, 255, true, true ) render.SetRenderTarget( OldRT ) end frame_blend.AddFrame = function() NumFramesTaken = NumFramesTaken + 1 if ( NumFramesTaken >= pp_fb_frames:GetInt() ) then frame_blend.CompleteFrame() NumFramesTaken = 0 end end frame_blend.BlendFrame = function() local padding = math.floor( pp_fb_frames:GetInt() * pp_fb_shutter:GetFloat() * 0.5 ) local frames = pp_fb_frames:GetInt() render.PushRenderTarget( texFB ) render.UpdateScreenEffectTexture() render.PopRenderTarget() local delta = ( NumFramesTaken - padding ) / ( frames - padding * 2 ) local curve = FrameCurve( NumFramesTaken - padding, frames-padding * 2 ) if ( !curve ) then return end curve = ( 1 / ( NumFramesTaken - padding ) ) * curve matFB:SetFloat( "$alpha", curve ) local OldRT = render.GetRenderTarget() render.SetRenderTarget( texMB0 ) render.SetMaterial( matFB ) render.DrawScreenQuad() render.SetRenderTarget( OldRT ) end -- -- Don't use these hooks when rendering a demo -- if ( engine.IsPlayingDemo() ) then return end hook.Add( "PostRender", "RenderFrameBlend", function() if ( !frame_blend.IsActive() ) then return end if ( !frame_blend.ShouldSkipFrame() ) then render.CopyRenderTargetToTexture( texFB ) frame_blend.BlendFrame() end frame_blend.AddFrame() frame_blend.DrawPreview() end ) list.Set( "PostProcess", "#frame_blend_pp", { icon = "gui/postprocess/frame_blend.png", convar = "pp_fb", category = "#effects_pp", cpanel = function( CPanel ) CPanel:AddControl( "Header", { Description = "#frame_blend_pp.desc" } ) CPanel:AddControl( "Header", { Description = "#frame_blend_pp.desc2" } ) CPanel:AddControl( "CheckBox", { Label = "#frame_blend_pp.enable", Command = "pp_fb" } ) local params = { Options = {}, CVars = {}, MenuButton = "1", Folder = "frame_blend" } params.Options[ "#preset.default" ] = { pp_fb_frames = "16", pp_fb_shutter = "0.5" } params.CVars = table.GetKeys( params.Options[ "#preset.default" ] ) CPanel:AddControl( "ComboBox", params ) CPanel:AddControl( "Slider", { Label = "#frame_blend_pp.frames", Command = "pp_fb_frames", Type = "Int", Min = "3", Max = "64" } ) CPanel:AddControl( "Slider", { Label = "#frame_blend_pp.shutter", Command = "pp_fb_shutter", Type = "Float", Min = "0", Max = "0.99" } ) end } )