GMod - What are you working on? January 2017 (#65)

Happy new year!

Highlights from the previous thread

i’m sincerely disappointed that raubana’s sound seeing shit from the last waywo didn’t make highlights

I’m more disappointed that my automated skycam didn’t make the highlights, to be honest. That shit was not easy. I’m writing a script for a video on how it works right now, and even though it’s already very long I’m still not even close to finishing it. But it’s cool, there’s always next WAYWO.

So I’m working on my very first gamemode at the moment. It’s a zombie survival gamemode I’m making from scratch and it’s actually a remake of an old gamemode that doesn’t exist anymore[/t]




Nothing extremely hard to code but I learned a lot about scripting with this little project of mine

Holy shit, I got the effect to work! Check it out:


Ok, so the trick was to override writing to the depth buffer and to use a mask (stencil) to make only the outer part of the sphere render.

Here’s a simplified version of the code I used:
local echo_lifetime = 1.5
local echo_radius = 1000.0
local echo_thickness = 100.0

local color_mask = Color(0,0,0,0)

hook.Add( “PostDrawTranslucentRenderables”, “PostDrawTranslucentRenderablesDrawEcho”, function( )
local realtime = RealTime()


render.Clear(0.0, 0.0, 0.0, 255.0, false, false)


render.SetStencilPassOperation( STENCILOPERATION_REPLACE )
render.SetStencilFailOperation( STENCILOPERATION_KEEP )
render.SetStencilZFailOperation( STENCILOPERATION_KEEP )

render.OverrideDepthEnable( true, false )

for i, echo in ipairs(echoes) do
	local p = (realtime - echo.start) / (echo_lifetime*echo.volume)
	local r = Lerp(p*echo.volume, 0, echo_radius)
	render.SetStencilReferenceValue( 2 )
	render.DrawSphere(echo.pos, -r-(echo_thickness*(1-p)), 20, 20, color_mask)
	render.SetStencilReferenceValue( 1 )
	local color = echo.color
	color.a = 255*math.pow(1-p, 2)
	render.DrawSphere(echo.pos, -r, 20, 20, color)

render.OverrideDepthEnable( false, false )



That is a fantastic concept, really interested in seeing what you do with it later on.

I have to ask; during your exploration with the depth buffer, did you by any chance find a way to read the depth buffer’s value on a certain pixel?

Great work!

No, sorry. :pudge:

Damage is randomly distributed between the hull, other components, and crew.

Each component has a fun little failure state. A broken hull will cause the ship to fall out of the sky, a broken helm console will submit random commands to the ship, a broken gun will fire randomly, and a broken comms console will display random characters instead of messages.

You can even break the health indicator itself and it will start showing bogus stats.

I added repairs as well but forgot to show them in the video.

Probably not going to figure out how this works at scale until judging. :worried:

This looks like something I’d play a lot! I like how you made the map look a lot bigger, assuming that’s the intended effect.

No offense, but is this really the effect you wanted? I thought you were going for rings eminating from the sound source and traveling along surface, this is less rings and more spheres that only draw in certain conditions.

I’ve got an idea how to make rings, but I’ll need some time to fully understand it before making a mock-up


Okay, here’s the idea.

After the scene is fully drawn (PreDrawViewModel), you will want to draw 4 spheres for stencil:
A: Ring’s outer radius, inner wall (negative radius)
B: Ring’s outer radius, outer wall (positive radius)
C: Ring’s inner radius, inner wall (negative radius)
D: Ring’s inner radius, outer wall (positive radius)

The pixels you want to highlight are those where:
A fails the Z buffer AND
B passes the Z buffer AND
(C passes the Z buffer OR
D fails the Z buffer OR
neither C or D were drawn)

This can be accomplished via stencils, kinda tricky though.

Edit: actually you’ll need to draw them in the order A-C-D-B, otherwise C and D will always fail the Z buffer.

Edit: ugh, because of you I can’t focus on work. Now I’m toying around in my mind with ways to make this work through walls. That may actually be possible, but really expensive - it would require something like 2 calls to render.RenderView per echo. That means with one echo, your framerate would be cut in half, with 2 echoes 1/4, with 3 echoes 1/6 and so on.

I know it’s not perfect, but it does the job and it runs pretty decently for everyone.

I just tried to make it the way I described, but holy shit, stencils are not working right. STENCIL_GREATER is successful for pixels with value 0… That should never happen X_X

Edit: fuck my life. Wiki was wrong.

mic drop

mic pick back up
For some reason it doesn’t show when you’re inside the sphere (seen in the video), but I’ll figure it out.

Damn, this took longer than it should have. I blame my cold clouding my thoughts :huh:

Not shown because not actually tested, but this is definitely not limited to just one ring. You can have as many as you want, and the only factor that affects framerate is the drawsphere’s quality. (I’m assuming that stencil operations are cheap)

raubana, want it?

Releasing my cancerous loading screen for one final time.
My next project will be using a new one (without music) that’s way cooler than this one.



Yes please!

Uh, I’m already in bed, afraid I can’t reach that code any earlier than tomorrow night. As you can see, I am a master of foresight!

I assume you’ll give me credit somewhere? :smile:

I’ll try to figure it out before you wake then! :cat:

Holy flipping geeze, I got it! Thanks anyways, NeatNit.


Here’s a simplified version of my code:

local echoes = echoes or {}
local echo_thickness = 75.0
local color_mask = Color(0,0,0,0)

local function drawStencilSphere( pos, ref, compare_func, radius, color, detail )
render.SetStencilReferenceValue( ref )
render.SetStencilCompareFunction( compare_func )
render.DrawSphere(pos, radius, detail, detail, color)

hook.Add( “PostDrawTranslucentRenderables”, “PostDrawTranslucentRenderablesDrawEcho”, function( )
local localplayer_pos = LocalPlayer():EyePos()

local detail = 25

local realtime = RealTime()


render.SetStencilPassOperation( STENCILOPERATION_KEEP )
render.SetStencilFailOperation( STENCILOPERATION_KEEP )

for i, echo in ipairs(echoes) do
	local dist = echo.pos:Distance(localplayer_pos)

	local opacity = ((echo.radius - (dist/2))/echo.radius) * 0.25
	local p = (realtime - echo.start) / (echo.lifetime)
	if p < 1.0 and opacity > 0 then
		local outer_r = Lerp(p, 0, echo.radius)
		local inner_r = math.max(outer_r-echo_thickness,0)
		local color = echo.color
		color.a = 255*opacity*math.pow(1-p, 2)
		render.SetStencilZFailOperation( STENCILOPERATION_REPLACE )
		drawStencilSphere(echo.pos, 2, STENCILCOMPARISONFUNCTION_ALWAYS, -outer_r, color_mask, detail ) -- big, inside-out
		render.SetStencilZFailOperation( STENCILOPERATION_INCR )
		drawStencilSphere(echo.pos, 2, STENCILCOMPARISONFUNCTION_ALWAYS, outer_r, color_mask, detail ) -- big
		render.SetStencilZFailOperation( STENCILOPERATION_INCR )
		drawStencilSphere(echo.pos, 2, STENCILCOMPARISONFUNCTION_ALWAYS, -inner_r, color_mask, detail ) -- small, inside-out
		render.SetStencilZFailOperation( STENCILOPERATION_DECR )
		drawStencilSphere(echo.pos, 2, STENCILCOMPARISONFUNCTION_ALWAYS, inner_r, color_mask, detail ) -- small
		drawStencilSphere(echo.pos, 2, STENCILCOMPARISONFUNCTION_EQUAL, -outer_r, color, detail ) -- big, inside-out



Can you give that a cross-post to, would be a nice reference.