directional billboard
There is no browser build of this example yet.
Is it the same as C?
- Desktop:verified The Zig version renders a final frame that is byte-identical to the C example.
- Browser:not checked yet The browser comparison does not cover this example yet.
//! raylib [models] example - directional billboard
//!
//! Zig-API translation of examples/models/models_directional_billboard.c (raylib 6.2).
//! Example licensed under an unmodified zlib/libpng license.
//! Copyright (c) 2025 Robin (@RobinsAviary)
const rl = @import("raylib");
pub fn main() !void {
// Initialization
const screen_width = 800;
const screen_height = 450;
rl.initWindow(screen_width, screen_height, "raylib [models] example - directional billboard");
defer rl.closeWindow(); // Close window and OpenGL context
// Set up the camera
var camera: rl.Camera = .{
.position = .{ .x = 2.0, .y = 1.0, .z = 2.0 }, // Starting position
.target = .{ .x = 0.0, .y = 0.5, .z = 0.0 }, // Target position
.up = .{ .x = 0.0, .y = 1.0, .z = 0.0 }, // Up vector
.fovy = 45.0, // FOV
.projection = .perspective, // Projection type (Standard 3D perspective)
};
// Load billboard texture
const skillbot = try rl.loadTexture("resources/skillbot.png");
defer rl.unloadTexture(skillbot);
// Timer to update animation
var anim_timer: f32 = 0.0;
// Animation frame
var anim: u32 = 0;
rl.setTargetFPS(60);
// Main game loop
while (!rl.windowShouldClose()) { // Detect window close button or ESC key
// Update
rl.updateCamera(&camera, .orbital);
// Update timer with delta time
anim_timer += rl.getFrameTime();
// Update frame index after a certain amount of time (half a second)
if (anim_timer > 0.5) {
anim_timer = 0.0;
anim += 1;
}
// Reset frame index to zero on overflow
if (anim >= 4) anim = 0;
// Find the current direction frame based on the camera position to the billboard object
const angle = rl.math.vector2Angle(.{ .x = 2.0, .y = 0.0 }, .{ .x = camera.position.x, .y = camera.position.z });
var dir = @floor(((angle / rl.pi) * 4.0) + 0.25);
// Correct frame index if angle is negative (dir is integral, so |dir| needs no truncation)
if (dir < 0.0) dir = 8.0 - @abs(dir);
// Draw
rl.beginDrawing();
defer rl.endDrawing();
rl.clearBackground(.ray_white);
{
rl.beginMode3D(camera);
defer rl.endMode3D();
rl.drawGrid(10, 1.0);
// Draw billboard pointing straight up to the sky, rotated relative to the camera and offset from the bottom
const source: rl.Rectangle = .{ .x = 0.0 + (@as(f32, @floatFromInt(anim)) * 24.0), .y = 0.0 + (dir * 24.0), .width = 24.0, .height = 24.0 };
rl.drawBillboardPro(camera, skillbot, source, rl.math.vector3Zero(), .{ .x = 0.0, .y = 1.0, .z = 0.0 }, rl.math.vector2One(), .{ .x = 0.5, .y = 0.0 }, 0, .white);
}
// Render various variables for reference
rl.drawText(rl.textFormat("animation: {d}", .{anim}), 10, 10, 20, .dark_gray);
rl.drawText(rl.textFormat("direction frame: {d:.0}", .{dir}), 10, 40, 20, .dark_gray);
}
}/*******************************************************************************************
*
* raylib [models] example - directional billboard
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by Robin (@RobinsAviary) 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 Robin (@RobinsAviary)
* Killbot art by patvanmackelberg https://opengameart.org/content/killbot-8-directional under CC0
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
#include <stdlib.h>
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - directional billboard");
// Set up the camera
Camera camera = { 0 };
camera.position = (Vector3){ 2.0f, 1.0f, 2.0f }; // Starting position
camera.target = (Vector3){ 0.0f, 0.5f, 0.0f }; // Target position
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Up vector
camera.fovy = 45.0f; // FOV
camera.projection = CAMERA_PERSPECTIVE; // Projection type (Standard 3D perspective)
// Load billboard texture
Texture skillbot = LoadTexture("resources/skillbot.png");
// Timer to update animation
float anim_timer = 0.0f;
// Animation frame
unsigned int anim = 0;
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_ORBITAL);
// Update timer with delta time
anim_timer += GetFrameTime();
// Update frame index after a certain amount of time (half a second)
if (anim_timer > 0.5f)
{
anim_timer = 0.0f;
anim += 1;
}
// Reset frame index to zero on overflow
if (anim >= 4) anim = 0;
// Find the current direction frame based on the camera position to the billboard object
float dir = (float)floor(((Vector2Angle((Vector2){ 2.0f, 0.0f }, (Vector2){ camera.position.x, camera.position.z })/PI)*4.0f) + 0.25f);
// Correct frame index if angle is negative
if (dir < 0.0f)
{
dir = 8.0f - (float)abs((int)dir);
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
DrawGrid(10, 1.0f);
// Draw billboard pointing straight up to the sky, rotated relative to the camera and offset from the bottom
DrawBillboardPro(camera, skillbot, (Rectangle){ 0.0f + (anim*24.0f), 0.0f + (dir*24.0f), 24.0f, 24.0f }, Vector3Zero(), (Vector3){ 0.0f, 1.0f, 0.0f }, Vector2One(), (Vector2){ 0.5f, 0.0f }, 0, WHITE);
EndMode3D();
// Render various variables for reference
DrawText(TextFormat("animation: %d", anim), 10, 10, 20, DARKGRAY);
DrawText(TextFormat("direction frame: %.0f", dir), 10, 40, 20, DARKGRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
// Unload billboard texture
UnloadTexture(skillbot);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}From raylib 6.2. The original on GitHub.