Drawing Model Outline on Wall

So in the gamemode we’re making, we want to draw a chalk-like outline on the wall based on the weapons model. We can’t really use Halos as good, as they rotate with your view, and we want it to draw flat on the wall (or just floating on the model, but flat based on its angle). This picture demonstrates what we want to do:

The picture on the left is what we have now, the right is what we would like. Does anyone have some insight on how to achieve this, or is it even possible? I think I remember seeing someone making something similar with a crime scene drawn on the floor for TTT, but I really can’t find it again. It would be awesome if someone has any knowledge on something like this.

Not sure if this would help but I remember this post seemed to do something similar to what you’re trying to do:

I snipped some of the stuff out of that post since it’s pretty long, perhaps if you drew a TexturedRect (with a chalk texture) instead of a DrawRect in the cam.Start3D2D bit it might work?

I did come across that too yeah, but my main concern is, wouldn’t that outline follow the angles at which you view the entity? What we want would be a flat texture, so that if you look at it from the side, it’s practically invisible. I’ll give this some experimentation though, maybe if we lock the angle it could be drawn 2D. Another thought we had was to create a rendertarget from the correct angle and copy that to a texture, then draw that in 3D2D.

[editline]24th February 2016[/editline]

Yeah it also doesn’t scale well. Since it just draws an increased scale model in white, it won’t be a correct outline for any non-symmetrical models (like most weapons). Is there a way to make the stencil function not scale the model, but rather just use the original scale but then also select pixels in an x width around the other selected ones? So we basically increase the thickness of the drawing, meaning it’ll become a real outline. I don’t really know too much about stencils.

:snip:

So we tried a few things to try and make this work, but so far what we could do didn’t work but I have a feeling it’s possible, I just don’t know how. Here’s what I was thinking:

  • Is it possible to use a normal halo drawn with 100 passes (so it becomes much more solid) only once, and capture that in a rendertarget that you then copy to a new material you create and render on the model later?
  • Is it possible to perform another stencil test and grab all pixels that were colored by the halo and make them all solid white?
  • Is it possible to increase the size of the area passing the stencil test (maybe if you can modify the stencils’ values to “fade” into neighboring pixels and then use an >= test with a lower value)?

I think it would be easier if you just use the method above, with a chalk material, and SetNoDraw(true). If you put the weapon on a wall behind a table or something like that, players will always see it drawn flat to the wall as long as they are in front of it.

I know very little about rendertarget stuff, but perhaps you could capture what is drawn in the stencil block, and then draw it again in a 3D2D block.

  1. No.
  2. What?
  3. I am not a stencil expert, but I don’t think that’s how it works.

What you should do is use the method above but scale the model only on one axis, that would be facing away from the wall.

Scaling a single model a bit bigger wouldn’t create a proper outline as the models are asymmetrical, so the outline would have stuff off-center such as the magazine offset and it’d just generally look bad. Also couldn’t even get the scaling to work, as it seemingly didn’t want to scale more than once (just like MaxShadow’s problem).

I did find a solution I’m satisfied with (in case anyone else want to know), and that is to create 4 Clientside Models and offset them a bit towards each corner without scaling them (except making them flat). Then using stencils to loop through these 4 models and drawing them, then drawing a center model with STENCILOPERATION_ZERO to create the hole in the middle. The result is this:

This is the code:
[lua]self.Chalk1 = ClientsideModel(self:GetModel())
self.Chalk1:SetPos(self:GetPos() + Vector(0,-0.5,0.5))
self.Chalk1:SetAngles(self:GetAngles())
self.Chalk1:SetMaterial(chalkmaterial)

local scale = Vector(1.5, 0.1, 1.5) – The model is by default scaled by 1.5, this flattens it
local mat = Matrix()
mat:Scale( scale )

self.Chalk1:EnableMatrix( “RenderMultiply”, mat )
– Repeat 4 times with different offset, also create a center with no offset for the hole
[/lua]
[lua]function ENT:Draw()
local pos = LocalPlayer():EyePos()+LocalPlayer():EyeAngles():Forward()*10
local ang = LocalPlayer():EyeAngles()
ang = Angle(ang.p+90,ang.y,0)

render.ClearStencil()
render.SetStencilEnable(true)
	render.SetStencilWriteMask(255)
	render.SetStencilTestMask(255)
	render.SetStencilReferenceValue(15)
	render.SetStencilFailOperation(STENCILOPERATION_KEEP)
	render.SetStencilZFailOperation(STENCILOPERATION_KEEP)
	render.SetStencilPassOperation(STENCILOPERATION_REPLACE)
	render.SetStencilCompareFunction(STENCILCOMPARISONFUNCTION_ALWAYS)
	render.SetBlend(0)

	for i = 1, 4 do	
		self["Chalk"..i]:DrawModel()
	end

	render.SetStencilPassOperation(STENCILOPERATION_ZERO) -- Make it deselect the center model
	self.ChalkCenter:DrawModel()
			
	render.SetBlend(1)
	render.SetStencilCompareFunction(STENCILCOMPARISONFUNCTION_EQUAL)
	cam.Start3D2D(pos,ang,1)
		surface.SetDrawColor(255,255,255)
		surface.DrawRect(-ScrW(),-ScrH(),ScrW()*2,ScrH()*2)
	cam.End3D2D()
render.SetStencilEnable(false)

end
[/lua]