Skip to content

Panel Background

This example shows a custom panel background behind a foreground primitive.

Preview

Run And Adapt

Commands below assume a Datoviz source checkout and start at the repository root. Use your configured build environment; Python routes additionally require local bindings.

Route Availability Command or action
C Canonical native source just example-c features/panel_background (build and run), or rerun ./build/examples/c/features/panel_background
Python Available; direct-engine adaptation python3 -m examples.python.gallery.features.panel_background
Browser Live WebGPU route Open live example

This example is approved as a starting point for user code and coding agents. Keep the object lifetimes and data shapes intact while adapting the data and styling.

What To Look For

The panel rectangle is explicitly inset inside the figure and receives a linear-gradient background before a triangle-list primitive uploads position, color, and normal arrays. Compare the gradient panel area with the surrounding figure space; styled backgrounds are useful for separating dense scientific plots, dark-field images, or instrument overlays from the rest of a figure.

Source

#!/usr/bin/env python3
"""Custom panel background behind a foreground primitive."""

from __future__ import annotations

import ctypes

import numpy as np

import datoviz as dvz

from examples.python.gallery import common as ex


def _set_gradient_background(panel) -> None:
    background = dvz.dvz_panel_background_desc()
    background.type = dvz.DVZ_PANEL_BACKGROUND_LINEAR_GRADIENT
    background.gradient.start[:] = (0.0, 0.0)
    background.gradient.end[:] = (1.0, 1.0)
    background.gradient.color0[:] = (0.010, 0.030, 0.065, 1.0)
    background.gradient.color1[:] = (0.025, 0.345, 0.380, 1.0)
    if dvz.dvz_panel_set_background(panel, ctypes.byref(background)) != 0:
        raise RuntimeError("dvz_panel_set_background() failed")


def main() -> None:
    scene = dvz.dvz_scene()
    if not scene:
        raise RuntimeError("dvz_scene() failed")
    figure = dvz.dvz_figure(scene, ex.WIDTH, ex.HEIGHT, 0)
    if not figure:
        raise RuntimeError("dvz_figure() failed")
    panel = ex.panel_rect(figure, 0.10, 0.12, 0.80, 0.76)
    _set_gradient_background(panel)

    positions = np.array(
        [
            [-0.70, -0.40, 0.0],
            [-0.10, -0.40, 0.0],
            [-0.40, +0.42, 0.0],
            [+0.10, -0.40, 0.0],
            [+0.70, -0.40, 0.0],
            [+0.40, +0.42, 0.0],
        ],
        dtype=np.float32,
    )
    colors = ex.color_array(ex.CYAN, ex.GREEN, ex.YELLOW, ex.GREEN, ex.CYAN, ex.TEXT)
    normals = np.zeros_like(positions)
    normals[:, 2] = 1.0

    visual = dvz.dvz_primitive(scene, dvz.DVZ_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0)
    if not visual:
        raise RuntimeError("dvz_primitive() failed")
    if dvz.dvz_visual_set_data_many(
        visual,
        {
            "position": positions,
            "color": colors,
            "normal": normals,
        },
    ) != 0:
        raise RuntimeError("dvz_visual_set_data_many() failed")
    if dvz.dvz_visual_set_depth_test(visual, False) != 0:
        raise RuntimeError("dvz_visual_set_depth_test() failed")

    attach = dvz.dvz_visual_attach_desc()
    attach.coord_space = dvz.DVZ_VISUAL_COORD_VIEW
    if dvz.dvz_panel_add_visual(panel, visual, ctypes.byref(attach)) != 0:
        raise RuntimeError("dvz_panel_add_visual() failed")

    ex.run(scene, figure, "Panel Background")


if __name__ == "__main__":
    main()
/*
 * Copyright (c) 2021 Cyrille Rossant and contributors. All rights reserved.
 * Licensed under the MIT license. See LICENSE file in the project root for details.
 * SPDX-License-Identifier: MIT
 */

/* This example shows a custom panel background behind a foreground primitive.
 *
 * What to look for: the panel rectangle is explicitly inset inside the figure and receives a
 * linear-gradient background before a triangle-list primitive uploads position, color, and normal
 * arrays. Compare the gradient panel area with the surrounding figure space; styled backgrounds
 * are useful for separating dense scientific plots, dark-field images, or instrument overlays from
 * the rest of a figure.
 *
 * Scenario: features_panel_background
 * Style: features, graphite_cyan, 1280x720 window target
 *
 * Build:  just example-c features/panel_background
 * Run:    ./build/examples/c/features/panel_background --live
 * Smoke:  ./build/examples/c/features/panel_background --png
 */



/*************************************************************************************************/
/*  Includes                                                                                     */
/*************************************************************************************************/

#include <stdbool.h>
#include <stdint.h>

#include "_assertions.h"
#include "datoviz/scene.h"
#include "example_style.h"
#include "runner/scenario_runner.h"



/*************************************************************************************************/
/*  Forward declarations                                                                         */
/*************************************************************************************************/

DvzScenarioSpec dvz_example_panel_background_scenario(void);



/*************************************************************************************************/
/*  Constants                                                                                    */
/*************************************************************************************************/

#define WIDTH  EXAMPLE_WINDOW_WIDTH
#define HEIGHT EXAMPLE_WINDOW_HEIGHT
#define VERTEX_COUNT 6u



/*************************************************************************************************/
/*  Helpers                                                                                      */
/*************************************************************************************************/

/**
 * Add one compact foreground primitive over the fixed panel background.
 *
 * @param scene scene owning the visual
 * @param panel panel receiving the visual
 * @return true when the visual was added
 */
static bool _add_foreground(DvzScene* scene, DvzPanel* panel)
{
    ANN(scene);
    ANN(panel);

    const vec3 positions[VERTEX_COUNT] = {
        {-0.70f, -0.40f, 0.0f}, {-0.10f, -0.40f, 0.0f}, {-0.40f, +0.42f, 0.0f},
        {+0.10f, -0.40f, 0.0f}, {+0.70f, -0.40f, 0.0f}, {+0.40f, +0.42f, 0.0f},
    };
    DvzColor colors[VERTEX_COUNT] = {
        example_graphite_cyan_color(EXAMPLE_STYLE_COLOR_ACCENT_PRIMARY),
        example_graphite_cyan_color(EXAMPLE_STYLE_COLOR_ACCENT_SECONDARY),
        example_graphite_cyan_color(EXAMPLE_STYLE_COLOR_WARNING),
        example_graphite_cyan_color(EXAMPLE_STYLE_COLOR_ACCENT_SECONDARY),
        example_graphite_cyan_color(EXAMPLE_STYLE_COLOR_ACCENT_PRIMARY),
        example_graphite_cyan_color(EXAMPLE_STYLE_COLOR_TEXT),
    };
    vec3 normals[VERTEX_COUNT] = {{0}};
    for (uint32_t i = 0; i < VERTEX_COUNT; i++)
        normals[i][2] = 1.0f;

    DvzVisual* visual = dvz_primitive(scene, DVZ_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0);
    if (visual == NULL)
        return false;

    DvzVisualDataUpdate updates[] = {
        {.attr_name = "position", .data = positions, .item_count = VERTEX_COUNT},
        {.attr_name = "color", .data = colors, .item_count = VERTEX_COUNT},
        {.attr_name = "normal", .data = normals, .item_count = VERTEX_COUNT},
    };
    if (dvz_visual_set_data_many(visual, updates, 3) != 0)
        return false;
    if (dvz_visual_set_depth_test(visual, false) != 0)
        return false;

    DvzVisualAttachDesc attach = dvz_visual_attach_desc();
    attach.coord_space = DVZ_VISUAL_COORD_VIEW;
    return dvz_panel_add_visual(panel, visual, &attach) == 0;
}



/*************************************************************************************************/
/*  Scenario callbacks                                                                           */
/*************************************************************************************************/

/**
 * Initialize the fixed panel background scenario.
 *
 * @param ctx scenario context
 * @param out_user scenario state output
 * @return true on success
 */
static bool _scenario_init(DvzScenarioContext* ctx, void** out_user)
{
    if (ctx == NULL)
        return false;
    if (out_user != NULL)
        *out_user = NULL;

    ctx->figure = dvz_figure(ctx->scene, ctx->width, ctx->height, 0);
    if (ctx->figure == NULL)
        return false;

    DvzPanel* panel = dvz_panel_full(ctx->figure);
    if (panel == NULL)
        return false;
    if (dvz_panel_set_desc(
            panel,
            &(DvzPanelDesc){.x = 0.10f, .y = 0.12f, .width = 0.80f, .height = 0.76f}) !=
        DVZ_OK)
        return false;
    DvzPanelBackgroundDesc background = {DVZ_STRUCT_INIT_FIELDS(DvzPanelBackgroundDesc),
        .type = DVZ_PANEL_BACKGROUND_LINEAR_GRADIENT,
        .gradient = {
            .start = {0.0f, 0.0f},
            .end = {1.0f, 1.0f},
            .color0 = {0.010f, 0.030f, 0.065f, 1.0f},
            .color1 = {0.025f, 0.345f, 0.380f, 1.0f},
        }};
    if (dvz_panel_set_background(panel, &background) != DVZ_OK)
        return false;

    return _add_foreground(ctx->scene, panel);
}



/**
 * Return the panel-background scenario specification.
 *
 * @return scenario specification
 */
DvzScenarioSpec dvz_example_panel_background_scenario(void)
{
    return (DvzScenarioSpec){
        .id = "features_panel_background",
        .title = "Panel Background",
        .width = WIDTH,
        .height = HEIGHT,
        .fps = 60.0,
        .init = _scenario_init,
    };
}



/*************************************************************************************************/
/*  Functions                                                                                    */
/*************************************************************************************************/

/**
 * Run the fixed panel background feature example through the native scenario runner.
 *
 * @param argc command-line argument count
 * @param argv command-line argument vector
 * @return process exit code
 */
#ifndef DVZ_EXAMPLE_NO_MAIN
int main(int argc, char** argv)
{
    DvzScenarioSpec spec = dvz_example_panel_background_scenario();
    return dvz_scenario_run_native_cli(&spec, argc, argv) == 0 ? 0 : 1;
}
#endif
Example details

Data

Field Value
kind synthetic