Sculpt Mode vs Paint Mode in ArmorPaint: Architecture and Pipeline Differences

ArmorPaint’s Sculpt Mode and Paint Mode represent distinct workflow architectures governed by the g_config->workflow enumeration, where Paint Mode targets standard PBR texture maps via texpaint buffers while Sculpt Mode operates on high-precision displacement textures (texpaint_sculpt) using specialized sculpt brushes and separate render commands.

ArmorPaint is an open-source 3D texture painting application that supports two fundamentally different creative workflows. The system distinguishes between these modes through the g_config->workflow configuration value defined in paint/sources/enums.h, which determines texture allocation, brush behavior, and render pipeline routing.

Workflow Enumeration and Core Architecture

The primary distinction begins with the workflow constant assigned to the global configuration. In paint/sources/enums.h (lines 87‑89), the workflow is defined as:

  • Paint Mode: Uses WORKFLOW_PBR (0) or WORKFLOW_BASE (1)
  • Sculpt Mode: Uses WORKFLOW_SCULPT (2)

When the user selects Sculpt from the main menu in paint/sources/ui/ui_menubar.c (line 788), the application sets g_config->workflow = WORKFLOW_SCULPT and triggers a complete reinitialization of the layer system. This switch allocates an entirely different class of render targets and redirects brush input to the sculpt-specific pipeline.

Texture Targets and Memory Layout

Paint Mode and Sculpt Mode write to fundamentally different GPU textures. In paint/sources/util/util_layer.c, the allocation logic diverges based on the active workflow:

  • Paint Mode creates texpaint targets (lines 30‑38) for base color, metallic, roughness, and other PBR channels using standard precision formats.
  • Sculpt Mode allocates texpaint_sculpt (lines 119‑132) as a 128‑bit floating‑point texture (GPU_TEXTURE_FORMAT_RGBA128) to store high‑precision displacement data.

Sculpt Mode additionally maintains auxiliary render targets including texpaint_sculpt_base and texpaint_sculpt_ref for intermediate displacement calculations, whereas Paint Mode relies solely on the standard PBR texture stack.

Brush Systems and Tool Architecture

The brush engines differ significantly between the two modes. In paint/sources/ui/ui_header.c (line 382), the UI exposes standard paint brushes—color, fill, erase, and masking tools—that manipulate the texpaint buffers directly.

Conversely, Sculpt Mode brushes are defined in paint/sources/render/make_sculpt.c (line 184) and accessed through g_context->brush_sculpt. These include specialized sculpt operations such as:

  • SCULPT_TYPE_GRAB
  • SCULPT_TYPE_PINCH
  • Flatten and Smooth variants

These tools do not paint color values; instead, they deform the mesh by writing displacement vectors to the texpaint_sculpt texture.

Render Pipeline Execution

The render path conditionally executes sculpt commands only when valid sculpt data exists. In paint/sources/render/render_path_paint.c (lines 231‑233), the engine checks:

if (g_context->layer->texpaint_sculpt != NULL && !picking_tool && !g_context->material_preview) {
    render_path_sculpt_commands();   // Lines 510‑518
}

Paint Mode executes the standard pipeline defined in render_path_paint.c, drawing directly to the PBR targets. Sculpt Mode invokes render_path_sculpt_commands() to dispatch compute shaders that process displacement data. When g_context->layer->texpaint_sculpt is NULL, the engine skips all sculpt commands and reverts to standard painting (line 231).

Layer Management and Identification

Layers are type‑tagged by the presence of specific texture pointers. In paint/sources/ui/ui_view2d.c (line 218), the UI identifies sculpt layers by checking l->texpaint_sculpt != NULL, while regular paint layers satisfy l->texpaint != NULL.

The context menu logic in paint/sources/ui/tab_layers.c (lines 927‑937) exposes different operations based on this distinction. Sculpt layers feature an Apply Sculpt command that bakes displacement data into the standard PBR maps.

Creating and Switching Modes Programmatically

To switch workflows in code, set the global configuration and reinitialize the layer path:

// Force Sculpt workflow
g_config->workflow = WORKFLOW_SCULPT;

/* Re‑initialise render targets for sculpting */
layers_new_path_layer_sculpt_init(NULL);

Creating a dedicated sculpt layer (triggered from tab_layers.c lines 1041‑1042) allocates the high‑precision texture:

// Called from the UI "Sculpt Layer" button
void tab_layers_button_new_sculpt_layer(void *_) {
    sculpt_layers_create_sculpt_layer();   // allocates texpaint_sculpt
    sys_notify_on_next_frame(&tab_layers_button_new_sculpt_layer, NULL);
}

Applying Sculpt Data to Paint Layers

To merge sculpt displacement into standard PBR textures, the Apply Sculpt command invokes:

// Context‑menu command "Apply Sculpt"
void tab_layers_draw_layer_context_menu_apply_sculpt(void *_) {
    slot_layer_apply_sculpt(l);   // merges texpaint_sculpt into l->texpaint
    sys_notify_on_next_frame(&tab_layers_draw_layer_context_menu_apply_sculpt, NULL);
}

This operation samples the texpaint_sculpt texture and bakes the displacement into the layer’s base color and normal maps, allowing the sculpted detail to persist after switching back to Paint Mode.

Summary

  • Workflow constants: Paint Mode uses WORKFLOW_PBR or WORKFLOW_BASE, while Sculpt Mode requires WORKFLOW_SCULPT as defined in enums.h.
  • Texture targets: Paint Mode writes to standard texpaint buffers; Sculpt Mode requires texpaint_sculpt with 128‑bit floating‑point precision.
  • Brush systems: Paint uses color/fill tools via ui_header.c; Sculpt uses displacement brushes (SCULPT_TYPE_GRAB, SCULPT_TYPE_PINCH) managed in make_sculpt.c.
  • Render paths: The engine checks layer->texpaint_sculpt in render_path_paint.c to conditionally execute render_path_sculpt_commands().
  • Layer identification: Sculpt layers are validated by l->texpaint_sculpt != NULL and can be baked to paint layers via slot_layer_apply_sculpt().

Frequently Asked Questions

How do I switch from Paint Mode to Sculpt Mode in ArmorPaint?

Set g_config->workflow = WORKFLOW_SCULPT and call the layer initialization routine. According to util_layer.c (lines 660‑693), changing the workflow automatically recreates the appropriate render targets. The UI entry point in ui_menubar.c (line 788) triggers sculpt_layers_create_sculpt_layer(), which allocates the high‑precision texpaint_sculpt texture required for displacement editing.

What texture format does Sculpt Mode use for displacement?

Sculpt Mode allocates texpaint_sculpt as a 128‑bit floating‑point texture (GPU_TEXTURE_FORMAT_RGBA128) as implemented in util_layer.c (lines 119‑132). This format provides the numerical precision necessary for high‑frequency displacement data, whereas Paint Mode uses standard 8‑bit or 16‑bit textures for color and material channels.

Why are sculpt brushes different from standard paint brushes?

Sculpt brushes manipulate geometric displacement rather than surface color. In make_sculpt.c (line 184), sculpt brush types like SCULPT_TYPE_GRAB and SCULPT_TYPE_PINCH are stored in g_context->brush_sculpt and processed by the render_path_sculpt_commands() pipeline. These tools write to the texpaint_sculpt render targets using compute shaders, while paint brushes update the texpaint PBR buffers through the standard rasterization path.

Can I convert Sculpt Mode data into regular PBR textures?

Yes. The Apply Sculpt operation in tab_layers.c calls slot_layer_apply_sculpt(l), which samples the displacement data from l->texpaint_sculpt and bakes it into the layer’s standard PBR textures. This merges the sculpt detail into the base color and normal maps, allowing you to continue editing in Paint Mode while preserving the sculpted surface detail.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →