Draw silhouette of player model if they are obstructed

I want to render the silhouette of a player’s model if they are obstructed from view, but otherwise just draw their normal model if they are unobstructed. Also, if they are partially obstructed, then there should be a partial silhouette over the obstructed portion, and nothing over the visible portion. How would I go about doing this?

Stencils :eng101:

Stencils seem like the kind of thing i’d want, but the method for programming them seems fairly nonstandard. I assume it’s because they tie directly into source’s rendering engine, and have to interact with compiled assembly code?

Either way, I’m not entirely sure how I would go about using them for my purpose.

To quickly explain what happens: Imagine a stencil as a greyscale canvas. You can draw stuff to it, and depending on how you set it up, change the “whiteness” of said greayscale canvas. Then, you can draw stuff to the screen, but only where the pixels of the stencil are a certain colour. I will try and write the script because stencils are quite hard to grasp (I’ve been programming for years and I still don’t fully grasp it)

[editline]15th April 2015[/editline]

Sadly, as I said in my previous post, I haven’t fully grasped it, and the closest I could get to what you need is this:

[lua]
local mat2 = Material( “tools/toolsblack”, “unlitgeneric” )

hook.Add( "PostDrawOpaqueRenderables", "Stencil", function()

	render.ClearStencil() --Clear stencil
	render.SetStencilEnable( true ) --Enable stencil
	
	render.SetStencilCompareFunction( STENCILCOMPARISONFUNCTION_NOTEQUAL )
	render.SetStencilFailOperation( STENCILOPERATION_KEEP )
	render.SetStencilPassOperation( STENCILOPERATION_KEEP)
	render.SetStencilZFailOperation( STENCILOPERATION_INCR )
	render.SetStencilReferenceValue( 1 )

	for _, pl in pairs(player.GetAll()) do
		pl:DrawModel()
	end
		
	render.SetStencilReferenceValue( 1 )
	render.SetStencilCompareFunction( STENCILCOMPARISONFUNCTION_EQUAL )
		
	render.SetMaterial( mat2 )
	render.DrawScreenQuad()

	render.SetStencilEnable( false )
end)

[/lua]

It draws the silhouette of the player when you can’t see it, but also draws silhouettes of the parts of the player you can’t see even when the player is clearly in your line of sight. I’m posting the code in case someone else knows what needs to be done in order to help you further.

I just took a very thorough look over the stencil tutorial, and I think I understand it to complete the work that you started, and answer my original question.

Here’s the code I’ve written;

[lua]
local mat = Material( “tools/toolsblack”, “unlitgeneric” )

hook.Add( “PostDrawOpaqueRenderables”, “silhouette”, function()
render.ClearStencil()
render.SetStencilEnable( true )

render.SetStencilFailOperation( STENCILOPERATION_INCR )
render.SetStencilZFailOperation( STENCILOPERATION_INCR )
render.SetStencilPassOperation( STENCILOPERATION_KEEP )
render.SetStencilCompareFunction( STENCILCOMPARISONFUNCTION_ALWAYS )

for _, p in pairs(player.GetAll()) do
	p:DrawModel()
end

render.SetStencilCompareFunction( STENCILCOMPARISONFUNCTION_EQUAL )
render.SetStencilReferenceValue( 1 )


render.SetMaterial( mat )
render.DrawScreenQuad()
render.SetStencilEnable( false )

end )
[/lua]

This is untested, but I have a feeling it might do what I want.

Sadly not, just tested.

I have no idea how to use these stencils. Even the old wiki example doesn’t work; https://maurits.tv/data/garrysmod/wiki/wiki.garrysmod.com/indexd0aa.html. And that’s after I changed the arguments of SetModelScale.

[editline]15th April 2015[/editline]

Do you know what happens when DrawModel is called?

[editline]15th April 2015[/editline]

I’m going to make a more general post about how to use stencils; I’ll have a better chance of someone who knows how they work appearing.

Moved from other thread on request.