textured cube
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 - textured cube
//!
//! Zig-API translation of examples/models/models_textured_cube.c (raylib 6.2).
//! Example licensed under an unmodified zlib/libpng license.
//! Copyright (c) 2022-2025 Ramon Santamaria (@raysan5)
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 - textured cube");
defer rl.closeWindow(); // Close window and OpenGL context
// Define the camera to look into our 3d world
const camera: rl.Camera = .{
.position = .{ .x = 0.0, .y = 10.0, .z = 10.0 },
.target = .{ .x = 0.0, .y = 0.0, .z = 0.0 },
.up = .{ .x = 0.0, .y = 1.0, .z = 0.0 },
.fovy = 45.0,
.projection = .perspective,
};
// Load texture to be applied to the cubes sides
const texture = try rl.loadTexture("resources/cubicmap_atlas.png");
defer rl.unloadTexture(texture); // Unload texture
const tex_width: f32 = @floatFromInt(texture.width);
const tex_height: f32 = @floatFromInt(texture.height);
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
// Main game loop
while (!rl.windowShouldClose()) { // Detect window close button or ESC key
// Draw
rl.beginDrawing();
defer rl.endDrawing();
rl.clearBackground(.ray_white);
{
rl.beginMode3D(camera);
defer rl.endMode3D();
// Draw cube with an applied texture
drawCubeTexture(texture, .{ .x = -2.0, .y = 2.0, .z = 0.0 }, 2.0, 4.0, 2.0, .white);
// Draw cube with an applied texture, but only a defined rectangle piece of the texture
drawCubeTextureRec(
texture,
.{ .x = 0.0, .y = tex_height / 2.0, .width = tex_width / 2.0, .height = tex_height / 2.0 },
.{ .x = 2.0, .y = 1.0, .z = 0.0 },
2.0,
2.0,
2.0,
.white,
);
rl.drawGrid(10, 1.0); // Draw a grid
}
rl.drawFPS(10, 10);
}
}
/// Draw cube textured
/// NOTE: Cube position is the center position
fn drawCubeTexture(texture: rl.Texture2D, position: rl.Vector3, width: f32, height: f32, length: f32, color: rl.Color) void {
// The whole texture: same as drawCubeTextureRec() with uv rect (0, 0)-(1, 1)
drawCubeUv(texture, .{ .u0 = 0.0, .v0 = 0.0, .u1 = 1.0, .v1 = 1.0 }, position, width, height, length, color, .flipped);
}
/// Draw cube with texture piece applied to all faces
fn drawCubeTextureRec(texture: rl.Texture2D, source: rl.Rectangle, position: rl.Vector3, width: f32, height: f32, length: f32, color: rl.Color) void {
const tex_width: f32 = @floatFromInt(texture.width);
const tex_height: f32 = @floatFromInt(texture.height);
// We calculate the normalized texture coordinates for the desired texture-source-rectangle
// It means converting from (tex.width, tex.height) coordinates to [0.0, 1.0] equivalent
const uv: Uv = .{
.u0 = source.x / tex_width,
.v0 = source.y / tex_height,
.u1 = (source.x + source.width) / tex_width,
.v1 = (source.y + source.height) / tex_height,
};
drawCubeUv(texture, uv, position, width, height, length, color, .upright);
}
/// Normalized texture rectangle: (u0, v0) top-left, (u1, v1) bottom-right.
const Uv = struct { u0: f32, v0: f32, u1: f32, v1: f32 };
/// drawCubeTexture() maps the texture bottom-up (v0 at the bottom edge of each
/// face), drawCubeTextureRec() top-down.
const VOrientation = enum { flipped, upright };
fn drawCubeUv(texture: rl.Texture2D, uv: Uv, position: rl.Vector3, width: f32, height: f32, length: f32, color: rl.Color, orientation: VOrientation) void {
const x = position.x;
const y = position.y;
const z = position.z;
// Bottom/top texture rows of every face
const vb, const vt = switch (orientation) {
.flipped => .{ uv.v0, uv.v1 },
.upright => .{ uv.v1, uv.v0 },
};
const l = uv.u0;
const r = uv.u1;
// Set desired texture to be enabled while drawing following vertex data
rl.gl.setTexture(texture.id);
defer rl.gl.setTexture(0);
rl.gl.begin(rl.gl.quads);
defer rl.gl.end();
rl.gl.color4ub(color.r, color.g, color.b, color.a);
// Front Face
rl.gl.normal3f(0.0, 0.0, 1.0); // Normal Pointing Towards Viewer
vertex(l, vb, x - width / 2, y - height / 2, z + length / 2); // Bottom Left Of The Texture and Quad
vertex(r, vb, x + width / 2, y - height / 2, z + length / 2); // Bottom Right Of The Texture and Quad
vertex(r, vt, x + width / 2, y + height / 2, z + length / 2); // Top Right Of The Texture and Quad
vertex(l, vt, x - width / 2, y + height / 2, z + length / 2); // Top Left Of The Texture and Quad
// Back Face
rl.gl.normal3f(0.0, 0.0, -1.0); // Normal Pointing Away From Viewer
vertex(r, vb, x - width / 2, y - height / 2, z - length / 2); // Bottom Right Of The Texture and Quad
vertex(r, vt, x - width / 2, y + height / 2, z - length / 2); // Top Right Of The Texture and Quad
vertex(l, vt, x + width / 2, y + height / 2, z - length / 2); // Top Left Of The Texture and Quad
vertex(l, vb, x + width / 2, y - height / 2, z - length / 2); // Bottom Left Of The Texture and Quad
// Top Face
rl.gl.normal3f(0.0, 1.0, 0.0); // Normal Pointing Up
vertex(l, vt, x - width / 2, y + height / 2, z - length / 2); // Top Left Of The Texture and Quad
vertex(l, vb, x - width / 2, y + height / 2, z + length / 2); // Bottom Left Of The Texture and Quad
vertex(r, vb, x + width / 2, y + height / 2, z + length / 2); // Bottom Right Of The Texture and Quad
vertex(r, vt, x + width / 2, y + height / 2, z - length / 2); // Top Right Of The Texture and Quad
// Bottom Face
rl.gl.normal3f(0.0, -1.0, 0.0); // Normal Pointing Down
vertex(r, vt, x - width / 2, y - height / 2, z - length / 2); // Top Right Of The Texture and Quad
vertex(l, vt, x + width / 2, y - height / 2, z - length / 2); // Top Left Of The Texture and Quad
vertex(l, vb, x + width / 2, y - height / 2, z + length / 2); // Bottom Left Of The Texture and Quad
vertex(r, vb, x - width / 2, y - height / 2, z + length / 2); // Bottom Right Of The Texture and Quad
// Right face
rl.gl.normal3f(1.0, 0.0, 0.0); // Normal Pointing Right
vertex(r, vb, x + width / 2, y - height / 2, z - length / 2); // Bottom Right Of The Texture and Quad
vertex(r, vt, x + width / 2, y + height / 2, z - length / 2); // Top Right Of The Texture and Quad
vertex(l, vt, x + width / 2, y + height / 2, z + length / 2); // Top Left Of The Texture and Quad
vertex(l, vb, x + width / 2, y - height / 2, z + length / 2); // Bottom Left Of The Texture and Quad
// Left Face
rl.gl.normal3f(-1.0, 0.0, 0.0); // Normal Pointing Left
vertex(l, vb, x - width / 2, y - height / 2, z - length / 2); // Bottom Left Of The Texture and Quad
vertex(r, vb, x - width / 2, y - height / 2, z + length / 2); // Bottom Right Of The Texture and Quad
vertex(r, vt, x - width / 2, y + height / 2, z + length / 2); // Top Right Of The Texture and Quad
vertex(l, vt, x - width / 2, y + height / 2, z - length / 2); // Top Left Of The Texture and Quad
}
fn vertex(u: f32, v: f32, x: f32, y: f32, z: f32) void {
rl.gl.texCoord2f(u, v);
rl.gl.vertex3f(x, y, z);
}/*******************************************************************************************
*
* raylib [models] example - textured cube
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 4.5, last time updated with raylib 4.5
*
* 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) 2022-2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#include "rlgl.h" // Required to define vertex data (immediate-mode style)
//------------------------------------------------------------------------------------
// Custom Functions Declaration
//------------------------------------------------------------------------------------
void DrawCubeTexture(Texture2D texture, Vector3 position, float width, float height, float length, Color color); // Draw cube textured
void DrawCubeTextureRec(Texture2D texture, Rectangle source, Vector3 position, float width, float height, float length, Color color); // Draw cube with a region of a texture
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - textured cube");
// Define the camera to look into our 3d world
Camera camera = { 0 };
camera.position = (Vector3){ 0.0f, 10.0f, 10.0f };
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f };
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };
camera.fovy = 45.0f;
camera.projection = CAMERA_PERSPECTIVE;
// Load texture to be applied to the cubes sides
Texture2D texture = LoadTexture("resources/cubicmap_atlas.png");
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
// TODO: Update your variables here
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
// Draw cube with an applied texture
DrawCubeTexture(texture, (Vector3){ -2.0f, 2.0f, 0.0f }, 2.0f, 4.0f, 2.0f, WHITE);
// Draw cube with an applied texture, but only a defined rectangle piece of the texture
DrawCubeTextureRec(texture, (Rectangle){ 0.0f, texture.height/2.0f, texture.width/2.0f, texture.height/2.0f },
(Vector3){ 2.0f, 1.0f, 0.0f }, 2.0f, 2.0f, 2.0f, WHITE);
DrawGrid(10, 1.0f); // Draw a grid
EndMode3D();
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadTexture(texture); // Unload texture
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//------------------------------------------------------------------------------------
// Custom Functions Definition
//------------------------------------------------------------------------------------
// Draw cube textured
// NOTE: Cube position is the center position
void DrawCubeTexture(Texture2D texture, Vector3 position, float width, float height, float length, Color color)
{
float x = position.x;
float y = position.y;
float z = position.z;
// Set desired texture to be enabled while drawing following vertex data
rlSetTexture(texture.id);
// Vertex data transformation can be defined with the commented lines,
// but in this example we calculate the transformed vertex data directly when calling rlVertex3f()
//rlPushMatrix();
// NOTE: Transformation is applied in inverse order (scale -> rotate -> translate)
//rlTranslatef(2.0f, 0.0f, 0.0f);
//rlRotatef(45, 0, 1, 0);
//rlScalef(2.0f, 2.0f, 2.0f);
rlBegin(RL_QUADS);
rlColor4ub(color.r, color.g, color.b, color.a);
// Front Face
rlNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Left Of The Texture and Quad
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Right Of The Texture and Quad
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + width/2, y + height/2, z + length/2); // Top Right Of The Texture and Quad
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - width/2, y + height/2, z + length/2); // Top Left Of The Texture and Quad
// Back Face
rlNormal3f(0.0f, 0.0f, - 1.0f); // Normal Pointing Away From Viewer
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom Right Of The Texture and Quad
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Right Of The Texture and Quad
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Left Of The Texture and Quad
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom Left Of The Texture and Quad
// Top Face
rlNormal3f(0.0f, 1.0f, 0.0f); // Normal Pointing Up
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Left Of The Texture and Quad
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - width/2, y + height/2, z + length/2); // Bottom Left Of The Texture and Quad
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + width/2, y + height/2, z + length/2); // Bottom Right Of The Texture and Quad
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Right Of The Texture and Quad
// Bottom Face
rlNormal3f(0.0f, - 1.0f, 0.0f); // Normal Pointing Down
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - width/2, y - height/2, z - length/2); // Top Right Of The Texture and Quad
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + width/2, y - height/2, z - length/2); // Top Left Of The Texture and Quad
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Left Of The Texture and Quad
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Right Of The Texture and Quad
// Right face
rlNormal3f(1.0f, 0.0f, 0.0f); // Normal Pointing Right
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom Right Of The Texture and Quad
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Right Of The Texture and Quad
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + width/2, y + height/2, z + length/2); // Top Left Of The Texture and Quad
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Left Of The Texture and Quad
// Left Face
rlNormal3f( - 1.0f, 0.0f, 0.0f); // Normal Pointing Left
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom Left Of The Texture and Quad
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Right Of The Texture and Quad
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - width/2, y + height/2, z + length/2); // Top Right Of The Texture and Quad
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Left Of The Texture and Quad
rlEnd();
//rlPopMatrix();
rlSetTexture(0);
}
// Draw cube with texture piece applied to all faces
void DrawCubeTextureRec(Texture2D texture, Rectangle source, Vector3 position, float width, float height, float length, Color color)
{
float x = position.x;
float y = position.y;
float z = position.z;
float texWidth = (float)texture.width;
float texHeight = (float)texture.height;
// Set desired texture to be enabled while drawing following vertex data
rlSetTexture(texture.id);
// We calculate the normalized texture coordinates for the desired texture-source-rectangle
// It means converting from (tex.width, tex.height) coordinates to [0.0f, 1.0f] equivalent
rlBegin(RL_QUADS);
rlColor4ub(color.r, color.g, color.b, color.a);
// Front face
rlNormal3f(0.0f, 0.0f, 1.0f);
rlTexCoord2f(source.x/texWidth, (source.y + source.height)/texHeight);
rlVertex3f(x - width/2, y - height/2, z + length/2);
rlTexCoord2f((source.x + source.width)/texWidth, (source.y + source.height)/texHeight);
rlVertex3f(x + width/2, y - height/2, z + length/2);
rlTexCoord2f((source.x + source.width)/texWidth, source.y/texHeight);
rlVertex3f(x + width/2, y + height/2, z + length/2);
rlTexCoord2f(source.x/texWidth, source.y/texHeight);
rlVertex3f(x - width/2, y + height/2, z + length/2);
// Back face
rlNormal3f(0.0f, 0.0f, - 1.0f);
rlTexCoord2f((source.x + source.width)/texWidth, (source.y + source.height)/texHeight);
rlVertex3f(x - width/2, y - height/2, z - length/2);
rlTexCoord2f((source.x + source.width)/texWidth, source.y/texHeight);
rlVertex3f(x - width/2, y + height/2, z - length/2);
rlTexCoord2f(source.x/texWidth, source.y/texHeight);
rlVertex3f(x + width/2, y + height/2, z - length/2);
rlTexCoord2f(source.x/texWidth, (source.y + source.height)/texHeight);
rlVertex3f(x + width/2, y - height/2, z - length/2);
// Top face
rlNormal3f(0.0f, 1.0f, 0.0f);
rlTexCoord2f(source.x/texWidth, source.y/texHeight);
rlVertex3f(x - width/2, y + height/2, z - length/2);
rlTexCoord2f(source.x/texWidth, (source.y + source.height)/texHeight);
rlVertex3f(x - width/2, y + height/2, z + length/2);
rlTexCoord2f((source.x + source.width)/texWidth, (source.y + source.height)/texHeight);
rlVertex3f(x + width/2, y + height/2, z + length/2);
rlTexCoord2f((source.x + source.width)/texWidth, source.y/texHeight);
rlVertex3f(x + width/2, y + height/2, z - length/2);
// Bottom face
rlNormal3f(0.0f, - 1.0f, 0.0f);
rlTexCoord2f((source.x + source.width)/texWidth, source.y/texHeight);
rlVertex3f(x - width/2, y - height/2, z - length/2);
rlTexCoord2f(source.x/texWidth, source.y/texHeight);
rlVertex3f(x + width/2, y - height/2, z - length/2);
rlTexCoord2f(source.x/texWidth, (source.y + source.height)/texHeight);
rlVertex3f(x + width/2, y - height/2, z + length/2);
rlTexCoord2f((source.x + source.width)/texWidth, (source.y + source.height)/texHeight);
rlVertex3f(x - width/2, y - height/2, z + length/2);
// Right face
rlNormal3f(1.0f, 0.0f, 0.0f);
rlTexCoord2f((source.x + source.width)/texWidth, (source.y + source.height)/texHeight);
rlVertex3f(x + width/2, y - height/2, z - length/2);
rlTexCoord2f((source.x + source.width)/texWidth, source.y/texHeight);
rlVertex3f(x + width/2, y + height/2, z - length/2);
rlTexCoord2f(source.x/texWidth, source.y/texHeight);
rlVertex3f(x + width/2, y + height/2, z + length/2);
rlTexCoord2f(source.x/texWidth, (source.y + source.height)/texHeight);
rlVertex3f(x + width/2, y - height/2, z + length/2);
// Left face
rlNormal3f( - 1.0f, 0.0f, 0.0f);
rlTexCoord2f(source.x/texWidth, (source.y + source.height)/texHeight);
rlVertex3f(x - width/2, y - height/2, z - length/2);
rlTexCoord2f((source.x + source.width)/texWidth, (source.y + source.height)/texHeight);
rlVertex3f(x - width/2, y - height/2, z + length/2);
rlTexCoord2f((source.x + source.width)/texWidth, source.y/texHeight);
rlVertex3f(x - width/2, y + height/2, z + length/2);
rlTexCoord2f(source.x/texWidth, source.y/texHeight);
rlVertex3f(x - width/2, y + height/2, z - length/2);
rlEnd();
rlSetTexture(0);
}From raylib 6.2. The original on GitHub.