477 Commits

Author SHA1 Message Date
a043255aa7 [examples] models_animation_blending: avoid crash when animations fail to load (#6234)
If resources/models/gltf/robot.glb can't be found (e.g. the example is
run from another working directory), LoadModelAnimations() returns NULL
with animCount = 0 and the example indexed anims[] in the update loop
and in the timeline drawing, crashing. Skip both when no animations
were loaded, so it just logs the usual load warnings.

Reported in #5664.
2026-10-08 15:33:10 +02:00
8c23ce44a0 [rcore][win32] Clean up window state in CloseWindow() (#6233) 2026-10-08 15:32:37 +02:00
48aaf6e2df [rcore][win32] Allow SetWindowSize() to change only the width or height (#6232) 2026-10-08 15:30:41 +02:00
0ed3570469 [raymath] Fix QuaternionFromVector3ToVector3() returning a zero quaternion for opposite vectors (#6230) 2026-10-08 15:26:36 +02:00
2dee47282a [raymath] Fix MatrixDecompose() reading rows instead of columns (#6225) 2026-10-07 13:13:42 +02:00
607a659363 [rcore][win32] Support MSAA (#6227) 2026-10-07 07:46:34 +02:00
040a4bafa9 [CHANGELOG] Fix typos in 6.2 release notes (#6228) 2026-10-07 07:44:20 +02:00
8571d445e9 [rtextures] Fix ImageDrawImageEx() blending on transparent destinations (#6224) 2026-10-06 20:55:35 +02:00
Ray
4722c9fa58 Minor tweaks 2026-10-06 18:35:06 +02:00
91d50e2938 [rcore][win32] Fix WGL pixel format not being applied (#6219)
* [rcore][win32] Fix WGL pixel format not being applied

* Specify Stencil Bits In Fallback Pixel Format
2026-10-06 08:22:59 +02:00
92f1f3d5d5 [rcore][web] Avoid glfwGetProcAddress() to reduce code size (#6220)
* [rcore][web] Avoid glfwGetProcAddress() to reduce code size

* [build][cmake] Remove unneeded GL_ENABLE_GET_PROC_ADDRESS flag
2026-10-06 08:20:40 +02:00
Ray
f0736f6fb5 GLFW: Boundaries check #6222 2026-10-06 07:49:07 +02:00
Ray
e18de07224 Update rcore_desktop_win32.c 2026-10-05 10:19:16 +02:00
Ray
3c1ab87ae1 Update Makefile 2026-10-05 10:19:08 +02:00
Ray
e8b23bfbe4 Minor tweaks 2026-10-05 09:39:02 +02:00
e5c0709fa2 [Examples] Clarify Camera2d.offset and how it works with High DPI scale mode (#6203)
* rlparser: update raylib_api.* by CI

* Notate that the offset in Camera2d is in pixels space (unscaled by DPI)
Update all the examples that use Camera2d.offset so that they are DPI aware if the user enables DPI scaling.

* rlparser: update raylib_api.* by CI

* remove DPI flag

* remove gltf tests that should not have been part of this PR

* formatting

* formatting

* formatting

* more formatting

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-10-05 09:29:59 +02:00
30fa673ef2 [build][Zig] 0.17 migration (#5951)
* Bump zemscripten to branch suporting latest zig 0.17

* zemscripten changes for build.zig

* general zig 0.17 changes for build.zig

- update calls to `buildDir` and `findProgram` to their new
interfaces/calling sites.
- fix issue where you can't import zon anymore as slice (?)

* Update minimum zig version

* Remove redundant emsdk activations

Examples depend on raylib anyway, and if using emsdk, it will be
activated already.  This activation was causing an error in zig
nightly, so the change here.

* better `getInstallPath` alternative

* Remove example install -> emcc dependency in graph

* Fix emrun path

* Fix file output issue

* Bump zig to latest nightly

* Get emrun step to work

* Remove zemscripten dependency and consolidate with emsdk struct

Bump zig to 0.17.0

Clean up zemscripten struct

Consolidate emscripten-related structs

* Less breaking changes, keep old name, bring back pub fields

* [build][Zig] Fix missing include path and make emsdk a lazy dependency

* [build][Zig] Replace deprecated lazyDependency with the new dependencyLazy

---------

Co-authored-by: Jairo Correa <jairo@omnidoki.com>
2026-10-04 19:08:17 +02:00
5c9e83e642 [rcore][SDL] Accumulate relative mouse motion per frame (#6215)
Co-authored-by: snowyukitty <270071858+snowyukitty@users.noreply.github.com>
2026-10-04 19:01:54 +02:00
791dd6d627 [rtext] Check for empty strings in TextToPascal and TextToCamel (#6213)
* [rtext] Check for empty strings in TextToPascal/TextToCamel

* [rtext] Add parentheses to conditions
2026-10-04 19:00:53 +02:00
a9e3027ebc [rcore][win32] Implement IsKeyPressedRepeat (#6218) 2026-10-04 18:55:27 +02:00
0e8385c890 [examples][textures_image_processing] Fix up arrow wraparound logic (#6217) 2026-10-04 16:54:33 +02:00
98ff2c33fe [build] Avoid _GNU_SOURCE on Linux to keep the library linkable with older glibc (#6214)
On glibc >= 2.38, _GNU_SOURCE implies _ISOC23_SOURCE, which redirects
sscanf(), strtol(), strtoul()... to __isoc23_*() symbols regardless of
-std=c99. Libraries built on a recent distro (like the release builds,
made on Ubuntu 24.04) then fail to link on systems with older glibc:

  undefined reference to `__isoc23_sscanf'
  undefined reference to `__isoc23_strtol'

- Makefile, build.zig: use _DEFAULT_SOURCE instead of _GNU_SOURCE for
  Linux desktop/DRM targets (other targets are unchanged)
- rcore.c: remove the _GNU_SOURCE define, it came after the first libc
  include so it had no effect
- rglfw.c: GLFW needs _GNU_SOURCE (ppoll(), mkostemp(), pipe2()), so
  keep it, but disable glibc's C23 strtol/scanf redirection once
  <features.h> has been processed (__GLIBC_USE_C2X_STRTOL on glibc
  2.38-2.39, __GLIBC_USE_C23_STRTOL on glibc >= 2.40)

Fixes #6205
2026-10-04 13:55:37 +02:00
a2ee68ea46 [rcore] Make FileText*() error handling consistent with Text*() helpers (#6210) 2026-10-03 22:37:01 +02:00
d8ddc8a0a6 [rmodels] UpdateModelAnimation(), compute bone normal matrices once per bone instead of per vertex (#6191)
* [rmodels] `UpdateModelAnimation()`, compute bone normal matrices once per bone instead of per vertex

* [rmodels] use a static buffer for bone normal matrices
2026-10-03 13:42:37 +02:00
8341321d1a [rcore][win32] Add missing break in WndProc switch statement (#6209) 2026-10-03 10:30:43 +02:00
51d713d54d [vox_loader] Prevent memory leak when loading voxel models (#6208) 2026-10-03 10:29:58 +02:00
3ff30034de [examples] Release mesh instancing resources on exit (#6207)
Co-authored-by: Hugohong258 <282228220+Hugohong258@users.noreply.github.com>
2026-10-03 10:26:53 +02:00
012e274ae8 [examples][text_codepoints_loading] Fix out of bounds error in CodepointRemoveDuplicates (#6206) 2026-10-02 18:02:24 +02:00
987a0e54c7 [examples][core_delta_time] Convert GetFrameTime() to milliseconds before printing (#6201) 2026-10-02 00:14:13 +02:00
ab23bd388e [rtext] Fix BDF glyph offsets (#6200)
LoadFontDataBDF() computed offsetX as charBBxoff0 + fontBByoff0, adding the
font bounding box's Y offset to a horizontal position, and offsetY as
fontBBh - (charBBh + charBByoff0 + fontBByoff0 + fontAscent). Every glyph
was drawn shifted, by an amount that depends on the font (4 px left and
up for Spleen 8x16, 5 px left and 3 px down for Helvetica 12), so text was
clipped at the top or left.

A glyph's BBX offsets are relative to the pen position on the baseline,
and the baseline is FONT_ASCENT below the top of the line, so
offsetX = charBBxoff0 and offsetY = fontAscent - (charBBh + charBByoff0).
FONT_ASCENT defaults to the top of the font bounding box when the font
doesn't define it.
2026-10-02 00:13:27 +02:00
38dad693fe [rmodels] Fix LoadOBJ() reading past vertex data on out-of-range face indices (#6199)
Face indices come straight from the file. Positions were read without any
bounds check, and texcoord/normal indices were only checked for >= 0, so
a face referencing a missing vertex, texcoord or normal (or a relative
index that resolves below zero) read outside the attribute arrays.

Skip out-of-range indices, keeping the zeroed position and texcoord and
the default normal, as already done for missing texcoords and normals.
2026-10-01 10:10:23 +02:00
Ray
d2d6fe6ef9 Update rtext.c 2026-09-30 22:41:55 +02:00
47dea9b452 [rtext] Fix BDF loading writing glyphs through a NULL-based pointer (#6198)
LoadFontDataBDF() used to track the glyph being filled in a separate
charGlyphInfo pointer. Since that pointer was folded into `glyphs`, the
loader resets the glyph array itself to NULL at every STARTCHAR and
BITMAP line, then computes the current glyph as &glyphs[index] from NULL.
Any BDF font with a glyph past the first requested codepoint crashes, and
the glyph array leaks.

Restore the separate per-glyph pointer, and allocate requiredCodepoints
after the NULL check and the default codepoint count are applied.
2026-09-30 22:37:42 +02:00
Ray
002f0310f3 Update rtextures.c 2026-09-30 22:30:44 +02:00
Ray
2ca7349a0c Update rtextures.c 2026-09-30 22:29:56 +02:00
Ray
3b028f0a17 ADDED: Implemented ImageDrawRectanglePro() 2026-09-30 22:26:19 +02:00
Ray
83b9c17366 ADDED: Implemented ImageDrawImageEx() 2026-09-30 22:24:14 +02:00
Ray
5496945d8b Update rtextures.c 2026-09-30 22:23:17 +02:00
6ecf21f700 [rcore][win32] Prevent infinite loop in SetWindowState (#6194) 2026-09-28 17:07:32 +02:00
Ray
ff7afc6ae1 rexm: REVIEWED: Some variables shadowing 2026-09-27 22:53:11 +02:00
Ray
9b4fa3a40e rexm: updated examples with new additions
Some working examples broke...
2026-09-27 22:52:36 +02:00
2fbb15f49a [rtextures] fix ImageKernelConvolution() sampling across rows at image edges and unclamped alpha (#6192)
neighbour pixels were indexed as `width*(x + xk) + (y + yk)` and only
checked against `width*height`, so taps past the left or right edge read
the last or first pixel of the adjacent row, and taps above or below the
image counted as transparent black. clamp the neighbour row and column
instead so edge pixels are repeated, and clamp alpha to [0, 1] like r, g
and b, since it was converted to unsigned char even when out of range.

sums are now accumulated directly into a `Color` buffer, which drops the
per-tap temp array and the `Vector4` copy of the image
2026-09-27 22:32:49 +02:00
d6d163c061 [examples] Fix example warnings. (#6182)
* [rexm] Regenerate `examples_testing_windows.md`.

* [examples] Fix example warnings.

The report (`examples_testing_windows.md`) generated by running `rexm test ALL` followed by `rexm testlog ALL` showed lots of problems with the examples.
I've only tested the examples on Windows 11, some of these changes would likely fix some problems on other platforms as well.
Examples were tested using a plain raylib library built using `make -B`.

## raygui unusued function `GuiFontIconBaking()`

Affected examples:
  - core_directory_files
  - core_clipboard_text
  - core_compute_hash
  - shapes_recursive_tree
  - shapes_ring_drawing
  - shapes_circle_sector_drawing
  - shapes_rounded_rectangle_drawing
  - shapes_splines_drawing
  - shapes_triangle_strip
  - shapes_pie_chart
  - shapes_kaleidoscope
  - shapes_math_sine_cosine
  - shapes_rlgl_color_wheel
  - shapes_hilbert_curve
  - models_animation_blending
  - models_animation_timing
  - shaders_color_correction
  - shaders_game_of_life

These examples had one `[CWARN]`, which was an unused function warning for `GuiFontIconBaking()` in raygui.
Rexm now builds examples with `-Wno-unused-function` to suppress this warning.

## [TIMER]

Affected examples:
  - textures_bunnymark
  - shaders_rlgl_compute

These examples didn't call `SetTargetFPS()`, because they want to showcase performance with an uncapped framerate.
This is trivially fixed by calling `SetTargetFPS(0)`, which doesn't cap the framerate.

## text_codepoints_loading

We were loading codepoints from `text`, which contained newlines ('\n'), which aren't in most fonts.

## text_font_filters

`KAISG.ttf` doesn't define a glyph for '@', so we avoid trying to load it by only loading the codepoints we need.

## textures_image_text

Same problem as `text_font_filters`, but now we load every graphical ASCII codepoint, excluding '@'.
The font atlas is now scaled to fit the screen.

## shaders_rlgl_compute

This example requires OpenGL 4.3, by default raylib uses OpenGL 3.3.
Using OpenGL 4.3 results in no warnings being generated.

## core_window_web

rexm inserts code into examples for testing, which requires every example has an expected structure.
`core_window_web` has a different structure from other examples, so some assumptions fell apart.
`requestedTestFrames` and `testFramesCount` (inserted by rexm) were moved outside of `main` function so now they're available from other functions.

## text_font_loading

Generated 11 warnings:
  - 9 for glyphs with heights bigger than the font size.
    I don't know if this is a problem with:
      1. The `.ttf` font.
      2. How `stb_truetype.h` determines glyph rectangles.
      3. No problem, just the expected behavior in some cases.
  - One warning was because we requested 250 codepoints, but only loaded 184.
  - Another warning was because `pixantiqua.ttf` defines a "glyph" for 0xA0 (No-break space), and raylib didn't handle that codepoint like how it handles other space codepoints.
    Only the codepoints `0x20` and `0x3000` were handled as spaces, which ignores some other spaces, so those are now handled.

## models_loading_iqm

`guy.iqm` had a material in it that didn't exist (MaterialCube), this resulted in a warning when trying to load it.
The material doesn't seem to be important (the model looks correct in the example), and seems like it never existed.

In blender, Cube.005 (`guy.iqm`) had a material, which I removed (so now material is an empty name in the `.iqm` file.)
I also stashed the armature animations (`Dope Sheet->Action->Stash Action`), now when exporting the armature, both animations are stored in `guyanim.iqm`.

In `rmodels.c`, it now only loads the material if the name isn't empty, which allows not having a material in the `.iqm` file.

**DISCLAIMER: I'm not very familiar with IQM models, so I don't know if the material is optional or not. It seems to be optional, because nothing breaks, but I don't know what the conventions are. If it should exist, `guy.iqm` needs updated.**

## Misc. changes

  - `shapes_drag_puzzle`: Trim trailing whitespace.
  - `rtext.c`: Comment-out unused variable.
  - `rtextures.c`: Fix log message, replace tabs with spaces.
  - `examples_list.txt`: Fixed small oversight.

* [examples] Just load default codepoints.

My codepoint loading idea was over-zealous. Also put the "last time updated" version back to what it was previously, since now the examples aren't meaningfully updated

* [rtext] Fix commented-out code.

* [rexm] Regenerate `examples_testing_windows.md`.

---------

Co-authored-by: Ray <raysan5@gmail.com>
2026-09-27 22:27:39 +02:00
f2d8a033bf examples: unload lightmap render texture (#6188)
Co-authored-by: Hugohong258 <282228220+Hugohong258@users.noreply.github.com>
2026-09-27 19:41:28 +02:00
ae55beabe5 [rcore][SDL] Fix only the first dropped file being registered (#6190) 2026-09-27 19:38:04 +02:00
fafa2cea97 [raymath] Fix MatrixCompose() rotating vectors with already overwritten components (#6187) 2026-09-25 07:45:50 +02:00
0152c69b95 [rcore][SDL] define DROP_EVENT_DATA in sdl (#6185)
* define DROP_EVENT_DATA in sdl

* drop the define entirely and use event.drop directly
2026-09-25 07:42:58 +02:00
5c41230605 [rcore][win32] Fix IsWindowResized always returning true (#6186) 2026-09-25 07:39:56 +02:00
Ray
79046d32b7 Review trailing spaces 2026-09-24 23:44:04 +02:00
Ray
e33f1cbd15 Update rcore_desktop_sdl.c 2026-09-24 23:43:45 +02:00
84cab61804 [rcore_desktop_sdl] Refactor dragdrop file onto window handling and grow dropFilepaths dynamically like glfw (#6178) 2026-09-24 23:39:11 +02:00
Ray
46395747e3 Update rexm.c 2026-09-24 23:25:58 +02:00
65d28cf605 [rexm] Fix missing null terminator and overwritten entries when running validate/update commands (#6184) 2026-09-24 22:55:27 +02:00
Auz
cb95b8fba7 Update listed version for Raylib.nelua in BINDINGS.md (#6183) 2026-09-23 16:38:04 +02:00
Ray
fc03d77be9 Update rtextures.c 2026-09-22 10:20:03 +02:00
Ray
8b165ae482 ADDED: ImageDrawCircleGradient(), implemented function 2026-09-22 10:19:32 +02:00
Ray
fec0780484 It seems repology.org is not available any more... 2026-09-22 10:00:33 +02:00
1b1925e1d2 [rcore][win32] Copy current mouse button state to previous in PollInputEvents (#6181) 2026-09-22 09:17:58 +02:00
Ray
938a22e460 Update README.md 2026-09-22 08:48:14 +02:00
Ray
5f886e208a ADDED: ImageDrawRectangleGradientEx(), implemented function 2026-09-21 22:26:03 +02:00
Ray
d33888dd28 Update rtextures.c 2026-09-21 18:43:44 +02:00
Ray
5f83146cac Some code claaning 2026-09-21 18:18:42 +02:00
c042cdc025 [vox_loader] Add bounds checks to Vox_SetVoxel and chunk parsing (#6175)
Vox_SetVoxel had both of its bounds checks commented out, and the voxel
coordinates it receives come straight from the XYZI chunk without being
checked against the volume the SIZE chunk declares. A .vox file that
places a voxel outside that volume indexes m_arrayChunks out of bounds
and writes through the resulting pointer.

Restores the two disabled checks and adds the same coordinate range test
Vox_GetVoxel already performs.

The chunk walk also read a 12 byte header, and up to 12 further content
bytes, after testing only fileDataPtr < endfileDataPtr, so a truncated
file read past the buffer. This also happens on well formed files: the
RGBA branch consumes 255 entries while the chunk carries 256, leaving 4
bytes that are then parsed as another chunk header. Each branch now
checks it has the bytes it is about to read.

Verified with ASAN: the out of bounds write and the header overread are
both gone, and files that loaded before produce identical vertex, index
and colour counts.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-21 10:56:29 +02:00
7bb0345f32 [cmake] Fix install export with vendored SDL (#6173)
* Fix install export with vendored SDL

* cmake: Clean up comment
2026-09-20 23:06:58 +02:00
0b63a64e6f [rshapes] Don't draw a circle when radius <= 0. (#6172)
A circle shouldn't be drawn if the radius is zero (and a negative radius probably doesn't make sense...)
2026-09-20 23:04:37 +02:00
49fe008c36 [examples] Fix inconsistent version metadata (#6171) 2026-09-20 18:16:35 +02:00
425e58ced9 [examples] Added shapes_drag_puzzle (#6165)
* Added shapes drag puzzle example

* Aligned to raylib code conventions and moved the example to shapes

* Fixed Makefile.Web updates
2026-09-20 14:00:09 +02:00
77967288d1 fixed minor typos (#6167) 2026-09-20 13:58:28 +02:00
d0cec73467 [examples] Fix the documented Zig build command (#6170)
Co-authored-by: Hugohong258 <282228220+Hugohong258@users.noreply.github.com>
2026-09-20 13:53:20 +02:00
b927f1b2b1 [rshapes] Cleanup formatting. (#6169)
* [rshapes] Cleanup formatting.

- Cleanup code formatting.
- Fix comment typos, and other cleanup.
- In `DrawRectangleRounded*()` functions, rename `point` array to `points`.

* [config.h] Fix copy/paste error in comment.

* [rexm] Fix typo in README.
2026-09-19 23:36:13 +02:00
Ray
a365e5617a Update clang_tidy.yml 2026-09-19 10:46:09 +02:00
250f2cf243 [gh actions] clang tidy linting: needless casts and assignments in if (#6163)
* [gh workflow] clang lint needless casts and assignments in loops

* [raudio, rcore, rmodels, rtext, rtextures]: Clang Lint: remove redudant casting

* [rlgl] remove needless casting

* [rshapes] EaseCubicInOut: move assignment statement out of if
2026-09-19 10:45:29 +02:00
16a8fb93f4 external/qoa: update vendored qoa.h with upstream out-of-bounds fixes (#6162)
Re-vendors src/external/qoa.h from phoboslab/qoa (f73b4a36). The bundled copy predated two upstream bounds fixes, so a crafted .qoa passed to LoadWaveFromMemory() could overflow the heap (frame samples not bounded against the allocation, qoa.h:640) and the stack (frame channel count not bounded against QOA_MAX_CHANNELS, qoa.h:615). Fixes #6161.


Claude-Session: https://claude.ai/code/session_01JfEozSeCHNgikWTQMDta5U

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-19 09:51:46 +02:00
c6e5cbcdd5 changed MAX_FILEPATH_LENGTH to be the same as MAX_PATH (#6164)
just to make things consistent in case the platform is windows
2026-09-19 00:36:56 +02:00
2525c16f4b [rshapes] fix out of date docs. QUADS are now thee default (#6160) 2026-09-18 13:09:23 +02:00
dba9f418c1 [rshapes] Change DrawRectangleRounded*() segment auto-calculation threshold. (#6159)
* [rshapes] Change rounded rectangle segment auto-calculation threshold.

Auto-calculating rounded rectangle segments when there are fewer than 4 segments seems overly aggressive (a user may actually want 1, 2, or 3 segments.) If a user wants the segments to be auto-calculated, they can still pass in 0 (or any value smaller than 1) for the segments.

Using 4 as the minimum segments may have been copied from circle drawing logic (where fewer than 4 segments may be undesirable.) For rounded rectangles though, the segments are drawn per corner, so the total drawn segments are `segments*4`.

* [rshapes] Refactoring.

 Move some logic around and make formatting more consistent in:
  - `DrawRectangleRounded()`
  - `DrawRectangleRoundedLines()`
  - `DrawRectangleRoundedLinesEx()`
2026-09-17 23:47:21 +02:00
Ray
260d270c58 Update rcore_desktop_glfw.c 2026-09-17 20:46:02 +02:00
bdf10f516c [rcore][GLFW] Fixed issue with non-fullscreen window being able to be larger than a workable area (#6137)
* Fixed issue with non-fullscreen window being able to be larger than a workable area

GLFW has a problem where if the window is greater than the workable area (this means
the taskbar / dockable areas) it won't show up if the window isn't fullscreen. This fix clamps the size of the window to that maximum workable area

* Aligned pointer convention
2026-09-17 20:42:06 +02:00
6f5f7acdd6 [examples] update example to current version of raylib (#6154) 2026-09-16 23:42:01 +02:00
Ray
3d8a9729f9 Update models_skybox_rendering.c 2026-09-16 23:34:15 +02:00
e981377f65 mach-raylib 6.x-dev (#6153)
6.2 latest version now

Co-authored-by: Ray <raysan5@gmail.com>
2026-09-16 23:31:29 +02:00
88b17d974f Add gcl native raylib module entry to BINDINGS.md (#6152)
What I did before was extremely amateurish, and I deleted the repo out of frustration. This time, I’m trying to be more professional and built a system that works with more native built-in modules. The goal is entirely education-focused. Since the system includes both Lua and Python as well, the main focus will of course be on my own C-like language.
2026-09-16 23:28:42 +02:00
6715a6ea95 review of examples memory deallocation (#6151) 2026-09-16 23:26:37 +02:00
010647936f [rexm] Make search boundaries explicit. (#6156)
Avoids accidentally modifying examples (i.e. modifying `shapes_logo_raylib_anim` when you're trying to work with `shapes_logo_raylib`.)
2026-09-16 19:11:09 +02:00
Ray
d5d7b948e1 Update CHANGELOG 2026-09-15 21:32:29 +02:00
Ray
f3bcaf978f Update CHANGELOG 2026-09-15 21:30:15 +02:00
87ce282eee [docs] Replace Youtube Subscriber Badge with Static Badge (#6148)
* Update README.md

* Recolor Youtube Icon

Colored Youtube Icon Red for Consistency
2026-09-14 20:08:37 +02:00
c172619cda Disable ShadowMap Texture Slot To Prevent Global State Leak (#6147) 2026-09-13 22:55:43 +02:00
8564d55149 [examples] Release source images in image rotate example (#6145)
Co-authored-by: Hugohong258 <282228220+Hugohong258@users.noreply.github.com>
2026-09-12 20:30:59 +02:00
a414da391b Fix make shell detection (#6146)
* Detect the recipe shell in Makefiles

GNU Make on Windows may use sh even when invoked from cmd. Probe how
echo handles quotes instead of choosing shell syntax from the target OS.

Apply this to the library, examples and tools, preserving explicit
PLATFORM_SHELL overrides. Stop forcing cmd for library cleanup and fix
Win32 recipe indentation.

* Pass rlparser variables directly to recursive make

The form FORMAT=JSON EXTENSION=json $(MAKE) parse uses sh environment
assignments. Under cmd, FORMAT=JSON is treated as a command and fails.

Use $(MAKE) parse FORMAT=JSON EXTENSION=json instead. This passes the
variables directly to make and works under both shells.
2026-09-12 20:28:57 +02:00
9f59089de1 [rcore][GLFW] Fix window centering overflow with unsigned screen size (#6119)
CORE.Window.screen/render sizes are unsigned, so the subtraction against
the monitor workarea wraps when the window is larger than the monitor,
producing a huge positive position instead of a negative one.
2026-09-12 10:54:30 +02:00
2f699f6bf0 Update h-raylib version in BINDINGS.md (#6142)
Updated Haskell binding version from 5.5-dev to 6.1-dev.
2026-09-12 10:38:02 +02:00
98c175e692 [rcore] Fix ComputeSHA256() wrong hash when message length mod 64 is 56..59 (#6144) 2026-09-12 10:24:51 +02:00
Ray
2f768eb670 Update rlparser output 2026-09-11 18:27:01 +02:00
98f170c1d2 [Bindings] Add recomendations for binding authors (#6141)
* rlparser: update raylib_api.* by CI

* Add some guidelines for binding authors

* Delete tools/rlparser/output/raylib_api.json

* Create raylib_api.json

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Ray <raysan5@gmail.com>
2026-09-11 18:25:59 +02:00
75909072c2 Handle raylib conflict with PlaySoundW for wide string builds (#6140) 2026-09-11 18:22:43 +02:00
Ray
647755ad6d Fixed issues with struct parsing 2026-09-11 18:17:55 +02:00
Ray
77450a6abb Update README.md 2026-09-11 16:44:45 +02:00
Ray
01d9ad64fb Update README.md 2026-09-11 16:43:08 +02:00
abd4cd1155 [docs] Fix minor grammar issues in README (#6139)
* Update README.md

* Update README.md
2026-09-11 16:41:17 +02:00
Ray
569ce9b2ec Update CONVENTIONS.md 2026-09-11 16:29:48 +02:00
3a7aa76509 [rcore_desktop_glfw.c] Do not reset mouse position user when user is off window (#6134)
See this comment and Jeffs as to why
https://github.com/raysan5/raylib/issues/5945#issuecomment-5595141064
2026-09-11 16:18:19 +02:00
Ray
73dce3635c Update raymath.h 2026-09-11 16:11:45 +02:00
c66c92962b [raymath.h] Changed MatrixCompose to follow raymath conventions (#6133)
Co-authored-by: Carlos GS <carlosgs161@proton.me>
2026-09-10 15:14:32 +02:00
94a69ad9e2 [rtext] Fix TextSplit() reading past its buffer on text of 1024 bytes or more (#6136)
The copy loop filled all MAX_TEXT_BUFFER_LENGTH bytes, so the last substring
could come back with no terminator, and a delimiter on the last byte made
buffers[] point one past the end of the array. Stop one byte earlier so the
zero left by the memset() at the top of the function always terminates the
last substring.
2026-09-10 15:13:05 +02:00
Ray
f25c8241f3 tweaks 2026-09-08 18:22:22 +02:00
2b991b0243 [rtext] Fix TextToPascal()/TextToCamel() truncating text after a separator (#6132)
Both functions walk the input with two indexes and, on hitting '_', advance
j once and only write buffer[i] when the next character is one they know how
to handle. TextToPascal() (src/rtext.c:2186) covers 'a'-'z' and '0'-'9',
TextToCamel() (src/rtext.c:2270) covers only 'a'-'z'. Anything else leaves
buffer[i] at the zero it was memset to, so the returned string ends there
and the rest of the text is silently dropped: TextToPascal("text_UTF8_load")
returned "Text" and TextToCamel("sound_3d_mix") returned "sound".

The same path also reads past the end of the string. When '_' is the last
character, j++ lands on the '\0', neither branch matches, and then the loop
increment moves j one further before the condition reads text[j], one byte
beyond the terminator.

Skip the whole run of separators instead, stop when it reaches the end of
the text, and copy any character that has no upper case form as it is.
2026-09-07 00:17:52 +02:00
c64eda6377 Updated BINDINGS.md (#6131)
* Updated bindings' versions
Bindings in the `Older or Unmaintained Language Bindings` category are untouched.

* Fix Target link

* Moved archived and projects with invalid links to a "Unmaintained" category

* `raylib4fb` was moved from GitHub to Codeberg

* Fix table formatting

* Moved outdated to the `Older bindings` category

* Fix tables formatting

* Changed the first paragraph
Added advice on when to update `BINDINGS.md`.
2026-09-07 00:16:07 +02:00
Ray
a2cc9b1614 Merge branch 'master' of https://github.com/raysan5/raylib 2026-09-05 21:22:21 +02:00
30f918cc15 [rlparser] Fix formatting to follow raylib conventions (#6127)
Moved curly brace to newline in `if` block.
2026-09-05 21:21:54 +02:00
Ray
f3d143019b Merge branch 'master' of https://github.com/raysan5/raylib 2026-09-05 18:53:52 +02:00
Ray
2237618acf Update rshapes.c 2026-09-05 18:53:39 +02:00
550dd0e3a8 [rlparser] Fix type aliases (typedefs): added support to type pointers (#6126)
Fix issue #6122
2026-09-04 22:32:03 +02:00
e9d75a4fe9 rlparser: update raylib_api.* by CI 2026-09-04 16:24:23 +00:00
Ray
1829f9282c ADDED: IsFileHidden() 2026-09-04 18:24:04 +02:00
Ray
08a8068702 Merge branch 'master' of https://github.com/raysan5/raylib 2026-09-04 18:13:41 +02:00
Ray
3449d81f67 ADDED: IsFileHidden() 2026-09-04 18:13:28 +02:00
f9c2abdc9e [rexm] Add clean command. (#6124)
`build`, `test`, and `testlog` generate lots of files (`.exe`, `.html`, etc.) when executed. When you build/test enough examples, it's kind of annoying manually deleting the files. The generated reports (`.md` files) are not deleted.
2026-09-04 14:34:36 +02:00
Ray
3f3b4ccd4f Update rexm.c 2026-09-04 14:21:39 +02:00
df4bf2f6a0 fix typo in rtextures.c (#6125) 2026-09-04 08:04:02 +02:00
a65f8be3c2 [rexm] Fix Makefile and change port number. (#6123)
* [rexm] Fix `Makefile`.

The `make` program that comes with `w64devkit` uses a UNIX-style shell, so we can't use `del` (we could set `SHELL` to `cmd`, but this is easier, and the expectation is that `w64devkit` is being used anyway.)

* [rexm] Use less common port number.

When using a port that's already in use, the server fails to start. Using a different (hopefully less common) port should help mitigate this.
2026-09-03 22:26:29 +02:00
9b2efc4552 [rtextures] Fix ImageDrawCircle asymmetry (#6118)
ImageDrawCircle filled 2*radius pixels wide but 2*radius + 1 tall. Each
horizontal span started at centerX - x with width 2*x, which covers
centerX - x through centerX + x - 1, leaving the column at centerX + x
unwritten. The result was one column short on the right, off-centre, and
inconsistent with ImageDrawCircleLines, which is 2*radius + 1 in both
directions.

Widen the four spans by one pixel so the fill is (2r+1) x (2r+1), centred
on (centerX, centerY) and aligned with ImageDrawCircleLines.

Fixes #6117
2026-09-02 12:31:04 +02:00
5a433a51a3 [rTextures] Add LoadRenderTextureEx with user defined format (#6114)
* Add LoadRenderTextureEx that defines the FBO pixel format

* rlparser: update raylib_api.* by CI

* requested review

* rlparser: update raylib_api.* by CI

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-09-02 09:42:56 +02:00
237c1f85dd [rtextures] Fix GetPixelColor() reading the wrong bits for R5G5B5A1 blue (#6113)
R5G5B5A1 packs blue in bits 5..1 and alpha in bit 0, which is what
SetPixelColor(), ImageFormat(), LoadImageColors() and GetImageColor()
all do. GetPixelColor() masked bits 4..0 instead, so the decoded blue
was the low four bits of blue shifted up with the alpha bit pulled in
as its LSB.

Packing r == g == b and decoding it back gave (164, 164, 74) for
r=g=b=20; 31 of the 32 possible grey values decoded with unequal
channels. ImageDrawImage() blends through GetPixelColor(), so drawing
onto an R5G5B5A1 image was affected too.

Co-authored-by: Dylan Pulver <dylanpulver@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
2026-09-02 09:42:19 +02:00
656d42c4da Support rlGetActiveFramebuffer() on OpenGL ES 2.0. (#6115)
Alias GL_DRAW_FRAMEBUFFER_BINDING to GL_FRAMEBUFFER_BINDING for ES 2.0,
alongside the existing GL_READ_FRAMEBUFFER/GL_DRAW_FRAMEBUFFER aliases, and
widen the guard to ES 2.0. The guard now matches rlEnableFramebuffer() and
rlDisableFramebuffer().
2026-09-02 09:36:59 +02:00
9f3cadf1e6 docs: fix typo relase -> release (#6109)
Signed-off-by: Vaibhav Srivastava <vaibhavsri1712@gmail.com>
2026-08-29 12:39:21 +02:00
1948bdf3f7 [rcore][drm] Raise MAX_DRM_CACHED_BUFFERS to 4 and warn when the cache fills (#6107)
The cache has no eviction, so a driver rotating a fourth buffer never gets a
framebuffer for it and the display stops updating for good. Mesa rotates
three, ARM's Mali blob on RK3326 rotates four.

Verified on an R36S. See #6056.
2026-08-29 11:41:46 +02:00
39d00cb025 [rexm] Fix small oversight. (#6106)
The leading double quote was accidentally deleted.
2026-08-28 21:40:23 +02:00
Ray
cef6136325 Update rexm.c 2026-08-28 19:39:05 +02:00
29d232c7cc [rexm] Leave environment setup up to the user. (#6101)
rexm used to assume certain paths existed and then `_putenv()` them into `PATH`, which is very error prone. `make` was also assumed, though `mingw32-make` seems to be more common on Windows. Since this shifts things to expect the user to setup their environment, I added some explanation to the README as well.

OP_TESTLOG still uses a hardcoded path when doing web testing (`BUILD_TESTING_WEB`,) unfortunately.
2026-08-28 19:35:46 +02:00
3e2c0132a9 Invert emscripten scroll wheel direction (#6104) 2026-08-28 19:23:47 +02:00
f2441a17c8 [rcore][desktop] Fix clipboard image memory leak (GLFW, RGFW) (#6103) 2026-08-28 19:21:17 +02:00
caba629ca1 Add raylib binding for solod (#6102) 2026-08-26 21:11:33 +02:00
Ray
a946097de4 Remove trailing spaces 2026-08-26 19:47:40 +02:00
Ray
ba0ac542c5 Update rtext.c 2026-08-26 19:46:45 +02:00
173b854168 Fix memory leak in rtext LoadFontFromImage method (#6100)
Fix for
[rtext] Memory leak at LoadFontFromImage when failing to compute spacing's
2026-08-26 19:43:03 +02:00
4c1dc51a6f Fix unused variable warnings (SDL) (#6096) 2026-08-26 18:39:42 +02:00
b7d7e70ac5 Fix Font name conflict (#6094) 2026-08-26 18:38:45 +02:00
d9bf63bdf4 Updated BINDINGS.md for raylib-py 6.0 (#6095)
Co-authored-by: Jorge A. Gomes <jorgegomes83@gmail.com>
2026-08-26 18:37:52 +02:00
Ray
71643d8cda REVIEWED: GetWindowHandle(), avoid on SDL2 with Linux #6085
It generates conflicts with raylib Font symbol
2026-08-25 20:18:08 +02:00
Ray
0fb5c98293 Update models_mesh_uv_painting.c 2026-08-25 19:44:14 +02:00
Ray
e4ccc91d4e REVIEWED: example: textures_portal_window 2026-08-25 19:38:34 +02:00
f3a471fd89 rlparser: update raylib_api.* by CI 2026-08-25 17:26:56 +00:00
820b971eff [rshapes] Add some missing Draw*LinesEx() functions and new example shapes_outlines_testbed (#6072)
* [rshapes] Add `DrawEllipseLinesEx()`

Add DrawEllipseLinesEx() to the API for consistency with other shape drawing functions.

* [rshapes] Add `DrawTriangleLinesEx()`

Add DrawTriangleLinesEx() to the API for consistency with other shape drawing functions.

* [rshapes] Add `DrawCircleSectorLinesEx()`

Add DrawCircleSectorLinesEx() to the API for consistency with other shape drawing functions.

* [rshapes] Add `DrawRingLinesEx()`

Add DrawRingLinesEx() to the API for consistency with other shape drawing functions.

* [examples] Add shapes_outlines_testbed

This example stress tests the previously existing and newly added shape outline functions.
2026-08-25 19:26:42 +02:00
5f58fbe6d7 Added raylib_mojo binding for Mojo language (#6093) 2026-08-25 19:17:03 +02:00
5c5b357b4a [rcore][win32] Implement GetClipboardImage() (#6091) 2026-08-25 19:16:28 +02:00
bcc834fc3e [examples] Add models_mesh_uv_painting (#6084)
* [examples] Add models_mesh_uv_painting

Example showing paintable models textures

* Fixed window size and use the raygui header for the buttons
2026-08-25 19:15:43 +02:00
5b818bb318 [examples] New example models procedural decals (#6083)
* [examples] Add models_procedural_decals

A decal example that works on the web

* Using raygui button
2026-08-25 19:14:58 +02:00
e1efefb7f4 [cmake] Propagate Cocoa backend frameworks to consumers of static raylib on macOS (#6086)
* [cmake] Fix standalone configuration of examples project

Configuring examples/ as a standalone project (cd examples && cmake .)
failed with 'Unknown CMake command add_if_flag_compiles' and a missing
cmake_minimum_required() error on CMake 4.x.

- Add cmake_minimum_required(VERSION 3.22), matching the root project
- Include raylib's AddIfFlagCompiles helper via ../cmake
- Default PLATFORM to Desktop when not inherited from the raylib build

* [cmake] Propagate Cocoa backend frameworks to consumers of static raylib on macOS

Bundled GLFW links '-framework Cocoa/IOKit/QuartzCore' privately, and the
static-install export block removes glfw from the exported dependencies.
As a result the installed CMake package only carried OpenGL.framework,
and linking any consumer of libraylib.a failed with undefined Objective-C
symbols (_objc_retain etc.).

Append the three frameworks to the static install interface when the
bundled GLFW is used, so installed consumers get a complete link line.

* Gate macOS Cocoa framework propagation to the Desktop platform
2026-08-24 16:19:56 +02:00
2c0021ad89 [cmake] Fix standalone configuration of examples project (#6079)
Configuring examples/ as a standalone project (cd examples && cmake .)
failed with 'Unknown CMake command add_if_flag_compiles' and a missing
cmake_minimum_required() error on CMake 4.x.

- Add cmake_minimum_required(VERSION 3.22), matching the root project
- Include raylib's AddIfFlagCompiles helper via ../cmake
- Default PLATFORM to Desktop when not inherited from the raylib build
2026-08-24 13:34:47 +02:00
9bde204f1d [examples] Add textures_portal_window (#6082)
Add a example showing a portal like effect
2026-08-24 13:33:43 +02:00
Ray
47231e37ef REVIEWED: shaders_lights_bloom example 2026-08-23 21:05:34 +02:00
0088b85952 [examples] Add lights_bloom_post (#6081)
Add a bloom light effect example
2026-08-23 20:58:02 +02:00
338458a92b Fix crash when adding a new textures or audio examples (#6089)
rexm could crash and corrupt examples_list.txt when adding a new example in the textures category. This happened because the tool searched for the category name as plain text, and "text" happens to be part of "textures" (and shows up inside names like core_render_texture), so it sometimes found the wrong spot and inserted the new example in the middle of an unrelated line.

This fix makes the search look for the exact category boundary instead of just any matching text, so it always finds the right place. It also fixes a small out-of-bounds issue that could happen specifically with the audio category, since it's the last one in the list.

Tested by creating a new textures example and a new audio example, both now work correctly and the examples list stays intact.
2026-08-23 20:50:26 +02:00
3836f13878 Also include the playsoundapi.h file that is where playsound is now in lean and mean, this ensures that it gets picked up by the replacement macro in more modern SDKs. (#6088) 2026-08-23 15:29:28 +02:00
abe23bf82d [build] Updated examples/Makefile after testing on OSX (#6077)
* Updated examples/Makefile after testing on OSX

I may be wrong, but the best way to install ray lib is through home-brew, and I'd expect that that should be a search path for others.

* Update Makefile

Fixed issues
2026-08-21 21:14:57 +02:00
Ray
6cceb2b873 Update README.md 2026-08-21 21:14:21 +02:00
Ray
86430c156c Update README.md 2026-08-21 21:13:25 +02:00
Ray
3b57140640 Update README.md 2026-08-21 21:11:29 +02:00
Ray
f472c67bb2 Update README.md 2026-08-21 21:08:36 +02:00
Ray
23033d1f18 Update README.md 2026-08-21 21:07:03 +02:00
d7225acd8e Add raymojo binding for Mojo language (#6076) 2026-08-21 20:53:09 +02:00
af3045377a add raystar binding to BINDINGS.md (#6075) 2026-08-20 16:25:23 +02:00
Ray
f9e2215c49 Update README.md 2026-08-19 21:17:17 +02:00
Ray
d75a6589f0 REVIEWED: GetWindowPosition() #5932 2026-08-19 20:25:01 +02:00
47c8e897ce [rcore][GLFW] Fix borderless-windowed mode being always on top (#5868)
* Fix borderless fullscreen always on top

Don't pass a monitor to glfwSetWindowMonitor(). This avoids setting the flag which keeps the window always on top.

* Update for borderless-windowed always on top bug

Only apply the fix for Windows OS, since that seems to be the only
platform with the issue.
2026-08-19 20:02:32 +02:00
1129d42b48 Mostly rewrote GetPrevDirectoryPath() to correct its behavior in a few cases (#6073) 2026-08-19 19:53:56 +02:00
c58072d595 Update emscripten mouse handling (#6070) 2026-08-18 14:33:31 +02:00
b98c4e031d [rcore_web_emscripten] Handle emscripten keyboard events (#6067)
* Handle emscripten keyboard events

* Prevent stuck keys by clearing on blur event
2026-08-17 18:51:06 +02:00
Ray
9506b58633 Update BINDINGS.md 2026-08-17 18:46:33 +02:00
44aa771cc0 add raymod binding for modula 2 and 3 (#6068) 2026-08-17 18:45:49 +02:00
dad422a430 Fix time calculation in GetTime function (#6061) 2026-08-14 00:46:53 +02:00
ae83a50fb3 Update BINDINGS.md (#6060) 2026-08-13 21:20:52 +02:00
4f4b3aef45 Use unmodified GLFW (#6058)
* Use unmodified GLFW

* egl_context.c and osmesa_context.c are common to all platforms

* Define _glfwConnectNull() function
2026-08-13 11:01:10 +02:00
Ray
6862f7b9ca Update BINDINGS.md 2026-08-13 10:56:03 +02:00
ad6b19a37c Add mach-raylib (#6059) 2026-08-13 10:50:22 +02:00
Ray
bb474f69d8 Updated macOS libraries 2026-08-12 13:06:29 +02:00
77353e7f31 Update GLFW to 3.5.1 (#6051)
* Update GLFW to 3.5.1

* Remove cocoa_time.c from rglfw.c

* Add macos_time.c to rglfw.c

* Redo changes from pull request #3863

* Makefile: add QuartzCore framework when building for macOS

* Add QuartzCore when building for macOS to other build files

* Remove unused GLFW dependencies
2026-08-12 13:02:51 +02:00
fba8ea01f5 [rlsw] Fix #ifdef -> #if for RLSW_DOUBLE_BUFFERING in sw_default_framebuffer_free() (#6054) 2026-08-12 12:57:23 +02:00
57917f1656 add component pascal/oberon2 bindings (#6055) 2026-08-12 12:55:13 +02:00
d46a59367f [msbuild] MSVC x64 build compatibility support (#6052) (#6053)
Change EnableEnhancedInstructionSet to NotSet for compatibility old hardware.
2026-08-11 21:14:47 +02:00
868413839a Fix glTF pose sampled at the end of an animation returning a pose from the start (#6048)
GetPoseAtTimeGLTF searches for the interval containing the requested time
with (tstart <= time) && (time < tend). A time equal to the last keyframe
satisfies no interval, so the loop ends without a match and keyframe stays
at its 0 default, making the function return a pose from the beginning of
the animation.

LoadModelAnimationsGLTF samples at t = j/60 for j in [0, keyframeCount),
with keyframeCount = (int)(duration*60) + 1, so the last sample lands
exactly on the end of the animation whenever duration*60 is a whole
number. The last pose of those clips is wrong, which looks like a jerk
right before the animation ends.

Measured on a glTF with a 0.85 s clip: the delta between the last two
poses was 23x the median delta between consecutive poses; with this
change it is 0.3x, in line with every other step.
2026-08-11 21:13:19 +02:00
1225932449 [examples] Add core_scissor_shape (#6032)
* [examples] Add core_scissor_shape

Clip drawing to an arbitrary shape using the stencil buffer, since
BeginScissorMode() only supports axis-aligned rectangles.

* [examples] Rename to gl_scissor_shapes.c

Rename core_scissor_shape to gl_scissor_shapes, move to others. Per @raysan5's review feedback on the PR: keep OpenGL-facing examples
under examples/others, consistent with rlgl_standalone and
raylib_opengl_interop, to avoid multi-platform/build-system issues.
2026-08-11 18:33:25 +02:00
f28c2221cc Fix window Y position reading X in RGFW move callback (#6044) 2026-08-11 18:32:19 +02:00
4245423cc1 Update miniaudio to 0.11.25 (#6050) 2026-08-11 11:37:57 +02:00
9beca068b9 [rshapes] Fix drawing circle sectors (#6045)
* [rshapes] Fix drawing circle sectors

Functions that draw a sector of a circle would keep drawing segments past a full rotation, which looked bad.

* [rshapes] Change `DrawCircleSectorLines()` and `DrawRingLines()`

`DrawCircleSectorLines()` and `DrawRingLines()` drew the cap lines even when drawing a full circle, which seems undesirable.
2026-08-10 14:51:59 +02:00
Ray
079cc2df09 Update shaders_shadowmap_rendering.c 2026-08-08 17:03:55 +02:00
388806f24d [examples] shaders shadowmap rendering camera fix (#6041)
* Update the camera before sending it to the shader

* tabs to spaces (oops)
2026-08-08 16:58:39 +02:00
b0005129c7 fix typo in fix_win32_compatibility.h (#6043)
* fix typo in fix_win32_compatibility.h

* fix another typo in fix_win32_compatibility.h

* fix yet another typo in fix_win32_compatibility.h
2026-08-08 16:57:40 +02:00
1893226cb7 Fix crash on CloseAudioDevice: uninit device before mutex (#6039)
On Android (AAudio) the callback thread could still run when the mutex was
destroyed, causing a SIGABRT (pthread_mutex_lock on a destroyed mutex).
Uninit the device first so its callback thread stops before ma_mutex_uninit.
2026-08-07 22:44:06 +02:00
3580240743 [examples] Several fixes and improvements (#6042)
* models_loading_iqm - actually use animIndex

* models_decals - fix button placement

* core_highdpi_testbed - unrelated TODO

* audio_sound_positioning - fix SetSoundPosition and panning

* SetSoundPan is clamped already

* remove version check

* fix 'updated with' in the header
2026-08-07 21:30:27 +02:00
7ee0b08647 Fix Android relaunch hang after destroy while paused (#6040)
When the activity is destroyed while the app is paused, PollInputEvents
kept looping after setting CORE.Window.shouldClose: while paused,
ALooper_pollAll is called with an infinite timeout (-1), so on the next
iteration it blocked forever waiting for an event that never arrives.
main() never returned, the native thread stayed alive, and the following
launch hung inheriting that thread.
2026-08-07 18:37:57 +02:00
a55d49b754 [examples] Add shapes_outlines_thickness (#6037)
Add an example to demonstrate the new thickness behavior in `Draw*LinesEx()` functions.
2026-08-05 12:53:25 +02:00
Ray
3d671a6dd4 Merge branch 'master' of https://github.com/raysan5/raylib 2026-08-04 21:16:17 +02:00
Ray
7711de62fb Code gardening 2026-08-04 21:16:08 +02:00
37712a8fbe [rshapes] Fix Draw*LinesEx() functions' inconsistent handling of thick parameter. (#6035)
* [rshapes] Update `DrawRectangleLinesEx()`

Add support for negative `thick` values. When `thick` is negative, lines are drawn growing outside of the rectangle.

* [rshapes] Update `DrawPolyLinesEx()`

Add support for negative `thick` values. When `thick` is negative, lines are drawn growing outside of the polygon. Also refactored to explicitly use an `outerRadius` variable instead of using `radius` as the outer radius.

* [rshapes] Update `DrawRectangleRoundedLinesEx()`

Make the outline vertices easier to work with.

* [rshapes] Updated `DrawRectangleRoundedLinesEx()`.

Lines used to draw outside when `thick` was positive. Added support for negative `thick` values. When `thick` is negative, lines are drawn growing outside of the rectangle.

* [rshapes] Update `DrawRectangleRoundedLines()`.

Make the formatting of the points' x and y coordinates in DrawRectangleRoundedLines() match DrawRectangleRoundedLinesEx().
2026-08-04 18:04:56 +02:00
99b61089c8 Added ElfScript to Bindings (#6036) 2026-08-02 23:04:22 +02:00
c5a6d94110 Update BINDINGS.md (#6034)
Added bindings of Raylib 6.0 for openEuphoria
2026-08-01 14:52:45 +02:00
Ray
912085c831 Update raygui 2026-07-31 13:48:34 +02:00
7d85ff76a6 Update BINDINGS.md (#6033) 2026-07-31 13:32:45 +02:00
Ray
3e49c80799 REVIEWED: Macros prefixes #6029 2026-07-30 10:14:27 +02:00
e5aaed2a3f change prefix of all public compile time options from SW_ to RLSW_ (#6029) 2026-07-30 10:05:20 +02:00
ea0dcbdb7c review inlining (#6028) 2026-07-30 10:03:35 +02:00
Ray
63f82f0ca8 REVIEWED: DrawRectangleLinesEx(), avoid early-return
NOTE: raylib data validation policy defines not to validate any data that does not suppose a crash in the program, letting user manage that layer... probably several functions should be carefully reviewed or the policy itself...
2026-07-29 10:10:26 +02:00
Ray
60b9f20469 Merge branch 'master' of https://github.com/raysan5/raylib 2026-07-29 10:04:19 +02:00
9f9c11db41 [rshapes] Fix DrawRectangleLinesEx() (#6027)
Previously DrawRectangleLinesEx() would draw lines overlapping each other when they were thick enough (which was only noticeable if the color's alpha was lower than 255.)
2026-07-29 10:03:22 +02:00
935f3da3ff [examples] Add shapes_polygon_lines (#6023)
Add an example to demonstrate/observe DrawPolyLinesEx() behavior.
2026-07-27 16:30:30 +02:00
de24a6c1eb fix: use rlGetPixelDataSize in rlgl.h (#6024) 2026-07-27 16:29:32 +02:00
3ea8b9298f Refactor text insertion logic in rtext.c (#6022)
Fixed nasty bug, text after insertion is deleted
2026-07-26 20:54:54 +02:00
Ray
86684cd246 Merge branch 'master' of https://github.com/raysan5/raylib 2026-07-26 16:58:14 +02:00
Ray
f3d7d5a3cd Update raygui 2026-07-26 16:58:01 +02:00
14d3587858 Refactor text insertion logic in rtext.c (#6021)
Fixed nasty bug
2026-07-26 15:11:39 +02:00
a18051fdd9 Fix various warnings when building in VC2022 (#6020) 2026-07-26 15:10:19 +02:00
ac06acbaee Add rayscal binding for Scala Native (#6019) 2026-07-26 15:09:14 +02:00
ae7c58e5b9 Fix typo in 'Utility Wrapers' heading (#6017) 2026-07-26 15:08:28 +02:00
c15f3214d5 [rshapes] Correct DrawPolyLinesEx() line thickness. (#6014)
Follow up to #6004. The previous formula would produce inconsistent results for different polygons with the same `thick` parameter.
2026-07-24 21:38:50 +02:00
Ray
a408dd332e REVIEWED: IsPathAbsolute(), remove isalpha() dependency 2026-07-24 21:17:11 +02:00
Ray
f0a8201733 Update CHANGELOG for upcoming raylib 6.2 release 2026-07-23 12:15:38 +02:00
127e7441da [rshapes] Fix DrawPolyLinesEx() (#6004)
If `innerRadius` is less than 0, it causes the outline to overlap itself and even grow outside of the polygon's bounds when `thick` is greater than `radius`. Clamping `innerRadius` to 0 fixes these problems.
2026-07-23 09:50:11 +02:00
353268b7cf [rmodels] Fix GLTF animation interpolation (#6007) 2026-07-23 09:41:20 +02:00
8eb433518d [build][Zig] Update to raygui 5.0 (#6005) 2026-07-23 09:39:38 +02:00
7d4f5f79e7 [build][Zig] Fix web examples building all the time (#6006) 2026-07-23 09:38:45 +02:00
aa4cf20eae [rlsw] Variant dispatch refactor + bunch of improvements (#5996)
* rlsw config section

* use raster flags to define rasterizer variants

* simplifies the generation of dispatch tables

* single dispatch table for the lines
same logic as for the points

* internal color interp state

* check whether vertex colors should be interpolated

* vector op helper macro + pick sampler once before primitive drawing

* op order tweaks

* refactoring without gotos for triangle and quad rasterizers

* same cleaning for the lines
2026-07-21 18:22:58 +02:00
78535d2343 [rlsw] First batch of embedded optimizations and compiler requirements Pico 2 (#5994)
* pico doesn't implement time.h

* add option for RLSW to hold a back buffer, and give it a sw method to swap

* Remove unused pointer and give swSwapColorBuffers a default nop-behaviour

* Fix compilation by removing old colorBackBuffer setters

* use the correct logger

* return line

* rename RLSW_BACKBUFFER to SW_DOUBLE_BUFFERING
2026-07-21 18:20:58 +02:00
e809face7b [rmodels] DrawSphereWires(), code optimization (#6000)
* Fix DrawSphereWires (Less aggressively) 

Summary:
- Eliminated some redundancies
- Fixed a bug(?) where the sphere would have 1 more "ring" (latitude division) than expected
- Fixed a bug where the top ring was double-covered
- Added comments denoting which code draws which lines

* DrawSphereWires + DrawSphereEx parity

Summary:
- Replaced DrawSphereWires algorithm with one based on the much faster algorithm from DrawSphereEx
- Fixed +1 ring quirk on DrawSphereEx to match the change made to DrawSphereWires
2026-07-21 17:48:07 +02:00
9fd4726c31 [rshapes] Fix DrawRectangleRoundedLines() (#5992)
In #5980 a bug was introduced for `DrawRectangleRoundedLines()`. `DrawRectangleRoundedLines()` previously assumed that `DrawRectangleRoundedLinesEx()` uses `RL_LINES` when line thickness is 1 (which is no longer true, it now uses `RL_QUADS` or `RL_TRIANGLES`.)

I copy/pasted the previous `DrawRectangleRoundedLinesEx()` implementation and trimmed it down (since now the line thickness is always 1), so now `DrawRectangleRoundedLines()` uses `RL_LINES`. This makes it consistent with all other `Draw*Lines()` functions, which use `RL_LINES`.
2026-07-21 17:46:22 +02:00
Ray
1c3a7748ea Update examples dep. raygui 5.0 2026-07-21 08:40:56 +02:00
Ray
ce40053a6c Remove trailing spaces 2026-07-20 20:36:14 +02:00
Ray
9ef6850cc4 Update build_examples_windows.yml 2026-07-18 17:52:07 +02:00
Ray
3094389a2a Update analyze_codeql.yml 2026-07-18 17:49:35 +02:00
Ray
b812c18e6b Merge branch 'master' of https://github.com/raysan5/raylib 2026-07-18 17:14:10 +02:00
Ray
6c6a248be8 Update rcore.c 2026-07-18 17:14:03 +02:00
ce6ac7d8c7 rlparser: update raylib_api.* by CI 2026-07-18 14:50:44 +00:00
Ray
baa9a4df51 REVIEWED: ImageToImage(), reorganize conditionals checks optimization, align brackets 2026-07-18 16:50:28 +02:00
Ray
58e03dbc6c REVIEWED: TakeScreenshot() to support absolute paths 2026-07-18 16:45:28 +02:00
Ray
cfccb83ddd ADDED: IsPathAbsolute() to check absolute paths 2026-07-18 16:44:41 +02:00
Ray
b806e3d2ec Replaced comments text given by provided 2026-07-18 16:44:10 +02:00
Ray
0725811224 Added a note reminder 2026-07-18 16:43:04 +02:00
5b1445b381 FIXED: ImageFromImage() heap-buffer-overflow on compressed formats (#5991) 2026-07-17 23:22:35 +02:00
aa088e42d1 fix static link deps (#5990) 2026-07-17 23:12:57 +02:00
7aceceb467 Fix logging format for automation event capacity warning (#5986)
Co-authored-by: gideons <gse@newspacesystems.com>
2026-07-17 20:31:26 +02:00
Ray
66bb527d22 Update README.md 2026-07-16 15:10:46 +02:00
Ray
f1d44c166f REMOVED: Unmaintained project: VS2019-Android 2026-07-16 15:08:46 +02:00
Ray
9c834d6e4d Merge branch 'master' of https://github.com/raysan5/raylib 2026-07-16 15:08:35 +02:00
Ray
742ccb390a REMOVED: Unmaintained project: 4coder 2026-07-16 15:08:12 +02:00
Ray
62a74a342c Update README.md 2026-07-16 15:05:32 +02:00
Ray
8eb613e50a Update rcore_desktop_glfw.c 2026-07-16 12:28:25 +02:00
89b4fbd298 [rcore] fic position on mouse leave for emscripten. Issue raysan5#5945 followup (#5981) 2026-07-16 12:10:03 +02:00
93e64f2210 Fix TextInsertAlloc overflow by correcting loop bounds (#5982)
Co-authored-by: gideons <gse@newspacesystems.com>
2026-07-16 12:08:41 +02:00
a9a0c046f1 Fix pixel data size regressions (#5984)
Co-authored-by: gideons <gse@newspacesystems.com>
2026-07-16 12:07:19 +02:00
d224912bd5 Fix rlsw persistent alpha blending state (#5964) 2026-07-15 21:21:38 +02:00
39706cccbe [rshapes] Fix DrawRectangleRoundedLinesEx not scaling with transform when thick=1 (#5980) 2026-07-15 21:20:18 +02:00
Ray
4640c84920 WARNING: Not updating mouse.previousPosition when SeMousePosition() #5962
This could be a sensible change, not sure if it can break anything...
2026-07-13 19:32:30 +02:00
Ray
af98e3126e Merge branch 'master' of https://github.com/raysan5/raylib 2026-07-13 19:25:08 +02:00
Ray
e063385c47 Fix #5965 2026-07-13 19:24:49 +02:00
7a247ff40f Fix swScissor() Y-axis clipping inversion in software renderer (#5976) 2026-07-13 19:19:02 +02:00
5de8c3521f fix: ImageFromImage rectangle validation use >= and <= (#5979) 2026-07-13 15:13:12 +02:00
b631fb3d05 Fix TextSubtext() returning empty string when position is 0 (#5975) 2026-07-13 15:11:42 +02:00
fb4649a3fe [rcore][desktop] Fix clipboard image memory leak (#5968)
* [rcore][desktop] Fix clipboard image memory leak

* [delete] delete comment GetClipboardImage into  NOTE about where put SDL_free() .
2026-07-13 15:10:27 +02:00
Ray
f00317bead Added required library 2026-07-11 17:01:09 +02:00
Ray
8805ab3ee2 Update rmodels.c 2026-07-11 16:57:49 +02:00
Ray
ebec978443 REVIEWED: TextJoin(), TextSubtext(), TextInsert*() - ROS: CLN-018 2026-07-11 16:45:56 +02:00
Ray
cfe56d97ea REVIEWED: GetPixelDataSize(), avoid allocations >2GB - ROS: CLN-013
REVIEWED: `GenImageColor()`, `ImageRotate()`
2026-07-11 16:42:57 +02:00
Ray
97d2b0146c REVIEWED: Replace assert() by runtime checks - ROS: CLN-012 2026-07-11 16:22:05 +02:00
Ray
c31666fe2a REVIEWED: ImageFromImage() - ROS: CLN-007 2026-07-11 16:20:41 +02:00
Ray
ab35e0f712 REVIEWED: LoadAutomationEventList() - ROS: CLN-005, CLN-006 2026-07-11 16:18:34 +02:00
Ray
c85cd07db0 Update rmodels.c 2026-07-11 12:22:03 +02:00
Ray
f458296a07 small optimization 2026-07-11 12:21:24 +02:00
Ray
8df2f13962 Update raudio.c 2026-07-11 12:20:57 +02:00
cba8f4286d Fix initial macOS window size (#5967) 2026-07-11 12:06:54 +02:00
86c7edfd74 [raudio] Fix memory leak when loading .wav files (#5963)
* [raudio] Fix memory leak when loading .wav files

* [change] Insert a space.
2026-07-11 12:03:41 +02:00
Ray
caadb48e25 Update SECURITY.md 2026-07-07 15:54:57 +02:00
Ray
3e9fb4757f Update rcore_drm.c 2026-07-07 12:17:23 +02:00
d159739a8b Fix DRM/EGL segfault on some NVIDIA proprietary drivers (#5960) 2026-07-07 12:15:54 +02:00
Ray
f20f61d754 Merge branch 'master' of https://github.com/raysan5/raylib 2026-07-07 11:47:31 +02:00
Ray
81b740403a Updated 2026-07-07 11:47:19 +02:00
3cb8a3d782 ReiLua Lua binding update to raylib 6.0. (#5959) 2026-07-07 11:46:07 +02:00
Ray
f8e42cb509 REVIEWED: OpenURL(), added some safety checks to mitigate possible malicious url inputs 2026-07-07 11:45:30 +02:00
Ray
d631a5a466 Merge branch 'master' of https://github.com/raysan5/raylib 2026-07-06 19:14:22 +02:00
Ray
5992929e56 REVIEWED: Security: strncpy() replaced by snprintf() 2026-07-06 19:13:44 +02:00
3d640698d8 fix UB in ComputeSHA-1 (#5957) 2026-07-06 18:35:02 +02:00
088177b269 rlparser: update raylib_api.* by CI 2026-07-06 16:33:13 +00:00
2e03c9c266 Change boneCount field type from int to unsigned int (#5955) 2026-07-06 18:33:01 +02:00
Ray
65abee1cba Updated GA setup-emsdk action 2026-07-04 12:25:06 +02:00
Ray
1911a2827b REVIEWED: GitHub Actuions update to latest actions 2026-07-03 23:09:19 +02:00
Ray
bb96b920d3 Update rtextures.c 2026-07-03 11:31:45 +02:00
350124a45b [rcore] Fix SDL3 backend using wrong joystick functions (#5948)
* [rcore] Fix gamepad code using outdated functions

* [rcore] Remove printing available joysticks
2026-07-03 01:00:51 +02:00
Ray
5e374218ee REVIEWED: Set mouse position to (0,0) when mouse leaves window area #5945 2026-07-02 18:58:01 +02:00
9f60957b84 rlparser: update raylib_api.* by CI 2026-07-02 08:49:50 +00:00
Ray
0c0375f8ae ADDED: IsPathDirectory(), for convenience and more readability at user code 2026-07-02 10:49:31 +02:00
Ray
77ecd5befc REVIEWED: TextToSnake(), not considering spaces properly 2026-07-02 10:46:38 +02:00
Ray
a7ac5c2823 Merge branch 'master' of https://github.com/raysan5/raylib 2026-07-01 12:19:29 +02:00
Ray
44b16a548f Update rtextures.c 2026-07-01 12:18:58 +02:00
9deaae0716 rlparser: update raylib_api.* by CI 2026-07-01 10:09:45 +00:00
Ray
122e378e93 ADDED: New image drawing functions, aligned with texture/text drawing -WIP-
The new functions are direct maps of the Texture2D equivalents, they can be useful for a future mapping Texture2D --> Image; an alternative 2d software renderer...
2026-07-01 12:09:26 +02:00
Ray
2c24ca1407 Typos 2026-07-01 11:55:43 +02:00
Ray
04a269f4f8 ADDED: Support for .pep image fileformat, useful for pixl-art 2026-07-01 11:55:27 +02:00
8999d2ba44 [tools] Add S-Expression Output Type to rlparser (#5943)
* Add S-Expression output to rlparser.c

* minor whitespace fix
2026-07-01 10:05:11 +02:00
Ray
7ac798cef9 REVIEWED: Shader attribute/uniform default names can not be overriden #5925 2026-07-01 10:04:24 +02:00
67359073ca [rcore] Add gamepad >= 0 lower-bound guard to six sibling functions (#5938)
Commit 3edfe194 added a `gamepad >= 0` lower-bound check to
GetGamepadAxisCount() and GetGamepadName(), but six sibling functions
were left with only the upper-bound check (`gamepad < MAX_GAMEPADS`).
A negative signed int passes that check and triggers out-of-bounds
access on CORE.Input.Gamepad.ready[gamepad] and related arrays (UB in C).

Apply the same `(gamepad >= 0) &&` guard added in 3edfe194 to:
- IsGamepadAvailable
- IsGamepadButtonPressed
- IsGamepadButtonDown
- IsGamepadButtonReleased
- IsGamepadButtonUp
- GetGamepadAxisMovement
2026-06-27 21:06:49 +02:00
3edfe19438 [rcore] Bounds-check gamepad index in GetGamepadAxisCount() and GetGamepadName() (#5937)
* [rcore] Bounds-check gamepad index in GetGamepadAxisCount() and GetGamepadName()

Both public getters indexed CORE.Input.Gamepad.axisCount[gamepad] / .name[gamepad]
with an unvalidated gamepad argument -- an out-of-bounds read for gamepad < 0 or
gamepad >= MAX_GAMEPADS. Every sibling gamepad accessor (IsGamepadAvailable,
IsGamepadButton*, GetGamepadAxisMovement) already guards the index; add the same
check, returning a safe default (0 / NULL).

* Refactor GetGamepadName/GetGamepadAxisCount to single-return pattern

---------

Co-authored-by: Brandon Arrendondo <brandon.arrendondo@bissell.com>
2026-06-24 17:40:28 +02:00
9215540015 [rtext] Fix buffer overflow in TextReplaceBetween() (#5936)
The MAX_TEXT_BUFFER_LENGTH guard present in TextReplace()/TextInsert() was
missing here, so the three strncpy() calls could write past the 1024-byte
static buffer for long inputs. Add the same length check before copying.

Co-authored-by: Brandon Arrendondo <brandon.arrendondo@bissell.com>
2026-06-24 16:41:19 +02:00
83cb4cc210 [rlgl] Fix matrix stack overflow in rlPushMatrix() (#5935)
The RL_MAX_MATRIX_STACK_SIZE check logged an error but did not return, so
RLGL.State.stack[stackCounter] = *currentMatrix still executed when the stack
was full -- writing one element past stack[RL_MAX_MATRIX_STACK_SIZE] and
corrupting the adjacent RLGL.State members (stackCounter, etc.). rlPopMatrix()
already guards the symmetric underflow case; add the missing early return.

Co-authored-by: Brandon Arrendondo <brandon.arrendondo@bissell.com>
2026-06-24 16:38:08 +02:00
Ray
d1a14bee5d Update rmodels.c 2026-06-24 10:38:20 +02:00
eu
ba3b8f8370 Add comments for GenMeshTorus (#5934) 2026-06-24 10:36:30 +02:00
Ray
962bbfc6bf Revert "Implemented JS output format. (#5929)"
This reverts commit b00e465deb.
2026-06-23 09:24:06 +02:00
b00e465deb Implemented JS output format. (#5929) 2026-06-23 00:55:08 +02:00
db0870f31f Update supported version for Jai to 6.0 (#5928)
Update supported version for Jai to 6.0
2026-06-19 23:09:30 +02:00
Ray
87a6e9693c Format tweaks 2026-06-19 12:27:02 +02:00
aaacda6e14 Remove commit message from CMakeLists.txt (#5924)
Remove ambiguous footnote that would be better suited for the commit log.
2026-06-17 16:55:51 +02:00
Ray
f9c41a0866 Reemove trailing spaces 2026-06-16 21:12:12 +02:00
Ray
fa8aca8789 Update rlgl.h 2026-06-16 13:06:16 +02:00
Ray
efef4e31dd REVIEWED: LoadImageFromTexture() for Wasm https://github.com/raysan5/rguistyler/issues/10
Let's see if it breaks on some other platform...
2026-06-16 13:01:50 +02:00
Ray
3973766b84 Update rexm.c 2026-06-15 23:19:31 +02:00
Ray
4d2b1d51e4 Update rcore_desktop_glfw.c 2026-06-15 23:19:27 +02:00
Ray
8713741782 Update rcore.c 2026-06-13 09:21:39 +02:00
ac6526b731 [rcore] Fix `FileCopy` doesn't copy file when directory exists (#5920)
* Fix FileCopy result

* fix code style
2026-06-13 09:18:41 +02:00
94897c4eca [platform/RGFW] update rgfw (#5919)
* update rgfw + platform v1

* added drop events

* updates
2026-06-10 08:56:07 +02:00
Dz
444cc22633 update BINDINGS.md (#5917)
Dart binding for Raylib: support hooks
2026-06-09 14:57:52 +02:00
Ray
aeea213873 Update raudio.c 2026-06-09 13:19:19 +02:00
8d31d0c3cc remove extra drflac_free (#5916) 2026-06-09 13:16:41 +02:00
Ray
9bd3d84f3d Update models_basic_voxel.c 2026-06-07 22:59:20 +02:00
Ray
04b66f1965 Merge branch 'master' of https://github.com/raysan5/raylib 2026-06-07 22:54:16 +02:00
Ray
7c1b9d0a32 Update textures_image_drawing.c 2026-06-07 22:53:36 +02:00
02869da279 rlparser: update raylib_api.* by CI 2026-06-07 19:53:22 +00:00
Ray
aebfd788c7 WARNING: BREAKING: REDESIGNED: ImageDraw() API, align with DrawTexture() 2026-06-07 21:53:07 +02:00
26d82cf55d rlparser: update raylib_api.* by CI 2026-06-07 19:51:18 +00:00
Ray
d9335f6a95 ADDED: TODO: ImageDrawCircleGradient() 2026-06-07 21:51:02 +02:00
0e7cc36567 rlparser: update raylib_api.* by CI 2026-06-07 19:29:40 +00:00
Ray
e57663c937 Update raylib.h 2026-06-07 21:29:26 +02:00
23433fe2dc rlparser: update raylib_api.* by CI 2026-06-07 19:29:06 +00:00
Ray
fefb9f4428 Merge branch 'master' of https://github.com/raysan5/raylib 2026-06-07 21:27:07 +02:00
Ray
68c4b8a60f Removed old compatibility hack 2026-06-07 21:26:59 +02:00
33b6f0f3a4 rlparser: update raylib_api.* by CI 2026-06-07 19:26:49 +00:00
Ray
ca0ba55050 Reviewed parameter names, added comment about order 2026-06-07 21:26:32 +02:00
Ray
236618f87b Reorder functions by drawing vertex/sides 2026-06-07 21:06:53 +02:00
f5ea52a2b8 rlparser: update raylib_api.* by CI 2026-06-07 16:49:09 +00:00
Ray
6a6daad739 Merge branch 'master' of https://github.com/raysan5/raylib 2026-06-07 18:48:50 +02:00
Ray
4724e5fec3 ADDED: ImageDrawLineStrip() 2026-06-07 18:48:41 +02:00
Ray
d3d1b0cbcc ADDED: DrawCircleLinesEx(), simpler naming than DrawRing() 2026-06-07 18:48:16 +02:00
20aa6cb764 rlparser: update raylib_api.* by CI 2026-06-07 16:47:29 +00:00
Ray
a41bb7c07a Reorder shapes drawing API functions by number of vertices
NOTE: Consistency between shapes and Image drawing functionality is being aligned (as much as possible)
2026-06-07 18:47:14 +02:00
Ray
53ccae09cc Merge branch 'master' of https://github.com/raysan5/raylib 2026-06-07 18:43:00 +02:00
Ray
869251e590 REVIEWED: Parameter name, shorter 2026-06-07 18:42:50 +02:00
45f1af2bde rlparser: update raylib_api.* by CI 2026-06-07 16:42:02 +00:00
Ray
15d25242be REVIEWED: Comments to be more descriptive 2026-06-07 18:41:44 +02:00
22509ab2d4 Update ocaml bindings version (#5912) 2026-06-06 23:30:21 +02:00
796e1ad22a Use CORE.Input.Keyboard.exitKey instead of KEY_ESCAPE (#5911)
... in rcore_desktop_win32 when handling window closing
2026-06-06 22:25:48 +02:00
acfcf2f1d1 [rmodels] Fix minimum rings validation in DrawCapsule and DrawCapsuleWires (#5909)
Ensure rings is at least 1 to prevent rendering issues or crashes when 0 or negative values are passed.
2026-06-06 19:47:57 +02:00
ca46387b64 use inverse bind matrices for bind pose in gltf loader (#5832) 2026-06-05 09:27:05 +02:00
fd79b81918 Fix memory leak in UnloadModel() (#5907) 2026-06-04 23:32:52 +02:00
9ace148917 rlparser: update raylib_api.* by CI 2026-06-03 19:07:28 +00:00
Ray
a85c9f4898 REVIEWED: File*() functions for consistent return result value
NOTE: `SaveFile*()` still follows original convention, returning true on success...
2026-06-03 21:07:07 +02:00
fadcd1fac5 rlparser: update raylib_api.* by CI 2026-06-03 19:05:06 +00:00
Ray
1a4445f510 Renamed parameters to align with internal implementations 2026-06-03 21:03:47 +02:00
fc824ff6d4 rlparser: update raylib_api.* by CI 2026-06-03 19:03:21 +00:00
Ray
2c690425c9 Reviewed comments, remove article usage 2026-06-03 21:02:59 +02:00
Ray
ee71f0f870 REVIEWED: GetPixelColor() const 2026-06-03 21:00:34 +02:00
e8650c1b8e rlparser: update raylib_api.* by CI 2026-06-03 18:16:31 +00:00
Ray
cef7718468 RENAMED: Some Rectangle parameters with more descriptive names 2026-06-03 20:16:12 +02:00
Ray
895154bcb2 Clarify that GPU_SKINNING is not enabled by default and the requirements 2026-06-01 21:00:17 +02:00
Ray
f421b74c0f Revert "Enable GPU skinning for GL 3.3+, (#5902)"
This reverts commit f1d602029c.
2026-06-01 20:42:48 +02:00
Ray
90edc3b0a5 Update models_animation_blending.c 2026-06-01 20:42:38 +02:00
f1d602029c Enable GPU skinning for GL 3.3+, (#5902)
only do GPU skinning if the shader supports bone IDs.
2026-06-01 20:25:09 +02:00
10a889c482 [rlsw] Replace SW_TEXTURE_REPEAT_POT_FAST with SW_SUPPORT_NPOT_TEXTURE (#5901)
* replace `SW_TEXTURE_REPEAT_POT_FAST` by `SW_SUPPORT_NPOT_TEXTURE`

* tweak `SW_SUPPORT_NPOT_TEXTURE` comment

* remove extra comment
2026-05-30 19:44:45 +02:00
b7f50b2fb6 [rtextures] ImageDrawLine() rounding and length fix (#5896)
* Fixing ImageDrawLine to be more pixel accurate

Changes to ImageDrawLine() function.
. Added one pixel to the length of a line so it wont draw lines one pixel short.
. Changed rounding by adding 0.5 in 16 bit fixed point to 'j' in for-loop.

* Changed ImagDrawLine to be more acurate
2026-05-30 19:39:16 +02:00
Ray
2ee6a76464 REVIEWED: GetWindowHandle(), to be consistent between backends, fix #5885
Returns the underlying window handle for platforms with some windowing system.
2026-05-30 12:20:58 +02:00
f0d3e9a5c8 Security fixes (rcore_desktop_win32.c) (#5899)
* Security fixes in rcore_desktop_win32.c

* Avoid calling strlen() twice
2026-05-30 08:49:34 +02:00
7c284cc5bc Fix warning about unused variables (#5898) 2026-05-30 08:47:35 +02:00
7b96144716 [rcore] GetCurrentMonitor(), fix for integer overflow in distance calculation (#5842)
* Fix signed integer overflow in GetCurrentMonitor distance calc

* Revert "Fix signed integer overflow in GetCurrentMonitor distance calc"

This reverts commit e0083bc7fe.

* fix GetCurrentMonitor() distance calc overflow

* fix GetCurrentMonitor() distance calc
2026-05-29 18:18:18 +02:00
81c7cb6527 [rmodels] Fix glTF skinning when joints have non-joint parent nodes (#5876)
* [rmodels] Fix glTF skinning when joints have non-joint parent nodes

Some glTF exporters (notably wow.export, but also various other DCC pipelines) place skin joints under intermediate non-joint transform nodes that carry part of the bind-pose offset. raylib's existing LoadBoneInfoGLTF and LoadModelAnimationsGLTF only inspected a joint's immediate parent and only sampled joint-local TRS, so any transform stored on an intermediate non-joint ancestor was silently dropped, producing exploded or stretched meshes at runtime.

Two surgical changes:

LoadBoneInfoGLTF: walk the parent chain past any non-joint ancestors when looking up parentIndex, instead of comparing only against node.parent. Joints whose direct parent is a non-joint were previously treated as skeleton roots.

LoadModelAnimationsGLTF: precompute a per-joint extOffset matrix that bakes in the static TRS contribution of any intermediate non-joint nodes between the joint and its nearest joint ancestor. Apply it to each frame's joint TRS before BuildPoseFromParentJoints so the per-frame world transforms match the bind-pose world transforms (LoadGLTF already used cgltf_node_transform_world for bindPose, so this aligns the two code paths).

The replaced root-only worldTransform adjustment is a strict subset of the new per-joint extOffset machinery, so it has been removed.

Spec-compliant files (the six skeletal-skinning .glb examples shipped with raylib) render bit-identically before and after; previously broken files (e.g. wow.export's babyoctopus.gltf) now match the reference rendering from f3d, the Khronos sample viewer, and three.js.

* Resolve review: NULL-check joint offset allocation, fail fast

[rmodels] Address review feedback on glTF joint offset handling

Resolve the open review points raised on PR #5876 for the per-joint
extOffset precompute in LoadModelAnimationsGLTF.

* NULL check: validate the extOffset RL_MALLOC result before use, which
  was previously missing.

* Fail-fast handling: detect the allocation failure at its source and
  abort animation loading (log a warning, free resources, return NULL)
  instead of propagating a NULL pointer into the per-frame loop.

* Brace formatting: expand the collapsed one-line joint-match check
  (if (...) { isJoint = true; break; }) into raylib's standard Allman
  brace style.

* Readability: break the deeply nested MatrixMultiply(MatrixMultiply(...))
  into named nodeScale/nodeRotation/nodeTranslation/nodeTransform locals,
  mirroring the existing S/R/T composition later in the function.

* Spacing/line breaks: add blank lines within the precompute block to
  match the surrounding code style.
2026-05-29 18:17:04 +02:00
186d3ce9fb [CMake] Properly remove raudio.c and rmodels.c if they're disabled modules (#5878)
* only build raudio.c in cmake if it's still enabled

* only compile rmodels if it's supported
2026-05-29 18:16:17 +02:00
e7edb181dc cmake: Reduce minimum CMake version from 3.25 to 3.22 (#5890)
There isn't anything in 3.25 that we actually need, so we can reduce the minimum requirement. 3.22 is commonly available across many package managers.

For a list of the changes in `FetchContent`, see:
https://cmake.org/cmake/help/latest/module/FetchContent.html
2026-05-27 09:20:11 +02:00
Ray
ef8b3e6195 Update rlgl.h 2026-05-26 20:46:56 +02:00
7f9ded7642 [makefile] ANDROID_ARCH check (#5888) 2026-05-26 18:13:58 +02:00
34b06ca587 Update BINDINGS.md (#5887) 2026-05-25 16:05:20 +02:00
4d845608b8 Update listed Raylib version for zig bindings (#5886)
As per the README at https://github.com/raylib-zig/raylib-zig, raylib-zig now supports raylib 6.0
2026-05-25 08:32:52 +02:00
Ray
eaf32c83bf REXM: Latest w64devkit supports make directly, simplifying code to avoid mingw32-make 2026-05-25 00:26:26 +02:00
808e6b9b20 Raylib-lua version to 5.5 (#5884)
raylib-lua from 5.0 to 5.5 in bindings.
2026-05-24 17:36:12 +02:00
7dd72e7328 rlparser: update raylib_api.* by CI 2026-05-24 07:25:01 +00:00
Ray
f8270483e1 Merge branch 'master' of https://github.com/raysan5/raylib 2026-05-24 09:24:33 +02:00
Ray
f17babfe8a REVIEWED: #5879 2026-05-24 09:24:26 +02:00
f65d5ad7a9 rshapes: fix auto segment rounded-corner math and rounding (#5883) 2026-05-24 08:55:08 +02:00
Ray
0d78f10161 Reviewed comments formating 2026-05-20 09:16:16 +02:00
7d5b61ce01 [rlsw][SEGFAULT] Fix triangle and quad spans applying pixels out of bounds (#5849)
* fix triangle and quad spans applying pixels out of bounds

* remove off by one errors on x/y LoopMax

* apply the RASTER_QUAD offset at the loop start so it increments correctly

* fix missing endif

* remove include guard to allow dyMin usage

* early exit if nothing to draw on a span

* incorporate dxStart into xSubstep to make xOffset calculate a single time

* remove ghost comment

* early exit for quads, with a float cast on the left and top distance calculation

* remove duplicate xLoopEnd
2026-05-20 09:12:20 +02:00
Ray
b48933b096 Merge branch 'master' of https://github.com/raysan5/raylib 2026-05-19 18:59:30 +02:00
Ray
fd1dfd7d65 ADDED: rprand_get_value_raw() 2026-05-19 18:59:23 +02:00
be56f2c524 [rcore][GLFW] Fix GetClipboardImage() creating new connection under X11 (#5871)
* Improve GetClipboardImage implementation under X11

* Remove code for creating new connection, handle selection in GLFW connection instead.

* `GetClipboardImage()`: Small fix to remove unnecessary boolean
2026-05-19 18:57:42 +02:00
d31c10a01e Adjust segment calculation in DrawRectangleRounded to be consistent with DrawRectangleRoundedLinesEx (#5875) 2026-05-19 18:48:28 +02:00
c04e57399a Fix compilation for -DPLATFORM=RGFW (#5870)
When compiling with
cmake -S . -B build-desktop-rgfw -DPLATFORM=RGFW -DCMAKE_BUILD_TYPE=Release
cmake --build build-desktop-rgfw

these errors appeared:
raylib/examples/others/raylib_opengl_interop.c💯5: error: unknown type name ‘GLuint’
  100 |     GLuint vao = 0;
[etc]
2026-05-15 17:40:26 +02:00
6c090f6193 Fix build.zig building examples all the time (#5869) 2026-05-15 17:39:27 +02:00
Ray
5ca45bce37 Update rcore.c 2026-05-14 20:05:25 +02:00
Ray
729327a078 Update .gitignore 2026-05-14 20:05:21 +02:00
ea76845ecb [cmake]: remove GLFW_BUILD warnings for when platform is SDL (#5865) 2026-05-14 13:02:38 +02:00
5506aed190 BINDINGS.md: update golang binding to v6.0 (#5866) 2026-05-14 13:00:40 +02:00
Ray
43366d1c6a Some formatting tweaks 2026-05-13 09:28:08 +02:00
Ray
f35f4b9fad REVIEWED: GetTime(), small addition for RPI Pico 2 2026-05-13 09:17:04 +02:00
Ray
c4b4fcc17e Format review 2026-05-13 09:16:29 +02:00
Ray
fbf132d1d1 Use rlgl provided interface instead of rlsw direct access 2026-05-13 09:16:19 +02:00
Ray
e274c195af Update rcore.c 2026-05-13 09:15:50 +02:00
fd28dc5644 [rtext] add warning for loadfontex/loadfontfrommemory (#5864)
* add warning for loadfontex/loadfontfrommemory

* bump to re-run build tests
2026-05-13 08:56:13 +02:00
Ray
5aa3de194c Updated miniaudio warnings with emscripten 2026-05-12 20:33:20 +02:00
9400199b80 [rcore][RGFW] Add fullscreen behaviour on size 0 window creation (#5859)
* port glfw's behaviour on size 0 window creation to rgfw

* updates with change suggestions

* don't do the FLAG_FULLSCREEN_MODE check twice for no reason

---------

Co-authored-by: CrackedPixel <5776225+CrackedPixel@users.noreply.github.com>
2026-05-11 23:25:00 +02:00
Ray
200d344dee Merge branch 'master' of https://github.com/raysan5/raylib 2026-05-10 19:31:22 +02:00
Ray
094edcd32e Update Makefile 2026-05-10 19:31:19 +02:00
a005a044da [rcore_android] Restore face-button input on Android gamepads (#5824)
The KEYBOARD-source veto added in #5439 drops face-button key
events that arrive with both AINPUT_SOURCE_KEYBOARD and
AINPUT_SOURCE_GAMEPAD set on the source bitmask. Confirmed
reproducible on GameSir X2 Type-C and 8BitDo Ultimate Bluetooth,
both reporting source 0x501 on every face-button key event.

This source-bit pattern is general AOSP behaviour since Android
3.2 (commit 6f2fba4 in frameworks/base, Feb 2011): EventHub adds
InputDeviceClass::KEYBOARD to any device whose evdev keyBitmask
claims gamepad buttons (BTN_JOYSTICK..BTN_DIGI), and
KeyboardInputMapper::getEventSource stamps the resulting
KEYBOARD|GAMEPAD source on every outgoing key event.

Use AndroidTranslateGamepadButton(keycode) as the discriminator
instead. Recognised gamepad keycodes route to the gamepad path;
unknown keycodes fall through to the keyboard handler.

Assisted-by: Claude:claude-opus-4-7
2026-05-10 19:20:35 +02:00
ae315eecb9 added win32 to cmake + examples (#5855) 2026-05-10 19:09:24 +02:00
dcb0ca5d14 [raudio]: free converterResidual in UnloadSoundAlias to prevent leak (#5857)
The example audio_sound_multi was leaking memory every single time the spacebar was pressed.

```c
Direct leak of 576 byte(s) in 9 object(s) allocated from:
    #0 0x758a41019447 in calloc (/usr/lib/liblsan.so.0+0x19447) (BuildId: 8ee115309adc591d231c961c43d245cfa68d9aa7)
    #1 0x562dfbd2c4f3 in LoadAudioBuffer (/home/peter/raylib/examples/audio/audio_sound_multi+0xfa4f3) (BuildId: ea2a6f45d724abeccf904143a32012266f259f93)
```

This patch fixes that leak.
2026-05-10 15:01:38 +02:00
07b729d5d6 fix: check fread return value in jar_mod_load_file (#5840) 2026-05-09 18:55:02 +02:00
cd4599b447 Update BINDINGS.md (#5850) 2026-05-09 18:48:10 +02:00
Ray
b2ea5eae5e REVIEWED: long long usage in all raylib, minimize
REVIEWED: Using `long long` format instead of `long long int`, more consistent with the `short` alternative for smaller `int`, instead of `short int`
2026-05-08 22:59:55 +02:00
mjt
29ff1f02e9 Update Makefile comment (#5846) 2026-05-08 20:19:08 +02:00
d840a100a7 [CMake] Add configure-time test for libatomic requirement (#5847)
CMake now checks if -latomic is required for 64-bit atomics, and links
it if it's required. Miniaudio is the only thing in raylib that needs
it, so it's put behind SUPPORT_MODULE_RAUDIO.
2026-05-08 20:16:45 +02:00
95bfa196fd [cmake] Fix config.h parsing into cmake options (#5844)
Parse SUPPORT_ defines from src/config.h by their actual 0/1 values so CUSTOMIZE_BUILD exposes the correct defaults. Apply INCLUDE_EVERYTHING explicitly when registering dependent options.
2026-05-08 10:08:09 +02:00
Ray
aceb8ce3a8 Re-enable GLFW_LINUX_ENABLE_WAYLAND flag by default #5816
Wayland should be more stable at this point...
2026-05-07 15:24:08 +02:00
Ray
33e889907e ADDED: GL_SHADING_LANGUAGE_VERSION for swGetString() 2026-05-07 15:20:24 +02:00
Ray
61537200c0 Code cleaning 2026-05-07 15:18:42 +02:00
080f5c94bd [rlsw][rcore_drm] Silence warnings when using PLATFORM_DRM and GRAPHICS_API_OPENGL_SOFTWARE (#5839)
* fix warnings: goto label not used outside of SW_ENABLE_DEPTH_TEST

* comment out x coordinates that aren't used in SW_RASTER_TRIANGLE

* silence warnings: unused DrmModeConnector functions in rcore_drm.c when using GRAPHICS_API_OPENGL_SOFTWARE
2026-05-07 15:17:20 +02:00
7207c03c72 [rlsw] ESP32 optimizations (#5827)
* [rlsw] Add sw_rcp helper using Xtensa recip0.s for hot-path divisions

Adds a `sw_rcp(x)` inline reciprocal that on Xtensa (ESP32 / ESP32-S3
LX6/LX7) emits a `recip0.s` seed plus two Newton-Raphson refinement
steps -- 1-ULP accurate in ~7 instructions, all in FPU registers.
On every other target it expands to plain `1.0f/x`, so generated code
is byte-identical to before for non-Xtensa builds.

Replaces the hot-path `1.0f/x` calls that were previously compiling to
the `__divsf3` software helper on Xtensa:

  - perspective divide (1/w) in triangle clip-and-project (PCT and PC paths)
  - line and point clip-and-project NDC conversion
  - triangle span setup: dxRcp, blockLenRcp, wRcpA, wRcpB
  - triangle scanline setup: h02Rcp, h01Rcp, h12Rcp
  - axis-aligned quad: wRcp, hRcp
  - line rasterizer: stepRcp

Other `1.0f/x` uses (matrix translate/normalize, texture init `tx`/`ty`,
sw_matrix_rotate inverse-length) are not on the per-pixel hot path and
are left untouched.

Measured on ESP32-S3 @ 240 MHz, R5G6B5 240x240, textured 3D model:
contributes to a ~10-15% rasterization speedup.

Made-with: Cursor

* [rlsw] Use ESP-DSP for 4x4 matrix multiply and per-vertex MVP transform

Adds an opt-in ESP-DSP code path for ESP32 / ESP32-S3 builds. ESP-DSP is
ESP-IDF's official optimized math library and ships hand-vectorized
kernels that beat the scalar implementations on Xtensa.

Two integration points:

  1. `sw_matrix_mul_rst` -> `dspm_mult_4x4x4_f32` for any 4x4*4x4 multiply
     (used for MVP build, gluLookAt, push/multiply, etc.). rlsw stores
     matrices column-major and ESP-DSP reads row-major; the comment on the
     call site explains why the flat-buffer call still produces the
     correct column-major product (transpose-of-transposes equivalence).

  2. `sw_immediate_push_vertex` -> `dspm_mult_4x4x1_f32` for the per-vertex
     clip-space transform. Because ESP-DSP expects a row-major matrix in
     this case, a row-major copy `matMVP_rm[16]` is maintained alongside
     `matMVP` and refreshed once per `isDirtyMVP` rebuild in
     `sw_immediate_begin`. Cost is 16 scalar copies per matrix update,
     amortized over thousands of vertices per frame.

Detection is **opt-in** via `SW_USE_ESP_DSP` so existing ESP-IDF projects
that don't depend on the `esp-dsp` component keep building unchanged.
A user enables it from CMakeLists.txt (or anywhere before including
rlgl.h):

    target_compile_definitions(${COMPONENT_LIB} PRIVATE SW_USE_ESP_DSP=1)

and adds the dependency to `idf_component.yml`:

    espressif/esp-dsp: "^1.4.0"

Measured on ESP32-S3 @ 240 MHz, R5G6B5 240x240, textured 3D model:
contributes meaningfully to the overall frame-time improvement
(combined with sw_rcp).

Made-with: Cursor

* [rlsw] Add SW_TEXTURE_REPEAT_POT_FAST opt-in for POT bitmask wrap

Adds an opt-in compile-time flag that replaces the SW_REPEAT wrap chain
with a bitmask (`x & (size-1)`) for power-of-two textures. NPOT textures
keep using the original `sw_fract` / signed-modulo paths via a runtime
`(size & (size-1)) == 0` check, so SW_REPEAT remains correct for them.

Affects two samplers:

  - `sw_texture_sample_nearest`: drops the `floorf` + multiply + cast for
    POT textures in REPEAT mode (saves a software call on Xtensa).
  - `sw_texture_sample_linear`: replaces the `(x % w + w) % w` two-step
    modulo (a software divide on Xtensa) with a single bitwise AND for
    POT textures in REPEAT mode. Two's-complement int wrap covers
    negative coordinates correctly.

Off by default: for POT textures sampled with negative UVs, bitmask wrap
can differ from `sw_fract` wrap by one texel at the boundary. That is
imperceptible at typical resolutions but technically a behavior change,
so existing users get bit-for-bit identical output. Opt in if you
control your asset UVs and want the speedup:

    #define SW_TEXTURE_REPEAT_POT_FAST

This addresses the long-standing TODO comment "If the textures are POT,
avoid the division for SW_REPEAT" in `sw_texture_sample_linear`.

Made-with: Cursor
2026-05-06 12:38:52 +02:00
Ray
cf9f27db54 Update raymath.h 2026-05-02 09:09:50 +02:00
Ray
0a2b81b128 Update rcore_web.c 2026-05-02 09:09:40 +02:00
05c15c8ba7 SDL: Use precise mouse wheel values (#5830) 2026-05-01 19:29:51 +02:00
d768dae402 [build] Shift __cplusplus check to a higher level for bool type define (#5804)
* Adds a missing macro definition check

* Shifts __cplusplus check to a higher level for bool define

* Copy same change to rgestures.h and rlgl.h

* Fixes float comparison issues in raymath functions

* Revert "Fixes float comparison issues in raymath functions"

This reverts commit a266d0bbaa.
2026-04-29 18:02:49 +02:00
d580c47504 [raymath.h] Add missing (float * Vector) operator overloads (#5815) 2026-04-29 17:49:23 +02:00
7b7ded566c Fix directory navigation in core_directory_files (#5823)
Co-authored-by: zhanlong9890 <lichuang59559890@gmail.com>
2026-04-29 17:45:25 +02:00
Ray
d9427b1e6f REVIEWED: Avoid static variable floating around and include it to PlatformData struct 2026-04-29 17:42:51 +02:00
da55d9067c added NPOT check to rlLoadTexture to match rlGenTextureMipmaps and WebGL 1.0 standard (#5820) 2026-04-29 08:43:50 +02:00
e5702a716f Update DenoRaylib550 to Deno-Raylib with version 6.0 (#5821) 2026-04-29 08:41:48 +02:00
Ray
2dd8d7e8b1 Update rcore_desktop_sdl.c 2026-04-29 01:08:16 +02:00
168e2c43d0 fix(rcore): correct string boundary handling (#5812)
Co-authored-by: Huang Zhaobin <xcpky@proton.me>
2026-04-29 00:18:33 +02:00
638c1cb339 Update BINDINGS.md (#5819)
Raylib 6.0 support has been released for C3
2026-04-28 23:10:15 +02:00
6a430eb834 [examples] Update build.zig to support wasm examples (#5811)
* Include resource preloads when building wasm examples with Zig.

List of resources derived from examples/Makefile.Web

* Move resource list to zon file to reduce build.zig bloat
2026-04-28 12:26:30 +02:00
3c82b48b1f Update BINDINGS.md to reflect raylib4fb project supporting 6.0 (#5813) 2026-04-27 22:27:13 +02:00
Ray
72a341a37f Update rtext.c 2026-04-27 12:34:43 +02:00
79d5353cfd rlparser: update raylib_api.* by CI 2026-04-27 09:48:08 +00:00
Ray
98efce4b0d WARNING: RENAMED: GetSplinePointBezierQuad() to GetSplinePointBezierQuadratic()
Consistent with similar spline functions and avoid confusion with `Quad` related functions.
2026-04-27 11:47:48 +02:00
Ray
c9c26d8071 REVIEWED: ImageColorContrast() parameter type, consistent with other Image*() functions 2026-04-27 11:46:43 +02:00
Ray
0e68f812b5 WARNING: REDESIGNED: ImageDrawRectangleLines(), consistency with DrawRectangleLines()
ADDED: `ImageDrawRectangleLinesEx()`
2026-04-27 11:45:50 +02:00
Ray
2752837839 REVIEWED: UpdateSound(), missleading parameter name! 2026-04-27 11:44:14 +02:00
a627cd5b65 rlparser: update raylib_api.* by CI 2026-04-27 09:43:37 +00:00
Ray
361dcb2a1f WARNING: REVIEWED: DrawCapsule()/DrawCapsuleWires() parameter order
for consistency with `DrawSphere*()`
2026-04-27 11:42:53 +02:00
5082f5a813 rlparser: update raylib_api.* by CI 2026-04-27 09:40:32 +00:00
Ray
3d2008c70b RENAMED: ImageDrawTriangleEx() to ImageDrawTriangleGradient()
For consistency with the new `DrawTriangleGradient()`
2026-04-27 11:40:14 +02:00
a685b812d9 rlparser: update raylib_api.* by CI 2026-04-27 09:38:41 +00:00
Ray
3b70f83c7d Update raylib.h 2026-04-27 11:38:23 +02:00
Ray
a28b924f94 Merge branch 'master' of https://github.com/raysan5/raylib 2026-04-27 11:38:00 +02:00
Ray
636269f6af ADDED: DrawTriangleGradient() 2026-04-27 11:37:48 +02:00
826ca42d83 rlparser: update raylib_api.* by CI 2026-04-27 09:36:49 +00:00
Ray
620b21bfce REVIEWED: Several functions const correctness 2026-04-27 11:36:32 +02:00
52dc7658da rlparser: update raylib_api.* by CI 2026-04-27 09:35:19 +00:00
Ray
06621eb3b7 REVIEWED: Comments for consistency and spelling 2026-04-27 11:34:58 +02:00
Ray
3b9ee2e9f3 Merge branch 'master' of https://github.com/raysan5/raylib 2026-04-27 10:23:44 +02:00
Ray
6ae16c9895 REVIEWED: FileMove(), additional security checks 2026-04-27 10:23:28 +02:00
aa1100817a rlparser: update raylib_api.* by CI 2026-04-27 08:23:03 +00:00
Ray
725c8b57ae Merge branch 'master' of https://github.com/raysan5/raylib 2026-04-27 10:22:42 +02:00
Ray
00f3af78e3 UPDATED: Set version to raylib 6.1-dev to avoid confusions 2026-04-27 10:22:31 +02:00
3d3e6996b0 rlparser: update raylib_api.* by CI 2026-04-27 08:22:08 +00:00
Ray
47bb749ce9 RVIEWED: Comment to avoid invalid json gneration #5809 2026-04-27 10:21:50 +02:00
ba72d25867 [examples] Improve core_smooth_pixelperfect (#5803)
* Improve smooth pixel-perfect example: add overscan and smoothing toggles

* Add render size
2026-04-27 10:08:12 +02:00
8e82249f65 Update to latest DR libs to fix some warnings in MSVC (#5808) 2026-04-26 20:16:35 +02:00
dff07d020c Fix FileMove from delete file if FileCopy did not work (#5806) 2026-04-26 20:15:33 +02:00
Ray
0f98d78a67 Update README.md 2026-04-25 21:02:34 +02:00
c2ea6a38b5 Fix: Add NULL check to CheckCollisionLines (#5802) 2026-04-25 19:53:34 +02:00
ccc0d7452a chore(bindings): Update binding version for raylib-d to 6.0 (#5799) 2026-04-25 14:49:29 +02:00
386eabb932 Update sola-raylib Raylib supported version to 6 (#5795)
I just published crate version 6.0.0 which supports Raylib 6's new
functions and platforms.
2026-04-24 22:22:34 +02:00
4ee2013169 various rlparser fixes (#5794) 2026-04-24 21:08:20 +02:00
Ray
d892f3ba4a Update shapes_ball_physics.c 2026-04-24 15:11:39 +02:00
61dd488b76 [examples] Move window for ball shake (#5791) 2026-04-24 15:09:02 +02:00
Ray
4cae4ba9d5 REVIEWED: IsModelValid() #5780 2026-04-24 14:03:59 +02:00
Ray
07a056441a Update raudio.c 2026-04-24 13:59:41 +02:00
Ray
254953611e Update rcore.c 2026-04-24 13:58:52 +02:00
5608460901 add missing UnloadFileData() (#5787)
Adds missing function necessary for using the module as a standalone library.
2026-04-24 13:57:20 +02:00
3b23200b85 Update BINDINGS.md to add vala-vapi version update (#5789) 2026-04-24 13:56:30 +02:00
1c5cd35372 Add sola-raylib to BINDINGS.md (#5790)
Rust bindings and wrapper library. A maintained fork of raylib-rs with
bug fixes in the 5.5.x series and upcoming support for 6.0.
2026-04-24 13:55:59 +02:00
e9caf5a981 BINDINGS: Update raylib-cpp version to 6.0 (#5785)
The C++ wrapper, [raylib-cpp](https://github.com/RobLoach/raylib-cpp), now works with raylib 6.0:
https://github.com/RobLoach/raylib-cpp/releases/tag/v6.0.0
2026-04-23 15:01:58 +02:00
de8419cc8b removed web_basic_window mentions (#5782) 2026-04-23 13:28:34 +02:00
f220848896 Update pascal binding (#5784)
* Update BINDINGS.md

added support for Delphi

* Update BINDINGS.md
2026-04-23 13:27:42 +02:00
302 changed files with 54496 additions and 35966 deletions

View File

@ -44,7 +44,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@master
with:
submodules: recursive
@ -71,7 +71,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@ -90,7 +90,7 @@ jobs:
cmake --build . --config $BUILD_TYPE
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
uses: github/codeql-action/analyze@v4
with:
category: "/language:${{matrix.language}}"
upload: false
@ -99,7 +99,7 @@ jobs:
# Filter out rules with low severity or high false positve rate
# Also filter out warnings in third-party code
- name: Filter out unwanted errors and warnings
uses: advanced-security/filter-sarif@v1
uses: advanced-security/filter-sarif@v1.1
with:
patterns: |
-**:cpp/path-injection
@ -121,14 +121,14 @@ jobs:
output: ${{ steps.step1.outputs.sarif-output }}/cpp.sarif
- name: Upload CodeQL results to code scanning
uses: github/codeql-action/upload-sarif@v2
uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: ${{ steps.step1.outputs.sarif-output }}
category: "/language:${{matrix.language}}"
- name: Upload CodeQL results as an artifact
if: success() || failure()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: codeql-results
path: ${{ steps.step1.outputs.sarif-output }}

View File

@ -21,7 +21,7 @@ permissions:
jobs:
build:
permissions:
contents: write # for actions/upload-release-asset to upload release asset
contents: write # Required for actions/upload-release-asset to upload release asset
runs-on: windows-latest
strategy:
fail-fast: false
@ -82,7 +82,7 @@ jobs:
tar -czvf ${{ env.RELEASE_NAME }}.tar.gz ${{ env.RELEASE_NAME }}
- name: Upload Artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: ${{ env.RELEASE_NAME }}
path: |
@ -90,7 +90,7 @@ jobs:
!./build/${{ env.RELEASE_NAME }}.tar.gz
- name: Upload Artifact to Release
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v3
with:
files: ./build/${{ env.RELEASE_NAME }}.tar.gz
env:

View File

@ -36,7 +36,7 @@ jobs:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@master
- name: Create Build Environment
# Some projects don't allow in-source building, so create a separate build directory
@ -75,7 +75,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@master
- name: Create Build Environment
# Some projects don't allow in-source building, so create a separate build directory

View File

@ -22,7 +22,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@master
- name: Setup Environment
run: |

View File

@ -22,10 +22,10 @@ jobs:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@master
- name: Add MSBuild to PATH
uses: microsoft/setup-msbuild@v1
uses: microsoft/setup-msbuild@v3
- name: Build Library (MSVC16)
run: |

View File

@ -21,7 +21,7 @@ permissions:
jobs:
build:
permissions:
contents: write # for actions/upload-release-asset to upload release asset
contents: write # Required for actions/upload-release-asset to upload release asset
strategy:
fail-fast: false
max-parallel: 1
@ -112,7 +112,7 @@ jobs:
tar -czvf ${{ env.RELEASE_NAME }}.tar.gz ${{ env.RELEASE_NAME }}
- name: Upload Artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: ${{ env.RELEASE_NAME }}
path: |
@ -120,7 +120,7 @@ jobs:
!./build/${{ env.RELEASE_NAME }}.tar.gz
- name: Upload Artifact to Release
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v3
with:
files: ./build/${{ env.RELEASE_NAME }}.tar.gz
env:

View File

@ -21,7 +21,7 @@ permissions:
jobs:
build:
permissions:
contents: write # for actions/upload-release-asset to upload release asset
contents: write # Required for actions/upload-release-asset to upload release asset
runs-on: macos-latest
env:
@ -99,7 +99,7 @@ jobs:
tar -czvf ${{ env.RELEASE_NAME }}.tar.gz ${{ env.RELEASE_NAME }}
- name: Upload Artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: ${{ env.RELEASE_NAME }}
path: |
@ -107,7 +107,7 @@ jobs:
!./build/${{ env.RELEASE_NAME }}.tar.gz
- name: Upload Artifact to Release
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v3
with:
files: ./build/${{ env.RELEASE_NAME }}.tar.gz
env:

View File

@ -27,7 +27,7 @@ jobs:
uses: actions/checkout@master
- name: Setup emsdk
uses: mymindstorm/setup-emsdk@v14
uses: emscripten-core/setup-emsdk@v15
with:
version: 5.0.3
actions-cache-folder: 'emsdk-cache'
@ -69,7 +69,7 @@ jobs:
shell: cmd
- name: Upload Artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: ${{ env.RELEASE_NAME }}
path: |
@ -77,7 +77,7 @@ jobs:
!./build/${{ env.RELEASE_NAME }}.zip
- name: Upload Artifact to Release
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v3
with:
files: ./build/${{ env.RELEASE_NAME }}.zip
env:

View File

@ -21,7 +21,7 @@ permissions:
jobs:
build:
permissions:
contents: write # for actions/upload-release-asset to upload release asset
contents: write # Required for actions/upload-release-asset to upload release asset
runs-on: windows-latest
strategy:
fail-fast: false
@ -81,7 +81,7 @@ jobs:
# Setup MSBuild.exe path if required
- name: Setup MSBuild
uses: microsoft/setup-msbuild@v2
uses: microsoft/setup-msbuild@v3
if: matrix.compiler == 'msvc16'
- name: Build Library (MinGW-w64 32bit)
@ -140,7 +140,7 @@ jobs:
shell: cmd
- name: Upload Artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: ${{ env.RELEASE_NAME }}
path: |
@ -148,7 +148,7 @@ jobs:
!./build/${{ env.RELEASE_NAME }}.zip
- name: Upload Artifact to Release
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v3
with:
files: ./build/${{ env.RELEASE_NAME }}.zip
env:

81
.github/workflows/clang_tidy.yml vendored Normal file
View File

@ -0,0 +1,81 @@
name: Clang Tidy Lints
on:
workflow_dispatch:
permissions:
contents: read
concurrency:
group: clang-tidy-${{ github.ref }}
cancel-in-progress: true
jobs:
clang-tidy:
name: C lint
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v4
- name: Install clang-tidy 19
run: |
sudo apt-get update
sudo apt-get install --yes clang-tidy-19
- name: Run clang-tidy
shell: bash
run: |
checks='-*,
bugprone-assignment-in-if-condition,
bugprone-infinite-loop,
bugprone-misplaced-widening-cast,
bugprone-multiple-statement-macro,
bugprone-suspicious-memory-comparison,
bugprone-suspicious-memset-usage,
readability-duplicate-include,
readability-redundant-casting,
readability-simplify-boolean-expr'
lint_log="$(mktemp)"
filtered_log="$(mktemp)"
lint_pattern='\[(bugprone|readability)-[^]]+\]'
echo "Using clang-tidy:"
clang-tidy-19 --version
echo
echo "Running clang-tidy..."
# Capture everything silently. Do not use tee here.
find src \
-path 'src/external' -prune \
-o -type f -name '*.c' -exec \
clang-tidy-19 \
--quiet \
--checks="$checks" \
--header-filter='.*' \
--exclude-header-filter='(^|.*/)external/.*' \
{} -- \
-std=c11 \
-Isrc \
-isystem src/external \
\; >"$lint_log" 2>&1 || true
# Retain only selected lint warnings, then remove any remaining
# diagnostics whose path passes through an external directory.
grep -E "$lint_pattern" "$lint_log" |
grep -Ev '(^|/)([^/]+/\.\./)*external/' \
>"$filtered_log" || true
if [[ -s "$filtered_log" ]]; then
echo "clang-tidy found the following lint violations:"
echo
cat "$filtered_log"
echo
echo "::error::clang-tidy found lint violations."
exit 1
fi
echo "clang-tidy found no selected lint violations."

View File

@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@master
- name: Update parse files
working-directory: tools/rlparser

View File

@ -15,10 +15,10 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@master
- name: Setup emsdk
uses: mymindstorm/setup-emsdk@v14
uses: emscripten-core/setup-emsdk@v15
with:
version: 'latest'
actions-cache-folder: 'emsdk-cache'

6
.gitignore vendored
View File

@ -65,7 +65,7 @@ src/external/SDL3
# Emscripten
emsdk
# Ignore wasm data in examples/
# Ignore binaries generated in examples/
examples/**/*
!examples/**/*.*
!examples/**/*/
@ -125,8 +125,8 @@ build-*/
docgen_tmp/
# Tools stuff
tools/parser/rlparser.exe
tools/parser/rlparser
tools/rlparser/rlparser.exe
tools/rlparser/rlparser
tools/rexm/rexm.exe
tools/rexm/rexm

View File

@ -1,187 +1,218 @@
# raylib bindings and wrappers
Some people ported raylib to other languages in the form of bindings or wrappers to the library. Here is a list with all the ports available. Feel free to send a PR if you know of any binding/wrapper not in this list.
Some people ported raylib to other languages in the form of bindings or wrappers to the library. Here is a list with all the ports available. Feel free to send a PR if you know of any binding/wrapper not in this list or if it had been updated/archived.
# Recommendations for binding authors.
This is a set of recomendations and guidelines for binding authors, meant to help your binding be as useful as possible to your users.
* Binding should be reasonably up to date with the last release, out of date bindings may be removed from bindings.md
* Binding should expose all of raylib's API. This is to ensure compatibility with all raylib features, and allow your users to do everything in the target language they can do in C raylib.
* raylib.h
* raymath.h
* rcamera.h
* rlgl.h
* rgestures.h
* Bindings should expose the base API in order to match the C examples when possible.
* Bindings that expose additional 'high level' functions to make the binding more native to the host language, should also include the base C style API in addition to those other functions. This is requested in order to make it easier for people to understand the raylib API independent of the language being used.
* Bindings should have clear usage and setup instructions. Examples in the host language are highly recommended. You want your users to be able to get started right away.
* If a binding exists for a language, before making a new one, binding authors should try to work together on maintaining a single binding for a language, this is requested in order to prevent fragmentation and confusion for users.
* Instructions on how to build for web are highly recomeneed if the langauge supports it. This allows your bindings to be used for game jams :)
### Language Bindings
| Name | raylib Version | Language | License |
| :--------------------------------------------------------------------------------------- | :--------------: | :------------------------------------------------------------------: | :------------------: |
| [raylib](https://github.com/raysan5/raylib) | **6.0** | [C/C++](https://en.wikipedia.org/wiki/C_(programming_language)) | Zlib |
| [raylib-ada](https://github.com/Fabien-Chouteau/raylib-ada) | **5.5** | [Ada](https://en.wikipedia.org/wiki/Ada_(programming_language)) | MIT |
| [raylib-beef](https://github.com/Starpelly/raylib-beef) | **5.5** | [Beef](https://www.beeflang.org) | MIT |
| [raybit](https://github.com/Alex-Velez/raybit) | **5.0** | [Brainfuck](https://en.wikipedia.org/wiki/Brainfuck) | MIT |
| [raylib-c3](https://github.com/c3lang/vendor/tree/main/libraries/raylib55.c3l) | **5.5** | [C3](https://c3-lang.org) | MIT |
| [raylib-cs](https://github.com/raylib-cs/raylib-cs) | **5.5** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | Zlib |
| [Raylib-CsLo](https://github.com/NotNotTech/Raylib-CsLo) | 4.2 | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MPL-2.0 |
| [Raylib-CSharp-Vinculum](https://github.com/ZeroElectric/Raylib-CSharp-Vinculum) | **5.0** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MPL-2.0 |
| [Raylib-CSharp](https://github.com/MrScautHD/Raylib-CSharp) | **5.5** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MIT |
| [Raylib-cs.BleedingEdge](https://github.com/danilwhale/Raylib-cs.BleedingEdge) | **5.6-dev** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | Zlib |
| [cl-raylib](https://github.com/longlene/cl-raylib) | 4.0 | [Common Lisp](https://common-lisp.net) | MIT |
| [claylib/wrap](https://github.com/defun-games/claylib) | 4.5 | [Common Lisp](https://common-lisp.net) | Zlib |
| [claw-raylib](https://github.com/bohonghuang/claw-raylib) | **auto** | [Common Lisp](https://common-lisp.net) | Apache-2.0 |
| [raylib](https://github.com/fosskers/raylib) | 5.5 | [Common Lisp](https://common-lisp.net) | MPL-2.0 |
| [chez-raylib](https://github.com/Yunoinsky/chez-raylib) | **auto** | [Chez Scheme](https://cisco.github.io/ChezScheme) | GPLv3 |
| [chicken-raylib](https://github.com/meowstr/chicken-raylib) | 5.5 | [CHICKEN Scheme](https://wiki.call-cc.org) | MIT |
| [CLIPSraylib](https://github.com/mrryanjohnston/CLIPSraylib) | **auto** | [CLIPS](https://www.clipsrules.net/) | MIT |
| [raylib-cr](https://github.com/sol-vin/raylib-cr) | 4.6-dev (5e1a81) | [Crystal](https://crystal-lang.org) | Apache-2.0 |
| [ray-cyber](https://github.com/fubark/ray-cyber) | **5.0** | [Cyber](https://cyberscript.dev) | MIT |
| [dart-raylib](https://gitlab.com/wolfenrain/dart-raylib) | 4.0 | [Dart](https://dart.dev) | MIT |
| [bindbc-raylib3](https://github.com/o3o/bindbc-raylib3) | **5.0** | [D](https://dlang.org) | BSL-1.0 |
| [dray](https://github.com/redthing1/dray) | **5.0** | [D](https://dlang.org) | Apache-2.0 |
| [raylib-d](https://github.com/schveiguy/raylib-d) | **5.5** | [D](https://dlang.org) | Zlib |
| [DenoRaylib550](https://github.com/JJLDonley/DenoRaylib550) | **5.5** | [Deno](https://deno.land) | MIT |
| [rayex](https://github.com/shiryel/rayex) | 3.7 | [elixir](https://elixir-lang.org) | Apache-2.0 |
| [raylib-elle](https://github.com/acquitelol/elle/blob/rewrite/std/raylib.le) | **5.5** | [Elle](https://github.com/acquitelol/elle) | GPL-3.0 |
| [raylib-factor](https://github.com/factor/factor/blob/master/extra/raylib/raylib.factor) | 5.5 | [Factor](https://factorcode.org) | BSD |
| [raylib4fb](https://github.com/mudhairless/raylib4fb) | **5.5** | [FreeBASIC](https://www.freebasic.net) | Zlib |
| [raylib-freebasic](https://github.com/WIITD/raylib-freebasic) | **5.0** | [FreeBASIC](https://www.freebasic.net) | MIT |
| [raylib.f](https://github.com/cthulhuology/raylib.f) | **5.5** | [Forth](https://forth.com) | Zlib |
| [fortran-raylib](https://github.com/interkosmos/fortran-raylib) | **5.5** | [Fortran](https://fortran-lang.org) | ISC |
| [raylib-go](https://github.com/gen2brain/raylib-go) | **5.5** | [Go](https://golang.org) | Zlib |
| [raylib-guile](https://github.com/petelliott/raylib-guile) | **auto** | [Guile](https://www.gnu.org/software/guile) | Zlib |
| [gforth-raylib](https://github.com/ArnautDaniel/gforth-raylib) | 3.5 | [Gforth](https://gforth.org) | **???** |
| [h-raylib](https://github.com/Anut-py/h-raylib) | **5.5-dev** | [Haskell](https://haskell.org) | Apache-2.0 |
| [raylib-hx](https://github.com/foreignsasquatch/raylib-hx) | 4.2 | [Haxe](https://haxe.org) | Zlib |
| [hb-raylib](https://github.com/MarcosLeonardoMendezGerencir/hb-raylib) | 3.5 | [Harbour](https://harbour.github.io) | MIT |
| [jaylib](https://github.com/janet-lang/jaylib) | **5.0** | [Janet](https://janet-lang.org) | MIT |
| [jaylib](https://github.com/electronstudio/jaylib/) | **5.5** | [Java](https://en.wikipedia.org/wiki/Java_(programming_language)) | GPLv3+CE |
| [raylib-j](https://github.com/CreedVI/Raylib-J) | 4.0 | [Java](https://en.wikipedia.org/wiki/Java_(programming_language)) | Zlib |
| [Raylib.jl](https://github.com/chengchingwen/Raylib.jl) | 4.2 | [Julia](https://julialang.org) | Zlib |
| [kaylib](https://github.com/electronstudio/kaylib) | 3.7 | [Kotlin/native](https://kotlinlang.org) | **???** |
| [KaylibKit](https://codeberg.org/Kenta/KaylibKit) | 4.5 | [Kotlin/native](https://kotlinlang.org) | Zlib |
| [raylib-lua](https://github.com/TSnake41/raylib-lua) | 5.0 | [Lua](http://www.lua.org) | ISC |
| [raylib-lua-bindings (WIP)](https://github.com/legendaryredfox/raylib-lua-bindings) | 5.5 | [Lua](http://www.lua.org) | ISC |
| [ReiLua](https://github.com/nullstare/ReiLua) | 5.5 | [Lua](http://www.lua.org) | MIT |
| [raylib-lua-sol](https://github.com/RobLoach/raylib-lua-sol) | 5.5 | [Lua](http://www.lua.org) | Zlib |
| [raylib-luajit](https://github.com/homma/raylib-luajit) | 5.5 | [Lua](http://www.lua.org) | MIT |
| [raylib-luajit-generated](https://github.com/james2doyle/raylib-luajit-generated) | 5.5 | [Lua](http://www.lua.org) | MIT |
| [raylib-matte](https://github.com/jcorks/raylib-matte) | 4.6-dev | [Matte](https://github.com/jcorks/matte) | **???** |
| [Raylib.nelua](https://github.com/AuzFox/Raylib.nelua) | **5.5** | [nelua](https://nelua.io) | Zlib |
| [raylib-bindings](https://github.com/vaiorabbit/raylib-bindings) | 5.6-dev | [Ruby](https://www.ruby-lang.org/en) | Zlib |
| [naylib](https://github.com/planetis-m/naylib) | **5.6-dev** | [Nim](https://nim-lang.org) | MIT |
| [node-raylib](https://github.com/RobLoach/node-raylib) | 4.5 | [Node.js](https://nodejs.org/en) | Zlib |
| [raylib-odin](https://github.com/odin-lang/Odin/tree/master/vendor/raylib) | **5.5** | [Odin](https://odin-lang.org) | Zlib |
| [raylib_odin_bindings](https://github.com/Deathbat2190/raylib_odin_bindings) | 4.0-dev | [Odin](https://odin-lang.org) | MIT |
| [raylib-ocaml](https://github.com/tjammer/raylib-ocaml) | **5.0** | [OCaml](https://ocaml.org) | MIT |
| [TurboRaylib](https://github.com/turborium/TurboRaylib) | 4.5 | [Object Pascal](https://en.wikipedia.org/wiki/Object_Pascal) | MIT |
| [Ray4Laz](https://github.com/GuvaCode/Ray4Laz) | **5.5** | [Free Pascal](https://en.wikipedia.org/wiki/Free_Pascal)/[Delphi](https://en.wikipedia.org/wiki/Delphi_(software)) | Zlib |
| [Raylib.4.0.Pascal](https://github.com/sysrpl/Raylib.4.0.Pascal) | 4.0 | [Free Pascal](https://en.wikipedia.org/wiki/Free_Pascal) | Zlib |
| [pyraylib](https://github.com/Ho011/pyraylib) | 3.7 | [Python](https://www.python.org) | Zlib |
| [raylib-python-cffi](https://github.com/electronstudio/raylib-python-cffi) | **5.5** | [Python](https://www.python.org) | EPL-2.0 |
| [raylibpyctbg](https://github.com/overdev/raylibpyctbg) | 5.5 | [Python](https://www.python.org) | MIT |
| [raylib-py](https://github.com/overdev/raylib-py) | 5.5 | [Python](https://www.python.org) | MIT |
| [raylib-python-ctypes](https://github.com/sDos280/raylib-python-ctypes) | 4.6-dev | [Python](https://www.python.org) | MIT |
| [raylib-pkpy-bindings](https://github.com/blueloveTH/pkpy-bindings) | 5.1-dev | [pocketpy](https://pocketpy.dev) | MIT |
| [raylib-php](https://github.com/joseph-montanez/raylib-php) | 4.5 | [PHP](https://en.wikipedia.org/wiki/PHP) | Zlib |
| [raylib-phpcpp](https://github.com/oraoto/raylib-phpcpp) | 3.5 | [PHP](https://en.wikipedia.org/wiki/PHP) | Zlib |
| [raylibr](https://github.com/jeroenjanssens/raylibr) | 4.0 | [R](https://www.r-project.org) | MIT |
| [raylib-ffi](https://github.com/ewpratten/raylib-ffi) | 5.5 | [Rust](https://www.rust-lang.org) | GPLv3 |
| [raylib-rs](https://github.com/raylib-rs/raylib-rs) | **5.5** | [Rust](https://www.rust-lang.org) | Zlib |
| [raylib-ruby](https://github.com/wilsonsilva/raylib-ruby) | 4.5 | [Ruby](https://www.ruby-lang.org) | Zlib |
| [Relib](https://github.com/RedCubeDev-ByteSpace/Relib) | 3.5 | [ReCT](https://github.com/RedCubeDev-ByteSpace/ReCT) | **???** |
| [racket-raylib](https://github.com/eutro/racket-raylib) | **5.5** | [Racket](https://racket-lang.org) | MIT/Apache-2.0 |
| [raylib-swift](https://github.com/STREGAsGate/Raylib) | 4.0 | [Swift](https://swift.org) | MIT |
| [raylib-scopes](https://github.com/salotz/raylib-scopes) | auto | [Scopes](http://scopes.rocks) | MIT |
| [raylib-SmallBASIC](https://github.com/smallbasic/smallbasic.plugins/tree/master/raylib) | **5.5** | [SmallBASIC](https://github.com/smallbasic/SmallBASIC) | GPLv3 |
| [raylib-umka](https://github.com/robloach/raylib-umka) | 4.5 | [Umka](https://github.com/vtereshkov/umka-lang) | Zlib |
| [raylib-v](https://github.com/vlang/raylib) | 5.5 | [V](https://vlang.io) | MIT/Unlicense |
| [raylib.v](https://github.com/irishgreencitrus/raylib.v) | 4.2 | [V](https://vlang.io) | Zlib |
| [raylib-vapi](https://github.com/lxmcf/raylib-vapi) | **5.0** | [Vala](https://vala.dev) | Zlib |
| [raylib-wave](https://github.com/wavefnd/raylib-wave) | **auto** |[Wave](http://wave-lang.dev) | Zlib |
| [raylib-wren](https://github.com/TSnake41/raylib-wren) | 4.5 | [Wren](http://wren.io) | ISC |
| [raylib-zig](https://github.com/raylib-zig/raylib-zig) | **5.6-dev** | [Zig](https://ziglang.org) | MIT |
| [raylib.zig](https://github.com/ryupold/raylib.zig) | **5.1-dev** | [Zig](https://ziglang.org) | MIT |
| [raylib-zig-bindings](https://github.com/L-Briand/raylib-zig-bindings) | **5.0** | [Zig](https://ziglang.org) | Zlib |
| [hare-raylib](https://git.sr.ht/~evantj/hare-raylib) | **auto** | [Hare](https://harelang.org) | Zlib |
| [raylib-sunder](https://github.com/ashn-dot-dev/raylib-sunder) | **auto** | [Sunder](https://github.com/ashn-dot-dev/sunder) | 0BSD |
| [raylib-bqn](https://github.com/Brian-ED/raylib-bqn) | **5.0** | [BQN](https://mlochbaum.github.io/BQN) | MIT |
| [rayjs](https://github.com/mode777/rayjs) | 4.6-dev | [QuickJS](https://bellard.org/quickjs) | MIT |
| [rayjule](https://github.com/SabeDoesThings/rayjule) | **5.5** | [Jule](https://jule.dev/) | MIT |
| [raylib-raku](https://github.com/vushu/raylib-raku) | **auto** | [Raku](https://www.raku.org) | Artistic License 2.0 |
| [Raylib.lean](https://github.com/KislyjKisel/Raylib.lean) | **5.5-dev** | [Lean4](https://lean-lang.org) | BSD-3-Clause |
| [raylib-cobol](https://codeberg.org/glowiak/raylib-cobol) | **auto** | [COBOL](https://gnucobol.sourceforge.io) | Public domain |
| [raylib-apl](https://github.com/Brian-ED/raylib-apl) | **5.0** | [Dyalog APL](https://www.dyalog.com/) | MIT |
| [raylib-jai](https://github.com/ahmedqarmout2/raylib-jai) | **5.5** | [Jai](https://github.com/BSVino/JaiPrimer/blob/master/JaiPrimer.md) | MIT |
| [fnl-raylib](https://github.com/0riginaln0/fnl-raylib) | **5.5** | [Fennel](https://fennel-lang.org/) | MIT |
| [Rayua](https://github.com/uiua-lang/rayua) | **5.5** | [Uiua](https://www.uiua.org/) | **???** |
| [Target](https://github.com/FinnDemonCat/Target/tree/main/libs/raylib) | **5.5** | [Dart](https://dart.dev/) | Apache-2.0 license |
| Name | raylib Version | Language | License |
| :--------------------------------------------------------------------------------------: | :--------------: | :---------------------------------------------------------------------: | :------------------: |
| [raylib](https://github.com/raysan5/raylib) | **6.0** | [C/C++](https://en.wikipedia.org/wiki/C_(programming_language)) | Zlib |
| [raylib-ada](https://github.com/Fabien-Chouteau/raylib-ada) | **6.0** | [Ada](https://en.wikipedia.org/wiki/Ada_(programming_language)) | MIT |
| [raylib-asm](https://github.com/gAndy50/ASMRay) | **6.0** | [Assembly (x86)](https://en.wikipedia.org/wiki/X86_assembly_language) | Zlib |
| [raylib-beef](https://github.com/Starpelly/raylib-beef) | **auto** | [Beef](https://www.beeflang.org) | MIT |
| [raybit](https://github.com/Alex-Velez/raybit) | **5.0** | [Brainfuck](https://en.wikipedia.org/wiki/Brainfuck) | MIT |
| [raylib-c3](https://github.com/c3lang/vendor/tree/main/libraries/raylib6.c3l) | **6** | [C3](https://c3-lang.org) | MIT |
| [raylib-cs](https://github.com/raylib-cs/raylib-cs) | **6.0** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | Zlib |
| [Raylib-CSharp-Vinculum](https://github.com/ZeroElectric/Raylib-CSharp-Vinculum) | **5.0** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MPL-2.0 |
| [Raylib-CSharp](https://github.com/MrScautHD/Raylib-CSharp) | **5.5** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MIT |
| [Raylib-cs.BleedingEdge](https://github.com/danilwhale/Raylib-cs.BleedingEdge) | **5.6-dev** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | Zlib |
| [cl-raylib](https://github.com/longlene/cl-raylib) | 4.0 | [Common Lisp](https://common-lisp.net) | MIT |
| [claylib/wrap](https://github.com/defun-games/claylib) | 4.5 | [Common Lisp](https://common-lisp.net) | Zlib |
| [claw-raylib](https://github.com/bohonghuang/claw-raylib) | **auto** | [Common Lisp](https://common-lisp.net) | Apache-2.0 |
| [raylib](https://github.com/fosskers/raylib) | 5.5 | [Common Lisp](https://common-lisp.net) | MPL-2.0 |
| [chez-raylib](https://github.com/Yunoinsky/chez-raylib) | **auto** | [Chez Scheme](https://cisco.github.io/ChezScheme) | GPLv3 |
| [chicken-raylib](https://github.com/meowstr/chicken-raylib) | 5.5 | [CHICKEN Scheme](https://wiki.call-cc.org) | MIT |
| [CLIPSraylib](https://github.com/mrryanjohnston/CLIPSraylib) | **auto** | [CLIPS](https://www.clipsrules.net/) | MIT |
| [raylib-cr](https://github.com/sol-vin/raylib-cr) | 6.0 | [Crystal](https://crystal-lang.org) | Apache-2.0 |
| [ray-cyber](https://github.com/fubark/ray-cyber) | **5.0** | [Cyber](https://cyberscript.dev) | MIT |
| [dart-raylib](https://gitlab.com/wolfenrain/dart-raylib) | 4.0 | [Dart](https://dart.dev) | MIT |
| [raylib_dart](https://pub.dev/packages/raylib_dart) | 6.0 | [Dart](https://dart.dev) | MIT |
| [bindbc-raylib3](https://github.com/o3o/bindbc-raylib3) | **5.0** | [D](https://dlang.org) | BSL-1.0 |
| [raylib-d](https://github.com/schveiguy/raylib-d) | **6.0** | [D](https://dlang.org) | Zlib |
| [Deno-Raylib](https://github.com/JJLDonley/Deno-Raylib) | **6.0** | [Deno / TS](https://deno.land) | MIT |
| [rayex](https://github.com/shiryel/rayex) | 5.5 | [elixir](https://elixir-lang.org) | Apache-2.0 |
| [raylib-elfscript](https://github.com/ohmtal/raylib-elfscript) | 6.0 | [ElfScript](https://github.com/ohmtal/ElfScript) | MIT |
| [raylib-elle](https://github.com/acquitelol/elle/blob/rewrite/std/raylib.le) | **5.5** | [Elle](https://github.com/acquitelol/elle) | GPL-3.0 |
| [raylib-factor](https://github.com/factor/factor/blob/master/extra/raylib/raylib.factor) | 6.0 | [Factor](https://factorcode.org) | BSD |
| [raystar](https://github.com/RobertFlexx/raystar) | **6.0** | [F*](https://www.fstar-lang.org/) | EPL-2.0 |
| [raylib4fb](https://codeberg.org/mudhairless/raylib4fb) | **6.0** | [FreeBASIC](https://www.freebasic.net) | Zlib |
| [raylib-freebasic](https://github.com/WIITD/raylib-freebasic) | **5.0** | [FreeBASIC](https://www.freebasic.net) | MIT |
| [raylib.f](https://github.com/cthulhuology/raylib.f) | **5.5** | [Forth](https://forth.com) | Zlib |
| [fortran-raylib](https://github.com/interkosmos/fortran-raylib) | **6.0** | [Fortran](https://fortran-lang.org) | ISC |
| [raylib-go](https://github.com/gen2brain/raylib-go) | **6.0** | [Go](https://golang.org) | Zlib |
| [raylib-guile](https://github.com/petelliott/raylib-guile) | **auto** | [Guile](https://www.gnu.org/software/guile) | Zlib |
| [h-raylib](https://github.com/Anut-py/h-raylib) | **6.1-dev** | [Haskell](https://haskell.org) | Apache-2.0 |
| [raylib-hx](https://github.com/foreignsasquatch/raylib-hx) | 5.5 | [Haxe](https://haxe.org) | Zlib |
| [jaylib](https://github.com/janet-lang/jaylib) | **5.0** | [Janet](https://janet-lang.org) | MIT |
| [jaylib](https://github.com/electronstudio/jaylib/) | **6.0** | [Java](https://en.wikipedia.org/wiki/Java_(programming_language)) | GPLv3+CE |
| [raylib-j](https://github.com/CreedVI/Raylib-J) | 4.2 | [Java](https://en.wikipedia.org/wiki/Java_(programming_language)) | Zlib |
| [Raylib.jl](https://github.com/chengchingwen/Raylib.jl) | 4.2 | [Julia](https://julialang.org) | Zlib |
| [KaylibKit](https://codeberg.org/Kenta/KaylibKit) | 4.5 | [Kotlin/native](https://kotlinlang.org) | Zlib |
| [raylib-lua](https://github.com/TSnake41/raylib-lua) | 5.5 | [Lua](http://www.lua.org) | ISC |
| [raylib-lua-bindings (WIP)](https://github.com/legendaryredfox/raylib-lua-bindings) | 6.0 | [Lua](http://www.lua.org) | ISC |
| [ReiLua](https://github.com/nullstare/ReiLua) | 6.0 | [Lua](http://www.lua.org) | MIT |
| [raylib-lua-sol](https://github.com/RobLoach/raylib-lua-sol) | 5.5 | [Lua](http://www.lua.org) | Zlib |
| [raylib-luajit](https://github.com/homma/raylib-luajit) | 5.5 | [Lua](http://www.lua.org) | MIT |
| [raylib-luajit-generated](https://github.com/james2doyle/raylib-luajit-generated) | 5.5 | [Lua](http://www.lua.org) | MIT |
| [raylib-matte](https://github.com/jcorks/raylib-matte) | 4.6-dev | [Matte](https://github.com/jcorks/matte) | **???** |
| [raylib_mojo](https://github.com/willGuimont/raylib_mojo) | **6.0** | [Mojo](https://www.modular.com/mojo) | ZLib |
| [raymojo](https://github.com/RobertFlexx/raymojo) | **6.0** | [Mojo](https://www.modular.com/mojo) | GPLv3 |
| [raymod](https://github.com/RobertFlexx/raymod) | **6.0** | [Modula-2](https://en.wikipedia.org/wiki/Modula-2) / [Modula-3](https://en.wikipedia.org/wiki/Modula-3) | Apache-2.0 |
| [Raylib.nelua](https://github.com/AuzFox/Raylib.nelua) | 6.1-dev | [nelua](https://nelua.io) | Zlib |
| [raylib-bindings](https://github.com/vaiorabbit/raylib-bindings) | 6.1-dev | [Ruby](https://www.ruby-lang.org/en) | Zlib |
| [node-raylib](https://github.com/RobLoach/node-raylib) | 5.5 | [Node.js](https://nodejs.org/en) | Zlib |
| [raylib-odin](https://github.com/odin-lang/Odin/tree/master/vendor/raylib) | **6.0** | [Odin](https://odin-lang.org) | Zlib |
| [raylib_odin_bindings](https://github.com/Deathbat2190/raylib_odin_bindings) | 4.0-dev | [Odin](https://odin-lang.org) | MIT |
| [raylib-ocaml](https://github.com/tjammer/raylib-ocaml) | **6.0** | [OCaml](https://ocaml.org) | MIT |
| [TurboRaylib](https://github.com/turborium/TurboRaylib) | 4.5 | [Object Pascal](https://en.wikipedia.org/wiki/Object_Pascal) | MIT |
| [Rayberon](https://github.com/RobertFlexx/Rayberon) | **6.0** | [Oberon-2](https://en.wikipedia.org/wiki/Oberon-2) | MIT |
| [EuRaylib](https://github.com/gAndy50/EuRaylib6) | **6.0** | [openEuphoria](https://openeuphoria.org/) | Zlib |
| [Ray4Laz](https://github.com/GuvaCode/Ray4Laz) | **6.0** | [Free Pascal](https://en.wikipedia.org/wiki/Free_Pascal) | Zlib |
| [Raylib.4.0.Pascal](https://github.com/sysrpl/Raylib.4.0.Pascal) | 4.0 | [Free Pascal](https://en.wikipedia.org/wiki/Free_Pascal) | Zlib |
| [raylib-python-cffi](https://github.com/electronstudio/raylib-python-cffi) | **6.0** | [Python](https://www.python.org) | EPL-2.0 |
| [raylibpyctbg](https://github.com/overdev/raylibpyctbg) | 5.5 | [Python](https://www.python.org) | MIT |
| [raylib-py](https://github.com/overdev/raylib-py) | **6.0** | [Python](https://www.python.org) | MIT |
| [raylib-python-ctypes](https://github.com/sDos280/raylib-python-ctypes) | 4.6-dev | [Python](https://www.python.org) | MIT |
| [raylib-pkpy-bindings](https://github.com/blueloveTH/pkpy-bindings) | 5.5 | [pocketpy](https://pocketpy.dev) | MIT |
| [raylib-php](https://github.com/joseph-montanez/raylib-php) | 4.5 | [PHP](https://en.wikipedia.org/wiki/PHP) | Zlib |
| [raylibr](https://github.com/jeroenjanssens/raylibr) | auto | [R](https://www.r-project.org) | MIT |
| [raylib-ffi](https://github.com/ewpratten/raylib-ffi) | 5.5 | [Rust](https://www.rust-lang.org) | GPLv3 |
| [raylib-rs](https://github.com/raylib-rs/raylib-rs) | **6.0** | [Rust](https://www.rust-lang.org) | Zlib |
| [sola-raylib](https://github.com/brettchalupa/sola-raylib) | **6.0** | [Rust](https://www.rust-lang.org) | Zlib |
| [raylib-ruby](https://github.com/wilsonsilva/raylib-ruby) | 4.5 | [Ruby](https://www.ruby-lang.org) | Zlib |
| [racket-raylib](https://github.com/eutro/racket-raylib) | **6.0** | [Racket](https://racket-lang.org) | MIT/Apache-2.0 |
| [raylib-swift](https://github.com/STREGAsGate/Raylib) | 4.0 | [Swift](https://swift.org) | MIT |
| [raylib-scopes](https://github.com/salotz/raylib-scopes) | auto | [Scopes](http://scopes.rocks) | MIT |
| [raylib-SmallBASIC](https://github.com/smallbasic/smallbasic.plugins/tree/master/raylib) | **6.0** | [SmallBASIC](https://github.com/smallbasic/SmallBASIC) | GPLv3 |
| [raylib-solod](https://github.com/solod-dev/raylib) | 6.0 | [Solod](https://solod.dev) | BSD-3-Clause |
| [rayscal](https://github.com/RobertFlexx/rayscal) | **6.0** | [Scala Native](https://scala-native.org) | MIT |
| [raylib-umka](https://github.com/robloach/raylib-umka) | 4.5 | [Umka](https://github.com/vtereshkov/umka-lang) | Zlib |
| [raylib-v](https://github.com/vlang/raylib) | auto | [V](https://vlang.io) | MIT/Unlicense |
| [raylib.v](https://github.com/irishgreencitrus/raylib.v) | 4.2 | [V](https://vlang.io) | Zlib |
| [raylib-vapi](https://github.com/lxmcf/raylib-vapi) | **6.0** | [Vala](https://vala.dev) | Zlib |
| [raylib-wave](https://github.com/wavefnd/raylib-wave) | **auto** | [Wave](http://wave-lang.dev) | Zlib |
| [raylib-wren](https://github.com/TSnake41/raylib-wren) | 4.5 | [Wren](http://wren.io) | ISC |
| [raylib-zig](https://github.com/raylib-zig/raylib-zig) | **6.0** | [Zig](https://ziglang.org) | MIT |
| [raylib.zig](https://github.com/ryupold/raylib.zig) | **5.1-dev** | [Zig](https://ziglang.org) | MIT |
| [raylib-zig-bindings](https://github.com/L-Briand/raylib-zig-bindings) | **5.0** | [Zig](https://ziglang.org) | Zlib |
| [hare-raylib](https://git.sr.ht/~evantj/hare-raylib) | **auto** | [Hare](https://harelang.org) | Zlib |
| [raylib-sunder](https://github.com/ashn-dot-dev/raylib-sunder) | **auto** | [Sunder](https://github.com/ashn-dot-dev/sunder) | 0BSD |
| [raylib-bqn](https://github.com/Brian-ED/raylib-bqn) | **auto** | [BQN](https://mlochbaum.github.io/BQN) | MIT |
| [rayjs](https://github.com/mode777/rayjs) | 4.6-dev | [QuickJS](https://bellard.org/quickjs) | MIT |
| [raylib-raku](https://github.com/vushu/raylib-raku) | **auto** | [Raku](https://www.raku.org) | Artistic License 2.0 |
| [Raylib.lean](https://github.com/KislyjKisel/Raylib.lean) | **5.6-dev** | [Lean4](https://lean-lang.org) | BSD-3-Clause |
| [raylib-cobol](https://codeberg.org/glowiak/raylib-cobol) | **auto** | [COBOL](https://gnucobol.sourceforge.io) | Public domain |
| [raylib-apl](https://github.com/Brian-ED/raylib-apl) | **auto** | [Dyalog APL](https://www.dyalog.com/) | MIT |
| [raylib-jai](https://github.com/ahmedqarmout2/raylib-jai) | **6.0** | [Jai](https://github.com/BSVino/JaiPrimer/blob/master/JaiPrimer.md) | MIT |
| [fnl-raylib](https://github.com/0riginaln0/fnl-raylib) | **5.5** | [Fennel](https://fennel-lang.org/) | MIT |
| [Rayua](https://github.com/uiua-lang/rayua) | **5.5** | [Uiua](https://www.uiua.org/) | **???** |
| [Target](https://github.com/FinnDemonCat/Target/tree/main/lib/raylib) | **5.5** | [Dart](https://dart.dev/) | Apache-2.0 license |
| [mach-raylib](https://github.com/angluca/mach-raylib) | **6.x-dev** | [Mach](https://machlang.org/) | MIT |
| [gcl native raylib module](https://github.com/gnuchanos/GnuchanOS/tree/main/language) | **6.0** | [gclang](https://github.com/gnuchanos/GnuchanOS/tree/main/language) | GPLv3 |
### Utility Wrapers
### Utility Wrappers
These are utility wrappers for specific languages, they are not required to use raylib in the language but may adapt the raylib API to be more inline with the language's paradigm.
| Name | raylib Version | Language | License |
| ---------------------------------------------------- | :------------: | :------------------------------------------: | :-----: |
| [raylib-cpp](https://github.com/robloach/raylib-cpp) | **5.5** | [C++](https://en.wikipedia.org/wiki/C%2B%2B) | Zlib |
| [raylib-cpp](https://github.com/robloach/raylib-cpp) | **6.0** | [C++](https://en.wikipedia.org/wiki/C%2B%2B) | Zlib |
| [claylib](https://github.com/defun-games/claylib) | 4.5 | [Common Lisp](https://common-lisp.net) | Zlib |
| [rayed-bqn](https://github.com/Brian-ED/rayed-bqn) | **5.0** | [BQN](https://mlochbaum.github.io/BQN) | MIT |
| [rayed-bqn](https://github.com/Brian-ED/rayed-bqn) | **auto** | [BQN](https://mlochbaum.github.io/BQN) | MIT |
| [DOOR](https://github.com/RealDoigt/DOOR) | 4.0 | [D](https://dlang.org) | MIT |
| [Iris](https://github.com/Marcos-cat/iris) | **5.5** | [Uiua](https://www.uiua.org/) | MIT |
### Older or Unmaintained Language Bindings
These are older raylib bindings that are more than 2 versions old or have not been maintained.
| Name | raylib Version | Language |
| ---------------------------------------------------------------------------------- | :------------: | :---------------------------------------------------------------------: |
| [raylib-cppsharp](https://github.com/phxvyper/raylib-cppsharp) | 2.5 | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) |
| [RaylibFS](https://github.com/dallinbeutler/RaylibFS) | 2.5 | [F#](https://fsharp.org) |
| [raylib\*d](https://github.com/Sepheus/raylib_d) | 2.5 | [D](https://dlang.org) |
| [bindbc-raylib](https://github.com/o3o/bindbc-raylib) | 3.0 | [D](https://dlang.org) |
| [go-raylib](https://github.com/chunqian/go-raylib) | 3.5 | [Go](https://golang.org) |
| [raylib-goplus](https://github.com/Lachee/raylib-goplus) | 2.6-dev | [Go](https://golang.org) |
| [ray-go](https://github.com/hecate-tech/ray-go) | 2.6-dev | [Go](https://golang.org) |
| [raylib-luamore](https://github.com/HDPLocust/raylib-luamore) | 3.0 | [Lua](http://www.lua.org) |
| [LuaJIT-Raylib](https://github.com/Bambofy/LuaJIT-Raylib) | 2.6 | [Lua](http://www.lua.org) |
| [raylib-lua-sol](https://github.com/RobLoach/raylib-lua-sol) | 2.5 | [Lua](http://www.lua.org) |
| [raylib-lua-ffi](https://github.com/raysan5/raylib/issues/693) | 2.0 | [Lua](http://www.lua.org) |
| [raylib-lua](https://github.com/raysan5/raylib-lua) | 1.7 | [Lua](http://www.lua.org) |
| [raylib-nelua](https://github.com/Andre-LA/raylib-nelua) | 3.0 | [Nelua](https://nelua.io) |
| [raylib-nim](https://github.com/Skrylar/raylib-nim) | 2.0 | [Nim](https://nim-lang.org) |
| [raylib-Nim](https://gitlab.com/define-private-public/raylib-Nim) | 1.7 | [Nim](https://nim-lang.org) |
| [nim-raylib](https://github.com/tomc1998/nim-raylib) | 3.1-dev | [Nim](https://nim-lang.org) |
| [raylib-Forever](https://github.com/Guevara-chan/Raylib-Forever) | auto | [Nim](https://nim-lang.org) |
| [NimraylibNow!](https://github.com/greenfork/nimraylib_now) | 4.2 | [Nim](https://nim-lang.org) |
| [raylib-haskell](https://github.com/DevJac/raylib-haskell) | 2.0 | [Haskell](https://www.haskell.org) |
| [raylib-cr](https://github.com/AregevDev/raylib-cr) | 2.5-dev | [Crystal](https://crystal-lang.org) |
| [raylib.cr](https://github.com/sam0x17/raylib.cr) | 2.0 | [Crystal](https://crystal-lang.org) |
| [cray](https://gitlab.com/Zatherz/cray) | 1.8 | [Crystal](https://crystal-lang.org) |
| [raylib-pas](https://github.com/tazdij/raylib-pas) | 3.0 | [Pascal](https://en.wikipedia.org/wiki/Pascal*(programming*language)) |
| [raylib-pascal](https://github.com/drezgames/raylib-pascal) | 2.0 | [Pascal](https://en.wikipedia.org/wiki/Pascal*(programming*language)) |
| [Graphics-Raylib](https://github.com/athreef/Graphics-Raylib) | 1.4 | [Perl](https://www.perl.org) |
| [raylib-ruby](https://github.com/a0/raylib-ruby) | 2.6 | [Ruby](https://www.ruby-lang.org/en) |
| [raylib-ruby-ffi](https://github.com/D3nX/raylib-ruby-ffi) | 2.0 | [Ruby](https://www.ruby-lang.org/en) |
| [raylib-mruby](https://github.com/lihaochen910/raylib-mruby) | 2.5-dev | [mruby](https://github.com/mruby/mruby) |
| [raylib-java](https://github.com/XoanaIO/raylib-java) | 2.0 | [Java](https://en.wikipedia.org/wiki/Java*(programming_language)) |
| [clj-raylib](https://github.com/lsevero/clj-raylib) | 3.0 | [Clojure](https://clojure.org) |
| [QuickJS-raylib](https://github.com/sntg-p/QuickJS-raylib) | 3.0 | [QuickJS](https://bellard.org/quickjs) |
| [raylib-duktape](https://github.com/RobLoach/raylib-duktape) | 2.6 | [JavaScript (Duktape)](https://en.wikipedia.org/wiki/JavaScript) |
| [raylib-chaiscript](https://github.com/RobLoach/raylib-chaiscript) | 2.6 | [ChaiScript](http://chaiscript.com) |
| [raylib-squirrel](https://github.com/RobLoach/raylib-squirrel) | 2.5 | [Squirrel](http://www.squirrel-lang.org) |
| [racket-raylib-2d](https://github.com/arvyy/racket-raylib-2d) | 2.5 | [Racket](https://racket-lang.org) |
| [raylib-php-ffi](https://github.com/oraoto/raylib-php-ffi) | 2.4-dev | [PHP](https://en.wikipedia.org/wiki/PHP) |
| [raylib-haxe](https://github.com/ibilon/raylib-haxe) | 2.4 | [Haxe](https://haxe.org) |
| [ringraylib](https://github.com/ringpackages/ringraylib) | 2.6 | [Ring](http://ring-lang.sourceforge.net) |
| [raylib-scm](https://github.com/yashrk/raylib-scm) | 2.5 | [Chicken Scheme](https://www.call-cc.org) |
| [raylib-chibi](https://github.com/VincentToups/raylib-chibi) | 2.5 | [Chibi-Scheme](https://github.com/ashinn/chibi-scheme) |
| [raylib-gambit-scheme](https://github.com/georgjz/raylib-gambit-scheme) | 3.1-dev | [Gambit Scheme](https://github.com/gambit/gambit) |
| [Euraylib](https://github.com/gAndy50/Euraylib) | 3.0 | [Euphoria](https://openeuphoria.org) |
| [raylib-odin](https://github.com/kevinw/raylib-odin) | 3.0 | [Odin](https://odin-lang.org) |
| [vraylib](https://github.com/waotzi/vraylib) | 3.5 | [V](https://vlang.io) |
| [raylib-vala](https://code.guddler.uk/mart/raylibVapi) | 3.0 | [Vala](https://wiki.gnome.org/Projects/Vala) |
| [raylib-jai](https://github.com/kujukuju/raylib-jai) | 3.1-dev | [Jai](https://github.com/BSVino/JaiPrimer/blob/master/JaiPrimer.md) |
| [ray.zig](https://github.com/BitPuffin/zig-raylib-experiments) | 2.5 | [Zig](https://ziglang.org) |
| [raylib-Ada](https://github.com/mimo/raylib-Ada) | 3.0 | [Ada](https://www.adacore.com/about-ada) |
| [raykit](https://github.com/Gamerfiend/raykit) | **???** | [Kit](https://www.kitlang.org) |
| [ray.mod](https://github.com/bmx-ng/ray.mod) | 3.0 | [BlitzMax](https://blitzmax.org) |
| [raylib-mosaic](https://github.com/pluckyporcupine/raylib-mosaic) | 3.0 | [Mosaic](https://github.com/sal55/langs/tree/master/Mosaic) |
| [raylib-xdpw](https://github.com/vtereshkov/raylib-xdpw) | 2.6 | [XD Pascal](https://github.com/vtereshkov/xdpw) |
| [raylib-carp](https://github.com/sacredbirdman/raylib-carp) | 3.0 | [Carp](https://github.com/carp-lang/Carp) |
| [raylib-fb](https://github.com/IchMagBier/raylib-fb) | 3.0 | [FreeBasic](https://www.freebasic.net) |
| [raylib-purebasic](https://github.com/D-a-n-i-l-o/raylib-purebasic) | 3.0 | [PureBasic](https://www.purebasic.com) |
| [raylib-ats2](https://github.com/mephistopheles-8/raylib-ats2) | 3.0 | [ATS2](http://www.ats-lang.org) |
| [raylib-beef](https://github.com/M0n7y5/raylib-beef) | 3.0 | [Beef](https://www.beeflang.org) |
| [raylib-never](https://github.com/never-lang/raylib-never) | 3.0 | [Never](https://github.com/never-lang/never) |
| [raylib.cbl](https://github.com/Martinfx/Cobol/tree/master/OpenCobol/Games/raylib) | 2.0 | [COBOL](https://en.wikipedia.org/wiki/COBOL) |
| Name | raylib Version | Language |
| :--------------------------------------------------------------------------------------: | :--------------: | :---------------------------------------------------------------------: |
| [raylib-cppsharp](https://github.com/phxvyper/raylib-cppsharp) | 2.5 | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) |
| [Raylib-CsLo](https://github.com/NotNotTech/Raylib-CsLo) | 4.2 | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) |
| [RaylibFS](https://github.com/dallinbeutler/RaylibFS) | 2.5 | [F#](https://fsharp.org) |
| [gforth-raylib](https://github.com/ArnautDaniel/gforth-raylib) | 3.5 | [Gforth](https://gforth.org) |
| [raylib\*d](https://github.com/Sepheus/raylib_d) | 2.5 | [D](https://dlang.org) |
| [bindbc-raylib](https://github.com/o3o/bindbc-raylib) | 3.0 | [D](https://dlang.org) |
| [dray](https://github.com/redthing1/dray) | **5.0** | [D](https://dlang.org) |
| [go-raylib](https://github.com/chunqian/go-raylib) | 3.5 | [Go](https://golang.org) |
| [raylib-goplus](https://github.com/Lachee/raylib-goplus) | 2.6-dev | [Go](https://golang.org) |
| [ray-go](https://github.com/hecate-tech/ray-go) | 2.6-dev | [Go](https://golang.org) |
| [raylib-luamore](https://github.com/HDPLocust/raylib-luamore) | 3.0 | [Lua](http://www.lua.org) |
| [LuaJIT-Raylib](https://github.com/Bambofy/LuaJIT-Raylib) | 2.6 | [Lua](http://www.lua.org) |
| [raylib-lua-sol](https://github.com/RobLoach/raylib-lua-sol) | 2.5 | [Lua](http://www.lua.org) |
| [raylib-lua-ffi](https://github.com/raysan5/raylib/issues/693) | 2.0 | [Lua](http://www.lua.org) |
| [raylib-lua](https://github.com/raysan5/raylib-lua) | 1.7 | [Lua](http://www.lua.org) |
| [raylib-nelua](https://github.com/Andre-LA/raylib-nelua) | 3.0 | [Nelua](https://nelua.io) |
| [raylib-nim](https://github.com/Skrylar/raylib-nim) | 2.0 | [Nim](https://nim-lang.org) |
| [raylib-Nim](https://gitlab.com/define-private-public/raylib-Nim) | 1.7 | [Nim](https://nim-lang.org) |
| [nim-raylib](https://github.com/tomc1998/nim-raylib) | 3.1-dev | [Nim](https://nim-lang.org) |
| [raylib-Forever](https://github.com/Guevara-chan/Raylib-Forever) | auto | [Nim](https://nim-lang.org) |
| [NimraylibNow!](https://github.com/greenfork/nimraylib_now) | 4.2 | [Nim](https://nim-lang.org) |
| [naylib](https://github.com/planetis-m/naylib) | **5.6-dev** | [Nim](https://nim-lang.org) |
| [raylib-haskell](https://github.com/DevJac/raylib-haskell) | 2.0 | [Haskell](https://www.haskell.org) |
| [hb-raylib](https://github.com/MarcosLeonardoMendezGerencir/hb-raylib) | 3.7 | [Harbour](https://harbour.github.io) |
| [raylib-cr](https://github.com/AregevDev/raylib-cr) | 2.5-dev | [Crystal](https://crystal-lang.org) |
| [raylib.cr](https://github.com/sam0x17/raylib.cr) | 2.0 | [Crystal](https://crystal-lang.org) |
| [cray](https://gitlab.com/Zatherz/cray) | 1.8 | [Crystal](https://crystal-lang.org) |
| [raylib-pas](https://github.com/tazdij/raylib-pas) | 3.0 | [Pascal](https://en.wikipedia.org/wiki/Pascal*(programming*language)) |
| [raylib-pascal](https://github.com/drezgames/raylib-pascal) | 2.0 | [Pascal](https://en.wikipedia.org/wiki/Pascal*(programming*language)) |
| [Graphics-Raylib](https://github.com/athreef/Graphics-Raylib) | 1.4 | [Perl](https://www.perl.org) |
| [Relib](https://github.com/RedCubeDev-ByteSpace/Relib) | 3.5 | [ReCT](https://github.com/RedCubeDev-ByteSpace/ReCT) |
| [raylib-ruby](https://github.com/a0/raylib-ruby) | 2.6 | [Ruby](https://www.ruby-lang.org/en) |
| [raylib-ruby-ffi](https://github.com/D3nX/raylib-ruby-ffi) | 2.0 | [Ruby](https://www.ruby-lang.org/en) |
| [raylib-mruby](https://github.com/lihaochen910/raylib-mruby) | 2.5-dev | [mruby](https://github.com/mruby/mruby) |
| [raylib-java](https://github.com/XoanaIO/raylib-java) | 2.0 | [Java](https://en.wikipedia.org/wiki/Java*(programming_language)) |
| [kaylib](https://github.com/electronstudio/kaylib) | 3.7 | [Kotlin/native](https://kotlinlang.org) |
| [clj-raylib](https://github.com/lsevero/clj-raylib) | 3.0 | [Clojure](https://clojure.org) |
| [QuickJS-raylib](https://github.com/sntg-p/QuickJS-raylib) | 3.0 | [QuickJS](https://bellard.org/quickjs) |
| [raylib-duktape](https://github.com/RobLoach/raylib-duktape) | 2.6 | [JavaScript (Duktape)](https://en.wikipedia.org/wiki/JavaScript) |
| [rayjule](https://github.com/SabeDoesThings/rayjule) | **5.5** | [Jule](https://jule.dev/) |
| [raylib-chaiscript](https://github.com/RobLoach/raylib-chaiscript) | 2.6 | [ChaiScript](http://chaiscript.com) |
| [raylib-squirrel](https://github.com/RobLoach/raylib-squirrel) | 2.5 | [Squirrel](http://www.squirrel-lang.org) |
| [racket-raylib-2d](https://github.com/arvyy/racket-raylib-2d) | 2.5 | [Racket](https://racket-lang.org) |
| [raylib-php-ffi](https://github.com/oraoto/raylib-php-ffi) | 2.4-dev | [PHP](https://en.wikipedia.org/wiki/PHP) |
| [raylib-phpcpp](https://github.com/oraoto/raylib-phpcpp) | 3.5 | [PHP](https://en.wikipedia.org/wiki/PHP) |
| [raylib-haxe](https://github.com/ibilon/raylib-haxe) | 2.4 | [Haxe](https://haxe.org) |
| [ringraylib](https://github.com/ringpackages/ringraylib) | 2.6 | [Ring](http://ring-lang.sourceforge.net) |
| [raylib-scm](https://github.com/yashrk/raylib-scm) | 2.5 | [Chicken Scheme](https://www.call-cc.org) |
| [raylib-chibi](https://github.com/VincentToups/raylib-chibi) | 2.5 | [Chibi-Scheme](https://github.com/ashinn/chibi-scheme) |
| [raylib-gambit-scheme](https://github.com/georgjz/raylib-gambit-scheme) | 3.1-dev | [Gambit Scheme](https://github.com/gambit/gambit) |
| [Euraylib](https://github.com/gAndy50/Euraylib) | 3.0 | [Euphoria](https://openeuphoria.org) |
| [raylib-odin](https://github.com/kevinw/raylib-odin) | 3.0 | [Odin](https://odin-lang.org) |
| [vraylib](https://github.com/waotzi/vraylib) | 3.5 | [V](https://vlang.io) |
| [raylib-vala](https://code.guddler.uk/mart/raylibVapi) | 3.0 | [Vala](https://wiki.gnome.org/Projects/Vala) |
| [raylib-jai](https://github.com/kujukuju/raylib-jai) | 3.1-dev | [Jai](https://github.com/BSVino/JaiPrimer/blob/master/JaiPrimer.md) |
| [ray.zig](https://github.com/BitPuffin/zig-raylib-experiments) | 2.5 | [Zig](https://ziglang.org) |
| [raylib-Ada](https://github.com/mimo/raylib-Ada) | 3.0 | [Ada](https://www.adacore.com/about-ada) |
| [raykit](https://github.com/Gamerfiend/raykit) | **???** | [Kit](https://www.kitlang.org) |
| [ray.mod](https://github.com/bmx-ng/ray.mod) | 3.0 | [BlitzMax](https://blitzmax.org) |
| [raylib-mosaic](https://github.com/pluckyporcupine/raylib-mosaic) | 3.0 | [Mosaic](https://github.com/sal55/langs/tree/master/Mosaic) |
| [raylib-xdpw](https://github.com/vtereshkov/raylib-xdpw) | 2.6 | [XD Pascal](https://github.com/vtereshkov/xdpw) |
| [raylib-carp](https://github.com/sacredbirdman/raylib-carp) | 3.0 | [Carp](https://github.com/carp-lang/Carp) |
| [raylib-fb](https://github.com/IchMagBier/raylib-fb) | 3.0 | [FreeBasic](https://www.freebasic.net) |
| [raylib-purebasic](https://github.com/D-a-n-i-l-o/raylib-purebasic) | 3.0 | [PureBasic](https://www.purebasic.com) |
| [pyraylib](https://github.com/Ho011/pyraylib) | 3.7 | [Python](https://www.python.org) |
| [raylib-ats2](https://github.com/mephistopheles-8/raylib-ats2) | 3.0 | [ATS2](http://www.ats-lang.org) |
| [raylib-beef](https://github.com/M0n7y5/raylib-beef) | 3.0 | [Beef](https://www.beeflang.org) |
| [raylib-never](https://github.com/never-lang/raylib-never) | 3.0 | [Never](https://github.com/never-lang/never) |
| [raylib.cbl](https://github.com/Martinfx/Cobol/tree/master/OpenCobol/Games/raylib) | 2.0 | [COBOL](https://en.wikipedia.org/wiki/COBOL) |
Missing some language or wrapper? Feel free to create a new one! :)

252
CHANGELOG
View File

@ -3,6 +3,258 @@ changelog
Current Release: raylib 6.0 (23 April 2026)
-------------------------------------------------------------------------
Release: raylib 6.2 (xx Sep 2026)
-------------------------------------------------------------------------
KEY CHANGES:
- REDESIGNED: Image API for more alignment with Texture API
- REDESIGNED: File API for more standard return result values
- REVIEWED: Shapes lines drawing functions, added new ones and unify behaviour
Detailed changes (until 12-Sept-2026):
[rcore] ADDED: `IsPathDirectory()`, for convenience and more readability at user code by @raysan5
[rcore] ADDED: `IsPathAbsolute()`, check absolute paths by @raysan5
[rcore] ADDED: `IsFileHidden()`, check file hidden (OS-dependant) by @raysan5
[rcore] REVIEWED: `File*()` functions for consistent return result value by @raysan5 -WARNING-
[rcore] REVIEWED: Not updating mouse.previousPosition when `SetMousePosition()` #5962 by @raysan5 -WARNING-
[rcore] REVIEWED: Use `rlgl` provided interface instead of `rlsw` direct access by @raysan5
[rcore] REVIEWED: Set mouse position to (0,0) when mouse leaves window area #5945 by @raysan5
[rcore] REVIEWED: Multiple string boundary handling (#5812) by @zhaob1n
[rcore] REVIEWED: Gamepad lower-bound guard to six sibling functions (#5938) by @mahirhir
[rcore] REVIEWED: Fix logging format for automation event capacity warning (#5986) by @GideonSerf
[rcore] REVIEWED: Fix initial macOS window size (#5967) by @loukamb
[rcore] REVIEWED: Fix clipboard image memory leak (#5968) by @LuisR385
[rcore] REVIEWED: `TakeScreenshot()`, support absolute paths by @raysan5
[rcore] REVIEWED: `OpenURL()`, added some safety checks to mitigate malicious url inputs - ROS: `CLN-002` by @raysan5 -WARNING-
[rcore] REVIEWED: `LoadAutomationEventList()` - ROS: `CLN-005`, `CLN-006` by @raysan5
[rcore] REVIEWED: `GetWindowHandle()`, to be consistent between backends, fix #5885 by @raysan5
[rcore] REVIEWED: `GetWindowPosition()` #5932 by @raysan5
[rcore] REVIEWED: `GetTime()`, small addition for RPI Pico 2 by @raysan5
[rcore] REVIEWED: `GetCurrentMonitor()`, fix for integer overflow in distance calculation (#5842) by @Vasilis-Narain
[rcore] REVIEWED: `FileMove()`, additional security checks by @raysan5
[rcore] REVIEWED: `FileCopy()`, create directory to copy if it does not exist (#5920) by @InviseDivine
[rcore] REVIEWED: `FileMove()`, fix deleting files if `FileCopy()` fails (#5806) by @Lucrecious -WARNING-
[rcore] REVIEWED: `IsPathAbsolute()`, remove `isalpha()` dependency by @raysan5
[rcore] REVIEWED: `ComputeSHA1()`, fix undefined behaviour (#5957) by @TheFissk
[rcore] REVIEWED: `ComputeSHA256()`, wrong hash when message length mod 64 is 56..59 (#6144) by @killerdevildog -WARNING-
[rcore] REVIEWED: `GetPrevDirectoryPath()` behavior to better support side cases (#6073) by @luphi
[rcore] REVIEWED: `GetGamepadAxisCount()`, `GetGamepadName()`, bounds-check gamepad index (#5937) by @szarta
[rcore][GLFW] REVIEWED: `GetClipboardImage()`, fix creating new connection under X11 (#5871) by @steampuker
[rcore][GLFW] REVIEWED: Borderless-windowed mode being always on top (#5868) by @auwsmit
[rcore][GLFW] REVIEWED: Clipboard image memory leak (GLFW, RGFW) (#6103) by @omaribrahimsaad
[rcore][GLFW] REVIEWED: Do not reset mouse position user when user is off window (#6134) by @jestarray
[rcore][GLFW] REVIEWED: `Font` symbol conflict (#6094) by @M374LX
[rcore][RGFW] REVIEWED: Add fullscreen behaviour on size 0 window creation (#5859) by @keks137
[rcore][RGFW] REVIEWED: Fix window Y position reading X in RGFW move callback (#6044) by @latent-9
[rcore][SDL] REVIEWED: Use precise mouse wheel values (#5830) by @Menduist
[rcore][SDL] REVIEWED: Fix SDL3 wrong joystick functions usage (#5948) by @0xFishbyte
[rcore][DRM] REVIEWED: Silence warnings when using GRAPHICS_API_OPENGL_SOFTWARE (#5839) by @NighthowlerStudios
[rcore][DRM] REVIEWED: Segfault on some NVIDIA proprietary drivers (#5960) by @girvel
[rcore][DRM] REVIEWED: Raise MAX_DRM_CACHED_BUFFERS to 4 and warn when the cache fills (#6107) by @jtakakura
[rcore][Web] REVIEWED: Fix for stale mouse position (#5981) by @largenumberhere
[rcore][Win32] ADDED: GetClipboardImage() (#6091) by @omaribrahimsaad
[rcore][Win32] REVIEWED: Use `CORE.Input.Keyboard.exitKey` when handling window closing (#5911) by @aceinetx
[rcore][Win32] REVIEWED: Security fixes (#5899) by @M374LX
[rcore][Win32] REVIEWED: Handle conflict with `PlaySoundW()` for wide string builds (#6140) by @JeffM2501
[rcore][Android] REVIEWED: Restore face-button input on Android gamepads (#5824) by @Tubbles
[rcore][Android] REVIEWED: Relaunch hang after destroy while paused (#6040) by @get-charlie
[rcore][Emscripten] REVIEWED: GetTime(), fix time calculation (#6061) by @andzdroid
[rcore][Emscripten] REVIEWED: Handle emscripten keyboard events (#6067) by @andzdroid
[rcore][Emscripten] REVIEWED: Invert emscripten scroll wheel direction (#6104) by @andzdroid
[rcore][Emscripten] REVIEWED: Update emscripten mouse handling (#6070) by @andzdroid
[rlsw] ADDED: Double buffering support and compiler requirements Pico 2 (#5994) by @NighthowlerStudios
[rlsw] ADDED: `GL_SHADING_LANGUAGE_VERSION` for `swGetString()` by @raysan5
[rlsw] REVIEWED: Variant dispatch refactor and render optimizations (#5996) by @Bigfoot71
[rlgl] REVIEWED: `rlGetPixelDataSize()`, fix pixel data size regressions (#5984) by @GideonSerf
[rlgl] REVIEWED: `rlPushMatrix()`, fix matrix stack overflow (#5935) by @szarta
[rlgl] REVIEWED: `rlLoadTexture()`, add power-of-two check for GL_REPEAT wrap mode (#5820) by @noinodev
[rlgl] REVIEWED: Shader attribute/uniform default names can not be overriden #5925 by @raysan5
[rlgl] REVIEWED: Fix DRM/EGL segfault on some NVIDIA proprietary drivers (#5960) by @girvel
[rlgl] REVIEWED: Use `rlGetPixelDataSize()` instead of `GetPixelDataSize()` (#6024) by @leoagomes
[rlgl] REVIEWED: `rlGetActiveFramebuffer()` supported on OpenGL ES 2.0 (#6115) by @JoeStrout
[rlsw] REVIEWED: Replace `SW_TEXTURE_REPEAT_POT_FAST` with `SW_SUPPORT_NPOT_TEXTURE` (#5901) by @Bigfoot71
[rlsw] REVIEWED: Fix triangle and quad spans applying pixels out of bounds (#5849) by @NighthowlerStudios
[rlsw] REVIEWED: Fix swScissor() Y-axis clipping inversion in software renderer (#5976) by @thiagomucci
[rlsw] REVIEWED: Fix persistent alpha blending state (#5964) by @iztanos
[rlsw] REVIEWED: ESP32 optimizations (#5827) by @jensroth-git
[rlsw] REVIEWED: Internal functions declarations (#6028) by @Bigfoot71
[rlsw] REVIEWED: Optimizations for embedded and compiler requirements Pico 2 (#5994) by @NighthowlerStudios
[rlsw] REVIEWED: Rename public compile-time option prefix to `RLSW_` (#6029) by @Bigfoot71
[rlsw] REVIEWED: Variant dispatch refactor and other improvements (#5996) by @Bigfoot71
[rshapes] ADDED: `Draw*LinesEx()` functions (#6072) by @MatthewRoush
[rshapes] RENAMED: `GetSplinePointBezierQuad()` to `GetSplinePointBezierQuadratic()` by @raysan5 -WARNING-
[rshapes] REVIEWED: Reorder drawing functions by number of vertices by @raysan5
[rshapes] REVIEWED: Comments to be more descriptive by @raysan5
[rshapes] REVIEWED: `DrawRectangleRoundedLinesEx()`, not scaling with transform when thick=1 (#5980) by @SamaelHeaven
[rshapes] REVIEWED: `DrawRectangleRoundedLines()` (#5992) by @MatthewRoush
[rshapes] REVIEWED: `DrawRectangleRounded()`, automatic segments count (#5875) by @anstropleuton
[rshapes] REVIEWED: `DrawRectangleRounded()`, `DrawRectangleRoundedLinesEx()`, fix auto segment rounded-corner math (#5883) by @ghera
[rshapes] REVIEWED: `CheckCollisionLines()`, add NULL check (#5802) by @bielern
[rshapes] REVIEWED: `Draw*LinesEx()`, inconsistencies handling of `thick` parameter (#6035) by @MatthewRoush
[rshapes] REVIEWED: `DrawCircleSector()` (#6045) by @MatthewRoush
[rshapes] REVIEWED: `DrawPolyLinesEx()` (#6004) by @MatthewRoush
[rshapes] REVIEWED: `DrawPolyLinesEx()` line thickness (#6014) by @MatthewRoush
[rshapes] REVIEWED: `DrawRectangleLinesEx()` (#6027) by @MatthewRoush
[rshapes] REVIEWED: `DrawRectangleRoundedLines()` (#5992) by @MatthewRoush
[rtextures] ADDED: `LoadRenderTextureEx()` with user defined pixel format (#6114) by @JeffM2501
[rtextures] ADDED: `ImageDrawLineStrip()` by @raysan5
[rtextures] ADDED: `DrawTriangleGradient()` by @raysan5
[rtextures] ADDED: `DrawCircleLinesEx()`, simpler naming than `DrawRing()` by @raysan5
[rtextures] ADDED: `ImageDrawCircleGradient()` by @raysan5
[rtextures] ADDED: Support for .pep image fileformat, useful for pixel-art by @raysan5
[rtextures] RENAMED: `ImageDrawTriangleEx()` to `ImageDrawTriangleGradient()` by @raysan5 -WARNING-
[rtextures] REDESIGNED: `ImageDraw()`, align with `DrawTexture()` by @raysan5 -WARNING-
[rtextures] REDESIGNED: `ImageDrawRectangleLines()`, consistency with `DrawRectangleLines()` by @raysan5 -WARNING-
[rtextures] REVIEWED: `DrawRectangleLinesEx()`, avoid early-return by @raysan5
[rtextures] REVIEWED: `GetPixelColor()` reading the wrong bits for R5G5B5A1 blue (#6113) by @dylanpulver
[rtextures] REVIEWED: `ImageDrawCircle()`, asymmetry compared with `DrawCircle()` (#6118) by @Risu-swift
[rtextures] REVIEWED: `LoadImageFromTexture()` for wasm by @raysan5
[rtextures] REVIEWED: `ImageFromImage()` - ROS: `CLN-007` by @raysan5
[rtextures] REVIEWED: `ImageFromImage()`, rectangle validation using strict comparisons (#5979) by @CommandPrompt-Wang
[rtextures] REVIEWED: `ImageFromImage()` heap-buffer-overflow on compressed formats (#5991) by @gummyniki
[rtextures] REVIEWED: `ImageToImage()`, reorganize conditionals checks optimization by @raysan5
[rtextures] REVIEWED: `ImageDrawLine()`, rounding and length fix (#5896) by @Kaggen67
[rtextures] REVIEWED: `ImageColorContrast()` parameter type, consistent with other `Image*()` functions by @raysan5 -WARNING-
[rtextures] REVIEWED: `GetPixelDataSize()`, avoid allocations >2GB - ROS: `CLN-013` by @raysan5
[rtextures] REVIEWED: `GetPixelColor()` const by @raysan5
[rtext] REVIEWED: `LoadFontEx()`, `LoadFontFromMemory()`, additional warnings (#5864) by @CrackedPixel
[rtext] REVIEWED: `TextToSnake()`, not considering spaces properly by @raysan5
[rtext] REVIEWED: `TextSubtext()`, fix returning empty string when position is 0 (#5975) by @thiagomucci
[rtext] REVIEWED: `TextReplaceBetween()`, fix buffer overflow (#5936) by @szarta
[rtext] REVIEWED: `TextInsertAlloc()`, overflow by correcting loop bounds (#5982) by @GideonSerf
[rtext] REVIEWED: `TextJoin()`, `TextSubtext()`, `TextInsert*()` - ROS: `CLN-018` by @raysan5
[rtext] REVIEWED: `LoadFontFromImage()`, memory leak (#6100) by @ApexNadir
[rtext] REVIEWED: `TextInsert()`/`TextInsertAlloc()` (#6021) by @SewerynKaminski
[rtext] REVIEWED: `TextSplit()` reading past its buffer on text of 1024 bytes (#6136) by @MaxFreedomPollard
[rtext] REVIEWED: `TextToPascal()`/`TextToCamel()` truncating text after a separator (#6132) by @MaxFreedomPollard
[rmodels] REDESIGNED: `DrawCapsule()`, `DrawCapsuleWires()`, parameter order by @raysan5 -WARNING-
[rmodels] REVIEWED: Fix glTF skinning when joints have non-joint parent nodes (#5876) by @cseelhoff
[rmodels] REVIEWED: Change `boneCount` field type to `unsigned int` (#5955) by @lauchimoon
[rmodels] REVIEWED: `LoadGLTF()`, use inverse bind matrices for bind pose (#5832) by @fyl2xp1
[rmodels] REVIEWED: `IsModelValid()` #5780 by @raysan5
[rmodels] REVIEWED: `GenMeshTorus()`, improved comments (#5934) by @EugenioBarbieriViale
[rmodels] REVIEWED: `DrawSphereWires()`, code optimization (#6000) by @oscujic
[rmodels] REVIEWED: `DrawSphereWires()`, code optimization (#6000) by @oscujic
[rmodels] REVIEWED: `DrawCapsule()`, `DrawCapsuleWires()`, validate minimum rings (#5909) by @LuisR385
[rmodels] REVIEWED: `UnloadModel()`, fix memory leak (#5907) by @LuisR385
[rmodels] REVIEWED: GLTF animation interpolation (#6007) by @lassade
[rmodels] REVIEWED: glTF pose sampled at the end of an animation returning a pose from the start (#6048) by @LeFede
[raudio] REVIEWED: `UpdateSound()`, missleading parameter name by @raysan5
[raudio] REVIEWED: `UnloadSoundAlias()`, prevent leak (#5857) by @Peter0x44
[raudio] REVIEWED: Remove extra `drflac_free()` call (#5916) by @CrackedPixel
[raudio] REVIEWED: Fix memory leak when loading .wav files (#5963) by @LuisR385
[raudio] REVIEWED: Define missing `UnloadFileData()` on standalone mode (#5787) by @rigidatoms
[raudio] REVIEWED: Update to latest DR libs to fix some warnings in MSVC (#5808) by @JeffM2501
[raudio] REVIEWED: `CloseAudioDevice()`, crash when uninit device before mutex (#6039) by @get-charlie
[raymath] ADDED: Operator overload for (float * Vector) (#5815) by @alphahex99
[raymath] REVIEWED: `MatrixCompose()` to follow raymath conventions (#6133) by @carlost0
[build] REMOVED: Unmaintained project: 4coder by @raysan5
[build] REMOVED: Unmaintained project: VS2019-Android by @raysan5
[build][Make] REVIEWED: Add `ANDROID_ARCH` check (#5888) by @Fipaan
[build][Make] REVIEWED: Re-enable `GLFW_LINUX_ENABLE_WAYLAND` flag by default #5816 by @raysan5
[build][Make] REVIEWED: examples/Makefile after testing on OSX (#6077) by @WilliamIsMe1
[build][Make] REVIEWED: Detect the recipe shell for proper clean (#6146) by @Peter0x44
[build][VS2022] REVIEWED: x64 build compatibility support (#6052) (#6053) by @yoobezxc
[build][CMake] ADDED: Support for Win32 platform + examples (#5855) by @CrackedPixel
[build][CMake] REVIEWED: Fix config.h parsing into cmake options (#5844) by @Peter0x44
[build][CMake] REVIEWED: Add configure-time test for libatomic requirement (#5847) by @Peter0x44
[build][CMake] REVIEWED: Remove `raudio` and `rmodels` modules if disabled (#5878) by @NighthowlerStudios
[build][CMake] REVIEWED: Remove GLFW_BUILD warnings for platform SDL (#5865) by @jestarray
[build][CMake] REVIEWED: Reduce minimum CMake version from 3.25 to 3.22 (#5890) by @RobLoach
[build][CMake] REVIEWED: Fix static link dependencies (#5990) by @meta-legend
[build][CMake] REVIEWED: Fix standalone configuration of examples project (#6079) by @zaveshaa
[build][CMake] REVIEWED: Propagate Cocoa backend frameworks to consumers of static raylib on macOS (#6086) by @zaveshaa
[build][Zig] REVIEWED: Support wasm examples building (#5811) by @shadeops
[build][Zig] REVIEWED: Avoid building examples all the time (#5869) by @jn-jairo
[build][Zig] REVIEWED: Avoid building web examples all the time (#6006) by @jn-jairo
[build][Zig] REVIEWED: Update to raygui 5.0 (#6005) by @jn-jairo
[build][CI] REVIEWED: GitHub Actions update to latest actions versions by @raysan5
[build][CI] REVIEWED: `build_examples_windows.yml`, use latest actions versions by @raysan5
[build][CI] REVIEWED: `analyze_codeql.yml`, use latest actions versions by @raysan5
[build][CI] REVIEWED: `setup-emsdk`, use latest actions version by @raysan5
[bindings] ADDED: Recomendations for binding authors (#6141) by @JeffM2501
[bindings] ADDED: sola-raylib (6.0) (#5790, #5795) by @brettchalupa
[bindings] ADDED: gclang-raylib (6.0) (#5850) by @gnuchanos
[bindings] ADDED: mach-raylib (#6059) by @Angluca
[bindings] ADDED: solod (#6102) by @nalgeon
[bindings] ADDED: raymojo (#6076) by @RobertFlexx
[bindings] ADDED: raylib_mojo, for Mojo language (#6093) by @willGuimont
[bindings] ADDED: rayscal, for Scala Native (#6019) by @RobertFlexx
[bindings] ADDED: raylib-elfscript, for ElfScript (#6036) by @ohmtal
[bindings] ADDED: raylib component pascal/oberon2 bindings (#6055) by @RobertFlexx
[bindings] ADDED: raylib binding for modula 2 and 3 (#6068) by @RobertFlexx
[bindings] ADDED: raystar (#6075) by @RobertFlexx
[bindings] UPDATED: vala-vapi to raylib 6.0 (#5789) by @edwood-grant
[bindings] UPDATED: raylib_dart to raylib 6.0 (#5917) by @dzylikecode
[bindings] UPDATED: raylib4fb to raylib 6.0 (#5813) by @mudhairless
[bindings] UPDATED: raylib-d to raylib 6.0 (#5799) by @schveiguy
[bindings] UPDATED: raylib-cpp to raylib 6.0 (#5785) by @RobLoach
[bindings] UPDATED: raylib-go to raylib 6.0 (#5866) by @JupiterRider
[bindings] UPDATED: raylib-cpp to raylib 6.0 (#5785) by @RobLoach
[bindings] UPDATED: raylib-zig to raylib 6.0 (#5886) by @coal-rock
[bindings] UPDATED: Deno-Raylib to raylib 6.0 (#5821) by @JJLDonley
[bindings] UPDATED: raylib-cs to raylib 6.0 (#5887) by @rgebee
[bindings] UPDATED: ReiLua to raylib 6.0 (#5959) by @nullstare
[bindings] UPDATED: Raylib-lua to raylib 5.5 (#5884) by @keyle
[bindings] UPDATED: Ray4Laz to raylib 6.0 (#5784) by @GuvaCode
[bindings] UPDATED: EuRaylib to raylib 6.0 (#6034) by @gAndy50
[bindings] UPDATED: raylib-ocaml to raylib 6.0 (#5912) by @tjammer
[bindings] UPDATED: raylib-jai to raylib 6.0 (#5928) by @ahmedqarmout2
[bindings] UPDATED: raylib-c3 to raylib 6.0 (#5819) by @surrealism21
[bindings] UPDATED: raylib-asm to raylib 6.0 (#6033) by @gAndy50
[bindings] UPDATED: fortran-raylib to raylib 6.0 (#6060) by @interkosmos
[bindings] UPDATED: raylib-py to raylib 6.0 (#6095) by @overdev
[bindings] UPDATED: h-raylib to raylib 6.0 (#6142) by @Anut-py
[examples] ADDED: `core_scissor_shape` (#6032) by @davidbuzatto
[examples] ADDED: `models_mesh_uv_painting` (#6084) by @PanicTitan
[examples] ADDED: `models_procedural_decals` (#6083) by @PanicTitan
[examples] ADDED: `shaders_lights_bloom` (#6081) by @PanicTitan
[examples] ADDED: `shapes_outlines_testbed` (#6072) by @MatthewRoush
[examples] ADDED: `shapes_outlines_thickness` (#6037) by @MatthewRoush
[examples] ADDED: `shapes_polygon_lines` (#6023) by @MatthewRoush
[examples] ADDED: `textures_portal_window` (#6082) by @PanicTitan
[examples] REVIEWED: `shaders_shadowmap_rendering` by @raysan5
[examples] REVIEWED: `models_mesh_uv_painting` by @raysan5
[examples] REVIEWED: `shaders_lights_bloom` by @raysan5
[examples] REVIEWED: `textures_portal_window` by @raysan5
[examples] REVIEWED: `core_smooth_pixelperfect` (#5803) by @rose-mtz
[examples] REVIEWED: `core_directory_files` (#5823) by @MAXDVVV
[examples] REVIEWED: `shapes_ball_physics`, move window for ball shake (#5791) by @Sebbl0508
[examples] REVIEWED: `textures_image_drawing` by @raysan5
[examples] REVIEWED: `models_basic_voxel` by @raysan5
[examples] REVIEWED: `models_animation_blending` by @raysan5
[examples] REVIEWED: `shaders_*`, `pbr.fs`, using wrong uniform value (#5965) by @raysan5
[rlparser] ADDED: S-Expression output type (#5943) by @VisenDev
[rlparser] REVIEWED: Path fixes (#5794) by @gigamonster256
[rlparser] REVIEWED: Fix formatting to follow raylib conventions (#6127) by @Nomobyte
[rlparser] REVIEWED: Fix type aliases, added support to type pointers (#6126) by @Nomobyte
[rexm] ADDED: New command: clean (#6124) by @MatthewRoush
[rexm] REVIEWED: Crash when adding a new textures or audio examples (#6089) by @PanicTitan
[rexm] REVIEWED: Leave environment setup up to the user (#6101) by @MatthewRoush
[rexm] REVIEWED: Makefile and change web local testing port number (#6123) by @MatthewRoush
[rexm] REVIEWED: Simplify code, latest w64devkit supports `make` directly, no need for `mingw32-make` by @raysan5
[misc] ADDED: SECURITY.md document by @raysan5
[misc] REVIEWED: Several functions `const` correctness by @raysan5
[misc] REVIEWED: `strncpy()` replaced by `snprintf()` for safety by @raysan5
[misc] REVIEWED: Minimize `long long` usage in all raylib by @raysan5
[misc] REVIEWED: Comments for consistency and spelling by @raysan5
[misc] REVIEWED: Some Rectangle parameters with more descriptive names by @raysan5
[misc] REVIEWED: Shift `__cplusplus` check to a higher level for `bool` type define (#5804) by @lamweilun
[external] ADDED: `rprand_get_value_raw()` to `rprand` library by @raysan5
[external] UPDATED: GLFW to 3.5.1 (#6051) by @M374LX
[external] UPDATED: miniaudio to 0.11.25 (#6050) by @M374LX
[external] UPDATED: `raygui` to latest master (raygui 5.0) by @raysan5
[external] REVIEWED: `jar_mod_load_file()`, check fread return value (#5840) by @fffaraz
[external] REVIEWED: `tiny_obj_loader` Replace `assert()` by runtime checks - ROS: `CLN-012` by @raysan5
[external] REVIEWED: `fix_win32_compatibility.h`, fix for newer windows SDK versions (#6088) by @JeffM2501
-------------------------------------------------------------------------
Release: raylib 6.0 (23 April 2026)
-------------------------------------------------------------------------

View File

@ -1,5 +1,4 @@
cmake_minimum_required(VERSION 3.25)
#this change avoid the warning that appear when we include raylib using Cmake fatch content
cmake_minimum_required(VERSION 3.22)
project(raylib)
# Avoid excessive expansion of variables in conditionals. In particular, if
@ -29,7 +28,7 @@ include(CompilerFlags)
# Registers build options that are exposed to cmake
include(CMakeOptions.txt)
if (UNIX AND NOT APPLE AND NOT "${PLATFORM}" MATCHES "DRM" AND NOT "${PLATFORM}" MATCHES "Web")
if (UNIX AND NOT APPLE AND NOT "${PLATFORM}" MATCHES "DRM" AND NOT "${PLATFORM}" MATCHES "Web" AND NOT "${PLATFORM}" MATCHES "SDL")
if (NOT GLFW_BUILD_WAYLAND AND NOT GLFW_BUILD_X11)
message(FATAL_ERROR "Cannot disable both Wayland and X11")
endif()

View File

@ -6,7 +6,7 @@ if(EMSCRIPTEN)
# When configuring web builds with "emcmake cmake -B build -S .", set PLATFORM to Web by default
SET(PLATFORM Web CACHE STRING "Platform to build for.")
endif()
enum_option(PLATFORM "Desktop;Web;WebRGFW;Android;Raspberry Pi;DRM;SDL;RGFW;Memory" "Platform to build for.")
enum_option(PLATFORM "Desktop;Win32;Web;WebRGFW;Android;Raspberry Pi;DRM;SDL;RGFW;Memory" "Platform to build for.")
enum_option(OPENGL_VERSION "OFF;4.3;3.3;2.1;1.1;ES 2.0;ES 3.0;Software" "Force a specific OpenGL Version?")
@ -29,11 +29,15 @@ option(GLFW_BUILD_WAYLAND "Build the bundled GLFW with Wayland support" OFF)
option(GLFW_BUILD_X11 "Build the bundled GLFW with X11 support" ON)
option(INCLUDE_EVERYTHING "Include everything disabled by default (for CI usage)" OFF)
set(OFF ${INCLUDE_EVERYTHING} CACHE INTERNAL "Replace any OFF by default with \${OFF} to have it covered by this option")
include(ParseConfigHeader)
foreach(FLAG IN LISTS CONFIG_HEADER_FLAGS)
string(REGEX MATCH "([^=]+)=(.+)" _ ${FLAG})
cmake_dependent_option(${CMAKE_MATCH_1} "" ${CMAKE_MATCH_2} CUSTOMIZE_BUILD ${CMAKE_MATCH_2})
set(CONFIG_HEADER_FLAG_DEFAULT ${CMAKE_MATCH_2})
if (INCLUDE_EVERYTHING AND "${CONFIG_HEADER_FLAG_DEFAULT}" STREQUAL "OFF")
set(CONFIG_HEADER_FLAG_DEFAULT ON)
endif()
cmake_dependent_option(${CMAKE_MATCH_1} "" ${CONFIG_HEADER_FLAG_DEFAULT} CUSTOMIZE_BUILD ${CONFIG_HEADER_FLAG_DEFAULT})
endforeach()

View File

@ -25,7 +25,7 @@ Functions params | lowerCase | `width`, `height`
Ternary Operator | (condition)? result1 : result2 | `printf("Value is 0: %s", (value == 0)? "yes" : "no");`
Some other conventions to follow:
- **ALWAYS** initialize all defined variables.
- **ALWAYS** initialize all defined variables, avoid defining variables in same code line, use multiple lines.
- **Do not use TABS**, use 4 spaces instead.
- Avoid trailing spaces, please, avoid them
- Comments always start with space + capital letter and never end with a '.', place them **before** the line(s) they refer to

View File

@ -14,14 +14,13 @@ Ready to learn? Jump to [code examples!](https://www.raylib.com/examples.html)
[![GitHub Releases Downloads](https://img.shields.io/github/downloads/raysan5/raylib/total)](https://github.com/raysan5/raylib/releases)
[![GitHub Stars](https://img.shields.io/github/stars/raysan5/raylib?style=flat&label=stars)](https://github.com/raysan5/raylib/stargazers)
[![GitHub commits since tagged version](https://img.shields.io/github/commits-since/raysan5/raylib/5.5)](https://github.com/raysan5/raylib/commits/master)
[![GitHub commits since tagged version](https://img.shields.io/github/commits-since/raysan5/raylib/6.0)](https://github.com/raysan5/raylib/commits/master)
[![GitHub Sponsors](https://img.shields.io/github/sponsors/raysan5?label=sponsors)](https://github.com/sponsors/raysan5)
[![Packaging Status](https://repology.org/badge/tiny-repos/raylib.svg)](https://repology.org/project/raylib/versions)
[![License](https://img.shields.io/badge/license-zlib%2Flibpng-blue.svg)](LICENSE)
[![Discord Members](https://img.shields.io/discord/426912293134270465.svg?label=Discord&logo=discord)](https://discord.gg/raylib)
[![Reddit Static Badge](https://img.shields.io/badge/-r%2Fraylib-red?style=flat&logo=reddit&label=reddit)](https://www.reddit.com/r/raylib/)
[![Youtube Subscribers](https://img.shields.io/youtube/channel/subscribers/UC8WIBkhYb5sBNqXO1mZ7WSQ?style=flat&label=Youtube&logo=youtube)](https://www.youtube.com/c/raylib)
[![Youtube Static Badge](https://img.shields.io/badge/YouTube-raylib-red?style=flat&logo=youtube&logoColor=red)](https://www.youtube.com/c/raylib)
[![Twitch Status](https://img.shields.io/twitch/status/raysan5?style=flat&label=Twitch&logo=twitch)](https://www.twitch.tv/raysan5)
[![Build Windows](https://github.com/raysan5/raylib/actions/workflows/build_windows.yml/badge.svg)](https://github.com/raysan5/raylib/actions/workflows/build_windows.yml)
@ -35,7 +34,7 @@ Ready to learn? Jump to [code examples!](https://www.raylib.com/examples.html)
features
--------
- **NO external dependencies**, all required libraries are [included into raylib](https://github.com/raysan5/raylib/tree/master/src/external)
- **NO external dependencies**, all required libraries are [included in raylib](https://github.com/raysan5/raylib/tree/master/src/external)
- Multiple platforms supported: **Windows, Linux, MacOS, RPI, Android, HTML5... and more!**
- Written in plain C code (C99) using PascalCase/camelCase notation
- Hardware accelerated with OpenGL: **1.1, 2.1, 3.3, 4.3, ES 2.0, ES 3.0**
@ -50,10 +49,21 @@ features
- **Powerful math module** for Vector, Matrix and Quaternion operations: [raymath](https://github.com/raysan5/raylib/blob/master/src/raymath.h)
- Audio loading and playing with streaming support (WAV, QOA, OGG, MP3, FLAC, XM, MOD)
- **VR stereo rendering** support with configurable HMD device parameters
- Huge examples collection with [+140 code examples](https://github.com/raysan5/raylib/tree/master/examples)!
- Huge examples collection with [+200 code examples](https://github.com/raysan5/raylib/tree/master/examples)!
- Bindings to [+70 programming languages](https://github.com/raysan5/raylib/blob/master/BINDINGS.md)!
- **Free and open source**
limitations
-----------
raylib presents some limitations by design for code simplicity. Some forks, alternatives, and samples are available to overcome most of them but it's up to the users to modify the library for their specific needs.
- Single window with single OpenGL context by default, no multi-window support
- Window resize and move stops the rendering loop on platforms supporting a window
- `RenderTextures` are flipped vertically, as provided by OpenGL, it's up to the user to draw them flipped to the screen
- Font rasterization has lower quality than alternatives using `Freetype2`, `HarfBuzz` or `Slug`
- Text drawing does not support RTL, ligatures or emojis
basic example
--------------
This is a basic raylib example, it creates a window and draws the text `"Congrats! You created your first window!"` in the middle of the screen. Check this example [running live on web here](https://www.raylib.com/examples/core/loader.html?name=core_basic_window).
@ -99,7 +109,7 @@ raylib is also available via multiple package managers on multiple OS distributi
- [Working for Web (HTML5)](https://github.com/raysan5/raylib/wiki/Working-for-Web-(HTML5))
- [Working anywhere with CMake](https://github.com/raysan5/raylib/wiki/Working-with-CMake)
*Note that the Wiki is open for edit, if you find some issues while building raylib for your target platform, feel free to edit the Wiki or open an issue related to it.*
*Note that the Wiki is open to edits, if you find some issues while building raylib for your target platform, feel free to edit the Wiki or open an issue related to it.*
#### Setup raylib with multiple IDEs
@ -112,7 +122,7 @@ raylib has been developed on Windows platform using [Notepad++](https://notepad-
learning and docs
------------------
raylib is designed to be learned using [the examples](https://github.com/raysan5/raylib/tree/master/examples) as the main reference. There is no standard API documentation but there is a [**cheatsheet**](https://www.raylib.com/cheatsheet/cheatsheet.html) containing all the functions available on the library a short description of each one of them, input parameters and result value names should be intuitive enough to understand how each function works.
raylib is designed to be learned using [the examples](https://github.com/raysan5/raylib/tree/master/examples) as the main reference. There is no standard API documentation but there is a [**cheatsheet**](https://www.raylib.com/cheatsheet/cheatsheet.html) containing all the functions available in the library with a short description of each one; input parameters and result value names should be intuitive enough to understand how each function works.
Some additional documentation about raylib design can be found in [raylib GitHub Wiki](https://github.com/raysan5/raylib/wiki). Here are the relevant links:

View File

@ -11,8 +11,4 @@ Most considerations of errors and defects can be handled using the project Issue
## Reporting a Vulnerability
Discovered vulnerability can be directly reported using the project Issues and/or Discussions.
_TODO: Tell them where to go, how often they can expect to get an update on a
reported vulnerability, what to expect if the vulnerability is accepted or
declined, etc._
Discovered vulnerability can be directly reported using the project Issues and/or Discussions. They will be reviewed as soon as possible.

396
build.zig
View File

@ -2,85 +2,257 @@ const std = @import("std");
const builtin = @import("builtin");
pub const emsdk = struct {
const zemscripten = @import("zemscripten");
const emsdk_version = "4.0.19"; // inline constant used only in activate
var emsdk_dep: ?*std.Build.Dependency = null;
pub fn shell(raylib_dep: *std.Build.Dependency) std.Build.LazyPath {
return raylib_dep.path("src/shell.html");
}
pub const FlagsOptions = struct {
optimize: std.builtin.OptimizeMode,
asyncify: bool = true,
// ---------- core types ----------
pub const EmccFlags = std.StringHashMap(void);
pub const EmccSettings = std.StringHashMap([]const u8);
const EmsdkAllocator = enum {
none,
dlmalloc,
emmalloc,
@"emmalloc-debug",
@"emmalloc-memvalidate",
@"emmalloc-verbose",
mimalloc,
};
pub fn emccDefaultFlags(allocator: std.mem.Allocator, options: FlagsOptions) zemscripten.EmccFlags {
var emcc_flags = zemscripten.emccDefaultFlags(allocator, .{
.optimize = options.optimize,
.fsanitize = true,
});
pub const ResourceFile = struct {
src_path: std.Build.LazyPath,
virtual_path: ?[]const u8 = null,
if (options.asyncify)
emcc_flags.put("-sASYNCIFY", {}) catch unreachable;
fn get(self: ResourceFile, b: *std.Build) []const u8 {
return if (self.virtual_path) |vp|
b.fmt("{s}@{s}", .{ self.src_path.getDisplayName(), vp })
else
self.src_path.getDisplayName();
}
};
return emcc_flags;
pub const EmccStepOptions = struct {
optimize: std.builtin.OptimizeMode,
flags: EmccFlags,
settings: EmccSettings,
use_preload_plugins: bool = false,
embed_paths: ?[]const ResourceFile = null,
preload_paths: ?[]const ResourceFile = null,
shell_file_path: ?std.Build.LazyPath = null,
js_library_path: ?std.Build.LazyPath = null,
out_file_name: []const u8,
install_dir: std.Build.InstallDir,
};
// ---------- helpers ----------
pub fn emsdkDep(b: *std.Build) !*std.Build.Dependency {
if (emsdk_dep == null) {
emsdk_dep = try b.dependencyLazy("emsdk", .{});
}
return emsdk_dep.?;
}
pub const SettingsOptions = struct {
pub fn path(b: *std.Build, sub_path: []const u8) !std.Build.LazyPath {
return (try emsdkDep(b)).path(sub_path);
}
pub fn emccPath(b: *std.Build) !std.Build.LazyPath {
return try emsdk.path(b, "upstream/emscripten/emcc.py");
}
pub fn emrunPath(b: *std.Build) !std.Build.LazyPath {
return switch (builtin.target.os.tag) {
.windows => try emsdk.path(b, "upstream/emscripten/emrun.bat"),
else => try emsdk.path(b, "upstream/emscripten/emrun"),
};
}
pub fn emccDefaultFlags(allocator: std.mem.Allocator, options: struct {
optimize: std.builtin.OptimizeMode,
asyncify: bool = true,
fsanitize: bool = true,
}) EmccFlags {
var flags = EmccFlags.init(allocator);
switch (options.optimize) {
.Debug => {
flags.put("-O0", {}) catch @panic("OOM");
flags.put("-gsource-map", {}) catch @panic("OOM");
if (options.fsanitize)
flags.put("-fsanitize=undefined", {}) catch @panic("OOM");
},
.ReleaseSafe => {
flags.put("-O3", {}) catch @panic("OOM");
if (options.fsanitize) {
flags.put("-fsanitize=undefined", {}) catch @panic("OOM");
flags.put("-fsanitize-minimal-runtime", {}) catch @panic("OOM");
}
},
.ReleaseFast => flags.put("-O3", {}) catch @panic("OOM"),
.ReleaseSmall => flags.put("-Oz", {}) catch @panic("OOM"),
}
if (options.asyncify)
flags.put("-sASYNCIFY", {}) catch @panic("OOM");
return flags;
}
pub fn emccDefaultSettings(allocator: std.mem.Allocator, options: struct {
optimize: std.builtin.OptimizeMode,
es3: bool = false,
glfw3: bool = true,
memory_growth: bool = false,
total_memory: u32 = 134217728,
emsdk_allocator: zemscripten.EmsdkAllocator = .emmalloc,
};
pub fn emccDefaultSettings(allocator: std.mem.Allocator, options: SettingsOptions) zemscripten.EmccSettings {
var emcc_settings = zemscripten.emccDefaultSettings(allocator, .{
.optimize = options.optimize,
.emsdk_allocator = options.emsdk_allocator,
});
emsdk_allocator: EmsdkAllocator = .emmalloc,
}) EmccSettings {
var settings = EmccSettings.init(allocator);
switch (options.optimize) {
.Debug, .ReleaseSafe => {
settings.put("SAFE_HEAP", "1") catch @panic("OOM");
settings.put("STACK_OVERFLOW_CHECK", "1") catch @panic("OOM");
settings.put("ASSERTIONS", "1") catch @panic("OOM");
},
else => {},
}
settings.put("MALLOC", @tagName(options.emsdk_allocator)) catch @panic("OOM");
if (options.es3) {
emcc_settings.put("FULL_ES3", "1") catch unreachable;
emcc_settings.put("MIN_WEBGL_VERSION", "2") catch unreachable;
emcc_settings.put("MAX_WEBGL_VERSION", "2") catch unreachable;
}
if (options.glfw3) {
emcc_settings.put("USE_GLFW", "3") catch unreachable;
settings.put("FULL_ES3", "1") catch @panic("OOM");
settings.put("MIN_WEBGL_VERSION", "2") catch @panic("OOM");
settings.put("MAX_WEBGL_VERSION", "2") catch @panic("OOM");
}
if (options.glfw3)
settings.put("USE_GLFW", "3") catch @panic("OOM");
const total_memory = std.fmt.allocPrint(allocator, "{d}", .{options.total_memory}) catch unreachable;
emcc_settings.put("EXPORTED_RUNTIME_METHODS", "['requestFullscreen']") catch unreachable;
emcc_settings.put("TOTAL_MEMORY", total_memory) catch unreachable;
emcc_settings.put("FORCE_FILESYSTEM", "1") catch unreachable;
emcc_settings.put("EXPORTED_RUNTIME_METHODS", "ccall") catch unreachable;
const total_memory = std.fmt.allocPrint(allocator, "{d}", .{options.total_memory}) catch @panic("OOM");
settings.put("EXPORTED_RUNTIME_METHODS", "['requestFullscreen']") catch @panic("OOM");
settings.put("TOTAL_MEMORY", total_memory) catch @panic("OOM");
settings.put("FORCE_FILESYSTEM", "1") catch @panic("OOM");
settings.put("EXPORTED_RUNTIME_METHODS", "ccall") catch @panic("OOM");
if (options.memory_growth)
emcc_settings.put("ALLOW_MEMORY_GROWTH", "1") catch unreachable;
settings.put("ALLOW_MEMORY_GROWTH", "1") catch @panic("OOM");
return emcc_settings;
return settings;
}
pub fn emccStep(b: *std.Build, raylib: *std.Build.Step.Compile, wasm: *std.Build.Step.Compile, options: zemscripten.StepOptions) *std.Build.Step {
const activate_emsdk_step = zemscripten.activateEmsdkStep(b);
// ---------- step builders ----------
pub fn emccStep(b: *std.Build, src_paths: []const std.Build.LazyPath, compile_steps: []const *std.Build.Step.Compile, options: EmccStepOptions) !*std.Build.Step {
var emcc = b.addRunFile(try emccPath(b));
const emsdk_dep = b.dependency("emsdk", .{});
raylib.root_module.addIncludePath(emsdk_dep.path("upstream/emscripten/cache/sysroot/include"));
wasm.root_module.addIncludePath(emsdk_dep.path("upstream/emscripten/cache/sysroot/include"));
// flags
{
var it = options.flags.iterator();
while (it.next()) |kv| emcc.addArg(kv.key_ptr.*);
}
const emcc_step = zemscripten.emccStep(b, wasm, options);
emcc_step.dependOn(activate_emsdk_step);
// settings
{
var it = options.settings.iterator();
while (it.next()) |kv| {
emcc.addArg(b.fmt("-s{s}={s}", .{ kv.key_ptr.*, kv.value_ptr.* }));
}
}
return emcc_step;
// source files & artifact dependencies
for (src_paths) |sp| emcc.addFileArg(sp);
for (compile_steps) |cs| {
emcc.addArtifactArg(cs);
cs.root_module.addIncludePath(try emsdk.path(b, "upstream/emscripten/cache/sysroot/include"));
for (cs.root_module.getGraph().modules) |mod| {
for (mod.link_objects.items) |lo| {
if (lo == .other_step) {
const linked = lo.other_step;
if (linked.kind == .lib) emcc.addArtifactArg(linked);
}
}
}
}
emcc.addArg("-o");
const out_file = emcc.addOutputFileArg(options.out_file_name);
// optional args
if (options.use_preload_plugins) emcc.addArg("--use-preload-plugins");
if (options.embed_paths) |eps| for (eps) |ep| {
emcc.addArg("--embed-file");
emcc.addFileArg(ep.src_path);
};
if (options.preload_paths) |pps| for (pps) |pp| {
emcc.addArg("--preload-file");
emcc.addArg(pp.get(b));
};
if (options.shell_file_path) |sfp| {
emcc.addArg("--shell-file");
emcc.addFileArg(sfp);
}
if (options.js_library_path) |jlp| {
emcc.addArg("--js-library");
emcc.addFileArg(jlp);
}
const install = b.addInstallDirectory(.{
.source_dir = out_file.dirname(),
.install_dir = options.install_dir,
.install_subdir = "",
});
install.step.dependOn(&emcc.step);
return &install.step;
}
pub fn emrunStep(
b: *std.Build,
html_path: []const u8,
extra_args: []const []const u8,
) *std.Build.Step {
return zemscripten.emrunStep(b, html_path, extra_args);
pub fn emrunStep(b: *std.Build, html_path: std.Build.LazyPath, extra_args: []const []const u8) !*std.Build.Step {
var emrun = b.addRunFile(try emrunPath(b));
emrun.addArgs(extra_args);
emrun.addFileArg(html_path);
return &emrun.step;
}
pub fn activateEmsdkStep(b: *std.Build) !*std.Build.Step {
const user = b.step("Activate EMSDK", "Install/Update and prepare emscripten sdk");
const script = switch (builtin.target.os.tag) {
.windows => try emsdk.path(b, "emsdk.bat"),
else => try emsdk.path(b, "emsdk"),
};
var update = b.addRunFile(script);
update.addArg("update");
// chmod / takeown for script
const make_script_exec: ?*std.Build.Step.Run = switch (builtin.target.os.tag) {
.linux, .macos => blk: {
var cmd = b.addSystemCommand(&.{ "chmod", "+x" });
cmd.addFileArg(script);
break :blk cmd;
},
.windows => blk: {
var cmd = b.addSystemCommand(&.{ "takeown", "/f" });
cmd.addFileArg(script);
break :blk cmd;
},
else => null,
};
if (make_script_exec) |mse| update.step.dependOn(&mse.step);
var install = b.addRunFile(script);
install.addArg("install");
install.addArg(emsdk_version);
install.step.dependOn(&update.step);
var activate = b.addRunFile(script);
activate.addArg("activate");
activate.addArg(emsdk_version);
activate.step.dependOn(&install.step);
user.dependOn(&activate.step);
// also ensure emcc/emrun are executable on Unix
if (builtin.target.os.tag == .linux or builtin.target.os.tag == .macos) {
for ([_]std.Build.LazyPath{ try emccPath(b), try emrunPath(b) }) |p| {
var cmd = b.addSystemCommand(&.{ "chmod", "a+x" });
cmd.addFileArg(p);
cmd.step.dependOn(&install.step);
user.dependOn(&cmd.step);
}
}
return user;
}
};
@ -92,7 +264,7 @@ pub fn linkWindows(mod: *std.Build.Module, opengl: bool, comptime shcore: bool)
}
fn findWaylandScanner(b: *std.Build) void {
_ = b.findProgram(&.{"wayland-scanner"}, &.{}) catch {
_ = b.findProgram(.{ .names = &.{"wayland-scanner"} }) orelse {
std.log.err(
\\ `wayland-scanner` may not be installed on the system.
\\ You can switch to X11 in your `build.zig` by changing `Options.linux_display_backend`
@ -126,19 +298,20 @@ pub fn linkBSD(_: *std.Build, mod: *std.Build.Module) void {
mod.linkSystemLibrary("GL", .{});
}
pub fn linkMacOS(b: *std.Build, mod: *std.Build.Module) void {
pub fn linkMacOS(b: *std.Build, mod: *std.Build.Module) !void {
// Include xcode_frameworks for cross compilation
if (b.lazyDependency("xcode_frameworks", .{})) |dep| {
mod.addSystemFrameworkPath(dep.path("Frameworks"));
mod.addSystemIncludePath(dep.path("include"));
mod.addLibraryPath(dep.path("lib"));
}
const dep = try b.dependencyLazy("xcode_frameworks", .{});
mod.addSystemFrameworkPath(dep.path("Frameworks"));
mod.addSystemIncludePath(dep.path("include"));
mod.addLibraryPath(dep.path("lib"));
mod.linkFramework("Foundation", .{});
mod.linkFramework("CoreServices", .{});
mod.linkFramework("CoreGraphics", .{});
mod.linkFramework("AppKit", .{});
mod.linkFramework("IOKit", .{});
mod.linkFramework("QuartzCore", .{});
}
fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, options: Options) !*std.Build.Step.Compile {
@ -154,7 +327,13 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
.root_module = raylib_mod,
});
raylib_mod.addCMacro("_GNU_SOURCE", "");
// On Linux (glibc) avoid _GNU_SOURCE, on glibc >= 2.38 it redirects sscanf(), strtol()...
// to __isoc23_*() symbols, so the generated library fails to link with older glibc versions
if (target.result.os.tag == .linux and !target.result.abi.isAndroid()) {
raylib_mod.addCMacro("_DEFAULT_SOURCE", "");
} else {
raylib_mod.addCMacro("_GNU_SOURCE", "");
}
raylib_mod.addCMacro("GL_SILENCE_DEPRECATION", "199309L");
var arena: std.heap.ArenaAllocator = .init(b.allocator);
@ -261,7 +440,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
});
_ = raylib_flags_arr.pop();
linkMacOS(b, raylib_mod);
try linkMacOS(b, raylib_mod);
},
.emscripten => {
switch (opengl_version) {
@ -272,7 +451,9 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
raylib_mod.addCMacro("PLATFORM_WEB", "");
const activate_emsdk_step = emsdk.zemscripten.activateEmsdkStep(b);
raylib_mod.addIncludePath(try emsdk.path(b, "upstream/emscripten/cache/sysroot/include"));
const activate_emsdk_step = try emsdk.activateEmsdkStep(b);
raylib.step.dependOn(activate_emsdk_step);
},
else => @panic("Target is not supported with this platform"),
@ -321,7 +502,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
}
},
.freebsd, .openbsd, .netbsd, .dragonfly => linkBSD(b, raylib_mod),
.macos => linkMacOS(b, raylib_mod),
.macos => try linkMacOS(b, raylib_mod),
.emscripten => {
switch (opengl_version) {
.auto => opengl_version = OpenglVersion.gles_2,
@ -330,7 +511,10 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
}
raylib_mod.addCMacro("PLATFORM_WEB_RGFW", "");
const activate_emsdk_step = emsdk.zemscripten.activateEmsdkStep(b);
raylib_mod.addIncludePath(try emsdk.path(b, "upstream/emscripten/cache/sysroot/include"));
const activate_emsdk_step = try emsdk.activateEmsdkStep(b);
raylib.step.dependOn(activate_emsdk_step);
},
else => @panic("Target is not supported with this platform"),
@ -476,33 +660,33 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
return raylib;
}
fn addRaygui(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, raylib: *std.Build.Step.Compile) void {
if (b.lazyDependency("raygui", .{
fn addRaygui(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, raylib: *std.Build.Step.Compile) !void {
const raygui_dep = try b.dependencyLazy("raygui", .{
.target = target,
.optimize = optimize,
.link_libc = true,
})) |raygui_dep| {
var gen_step = b.addWriteFiles();
raylib.step.dependOn(&gen_step.step);
});
const raygui_c_path = gen_step.add("raygui.c", "#define RAYGUI_IMPLEMENTATION\n#include \"raygui.h\"\n");
raylib.root_module.addCSourceFile(.{ .file = raygui_c_path });
raylib.root_module.addIncludePath(raygui_dep.path("src"));
raylib.root_module.addIncludePath(b.path("src"));
var gen_step = b.addWriteFiles();
raylib.step.dependOn(&gen_step.step);
raylib.installHeader(raygui_dep.path("src/raygui.h"), "raygui.h");
const raygui_c_path = gen_step.add("raygui.c", "#define RAYGUI_IMPLEMENTATION\n#include \"raygui.h\"\n");
raylib.root_module.addCSourceFile(.{ .file = raygui_c_path });
raylib.root_module.addIncludePath(raygui_dep.path("src"));
raylib.root_module.addIncludePath(b.path("src"));
const c = b.addTranslateC(.{
.root_source_file = raygui_dep.path("src/raygui.h"),
.target = target,
.optimize = optimize,
.link_libc = true,
});
c.addIncludePath(b.path("src"));
const c_mod = c.createModule();
c_mod.linkLibrary(raylib);
b.modules.put(b.graph.arena, "raygui", c_mod) catch @panic("OOM");
}
raylib.installHeader(raygui_dep.path("src/raygui.h"), "raygui.h");
const c = b.addTranslateC(.{
.root_source_file = raygui_dep.path("src/raygui.h"),
.target = target,
.optimize = optimize,
.link_libc = true,
});
c.addIncludePath(b.path("src"));
const c_mod = c.createModule();
c_mod.linkLibrary(raylib);
b.modules.put(b.graph.arena, "raygui", c_mod) catch @panic("OOM");
}
pub const Options = struct {
@ -623,7 +807,7 @@ pub fn build(b: *std.Build) !void {
translateCMod("rlgl", b, target, optimize, lib);
if (options.raygui) {
addRaygui(b, target, optimize, lib);
try addRaygui(b, target, optimize, lib);
}
const examples = b.step("examples", "build/install all examples");
@ -648,7 +832,7 @@ fn addExamples(
const all = b.step(module, "All " ++ module ++ " examples");
const module_subpath = b.pathJoin(&.{ "examples", module });
var dir = try b.build_root.handle.openDir(b.graph.io, module_subpath, .{ .iterate = true });
var dir = try b.root.openDir(b.graph.io, module_subpath, .{ .iterate = true });
defer dir.close(b.graph.io);
var iter = dir.iterate();
@ -698,7 +882,7 @@ fn addExamples(
exe_mod.addCMacro("PLATFORM_WEB", "");
const wasm = b.addLibrary(.{
.name = filename,
.name = b.fmt("{s}.html", .{filename}),
.root_module = exe_mod,
});
@ -706,19 +890,40 @@ fn addExamples(
const emcc_flags = emsdk.emccDefaultFlags(b.allocator, .{ .optimize = optimize });
const emcc_settings = emsdk.emccDefaultSettings(b.allocator, .{ .optimize = optimize });
const emcc_step = emsdk.emccStep(b, raylib, wasm, .{
const SerialResourceFile = struct { src_path: []const u8, virtual_path: []const u8 };
const EmccExamplesPreloadMap = std.static_string_map.StaticStringMap([]const SerialResourceFile);
const EmccExamplesPreloadSerial = struct { []const u8, []const SerialResourceFile };
const emcc_examples_preloads_serial: []const EmccExamplesPreloadSerial = @import("examples/example_resources.zon");
const emcc_examples_preloads_map = EmccExamplesPreloadMap.initComptime(emcc_examples_preloads_serial);
const preload_paths: ?[]emsdk.ResourceFile = blk: {
if (emcc_examples_preloads_map.get(filename)) |resource_files| {
var rfs = try b.allocator.alloc(emsdk.ResourceFile, resource_files.len);
for (resource_files, 0..) |resource_file, rfidx| {
rfs[rfidx] = .{
.src_path = b.path(resource_file.src_path),
.virtual_path = resource_file.virtual_path,
};
}
break :blk rfs;
} else break :blk null;
};
const emcc_step = try emsdk.emccStep(b, &.{}, &.{ raylib, wasm }, .{
.optimize = optimize,
.flags = emcc_flags,
.settings = emcc_settings,
.preload_paths = preload_paths,
.shell_file_path = b.path("src/shell.html"),
.install_dir = install_dir,
.out_file_name = wasm.name,
});
b.getInstallStep().dependOn(emcc_step);
const html_filename = try std.fmt.allocPrint(b.allocator, "{s}.html", .{wasm.name});
const emrun_step = emsdk.emrunStep(
const emrun_step = try emsdk.emrunStep(
b,
b.getInstallPath(install_dir, html_filename),
b.graph.path(.install_prefix, b.fmt(
"web/{s}/{s}/{s}",
.{ module, filename, wasm.name },
)),
&.{},
);
@ -733,7 +938,6 @@ fn addExamples(
.root_module = exe_mod,
.use_lld = target.result.os.tag == .windows,
});
b.installArtifact(exe);
const install_cmd = b.addInstallArtifact(exe, .{ .dest_sub_path = b.fmt("{s}/{s}", .{ module, filename }) });
@ -754,7 +958,7 @@ fn waylandGenerate(
comptime waylandDir: []const u8,
comptime source: bool,
) !void {
const dir = try b.build_root.handle.openDir(b.graph.io, waylandDir, .{ .iterate = true });
const dir = try b.root.openDir(b.graph.io, waylandDir, .{ .iterate = true });
defer dir.close(b.graph.io);
var iter = dir.iterate();

View File

@ -1,7 +1,7 @@
.{
.name = .raylib,
.version = "6.0.0",
.minimum_zig_version = "0.16.0",
.minimum_zig_version = "0.17.0",
.fingerprint = 0x13035e5cb8bc1ac2, // Changing this has security and trust implications.
@ -12,17 +12,14 @@
.lazy = true,
},
.raygui = .{
.url = "git+https://github.com/raysan5/raygui#3b2855842ab578a034f827c38cf8f62c042fc983",
.hash = "N-V-__8AAHvybwBw1kyBGn0BW_s1RqIpycNjLf_XbE-fpLUF",
.url = "git+https://github.com/raysan5/raygui#3f81e2bd02bf08dcd9d350e8e8b3cf58044d6877",
.hash = "N-V-__8AAPPCmABYkTrLoRGTR6whFQP1bvg7p5vpLsKIcn4G",
.lazy = true,
},
.emsdk = .{
.url = "git+https://github.com/emscripten-core/emsdk#4.0.9",
.hash = "N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ",
},
.zemscripten = .{
.url = "git+https://github.com/zig-gamedev/zemscripten#3fa4b778852226c7346bdcc3c1486e875a9a6d02",
.hash = "zemscripten-0.2.0-dev-sRlDqApRAACspTbAZnuNKWIzfWzSYgYkb2nWAXZ-tqqt",
.lazy = true,
},
},

View File

@ -7,6 +7,30 @@ if(POLICY CMP0072)
cmake_policy(SET CMP0072 NEW)
endif()
include(CheckCSourceCompiles)
include(CMakePushCheckState)
function(raylib_check_libatomic_required result)
set(_atomic_test_source "
int main(void)
{
volatile long long value = 0;
return (int)__atomic_fetch_add(&value, 1, __ATOMIC_SEQ_CST);
}")
check_c_source_compiles("${_atomic_test_source}" RAYLIB_ATOMICS_WITHOUT_LIBATOMIC)
if (RAYLIB_ATOMICS_WITHOUT_LIBATOMIC)
set(${result} FALSE PARENT_SCOPE)
else ()
cmake_push_check_state()
list(APPEND CMAKE_REQUIRED_LIBRARIES atomic)
check_c_source_compiles("${_atomic_test_source}" RAYLIB_ATOMICS_WITH_LIBATOMIC)
cmake_pop_check_state()
set(${result} ${RAYLIB_ATOMICS_WITH_LIBATOMIC} PARENT_SCOPE)
endif ()
endfunction()
set(RAYLIB_DEPENDENCIES "include(CMakeFindDependencyMacro)")
if (${PLATFORM} STREQUAL "Desktop")
@ -67,6 +91,21 @@ if (${PLATFORM} STREQUAL "Desktop")
endif ()
endif ()
elseif (${PLATFORM} STREQUAL "Win32")
if ((NOT WIN32) AND (NOT CMAKE_C_COMPILER MATCHES "mingw|mingw32|mingw64"))
message(FATAL_ERROR "Win32 platform requires Windows or a cross compiler.")
endif ()
set(PLATFORM_CPP "PLATFORM_DESKTOP_WIN32")
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
if (${OPENGL_VERSION} MATCHES "Software")
set(GRAPHICS "GRAPHICS_API_OPENGL_SOFTWARE")
endif ()
find_package(OpenGL QUIET)
set(LIBS_PRIVATE ${OPENGL_LIBRARIES} winmm)
elseif (${PLATFORM} STREQUAL "Web")
set(PLATFORM_CPP "PLATFORM_WEB")
if(NOT GRAPHICS)
@ -222,6 +261,14 @@ endif ()
set(LIBS_PRIVATE ${LIBS_PRIVATE} ${OPENAL_LIBRARY})
if (SUPPORT_MODULE_RAUDIO AND UNIX AND NOT APPLE)
raylib_check_libatomic_required(RAYLIB_LIBATOMIC_REQUIRED)
if (RAYLIB_LIBATOMIC_REQUIRED)
message(STATUS "64-bit atomics require libatomic")
list(APPEND LIBS_PRIVATE atomic)
endif ()
endif ()
if (${PLATFORM} MATCHES "Desktop")
set(LIBS_PRIVATE ${LIBS_PRIVATE} glfw)
endif ()

View File

@ -10,7 +10,9 @@ string(REGEX MATCHALL ${MACRO_REGEX} MACRO_LIST ${CONFIG_HEADER_CONTENT})
set(CONFIG_HEADER_FLAGS ${MACRO_LIST})
list(FILTER CONFIG_HEADER_FLAGS INCLUDE REGEX "^.+SUPPORT_")
list(TRANSFORM CONFIG_HEADER_FLAGS REPLACE ${MACRO_REGEX} [[\2=OFF]] REGEX "^//")
list(TRANSFORM CONFIG_HEADER_FLAGS REPLACE ${MACRO_REGEX} [[\2=ON]])
list(TRANSFORM CONFIG_HEADER_FLAGS REPLACE ${MACRO_REGEX} [[\2=\3]] REGEX "^[^/]")
list(TRANSFORM CONFIG_HEADER_FLAGS REPLACE [[=0$]] [[=OFF]])
list(TRANSFORM CONFIG_HEADER_FLAGS REPLACE [[=1$]] [[=ON]])
set(CONFIG_HEADER_VALUES ${MACRO_LIST})
list(FILTER CONFIG_HEADER_VALUES EXCLUDE REGEX "(^.+SUPPORT_)|(^//)")

View File

@ -1,6 +1,18 @@
# Setup the project and settings
cmake_minimum_required(VERSION 3.22)
project(examples)
# Include raylib's cmake helper functions, so the examples can also be
# configured standalone (`cd examples && cmake .`) and not only as part
# of the raylib project.
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../cmake")
include(AddIfFlagCompiles)
# Default to the Desktop platform when configured standalone.
if (NOT DEFINED PLATFORM)
set(PLATFORM "Desktop" CACHE STRING "Platform to build examples for")
endif ()
# Directories that contain examples
set(example_dirs
audio
@ -98,7 +110,6 @@ if (${PLATFORM} MATCHES "Android")
elseif (${PLATFORM} MATCHES "Web")
set(example_sources) # clear example_sources
list(APPEND example_sources others/web_basic_window.c)
list(APPEND example_sources core/core_input_gestures_testbed.c)
elseif ("${PLATFORM}" STREQUAL "DRM")
@ -190,6 +201,7 @@ foreach (example_source ${example_sources})
target_link_libraries(${example_name} "-framework IOKit")
target_link_libraries(${example_name} "-framework Cocoa")
target_link_libraries(${example_name} "-framework OpenGL")
target_link_libraries(${example_name} "-framework QuartzCore")
endif()
elseif (${PLATFORM} MATCHES "RGFW")

View File

@ -18,8 +18,10 @@
# > PLATFORM_DESKTOP_RGFW (RGFW backend):
# - Windows (Win32, Win64)
# - Linux (X11 desktop mode)
# - macOS/OSX (x64, arm64 (not tested))
# - macOS/OSX (x64, arm64)
# - Others (not tested)
# > PLATFORM_DESKTOP_WIN32 (native Win32):
# - Windows (Win32, Win64)
# > PLATFORM_WEB_RGFW:
# - HTML5 (WebAssembly)
# > PLATFORM_WEB:
@ -120,6 +122,14 @@ BUILD_WEB_RESOURCES_PATH ?= $(dir $<)resources@resources
# WARNING: Requires raylib compiled with GRAPHICS_API_OPENGL_ES3
BUILD_WEB_WEBGL2 ?= FALSE
# Detect the shell used by make: cmd preserves quotes, while sh removes them.
ifndef PLATFORM_SHELL
PLATFORM_SHELL = sh
ifeq ($(shell echo "test"),"test")
PLATFORM_SHELL = cmd
endif
endif
# Determine PLATFORM_OS when required
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW PLATFORM_DESKTOP_SDL PLATFORM_DESKTOP_RGFW PLATFORM_WEB PLATFORM_WEB_RGFW))
# No uname.exe on MinGW!, but OS=Windows_NT on Windows!
@ -312,6 +322,9 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
ifeq ($(PLATFORM_OS),BSD)
LDFLAGS += -Lsrc -L$(RAYLIB_LIB_PATH)
endif
ifeq ($(PLATFORM_OS),OSX)
LDFLAGS += -L/opt/homebrew/lib -L$(RAYLIB_LIB_PATH)
endif
endif
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_SDL)
ifeq ($(PLATFORM_OS),WINDOWS)
@ -416,7 +429,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
ifeq ($(PLATFORM_OS),OSX)
# Libraries for OSX 10.9 desktop compiling
# NOTE: Required packages: libopenal-dev libegl1-mesa-dev
LDLIBS = -lraylib -framework OpenGL -framework Cocoa -framework IOKit -framework CoreAudio -framework CoreVideo
LDLIBS = -lraylib -framework OpenGL -framework Cocoa -framework IOKit -framework CoreAudio -framework CoreVideo -framework QuartzCore
endif
ifeq ($(PLATFORM_OS),BSD)
# Libraries for FreeBSD, OpenBSD, NetBSD, DragonFly desktop compiling
@ -494,7 +507,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_RGFW)
# NOTE: Required packages: libegl1-mesa-dev
LDFLAGS += -L../src
LDLIBS = -lraylib -lm
LDLIBS += -framework Foundation -framework AppKit -framework IOKit -framework OpenGL -framework CoreVideo
LDLIBS += -framework Foundation -framework AppKit -framework IOKit -framework OpenGL -framework CoreVideo -framework QuartzCore
endif
endif
ifeq ($(TARGET_PLATFORM),PLATFORM_DRM)
@ -587,10 +600,12 @@ SHAPES = \
shapes/shapes_dashed_line \
shapes/shapes_digital_clock \
shapes/shapes_double_pendulum \
shapes/shapes_drag_puzzle \
shapes/shapes_easings_ball \
shapes/shapes_easings_box \
shapes/shapes_easings_rectangles \
shapes/shapes_easings_testbed \
shapes/shapes_ellipse_collision \
shapes/shapes_following_eyes \
shapes/shapes_hilbert_curve \
shapes/shapes_kaleidoscope \
@ -601,8 +616,11 @@ SHAPES = \
shapes/shapes_math_angle_rotation \
shapes/shapes_math_sine_cosine \
shapes/shapes_mouse_trail \
shapes/shapes_outlines_testbed \
shapes/shapes_outlines_thickness \
shapes/shapes_penrose_tile \
shapes/shapes_pie_chart \
shapes/shapes_polygon_lines \
shapes/shapes_rectangle_advanced \
shapes/shapes_rectangle_scaling \
shapes/shapes_recursive_tree \
@ -640,6 +658,7 @@ TEXTURES = \
textures/textures_npatch_drawing \
textures/textures_particles_blending \
textures/textures_polygon_drawing \
textures/textures_portal_window \
textures/textures_raw_data \
textures/textures_screen_buffer \
textures/textures_sprite_animation \
@ -691,8 +710,10 @@ MODELS = \
models/models_loading_vox \
models/models_mesh_generation \
models/models_mesh_picking \
models/models_mesh_uv_painting \
models/models_orthographic_projection \
models/models_point_rendering \
models/models_procedural_decals \
models/models_rlgl_solar_system \
models/models_rotating_cube \
models/models_skybox_rendering \
@ -718,6 +739,7 @@ SHADERS = \
shaders/shaders_hybrid_rendering \
shaders/shaders_julia_set \
shaders/shaders_lightmap_rendering \
shaders/shaders_lights_bloom \
shaders/shaders_mandelbrot_set \
shaders/shaders_mesh_instancing \
shaders/shaders_model_shader \
@ -739,6 +761,7 @@ SHADERS = \
shaders/shaders_vertex_displacement
AUDIO = \
audio/audio_amp_envelope \
audio/audio_mixed_processor \
audio/audio_module_playing \
audio/audio_music_stream \
@ -779,7 +802,32 @@ endif
clean:
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
ifeq ($(PLATFORM_OS),WINDOWS)
ifeq ($(PLATFORM_SHELL),cmd)
del *.o *.exe /s
else
find . -type f '(' -name '*.o' -o -name '*.exe' ')' -exec rm -f {} +
endif
endif
ifeq ($(PLATFORM_OS),BSD)
find . -type f -perm -ugo+x -delete
rm -fv *.o
endif
ifeq ($(PLATFORM_OS),LINUX)
find . -type f -executable -delete
rm -fv *.o
endif
ifeq ($(PLATFORM_OS),OSX)
find . -type f -perm +ugo+x -delete
rm -f *.o
endif
endif
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_WIN32)
ifeq ($(PLATFORM_OS),WINDOWS)
ifeq ($(PLATFORM_SHELL),cmd)
del *.o *.exe /s
else
find . -type f '(' -name '*.o' -o -name '*.exe' ')' -exec rm -f {} +
endif
endif
ifeq ($(PLATFORM_OS),BSD)
find . -type f -perm -ugo+x -delete
@ -799,7 +847,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DRM)
rm -fv *.o
endif
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW))
ifeq ($(PLATFORM_OS),WINDOWS)
ifeq ($(PLATFORM_SHELL),cmd)
del *.wasm *.html *.js *.data
else
rm -f */*.wasm */*.html */*.js */*.data

View File

@ -411,7 +411,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
ifeq ($(PLATFORM_OS),OSX)
# Libraries for OSX 10.9 desktop compiling
# NOTE: Required packages: libopenal-dev libegl1-mesa-dev
LDLIBS = -lraylib -framework OpenGL -framework Cocoa -framework IOKit -framework CoreAudio -framework CoreVideo
LDLIBS = -lraylib -framework OpenGL -framework Cocoa -framework IOKit -framework CoreAudio -framework CoreVideo -framework QuartzCore
endif
ifeq ($(PLATFORM_OS),BSD)
# Libraries for FreeBSD, OpenBSD, NetBSD, DragonFly desktop compiling
@ -480,7 +480,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_RGFW)
# NOTE: Required packages: libegl1-mesa-dev
LDFLAGS += -L../src
LDLIBS = -lraylib -lm
LDLIBS += -framework Foundation -framework AppKit -framework IOKit -framework OpenGL -framework CoreVideo
LDLIBS += -framework Foundation -framework AppKit -framework IOKit -framework OpenGL -framework CoreVideo -framework QuartzCore
endif
endif
ifeq ($(TARGET_PLATFORM),PLATFORM_DRM)
@ -561,10 +561,12 @@ SHAPES = \
shapes/shapes_dashed_line \
shapes/shapes_digital_clock \
shapes/shapes_double_pendulum \
shapes/shapes_drag_puzzle \
shapes/shapes_easings_ball \
shapes/shapes_easings_box \
shapes/shapes_easings_rectangles \
shapes/shapes_easings_testbed \
shapes/shapes_ellipse_collision \
shapes/shapes_following_eyes \
shapes/shapes_hilbert_curve \
shapes/shapes_kaleidoscope \
@ -575,8 +577,11 @@ SHAPES = \
shapes/shapes_math_angle_rotation \
shapes/shapes_math_sine_cosine \
shapes/shapes_mouse_trail \
shapes/shapes_outlines_testbed \
shapes/shapes_outlines_thickness \
shapes/shapes_penrose_tile \
shapes/shapes_pie_chart \
shapes/shapes_polygon_lines \
shapes/shapes_rectangle_advanced \
shapes/shapes_rectangle_scaling \
shapes/shapes_recursive_tree \
@ -614,6 +619,7 @@ TEXTURES = \
textures/textures_npatch_drawing \
textures/textures_particles_blending \
textures/textures_polygon_drawing \
textures/textures_portal_window \
textures/textures_raw_data \
textures/textures_screen_buffer \
textures/textures_sprite_animation \
@ -665,8 +671,10 @@ MODELS = \
models/models_loading_vox \
models/models_mesh_generation \
models/models_mesh_picking \
models/models_mesh_uv_painting \
models/models_orthographic_projection \
models/models_point_rendering \
models/models_procedural_decals \
models/models_rlgl_solar_system \
models/models_rotating_cube \
models/models_skybox_rendering \
@ -692,6 +700,7 @@ SHADERS = \
shaders/shaders_hybrid_rendering \
shaders/shaders_julia_set \
shaders/shaders_lightmap_rendering \
shaders/shaders_lights_bloom \
shaders/shaders_mandelbrot_set \
shaders/shaders_mesh_instancing \
shaders/shaders_model_shader \
@ -713,6 +722,7 @@ SHADERS = \
shaders/shaders_vertex_displacement
AUDIO = \
audio/audio_amp_envelope \
audio/audio_mixed_processor \
audio/audio_module_playing \
audio/audio_music_stream \
@ -921,6 +931,9 @@ shapes/shapes_digital_clock: shapes/shapes_digital_clock.c
shapes/shapes_double_pendulum: shapes/shapes_double_pendulum.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_drag_puzzle: shapes/shapes_drag_puzzle.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_easings_ball: shapes/shapes_easings_ball.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
@ -933,6 +946,9 @@ shapes/shapes_easings_rectangles: shapes/shapes_easings_rectangles.c
shapes/shapes_easings_testbed: shapes/shapes_easings_testbed.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_ellipse_collision: shapes/shapes_ellipse_collision.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_following_eyes: shapes/shapes_following_eyes.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
@ -963,12 +979,21 @@ shapes/shapes_math_sine_cosine: shapes/shapes_math_sine_cosine.c
shapes/shapes_mouse_trail: shapes/shapes_mouse_trail.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_outlines_testbed: shapes/shapes_outlines_testbed.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_outlines_thickness: shapes/shapes_outlines_thickness.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_penrose_tile: shapes/shapes_penrose_tile.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_pie_chart: shapes/shapes_pie_chart.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_polygon_lines: shapes/shapes_polygon_lines.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_rectangle_advanced: shapes/shapes_rectangle_advanced.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
@ -1098,6 +1123,9 @@ textures/textures_polygon_drawing: textures/textures_polygon_drawing.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file textures/resources/cat.png@resources/cat.png
textures/textures_portal_window: textures/textures_portal_window.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
textures/textures_raw_data: textures/textures_raw_data.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file textures/resources/fudesumi.raw@resources/fudesumi.raw
@ -1317,12 +1345,18 @@ models/models_mesh_picking: models/models_mesh_picking.c
--preload-file models/resources/models/obj/turret.obj@resources/models/obj/turret.obj \
--preload-file models/resources/models/obj/turret_diffuse.png@resources/models/obj/turret_diffuse.png
models/models_mesh_uv_painting: models/models_mesh_uv_painting.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
models/models_orthographic_projection: models/models_orthographic_projection.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
models/models_point_rendering: models/models_point_rendering.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
models/models_procedural_decals: models/models_procedural_decals.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
models/models_rlgl_solar_system: models/models_rlgl_solar_system.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
@ -1460,6 +1494,12 @@ shaders/shaders_lightmap_rendering: shaders/shaders_lightmap_rendering.c
--preload-file shaders/resources/cubicmap_atlas.png@resources/cubicmap_atlas.png \
--preload-file shaders/resources/spark_flame.png@resources/spark_flame.png
shaders/shaders_lights_bloom: shaders/shaders_lights_bloom.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file shaders/resources/shaders/glsl100/lights_bloom.vs@resources/shaders/glsl100/lights_bloom.vs \
--preload-file shaders/resources/shaders/glsl100/lights_bloom.fs@resources/shaders/glsl100/lights_bloom.fs \
--preload-file shaders/resources/shaders/glsl100/lights_bloom_post.fs@resources/shaders/glsl100/lights_bloom_post.fs
shaders/shaders_mandelbrot_set: shaders/shaders_mandelbrot_set.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file shaders/resources/shaders/glsl100/mandelbrot_set.fs@resources/shaders/glsl100/mandelbrot_set.fs
@ -1567,6 +1607,9 @@ shaders/shaders_vertex_displacement: shaders/shaders_vertex_displacement.c
--preload-file shaders/resources/shaders/glsl100/vertex_displacement.fs@resources/shaders/glsl100/vertex_displacement.fs
# Compile AUDIO examples
audio/audio_amp_envelope: audio/audio_amp_envelope.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
audio/audio_mixed_processor: audio/audio_mixed_processor.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file audio/resources/country.mp3@resources/country.mp3 \

View File

@ -13,11 +13,13 @@ The examples assume you have already built the `raylib` library in `../src`.
The [Zig](https://ziglang.org/) toolchain can compile `C` and `C++` in addition to `Zig`.
You may find it easier to use than other toolchains, especially when it comes to cross-compiling.
- `zig build` to compile all examples
Run the following commands from the repository root:
- `zig build examples` to compile all examples
- `zig build [module]` to compile all examples for a module (e.g. `zig build core`)
- `zig build [example]` to compile _and run_ a particular example (e.g. `zig build core_basic_window`)
## EXAMPLES COLLECTION [TOTAL: 212]
## EXAMPLES COLLECTION [TOTAL: 222]
### category: core [49]
@ -75,7 +77,7 @@ Examples using raylib [core](../src/rcore.c) module platform functionality: wind
| [core_keyboard_testbed](core/core_keyboard_testbed.c) | <img src="core/core_keyboard_testbed.png" alt="core_keyboard_testbed" width="80"> | ⭐⭐☆☆ | 5.6 | 5.6 | [Ramon Santamaria](https://github.com/raysan5) |
| [core_window_web](core/core_window_web.c) | <img src="core/core_window_web.png" alt="core_window_web" width="80"> | ⭐☆☆☆ | 1.3 | 5.5 | [Ramon Santamaria](https://github.com/raysan5) |
### category: shapes [40]
### category: shapes [45]
Examples using raylib shapes drawing functionality, provided by raylib [shapes](../src/rshapes.c) module.
@ -121,8 +123,13 @@ Examples using raylib shapes drawing functionality, provided by raylib [shapes](
| [shapes_penrose_tile](shapes/shapes_penrose_tile.c) | <img src="shapes/shapes_penrose_tile.png" alt="shapes_penrose_tile" width="80"> | ⭐⭐⭐⭐️ | 5.5 | 6.0 | [David Buzatto](https://github.com/davidbuzatto) |
| [shapes_hilbert_curve](shapes/shapes_hilbert_curve.c) | <img src="shapes/shapes_hilbert_curve.png" alt="shapes_hilbert_curve" width="80"> | ⭐⭐⭐☆ | 5.6 | 5.6 | [Hamza RAHAL](https://github.com/hmz-rhl) |
| [shapes_easings_testbed](shapes/shapes_easings_testbed.c) | <img src="shapes/shapes_easings_testbed.png" alt="shapes_easings_testbed" width="80"> | ⭐⭐⭐☆ | 2.5 | 2.5 | [Juan Miguel López](https://github.com/flashback-fx) |
| [shapes_drag_puzzle](shapes/shapes_drag_puzzle.c) | <img src="shapes/shapes_drag_puzzle.png" alt="shapes_drag_puzzle" width="80"> | ⭐☆☆☆ | 6.0 | 6.0 | [Gabriel Piangers](https://github.com/gabriel-piangers) |
| [shapes_ellipse_collision](shapes/shapes_ellipse_collision.c) | <img src="shapes/shapes_ellipse_collision.png" alt="shapes_ellipse_collision" width="80"> | ⭐⭐☆☆ | 5.5 | 5.5 | [Ziya](https://github.com/Monjaris) |
| [shapes_outlines_testbed](shapes/shapes_outlines_testbed.c) | <img src="shapes/shapes_outlines_testbed.png" alt="shapes_outlines_testbed" width="80"> | ⭐⭐⭐☆ | 6.1 | 6.1 | [Matthew Roush](https://github.com/MatthewRoush) |
| [shapes_outlines_thickness](shapes/shapes_outlines_thickness.c) | <img src="shapes/shapes_outlines_thickness.png" alt="shapes_outlines_thickness" width="80"> | ⭐☆☆☆ | 6.1 | 6.1 | [Matthew Roush](https://github.com/MatthewRoush) |
| [shapes_polygon_lines](shapes/shapes_polygon_lines.c) | <img src="shapes/shapes_polygon_lines.png" alt="shapes_polygon_lines" width="80"> | ⭐⭐☆☆ | 6.1 | 6.1 | [Matthew Roush](https://github.com/MatthewRoush) |
### category: textures [32]
### category: textures [33]
Examples using raylib textures functionality, including image/textures loading/generation and drawing, provided by raylib [textures](../src/rtextures.c) module.
@ -146,7 +153,7 @@ Examples using raylib textures functionality, including image/textures loading/g
| [textures_sprite_button](textures/textures_sprite_button.c) | <img src="textures/textures_sprite_button.png" alt="textures_sprite_button" width="80"> | ⭐⭐☆☆ | 2.5 | 2.5 | [Ramon Santamaria](https://github.com/raysan5) |
| [textures_sprite_explosion](textures/textures_sprite_explosion.c) | <img src="textures/textures_sprite_explosion.png" alt="textures_sprite_explosion" width="80"> | ⭐⭐☆☆ | 2.5 | 3.5 | [Ramon Santamaria](https://github.com/raysan5) |
| [textures_bunnymark](textures/textures_bunnymark.c) | <img src="textures/textures_bunnymark.png" alt="textures_bunnymark" width="80"> | ⭐⭐⭐☆ | 1.6 | 2.5 | [Ramon Santamaria](https://github.com/raysan5) |
| [textures_mouse_painting](textures/textures_mouse_painting.c) | <img src="textures/textures_mouse_painting.png" alt="textures_mouse_painting" width="80"> | ⭐⭐⭐☆ | 3.0 | 3.0 | [Chris Dill](https://github.com/MysteriousSpace) |
| [textures_mouse_painting](textures/textures_mouse_painting.c) | <img src="textures/textures_mouse_painting.png" alt="textures_mouse_painting" width="80"> | ⭐⭐⭐☆ | 3.0 | 6.0 | [Chris Dill](https://github.com/MysteriousSpace) |
| [textures_blend_modes](textures/textures_blend_modes.c) | <img src="textures/textures_blend_modes.png" alt="textures_blend_modes" width="80"> | ⭐☆☆☆ | 3.5 | 3.5 | [Karlo Licudine](https://github.com/accidentalrebel) |
| [textures_tiled_drawing](textures/textures_tiled_drawing.c) | <img src="textures/textures_tiled_drawing.png" alt="textures_tiled_drawing" width="80"> | ⭐⭐⭐☆ | 3.0 | 4.2 | [Vlad Adrian](https://github.com/demizdor) |
| [textures_polygon_drawing](textures/textures_polygon_drawing.c) | <img src="textures/textures_polygon_drawing.png" alt="textures_polygon_drawing" width="80"> | ⭐☆☆☆ | 3.7 | 3.7 | [Chris Camacho](https://github.com/chriscamacho) |
@ -160,6 +167,7 @@ Examples using raylib textures functionality, including image/textures loading/g
| [textures_sprite_stacking](textures/textures_sprite_stacking.c) | <img src="textures/textures_sprite_stacking.png" alt="textures_sprite_stacking" width="80"> | ⭐⭐☆☆ | 6.0 | 6.0 | [Robin](https://github.com/RobinsAviary) |
| [textures_cellular_automata](textures/textures_cellular_automata.c) | <img src="textures/textures_cellular_automata.png" alt="textures_cellular_automata" width="80"> | ⭐⭐☆☆ | 5.6 | 5.6 | [Jordi Santonja](https://github.com/JordSant) |
| [textures_framebuffer_rendering](textures/textures_framebuffer_rendering.c) | <img src="textures/textures_framebuffer_rendering.png" alt="textures_framebuffer_rendering" width="80"> | ⭐⭐☆☆ | 5.6 | 5.6 | [Jack Boakes](https://github.com/jackboakes) |
| [textures_portal_window](textures/textures_portal_window.c) | <img src="textures/textures_portal_window.png" alt="textures_portal_window" width="80"> | ⭐⭐⭐⭐️ | 6.0 | 6.0 | [PanicTitan](https://github.com/PanicTitan) |
### category: text [16]
@ -184,7 +192,7 @@ Examples using raylib text functionality, including sprite fonts loading/generat
| [text_words_alignment](text/text_words_alignment.c) | <img src="text/text_words_alignment.png" alt="text_words_alignment" width="80"> | ⭐☆☆☆ | 6.0 | 6.0 | [JP Mortiboys](https://github.com/themushroompirates) |
| [text_strings_management](text/text_strings_management.c) | <img src="text/text_strings_management.png" alt="text_strings_management" width="80"> | ⭐⭐⭐☆ | 6.0 | 6.0 | [David Buzatto](https://github.com/davidbuzatto) |
### category: models [30]
### category: models [32]
Examples using raylib models functionality, including models loading/generation and drawing, provided by raylib [models](../src/rmodels.c) module.
@ -220,8 +228,10 @@ Examples using raylib models functionality, including models loading/generation
| [models_animation_blend_custom](models/models_animation_blend_custom.c) | <img src="models/models_animation_blend_custom.png" alt="models_animation_blend_custom" width="80"> | ⭐⭐⭐⭐️ | 5.5 | 6.0 | [dmitrii-brand](https://github.com/dmitrii-brand) |
| [models_animation_blending](models/models_animation_blending.c) | <img src="models/models_animation_blending.png" alt="models_animation_blending" width="80"> | ⭐⭐⭐⭐️ | 5.5 | 6.0 | [Kirandeep](https://github.com/Kirandeep-Singh-Khehra) |
| [models_animation_timing](models/models_animation_timing.c) | <img src="models/models_animation_timing.png" alt="models_animation_timing" width="80"> | ⭐⭐⭐☆ | 6.0 | 6.0 | [Ramon Santamaria](https://github.com/raysan5) |
| [models_mesh_uv_painting](models/models_mesh_uv_painting.c) | <img src="models/models_mesh_uv_painting.png" alt="models_mesh_uv_painting" width="80"> | ⭐⭐⭐⭐️ | 6.0 | 6.0 | [PanicTitan](https://github.com/PanicTitan) |
| [models_procedural_decals](models/models_procedural_decals.c) | <img src="models/models_procedural_decals.png" alt="models_procedural_decals" width="80"> | ⭐⭐⭐⭐️ | 6.0 | 6.0 | [PanicTitan](https://github.com/PanicTitan) |
### category: shaders [35]
### category: shaders [36]
Examples using raylib shaders functionality, including shaders loading, parameters configuration and drawing using them (model shaders and postprocessing shaders). This functionality is directly provided by raylib [rlgl](../src/rlgl.h) module.
@ -262,8 +272,9 @@ Examples using raylib shaders functionality, including shaders loading, paramete
| [shaders_game_of_life](shaders/shaders_game_of_life.c) | <img src="shaders/shaders_game_of_life.png" alt="shaders_game_of_life" width="80"> | ⭐⭐⭐☆ | 6.0 | 6.0 | [Jordi Santonja](https://github.com/JordSant) |
| [shaders_rlgl_compute](shaders/shaders_rlgl_compute.c) | <img src="shaders/shaders_rlgl_compute.png" alt="shaders_rlgl_compute" width="80"> | ⭐⭐⭐⭐️ | 4.0 | 4.0 | [Teddy Astie](https://github.com/tsnake41) |
| [shaders_cel_shading](shaders/shaders_cel_shading.c) | <img src="shaders/shaders_cel_shading.png" alt="shaders_cel_shading" width="80"> | ⭐⭐⭐☆ | 6.0 | 6.0 | [Gleb A](https://github.com/ggrizzly) |
| [shaders_lights_bloom](shaders/shaders_lights_bloom.c) | <img src="shaders/shaders_lights_bloom.png" alt="shaders_lights_bloom" width="80"> | ⭐⭐⭐☆ | 6.0 | 6.0 | [PanicTitan](https://github.com/PanicTitan) |
### category: audio [10]
### category: audio [11]
Examples using raylib audio functionality, including sound/music loading and playing. This functionality is provided by raylib [raudio](../src/raudio.c) module. Note this module can be used standalone independently of raylib.
@ -276,9 +287,10 @@ Examples using raylib audio functionality, including sound/music loading and pla
| [audio_mixed_processor](audio/audio_mixed_processor.c) | <img src="audio/audio_mixed_processor.png" alt="audio_mixed_processor" width="80"> | ⭐⭐⭐⭐️ | 4.2 | 4.2 | [hkc](https://github.com/hatkidchan) |
| [audio_stream_effects](audio/audio_stream_effects.c) | <img src="audio/audio_stream_effects.png" alt="audio_stream_effects" width="80"> | ⭐⭐⭐⭐️ | 4.2 | 5.0 | [Ramon Santamaria](https://github.com/raysan5) |
| [audio_sound_multi](audio/audio_sound_multi.c) | <img src="audio/audio_sound_multi.png" alt="audio_sound_multi" width="80"> | ⭐⭐☆☆ | 5.0 | 5.0 | [Jeffery Myers](https://github.com/JeffM2501) |
| [audio_sound_positioning](audio/audio_sound_positioning.c) | <img src="audio/audio_sound_positioning.png" alt="audio_sound_positioning" width="80"> | ⭐⭐☆☆ | 5.5 | 5.5 | [Le Juez Victor](https://github.com/Bigfoot71) |
| [audio_sound_positioning](audio/audio_sound_positioning.c) | <img src="audio/audio_sound_positioning.png" alt="audio_sound_positioning" width="80"> | ⭐⭐☆☆ | 5.5 | 6.0 | [Le Juez Victor](https://github.com/Bigfoot71) |
| [audio_spectrum_visualizer](audio/audio_spectrum_visualizer.c) | <img src="audio/audio_spectrum_visualizer.png" alt="audio_spectrum_visualizer" width="80"> | ⭐⭐⭐☆ | 6.0 | 6.0 | [IANN](https://github.com/meisei4) |
| [audio_stream_callback](audio/audio_stream_callback.c) | <img src="audio/audio_stream_callback.png" alt="audio_stream_callback" width="80"> | ⭐⭐⭐☆ | 6.0 | 6.0 | [Dan Hoang](https://github.com/dan-hoang) |
| [audio_amp_envelope](audio/audio_amp_envelope.c) | <img src="audio/audio_amp_envelope.png" alt="audio_amp_envelope" width="80"> | ⭐☆☆☆ | 6.0 | 6.0 | [Arbinda Rizki Muhammad](https://github.com/arbipink) |
Some example missing? As always, contributions are welcome, feel free to send new examples!
Here is an [examples template](examples_template.c) with instructions to start with!

View File

@ -113,6 +113,7 @@ int main(void)
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadMusicStream(music); // Unload music stream buffers from RAM
UnloadSound(sound);
DetachAudioMixedProcessor(ProcessAudio); // Disconnect audio processor

View File

@ -90,7 +90,7 @@ int main(void)
for (int i = 0; i < BUFFER_SIZE; i++)
{
int wavelength = SAMPLE_RATE/sineFrequency;
buffer[i] = sin(2*PI*sineIndex/wavelength);
buffer[i] = sinf(2*PI*sineIndex/wavelength);
sineIndex++;
if (sineIndex >= wavelength)
@ -116,8 +116,8 @@ int main(void)
DrawText("Up/down to change frequency", 10, 10, 20, DARKGRAY);
DrawText("Left/right to pan", 10, 30, 20, DARKGRAY);
int windowStart = (GetTime() - sineStartTime)*SAMPLE_RATE;
int windowSize = 0.1f*SAMPLE_RATE;
int windowStart = (int)((GetTime() - sineStartTime)*SAMPLE_RATE);
int windowSize = SAMPLE_RATE/10;
int wavelength = SAMPLE_RATE/sineFrequency;
// Draw a sine wave with the same frequency as the one being sent to the audio stream
@ -125,8 +125,8 @@ int main(void)
{
int t0 = windowStart + i*windowSize/screenWidth;
int t1 = windowStart + (i + 1)*windowSize/screenWidth;
Vector2 startPos = { i, 250 + 50*sin(2*PI*t0/wavelength) };
Vector2 endPos = { i + 1, 250 + 50*sin(2*PI*t1/wavelength) };
Vector2 startPos = { (float)i, 250 + 50*sinf(2*PI*t0/wavelength) };
Vector2 endPos = { (float)i + 1, 250 + 50*sinf(2*PI*t1/wavelength) };
DrawLineV(startPos, endPos, RED);
}

View File

@ -4,7 +4,7 @@
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 5.5, last time updated with raylib 5.5
* Example originally created with raylib 5.5, last time updated with raylib 6.0
*
* Example contributed by Le Juez Victor (@Bigfoot71) and reviewed by Ramon Santamaria (@raysan5)
*
@ -116,14 +116,14 @@ static void SetSoundPosition(Camera listener, Sound sound, Vector3 position, flo
// Calculate normalized vectors for spatial positioning
Vector3 normalizedDirection = Vector3Normalize(direction);
Vector3 forward = Vector3Normalize(Vector3Subtract(listener.target, listener.position));
Vector3 right = Vector3Normalize(Vector3CrossProduct(listener.up, forward));
Vector3 right = Vector3Normalize(Vector3CrossProduct(forward, listener.up));
// Reduce volume for sounds behind the listener
float dotProduct = Vector3DotProduct(forward, normalizedDirection);
if (dotProduct < 0.0f) attenuation *= (1.0f + dotProduct*0.5f);
// Set stereo panning based on sound position relative to listener
float pan = 0.5f + 0.5f*Vector3DotProduct(normalizedDirection, right);
float pan = Vector3DotProduct(normalizedDirection, right);
// Apply final sound properties
SetSoundVolume(sound, attenuation);

View File

@ -133,8 +133,8 @@ int main(void)
// Draw the last 10 ms of uploaded audio
for (int i = 0; i < screenWidth; i++)
{
Vector2 startPos = { i, 250 - 50*buffer[SAMPLE_RATE - SAMPLE_RATE/100 + i*SAMPLE_RATE/100/screenWidth] };
Vector2 endPos = { i + 1, 250 - 50*buffer[SAMPLE_RATE - SAMPLE_RATE/100 + (i + 1)*SAMPLE_RATE/100/screenWidth] };
Vector2 startPos = {(float)i, 250 - 50*buffer[SAMPLE_RATE - SAMPLE_RATE/100 + i*SAMPLE_RATE/100/screenWidth] };
Vector2 endPos = { (float)(i + 1), 250 - 50*buffer[SAMPLE_RATE - SAMPLE_RATE/100 + (i + 1)*SAMPLE_RATE/100/screenWidth] };
DrawLineV(startPos, endPos, RED);
}
@ -161,9 +161,9 @@ static void SineCallback(void *framesOut, unsigned int frameCount)
int wavelength = SAMPLE_RATE/waveFrequency;
// Synthesize the sine wave
for (int i = 0; i < frameCount; i++)
for (unsigned int i = 0; i < frameCount; i++)
{
((float *)framesOut)[i] = sin(2*PI*waveIndex/wavelength);
((float *)framesOut)[i] = sinf(2*PI*waveIndex/wavelength);
waveIndex++;
@ -175,8 +175,8 @@ static void SineCallback(void *framesOut, unsigned int frameCount)
}
// Save the synthesized samples for later drawing
for (int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
for (int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float *)framesOut)[i];
for (unsigned int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
for (unsigned int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float *)framesOut)[i];
}
static void SquareCallback(void *framesOut, unsigned int frameCount)
@ -184,9 +184,9 @@ static void SquareCallback(void *framesOut, unsigned int frameCount)
int wavelength = SAMPLE_RATE/waveFrequency;
// Synthesize the square wave
for (int i = 0; i < frameCount; i++)
for (unsigned int i = 0; i < frameCount; i++)
{
((float *)framesOut)[i] = (waveIndex < wavelength/2)? 1 : -1;
((float *)framesOut)[i] = (waveIndex < wavelength/2)? 1.0f : -1.0f;
waveIndex++;
if (waveIndex >= wavelength)
@ -197,8 +197,8 @@ static void SquareCallback(void *framesOut, unsigned int frameCount)
}
// Save the synthesized samples for later drawing
for (int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
for (int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float *)framesOut)[i];
for (unsigned int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
for (unsigned int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float *)framesOut)[i];
}
static void TriangleCallback(void *framesOut, unsigned int frameCount)
@ -206,7 +206,7 @@ static void TriangleCallback(void *framesOut, unsigned int frameCount)
int wavelength = SAMPLE_RATE/waveFrequency;
// Synthesize the triangle wave
for (int i = 0; i < frameCount; i++)
for (unsigned int i = 0; i < frameCount; i++)
{
((float *)framesOut)[i] = (waveIndex < wavelength/2)? (-1 + 2.0f*waveIndex/(wavelength/2)) : (1 - 2.0f*(waveIndex - wavelength/2)/(wavelength/2));
waveIndex++;
@ -219,8 +219,8 @@ static void TriangleCallback(void *framesOut, unsigned int frameCount)
}
// Save the synthesized samples for later drawing
for (int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
for (int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float *)framesOut)[i];
for (unsigned int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
for (unsigned int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float *)framesOut)[i];
}
static void SawtoothCallback(void *framesOut, unsigned int frameCount)
@ -228,7 +228,7 @@ static void SawtoothCallback(void *framesOut, unsigned int frameCount)
int wavelength = SAMPLE_RATE/waveFrequency;
// Synthesize the sawtooth wave
for (int i = 0; i < frameCount; i++)
for (unsigned int i = 0; i < frameCount; i++)
{
((float *)framesOut)[i] = -1 + 2.0f*waveIndex/wavelength;
waveIndex++;
@ -241,6 +241,6 @@ static void SawtoothCallback(void *framesOut, unsigned int frameCount)
}
// Save the synthesized samples for later drawing
for (int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
for (int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float *)framesOut)[i];
for (unsigned int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
for (unsigned int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float*)framesOut)[i];
}

File diff suppressed because it is too large Load Diff

View File

@ -54,7 +54,7 @@ int main(void)
Camera2D camera = { 0 };
camera.target = (Vector2){ player.x + 20.0f, player.y + 20.0f };
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
camera.offset = (Vector2){ GetRenderWidth()/2.0f, GetRenderHeight()/2.0f };
camera.rotation = 0.0f;
camera.zoom = 1.0f;

View File

@ -65,8 +65,8 @@ int main(void)
// Get the world point that is under the mouse
Vector2 mouseWorldPos = GetScreenToWorld2D(GetMousePosition(), camera);
// Set the offset to where the mouse is
camera.offset = GetMousePosition();
// Set the offset to where the mouse is, mouse is scaled to viewport space, but offset is in unscaled pixels
camera.offset = Vector2Multiply(GetMousePosition(), GetWindowScaleDPI());
// Set the target to match, so that the camera maps the world space point
// under the cursor to the screen space point under the cursor at any zoom
@ -86,8 +86,8 @@ int main(void)
// Get the world point that is under the mouse
Vector2 mouseWorldPos = GetScreenToWorld2D(GetMousePosition(), camera);
// Set the offset to where the mouse is
camera.offset = GetMousePosition();
// Set the offset to where the mouse is, mouse is scaled to viewport space, but offset is in unscaled pixels
camera.offset = Vector2Multiply(GetMousePosition(), GetWindowScaleDPI());
// Set the target to match, so that the camera maps the world space point
// under the cursor to the screen space point under the cursor at any zoom

View File

@ -75,7 +75,7 @@ int main(void)
Camera2D camera = { 0 };
camera.target = player.position;
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
camera.offset = (Vector2){ GetRenderWidth()/2.0f, GetRenderHeight()/2.0f };
camera.rotation = 0.0f;
camera.zoom = 1.0f;

View File

@ -19,6 +19,7 @@
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
#define PLAYER_SIZE 40
@ -39,13 +40,13 @@ int main(void)
Camera2D camera1 = { 0 };
camera1.target = (Vector2){ player1.x, player1.y };
camera1.offset = (Vector2){ 200.0f, 200.0f };
camera1.offset = Vector2Multiply((Vector2){ 200.0f, 200.0f }, GetWindowScaleDPI());
camera1.rotation = 0.0f;
camera1.zoom = 1.0f;
Camera2D camera2 = { 0 };
camera2.target = (Vector2){ player2.x, player2.y };
camera2.offset = (Vector2){ 200.0f, 200.0f };
camera2.offset = Vector2Multiply((Vector2){ 200.0f, 200.0f }, GetWindowScaleDPI());
camera2.rotation = 0.0f;
camera2.zoom = 1.0f;

View File

@ -69,7 +69,7 @@ int main(void)
// Define camera
Camera2D camera = { 0 };
camera.target = player.position;
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
camera.offset = (Vector2){ GetRenderWidth()/2.0f, GetRenderHeight()/2.0f };
camera.rotation = 0.0f;
camera.zoom = 1.0f;
@ -117,7 +117,7 @@ int main(void)
player.canJump = false;
camera.target = player.position;
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
camera.offset = (Vector2){ GetRenderWidth()/2.0f, GetRenderHeight()/2.0f };
camera.rotation = 0.0f;
camera.zoom = 1.0f;
}
@ -169,7 +169,7 @@ int main(void)
player.canJump = false;
camera.target = player.position;
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
camera.offset = (Vector2){ GetRenderWidth()/2.0f, GetRenderHeight()/2.0f };
camera.rotation = 0.0f;
camera.zoom = 1.0f;
}
@ -205,7 +205,7 @@ int main(void)
// Update camera
//----------------------------------------------------------------------------------
camera.target = player.position;
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
camera.offset = (Vector2){ GetRenderWidth()/2.0f, GetRenderHeight()/2.0f };
float minX = 1000, minY = 1000, maxX = -1000, maxY = -1000;
// WARNING: On event replay, mouse-wheel internal value is set
@ -267,7 +267,7 @@ int main(void)
player.canJump = false;
camera.target = player.position;
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
camera.offset = (Vector2){ GetRenderWidth()/2.0f, GetRenderHeight()/2.0f };
camera.rotation = 0.0f;
camera.zoom = 1.0f;
}

View File

@ -92,7 +92,7 @@ int main(void)
if (currentFps <= 0) fpsText = TextFormat("FPS: unlimited (%i)", GetFPS());
else fpsText = TextFormat("FPS: %i (target: %i)", GetFPS(), currentFps);
DrawText(fpsText, 10, 10, 20, DARKGRAY);
DrawText(TextFormat("Frame time: %02.02f ms", GetFrameTime()), 10, 30, 20, DARKGRAY);
DrawText(TextFormat("Frame time: %02.02f ms", GetFrameTime()*1000.0f), 10, 30, 20, DARKGRAY);
DrawText("Use the scroll wheel to change the fps limit, r to reset", 10, 50, 20, DARKGRAY);
// Draw the text above the circles

View File

@ -21,6 +21,7 @@
#include "raygui.h" // Required for GUI controls
#define MAX_FILEPATH_SIZE 1024
#define FILE_FILTER "DIRS*;.png;.c"
//------------------------------------------------------------------------------------
// Program main entry point
@ -41,7 +42,7 @@ int main(void)
// NOTE: LoadDirectoryFiles() loads files and directories by default,
// use LoadDirectoryFilesEx() for custom filters and recursive directories loading
//FilePathList files = LoadDirectoryFiles(directory);
FilePathList files = LoadDirectoryFilesEx(directory, ".png;.c", false);
FilePathList files = LoadDirectoryFilesEx(directory, FILE_FILTER, false);
int btnBackPressed = false;
@ -61,7 +62,22 @@ int main(void)
{
TextCopy(directory, GetPrevDirectoryPath(directory));
UnloadDirectoryFiles(files);
files = LoadDirectoryFiles(directory);
files = LoadDirectoryFilesEx(directory, FILE_FILTER, false);
listScrollIndex = 0;
listItemActive = -1;
listItemFocused = -1;
}
if ((listItemActive >= 0) && (listItemActive < (int)files.count) && DirectoryExists(files.paths[listItemActive]))
{
TextCopy(directory, files.paths[listItemActive]);
UnloadDirectoryFiles(files);
files = LoadDirectoryFilesEx(directory, FILE_FILTER, false);
listScrollIndex = 0;
listItemActive = -1;
listItemFocused = -1;
}
//----------------------------------------------------------------------------------

View File

@ -88,7 +88,7 @@ int main(void)
DrawCircleV(GetMousePosition(), 20, MAROON);
DrawRectangleRec((Rectangle) { mousePos.x - 25, mousePos.y, 50, 2 }, BLACK);
DrawRectangleRec((Rectangle) { mousePos.x, mousePos.y - 25, 2, 50 }, BLACK);
DrawText(TextFormat("[%i,%i]", GetMouseX(), GetMouseY()), mousePos.x - 44,
DrawText(TextFormat("[%i,%i]", GetMouseX(), GetMouseY()), (int)mousePos.x - 44,
(mousePos.y > GetScreenHeight() - 60)? (int)mousePos.y - 46 : (int)mousePos.y + 30, 20, BLACK);
EndDrawing();
@ -97,9 +97,6 @@ int main(void)
// De-Initialization
//--------------------------------------------------------------------------------------
// TODO: Unload all loaded resources at this point
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------

View File

@ -94,6 +94,7 @@ int main(void)
// De-Initialization
//---------------------------------------------------------
UnloadRenderTexture(target);
CloseWindow(); // Close window and OpenGL context
//----------------------------------------------------------

View File

@ -52,7 +52,7 @@ int main(void)
// The target's height is flipped (in the source Rectangle), due to OpenGL reasons
Rectangle sourceRec = { 0.0f, 0.0f, (float)target.texture.width, -(float)target.texture.height };
Rectangle destRec = { -virtualRatio, -virtualRatio, screenWidth + (virtualRatio*2), screenHeight + (virtualRatio*2) };
Rectangle destRec = { (screenWidth - screenWidth/1.25f)/2.0f, (screenHeight - screenHeight/1.25f)/2.0f, screenWidth/1.25f, screenHeight/1.25f };
Vector2 origin = { 0.0f, 0.0f };
@ -61,6 +61,9 @@ int main(void)
float cameraX = 0.0f;
float cameraY = 0.0f;
bool smoothOn = true;
bool overscan = false;
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
@ -86,6 +89,18 @@ int main(void)
worldSpaceCamera.target.y = truncf(screenSpaceCamera.target.y);
screenSpaceCamera.target.y -= worldSpaceCamera.target.y;
screenSpaceCamera.target.y *= virtualRatio;
if (IsKeyPressed(KEY_S)) smoothOn = !smoothOn;
if (IsKeyPressed(KEY_O)) overscan = !overscan;
if (overscan)
{
destRec = (Rectangle) { -virtualRatio, -virtualRatio, screenWidth + (virtualRatio*2), screenHeight + (virtualRatio*2) };
}
else
{
destRec = (Rectangle) { (screenWidth - screenWidth/1.25f)/2.0f, (screenHeight - screenHeight/1.25f)/2.0f, screenWidth/1.25f, screenHeight/1.25f };
}
//----------------------------------------------------------------------------------
// Draw
@ -101,14 +116,23 @@ int main(void)
EndTextureMode();
BeginDrawing();
ClearBackground(RED);
ClearBackground(LIGHTGRAY);
BeginMode2D(screenSpaceCamera);
if (smoothOn)
{
BeginMode2D(screenSpaceCamera);
DrawTexturePro(target.texture, sourceRec, destRec, origin, 0.0f, WHITE);
EndMode2D();
}
else
{
DrawTexturePro(target.texture, sourceRec, destRec, origin, 0.0f, WHITE);
EndMode2D();
}
DrawText(TextFormat("Screen resolution: %ix%i", screenWidth, screenHeight), 10, 10, 20, DARKBLUE);
DrawText(TextFormat("World resolution: %ix%i", virtualScreenWidth, virtualScreenHeight), 10, 40, 20, DARKGREEN);
DrawText(TextFormat("Smooth: %s", (smoothOn ? "ON" : "OFF")), 10, screenHeight - 60, 20, RED);
DrawText(TextFormat("Overscan: %s", (overscan ? "ON" : "OFF")), 10, screenHeight - 30, 20, RED);
DrawFPS(GetScreenWidth() - 95, 10);
EndDrawing();
//----------------------------------------------------------------------------------
@ -122,4 +146,4 @@ int main(void)
//--------------------------------------------------------------------------------------
return 0;
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -9,7 +9,7 @@
#
# This list is used as the main reference by [rexm] tool for examples collection validation and management
#
core;core_basic_window;★☆☆☆;1.0;1.0;2013;2025;"Ramon Santamaria";@raysan5
core;core_basic_window;★☆☆☆;1.0;1.0;2013;2026;"Ramon Santamaria";@raysan5
core;core_delta_time;★☆☆☆;5.5;6.0;2025;2025;"Robin";@RobinsAviary
core;core_input_keys;★☆☆☆;1.0;1.0;2014;2025;"Ramon Santamaria";@raysan5
core;core_input_mouse;★☆☆☆;1.0;5.5;2014;2025;"Ramon Santamaria";@raysan5
@ -98,6 +98,11 @@ shapes;shapes_ball_physics;★★☆☆;6.0;6.0;2025;2025;"David Buzatto";@david
shapes;shapes_penrose_tile;★★★★;5.5;6.0;2025;2025;"David Buzatto";@davidbuzatto
shapes;shapes_hilbert_curve;★★★☆;5.6;5.6;2025;2025;"Hamza RAHAL";@hmz-rhl
shapes;shapes_easings_testbed;★★★☆;2.5;2.5;2019;2025;"Juan Miguel López";@flashback-fx
shapes;shapes_drag_puzzle;★☆☆☆;6.0;6.0;2026;2026;"Gabriel Piangers";@gabriel-piangers
shapes;shapes_ellipse_collision;★★☆☆;5.5;5.5;2025;2025;"Ziya";@Monjaris
shapes;shapes_outlines_testbed;★★★☆;6.1;6.1;2026;2026;"Matthew Roush";@MatthewRoush
shapes;shapes_outlines_thickness;★☆☆☆;6.1;6.1;2026;2026;"Matthew Roush";@MatthewRoush
shapes;shapes_polygon_lines;★★☆☆;6.1;6.1;2026;2026;"Matthew Roush";@MatthewRoush
textures;textures_clipboard_image;★☆☆☆;6.0;6.0;2026;2026;"Maicon Santana";@maiconpintoabreu
textures;textures_magnifying_glass;★★★☆;5.6;5.6;2026;2026;"Luke Vaughan";@badram
textures;textures_logo_raylib;★☆☆☆;1.0;1.0;2014;2025;"Ramon Santamaria";@raysan5
@ -116,7 +121,7 @@ textures;textures_sprite_animation;★★☆☆;1.3;1.3;2014;2025;"Ramon Santama
textures;textures_sprite_button;★★☆☆;2.5;2.5;2019;2025;"Ramon Santamaria";@raysan5
textures;textures_sprite_explosion;★★☆☆;2.5;3.5;2019;2025;"Ramon Santamaria";@raysan5
textures;textures_bunnymark;★★★☆;1.6;2.5;2014;2025;"Ramon Santamaria";@raysan5
textures;textures_mouse_painting;★★★☆;3.0;3.0;2019;2025;"Chris Dill";@MysteriousSpace
textures;textures_mouse_painting;★★★☆;3.0;6.0;2019;2025;"Chris Dill";@MysteriousSpace
textures;textures_blend_modes;★☆☆☆;3.5;3.5;2020;2025;"Karlo Licudine";@accidentalrebel
textures;textures_tiled_drawing;★★★☆;3.0;4.2;2020;2025;"Vlad Adrian";@demizdor
textures;textures_polygon_drawing;★☆☆☆;3.7;3.7;2021;2025;"Chris Camacho";@chriscamacho
@ -130,6 +135,7 @@ textures;textures_textured_curve;★★★☆;4.5;4.5;2022;2025;"Jeffery Myers";
textures;textures_sprite_stacking;★★☆☆;6.0;6.0;2025;2025;"Robin";@RobinsAviary
textures;textures_cellular_automata;★★☆☆;5.6;5.6;2025;2025;"Jordi Santonja";@JordSant
textures;textures_framebuffer_rendering;★★☆☆;5.6;5.6;2026;2026;"Jack Boakes";@jackboakes
textures;textures_portal_window;★★★★;6.0;6.0;2025;2025;"PanicTitan";@PanicTitan
text;text_sprite_fonts;★☆☆☆;1.7;3.7;2017;2025;"Ramon Santamaria";@raysan5
text;text_font_spritefont;★☆☆☆;1.0;1.0;2014;2025;"Ramon Santamaria";@raysan5
text;text_font_filters;★★☆☆;1.3;4.2;2015;2025;"Ramon Santamaria";@raysan5
@ -176,6 +182,8 @@ models;models_directional_billboard;★★☆☆;6.0;6.0;2025;2025;"Robin";@Robi
models;models_animation_blend_custom;★★★★;5.5;6.0;2026;2026;"dmitrii-brand";@dmitrii-brand
models;models_animation_blending;★★★★;5.5;6.0;2024;2026;"Kirandeep";@Kirandeep-Singh-Khehra
models;models_animation_timing;★★★☆;6.0;6.0;2026;2026;"Ramon Santamaria";@raysan5
models;models_mesh_uv_painting;★★★★;6.0;6.0;2025;2025;"PanicTitan";@PanicTitan
models;models_procedural_decals;★★★★;6.0;6.0;2025;2025;"PanicTitan";@PanicTitan
shaders;shaders_ascii_rendering;★★☆☆;5.5;6.0;2025;2025;"Maicon Santana";@maiconpintoabreu
shaders;shaders_basic_lighting;★★★★;3.0;4.2;2019;2025;"Chris Camacho";@chriscamacho
shaders;shaders_model_shader;★★☆☆;1.3;3.7;2014;2025;"Ramon Santamaria";@raysan5
@ -211,6 +219,7 @@ shaders;shaders_depth_rendering;★★★☆;6.0;6.0;2025;2025;"Luís Almeida";@
shaders;shaders_game_of_life;★★★☆;6.0;6.0;2025;2025;"Jordi Santonja";@JordSant
shaders;shaders_rlgl_compute;★★★★;4.0;4.0;2021;2025;"Teddy Astie";@tsnake41
shaders;shaders_cel_shading;★★★☆;6.0;6.0;2026;2026;"Gleb A";@ggrizzly
shaders;shaders_lights_bloom;★★★☆;6.0;6.0;2025;2025;"PanicTitan";@PanicTitan
audio;audio_module_playing;★☆☆☆;1.5;3.5;2016;2025;"Ramon Santamaria";@raysan5
audio;audio_music_stream;★☆☆☆;1.3;4.2;2015;2025;"Ramon Santamaria";@raysan5
audio;audio_raw_stream;★★★☆;1.6;6.0;2015;2026;"Ramon Santamaria";@raysan5
@ -218,6 +227,7 @@ audio;audio_sound_loading;★☆☆☆;1.1;3.5;2014;2025;"Ramon Santamaria";@ray
audio;audio_mixed_processor;★★★★;4.2;4.2;2023;2025;"hkc";@hatkidchan
audio;audio_stream_effects;★★★★;4.2;5.0;2022;2025;"Ramon Santamaria";@raysan5
audio;audio_sound_multi;★★☆☆;5.0;5.0;2023;2025;"Jeffery Myers";@JeffM2501
audio;audio_sound_positioning;★★☆☆;5.5;5.5;2025;2025;"Le Juez Victor";@Bigfoot71
audio;audio_sound_positioning;★★☆☆;5.5;6.0;2025;2025;"Le Juez Victor";@Bigfoot71
audio;audio_spectrum_visualizer;★★★☆;6.0;6.0;2025;2025;"IANN";@meisei4
audio;audio_stream_callback;★★★☆;6.0;6.0;2026;2026;"Dan Hoang";@dan-hoang
audio;audio_amp_envelope;★☆☆☆;6.0;6.0;2026;2026;"Arbinda Rizki Muhammad";@arbipink

View File

@ -212,12 +212,12 @@ static void UpdateModelAnimationBones(Model *model, ModelAnimation *anim0, int f
if (frame1 < 0) frame1 = 0;
// Get bone count (use minimum of all to be safe)
int boneCount = model->skeleton.boneCount;
unsigned int boneCount = model->skeleton.boneCount;
if (anim0->boneCount < boneCount) boneCount = anim0->boneCount;
if (anim1->boneCount < boneCount) boneCount = anim1->boneCount;
// Blend each bone
for (int boneIndex = 0; boneIndex < boneCount; boneIndex++)
for (unsigned int boneIndex = 0; boneIndex < boneCount; boneIndex++)
{
// Determine blend factor for this bone
float boneBlendFactor = blend;

View File

@ -53,13 +53,19 @@ int main(void)
Model model = LoadModel("resources/models/gltf/robot.glb"); // Load character model
Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model world position
#if SUPPORT_GPU_SKINNING
// WARNING: SUPPORT_GPU_SKINNING is required to be enabled at raylib compile time (disabled by default)
// It will skip loading CPU required buffers to store animation updated data, so, both modes are exclusive
// Load skinning shader
// WARNING: It requires SUPPORT_GPU_SKINNING enabled on raylib (disabled by default)
// NOTE: It must be a valid shader, following raylib attribs/uniform conventions for GPU skinning
Shader skinningShader = LoadShader(TextFormat("resources/shaders/glsl%i/skinning.vs", GLSL_VERSION),
TextFormat("resources/shaders/glsl%i/skinning.fs", GLSL_VERSION));
// Assign skinning shader to all materials shaders
//for (int i = 0; i < model.materialCount; i++) model.materials[i].shader = skinningShader;
// Skinning shader could be required to be assigned to all materials shaders, just to make
// sure required uniforms are being updated for the mesh using that material (and shader)
for (int i = 0; i < model.materialCount; i++) model.materials[i].shader = skinningShader;
#endif
// Load model animations
int animCount = 0;
@ -108,7 +114,7 @@ int main(void)
if (IsKeyPressed(KEY_P)) animPause = !animPause;
if (!animPause)
if (!animPause && (animCount > 0)) // Animations could fail to load
{
// Start transition from anim0[] to anim1[]
if (IsKeyPressed(KEY_SPACE) && !animTransition)
@ -244,21 +250,30 @@ int main(void)
if (GuiDropdownBox((Rectangle){ GetScreenWidth() - 170.0f, 10, 160, 24 }, TextJoin(animNames, animCount, ";"),
&animIndex1, dropdownEditMode1)) dropdownEditMode1 = !dropdownEditMode1;
// Draw playing timeline with keyframes for anim0[]
GuiProgressBar((Rectangle){ 60, GetScreenHeight() - 60.0f, GetScreenWidth() - 180.0f, 20 }, "ANIM 0",
TextFormat("FRAME: %.2f / %i", animFrameProgress0, anims[animIndex0].keyframeCount),
&animFrameProgress0, 0.0f, (float)anims[animIndex0].keyframeCount);
for (int i = 0; i < anims[animIndex0].keyframeCount; i++)
DrawRectangle(60 + (int)(((float)(GetScreenWidth() - 180)/(float)anims[animIndex0].keyframeCount)*(float)i),
GetScreenHeight() - 60, 1, 20, BLUE);
GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
GuiSetStyle(DEFAULT, TEXT_SIZE, GuiGetFont().baseSize*2);
GuiLabel((Rectangle){ 0, GetScreenHeight() - 100.0f, (float)GetScreenWidth(), 40 }, "PRESS SPACE to START BLENDING");
GuiSetStyle(DEFAULT, TEXT_SIZE, GuiGetFont().baseSize);
GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
// Draw playing timeline with keyframes for anim1[]
GuiProgressBar((Rectangle){ 60, GetScreenHeight() - 30.0f, GetScreenWidth() - 180.0f, 20 }, "ANIM 1",
TextFormat("FRAME: %.2f / %i", animFrameProgress1, anims[animIndex1].keyframeCount),
&animFrameProgress1, 0.0f, (float)anims[animIndex1].keyframeCount);
for (int i = 0; i < anims[animIndex1].keyframeCount; i++)
DrawRectangle(60 + (int)(((float)(GetScreenWidth() - 180)/(float)anims[animIndex1].keyframeCount)*(float)i),
GetScreenHeight() - 30, 1, 20, BLUE);
if (animCount > 0)
{
// Draw playing timeline with keyframes for anim0[]
GuiProgressBar((Rectangle){ 60, GetScreenHeight() - 60.0f, GetScreenWidth() - 180.0f, 20 }, "ANIM 0",
TextFormat("FRAME: %.2f / %i", animFrameProgress0, anims[animIndex0].keyframeCount),
&animFrameProgress0, 0.0f, (float)anims[animIndex0].keyframeCount);
for (int i = 0; i < anims[animIndex0].keyframeCount; i++)
DrawRectangle(60 + (int)(((float)(GetScreenWidth() - 180)/(float)anims[animIndex0].keyframeCount)*(float)i),
GetScreenHeight() - 60, 1, 20, BLUE);
// Draw playing timeline with keyframes for anim1[]
GuiProgressBar((Rectangle){ 60, GetScreenHeight() - 30.0f, GetScreenWidth() - 180.0f, 20 }, "ANIM 1",
TextFormat("FRAME: %.2f / %i", animFrameProgress1, anims[animIndex1].keyframeCount),
&animFrameProgress1, 0.0f, (float)anims[animIndex1].keyframeCount);
for (int i = 0; i < anims[animIndex1].keyframeCount; i++)
DrawRectangle(60 + (int)(((float)(GetScreenWidth() - 180)/(float)anims[animIndex1].keyframeCount)*(float)i),
GetScreenHeight() - 30, 1, 20, BLUE);
}
//---------------------------------------------------------------------------------------------
EndDrawing();
@ -269,7 +284,9 @@ int main(void)
//--------------------------------------------------------------------------------------
UnloadModelAnimations(anims, animCount); // Unload model animation
UnloadModel(model); // Unload model and meshes/material
#if SUPPORT_GPU_SKINNING
UnloadShader(skinningShader); // Unload GPU skinning shader
#endif
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------

View File

@ -52,12 +52,19 @@ int main(void)
Model model = LoadModel("resources/models/gltf/greenman.glb"); // Load character model
Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position
#if SUPPORT_GPU_SKINNING
// WARNING: SUPPORT_GPU_SKINNING is required to be enabled at raylib compile time (disabled by default)
// It will skip loading CPU required buffers to store animation updated data, so, both modes are exclusive
// Load skinning shader
// WARNING: GPU skinning must be enabled in raylib with a compilation flag,
// if not enabled, CPU skinning will be used instead
// NOTE: It must be a valid shader, following raylib attribs/uniform conventions for GPU skinning
Shader skinningShader = LoadShader(TextFormat("resources/shaders/glsl%i/skinning.vs", GLSL_VERSION),
TextFormat("resources/shaders/glsl%i/skinning.fs", GLSL_VERSION));
model.materials[1].shader = skinningShader;
TextFormat("resources/shaders/glsl%i/skinning.fs", GLSL_VERSION));
// Skinning shader could be required to be assigned to all materials shaders, just to make
// sure required uniforms are being updated for the mesh using that material (and shader)
model.materials[1].shader = skinningShader; // Just assigning to materials[1] for this model
#endif
// Load gltf model animations
int animCount = 0;
@ -111,7 +118,9 @@ int main(void)
//--------------------------------------------------------------------------------------
UnloadModelAnimations(anims, animCount); // Unload model animation
UnloadModel(model); // Unload model and meshes/material
#if SUPPORT_GPU_SKINNING
UnloadShader(skinningShader); // Unload GPU skinning shader
#endif
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------

View File

@ -77,7 +77,7 @@ int main(void)
{
// Cast a ray from the screen center (where crosshair would be)
Vector2 screenCenter = { GetScreenWidth()/2.0f, GetScreenHeight()/2.0f };
Ray ray = GetMouseRay(screenCenter, camera);
Ray ray = GetScreenToWorldRay(screenCenter, camera);
// Check ray collision with all voxels
float closestDistance = 99999.0f;
@ -103,7 +103,7 @@ int main(void)
if (collision.hit && (collision.distance < closestDistance))
{
closestDistance = collision.distance;
closestVoxelPosition = (Vector3){ x, y, z };
closestVoxelPosition = (Vector3){ (float)x, (float)y, (float)z };
voxelFound = true;
}
}

View File

@ -64,7 +64,7 @@ int main(void)
int boneSocketIndex[BONE_SOCKETS] = { -1, -1, -1 };
// Search bones for sockets
for (int i = 0; i < characterModel.skeleton.boneCount; i++)
for (unsigned int i = 0; i < characterModel.skeleton.boneCount; i++)
{
if (TextIsEqual(characterModel.skeleton.bones[i].name, "socket_hat"))
{

View File

@ -249,7 +249,7 @@ int main(void)
DrawText("(c) Character model and texture from kenney.nl", screenWidth - 260, screenHeight - 20, 10, GRAY);
// UI elements
if (GuiButton((Rectangle){ 10, screenHeight - 1000.f, 100, 60 }, showModel ? "Hide Model" : "Show Model")) showModel = !showModel;
if (GuiButton((Rectangle){ 10, screenHeight - 100.0f, 100, 60 }, showModel ? "Hide Model" : "Show Model")) showModel = !showModel;
if (GuiButton((Rectangle){ 10 + 110, screenHeight - 100.0f, 100, 60 }, "Clear Decals"))
{
@ -267,6 +267,7 @@ int main(void)
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadModel(model);
UnloadModel(placementCube);
UnloadTexture(modelTexture);
// Unload decal models

View File

@ -106,4 +106,3 @@ int main(void)
}

View File

@ -21,6 +21,8 @@
#include "raylib.h"
#include <math.h> // Required for: fmaxf(), fminf()
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
@ -53,6 +55,7 @@ int main(void)
// Animation playing variables
unsigned int animIndex = 0; // Current animation playing
float animCurrentFrame = 0.0f; // Current animation frame (supporting interpolated frames)
float animSpeed = 1.0f; // How fast the animation plays
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
@ -64,10 +67,23 @@ int main(void)
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_ORBITAL);
// Play animation when spacebar is held down
animCurrentFrame += 1.0f;
UpdateModelAnimation(model, anims[0], animCurrentFrame);
if (animCurrentFrame >= anims[0].keyframeCount) animCurrentFrame = 0;
if (IsKeyPressed(KEY_RIGHT))
{
animIndex = (animIndex == animCount - 1)? 0 : animIndex + 1;
animCurrentFrame = 0.0f;
}
if (IsKeyPressed(KEY_LEFT))
{
animIndex = (animIndex == 0)? animCount - 1 : animIndex - 1;
animCurrentFrame = 0.0f;
}
if (IsKeyPressed(KEY_UP)) animSpeed = fminf(5.0f, animSpeed + 0.1f);
if (IsKeyPressed(KEY_DOWN)) animSpeed = fmaxf(0.0f, animSpeed - 0.1f);
animCurrentFrame += animSpeed;
UpdateModelAnimation(model, anims[animIndex], animCurrentFrame);
if (animCurrentFrame >= anims[animIndex].keyframeCount) animCurrentFrame = 0;
//----------------------------------------------------------------------------------
// Draw
@ -85,6 +101,9 @@ int main(void)
EndMode3D();
DrawText(TextFormat("Current animation: %s", anims[animIndex].name), 10, 10, 20, MAROON);
DrawText(TextFormat("Animation speed: %.2f", animSpeed), 10, 40, 20, MAROON);
DrawText("Use left and right arrow keys to change current animation", 10, screenHeight - 34, 10, BLACK);
DrawText("Use up and down arrow keys to change animation speed", 10, screenHeight - 20, 10, BLACK);
DrawText("(c) Guy IQM 3D model by @culacant", screenWidth - 200, screenHeight - 20, 10, GRAY);
EndDrawing();

View File

@ -119,7 +119,7 @@ static void DrawModelSkeleton(ModelSkeleton skeleton, ModelAnimPose pose, float
{
// Loop to (boneCount - 1) because the last one is a special "no bone" bone,
// needed to workaround buggy models without a -1, a cube is always drawn at the origin
for (int i = 0; i < skeleton.boneCount - 1; i++)
for (unsigned int i = 0; i < skeleton.boneCount - 1; i++)
{
// Display the frame-pose skeleton
DrawCube(pose[i].translation, scale*0.05f, scale*0.05f, scale*0.05f, color);

View File

@ -185,6 +185,9 @@ int main(void)
// Unload models data (GPU VRAM)
for (int i = 0; i < MAX_VOX_FILES; i++) UnloadModel(models[i]);
// Unload shader data
UnloadShader(shader);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------

View File

@ -0,0 +1,323 @@
/*******************************************************************************************
*
* raylib [models] example - mesh uv painting
*
* Example demonstrates painting directly onto a mesh's texture: a ray is cast from the
* mouse into the scene, the hit triangle is found, and the hit point is converted into
* UV space using barycentric interpolation so a brush stroke can be drawn on the texture
*
* Example complexity rating: [★★★★] 4/4
*
* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by PanicTitan (@PanicTitan) 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 PanicTitan (@PanicTitan)
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
#define RAYGUI_IMPLEMENTATION
#include "raygui.h"
#include <math.h> // Required for: fabsf(), floorf()
#include <stddef.h> // Required for: NULL
//--------------------------------------------------------------------------------------
// Global Definitions
//--------------------------------------------------------------------------------------
#define CANVAS_SIZE 512
#define PALETTE_COUNT 8
//--------------------------------------------------------------------------------------
// Types and Structures Definition
//--------------------------------------------------------------------------------------
typedef enum { TOOL_PAINT = 0, TOOL_PICKER } ToolMode;
typedef enum { SHAPE_SPHERE = 0, SHAPE_CUBE, SHAPE_CYLINDER, SHAPE_TORUS } ShapeType;
//------------------------------------------------------------------------------------
// Module Functions Declaration
//------------------------------------------------------------------------------------
static void ChangeShape(Model *model, BoundingBox *bbox, ShapeType *currentShape, ShapeType newShape, Texture2D canvasTexture);
static bool GetMeshHitUV(Ray ray, Model model, BoundingBox bbox, Vector2 *outUV);
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - mesh uv painting");
Camera3D camera = { 0 };
camera.position = (Vector3){ 0.0f, 3.5f, 6.5f };
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;
// CPU-side canvas plus the GPU texture it gets pushed to after every stroke
Image canvasImage = GenImageColor(CANVAS_SIZE, CANVAS_SIZE, RAYWHITE);
Texture2D canvasTexture = LoadTextureFromImage(canvasImage);
SetTextureFilter(canvasTexture, TEXTURE_FILTER_BILINEAR);
Model model = { 0 };
BoundingBox modelBBox = { 0 };
ShapeType currentShape = SHAPE_SPHERE;
ChangeShape(&model, &modelBBox, &currentShape, SHAPE_SPHERE, canvasTexture);
ToolMode currentTool = TOOL_PAINT;
Color activeColor = RED;
int brushRadius = 12;
Vector2 lastHitUV = { 0 };
bool hasLastHit = false;
Color palette[PALETTE_COUNT] = { RED, ORANGE, GOLD, LIME, SKYBLUE, PURPLE, DARKGRAY, WHITE };
Rectangle uiPanelRec = { 10.0f, 10.0f, 230.0f, 490.0f };
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
Vector2 mousePos = GetMousePosition();
bool isMouseOverUI = CheckCollisionPointRec(mousePos, uiPanelRec);
if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT)) UpdateCamera(&camera, CAMERA_THIRD_PERSON);
if (!isMouseOverUI && IsMouseButtonDown(MOUSE_BUTTON_LEFT))
{
Ray ray = GetScreenToWorldRay(mousePos, camera);
Vector2 hitUV = { 0 };
if (GetMeshHitUV(ray, model, modelBBox, &hitUV))
{
int px = (int)(hitUV.x * CANVAS_SIZE);
int py = (int)(hitUV.y * CANVAS_SIZE);
if (currentTool == TOOL_PAINT)
{
// Stroke from the last hit to this one, guarding against jumps across a UV seam
if (hasLastHit && (fabsf(hitUV.x - lastHitUV.x) < 0.25f) && (fabsf(hitUV.y - lastHitUV.y) < 0.25f))
{
int lastPx = (int)(lastHitUV.x * CANVAS_SIZE);
int lastPy = (int)(lastHitUV.y * CANVAS_SIZE);
float dist = Vector2Distance((Vector2){ (float)lastPx, (float)lastPy }, (Vector2){ (float)px, (float)py });
int steps = (int)(dist / 2.0f) + 1;
for (int i = 0; i <= steps; i++)
{
float t = (float)i / (float)steps;
ImageDrawCircle(&canvasImage, (int)Lerp((float)lastPx, (float)px, t),
(int)Lerp((float)lastPy, (float)py, t), brushRadius, activeColor);
}
}
else ImageDrawCircle(&canvasImage, px, py, brushRadius, activeColor);
UpdateTexture(canvasTexture, canvasImage.data);
lastHitUV = hitUV;
hasLastHit = true;
}
else
{
activeColor = GetImageColor(canvasImage, px, py);
currentTool = TOOL_PAINT;
hasLastHit = false;
}
}
else hasLastHit = false;
}
else hasLastHit = false;
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground((Color){ 30, 32, 40, 255 });
BeginMode3D(camera);
DrawModel(model, Vector3Zero(), 1.0f, WHITE);
DrawGrid(10, 1.0f);
EndMode3D();
// Side panel
DrawRectangleRec(uiPanelRec, Fade(BLACK, 0.8f));
DrawRectangleLinesEx(uiPanelRec, 2.0f, DARKGRAY);
DrawText("MESH UV PAINTER", 25, 22, 20, GOLD);
// Tool selection toggles
bool paintActive = (currentTool == TOOL_PAINT);
bool pickerActive = (currentTool == TOOL_PICKER);
if (GuiToggle((Rectangle){ 25, 55, 95, 32 }, "PAINT", &paintActive)) currentTool = TOOL_PAINT;
if (GuiToggle((Rectangle){ 125, 55, 95, 32 }, "PICKER", &pickerActive)) currentTool = TOOL_PICKER;
// Shape selection toggles
DrawText("Mesh Shape:", 25, 100, 10, LIGHTGRAY);
bool sphereActive = (currentShape == SHAPE_SPHERE);
bool cubeActive = (currentShape == SHAPE_CUBE);
bool cylinderActive = (currentShape == SHAPE_CYLINDER);
bool torusActive = (currentShape == SHAPE_TORUS);
if (GuiToggle((Rectangle){ 25, 120, 95, 28 }, "SPHERE", &sphereActive))
ChangeShape(&model, &modelBBox, &currentShape, SHAPE_SPHERE, canvasTexture);
if (GuiToggle((Rectangle){ 125, 120, 95, 28 }, "CUBE", &cubeActive))
ChangeShape(&model, &modelBBox, &currentShape, SHAPE_CUBE, canvasTexture);
if (GuiToggle((Rectangle){ 25, 153, 95, 28 }, "CYLINDER", &cylinderActive))
ChangeShape(&model, &modelBBox, &currentShape, SHAPE_CYLINDER, canvasTexture);
if (GuiToggle((Rectangle){ 125, 153, 95, 28 }, "TORUS", &torusActive))
ChangeShape(&model, &modelBBox, &currentShape, SHAPE_TORUS, canvasTexture);
// Color display
DrawText("Active Color:", 25, 195, 10, LIGHTGRAY);
DrawRectangle(125, 193, 95, 20, activeColor);
DrawRectangleLines(125, 193, 95, 20, WHITE);
// Color swatches
DrawText("Palette Swatches:", 25, 225, 10, LIGHTGRAY);
for (int i = 0; i < PALETTE_COUNT; i++)
{
Rectangle swatchRec = { 25.0f + (i%4)*48, 245.0f + (i/4)*45, 40.0f, 38.0f };
DrawRectangleRec(swatchRec, palette[i]);
DrawRectangleLinesEx(swatchRec, 1.0f, WHITE);
if (CheckCollisionPointRec(mousePos, swatchRec) && IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) activeColor = palette[i];
}
// Brush size buttons
DrawText(TextFormat("Brush Size: %dpx", brushRadius), 25, 345, 10, LIGHTGRAY);
if (GuiButton((Rectangle){ 25, 365, 95, 30 }, "SIZE -") && (brushRadius > 2)) brushRadius -= 2;
if (GuiButton((Rectangle){ 125, 365, 95, 30 }, "SIZE +") && (brushRadius < 64)) brushRadius += 2;
// Canvas action buttons
if (GuiButton((Rectangle){ 25, 410, 95, 30 }, "CLEAR"))
{
ImageClearBackground(&canvasImage, RAYWHITE);
UpdateTexture(canvasTexture, canvasImage.data);
}
if (GuiButton((Rectangle){ 125, 410, 95, 30 }, "FILL"))
{
ImageClearBackground(&canvasImage, activeColor);
UpdateTexture(canvasTexture, canvasImage.data);
}
DrawText("Left click: paint / pick color | Right drag: orbit camera", 260, screenHeight - 25, 10, RAYWHITE);
DrawFPS(screenWidth - 90, 15);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadModel(model);
UnloadImage(canvasImage);
UnloadTexture(canvasTexture);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
// Unloads the current model and builds a new primitive shape in its place, sharing the
// same canvas texture, and recomputes the transformed bounding box used for ray testing
static void ChangeShape(Model *model, BoundingBox *bbox, ShapeType *currentShape, ShapeType newShape, Texture2D canvasTexture)
{
UnloadModel(*model);
Mesh mesh = { 0 };
switch (newShape)
{
case SHAPE_SPHERE: mesh = GenMeshSphere(1.5f, 32, 32); break;
case SHAPE_CUBE: mesh = GenMeshCube(2.2f, 2.2f, 2.2f); break;
case SHAPE_CYLINDER: mesh = GenMeshCylinder(1.2f, 2.5f, 24); break;
case SHAPE_TORUS: mesh = GenMeshTorus(0.6f, 1.6f, 24, 36); break;
default: mesh = GenMeshSphere(1.5f, 32, 32); break;
}
*model = LoadModelFromMesh(mesh);
// GenMeshCylinder builds upward from y = 0; shift it down to center on the origin
if (newShape == SHAPE_CYLINDER) model->transform = MatrixTranslate(0.0f, -1.25f, 0.0f);
model->materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = canvasTexture;
BoundingBox box = GetMeshBoundingBox(model->meshes[0]);
box.min = Vector3Transform(box.min, model->transform);
box.max = Vector3Transform(box.max, model->transform);
*bbox = box;
*currentShape = newShape;
}
// Raycasts against the model's mesh triangles and returns the UV coordinate of the
// closest hit, interpolated from the hit triangle's vertices with barycentric weights
static bool GetMeshHitUV(Ray ray, Model model, BoundingBox bbox, Vector2 *outUV)
{
if (!GetRayCollisionBox(ray, bbox).hit) return false; // Fast reject
Mesh mesh = model.meshes[0];
float closestDistance = 1e9f;
bool found = false;
Vector2 hitUV = { 0 };
for (int tri = 0; tri < mesh.triangleCount; tri++)
{
int i0, i1, i2;
if (mesh.indices != NULL)
{
i0 = mesh.indices[3*tri + 0];
i1 = mesh.indices[3*tri + 1];
i2 = mesh.indices[3*tri + 2];
}
else { i0 = 3*tri; i1 = 3*tri + 1; i2 = 3*tri + 2; }
Vector3 a = Vector3Transform((Vector3){ mesh.vertices[3*i0], mesh.vertices[3*i0 + 1], mesh.vertices[3*i0 + 2] }, model.transform);
Vector3 b = Vector3Transform((Vector3){ mesh.vertices[3*i1], mesh.vertices[3*i1 + 1], mesh.vertices[3*i1 + 2] }, model.transform);
Vector3 c = Vector3Transform((Vector3){ mesh.vertices[3*i2], mesh.vertices[3*i2 + 1], mesh.vertices[3*i2 + 2] }, model.transform);
RayCollision hit = GetRayCollisionTriangle(ray, a, b, c);
if (hit.hit && (hit.distance < closestDistance))
{
closestDistance = hit.distance;
found = true;
Vector2 uvA = { mesh.texcoords[2*i0], mesh.texcoords[2*i0 + 1] };
Vector2 uvB = { mesh.texcoords[2*i1], mesh.texcoords[2*i1 + 1] };
Vector2 uvC = { mesh.texcoords[2*i2], mesh.texcoords[2*i2 + 1] };
Vector3 w = Vector3Barycenter(hit.point, a, b, c);
hitUV.x = w.x*uvA.x + w.y*uvB.x + w.z*uvC.x;
hitUV.y = w.x*uvA.y + w.y*uvB.y + w.z*uvC.y;
// Wrap into [0, 1] in case of minor floating point drift at UV seams
hitUV.x -= floorf(hitUV.x);
hitUV.y -= floorf(hitUV.y);
}
}
if (found && (outUV != NULL)) *outUV = hitUV;
return found;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -0,0 +1,504 @@
/*******************************************************************************************
*
* raylib [models] example - procedural decals
*
* Example demonstrates projecting decals onto a 3D mesh surface by transforming the
* mesh's own triangles into the decal's local space and clipping them against a box,
* using only procedurally generated geometry and textures (no external resource files)
*
* NOTE: This is the same clip-space decal projection idea used by models_decals.c
* (in turn based on three.js' DecalGeometry), applied here to a generated mesh and
* generated textures instead of a loaded model, so the example is fully self-contained
*
* Example complexity rating: [★★★★] 4/4
*
* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by PanicTitan (@PanicTitan) 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 PanicTitan (@PanicTitan)
*
********************************************************************************************/
#include "raylib.h"
#define RAYGUI_IMPLEMENTATION
#include "raygui.h"
#include "raymath.h"
#include <stddef.h> // Required for: NULL
#include <string.h> // Required for: memcpy()
#include <math.h> // Required for: fabsf(), fminf()
//--------------------------------------------------------------------------------------
// Global Definitions
//--------------------------------------------------------------------------------------
#define MAX_DECALS 256
//--------------------------------------------------------------------------------------
// Types and Structures Definition
//--------------------------------------------------------------------------------------
// Growable triangle-soup buffer used while building a clipped decal mesh
typedef struct MeshBuilder {
int vertexCount;
int vertexCapacity;
Vector3 *vertices;
Vector2 *uvs;
} MeshBuilder;
//------------------------------------------------------------------------------------
// Module Functions Declaration
//------------------------------------------------------------------------------------
static void AddTriangleToMeshBuilder(MeshBuilder *mb, Vector3 v0, Vector3 v1, Vector3 v2);
static void FreeMeshBuilder(MeshBuilder *mb);
static Mesh BuildMesh(MeshBuilder *mb);
static Vector3 ClipSegment(Vector3 v0, Vector3 v1, Vector3 p, float s);
static Mesh GenMeshDecal(Model model, Matrix projection, float decalSize, float decalOffset);
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
SetConfigFlags(FLAG_MSAA_4X_HINT);
InitWindow(screenWidth, screenHeight, "raylib [models] example - procedural decals");
Camera3D camera = { 0 };
camera.position = (Vector3){ 0.0f, 2.5f, 5.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;
// Target model: a procedurally generated knot with a checkerboard skin
Model model = LoadModelFromMesh(GenMeshTorus(0.8f, 1.8f, 32, 64));
Image checkerImage = GenImageChecked(512, 512, 32, 32, LIGHTGRAY, GRAY);
Texture2D modelTexture = LoadTextureFromImage(checkerImage);
UnloadImage(checkerImage);
SetTextureFilter(modelTexture, TEXTURE_FILTER_BILINEAR);
model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = modelTexture;
BoundingBox modelBBox = GetMeshBoundingBox(model.meshes[0]);
camera.target = Vector3Lerp(modelBBox.min, modelBBox.max, 0.5f);
float modelSize = fminf(fminf(fabsf(modelBBox.max.x - modelBBox.min.x),
fabsf(modelBBox.max.y - modelBBox.min.y)), fabsf(modelBBox.max.z - modelBBox.min.z));
float decalSize = modelSize*0.35f;
float decalOffset = 0.01f;
// Translucent cube previewing where the next decal will land
Model placementCube = LoadModelFromMesh(GenMeshCube(decalSize, decalSize, decalSize));
placementCube.materials[0].maps[0].color = LIME;
// Decal texture: a procedurally drawn target/bullseye, no image file needed
Image decalImage = GenImageColor(128, 128, BLANK);
ImageDrawCircle(&decalImage, 64, 64, 60, RED);
ImageDrawCircle(&decalImage, 64, 64, 45, WHITE);
ImageDrawCircle(&decalImage, 64, 64, 30, RED);
ImageDrawCircle(&decalImage, 64, 64, 15, YELLOW);
Texture2D decalTexture = LoadTextureFromImage(decalImage);
UnloadImage(decalImage);
SetTextureFilter(decalTexture, TEXTURE_FILTER_BILINEAR);
Material decalMaterial = LoadMaterialDefault();
decalMaterial.maps[MATERIAL_MAP_DIFFUSE].texture = decalTexture;
decalMaterial.maps[MATERIAL_MAP_DIFFUSE].color = RAYWHITE;
bool showModel = true;
Model decals[MAX_DECALS] = { 0 };
int decalCount = 0;
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT)) UpdateCamera(&camera, CAMERA_THIRD_PERSON);
// Cast a ray from the mouse and keep the closest point it hits on the model
Ray ray = GetScreenToWorldRay(GetMousePosition(), camera);
RayCollision collision = { 0 };
if (GetRayCollisionBox(ray, modelBBox).hit && (decalCount < MAX_DECALS))
{
for (int m = 0; m < model.meshCount; m++)
{
RayCollision meshHit = GetRayCollisionMesh(ray, model.meshes[m], model.transform);
if (meshHit.hit && (!collision.hit || (meshHit.distance < collision.distance))) collision = meshHit;
}
}
// Project a new decal at the hit point, facing along the surface normal
if (collision.hit && IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && (decalCount < MAX_DECALS))
{
Vector3 lookTarget = Vector3Add(collision.point, collision.normal);
Matrix splat = MatrixLookAt(collision.point, lookTarget, (Vector3){ 0.0f, 1.0f, 0.0f });
splat = MatrixMultiply(splat, MatrixRotateZ(DEG2RAD*(float)GetRandomValue(-180, 180)));
Mesh decalMesh = GenMeshDecal(model, splat, decalSize, decalOffset);
if (decalMesh.vertexCount > 0)
{
decals[decalCount] = LoadModelFromMesh(decalMesh);
decals[decalCount].materials[0].maps[0] = decalMaterial.maps[0];
decalCount++;
}
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
if (showModel) DrawModel(model, Vector3Zero(), 1.0f, WHITE);
for (int i = 0; i < decalCount; i++) DrawModel(decals[i], Vector3Zero(), 1.0f, WHITE);
// Preview cube at the surface point currently under the mouse
if (collision.hit)
{
Vector3 lookTarget = Vector3Add(collision.point, collision.normal);
Matrix splat = MatrixLookAt(collision.point, lookTarget, (Vector3){ 0.0f, 1.0f, 0.0f });
placementCube.transform = MatrixInvert(splat);
DrawModel(placementCube, Vector3Zero(), 1.0f, Fade(WHITE, 0.5f));
}
DrawGrid(10, 1.0f);
EndMode3D();
// Vertex/triangle counts: base model vs total once decal geometry is added
int baseVertices = 0, baseTriangles = 0;
for (int i = 0; i < model.meshCount; i++)
{
baseVertices += model.meshes[i].vertexCount;
baseTriangles += model.meshes[i].triangleCount;
}
int totalVertices = baseVertices, totalTriangles = baseTriangles;
for (int i = 0; i < decalCount; i++)
{
totalVertices += decals[i].meshes[0].vertexCount;
totalTriangles += decals[i].meshes[0].triangleCount;
}
int statX = screenWidth - 280;
DrawText("Vertices", statX + 90, 10, 10, LIME);
DrawText("Triangles", statX + 180, 10, 10, LIME);
DrawText("Base Model", statX, 25, 10, LIME);
DrawText(TextFormat("%d", baseVertices), statX + 90, 25, 10, LIME);
DrawText(TextFormat("%d", baseTriangles), statX + 180, 25, 10, LIME);
DrawText("TOTAL", statX, 40, 10, LIME);
DrawText(TextFormat("%d", totalVertices), statX + 90, 40, 10, LIME);
DrawText(TextFormat("%d", totalTriangles), statX + 180, 40, 10, LIME);
if (GuiButton((Rectangle){ 10, screenHeight - 80.0f, 100, 40 }, showModel ? "Hide Model" : "Show Model"))
showModel = !showModel;
if (GuiButton((Rectangle){ 120, screenHeight - 80.0f, 100, 40 }, "Clear Decals"))
{
for (int i = 0; i < decalCount; i++) UnloadModel(decals[i]);
decalCount = 0;
}
DrawText("Left click: place decal | Right drag: orbit camera", 10, screenHeight - 25, 10, DARKGRAY);
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
for (int i = 0; i < decalCount; i++) UnloadModel(decals[i]);
UnloadModel(placementCube);
UnloadTexture(decalTexture);
UnloadTexture(modelTexture);
UnloadModel(model);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
// Appends a triangle to a growable mesh builder buffer, growing it in fixed-size chunks
static void AddTriangleToMeshBuilder(MeshBuilder *mb, Vector3 v0, Vector3 v1, Vector3 v2)
{
if (mb->vertexCapacity <= (mb->vertexCount + 3))
{
int newVertexCapacity = (1 + (mb->vertexCapacity/256))*256;
Vector3 *newVertices = (Vector3 *)MemAlloc(newVertexCapacity*sizeof(Vector3));
if (mb->vertexCapacity > 0)
{
memcpy(newVertices, mb->vertices, mb->vertexCount*sizeof(Vector3));
MemFree(mb->vertices);
}
mb->vertices = newVertices;
mb->vertexCapacity = newVertexCapacity;
}
int index = mb->vertexCount;
mb->vertexCount += 3;
mb->vertices[index + 0] = v0;
mb->vertices[index + 1] = v1;
mb->vertices[index + 2] = v2;
}
// Frees a mesh builder's backing buffers
static void FreeMeshBuilder(MeshBuilder *mb)
{
if (mb->vertices != NULL) MemFree(mb->vertices);
if (mb->uvs != NULL) MemFree(mb->uvs);
*mb = (MeshBuilder){ 0 };
}
// Converts a mesh builder's triangle soup into a standard uploaded raylib Mesh
static Mesh BuildMesh(MeshBuilder *mb)
{
Mesh outMesh = { 0 };
outMesh.vertexCount = mb->vertexCount;
outMesh.triangleCount = mb->vertexCount/3;
outMesh.vertices = (float *)MemAlloc(outMesh.vertexCount*3*sizeof(float));
if (mb->uvs != NULL) outMesh.texcoords = (float *)MemAlloc(outMesh.vertexCount*2*sizeof(float));
for (int i = 0; i < mb->vertexCount; i++)
{
outMesh.vertices[3*i + 0] = mb->vertices[i].x;
outMesh.vertices[3*i + 1] = mb->vertices[i].y;
outMesh.vertices[3*i + 2] = mb->vertices[i].z;
if (mb->uvs != NULL)
{
outMesh.texcoords[2*i + 0] = mb->uvs[i].x;
outMesh.texcoords[2*i + 1] = mb->uvs[i].y;
}
}
UploadMesh(&outMesh, false);
return outMesh;
}
// Clips the segment [v0, v1] against the plane p.x = s, returning the intersection point
static Vector3 ClipSegment(Vector3 v0, Vector3 v1, Vector3 p, float s)
{
float d0 = Vector3DotProduct(v0, p) - s;
float d1 = Vector3DotProduct(v1, p) - s;
float t = d0/(d0 - d1);
return Vector3Lerp(v0, v1, t);
}
// Builds a decal mesh: the model's triangles are transformed into the decal's local space
// (so the decal sits at the origin, facing +Z) and clipped against a decalSize-sided box,
// following the same clip-space projection idea used by engines' decal systems (and by
// three.js' DecalGeometry, which the technique is commonly traced back to). What's left
// after clipping becomes the decal's own small mesh, UV-mapped from its local coordinates
static Mesh GenMeshDecal(Model model, Matrix projection, float decalSize, float decalOffset)
{
Matrix invProj = MatrixInvert(projection);
MeshBuilder meshBuilders[2] = { 0 };
int mbIndex = 0;
// Gather triangles that land anywhere near the decal box; this is a loose, cheap
// pre-filter meant to skip most of the model, the precise clip happens below
for (int meshIndex = 0; meshIndex < model.meshCount; meshIndex++)
{
Mesh mesh = model.meshes[meshIndex];
for (int tri = 0; tri < mesh.triangleCount; tri++)
{
Vector3 vertices[3] = { 0 };
if (mesh.indices == NULL)
{
for (int v = 0; v < 3; v++)
{
vertices[v] = (Vector3){
mesh.vertices[3*3*tri + 3*v + 0],
mesh.vertices[3*3*tri + 3*v + 1],
mesh.vertices[3*3*tri + 3*v + 2]
};
}
}
else
{
for (int v = 0; v < 3; v++)
{
int idx = mesh.indices[3*tri + v];
vertices[v] = (Vector3){
mesh.vertices[3*idx + 0],
mesh.vertices[3*idx + 1],
mesh.vertices[3*idx + 2]
};
}
}
int insideCount = 0;
for (int i = 0; i < 3; i++)
{
Vector3 v = Vector3Transform(vertices[i], projection);
if ((fabsf(v.x) < decalSize) || (fabsf(v.y) <= decalSize) || (fabsf(v.z) <= decalSize)) insideCount++;
vertices[i] = v;
}
if (insideCount > 0) AddTriangleToMeshBuilder(&meshBuilders[mbIndex], vertices[0], vertices[1], vertices[2]);
}
}
// Clip the surviving triangles against each of the decal box's 6 faces in turn
Vector3 planes[6] = {
{ 1, 0, 0 }, { -1, 0, 0 },
{ 0, 1, 0 }, { 0, -1, 0 },
{ 0, 0, 1 }, { 0, 0, -1 }
};
for (int face = 0; face < 6; face++)
{
mbIndex = 1 - mbIndex;
MeshBuilder *inMesh = &meshBuilders[1 - mbIndex];
MeshBuilder *outMesh = &meshBuilders[mbIndex];
outMesh->vertexCount = 0;
float s = 0.5f*decalSize;
for (int i = 0; i < inMesh->vertexCount; i += 3)
{
Vector3 nV1, nV2, nV3, nV4;
float d1 = Vector3DotProduct(inMesh->vertices[i + 0], planes[face]) - s;
float d2 = Vector3DotProduct(inMesh->vertices[i + 1], planes[face]) - s;
float d3 = Vector3DotProduct(inMesh->vertices[i + 2], planes[face]) - s;
int v1Out = (d1 > 0);
int v2Out = (d2 > 0);
int v3Out = (d3 > 0);
int total = v1Out + v2Out + v3Out;
switch (total)
{
case 0:
// Whole triangle is inside this face, keep it as-is
AddTriangleToMeshBuilder(outMesh, inMesh->vertices[i], inMesh->vertices[i + 1], inMesh->vertices[i + 2]);
break;
case 1:
// One corner is outside; clip it off, turning the triangle into a quad
if (v1Out)
{
nV1 = inMesh->vertices[i + 1];
nV2 = inMesh->vertices[i + 2];
nV3 = ClipSegment(inMesh->vertices[i], nV1, planes[face], s);
nV4 = ClipSegment(inMesh->vertices[i], nV2, planes[face], s);
}
if (v2Out)
{
nV1 = inMesh->vertices[i];
nV2 = inMesh->vertices[i + 2];
nV3 = ClipSegment(inMesh->vertices[i + 1], nV1, planes[face], s);
nV4 = ClipSegment(inMesh->vertices[i + 1], nV2, planes[face], s);
AddTriangleToMeshBuilder(outMesh, nV3, nV2, nV1);
AddTriangleToMeshBuilder(outMesh, nV2, nV3, nV4);
break;
}
if (v3Out)
{
nV1 = inMesh->vertices[i];
nV2 = inMesh->vertices[i + 1];
nV3 = ClipSegment(inMesh->vertices[i + 2], nV1, planes[face], s);
nV4 = ClipSegment(inMesh->vertices[i + 2], nV2, planes[face], s);
}
AddTriangleToMeshBuilder(outMesh, nV1, nV2, nV3);
AddTriangleToMeshBuilder(outMesh, nV4, nV3, nV2);
break;
case 2:
// Two corners are outside; only the small corner near the surviving vertex remains
if (!v1Out)
{
nV1 = inMesh->vertices[i];
nV2 = ClipSegment(nV1, inMesh->vertices[i + 1], planes[face], s);
nV3 = ClipSegment(nV1, inMesh->vertices[i + 2], planes[face], s);
AddTriangleToMeshBuilder(outMesh, nV1, nV2, nV3);
}
if (!v2Out)
{
nV1 = inMesh->vertices[i + 1];
nV2 = ClipSegment(nV1, inMesh->vertices[i + 2], planes[face], s);
nV3 = ClipSegment(nV1, inMesh->vertices[i], planes[face], s);
AddTriangleToMeshBuilder(outMesh, nV1, nV2, nV3);
}
if (!v3Out)
{
nV1 = inMesh->vertices[i + 2];
nV2 = ClipSegment(nV1, inMesh->vertices[i], planes[face], s);
nV3 = ClipSegment(nV1, inMesh->vertices[i + 1], planes[face], s);
AddTriangleToMeshBuilder(outMesh, nV1, nV2, nV3);
}
break;
default:
// All 3 corners are outside this face, the triangle is fully clipped away
break;
}
}
}
MeshBuilder *finalMesh = &meshBuilders[mbIndex];
Mesh decalMesh = { 0 };
if (finalMesh->vertexCount > 0)
{
finalMesh->uvs = (Vector2 *)MemAlloc(sizeof(Vector2)*finalMesh->vertexCount);
for (int i = 0; i < finalMesh->vertexCount; i++)
{
// Clipped coordinates run roughly (-decalSize/2 .. decalSize/2); remap to (0..1)
finalMesh->uvs[i].x = (finalMesh->vertices[i].x/decalSize + 0.5f);
finalMesh->uvs[i].y = (finalMesh->vertices[i].y/decalSize + 0.5f);
// Nudge slightly along the normal so the decal doesn't z-fight with the surface
finalMesh->vertices[i].z -= decalOffset;
finalMesh->vertices[i] = Vector3Transform(finalMesh->vertices[i], invProj);
}
decalMesh = BuildMesh(finalMesh);
}
FreeMeshBuilder(&meshBuilders[0]);
FreeMeshBuilder(&meshBuilders[1]);
return decalMesh;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View File

@ -180,8 +180,8 @@ int main(void)
//--------------------------------------------------------------------------------------
UnloadShader(skybox.materials[0].shader);
UnloadTexture(skybox.materials[0].maps[MATERIAL_MAP_CUBEMAP].texture);
UnloadModel(skybox); // Unload skybox model
UnloadShader(shdrCubemap);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,153 @@
/*******************************************************************************************
*
* raylib [others] example - scissor shapes
*
* Example complexity rating: [★★★☆] 3/4
*
* Example originally created with raylib 6.0
*
* Example contributed by David Buzatto (@davidbuzatto) 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) 2026 David Buzatto (@davidbuzatto)
*
********************************************************************************************/
#include "raylib.h"
#include "rlgl.h"
#include <math.h> // Required for: sinf()
// BeginScissorMode() only clips to an axis-aligned rectangle, since it maps
// directly to glScissor. Clipping to an arbitrary shape (the same idea as
// Graphics2D.setClip(Shape) in Java2D) needs the stencil buffer instead:
// the clip shape is rasterized into the stencil buffer first, then further
// draws are only let through where the stencil was written.
//
// rlgl has no stencil wrapper (see raysan5/raylib discussion #2964), so this
// example calls the handful of OpenGL 1.0 stencil functions directly - they
// don't need glad/extension loading, same as glScissor doesn't.
#if defined(__APPLE__)
#include <OpenGL/gl.h>
#else
#if !defined(APIENTRY)
#if defined(_WIN32)
#define APIENTRY __stdcall
#else
#define APIENTRY
#endif
#endif
#if !defined(WINGDIAPI) && defined(_WIN32)
#define WINGDIAPI __declspec(dllimport)
#endif
#include <GL/gl.h>
#endif
// mask is a callback instead of a fixed shape, so the clip region can be any
// combination of Draw* calls (circle, polygon, text, several shapes together)
typedef void (*ScissorMaskDrawFunc)(void *userData);
static void BeginScissorModeShape(ScissorMaskDrawFunc mask, void *userData)
{
rlDrawRenderBatchActive(); // Flush before touching stencil state
glClear(GL_STENCIL_BUFFER_BIT);
glEnable(GL_STENCIL_TEST);
glStencilMask(0xFF);
// Pass 1: rasterize the mask into the stencil buffer only, no color write
rlColorMask(false, false, false, false);
glStencilFunc(GL_ALWAYS, 1, 0xFF);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
mask(userData);
rlDrawRenderBatchActive(); // Flush the mask draw
// Pass 2: subsequent draws only survive where the stencil was written
rlColorMask(true, true, true, true);
glStencilFunc(GL_EQUAL, 1, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
}
static void EndScissorModeShape(void)
{
rlDrawRenderBatchActive();
glDisable(GL_STENCIL_TEST);
}
// Two example mask shapes, drawn in WHITE (the color is irrelevant here,
// only the stencil write from pass 1 matters)
typedef struct { Vector2 center; float radius; } CircleMask;
static void DrawCircleMask(void *userData)
{
CircleMask *m = (CircleMask *)userData;
DrawCircleV(m->center, m->radius, WHITE);
}
typedef struct { Vector2 center; float radius; int sides; } PolyMask;
static void DrawPolyMask(void *userData)
{
PolyMask *m = (PolyMask *)userData;
DrawPoly(m->center, m->sides, m->radius, 0.0f, WHITE);
}
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [others] example - scissor shapes");
Vector2 circleCenter = { screenWidth/2.0f - 120, screenHeight/2.0f };
Vector2 hexCenter = { screenWidth/2.0f + 120, screenHeight/2.0f };
float maskRadius = 100.0f;
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
circleCenter.y = screenHeight/2.0f + sinf((float)GetTime())*40.0f;
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
// Circle-shaped clip: the full-screen rectangle only shows inside the circle
CircleMask circleMask = { circleCenter, maskRadius };
BeginScissorModeShape(DrawCircleMask, &circleMask);
DrawRectangle(0, 0, screenWidth, screenHeight, BLUE);
EndScissorModeShape();
// Hexagon-shaped clip: same mechanism, a different mask shape
PolyMask hexMask = { hexCenter, maskRadius, 6 };
BeginScissorModeShape(DrawPolyMask, &hexMask);
DrawRectangle(0, 0, screenWidth, screenHeight, ORANGE);
EndScissorModeShape();
DrawText("BeginScissorMode() only clips to a rectangle (glScissor)", 10, 10, 10, DARKGRAY);
DrawText("This clips to arbitrary shapes instead, using the stencil buffer", 10, 25, 10, DARKGRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -28,7 +28,7 @@
#include "raylib.h"
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_DESKTOP_SDL)
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_DESKTOP_SDL) || defined(PLATFORM_DESKTOP_RGFW)
#if defined(GRAPHICS_API_OPENGL_ES2)
#include "glad_gles2.h" // Required for: OpenGL functionality
#define glGenVertexArrays glGenVertexArraysOES

View File

@ -24,7 +24,7 @@
*
* APPLE COMPILATION:
* gcc -o rlgl_standalone rlgl_standalone.c -I../../src -Iexternal/include -Lexternal/lib \
* -lglfw3 -framework CoreVideo -framework OpenGL -framework IOKit -framework Cocoa
* -lglfw3 -framework CoreVideo -framework OpenGL -framework IOKit -framework Cocoa -framework QuartzCore
* -Wno-deprecated-declarations -std=c99 -DGRAPHICS_API_OPENGL_33
*
*

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,44 @@
#version 100
precision mediump float;
// Input values from vertex shader
varying vec3 fragPosition;
varying vec3 fragNormal;
varying vec2 fragTexCoord;
// Input uniform values
uniform sampler2D texture0;
uniform vec3 viewPos;
uniform vec3 lightPositions[8];
uniform vec3 lightColors[8];
void main()
{
vec4 texColor = texture2D(texture0, fragTexCoord);
vec3 norm = normalize(fragNormal);
vec3 viewDir = normalize(viewPos - fragPosition);
vec3 ambient = 0.05*texColor.rgb;
vec3 totalDiffuse = vec3(0.0);
vec3 totalSpecular = vec3(0.0);
for (int i = 0; i < 8; i++)
{
vec3 lightDir = normalize(lightPositions[i] - fragPosition);
float dist = length(lightPositions[i] - fragPosition);
float attenuation = 1.0/(1.0 + 0.8*dist + 0.4*dist*dist);
// Diffuse shading
float diff = max(dot(norm, lightDir), 0.0);
totalDiffuse += diff*lightColors[i]*attenuation*1.2;
// Blinn-Phong specular
vec3 halfwayDir = normalize(lightDir + viewDir);
float spec = pow(max(dot(norm, halfwayDir), 0.0), 32.0);
totalSpecular += spec*lightColors[i]*attenuation*0.8;
}
vec3 result = ambient + (totalDiffuse*texColor.rgb) + totalSpecular;
gl_FragColor = vec4(result, texColor.a);
}

View File

@ -0,0 +1,23 @@
#version 100
// Input vertex attributes
attribute vec3 vertexPosition;
attribute vec2 vertexTexCoord;
attribute vec3 vertexNormal;
// Output values to fragment shader
varying vec3 fragPosition;
varying vec3 fragNormal;
varying vec2 fragTexCoord;
// Input uniform values
uniform mat4 mvp;
uniform mat4 matModel;
void main()
{
fragPosition = vec3(matModel*vec4(vertexPosition, 1.0));
fragNormal = normalize(vec3(matModel*vec4(vertexNormal, 0.0)));
fragTexCoord = vertexTexCoord;
gl_Position = mvp*vec4(vertexPosition, 1.0);
}

View File

@ -0,0 +1,33 @@
#version 100
precision mediump float;
varying vec2 fragTexCoord;
uniform sampler2D texture0;
void main()
{
vec4 color = texture2D(texture0, fragTexCoord);
// High-pass threshold blur: only pixels brighter than 0.75 in any channel contribute
vec4 bloom = vec4(0.0);
vec2 texel = vec2(1.0/1280.0, 1.0/720.0)*2.5;
for (int x = -2; x <= 2; x++)
{
for (int y = -2; y <= 2; y++)
{
vec4 smp = texture2D(texture0, fragTexCoord + vec2(float(x), float(y))*texel);
float brightness = max(smp.r, max(smp.g, smp.b));
if (brightness > 0.75) bloom += smp;
}
}
bloom /= 25.0;
// Combine original with the bloom glow, then Reinhard tone-map back to [0, 1]
vec3 hdr = color.rgb + bloom.rgb*1.2;
vec3 ldr = hdr/(hdr + vec3(1.0));
gl_FragColor = vec4(ldr, color.a);
}

View File

@ -99,7 +99,7 @@ vec3 ComputePBR()
vec3 N = normalize(fragNormal);
if (useTexNormal == 1)
{
N = texture2D(normalMap, vec2(fragTexCoord.x*tiling.x + offset.y, fragTexCoord.y*tiling.y + offset.y)).rgb;
N = texture2D(normalMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb;
N = normalize(N*2.0 - 1.0);
N = normalize(N*TBN);
}

View File

@ -97,7 +97,7 @@ vec3 ComputePBR()
vec3 N = normalize(fragNormal);
if (useTexNormal == 1)
{
N = texture2D(normalMap, vec2(fragTexCoord.x*tiling.x + offset.y, fragTexCoord.y*tiling.y + offset.y)).rgb;
N = texture2D(normalMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb;
N = normalize(N*2.0 - 1.0);
N = normalize(N*TBN);
}

View File

@ -0,0 +1,44 @@
#version 330
// Input values from vertex shader
in vec3 fragPosition;
in vec3 fragNormal;
in vec2 fragTexCoord;
out vec4 finalColor;
// Input uniform values
uniform sampler2D texture0;
uniform vec3 viewPos;
uniform vec3 lightPositions[8];
uniform vec3 lightColors[8];
void main()
{
vec4 texColor = texture(texture0, fragTexCoord);
vec3 norm = normalize(fragNormal);
vec3 viewDir = normalize(viewPos - fragPosition);
vec3 ambient = 0.05*texColor.rgb;
vec3 totalDiffuse = vec3(0.0);
vec3 totalSpecular = vec3(0.0);
for (int i = 0; i < 8; i++)
{
vec3 lightDir = normalize(lightPositions[i] - fragPosition);
float dist = length(lightPositions[i] - fragPosition);
float attenuation = 1.0/(1.0 + 0.8*dist + 0.4*dist*dist);
// Diffuse shading
float diff = max(dot(norm, lightDir), 0.0);
totalDiffuse += diff*lightColors[i]*attenuation*1.2;
// Blinn-Phong specular
vec3 halfwayDir = normalize(lightDir + viewDir);
float spec = pow(max(dot(norm, halfwayDir), 0.0), 32.0);
totalSpecular += spec*lightColors[i]*attenuation*0.8;
}
vec3 result = ambient + (totalDiffuse*texColor.rgb) + totalSpecular;
finalColor = vec4(result, texColor.a);
}

View File

@ -0,0 +1,23 @@
#version 330
// Input vertex attributes
in vec3 vertexPosition;
in vec2 vertexTexCoord;
in vec3 vertexNormal;
// Output values to fragment shader
out vec3 fragPosition;
out vec3 fragNormal;
out vec2 fragTexCoord;
// Input uniform values
uniform mat4 mvp;
uniform mat4 matModel;
void main()
{
fragPosition = vec3(matModel*vec4(vertexPosition, 1.0));
fragNormal = normalize(vec3(matModel*vec4(vertexNormal, 0.0)));
fragTexCoord = vertexTexCoord;
gl_Position = mvp*vec4(vertexPosition, 1.0);
}

View File

@ -0,0 +1,32 @@
#version 330
in vec2 fragTexCoord;
out vec4 finalColor;
uniform sampler2D texture0;
void main()
{
vec4 color = texture(texture0, fragTexCoord);
// High-pass threshold blur: only pixels brighter than 0.75 in any channel contribute
vec4 bloom = vec4(0.0);
vec2 texel = vec2(1.0/1280.0, 1.0/720.0)*2.5;
for (int x = -2; x <= 2; x++)
{
for (int y = -2; y <= 2; y++)
{
vec4 smp = texture(texture0, fragTexCoord + vec2(float(x), float(y))*texel);
float brightness = max(smp.r, max(smp.g, smp.b));
if (brightness > 0.75) bloom += smp;
}
}
bloom /= 25.0;
// Combine original with the bloom glow, then Reinhard tone-map back to [0, 1]
vec3 hdr = color.rgb + bloom.rgb*1.2;
vec3 ldr = hdr/(hdr + vec3(1.0));
finalColor = vec4(ldr, color.a);
}

View File

@ -100,7 +100,7 @@ vec3 ComputePBR()
vec3 N = normalize(fragNormal);
if (useTexNormal == 1)
{
N = texture(normalMap, vec2(fragTexCoord.x*tiling.x + offset.y, fragTexCoord.y*tiling.y + offset.y)).rgb;
N = texture(normalMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb;
N = normalize(N*2.0 - 1.0);
N = normalize(N*TBN);
}

View File

@ -9,6 +9,8 @@
*
* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3)
*
* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by Gleb A (@ggrizzly) and reviewed by Ramon Santamaria (@raysan5)
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,

View File

@ -168,6 +168,7 @@ int main(void)
UnloadShader(shader); // Unload shader
UnloadTexture(texture); // Unload texture
UnloadTexture(light); // Unload texture
UnloadRenderTexture(lightmap); // Unload lightmap render texture
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------

View File

@ -0,0 +1,185 @@
/*******************************************************************************************
*
* raylib [shaders] example - lights bloom
*
* Example demonstrates forward multi-point lighting (8 point lights, attenuation and
* Blinn-Phong specular) combined with a threshold-based bloom pass and Reinhard tone
* mapping, applied as a full-screen post-process pass
*
* Example complexity rating: [★★★☆] 3/4
*
* Example uses resources/shaders/glsl100 and resources/shaders/glsl330, shared with the
* rest of the shaders examples
*
* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by PanicTitan (@PanicTitan) 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 PanicTitan (@PanicTitan)
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
#include "rlgl.h"
#include <math.h> // Required for: sinf(), cosf()
#if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330
#else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100
#endif
//--------------------------------------------------------------------------------------
// Global Definitions
//--------------------------------------------------------------------------------------
#define MAX_LIGHTS 8
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
SetConfigFlags(FLAG_MSAA_4X_HINT | FLAG_VSYNC_HINT);
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - lights bloom");
Camera3D camera = { 0 };
camera.position = (Vector3){ 0.0f, 5.0f, 9.0f };
camera.target = (Vector3){ 0.0f, 0.5f, 0.0f };
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };
camera.fovy = 45.0f;
camera.projection = CAMERA_PERSPECTIVE;
RenderTexture2D target = LoadRenderTexture(screenWidth, screenHeight);
// Forward multi-light shader and bloom post-process shader, both loaded from the
// resources folder shared with the rest of the shaders examples. If the GLSL version
// guessed from the PLATFORM_DESKTOP build flag turns out to be wrong for whatever
// raylib was built against, linking fails and silently falls back to the default
// shader - so this retries once with the other version, and either way the result
// is checked explicitly and reported on screen rather than staying silently wrong
Shader lightShader = LoadShader(TextFormat("resources/shaders/glsl%i/lights_bloom.vs", GLSL_VERSION),
TextFormat("resources/shaders/glsl%i/lights_bloom.fs", GLSL_VERSION));
Shader bloomShader = LoadShader(0, TextFormat("resources/shaders/glsl%i/lights_bloom_post.fs", GLSL_VERSION));
// Load models from generated cube mesh and plane
// NOTE: Meshes are automatically unloaded on UnloadModel()
Model cube = LoadModelFromMesh(GenMeshCube(2.0f, 2.0f, 2.0f));
Model floor = LoadModelFromMesh(GenMeshPlane(14.0f, 14.0f, 1, 1));
cube.materials[0].shader = lightShader;
floor.materials[0].shader = lightShader;
int lightPosLoc = GetShaderLocation(lightShader, "lightPositions");
int lightColLoc = GetShaderLocation(lightShader, "lightColors");
int viewPosLoc = GetShaderLocation(lightShader, "viewPos");
Vector3 lightPositions[MAX_LIGHTS] = { 0 };
Vector3 lightColors[MAX_LIGHTS] = {
{ 1.0f, 0.2f, 0.2f }, // Red
{ 0.2f, 1.0f, 0.3f }, // Green
{ 0.2f, 0.5f, 1.0f }, // Blue
{ 1.0f, 0.8f, 0.1f }, // Yellow
{ 1.0f, 0.1f, 0.8f }, // Magenta
{ 0.1f, 1.0f, 1.0f }, // Cyan
{ 1.0f, 0.4f, 0.1f }, // Orange
{ 0.7f, 0.2f, 1.0f }, // Purple
};
SetShaderValueV(lightShader, lightColLoc, lightColors, SHADER_UNIFORM_VEC3, MAX_LIGHTS);
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_ORBITAL);
float time = (float)GetTime();
// Orbital path for each point light, its own radius/height offset by index
for (int i = 0; i < MAX_LIGHTS; i++)
{
float angle = (i/(float)MAX_LIGHTS)*2.0f*PI + time*0.6f;
float radius = 4.2f + sinf(time*1.2f + i)*0.4f;
float height = 1.0f + sinf(time*1.8f + i)*0.6f;
lightPositions[i] = (Vector3){ sinf(angle)*radius, height, cosf(angle)*radius };
}
SetShaderValueV(lightShader, lightPosLoc, lightPositions, SHADER_UNIFORM_VEC3, MAX_LIGHTS);
SetShaderValue(lightShader, viewPosLoc, &camera.position, SHADER_UNIFORM_VEC3);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
// Render the lit scene to an offscreen texture
BeginTextureMode(target);
ClearBackground((Color){ 12, 12, 18, 255 });
BeginMode3D(camera);
DrawModel(cube, (Vector3){ 0.0f, 1.0f, 0.0f }, 1.0f, GRAY);
DrawModel(floor, (Vector3){ 0.0f, 0.0f, 0.0f }, 1.0f, DARKGRAY);
DrawGrid(10, 1.0f);
// Glowing bulbs mark each light's position
for (int i = 0; i < MAX_LIGHTS; i++)
{
Color bulbColor = (Color){
(unsigned char)(lightColors[i].x*255),
(unsigned char)(lightColors[i].y*255),
(unsigned char)(lightColors[i].z*255),
255 };
DrawSphere(lightPositions[i], 0.15f, bulbColor);
}
EndMode3D();
EndTextureMode();
// Present the offscreen texture through the bloom + tone mapping shader
BeginDrawing();
ClearBackground(BLACK);
Rectangle srcRec = { 0, 0, (float)target.texture.width, (float)-target.texture.height };
BeginShaderMode(bloomShader);
// NOTE: Render texture must be y-flipped due to default OpenGL coordinates (left-bottom)
DrawTextureRec(target.texture, srcRec, (Vector2){ 0, 0 }, WHITE);
EndShaderMode();
DrawText("BALANCED MULTI-LIGHT + REINHARD TONE MAPPED BLOOM", 20, 20, 20, GREEN);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadModel(cube);
UnloadModel(floor);
UnloadShader(lightShader);
UnloadShader(bloomShader);
UnloadRenderTexture(target);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 KiB

View File

@ -139,6 +139,9 @@ int main(void)
// De-Initialization
//--------------------------------------------------------------------------------------
RL_FREE(transforms); // Free transforms
UnloadMaterial(matInstances); // Also unloads the instancing shader
UnloadMaterial(matDefault); // Unload default material
UnloadMesh(cube); // Unload cube mesh
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------

View File

@ -91,6 +91,8 @@ int main(void)
Image whiteImage = GenImageColor(GOL_WIDTH, GOL_WIDTH, WHITE);
Texture whiteTex = LoadTextureFromImage(whiteImage);
UnloadImage(whiteImage);
SetTargetFPS(0); // Set our game to run with an uncapped framerate
//--------------------------------------------------------------------------------------
// Main game loop

View File

@ -68,7 +68,7 @@ int main(void)
SetShaderValue(shadowShader, lightDirLoc, &lightDir, SHADER_UNIFORM_VEC3);
SetShaderValue(shadowShader, lightColLoc, &lightColorNormalized, SHADER_UNIFORM_VEC4);
int ambientLoc = GetShaderLocation(shadowShader, "ambient");
float ambient[4] = {0.1f, 0.1f, 0.1f, 1.0f};
float ambient[4] = { 0.1f, 0.1f, 0.1f, 1.0f };
SetShaderValue(shadowShader, ambientLoc, ambient, SHADER_UNIFORM_VEC4);
int lightVPLoc = GetShaderLocation(shadowShader, "lightVP");
int shadowMapLoc = GetShaderLocation(shadowShader, "shadowMap");
@ -81,7 +81,7 @@ int main(void)
for (int i = 0; i < robot.materialCount; i++) robot.materials[i].shader = shadowShader;
int animCount = 0;
ModelAnimation *anims = LoadModelAnimations("resources/models/robot.glb", &animCount);
ModelAnimation* anims = LoadModelAnimations("resources/models/robot.glb", &animCount);
RenderTexture2D shadowMap = LoadShadowmapRenderTexture(SHADOWMAP_RESOLUTION, SHADOWMAP_RESOLUTION);
@ -111,9 +111,11 @@ int main(void)
//----------------------------------------------------------------------------------
float deltaTime = GetFrameTime();
UpdateCamera(&camera, CAMERA_ORBITAL);
// send the updated camera position to the shader so that it can calculate the correct lighting for the scene
Vector3 cameraPos = camera.position;
SetShaderValue(shadowShader, shadowShader.locs[SHADER_LOC_VECTOR_VIEW], &cameraPos, SHADER_UNIFORM_VEC3);
UpdateCamera(&camera, CAMERA_ORBITAL);
frameCounter++;
frameCounter %= (anims[0].keyframeCount);
@ -160,6 +162,7 @@ int main(void)
EndMode3D();
EndTextureMode();
lightViewProj = MatrixMultiply(lightView, lightProj);
// PASS 02: Draw the scene into main framebuffer, using the generated shadowmap
@ -177,6 +180,9 @@ int main(void)
DrawScene(cube, robot); // Draw the same exact things as we drew in the shadowmap!
EndMode3D();
rlActiveTextureSlot(textureActiveSlot);
rlDisableTexture();
DrawText("Use the arrow keys to rotate the light!", 10, 10, 30, RED);
DrawText("Shadows in raylib using the shadowmapping algorithm!", screenWidth - 280, screenHeight - 20, 10, GRAY);

File diff suppressed because it is too large Load Diff

View File

@ -17,6 +17,8 @@
#include "raylib.h"
#include "raymath.h"
#include <stdlib.h> // Required for: malloc(), free()
#include <math.h> // Required for: hypot()
@ -68,6 +70,8 @@ int main(void)
Vector2 pressOffset = { 0 }; // Mouse press offset relative to the ball that grabbedd
float gravity = 100; // World gravity
Vector2 windowPosition = GetWindowPosition();
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//---------------------------------------------------------------------------------------
@ -128,6 +132,17 @@ int main(void)
}
}
// Get window position change for shaking
Vector2 windowPositionDelta = Vector2Subtract(windowPosition, GetWindowPosition());
if (Vector2Length(windowPositionDelta) > 5.0f)
{
for (int i = 0; i < ballCount; i++)
{
if (!balls[i].grabbed) balls[i].speed = Vector2Add(balls[i].speed, Vector2Scale(windowPositionDelta, 10.0f));
}
}
// Shake balls
if (IsMouseButtonPressed(MOUSE_BUTTON_MIDDLE))
{
@ -194,6 +209,8 @@ int main(void)
ball->prevPosition = ball->position;
}
}
windowPosition = GetWindowPosition();
//----------------------------------------------------------------------------------
// Draw
@ -222,8 +239,9 @@ int main(void)
// De-Initialization
//--------------------------------------------------------------------------------------
RL_FREE(balls);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
}

View File

@ -0,0 +1,164 @@
/*******************************************************************************************
*
* raylib [shapes] example - drag puzzle
*
* Example complexity rating: [★☆☆☆] 1/4
*
* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by Gabriel Piangers (@gabriel-piangers) 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) 2026 Gabriel Piangers (@gabriel-piangers)
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
typedef struct {
Vector2 center;
float radius;
} Circle;
typedef struct {
Vector2 v1;
Vector2 v2;
Vector2 v3;
} Triangle;
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - drag puzzle");
// Rectangle
Rectangle rec = { screenWidth/2 - 250, screenHeight/2 + 50, 100.0f, 100.0f };
Rectangle recArea = { screenWidth/2 - 60, screenHeight/2 - 110, 110.0f, 110.0f };
bool recPickedUp = false;
// Circle
Circle circ = { screenWidth/2, screenHeight/2 + 100, 50.0f };
Circle circArea = { screenWidth/2 - 195, screenHeight/2 - 55, 55.0f };
bool circPickedUp = false;
// Triangle
Triangle tri = { { 600, 282 }, { 550, 369 }, { 650, 369 } };
Triangle triArea = { { 600, 115 }, { 540, 222 }, { 660, 222 } };
bool triPickedUp = false;
Vector2 mouseOffset = { 0.0f, 0.0f }; // Stores the offset of the mouse relative to the object's pivot point
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
Vector2 mousePosition = GetMousePosition();
bool recPlaced = false;
bool circPlaced = false;
bool triPlaced = false;
// Detect object pickup input
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && CheckCollisionPointRec(mousePosition, rec))
{
recPickedUp = true;
mouseOffset = (Vector2) { rec.x - mousePosition.x, rec.y - mousePosition.y };
}
else if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && CheckCollisionPointCircle(mousePosition, circ.center, circ.radius))
{
circPickedUp = true;
mouseOffset = (Vector2) { circ.center.x - mousePosition.x, circ.center.y - mousePosition.y };
}
else if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && CheckCollisionPointTriangle(mousePosition, tri.v1, tri.v2, tri.v3))
{
triPickedUp = true;
mouseOffset = (Vector2) { tri.v1.x - mousePosition.x, tri.v1.y - mousePosition.y }; // Uses v1 as the pivot point
}
// Detect object drop input
if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT) && recPickedUp) recPickedUp = false;
else if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT) && circPickedUp) circPickedUp = false;
else if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT) && triPickedUp) triPickedUp = false;
// Rectangle update
if (recPickedUp)
{
rec.x = mousePosition.x + mouseOffset.x;
rec.y = mousePosition.y + mouseOffset.y;
}
Rectangle RecCol = GetCollisionRec(recArea, rec);
if (RecCol.width == rec.width && RecCol.height == rec.height) recPlaced = true;
// Circle update
if (circPickedUp)
{
circ.center.x = mousePosition.x + mouseOffset.x;
circ.center.y = mousePosition.y + mouseOffset.y;
}
if (Vector2Distance(circ.center, circArea.center) < circArea.radius - circ.radius) circPlaced = true;
// Triangle update
if (triPickedUp)
{
Vector2 v2Offset = { tri.v2.x - tri.v1.x, tri.v2.y - tri.v1.y };
Vector2 v3Offset = { tri.v3.x - tri.v1.x, tri.v3.y - tri.v1.y };
tri.v1 = (Vector2) { mousePosition.x + mouseOffset.x, mousePosition.y + mouseOffset.y };
tri.v2 = (Vector2) { tri.v1.x + v2Offset.x, tri.v1.y + v2Offset.y };
tri.v3 = (Vector2) { tri.v1.x + v3Offset.x, tri.v1.y + v3Offset.y };
}
if (
CheckCollisionPointTriangle(tri.v1, triArea.v1, triArea.v2, triArea.v3) &&
CheckCollisionPointTriangle(tri.v2, triArea.v1, triArea.v2, triArea.v3) &&
CheckCollisionPointTriangle(tri.v2, triArea.v1, triArea.v2, triArea.v3)
) triPlaced = true;
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
DrawRectangleLinesEx(recArea, 2.0f, recPlaced ? GREEN : RED);
DrawCircleLinesEx(circArea.center, circArea.radius, 2.0f, circPlaced ? GREEN : RED);
DrawTriangleLinesEx(triArea.v1, triArea.v2, triArea.v3, 2.0f, triPlaced ? GREEN : RED);
// Draws objects that are not picked up first
if (!triPickedUp) DrawTriangle(tri.v1, tri.v2, tri.v3, VIOLET);
if (!circPickedUp) DrawCircleV(circ.center, circ.radius, BLUE);
if (!recPickedUp) DrawRectangleRec(rec, ORANGE);
// Draws the object that is being dragged on top of others
if (triPickedUp) DrawTriangle(tri.v1, tri.v2, tri.v3, VIOLET);
if (circPickedUp) DrawCircleV(circ.center, circ.radius, BLUE);
if (recPickedUp) DrawRectangleRec(rec, ORANGE);
DrawText("Use mouse to drag and drop the objects into the right spot!", 10, 10, 20, GRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

View File

@ -59,7 +59,7 @@ int main(void)
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - collision ellipses");
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - ellipse collision");
SetTargetFPS(60);
Vector2 ellipseACenter = { (float)screenWidth/4, (float)screenHeight/2 };

View File

@ -56,7 +56,7 @@ int main(void)
Vector2 mousePos = { 0 };
Vector2 prevMousePos = { 0 };
Vector2 scaleVector = { 1.0f, -1.0f };
Vector2 offset = { (float)screenWidth/2.0f, (float)screenHeight/2.0f };
Vector2 offset = { GetRenderWidth()/2.0f, GetRenderHeight()/2.0f };
Camera2D camera = { 0 };
camera.target = (Vector2){ 0 };

View File

@ -4,9 +4,9 @@
*
* Example complexity rating: [★☆☆☆] 1/4
*
* Example originally created with raylib 5.6
* Example originally created with raylib 5.6, last time updated with raylib 6.0
*
* Example contributed by Balamurugan R (@Bala050814]) and reviewed by Ramon Santamaria (@raysan5)
* Example contributed by Balamurugan R (@Bala050814) 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

View File

@ -0,0 +1,407 @@
/*******************************************************************************************
*
* raylib [shapes] example - outlines testbed
*
* Example complexity rating: [★★★☆] 3/4
*
* Example originally created with raylib 6.1, last time updated with raylib 6.1
*
* Example contributed by Matthew Roush (@MatthewRoush) 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) 2026 Matthew Roush (@MatthewRoush)
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
#define RAYGUI_IMPLEMENTATION
#include "raygui.h" // Required for GUI controls
#include <stdbool.h>
#define COLOR_FILLED DARKBLUE
#define COLOR_OUTLINE YELLOW
#define SHAPE_SPACING 14.0f
#define SHAPE_SIZE 46.0f
#define BOX_SPACING 10.0f
#define MOUSE_CAMERA_ZOOM_SPEED 0.3f
#define KEYBOARD_CAMERA_MOVE_SPEED 10.0f
#define KEYBOARD_CAMERA_ZOOM_SPEED 0.1f
#define CAMERA_ZOOM_MIN 0.1f
#define CAMERA_ZOOM_MAX 1000.0f
// The shapes are ordered according to their order in this enum, left to right
enum {
ORDER_RECTANGLE = 0,
ORDER_RECTANGLE_ROUNDED,
ORDER_CIRCLE,
ORDER_ELLIPSE,
ORDER_CIRCLE_SECTOR,
ORDER_RING,
ORDER_TRIANGLE,
ORDER_POLYGON,
COUNT_SHAPES
};
// The line style groups are ordered according to their order in this enum, top to bottom
enum {
ORDER_LINES = 0,
ORDER_LINES_EX_WORLD,
ORDER_LINES_EX_SCREEN,
};
#define BOX_WIDTH (SHAPE_SIZE*COUNT_SHAPES + SHAPE_SPACING*(COUNT_SHAPES - 1) + BOX_SPACING*2.0f)
#define BOX_HEIGHT (SHAPE_SIZE + BOX_SPACING*2.0f)
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - outlines testbed");
Camera2D camera = { .zoom = 1 };
// User configurable options while running the program.
float lineOpacity = 130;
float lineThickness = 4.0f;
float rectangleRoundness = 0.4f;
float rectangleSegments = 9;
float ellipseRadiusY = 0.5f;
float circleStartAngle = 20.0f;
float circleEndAngle = 270.0f;
float circleSegments = 36;
float ringInnerRadiusScale = 0.3f;
float polygonSides = 6;
bool disableMouseControl = false;
const Rectangle optionsBackground = { 510, 0, 290, 450 };
const Vector2 zoomPoint = {((float)screenWidth - optionsBackground.width)/2.0f, (float)screenHeight/2.0f};
GuiSetStyle(LABEL, TEXT_COLOR_NORMAL, ColorToInt(WHITE));
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
const Vector2 mousePosScreen = GetMousePosition();
const Vector2 mouseWheelVec = GetMouseWheelMoveV();
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && CheckCollisionPointRec(mousePosScreen, optionsBackground)) disableMouseControl = true;
if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) disableMouseControl = false;
if (!disableMouseControl) {
if (mouseWheelVec.y != 0.0f) {
const Vector2 prevWorldZoomPoint = GetScreenToWorld2D(zoomPoint, camera);
camera.zoom *= exp2f(MOUSE_CAMERA_ZOOM_SPEED*mouseWheelVec.y); // Constant zoom rate
camera.zoom = Clamp(camera.zoom, CAMERA_ZOOM_MIN, CAMERA_ZOOM_MAX);
const Vector2 worldZoomPoint = GetScreenToWorld2D(zoomPoint, camera);
camera.target = Vector2Add(camera.target, Vector2Subtract(prevWorldZoomPoint, worldZoomPoint));
}
if (IsMouseButtonDown(MOUSE_BUTTON_LEFT)) {
const Vector2 mouseDelta = GetMouseDelta();
camera.target.x -= mouseDelta.x/camera.zoom;
camera.target.y -= mouseDelta.y/camera.zoom;
const int mouseMaxX = (int)optionsBackground.x;
const int mouseMaxY = screenHeight;
int newX = (int)mousePosScreen.x;
int newY = (int)mousePosScreen.y;
// In C, the '%' operator computes the remainder, we want the modulus
newX = (newX%mouseMaxX + mouseMaxX)%mouseMaxX;
newY = (newY%mouseMaxY + mouseMaxY)%mouseMaxY;
if ((newX != (int)mousePosScreen.x) || (newY != (int)mousePosScreen.y)) SetMousePosition(newX, newY);
}
}
if (IsKeyDown(KEY_A)) camera.target.x -= KEYBOARD_CAMERA_MOVE_SPEED/camera.zoom;
if (IsKeyDown(KEY_D)) camera.target.x += KEYBOARD_CAMERA_MOVE_SPEED/camera.zoom;
if (IsKeyDown(KEY_W)) camera.target.y -= KEYBOARD_CAMERA_MOVE_SPEED/camera.zoom;
if (IsKeyDown(KEY_S)) camera.target.y += KEYBOARD_CAMERA_MOVE_SPEED/camera.zoom;
if (IsKeyDown(KEY_UP))
{
const Vector2 prevWorldZoomPoint = GetScreenToWorld2D(zoomPoint, camera);
camera.zoom *= exp2f(KEYBOARD_CAMERA_ZOOM_SPEED);
camera.zoom = Clamp(camera.zoom, CAMERA_ZOOM_MIN, CAMERA_ZOOM_MAX);
const Vector2 worldZoomPoint = GetScreenToWorld2D(zoomPoint, camera);
camera.target = Vector2Add(camera.target, Vector2Subtract(prevWorldZoomPoint, worldZoomPoint));
}
if (IsKeyDown(KEY_DOWN))
{
const Vector2 prevWorldZoomPoint = GetScreenToWorld2D(zoomPoint, camera);
camera.zoom *= exp2f(-KEYBOARD_CAMERA_ZOOM_SPEED);
camera.zoom = Clamp(camera.zoom, CAMERA_ZOOM_MIN, CAMERA_ZOOM_MAX);
const Vector2 worldZoomPoint = GetScreenToWorld2D(zoomPoint, camera);
camera.target = Vector2Add(camera.target, Vector2Subtract(prevWorldZoomPoint, worldZoomPoint));
}
if (IsKeyPressed(KEY_Z))
{
const Vector2 zoomPoint = {((float)screenWidth - optionsBackground.width)/2.0f, (float)screenHeight/2.0f};
const Vector2 prevWorldZoomPoint = GetScreenToWorld2D(zoomPoint, camera);
camera.zoom = 1.0f;
const Vector2 worldZoomPoint = GetScreenToWorld2D(zoomPoint, camera);
camera.target = Vector2Add(camera.target, Vector2Subtract(prevWorldZoomPoint, worldZoomPoint));
}
if (IsKeyPressed(KEY_C)) camera.target = (Vector2){ 0 };
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground((Color){ 50, 50, 55, 255 });
Color colorOutline = COLOR_OUTLINE;
colorOutline.a = (unsigned char)lineOpacity;
BeginMode2D(camera);
const float shapeOffset = BOX_SPACING*2.0f;
const float shapePaddingX = SHAPE_SIZE + SHAPE_SPACING;
const float shapePaddingY = SHAPE_SIZE + SHAPE_SPACING + BOX_SPACING*2.0f;
const float radiusX = SHAPE_SIZE/2.0f;
const float radiusY = radiusX*ellipseRadiusY;
const float ringOuterRadius = SHAPE_SIZE/2.0f;
const float ringInnerRadius = ringOuterRadius*ringInnerRadiusScale;
const Vector2 triangleVertex0Offset = { 0.0f, SHAPE_SIZE*0.8f };
const Vector2 triangleVertex1Offset = { SHAPE_SIZE*0.6f, SHAPE_SIZE };
const Vector2 triangleVertex2Offset = { SHAPE_SIZE, 0.0f };
// ----------------------------------------
// Draw*Lines()
float posY = shapeOffset + shapePaddingY*ORDER_LINES;
// Rectangle
float posX = shapeOffset + shapePaddingX*ORDER_RECTANGLE;
DrawRectangleRec((Rectangle){ posX, posY, SHAPE_SIZE, SHAPE_SIZE }, COLOR_FILLED);
DrawRectangleLines(posX, posY, SHAPE_SIZE, SHAPE_SIZE, colorOutline);
// Rectangle Rounded
posX = shapeOffset + shapePaddingX*ORDER_RECTANGLE_ROUNDED;
DrawRectangleRounded((Rectangle){ posX, posY, SHAPE_SIZE, SHAPE_SIZE }, rectangleRoundness, (int)rectangleSegments, COLOR_FILLED);
DrawRectangleRoundedLines((Rectangle){ posX, posY, SHAPE_SIZE, SHAPE_SIZE }, rectangleRoundness, (int)rectangleSegments, colorOutline);
// Circle
posX = shapeOffset + shapePaddingX*ORDER_CIRCLE;
DrawCircleV((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, COLOR_FILLED);
DrawCircleLinesV((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, colorOutline);
// Ellipse
posX = shapeOffset + shapePaddingX*ORDER_ELLIPSE;
DrawEllipseV((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, radiusY, COLOR_FILLED);
DrawEllipseLinesV((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, radiusY, colorOutline);
// Circle Sector
posX = shapeOffset + shapePaddingX*ORDER_CIRCLE_SECTOR;
DrawCircleSector((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, circleStartAngle, circleEndAngle, (int)circleSegments, COLOR_FILLED);
DrawCircleSectorLines((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, circleStartAngle, circleEndAngle, (int)circleSegments, colorOutline);
// Ring
posX = shapeOffset + shapePaddingX*ORDER_RING;
DrawRing((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, ringInnerRadius, ringOuterRadius, circleStartAngle, circleEndAngle, (int)circleSegments, COLOR_FILLED);
DrawRingLines((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, ringInnerRadius, ringOuterRadius, circleStartAngle, circleEndAngle, (int)circleSegments, colorOutline);
// Triangle
posX = shapeOffset + shapePaddingX*ORDER_TRIANGLE;
DrawTriangle((Vector2){ posX + triangleVertex0Offset.x, posY + triangleVertex0Offset.y },
(Vector2){ posX + triangleVertex1Offset.x, posY + triangleVertex1Offset.y },
(Vector2){ posX + triangleVertex2Offset.x, posY + triangleVertex2Offset.y },
COLOR_FILLED);
DrawTriangleLines((Vector2){ posX + triangleVertex0Offset.x, posY + triangleVertex0Offset.y },
(Vector2){ posX + triangleVertex1Offset.x, posY + triangleVertex1Offset.y },
(Vector2){ posX + triangleVertex2Offset.x, posY + triangleVertex2Offset.y },
colorOutline);
// Polygon
posX = shapeOffset + shapePaddingX*ORDER_POLYGON;
DrawPoly((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, (int)polygonSides, radiusX, 0.0f, COLOR_FILLED);
DrawPolyLines((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, (int)polygonSides, radiusX, 0.0f, colorOutline);
// Group the shapes
GuiGroupBox((Rectangle){ shapeOffset - BOX_SPACING, posY - BOX_SPACING, BOX_WIDTH, BOX_HEIGHT }, "Draw*Lines()");
// ----------------------------------------
// ----------------------------------------
// Draw*LinesEx() with world space pixel thickness
posY = shapeOffset + shapePaddingY*ORDER_LINES_EX_WORLD;
// Rectangle
posX = shapeOffset + shapePaddingX*ORDER_RECTANGLE;
DrawRectangleRec((Rectangle){ posX, posY, SHAPE_SIZE, SHAPE_SIZE }, COLOR_FILLED);
DrawRectangleLinesEx((Rectangle){ posX, posY, SHAPE_SIZE, SHAPE_SIZE }, lineThickness, colorOutline);
// Rectangle Rounded
posX = shapeOffset + shapePaddingX*ORDER_RECTANGLE_ROUNDED;
DrawRectangleRounded((Rectangle){ posX, posY, SHAPE_SIZE, SHAPE_SIZE }, rectangleRoundness, (int)rectangleSegments, COLOR_FILLED);
DrawRectangleRoundedLinesEx((Rectangle){ posX, posY, SHAPE_SIZE, SHAPE_SIZE }, rectangleRoundness, (int)rectangleSegments, lineThickness, colorOutline);
// Circle
posX = shapeOffset + shapePaddingX*ORDER_CIRCLE;
DrawCircleV((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, COLOR_FILLED);
DrawCircleLinesEx((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, lineThickness, colorOutline);
// Ellipse
posX = shapeOffset + shapePaddingX*ORDER_ELLIPSE;
DrawEllipseV((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, radiusY, COLOR_FILLED);
DrawEllipseLinesEx((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, radiusY, lineThickness, colorOutline);
// Circle Sector
posX = shapeOffset + shapePaddingX*ORDER_CIRCLE_SECTOR;
DrawCircleSector((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, circleStartAngle, circleEndAngle, (int)circleSegments, COLOR_FILLED);
DrawCircleSectorLinesEx((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, circleStartAngle, circleEndAngle, (int)circleSegments, lineThickness, colorOutline);
// Ring
posX = shapeOffset + shapePaddingX*ORDER_RING;
DrawRing((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, ringInnerRadius, ringOuterRadius, circleStartAngle, circleEndAngle, (int)circleSegments, COLOR_FILLED);
DrawRingLinesEx((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, ringInnerRadius, ringOuterRadius, circleStartAngle, circleEndAngle, (int)circleSegments, lineThickness, colorOutline);
// Triangle
posX = shapeOffset + shapePaddingX*ORDER_TRIANGLE;
DrawTriangle((Vector2){ posX + triangleVertex0Offset.x, posY + triangleVertex0Offset.y },
(Vector2){ posX + triangleVertex1Offset.x, posY + triangleVertex1Offset.y },
(Vector2){ posX + triangleVertex2Offset.x, posY + triangleVertex2Offset.y },
COLOR_FILLED);
DrawTriangleLinesEx((Vector2){ posX + triangleVertex0Offset.x, posY + triangleVertex0Offset.y },
(Vector2){ posX + triangleVertex1Offset.x, posY + triangleVertex1Offset.y },
(Vector2){ posX + triangleVertex2Offset.x, posY + triangleVertex2Offset.y },
lineThickness, colorOutline);
// Polygon
posX = shapeOffset + shapePaddingX*ORDER_POLYGON;
DrawPoly((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, (int)polygonSides, radiusX, 0.0f, COLOR_FILLED);
DrawPolyLinesEx((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, (int)polygonSides, radiusX, 0.0f, lineThickness, colorOutline);
// Group the shapes
GuiGroupBox((Rectangle){ shapeOffset - BOX_SPACING, posY - BOX_SPACING, BOX_WIDTH, BOX_HEIGHT }, "Draw*LinesEx() with *world space* pixel thickness");
// ----------------------------------------
// ----------------------------------------
// Draw*LinesEx() with screen space pixel thickness
posY = shapeOffset + shapePaddingY*ORDER_LINES_EX_SCREEN;
float constantThickness = lineThickness/camera.zoom;
// Rectangle
posX = shapeOffset + shapePaddingX*ORDER_RECTANGLE;
DrawRectangleRec((Rectangle){ posX, posY, SHAPE_SIZE, SHAPE_SIZE }, COLOR_FILLED);
DrawRectangleLinesEx((Rectangle){ posX, posY, SHAPE_SIZE, SHAPE_SIZE }, constantThickness, colorOutline);
// Rectangle Rounded
posX = shapeOffset + shapePaddingX*ORDER_RECTANGLE_ROUNDED;
DrawRectangleRounded((Rectangle){ posX, posY, SHAPE_SIZE, SHAPE_SIZE }, rectangleRoundness, (int)rectangleSegments, COLOR_FILLED);
DrawRectangleRoundedLinesEx((Rectangle){ posX, posY, SHAPE_SIZE, SHAPE_SIZE }, rectangleRoundness, (int)rectangleSegments, constantThickness, colorOutline);
// Circle
posX = shapeOffset + shapePaddingX*ORDER_CIRCLE;
DrawCircleV((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, COLOR_FILLED);
DrawCircleLinesEx((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, constantThickness, colorOutline);
// Ellipse
posX = shapeOffset + shapePaddingX*ORDER_ELLIPSE;
DrawEllipseV((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, radiusY, COLOR_FILLED);
DrawEllipseLinesEx((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, radiusY, constantThickness, colorOutline);
// Circle Sector
posX = shapeOffset + shapePaddingX*ORDER_CIRCLE_SECTOR;
DrawCircleSector((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, circleStartAngle, circleEndAngle, (int)circleSegments, COLOR_FILLED);
DrawCircleSectorLinesEx((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, circleStartAngle, circleEndAngle, (int)circleSegments, constantThickness, colorOutline);
// Ring
posX = shapeOffset + shapePaddingX*ORDER_RING;
DrawRing((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, ringInnerRadius, ringOuterRadius, circleStartAngle, circleEndAngle, (int)circleSegments, COLOR_FILLED);
DrawRingLinesEx((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, ringInnerRadius, ringOuterRadius, circleStartAngle, circleEndAngle, (int)circleSegments, constantThickness, colorOutline);
// Triangle
posX = shapeOffset + shapePaddingX*ORDER_TRIANGLE;
DrawTriangle((Vector2){ posX + triangleVertex0Offset.x, posY + triangleVertex0Offset.y },
(Vector2){ posX + triangleVertex1Offset.x, posY + triangleVertex1Offset.y },
(Vector2){ posX + triangleVertex2Offset.x, posY + triangleVertex2Offset.y },
COLOR_FILLED);
DrawTriangleLinesEx((Vector2){ posX + triangleVertex0Offset.x, posY + triangleVertex0Offset.y },
(Vector2){ posX + triangleVertex1Offset.x, posY + triangleVertex1Offset.y },
(Vector2){ posX + triangleVertex2Offset.x, posY + triangleVertex2Offset.y },
constantThickness, colorOutline);
// Polygon
posX = shapeOffset + shapePaddingX*ORDER_POLYGON;
DrawPoly((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, (int)polygonSides, radiusX, 0.0f, COLOR_FILLED);
DrawPolyLinesEx((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, (int)polygonSides, radiusX, 0.0f, constantThickness, colorOutline);
// Group the shapes
GuiGroupBox((Rectangle){ shapeOffset - BOX_SPACING, posY - BOX_SPACING, BOX_WIDTH, BOX_HEIGHT }, "Draw*LinesEx() with *screen space* pixel thickness");
// ----------------------------------------
EndMode2D();
DrawRectangleRec(optionsBackground, Fade(DARKGRAY, 0.75f));
DrawRectangleRec((Rectangle){ optionsBackground.x, 360, optionsBackground.width, 90 }, Fade(BLACK, 0.4f));
DrawLineEx((Vector2){ optionsBackground.x, 360 }, (Vector2){ optionsBackground.x + optionsBackground.width, 360 }, 1.0f, BLACK);
DrawText("Move with the mouse or WASD keys", (int)optionsBackground.x + 10, 370, 10, ORANGE);
DrawText("Zoom with the mouse or UP and DOWN keys", (int)optionsBackground.x + 10, 390, 10, ORANGE);
DrawText("Press C to reset position", (int)optionsBackground.x + 10, 410, 10, ORANGE);
DrawText("Press Z to reset zoom", (int)optionsBackground.x + 10, 430, 10, ORANGE);
DrawLineEx((Vector2){ optionsBackground.x, optionsBackground.y }, (Vector2){ optionsBackground.x, optionsBackground.y + optionsBackground.height }, 1.0f, BLACK);
GuiSliderBar((Rectangle){ 605, 10, 150, 25 }, "Line Opacity" , TextFormat("%d" , (int)lineOpacity) , &lineOpacity , 0 , 255);
GuiSliderBar((Rectangle){ 605, 45, 150, 25 }, "Thickness" , TextFormat("%.2f", lineThickness) , &lineThickness , -20.0f , 40.0f);
GuiSliderBar((Rectangle){ 605, 80, 150, 25 }, "Rect Roundness" , TextFormat("%.2f", rectangleRoundness) , &rectangleRoundness , -1.0f , 2.0f);
GuiSliderBar((Rectangle){ 605, 115, 150, 25 }, "Rect Segments" , TextFormat("%d" , (int)rectangleSegments), &rectangleSegments , -1 , 100);
GuiSliderBar((Rectangle){ 605, 150, 150, 25 }, "Ellipse Radius Y", TextFormat("%.2f", ellipseRadiusY) , &ellipseRadiusY , 0.0f , 1.25f);
GuiSliderBar((Rectangle){ 605, 185, 150, 25 }, "Start Angle" , TextFormat("%.2f", circleStartAngle) , &circleStartAngle , -360.0f, 360.0f);
GuiSliderBar((Rectangle){ 605, 220, 150, 25 }, "End Angle" , TextFormat("%.2f", circleEndAngle) , &circleEndAngle , -360.0f, 360.0f);
GuiSliderBar((Rectangle){ 605, 255, 150, 25 }, "Circle Segments" , TextFormat("%d" , (int)circleSegments) , &circleSegments , -1 , 100);
GuiSliderBar((Rectangle){ 605, 290, 150, 25 }, "Ring Radius" , TextFormat("%.2f", ringInnerRadiusScale) , &ringInnerRadiusScale, -1.0f , 2.0f);
GuiSliderBar((Rectangle){ 605, 325, 150, 25 }, "Poly Sides" , TextFormat("%d" , (int)polygonSides) , &polygonSides , -1 , 100);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@ -0,0 +1,78 @@
/*******************************************************************************************
*
* raylib [shapes] example - outlines thickness
*
* Example complexity rating: [★☆☆☆] 1/4
*
* Example originally created with raylib 6.1, last time updated with raylib 6.1
*
* Example contributed by Matthew Roush (@MatthewRoush) 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) 2026 Matthew Roush (@MatthewRoush)
*
********************************************************************************************/
#include "raylib.h"
#define RAYGUI_IMPLEMENTATION
#include "raygui.h" // Required for GUI controls
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - outlines thickness");
float thick = 5.0f;
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
// TODO: Update variables / Implement example logic at this point
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
GuiSliderBar((Rectangle){ 290, 50, 220, 24 }, "Thickness", TextFormat("%.2f", thick), &thick, -30.0f, 30.0f);
DrawRectangle(35, 180, 220, 220, LIGHTGRAY);
DrawRectangleLinesEx((Rectangle){ 35, 180, 220, 220 }, thick, BLUE);
DrawText("DrawRectangleLinesEx()", 35, 160, 10, BLACK);
DrawRectangleRounded((Rectangle){ 290, 180, 220, 220 }, 0.2f, 9, LIGHTGRAY);
DrawRectangleRoundedLinesEx((Rectangle){ 290, 180, 220, 220 }, 0.2f, 9, thick, BLUE);
DrawText("DrawRectangleRoundedLinesEx()", 290, 160, 10, BLACK);
DrawCircle(655, 290, 110, LIGHTGRAY);
DrawCircleLinesEx((Vector2){ 655, 290 }, 110, thick, BLUE);
DrawText("DrawCircleLinesEx()", 545, 160, 10, BLACK);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -16,12 +16,13 @@
********************************************************************************************/
#include "raylib.h"
#include <math.h>
#include <stdio.h>
#define RAYGUI_IMPLEMENTATION
#include "raygui.h"
#include <math.h>
#include <stdio.h>
#define MAX_PIE_SLICES 10 // Max pie slices
//------------------------------------------------------------------------------------
@ -39,12 +40,8 @@ int main(void)
int sliceCount = 7;
float donutInnerRadius = 25.0f;
float values[MAX_PIE_SLICES] = { 300.0f, 100.0f, 450.0f, 350.0f, 600.0f, 380.0f, 750.0f }; // Initial slice values
char labels[MAX_PIE_SLICES][32] = { 0 };
bool editingLabel[MAX_PIE_SLICES] = { 0 };
for (int i = 0; i < MAX_PIE_SLICES; i++)
snprintf(labels[i], 32, "Slice %02i", i + 1);
bool showValues = true;
bool showPercentages = false;
bool showDonut = false;
@ -59,7 +56,7 @@ int main(void)
// UI Panel top-left anchor
const Vector2 panelPos = {
(float)screenWidth - panelMargin - panelWidth,
(float)screenWidth - panelMargin - panelWidth,
(float)panelMargin
};
@ -72,7 +69,7 @@ int main(void)
// Pie chart geometry
const Rectangle canvas = { 0, 0, panelPos.x, (float)screenHeight };
const Vector2 center = { canvas.width/2.0f, canvas.height/2.0f};
const Vector2 center = { canvas.width/2.0f, canvas.height/2.0f };
const float radius = 205.0f;
// Total value for percentage calculations
@ -93,6 +90,7 @@ int main(void)
// Check for mouse hover over slices
hoveredSlice = -1; // Reset hovered slice
Vector2 mousePos = GetMousePosition();
if (CheckCollisionPointRec(mousePos, canvas)) // Only check if mouse is inside the canvas
{
float dx = mousePos.x - center.x;
@ -176,7 +174,7 @@ int main(void)
if (showDonut) GuiDisable();
GuiSliderBar((Rectangle){ panelPos.x + 80, (float)panelPos.y + 12 + 130, panelRect.width - 100, 30 },
"Inner Radius", NULL, &donutInnerRadius, 5.0f, radius - 10.0f);
"Inner Radius", NULL, & donutInnerRadius, 5.0f, radius - 10.0f);
GuiEnable();
GuiLine((Rectangle){ panelPos.x + 10, (float)panelPos.y + 12 + 170, panelRect.width - 20, 1 }, NULL);
@ -190,8 +188,7 @@ int main(void)
};
int contentHeight = sliceCount*35;
GuiScrollPanel(scrollPanelBounds, NULL,
(Rectangle){ 0, 0, panelRect.width - 25, (float)contentHeight },
GuiScrollPanel(scrollPanelBounds, NULL, (Rectangle){ 0, 0, panelRect.width - 25, (float)contentHeight },
&scrollContentOffset, &view);
const float contentX = view.x + scrollContentOffset.x; // Left of content
@ -208,7 +205,8 @@ int main(void)
DrawRectangle((int)(contentX + 15), rowY + 5, 20, 20, color);
// Label textbox
if (GuiTextBox((Rectangle){ contentX + 45, (float)rowY, 75, 30 }, labels[i], 32, editingLabel[i])) editingLabel[i] = !editingLabel[i];
if (GuiTextBox((Rectangle){ contentX + 45, (float)rowY, 75, 30 }, TextFormat("Slice %02i", i + 1), 32, editingLabel[i]))
editingLabel[i] = !editingLabel[i];
GuiSliderBar((Rectangle){ contentX + 130, (float)rowY, 110, 30 }, NULL, NULL, &values[i], 0.0f, 1000.0f);
}

View File

@ -0,0 +1,118 @@
/*******************************************************************************************
*
* raylib [shapes] example - polygon lines
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 6.1, last time updated with raylib 6.1
*
* Example contributed by Matthew Roush (@MatthewRoush) 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) 2026 Matthew Roush (@MatthewRoush)
*
********************************************************************************************/
#include "raylib.h"
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - polygon lines");
int thick = 2;
float rotation = 0.0f;
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
if (IsKeyPressed(KEY_UP)) thick = thick + 1;
if (IsKeyPressed(KEY_DOWN)) thick = thick - 1;
thick = (thick < 1) ? 1 : (thick > 60) ? 60 : thick;
rotation += (360.0f/10.0f)*GetFrameTime();
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
DrawText(TextFormat("thick = %d", thick), 10, 280, 20, LIME);
// The square and circle outlines in the top left should match
// The fist pair of outlines are drawn using `DrawRectangleLinesEx()` and `DrawCircleLinesEx()`
// The second pair are drawn using `DrawPolyLinesEx()` with parameters that should visually match the first pair
DrawText("These should look identical!", 10, 10, 20, MAROON);
// Outline pair 1
DrawRectangle(10, 40, 50, 50, LIGHTGRAY);
DrawRectangleLinesEx((Rectangle){ 10, 40, 50, 50 }, (float)thick, RED);
DrawCircle(95, 65, 25, LIGHTGRAY);
DrawCircleLinesEx((Vector2){ 95, 65 }, 25, (float)thick, RED);
DrawText("DrawRectangleLinesEx() and DrawCircleLinesEx()", 130, 60, 10, BLACK);
// Outline pair 2
DrawPoly((Vector2){ 35, 125 }, 4, 35.355f, 45, LIGHTGRAY);
DrawPolyLinesEx((Vector2){ 35, 125 }, 4, 35.355f, 45, (float)thick, RED);
DrawPoly((Vector2){ 95, 125 }, 36, 25, 0, LIGHTGRAY);
DrawPolyLinesEx((Vector2){ 95, 125 }, 36, 25, 0, (float)thick, RED);
DrawText("DrawPolyLinesEx()", 130, 120, 10, BLACK);
// Some other shapes, all of these outlines should have the same looking thickness
DrawPoly((Vector2){ 290, 220 }, 3, 60, rotation, LIGHTGRAY);
DrawPolyLinesEx((Vector2){ 290, 220 }, 3, 60, rotation, (float)thick, BLUE);
DrawPoly((Vector2){ 430, 220 }, 4, 60, rotation, LIGHTGRAY);
DrawPolyLinesEx((Vector2){ 430, 220 }, 4, 60, rotation, (float)thick, BLUE);
DrawPoly((Vector2){ 570, 220 }, 5, 60, rotation, LIGHTGRAY);
DrawPolyLinesEx((Vector2){ 570, 220 }, 5, 60, rotation, (float)thick, BLUE);
DrawPoly((Vector2){ 710, 220 }, 6, 60, rotation, LIGHTGRAY);
DrawPolyLinesEx((Vector2){ 710, 220 }, 6, 60, rotation, (float)thick, BLUE);
DrawPoly((Vector2){ 290, 360 }, 7, 60, rotation, LIGHTGRAY);
DrawPolyLinesEx((Vector2){ 290, 360 }, 7, 60, rotation, (float)thick, BLUE);
DrawPoly((Vector2){ 430, 360 }, 8, 60, rotation, LIGHTGRAY);
DrawPolyLinesEx((Vector2){ 430, 360 }, 8, 60, rotation, (float)thick, BLUE);
DrawPoly((Vector2){ 570, 360 }, 9, 60, rotation, LIGHTGRAY);
DrawPolyLinesEx((Vector2){ 570, 360 }, 9, 60, rotation, (float)thick, BLUE);
DrawPoly((Vector2){ 710, 360 }, 10, 60, rotation, LIGHTGRAY);
DrawPolyLinesEx((Vector2){ 710, 360 }, 10, 60, rotation, (float)thick, BLUE);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

Some files were not shown because too many files have changed in this diff Show More