Stencil Troubles

Hey, I’m trying to clip some hud elements to a circle using stencils. I’m following along with some stencil tutorials and I’m doing something wrong somewhere and I’m hoping someone can correct me.

The goal is to clip the red rectangle drawn at the end of the stencil operations to the circle drawn in the middle. In the end it’ll be clipping things appearing on radar to the radar UI but for now I just need to get anything clipping to a drawn area.

My understanding of my code is that I’m telling the stencil operations that all of the pixels I draw a circle on in the middle has its stored int incremented to 1 from the 0 it defaults to. After that I set the reference number to 1 (To match the circle’s pixels) and then I draw a red rectangle across the entire screen wherever the pixel’s int matches the reference int of 1. In theory this should only be drawing on the circle I drew earlier but it’s drawing across the entire screen.

I’m pretty sure I’m missing some piece of information here but the tutorials I’ve found leave a bit to be desired.

Any help would be appreciated.




local radarRange = 250
local angle = 180
local drawScale = 100

local radarX = ScrW() - ( drawScale * 1.1 )
local radarY = ScrH() - ( drawScale * 2.2 )
	
local radarQuality = 0.075

local function drawCircle( x, y, radius, res )
	local tbl = {}
	processedRes = math.floor( 360 * res )
	for I = 1, processedRes do
		
		local curX = x + math.cos( math.rad( I * ( 360 / processedRes ) ) ) * radius
		local curY = y + math.sin( math.rad( I * ( 360 / processedRes ) ) ) * radius
			
		table.insert( tbl, { x = curX, y = curY } )
	end
		
	surface.DrawPoly( tbl )
		
end
	
hook.Add( "HUDPaint", "DrawRadar", function()
	
	render.ClearStencil()
	render.SetStencilEnable( true )
		
	render.SetStencilFailOperation( STENCILOPERATION_KEEP )
	render.SetStencilPassOperation( STENCILOPERATION_KEEP )
	render.SetStencilZFailOperation( STENCILOPERATION_INCRSAT )
		
	surface.SetDrawColor( Color( 255, 255, 255, 255 ) )
	drawCircle( radarX, radarY, drawScale, radarQuality )
	
	render.SetStencilReferenceValue( 1 )
	render.SetStencilCompareFunction( STENCILCOMPARISONFUNCTION_EQUAL )
		
	surface.SetDrawColor( Color( 255, 0, 0, 255 ) )
	surface.DrawRect( 0, 0, ScrW(), ScrH() )
		
	render.SetStencilEnable( false )
end


[lua]
hook.Add( “HUDPaint”, “DrawRadar”, function()

render.ClearStencil()
render.SetStencilEnable( true )
	
render.SetStencilFailOperation( STENCILOPERATION_KEEP )
render.SetStencilPassOperation( STENCILOPERATION_REPLACE )
render.SetStencilZFailOperation( STENCILOPERATION_KEEP )
    render.SetStencilReferenceValue(15)
    render.SetStencilCompareFunction( STENCILCOMPARISONFUNCTION_ALWAYS )
	
surface.SetDrawColor( Color( 255, 255, 255, 255 ) )
drawCircle( radarX, radarY, drawScale, radarQuality )

render.SetStencilCompareFunction( STENCILCOMPARISONFUNCTION_EQUAL )
	
surface.SetDrawColor( Color( 255, 0, 0, 255 ) )
surface.DrawRect( 0, 0, ScrW(), ScrH() )
	
render.SetStencilEnable( false )

end[/lua]

try that

this way you’re saying to write an explicit value of 15 to the stencil buffer for all screen space affected by any render (thanks to the ‘always’ comparison function)

then you ask for explicitly the ones equal to 15 to be considered next, and draw your new minimap or whatever that will be constrained to the mask

also, the ‘mask’ where you create the space to draw into (the drawCircle) can be drawn invisibly (alpha set to 0, being the fourth argument to the Color function); an invisible mask is still a mask

[editline]25th November 2016[/editline]

http://forum.facepunch.com/showthread.php?t=1257350&p=40080246#post40080246

That’s done the trick perfectly. Thank you for the explanation as well, that’s helped me understand better