Garry's Mod Wiki

cam.Start3D2D

  cam.Start3D2D( Vector pos, Angle angles, number scale )

Description

Sets up a new 2D rendering context. Must be finished by cam.End3D2D. This function pushes a new matrix onto the stack. (cam.PushModelMatrix)

Matrix formula:

local m = Matrix() m:SetAngles(angles) m:SetTranslation(pos) m:SetScale(Vector(scale, -scale, 1))
This is a rendering hook which provides a 2d rendering context.
This is a rendering hook which provides a 3d rendering context.
This should be closed by cam.End3D2D otherwise the game crashes

Arguments

1 Vector pos
Origin of the 3D2D context, ie. the top left corner, (0, 0).
2 Angle angles
Angles of the 3D2D context. +x in the 2d context corresponds to +x of the angle (its forward direction). +y in the 2d context corresponds to -y of the angle (its right direction).

If (dx, dy) are your desired (+x, +y) unit vectors, the angle you want is dx:AngleEx(dx:Cross(-dy)).

3 number scale
The scale of the render context. If scale is 1 then 1 pixel in 2D context will equal to 1 unit in 3D context.

Example

Makes a floating rectangle with text above where the player is looking at, pointing at the player

hook.Add("PostDrawOpaqueRenderables", "example", function() -- Get the game's camera angles local angle = EyeAngles() -- Only use the Yaw component of the angle angle = Angle( 0, angle.y, 0 ) -- Apply some animation to the angle angle.y = angle.y + math.sin( CurTime() ) * 10 -- Correct the angle so it points at the camera -- This is usually done by trial and error using Up(), Right() and Forward() axes angle:RotateAroundAxis( angle:Up(), -90 ) angle:RotateAroundAxis( angle:Forward(), 90 ) -- A trace just for a position local trace = LocalPlayer():GetEyeTrace() local pos = trace.HitPos -- Raise the hitpos off the ground by 20 units and apply some animation pos = pos + Vector( 0, 0, math.cos( CurTime() / 2 ) + 20 ) -- Notice the scale is small, so text looks crispier cam.Start3D2D( pos, angle, 0.1 ) -- Get the size of the text we are about to draw local text = "Testing" surface.SetFont( "Default" ) local tW, tH = surface.GetTextSize( "Testing" ) -- This defines amount of padding for the box around the text local pad = 5 -- Draw a rectable. This has to be done before drawing the text, to prevent overlapping -- Notice how we start drawing in negative coordinates -- This is to make sure the 3d2d display rotates around our position by its center, not left corner surface.SetDrawColor( 0, 0, 0, 255 ) surface.DrawRect( -tW / 2 - pad, -pad, tW + pad * 2, tH + pad * 2 ) -- Draw some text draw.SimpleText( "Testing", "Default", -tW / 2, 0, color_white ) cam.End3D2D() end )

Example

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.SetDrawColor( 255, 165, 0, 255 ) surface.DrawRect( 0, 0, 8, 8 ) render.DrawLine( Vector( 0, 0, 0 ), Vector( 8, 8, 8 ), Color( 100, 149, 237, 255 ), true ) cam.End3D2D() end )
Output: