This guide explains how to integrate raylib-backends into an application that
already builds raylib.
Put raylib and raylib-backends in separate directories:
deps/
raylib/
raylib-backends/
Do not copy raylib/src into raylib-backends. Do not apply checked-in patches
to raylib/src. The consumer project decides which raylib revision to use.
set(RAYLIB_DIR "${CMAKE_SOURCE_DIR}/deps/raylib")
set(RAYLIB_BACKENDS_DIR "${CMAKE_SOURCE_DIR}/deps/raylib-backends")
include("${RAYLIB_BACKENDS_DIR}/cmake/RaylibBackend.cmake")For a plain Vulkan build:
add_library(raylib STATIC
"${RAYLIB_DIR}/src/rcore.c"
"${RAYLIB_DIR}/src/rshapes.c"
"${RAYLIB_DIR}/src/rtextures.c"
"${RAYLIB_DIR}/src/rtext.c"
"${RAYLIB_DIR}/src/rmodels.c"
"${RAYLIB_DIR}/src/raudio.c"
)
target_include_directories(raylib PUBLIC
"${RAYLIB_DIR}/src"
"${RAYLIB_DIR}/src/platforms"
)For Metal or Android SurfaceView, generate the rcore source first and use the
generated path in the target.
Metal:
raylib_backend_prepare_rcore_overlay(
OUT_VAR RAYLIB_RCORE_SRC
RAYLIB_DIR "${RAYLIB_DIR}"
RAYLIB_BACKENDS_DIR "${RAYLIB_BACKENDS_DIR}"
)Android SurfaceView:
raylib_backend_prepare_android_surface_overlay(
OUT_VAR RAYLIB_RCORE_SRC
RAYLIB_DIR "${RAYLIB_DIR}"
RAYLIB_BACKENDS_DIR "${RAYLIB_BACKENDS_DIR}"
)Then use:
add_library(raylib STATIC
"${RAYLIB_RCORE_SRC}"
"${RAYLIB_DIR}/src/rshapes.c"
"${RAYLIB_DIR}/src/rtextures.c"
"${RAYLIB_DIR}/src/rtext.c"
"${RAYLIB_DIR}/src/rmodels.c"
"${RAYLIB_DIR}/src/raudio.c"
)raylib_backend_attach(
TARGET raylib
BACKEND VULKAN
RAYLIB_BACKENDS_DIR "${RAYLIB_BACKENDS_DIR}"
)or:
raylib_backend_attach(
TARGET raylib
BACKEND METAL
RAYLIB_BACKENDS_DIR "${RAYLIB_BACKENDS_DIR}"
)The helper rejects conflicting backend selections on the same target.
add_executable(my_app main.c)
target_link_libraries(my_app PRIVATE raylib)Link other platform libraries required by your application as usual.
PLATFORM_ANDROID_SURFACE is for apps that own the Android Activity and pass
an externally-owned ANativeWindow into raylib. The host calls the functions in
backends/rlvk/platforms/rcore_android_surface.h to provide the window, input,
surface lifecycle, and multi-surface control.
Use the Android example as the reference layout:
examples/android/
app/src/main/
app/src/main/cpp/
Required Gradle properties:
RAYLIB_DIR: upstream raylib checkoutRAYLIB_BACKENDS_DIR: this packageRAYGPU_DIR: glslang source used by the Vulkan backend
Build from the package root:
cmake -S . -B build -DRAYLIB_DIR=/absolute/path/to/raylib
cmake --build buildThe desktop example source is examples/clear_cube.c. The CMake example
selects Metal on macOS and Vulkan on Linux.
raylib_backend_attach() adds target properties only:
- backend include directories
- backend source files
- backend compile definitions
- backend link libraries
Overlay helpers create generated .c files under the CMake build directory.
They do not write to your raylib checkout.
- Update the consumer-owned raylib checkout.
- Reconfigure your build from a clean CMake build directory.
- Build the desktop or Android cube example for the backend you use.
- If overlay generation fails, update the helper pattern in
cmake/RaylibBackend.cmakeinstead of patchingraylib/src.
rlwg is a browser WebGPU backend (Emscripten / emdawnwebgpu) that re-implements
the rlgl API and emulates OpenGL 3.3 1:1, exactly like rlvk/rlmt. It is a fresh
implementation on the WebGPU C API (webgpu/webgpu.h) - it does not use raygpu,
and so does not inherit raygpu's shader caveats.
Files: backends/rlwg/rlwg.h (+ rlwg_impl.h, rlwg_impl2.h), the default shaders
in backends/rlwg/rlwg_default_wgsl.h, the wrapper backends/rlwg/rlgl.h, and the
web platform backends/rlwg/platforms/rcore_web.c.
- Fixed attribute locations: 0 position, 1 texcoord, 2 normal, 3 color, 4 tangent, 5 texcoord2.
- The genuine rlgl path: raw model-space vertices upload and the shader transforms by
the
mvpuniform (no CPU pre-transform), so stock raylib shaders behave as on GL. - Loose GL uniforms are packed into uniform buffers; the C mirror matches the default
shader's byte layout so
rlSetUniform/rlSetUniformMatrixwrite by offset. - Two unavoidable WebGPU deviations, both invisible to rlgl callers:
- clip-space z
[-1,1] -> [0,1]is remapped in the default vertex shader; - matrices upload column-major (raylib's
Matrixstruct memory order is the transpose, so they are reordered likeMatrixToFloatbefore upload).
- clip-space z
Browser WebGPU accepts WGSL only (no SPIR-V). Pass WGSL to LoadShader/
rlLoadShaderProgram (a single source string holding vs_main + fs_main).
GL 3.3 GLSL must be translated offline (e.g. glslang -> SPIR-V -> Tint -> WGSL); no
shader compiler is bundled into the WASM payload.
emcmake cmake -S . -B build-web -DRAYLIB_DIR=/path/to/raylib -DCMAKE_BUILD_TYPE=Release
cmake --build build-web -j
# serve build-web/examples and open clear_cube_webgpu.html in a WebGPU browser
python3 -m http.server --directory build-web/examples
Attach to your own raylib target with raylib_backend_attach(TARGET raylib BACKEND WEBGPU) under the Emscripten toolchain. Link flags pulled in: --use-port=emdawnwebgpu,
-sASYNCIFY, -sALLOW_MEMORY_GROWTH=1.
- Immediate-mode batch path (shapes, text, DrawCube/DrawGrid via batch) is complete.
- Generic mesh VAO draws (
rlDrawVertexArray*), cubemaps, mipmap generation, pixel readback, and compute/SSBO are stubbed pending follow-up.
- Vulkan, Metal, and WebGPU (browser) are the active backends.
- The examples are smoke tests, not full raylib feature coverage.