CS2 Lua API

render

The render module draws shapes on top of the game and converts world coordinates to screen coordinates. This page covers shapes and the screen; state stacks, fonts and images are described on separate pages.

General rules#

  • Only inside the render event. Drawing functions work only while the render event is being dispatched. Outside it you get the error this function may only be called inside the 'render' event. screen_size, world_to_screen, offscreen, camera_angles, font and image loading and measure_text work without the event.
  • A rectangle is given as (pos, size): the second vector2 is the size, the bottom-right corner = pos + size.
  • Rounding rounding is a number (one radius for all corners) or a table {tl, tr, br, bl} (top-left, top-right, bottom-right, bottom-left). If not passed, corners are square.
  • Arc angles. start is the start angle in degrees (default 0), pct is the fraction of a full circle (1 — full circle, 0.5 — half; default 1).
  • Optional arguments count only with the exact type: a string with a number cannot be passed instead of a number. nil means "not passed".

color(255, 0, 0) without alpha is invisible: alpha defaults to 0. Write color(255, 0, 0, 255).

render.screen_size()#

Screen size in pixels. Also works outside the render event.

Returns: vector2 — width and height.

local font = render.load_font("Verdana", 14, "outline")

events.render:set(function()
    local center = render.screen_size() / 2
    render.text(center, color(255, 255, 255, 255), font, "c", "+")
end)

render.world_to_screen(pos: vector)#

Converts a world point to a screen point. The result is rounded to whole pixels.

Parameter Type Description
pos vector world point

Returns: vector2 or nil if the point cannot be projected (for example, it is behind the camera).

events.render:set(function()
    for _, pawn in ipairs(entity.pawns(true)) do
        local p = render.world_to_screen(pawn:origin())
        if p then
            render.circle(p, color(255, 60, 60, 255), 4)   -- dot at the enemy's feet
        end
    end
end)

render.offscreen(pos: vector, t?: number)#

Projects a world point for an arrow indicator at the screen edge. If the point is visible on screen, its screen position is returned. If the point is beyond the screen edge or behind the camera, a point on a circle around the screen center, in the direction of the target, is returned.

Parameter Type Description
pos vector world point
t number circle radius as a fraction of half the smaller screen side: 0 — center, 1 — edge. Clamped to [0, 1]; default 1

Example: on a 3440×1440 screen half the smaller side is 720 px, so with t = 0.25 the point is placed 180 px from the center.

Returns: vector, number, boolean:

  • the screen point (vector, z is always 0);
  • the direction angle to the point in degrees (0 if the point is visible);
  • true if the point is beyond the screen edge; false if it is visible.

Also works outside the render event. If the screen size is not available, the error is offscreen: screen size unavailable.

-- A marker dot for every enemy beyond the screen edge
events.render:set(function()
    for _, pawn in ipairs(entity.pawns(true)) do
        local p, ang, off = render.offscreen(pawn:origin(), 0.8)
        if off then
            render.circle(vector2(p.x, p.y), color(255, 60, 60, 255), 5)
        end
    end
end)

render.camera_angles()#

Angles of the main game camera.

Returns: angle — a copy of the camera angles.

local font = render.load_font("Verdana", 14, "outline")

events.render:set(function()
    local a = render.camera_angles()
    render.text(vector2(20, 60), color(255, 255, 255, 255), font, nil, string.format("pitch %.1f  yaw %.1f", a.x, a.y))
end)

render.line(a: vector2, b: vector2, col: color, thickness?: number)#

Draws a line segment.

Parameter Type Description
a vector2 start
b vector2 end
col color color
thickness number thickness, default 1

Returns: nothing.

-- A line from the bottom center of the screen to each enemy
events.render:set(function()
    local s = render.screen_size()
    local from = vector2(s.x / 2, s.y)
    for _, pawn in ipairs(entity.pawns(true)) do
        local p = render.world_to_screen(pawn:origin())
        if p then
            render.line(from, p, color(255, 200, 0, 180), 1)
        end
    end
end)

render.bezier(p1: vector2, p2: vector2, p3: vector2, p4: vector2, col: color, thickness: number, segments?: number)#

Draws a cubic Bezier curve from p1 to p4 with control points p2 and p3.

Parameter Type Description
p1 … p4 vector2 start, two control points, end
col color color; nothing is drawn with alpha 0
thickness number thickness (required)
segments number number of segments; default 0 — chosen automatically

Returns: nothing.

events.render:set(function()
    render.bezier(vector2(40, 300), vector2(90, 240), vector2(140, 360), vector2(190, 300), color(0, 200, 255, 255), 2)
end)

render.rect(pos: vector2, size: vector2, col: color, rounding?: number|table)#

Draws a filled rectangle.

Parameter Type Description
pos vector2 top-left corner
size vector2 size
col color fill color
rounding number or table corner rounding

Returns: nothing.

events.render:set(function()
    render.rect(vector2(20, 100), vector2(160, 40), color(20, 20, 20, 200), 6)
end)

render.rect_outline(pos: vector2, size: vector2, col: color, thickness?: number, rounding?: number|table)#

Draws a rectangle outline.

Parameter Type Description
pos vector2 top-left corner
size vector2 size
col color color
thickness number thickness, default 1
rounding number or table corner rounding

Returns: nothing.

events.render:set(function()
    -- only the top corners are rounded
    render.rect_outline(vector2(20, 100), vector2(160, 40), color(255, 255, 255, 255), 1, { 6, 6, 0, 0 })
end)

render.rect_shadow(pos: vector2, size: vector2, col: color, rounding?: number|table, blur?: number, offset?: vector2)#

Draws a soft rectangle shadow.

Parameter Type Description
pos vector2 top-left corner
size vector2 size
col color shadow color
rounding number or table corner rounding
blur number blur, default 0
offset vector2 shadow offset, default (0, 0)

Returns: nothing.

events.render:set(function()
    local pos, size = vector2(20, 160), vector2(160, 40)
    render.rect_shadow(pos, size, color(0, 0, 0, 200), 6, 12, vector2(0, 2))
    render.rect(pos, size, color(30, 30, 30, 255), 6)
end)

render.rect_gradient(pos: vector2, size: vector2, c1: color, c2: color, c3: color, c4: color, rounding?: number|table)#

Draws a rectangle with a corner gradient.

Parameter Type Description
pos vector2 top-left corner
size vector2 size
c1 color top-left corner
c2 color top-right corner
c3 color bottom-left corner
c4 color bottom-right corner
rounding number or table corner rounding

Returns: nothing.

events.render:set(function()
    local a, b = color(255, 80, 80, 255), color(80, 80, 255, 255)
    -- horizontal gradient: red on the left, blue on the right
    render.rect_gradient(vector2(20, 220), vector2(160, 8), a, b, a, b, 4)
end)

render.rect_glow(pos: vector2, size: vector2, col: color, rounding?: number|table)#

Draws a glowing accent bar. Only the top-left radius is taken from the rounding.

Parameter Type Description
pos vector2 top-left corner
size vector2 size
col color glow color
rounding number or table rounding

Returns: nothing.

events.render:set(function()
    render.rect_glow(vector2(20, 240), vector2(4, 40), color(120, 160, 255, 255), 8)
end)

render.rect_window(pos: vector2, size: vector2, rounding?: number|table)#

Draws a window background in the menu style (with background blur and a shadow). The top-left radius is taken from the rounding.

Parameter Type Description
pos vector2 top-left corner
size vector2 size
rounding number or table rounding

Returns: nothing.

  • The call removes an active render.push_blur.
local font = render.load_font("Verdana", 14)

events.render:set(function()
    render.rect_window(vector2(20, 300), vector2(180, 50), 10)
    render.text(vector2(110, 325), color(255, 255, 255, 255), font, "c", "Script window")
end)

render.rect_window_shadow(pos: vector2, size: vector2, rounding?: number|table)#

Draws only the window shadow in the menu style. The top-left radius is applied to all corners.

Parameter Type Description
pos vector2 top-left corner
size vector2 size
rounding number or table rounding

Returns: nothing.

events.render:set(function()
    render.rect_window_shadow(vector2(220, 300), vector2(120, 50), 8)
    render.rect(vector2(220, 300), vector2(120, 50), color(25, 25, 25, 255), 8)
end)

render.circle(center: vector2, col: color, radius: number, start?: number, pct?: number)#

Draws a filled circle or sector. Nothing is drawn with alpha 0 or radius <= 0.

Parameter Type Description
center vector2 center
col color color
radius number radius
start number start angle, degrees; default 0
pct number circle fraction; default 1

Returns: nothing.

events.render:set(function()
    render.circle(vector2(60, 400), color(255, 0, 255, 255), 16, 0, 0.75)   -- three quarters
end)

render.circle_outline(center: vector2, col: color, radius: number, start?: number, pct?: number, thickness?: number)#

Draws a circle or an arc as an outline.

Parameter Type Description
center vector2 center
col color color
radius number radius
start number start angle, degrees; default 0
pct number circle fraction; default 1
thickness number thickness, default 1

Returns: nothing.

-- Health indicator as an arc around the crosshair
events.render:set(function()
    local me = entity.local_pawn()
    if not me or not me:is_alive() then return end
    local center = render.screen_size() / 2
    render.circle_outline(center, color(80, 255, 120, 255), 24, -90, me:health() / 100, 2)
end)

render.circle_gradient(center: vector2, edge: color, inner: color, radius: number, softness?: number, start?: number, pct?: number)#

Draws a circle with a radial gradient from the center to the edge.

Parameter Type Description
center vector2 center
edge color edge color
inner color center color
radius number radius
softness number fraction of the radius taken by the transition from the edge color to the center color; default 1 — a smooth gradient
start number start angle, degrees; default 0
pct number circle fraction; default 1
  • Small softness values (for example, 0.1) give a solid circle of the inner color with a thin transition to edge at the rim.
  • Values of 0.5 and above give a smooth gradient. Values above 1 work like 1.

Returns: nothing.

events.render:set(function()
    -- smooth gradient
    render.circle_gradient(vector2(120, 400), color(255, 0, 0, 0), color(255, 0, 0, 255), 20)
    -- solid circle with a soft rim
    render.circle_gradient(vector2(180, 400), color(255, 0, 0, 0), color(255, 0, 0, 255), 20, 0.1)
end)

render.circle_shadow(center: vector2, col: color, radius: number, blur: number, start?: number, pct?: number, offset?: vector2)#

Draws a soft circle shadow.

Parameter Type Description
center vector2 center
col color shadow color
radius number radius
blur number blur (required)
start number start angle, degrees; default 0
pct number circle fraction; default 1
offset vector2 offset, default (0, 0)

Returns: nothing.

events.render:set(function()
    local c = vector2(180, 400)
    render.circle_shadow(c, color(0, 0, 0, 255), 14, 10)
    render.circle(c, color(240, 240, 240, 255), 14)
end)

render.circle_blur(center: vector2, alpha: number, radius: number, start?: number, pct?: number)#

Draws a circle of blurred background.

Parameter Type Description
center vector2 center
alpha number blur opacity, 0–1
radius number radius
start number start angle, degrees; default 0
pct number circle fraction; default 1

Returns: nothing.

events.render:set(function()
    render.circle_blur(vector2(240, 400), 1, 28)
end)

render.triangle(a: vector2, b: vector2, c: vector2, col: color)#

Draws a filled triangle.

Parameter Type Description
a, b, c vector2 vertices
col color color

Returns: nothing.

-- A pointer arrow above the screen center
events.render:set(function()
    local c = render.screen_size() / 2
    render.triangle(vector2(c.x, c.y - 40), vector2(c.x + 8, c.y - 52), vector2(c.x - 8, c.y - 52), color(255, 255, 255, 255))
end)

render.triangle_outline(a: vector2, b: vector2, c: vector2, col: color, thickness?: number)#

Draws a triangle outline.

Parameter Type Description
a, b, c vector2 vertices
col color color
thickness number thickness, default 1

Returns: nothing.

events.render:set(function()
    render.triangle_outline(vector2(300, 380), vector2(320, 410), vector2(280, 410), color(255, 255, 255, 255), 1.5)
end)

render.poly(points: table, col: color)#

Draws a convex filled polygon.

Parameter Type Description
points table array of vertices {vector2, ...}
col color color

Returns: nothing.

events.render:set(function()
    render.poly({ vector2(340, 380), vector2(360, 390), vector2(350, 410), vector2(330, 400) }, color(0, 128, 255, 255))
end)

render.polyline(points: table, col: color, closed: boolean, thickness: number)#

Draws a polyline.

Parameter Type Description
points table array of points {vector2, ...}
col color color
closed boolean close the polyline (required)
thickness number thickness (required)

Returns: nothing.

-- FPS graph for the last 60 frames
local history = {}

events.render:set(function()
    table.insert(history, 1 / math.max(globals.absoluteframetime, 0.001))
    if #history > 60 then table.remove(history, 1) end

    local pts = {}
    for i, fps in ipairs(history) do
        pts[i] = vector2(20 + i * 3, 500 - math.min(fps, 300) / 3)
    end
    if #pts > 1 then
        render.polyline(pts, color(0, 255, 120, 255), false, 1)
    end
end)

render.poly_gradient(anchor: vector2|nil, points: table, edge: color, center: color, extent?: number)#

Draws a polygon with a gradient from the edge to the center.

Parameter Type Description
anchor vector2 or nil gradient center point; nil — the average of all vertices is used as the center
points table array of vertices {vector2, ...}
edge color edge color
center color center color
extent number gradient extent, default 1

Returns: nothing.

events.render:set(function()
    local pts = { vector2(400, 380), vector2(480, 380), vector2(480, 440), vector2(400, 440) }
    render.poly_gradient(vector2(440, 410), pts, color(0, 255, 0, 0), color(0, 255, 0, 255), 0.6)
end)

render.poly_shadow(points: table, col: color, thickness: number, offset: vector2)#

Draws a polygon shadow. All arguments are required.

Parameter Type Description
points table array of vertices {vector2, ...}
col color shadow color
thickness number shadow width
offset vector2 shadow offset

Returns: nothing.

events.render:set(function()
    local pts = { vector2(500, 380), vector2(580, 380), vector2(540, 440) }
    render.poly_shadow(pts, color(0, 0, 0, 255), 20, vector2(4, 4))
    render.poly(pts, color(200, 200, 200, 255))
end)