How to render floating text?

I’ve seen floating text in some servers I’ve been to, but I have no idea how do it myself. The wiki isn’t much help, since my search terms would be too vague.

http://wiki.garrysmod.com/page/cam/Start3D2D is what most developers use.

Thanks, although it’s seems pretty complicated. How would I use this to render floating text?

[editline]8th April 2015[/editline]

I tried this slightly modified code from the example on the wiki page;
[lua]
hook.Add(“PostDrawOpaqueRenderables”, “example”, function()
local trace = LocalPlayer():GetEyeTrace()
local angle = trace.HitNormal:Angle()

render.DrawLine( trace.HitPos, trace.HitPos + 8 * angle:Forward(), Color( 255, 0, 0 ), true )
render.DrawLine( trace.HitPos, trace.HitPos + 8 * -angle:Right(), Color( 0, 255, 0 ), true )
render.DrawLine( trace.HitPos, trace.HitPos + 8 * angle:Up(), Color( 0, 0, 255 ), true )
]
cam.Start3D2D( trace.HitPos, angle, 1 )
	surface.SetTextPos(0, 0) 
	surface.DrawText("Hello World")
cam.End3D2D()

end )
[/lua]

but the text doesn’t show up.

[editline]8th April 2015[/editline]

Actually, the text does appear sometimes, but in different colors each time.

An easy way to start messing with rendering with GLua, is to imagine some globally variables that you set.
The reason why the textcolor is ‘random’ is caused by another addon that just drew some text.

You need to set the textcolor before you draw the text (surface.SetTextColor(Color)).
[lua]surface.SetTextColor(Color(255,255,255))
surface.SetTextPos(0, 0)
surface.DrawText(“Hello World”)[/lua]

I created this snippet which is supposed to render the names above the heads of every other player in the server if the client is an admin;

[lua]
hook.Add( “PostDrawOpaqueRenderables”, “draw_names_admin”, function()
local ply = LocalPlayer()
if ply:IsAdmin() then
local plyPos = ply:EyePos()
for _, p in pairs( player.GetAll() ) do
local targetPos = p:EyePos()
local textPos = (targetPos - plyPos):GetNormalized() * 50
local textAngle = textPos:Angle()
cam.Start3D2D( textPos, textAngle, 1 )
surface.SetFont( “CloseCaption_Normal” )
surface.SetTextColor( 255, 255, 255, 255 )
surface.SetTextPos( 0, 0 )
surface.DrawText( p:Name() )
cam.End3D2D()
end
end
end )
[/lua]
However, it doesn’t work at all; even a little. I know it’s being called, because I put a print statement in there and it is indeed being printed.

I managed to get it working by messing with the angles enough. Here’s the finished product;
[lua]
hook.Add( “PostDrawOpaqueRenderables”, “draw_names_admin”, function()
local ply = LocalPlayer()
if ply:IsAdmin() then
local plyPos = ply:EyePos()
for _, p in pairs( player.GetAll() ) do
if p ~= ply then
local targetPos = p:EyePos()
local textDelta = (targetPos - plyPos)
local textPos = textDelta:GetNormalized() * 10 + ply:EyePos()
local textAngle = textDelta:Angle()
cam.Start3D2D( textPos, Angle(0, textAngle.y - 90, 90 - textAngle.p), 0.04 )
surface.SetFont( “CloseCaption_Normal” )
surface.SetTextColor( 255, 255, 255, 255 )
surface.SetTextPos( 0, 0 )
surface.DrawText( p:Name() )
cam.End3D2D()
end
end
end
end )
[/lua]