Merge branch 'master' into drm_gamepad_polling

This commit is contained in:
Cinghy Creations 2023-12-15 19:39:52 +01:00 committed by GitHub
commit 35159abd66
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
59 changed files with 4642 additions and 1264 deletions

1
.gitignore vendored
View File

@ -54,6 +54,7 @@ packages/
*.bc *.bc
*.so *.so
*.so.* *.so.*
*.dll
# Ignore wasm data in examples/ # Ignore wasm data in examples/
examples/**/*.wasm examples/**/*.wasm

View File

@ -6,7 +6,8 @@ Some people ported raylib to other languages in form of bindings or wrappers to
| name | raylib version | language | license | repo | | name | raylib version | language | license | repo |
|:------------------:|:---------------:|:---------:|:----------:|-----------------------------------------------------------| |:------------------:|:---------------:|:---------:|:----------:|-----------------------------------------------------------|
| raylib | **4.5** | [C/C++](https://en.wikipedia.org/wiki/C_(programming_language)) | Zlib | https://github.com/raysan5/raylib | | raylib | **5.0** | [C/C++](https://en.wikipedia.org/wiki/C_(programming_language)) | Zlib | https://github.com/raysan5/raylib |
| raylib-beef | **5.0** | [Beef](https://www.beeflang.org/) | MIT | https://github.com/Starpelly/raylib-beef |
| raylib-boo | 3.7 | [Boo](http://boo-language.github.io/)| MIT | https://github.com/Rabios/raylib-boo | | raylib-boo | 3.7 | [Boo](http://boo-language.github.io/)| MIT | https://github.com/Rabios/raylib-boo |
| Raylib-cs | **4.5** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | Zlib | https://github.com/ChrisDill/Raylib-cs | | Raylib-cs | **4.5** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | Zlib | https://github.com/ChrisDill/Raylib-cs |
| Raylib-CsLo | 4.2 | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MPL-2.0 | https://github.com/NotNotTech/Raylib-CsLo | | Raylib-CsLo | 4.2 | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MPL-2.0 | https://github.com/NotNotTech/Raylib-CsLo |
@ -20,20 +21,20 @@ Some people ported raylib to other languages in form of bindings or wrappers to
| dart-raylib | 4.0 | [Dart](https://dart.dev/) | MIT | https://gitlab.com/wolfenrain/dart-raylib | | dart-raylib | 4.0 | [Dart](https://dart.dev/) | MIT | https://gitlab.com/wolfenrain/dart-raylib |
| bindbc-raylib3 | **4.5** | [D](https://dlang.org/) | BSL-1.0 | https://github.com/o3o/bindbc-raylib3 | | bindbc-raylib3 | **4.5** | [D](https://dlang.org/) | BSL-1.0 | https://github.com/o3o/bindbc-raylib3 |
| dray | 4.2 | [D](https://dlang.org/) | Apache-2.0 | https://github.com/redthing1/dray | | dray | 4.2 | [D](https://dlang.org/) | Apache-2.0 | https://github.com/redthing1/dray |
| raylib-d | **4.5** | [D](https://dlang.org/) | Zlib | https://github.com/schveiguy/raylib-d | | raylib-d | **5.0** | [D](https://dlang.org/) | Zlib | https://github.com/schveiguy/raylib-d |
| dlang_raylib | 4.0 | [D](https://dlang.org) | MPL-2.0 |https://github.com/rc-05/dlang_raylib | | dlang_raylib | 4.0 | [D](https://dlang.org) | MPL-2.0 |https://github.com/rc-05/dlang_raylib |
| rayex | 3.7 | [elixir](https://elixir-lang.org/) | Apache-2.0 | https://github.com/shiryel/rayex | | rayex | 3.7 | [elixir](https://elixir-lang.org/) | Apache-2.0 | https://github.com/shiryel/rayex |
| raylib-factor | **4.5** | [Factor](https://factorcode.org/) | BSD | https://github.com/factor/factor/blob/master/extra/raylib/raylib.factor | | raylib-factor | **4.5** | [Factor](https://factorcode.org/) | BSD | https://github.com/factor/factor/blob/master/extra/raylib/raylib.factor |
| raylib-freebasic | **4.5** | [FreeBASIC](https://www.freebasic.net/) | MIT | https://github.com/WIITD/raylib-freebasic | | raylib-freebasic | **5.0** | [FreeBASIC](https://www.freebasic.net/) | MIT | https://github.com/WIITD/raylib-freebasic |
| fortran-raylib | **4.5** | [Fortran](https://fortran-lang.org/) | ISC | https://github.com/interkosmos/fortran-raylib | | fortran-raylib | **4.5** | [Fortran](https://fortran-lang.org/) | ISC | https://github.com/interkosmos/fortran-raylib |
| raylib for Pascal | **4.5** | [Object Pascal](https://en.wikipedia.org/wiki/Object_Pascal) | Modified Zlib | https://github.com/tinyBigGAMES/raylib | | raylib for Pascal | **4.5** | [Object Pascal](https://en.wikipedia.org/wiki/Object_Pascal) | Modified Zlib | https://github.com/tinyBigGAMES/raylib |
| raylib-go | **5.0** | [Go](https://golang.org/) | Zlib | https://github.com/gen2brain/raylib-go | | raylib-go | **5.0** | [Go](https://golang.org/) | Zlib | https://github.com/gen2brain/raylib-go |
| raylib-guile | **auto** | [Guile](https://www.gnu.org/software/guile/) | Zlib | https://github.com/petelliott/raylib-guile | | raylib-guile | **auto** | [Guile](https://www.gnu.org/software/guile/) | Zlib | https://github.com/petelliott/raylib-guile |
| gforth-raylib | 3.5 | [Gforth](https://gforth.org/) | MIT | https://github.com/ArnautDaniel/gforth-raylib | | gforth-raylib | 3.5 | [Gforth](https://gforth.org/) | **???** | https://github.com/ArnautDaniel/gforth-raylib |
| h-raylib | **4.6-dev** | [Haskell](https://haskell.org/) | Apache-2.0 | https://github.com/Anut-py/h-raylib | | h-raylib | **4.6-dev** | [Haskell](https://haskell.org/) | Apache-2.0 | https://github.com/Anut-py/h-raylib |
| raylib-hx | 4.2 | [Haxe](https://haxe.org/) | Zlib | https://github.com/foreignsasquatch/raylib-hx | | raylib-hx | 4.2 | [Haxe](https://haxe.org/) | Zlib | https://github.com/foreignsasquatch/raylib-hx |
| hb-raylib | 3.5 | [Harbour](https://harbour.github.io) | MIT | https://github.com/MarcosLeonardoMendezGerencir/hb-raylib | | hb-raylib | 3.5 | [Harbour](https://harbour.github.io) | MIT | https://github.com/MarcosLeonardoMendezGerencir/hb-raylib |
| jaylib | 4.5 | [Janet](https://janet-lang.org/) | MIT | https://github.com/janet-lang/jaylib | | jaylib | 5.0 | [Janet](https://janet-lang.org/) | MIT | https://github.com/janet-lang/jaylib |
| jaylib | **4.5** | [Java](https://en.wikipedia.org/wiki/Java_(programming_language)) | GPLv3+CE | https://github.com/electronstudio/jaylib/ | | jaylib | **4.5** | [Java](https://en.wikipedia.org/wiki/Java_(programming_language)) | GPLv3+CE | https://github.com/electronstudio/jaylib/ |
| raylib-j | 4.0 | [Java](https://en.wikipedia.org/wiki/Java_(programming_language)) | Zlib | https://github.com/CreedVI/Raylib-J | | raylib-j | 4.0 | [Java](https://en.wikipedia.org/wiki/Java_(programming_language)) | Zlib | https://github.com/CreedVI/Raylib-J |
| raylib.jl | 4.2 | [Julia](https://julialang.org/) | Zlib | https://github.com/irishgreencitrus/raylib.jl | | raylib.jl | 4.2 | [Julia](https://julialang.org/) | Zlib | https://github.com/irishgreencitrus/raylib.jl |
@ -43,7 +44,7 @@ Some people ported raylib to other languages in form of bindings or wrappers to
| raylua | 4.0 | [Lua](http://www.lua.org/) | MIT | https://github.com/Rabios/raylua | | raylua | 4.0 | [Lua](http://www.lua.org/) | MIT | https://github.com/Rabios/raylua |
| raylib-matte | 4.6-dev | [Matte](https://github.com/jcorks/matte/) | MIT | https://github.com/jcorks/raylib-matte | | raylib-matte | 4.6-dev | [Matte](https://github.com/jcorks/matte/) | MIT | https://github.com/jcorks/raylib-matte |
| nelua-raylib | 4.0 | [nelua](https://nelua.io/) | MIT | https://github.com/AKDev21/nelua-raylib | | nelua-raylib | 4.0 | [nelua](https://nelua.io/) | MIT | https://github.com/AKDev21/nelua-raylib |
| Raylib.nelua | **4.5** | [nelua](https://nelua.io/) | Zlib | https://github.com/Its-Kenta/Raylib-Nelua | | Raylib.nelua | **5.0** | [nelua](https://nelua.io/) | Zlib | https://github.com/AuzFox/Raylib.nelua |
| NimraylibNow! | 4.2 | [Nim](https://nim-lang.org/) | MIT | https://github.com/greenfork/nimraylib_now | | NimraylibNow! | 4.2 | [Nim](https://nim-lang.org/) | MIT | https://github.com/greenfork/nimraylib_now |
| raylib-bindings | **4.5** | [Ruby](https://www.ruby-lang.org/en/) | Zlib | https://github.com/vaiorabbit/raylib-bindings | | raylib-bindings | **4.5** | [Ruby](https://www.ruby-lang.org/en/) | Zlib | https://github.com/vaiorabbit/raylib-bindings |
| raylib-Forever | auto | [Nim](https://nim-lang.org/) | ? | https://github.com/Guevara-chan/Raylib-Forever | | raylib-Forever | auto | [Nim](https://nim-lang.org/) | ? | https://github.com/Guevara-chan/Raylib-Forever |
@ -53,12 +54,12 @@ Some people ported raylib to other languages in form of bindings or wrappers to
| raylib_odin_bindings | 4.0-dev | [Odin](https://odin-lang.org/) | MIT | https://github.com/Deathbat2190/raylib_odin_bindings | | raylib_odin_bindings | 4.0-dev | [Odin](https://odin-lang.org/) | MIT | https://github.com/Deathbat2190/raylib_odin_bindings |
| raylib-ocaml | **4.5** | [OCaml](https://ocaml.org/) | MIT | https://github.com/tjammer/raylib-ocaml | | raylib-ocaml | **4.5** | [OCaml](https://ocaml.org/) | MIT | https://github.com/tjammer/raylib-ocaml |
| TurboRaylib | **4.5** | [Object Pascal](https://en.wikipedia.org/wiki/Object_Pascal) | MIT | https://github.com/turborium/TurboRaylib | | TurboRaylib | **4.5** | [Object Pascal](https://en.wikipedia.org/wiki/Object_Pascal) | MIT | https://github.com/turborium/TurboRaylib |
| Ray4Laz | **4.5** | [Free Pascal](https://en.wikipedia.org/wiki/Free_Pascal)| Zlib | https://github.com/GuvaCode/Ray4Laz | | Ray4Laz | **5.0** | [Free Pascal](https://en.wikipedia.org/wiki/Free_Pascal)| Zlib | https://github.com/GuvaCode/Ray4Laz |
| Raylib.4.0.Pascal | 4.0 | [Free Pascal](https://en.wikipedia.org/wiki/Free_Pascal)| Zlib | https://github.com/sysrpl/Raylib.4.0.Pascal | | Raylib.4.0.Pascal | 4.0 | [Free Pascal](https://en.wikipedia.org/wiki/Free_Pascal)| Zlib | https://github.com/sysrpl/Raylib.4.0.Pascal |
| pyraylib | 3.7 | [Python](https://www.python.org/) | Zlib | https://github.com/Ho011/pyraylib | | pyraylib | 3.7 | [Python](https://www.python.org/) | Zlib | https://github.com/Ho011/pyraylib |
| raylib-python-cffi | 4.2 | [Python](https://www.python.org/) | EPL-2.0 | https://github.com/electronstudio/raylib-python-cffi | | raylib-python-cffi | 4.2 | [Python](https://www.python.org/) | EPL-2.0 | https://github.com/electronstudio/raylib-python-cffi |
| raylibpyctbg | **4.5** | [Python](https://www.python.org/) | MIT | https://github.com/overdev/raylibpyctbg | | raylibpyctbg | **4.5** | [Python](https://www.python.org/) | MIT | https://github.com/overdev/raylibpyctbg |
| raylib-py | **4.5** | [Python](https://www.python.org/) | MIT | https://github.com/overdev/raylib-py | | raylib-py | **5.0b1** | [Python](https://www.python.org/) | MIT | https://github.com/overdev/raylib-py |
| raylib-python-ctypes | 4.6-dev | [Python](https://www.python.org/) | MIT | https://github.com/sDos280/raylib-python-ctypes | | raylib-python-ctypes | 4.6-dev | [Python](https://www.python.org/) | MIT | https://github.com/sDos280/raylib-python-ctypes |
| raylib-pkpy-bindings | 4.6-dev | [pocketpy](https://pocketpy.dev/) | MIT | https://github.com/blueloveTH/pkpy-bindings | | raylib-pkpy-bindings | 4.6-dev | [pocketpy](https://pocketpy.dev/) | MIT | https://github.com/blueloveTH/pkpy-bindings |
| raylib-php | **4.5** | [PHP](https://en.wikipedia.org/wiki/PHP) | Zlib | https://github.com/joseph-montanez/raylib-php | | raylib-php | **4.5** | [PHP](https://en.wikipedia.org/wiki/PHP) | Zlib | https://github.com/joseph-montanez/raylib-php |
@ -70,7 +71,7 @@ Some people ported raylib to other languages in form of bindings or wrappers to
| racket-raylib | 4.0 | [Racket](https://racket-lang.org/) | MIT/Apache-2.0 | https://github.com/eutro/racket-raylib | | racket-raylib | 4.0 | [Racket](https://racket-lang.org/) | MIT/Apache-2.0 | https://github.com/eutro/racket-raylib |
| raylib-swift | 4.0 | [Swift](https://swift.org/) | MIT | https://github.com/STREGAsGate/Raylib | | raylib-swift | 4.0 | [Swift](https://swift.org/) | MIT | https://github.com/STREGAsGate/Raylib |
| raylib-scopes | auto | [Scopes](http://scopes.rocks) | MIT | https://github.com/salotz/raylib-scopes | | raylib-scopes | auto | [Scopes](http://scopes.rocks) | MIT | https://github.com/salotz/raylib-scopes |
| raylib-smallBasic | 4.1-dev | [SmallBASIC](https://github.com/smallbasic/SmallBASIC) | GPLv3 | https://github.com/smallbasic/smallbasic.plugins/tree/master/raylib | | raylib-SmallBASIC | 5.0 | [SmallBASIC](https://github.com/smallbasic/SmallBASIC) | GPLv3 | https://github.com/smallbasic/smallbasic.plugins/tree/master/raylib |
| raylib-umka | **4.5** | [Umka](https://github.com/vtereshkov/umka-lang) | Zlib | https://github.com/robloach/raylib-umka | | raylib-umka | **4.5** | [Umka](https://github.com/vtereshkov/umka-lang) | Zlib | https://github.com/robloach/raylib-umka |
| raylib.v | 4.2 | [V](https://vlang.io/) | Zlib | https://github.com/irishgreencitrus/raylib.v | | raylib.v | 4.2 | [V](https://vlang.io/) | Zlib | https://github.com/irishgreencitrus/raylib.v |
| raylib-vapi | 4.2 | [Vala](https://vala.dev/) | Zlib | https://github.com/lxmcf/raylib-vapi | | raylib-vapi | 4.2 | [Vala](https://vala.dev/) | Zlib | https://github.com/lxmcf/raylib-vapi |
@ -83,12 +84,13 @@ Some people ported raylib to other languages in form of bindings or wrappers to
| rayjs | 4.6-dev | [QuickJS](https://bellard.org/quickjs/) | MIT | https://github.com/mode777/rayjs | | rayjs | 4.6-dev | [QuickJS](https://bellard.org/quickjs/) | MIT | https://github.com/mode777/rayjs |
| raylib-raku | **auto** | [Raku](https://www.raku.org/) | Artistic License 2.0 | https://github.com/vushu/raylib-raku | | raylib-raku | **auto** | [Raku](https://www.raku.org/) | Artistic License 2.0 | https://github.com/vushu/raylib-raku |
| Raylib.lean | 4.5 | [Lean4](https://lean-lang.org/) | BSD-3-Clause | https://github.com/KislyjKisel/Raylib.lean | | Raylib.lean | 4.5 | [Lean4](https://lean-lang.org/) | BSD-3-Clause | https://github.com/KislyjKisel/Raylib.lean |
| Raylib-CSharp-Vinculum | 5.0 | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MPL-2.0 | https://github.com/ZeroElectric/Raylib-CSharp-Vinculum |
### Utility Wrapers ### Utility Wrapers
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 pardigm. 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 pardigm.
| name | raylib version | language | license | repo | | name | raylib version | language | license | repo |
|:------------------:|:-------------: | :--------:|:-------:|:-------------------------------------------------------------| |:------------------:|:-------------: | :--------:|:-------:|:-------------------------------------------------------------|
| raylib-cpp | **4.5** | [C++](https://en.wikipedia.org/wiki/C%2B%2B) | Zlib | https://github.com/robloach/raylib-cpp | | raylib-cpp | **5.0** | [C++](https://en.wikipedia.org/wiki/C%2B%2B) | Zlib | https://github.com/robloach/raylib-cpp |
| claylib | **4.5** | [Common Lisp](https://common-lisp.net/) | Zlib | https://github.com/defun-games/claylib | | claylib | **4.5** | [Common Lisp](https://common-lisp.net/) | Zlib | https://github.com/defun-games/claylib |
### Older or Unmaintained Language Bindings ### Older or Unmaintained Language Bindings

View File

@ -1,8 +1,8 @@
cmake_minimum_required(VERSION 3.0) cmake_minimum_required(VERSION 3.5)
project(raylib) project(raylib)
# Avoid excessive expansion of variables in conditionals. In particular, if # Avoid excessive expansion of variables in conditionals. In particular, if
# "PLATFORM" is "DRM" than: # "PLATFORM" is "DRM" then:
# #
# if (${PLATFORM} MATCHES "DRM") # if (${PLATFORM} MATCHES "DRM")
# #
@ -13,6 +13,11 @@ project(raylib)
# See https://cmake.org/cmake/help/latest/policy/CMP0054.html # See https://cmake.org/cmake/help/latest/policy/CMP0054.html
cmake_policy(SET CMP0054 NEW) cmake_policy(SET CMP0054 NEW)
# Makes a hidden visibility preset on a static lib respected
# This is used to hide glfw's symbols from the library exports when building an so/dylib
# See https://cmake.org/cmake/help/latest/policy/CMP0063.html
cmake_policy(SET CMP0063 NEW)
# Directory for easier includes # Directory for easier includes
# Anywhere you see include(...) you can check <root>/cmake for that file # Anywhere you see include(...) you can check <root>/cmake for that file
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)

View File

@ -17,14 +17,15 @@ if(NOT glfw3_FOUND AND NOT USE_EXTERNAL_GLFW STREQUAL "ON" AND "${PLATFORM}" MAT
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
set(GLFW_INSTALL OFF CACHE BOOL "" FORCE) set(GLFW_INSTALL OFF CACHE BOOL "" FORCE)
set(GLFW_USE_WAYLAND ${USE_WAYLAND} CACHE BOOL "" FORCE) set(GLFW_USE_WAYLAND ${USE_WAYLAND} CACHE BOOL "" FORCE)
set(GLFW_LIBRARY_TYPE "OBJECT" CACHE STRING "" FORCE)
set(WAS_SHARED ${BUILD_SHARED_LIBS})
set(BUILD_SHARED_LIBS OFF CACHE BOOL " " FORCE)
add_subdirectory(external/glfw) add_subdirectory(external/glfw)
set(BUILD_SHARED_LIBS ${WAS_SHARED} CACHE BOOL " " FORCE) # Hide glfw's symbols when building a shared lib
unset(WAS_SHARED) if (BUILD_SHARED_LIBS)
set_property(TARGET glfw PROPERTY C_VISIBILITY_PRESET hidden)
endif()
list(APPEND raylib_sources $<TARGET_OBJECTS:glfw>) list(APPEND raylib_sources $<TARGET_OBJECTS:glfw>)
include_directories(BEFORE SYSTEM external/glfw/include) include_directories(BEFORE SYSTEM external/glfw/include)

View File

@ -490,6 +490,7 @@ TEXTURES = \
textures/textures_gif_player \ textures/textures_gif_player \
textures/textures_image_drawing \ textures/textures_image_drawing \
textures/textures_image_generation \ textures/textures_image_generation \
textures/textures_image_kernel \
textures/textures_image_loading \ textures/textures_image_loading \
textures/textures_image_processing \ textures/textures_image_processing \
textures/textures_image_rotate \ textures/textures_image_rotate \

View File

@ -396,6 +396,7 @@ TEXTURES = \
textures/textures_gif_player \ textures/textures_gif_player \
textures/textures_image_drawing \ textures/textures_image_drawing \
textures/textures_image_generation \ textures/textures_image_generation \
textures/textures_image_kernel \
textures/textures_image_loading \ textures/textures_image_loading \
textures/textures_image_processing \ textures/textures_image_processing \
textures/textures_image_rotate \ textures/textures_image_rotate \
@ -703,6 +704,10 @@ textures/textures_image_drawing: textures/textures_image_drawing.c
textures/textures_image_generation: textures/textures_image_generation.c textures/textures_image_generation: textures/textures_image_generation.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) -s TOTAL_MEMORY=67108864 $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) -s TOTAL_MEMORY=67108864
textures/textures_image_kernel: textures/textures_image_kernel.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file textures/resources/cat.png@resources/cat.png
textures/textures_image_loading: textures/textures_image_loading.c textures/textures_image_loading: textures/textures_image_loading.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file textures/resources/raylib_logo.png@resources/raylib_logo.png --preload-file textures/resources/raylib_logo.png@resources/raylib_logo.png
@ -968,10 +973,10 @@ shaders/shaders_julia_set: shaders/shaders_julia_set.c
shaders/shaders_lightmap: shaders/shaders_lightmap.c shaders/shaders_lightmap: shaders/shaders_lightmap.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) -s FORCE_FILESYSTEM=1 \ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) -s FORCE_FILESYSTEM=1 \
--preload-file shaders/resources/shaders/glsl330/lightmap.vs \ --preload-file shaders/resources/shaders/glsl100/lightmap.vs@resources/shaders/glsl100/lightmap.vs \
--preload-file shaders/resources/shaders/glsl330/lightmap.fs \ --preload-file shaders/resources/shaders/glsl100/lightmap.fs@resources/shaders/glsl100/lightmap.fs \
--preload-file shaders/resources/cubicmap_atlas.png \ --preload-file shaders/resources/cubicmap_atlas.png@resources/cubicmap_atlas.png \
--preload-file shaders/resources/spark_flame.png --preload-file shaders/resources/spark_flame.png@resources/spark_flame.png
shaders/shaders_mesh_instancing: shaders/shaders_mesh_instancing.c shaders/shaders_mesh_instancing: shaders/shaders_mesh_instancing.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \

View File

@ -38,8 +38,7 @@ float sineIdx = 0.0f;
void AudioInputCallback(void *buffer, unsigned int frames) void AudioInputCallback(void *buffer, unsigned int frames)
{ {
audioFrequency = frequency + (audioFrequency - frequency)*0.95f; audioFrequency = frequency + (audioFrequency - frequency)*0.95f;
audioFrequency += 1.0f;
audioFrequency -= 1.0f;
float incr = audioFrequency/44100.0f; float incr = audioFrequency/44100.0f;
short *d = (short *)buffer; short *d = (short *)buffer;

View File

@ -2,7 +2,7 @@
* *
* raylib [audio] example - Music stream processing effects * raylib [audio] example - Music stream processing effects
* *
* Example originally created with raylib 4.2, last time updated with raylib 4.2 * Example originally created with raylib 4.2, last time updated with raylib 5.0
* *
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software * BSD-like license that allows static linking with closed source software
@ -13,7 +13,7 @@
#include "raylib.h" #include "raylib.h"
#include <stdlib.h> // Required for: NULL #include <stdlib.h> // Required for: NULL
// Required delay effect variables // Required delay effect variables
static float *delayBuffer = NULL; static float *delayBuffer = NULL;
@ -149,13 +149,17 @@ static void AudioProcessEffectLPF(void *buffer, unsigned int frames)
static const float cutoff = 70.0f / 44100.0f; // 70 Hz lowpass filter static const float cutoff = 70.0f / 44100.0f; // 70 Hz lowpass filter
const float k = cutoff / (cutoff + 0.1591549431f); // RC filter formula const float k = cutoff / (cutoff + 0.1591549431f); // RC filter formula
// Converts the buffer data before using it
float *bufferData = (float *)buffer;
for (unsigned int i = 0; i < frames*2; i += 2) for (unsigned int i = 0; i < frames*2; i += 2)
{ {
float l = ((float *)buffer)[i], r = ((float *)buffer)[i + 1]; const float l = bufferData[i];
const float r = bufferData[i + 1];
low[0] += k * (l - low[0]); low[0] += k * (l - low[0]);
low[1] += k * (r - low[1]); low[1] += k * (r - low[1]);
((float *)buffer)[i] = low[0]; bufferData[i] = low[0];
((float *)buffer)[i + 1] = low[1]; bufferData[i + 1] = low[1];
} }
} }

View File

@ -39,7 +39,6 @@ int main(void)
.vResolution = 1200, // Vertical resolution in pixels .vResolution = 1200, // Vertical resolution in pixels
.hScreenSize = 0.133793f, // Horizontal size in meters .hScreenSize = 0.133793f, // Horizontal size in meters
.vScreenSize = 0.0669f, // Vertical size in meters .vScreenSize = 0.0669f, // Vertical size in meters
.vScreenCenter = 0.04678f, // Screen center in meters
.eyeToScreenDistance = 0.041f, // Distance between eye and display in meters .eyeToScreenDistance = 0.041f, // Distance between eye and display in meters
.lensSeparationDistance = 0.07f, // Lens separation distance in meters .lensSeparationDistance = 0.07f, // Lens separation distance in meters
.interpupillaryDistance = 0.07f, // IPD (distance between pupils) in meters .interpupillaryDistance = 0.07f, // IPD (distance between pupils) in meters

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 623 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 657 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 645 KiB

View File

@ -0,0 +1,22 @@
#version 100
precision mediump float;
// Input vertex attributes (from vertex shader)
varying vec2 fragTexCoord;
varying vec2 fragTexCoord2;
varying vec3 fragPosition;
varying vec4 fragColor;
// Input uniform values
uniform sampler2D texture0;
uniform sampler2D texture1;
void main()
{
// Texel color fetching from texture sampler
vec4 texelColor = texture2D(texture0, fragTexCoord);
vec4 texelColor2 = texture2D(texture1, fragTexCoord2);
gl_FragColor = texelColor * texelColor2;
}

View File

@ -0,0 +1,31 @@
#version 100
// Input vertex attributes
attribute vec3 vertexPosition;
attribute vec2 vertexTexCoord;
attribute vec2 vertexTexCoord2;
attribute vec4 vertexColor;
// Input uniform values
uniform mat4 mvp;
uniform mat4 matModel;
// Output vertex attributes (to fragment shader)
varying vec3 fragPosition;
varying vec2 fragTexCoord;
varying vec2 fragTexCoord2;
varying vec4 fragColor;
// NOTE: Add here your custom variables
void main()
{
// Send vertex attributes to fragment shader
fragPosition = vec3(matModel*vec4(vertexPosition, 1.0));
fragTexCoord = vertexTexCoord;
fragTexCoord2 = vertexTexCoord2;
fragColor = vertexColor;
// Calculate final vertex position
gl_Position = mvp*vec4(vertexPosition, 1.0);
}

View File

@ -0,0 +1,156 @@
#version 100
precision mediump float;
#define MAX_LIGHTS 4
#define LIGHT_DIRECTIONAL 0
#define LIGHT_POINT 1
#define PI 3.14159265358979323846
struct Light {
int enabled;
int type;
vec3 position;
vec3 target;
vec4 color;
float intensity;
};
// Input vertex attributes (from vertex shader)
varying in vec3 fragPosition;
varying in vec2 fragTexCoord;
varying in vec4 fragColor;
varying in vec3 fragNormal;
varying in vec4 shadowPos;
varying in mat3 TBN;
// Input uniform values
uniform int numOfLights;
uniform sampler2D albedoMap;
uniform sampler2D mraMap;
uniform sampler2D normalMap;
uniform sampler2D emissiveMap; // r: Hight g:emissive
uniform vec2 tiling;
uniform vec2 offset;
uniform int useTexAlbedo;
uniform int useTexNormal;
uniform int useTexMRA;
uniform int useTexEmissive;
uniform vec4 albedoColor;
uniform vec4 emissiveColor;
uniform float normalValue;
uniform float metallicValue;
uniform float roughnessValue;
uniform float aoValue;
uniform float emissivePower;
// Input lighting values
uniform Light lights[MAX_LIGHTS];
uniform vec3 viewPos;
uniform vec3 ambientColor;
uniform float ambient;
// refl in range 0 to 1
// returns base reflectivity to 1
// incrase reflectivity when surface view at larger angle
vec3 schlickFresnel(float hDotV,vec3 refl)
{
return refl + (1.0 - refl) * pow(1.0 - hDotV,5.0);
}
float ggxDistribution(float nDotH,float roughness)
{
float a = roughness * roughness * roughness * roughness;
float d = nDotH * nDotH * (a - 1.0) + 1.0;
d = PI * d * d;
return a / max(d,0.0000001);
}
float geomSmith(float nDotV,float nDotL,float roughness)
{
float r = roughness + 1.0;
float k = r * r / 8.0;
float ik = 1.0 - k;
float ggx1 = nDotV / (nDotV * ik + k);
float ggx2 = nDotL / (nDotL * ik + k);
return ggx1 * ggx2;
}
vec3 pbr(){
vec3 albedo = texture2D(albedoMap,vec2(fragTexCoord.x*tiling.x+offset.x,fragTexCoord.y*tiling.y+offset.y)).rgb;
albedo = vec3(albedoColor.x*albedo.x,albedoColor.y*albedo.y,albedoColor.z*albedo.z);
float metallic = clamp(metallicValue,0.0,1.0);
float roughness = clamp(roughnessValue,0.0,1.0);
float ao = clamp(aoValue,0.0,1.0);
if(useTexMRA == 1) {
vec4 mra = texture2D(mraMap, vec2(fragTexCoord.x * tiling.x + offset.x, fragTexCoord.y * tiling.y + offset.y));
metallic = clamp(mra.r+metallicValue,0.04,1.0);
roughness = clamp(mra.g+roughnessValue,0.04,1.0);
ao = (mra.b+aoValue)*0.5;
}
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 = normalize(N * 2.0 - 1.0);
N = normalize(N * TBN);
}
vec3 V = normalize(viewPos - fragPosition);
vec3 e = vec3(0);
e = (texture2D(emissiveMap, vec2(fragTexCoord.x*tiling.x+offset.x, fragTexCoord.y*tiling.y+offset.y)).rgb).g * emissiveColor.rgb*emissivePower * float(useTexEmissive);
//return N;//vec3(metallic,metallic,metallic);
//if dia-electric use base reflectivity of 0.04 otherwise ut is a metal use albedo as base reflectivity
vec3 baseRefl = mix(vec3(0.04),albedo.rgb,metallic);
vec3 Lo = vec3(0.0); // acumulate lighting lum
for(int i=0;i<numOfLights;++i){
vec3 L = normalize(lights[i].position - fragPosition); // calc light vector
vec3 H = normalize(V + L); // calc halfway bisecting vector
float dist = length(lights[i].position - fragPosition); // calc distance to light
float attenuation = 1.0 / (dist * dist * 0.23); // calc attenuation
vec3 radiance = lights[i].color.rgb * lights[i].intensity * attenuation; // calc input radiance,light energy comming in
//Cook-Torrance BRDF distribution function
float nDotV = max(dot(N,V),0.0000001);
float nDotL = max(dot(N,L),0.0000001);
float hDotV = max(dot(H,V),0.0);
float nDotH = max(dot(N,H),0.0);
float D = ggxDistribution(nDotH,roughness); // larger the more micro-facets aligned to H
float G = geomSmith(nDotV,nDotL,roughness); // smaller the more micro-facets shadow
vec3 F = schlickFresnel(hDotV, baseRefl); // fresnel proportion of specular reflectance
vec3 spec = (D * G * F) / (4.0 * nDotV * nDotL);
// difuse and spec light can't be above 1.0
// kD = 1.0 - kS diffuse component is equal 1.0 - spec comonent
vec3 kD = vec3(1.0) - F;
//mult kD by the inverse of metallnes , only non-metals should have diffuse light
kD *= 1.0 - metallic;
Lo += ((kD * albedo.rgb / PI + spec) * radiance * nDotL)*float(lights[i].enabled); // angle of light has impact on result
}
vec3 ambient_final = (ambientColor + albedo)* ambient * 0.5;
return ambient_final+Lo*ao+e;
}
void main()
{
vec3 color = pbr();
//HDR tonemapping
color = pow(color,color + vec3(1.0));
//gamma correction
color = pow(color,vec3(1.0/2.2));
gl_FragColor = vec4(color,1.0);
}

View File

@ -0,0 +1,75 @@
#version 100
// Input vertex attributes
attribute vec3 vertexPosition;
attribute vec2 vertexTexCoord;
attribute vec3 vertexNormal;
attribute vec3 vertexTangent;
attribute vec4 vertexColor;
// Input uniform values
uniform mat4 mvp;
uniform mat4 matModel;
uniform mat4 matNormal;
uniform vec3 lightPos;
uniform vec4 difColor;
// Output vertex attributes (to fragment shader)
varying vec3 fragPosition;
varying vec2 fragTexCoord;
varying vec4 fragColor;
varying vec3 fragNormal;
varying mat3 TBN;
const float normalOffset = 0.1;
// https://github.com/glslify/glsl-inverse
mat3 inverse(mat3 m)
{
float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];
float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];
float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];
float b01 = a22*a11 - a12*a21;
float b11 = -a22*a10 + a12*a20;
float b21 = a21*a10 - a11*a20;
float det = a00*b01 + a01*b11 + a02*b21;
return mat3(b01, (-a22*a01 + a02*a21), (a12*a01 - a02*a11),
b11, (a22*a00 - a02*a20), (-a12*a00 + a02*a10),
b21, (-a21*a00 + a01*a20), (a11*a00 - a01*a10))/det;
}
// https://github.com/glslify/glsl-transpose
mat3 transpose(mat3 m)
{
return mat3(m[0][0], m[1][0], m[2][0],
m[0][1], m[1][1], m[2][1],
m[0][2], m[1][2], m[2][2]);
}
void main()
{
// calc binormal from vertex normal and tangent
vec3 vertexBinormal = cross(vertexNormal, vertexTangent);
// calc fragment normal based on normal transformations
mat3 normalMatrix = transpose(inverse(mat3(matModel)));
// calc fragment position based on model transformations
fragPosition = vec3(matModel*vec4(vertexPosition, 1.0));
fragTexCoord = vertexTexCoord*2.0;
fragNormal = normalize(normalMatrix*vertexNormal);
vec3 fragTangent = normalize(normalMatrix*vertexTangent);
fragTangent = normalize(fragTangent - dot(fragTangent, fragNormal)*fragNormal);
vec3 fragBinormal = normalize(normalMatrix*vertexBinormal);
fragBinormal = cross(fragNormal, fragTangent);
TBN = transpose(mat3(fragTangent, fragBinormal, fragNormal));
// Calculate final vertex position
gl_Position = mvp * vec4(vertexPosition, 1.0);
}

View File

@ -0,0 +1,20 @@
#version 120
// Input vertex attributes (from vertex shader)
varying vec2 fragTexCoord;
varying vec2 fragTexCoord2;
varying vec3 fragPosition;
varying vec4 fragColor;
// Input uniform values
uniform sampler2D texture0;
uniform sampler2D texture1;
void main()
{
// Texel color fetching from texture sampler
vec4 texelColor = texture2D(texture0, fragTexCoord);
vec4 texelColor2 = texture2D(texture1, fragTexCoord2);
gl_FragColor = texelColor * texelColor2;
}

View File

@ -0,0 +1,31 @@
#version 120
// Input vertex attributes
attribute vec3 vertexPosition;
attribute vec2 vertexTexCoord;
attribute vec2 vertexTexCoord2;
attribute vec4 vertexColor;
// Input uniform values
uniform mat4 mvp;
uniform mat4 matModel;
// Output vertex attributes (to fragment shader)
varying vec3 fragPosition;
varying vec2 fragTexCoord;
varying vec2 fragTexCoord2;
varying vec4 fragColor;
// NOTE: Add here your custom variables
void main()
{
// Send vertex attributes to fragment shader
fragPosition = vec3(matModel*vec4(vertexPosition, 1.0));
fragTexCoord = vertexTexCoord;
fragTexCoord2 = vertexTexCoord2;
fragColor = vertexColor;
// Calculate final vertex position
gl_Position = mvp*vec4(vertexPosition, 1.0);
}

View File

@ -0,0 +1,156 @@
#version 120
precision mediump float;
#define MAX_LIGHTS 4
#define LIGHT_DIRECTIONAL 0
#define LIGHT_POINT 1
#define PI 3.14159265358979323846
struct Light {
int enabled;
int type;
vec3 position;
vec3 target;
vec4 color;
float intensity;
};
// Input vertex attributes (from vertex shader)
varying in vec3 fragPosition;
varying in vec2 fragTexCoord;
varying in vec4 fragColor;
varying in vec3 fragNormal;
varying in vec4 shadowPos;
varying in mat3 TBN;
// Input uniform values
uniform int numOfLights;
uniform sampler2D albedoMap;
uniform sampler2D mraMap;
uniform sampler2D normalMap;
uniform sampler2D emissiveMap; // r: Hight g:emissive
uniform vec2 tiling;
uniform vec2 offset;
uniform int useTexAlbedo;
uniform int useTexNormal;
uniform int useTexMRA;
uniform int useTexEmissive;
uniform vec4 albedoColor;
uniform vec4 emissiveColor;
uniform float normalValue;
uniform float metallicValue;
uniform float roughnessValue;
uniform float aoValue;
uniform float emissivePower;
// Input lighting values
uniform Light lights[MAX_LIGHTS];
uniform vec3 viewPos;
uniform vec3 ambientColor;
uniform float ambient;
// refl in range 0 to 1
// returns base reflectivity to 1
// incrase reflectivity when surface view at larger angle
vec3 schlickFresnel(float hDotV,vec3 refl)
{
return refl + (1.0 - refl) * pow(1.0 - hDotV,5.0);
}
float ggxDistribution(float nDotH,float roughness)
{
float a = roughness * roughness * roughness * roughness;
float d = nDotH * nDotH * (a - 1.0) + 1.0;
d = PI * d * d;
return a / max(d,0.0000001);
}
float geomSmith(float nDotV,float nDotL,float roughness)
{
float r = roughness + 1.0;
float k = r * r / 8.0;
float ik = 1.0 - k;
float ggx1 = nDotV / (nDotV * ik + k);
float ggx2 = nDotL / (nDotL * ik + k);
return ggx1 * ggx2;
}
vec3 pbr(){
vec3 albedo = texture2D(albedoMap,vec2(fragTexCoord.x*tiling.x+offset.x,fragTexCoord.y*tiling.y+offset.y)).rgb;
albedo = vec3(albedoColor.x*albedo.x,albedoColor.y*albedo.y,albedoColor.z*albedo.z);
float metallic = clamp(metallicValue,0.0,1.0);
float roughness = clamp(roughnessValue,0.0,1.0);
float ao = clamp(aoValue,0.0,1.0);
if(useTexMRA == 1) {
vec4 mra = texture2D(mraMap, vec2(fragTexCoord.x * tiling.x + offset.x, fragTexCoord.y * tiling.y + offset.y));
metallic = clamp(mra.r+metallicValue,0.04,1.0);
roughness = clamp(mra.g+roughnessValue,0.04,1.0);
ao = (mra.b+aoValue)*0.5;
}
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 = normalize(N * 2.0 - 1.0);
N = normalize(N * TBN);
}
vec3 V = normalize(viewPos - fragPosition);
vec3 e = vec3(0);
e = (texture2D(emissiveMap, vec2(fragTexCoord.x*tiling.x+offset.x, fragTexCoord.y*tiling.y+offset.y)).rgb).g * emissiveColor.rgb*emissivePower * float(useTexEmissive);
//return N;//vec3(metallic,metallic,metallic);
//if dia-electric use base reflectivity of 0.04 otherwise ut is a metal use albedo as base reflectivity
vec3 baseRefl = mix(vec3(0.04),albedo.rgb,metallic);
vec3 Lo = vec3(0.0); // acumulate lighting lum
for(int i=0;i<numOfLights;++i){
vec3 L = normalize(lights[i].position - fragPosition); // calc light vector
vec3 H = normalize(V + L); // calc halfway bisecting vector
float dist = length(lights[i].position - fragPosition); // calc distance to light
float attenuation = 1.0 / (dist * dist * 0.23); // calc attenuation
vec3 radiance = lights[i].color.rgb * lights[i].intensity * attenuation; // calc input radiance,light energy comming in
//Cook-Torrance BRDF distribution function
float nDotV = max(dot(N,V),0.0000001);
float nDotL = max(dot(N,L),0.0000001);
float hDotV = max(dot(H,V),0.0);
float nDotH = max(dot(N,H),0.0);
float D = ggxDistribution(nDotH,roughness); // larger the more micro-facets aligned to H
float G = geomSmith(nDotV,nDotL,roughness); // smaller the more micro-facets shadow
vec3 F = schlickFresnel(hDotV, baseRefl); // fresnel proportion of specular reflectance
vec3 spec = (D * G * F) / (4.0 * nDotV * nDotL);
// difuse and spec light can't be above 1.0
// kD = 1.0 - kS diffuse component is equal 1.0 - spec comonent
vec3 kD = vec3(1.0) - F;
//mult kD by the inverse of metallnes , only non-metals should have diffuse light
kD *= 1.0 - metallic;
Lo += ((kD * albedo.rgb / PI + spec) * radiance * nDotL)*float(lights[i].enabled); // angle of light has impact on result
}
vec3 ambient_final = (ambientColor + albedo)* ambient * 0.5;
return ambient_final+Lo*ao+e;
}
void main()
{
vec3 color = pbr();
//HDR tonemapping
color = pow(color,color + vec3(1.0));
//gamma correction
color = pow(color,vec3(1.0/2.2));
gl_FragColor = vec4(color,1.0);
}

View File

@ -0,0 +1,75 @@
#version 120
// Input vertex attributes
attribute vec3 vertexPosition;
attribute vec2 vertexTexCoord;
attribute vec3 vertexNormal;
attribute vec3 vertexTangent;
attribute vec4 vertexColor;
// Input uniform values
uniform mat4 mvp;
uniform mat4 matModel;
uniform mat4 matNormal;
uniform vec3 lightPos;
uniform vec4 difColor;
// Output vertex attributes (to fragment shader)
varying vec3 fragPosition;
varying vec2 fragTexCoord;
varying vec4 fragColor;
varying vec3 fragNormal;
varying mat3 TBN;
const float normalOffset = 0.1;
// https://github.com/glslify/glsl-inverse
mat3 inverse(mat3 m)
{
float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];
float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];
float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];
float b01 = a22*a11 - a12*a21;
float b11 = -a22*a10 + a12*a20;
float b21 = a21*a10 - a11*a20;
float det = a00*b01 + a01*b11 + a02*b21;
return mat3(b01, (-a22*a01 + a02*a21), (a12*a01 - a02*a11),
b11, (a22*a00 - a02*a20), (-a12*a00 + a02*a10),
b21, (-a21*a00 + a01*a20), (a11*a00 - a01*a10))/det;
}
// https://github.com/glslify/glsl-transpose
mat3 transpose(mat3 m)
{
return mat3(m[0][0], m[1][0], m[2][0],
m[0][1], m[1][1], m[2][1],
m[0][2], m[1][2], m[2][2]);
}
void main()
{
// calc binormal from vertex normal and tangent
vec3 vertexBinormal = cross(vertexNormal, vertexTangent);
// calc fragment normal based on normal transformations
mat3 normalMatrix = transpose(inverse(mat3(matModel)));
// calc fragment position based on model transformations
fragPosition = vec3(matModel*vec4(vertexPosition, 1.0));
fragTexCoord = vertexTexCoord*2.0;
fragNormal = normalize(normalMatrix*vertexNormal);
vec3 fragTangent = normalize(normalMatrix*vertexTangent);
fragTangent = normalize(fragTangent - dot(fragTangent, fragNormal)*fragNormal);
vec3 fragBinormal = normalize(normalMatrix*vertexBinormal);
fragBinormal = cross(fragNormal, fragTangent);
TBN = transpose(mat3(fragTangent, fragBinormal, fragNormal));
// Calculate final vertex position
gl_Position = mvp * vec4(vertexPosition, 1.0);
}

View File

@ -0,0 +1,159 @@
#version 330
#define MAX_LIGHTS 4
#define LIGHT_DIRECTIONAL 0
#define LIGHT_POINT 1
#define PI 3.14159265358979323846
struct Light {
int enabled;
int type;
vec3 position;
vec3 target;
vec4 color;
float intensity;
};
// Input vertex attributes (from vertex shader)
in vec3 fragPosition;
in vec2 fragTexCoord;
in vec4 fragColor;
in vec3 fragNormal;
in vec4 shadowPos;
in mat3 TBN;
// Output fragment color
out vec4 finalColor;
// Input uniform values
uniform int numOfLights;
uniform sampler2D albedoMap;
uniform sampler2D mraMap;
uniform sampler2D normalMap;
uniform sampler2D emissiveMap; // r: Hight g:emissive
uniform vec2 tiling;
uniform vec2 offset;
uniform int useTexAlbedo;
uniform int useTexNormal;
uniform int useTexMRA;
uniform int useTexEmissive;
uniform vec4 albedoColor;
uniform vec4 emissiveColor;
uniform float normalValue;
uniform float metallicValue;
uniform float roughnessValue;
uniform float aoValue;
uniform float emissivePower;
// Input lighting values
uniform Light lights[MAX_LIGHTS];
uniform vec3 viewPos;
uniform vec3 ambientColor;
uniform float ambient;
// refl in range 0 to 1
// returns base reflectivity to 1
// incrase reflectivity when surface view at larger angle
vec3 schlickFresnel(float hDotV,vec3 refl)
{
return refl + (1.0 - refl) * pow(1.0 - hDotV,5.0);
}
float ggxDistribution(float nDotH,float roughness)
{
float a = roughness * roughness * roughness * roughness;
float d = nDotH * nDotH * (a - 1.0) + 1.0;
d = PI * d * d;
return a / max(d,0.0000001);
}
float geomSmith(float nDotV,float nDotL,float roughness)
{
float r = roughness + 1.0;
float k = r * r / 8.0;
float ik = 1.0 - k;
float ggx1 = nDotV / (nDotV * ik + k);
float ggx2 = nDotL / (nDotL * ik + k);
return ggx1 * ggx2;
}
vec3 pbr(){
vec3 albedo = texture(albedoMap,vec2(fragTexCoord.x*tiling.x+offset.x,fragTexCoord.y*tiling.y+offset.y)).rgb;
albedo = vec3(albedoColor.x*albedo.x,albedoColor.y*albedo.y,albedoColor.z*albedo.z);
float metallic = clamp(metallicValue,0.0,1.0);
float roughness = clamp(roughnessValue,0.0,1.0);
float ao = clamp(aoValue,0.0,1.0);
if(useTexMRA == 1) {
vec4 mra = texture(mraMap, vec2(fragTexCoord.x * tiling.x + offset.x, fragTexCoord.y * tiling.y + offset.y)) * useTexMRA;
metallic = clamp(mra.r+metallicValue,0.04,1.0);
roughness = clamp(mra.g+roughnessValue,0.04,1.0);
ao = (mra.b+aoValue)*0.5;
}
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 = normalize(N * 2.0 - 1.0);
N = normalize(N * TBN);
}
vec3 V = normalize(viewPos - fragPosition);
vec3 e = vec3(0);
e = (texture(emissiveMap, vec2(fragTexCoord.x*tiling.x+offset.x, fragTexCoord.y*tiling.y+offset.y)).rgb).g * emissiveColor.rgb*emissivePower * useTexEmissive;
//return N;//vec3(metallic,metallic,metallic);
//if dia-electric use base reflectivity of 0.04 otherwise ut is a metal use albedo as base reflectivity
vec3 baseRefl = mix(vec3(0.04),albedo.rgb,metallic);
vec3 Lo = vec3(0.0); // acumulate lighting lum
for(int i=0;i<numOfLights;++i){
vec3 L = normalize(lights[i].position - fragPosition); // calc light vector
vec3 H = normalize(V + L); // calc halfway bisecting vector
float dist = length(lights[i].position - fragPosition); // calc distance to light
float attenuation = 1.0 / (dist * dist * 0.23); // calc attenuation
vec3 radiance = lights[i].color.rgb * lights[i].intensity * attenuation; // calc input radiance,light energy comming in
//Cook-Torrance BRDF distribution function
float nDotV = max(dot(N,V),0.0000001);
float nDotL = max(dot(N,L),0.0000001);
float hDotV = max(dot(H,V),0.0);
float nDotH = max(dot(N,H),0.0);
float D = ggxDistribution(nDotH,roughness); // larger the more micro-facets aligned to H
float G = geomSmith(nDotV,nDotL,roughness); // smaller the more micro-facets shadow
vec3 F = schlickFresnel(hDotV, baseRefl); // fresnel proportion of specular reflectance
vec3 spec = (D * G * F) / (4.0 * nDotV * nDotL);
// difuse and spec light can't be above 1.0
// kD = 1.0 - kS diffuse component is equal 1.0 - spec comonent
vec3 kD = vec3(1.0) - F;
//mult kD by the inverse of metallnes , only non-metals should have diffuse light
kD *= 1.0 - metallic;
Lo += ((kD * albedo.rgb / PI + spec) * radiance * nDotL)*lights[i].enabled; // angle of light has impact on result
}
vec3 ambient_final = (ambientColor + albedo)* ambient * 0.5;
return ambient_final+Lo*ao+e;
}
void main()
{
vec3 color = pbr();
//HDR tonemapping
color = pow(color,color + vec3(1.0));
//gamma correction
color = pow(color,vec3(1.0/2.2));
finalColor = vec4(color,1.0);
}

View File

@ -0,0 +1,49 @@
#version 330
// Input vertex attributes
in vec3 vertexPosition;
in vec2 vertexTexCoord;
in vec3 vertexNormal;
in vec3 vertexTangent;
in vec4 vertexColor;
// Input uniform values
uniform mat4 mvp;
uniform mat4 matModel;
uniform mat4 matNormal;
uniform vec3 lightPos;
uniform vec4 difColor;
// Output vertex attributes (to fragment shader)
out vec3 fragPosition;
out vec2 fragTexCoord;
out vec4 fragColor;
out vec3 fragNormal;
out mat3 TBN;
const float normalOffset = 0.1;
void main()
{
// calc binormal from vertex normal and tangent
vec3 vertexBinormal = cross(vertexNormal, vertexTangent);
// calc fragment normal based on normal transformations
mat3 normalMatrix = transpose(inverse(mat3(matModel)));
// calc fragment position based on model transformations
fragPosition = vec3(matModel*vec4(vertexPosition, 1.0f));
fragTexCoord = vertexTexCoord*2.0;
fragNormal = normalize(normalMatrix*vertexNormal);
vec3 fragTangent = normalize(normalMatrix*vertexTangent);
fragTangent = normalize(fragTangent - dot(fragTangent, fragNormal)*fragNormal);
vec3 fragBinormal = normalize(normalMatrix*vertexBinormal);
fragBinormal = cross(fragNormal, fragTangent);
TBN = transpose(mat3(fragTangent, fragBinormal, fragNormal));
// Calculate final vertex position
gl_Position = mvp * vec4(vertexPosition, 1.0);
}

466
examples/shaders/rpbr.h Normal file
View File

@ -0,0 +1,466 @@
/**********************************************************************************************
*
* raylib.pbr - Some useful functions to deal with pbr materials and lights
*
* CONFIGURATION:
*
* #define RPBR_IMPLEMENTATION
* Generates the implementation of the library into the included file.
* If not defined, the library is in header only mode and can be included in other headers
* or source files without problems. But only ONE file should hold the implementation.
*
* LICENSE: zlib/libpng
*
* Copyright (c) 2023-2024 Afan OLOVCIC (@_DevDad) 2017-2020 Victor Fisac(@victorfisac),Ramon Santamaria (@raysan5)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
**********************************************************************************************/
#ifndef RPBR_H
#define RPBR_H
#include "raylib.h"
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
#define MAX_LIGHTS 4 // Max dynamic lights supported by shader
#define SHADER_LOC_MAP_MRA SHADER_LOC_MAP_METALNESS //METALLIC, ROUGHNESS and AO
#define SHADER_LOC_MAP_EMISSIVE SHADER_LOC_MAP_HEIGHT //EMISSIVE
#define MATERIAL_MAP_MRA MATERIAL_MAP_METALNESS
#define MATERIAL_MAP_EMISSIVE MATERIAL_MAP_HEIGHT
#define NULL 0
#define COLOR_TO_ARRAY(c)
typedef struct {
int enabled;
int type;
Vector3 position;
Vector3 target;
float color[4];
float intensity;
int enabledLoc;
int typeLoc;
int positionLoc;
int targetLoc;
int colorLoc;
int intensityLoc;
} PBRLight;
typedef enum {
LIGHT_DIRECTIONAL = 0,
LIGHT_POINT,
LIGHT_SPOT
} PBRLightType;
typedef struct{
Shader pbrShader;
Shader skyShader;
unsigned int cubemap;
unsigned int irradiance;
unsigned int prefilter;
unsigned int brdf;
int modelMatrixLoc;
int pbrViewLoc;
int skyViewLoc;
int skyResolutionLoc;
} PBREnvironment;
typedef enum{
PBR_COLOR_ALBEDO = 0,
PBR_COLOR_EMISSIVE
}PBRColorType;
typedef enum{
PBR_VEC2_TILING = 0,
PBR_VEC2_OFFSET
}PBRVec2Type;
typedef enum{
PBR_PARAM_NORMAL =0,
PBR_PARAM_METALLIC,
PBR_PARAM_ROUGHNESS,
PBR_PARAM_EMISSIVE,
PBR_PARAM_AO
}PBRFloatType;
typedef enum{
PBR_TEXTURE_ALBEDO = 0,
PBR_TEXTURE_NORMAL,
PBR_TEXTURE_MRA,
PBR_TEXTURE_EMISSIVE
}PBRTexType;
// Textures are moved to material from params to pack better and use less textures on the end
// texture MRAE 4Channel R: Metallic G: Roughness B: A: Ambient Occlusion
// texEmissive use just one channel, so we have 3 channels still to use if we need
typedef struct {
Shader pbrShader;
float albedo[4];
float normal;
float metallic;
float roughness;
float ao;
float emissive[4];
float ambient[3];
float emissivePower;
Texture2D texAlbedo;
Texture2D texNormal;
Texture2D texMRA;//r: Metallic g: Roughness b: AO a:Empty
Texture2D texEmissive; //Emissive Texture
// Using float4 to store tilling at 1st and 2nd position and offset at 3rd and 4th
float texTiling[2];
float texOffset[2];
int useTexAlbedo;
int useTexNormal;
int useTexMRA;
int useTexEmissive;
int albedoLoc;
int normalLoc;
int metallicLoc;
int roughnessLoc;
int aoLoc;
int emissiveColorLoc;
int emissivePowerLoc;
int texTilingLoc;
int texOffsetLoc;
int useTexAlbedoLoc;
int useTexNormalLoc;
int useTexMRAELoc;
int useTexEmissiveLoc;
} PBRMaterial;
typedef struct{
Model model;
PBRMaterial pbrMat;
}PBRModel;
#ifdef __cplusplus
extern "C" {
#endif
//----------------------------------------------------------------------------------
// Module Functions Declaration
//----------------------------------------------------------------------------------
// Create a light and get shader locations
PBRLight PBRLightCreate(int type, Vector3 position, Vector3 target, Color color,float intensity, Shader shader);
// Send light properties to shader
void PBRLightUpdate(Shader shader, PBRLight light);
//For now until we do real skylight
void PBRSetAmbient(Shader shader, Color color, float intensity);
PBRModel PBRModelLoad(const char *fileName);
PBRModel PBRModelLoadFromMesh(Mesh mesh);
void PBRLoadTextures(PBRMaterial *pbrMat,PBRTexType pbrTexType,const char *fileName);
void UnloadPBRMaterial(PBRMaterial pbrMat);
void PBRSetColor(PBRMaterial *pbrMat,PBRColorType pbrColorType,Color color);
void PBRSetVec2(PBRMaterial *pbrMat,PBRVec2Type type,Vector2 value);
void PBRSetFloat(PBRMaterial *pbrMat, PBRFloatType pbrParamType, float value);
void PBRMaterialSetup( PBRMaterial *pbrMat,Shader pbrShader, PBREnvironment* environment);
void PBRSetMaterial(PBRModel* model,PBRMaterial* pbrMat,int matIndex);
void PBRDrawModel(PBRModel pbrModel, Vector3 position, float scale);
#ifdef __cplusplus
}
#endif
#endif //RPBR_H
/***********************************************************************************
*
* RPBR IMPLEMENTATION
*
************************************************************************************/
#if defined(RPBR_IMPLEMENTATION)
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
static int lightsCount = 0; // Current amount of created lights
// Create a light and get shader locations
PBRLight PBRLightCreate(int type, Vector3 position, Vector3 target, Color color,float intensity, Shader shader)
{
PBRLight light = { 0 };
if (lightsCount < MAX_LIGHTS)
{
light.enabled = 1;
light.type = type;
light.position = position;
light.target = target;
light.color[0] = (float)color.r/(float)255;
light.color[1] = (float)color.g/(float)255;
light.color[2] = (float)color.b/(float)255;
light.color[3] = (float)color.a/(float)255;
light.intensity = intensity;
// NOTE: Lighting shader naming must be the provided ones
light.enabledLoc = GetShaderLocation(shader, TextFormat("lights[%i].enabled", lightsCount));
light.typeLoc = GetShaderLocation(shader, TextFormat("lights[%i].type", lightsCount));
light.positionLoc = GetShaderLocation(shader, TextFormat("lights[%i].position", lightsCount));
light.targetLoc = GetShaderLocation(shader, TextFormat("lights[%i].target", lightsCount));
light.colorLoc = GetShaderLocation(shader, TextFormat("lights[%i].color", lightsCount));
light.intensityLoc = GetShaderLocation(shader, TextFormat("lights[%i].intensity", lightsCount));
PBRLightUpdate(shader, light);
lightsCount++;
}
return light;
}
// Send light properties to shader
// NOTE: Light shader locations should be available
void PBRLightUpdate(Shader shader, PBRLight light)
{
SetShaderValue(shader, light.enabledLoc, &light.enabled, SHADER_UNIFORM_INT);
SetShaderValue(shader, light.typeLoc, &light.type, SHADER_UNIFORM_INT);
// Send to shader light position values
float position[3] = { light.position.x, light.position.y, light.position.z };
SetShaderValue(shader, light.positionLoc, position, SHADER_UNIFORM_VEC3);
// Send to shader light target position values
float target[3] = { light.target.x, light.target.y, light.target.z };
SetShaderValue(shader, light.targetLoc, target, SHADER_UNIFORM_VEC3);
SetShaderValue(shader, light.colorLoc, light.color, SHADER_UNIFORM_VEC4);
SetShaderValue(shader, light.intensityLoc, &light.intensity, SHADER_UNIFORM_FLOAT);
}
void PBRSetAmbient(Shader shader, Color color, float intensity){
float col[3] = {color.r/255,color.g/255,color.b/255};
SetShaderValue(shader, GetShaderLocation(shader, "ambientColor"), col, SHADER_UNIFORM_VEC3);
SetShaderValue(shader, GetShaderLocation(shader, "ambient"), &intensity, SHADER_UNIFORM_FLOAT);
}
void PBRMaterialSetup(PBRMaterial *pbrMat, Shader pbrShader, PBREnvironment* environment){
pbrMat->pbrShader = pbrShader;
pbrMat->texAlbedo = (Texture2D){0};
pbrMat->texNormal = (Texture2D){0};
pbrMat->texMRA = (Texture2D){0};
pbrMat->texEmissive = (Texture2D){0};
//PBRParam
pbrMat->albedo[0] = 1.0;
pbrMat->albedo[1] = 1.0;
pbrMat->albedo[2] = 1.0;
pbrMat->albedo[3] = 1.0;
pbrMat->metallic = 0;
pbrMat->roughness = 0;
pbrMat->ao = 1.0;
pbrMat->normal = 1;
pbrMat->emissive[0] = 0;
pbrMat->emissive[1] = 0;
pbrMat->emissive[2] = 0;
pbrMat->emissive[3] = 0;
pbrMat->texTiling[0] = 1.0;
pbrMat->texTiling[1] = 1.0;
pbrMat->texOffset[0] = 0.0;
pbrMat->texOffset[1] = 0.0;
pbrMat->emissivePower = 1.0;
// Set up PBR shader material locations
pbrMat->albedoLoc = GetShaderLocation(pbrMat->pbrShader, "albedoColor");
pbrMat->normalLoc = GetShaderLocation(pbrMat->pbrShader, "normalValue");
pbrMat->metallicLoc = GetShaderLocation(pbrMat->pbrShader, "metallicValue");
pbrMat->roughnessLoc = GetShaderLocation(pbrMat->pbrShader, "roughnessValue");
pbrMat->aoLoc = GetShaderLocation(pbrMat->pbrShader, "aoValue");
pbrMat->emissiveColorLoc = GetShaderLocation(pbrMat->pbrShader, "emissiveColor");
pbrMat->emissivePowerLoc = GetShaderLocation(pbrMat->pbrShader, "emissivePower");
pbrMat->texTilingLoc = GetShaderLocation(pbrMat->pbrShader, "tiling");
pbrMat->texOffsetLoc = GetShaderLocation(pbrMat->pbrShader, "offset");
pbrMat->useTexAlbedoLoc = GetShaderLocation(pbrMat->pbrShader, "useTexAlbedo");
pbrMat->useTexNormalLoc = GetShaderLocation(pbrMat->pbrShader, "useTexNormal");
pbrMat->useTexMRAELoc = GetShaderLocation(pbrMat->pbrShader, "useTexMRA");
pbrMat->useTexEmissiveLoc = GetShaderLocation(pbrMat->pbrShader, "useTexEmissive");
SetShaderValue(pbrMat->pbrShader,pbrMat->albedoLoc,pbrMat->albedo,SHADER_UNIFORM_VEC4);
SetShaderValue(pbrMat->pbrShader, pbrMat->emissiveColorLoc, pbrMat->emissive, SHADER_UNIFORM_VEC4);
SetShaderValue(pbrMat->pbrShader, pbrMat->emissivePowerLoc, &pbrMat->emissivePower, SHADER_UNIFORM_FLOAT);
SetShaderValue(pbrMat->pbrShader,pbrMat->metallicLoc,&pbrMat->metallic,SHADER_UNIFORM_FLOAT);
SetShaderValue(pbrMat->pbrShader,pbrMat->roughnessLoc,&pbrMat->roughness,SHADER_UNIFORM_FLOAT);
SetShaderValue(pbrMat->pbrShader,pbrMat->aoLoc,&pbrMat->ao,SHADER_UNIFORM_FLOAT);
SetShaderValue(pbrMat->pbrShader,pbrMat->normalLoc,&pbrMat->normal,SHADER_UNIFORM_FLOAT);
SetShaderValue(pbrMat->pbrShader,pbrMat->texTilingLoc,pbrMat->texTiling,SHADER_UNIFORM_VEC2);
SetShaderValue(pbrMat->pbrShader,pbrMat->texOffsetLoc,pbrMat->texOffset,SHADER_UNIFORM_VEC2);
}
void PBRLoadTextures(PBRMaterial *pbrMat,PBRTexType pbrTexType,const char *fileName){
if(pbrMat == NULL) return;
switch(pbrTexType){
case PBR_TEXTURE_ALBEDO:
pbrMat->texAlbedo = LoadTexture(fileName);
pbrMat->useTexAlbedo = 1;
break;
case PBR_TEXTURE_MRA:
pbrMat->texMRA = LoadTexture(fileName);
pbrMat->useTexMRA = 1;
break;
case PBR_TEXTURE_NORMAL:
pbrMat->texNormal = LoadTexture(fileName);
pbrMat->useTexNormal = 1;
break;
case PBR_TEXTURE_EMISSIVE:
pbrMat->texEmissive = LoadTexture(fileName);
pbrMat->useTexEmissive = 1;
break;
}
}
void UnloadPBRMaterial(PBRMaterial pbrMat){
if(pbrMat.useTexAlbedo == 1) UnloadTexture(pbrMat.texAlbedo);
if(pbrMat.useTexNormal == 1) UnloadTexture(pbrMat.texNormal);
if(pbrMat.useTexMRA == 1) UnloadTexture(pbrMat.texMRA);
if(pbrMat.useTexEmissive == 1) UnloadTexture(pbrMat.texEmissive);
}
void PBRSetColor(PBRMaterial *pbrMat,PBRColorType pbrColorType,Color color){
if(pbrMat == NULL) return;
switch(pbrColorType){
case PBR_COLOR_ALBEDO:
pbrMat->albedo[0] = (float) color.r / 255;
pbrMat->albedo[1] = (float) color.g / 255;
pbrMat->albedo[2] = (float) color.b / 255;
pbrMat->albedo[3] = (float) color.a / 255;
SetShaderValue(pbrMat->pbrShader,pbrMat->albedoLoc,pbrMat->albedo,SHADER_UNIFORM_VEC4);
break;
case PBR_COLOR_EMISSIVE:
pbrMat->emissive[0] = (float) color.r / 255;
pbrMat->emissive[1] = (float) color.g / 255;
pbrMat->emissive[2] = (float) color.b / 255;
pbrMat->emissive[3] = (float) color.a / 255;
SetShaderValue(pbrMat->pbrShader, pbrMat->emissiveColorLoc, pbrMat->emissive, SHADER_UNIFORM_VEC4);
break;
}
}
void PBRSetFloat(PBRMaterial *pbrMat, PBRFloatType pbrParamType, float value){
if(pbrMat == NULL) return;
switch(pbrParamType){
case PBR_PARAM_METALLIC:
pbrMat->metallic = value;
SetShaderValue(pbrMat->pbrShader,pbrMat->metallicLoc,&pbrMat->metallic,SHADER_UNIFORM_FLOAT);
break;
case PBR_PARAM_ROUGHNESS:
pbrMat->roughness = value;
SetShaderValue(pbrMat->pbrShader,pbrMat->roughnessLoc,&pbrMat->roughness,SHADER_UNIFORM_FLOAT);
break;
case PBR_PARAM_NORMAL:
pbrMat->normal = value;
SetShaderValue(pbrMat->pbrShader,pbrMat->normalLoc,&pbrMat->normal,SHADER_UNIFORM_FLOAT);
break;
case PBR_PARAM_AO:
pbrMat->ao = value;
SetShaderValue(pbrMat->pbrShader,pbrMat->aoLoc,&pbrMat->ao,SHADER_UNIFORM_FLOAT);
break;
case PBR_PARAM_EMISSIVE:
pbrMat->emissivePower = value;
SetShaderValue(pbrMat->pbrShader,pbrMat->emissivePowerLoc,&pbrMat->emissivePower,SHADER_UNIFORM_FLOAT);
break;
}
}
void PBRSetVec2(PBRMaterial *pbrMat,PBRVec2Type type,Vector2 value){
switch(type){
case PBR_VEC2_TILING:
pbrMat->texTiling[0] = value.x;
pbrMat->texTiling[1] = value.y;
SetShaderValue(pbrMat->pbrShader,pbrMat->texTilingLoc,&pbrMat->texTiling,SHADER_UNIFORM_VEC2);
break;
case PBR_VEC2_OFFSET:
pbrMat->texOffset[0] = value.x;
pbrMat->texOffset[1] = value.y;
SetShaderValue(pbrMat->pbrShader,pbrMat->texOffsetLoc,&pbrMat->texOffset,SHADER_UNIFORM_VEC2);
break;
}
}
void PBRSetMaterial(PBRModel* model,PBRMaterial* pbrMat,int matIndex){
model->pbrMat = *pbrMat;
model->model.materials[matIndex].shader = model->pbrMat.pbrShader;
pbrMat->pbrShader.locs[SHADER_LOC_MAP_MRA] = GetShaderLocation(pbrMat->pbrShader, "mraMap");
pbrMat->pbrShader.locs[SHADER_LOC_MAP_EMISSIVE] = GetShaderLocation(pbrMat->pbrShader, "emissiveMap");
pbrMat->pbrShader.locs[SHADER_LOC_MAP_NORMAL] = GetShaderLocation(pbrMat->pbrShader, "normalMap");
if(pbrMat->useTexAlbedo) {
model->model.materials[matIndex].maps[MATERIAL_MAP_ALBEDO].texture = pbrMat->texAlbedo;
}
if(pbrMat->useTexMRA) {
model->model.materials[matIndex].maps[MATERIAL_MAP_MRA].texture = pbrMat->texMRA;
}
if(pbrMat->useTexNormal) {
model->model.materials[matIndex].maps[MATERIAL_MAP_NORMAL].texture = pbrMat->texNormal;
}
if(pbrMat->useTexEmissive) {
model->model.materials[matIndex].maps[MATERIAL_MAP_EMISSIVE].texture = pbrMat->texEmissive;
}
SetShaderValue(pbrMat->pbrShader,pbrMat->useTexAlbedoLoc,&pbrMat->useTexAlbedo,SHADER_UNIFORM_INT);
SetShaderValue(pbrMat->pbrShader,pbrMat->useTexNormalLoc,&pbrMat->useTexNormal,SHADER_UNIFORM_INT);
SetShaderValue(pbrMat->pbrShader, pbrMat->useTexMRAELoc, &pbrMat->useTexMRA, SHADER_UNIFORM_INT);
SetShaderValue(pbrMat->pbrShader, pbrMat->useTexEmissiveLoc, &pbrMat->useTexEmissive, SHADER_UNIFORM_INT);
}
void PBRDrawModel(PBRModel pbrModel, Vector3 position, float scale){
PBRMaterial *pbrMat = &pbrModel.pbrMat;
SetShaderValue(pbrMat->pbrShader,pbrMat->albedoLoc,pbrMat->albedo,SHADER_UNIFORM_VEC4);
SetShaderValue(pbrMat->pbrShader, pbrMat->emissiveColorLoc, pbrMat->emissive, SHADER_UNIFORM_VEC4);
SetShaderValue(pbrMat->pbrShader,pbrMat->metallicLoc,&pbrMat->metallic,SHADER_UNIFORM_FLOAT);
SetShaderValue(pbrMat->pbrShader,pbrMat->roughnessLoc,&pbrMat->roughness,SHADER_UNIFORM_FLOAT);
SetShaderValue(pbrMat->pbrShader,pbrMat->aoLoc,&pbrMat->ao,SHADER_UNIFORM_FLOAT);
SetShaderValue(pbrMat->pbrShader,pbrMat->normalLoc,&pbrMat->normal,SHADER_UNIFORM_FLOAT);
SetShaderValue(pbrMat->pbrShader,pbrMat->texTilingLoc,pbrMat->texTiling,SHADER_UNIFORM_VEC2);
SetShaderValue(pbrMat->pbrShader,pbrMat->texOffsetLoc,pbrMat->texOffset,SHADER_UNIFORM_VEC2);
SetShaderValue(pbrMat->pbrShader,pbrMat->useTexAlbedoLoc,&pbrMat->useTexAlbedo,SHADER_UNIFORM_INT);
SetShaderValue(pbrMat->pbrShader,pbrMat->useTexNormalLoc,&pbrMat->useTexNormal,SHADER_UNIFORM_INT);
SetShaderValue(pbrMat->pbrShader, pbrMat->useTexMRAELoc, &pbrMat->useTexMRA, SHADER_UNIFORM_INT);
SetShaderValue(pbrMat->pbrShader, pbrMat->useTexEmissiveLoc, &pbrMat->useTexEmissive, SHADER_UNIFORM_INT);
DrawModel(pbrModel.model,position,scale,WHITE);
}
PBRModel PBRModelLoad(const char *fileName){
PBRModel pbrModel = (PBRModel){0};
pbrModel.model = LoadModel(fileName);
return pbrModel;
}
PBRModel PBRModelLoadFromMesh(Mesh mesh){
PBRModel pbrModel = (PBRModel){0};
pbrModel.model = LoadModelFromMesh(mesh);
return pbrModel;
}
#endif // RPBR_IMPLEMENTATION

View File

@ -0,0 +1,171 @@
/*******************************************************************************************
*
* raylib [core] example - Model Defuse Normal Shader (adapted for HTML5 platform)
*
* This example is prepared to compile for PLATFORM_WEB and PLATFORM_DESKTOP
* As you will notice, code structure is slightly different to the other examples...
* To compile it for PLATFORM_WEB just uncomment #define PLATFORM_WEB at beginning
*
* This example has been created using raylib 5.0 (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
*
* Copyright (c) 2023-2024 Afan OLOVCIC (@_DevDad) 2015 Ramon Santamaria (@raysan5)
* Model: "Old Rusty Car" (https://skfb.ly/LxRy) by Renafox is licensed under Creative Commons Attribution-NonCommercial (http://creativecommons.org/licenses/by-nc/4.0/).
********************************************************************************************/
#include "raylib.h"
#if defined(PLATFORM_WEB)
#include <emscripten/emscripten.h>
#endif
#define RPBR_IMPLEMENTATION
#include "rpbr.h"
#if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330
#else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 120
#endif
//----------------------------------------------------------------------------------
// Main Entry Point
//----------------------------------------------------------------------------------
int main()
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
SetConfigFlags(FLAG_MSAA_4X_HINT);
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - basic pbr");
// Define the camera to look into our 3d world
Camera camera = { 0 };
camera.position = (Vector3){ 2.0f, 2.0f, 6.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 0.5f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
Shader shader = LoadShader(TextFormat("resources/shaders/glsl%i/pbr.vs",GLSL_VERSION),
TextFormat("resources/shaders/glsl%i/pbr.fs",GLSL_VERSION));
PBRModel model = PBRModelLoad("resources/models/old_car_new.glb");
//if we use obj file formator if model doesn't have tangents we have to calculate MeshTangents
//by using raylib function GenMeshTangents(mesh) for example: obj file doesn't support tangents
//GenMeshTangents(&model.model.meshes[0]);
PBRMaterial model_mat = (PBRMaterial){0};
PBRMaterialSetup(&model_mat, shader, NULL); //environment = NULL for now
PBRLoadTextures(&model_mat, PBR_TEXTURE_ALBEDO, "resources/old_car_d.png");
PBRLoadTextures(&model_mat, PBR_TEXTURE_MRA, "resources/old_car_mra.png");
PBRLoadTextures(&model_mat, PBR_TEXTURE_NORMAL, "resources/old_car_n.png");
PBRLoadTextures(&model_mat, PBR_TEXTURE_EMISSIVE, "resources/old_car_e.png");
PBRSetColor(&model_mat,PBR_COLOR_EMISSIVE, (Color){255,162,0,255});
PBRSetVec2(&model_mat, PBR_VEC2_TILING,(Vector2){0.5,0.5});
PBRSetMaterial(&model,&model_mat,0);
PBRModel floor = PBRModelLoad("resources/models/plane.glb");
PBRMaterial floor_mat = (PBRMaterial){0};
PBRMaterialSetup(&floor_mat, shader, NULL);
PBRLoadTextures(&floor_mat, PBR_TEXTURE_ALBEDO, "resources/road_a.png");
PBRLoadTextures(&floor_mat, PBR_TEXTURE_MRA, "resources/road_mra.png");
PBRLoadTextures(&floor_mat, PBR_TEXTURE_NORMAL, "resources/road_n.png");
PBRSetVec2(&floor_mat, PBR_VEC2_TILING,(Vector2){0.5,0.5});
PBRSetMaterial(&floor,&floor_mat,0);
shader.locs[SHADER_LOC_VECTOR_VIEW] = GetShaderLocation(shader, "viewPos");
int numOfLightsLoc = GetShaderLocation(shader, "numOfLights");
int numOfLights = 4;
SetShaderValue(shader, numOfLightsLoc, &numOfLights, SHADER_UNIFORM_INT);
Color ambCol = (Color){26,32,135,255};
float ambIntens = 0.02;
int albedoLoc = GetShaderLocation(shader, "albedo");
PBRSetAmbient(shader,ambCol,ambIntens);
// Create lights
PBRLight lights[MAX_LIGHTS] = { 0 };
lights[0] = PBRLightCreate(LIGHT_POINT, (Vector3){ -1, 1, -2 }, (Vector3){0,0,0}, YELLOW,4, shader);
lights[1] = PBRLightCreate(LIGHT_POINT, (Vector3){ 2, 1, 1 }, (Vector3){0,0,0}, GREEN,3.3, shader);
lights[2] = PBRLightCreate(LIGHT_POINT, (Vector3){ -2, 1, 1 }, (Vector3){0,0,0}, RED,8.3, shader);
lights[3] = PBRLightCreate(LIGHT_POINT, (Vector3){ 1, 1, -2 }, (Vector3){0,0,0}, BLUE,2, shader);
SetShaderValueV(shader, GetShaderLocation(shader, "lights"), lights, SHADER_UNIFORM_FLOAT, numOfLights);
SetTargetFPS(60); // Set our game to run at 60 frames-per-second-------------------------------------------------------------
int emissiveCnt = 0;
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_ORBITAL);
// Update the shader with the camera view vector (points towards { 0.0f, 0.0f, 0.0f })
float cameraPos[3] = {camera.position.x, camera.position.y, camera.position.z};
SetShaderValue(shader, shader.locs[SHADER_LOC_VECTOR_VIEW], cameraPos, SHADER_UNIFORM_VEC3);
// Check key inputs to enable/disable lights
if (IsKeyPressed(KEY_Y)) { lights[0].enabled = !lights[0].enabled; }
if (IsKeyPressed(KEY_G)) { lights[1].enabled = !lights[1].enabled; }
if (IsKeyPressed(KEY_R)) { lights[2].enabled = !lights[2].enabled; }
if (IsKeyPressed(KEY_B)) { lights[3].enabled = !lights[3].enabled; }
// Update light values (actually, only enable/disable them)
for (int i = 0; i < MAX_LIGHTS; i++) PBRLightUpdate(shader, lights[i]);
emissiveCnt--;
if(emissiveCnt<=0){
emissiveCnt = GetRandomValue(0,20);
PBRSetFloat(&model_mat,PBR_PARAM_EMISSIVE,(float)GetRandomValue(0,100)/100);
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(BLACK);
BeginMode3D(camera);
PBRDrawModel(floor, (Vector3){0,0,0}, 5.0f);
PBRDrawModel(model, (Vector3) {0, 0.0, 0}, 0.005);
// Draw spheres to show where the lights are
for (int i = 0; i < MAX_LIGHTS; i++) {
Color col = (Color) {lights[i].color[0] * 255, lights[i].color[1] * 255, lights[i].color[2] * 255,
lights[i].color[3] * 255};
if (lights[i].enabled) DrawSphereEx(lights[i].position, 0.2f, 8, 8, col);
else DrawSphereWires(lights[i].position, 0.2f, 8, 8, ColorAlpha(col, 0.3f));
}
EndMode3D();
DrawText("(c) Old Rusty Car model by Renafox (https://skfb.ly/LxRy)", screenWidth - 320, screenHeight - 20, 10, GRAY);
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
//--------------------------------------------------------------------------------------
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadModel(floor.model); // Unload model
UnloadModel(model.model); // Unload model
UnloadShader(shader); // Unload Shader
UnloadPBRMaterial(floor_mat); // Unload PBRMaterial
UnloadPBRMaterial(model_mat); // Unload PBRMaterial
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -170,4 +170,3 @@ int main(void)
return 0; return 0;
} }

View File

@ -0,0 +1,130 @@
/*******************************************************************************************
*
* raylib [textures] example - Image loading and texture creation
*
* NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM)
*
* Example originally created with raylib 1.3, last time updated with raylib 1.3
*
* 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) 2015-2023 Karim Salem (@kimo-s)
*
********************************************************************************************/
#include "raylib.h"
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
void NormalizeKernel(float *kernel, int size)
{
float sum = 0.0f;
for (int i = 0; i < size; i++) sum += kernel[i];
if (sum != 0.0f)
{
for (int i = 0; i < size; i++) kernel[i] /= sum;
}
}
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [textures] example - image convolution");
Image image = LoadImage("resources/cat.png"); // Loaded in CPU memory (RAM)
float gaussiankernel[] = {
1.0f, 2.0f, 1.0f,
2.0f, 4.0f, 2.0f,
1.0f, 2.0f, 1.0f };
float sobelkernel[] = {
1.0f, 0.0f, -1.0f,
2.0f, 0.0f, -2.0f,
1.0f, 0.0f, -1.0f };
float sharpenkernel[] = {
0.0f, -1.0f, 0.0f,
-1.0f, 5.0f, -1.0f,
0.0f, -1.0f, 0.0f };
NormalizeKernel(gaussiankernel, 9);
NormalizeKernel(sharpenkernel, 9);
NormalizeKernel(sobelkernel, 9);
Image catSharpend = ImageCopy(image);
ImageKernelConvolution(&catSharpend, sharpenkernel, 9);
Image catSobel = ImageCopy(image);
ImageKernelConvolution(&catSobel, sobelkernel, 9);
Image catGaussian = ImageCopy(image);
for (int i = 0; i < 6; i++)
{
ImageKernelConvolution(&catGaussian, gaussiankernel, 9);
}
ImageCrop(&image, (Rectangle){ 0, 0, (float)200, (float)450 });
ImageCrop(&catGaussian, (Rectangle){ 0, 0, (float)200, (float)450 });
ImageCrop(&catSobel, (Rectangle){ 0, 0, (float)200, (float)450 });
ImageCrop(&catSharpend, (Rectangle){ 0, 0, (float)200, (float)450 });
// Images converted to texture, GPU memory (VRAM)
Texture2D texture = LoadTextureFromImage(image);
Texture2D catSharpendTexture = LoadTextureFromImage(catSharpend);
Texture2D catSobelTexture = LoadTextureFromImage(catSobel);
Texture2D catGaussianTexture = LoadTextureFromImage(catGaussian);
// Once images have been converted to texture and uploaded to VRAM,
// they can be unloaded from RAM
UnloadImage(image);
UnloadImage(catGaussian);
UnloadImage(catSobel);
UnloadImage(catSharpend);
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//---------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
// TODO: Update your variables here
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
DrawTexture(catSharpendTexture, 0, 0, WHITE);
DrawTexture(catSobelTexture, 200, 0, WHITE);
DrawTexture(catGaussianTexture, 400, 0, WHITE);
DrawTexture(texture, 600, 0, WHITE);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadTexture(texture);
UnloadTexture(catGaussianTexture);
UnloadTexture(catSobelTexture);
UnloadTexture(catSharpendTexture);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

BIN
logo/raylib.icns Normal file

Binary file not shown.

BIN
logo/raylib_1024x1024.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -9,13 +9,13 @@
{ {
"name": "RAYLIB_VERSION_MAJOR", "name": "RAYLIB_VERSION_MAJOR",
"type": "INT", "type": "INT",
"value": 4, "value": 5,
"description": "" "description": ""
}, },
{ {
"name": "RAYLIB_VERSION_MINOR", "name": "RAYLIB_VERSION_MINOR",
"type": "INT", "type": "INT",
"value": 6, "value": 1,
"description": "" "description": ""
}, },
{ {
@ -27,7 +27,7 @@
{ {
"name": "RAYLIB_VERSION", "name": "RAYLIB_VERSION",
"type": "STRING", "type": "STRING",
"value": "4.6-dev", "value": "5.1-dev",
"description": "" "description": ""
}, },
{ {
@ -1329,6 +1329,48 @@
"description": "Filepaths entries" "description": "Filepaths entries"
} }
] ]
},
{
"name": "AutomationEvent",
"description": "Automation event",
"fields": [
{
"type": "unsigned int",
"name": "frame",
"description": "Event frame"
},
{
"type": "unsigned int",
"name": "type",
"description": "Event type (AutomationEventType)"
},
{
"type": "int[4]",
"name": "params",
"description": "Event parameters (if required)"
}
]
},
{
"name": "AutomationEventList",
"description": "Automation event list",
"fields": [
{
"type": "unsigned int",
"name": "capacity",
"description": "Events max entries (MAX_AUTOMATION_EVENTS)"
},
{
"type": "unsigned int",
"name": "count",
"description": "Events entries count"
},
{
"type": "AutomationEvent *",
"name": "events",
"description": "Events entries"
}
]
} }
], ],
"aliases": [ "aliases": [
@ -3092,16 +3134,16 @@
} }
] ]
}, },
{
"name": "WindowShouldClose",
"description": "Check if KEY_ESCAPE pressed or Close icon pressed",
"returnType": "bool"
},
{ {
"name": "CloseWindow", "name": "CloseWindow",
"description": "Close window and unload OpenGL context", "description": "Close window and unload OpenGL context",
"returnType": "void" "returnType": "void"
}, },
{
"name": "WindowShouldClose",
"description": "Check if application should close (KEY_ESCAPE pressed or windows close icon clicked)",
"returnType": "bool"
},
{ {
"name": "IsWindowReady", "name": "IsWindowReady",
"description": "Check if window has been initialized successfully", "description": "Check if window has been initialized successfully",
@ -3467,27 +3509,6 @@
"description": "Disable waiting for events on EndDrawing(), automatic events polling", "description": "Disable waiting for events on EndDrawing(), automatic events polling",
"returnType": "void" "returnType": "void"
}, },
{
"name": "SwapScreenBuffer",
"description": "Swap back buffer with front buffer (screen drawing)",
"returnType": "void"
},
{
"name": "PollInputEvents",
"description": "Register all input events",
"returnType": "void"
},
{
"name": "WaitTime",
"description": "Wait for some time (halt program execution)",
"returnType": "void",
"params": [
{
"type": "double",
"name": "seconds"
}
]
},
{ {
"name": "ShowCursor", "name": "ShowCursor",
"description": "Shows cursor", "description": "Shows cursor",
@ -3971,11 +3992,6 @@
} }
] ]
}, },
{
"name": "GetFPS",
"description": "Get current FPS",
"returnType": "int"
},
{ {
"name": "GetFrameTime", "name": "GetFrameTime",
"description": "Get time in seconds for last frame drawn (delta time)", "description": "Get time in seconds for last frame drawn (delta time)",
@ -3986,6 +4002,43 @@
"description": "Get elapsed time in seconds since InitWindow()", "description": "Get elapsed time in seconds since InitWindow()",
"returnType": "double" "returnType": "double"
}, },
{
"name": "GetFPS",
"description": "Get current FPS",
"returnType": "int"
},
{
"name": "SwapScreenBuffer",
"description": "Swap back buffer with front buffer (screen drawing)",
"returnType": "void"
},
{
"name": "PollInputEvents",
"description": "Register all input events",
"returnType": "void"
},
{
"name": "WaitTime",
"description": "Wait for some time (halt program execution)",
"returnType": "void",
"params": [
{
"type": "double",
"name": "seconds"
}
]
},
{
"name": "SetRandomSeed",
"description": "Set the seed for the random number generator",
"returnType": "void",
"params": [
{
"type": "unsigned int",
"name": "seed"
}
]
},
{ {
"name": "GetRandomValue", "name": "GetRandomValue",
"description": "Get a random value between min and max (both included)", "description": "Get a random value between min and max (both included)",
@ -4002,13 +4055,32 @@
] ]
}, },
{ {
"name": "SetRandomSeed", "name": "LoadRandomSequence",
"description": "Set the seed for the random number generator", "description": "Load random values sequence, no values repeated",
"returnType": "void", "returnType": "int *",
"params": [ "params": [
{ {
"type": "unsigned int", "type": "unsigned int",
"name": "seed" "name": "count"
},
{
"type": "int",
"name": "min"
},
{
"type": "int",
"name": "max"
}
]
},
{
"name": "UnloadRandomSequence",
"description": "Unload random values sequence",
"returnType": "void",
"params": [
{
"type": "int *",
"name": "sequence"
} }
] ]
}, },
@ -4034,6 +4106,17 @@
} }
] ]
}, },
{
"name": "OpenURL",
"description": "Open URL with default system browser (if available)",
"returnType": "void",
"params": [
{
"type": "const char *",
"name": "url"
}
]
},
{ {
"name": "TraceLog", "name": "TraceLog",
"description": "Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR...)", "description": "Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR...)",
@ -4101,17 +4184,6 @@
} }
] ]
}, },
{
"name": "OpenURL",
"description": "Open URL with default system browser (if available)",
"returnType": "void",
"params": [
{
"type": "const char *",
"name": "url"
}
]
},
{ {
"name": "SetTraceLogCallback", "name": "SetTraceLogCallback",
"description": "Set custom trace log", "description": "Set custom trace log",
@ -4548,6 +4620,86 @@
} }
] ]
}, },
{
"name": "LoadAutomationEventList",
"description": "Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS",
"returnType": "AutomationEventList",
"params": [
{
"type": "const char *",
"name": "fileName"
}
]
},
{
"name": "UnloadAutomationEventList",
"description": "Unload automation events list from file",
"returnType": "void",
"params": [
{
"type": "AutomationEventList *",
"name": "list"
}
]
},
{
"name": "ExportAutomationEventList",
"description": "Export automation events list as text file",
"returnType": "bool",
"params": [
{
"type": "AutomationEventList",
"name": "list"
},
{
"type": "const char *",
"name": "fileName"
}
]
},
{
"name": "SetAutomationEventList",
"description": "Set automation event list to record to",
"returnType": "void",
"params": [
{
"type": "AutomationEventList *",
"name": "list"
}
]
},
{
"name": "SetAutomationEventBaseFrame",
"description": "Set automation event internal base frame to start recording",
"returnType": "void",
"params": [
{
"type": "int",
"name": "frame"
}
]
},
{
"name": "StartAutomationEventRecording",
"description": "Start recording automation events (AutomationEventList must be set)",
"returnType": "void"
},
{
"name": "StopAutomationEventRecording",
"description": "Stop recording automation events",
"returnType": "void"
},
{
"name": "PlayAutomationEvent",
"description": "Play a recorded automation event",
"returnType": "void",
"params": [
{
"type": "AutomationEvent",
"name": "event"
}
]
},
{ {
"name": "IsKeyPressed", "name": "IsKeyPressed",
"description": "Check if a key has been pressed once", "description": "Check if a key has been pressed once",
@ -4603,6 +4755,16 @@
} }
] ]
}, },
{
"name": "GetKeyPressed",
"description": "Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty",
"returnType": "int"
},
{
"name": "GetCharPressed",
"description": "Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty",
"returnType": "int"
},
{ {
"name": "SetExitKey", "name": "SetExitKey",
"description": "Set a custom key to exit program (default is ESC)", "description": "Set a custom key to exit program (default is ESC)",
@ -4614,16 +4776,6 @@
} }
] ]
}, },
{
"name": "GetKeyPressed",
"description": "Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty",
"returnType": "int"
},
{
"name": "GetCharPressed",
"description": "Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty",
"returnType": "int"
},
{ {
"name": "IsGamepadAvailable", "name": "IsGamepadAvailable",
"description": "Check if a gamepad is available", "description": "Check if a gamepad is available",
@ -5083,7 +5235,7 @@
}, },
{ {
"name": "DrawLineV", "name": "DrawLineV",
"description": "Draw a line (Vector version)", "description": "Draw a line (using gl lines)",
"returnType": "void", "returnType": "void",
"params": [ "params": [
{ {
@ -5102,7 +5254,7 @@
}, },
{ {
"name": "DrawLineEx", "name": "DrawLineEx",
"description": "Draw a line defining thickness", "description": "Draw a line (using triangles/quads)",
"returnType": "void", "returnType": "void",
"params": [ "params": [
{ {
@ -5123,136 +5275,9 @@
} }
] ]
}, },
{
"name": "DrawLineBezier",
"description": "Draw a line using cubic-bezier curves in-out",
"returnType": "void",
"params": [
{
"type": "Vector2",
"name": "startPos"
},
{
"type": "Vector2",
"name": "endPos"
},
{
"type": "float",
"name": "thick"
},
{
"type": "Color",
"name": "color"
}
]
},
{
"name": "DrawLineBezierQuad",
"description": "Draw line using quadratic bezier curves with a control point",
"returnType": "void",
"params": [
{
"type": "Vector2",
"name": "startPos"
},
{
"type": "Vector2",
"name": "endPos"
},
{
"type": "Vector2",
"name": "controlPos"
},
{
"type": "float",
"name": "thick"
},
{
"type": "Color",
"name": "color"
}
]
},
{
"name": "DrawLineBezierCubic",
"description": "Draw line using cubic bezier curves with 2 control points",
"returnType": "void",
"params": [
{
"type": "Vector2",
"name": "startPos"
},
{
"type": "Vector2",
"name": "endPos"
},
{
"type": "Vector2",
"name": "startControlPos"
},
{
"type": "Vector2",
"name": "endControlPos"
},
{
"type": "float",
"name": "thick"
},
{
"type": "Color",
"name": "color"
}
]
},
{
"name": "DrawLineBSpline",
"description": "Draw a B-Spline line, minimum 4 points",
"returnType": "void",
"params": [
{
"type": "Vector2 *",
"name": "points"
},
{
"type": "int",
"name": "pointCount"
},
{
"type": "float",
"name": "thick"
},
{
"type": "Color",
"name": "color"
}
]
},
{
"name": "DrawLineCatmullRom",
"description": "Draw a Catmull Rom spline line, minimum 4 points",
"returnType": "void",
"params": [
{
"type": "Vector2 *",
"name": "points"
},
{
"type": "int",
"name": "pointCount"
},
{
"type": "float",
"name": "thick"
},
{
"type": "Color",
"name": "color"
}
]
},
{ {
"name": "DrawLineStrip", "name": "DrawLineStrip",
"description": "Draw lines sequence", "description": "Draw lines sequence (using gl lines)",
"returnType": "void", "returnType": "void",
"params": [ "params": [
{ {
@ -5269,6 +5294,29 @@
} }
] ]
}, },
{
"name": "DrawLineBezier",
"description": "Draw line segment cubic-bezier in-out interpolation",
"returnType": "void",
"params": [
{
"type": "Vector2",
"name": "startPos"
},
{
"type": "Vector2",
"name": "endPos"
},
{
"type": "float",
"name": "thick"
},
{
"type": "Color",
"name": "color"
}
]
},
{ {
"name": "DrawCircle", "name": "DrawCircle",
"description": "Draw a color-filled circle", "description": "Draw a color-filled circle",
@ -5423,6 +5471,25 @@
} }
] ]
}, },
{
"name": "DrawCircleLinesV",
"description": "Draw circle outline (Vector version)",
"returnType": "void",
"params": [
{
"type": "Vector2",
"name": "center"
},
{
"type": "float",
"name": "radius"
},
{
"type": "Color",
"name": "color"
}
]
},
{ {
"name": "DrawEllipse", "name": "DrawEllipse",
"description": "Draw ellipse", "description": "Draw ellipse",
@ -5985,6 +6052,387 @@
} }
] ]
}, },
{
"name": "DrawSplineLinear",
"description": "Draw spline: Linear, minimum 2 points",
"returnType": "void",
"params": [
{
"type": "Vector2 *",
"name": "points"
},
{
"type": "int",
"name": "pointCount"
},
{
"type": "float",
"name": "thick"
},
{
"type": "Color",
"name": "color"
}
]
},
{
"name": "DrawSplineBasis",
"description": "Draw spline: B-Spline, minimum 4 points",
"returnType": "void",
"params": [
{
"type": "Vector2 *",
"name": "points"
},
{
"type": "int",
"name": "pointCount"
},
{
"type": "float",
"name": "thick"
},
{
"type": "Color",
"name": "color"
}
]
},
{
"name": "DrawSplineCatmullRom",
"description": "Draw spline: Catmull-Rom, minimum 4 points",
"returnType": "void",
"params": [
{
"type": "Vector2 *",
"name": "points"
},
{
"type": "int",
"name": "pointCount"
},
{
"type": "float",
"name": "thick"
},
{
"type": "Color",
"name": "color"
}
]
},
{
"name": "DrawSplineBezierQuadratic",
"description": "Draw spline: Quadratic Bezier, minimum 3 points (1 control point): [p1, c2, p3, c4...]",
"returnType": "void",
"params": [
{
"type": "Vector2 *",
"name": "points"
},
{
"type": "int",
"name": "pointCount"
},
{
"type": "float",
"name": "thick"
},
{
"type": "Color",
"name": "color"
}
]
},
{
"name": "DrawSplineBezierCubic",
"description": "Draw spline: Cubic Bezier, minimum 4 points (2 control points): [p1, c2, c3, p4, c5, c6...]",
"returnType": "void",
"params": [
{
"type": "Vector2 *",
"name": "points"
},
{
"type": "int",
"name": "pointCount"
},
{
"type": "float",
"name": "thick"
},
{
"type": "Color",
"name": "color"
}
]
},
{
"name": "DrawSplineSegmentLinear",
"description": "Draw spline segment: Linear, 2 points",
"returnType": "void",
"params": [
{
"type": "Vector2",
"name": "p1"
},
{
"type": "Vector2",
"name": "p2"
},
{
"type": "float",
"name": "thick"
},
{
"type": "Color",
"name": "color"
}
]
},
{
"name": "DrawSplineSegmentBasis",
"description": "Draw spline segment: B-Spline, 4 points",
"returnType": "void",
"params": [
{
"type": "Vector2",
"name": "p1"
},
{
"type": "Vector2",
"name": "p2"
},
{
"type": "Vector2",
"name": "p3"
},
{
"type": "Vector2",
"name": "p4"
},
{
"type": "float",
"name": "thick"
},
{
"type": "Color",
"name": "color"
}
]
},
{
"name": "DrawSplineSegmentCatmullRom",
"description": "Draw spline segment: Catmull-Rom, 4 points",
"returnType": "void",
"params": [
{
"type": "Vector2",
"name": "p1"
},
{
"type": "Vector2",
"name": "p2"
},
{
"type": "Vector2",
"name": "p3"
},
{
"type": "Vector2",
"name": "p4"
},
{
"type": "float",
"name": "thick"
},
{
"type": "Color",
"name": "color"
}
]
},
{
"name": "DrawSplineSegmentBezierQuadratic",
"description": "Draw spline segment: Quadratic Bezier, 2 points, 1 control point",
"returnType": "void",
"params": [
{
"type": "Vector2",
"name": "p1"
},
{
"type": "Vector2",
"name": "c2"
},
{
"type": "Vector2",
"name": "p3"
},
{
"type": "float",
"name": "thick"
},
{
"type": "Color",
"name": "color"
}
]
},
{
"name": "DrawSplineSegmentBezierCubic",
"description": "Draw spline segment: Cubic Bezier, 2 points, 2 control points",
"returnType": "void",
"params": [
{
"type": "Vector2",
"name": "p1"
},
{
"type": "Vector2",
"name": "c2"
},
{
"type": "Vector2",
"name": "c3"
},
{
"type": "Vector2",
"name": "p4"
},
{
"type": "float",
"name": "thick"
},
{
"type": "Color",
"name": "color"
}
]
},
{
"name": "GetSplinePointLinear",
"description": "Get (evaluate) spline point: Linear",
"returnType": "Vector2",
"params": [
{
"type": "Vector2",
"name": "startPos"
},
{
"type": "Vector2",
"name": "endPos"
},
{
"type": "float",
"name": "t"
}
]
},
{
"name": "GetSplinePointBasis",
"description": "Get (evaluate) spline point: B-Spline",
"returnType": "Vector2",
"params": [
{
"type": "Vector2",
"name": "p1"
},
{
"type": "Vector2",
"name": "p2"
},
{
"type": "Vector2",
"name": "p3"
},
{
"type": "Vector2",
"name": "p4"
},
{
"type": "float",
"name": "t"
}
]
},
{
"name": "GetSplinePointCatmullRom",
"description": "Get (evaluate) spline point: Catmull-Rom",
"returnType": "Vector2",
"params": [
{
"type": "Vector2",
"name": "p1"
},
{
"type": "Vector2",
"name": "p2"
},
{
"type": "Vector2",
"name": "p3"
},
{
"type": "Vector2",
"name": "p4"
},
{
"type": "float",
"name": "t"
}
]
},
{
"name": "GetSplinePointBezierQuad",
"description": "Get (evaluate) spline point: Quadratic Bezier",
"returnType": "Vector2",
"params": [
{
"type": "Vector2",
"name": "p1"
},
{
"type": "Vector2",
"name": "c2"
},
{
"type": "Vector2",
"name": "p3"
},
{
"type": "float",
"name": "t"
}
]
},
{
"name": "GetSplinePointBezierCubic",
"description": "Get (evaluate) spline point: Cubic Bezier",
"returnType": "Vector2",
"params": [
{
"type": "Vector2",
"name": "p1"
},
{
"type": "Vector2",
"name": "c2"
},
{
"type": "Vector2",
"name": "c3"
},
{
"type": "Vector2",
"name": "p4"
},
{
"type": "float",
"name": "t"
}
]
},
{ {
"name": "CheckCollisionRecs", "name": "CheckCollisionRecs",
"description": "Check collision between two rectangles", "description": "Check collision between two rectangles",
@ -6768,6 +7216,25 @@
} }
] ]
}, },
{
"name": "ImageKernelConvolution",
"description": "Apply Custom Square image convolution kernel",
"returnType": "void",
"params": [
{
"type": "Image *",
"name": "image"
},
{
"type": "float*",
"name": "kernel"
},
{
"type": "int",
"name": "kernelSize"
}
]
},
{ {
"name": "ImageResize", "name": "ImageResize",
"description": "Resize image (Bicubic scaling algorithm)", "description": "Resize image (Bicubic scaling algorithm)",
@ -10339,6 +10806,11 @@
} }
] ]
}, },
{
"name": "GetMasterVolume",
"description": "Get master volume (listener)",
"returnType": "float"
},
{ {
"name": "LoadWave", "name": "LoadWave",
"description": "Load wave data from file", "description": "Load wave data from file",

View File

@ -9,13 +9,13 @@ return {
{ {
name = "RAYLIB_VERSION_MAJOR", name = "RAYLIB_VERSION_MAJOR",
type = "INT", type = "INT",
value = 4, value = 5,
description = "" description = ""
}, },
{ {
name = "RAYLIB_VERSION_MINOR", name = "RAYLIB_VERSION_MINOR",
type = "INT", type = "INT",
value = 6, value = 1,
description = "" description = ""
}, },
{ {
@ -27,7 +27,7 @@ return {
{ {
name = "RAYLIB_VERSION", name = "RAYLIB_VERSION",
type = "STRING", type = "STRING",
value = "4.6-dev", value = "5.1-dev",
description = "" description = ""
}, },
{ {
@ -1329,6 +1329,48 @@ return {
description = "Filepaths entries" description = "Filepaths entries"
} }
} }
},
{
name = "AutomationEvent",
description = "Automation event",
fields = {
{
type = "unsigned int",
name = "frame",
description = "Event frame"
},
{
type = "unsigned int",
name = "type",
description = "Event type (AutomationEventType)"
},
{
type = "int[4]",
name = "params",
description = "Event parameters (if required)"
}
}
},
{
name = "AutomationEventList",
description = "Automation event list",
fields = {
{
type = "unsigned int",
name = "capacity",
description = "Events max entries (MAX_AUTOMATION_EVENTS)"
},
{
type = "unsigned int",
name = "count",
description = "Events entries count"
},
{
type = "AutomationEvent *",
name = "events",
description = "Events entries"
}
}
} }
}, },
aliases = { aliases = {
@ -3044,16 +3086,16 @@ return {
{type = "const char *", name = "title"} {type = "const char *", name = "title"}
} }
}, },
{
name = "WindowShouldClose",
description = "Check if KEY_ESCAPE pressed or Close icon pressed",
returnType = "bool"
},
{ {
name = "CloseWindow", name = "CloseWindow",
description = "Close window and unload OpenGL context", description = "Close window and unload OpenGL context",
returnType = "void" returnType = "void"
}, },
{
name = "WindowShouldClose",
description = "Check if application should close (KEY_ESCAPE pressed or windows close icon clicked)",
returnType = "bool"
},
{ {
name = "IsWindowReady", name = "IsWindowReady",
description = "Check if window has been initialized successfully", description = "Check if window has been initialized successfully",
@ -3344,24 +3386,6 @@ return {
description = "Disable waiting for events on EndDrawing(), automatic events polling", description = "Disable waiting for events on EndDrawing(), automatic events polling",
returnType = "void" returnType = "void"
}, },
{
name = "SwapScreenBuffer",
description = "Swap back buffer with front buffer (screen drawing)",
returnType = "void"
},
{
name = "PollInputEvents",
description = "Register all input events",
returnType = "void"
},
{
name = "WaitTime",
description = "Wait for some time (halt program execution)",
returnType = "void",
params = {
{type = "double", name = "seconds"}
}
},
{ {
name = "ShowCursor", name = "ShowCursor",
description = "Shows cursor", description = "Shows cursor",
@ -3686,11 +3710,6 @@ return {
{type = "int", name = "fps"} {type = "int", name = "fps"}
} }
}, },
{
name = "GetFPS",
description = "Get current FPS",
returnType = "int"
},
{ {
name = "GetFrameTime", name = "GetFrameTime",
description = "Get time in seconds for last frame drawn (delta time)", description = "Get time in seconds for last frame drawn (delta time)",
@ -3701,6 +3720,37 @@ return {
description = "Get elapsed time in seconds since InitWindow()", description = "Get elapsed time in seconds since InitWindow()",
returnType = "double" returnType = "double"
}, },
{
name = "GetFPS",
description = "Get current FPS",
returnType = "int"
},
{
name = "SwapScreenBuffer",
description = "Swap back buffer with front buffer (screen drawing)",
returnType = "void"
},
{
name = "PollInputEvents",
description = "Register all input events",
returnType = "void"
},
{
name = "WaitTime",
description = "Wait for some time (halt program execution)",
returnType = "void",
params = {
{type = "double", name = "seconds"}
}
},
{
name = "SetRandomSeed",
description = "Set the seed for the random number generator",
returnType = "void",
params = {
{type = "unsigned int", name = "seed"}
}
},
{ {
name = "GetRandomValue", name = "GetRandomValue",
description = "Get a random value between min and max (both included)", description = "Get a random value between min and max (both included)",
@ -3711,11 +3761,21 @@ return {
} }
}, },
{ {
name = "SetRandomSeed", name = "LoadRandomSequence",
description = "Set the seed for the random number generator", description = "Load random values sequence, no values repeated",
returnType = "int *",
params = {
{type = "unsigned int", name = "count"},
{type = "int", name = "min"},
{type = "int", name = "max"}
}
},
{
name = "UnloadRandomSequence",
description = "Unload random values sequence",
returnType = "void", returnType = "void",
params = { params = {
{type = "unsigned int", name = "seed"} {type = "int *", name = "sequence"}
} }
}, },
{ {
@ -3734,6 +3794,14 @@ return {
{type = "unsigned int", name = "flags"} {type = "unsigned int", name = "flags"}
} }
}, },
{
name = "OpenURL",
description = "Open URL with default system browser (if available)",
returnType = "void",
params = {
{type = "const char *", name = "url"}
}
},
{ {
name = "TraceLog", name = "TraceLog",
description = "Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR...)", description = "Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR...)",
@ -3777,14 +3845,6 @@ return {
{type = "void *", name = "ptr"} {type = "void *", name = "ptr"}
} }
}, },
{
name = "OpenURL",
description = "Open URL with default system browser (if available)",
returnType = "void",
params = {
{type = "const char *", name = "url"}
}
},
{ {
name = "SetTraceLogCallback", name = "SetTraceLogCallback",
description = "Set custom trace log", description = "Set custom trace log",
@ -4077,6 +4137,65 @@ return {
{type = "int *", name = "outputSize"} {type = "int *", name = "outputSize"}
} }
}, },
{
name = "LoadAutomationEventList",
description = "Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS",
returnType = "AutomationEventList",
params = {
{type = "const char *", name = "fileName"}
}
},
{
name = "UnloadAutomationEventList",
description = "Unload automation events list from file",
returnType = "void",
params = {
{type = "AutomationEventList *", name = "list"}
}
},
{
name = "ExportAutomationEventList",
description = "Export automation events list as text file",
returnType = "bool",
params = {
{type = "AutomationEventList", name = "list"},
{type = "const char *", name = "fileName"}
}
},
{
name = "SetAutomationEventList",
description = "Set automation event list to record to",
returnType = "void",
params = {
{type = "AutomationEventList *", name = "list"}
}
},
{
name = "SetAutomationEventBaseFrame",
description = "Set automation event internal base frame to start recording",
returnType = "void",
params = {
{type = "int", name = "frame"}
}
},
{
name = "StartAutomationEventRecording",
description = "Start recording automation events (AutomationEventList must be set)",
returnType = "void"
},
{
name = "StopAutomationEventRecording",
description = "Stop recording automation events",
returnType = "void"
},
{
name = "PlayAutomationEvent",
description = "Play a recorded automation event",
returnType = "void",
params = {
{type = "AutomationEvent", name = "event"}
}
},
{ {
name = "IsKeyPressed", name = "IsKeyPressed",
description = "Check if a key has been pressed once", description = "Check if a key has been pressed once",
@ -4117,14 +4236,6 @@ return {
{type = "int", name = "key"} {type = "int", name = "key"}
} }
}, },
{
name = "SetExitKey",
description = "Set a custom key to exit program (default is ESC)",
returnType = "void",
params = {
{type = "int", name = "key"}
}
},
{ {
name = "GetKeyPressed", name = "GetKeyPressed",
description = "Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty", description = "Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty",
@ -4135,6 +4246,14 @@ return {
description = "Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty", description = "Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty",
returnType = "int" returnType = "int"
}, },
{
name = "SetExitKey",
description = "Set a custom key to exit program (default is ESC)",
returnType = "void",
params = {
{type = "int", name = "key"}
}
},
{ {
name = "IsGamepadAvailable", name = "IsGamepadAvailable",
description = "Check if a gamepad is available", description = "Check if a gamepad is available",
@ -4453,7 +4572,7 @@ return {
}, },
{ {
name = "DrawLineV", name = "DrawLineV",
description = "Draw a line (Vector version)", description = "Draw a line (using gl lines)",
returnType = "void", returnType = "void",
params = { params = {
{type = "Vector2", name = "startPos"}, {type = "Vector2", name = "startPos"},
@ -4463,7 +4582,7 @@ return {
}, },
{ {
name = "DrawLineEx", name = "DrawLineEx",
description = "Draw a line defining thickness", description = "Draw a line (using triangles/quads)",
returnType = "void", returnType = "void",
params = { params = {
{type = "Vector2", name = "startPos"}, {type = "Vector2", name = "startPos"},
@ -4472,67 +4591,9 @@ return {
{type = "Color", name = "color"} {type = "Color", name = "color"}
} }
}, },
{
name = "DrawLineBezier",
description = "Draw a line using cubic-bezier curves in-out",
returnType = "void",
params = {
{type = "Vector2", name = "startPos"},
{type = "Vector2", name = "endPos"},
{type = "float", name = "thick"},
{type = "Color", name = "color"}
}
},
{
name = "DrawLineBezierQuad",
description = "Draw line using quadratic bezier curves with a control point",
returnType = "void",
params = {
{type = "Vector2", name = "startPos"},
{type = "Vector2", name = "endPos"},
{type = "Vector2", name = "controlPos"},
{type = "float", name = "thick"},
{type = "Color", name = "color"}
}
},
{
name = "DrawLineBezierCubic",
description = "Draw line using cubic bezier curves with 2 control points",
returnType = "void",
params = {
{type = "Vector2", name = "startPos"},
{type = "Vector2", name = "endPos"},
{type = "Vector2", name = "startControlPos"},
{type = "Vector2", name = "endControlPos"},
{type = "float", name = "thick"},
{type = "Color", name = "color"}
}
},
{
name = "DrawLineBSpline",
description = "Draw a B-Spline line, minimum 4 points",
returnType = "void",
params = {
{type = "Vector2 *", name = "points"},
{type = "int", name = "pointCount"},
{type = "float", name = "thick"},
{type = "Color", name = "color"}
}
},
{
name = "DrawLineCatmullRom",
description = "Draw a Catmull Rom spline line, minimum 4 points",
returnType = "void",
params = {
{type = "Vector2 *", name = "points"},
{type = "int", name = "pointCount"},
{type = "float", name = "thick"},
{type = "Color", name = "color"}
}
},
{ {
name = "DrawLineStrip", name = "DrawLineStrip",
description = "Draw lines sequence", description = "Draw lines sequence (using gl lines)",
returnType = "void", returnType = "void",
params = { params = {
{type = "Vector2 *", name = "points"}, {type = "Vector2 *", name = "points"},
@ -4540,6 +4601,17 @@ return {
{type = "Color", name = "color"} {type = "Color", name = "color"}
} }
}, },
{
name = "DrawLineBezier",
description = "Draw line segment cubic-bezier in-out interpolation",
returnType = "void",
params = {
{type = "Vector2", name = "startPos"},
{type = "Vector2", name = "endPos"},
{type = "float", name = "thick"},
{type = "Color", name = "color"}
}
},
{ {
name = "DrawCircle", name = "DrawCircle",
description = "Draw a color-filled circle", description = "Draw a color-filled circle",
@ -4610,6 +4682,16 @@ return {
{type = "Color", name = "color"} {type = "Color", name = "color"}
} }
}, },
{
name = "DrawCircleLinesV",
description = "Draw circle outline (Vector version)",
returnType = "void",
params = {
{type = "Vector2", name = "center"},
{type = "float", name = "radius"},
{type = "Color", name = "color"}
}
},
{ {
name = "DrawEllipse", name = "DrawEllipse",
description = "Draw ellipse", description = "Draw ellipse",
@ -4866,6 +4948,180 @@ return {
{type = "Color", name = "color"} {type = "Color", name = "color"}
} }
}, },
{
name = "DrawSplineLinear",
description = "Draw spline: Linear, minimum 2 points",
returnType = "void",
params = {
{type = "Vector2 *", name = "points"},
{type = "int", name = "pointCount"},
{type = "float", name = "thick"},
{type = "Color", name = "color"}
}
},
{
name = "DrawSplineBasis",
description = "Draw spline: B-Spline, minimum 4 points",
returnType = "void",
params = {
{type = "Vector2 *", name = "points"},
{type = "int", name = "pointCount"},
{type = "float", name = "thick"},
{type = "Color", name = "color"}
}
},
{
name = "DrawSplineCatmullRom",
description = "Draw spline: Catmull-Rom, minimum 4 points",
returnType = "void",
params = {
{type = "Vector2 *", name = "points"},
{type = "int", name = "pointCount"},
{type = "float", name = "thick"},
{type = "Color", name = "color"}
}
},
{
name = "DrawSplineBezierQuadratic",
description = "Draw spline: Quadratic Bezier, minimum 3 points (1 control point): [p1, c2, p3, c4...]",
returnType = "void",
params = {
{type = "Vector2 *", name = "points"},
{type = "int", name = "pointCount"},
{type = "float", name = "thick"},
{type = "Color", name = "color"}
}
},
{
name = "DrawSplineBezierCubic",
description = "Draw spline: Cubic Bezier, minimum 4 points (2 control points): [p1, c2, c3, p4, c5, c6...]",
returnType = "void",
params = {
{type = "Vector2 *", name = "points"},
{type = "int", name = "pointCount"},
{type = "float", name = "thick"},
{type = "Color", name = "color"}
}
},
{
name = "DrawSplineSegmentLinear",
description = "Draw spline segment: Linear, 2 points",
returnType = "void",
params = {
{type = "Vector2", name = "p1"},
{type = "Vector2", name = "p2"},
{type = "float", name = "thick"},
{type = "Color", name = "color"}
}
},
{
name = "DrawSplineSegmentBasis",
description = "Draw spline segment: B-Spline, 4 points",
returnType = "void",
params = {
{type = "Vector2", name = "p1"},
{type = "Vector2", name = "p2"},
{type = "Vector2", name = "p3"},
{type = "Vector2", name = "p4"},
{type = "float", name = "thick"},
{type = "Color", name = "color"}
}
},
{
name = "DrawSplineSegmentCatmullRom",
description = "Draw spline segment: Catmull-Rom, 4 points",
returnType = "void",
params = {
{type = "Vector2", name = "p1"},
{type = "Vector2", name = "p2"},
{type = "Vector2", name = "p3"},
{type = "Vector2", name = "p4"},
{type = "float", name = "thick"},
{type = "Color", name = "color"}
}
},
{
name = "DrawSplineSegmentBezierQuadratic",
description = "Draw spline segment: Quadratic Bezier, 2 points, 1 control point",
returnType = "void",
params = {
{type = "Vector2", name = "p1"},
{type = "Vector2", name = "c2"},
{type = "Vector2", name = "p3"},
{type = "float", name = "thick"},
{type = "Color", name = "color"}
}
},
{
name = "DrawSplineSegmentBezierCubic",
description = "Draw spline segment: Cubic Bezier, 2 points, 2 control points",
returnType = "void",
params = {
{type = "Vector2", name = "p1"},
{type = "Vector2", name = "c2"},
{type = "Vector2", name = "c3"},
{type = "Vector2", name = "p4"},
{type = "float", name = "thick"},
{type = "Color", name = "color"}
}
},
{
name = "GetSplinePointLinear",
description = "Get (evaluate) spline point: Linear",
returnType = "Vector2",
params = {
{type = "Vector2", name = "startPos"},
{type = "Vector2", name = "endPos"},
{type = "float", name = "t"}
}
},
{
name = "GetSplinePointBasis",
description = "Get (evaluate) spline point: B-Spline",
returnType = "Vector2",
params = {
{type = "Vector2", name = "p1"},
{type = "Vector2", name = "p2"},
{type = "Vector2", name = "p3"},
{type = "Vector2", name = "p4"},
{type = "float", name = "t"}
}
},
{
name = "GetSplinePointCatmullRom",
description = "Get (evaluate) spline point: Catmull-Rom",
returnType = "Vector2",
params = {
{type = "Vector2", name = "p1"},
{type = "Vector2", name = "p2"},
{type = "Vector2", name = "p3"},
{type = "Vector2", name = "p4"},
{type = "float", name = "t"}
}
},
{
name = "GetSplinePointBezierQuad",
description = "Get (evaluate) spline point: Quadratic Bezier",
returnType = "Vector2",
params = {
{type = "Vector2", name = "p1"},
{type = "Vector2", name = "c2"},
{type = "Vector2", name = "p3"},
{type = "float", name = "t"}
}
},
{
name = "GetSplinePointBezierCubic",
description = "Get (evaluate) spline point: Cubic Bezier",
returnType = "Vector2",
params = {
{type = "Vector2", name = "p1"},
{type = "Vector2", name = "c2"},
{type = "Vector2", name = "c3"},
{type = "Vector2", name = "p4"},
{type = "float", name = "t"}
}
},
{ {
name = "CheckCollisionRecs", name = "CheckCollisionRecs",
description = "Check collision between two rectangles", description = "Check collision between two rectangles",
@ -5286,6 +5542,16 @@ return {
{type = "int", name = "blurSize"} {type = "int", name = "blurSize"}
} }
}, },
{
name = "ImageKernelConvolution",
description = "Apply Custom Square image convolution kernel",
returnType = "void",
params = {
{type = "Image *", name = "image"},
{type = "float*", name = "kernel"},
{type = "int", name = "kernelSize"}
}
},
{ {
name = "ImageResize", name = "ImageResize",
description = "Resize image (Bicubic scaling algorithm)", description = "Resize image (Bicubic scaling algorithm)",
@ -7195,6 +7461,11 @@ return {
{type = "float", name = "volume"} {type = "float", name = "volume"}
} }
}, },
{
name = "GetMasterVolume",
description = "Get master volume (listener)",
returnType = "float"
},
{ {
name = "LoadWave", name = "LoadWave",
description = "Load wave data from file", description = "Load wave data from file",

File diff suppressed because it is too large Load Diff

View File

@ -2,10 +2,10 @@
<raylibAPI> <raylibAPI>
<Defines count="56"> <Defines count="56">
<Define name="RAYLIB_H" type="GUARD" value="" desc="" /> <Define name="RAYLIB_H" type="GUARD" value="" desc="" />
<Define name="RAYLIB_VERSION_MAJOR" type="INT" value="4" desc="" /> <Define name="RAYLIB_VERSION_MAJOR" type="INT" value="5" desc="" />
<Define name="RAYLIB_VERSION_MINOR" type="INT" value="6" desc="" /> <Define name="RAYLIB_VERSION_MINOR" type="INT" value="1" desc="" />
<Define name="RAYLIB_VERSION_PATCH" type="INT" value="0" desc="" /> <Define name="RAYLIB_VERSION_PATCH" type="INT" value="0" desc="" />
<Define name="RAYLIB_VERSION" type="STRING" value="4.6-dev" desc="" /> <Define name="RAYLIB_VERSION" type="STRING" value="5.1-dev" desc="" />
<Define name="__declspec(x)" type="MACRO" value="__attribute__((x))" desc="" /> <Define name="__declspec(x)" type="MACRO" value="__attribute__((x))" desc="" />
<Define name="RLAPI" type="UNKNOWN" value="__declspec(dllexport)" desc="We are building the library as a Win32 shared library (.dll)" /> <Define name="RLAPI" type="UNKNOWN" value="__declspec(dllexport)" desc="We are building the library as a Win32 shared library (.dll)" />
<Define name="PI" type="FLOAT" value="3.14159265358979323846" desc="" /> <Define name="PI" type="FLOAT" value="3.14159265358979323846" desc="" />
@ -58,7 +58,7 @@
<Define name="SHADER_LOC_MAP_DIFFUSE" type="UNKNOWN" value="SHADER_LOC_MAP_ALBEDO" desc="" /> <Define name="SHADER_LOC_MAP_DIFFUSE" type="UNKNOWN" value="SHADER_LOC_MAP_ALBEDO" desc="" />
<Define name="SHADER_LOC_MAP_SPECULAR" type="UNKNOWN" value="SHADER_LOC_MAP_METALNESS" desc="" /> <Define name="SHADER_LOC_MAP_SPECULAR" type="UNKNOWN" value="SHADER_LOC_MAP_METALNESS" desc="" />
</Defines> </Defines>
<Structs count="32"> <Structs count="34">
<Struct name="Vector2" fieldCount="2" desc="Vector2, 2 components"> <Struct name="Vector2" fieldCount="2" desc="Vector2, 2 components">
<Field type="float" name="x" desc="Vector x component" /> <Field type="float" name="x" desc="Vector x component" />
<Field type="float" name="y" desc="Vector y component" /> <Field type="float" name="y" desc="Vector y component" />
@ -283,6 +283,16 @@
<Field type="unsigned int" name="count" desc="Filepaths entries count" /> <Field type="unsigned int" name="count" desc="Filepaths entries count" />
<Field type="char **" name="paths" desc="Filepaths entries" /> <Field type="char **" name="paths" desc="Filepaths entries" />
</Struct> </Struct>
<Struct name="AutomationEvent" fieldCount="3" desc="Automation event">
<Field type="unsigned int" name="frame" desc="Event frame" />
<Field type="unsigned int" name="type" desc="Event type (AutomationEventType)" />
<Field type="int[4]" name="params" desc="Event parameters (if required)" />
</Struct>
<Struct name="AutomationEventList" fieldCount="3" desc="Automation event list">
<Field type="unsigned int" name="capacity" desc="Events max entries (MAX_AUTOMATION_EVENTS)" />
<Field type="unsigned int" name="count" desc="Events entries count" />
<Field type="AutomationEvent *" name="events" desc="Events entries" />
</Struct>
</Structs> </Structs>
<Aliases count="5"> <Aliases count="5">
<Alias type="Quaternion" name="Vector4" desc="Quaternion, 4 components (Vector4 alias)" /> <Alias type="Quaternion" name="Vector4" desc="Quaternion, 4 components (Vector4 alias)" />
@ -660,16 +670,16 @@
<Param type="unsigned int" name="frames" desc="" /> <Param type="unsigned int" name="frames" desc="" />
</Callback> </Callback>
</Callbacks> </Callbacks>
<Functions count="529"> <Functions count="553">
<Function name="InitWindow" retType="void" paramCount="3" desc="Initialize window and OpenGL context"> <Function name="InitWindow" retType="void" paramCount="3" desc="Initialize window and OpenGL context">
<Param type="int" name="width" desc="" /> <Param type="int" name="width" desc="" />
<Param type="int" name="height" desc="" /> <Param type="int" name="height" desc="" />
<Param type="const char *" name="title" desc="" /> <Param type="const char *" name="title" desc="" />
</Function> </Function>
<Function name="WindowShouldClose" retType="bool" paramCount="0" desc="Check if KEY_ESCAPE pressed or Close icon pressed">
</Function>
<Function name="CloseWindow" retType="void" paramCount="0" desc="Close window and unload OpenGL context"> <Function name="CloseWindow" retType="void" paramCount="0" desc="Close window and unload OpenGL context">
</Function> </Function>
<Function name="WindowShouldClose" retType="bool" paramCount="0" desc="Check if application should close (KEY_ESCAPE pressed or windows close icon clicked)">
</Function>
<Function name="IsWindowReady" retType="bool" paramCount="0" desc="Check if window has been initialized successfully"> <Function name="IsWindowReady" retType="bool" paramCount="0" desc="Check if window has been initialized successfully">
</Function> </Function>
<Function name="IsWindowFullscreen" retType="bool" paramCount="0" desc="Check if window is currently fullscreen"> <Function name="IsWindowFullscreen" retType="bool" paramCount="0" desc="Check if window is currently fullscreen">
@ -785,13 +795,6 @@
</Function> </Function>
<Function name="DisableEventWaiting" retType="void" paramCount="0" desc="Disable waiting for events on EndDrawing(), automatic events polling"> <Function name="DisableEventWaiting" retType="void" paramCount="0" desc="Disable waiting for events on EndDrawing(), automatic events polling">
</Function> </Function>
<Function name="SwapScreenBuffer" retType="void" paramCount="0" desc="Swap back buffer with front buffer (screen drawing)">
</Function>
<Function name="PollInputEvents" retType="void" paramCount="0" desc="Register all input events">
</Function>
<Function name="WaitTime" retType="void" paramCount="1" desc="Wait for some time (halt program execution)">
<Param type="double" name="seconds" desc="" />
</Function>
<Function name="ShowCursor" retType="void" paramCount="0" desc="Shows cursor"> <Function name="ShowCursor" retType="void" paramCount="0" desc="Shows cursor">
</Function> </Function>
<Function name="HideCursor" retType="void" paramCount="0" desc="Hides cursor"> <Function name="HideCursor" retType="void" paramCount="0" desc="Hides cursor">
@ -931,18 +934,33 @@
<Function name="SetTargetFPS" retType="void" paramCount="1" desc="Set target FPS (maximum)"> <Function name="SetTargetFPS" retType="void" paramCount="1" desc="Set target FPS (maximum)">
<Param type="int" name="fps" desc="" /> <Param type="int" name="fps" desc="" />
</Function> </Function>
<Function name="GetFPS" retType="int" paramCount="0" desc="Get current FPS">
</Function>
<Function name="GetFrameTime" retType="float" paramCount="0" desc="Get time in seconds for last frame drawn (delta time)"> <Function name="GetFrameTime" retType="float" paramCount="0" desc="Get time in seconds for last frame drawn (delta time)">
</Function> </Function>
<Function name="GetTime" retType="double" paramCount="0" desc="Get elapsed time in seconds since InitWindow()"> <Function name="GetTime" retType="double" paramCount="0" desc="Get elapsed time in seconds since InitWindow()">
</Function> </Function>
<Function name="GetFPS" retType="int" paramCount="0" desc="Get current FPS">
</Function>
<Function name="SwapScreenBuffer" retType="void" paramCount="0" desc="Swap back buffer with front buffer (screen drawing)">
</Function>
<Function name="PollInputEvents" retType="void" paramCount="0" desc="Register all input events">
</Function>
<Function name="WaitTime" retType="void" paramCount="1" desc="Wait for some time (halt program execution)">
<Param type="double" name="seconds" desc="" />
</Function>
<Function name="SetRandomSeed" retType="void" paramCount="1" desc="Set the seed for the random number generator">
<Param type="unsigned int" name="seed" desc="" />
</Function>
<Function name="GetRandomValue" retType="int" paramCount="2" desc="Get a random value between min and max (both included)"> <Function name="GetRandomValue" retType="int" paramCount="2" desc="Get a random value between min and max (both included)">
<Param type="int" name="min" desc="" /> <Param type="int" name="min" desc="" />
<Param type="int" name="max" desc="" /> <Param type="int" name="max" desc="" />
</Function> </Function>
<Function name="SetRandomSeed" retType="void" paramCount="1" desc="Set the seed for the random number generator"> <Function name="LoadRandomSequence" retType="int *" paramCount="3" desc="Load random values sequence, no values repeated">
<Param type="unsigned int" name="seed" desc="" /> <Param type="unsigned int" name="count" desc="" />
<Param type="int" name="min" desc="" />
<Param type="int" name="max" desc="" />
</Function>
<Function name="UnloadRandomSequence" retType="void" paramCount="1" desc="Unload random values sequence">
<Param type="int *" name="sequence" desc="" />
</Function> </Function>
<Function name="TakeScreenshot" retType="void" paramCount="1" desc="Takes a screenshot of current screen (filename extension defines format)"> <Function name="TakeScreenshot" retType="void" paramCount="1" desc="Takes a screenshot of current screen (filename extension defines format)">
<Param type="const char *" name="fileName" desc="" /> <Param type="const char *" name="fileName" desc="" />
@ -950,6 +968,9 @@
<Function name="SetConfigFlags" retType="void" paramCount="1" desc="Setup init configuration flags (view FLAGS)"> <Function name="SetConfigFlags" retType="void" paramCount="1" desc="Setup init configuration flags (view FLAGS)">
<Param type="unsigned int" name="flags" desc="" /> <Param type="unsigned int" name="flags" desc="" />
</Function> </Function>
<Function name="OpenURL" retType="void" paramCount="1" desc="Open URL with default system browser (if available)">
<Param type="const char *" name="url" desc="" />
</Function>
<Function name="TraceLog" retType="void" paramCount="3" desc="Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR...)"> <Function name="TraceLog" retType="void" paramCount="3" desc="Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR...)">
<Param type="int" name="logLevel" desc="" /> <Param type="int" name="logLevel" desc="" />
<Param type="const char *" name="text" desc="" /> <Param type="const char *" name="text" desc="" />
@ -968,9 +989,6 @@
<Function name="MemFree" retType="void" paramCount="1" desc="Internal memory free"> <Function name="MemFree" retType="void" paramCount="1" desc="Internal memory free">
<Param type="void *" name="ptr" desc="" /> <Param type="void *" name="ptr" desc="" />
</Function> </Function>
<Function name="OpenURL" retType="void" paramCount="1" desc="Open URL with default system browser (if available)">
<Param type="const char *" name="url" desc="" />
</Function>
<Function name="SetTraceLogCallback" retType="void" paramCount="1" desc="Set custom trace log"> <Function name="SetTraceLogCallback" retType="void" paramCount="1" desc="Set custom trace log">
<Param type="TraceLogCallback" name="callback" desc="" /> <Param type="TraceLogCallback" name="callback" desc="" />
</Function> </Function>
@ -1091,6 +1109,29 @@
<Param type="const unsigned char *" name="data" desc="" /> <Param type="const unsigned char *" name="data" desc="" />
<Param type="int *" name="outputSize" desc="" /> <Param type="int *" name="outputSize" desc="" />
</Function> </Function>
<Function name="LoadAutomationEventList" retType="AutomationEventList" paramCount="1" desc="Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS">
<Param type="const char *" name="fileName" desc="" />
</Function>
<Function name="UnloadAutomationEventList" retType="void" paramCount="1" desc="Unload automation events list from file">
<Param type="AutomationEventList *" name="list" desc="" />
</Function>
<Function name="ExportAutomationEventList" retType="bool" paramCount="2" desc="Export automation events list as text file">
<Param type="AutomationEventList" name="list" desc="" />
<Param type="const char *" name="fileName" desc="" />
</Function>
<Function name="SetAutomationEventList" retType="void" paramCount="1" desc="Set automation event list to record to">
<Param type="AutomationEventList *" name="list" desc="" />
</Function>
<Function name="SetAutomationEventBaseFrame" retType="void" paramCount="1" desc="Set automation event internal base frame to start recording">
<Param type="int" name="frame" desc="" />
</Function>
<Function name="StartAutomationEventRecording" retType="void" paramCount="0" desc="Start recording automation events (AutomationEventList must be set)">
</Function>
<Function name="StopAutomationEventRecording" retType="void" paramCount="0" desc="Stop recording automation events">
</Function>
<Function name="PlayAutomationEvent" retType="void" paramCount="1" desc="Play a recorded automation event">
<Param type="AutomationEvent" name="event" desc="" />
</Function>
<Function name="IsKeyPressed" retType="bool" paramCount="1" desc="Check if a key has been pressed once"> <Function name="IsKeyPressed" retType="bool" paramCount="1" desc="Check if a key has been pressed once">
<Param type="int" name="key" desc="" /> <Param type="int" name="key" desc="" />
</Function> </Function>
@ -1106,13 +1147,13 @@
<Function name="IsKeyUp" retType="bool" paramCount="1" desc="Check if a key is NOT being pressed"> <Function name="IsKeyUp" retType="bool" paramCount="1" desc="Check if a key is NOT being pressed">
<Param type="int" name="key" desc="" /> <Param type="int" name="key" desc="" />
</Function> </Function>
<Function name="SetExitKey" retType="void" paramCount="1" desc="Set a custom key to exit program (default is ESC)">
<Param type="int" name="key" desc="" />
</Function>
<Function name="GetKeyPressed" retType="int" paramCount="0" desc="Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty"> <Function name="GetKeyPressed" retType="int" paramCount="0" desc="Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty">
</Function> </Function>
<Function name="GetCharPressed" retType="int" paramCount="0" desc="Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty"> <Function name="GetCharPressed" retType="int" paramCount="0" desc="Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty">
</Function> </Function>
<Function name="SetExitKey" retType="void" paramCount="1" desc="Set a custom key to exit program (default is ESC)">
<Param type="int" name="key" desc="" />
</Function>
<Function name="IsGamepadAvailable" retType="bool" paramCount="1" desc="Check if a gamepad is available"> <Function name="IsGamepadAvailable" retType="bool" paramCount="1" desc="Check if a gamepad is available">
<Param type="int" name="gamepad" desc="" /> <Param type="int" name="gamepad" desc="" />
</Function> </Function>
@ -1246,55 +1287,28 @@
<Param type="int" name="endPosY" desc="" /> <Param type="int" name="endPosY" desc="" />
<Param type="Color" name="color" desc="" /> <Param type="Color" name="color" desc="" />
</Function> </Function>
<Function name="DrawLineV" retType="void" paramCount="3" desc="Draw a line (Vector version)"> <Function name="DrawLineV" retType="void" paramCount="3" desc="Draw a line (using gl lines)">
<Param type="Vector2" name="startPos" desc="" /> <Param type="Vector2" name="startPos" desc="" />
<Param type="Vector2" name="endPos" desc="" /> <Param type="Vector2" name="endPos" desc="" />
<Param type="Color" name="color" desc="" /> <Param type="Color" name="color" desc="" />
</Function> </Function>
<Function name="DrawLineEx" retType="void" paramCount="4" desc="Draw a line defining thickness"> <Function name="DrawLineEx" retType="void" paramCount="4" desc="Draw a line (using triangles/quads)">
<Param type="Vector2" name="startPos" desc="" /> <Param type="Vector2" name="startPos" desc="" />
<Param type="Vector2" name="endPos" desc="" /> <Param type="Vector2" name="endPos" desc="" />
<Param type="float" name="thick" desc="" /> <Param type="float" name="thick" desc="" />
<Param type="Color" name="color" desc="" /> <Param type="Color" name="color" desc="" />
</Function> </Function>
<Function name="DrawLineBezier" retType="void" paramCount="4" desc="Draw a line using cubic-bezier curves in-out"> <Function name="DrawLineStrip" retType="void" paramCount="3" desc="Draw lines sequence (using gl lines)">
<Param type="Vector2" name="startPos" desc="" />
<Param type="Vector2" name="endPos" desc="" />
<Param type="float" name="thick" desc="" />
<Param type="Color" name="color" desc="" />
</Function>
<Function name="DrawLineBezierQuad" retType="void" paramCount="5" desc="Draw line using quadratic bezier curves with a control point">
<Param type="Vector2" name="startPos" desc="" />
<Param type="Vector2" name="endPos" desc="" />
<Param type="Vector2" name="controlPos" desc="" />
<Param type="float" name="thick" desc="" />
<Param type="Color" name="color" desc="" />
</Function>
<Function name="DrawLineBezierCubic" retType="void" paramCount="6" desc="Draw line using cubic bezier curves with 2 control points">
<Param type="Vector2" name="startPos" desc="" />
<Param type="Vector2" name="endPos" desc="" />
<Param type="Vector2" name="startControlPos" desc="" />
<Param type="Vector2" name="endControlPos" desc="" />
<Param type="float" name="thick" desc="" />
<Param type="Color" name="color" desc="" />
</Function>
<Function name="DrawLineBSpline" retType="void" paramCount="4" desc="Draw a B-Spline line, minimum 4 points">
<Param type="Vector2 *" name="points" desc="" /> <Param type="Vector2 *" name="points" desc="" />
<Param type="int" name="pointCount" desc="" /> <Param type="int" name="pointCount" desc="" />
<Param type="float" name="thick" desc="" />
<Param type="Color" name="color" desc="" /> <Param type="Color" name="color" desc="" />
</Function> </Function>
<Function name="DrawLineCatmullRom" retType="void" paramCount="4" desc="Draw a Catmull Rom spline line, minimum 4 points"> <Function name="DrawLineBezier" retType="void" paramCount="4" desc="Draw line segment cubic-bezier in-out interpolation">
<Param type="Vector2 *" name="points" desc="" /> <Param type="Vector2" name="startPos" desc="" />
<Param type="int" name="pointCount" desc="" /> <Param type="Vector2" name="endPos" desc="" />
<Param type="float" name="thick" desc="" /> <Param type="float" name="thick" desc="" />
<Param type="Color" name="color" desc="" /> <Param type="Color" name="color" desc="" />
</Function> </Function>
<Function name="DrawLineStrip" retType="void" paramCount="3" desc="Draw lines sequence">
<Param type="Vector2 *" name="points" desc="" />
<Param type="int" name="pointCount" desc="" />
<Param type="Color" name="color" desc="" />
</Function>
<Function name="DrawCircle" retType="void" paramCount="4" desc="Draw a color-filled circle"> <Function name="DrawCircle" retType="void" paramCount="4" desc="Draw a color-filled circle">
<Param type="int" name="centerX" desc="" /> <Param type="int" name="centerX" desc="" />
<Param type="int" name="centerY" desc="" /> <Param type="int" name="centerY" desc="" />
@ -1335,6 +1349,11 @@
<Param type="float" name="radius" desc="" /> <Param type="float" name="radius" desc="" />
<Param type="Color" name="color" desc="" /> <Param type="Color" name="color" desc="" />
</Function> </Function>
<Function name="DrawCircleLinesV" retType="void" paramCount="3" desc="Draw circle outline (Vector version)">
<Param type="Vector2" name="center" desc="" />
<Param type="float" name="radius" desc="" />
<Param type="Color" name="color" desc="" />
</Function>
<Function name="DrawEllipse" retType="void" paramCount="5" desc="Draw ellipse"> <Function name="DrawEllipse" retType="void" paramCount="5" desc="Draw ellipse">
<Param type="int" name="centerX" desc="" /> <Param type="int" name="centerX" desc="" />
<Param type="int" name="centerY" desc="" /> <Param type="int" name="centerY" desc="" />
@ -1481,6 +1500,105 @@
<Param type="float" name="lineThick" desc="" /> <Param type="float" name="lineThick" desc="" />
<Param type="Color" name="color" desc="" /> <Param type="Color" name="color" desc="" />
</Function> </Function>
<Function name="DrawSplineLinear" retType="void" paramCount="4" desc="Draw spline: Linear, minimum 2 points">
<Param type="Vector2 *" name="points" desc="" />
<Param type="int" name="pointCount" desc="" />
<Param type="float" name="thick" desc="" />
<Param type="Color" name="color" desc="" />
</Function>
<Function name="DrawSplineBasis" retType="void" paramCount="4" desc="Draw spline: B-Spline, minimum 4 points">
<Param type="Vector2 *" name="points" desc="" />
<Param type="int" name="pointCount" desc="" />
<Param type="float" name="thick" desc="" />
<Param type="Color" name="color" desc="" />
</Function>
<Function name="DrawSplineCatmullRom" retType="void" paramCount="4" desc="Draw spline: Catmull-Rom, minimum 4 points">
<Param type="Vector2 *" name="points" desc="" />
<Param type="int" name="pointCount" desc="" />
<Param type="float" name="thick" desc="" />
<Param type="Color" name="color" desc="" />
</Function>
<Function name="DrawSplineBezierQuadratic" retType="void" paramCount="4" desc="Draw spline: Quadratic Bezier, minimum 3 points (1 control point): [p1, c2, p3, c4...]">
<Param type="Vector2 *" name="points" desc="" />
<Param type="int" name="pointCount" desc="" />
<Param type="float" name="thick" desc="" />
<Param type="Color" name="color" desc="" />
</Function>
<Function name="DrawSplineBezierCubic" retType="void" paramCount="4" desc="Draw spline: Cubic Bezier, minimum 4 points (2 control points): [p1, c2, c3, p4, c5, c6...]">
<Param type="Vector2 *" name="points" desc="" />
<Param type="int" name="pointCount" desc="" />
<Param type="float" name="thick" desc="" />
<Param type="Color" name="color" desc="" />
</Function>
<Function name="DrawSplineSegmentLinear" retType="void" paramCount="4" desc="Draw spline segment: Linear, 2 points">
<Param type="Vector2" name="p1" desc="" />
<Param type="Vector2" name="p2" desc="" />
<Param type="float" name="thick" desc="" />
<Param type="Color" name="color" desc="" />
</Function>
<Function name="DrawSplineSegmentBasis" retType="void" paramCount="6" desc="Draw spline segment: B-Spline, 4 points">
<Param type="Vector2" name="p1" desc="" />
<Param type="Vector2" name="p2" desc="" />
<Param type="Vector2" name="p3" desc="" />
<Param type="Vector2" name="p4" desc="" />
<Param type="float" name="thick" desc="" />
<Param type="Color" name="color" desc="" />
</Function>
<Function name="DrawSplineSegmentCatmullRom" retType="void" paramCount="6" desc="Draw spline segment: Catmull-Rom, 4 points">
<Param type="Vector2" name="p1" desc="" />
<Param type="Vector2" name="p2" desc="" />
<Param type="Vector2" name="p3" desc="" />
<Param type="Vector2" name="p4" desc="" />
<Param type="float" name="thick" desc="" />
<Param type="Color" name="color" desc="" />
</Function>
<Function name="DrawSplineSegmentBezierQuadratic" retType="void" paramCount="5" desc="Draw spline segment: Quadratic Bezier, 2 points, 1 control point">
<Param type="Vector2" name="p1" desc="" />
<Param type="Vector2" name="c2" desc="" />
<Param type="Vector2" name="p3" desc="" />
<Param type="float" name="thick" desc="" />
<Param type="Color" name="color" desc="" />
</Function>
<Function name="DrawSplineSegmentBezierCubic" retType="void" paramCount="6" desc="Draw spline segment: Cubic Bezier, 2 points, 2 control points">
<Param type="Vector2" name="p1" desc="" />
<Param type="Vector2" name="c2" desc="" />
<Param type="Vector2" name="c3" desc="" />
<Param type="Vector2" name="p4" desc="" />
<Param type="float" name="thick" desc="" />
<Param type="Color" name="color" desc="" />
</Function>
<Function name="GetSplinePointLinear" retType="Vector2" paramCount="3" desc="Get (evaluate) spline point: Linear">
<Param type="Vector2" name="startPos" desc="" />
<Param type="Vector2" name="endPos" desc="" />
<Param type="float" name="t" desc="" />
</Function>
<Function name="GetSplinePointBasis" retType="Vector2" paramCount="5" desc="Get (evaluate) spline point: B-Spline">
<Param type="Vector2" name="p1" desc="" />
<Param type="Vector2" name="p2" desc="" />
<Param type="Vector2" name="p3" desc="" />
<Param type="Vector2" name="p4" desc="" />
<Param type="float" name="t" desc="" />
</Function>
<Function name="GetSplinePointCatmullRom" retType="Vector2" paramCount="5" desc="Get (evaluate) spline point: Catmull-Rom">
<Param type="Vector2" name="p1" desc="" />
<Param type="Vector2" name="p2" desc="" />
<Param type="Vector2" name="p3" desc="" />
<Param type="Vector2" name="p4" desc="" />
<Param type="float" name="t" desc="" />
</Function>
<Function name="GetSplinePointBezierQuad" retType="Vector2" paramCount="4" desc="Get (evaluate) spline point: Quadratic Bezier">
<Param type="Vector2" name="p1" desc="" />
<Param type="Vector2" name="c2" desc="" />
<Param type="Vector2" name="p3" desc="" />
<Param type="float" name="t" desc="" />
</Function>
<Function name="GetSplinePointBezierCubic" retType="Vector2" paramCount="5" desc="Get (evaluate) spline point: Cubic Bezier">
<Param type="Vector2" name="p1" desc="" />
<Param type="Vector2" name="c2" desc="" />
<Param type="Vector2" name="c3" desc="" />
<Param type="Vector2" name="p4" desc="" />
<Param type="float" name="t" desc="" />
</Function>
<Function name="CheckCollisionRecs" retType="bool" paramCount="2" desc="Check collision between two rectangles"> <Function name="CheckCollisionRecs" retType="bool" paramCount="2" desc="Check collision between two rectangles">
<Param type="Rectangle" name="rec1" desc="" /> <Param type="Rectangle" name="rec1" desc="" />
<Param type="Rectangle" name="rec2" desc="" /> <Param type="Rectangle" name="rec2" desc="" />
@ -1688,6 +1806,11 @@
<Param type="Image *" name="image" desc="" /> <Param type="Image *" name="image" desc="" />
<Param type="int" name="blurSize" desc="" /> <Param type="int" name="blurSize" desc="" />
</Function> </Function>
<Function name="ImageKernelConvolution" retType="void" paramCount="3" desc="Apply Custom Square image convolution kernel">
<Param type="Image *" name="image" desc="" />
<Param type="float*" name="kernel" desc="" />
<Param type="int" name="kernelSize" desc="" />
</Function>
<Function name="ImageResize" retType="void" paramCount="3" desc="Resize image (Bicubic scaling algorithm)"> <Function name="ImageResize" retType="void" paramCount="3" desc="Resize image (Bicubic scaling algorithm)">
<Param type="Image *" name="image" desc="" /> <Param type="Image *" name="image" desc="" />
<Param type="int" name="newWidth" desc="" /> <Param type="int" name="newWidth" desc="" />
@ -2632,6 +2755,8 @@
<Function name="SetMasterVolume" retType="void" paramCount="1" desc="Set master volume (listener)"> <Function name="SetMasterVolume" retType="void" paramCount="1" desc="Set master volume (listener)">
<Param type="float" name="volume" desc="" /> <Param type="float" name="volume" desc="" />
</Function> </Function>
<Function name="GetMasterVolume" retType="float" paramCount="0" desc="Get master volume (listener)">
</Function>
<Function name="LoadWave" retType="Wave" paramCount="1" desc="Load wave data from file"> <Function name="LoadWave" retType="Wave" paramCount="1" desc="Load wave data from file">
<Param type="const char *" name="fileName" desc="" /> <Param type="const char *" name="fileName" desc="" />
</Function> </Function>

View File

@ -5,7 +5,7 @@ project(example)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Dependencies # Dependencies
set(RAYLIB_VERSION 4.5.0) set(RAYLIB_VERSION 5.0)
find_package(raylib ${RAYLIB_VERSION} QUIET) # QUIET or REQUIRED find_package(raylib ${RAYLIB_VERSION} QUIET) # QUIET or REQUIRED
if (NOT raylib_FOUND) # If there's none, fetch and build raylib if (NOT raylib_FOUND) # If there's none, fetch and build raylib
include(FetchContent) include(FetchContent)

View File

@ -375,6 +375,7 @@ RLAPI void ImageAlphaClear(Image *image, Color color, float threshold);
RLAPI void ImageAlphaMask(Image *image, Image alphaMask); // Apply alpha mask to image RLAPI void ImageAlphaMask(Image *image, Image alphaMask); // Apply alpha mask to image
RLAPI void ImageAlphaPremultiply(Image *image); // Premultiply alpha channel RLAPI void ImageAlphaPremultiply(Image *image); // Premultiply alpha channel
RLAPI void ImageBlurGaussian(Image *image, int blurSize); // Apply Gaussian blur using a box blur approximation RLAPI void ImageBlurGaussian(Image *image, int blurSize); // Apply Gaussian blur using a box blur approximation
RLAPI void ImageKernelConvolution(Image *image, float* kernel, int kernelSize); // Apply Custom Square image convolution kernel
RLAPI void ImageResize(Image *image, int newWidth, int newHeight); // Resize image (Bicubic scaling algorithm) RLAPI void ImageResize(Image *image, int newWidth, int newHeight); // Resize image (Bicubic scaling algorithm)
RLAPI void ImageResizeNN(Image *image, int newWidth,int newHeight); // Resize image (Nearest-Neighbor scaling algorithm) RLAPI void ImageResizeNN(Image *image, int newWidth,int newHeight); // Resize image (Nearest-Neighbor scaling algorithm)
RLAPI void ImageResizeCanvas(Image *image, int newWidth, int newHeight, int offsetX, int offsetY, Color fill); // Resize canvas and fill with color RLAPI void ImageResizeCanvas(Image *image, int newWidth, int newHeight, int offsetX, int offsetY, Color fill); // Resize canvas and fill with color

View File

@ -1,7 +1,7 @@
# Setup the project and settings # Setup the project and settings
project(raylib C) project(raylib C)
set(PROJECT_VERSION 4.5.0) set(PROJECT_VERSION 5.0.0)
set(API_VERSION 450) set(API_VERSION 500)
include(GNUInstallDirs) include(GNUInstallDirs)
include(JoinPaths) include(JoinPaths)
@ -62,12 +62,10 @@ if (NOT BUILD_SHARED_LIBS)
add_library(raylib_static ALIAS raylib) add_library(raylib_static ALIAS raylib)
else() else()
MESSAGE(STATUS "Building raylib shared library") MESSAGE(STATUS "Building raylib shared library")
if (WIN32) target_compile_definitions(raylib
target_compile_definitions(raylib PRIVATE $<BUILD_INTERFACE:BUILD_LIBTYPE_SHARED>
PRIVATE $<BUILD_INTERFACE:BUILD_LIBTYPE_SHARED> INTERFACE $<INSTALL_INTERFACE:USE_LIBTYPE_SHARED>
INTERFACE $<INSTALL_INTERFACE:USE_LIBTYPE_SHARED> )
)
endif ()
endif() endif()
if (${PLATFORM} MATCHES "Web") if (${PLATFORM} MATCHES "Web")
@ -84,6 +82,11 @@ if (WITH_PIC OR BUILD_SHARED_LIBS)
set_property(TARGET raylib PROPERTY POSITION_INDEPENDENT_CODE ON) set_property(TARGET raylib PROPERTY POSITION_INDEPENDENT_CODE ON)
endif () endif ()
if (BUILD_SHARED_LIBS)
# Hide raylib's symbols by default so RLAPI can expose them
set_property(TARGET raylib PROPERTY C_VISIBILITY_PRESET hidden)
endif ()
target_link_libraries(raylib "${LIBS_PRIVATE}") target_link_libraries(raylib "${LIBS_PRIVATE}")
# Sets some compile time definitions for the pre-processor # Sets some compile time definitions for the pre-processor

View File

@ -114,7 +114,7 @@ HOST_PLATFORM_OS ?= WINDOWS
PLATFORM_OS ?= WINDOWS PLATFORM_OS ?= WINDOWS
# Determine PLATFORM_OS when required # Determine PLATFORM_OS when required
ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_DESKTOP PLATFORM_DESKTOP_SDL PLATFORM_WEB)) ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_DESKTOP PLATFORM_DESKTOP_SDL PLATFORM_WEB PLATFORM_ANDROID))
# No uname.exe on MinGW!, but OS=Windows_NT on Windows! # No uname.exe on MinGW!, but OS=Windows_NT on Windows!
# ifeq ($(UNAME),Msys) -> Windows # ifeq ($(UNAME),Msys) -> Windows
ifeq ($(OS),Windows_NT) ifeq ($(OS),Windows_NT)
@ -189,8 +189,12 @@ ifeq ($(PLATFORM),PLATFORM_ANDROID)
ANDROID_NDK ?= C:/android-ndk ANDROID_NDK ?= C:/android-ndk
ANDROID_TOOLCHAIN = $(ANDROID_NDK)/toolchains/llvm/prebuilt/windows-x86_64 ANDROID_TOOLCHAIN = $(ANDROID_NDK)/toolchains/llvm/prebuilt/windows-x86_64
else else
ANDROID_NDK ?= /usr/lib/android/ndk ANDROID_NDK ?= /usr/lib/android/ndk
ANDROID_TOOLCHAIN = $(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64 ifeq ($(PLATFORM_OS), OSX)
ANDROID_TOOLCHAIN = $(ANDROID_NDK)/toolchains/llvm/prebuilt/darwin-x86_64
else
ANDROID_TOOLCHAIN = $(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64
endif
endif endif
# NOTE: Sysroot can also be reference from $(ANDROID_NDK)/sysroot # NOTE: Sysroot can also be reference from $(ANDROID_NDK)/sysroot
@ -376,7 +380,7 @@ ifeq ($(PLATFORM),PLATFORM_ANDROID)
# -Werror=format-security # -Werror=format-security
CFLAGS += -Wa,--noexecstack -Wformat -no-canonical-prefixes CFLAGS += -Wa,--noexecstack -Wformat -no-canonical-prefixes
# Preprocessor macro definitions # Preprocessor macro definitions
CFLAGS += -D__ANDROID__ -DPLATFORM_ANDROID -D__ANDROID_API__=$(ANDROID_API_VERSION) -DMAL_NO_OSS CFLAGS += -D__ANDROID__ -DPLATFORM_ANDROID -D__ANDROID_API__=$(ANDROID_API_VERSION)
endif endif
# Define required compilation flags for raylib SHARED lib # Define required compilation flags for raylib SHARED lib
@ -385,7 +389,13 @@ ifeq ($(RAYLIB_LIBTYPE),SHARED)
# BE CAREFUL: It seems that for gcc -fpic is not the same as -fPIC # BE CAREFUL: It seems that for gcc -fpic is not the same as -fPIC
# MinGW32 just doesn't need -fPIC, it shows warnings # MinGW32 just doesn't need -fPIC, it shows warnings
CFLAGS += -fPIC -DBUILD_LIBTYPE_SHARED CFLAGS += -fPIC -DBUILD_LIBTYPE_SHARED
# hide all symbols by default, so RLAPI can expose them
ifeq ($(PLATFORM_OS),$(filter $(PLATFORM_OS), LINUX BSD OSX))
CFLAGS += -fvisibility=hidden
endif
endif endif
ifeq ($(PLATFORM),PLATFORM_DRM) ifeq ($(PLATFORM),PLATFORM_DRM)
# without EGL_NO_X11 eglplatform.h tears Xlib.h in which tears X.h in # without EGL_NO_X11 eglplatform.h tears Xlib.h in which tears X.h in
# which contains a conflicting type Font # which contains a conflicting type Font

View File

@ -200,8 +200,7 @@ int *rprand_load_sequence(unsigned int count, int min, int max)
for (unsigned int i = 0; i < count;) for (unsigned int i = 0; i < count;)
{ {
value = ((int)rprand_xoshiro()%(abs(max - min) + 1)) + min; value = ((unsigned int)rprand_xoshiro()%(abs(max - min) + 1)) + min;
value_is_dup = false;
for (int j = 0; j < i; j++) for (int j = 0; j < i; j++)
{ {
@ -217,6 +216,8 @@ int *rprand_load_sequence(unsigned int count, int min, int max)
sequence[i] = value; sequence[i] = value;
i++; i++;
} }
value_is_dup = false;
} }
return sequence; return sequence;

View File

@ -129,7 +129,7 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i
static void CharCallback(GLFWwindow *window, unsigned int key); // GLFW3 Char Key Callback, runs on key pressed (get char value) static void CharCallback(GLFWwindow *window, unsigned int key); // GLFW3 Char Key Callback, runs on key pressed (get char value)
static void MouseButtonCallback(GLFWwindow *window, int button, int action, int mods); // GLFW3 Mouse Button Callback, runs on mouse button pressed static void MouseButtonCallback(GLFWwindow *window, int button, int action, int mods); // GLFW3 Mouse Button Callback, runs on mouse button pressed
static void MouseCursorPosCallback(GLFWwindow *window, double x, double y); // GLFW3 Cursor Position Callback, runs on mouse move static void MouseCursorPosCallback(GLFWwindow *window, double x, double y); // GLFW3 Cursor Position Callback, runs on mouse move
static void MouseScrollCallback(GLFWwindow *window, double xoffset, double yoffset); // GLFW3 Srolling Callback, runs on mouse wheel static void MouseScrollCallback(GLFWwindow *window, double xoffset, double yoffset); // GLFW3 Scrolling Callback, runs on mouse wheel
static void CursorEnterCallback(GLFWwindow *window, int enter); // GLFW3 Cursor Enter Callback, cursor enters client area static void CursorEnterCallback(GLFWwindow *window, int enter); // GLFW3 Cursor Enter Callback, cursor enters client area
static void JoystickCallback(int jid, int event); // GLFW3 Joystick Connected/Disconnected Callback static void JoystickCallback(int jid, int event); // GLFW3 Joystick Connected/Disconnected Callback
@ -1137,7 +1137,7 @@ void PollInputEvents(void)
//for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.position[i] = (Vector2){ 0, 0 }; //for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.position[i] = (Vector2){ 0, 0 };
// Map touch position to mouse position for convenience // Map touch position to mouse position for convenience
// WARNING: If the target desktop device supports touch screen, this behavious should be reviewed! // WARNING: If the target desktop device supports touch screen, this behaviour should be reviewed!
// TODO: GLFW does not support multi-touch input just yet // TODO: GLFW does not support multi-touch input just yet
// https://www.codeproject.com/Articles/668404/Programming-for-Multi-Touch // https://www.codeproject.com/Articles/668404/Programming-for-Multi-Touch
// https://docs.microsoft.com/en-us/windows/win32/wintouch/getting-started-with-multi-touch-messages // https://docs.microsoft.com/en-us/windows/win32/wintouch/getting-started-with-multi-touch-messages
@ -1739,6 +1739,7 @@ static void MouseButtonCallback(GLFWwindow *window, int button, int action, int
// WARNING: GLFW could only return GLFW_PRESS (1) or GLFW_RELEASE (0) for now, // WARNING: GLFW could only return GLFW_PRESS (1) or GLFW_RELEASE (0) for now,
// but future releases may add more actions (i.e. GLFW_REPEAT) // but future releases may add more actions (i.e. GLFW_REPEAT)
CORE.Input.Mouse.currentButtonState[button] = action; CORE.Input.Mouse.currentButtonState[button] = action;
CORE.Input.Touch.currentTouchState[button] = action;
#if defined(SUPPORT_GESTURES_SYSTEM) && defined(SUPPORT_MOUSE_GESTURES) #if defined(SUPPORT_GESTURES_SYSTEM) && defined(SUPPORT_MOUSE_GESTURES)
// Process mouse events as touches to be able to use mouse-gestures // Process mouse events as touches to be able to use mouse-gestures

View File

@ -48,8 +48,14 @@
* *
**********************************************************************************************/ **********************************************************************************************/
#include "SDL.h" // SDL base library (window/rendered, input, timming... functionality) #include "SDL.h" // SDL base library (window/rendered, input, timing... functionality)
#include "SDL_opengl.h" // SDL OpenGL functionality (if required, instead of internal renderer)
#if defined(GRAPHICS_API_OPENGL_ES2)
// It seems it does not need to be included to work
//#include "SDL_opengles2.h"
#else
#include "SDL_opengl.h" // SDL OpenGL functionality (if required, instead of internal renderer)
#endif
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Types and Structures Definition // Types and Structures Definition
@ -493,9 +499,9 @@ void SetWindowIcon(Image image)
bmask = 0x001F, amask = 0; bmask = 0x001F, amask = 0;
depth = 16, pitch = image.width * 2; depth = 16, pitch = image.width * 2;
break; break;
case PIXELFORMAT_UNCOMPRESSED_R8G8B8: case PIXELFORMAT_UNCOMPRESSED_R8G8B8: // Uses BGR for 24-bit
rmask = 0xFF0000, gmask = 0x00FF00; rmask = 0x0000FF, gmask = 0x00FF00;
bmask = 0x0000FF, amask = 0; bmask = 0xFF0000, amask = 0;
depth = 24, pitch = image.width * 3; depth = 24, pitch = image.width * 3;
break; break;
case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1:
@ -592,7 +598,7 @@ void SetWindowMonitor(int monitor)
// NOTE: // NOTE:
// 1. SDL started supporting moving exclusive fullscreen windows between displays on SDL3, // 1. SDL started supporting moving exclusive fullscreen windows between displays on SDL3,
// see commit https://github.com/libsdl-org/SDL/commit/3f5ef7dd422057edbcf3e736107e34be4b75d9ba // see commit https://github.com/libsdl-org/SDL/commit/3f5ef7dd422057edbcf3e736107e34be4b75d9ba
// 2. A workround for SDL2 is leaving fullscreen, moving the window, then entering full screen again. // 2. A workaround for SDL2 is leaving fullscreen, moving the window, then entering full screen again.
const bool wasFullscreen = ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) ? true : false; const bool wasFullscreen = ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) ? true : false;
const int screenWidth = CORE.Window.screen.width; const int screenWidth = CORE.Window.screen.width;
@ -611,7 +617,7 @@ void SetWindowMonitor(int monitor)
// ending up positioned partly outside the target display. // ending up positioned partly outside the target display.
// 2. The workaround for that is, previously to moving the window, // 2. The workaround for that is, previously to moving the window,
// setting the window size to the target display size, so they match. // setting the window size to the target display size, so they match.
// 3. It was't done here because we can't assume changing the window size automatically // 3. It wasn't done here because we can't assume changing the window size automatically
// is acceptable behavior by the user. // is acceptable behavior by the user.
SDL_SetWindowPosition(platform.window, usableBounds.x, usableBounds.y); SDL_SetWindowPosition(platform.window, usableBounds.x, usableBounds.y);
CORE.Window.position.x = usableBounds.x; CORE.Window.position.x = usableBounds.x;
@ -935,6 +941,8 @@ int SetGamepadMappings(const char *mappings)
// Set mouse position XY // Set mouse position XY
void SetMousePosition(int x, int y) void SetMousePosition(int x, int y)
{ {
SDL_WarpMouseInWindow(platform.window, x, y);
CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y }; CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
} }
@ -961,9 +969,6 @@ void PollInputEvents(void)
CORE.Input.Keyboard.keyPressedQueueCount = 0; CORE.Input.Keyboard.keyPressedQueueCount = 0;
CORE.Input.Keyboard.charPressedQueueCount = 0; CORE.Input.Keyboard.charPressedQueueCount = 0;
// Reset key repeats
for (int i = 0; i < MAX_KEYBOARD_KEYS; i++) CORE.Input.Keyboard.keyRepeatInFrame[i] = 0;
// Reset mouse wheel // Reset mouse wheel
CORE.Input.Mouse.currentWheelMove.x = 0; CORE.Input.Mouse.currentWheelMove.x = 0;
CORE.Input.Mouse.currentWheelMove.y = 0; CORE.Input.Mouse.currentWheelMove.y = 0;
@ -991,7 +996,7 @@ void PollInputEvents(void)
CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition; CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;
int touchAction = -1; // 0-TOUCH_ACTION_UP, 1-TOUCH_ACTION_DOWN, 2-TOUCH_ACTION_MOVE int touchAction = -1; // 0-TOUCH_ACTION_UP, 1-TOUCH_ACTION_DOWN, 2-TOUCH_ACTION_MOVE
bool gestureUpdate = false; // Flag to note gestures require to update bool realTouch = false; // Flag to differentiate real touch gestures from mouse ones
// Register previous keys states // Register previous keys states
// NOTE: Android supports up to 260 keys // NOTE: Android supports up to 260 keys
@ -1004,7 +1009,7 @@ void PollInputEvents(void)
// Register previous mouse states // Register previous mouse states
for (int i = 0; i < MAX_MOUSE_BUTTONS; i++) CORE.Input.Mouse.previousButtonState[i] = CORE.Input.Mouse.currentButtonState[i]; for (int i = 0; i < MAX_MOUSE_BUTTONS; i++) CORE.Input.Mouse.previousButtonState[i] = CORE.Input.Mouse.currentButtonState[i];
// Poll input events for current plaform // Poll input events for current platform
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/* /*
// WARNING: Indexes into this array are obtained by using SDL_Scancode values, not SDL_Keycode values // WARNING: Indexes into this array are obtained by using SDL_Scancode values, not SDL_Keycode values
@ -1089,6 +1094,8 @@ void PollInputEvents(void)
KeyboardKey key = ConvertScancodeToKey(event.key.keysym.scancode); KeyboardKey key = ConvertScancodeToKey(event.key.keysym.scancode);
if (key != KEY_NULL) CORE.Input.Keyboard.currentKeyState[key] = 1; if (key != KEY_NULL) CORE.Input.Keyboard.currentKeyState[key] = 1;
if (event.key.repeat) CORE.Input.Keyboard.keyRepeatInFrame[key] = 1;
// TODO: Put exitKey verification outside the switch? // TODO: Put exitKey verification outside the switch?
if (CORE.Input.Keyboard.currentKeyState[CORE.Input.Keyboard.exitKey]) if (CORE.Input.Keyboard.currentKeyState[CORE.Input.Keyboard.exitKey])
{ {
@ -1102,6 +1109,25 @@ void PollInputEvents(void)
if (key != KEY_NULL) CORE.Input.Keyboard.currentKeyState[key] = 0; if (key != KEY_NULL) CORE.Input.Keyboard.currentKeyState[key] = 0;
} break; } break;
case SDL_TEXTINPUT:
{
// Check if there is space available in the key queue
if (CORE.Input.Keyboard.keyPressedQueueCount < MAX_KEY_PRESSED_QUEUE)
{
// Add character to the queue
CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = event.text.text[0];
CORE.Input.Keyboard.keyPressedQueueCount++;
}
// Check if there is space available in the queue
if (CORE.Input.Keyboard.charPressedQueueCount < MAX_CHAR_PRESSED_QUEUE)
{
// Add character to the queue
CORE.Input.Keyboard.charPressedQueue[CORE.Input.Keyboard.charPressedQueueCount] = event.text.text[0];
CORE.Input.Keyboard.charPressedQueueCount++;
}
} break;
// Check mouse events // Check mouse events
case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONDOWN:
{ {
@ -1112,9 +1138,9 @@ void PollInputEvents(void)
else if (btn == 1) btn = 2; else if (btn == 1) btn = 2;
CORE.Input.Mouse.currentButtonState[btn] = 1; CORE.Input.Mouse.currentButtonState[btn] = 1;
CORE.Input.Touch.currentTouchState[btn] = 1;
touchAction = 1; touchAction = 1;
gestureUpdate = true;
} break; } break;
case SDL_MOUSEBUTTONUP: case SDL_MOUSEBUTTONUP:
{ {
@ -1125,9 +1151,9 @@ void PollInputEvents(void)
else if (btn == 1) btn = 2; else if (btn == 1) btn = 2;
CORE.Input.Mouse.currentButtonState[btn] = 0; CORE.Input.Mouse.currentButtonState[btn] = 0;
CORE.Input.Touch.currentTouchState[btn] = 0;
touchAction = 0; touchAction = 0;
gestureUpdate = true;
} break; } break;
case SDL_MOUSEWHEEL: case SDL_MOUSEWHEEL:
{ {
@ -1150,7 +1176,38 @@ void PollInputEvents(void)
CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition; CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;
touchAction = 2; touchAction = 2;
gestureUpdate = true; } break;
// Check touch events
// NOTE: These cases need to be reviewed on a real touch screen
case SDL_FINGERDOWN:
{
const int touchId = (int)event.tfinger.fingerId;
CORE.Input.Touch.currentTouchState[touchId] = 1;
CORE.Input.Touch.position[touchId].x = event.tfinger.x * CORE.Window.screen.width;
CORE.Input.Touch.position[touchId].y = event.tfinger.y * CORE.Window.screen.height;
touchAction = 1;
realTouch = true;
} break;
case SDL_FINGERUP:
{
const int touchId = (int)event.tfinger.fingerId;
CORE.Input.Touch.currentTouchState[touchId] = 0;
CORE.Input.Touch.position[touchId].x = event.tfinger.x * CORE.Window.screen.width;
CORE.Input.Touch.position[touchId].y = event.tfinger.y * CORE.Window.screen.height;
touchAction = 0;
realTouch = true;
} break;
case SDL_FINGERMOTION:
{
const int touchId = (int)event.tfinger.fingerId;
CORE.Input.Touch.position[touchId].x = event.tfinger.x * CORE.Window.screen.width;
CORE.Input.Touch.position[touchId].y = event.tfinger.y * CORE.Window.screen.height;
touchAction = 2;
realTouch = true;
} break; } break;
// Check gamepad events // Check gamepad events
@ -1175,7 +1232,7 @@ void PollInputEvents(void)
} }
#if defined(SUPPORT_GESTURES_SYSTEM) #if defined(SUPPORT_GESTURES_SYSTEM)
if (gestureUpdate) if (touchAction > -1)
{ {
// Process mouse events as touches to be able to use mouse-gestures // Process mouse events as touches to be able to use mouse-gestures
GestureEvent gestureEvent = { 0 }; GestureEvent gestureEvent = { 0 };
@ -1190,7 +1247,7 @@ void PollInputEvents(void)
gestureEvent.pointCount = 1; gestureEvent.pointCount = 1;
// Register touch points position, only one point registered // Register touch points position, only one point registered
if (touchAction == 2) gestureEvent.position[0] = CORE.Input.Touch.position[0]; if (touchAction == 2 || realTouch) gestureEvent.position[0] = CORE.Input.Touch.position[0];
else gestureEvent.position[0] = GetMousePosition(); else gestureEvent.position[0] = GetMousePosition();
// Normalize gestureEvent.position[0] for CORE.Window.screen.width and CORE.Window.screen.height // Normalize gestureEvent.position[0] for CORE.Window.screen.width and CORE.Window.screen.height
@ -1199,6 +1256,8 @@ void PollInputEvents(void)
// Gesture data is sent to gestures-system for processing // Gesture data is sent to gestures-system for processing
ProcessGestureEvent(gestureEvent); ProcessGestureEvent(gestureEvent);
touchAction = -1;
} }
#endif #endif
} }
@ -1310,7 +1369,7 @@ int InitPlatform(void)
// Init OpenGL context // Init OpenGL context
platform.glContext = SDL_GL_CreateContext(platform.window); platform.glContext = SDL_GL_CreateContext(platform.window);
// Check window and glContext have been initialized succesfully // Check window and glContext have been initialized successfully
if ((platform.window != NULL) && (platform.glContext != NULL)) if ((platform.window != NULL) && (platform.glContext != NULL))
{ {
CORE.Window.ready = true; CORE.Window.ready = true;
@ -1351,10 +1410,15 @@ int InitPlatform(void)
//if (platform.gamepadgamepad == NULL) TRACELOG(LOG_WARNING, "PLATFORM: Unable to open game controller [ERROR: %s]", SDL_GetError()); //if (platform.gamepadgamepad == NULL) TRACELOG(LOG_WARNING, "PLATFORM: Unable to open game controller [ERROR: %s]", SDL_GetError());
} }
// Disable mouse events being interpreted as touch events
// NOTE: This is wanted because there are SDL_FINGER* events available which provide unique data
// Due to the way PollInputEvents() and rgestures.h are currently implemented, setting this won't break SUPPORT_MOUSE_GESTURES
SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");
SDL_EventState(SDL_DROPFILE, SDL_ENABLE); SDL_EventState(SDL_DROPFILE, SDL_ENABLE);
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Initialize timming system // Initialize timing system
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// NOTE: No need to call InitTimer(), let SDL manage it internally // NOTE: No need to call InitTimer(), let SDL manage it internally
CORE.Time.previous = GetTime(); // Get time as double CORE.Time.previous = GetTime(); // Get time as double

View File

@ -545,9 +545,6 @@ void PollInputEvents(void)
CORE.Input.Keyboard.keyPressedQueueCount = 0; CORE.Input.Keyboard.keyPressedQueueCount = 0;
CORE.Input.Keyboard.charPressedQueueCount = 0; CORE.Input.Keyboard.charPressedQueueCount = 0;
// Reset key repeats
for (int i = 0; i < MAX_KEYBOARD_KEYS; i++) CORE.Input.Keyboard.keyRepeatInFrame[i] = 0;
// Reset last gamepad button/axis registered state // Reset last gamepad button/axis registered state
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
//CORE.Input.Gamepad.axisCount = 0; //CORE.Input.Gamepad.axisCount = 0;
@ -573,6 +570,7 @@ void PollInputEvents(void)
{ {
CORE.Input.Mouse.previousButtonState[i] = CORE.Input.Mouse.currentButtonState[i]; CORE.Input.Mouse.previousButtonState[i] = CORE.Input.Mouse.currentButtonState[i];
CORE.Input.Mouse.currentButtonState[i] = platform.currentButtonStateEvdev[i]; CORE.Input.Mouse.currentButtonState[i] = platform.currentButtonStateEvdev[i];
CORE.Input.Touch.currentTouchState[i] = platform.currentButtonStateEvdev[i];
} }
// Register gamepads buttons events // Register gamepads buttons events
@ -603,7 +601,6 @@ void PollInputEvents(void)
struct input_event event = { 0 }; struct input_event event = { 0 };
int touchAction = -1; // 0-TOUCH_ACTION_UP, 1-TOUCH_ACTION_DOWN, 2-TOUCH_ACTION_MOVE int touchAction = -1; // 0-TOUCH_ACTION_UP, 1-TOUCH_ACTION_DOWN, 2-TOUCH_ACTION_MOVE
bool gestureUpdate = false; // Flag to note gestures require to update
// Try to read data from the mouse/touch/gesture and only continue if successful // Try to read data from the mouse/touch/gesture and only continue if successful
while (read(fd, &event, sizeof(event)) == (int)sizeof(event)) while (read(fd, &event, sizeof(event)) == (int)sizeof(event))
@ -622,7 +619,6 @@ void PollInputEvents(void)
CORE.Input.Touch.position[0].x = CORE.Input.Mouse.currentPosition.x; CORE.Input.Touch.position[0].x = CORE.Input.Mouse.currentPosition.x;
touchAction = 2; // TOUCH_ACTION_MOVE touchAction = 2; // TOUCH_ACTION_MOVE
gestureUpdate = true;
} }
if (event.code == REL_Y) if (event.code == REL_Y)
@ -636,7 +632,6 @@ void PollInputEvents(void)
CORE.Input.Touch.position[0].y = CORE.Input.Mouse.currentPosition.y; CORE.Input.Touch.position[0].y = CORE.Input.Mouse.currentPosition.y;
touchAction = 2; // TOUCH_ACTION_MOVE touchAction = 2; // TOUCH_ACTION_MOVE
gestureUpdate = true;
} }
if (event.code == REL_WHEEL) platform.eventWheelMove.y += event.value; if (event.code == REL_WHEEL) platform.eventWheelMove.y += event.value;
@ -652,7 +647,6 @@ void PollInputEvents(void)
CORE.Input.Touch.position[0].x = (event.value - platform.absRange.x)*CORE.Window.screen.width/platform.absRange.width; // Scale according to absRange CORE.Input.Touch.position[0].x = (event.value - platform.absRange.x)*CORE.Window.screen.width/platform.absRange.width; // Scale according to absRange
touchAction = 2; // TOUCH_ACTION_MOVE touchAction = 2; // TOUCH_ACTION_MOVE
gestureUpdate = true;
} }
if (event.code == ABS_Y) if (event.code == ABS_Y)
@ -661,7 +655,6 @@ void PollInputEvents(void)
CORE.Input.Touch.position[0].y = (event.value - platform.absRange.y)*CORE.Window.screen.height/platform.absRange.height; // Scale according to absRange CORE.Input.Touch.position[0].y = (event.value - platform.absRange.y)*CORE.Window.screen.height/platform.absRange.height; // Scale according to absRange
touchAction = 2; // TOUCH_ACTION_MOVE touchAction = 2; // TOUCH_ACTION_MOVE
gestureUpdate = true;
} }
// Multitouch movement // Multitouch movement
@ -697,7 +690,6 @@ void PollInputEvents(void)
platform.currentButtonStateEvdev[MOUSE_BUTTON_LEFT] = 0; platform.currentButtonStateEvdev[MOUSE_BUTTON_LEFT] = 0;
touchAction = 0; // TOUCH_ACTION_UP touchAction = 0; // TOUCH_ACTION_UP
gestureUpdate = true;
} }
if (event.value && !previousMouseLeftButtonState) if (event.value && !previousMouseLeftButtonState)
@ -705,7 +697,6 @@ void PollInputEvents(void)
platform.currentButtonStateEvdev[MOUSE_BUTTON_LEFT] = 1; platform.currentButtonStateEvdev[MOUSE_BUTTON_LEFT] = 1;
touchAction = 1; // TOUCH_ACTION_DOWN touchAction = 1; // TOUCH_ACTION_DOWN
gestureUpdate = true;
} }
} }
@ -721,7 +712,6 @@ void PollInputEvents(void)
if (event.value > 0) touchAction = 1; // TOUCH_ACTION_DOWN if (event.value > 0) touchAction = 1; // TOUCH_ACTION_DOWN
else touchAction = 0; // TOUCH_ACTION_UP else touchAction = 0; // TOUCH_ACTION_UP
gestureUpdate = true;
} }
if (event.code == BTN_RIGHT) platform.currentButtonStateEvdev[MOUSE_BUTTON_RIGHT] = event.value; if (event.code == BTN_RIGHT) platform.currentButtonStateEvdev[MOUSE_BUTTON_RIGHT] = event.value;
@ -750,7 +740,7 @@ void PollInputEvents(void)
} }
#if defined(SUPPORT_GESTURES_SYSTEM) #if defined(SUPPORT_GESTURES_SYSTEM)
if (gestureUpdate) if (touchAction > -1)
{ {
GestureEvent gestureEvent = { 0 }; GestureEvent gestureEvent = { 0 };
@ -765,7 +755,7 @@ void PollInputEvents(void)
ProcessGestureEvent(gestureEvent); ProcessGestureEvent(gestureEvent);
gestureUpdate = false; touchAction = -1;
} }
#endif #endif
} }
@ -1696,6 +1686,7 @@ static void PollKeyboardEvents(void)
// Event interface: 'value' is the value the event carries. Either a relative change for EV_REL, // Event interface: 'value' is the value the event carries. Either a relative change for EV_REL,
// absolute new value for EV_ABS (joysticks ...), or 0 for EV_KEY for release, 1 for keypress and 2 for autorepeat // absolute new value for EV_ABS (joysticks ...), or 0 for EV_KEY for release, 1 for keypress and 2 for autorepeat
CORE.Input.Keyboard.currentKeyState[keycode] = (event.value >= 1)? 1 : 0; CORE.Input.Keyboard.currentKeyState[keycode] = (event.value >= 1)? 1 : 0;
CORE.Input.Keyboard.keyRepeatInFrame[keycode] = (event.value == 2)? 1 : 0;
if (event.value >= 1) if (event.value >= 1)
{ {
CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = keycode; // Register last key pressed CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = keycode; // Register last key pressed

View File

@ -420,7 +420,7 @@ void PollInputEvents(void)
CORE.Input.Keyboard.keyRepeatInFrame[i] = 0; CORE.Input.Keyboard.keyRepeatInFrame[i] = 0;
} }
// TODO: Poll input events for current plaform // TODO: Poll input events for current platform
} }
@ -561,13 +561,13 @@ int InitPlatform(void)
// TODO: Initialize input events system // TODO: Initialize input events system
// It could imply keyboard, mouse, gamepad, touch... // It could imply keyboard, mouse, gamepad, touch...
// Depending on the platform libraries/SDK it could use a callbacks mechanims // Depending on the platform libraries/SDK it could use a callback mechanism
// For system events and inputs evens polling on a per-frame basis, use PollInputEvents() // For system events and inputs evens polling on a per-frame basis, use PollInputEvents()
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// ... // ...
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// TODO: Initialize timming system // TODO: Initialize timing system
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
InitTimer(); InitTimer();
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------

View File

@ -73,6 +73,7 @@
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
typedef struct { typedef struct {
GLFWwindow *handle; // GLFW window handle (graphic device) GLFWwindow *handle; // GLFW window handle (graphic device)
bool ourFullscreen; // Internal var to filter our handling of fullscreen vs the user handling of fullscreen
} PlatformData; } PlatformData;
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -140,6 +141,37 @@ bool WindowShouldClose(void)
// Toggle fullscreen mode // Toggle fullscreen mode
void ToggleFullscreen(void) void ToggleFullscreen(void)
{ {
platform.ourFullscreen = true;
bool enterFullscreen = false;
const bool wasFullscreen = EM_ASM_INT( { if (document.fullscreenElement) return 1; }, 0);
if (wasFullscreen)
{
EM_ASM(document.exitFullscreen(););
if (CORE.Window.flags & FLAG_FULLSCREEN_MODE) enterFullscreen = false;
else enterFullscreen = true;
CORE.Window.fullscreen = false;
CORE.Window.flags &= ~FLAG_FULLSCREEN_MODE;
CORE.Window.flags &= ~FLAG_BORDERLESS_WINDOWED_MODE;
}
else enterFullscreen = true;
if (enterFullscreen)
{
// NOTE: The setTimeouts handle the browser mode change delay
EM_ASM(
setTimeout(function()
{
Module.requestFullscreen(false, false);
}, 100);
);
CORE.Window.fullscreen = true;
CORE.Window.flags |= FLAG_FULLSCREEN_MODE;
}
// NOTE: Old notes below:
/* /*
EM_ASM EM_ASM
( (
@ -204,14 +236,44 @@ void ToggleFullscreen(void)
CORE.Window.flags &= ~FLAG_FULLSCREEN_MODE; CORE.Window.flags &= ~FLAG_FULLSCREEN_MODE;
} }
*/ */
CORE.Window.fullscreen = !CORE.Window.fullscreen; // Toggle fullscreen flag
} }
// Toggle borderless windowed mode // Toggle borderless windowed mode
void ToggleBorderlessWindowed(void) void ToggleBorderlessWindowed(void)
{ {
TRACELOG(LOG_WARNING, "ToggleBorderlessWindowed() not available on target platform"); platform.ourFullscreen = true;
bool enterBorderless = false;
const bool wasFullscreen = EM_ASM_INT( { if (document.fullscreenElement) return 1; }, 0);
if (wasFullscreen)
{
EM_ASM(document.exitFullscreen(););
if (CORE.Window.flags & FLAG_BORDERLESS_WINDOWED_MODE) enterBorderless = false;
else enterBorderless = true;
CORE.Window.fullscreen = false;
CORE.Window.flags &= ~FLAG_FULLSCREEN_MODE;
CORE.Window.flags &= ~FLAG_BORDERLESS_WINDOWED_MODE;
}
else enterBorderless = true;
if (enterBorderless)
{
// NOTE: 1. The setTimeouts handle the browser mode change delay
// 2. The style unset handles the possibility of a width="value%" like on the default shell.html file
EM_ASM(
setTimeout(function()
{
Module.requestFullscreen(false, true);
setTimeout(function()
{
canvas.style.width="unset";
}, 100);
}, 100);
);
CORE.Window.flags |= FLAG_BORDERLESS_WINDOWED_MODE;
}
} }
// Set window state: maximized, if resizable // Set window state: maximized, if resizable
@ -235,13 +297,215 @@ void RestoreWindow(void)
// Set window configuration state using flags // Set window configuration state using flags
void SetWindowState(unsigned int flags) void SetWindowState(unsigned int flags)
{ {
TRACELOG(LOG_WARNING, "SetWindowState() not available on target platform"); // Check previous state and requested state to apply required changes
// NOTE: In most cases the functions already change the flags internally
// State change: FLAG_VSYNC_HINT
if ((flags & FLAG_VSYNC_HINT) > 0)
{
TRACELOG(LOG_WARNING, "SetWindowState(FLAG_VSYNC_HINT) not available on target platform");
}
// State change: FLAG_BORDERLESS_WINDOWED_MODE
if (((CORE.Window.flags & FLAG_BORDERLESS_WINDOWED_MODE) != (flags & FLAG_BORDERLESS_WINDOWED_MODE)) && ((flags & FLAG_BORDERLESS_WINDOWED_MODE) > 0))
{
ToggleBorderlessWindowed(); // NOTE: Window state flag updated inside function
}
// State change: FLAG_FULLSCREEN_MODE
if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) != (flags & FLAG_FULLSCREEN_MODE))
{
ToggleFullscreen(); // NOTE: Window state flag updated inside function
}
// State change: FLAG_WINDOW_RESIZABLE
if (((CORE.Window.flags & FLAG_WINDOW_RESIZABLE) != (flags & FLAG_WINDOW_RESIZABLE)) && ((flags & FLAG_WINDOW_RESIZABLE) > 0))
{
glfwSetWindowAttrib(platform.handle, GLFW_RESIZABLE, GLFW_TRUE);
CORE.Window.flags |= FLAG_WINDOW_RESIZABLE;
}
// State change: FLAG_WINDOW_UNDECORATED
if ((flags & FLAG_WINDOW_UNDECORATED) > 0)
{
TRACELOG(LOG_WARNING, "SetWindowState(FLAG_WINDOW_UNDECORATED) not available on target platform");
}
// State change: FLAG_WINDOW_HIDDEN
if ((flags & FLAG_WINDOW_HIDDEN) > 0)
{
TRACELOG(LOG_WARNING, "SetWindowState(FLAG_WINDOW_HIDDEN) not available on target platform");
}
// State change: FLAG_WINDOW_MINIMIZED
if ((flags & FLAG_WINDOW_MINIMIZED) > 0)
{
TRACELOG(LOG_WARNING, "SetWindowState(FLAG_WINDOW_MINIMIZED) not available on target platform");
}
// State change: FLAG_WINDOW_MAXIMIZED
if ((flags & FLAG_WINDOW_MAXIMIZED) > 0)
{
TRACELOG(LOG_WARNING, "SetWindowState(FLAG_WINDOW_MAXIMIZED) not available on target platform");
}
// State change: FLAG_WINDOW_UNFOCUSED
if ((flags & FLAG_WINDOW_UNFOCUSED) > 0)
{
TRACELOG(LOG_WARNING, "SetWindowState(FLAG_WINDOW_UNFOCUSED) not available on target platform");
}
// State change: FLAG_WINDOW_TOPMOST
if ((flags & FLAG_WINDOW_TOPMOST) > 0)
{
TRACELOG(LOG_WARNING, "SetWindowState(FLAG_WINDOW_TOPMOST) not available on target platform");
}
// State change: FLAG_WINDOW_ALWAYS_RUN
if ((flags & FLAG_WINDOW_ALWAYS_RUN) > 0)
{
TRACELOG(LOG_WARNING, "SetWindowState(FLAG_WINDOW_ALWAYS_RUN) not available on target platform");
}
// The following states can not be changed after window creation
// NOTE: Review for PLATFORM_WEB
// State change: FLAG_WINDOW_TRANSPARENT
if ((flags & FLAG_WINDOW_TRANSPARENT) > 0)
{
TRACELOG(LOG_WARNING, "SetWindowState(FLAG_WINDOW_TRANSPARENT) not available on target platform");
}
// State change: FLAG_WINDOW_HIGHDPI
if ((flags & FLAG_WINDOW_HIGHDPI) > 0)
{
TRACELOG(LOG_WARNING, "SetWindowState(FLAG_WINDOW_HIGHDPI) not available on target platform");
}
// State change: FLAG_WINDOW_MOUSE_PASSTHROUGH
if ((flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) > 0)
{
TRACELOG(LOG_WARNING, "SetWindowState(FLAG_WINDOW_MOUSE_PASSTHROUGH) not available on target platform");
}
// State change: FLAG_MSAA_4X_HINT
if ((flags & FLAG_MSAA_4X_HINT) > 0)
{
TRACELOG(LOG_WARNING, "SetWindowState(FLAG_MSAA_4X_HINT) not available on target platform");
}
// State change: FLAG_INTERLACED_HINT
if ((flags & FLAG_INTERLACED_HINT) > 0)
{
TRACELOG(LOG_WARNING, "SetWindowState(FLAG_INTERLACED_HINT) not available on target platform");
}
} }
// Clear window configuration state flags // Clear window configuration state flags
void ClearWindowState(unsigned int flags) void ClearWindowState(unsigned int flags)
{ {
TRACELOG(LOG_WARNING, "ClearWindowState() not available on target platform"); // Check previous state and requested state to apply required changes
// NOTE: In most cases the functions already change the flags internally
// State change: FLAG_VSYNC_HINT
if ((flags & FLAG_VSYNC_HINT) > 0)
{
TRACELOG(LOG_WARNING, "ClearWindowState(FLAG_VSYNC_HINT) not available on target platform");
}
// State change: FLAG_BORDERLESS_WINDOWED_MODE
if (((CORE.Window.flags & FLAG_BORDERLESS_WINDOWED_MODE) > 0) && ((flags & FLAG_BORDERLESS_WINDOWED_MODE) > 0))
{
ToggleBorderlessWindowed(); // NOTE: Window state flag updated inside function
}
// State change: FLAG_FULLSCREEN_MODE
if (((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) && ((flags & FLAG_FULLSCREEN_MODE) > 0))
{
ToggleFullscreen(); // NOTE: Window state flag updated inside function
}
// State change: FLAG_WINDOW_RESIZABLE
if (((CORE.Window.flags & FLAG_WINDOW_RESIZABLE) > 0) && ((flags & FLAG_WINDOW_RESIZABLE) > 0))
{
glfwSetWindowAttrib(platform.handle, GLFW_RESIZABLE, GLFW_FALSE);
CORE.Window.flags &= ~FLAG_WINDOW_RESIZABLE;
}
// State change: FLAG_WINDOW_HIDDEN
if ((flags & FLAG_WINDOW_HIDDEN) > 0)
{
TRACELOG(LOG_WARNING, "ClearWindowState(FLAG_WINDOW_HIDDEN) not available on target platform");
}
// State change: FLAG_WINDOW_MINIMIZED
if ((flags & FLAG_WINDOW_MINIMIZED) > 0)
{
TRACELOG(LOG_WARNING, "ClearWindowState(FLAG_WINDOW_MINIMIZED) not available on target platform");
}
// State change: FLAG_WINDOW_MAXIMIZED
if ((flags & FLAG_WINDOW_MAXIMIZED) > 0)
{
TRACELOG(LOG_WARNING, "ClearWindowState(FLAG_WINDOW_MAXIMIZED) not available on target platform");
}
// State change: FLAG_WINDOW_UNDECORATED
if ((flags & FLAG_WINDOW_UNDECORATED) > 0)
{
TRACELOG(LOG_WARNING, "ClearWindowState(FLAG_WINDOW_UNDECORATED) not available on target platform");
}
// State change: FLAG_WINDOW_UNFOCUSED
if ((flags & FLAG_WINDOW_UNFOCUSED) > 0)
{
TRACELOG(LOG_WARNING, "ClearWindowState(FLAG_WINDOW_UNFOCUSED) not available on target platform");
}
// State change: FLAG_WINDOW_TOPMOST
if ((flags & FLAG_WINDOW_TOPMOST) > 0)
{
TRACELOG(LOG_WARNING, "ClearWindowState(FLAG_WINDOW_TOPMOST) not available on target platform");
}
// State change: FLAG_WINDOW_ALWAYS_RUN
if ((flags & FLAG_WINDOW_ALWAYS_RUN) > 0)
{
TRACELOG(LOG_WARNING, "ClearWindowState(FLAG_WINDOW_ALWAYS_RUN) not available on target platform");
}
// The following states can not be changed after window creation
// NOTE: Review for PLATFORM_WEB
// State change: FLAG_WINDOW_TRANSPARENT
if ((flags & FLAG_WINDOW_TRANSPARENT) > 0)
{
TRACELOG(LOG_WARNING, "ClearWindowState(FLAG_WINDOW_TRANSPARENT) not available on target platform");
}
// State change: FLAG_WINDOW_HIGHDPI
if ((flags & FLAG_WINDOW_HIGHDPI) > 0)
{
TRACELOG(LOG_WARNING, "ClearWindowState(FLAG_WINDOW_HIGHDPI) not available on target platform");
}
// State change: FLAG_WINDOW_MOUSE_PASSTHROUGH
if ((flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) > 0)
{
TRACELOG(LOG_WARNING, "ClearWindowState(FLAG_WINDOW_MOUSE_PASSTHROUGH) not available on target platform");
}
// State change: FLAG_MSAA_4X_HINT
if ((flags & FLAG_MSAA_4X_HINT) > 0)
{
TRACELOG(LOG_WARNING, "ClearWindowState(FLAG_MSAA_4X_HINT) not available on target platform");
}
// State change: FLAG_INTERLACED_HINT
if ((flags & FLAG_INTERLACED_HINT) > 0)
{
TRACELOG(LOG_WARNING, "ClearWindowState(FLAG_INTERLACED_HINT) not available on target platform");
}
} }
// Set icon for window // Set icon for window
@ -344,15 +608,19 @@ Vector2 GetMonitorPosition(int monitor)
// Get selected monitor width (currently used by monitor) // Get selected monitor width (currently used by monitor)
int GetMonitorWidth(int monitor) int GetMonitorWidth(int monitor)
{ {
TRACELOG(LOG_WARNING, "GetMonitorWidth() not implemented on target platform"); // NOTE: Returned value is limited to the current monitor where the browser window is located
return 0; int width = 0;
width = EM_ASM_INT( { return screen.width; }, 0);
return width;
} }
// Get selected monitor height (currently used by monitor) // Get selected monitor height (currently used by monitor)
int GetMonitorHeight(int monitor) int GetMonitorHeight(int monitor)
{ {
TRACELOG(LOG_WARNING, "GetMonitorHeight() not implemented on target platform"); // NOTE: Returned value is limited to the current monitor where the browser window is located
return 0; int height = 0;
height = EM_ASM_INT( { return screen.height; }, 0);
return height;
} }
// Get selected monitor physical width in millimetres // Get selected monitor physical width in millimetres
@ -386,8 +654,11 @@ const char *GetMonitorName(int monitor)
// Get window position XY on monitor // Get window position XY on monitor
Vector2 GetWindowPosition(void) Vector2 GetWindowPosition(void)
{ {
TRACELOG(LOG_WARNING, "GetWindowPosition() not implemented on target platform"); // NOTE: Returned position is relative to the current monitor where the browser window is located
return (Vector2){ 0, 0 }; Vector2 position = { 0, 0 };
position.x = (float)EM_ASM_INT( { return window.screenX; }, 0);
position.y = (float)EM_ASM_INT( { return window.screenY; }, 0);
return position;
} }
// Get window scale DPI factor for current monitor // Get window scale DPI factor for current monitor
@ -664,7 +935,7 @@ void PollInputEvents(void)
// TODO: This code does not seem to do anything?? // TODO: This code does not seem to do anything??
//if (CORE.Window.eventWaiting) glfwWaitEvents(); // Wait for in input events before continue (drawing is paused) //if (CORE.Window.eventWaiting) glfwWaitEvents(); // Wait for in input events before continue (drawing is paused)
//else glfwPollEvents(); // Poll input events: keyboard/mouse/window events (callbacks) --> WARNING: Where is key input reseted? //else glfwPollEvents(); // Poll input events: keyboard/mouse/window events (callbacks) --> WARNING: Where is key input reset?
} }
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -716,8 +987,13 @@ int InitPlatform(void)
if ((CORE.Window.flags & FLAG_WINDOW_TOPMOST) > 0) glfwWindowHint(GLFW_FLOATING, GLFW_TRUE); if ((CORE.Window.flags & FLAG_WINDOW_TOPMOST) > 0) glfwWindowHint(GLFW_FLOATING, GLFW_TRUE);
else glfwWindowHint(GLFW_FLOATING, GLFW_FALSE); else glfwWindowHint(GLFW_FLOATING, GLFW_FALSE);
// NOTE: Some GLFW flags are not supported on HTML5 // NOTE: Some GLFW flags are not supported on HTML5
// e.g.: GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_SCALE_TO_MONITOR, GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_MOUSE_PASSTHROUGH // e.g.: GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_MOUSE_PASSTHROUGH
// Scale content area based on the monitor content scale where window is placed on
// NOTE: This feature requires emscripten 3.1.51
//if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0) glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE);
//else glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_FALSE);
if (CORE.Window.flags & FLAG_MSAA_4X_HINT) if (CORE.Window.flags & FLAG_MSAA_4X_HINT)
{ {
@ -775,6 +1051,9 @@ int InitPlatform(void)
CORE.Window.display.width = CORE.Window.screen.width; CORE.Window.display.width = CORE.Window.screen.width;
CORE.Window.display.height = CORE.Window.screen.height; CORE.Window.display.height = CORE.Window.screen.height;
// Init fullscreen toggle required var:
platform.ourFullscreen = false;
if (CORE.Window.fullscreen) if (CORE.Window.fullscreen)
{ {
// remember center for switchinging from fullscreen to window // remember center for switchinging from fullscreen to window
@ -908,7 +1187,7 @@ int InitPlatform(void)
// Initialize input events callbacks // Initialize input events callbacks
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Setup callback functions for the DOM events // Setup callback functions for the DOM events
emscripten_set_fullscreenchange_callback("#canvas", NULL, 1, EmscriptenFullscreenChangeCallback); emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, 1, EmscriptenFullscreenChangeCallback);
// WARNING: Below resize code was breaking fullscreen mode for sample games and examples, it needs review // WARNING: Below resize code was breaking fullscreen mode for sample games and examples, it needs review
// Check fullscreen change events(note this is done on the window since most browsers don't support this on #canvas) // Check fullscreen change events(note this is done on the window since most browsers don't support this on #canvas)
@ -937,7 +1216,7 @@ int InitPlatform(void)
emscripten_set_gamepaddisconnected_callback(NULL, 1, EmscriptenGamepadCallback); emscripten_set_gamepaddisconnected_callback(NULL, 1, EmscriptenGamepadCallback);
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Initialize timming system // Initialize timing system
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
InitTimer(); InitTimer();
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -1093,6 +1372,7 @@ static void MouseButtonCallback(GLFWwindow *window, int button, int action, int
// WARNING: GLFW could only return GLFW_PRESS (1) or GLFW_RELEASE (0) for now, // WARNING: GLFW could only return GLFW_PRESS (1) or GLFW_RELEASE (0) for now,
// but future releases may add more actions (i.e. GLFW_REPEAT) // but future releases may add more actions (i.e. GLFW_REPEAT)
CORE.Input.Mouse.currentButtonState[button] = action; CORE.Input.Mouse.currentButtonState[button] = action;
CORE.Input.Touch.currentTouchState[button] = action;
#if defined(SUPPORT_GESTURES_SYSTEM) && defined(SUPPORT_MOUSE_GESTURES) #if defined(SUPPORT_GESTURES_SYSTEM) && defined(SUPPORT_MOUSE_GESTURES)
// Process mouse events as touches to be able to use mouse-gestures // Process mouse events as touches to be able to use mouse-gestures
@ -1171,7 +1451,19 @@ static void CursorEnterCallback(GLFWwindow *window, int enter)
// Register fullscreen change events // Register fullscreen change events
static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *event, void *userData) static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *event, void *userData)
{ {
// TODO: Implement EmscriptenFullscreenChangeCallback()? // NOTE: 1. Reset the fullscreen flags if the user left fullscreen manually by pressing the Escape key
// 2. Which is a necessary safeguard because that case will bypass the toggles CORE.Window.flags resets
if (platform.ourFullscreen) platform.ourFullscreen = false;
else
{
const bool wasFullscreen = EM_ASM_INT( { if (document.fullscreenElement) return 1; }, 0);
if (!wasFullscreen)
{
CORE.Window.fullscreen = false;
CORE.Window.flags &= ~FLAG_FULLSCREEN_MODE;
CORE.Window.flags &= ~FLAG_BORDERLESS_WINDOWED_MODE;
}
}
return 1; // The event was consumed by the callback handler return 1; // The event was consumed by the callback handler
} }

View File

@ -167,6 +167,10 @@ typedef struct tagBITMAPINFOHEADER {
#define MA_NO_WAV #define MA_NO_WAV
#define MA_NO_FLAC #define MA_NO_FLAC
#define MA_NO_MP3 #define MA_NO_MP3
#define MA_NO_RESOURCE_MANAGER
#define MA_NO_NODE_GRAPH
#define MA_NO_ENGINE
#define MA_NO_GENERATION
// Threading model: Default: [0] COINIT_MULTITHREADED: COM calls objects on any thread (free threading) // Threading model: Default: [0] COINIT_MULTITHREADED: COM calls objects on any thread (free threading)
#define MA_COINIT_VALUE 2 // [2] COINIT_APARTMENTTHREADED: Each object has its own thread (apartment model) #define MA_COINIT_VALUE 2 // [2] COINIT_APARTMENTTHREADED: Each object has its own thread (apartment model)

View File

@ -1,6 +1,6 @@
/********************************************************************************************** /**********************************************************************************************
* *
* raylib v5.0 - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com) * raylib v5.1-dev - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com)
* *
* FEATURES: * FEATURES:
* - NO external dependencies, all required libraries included with raylib * - NO external dependencies, all required libraries included with raylib
@ -82,21 +82,26 @@
#include <stdarg.h> // Required for: va_list - Only used by TraceLogCallback #include <stdarg.h> // Required for: va_list - Only used by TraceLogCallback
#define RAYLIB_VERSION_MAJOR 5 #define RAYLIB_VERSION_MAJOR 5
#define RAYLIB_VERSION_MINOR 0 #define RAYLIB_VERSION_MINOR 1
#define RAYLIB_VERSION_PATCH 0 #define RAYLIB_VERSION_PATCH 0
#define RAYLIB_VERSION "5.0" #define RAYLIB_VERSION "5.1-dev"
// Function specifiers in case library is build/used as a shared library (Windows) // Function specifiers in case library is build/used as a shared library
// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll // NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll
// NOTE: visibility("default") attribute makes symbols "visible" when compiled with -fvisibility=hidden
#if defined(_WIN32) #if defined(_WIN32)
#if defined(__TINYC__)
#define __declspec(x) __attribute__((x))
#endif
#if defined(BUILD_LIBTYPE_SHARED) #if defined(BUILD_LIBTYPE_SHARED)
#if defined(__TINYC__)
#define __declspec(x) __attribute__((x))
#endif
#define RLAPI __declspec(dllexport) // We are building the library as a Win32 shared library (.dll) #define RLAPI __declspec(dllexport) // We are building the library as a Win32 shared library (.dll)
#elif defined(USE_LIBTYPE_SHARED) #elif defined(USE_LIBTYPE_SHARED)
#define RLAPI __declspec(dllimport) // We are using the library as a Win32 shared library (.dll) #define RLAPI __declspec(dllimport) // We are using the library as a Win32 shared library (.dll)
#endif #endif
#else
#if defined(BUILD_LIBTYPE_SHARED)
#define RLAPI __attribute__((visibility("default"))) // We are building as a Unix shared library (.so/.dylib)
#endif
#endif #endif
#ifndef RLAPI #ifndef RLAPI
@ -479,7 +484,6 @@ typedef struct VrDeviceInfo {
int vResolution; // Vertical resolution in pixels int vResolution; // Vertical resolution in pixels
float hScreenSize; // Horizontal size in meters float hScreenSize; // Horizontal size in meters
float vScreenSize; // Vertical size in meters float vScreenSize; // Vertical size in meters
float vScreenCenter; // Screen center in meters
float eyeToScreenDistance; // Distance between eye and display in meters float eyeToScreenDistance; // Distance between eye and display in meters
float lensSeparationDistance; // Lens separation distance in meters float lensSeparationDistance; // Lens separation distance in meters
float interpupillaryDistance; // IPD (distance between pupils) in meters float interpupillaryDistance; // IPD (distance between pupils) in meters
@ -1329,6 +1333,7 @@ RLAPI void ImageAlphaClear(Image *image, Color color, float threshold);
RLAPI void ImageAlphaMask(Image *image, Image alphaMask); // Apply alpha mask to image RLAPI void ImageAlphaMask(Image *image, Image alphaMask); // Apply alpha mask to image
RLAPI void ImageAlphaPremultiply(Image *image); // Premultiply alpha channel RLAPI void ImageAlphaPremultiply(Image *image); // Premultiply alpha channel
RLAPI void ImageBlurGaussian(Image *image, int blurSize); // Apply Gaussian blur using a box blur approximation RLAPI void ImageBlurGaussian(Image *image, int blurSize); // Apply Gaussian blur using a box blur approximation
RLAPI void ImageKernelConvolution(Image *image, float* kernel, int kernelSize); // Apply Custom Square image convolution kernel
RLAPI void ImageResize(Image *image, int newWidth, int newHeight); // Resize image (Bicubic scaling algorithm) RLAPI void ImageResize(Image *image, int newWidth, int newHeight); // Resize image (Bicubic scaling algorithm)
RLAPI void ImageResizeNN(Image *image, int newWidth,int newHeight); // Resize image (Nearest-Neighbor scaling algorithm) RLAPI void ImageResizeNN(Image *image, int newWidth,int newHeight); // Resize image (Nearest-Neighbor scaling algorithm)
RLAPI void ImageResizeCanvas(Image *image, int newWidth, int newHeight, int offsetX, int offsetY, Color fill); // Resize canvas and fill with color RLAPI void ImageResizeCanvas(Image *image, int newWidth, int newHeight, int offsetX, int offsetY, Color fill); // Resize canvas and fill with color
@ -1475,6 +1480,7 @@ RLAPI const char *TextToUpper(const char *text); // Get upp
RLAPI const char *TextToLower(const char *text); // Get lower case version of provided string RLAPI const char *TextToLower(const char *text); // Get lower case version of provided string
RLAPI const char *TextToPascal(const char *text); // Get Pascal case notation version of provided string RLAPI const char *TextToPascal(const char *text); // Get Pascal case notation version of provided string
RLAPI int TextToInteger(const char *text); // Get integer value from text (negative values not supported) RLAPI int TextToInteger(const char *text); // Get integer value from text (negative values not supported)
RLAPI float TextToFloat(const char *text); // Get float value from text (negative values not supported)
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Basic 3d Shapes Drawing Functions (Module: models) // Basic 3d Shapes Drawing Functions (Module: models)
@ -1530,9 +1536,10 @@ RLAPI void UpdateMeshBuffer(Mesh mesh, int index, const void *data, int dataSize
RLAPI void UnloadMesh(Mesh mesh); // Unload mesh data from CPU and GPU RLAPI void UnloadMesh(Mesh mesh); // Unload mesh data from CPU and GPU
RLAPI void DrawMesh(Mesh mesh, Material material, Matrix transform); // Draw a 3d mesh with material and transform RLAPI void DrawMesh(Mesh mesh, Material material, Matrix transform); // Draw a 3d mesh with material and transform
RLAPI void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, int instances); // Draw multiple mesh instances with material and different transforms RLAPI void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, int instances); // Draw multiple mesh instances with material and different transforms
RLAPI bool ExportMesh(Mesh mesh, const char *fileName); // Export mesh data to file, returns true on success
RLAPI BoundingBox GetMeshBoundingBox(Mesh mesh); // Compute mesh bounding box limits RLAPI BoundingBox GetMeshBoundingBox(Mesh mesh); // Compute mesh bounding box limits
RLAPI void GenMeshTangents(Mesh *mesh); // Compute mesh tangents RLAPI void GenMeshTangents(Mesh *mesh); // Compute mesh tangents
RLAPI bool ExportMesh(Mesh mesh, const char *fileName); // Export mesh data to file, returns true on success
RLAPI bool ExportMeshAsCode(Mesh mesh, const char *fileName); // Export mesh as code file (.h) defining multiple arrays of vertex attributes
// Mesh generation functions // Mesh generation functions
RLAPI Mesh GenMeshPoly(int sides, float radius); // Generate polygonal mesh RLAPI Mesh GenMeshPoly(int sides, float radius); // Generate polygonal mesh

View File

@ -59,7 +59,9 @@
// Function specifiers definition // Function specifiers definition
#if defined(RAYMATH_IMPLEMENTATION) #if defined(RAYMATH_IMPLEMENTATION)
#if defined(_WIN32) && defined(BUILD_LIBTYPE_SHARED) #if defined(_WIN32) && defined(BUILD_LIBTYPE_SHARED)
#define RMAPI __declspec(dllexport) extern inline // We are building raylib as a Win32 shared library (.dll). #define RMAPI __declspec(dllexport) extern inline // We are building raylib as a Win32 shared library (.dll)
#elif defined(BUILD_LIBTYPE_SHARED)
#define RMAPI __attribute__((visibility("default"))) // We are building raylib as a Unix shared library (.so/.dylib)
#elif defined(_WIN32) && defined(USE_LIBTYPE_SHARED) #elif defined(_WIN32) && defined(USE_LIBTYPE_SHARED)
#define RMAPI __declspec(dllimport) // We are using raylib as a Win32 shared library (.dll) #define RMAPI __declspec(dllimport) // We are using raylib as a Win32 shared library (.dll)
#else #else

View File

@ -449,7 +449,7 @@ void UpdateCamera(Camera *camera, int mode)
bool moveInWorldPlane = ((mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON)); bool moveInWorldPlane = ((mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON));
bool rotateAroundTarget = ((mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL)); bool rotateAroundTarget = ((mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL));
bool lockView = ((mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL)); bool lockView = ((mode == CAMERA_FREE) || (mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL));
bool rotateUp = false; bool rotateUp = false;
if (mode == CAMERA_ORBITAL) if (mode == CAMERA_ORBITAL)
@ -471,31 +471,30 @@ void UpdateCamera(Camera *camera, int mode)
if (IsKeyDown(KEY_E)) CameraRoll(camera, CAMERA_ROTATION_SPEED); if (IsKeyDown(KEY_E)) CameraRoll(camera, CAMERA_ROTATION_SPEED);
// Camera movement // Camera movement
if (!IsGamepadAvailable(0)) // Camera pan (for CAMERA_FREE)
if ((mode == CAMERA_FREE) && (IsMouseButtonDown(MOUSE_BUTTON_MIDDLE)))
{ {
// Camera pan (for CAMERA_FREE) const Vector2 mouseDelta = GetMouseDelta();
if ((mode == CAMERA_FREE) && (IsMouseButtonDown(MOUSE_BUTTON_MIDDLE))) if (mouseDelta.x > 0.0f) CameraMoveRight(camera, CAMERA_PAN_SPEED, moveInWorldPlane);
{ if (mouseDelta.x < 0.0f) CameraMoveRight(camera, -CAMERA_PAN_SPEED, moveInWorldPlane);
const Vector2 mouseDelta = GetMouseDelta(); if (mouseDelta.y > 0.0f) CameraMoveUp(camera, -CAMERA_PAN_SPEED);
if (mouseDelta.x > 0.0f) CameraMoveRight(camera, CAMERA_PAN_SPEED, moveInWorldPlane); if (mouseDelta.y < 0.0f) CameraMoveUp(camera, CAMERA_PAN_SPEED);
if (mouseDelta.x < 0.0f) CameraMoveRight(camera, -CAMERA_PAN_SPEED, moveInWorldPlane);
if (mouseDelta.y > 0.0f) CameraMoveUp(camera, -CAMERA_PAN_SPEED);
if (mouseDelta.y < 0.0f) CameraMoveUp(camera, CAMERA_PAN_SPEED);
}
else
{
// Mouse support
CameraYaw(camera, -mousePositionDelta.x*CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget);
CameraPitch(camera, -mousePositionDelta.y*CAMERA_MOUSE_MOVE_SENSITIVITY, lockView, rotateAroundTarget, rotateUp);
}
// Keyboard support
if (IsKeyDown(KEY_W)) CameraMoveForward(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);
if (IsKeyDown(KEY_A)) CameraMoveRight(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);
if (IsKeyDown(KEY_S)) CameraMoveForward(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);
if (IsKeyDown(KEY_D)) CameraMoveRight(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);
} }
else else
{
// Mouse support
CameraYaw(camera, -mousePositionDelta.x*CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget);
CameraPitch(camera, -mousePositionDelta.y*CAMERA_MOUSE_MOVE_SENSITIVITY, lockView, rotateAroundTarget, rotateUp);
}
// Keyboard support
if (IsKeyDown(KEY_W)) CameraMoveForward(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);
if (IsKeyDown(KEY_A)) CameraMoveRight(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);
if (IsKeyDown(KEY_S)) CameraMoveForward(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);
if (IsKeyDown(KEY_D)) CameraMoveRight(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);
// Gamepad movement
if (IsGamepadAvailable(0))
{ {
// Gamepad controller support // Gamepad controller support
CameraYaw(camera, -(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_X) * 2)*CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget); CameraYaw(camera, -(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_X) * 2)*CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget);

View File

@ -1192,8 +1192,8 @@ VrStereoConfig LoadVrStereoConfig(VrDeviceInfo device)
// NOTE: Camera movement might seem more natural if we model the head. // NOTE: Camera movement might seem more natural if we model the head.
// Our axis of rotation is the base of our head, so we might want to add // Our axis of rotation is the base of our head, so we might want to add
// some y (base of head to eye level) and -z (center of head to eye protrusion) to the camera positions. // some y (base of head to eye level) and -z (center of head to eye protrusion) to the camera positions.
config.viewOffset[0] = MatrixTranslate(-device.interpupillaryDistance*0.5f, 0.075f, 0.045f); config.viewOffset[0] = MatrixTranslate(device.interpupillaryDistance*0.5f, 0.075f, 0.045f);
config.viewOffset[1] = MatrixTranslate(device.interpupillaryDistance*0.5f, 0.075f, 0.045f); config.viewOffset[1] = MatrixTranslate(-device.interpupillaryDistance*0.5f, 0.075f, 0.045f);
// Compute eyes Viewports // Compute eyes Viewports
/* /*
@ -2623,8 +2623,9 @@ void PlayAutomationEvent(AutomationEvent event)
{ {
CORE.Input.Gamepad.axisState[event.params[0]][event.params[1]] = ((float)event.params[2]/32768.0f); CORE.Input.Gamepad.axisState[event.params[0]][event.params[1]] = ((float)event.params[2]/32768.0f);
} break; } break;
#if defined(SUPPORT_GESTURES_SYSTEM)
case INPUT_GESTURE: GESTURES.current = event.params[0]; break; // param[0]: gesture (enum Gesture) -> rgestures.h: GESTURES.current case INPUT_GESTURE: GESTURES.current = event.params[0]; break; // param[0]: gesture (enum Gesture) -> rgestures.h: GESTURES.current
#endif
// Window event // Window event
case WINDOW_CLOSE: CORE.Window.shouldClose = true; break; case WINDOW_CLOSE: CORE.Window.shouldClose = true; break;
case WINDOW_MAXIMIZE: MaximizeWindow(); break; case WINDOW_MAXIMIZE: MaximizeWindow(); break;
@ -2632,11 +2633,13 @@ void PlayAutomationEvent(AutomationEvent event)
case WINDOW_RESIZE: SetWindowSize(event.params[0], event.params[1]); break; case WINDOW_RESIZE: SetWindowSize(event.params[0], event.params[1]); break;
// Custom event // Custom event
#if defined(SUPPORT_SCREEN_CAPTURE)
case ACTION_TAKE_SCREENSHOT: case ACTION_TAKE_SCREENSHOT:
{ {
TakeScreenshot(TextFormat("screenshot%03i.png", screenshotCounter)); TakeScreenshot(TextFormat("screenshot%03i.png", screenshotCounter));
screenshotCounter++; screenshotCounter++;
} break; } break;
#endif
case ACTION_SETTARGETFPS: SetTargetFPS(event.params[0]); break; case ACTION_SETTARGETFPS: SetTargetFPS(event.params[0]); break;
default: break; default: break;
} }
@ -3507,6 +3510,7 @@ static void RecordAutomationEvent(void)
} }
//------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------
#if defined(SUPPORT_GESTURES_SYSTEM)
// Gestures input currentEventList->events recording // Gestures input currentEventList->events recording
//------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------
if (GESTURES.current != GESTURE_NONE) if (GESTURES.current != GESTURE_NONE)
@ -3524,6 +3528,7 @@ static void RecordAutomationEvent(void)
if (currentEventList->count == currentEventList->capacity) return; // Security check if (currentEventList->count == currentEventList->capacity) return; // Security check
} }
//------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------
#endif
// Window events recording // Window events recording
//------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------

View File

@ -1,6 +1,6 @@
/********************************************************************************************** /**********************************************************************************************
* *
* rlgl v4.5 - A multi-OpenGL abstraction layer with an immediate-mode style API * rlgl v5.0 - A multi-OpenGL abstraction layer with an immediate-mode style API
* *
* DESCRIPTION: * DESCRIPTION:
* An abstraction layer for multiple OpenGL versions (1.1, 2.1, 3.3 Core, 4.3 Core, ES 2.0) * An abstraction layer for multiple OpenGL versions (1.1, 2.1, 3.3 Core, 4.3 Core, ES 2.0)
@ -109,16 +109,18 @@
#define RLGL_VERSION "4.5" #define RLGL_VERSION "4.5"
// Function specifiers in case library is build/used as a shared library (Windows) // Function specifiers in case library is build/used as a shared library
// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll // NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll
#if defined(_WIN32) // NOTE: visibility(default) attribute makes symbols "visible" when compiled with -fvisibility=hidden
#if defined(BUILD_LIBTYPE_SHARED) #if defined(_WIN32) && defined(BUILD_LIBTYPE_SHARED)
#define RLAPI __declspec(dllexport) // We are building the library as a Win32 shared library (.dll) #define RLAPI __declspec(dllexport) // We are building the library as a Win32 shared library (.dll)
#elif defined(USE_LIBTYPE_SHARED) #elif defined(BUILD_LIBTYPE_SHARED)
#define RLAPI __declspec(dllimport) // We are using the library as a Win32 shared library (.dll) #define RLAPI __attribute__((visibility("default"))) // We are building he library as a Unix shared library (.so/.dylib)
#endif #elif defined(_WIN32) && defined(USE_LIBTYPE_SHARED)
#define RLAPI __declspec(dllimport) // We are using the library as a Win32 shared library (.dll)
#endif #endif
// Function specifiers definition // Function specifiers definition
#ifndef RLAPI #ifndef RLAPI
#define RLAPI // Functions defined as 'extern' by default (implicit specifiers) #define RLAPI // Functions defined as 'extern' by default (implicit specifiers)
@ -555,14 +557,14 @@ typedef enum {
extern "C" { // Prevents name mangling of functions extern "C" { // Prevents name mangling of functions
#endif #endif
RLAPI void rlMatrixMode(int mode); // Choose the current matrix to be transformed RLAPI void rlMatrixMode(int mode); // Choose the current matrix to be transformed
RLAPI void rlPushMatrix(void); // Push the current matrix to stack RLAPI void rlPushMatrix(void); // Push the current matrix to stack
RLAPI void rlPopMatrix(void); // Pop latest inserted matrix from stack RLAPI void rlPopMatrix(void); // Pop latest inserted matrix from stack
RLAPI void rlLoadIdentity(void); // Reset current matrix to identity matrix RLAPI void rlLoadIdentity(void); // Reset current matrix to identity matrix
RLAPI void rlTranslatef(float x, float y, float z); // Multiply the current matrix by a translation matrix RLAPI void rlTranslatef(float x, float y, float z); // Multiply the current matrix by a translation matrix
RLAPI void rlRotatef(float angle, float x, float y, float z); // Multiply the current matrix by a rotation matrix RLAPI void rlRotatef(float angle, float x, float y, float z); // Multiply the current matrix by a rotation matrix
RLAPI void rlScalef(float x, float y, float z); // Multiply the current matrix by a scaling matrix RLAPI void rlScalef(float x, float y, float z); // Multiply the current matrix by a scaling matrix
RLAPI void rlMultMatrixf(const float *matf); // Multiply the current matrix by another matrix RLAPI void rlMultMatrixf(const float *matf); // Multiply the current matrix by another matrix
RLAPI void rlFrustum(double left, double right, double bottom, double top, double znear, double zfar); RLAPI void rlFrustum(double left, double right, double bottom, double top, double znear, double zfar);
RLAPI void rlOrtho(double left, double right, double bottom, double top, double znear, double zfar); RLAPI void rlOrtho(double left, double right, double bottom, double top, double znear, double zfar);
RLAPI void rlViewport(int x, int y, int width, int height); // Set the viewport area RLAPI void rlViewport(int x, int y, int width, int height); // Set the viewport area
@ -570,15 +572,15 @@ RLAPI void rlViewport(int x, int y, int width, int height); // Set the viewport
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Functions Declaration - Vertex level operations // Functions Declaration - Vertex level operations
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
RLAPI void rlBegin(int mode); // Initialize drawing mode (how to organize vertex) RLAPI void rlBegin(int mode); // Initialize drawing mode (how to organize vertex)
RLAPI void rlEnd(void); // Finish vertex providing RLAPI void rlEnd(void); // Finish vertex providing
RLAPI void rlVertex2i(int x, int y); // Define one vertex (position) - 2 int RLAPI void rlVertex2i(int x, int y); // Define one vertex (position) - 2 int
RLAPI void rlVertex2f(float x, float y); // Define one vertex (position) - 2 float RLAPI void rlVertex2f(float x, float y); // Define one vertex (position) - 2 float
RLAPI void rlVertex3f(float x, float y, float z); // Define one vertex (position) - 3 float RLAPI void rlVertex3f(float x, float y, float z); // Define one vertex (position) - 3 float
RLAPI void rlTexCoord2f(float x, float y); // Define one vertex (texture coordinate) - 2 float RLAPI void rlTexCoord2f(float x, float y); // Define one vertex (texture coordinate) - 2 float
RLAPI void rlNormal3f(float x, float y, float z); // Define one vertex (normal) - 3 float RLAPI void rlNormal3f(float x, float y, float z); // Define one vertex (normal) - 3 float
RLAPI void rlColor4ub(unsigned char r, unsigned char g, unsigned char b, unsigned char a); // Define one vertex (color) - 4 byte RLAPI void rlColor4ub(unsigned char r, unsigned char g, unsigned char b, unsigned char a); // Define one vertex (color) - 4 byte
RLAPI void rlColor3f(float x, float y, float z); // Define one vertex (color) - 3 float RLAPI void rlColor3f(float x, float y, float z); // Define one vertex (color) - 3 float
RLAPI void rlColor4f(float x, float y, float z, float w); // Define one vertex (color) - 4 float RLAPI void rlColor4f(float x, float y, float z, float w); // Define one vertex (color) - 4 float
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
@ -592,13 +594,13 @@ RLAPI bool rlEnableVertexArray(unsigned int vaoId); // Enable vertex array (
RLAPI void rlDisableVertexArray(void); // Disable vertex array (VAO, if supported) RLAPI void rlDisableVertexArray(void); // Disable vertex array (VAO, if supported)
RLAPI void rlEnableVertexBuffer(unsigned int id); // Enable vertex buffer (VBO) RLAPI void rlEnableVertexBuffer(unsigned int id); // Enable vertex buffer (VBO)
RLAPI void rlDisableVertexBuffer(void); // Disable vertex buffer (VBO) RLAPI void rlDisableVertexBuffer(void); // Disable vertex buffer (VBO)
RLAPI void rlEnableVertexBufferElement(unsigned int id);// Enable vertex buffer element (VBO element) RLAPI void rlEnableVertexBufferElement(unsigned int id); // Enable vertex buffer element (VBO element)
RLAPI void rlDisableVertexBufferElement(void); // Disable vertex buffer element (VBO element) RLAPI void rlDisableVertexBufferElement(void); // Disable vertex buffer element (VBO element)
RLAPI void rlEnableVertexAttribute(unsigned int index); // Enable vertex attribute index RLAPI void rlEnableVertexAttribute(unsigned int index); // Enable vertex attribute index
RLAPI void rlDisableVertexAttribute(unsigned int index);// Disable vertex attribute index RLAPI void rlDisableVertexAttribute(unsigned int index); // Disable vertex attribute index
#if defined(GRAPHICS_API_OPENGL_11) #if defined(GRAPHICS_API_OPENGL_11)
RLAPI void rlEnableStatePointer(int vertexAttribType, void *buffer); // Enable attribute state pointer RLAPI void rlEnableStatePointer(int vertexAttribType, void *buffer); // Enable attribute state pointer
RLAPI void rlDisableStatePointer(int vertexAttribType); // Disable attribute state pointer RLAPI void rlDisableStatePointer(int vertexAttribType); // Disable attribute state pointer
#endif #endif
// Textures state // Textures state
@ -621,7 +623,7 @@ RLAPI void rlActiveDrawBuffers(int count); // Activate multiple dra
RLAPI void rlBlitFramebuffer(int srcX, int srcY, int srcWidth, int srcHeight, int dstX, int dstY, int dstWidth, int dstHeight, int bufferMask); // Blit active framebuffer to main framebuffer RLAPI void rlBlitFramebuffer(int srcX, int srcY, int srcWidth, int srcHeight, int dstX, int dstY, int dstWidth, int dstHeight, int bufferMask); // Blit active framebuffer to main framebuffer
// General render state // General render state
RLAPI void rlEnableColorBlend(void); // Enable color blending RLAPI void rlEnableColorBlend(void); // Enable color blending
RLAPI void rlDisableColorBlend(void); // Disable color blending RLAPI void rlDisableColorBlend(void); // Disable color blending
RLAPI void rlEnableDepthTest(void); // Enable depth test RLAPI void rlEnableDepthTest(void); // Enable depth test
RLAPI void rlDisableDepthTest(void); // Disable depth test RLAPI void rlDisableDepthTest(void); // Disable depth test
@ -634,7 +636,7 @@ RLAPI void rlEnableScissorTest(void); // Enable scissor test
RLAPI void rlDisableScissorTest(void); // Disable scissor test RLAPI void rlDisableScissorTest(void); // Disable scissor test
RLAPI void rlScissor(int x, int y, int width, int height); // Scissor test RLAPI void rlScissor(int x, int y, int width, int height); // Scissor test
RLAPI void rlEnableWireMode(void); // Enable wire mode RLAPI void rlEnableWireMode(void); // Enable wire mode
RLAPI void rlEnablePointMode(void); // Enable point mode RLAPI void rlEnablePointMode(void); // Enable point mode
RLAPI void rlDisableWireMode(void); // Disable wire mode ( and point ) maybe rename RLAPI void rlDisableWireMode(void); // Disable wire mode ( and point ) maybe rename
RLAPI void rlSetLineWidth(float width); // Set the line drawing width RLAPI void rlSetLineWidth(float width); // Set the line drawing width
RLAPI float rlGetLineWidth(void); // Get the line drawing width RLAPI float rlGetLineWidth(void); // Get the line drawing width
@ -671,48 +673,48 @@ RLAPI int *rlGetShaderLocsDefault(void); // Get default shader lo
// Render batch management // Render batch management
// NOTE: rlgl provides a default render batch to behave like OpenGL 1.1 immediate mode // NOTE: rlgl provides a default render batch to behave like OpenGL 1.1 immediate mode
// but this render batch API is exposed in case of custom batches are required // but this render batch API is exposed in case of custom batches are required
RLAPI rlRenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements); // Load a render batch system RLAPI rlRenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements); // Load a render batch system
RLAPI void rlUnloadRenderBatch(rlRenderBatch batch); // Unload render batch system RLAPI void rlUnloadRenderBatch(rlRenderBatch batch); // Unload render batch system
RLAPI void rlDrawRenderBatch(rlRenderBatch *batch); // Draw render batch data (Update->Draw->Reset) RLAPI void rlDrawRenderBatch(rlRenderBatch *batch); // Draw render batch data (Update->Draw->Reset)
RLAPI void rlSetRenderBatchActive(rlRenderBatch *batch); // Set the active render batch for rlgl (NULL for default internal) RLAPI void rlSetRenderBatchActive(rlRenderBatch *batch); // Set the active render batch for rlgl (NULL for default internal)
RLAPI void rlDrawRenderBatchActive(void); // Update and draw internal render batch RLAPI void rlDrawRenderBatchActive(void); // Update and draw internal render batch
RLAPI bool rlCheckRenderBatchLimit(int vCount); // Check internal buffer overflow for a given number of vertex RLAPI bool rlCheckRenderBatchLimit(int vCount); // Check internal buffer overflow for a given number of vertex
RLAPI void rlSetTexture(unsigned int id); // Set current texture for render batch and check buffers limits RLAPI void rlSetTexture(unsigned int id); // Set current texture for render batch and check buffers limits
//------------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------------
// Vertex buffers management // Vertex buffers management
RLAPI unsigned int rlLoadVertexArray(void); // Load vertex array (vao) if supported RLAPI unsigned int rlLoadVertexArray(void); // Load vertex array (vao) if supported
RLAPI unsigned int rlLoadVertexBuffer(const void *buffer, int size, bool dynamic); // Load a vertex buffer attribute RLAPI unsigned int rlLoadVertexBuffer(const void *buffer, int size, bool dynamic); // Load a vertex buffer object
RLAPI unsigned int rlLoadVertexBufferElement(const void *buffer, int size, bool dynamic); // Load a new attributes element buffer RLAPI unsigned int rlLoadVertexBufferElement(const void *buffer, int size, bool dynamic); // Load vertex buffer elements object
RLAPI void rlUpdateVertexBuffer(unsigned int bufferId, const void *data, int dataSize, int offset); // Update GPU buffer with new data RLAPI void rlUpdateVertexBuffer(unsigned int bufferId, const void *data, int dataSize, int offset); // Update vertex buffer object data on GPU buffer
RLAPI void rlUpdateVertexBufferElements(unsigned int id, const void *data, int dataSize, int offset); // Update vertex buffer elements with new data RLAPI void rlUpdateVertexBufferElements(unsigned int id, const void *data, int dataSize, int offset); // Update vertex buffer elements data on GPU buffer
RLAPI void rlUnloadVertexArray(unsigned int vaoId); RLAPI void rlUnloadVertexArray(unsigned int vaoId); // Unload vertex array (vao)
RLAPI void rlUnloadVertexBuffer(unsigned int vboId); RLAPI void rlUnloadVertexBuffer(unsigned int vboId); // Unload vertex buffer object
RLAPI void rlSetVertexAttribute(unsigned int index, int compSize, int type, bool normalized, int stride, const void *pointer); RLAPI void rlSetVertexAttribute(unsigned int index, int compSize, int type, bool normalized, int stride, const void *pointer); // Set vertex attribute data configuration
RLAPI void rlSetVertexAttributeDivisor(unsigned int index, int divisor); RLAPI void rlSetVertexAttributeDivisor(unsigned int index, int divisor); // Set vertex attribute data divisor
RLAPI void rlSetVertexAttributeDefault(int locIndex, const void *value, int attribType, int count); // Set vertex attribute default value RLAPI void rlSetVertexAttributeDefault(int locIndex, const void *value, int attribType, int count); // Set vertex attribute default value, when attribute to provided
RLAPI void rlDrawVertexArray(int offset, int count); RLAPI void rlDrawVertexArray(int offset, int count); // Draw vertex array (currently active vao)
RLAPI void rlDrawVertexArrayElements(int offset, int count, const void *buffer); RLAPI void rlDrawVertexArrayElements(int offset, int count, const void *buffer); // Draw vertex array elements
RLAPI void rlDrawVertexArrayInstanced(int offset, int count, int instances); RLAPI void rlDrawVertexArrayInstanced(int offset, int count, int instances); // Draw vertex array (currently active vao) with instancing
RLAPI void rlDrawVertexArrayElementsInstanced(int offset, int count, const void *buffer, int instances); RLAPI void rlDrawVertexArrayElementsInstanced(int offset, int count, const void *buffer, int instances); // Draw vertex array elements with instancing
// Textures management // Textures management
RLAPI unsigned int rlLoadTexture(const void *data, int width, int height, int format, int mipmapCount); // Load texture in GPU RLAPI unsigned int rlLoadTexture(const void *data, int width, int height, int format, int mipmapCount); // Load texture data
RLAPI unsigned int rlLoadTextureDepth(int width, int height, bool useRenderBuffer); // Load depth texture/renderbuffer (to be attached to fbo) RLAPI unsigned int rlLoadTextureDepth(int width, int height, bool useRenderBuffer); // Load depth texture/renderbuffer (to be attached to fbo)
RLAPI unsigned int rlLoadTextureCubemap(const void *data, int size, int format); // Load texture cubemap RLAPI unsigned int rlLoadTextureCubemap(const void *data, int size, int format); // Load texture cubemap data
RLAPI void rlUpdateTexture(unsigned int id, int offsetX, int offsetY, int width, int height, int format, const void *data); // Update GPU texture with new data RLAPI void rlUpdateTexture(unsigned int id, int offsetX, int offsetY, int width, int height, int format, const void *data); // Update texture with new data on GPU
RLAPI void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned int *glFormat, unsigned int *glType); // Get OpenGL internal formats RLAPI void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned int *glFormat, unsigned int *glType); // Get OpenGL internal formats
RLAPI const char *rlGetPixelFormatName(unsigned int format); // Get name string for pixel format RLAPI const char *rlGetPixelFormatName(unsigned int format); // Get name string for pixel format
RLAPI void rlUnloadTexture(unsigned int id); // Unload texture from GPU memory RLAPI void rlUnloadTexture(unsigned int id); // Unload texture from GPU memory
RLAPI void rlGenTextureMipmaps(unsigned int id, int width, int height, int format, int *mipmaps); // Generate mipmap data for selected texture RLAPI void rlGenTextureMipmaps(unsigned int id, int width, int height, int format, int *mipmaps); // Generate mipmap data for selected texture
RLAPI void *rlReadTexturePixels(unsigned int id, int width, int height, int format); // Read texture pixel data RLAPI void *rlReadTexturePixels(unsigned int id, int width, int height, int format); // Read texture pixel data
RLAPI unsigned char *rlReadScreenPixels(int width, int height); // Read screen pixel data (color buffer) RLAPI unsigned char *rlReadScreenPixels(int width, int height); // Read screen pixel data (color buffer)
// Framebuffer management (fbo) // Framebuffer management (fbo)
RLAPI unsigned int rlLoadFramebuffer(int width, int height); // Load an empty framebuffer RLAPI unsigned int rlLoadFramebuffer(int width, int height); // Load an empty framebuffer
RLAPI void rlFramebufferAttach(unsigned int fboId, unsigned int texId, int attachType, int texType, int mipLevel); // Attach texture/renderbuffer to a framebuffer RLAPI void rlFramebufferAttach(unsigned int fboId, unsigned int texId, int attachType, int texType, int mipLevel); // Attach texture/renderbuffer to a framebuffer
RLAPI bool rlFramebufferComplete(unsigned int id); // Verify framebuffer is complete RLAPI bool rlFramebufferComplete(unsigned int id); // Verify framebuffer is complete
RLAPI void rlUnloadFramebuffer(unsigned int id); // Delete framebuffer from GPU RLAPI void rlUnloadFramebuffer(unsigned int id); // Delete framebuffer from GPU
@ -723,14 +725,14 @@ RLAPI unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fSha
RLAPI void rlUnloadShaderProgram(unsigned int id); // Unload shader program RLAPI void rlUnloadShaderProgram(unsigned int id); // Unload shader program
RLAPI int rlGetLocationUniform(unsigned int shaderId, const char *uniformName); // Get shader location uniform RLAPI int rlGetLocationUniform(unsigned int shaderId, const char *uniformName); // Get shader location uniform
RLAPI int rlGetLocationAttrib(unsigned int shaderId, const char *attribName); // Get shader location attribute RLAPI int rlGetLocationAttrib(unsigned int shaderId, const char *attribName); // Get shader location attribute
RLAPI void rlSetUniform(int locIndex, const void *value, int uniformType, int count); // Set shader value uniform RLAPI void rlSetUniform(int locIndex, const void *value, int uniformType, int count); // Set shader value uniform
RLAPI void rlSetUniformMatrix(int locIndex, Matrix mat); // Set shader value matrix RLAPI void rlSetUniformMatrix(int locIndex, Matrix mat); // Set shader value matrix
RLAPI void rlSetUniformSampler(int locIndex, unsigned int textureId); // Set shader value sampler RLAPI void rlSetUniformSampler(int locIndex, unsigned int textureId); // Set shader value sampler
RLAPI void rlSetShader(unsigned int id, int *locs); // Set shader currently active (id and locations) RLAPI void rlSetShader(unsigned int id, int *locs); // Set shader currently active (id and locations)
// Compute shader management // Compute shader management
RLAPI unsigned int rlLoadComputeShaderProgram(unsigned int shaderId); // Load compute shader program RLAPI unsigned int rlLoadComputeShaderProgram(unsigned int shaderId); // Load compute shader program
RLAPI void rlComputeShaderDispatch(unsigned int groupX, unsigned int groupY, unsigned int groupZ); // Dispatch compute shader (equivalent to *draw* for graphics pipeline) RLAPI void rlComputeShaderDispatch(unsigned int groupX, unsigned int groupY, unsigned int groupZ); // Dispatch compute shader (equivalent to *draw* for graphics pipeline)
// Shader buffer storage object management (ssbo) // Shader buffer storage object management (ssbo)
RLAPI unsigned int rlLoadShaderBuffer(unsigned int size, const void *data, int usageHint); // Load shader storage buffer object (SSBO) RLAPI unsigned int rlLoadShaderBuffer(unsigned int size, const void *data, int usageHint); // Load shader storage buffer object (SSBO)
@ -773,6 +775,12 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
#if defined(RLGL_IMPLEMENTATION) #if defined(RLGL_IMPLEMENTATION)
// Expose OpenGL functions from glad in raylib
#if defined(BUILD_LIBTYPE_SHARED)
#define GLAD_API_CALL_EXPORT
#define GLAD_API_CALL_EXPORT_BUILD
#endif
#if defined(GRAPHICS_API_OPENGL_11) #if defined(GRAPHICS_API_OPENGL_11)
#if defined(__APPLE__) #if defined(__APPLE__)
#include <OpenGL/gl.h> // OpenGL 1.1 library for OSX #include <OpenGL/gl.h> // OpenGL 1.1 library for OSX
@ -3787,6 +3795,10 @@ unsigned int rlLoadVertexArray(void)
void rlSetVertexAttribute(unsigned int index, int compSize, int type, bool normalized, int stride, const void *pointer) void rlSetVertexAttribute(unsigned int index, int compSize, int type, bool normalized, int stride, const void *pointer)
{ {
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
// NOTE: Data type could be: GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT
// Additional types (depends on OpenGL version or extensions):
// - GL_HALF_FLOAT, GL_FLOAT, GL_DOUBLE, GL_FIXED,
// - GL_INT_2_10_10_10_REV, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT_10F_11F_11F_REV
glVertexAttribPointer(index, compSize, type, normalized, stride, pointer); glVertexAttribPointer(index, compSize, type, normalized, stride, pointer);
#endif #endif
} }

View File

@ -1850,6 +1850,104 @@ bool ExportMesh(Mesh mesh, const char *fileName)
return success; return success;
} }
// Export mesh as code file (.h) defining multiple arrays of vertex attributes
bool ExportMeshAsCode(Mesh mesh, const char *fileName)
{
bool success = false;
#ifndef TEXT_BYTES_PER_LINE
#define TEXT_BYTES_PER_LINE 20
#endif
// NOTE: Text data buffer size is fixed to 64MB
char *txtData = (char *)RL_CALLOC(64*1024*1024, sizeof(char)); // 64 MB
int byteCount = 0;
byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n");
byteCount += sprintf(txtData + byteCount, "// //\n");
byteCount += sprintf(txtData + byteCount, "// MeshAsCode exporter v1.0 - Mesh vertex data exported as arrays //\n");
byteCount += sprintf(txtData + byteCount, "// //\n");
byteCount += sprintf(txtData + byteCount, "// more info and bugs-report: github.com/raysan5/raylib //\n");
byteCount += sprintf(txtData + byteCount, "// feedback and support: ray[at]raylib.com //\n");
byteCount += sprintf(txtData + byteCount, "// //\n");
byteCount += sprintf(txtData + byteCount, "// Copyright (c) 2023 Ramon Santamaria (@raysan5) //\n");
byteCount += sprintf(txtData + byteCount, "// //\n");
byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n\n");
// Get file name from path and convert variable name to uppercase
char varFileName[256] = { 0 };
strcpy(varFileName, GetFileNameWithoutExt(fileName));
for (int i = 0; varFileName[i] != '\0'; i++) if ((varFileName[i] >= 'a') && (varFileName[i] <= 'z')) { varFileName[i] = varFileName[i] - 32; }
// Add image information
byteCount += sprintf(txtData + byteCount, "// Mesh basic information\n");
byteCount += sprintf(txtData + byteCount, "#define %s_VERTEX_COUNT %i\n", varFileName, mesh.vertexCount);
byteCount += sprintf(txtData + byteCount, "#define %s_TRIANGLE_COUNT %i\n\n", varFileName, mesh.triangleCount);
// Define vertex attributes data as separate arrays
//-----------------------------------------------------------------------------------------
if (mesh.vertices != NULL) // Vertex position (XYZ - 3 components per vertex - float)
{
byteCount += sprintf(txtData + byteCount, "static float %s_VERTEX_DATA[%i] = { ", varFileName, mesh.vertexCount*3);
for (int i = 0; i < mesh.vertexCount*3 - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "%.3ff,\n" : "%.3ff, "), mesh.vertices[i]);
byteCount += sprintf(txtData + byteCount, "%.3ff };\n\n", mesh.vertices[mesh.vertexCount*3 - 1]);
}
if (mesh.texcoords != NULL) // Vertex texture coordinates (UV - 2 components per vertex - float)
{
byteCount += sprintf(txtData + byteCount, "static float %s_TEXCOORD_DATA[%i] = { ", varFileName, mesh.vertexCount*2);
for (int i = 0; i < mesh.vertexCount*2 - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "%.3ff,\n" : "%.3ff, "), mesh.texcoords[i]);
byteCount += sprintf(txtData + byteCount, "%.3ff };\n\n", mesh.texcoords[mesh.vertexCount*2 - 1]);
}
if (mesh.texcoords2 != NULL) // Vertex texture coordinates (UV - 2 components per vertex - float)
{
byteCount += sprintf(txtData + byteCount, "static float %s_TEXCOORD2_DATA[%i] = { ", varFileName, mesh.vertexCount*2);
for (int i = 0; i < mesh.vertexCount*2 - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "%.3ff,\n" : "%.3ff, "), mesh.texcoords2[i]);
byteCount += sprintf(txtData + byteCount, "%.3ff };\n\n", mesh.texcoords2[mesh.vertexCount*2 - 1]);
}
if (mesh.normals != NULL) // Vertex normals (XYZ - 3 components per vertex - float)
{
byteCount += sprintf(txtData + byteCount, "static float %s_NORMAL_DATA[%i] = { ", varFileName, mesh.vertexCount*3);
for (int i = 0; i < mesh.vertexCount*3 - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "%.3ff,\n" : "%.3ff, "), mesh.normals[i]);
byteCount += sprintf(txtData + byteCount, "%.3ff };\n\n", mesh.normals[mesh.vertexCount*3 - 1]);
}
if (mesh.tangents != NULL) // Vertex tangents (XYZW - 4 components per vertex - float)
{
byteCount += sprintf(txtData + byteCount, "static float %s_TANGENT_DATA[%i] = { ", varFileName, mesh.vertexCount*4);
for (int i = 0; i < mesh.vertexCount*4 - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "%.3ff,\n" : "%.3ff, "), mesh.tangents[i]);
byteCount += sprintf(txtData + byteCount, "%.3ff };\n\n", mesh.tangents[mesh.vertexCount*4 - 1]);
}
if (mesh.colors != NULL) // Vertex colors (RGBA - 4 components per vertex - unsigned char)
{
byteCount += sprintf(txtData + byteCount, "static unsigned char %s_COLOR_DATA[%i] = { ", varFileName, mesh.vertexCount*4);
for (int i = 0; i < mesh.vertexCount*4 - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%x,\n" : "0x%x, "), mesh.colors[i]);
byteCount += sprintf(txtData + byteCount, "0x%x };\n\n", mesh.colors[mesh.vertexCount*4 - 1]);
}
if (mesh.indices != NULL) // Vertex indices (3 index per triangle - unsigned short)
{
byteCount += sprintf(txtData + byteCount, "static unsigned short %s_INDEX_DATA[%i] = { ", varFileName, mesh.triangleCount*3);
for (int i = 0; i < mesh.triangleCount*3 - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "%i,\n" : "%i, "), mesh.indices[i]);
byteCount += sprintf(txtData + byteCount, "%i };\n", mesh.indices[mesh.triangleCount*3 - 1]);
}
//-----------------------------------------------------------------------------------------
// NOTE: Text data size exported is determined by '\0' (NULL) character
success = SaveFileText(fileName, txtData);
RL_FREE(txtData);
//if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Image as code exported successfully", fileName);
//else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export image as code", fileName);
return success;
}
#if defined(SUPPORT_FILEFORMAT_OBJ) || defined(SUPPORT_FILEFORMAT_MTL) #if defined(SUPPORT_FILEFORMAT_OBJ) || defined(SUPPORT_FILEFORMAT_MTL)
// Process obj materials // Process obj materials
static void ProcessMaterialsOBJ(Material *materials, tinyobj_material_t *mats, int materialCount) static void ProcessMaterialsOBJ(Material *materials, tinyobj_material_t *mats, int materialCount)
@ -5155,16 +5253,29 @@ static Model LoadGLTF(const char *fileName)
if ((attribute->component_type == cgltf_component_type_r_8u) && (attribute->type == cgltf_type_vec4)) if ((attribute->component_type == cgltf_component_type_r_8u) && (attribute->type == cgltf_type_vec4))
{ {
// Init raylib mesh bone ids to copy glTF attribute data // Handle 8-bit unsigned byte, vec4 format
model.meshes[meshIndex].boneIds = RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(unsigned char)); model.meshes[meshIndex].boneIds = RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(unsigned char));
// Load 4 components of unsigned char data type into mesh.boneIds
// for cgltf_attribute_type_joints we have:
// - data.meshes[0] (256 vertices)
// - 256 values, provided as cgltf_type_vec4 of bytes (4 byte per joint, stride 4)
LOAD_ATTRIBUTE(attribute, 4, unsigned char, model.meshes[meshIndex].boneIds) LOAD_ATTRIBUTE(attribute, 4, unsigned char, model.meshes[meshIndex].boneIds)
} }
else TRACELOG(LOG_WARNING, "MODEL: [%s] Joint attribute data format not supported, use vec4 u8", fileName); else if ((attribute->component_type == cgltf_component_type_r_16u) && (attribute->type == cgltf_type_vec2))
{
// Handle 16-bit unsigned short, vec2 format
model.meshes[meshIndex].boneIds = RL_CALLOC(model.meshes[meshIndex].vertexCount*2, sizeof(unsigned short));
LOAD_ATTRIBUTE(attribute, 2, unsigned short, model.meshes[meshIndex].boneIds)
}
else if ((attribute->component_type == cgltf_component_type_r_32u) && (attribute->type == cgltf_type_vec4))
{
// Handle 32-bit unsigned int, vec4 format
model.meshes[meshIndex].boneIds = RL_CALLOC(model.meshes[meshIndex].vertexCount*4, sizeof(unsigned int));
LOAD_ATTRIBUTE(attribute, 4, unsigned int, model.meshes[meshIndex].boneIds)
}
else if ((attribute->component_type == cgltf_component_type_r_32f) && (attribute->type == cgltf_type_vec2))
{
// Handle 32-bit float, vec2 format
model.meshes[meshIndex].boneIds = RL_CALLOC(model.meshes[meshIndex].vertexCount*2, sizeof(float));
LOAD_ATTRIBUTE(attribute, 2, float, model.meshes[meshIndex].boneIds)
}
else TRACELOG(LOG_WARNING, "MODEL: [%s] Joint attribute data format not supported", fileName);
} }
else if (data->meshes[i].primitives[p].attributes[j].type == cgltf_attribute_type_weights) // WEIGHTS_n (vec4 / u8, u16, f32) else if (data->meshes[i].primitives[p].attributes[j].type == cgltf_attribute_type_weights) // WEIGHTS_n (vec4 / u8, u16, f32)
{ {

View File

@ -1546,6 +1546,92 @@ void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, fl
// Draw spline: linear, minimum 2 points // Draw spline: linear, minimum 2 points
void DrawSplineLinear(Vector2 *points, int pointCount, float thick, Color color) void DrawSplineLinear(Vector2 *points, int pointCount, float thick, Color color)
{ {
if (pointCount < 2) return;
#if defined(SUPPORT_SPLINE_MITERS)
Vector2 prevNormal = (Vector2){-(points[1].y - points[0].y), (points[1].x - points[0].x)};
float prevLength = sqrtf(prevNormal.x*prevNormal.x + prevNormal.y*prevNormal.y);
if (prevLength > 0.0f)
{
prevNormal.x /= prevLength;
prevNormal.y /= prevLength;
}
else
{
prevNormal.x = 0.0f;
prevNormal.y = 0.0f;
}
Vector2 prevRadius = { 0.5f*thick*prevNormal.x, 0.5f*thick*prevNormal.y };
for (int i = 0; i < pointCount - 1; i++)
{
Vector2 normal = { 0 };
if (i < pointCount - 2)
{
normal = (Vector2){-(points[i + 2].y - points[i + 1].y), (points[i + 2].x - points[i + 1].x)};
float normalLength = sqrtf(normal.x*normal.x + normal.y*normal.y);
if (normalLength > 0.0f)
{
normal.x /= normalLength;
normal.y /= normalLength;
}
else
{
normal.x = 0.0f;
normal.y = 0.0f;
}
}
else
{
normal = prevNormal;
}
Vector2 radius = { prevNormal.x + normal.x, prevNormal.y + normal.y };
float radiusLength = sqrtf(radius.x*radius.x + radius.y*radius.y);
if (radiusLength > 0.0f)
{
radius.x /= radiusLength;
radius.y /= radiusLength;
}
else
{
radius.x = 0.0f;
radius.y = 0.0f;
}
float cosTheta = radius.x*normal.x + radius.y*normal.y;
if (cosTheta != 0.0f)
{
radius.x *= (thick*0.5f/cosTheta);
radius.y *= (thick*0.5f/cosTheta);
}
else
{
radius.x = 0.0f;
radius.y = 0.0f;
}
Vector2 strip[4] = {
{ points[i].x - prevRadius.x, points[i].y - prevRadius.y },
{ points[i].x + prevRadius.x, points[i].y + prevRadius.y },
{ points[i + 1].x - radius.x, points[i + 1].y - radius.y },
{ points[i + 1].x + radius.x, points[i + 1].y + radius.y }
};
DrawTriangleStrip(strip, 4, color);
prevRadius = radius;
prevNormal = normal;
}
#else // !SUPPORT_SPLINE_MITTERS
Vector2 delta = { 0 }; Vector2 delta = { 0 };
float length = 0.0f; float length = 0.0f;
float scale = 0.0f; float scale = 0.0f;
@ -1567,8 +1653,10 @@ void DrawSplineLinear(Vector2 *points, int pointCount, float thick, Color color)
DrawTriangleStrip(strip, 4, color); DrawTriangleStrip(strip, 4, color);
} }
#if defined(SUPPORT_SPLINE_SEGMENT_CAPS) #endif
#if defined(SUPPORT_SPLINE_SEGMENT_CAPS)
// TODO: Add spline segment rounded caps at the begin/end of the spline
#endif #endif
} }
@ -2132,11 +2220,11 @@ bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec)
{ {
bool collision = false; bool collision = false;
int recCenterX = (int)(rec.x + rec.width/2.0f); float recCenterX = rec.x + rec.width/2.0f;
int recCenterY = (int)(rec.y + rec.height/2.0f); float recCenterY = rec.y + rec.height/2.0f;
float dx = fabsf(center.x - (float)recCenterX); float dx = fabsf(center.x - recCenterX);
float dy = fabsf(center.y - (float)recCenterY); float dy = fabsf(center.y - recCenterY);
if (dx > (rec.width/2.0f + radius)) { return false; } if (dx > (rec.width/2.0f + radius)) { return false; }
if (dy > (rec.height/2.0f + radius)) { return false; } if (dy > (rec.height/2.0f + radius)) { return false; }

View File

@ -604,7 +604,6 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
// Fill fontChars in case not provided externally // Fill fontChars in case not provided externally
// NOTE: By default we fill glyphCount consecutively, starting at 32 (Space) // NOTE: By default we fill glyphCount consecutively, starting at 32 (Space)
if (codepoints == NULL) if (codepoints == NULL)
{ {
codepoints = (int *)RL_MALLOC(codepointCount*sizeof(int)); codepoints = (int *)RL_MALLOC(codepointCount*sizeof(int));
@ -612,7 +611,7 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
genFontChars = true; genFontChars = true;
} }
chars = (GlyphInfo *)RL_MALLOC(codepointCount*sizeof(GlyphInfo)); chars = (GlyphInfo *)RL_CALLOC(codepointCount, sizeof(GlyphInfo));
// NOTE: Using simple packaging, one char after another // NOTE: Using simple packaging, one char after another
for (int i = 0; i < codepointCount; i++) for (int i = 0; i < codepointCount; i++)
@ -626,54 +625,67 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
// stbtt_GetCodepointBitmapBox() -- how big the bitmap must be // stbtt_GetCodepointBitmapBox() -- how big the bitmap must be
// stbtt_MakeCodepointBitmap() -- renders into bitmap you provide // stbtt_MakeCodepointBitmap() -- renders into bitmap you provide
if (type != FONT_SDF) chars[i].image.data = stbtt_GetCodepointBitmap(&fontInfo, scaleFactor, scaleFactor, ch, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY); // Check if a glyph is available in the font
else if (ch != 32) chars[i].image.data = stbtt_GetCodepointSDF(&fontInfo, scaleFactor, ch, FONT_SDF_CHAR_PADDING, FONT_SDF_ON_EDGE_VALUE, FONT_SDF_PIXEL_DIST_SCALE, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY); // WARNING: if (index == 0), glyph not found, it could fallback to default .notdef glyph (if defined in font)
else chars[i].image.data = NULL; int index = stbtt_FindGlyphIndex(&fontInfo, ch);
stbtt_GetCodepointHMetrics(&fontInfo, ch, &chars[i].advanceX, NULL); if (index > 0)
chars[i].advanceX = (int)((float)chars[i].advanceX*scaleFactor);
// Load characters images
chars[i].image.width = chw;
chars[i].image.height = chh;
chars[i].image.mipmaps = 1;
chars[i].image.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE;
chars[i].offsetY += (int)((float)ascent*scaleFactor);
// NOTE: We create an empty image for space character, it could be further required for atlas packing
if (ch == 32)
{ {
Image imSpace = { switch (type)
.data = RL_CALLOC(chars[i].advanceX*fontSize, 2),
.width = chars[i].advanceX,
.height = fontSize,
.mipmaps = 1,
.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE
};
chars[i].image = imSpace;
}
if (type == FONT_BITMAP)
{
// Aliased bitmap (black & white) font generation, avoiding anti-aliasing
// NOTE: For optimum results, bitmap font should be generated at base pixel size
for (int p = 0; p < chw*chh; p++)
{ {
if (((unsigned char *)chars[i].image.data)[p] < FONT_BITMAP_ALPHA_THRESHOLD) ((unsigned char *)chars[i].image.data)[p] = 0; case FONT_DEFAULT:
else ((unsigned char *)chars[i].image.data)[p] = 255; case FONT_BITMAP: chars[i].image.data = stbtt_GetCodepointBitmap(&fontInfo, scaleFactor, scaleFactor, ch, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY); break;
case FONT_SDF: if (ch != 32) chars[i].image.data = stbtt_GetCodepointSDF(&fontInfo, scaleFactor, ch, FONT_SDF_CHAR_PADDING, FONT_SDF_ON_EDGE_VALUE, FONT_SDF_PIXEL_DIST_SCALE, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY); break;
default: break;
}
if (chars[i].image.data != NULL) // Glyph data has been found in the font
{
stbtt_GetCodepointHMetrics(&fontInfo, ch, &chars[i].advanceX, NULL);
chars[i].advanceX = (int)((float)chars[i].advanceX*scaleFactor);
// Load characters images
chars[i].image.width = chw;
chars[i].image.height = chh;
chars[i].image.mipmaps = 1;
chars[i].image.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE;
chars[i].offsetY += (int)((float)ascent*scaleFactor);
}
// NOTE: We create an empty image for space character,
// it could be further required for atlas packing
if (ch == 32)
{
stbtt_GetCodepointHMetrics(&fontInfo, ch, &chars[i].advanceX, NULL);
chars[i].advanceX = (int)((float)chars[i].advanceX*scaleFactor);
Image imSpace = {
.data = RL_CALLOC(chars[i].advanceX*fontSize, 2),
.width = chars[i].advanceX,
.height = fontSize,
.mipmaps = 1,
.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE
};
chars[i].image = imSpace;
}
if (type == FONT_BITMAP)
{
// Aliased bitmap (black & white) font generation, avoiding anti-aliasing
// NOTE: For optimum results, bitmap font should be generated at base pixel size
for (int p = 0; p < chw*chh; p++)
{
if (((unsigned char *)chars[i].image.data)[p] < FONT_BITMAP_ALPHA_THRESHOLD) ((unsigned char *)chars[i].image.data)[p] = 0;
else ((unsigned char *)chars[i].image.data)[p] = 255;
}
} }
} }
else
// Get bounding box for character (maybe offset to account for chars that dip above or below the line) {
/* // TODO: Use some fallback glyph for codepoints not found in the font
int chX1, chY1, chX2, chY2; }
stbtt_GetCodepointBitmapBox(&fontInfo, ch, scaleFactor, scaleFactor, &chX1, &chY1, &chX2, &chY2);
TRACELOGD("FONT: Character box measures: %i, %i, %i, %i", chX1, chY1, chX2 - chX1, chY2 - chY1);
TRACELOGD("FONT: Character offsetY: %i", (int)((float)ascent*scaleFactor) + chY1);
*/
} }
} }
else TRACELOG(LOG_WARNING, "FONT: Failed to process TTF font data"); else TRACELOG(LOG_WARNING, "FONT: Failed to process TTF font data");
@ -1409,6 +1421,28 @@ int TextToInteger(const char *text)
return value*sign; return value*sign;
} }
float TextToFloat(const char *text)
{
float value = 0.0f;
float sign = 1.0f;
if ((text[0] == '+') || (text[0] == '-'))
{
if (text[0] == '-') sign = -1;
text++;
}
int i = 0;
for (; ((text[i] >= '0') && (text[i] <= '9')); ++i) value = value*10.0f + (float)(text[i] - '0');
if (text[i++] != '.') return value*sign;
float divisor = 10.0f;
for (; ((text[i] >= '0') && (text[i] <= '9')); ++i)
{
value += ((float)(text[i] - '0'))/divisor;
divisor = divisor*10.0f;
}
return value;
}
#if defined(SUPPORT_TEXT_MANIPULATION) #if defined(SUPPORT_TEXT_MANIPULATION)
// Copy one string to another, returns bytes copied // Copy one string to another, returns bytes copied
int TextCopy(char *dst, const char *src) int TextCopy(char *dst, const char *src)
@ -2017,7 +2051,8 @@ static int GetLine(const char *origin, char *buffer, int maxLength)
// REQUIRES: strstr(), sscanf(), strrchr(), memcpy() // REQUIRES: strstr(), sscanf(), strrchr(), memcpy()
static Font LoadBMFont(const char *fileName) static Font LoadBMFont(const char *fileName)
{ {
#define MAX_BUFFER_SIZE 256 #define MAX_BUFFER_SIZE 256
#define MAX_FONT_IMAGE_PAGES 8
Font font = { 0 }; Font font = { 0 };
@ -2029,7 +2064,8 @@ static Font LoadBMFont(const char *fileName)
int imWidth = 0; int imWidth = 0;
int imHeight = 0; int imHeight = 0;
char imFileName[129] = { 0 }; int pageCount = 1;
char imFileName[MAX_FONT_IMAGE_PAGES][129] = { 0 };
int base = 0; // Useless data int base = 0; // Useless data
int readBytes = 0; // Data bytes read int readBytes = 0; // Data bytes read
@ -2048,17 +2084,26 @@ static Font LoadBMFont(const char *fileName)
// Read line data // Read line data
readBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE); readBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
searchPoint = strstr(buffer, "lineHeight"); searchPoint = strstr(buffer, "lineHeight");
readVars = sscanf(searchPoint, "lineHeight=%i base=%i scaleW=%i scaleH=%i", &fontSize, &base, &imWidth, &imHeight); readVars = sscanf(searchPoint, "lineHeight=%i base=%i scaleW=%i scaleH=%i pages=%i", &fontSize, &base, &imWidth, &imHeight, &pageCount);
fileTextPtr += (readBytes + 1); fileTextPtr += (readBytes + 1);
if (readVars < 4) { UnloadFileText(fileText); return font; } // Some data not available, file malformed if (readVars < 4) { UnloadFileText(fileText); return font; } // Some data not available, file malformed
readBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE); if (pageCount > MAX_FONT_IMAGE_PAGES)
searchPoint = strstr(buffer, "file"); {
readVars = sscanf(searchPoint, "file=\"%128[^\"]\"", imFileName); TRACELOG(LOG_WARNING, "FONT: [%s] Font defines more pages than supported: %i/%i", fileName, pageCount, MAX_FONT_IMAGE_PAGES);
fileTextPtr += (readBytes + 1); pageCount = MAX_FONT_IMAGE_PAGES;
}
if (readVars < 1) { UnloadFileText(fileText); return font; } // No fileName read for (int i = 0; i < pageCount; i++)
{
readBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
searchPoint = strstr(buffer, "file");
readVars = sscanf(searchPoint, "file=\"%128[^\"]\"", imFileName[i]);
fileTextPtr += (readBytes + 1);
if (readVars < 1) { UnloadFileText(fileText); return font; } // No fileName read
}
readBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE); readBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
searchPoint = strstr(buffer, "count"); searchPoint = strstr(buffer, "count");
@ -2067,50 +2112,56 @@ static Font LoadBMFont(const char *fileName)
if (readVars < 1) { UnloadFileText(fileText); return font; } // No glyphCount read if (readVars < 1) { UnloadFileText(fileText); return font; } // No glyphCount read
// Compose correct path using route of .fnt file (fileName) and imFileName // Load all required images for further compose
char *imPath = NULL; Image *imFonts = (Image *)RL_CALLOC(pageCount, sizeof(Image)); // Font atlases, multiple images
char *lastSlash = NULL;
lastSlash = strrchr(fileName, '/'); for (int i = 0; i < pageCount; i++)
if (lastSlash == NULL) lastSlash = strrchr(fileName, '\\');
if (lastSlash != NULL)
{ {
// NOTE: We need some extra space to avoid memory corruption on next allocations! imFonts[i] = LoadImage(TextFormat("%s/%s", GetDirectoryPath(fileName), imFileName[i]));
imPath = (char *)RL_CALLOC(TextLength(fileName) - TextLength(lastSlash) + TextLength(imFileName) + 4, 1);
memcpy(imPath, fileName, TextLength(fileName) - TextLength(lastSlash) + 1);
memcpy(imPath + TextLength(fileName) - TextLength(lastSlash) + 1, imFileName, TextLength(imFileName));
}
else imPath = imFileName;
TRACELOGD(" > Image loading path: %s", imPath); if (imFonts[i].format == PIXELFORMAT_UNCOMPRESSED_GRAYSCALE)
Image imFont = LoadImage(imPath);
if (imFont.format == PIXELFORMAT_UNCOMPRESSED_GRAYSCALE)
{
// Convert image to GRAYSCALE + ALPHA, using the mask as the alpha channel
Image imFontAlpha = {
.data = RL_CALLOC(imFont.width*imFont.height, 2),
.width = imFont.width,
.height = imFont.height,
.mipmaps = 1,
.format = PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA
};
for (int p = 0, i = 0; p < (imFont.width*imFont.height*2); p += 2, i++)
{ {
((unsigned char *)(imFontAlpha.data))[p] = 0xff; // Convert image to GRAYSCALE + ALPHA, using the mask as the alpha channel
((unsigned char *)(imFontAlpha.data))[p + 1] = ((unsigned char *)imFont.data)[i]; Image imFontAlpha = {
} .data = RL_CALLOC(imFonts[i].width*imFonts[i].height, 2),
.width = imFonts[i].width,
.height = imFonts[i].height,
.mipmaps = 1,
.format = PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA
};
UnloadImage(imFont); for (int p = 0, pi = 0; p < (imFonts[i].width*imFonts[i].height*2); p += 2, pi++)
imFont = imFontAlpha; {
((unsigned char *)(imFontAlpha.data))[p] = 0xff;
((unsigned char *)(imFontAlpha.data))[p + 1] = ((unsigned char *)imFonts[i].data)[pi];
}
UnloadImage(imFonts[i]);
imFonts[i] = imFontAlpha;
}
} }
font.texture = LoadTextureFromImage(imFont); Image fullFont = imFonts[0];
for (int i = 1; i < pageCount; i++) UnloadImage(imFonts[i]);
if (lastSlash != NULL) RL_FREE(imPath); // If multiple atlas, then merge atlas
// NOTE: WARNING: This process could be really slow!
if (pageCount > 1)
{
// Resize font atlas to draw additional images
ImageResizeCanvas(&fullFont, imWidth, imHeight*pageCount, 0, 0, BLACK);
for (int i = 1; i < pageCount; i++)
{
Rectangle srcRec = { 0.0f, 0.0f, (float)imWidth, (float)imHeight };
Rectangle destRec = { 0.0f, (float)imHeight*(float)i, (float)imWidth, (float)imHeight };
ImageDraw(&fullFont, imFonts[i], srcRec, destRec, WHITE);
}
}
RL_FREE(imFonts);
font.texture = LoadTextureFromImage(fullFont);
// Fill font characters info data // Fill font characters info data
font.baseSize = fontSize; font.baseSize = fontSize;
@ -2119,19 +2170,19 @@ static Font LoadBMFont(const char *fileName)
font.glyphs = (GlyphInfo *)RL_MALLOC(glyphCount*sizeof(GlyphInfo)); font.glyphs = (GlyphInfo *)RL_MALLOC(glyphCount*sizeof(GlyphInfo));
font.recs = (Rectangle *)RL_MALLOC(glyphCount*sizeof(Rectangle)); font.recs = (Rectangle *)RL_MALLOC(glyphCount*sizeof(Rectangle));
int charId, charX, charY, charWidth, charHeight, charOffsetX, charOffsetY, charAdvanceX; int charId, charX, charY, charWidth, charHeight, charOffsetX, charOffsetY, charAdvanceX, pageID;
for (int i = 0; i < glyphCount; i++) for (int i = 0; i < glyphCount; i++)
{ {
readBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE); readBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
readVars = sscanf(buffer, "char id=%i x=%i y=%i width=%i height=%i xoffset=%i yoffset=%i xadvance=%i", readVars = sscanf(buffer, "char id=%i x=%i y=%i width=%i height=%i xoffset=%i yoffset=%i xadvance=%i page=%i",
&charId, &charX, &charY, &charWidth, &charHeight, &charOffsetX, &charOffsetY, &charAdvanceX); &charId, &charX, &charY, &charWidth, &charHeight, &charOffsetX, &charOffsetY, &charAdvanceX, &pageID);
fileTextPtr += (readBytes + 1); fileTextPtr += (readBytes + 1);
if (readVars == 8) // Make sure all char data has been properly read if (readVars == 9) // Make sure all char data has been properly read
{ {
// Get character rectangle in the font atlas texture // Get character rectangle in the font atlas texture
font.recs[i] = (Rectangle){ (float)charX, (float)charY, (float)charWidth, (float)charHeight }; font.recs[i] = (Rectangle){ (float)charX, (float)charY + (float)imHeight*pageID, (float)charWidth, (float)charHeight };
// Save data properly in sprite font // Save data properly in sprite font
font.glyphs[i].value = charId; font.glyphs[i].value = charId;
@ -2139,13 +2190,13 @@ static Font LoadBMFont(const char *fileName)
font.glyphs[i].offsetY = charOffsetY; font.glyphs[i].offsetY = charOffsetY;
font.glyphs[i].advanceX = charAdvanceX; font.glyphs[i].advanceX = charAdvanceX;
// Fill character image data from imFont data // Fill character image data from full font data
font.glyphs[i].image = ImageFromImage(imFont, font.recs[i]); font.glyphs[i].image = ImageFromImage(fullFont, font.recs[i]);
} }
else TRACELOG(LOG_WARNING, "FONT: [%s] Some characters data not correctly provided", fileName); else TRACELOG(LOG_WARNING, "FONT: [%s] Some characters data not correctly provided", fileName);
} }
UnloadImage(imFont); UnloadImage(fullFont);
UnloadFileText(fileText); UnloadFileText(fileText);
if (font.texture.id == 0) if (font.texture.id == 0)
@ -2158,6 +2209,7 @@ static Font LoadBMFont(const char *fileName)
return font; return font;
} }
#endif #endif
#endif // SUPPORT_MODULE_RTEXT #endif // SUPPORT_MODULE_RTEXT

View File

@ -213,14 +213,14 @@
#define STBIR_MALLOC(size,c) ((void)(c), RL_MALLOC(size)) #define STBIR_MALLOC(size,c) ((void)(c), RL_MALLOC(size))
#define STBIR_FREE(ptr,c) ((void)(c), RL_FREE(ptr)) #define STBIR_FREE(ptr,c) ((void)(c), RL_FREE(ptr))
#define STB_IMAGE_RESIZE_IMPLEMENTATION #define STB_IMAGE_RESIZE_IMPLEMENTATION
#include "external/stb_image_resize2.h" // Required for: stbir_resize_uint8_linear() [ImageResize()] #include "external/stb_image_resize2.h" // Required for: stbir_resize_uint8_linear() [ImageResize()]
#if defined(SUPPORT_FILEFORMAT_SVG) #if defined(SUPPORT_FILEFORMAT_SVG)
#define NANOSVG_IMPLEMENTATION // Expands implementation #define NANOSVG_IMPLEMENTATION // Expands implementation
#include "external/nanosvg.h" #include "external/nanosvg.h"
#define NANOSVGRAST_IMPLEMENTATION #define NANOSVGRAST_IMPLEMENTATION
#include "external/nanosvgrast.h" #include "external/nanosvgrast.h"
#endif #endif
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -1959,29 +1959,24 @@ void ImageBlurGaussian(Image *image, int blurSize) {
float avgG = 0.0f; float avgG = 0.0f;
float avgB = 0.0f; float avgB = 0.0f;
float avgAlpha = 0.0f; float avgAlpha = 0.0f;
int convolutionSize = blurSize+1; int convolutionSize = blurSize;
for (int i = 0; i < blurSize+1; i++) for (int i = 0; i < blurSize; i++)
{ {
avgR += pixelsCopy1[row*image->width + i].x; avgR += pixelsCopy1[row*image->width + i].x;
avgG += pixelsCopy1[row*image->width + i].y; avgG += pixelsCopy1[row*image->width + i].y;
avgB += pixelsCopy1[row*image->width + i].z; avgB += pixelsCopy1[row*image->width + i].z;
avgAlpha += pixelsCopy1[row*image->width + i].w; avgAlpha += pixelsCopy1[row*image->width + i].w;
} }
pixelsCopy2[row*image->width].x = avgR/convolutionSize; for (int x = 0; x < image->width; x++)
pixelsCopy2[row*image->width].y = avgG/convolutionSize;
pixelsCopy2[row*image->width].z = avgB/convolutionSize;
pixelsCopy2[row*image->width].w = avgAlpha/convolutionSize;
for (int x = 1; x < image->width; x++)
{ {
if (x-blurSize >= 0) if (x-blurSize-1 >= 0)
{ {
avgR -= pixelsCopy1[row*image->width + x-blurSize].x; avgR -= pixelsCopy1[row*image->width + x-blurSize-1].x;
avgG -= pixelsCopy1[row*image->width + x-blurSize].y; avgG -= pixelsCopy1[row*image->width + x-blurSize-1].y;
avgB -= pixelsCopy1[row*image->width + x-blurSize].z; avgB -= pixelsCopy1[row*image->width + x-blurSize-1].z;
avgAlpha -= pixelsCopy1[row*image->width + x-blurSize].w; avgAlpha -= pixelsCopy1[row*image->width + x-blurSize-1].w;
convolutionSize--; convolutionSize--;
} }
@ -1999,7 +1994,7 @@ void ImageBlurGaussian(Image *image, int blurSize) {
pixelsCopy2[row*image->width + x].z = avgB/convolutionSize; pixelsCopy2[row*image->width + x].z = avgB/convolutionSize;
pixelsCopy2[row*image->width + x].w = avgAlpha/convolutionSize; pixelsCopy2[row*image->width + x].w = avgAlpha/convolutionSize;
} }
} }
// Vertical motion blur // Vertical motion blur
for (int col = 0; col < image->width; col++) for (int col = 0; col < image->width; col++)
@ -2008,9 +2003,9 @@ void ImageBlurGaussian(Image *image, int blurSize) {
float avgG = 0.0f; float avgG = 0.0f;
float avgB = 0.0f; float avgB = 0.0f;
float avgAlpha = 0.0f; float avgAlpha = 0.0f;
int convolutionSize = blurSize+1; int convolutionSize = blurSize;
for (int i = 0; i < blurSize+1; i++) for (int i = 0; i < blurSize; i++)
{ {
avgR += pixelsCopy2[i*image->width + col].x; avgR += pixelsCopy2[i*image->width + col].x;
avgG += pixelsCopy2[i*image->width + col].y; avgG += pixelsCopy2[i*image->width + col].y;
@ -2018,19 +2013,14 @@ void ImageBlurGaussian(Image *image, int blurSize) {
avgAlpha += pixelsCopy2[i*image->width + col].w; avgAlpha += pixelsCopy2[i*image->width + col].w;
} }
pixelsCopy1[col].x = (unsigned char) (avgR/convolutionSize); for (int y = 0; y < image->height; y++)
pixelsCopy1[col].y = (unsigned char) (avgG/convolutionSize);
pixelsCopy1[col].z = (unsigned char) (avgB/convolutionSize);
pixelsCopy1[col].w = (unsigned char) (avgAlpha/convolutionSize);
for (int y = 1; y < image->height; y++)
{ {
if (y-blurSize >= 0) if (y-blurSize-1 >= 0)
{ {
avgR -= pixelsCopy2[(y-blurSize)*image->width + col].x; avgR -= pixelsCopy2[(y-blurSize-1)*image->width + col].x;
avgG -= pixelsCopy2[(y-blurSize)*image->width + col].y; avgG -= pixelsCopy2[(y-blurSize-1)*image->width + col].y;
avgB -= pixelsCopy2[(y-blurSize)*image->width + col].z; avgB -= pixelsCopy2[(y-blurSize-1)*image->width + col].z;
avgAlpha -= pixelsCopy2[(y-blurSize)*image->width + col].w; avgAlpha -= pixelsCopy2[(y-blurSize-1)*image->width + col].w;
convolutionSize--; convolutionSize--;
} }
if (y+blurSize < image->height) if (y+blurSize < image->height)
@ -2082,6 +2072,148 @@ void ImageBlurGaussian(Image *image, int blurSize) {
ImageFormat(image, format); ImageFormat(image, format);
} }
// The kernel matrix is assumed to be square. Only supply the width of the kernel.
void ImageKernelConvolution(Image *image, float* kernel, int kernelSize){
if ((image->data == NULL) || (image->width == 0) || (image->height == 0) || kernel == NULL) return;
int kernelWidth = (int)sqrtf((float)kernelSize);
if (kernelWidth*kernelWidth != kernelSize)
{
TRACELOG(LOG_WARNING, "IMAGE: Convolution kernel must be square to be applied");
return;
}
Color *pixels = LoadImageColors(*image);
Vector4 *imageCopy2 = RL_MALLOC((image->height)*(image->width)*sizeof(Vector4));
Vector4 *temp = RL_MALLOC(kernelSize*sizeof(Vector4));
for(int i = 0; i < kernelSize; i++){
temp[i].x = 0.0f;
temp[i].y = 0.0f;
temp[i].z = 0.0f;
temp[i].w = 0.0f;
}
float rRes = 0.0f;
float gRes = 0.0f;
float bRes = 0.0f;
float aRes = 0.0f;
int startRange, endRange;
if(kernelWidth % 2 == 0)
{
startRange = -kernelWidth/2;
endRange = kernelWidth/2;
} else
{
startRange = -kernelWidth/2;
endRange = kernelWidth/2+1;
}
for(int x = 0; x < image->height; x++)
{
for(int y = 0; y < image->width; y++)
{
for(int xk = startRange; xk < endRange; xk++)
{
for(int yk = startRange; yk < endRange; yk++)
{
int xkabs = xk + kernelWidth/2;
int ykabs = yk + kernelWidth/2;
size_t imgindex = image->width * (x+xk) + (y+yk);
if(imgindex < 0 || imgindex >= image->width * image->height){
temp[kernelWidth * xkabs + ykabs].x = 0.0f;
temp[kernelWidth * xkabs + ykabs].y = 0.0f;
temp[kernelWidth * xkabs + ykabs].z = 0.0f;
temp[kernelWidth * xkabs + ykabs].w = 0.0f;
} else {
temp[kernelWidth * xkabs + ykabs].x = ((float)pixels[imgindex].r)/255.0f * kernel[kernelWidth * xkabs + ykabs];
temp[kernelWidth * xkabs + ykabs].y = ((float)pixels[imgindex].g)/255.0f * kernel[kernelWidth * xkabs + ykabs];
temp[kernelWidth * xkabs + ykabs].z = ((float)pixels[imgindex].b)/255.0f * kernel[kernelWidth * xkabs + ykabs];
temp[kernelWidth * xkabs + ykabs].w = ((float)pixels[imgindex].a)/255.0f * kernel[kernelWidth * xkabs + ykabs];
}
}
}
for(int i = 0; i < kernelSize; i++)
{
rRes += temp[i].x;
gRes += temp[i].y;
bRes += temp[i].z;
aRes += temp[i].w;
}
if(rRes < 0.0f)
{
rRes = 0.0f;
}
if(gRes < 0.0f)
{
gRes = 0.0f;
}
if(bRes < 0.0f)
{
bRes = 0.0f;
}
if(rRes > 1.0f)
{
rRes = 1.0f;
}
if(gRes > 1.0f)
{
gRes = 1.0f;
}
if(bRes > 1.0f)
{
bRes = 1.0f;
}
imageCopy2[image->width * (x) + (y)].x = rRes;
imageCopy2[image->width * (x) + (y)].y = gRes;
imageCopy2[image->width * (x) + (y)].z = bRes;
imageCopy2[image->width * (x) + (y)].w = aRes;
rRes = 0.0f;
gRes = 0.0f;
bRes = 0.0f;
aRes = 0.0f;
for(int i = 0; i < kernelSize; i++)
{
temp[i].x = 0.0f;
temp[i].y = 0.0f;
temp[i].z = 0.0f;
temp[i].w = 0.0f;
}
}
}
for (int i = 0; i < (image->width) * (image->height); i++)
{
float alpha = (float)imageCopy2[i].w;
pixels[i].r = (unsigned char)((imageCopy2[i].x)*255.0f);
pixels[i].g = (unsigned char)((imageCopy2[i].y)*255.0f);
pixels[i].b = (unsigned char)((imageCopy2[i].z)*255.0f);
pixels[i].a = (unsigned char)((alpha)*255.0f);
// printf("pixels[%d] = %d", i, pixels[i].r);
}
int format = image->format;
RL_FREE(image->data);
RL_FREE(imageCopy2);
RL_FREE(temp);
image->data = pixels;
image->format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
ImageFormat(image, format);
}
// Generate all mipmap levels for a provided image // Generate all mipmap levels for a provided image
// NOTE 1: Supports POT and NPOT images // NOTE 1: Supports POT and NPOT images
// NOTE 2: image.data is scaled to include mipmap levels // NOTE 2: image.data is scaled to include mipmap levels
@ -3564,7 +3696,7 @@ void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec, Color
// Draw text (default font) within an image (destination) // Draw text (default font) within an image (destination)
void ImageDrawText(Image *dst, const char *text, int posX, int posY, int fontSize, Color color) void ImageDrawText(Image *dst, const char *text, int posX, int posY, int fontSize, Color color)
{ {
#if defined(SUPPORT_MODULE_RTEXT) #if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
// Make sure default font is loaded to be used on image text drawing // Make sure default font is loaded to be used on image text drawing
if (GetFontDefault().texture.id == 0) LoadFontDefault(); if (GetFontDefault().texture.id == 0) LoadFontDefault();