This page covers the RenderingServer API — the public interface to Godot's rendering subsystem — along with how RenderingServerDefault implements it, how resources are managed through RIDs, and how the server coordinates its internal subsystems. For details on the GPU command abstraction layer, see RenderingDevice & Drivers. For the concrete 3D render pipelines (RenderForwardClustered, RenderForwardMobile), see Scene Rendering Pipelines.
RenderingServer is the sole public entry point to all rendering in Godot. The scene system, viewports, and editor all interact with it exclusively through this interface. It is a singleton (accessible via RenderingServer::get_singleton()) that owns all rendering resources for the lifetime of the engine.
The server is deliberately opaque: callers receive RID (Resource ID) handles for every created object and use those handles in subsequent calls. There are no returned pointers to internal objects. This design allows the server to run on a dedicated render thread while callers operate on the main thread.
Diagram: RenderingServer Layered Architecture
Sources: servers/rendering/rendering_server_default.h47-100 servers/rendering/renderer_scene_cull.h52-65 servers/rendering/renderer_viewport.h40-50
The concrete class is RenderingServerDefault in servers/rendering/rendering_server_default.h which inherits from RenderingServer. Every public method of RenderingServer is implemented here using a set of macro-generated wrappers.
The server can run in two modes:
| Mode | Trigger | Behavior |
|---|---|---|
| Single-threaded | create_thread = false | All calls execute immediately on the calling thread |
| Multi-threaded | create_thread = true | A dedicated render thread runs; main-thread calls are queued via CommandQueueMT |
The command_queue member (servers/rendering/rendering_server_default.h80) is a CommandQueueMT that serializes cross-thread calls. Methods are dispatched with macros like FUNC3, FUNC1RC, etc., which internally call command_queue.push(...) when the caller is not the server thread.
Certain operations (e.g., call_on_render_thread) allow user code to execute directly on the render thread via _call_on_render_thread, needed when interacting with RenderingDevice internals.
The header uses a large macro system to generate thread-aware method overrides. For example:
FUNCRIDTEX1(texture_2d, const Ref<Image> &) generates texture_2d_create that allocates a RID and initializes it either immediately (if on the server thread) or via the command queue.FUNC3(texture_2d_update, RID, const Ref<Image> &, int) generates the equivalent queued update call.Sources: servers/rendering/rendering_server_default.h116-265
All rendering objects are opaque handles of type RID. The lifecycle is always:
*_create() → returns RID*_set_*() calls using the RIDfree_rid(RID) to destroyNo object is visible unless attached to a viewport either directly or through the scene hierarchy.
Diagram: 3D Object Lifecycle
Sources: servers/rendering/renderer_scene_cull.cpp428-440 servers/rendering/renderer_viewport.cpp294-305 doc/classes/RenderingServer.xml11-14
Accessed via the RSG:: namespace, these are singleton pointers to the active storage and rendering backends:
| Symbol | Type | Responsibility |
|---|---|---|
RSG::texture_storage | RendererTextureStorage* | Textures, render targets |
RSG::mesh_storage | RendererMeshStorage* | Meshes, multimeshes, skeletons |
RSG::material_storage | RendererMaterialStorage* | Shaders, materials |
RSG::light_storage | RendererLightStorage* | Lights, shadow atlases, lightmaps |
RSG::particles_storage | RendererParticlesStorage* | Particle systems |
RSG::utilities | RendererUtilities* | Frame timing, resource queries |
RSG::rasterizer | RendererCompositor* | Top-level compositor |
RSG::canvas | RendererCanvasCull* | 2D canvas rendering |
Sources: servers/rendering/rendering_server_default.h131-145
viewport_*)Implemented by RendererViewport in servers/rendering/renderer_viewport.h A Viewport struct (servers/rendering/renderer_viewport.h45-187) stores:
RID camera — the active 3D cameraRID scenario — the 3D world to renderHashMap<RID, CanvasData> canvas_map — attached 2D canvases with layer orderingRef<RenderSceneBuffers> render_buffers — per-viewport GPU buffersRID render_target — the texture storage render targetKey viewport methods:
| Method | Effect |
|---|---|
viewport_create() | Creates a viewport RID |
viewport_set_size(vp, w, h) | Sets resolution, configures render buffers |
viewport_attach_camera(vp, cam) | Binds a camera RID |
viewport_set_scenario(vp, scen) | Binds a scenario (3D world) |
viewport_attach_canvas(vp, canvas) | Attaches a 2D canvas |
viewport_attach_to_screen(vp, rect, window_id) | Displays output to an OS window |
viewport_set_update_mode(vp, mode) | Controls when the viewport redraws |
The draw loop calls _draw_viewport() on each active viewport per frame, which internally calls _draw_3d() for 3D content and the canvas renderer for 2D.
Sources: servers/rendering/renderer_viewport.cpp294-305 servers/rendering/renderer_viewport.h219-290
scenario_*, instance_*)Implemented by RendererSceneCull in servers/rendering/renderer_scene_cull.h A scenario is a container for all 3D visible objects. An instance binds a resource (mesh, light, etc.) into a scenario at a given transform.
Instance base types (RSE::InstanceType):
| Constant | What it represents |
|---|---|
INSTANCE_MESH | Static or skeletal mesh |
INSTANCE_MULTIMESH | Instanced mesh batch |
INSTANCE_PARTICLES | GPU particle system |
INSTANCE_LIGHT | Omni / spot / directional light |
INSTANCE_REFLECTION_PROBE | Reflection capture |
INSTANCE_DECAL | Projected texture |
INSTANCE_LIGHTMAP | Baked lightmap |
INSTANCE_VOXEL_GI | Dynamic GI probe |
INSTANCE_FOG_VOLUME | Volumetric fog box/sphere |
INSTANCE_OCCLUDER | CPU occlusion mesh |
Pairing: RendererSceneCull maintains a DynamicBVH spatial structure over instances. When two instances' AABBs overlap (e.g., a light overlapping a mesh), _instance_pair() is called to build geometry–light associations (servers/rendering/renderer_scene_cull.cpp174-297).
Diagram: Instance–Scenario–Viewport Relationships
Sources: servers/rendering/renderer_scene_cull.h73-120 servers/rendering/renderer_scene_cull.cpp174-297
camera_*)Implemented in RendererSceneCull. The Camera struct stores projection type, near/far planes, visibility layers, and the active environment/compositor RIDs.
| Method | Projection type |
|---|---|
camera_set_perspective(cam, fovy, znear, zfar) | Perspective |
camera_set_orthogonal(cam, size, znear, zfar) | Orthographic |
camera_set_frustum(cam, size, offset, znear, zfar) | Tilted frustum |
camera_set_cull_mask controls which instance layers are visible to this camera.
Sources: servers/rendering/renderer_scene_cull.h73-119 servers/rendering/renderer_scene_cull.cpp80-156
environment_*) and Skies (sky_*)RendererSceneRender owns the RendererEnvironmentStorage and RendererCompositorStorage objects directly (servers/rendering/renderer_scene_render.h41-44). Environments configure:
A Sky resource is set on an environment with environment_set_sky(). The sky itself uses a shader material and is rendered at sky_set_radiance_size into a cubemap used for ambient/reflection.
Sources: servers/rendering/renderer_scene_render.h107-250
canvas_*, canvas_item_*)Handled by RendererCanvasCull. A canvas groups canvas items and is attached to a viewport with a layer ordering. Canvas items are the nodes of the 2D draw command list.
Canvas item draw commands (appended in order, cleared each frame):
| Method | Draws |
|---|---|
canvas_item_add_rect | Filled rectangle |
canvas_item_add_line | Anti-aliased line |
canvas_item_add_texture_rect | Textured quad |
canvas_item_add_polygon | Filled polygon |
canvas_item_add_triangle_array | Raw triangle batch (used by Line2D, StyleBoxFlat) |
canvas_item_add_mesh | 2D mesh with transform |
canvas_item_add_multimesh | Instanced 2D mesh batch |
canvas_item_add_particles | 2D GPU particles |
Canvas items form a parent–child hierarchy via canvas_item_set_parent. The accumulated transform chain is applied during rendering.
Sources: doc/classes/RenderingServer.xml200-435
material_*, shader_*)RSG::material_storage manages shaders and materials. Shaders are GLSL-like source strings parsed by the ShaderLanguage subsystem (see Shader Language & Compiler). Materials bind a shader and provide uniform values.
shader_create() → RID
shader_set_code(shader_rid, source_code)
material_create() → RID
material_set_shader(material_rid, shader_rid)
material_set_param(material_rid, param_name, value)
Materials are attached to mesh surfaces or canvas items. Per-instance overrides are set via instance_set_surface_override_material (3D) or canvas_item_set_material (2D).
*_light_*)Three light types are managed through RSG::light_storage:
| Type | Create function | Notes |
|---|---|---|
| Directional | directional_light_create() | Cascaded shadow maps |
| Omni | omni_light_create() | Dual-paraboloid or cubemap shadows |
| Spot | spot_light_create() | Single shadow map |
Lights require an Instance to be placed in a scenario (instance_set_base(instance, light_rid)). Shadow atlas allocation is configured per-viewport with viewport_set_shadow_atlas_size.
mesh_*)RSG::mesh_storage manages meshes. A mesh is a collection of surfaces, each with vertex data and a material slot.
mesh_create() → RID
mesh_add_surface(mesh_rid, surface_data)
mesh_surface_set_material(mesh_rid, surface_index, material_rid)
The surface_data dictionary contains vertex arrays (positions, normals, UVs, tangents, etc.), index arrays, and a primitive type (triangles, lines, points).
call_on_render_thread(callable) is the supported way to execute code that directly uses RenderingDevice APIs. From the doc:
"As the RenderingServer actual logic may run on a separate thread, accessing its internals from the main (or any other) thread will result in errors."
(doc/classes/RenderingServer.xml30-36)
Internally this dispatches via _call_on_render_thread which either calls directly (if already on the server thread) or pushes to the command queue.
Diagram: Per-Frame Draw Flow
Sources: servers/rendering/renderer_viewport.cpp94-310 servers/rendering/renderer_scene_cull.cpp1-50 servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp295-300
When started with --headless, RenderingServer is replaced by a stub that returns dummy RIDs and performs no GPU work. Most methods are no-ops. This is used for CI, servers, and dedicated game servers.
(doc/classes/RenderingServer.xml15-16)
| File | Role |
|---|---|
servers/rendering/rendering_server.h | Abstract RenderingServer base class |
servers/rendering/rendering_server_default.h | Concrete RenderingServerDefault with macro-generated thread dispatch |
servers/rendering/renderer_scene_cull.h/cpp | RendererSceneCull: scenario, instance, camera management + BVH |
servers/rendering/renderer_viewport.h/cpp | RendererViewport: viewport management and draw orchestration |
servers/rendering/renderer_scene_render.h | Abstract RendererSceneRender: environment, sky, GI, compositor interfaces |
servers/rendering/renderer_rd/renderer_scene_render_rd.cpp/h | RendererSceneRenderRD: post-processing, tonemap, GI integration |
servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp/h | RenderForwardClustered: desktop render pipeline |
servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp/h | RenderForwardMobile: mobile render pipeline |
Refresh this wiki
This wiki was recently refreshed. Please wait 2 days to refresh again.