Post Processing On Entities

This is pretty much just copy pasta from other scripts. Thanks to Ralle for helping me with stencil buffers.

[lua]
local tex_Bloom0 = render.GetBloomTex0()
local tex_Bloom1 = render.GetBloomTex1()

local function RenderColor(entity, params)
if params == {} then return end
render.UpdateScreenEffectTexture()
local tab = {}
tab[ “$pp_colour_addr” ] = params.addr or 0
tab[ “$pp_colour_addg” ] = params.addg or 0
tab[ “$pp_colour_addb” ] = params.addb or 0
tab[ “$pp_colour_brightness” ] = params.brightness or 0
tab[ “$pp_colour_contrast” ] = params.contrast or 1
tab[ “$pp_colour_colour” ] = params.color or 1
tab[ “$pp_colour_mulr” ] = params.mulr or 0
tab[ “$pp_colour_mulg” ] = params.mulg or 0
tab[ “$pp_colour_mulb” ] = params.mulb or 0
for k, v in pairs(tab) do

	entity.pp.color:SetMaterialFloat( k, v )
	
end
render.SetMaterial( entity.pp.color )
render.DrawScreenQuad()

end

local function RenderSharpen(entity, params)
if params.contrast and params.contrast == 0 or params == {} then return end

render.UpdateScreenEffectTexture()
entity.pp.sharpen:SetMaterialFloat( "$contrast", params.contrast or 0 )
entity.pp.sharpen:SetMaterialFloat( "$distance", params.distance or 0 )
render.SetMaterial( entity.pp.sharpen )
render.DrawScreenQuad()

end

local function RenderBloom(entity, params)
if params.multiply and params.multiply == 0 or params == {} then return end

render.UpdateScreenEffectTexture()
	
local OldRT = render.GetRenderTarget()

entity.pp.bloom.downsample:SetMaterialFloat( "$darken", params.darken or 0 )
entity.pp.bloom.downsample:SetMaterialFloat( "$multiply", params.multiply or 0 )

render.SetRenderTarget( tex_Bloom0 )

render.SetMaterial( entity.pp.bloom.downsample )
render.DrawScreenQuad()			 
				 
entity.pp.bloom.blurx:SetMaterialTexture( "$basetexture", tex_Bloom0 )
entity.pp.bloom.blury:SetMaterialTexture( "$basetexture", tex_Bloom1 )
entity.pp.bloom.blurx:SetMaterialFloat( "$size", params.sizex or 5 )
entity.pp.bloom.blury:SetMaterialFloat( "$size", params.sizey or 5 )

for i=1, params.passes or 1 do

	render.SetRenderTarget( tex_Bloom1 )
	render.SetMaterial( entity.pp.bloom.blurx )
	render.DrawScreenQuad()

	render.SetRenderTarget( tex_Bloom0 )
	render.SetMaterial( entity.pp.bloom.blury )
	render.DrawScreenQuad()

end
		 
render.SetRenderTarget( OldRT )

entity.pp.bloom.bloom:SetMaterialFloat( "$levelr", params.levelr or 1 )
entity.pp.bloom.bloom:SetMaterialFloat( "$levelg", params.levelg or 1 )
entity.pp.bloom.bloom:SetMaterialFloat( "$levelb", params.levelb or 1 )
entity.pp.bloom.bloom:SetMaterialFloat( "$colormul", params.colormul or 1)
entity.pp.bloom.bloom:SetMaterialTexture( "$basetexture", tex_Bloom0 )

render.SetMaterial( entity.pp.bloom.bloom )
render.DrawScreenQuad()

end

local function RenderSobel(entity, params)
if params.thershold and params.thershold >= 10 or not params.thershold then return end

render.UpdateScreenEffectTexture();

entity.pp.sobel:SetMaterialFloat( "$threshold", params.thershold or 10 );

render.SetMaterial( entity.pp.sobel );
render.DrawScreenQuad();

end

local function RenderPP(entity, params)
for key, param in pairs(params) do
if key == “bloom” then
RenderBloom(entity, param)
end
if key == “color” then
RenderColor(entity, param)
end
if key == “sharpen” then
RenderSharpen(entity, param)
end
if key == “sobel” then
RenderSobel(entity, param)
end
end
end

function PostProcessEntity(entity, params)
params.color = params.color or {}
params.sharpen = params.sharpen or {}
params.bloom = params.bloom or {}
params.sobel = params.sobel or {}

entity.pp = entity.pp or {}
entity.pp.bloom = {}

entity.pp.bloom.bloom = Material("pp/bloom")
entity.pp.bloom.downsample = Material("pp/downsample")
entity.pp.bloom.blurx = Material("pp/blurx")
entity.pp.bloom.blury = Material("pp/blury")
entity.pp.sharpen = Material( "pp/sharpen" )
entity.pp.color = Material("pp/colour")
entity.pp.color:SetMaterialTexture( "$fbtexture", render.GetScreenEffectTexture() )
entity.pp.sobel = Material( "pp/sobel" )
entity.pp.sobel:SetMaterialTexture( "$fbtexture", render.GetScreenEffectTexture() );

if type(entity) == "table" and entity ~= {} then
	render.ClearStencil()
	render.SetStencilEnable( true )
	for key, ent in pairs(entity) do
		if type(ent) ~= "table" then
			render.SetStencilReferenceValue( 1 )
			render.SetStencilPassOperation( STENCILOPERATION_REPLACE )
			render.SetStencilCompareFunction( STENCILCOMPARISONFUNCTION_ALWAYS )
			local _,_,_,alpha = ent:GetColor()
			render.SetBlend(alpha/255)
			ent:DrawModel()
		end
	end
	render.SetStencilCompareFunction( STENCILCOMPARISONFUNCTION_EQUAL )
	RenderPP(entity, params)
	render.SetStencilEnable(false)		
else
	render.ClearStencil()
	render.SetStencilEnable( true )
	render.SetStencilReferenceValue( 1 )
	render.SetStencilPassOperation( STENCILOPERATION_REPLACE )
	render.SetStencilCompareFunction( STENCILCOMPARISONFUNCTION_ALWAYS )
	local _,_,_,alpha = entity:GetColor()
	render.SetBlend(alpha/255)
	entity:DrawModel()
	render.SetStencilCompareFunction( STENCILCOMPARISONFUNCTION_EQUAL )
	RenderPP(entity, params)
	render.SetStencilEnable(false)
end

end
[/lua]

Example usage:

[lua]
hook.Add(“PostDrawOpaqueRenderables”, “pp test”,function()
local entity = LocalPlayer():GetEyeTrace().Entity
if not ValidEntity(entity) then return end
local params = {
sobel = {
thershold = 0.2,
},
color = {
color = 0,
},
bloom = {
multiply = 2,
darken = 0,
colormul = 4,
},
}
PostProcessEntity(entity, params)
end)
[/lua]

You can change the drawing order simply by defining the post process before or after the other post process.

http://errur.com/New/Uploads/206.jpg

http://errur.com/New/Uploads/205.jpg

http://errur.com/New/Uploads/204.jpg

http://errur.com/New/Uploads/203.jpg

http://errur.com/New/Uploads/207.jpg

If anyone knows how to make the bloom go outside the edges, I’d be happy if you told me how

Hope you find it useful for something. :smile:

This is very cool. How hard would it be to make the bloom go outside the prop render area?

I don’t even know how to do that.

Also, this is quite expensive to use.

I should make it so the entity argument can be a table of entities to apply the the effect on all at once.

It is horribly expensive… I get an fps drop of almost a hundred with my 5870.

What is your average fps? If your fps was really high from before and it dropped from something like 300 to 200 it doesn’t really mean much.

Is this legal?

(just kidding)

But now we may finally be able to create some awesome stained glass or something.

Uhhh

[img_thumb]http://img710.imageshack.us/img710/4890/d1trainstation020000l.jpg[/img_thumb]
Ta-dah

Anyhow—nice work CapsAdmin. Pretty original idea.

Yeah, it was 150-200 before, but then it dropped to around 30-50. However, I rigged it up for my 3D2D on doors script, which means it was doing it for 2 or 3 doors.

Very nice tutorial Caps, gonna test it when I’m coming home. :smiley:

Updated it to work with a table of entities.

It will apply it to all entities in an effective way so it doesn’t lag as if you used it individually on each entity.

So the entity argument can be a table.

Nice and simple. For the bloom, you could try setting the entity’s scale to 1.5x (or something) while rendering it’s model to the stencil.

I’ve tried this and it has the same effect hard edge effect.

Pretty awesome, this is gonna be useful.

How do you use it?

It’s for developers. See the example in the OP on how to use it.

This is why I didn’t want it in releases.

Oh ok, I might use this for my sent, I was expecting this to me some sort of addon that adds to the post processing menu already.

Lol. Make an x-ray.

I’m guessing this is client side, or can it be used on the server and clients still see it?

Can somebody make this into a STool?
I would, but i’m just beginning Lua.

That would be a good idea.