Reflecting mirror in Gmod?

-snip-

It’s not a property in hammer, it’s an entity that uses edited water shader. I don’t think you can easily replicate it without rendertargets.

-snip-

What if we were given the ability to apply such apparently special shaders to entities ourselves?

What do you mean “it’s not built into GMod”? The ToyBox portal thingies used rendertargers IIRC.

The one in gm_construct shows your player, but the valve wiki says “Note:This entity will not show a player their own reflection, however it will render other players.”

I’ll try a simple map with it and see if it works.

[editline]26th December 2013[/editline]

Automerge Update pls:
It works in a map just fine (and does show the local player), so it is “built in to gmod”. But now I reread your post I realise you meant a lua entity for it is not built into gmod?
You can use ents.Create to create the func_reflective_glass, but it won’t be tied to a brush entity. I don’t know to do the “tieing” in lua. If it is possible to somehow tie the created glass entity with a brush created via lua, then it should theoretically work (after some material manipulation on the created brush entity). But I don’t believe you can create brushes via lua, as they are compiled into the map.

Here’s some code from the source engine code that may help.

From looking at it my best guess is that reflective mirrors are drawn using the same code that does water reflection. Anyways, the more viable route like others have said is probably going to be rendertargets.

Edit: Honestly didn’t think I would get it to work. The only issue is the local player doesn’t draw, not sure how to correct it…

[img_thumb]http://i.imgur.com/dWkp7g5.jpg[/img_thumb]

Spot on though.

[img_thumb]http://i.imgur.com/tL6BxgO.jpg[/img_thumb]

Edit: Found http://forum.facepunch.com/showthread.php?t=1260443, but it draws both players regardless…

Here’s what I have so far though:



local width = ScrW()
local height = ScrH()

local mirror_width = 500
local mirror_height = 180

local tex_name = "texture_scene"
local mat_name = "material_scene"

local col_white = Color(255, 255, 255, 255)
local mat_white = Material("debug/debugdrawflat")

local indraw
local draw_player

local mirror_center
local mirror_normal

-- Thanks to Wizzard of Ass for this portion of the code.
-- Thread: http://forum.facepunch.com/showthread.php?t=1276039
local TEXTURE_FLAGS_CLAMP_S = 0x0004
local TEXTURE_FLAGS_CLAMP_T = 0x0008

local tex_scene = GetRenderTargetEx(tex_name,
	width,
	height,
	RT_SIZE_NO_CHANGE,
	MATERIAL_RT_DEPTH_SEPARATE,
	bit.bor(TEXTURE_FLAGS_CLAMP_S, TEXTURE_FLAGS_CLAMP_T),
	CREATERENDERTARGETFLAGS_UNFILTERABLE_OK,
    IMAGE_FORMAT_RGB888
)

local mat_scene = CreateMaterial(mat_name, "UnlitGeneric", {
	["$ignorez"] = 1,
	["$vertexcolor"] = 1,
	["$vertexalpha"] = 0,
	["$nolod"] = 1,
	["$basetexture"] = tex_scene:GetName(),
	["$basetexturetransform"] = "center .5 .5 scale -1 1 rotate 0 translate 0 0"
})

local view = {}
view.dopostprocess = true
view.drawhud       = false
view.drawmonitors  = false
view.drawviewmodel = false
view.fov           = 90+16
view.znear         = 1
view.zfar          = 10000
view.x           = 0
view.y           = 0
view.w           = width
view.h           = height
view.aspectratio = width/height

local function CalcData()
	if not mirror_center or not mirror_normal or LocalPlayer():KeyDown(IN_USE) then
		local trace   = LocalPlayer():GetEyeTrace()
		mirror_center  = trace.HitPos
		mirror_normal  = trace.HitNormal
	end
end

local function Mirror(vec, normal)
	return vec - 2*(vec:Dot(normal))*normal
end

hook.Add("RenderScene", "mirror", function(origin, angles, fov)
	
	if indraw then return end
	indraw = true
	
	CalcData()
	
	local origin_local = origin-mirror_center
	local mirror_angle = mirror_normal:Angle()
	local scalar_forward = mirror_normal:Dot(origin_local)
	
	view.origin = origin - 2 * scalar_forward * mirror_normal
	view.angles = Mirror(angles:Forward(), -mirror_normal):Angle()
	view.fov = fov
	
	local render_target = render.GetRenderTarget()
	render.SetRenderTarget(tex_scene)
		local w,h = ScrW(), ScrH()
		render.Clear(0, 0, 0, 255)
		render.ClearDepth()
		render.SetViewPort(0, 0, width, height)
			cam.Start2D()
				render.EnableClipping(true)
					draw_player = true
						render.RenderView(view)
					draw_player = nil
				render.EnableClipping(false)
			cam.End2D()
		render.SetViewPort(0, 0, w, h)
	render.SetRenderTarget(render_target)
	
	indraw = false
end)

hook.Add("PreDrawOpaqueRenderables", "mirror", function()
	
	if indraw then return end
	indraw = true
	
	CalcData()
	
	local trace   = LocalPlayer():GetEyeTrace()
	trace_center  = trace.HitPos
	trace_normal  = trace.HitNormal
	
	render.ClearStencil()
	render.SetStencilEnable(true)
		
		render.SetStencilWriteMask(255)
		render.SetStencilTestMask(255)
		
		render.SetStencilReferenceValue (1)
		render.SetStencilFailOperation  (STENCILOPERATION_KEEP)
		render.SetStencilZFailOperation (STENCILOPERATION_KEEP)
		render.SetStencilPassOperation  (STENCILOPERATION_REPLACE)
		render.SetStencilCompareFunction(STENCILCOMPARISONFUNCTION_ALWAYS)
		
		render.SetMaterial(mat_white)
		render.DrawQuadEasy(mirror_center, mirror_normal, mirror_width, mirror_height, col_white, 0)
		
		render.SetStencilCompareFunction(STENCILCOMPARISONFUNCTION_EQUAL)
		
		render.SetMaterial(mat_scene)
		render.DrawScreenQuad()
		
	render.SetStencilEnable(false)
	
	indraw = false
	
end)

hook.Add("ShouldDrawLocalPlayer", "mirror", function()
	return draw_player
end)


-snip-

That’s actually not third person, that’s where the first person camera normally draws (right behind where it should logically draw, to get more FOV) and the hook for “ShouldDrawLocalPlayer” is returning true during the playerdraw hook even though it shouldn’t because the RenderView hook changes it to nil after it is done drawing…

You can try “return draw_player and indraw” in that last hook.

-snip-

-snip-

Are you trying to make it look like a window, as if the player’s looking into another room? That would require a bit more calculations as you would need to know the position and normal of the surface in the other room as well.

Edit: So is this what you want?

[img_thumb]http://i.imgur.com/3ersGGB.jpg[/img_thumb]

Code here