← ziglang.inraylib-zigGitHub

rounded rectangle

★★★☆by Anstro Pleuton (@anstropleuton)

There is no browser build of this example yet.

Is it the same as C?

//! raylib [shaders] example - rounded rectangle
//!
//! Zig-API translation of examples/shaders/shaders_rounded_rectangle.c (raylib 6.2).
//! Example contributed by Anstro Pleuton (@anstropleuton) and reviewed by Ramon Santamaria (@raysan5)
//! Example licensed under an unmodified zlib/libpng license.
//! Copyright (c) 2025 Anstro Pleuton (@anstropleuton)

const std = @import("std");
const rl = @import("raylib");

const glsl_version = 330;

const screen_width = 800;
const screen_height = 450;

/// Rounded rectangle data
const RoundedRectangle = struct {
    corner_radius: rl.Vector4, // Individual corner radius (top-left, top-right, bottom-left, bottom-right)

    // Shadow variables
    shadow_radius: f32,
    shadow_offset: rl.Vector2,
    shadow_scale: f32,

    // Border variables
    border_thickness: f32, // Inner-border thickness

    // Shader locations
    rectangle_loc: i32,
    radius_loc: i32,
    color_loc: i32,
    shadow_radius_loc: i32,
    shadow_offset_loc: i32,
    shadow_scale_loc: i32,
    shadow_color_loc: i32,
    border_thickness_loc: i32,
    border_color_loc: i32,

    /// Create a rounded rectangle and set uniform locations
    fn init(
        corner_radius: rl.Vector4,
        shadow_radius: f32,
        shadow_offset: rl.Vector2,
        shadow_scale: f32,
        border_thickness: f32,
        shader: rl.Shader,
    ) RoundedRectangle {
        const rec: RoundedRectangle = .{
            .corner_radius = corner_radius,
            .shadow_radius = shadow_radius,
            .shadow_offset = shadow_offset,
            .shadow_scale = shadow_scale,
            .border_thickness = border_thickness,

            // Get shader uniform locations
            .rectangle_loc = rl.getShaderLocation(shader, "rectangle"),
            .radius_loc = rl.getShaderLocation(shader, "radius"),
            .color_loc = rl.getShaderLocation(shader, "color"),
            .shadow_radius_loc = rl.getShaderLocation(shader, "shadowRadius"),
            .shadow_offset_loc = rl.getShaderLocation(shader, "shadowOffset"),
            .shadow_scale_loc = rl.getShaderLocation(shader, "shadowScale"),
            .shadow_color_loc = rl.getShaderLocation(shader, "shadowColor"),
            .border_thickness_loc = rl.getShaderLocation(shader, "borderThickness"),
            .border_color_loc = rl.getShaderLocation(shader, "borderColor"),
        };
        rec.update(shader);
        return rec;
    }

    /// Update rounded rectangle uniforms
    fn update(rec: RoundedRectangle, shader: rl.Shader) void {
        rl.setShaderValue(shader, rec.radius_loc, rec.corner_radius);
        rl.setShaderValue(shader, rec.shadow_radius_loc, rec.shadow_radius);
        rl.setShaderValue(shader, rec.shadow_offset_loc, rec.shadow_offset);
        rl.setShaderValue(shader, rec.shadow_scale_loc, rec.shadow_scale);
        rl.setShaderValue(shader, rec.border_thickness_loc, rec.border_thickness);
    }

    /// Draw `rec` (framed and labelled, `margin` pixels around it) with the
    /// shader; pass `.blank` to leave a color layer (fill, shadow, border) out.
    fn draw(
        self: RoundedRectangle,
        shader: rl.Shader,
        rec: rl.Rectangle,
        margin: i32,
        label: [:0]const u8,
        color: rl.Color,
        shadow_color: rl.Color,
        border_color: rl.Color,
    ) void {
        const x: i32 = @intFromFloat(rec.x);
        const y: i32 = @intFromFloat(rec.y);
        const width: i32 = @intFromFloat(rec.width);
        const height: i32 = @intFromFloat(rec.height);
        rl.drawRectangleLines(x - margin, y - margin, width + 2 * margin, height + 2 * margin, .dark_gray);
        rl.drawText(label, x - margin, y - margin - 15, 10, .dark_gray);

        // Flip Y axis to match shader coordinate system
        const flipped: rl.Vector4 = .{ .x = rec.x, .y = screen_height - rec.y - rec.height, .z = rec.width, .w = rec.height };
        rl.setShaderValue(shader, self.rectangle_loc, flipped);

        rl.setShaderValue(shader, self.color_loc, rl.colorNormalize(color));
        rl.setShaderValue(shader, self.shadow_color_loc, rl.colorNormalize(shadow_color));
        rl.setShaderValue(shader, self.border_color_loc, rl.colorNormalize(border_color));

        rl.beginShaderMode(shader);
        defer rl.endShaderMode();

        rl.drawRectangle(0, 0, screen_width, screen_height, .white);
    }
};

pub fn main() !void {
    // Initialization
    rl.initWindow(screen_width, screen_height, "raylib [shaders] example - rounded rectangle");
    defer rl.closeWindow(); // Close window and OpenGL context

    // Load the shader
    const shader = try rl.loadShader(
        std.fmt.comptimePrint("resources/shaders/glsl{d}/base.vs", .{glsl_version}),
        std.fmt.comptimePrint("resources/shaders/glsl{d}/rounded_rectangle.fs", .{glsl_version}),
    );
    defer rl.unloadShader(shader);

    // Create a rounded rectangle
    const rounded_rectangle: RoundedRectangle = .init(
        .{ .x = 5.0, .y = 10.0, .z = 15.0, .w = 20.0 }, // Corner radius
        20.0, // Shadow radius
        .{ .x = 0.0, .y = -5.0 }, // Shadow offset
        0.95, // Shadow scale
        5.0, // Border thickness
        shader, // Shader
    );

    // Update shader uniforms
    rounded_rectangle.update(shader);

    const rectangle_color: rl.Color = .blue;
    const shadow_color: rl.Color = .dark_blue;
    const border_color: rl.Color = .sky_blue;

    rl.setTargetFPS(60);

    // Main game loop
    while (!rl.windowShouldClose()) { // Detect window close button or ESC key
        // Draw
        rl.beginDrawing();
        defer rl.endDrawing();

        rl.clearBackground(.ray_white);

        // Draw rectangle box with rounded corners using shader (only rectangle color)
        rounded_rectangle.draw(shader, .{ .x = 50, .y = 70, .width = 110, .height = 60 }, 20, "Rounded rectangle", rectangle_color, .blank, .blank);

        // Draw rectangle shadow using shader (only shadow color)
        rounded_rectangle.draw(shader, .{ .x = 50, .y = 200, .width = 110, .height = 60 }, 20, "Rounded rectangle shadow", .blank, shadow_color, .blank);

        // Draw rectangle's border using shader (only border color)
        rounded_rectangle.draw(shader, .{ .x = 50, .y = 330, .width = 110, .height = 60 }, 20, "Rounded rectangle border", .blank, .blank, border_color);

        // Draw one more rectangle with all three colors
        rounded_rectangle.draw(shader, .{ .x = 240, .y = 80, .width = 500, .height = 300 }, 30, "Rectangle with all three combined", rectangle_color, shadow_color, border_color);

        rl.drawText("(c) Rounded rectangle SDF by Iñigo Quilez. MIT License.", screen_width - 300, screen_height - 20, 10, .black);
    }
}
/*******************************************************************************************
*
*   raylib [shaders] example - rounded rectangle
*
*   Example complexity rating: [★★★☆] 3/4
*
*   Example originally created with raylib 5.5, last time updated with raylib 5.5
*
*   Example contributed by Anstro Pleuton (@anstropleuton) and reviewed by Ramon Santamaria (@raysan5)
*
*   Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
*   BSD-like license that allows static linking with closed source software
*
*   Copyright (c) 2025 Anstro Pleuton (@anstropleuton)
*
********************************************************************************************/

#include "raylib.h"

#if defined(PLATFORM_DESKTOP)
    #define GLSL_VERSION            330
#else   // PLATFORM_ANDROID, PLATFORM_WEB
    #define GLSL_VERSION            100
#endif

//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
// Rounded rectangle data
typedef struct {
    Vector4 cornerRadius; // Individual corner radius (top-left, top-right, bottom-left, bottom-right)

    // Shadow variables
    float shadowRadius;
    Vector2 shadowOffset;
    float shadowScale;

    // Border variables
    float borderThickness; // Inner-border thickness

    // Shader locations
    int rectangleLoc;
    int radiusLoc;
    int colorLoc;
    int shadowRadiusLoc;
    int shadowOffsetLoc;
    int shadowScaleLoc;
    int shadowColorLoc;
    int borderThicknessLoc;
    int borderColorLoc;
} RoundedRectangle;

//------------------------------------------------------------------------------------
// Module Functions Declaration
//------------------------------------------------------------------------------------
// Create a rounded rectangle and set uniform locations
static RoundedRectangle CreateRoundedRectangle(Vector4 cornerRadius, float shadowRadius, Vector2 shadowOffset, float shadowScale, float borderThickness, Shader shader);

// Update rounded rectangle uniforms
static void UpdateRoundedRectangle(RoundedRectangle rec, Shader shader);

//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
    // Initialization
    //--------------------------------------------------------------------------------------
    const int screenWidth = 800;
    const int screenHeight = 450;

    InitWindow(screenWidth, screenHeight, "raylib [shaders] example - rounded rectangle");

    // Load the shader
    Shader shader = LoadShader(TextFormat("resources/shaders/glsl%i/base.vs", GLSL_VERSION),
                               TextFormat("resources/shaders/glsl%i/rounded_rectangle.fs", GLSL_VERSION));

    // Create a rounded rectangle
    RoundedRectangle roundedRectangle = CreateRoundedRectangle(
        (Vector4){ 5.0f, 10.0f, 15.0f, 20.0f },     // Corner radius
        20.0f,                                      // Shadow radius
        (Vector2){ 0.0f, -5.0f },                   // Shadow offset
        0.95f,                                      // Shadow scale
        5.0f,                                       // Border thickness
        shader                                      // Shader
    );

    // Update shader uniforms
    UpdateRoundedRectangle(roundedRectangle, shader);

    const Color rectangleColor = BLUE;
    const Color shadowColor = DARKBLUE;
    const Color borderColor = SKYBLUE;

    SetTargetFPS(60);
    //--------------------------------------------------------------------------------------

    // Main game loop
    while (!WindowShouldClose())    // Detect window close button or ESC key
    {
        // Draw
        //----------------------------------------------------------------------------------
        BeginDrawing();

            ClearBackground(RAYWHITE);

            // Draw rectangle box with rounded corners using shader
            Rectangle rec = { 50, 70, 110, 60 };
            DrawRectangleLines((int)rec.x - 20, (int)rec.y - 20, (int)rec.width + 40, (int)rec.height + 40, DARKGRAY);
            DrawText("Rounded rectangle", (int)rec.x - 20, (int)rec.y - 35, 10, DARKGRAY);

            // Flip Y axis to match shader coordinate system
            rec.y = screenHeight - rec.y - rec.height;
            SetShaderValue(shader, roundedRectangle.rectangleLoc, (float[]){ rec.x, rec.y, rec.width, rec.height }, SHADER_UNIFORM_VEC4);

            // Only rectangle color
            SetShaderValue(shader, roundedRectangle.colorLoc, (float[]) { rectangleColor.r/255.0f, rectangleColor.g/255.0f, rectangleColor.b/255.0f, rectangleColor.a/255.0f }, SHADER_UNIFORM_VEC4);
            SetShaderValue(shader, roundedRectangle.shadowColorLoc, (float[]) { 0.0f, 0.0f, 0.0f, 0.0f }, SHADER_UNIFORM_VEC4);
            SetShaderValue(shader, roundedRectangle.borderColorLoc, (float[]) { 0.0f, 0.0f, 0.0f, 0.0f }, SHADER_UNIFORM_VEC4);

            BeginShaderMode(shader);
                DrawRectangle(0, 0, screenWidth, screenHeight, WHITE);
            EndShaderMode();

            // Draw rectangle shadow using shader
            rec = (Rectangle){ 50, 200, 110, 60 };
            DrawRectangleLines((int)rec.x - 20, (int)rec.y - 20, (int)rec.width + 40, (int)rec.height + 40, DARKGRAY);
            DrawText("Rounded rectangle shadow", (int)rec.x - 20, (int)rec.y - 35, 10, DARKGRAY);

            rec.y = screenHeight - rec.y - rec.height;
            SetShaderValue(shader, roundedRectangle.rectangleLoc, (float[]){ rec.x, rec.y, rec.width, rec.height }, SHADER_UNIFORM_VEC4);

            // Only shadow color
            SetShaderValue(shader, roundedRectangle.colorLoc, (float[]) { 0.0f, 0.0f, 0.0f, 0.0f }, SHADER_UNIFORM_VEC4);
            SetShaderValue(shader, roundedRectangle.shadowColorLoc, (float[]) { shadowColor.r/255.0f, shadowColor.g/255.0f, shadowColor.b/255.0f, shadowColor.a/255.0f }, SHADER_UNIFORM_VEC4);
            SetShaderValue(shader, roundedRectangle.borderColorLoc, (float[]) { 0.0f, 0.0f, 0.0f, 0.0f }, SHADER_UNIFORM_VEC4);

            BeginShaderMode(shader);
                DrawRectangle(0, 0, screenWidth, screenHeight, WHITE);
            EndShaderMode();

            // Draw rectangle's border using shader
            rec = (Rectangle){ 50, 330, 110, 60 };
            DrawRectangleLines((int)rec.x - 20, (int)rec.y - 20, (int)rec.width + 40, (int)rec.height + 40, DARKGRAY);
            DrawText("Rounded rectangle border", (int)rec.x - 20, (int)rec.y - 35, 10, DARKGRAY);

            rec.y = screenHeight - rec.y - rec.height;
            SetShaderValue(shader, roundedRectangle.rectangleLoc, (float[]){ rec.x, rec.y, rec.width, rec.height }, SHADER_UNIFORM_VEC4);

            // Only border color
            SetShaderValue(shader, roundedRectangle.colorLoc, (float[]) { 0.0f, 0.0f, 0.0f, 0.0f }, SHADER_UNIFORM_VEC4);
            SetShaderValue(shader, roundedRectangle.shadowColorLoc, (float[]) { 0.0f, 0.0f, 0.0f, 0.0f }, SHADER_UNIFORM_VEC4);
            SetShaderValue(shader, roundedRectangle.borderColorLoc, (float[]) { borderColor.r/255.0f, borderColor.g/255.0f, borderColor.b/255.0f, borderColor.a/255.0f }, SHADER_UNIFORM_VEC4);

            BeginShaderMode(shader);
                DrawRectangle(0, 0, screenWidth, screenHeight, WHITE);
            EndShaderMode();

            // Draw one more rectangle with all three colors
            rec = (Rectangle){ 240, 80, 500, 300 };
            DrawRectangleLines((int)rec.x - 30, (int)rec.y - 30, (int)rec.width + 60, (int)rec.height + 60, DARKGRAY);
            DrawText("Rectangle with all three combined", (int)rec.x - 30, (int)rec.y - 45, 10, DARKGRAY);

            rec.y = screenHeight - rec.y - rec.height;
            SetShaderValue(shader, roundedRectangle.rectangleLoc, (float[]){ rec.x, rec.y, rec.width, rec.height }, SHADER_UNIFORM_VEC4);

            // All three colors
            SetShaderValue(shader, roundedRectangle.colorLoc, (float[]) { rectangleColor.r/255.0f, rectangleColor.g/255.0f, rectangleColor.b/255.0f, rectangleColor.a/255.0f }, SHADER_UNIFORM_VEC4);
            SetShaderValue(shader, roundedRectangle.shadowColorLoc, (float[]) { shadowColor.r/255.0f, shadowColor.g/255.0f, shadowColor.b/255.0f, shadowColor.a/255.0f }, SHADER_UNIFORM_VEC4);
            SetShaderValue(shader, roundedRectangle.borderColorLoc, (float[]) { borderColor.r/255.0f, borderColor.g/255.0f, borderColor.b/255.0f, borderColor.a/255.0f }, SHADER_UNIFORM_VEC4);

            BeginShaderMode(shader);
                DrawRectangle(0, 0, screenWidth, screenHeight, WHITE);
            EndShaderMode();

            DrawText("(c) Rounded rectangle SDF by Iñigo Quilez. MIT License.", screenWidth - 300, screenHeight - 20, 10, BLACK);

        EndDrawing();
        //----------------------------------------------------------------------------------
    }

    // De-Initialization
    //--------------------------------------------------------------------------------------
    UnloadShader(shader); // Unload shader

    CloseWindow();        // Close window and OpenGL context
    //--------------------------------------------------------------------------------------

    return 0;
}

//------------------------------------------------------------------------------------
// Module Functions Definitions
//------------------------------------------------------------------------------------

// Create a rounded rectangle and set uniform locations
RoundedRectangle CreateRoundedRectangle(Vector4 cornerRadius, float shadowRadius, Vector2 shadowOffset, float shadowScale, float borderThickness, Shader shader)
{
    RoundedRectangle rec;
    rec.cornerRadius = cornerRadius;
    rec.shadowRadius = shadowRadius;
    rec.shadowOffset = shadowOffset;
    rec.shadowScale = shadowScale;
    rec.borderThickness = borderThickness;

    // Get shader uniform locations
    rec.rectangleLoc = GetShaderLocation(shader, "rectangle");
    rec.radiusLoc = GetShaderLocation(shader, "radius");
    rec.colorLoc = GetShaderLocation(shader, "color");
    rec.shadowRadiusLoc = GetShaderLocation(shader, "shadowRadius");
    rec.shadowOffsetLoc = GetShaderLocation(shader, "shadowOffset");
    rec.shadowScaleLoc = GetShaderLocation(shader, "shadowScale");
    rec.shadowColorLoc = GetShaderLocation(shader, "shadowColor");
    rec.borderThicknessLoc = GetShaderLocation(shader, "borderThickness");
    rec.borderColorLoc = GetShaderLocation(shader, "borderColor");

    UpdateRoundedRectangle(rec, shader);

    return rec;
}

// Update rounded rectangle uniforms
void UpdateRoundedRectangle(RoundedRectangle rec, Shader shader)
{
    SetShaderValue(shader, rec.radiusLoc, (float[]){ rec.cornerRadius.x, rec.cornerRadius.y, rec.cornerRadius.z, rec.cornerRadius.w }, SHADER_UNIFORM_VEC4);
    SetShaderValue(shader, rec.shadowRadiusLoc, &rec.shadowRadius, SHADER_UNIFORM_FLOAT);
    SetShaderValue(shader, rec.shadowOffsetLoc, (float[]){ rec.shadowOffset.x, rec.shadowOffset.y }, SHADER_UNIFORM_VEC2);
    SetShaderValue(shader, rec.shadowScaleLoc, &rec.shadowScale, SHADER_UNIFORM_FLOAT);
    SetShaderValue(shader, rec.borderThicknessLoc, &rec.borderThickness, SHADER_UNIFORM_FLOAT);
}

From raylib 6.2. The original on GitHub.