Skip to content
github-actions[bot] edited this page Sep 1, 2026 · 2 revisions

Tutorial 08 — 3D

Copyright (c) 2024-2026 Jack Waechter. MIT licensed.

3D is an optional pass on top of the 2D renderer. World space is right-handed, Y-up. Call it after AP_Clear and before GUI / HUD 2D.

AP_DrawCube, AP_DrawGrid3D, and friends are 3D helpers, not AP_Render* aliases.

Camera and a cube

AP_SetDrawColor(0.08f, 0.09f, 0.12f, 1.0f);
AP_Clear();

AP_Camera cam = AP_CameraPerspective(
    AP_V3(0.0f, 4.0f, 8.0f),
    AP_V3(0.0f, 0.0f, 0.0f),
    50.0f);

AP_Begin3D(&cam);
AP_AddLight(AP_LightPoint(AP_V3(2.0f, 3.0f, 1.0f),
                          AP_C4(1.0f, 0.85f, 0.6f, 1.0f), 2.0f, 12.0f));
AP_SetAmbientLight(AP_C4(0.12f, 0.13f, 0.16f, 1.0f));

AP_DrawGrid3D(10.0f, 10, AP_C4(0.35f, 0.38f, 0.42f, 1.0f));
AP_DrawCube(AP_V3(0.0f, 0.5f, 0.0f), AP_V3(1.0f, 1.0f, 1.0f),
            AP_C4(0.9f, 0.4f, 0.2f, 1.0f));
AP_End3D();

AP_Present();

AP_CameraOrtho is the orthographic variant (fov_degrees == 0, ortho_size is vertical world size).

Lights

Up to AP_3D_LIGHT_MAX (16). Mix directional, point, spot, ambient.

AP_ClearLights();
AP_AddLight(AP_LightDirectional(AP_V3(0.4f, 1.0f, 0.3f),
                                AP_C4(1, 1, 1, 1), 0.8f));
AP_AddLight(AP_LightPoint(AP_V3(2.0f, 2.0f, 0.0f),
                          AP_C4(1.0f, 0.5f, 0.2f, 1.0f), 2.0f, 8.0f));

AP_Set3DLight(direction, color, ambient) is a one-liner: one directional plus scene ambient.

Directional direction points toward the scene (light travels along -direction).

Meshes

AP_Mesh *sphere = AP_CreateMeshSphere(0.5f, 24, 16);
AP_Mesh *plane = AP_CreateMeshPlane(8.0f, 8.0f);

AP_Begin3D(&cam);
AP_DrawMesh(plane);
AP_DrawMeshEx(sphere, NULL, AP_C4(0.2f, 0.7f, 0.9f, 1.0f));
AP_End3D();

AP_DestroyMesh(sphere);
AP_DestroyMesh(plane);

AP_Set3DModel / AP_Reset3DModel apply a 4×4 transform from AP2_Math.h. AP_Set3DTexture samples a 2D texture on the mesh.

Orbit camera sketch

float yaw = 0.4f;
float dist = 8.0f;

/* after pump */
if (AP_IsMouseDown(AP_MOUSE_RIGHT)) {
  yaw += (float)AP_GetMouseDeltaX() * 0.01f;
}
dist = AP_Clampf(dist - (float)AP_GetMouseDeltaY() * 0.02f, 3.0f, 20.0f);

AP_Vec3 eye = AP_V3(sinf(yaw) * dist, 4.0f, cosf(yaw) * dist);
AP_Camera cam = AP_CameraPerspective(eye, AP_V3(0, 0, 0), 50.0f);

Mixing 2D HUD

After AP_End3D(), draw HUD with AP_FillRect / AP_DrawText as usual. GUI panels also go after AP_End3D().

Exclude

#define AP2_NO_3D
#include <AP2/AP2.h>

Next

Shaders and post · Advanced: a PBR product scene

Clone this wiki locally