Merge branch 'raysan5:master' into master

This commit is contained in:
Jason Mao 2025-11-28 14:09:48 -05:00 committed by GitHub
commit fe93749a88
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
181 changed files with 26073 additions and 4284 deletions

View File

@ -22,7 +22,7 @@ jobs:
- name: Diff parse files - name: Diff parse files
id: diff id: diff
run: | run: |
git add -N tools/rlparser git add -N tools/rlparser/output
git diff --name-only --exit-code git diff --name-only --exit-code
continue-on-error: true continue-on-error: true
@ -32,6 +32,6 @@ jobs:
set -x set -x
git config user.name "github-actions[bot]" git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com" git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add tools/rlparser git add tools/rlparser/output
git commit -m "rlparser: update raylib_api.* by CI" git commit -m "rlparser: update raylib_api.* by CI"
git push git push

8
.gitignore vendored
View File

@ -62,10 +62,15 @@ packages/
emsdk emsdk
# Ignore wasm data in examples/ # Ignore wasm data in examples/
examples/**/*
!examples/**/*.*
!examples/**/*/
examples/**/*.exe
examples/**/*.wasm examples/**/*.wasm
examples/**/*.data examples/**/*.data
examples/**/*.js examples/**/*.js
examples/**/*.html examples/**/*.html
examples/**/logs/*
# Ignore files build by xcode # Ignore files build by xcode
*.mode*v* *.mode*v*
@ -115,7 +120,8 @@ build-*/
docgen_tmp/ docgen_tmp/
# Tools stuff # Tools stuff
tools/parser/raylib_parser tools/parser/rlparser.exe
tools/parser/rlparser
tools/rexm/rexm.exe tools/rexm/rexm.exe
tools/rexm/rexm tools/rexm/rexm

View File

@ -29,8 +29,10 @@ Some people ported raylib to other languages in the form of bindings or wrappers
| [dray](https://github.com/redthing1/dray) | **5.0** | [D](https://dlang.org) | Apache-2.0 | | [dray](https://github.com/redthing1/dray) | **5.0** | [D](https://dlang.org) | Apache-2.0 |
| [raylib-d](https://github.com/schveiguy/raylib-d) | **5.5** | [D](https://dlang.org) | Zlib | | [raylib-d](https://github.com/schveiguy/raylib-d) | **5.5** | [D](https://dlang.org) | Zlib |
| [rayex](https://github.com/shiryel/rayex) | 3.7 | [elixir](https://elixir-lang.org) | Apache-2.0 | | [rayex](https://github.com/shiryel/rayex) | 3.7 | [elixir](https://elixir-lang.org) | Apache-2.0 |
| [raylib-elle](https://github.com/acquitelol/elle/blob/rewrite/std/raylib.le) | **5.5** | [Elle](https://github.com/acquitelol/elle) | GPL-3.0 |
| [raylib-factor](https://github.com/factor/factor/blob/master/extra/raylib/raylib.factor) | 4.5 | [Factor](https://factorcode.org) | BSD | | [raylib-factor](https://github.com/factor/factor/blob/master/extra/raylib/raylib.factor) | 4.5 | [Factor](https://factorcode.org) | BSD |
| [raylib-freebasic](https://github.com/WIITD/raylib-freebasic) | **5.0** | [FreeBASIC](https://www.freebasic.net) | MIT | | [raylib-freebasic](https://github.com/WIITD/raylib-freebasic) | **5.0** | [FreeBASIC](https://www.freebasic.net) | MIT |
| [raylib.f](https://github.com/cthulhuology/raylib.f) | **5.5** | [Forth](https://forth.com) | Zlib |
| [fortran-raylib](https://github.com/interkosmos/fortran-raylib) | **5.5** | [Fortran](https://fortran-lang.org) | ISC | | [fortran-raylib](https://github.com/interkosmos/fortran-raylib) | **5.5** | [Fortran](https://fortran-lang.org) | ISC |
| [raylib-go](https://github.com/gen2brain/raylib-go) | **5.5** | [Go](https://golang.org) | Zlib | | [raylib-go](https://github.com/gen2brain/raylib-go) | **5.5** | [Go](https://golang.org) | Zlib |
| [raylib-guile](https://github.com/petelliott/raylib-guile) | **auto** | [Guile](https://www.gnu.org/software/guile) | Zlib | | [raylib-guile](https://github.com/petelliott/raylib-guile) | **auto** | [Guile](https://www.gnu.org/software/guile) | Zlib |

View File

@ -41,6 +41,7 @@ while (!WindowShouldClose())
} }
// Always use accumulators as `x++` instead of `++x`
for (int i = 0; i < NUM_VALUES; i++) printf("%i", i); for (int i = 0; i < NUM_VALUES; i++) printf("%i", i);
// Be careful with the switch formatting! // Be careful with the switch formatting!

View File

@ -77,7 +77,7 @@ RAYLIB_SRC_PATH ?= ../src
# Locations of raylib.h and libraylib.a/libraylib.so # Locations of raylib.h and libraylib.a/libraylib.so
# NOTE: Those variables are only used for PLATFORM_OS: LINUX, BSD # NOTE: Those variables are only used for PLATFORM_OS: LINUX, BSD
DESTDIR ?= /usr/local DESTDIR ?= /usr/local
RAYLIB_INCLUDE_PATH ?= $(DESTDIR)/include RAYLIB_INCLUDE_PATH ?= $(DESTDIR)/include
RAYLIB_LIB_PATH ?= $(DESTDIR)/lib RAYLIB_LIB_PATH ?= $(DESTDIR)/lib
@ -231,7 +231,7 @@ endif
# -Wno-missing-braces ignore invalid warning (GCC bug 53119) # -Wno-missing-braces ignore invalid warning (GCC bug 53119)
# -Wno-unused-value ignore unused return values of some functions (i.e. fread()) # -Wno-unused-value ignore unused return values of some functions (i.e. fread())
# -D_DEFAULT_SOURCE use with -std=c99 on Linux and PLATFORM_WEB, required for timespec # -D_DEFAULT_SOURCE use with -std=c99 on Linux and PLATFORM_WEB, required for timespec
CFLAGS = -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces -Wunused-result CFLAGS = -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces -Wno-unused-result
ifeq ($(BUILD_MODE),DEBUG) ifeq ($(BUILD_MODE),DEBUG)
CFLAGS += -g -D_DEBUG CFLAGS += -g -D_DEBUG
@ -486,7 +486,19 @@ endif
ifeq ($(TARGET_PLATFORM),PLATFORM_DRM) ifeq ($(TARGET_PLATFORM),PLATFORM_DRM)
# Libraries for DRM compiling # Libraries for DRM compiling
# NOTE: Required packages: libasound2-dev (ALSA) # NOTE: Required packages: libasound2-dev (ALSA)
LDLIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lgbm -ldrm -ldl -latomic LDLIBS = -lraylib -lGLESv2 -lEGL -ldrm -lgbm -lpthread -lrt -lm -ldl -latomic
# TODO: Examples compilation does not define GRAPHICS, is it required?
#ifeq ($(GRAPHICS),GRAPHICS_API_OPENGL_ES2)
# LDLIBS += -lGLESv2 -lEGL
#endif
endif
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_WIN32)
# Libraries for Windows desktop compilation
LDFLAGS += -L..\src
LDLIBS = -lraylib -lgdi32 -lwinmm -lshcore
ifneq ($(GRAPHICS),GRAPHICS_API_OPENGL_11_SOFTWARE)
LDLIBS += -lopengl32
endif
endif endif
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW))
# Libraries for web (HTML5) compiling # Libraries for web (HTML5) compiling
@ -513,6 +525,7 @@ CORE = \
core/core_basic_screen_manager \ core/core_basic_screen_manager \
core/core_basic_window \ core/core_basic_window \
core/core_clipboard_text \ core/core_clipboard_text \
core/core_compute_hash \
core/core_custom_frame_control \ core/core_custom_frame_control \
core/core_custom_logging \ core/core_custom_logging \
core/core_delta_time \ core/core_delta_time \
@ -539,6 +552,7 @@ CORE = \
core/core_storage_values \ core/core_storage_values \
core/core_text_file_loading \ core/core_text_file_loading \
core/core_undo_redo \ core/core_undo_redo \
core/core_viewport_scaling \
core/core_vr_simulator \ core/core_vr_simulator \
core/core_window_flags \ core/core_window_flags \
core/core_window_letterbox \ core/core_window_letterbox \
@ -562,14 +576,19 @@ SHAPES = \
shapes/shapes_following_eyes \ shapes/shapes_following_eyes \
shapes/shapes_kaleidoscope \ shapes/shapes_kaleidoscope \
shapes/shapes_lines_bezier \ shapes/shapes_lines_bezier \
shapes/shapes_lines_drawing \
shapes/shapes_logo_raylib \ shapes/shapes_logo_raylib \
shapes/shapes_logo_raylib_anim \ shapes/shapes_logo_raylib_anim \
shapes/shapes_math_angle_rotation \
shapes/shapes_math_sine_cosine \
shapes/shapes_mouse_trail \ shapes/shapes_mouse_trail \
shapes/shapes_pie_chart \ shapes/shapes_pie_chart \
shapes/shapes_rectangle_advanced \ shapes/shapes_rectangle_advanced \
shapes/shapes_rectangle_scaling \ shapes/shapes_rectangle_scaling \
shapes/shapes_recursive_tree \ shapes/shapes_recursive_tree \
shapes/shapes_ring_drawing \ shapes/shapes_ring_drawing \
shapes/shapes_rlgl_color_wheel \
shapes/shapes_rlgl_triangle \
shapes/shapes_rounded_rectangle_drawing \ shapes/shapes_rounded_rectangle_drawing \
shapes/shapes_simple_particles \ shapes/shapes_simple_particles \
shapes/shapes_splines_drawing \ shapes/shapes_splines_drawing \
@ -598,9 +617,11 @@ TEXTURES = \
textures/textures_particles_blending \ textures/textures_particles_blending \
textures/textures_polygon_drawing \ textures/textures_polygon_drawing \
textures/textures_raw_data \ textures/textures_raw_data \
textures/textures_screen_buffer \
textures/textures_sprite_animation \ textures/textures_sprite_animation \
textures/textures_sprite_button \ textures/textures_sprite_button \
textures/textures_sprite_explosion \ textures/textures_sprite_explosion \
textures/textures_sprite_stacking \
textures/textures_srcrec_dstrec \ textures/textures_srcrec_dstrec \
textures/textures_textured_curve \ textures/textures_textured_curve \
textures/textures_tiled_drawing \ textures/textures_tiled_drawing \
@ -631,6 +652,8 @@ MODELS = \
models/models_bone_socket \ models/models_bone_socket \
models/models_box_collisions \ models/models_box_collisions \
models/models_cubicmap_rendering \ models/models_cubicmap_rendering \
models/models_decals \
models/models_directional_billboard \
models/models_first_person_maze \ models/models_first_person_maze \
models/models_geometric_shapes \ models/models_geometric_shapes \
models/models_heightmap_rendering \ models/models_heightmap_rendering \
@ -654,6 +677,7 @@ SHADERS = \
shaders/shaders_ascii_rendering \ shaders/shaders_ascii_rendering \
shaders/shaders_basic_lighting \ shaders/shaders_basic_lighting \
shaders/shaders_basic_pbr \ shaders/shaders_basic_pbr \
shaders/shaders_color_correction \
shaders/shaders_custom_uniform \ shaders/shaders_custom_uniform \
shaders/shaders_deferred_rendering \ shaders/shaders_deferred_rendering \
shaders/shaders_depth_rendering \ shaders/shaders_depth_rendering \
@ -691,6 +715,7 @@ AUDIO = \
audio/audio_sound_loading \ audio/audio_sound_loading \
audio/audio_sound_multi \ audio/audio_sound_multi \
audio/audio_sound_positioning \ audio/audio_sound_positioning \
audio/audio_spectrum_visualizer \
audio/audio_stream_effects audio/audio_stream_effects
OTHERS = \ OTHERS = \

View File

@ -513,6 +513,7 @@ CORE = \
core/core_basic_screen_manager \ core/core_basic_screen_manager \
core/core_basic_window \ core/core_basic_window \
core/core_clipboard_text \ core/core_clipboard_text \
core/core_compute_hash \
core/core_custom_frame_control \ core/core_custom_frame_control \
core/core_custom_logging \ core/core_custom_logging \
core/core_delta_time \ core/core_delta_time \
@ -539,6 +540,7 @@ CORE = \
core/core_storage_values \ core/core_storage_values \
core/core_text_file_loading \ core/core_text_file_loading \
core/core_undo_redo \ core/core_undo_redo \
core/core_viewport_scaling \
core/core_vr_simulator \ core/core_vr_simulator \
core/core_window_flags \ core/core_window_flags \
core/core_window_letterbox \ core/core_window_letterbox \
@ -562,14 +564,19 @@ SHAPES = \
shapes/shapes_following_eyes \ shapes/shapes_following_eyes \
shapes/shapes_kaleidoscope \ shapes/shapes_kaleidoscope \
shapes/shapes_lines_bezier \ shapes/shapes_lines_bezier \
shapes/shapes_lines_drawing \
shapes/shapes_logo_raylib \ shapes/shapes_logo_raylib \
shapes/shapes_logo_raylib_anim \ shapes/shapes_logo_raylib_anim \
shapes/shapes_math_angle_rotation \
shapes/shapes_math_sine_cosine \
shapes/shapes_mouse_trail \ shapes/shapes_mouse_trail \
shapes/shapes_pie_chart \ shapes/shapes_pie_chart \
shapes/shapes_rectangle_advanced \ shapes/shapes_rectangle_advanced \
shapes/shapes_rectangle_scaling \ shapes/shapes_rectangle_scaling \
shapes/shapes_recursive_tree \ shapes/shapes_recursive_tree \
shapes/shapes_ring_drawing \ shapes/shapes_ring_drawing \
shapes/shapes_rlgl_color_wheel \
shapes/shapes_rlgl_triangle \
shapes/shapes_rounded_rectangle_drawing \ shapes/shapes_rounded_rectangle_drawing \
shapes/shapes_simple_particles \ shapes/shapes_simple_particles \
shapes/shapes_splines_drawing \ shapes/shapes_splines_drawing \
@ -598,9 +605,11 @@ TEXTURES = \
textures/textures_particles_blending \ textures/textures_particles_blending \
textures/textures_polygon_drawing \ textures/textures_polygon_drawing \
textures/textures_raw_data \ textures/textures_raw_data \
textures/textures_screen_buffer \
textures/textures_sprite_animation \ textures/textures_sprite_animation \
textures/textures_sprite_button \ textures/textures_sprite_button \
textures/textures_sprite_explosion \ textures/textures_sprite_explosion \
textures/textures_sprite_stacking \
textures/textures_srcrec_dstrec \ textures/textures_srcrec_dstrec \
textures/textures_textured_curve \ textures/textures_textured_curve \
textures/textures_tiled_drawing \ textures/textures_tiled_drawing \
@ -631,6 +640,8 @@ MODELS = \
models/models_bone_socket \ models/models_bone_socket \
models/models_box_collisions \ models/models_box_collisions \
models/models_cubicmap_rendering \ models/models_cubicmap_rendering \
models/models_decals \
models/models_directional_billboard \
models/models_first_person_maze \ models/models_first_person_maze \
models/models_geometric_shapes \ models/models_geometric_shapes \
models/models_heightmap_rendering \ models/models_heightmap_rendering \
@ -654,6 +665,7 @@ SHADERS = \
shaders/shaders_ascii_rendering \ shaders/shaders_ascii_rendering \
shaders/shaders_basic_lighting \ shaders/shaders_basic_lighting \
shaders/shaders_basic_pbr \ shaders/shaders_basic_pbr \
shaders/shaders_color_correction \
shaders/shaders_custom_uniform \ shaders/shaders_custom_uniform \
shaders/shaders_deferred_rendering \ shaders/shaders_deferred_rendering \
shaders/shaders_depth_rendering \ shaders/shaders_depth_rendering \
@ -691,6 +703,7 @@ AUDIO = \
audio/audio_sound_loading \ audio/audio_sound_loading \
audio/audio_sound_multi \ audio/audio_sound_multi \
audio/audio_sound_positioning \ audio/audio_sound_positioning \
audio/audio_spectrum_visualizer \
audio/audio_stream_effects audio/audio_stream_effects
# Default target entry # Default target entry
@ -747,6 +760,9 @@ core/core_basic_window: core/core_basic_window.c
core/core_clipboard_text: core/core_clipboard_text.c core/core_clipboard_text: core/core_clipboard_text.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
core/core_compute_hash: core/core_compute_hash.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
core/core_custom_frame_control: core/core_custom_frame_control.c core/core_custom_frame_control: core/core_custom_frame_control.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
@ -828,6 +844,9 @@ core/core_text_file_loading: core/core_text_file_loading.c
core/core_undo_redo: core/core_undo_redo.c core/core_undo_redo: core/core_undo_redo.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
core/core_viewport_scaling: core/core_viewport_scaling.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
core/core_vr_simulator: core/core_vr_simulator.c core/core_vr_simulator: core/core_vr_simulator.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file core/resources/shaders/glsl100/distortion.fs@resources/shaders/glsl100/distortion.fs --preload-file core/resources/shaders/glsl100/distortion.fs@resources/shaders/glsl100/distortion.fs
@ -893,12 +912,21 @@ shapes/shapes_kaleidoscope: shapes/shapes_kaleidoscope.c
shapes/shapes_lines_bezier: shapes/shapes_lines_bezier.c shapes/shapes_lines_bezier: shapes/shapes_lines_bezier.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_lines_drawing: shapes/shapes_lines_drawing.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_logo_raylib: shapes/shapes_logo_raylib.c shapes/shapes_logo_raylib: shapes/shapes_logo_raylib.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_logo_raylib_anim: shapes/shapes_logo_raylib_anim.c shapes/shapes_logo_raylib_anim: shapes/shapes_logo_raylib_anim.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_math_angle_rotation: shapes/shapes_math_angle_rotation.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_math_sine_cosine: shapes/shapes_math_sine_cosine.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_mouse_trail: shapes/shapes_mouse_trail.c shapes/shapes_mouse_trail: shapes/shapes_mouse_trail.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
@ -917,6 +945,12 @@ shapes/shapes_recursive_tree: shapes/shapes_recursive_tree.c
shapes/shapes_ring_drawing: shapes/shapes_ring_drawing.c shapes/shapes_ring_drawing: shapes/shapes_ring_drawing.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_rlgl_color_wheel: shapes/shapes_rlgl_color_wheel.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_rlgl_triangle: shapes/shapes_rlgl_triangle.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_rounded_rectangle_drawing: shapes/shapes_rounded_rectangle_drawing.c shapes/shapes_rounded_rectangle_drawing: shapes/shapes_rounded_rectangle_drawing.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
@ -952,7 +986,7 @@ textures/textures_blend_modes: textures/textures_blend_modes.c
textures/textures_bunnymark: textures/textures_bunnymark.c textures/textures_bunnymark: textures/textures_bunnymark.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/wabbit_alpha.png@resources/wabbit_alpha.png --preload-file textures/resources/raybunny.png@resources/raybunny.png
textures/textures_fog_of_war: textures/textures_fog_of_war.c textures/textures_fog_of_war: textures/textures_fog_of_war.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
@ -1018,6 +1052,9 @@ textures/textures_raw_data: textures/textures_raw_data.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/fudesumi.raw@resources/fudesumi.raw --preload-file textures/resources/fudesumi.raw@resources/fudesumi.raw
textures/textures_screen_buffer: textures/textures_screen_buffer.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
textures/textures_sprite_animation: textures/textures_sprite_animation.c textures/textures_sprite_animation: textures/textures_sprite_animation.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/scarfy.png@resources/scarfy.png --preload-file textures/resources/scarfy.png@resources/scarfy.png
@ -1032,6 +1069,10 @@ textures/textures_sprite_explosion: textures/textures_sprite_explosion.c
--preload-file textures/resources/boom.wav@resources/boom.wav \ --preload-file textures/resources/boom.wav@resources/boom.wav \
--preload-file textures/resources/explosion.png@resources/explosion.png --preload-file textures/resources/explosion.png@resources/explosion.png
textures/textures_sprite_stacking: textures/textures_sprite_stacking.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file textures/resources/booth.png@resources/booth.png
textures/textures_srcrec_dstrec: textures/textures_srcrec_dstrec.c textures/textures_srcrec_dstrec: textures/textures_srcrec_dstrec.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/scarfy.png@resources/scarfy.png --preload-file textures/resources/scarfy.png@resources/scarfy.png
@ -1152,6 +1193,16 @@ models/models_cubicmap_rendering: models/models_cubicmap_rendering.c
--preload-file models/resources/cubicmap.png@resources/cubicmap.png \ --preload-file models/resources/cubicmap.png@resources/cubicmap.png \
--preload-file models/resources/cubicmap_atlas.png@resources/cubicmap_atlas.png --preload-file models/resources/cubicmap_atlas.png@resources/cubicmap_atlas.png
models/models_decals: models/models_decals.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file models/resources/models/obj/character.obj@resources/models/obj/character.obj \
--preload-file models/resources/models/obj/character_diffuse.png@resources/models/obj/character_diffuse.png \
--preload-file models/resources/raylib_logo.png@resources/raylib_logo.png
models/models_directional_billboard: models/models_directional_billboard.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file models/resources/skillbot.png@resources/skillbot.png
models/models_first_person_maze: models/models_first_person_maze.c models/models_first_person_maze: models/models_first_person_maze.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file models/resources/cubicmap.png@resources/cubicmap.png \ --preload-file models/resources/cubicmap.png@resources/cubicmap.png \
@ -1257,6 +1308,14 @@ shaders/shaders_basic_pbr: shaders/shaders_basic_pbr.c
--preload-file shaders/resources/road_mra.png@resources/road_mra.png \ --preload-file shaders/resources/road_mra.png@resources/road_mra.png \
--preload-file shaders/resources/road_n.png@resources/road_n.png --preload-file shaders/resources/road_n.png@resources/road_n.png
shaders/shaders_color_correction: shaders/shaders_color_correction.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file shaders/resources/parrots.png@resources/parrots.png \
--preload-file shaders/resources/cat.png@resources/cat.png \
--preload-file shaders/resources/mandrill.png@resources/mandrill.png \
--preload-file shaders/resources/fudesumi.png@resources/fudesumi.png \
--preload-file shaders/resources/shaders/glsl100/color_correction.fs@resources/shaders/glsl100/color_correction.fs
shaders/shaders_custom_uniform: shaders/shaders_custom_uniform.c shaders/shaders_custom_uniform: shaders/shaders_custom_uniform.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file shaders/resources/models/barracks.obj@resources/models/barracks.obj \ --preload-file shaders/resources/models/barracks.obj@resources/models/barracks.obj \
@ -1440,6 +1499,11 @@ audio/audio_sound_positioning: audio/audio_sound_positioning.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file audio/resources/coin.wav@resources/coin.wav --preload-file audio/resources/coin.wav@resources/coin.wav
audio/audio_spectrum_visualizer: audio/audio_spectrum_visualizer.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file audio/resources/shaders/glsl100/fft.fs@resources/shaders/glsl100/fft.fs \
--preload-file audio/resources/country.mp3@resources/country.mp3
audio/audio_stream_effects: audio/audio_stream_effects.c audio/audio_stream_effects: audio/audio_stream_effects.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file audio/resources/country.mp3@resources/country.mp3 --preload-file audio/resources/country.mp3@resources/country.mp3

View File

@ -17,11 +17,11 @@ You may find it easier to use than other toolchains, especially when it comes to
- `zig build [module]` to compile all examples for a module (e.g. `zig build core`) - `zig build [module]` to compile all examples for a module (e.g. `zig build core`)
- `zig build [example]` to compile _and run_ a particular example (e.g. `zig build core_basic_window`) - `zig build [example]` to compile _and run_ a particular example (e.g. `zig build core_basic_window`)
## EXAMPLES COLLECTION [TOTAL: 187] ## EXAMPLES COLLECTION [TOTAL: 200]
### category: core [45] ### category: core [47]
Examples using raylib[core](../src/rcore.c) platform functionality like window creation, inputs, drawing modes and system functionality. Examples using raylib [core](../src/rcore.c) module platform functionality: window creation, inputs, drawing modes and system functionality.
| example | image | difficulty<br>level | version<br>created | last version<br>updated | original<br>developer | | example | image | difficulty<br>level | version<br>created | last version<br>updated | original<br>developer |
|-----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------| |-----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------|
@ -43,7 +43,7 @@ Examples using raylib[core](../src/rcore.c) platform functionality like window c
| [core_3d_camera_free](core/core_3d_camera_free.c) | <img src="core/core_3d_camera_free.png" alt="core_3d_camera_free" width="80"> | ⭐☆☆☆ | 1.3 | 1.3 | [Ramon Santamaria](https://github.com/raysan5) | | [core_3d_camera_free](core/core_3d_camera_free.c) | <img src="core/core_3d_camera_free.png" alt="core_3d_camera_free" width="80"> | ⭐☆☆☆ | 1.3 | 1.3 | [Ramon Santamaria](https://github.com/raysan5) |
| [core_3d_camera_first_person](core/core_3d_camera_first_person.c) | <img src="core/core_3d_camera_first_person.png" alt="core_3d_camera_first_person" width="80"> | ⭐⭐☆☆ | 1.3 | 1.3 | [Ramon Santamaria](https://github.com/raysan5) | | [core_3d_camera_first_person](core/core_3d_camera_first_person.c) | <img src="core/core_3d_camera_first_person.png" alt="core_3d_camera_first_person" width="80"> | ⭐⭐☆☆ | 1.3 | 1.3 | [Ramon Santamaria](https://github.com/raysan5) |
| [core_3d_camera_split_screen](core/core_3d_camera_split_screen.c) | <img src="core/core_3d_camera_split_screen.png" alt="core_3d_camera_split_screen" width="80"> | ⭐⭐⭐☆ | 3.7 | 4.0 | [Jeffery Myers](https://github.com/JeffM2501) | | [core_3d_camera_split_screen](core/core_3d_camera_split_screen.c) | <img src="core/core_3d_camera_split_screen.png" alt="core_3d_camera_split_screen" width="80"> | ⭐⭐⭐☆ | 3.7 | 4.0 | [Jeffery Myers](https://github.com/JeffM2501) |
| [core_3d_camera_fps](core/core_3d_camera_fps.c) | <img src="core/core_3d_camera_fps.png" alt="core_3d_camera_fps" width="80"> | ⭐⭐⭐☆ | 5.5 | 5.5 | [Agnis Aldins](https://github.com/nezvers) | | [core_3d_camera_fps](core/core_3d_camera_fps.c) | <img src="core/core_3d_camera_fps.png" alt="core_3d_camera_fps" width="80"> | ⭐⭐⭐☆ | 5.5 | 5.5 | [Agnis Aldiņš](https://github.com/nezvers) |
| [core_3d_picking](core/core_3d_picking.c) | <img src="core/core_3d_picking.png" alt="core_3d_picking" width="80"> | ⭐⭐☆☆ | 1.3 | 4.0 | [Ramon Santamaria](https://github.com/raysan5) | | [core_3d_picking](core/core_3d_picking.c) | <img src="core/core_3d_picking.png" alt="core_3d_picking" width="80"> | ⭐⭐☆☆ | 1.3 | 4.0 | [Ramon Santamaria](https://github.com/raysan5) |
| [core_world_screen](core/core_world_screen.c) | <img src="core/core_world_screen.png" alt="core_world_screen" width="80"> | ⭐⭐☆☆ | 1.3 | 1.4 | [Ramon Santamaria](https://github.com/raysan5) | | [core_world_screen](core/core_world_screen.c) | <img src="core/core_world_screen.png" alt="core_world_screen" width="80"> | ⭐⭐☆☆ | 1.3 | 1.4 | [Ramon Santamaria](https://github.com/raysan5) |
| [core_window_flags](core/core_window_flags.c) | <img src="core/core_window_flags.png" alt="core_window_flags" width="80"> | ⭐⭐⭐☆ | 3.5 | 3.5 | [Ramon Santamaria](https://github.com/raysan5) | | [core_window_flags](core/core_window_flags.c) | <img src="core/core_window_flags.png" alt="core_window_flags" width="80"> | ⭐⭐⭐☆ | 3.5 | 3.5 | [Ramon Santamaria](https://github.com/raysan5) |
@ -64,14 +64,16 @@ Examples using raylib[core](../src/rcore.c) platform functionality like window c
| [core_high_dpi](core/core_high_dpi.c) | <img src="core/core_high_dpi.png" alt="core_high_dpi" width="80"> | ⭐⭐☆☆ | 5.0 | 5.5 | [Jonathan Marler](https://github.com/marler8997) | | [core_high_dpi](core/core_high_dpi.c) | <img src="core/core_high_dpi.png" alt="core_high_dpi" width="80"> | ⭐⭐☆☆ | 5.0 | 5.5 | [Jonathan Marler](https://github.com/marler8997) |
| [core_render_texture](core/core_render_texture.c) | <img src="core/core_render_texture.png" alt="core_render_texture" width="80"> | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) | | [core_render_texture](core/core_render_texture.c) | <img src="core/core_render_texture.png" alt="core_render_texture" width="80"> | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) |
| [core_undo_redo](core/core_undo_redo.c) | <img src="core/core_undo_redo.png" alt="core_undo_redo" width="80"> | ⭐⭐⭐☆ | 5.5 | 5.6 | [Ramon Santamaria](https://github.com/raysan5) | | [core_undo_redo](core/core_undo_redo.c) | <img src="core/core_undo_redo.png" alt="core_undo_redo" width="80"> | ⭐⭐⭐☆ | 5.5 | 5.6 | [Ramon Santamaria](https://github.com/raysan5) |
| [core_viewport_scaling](core/core_viewport_scaling.c) | <img src="core/core_viewport_scaling.png" alt="core_viewport_scaling" width="80"> | ⭐⭐☆☆ | 5.5 | 5.5 | [Agnis Aldiņš](https://github.com/nezvers) |
| [core_input_actions](core/core_input_actions.c) | <img src="core/core_input_actions.png" alt="core_input_actions" width="80"> | ⭐⭐☆☆ | 5.5 | 5.6 | [Jett](https://github.com/JettMonstersGoBoom) | | [core_input_actions](core/core_input_actions.c) | <img src="core/core_input_actions.png" alt="core_input_actions" width="80"> | ⭐⭐☆☆ | 5.5 | 5.6 | [Jett](https://github.com/JettMonstersGoBoom) |
| [core_directory_files](core/core_directory_files.c) | <img src="core/core_directory_files.png" alt="core_directory_files" width="80"> | ⭐☆☆☆ | 5.5 | 5.6 | [Hugo ARNAL](https://github.com/hugoarnal) | | [core_directory_files](core/core_directory_files.c) | <img src="core/core_directory_files.png" alt="core_directory_files" width="80"> | ⭐☆☆☆ | 5.5 | 5.6 | [Hugo ARNAL](https://github.com/hugoarnal) |
| [core_highdpi_testbed](core/core_highdpi_testbed.c) | <img src="core/core_highdpi_testbed.png" alt="core_highdpi_testbed" width="80"> | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) | | [core_highdpi_testbed](core/core_highdpi_testbed.c) | <img src="core/core_highdpi_testbed.png" alt="core_highdpi_testbed" width="80"> | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) |
| [core_screen_recording](core/core_screen_recording.c) | <img src="core/core_screen_recording.png" alt="core_screen_recording" width="80"> | ⭐☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) | | [core_screen_recording](core/core_screen_recording.c) | <img src="core/core_screen_recording.png" alt="core_screen_recording" width="80"> | ⭐☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) |
| [core_clipboard_text](core/core_clipboard_text.c) | <img src="core/core_clipboard_text.png" alt="core_clipboard_text" width="80"> | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Robin](https://github.com/RobinsAviary) | | [core_clipboard_text](core/core_clipboard_text.c) | <img src="core/core_clipboard_text.png" alt="core_clipboard_text" width="80"> | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Ananth S](https://github.com/Ananth1839) |
| [core_text_file_loading](core/core_text_file_loading.c) | <img src="core/core_text_file_loading.png" alt="core_text_file_loading" width="80"> | ⭐☆☆☆ | 5.5 | 5.6 | [Aanjishnu Bhattacharyya](https://github.com/NimComPoo-04) | | [core_text_file_loading](core/core_text_file_loading.c) | <img src="core/core_text_file_loading.png" alt="core_text_file_loading" width="80"> | ⭐☆☆☆ | 5.5 | 5.6 | [Aanjishnu Bhattacharyya](https://github.com/NimComPoo-04) |
| [core_compute_hash](core/core_compute_hash.c) | <img src="core/core_compute_hash.png" alt="core_compute_hash" width="80"> | ⭐⭐☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) |
### category: shapes [31] ### category: shapes [36]
Examples using raylib shapes drawing functionality, provided by raylib [shapes](../src/rshapes.c) module. Examples using raylib shapes drawing functionality, provided by raylib [shapes](../src/rshapes.c) module.
@ -105,11 +107,16 @@ Examples using raylib shapes drawing functionality, provided by raylib [shapes](
| [shapes_pie_chart](shapes/shapes_pie_chart.c) | <img src="shapes/shapes_pie_chart.png" alt="shapes_pie_chart" width="80"> | ⭐⭐⭐☆ | 5.5 | 5.6 | [Gideon Serfontein](https://github.com/GideonSerf) | | [shapes_pie_chart](shapes/shapes_pie_chart.c) | <img src="shapes/shapes_pie_chart.png" alt="shapes_pie_chart" width="80"> | ⭐⭐⭐☆ | 5.5 | 5.6 | [Gideon Serfontein](https://github.com/GideonSerf) |
| [shapes_kaleidoscope](shapes/shapes_kaleidoscope.c) | <img src="shapes/shapes_kaleidoscope.png" alt="shapes_kaleidoscope" width="80"> | ⭐⭐☆☆ | 5.5 | 5.6 | [Hugo ARNAL](https://github.com/hugoarnal) | | [shapes_kaleidoscope](shapes/shapes_kaleidoscope.c) | <img src="shapes/shapes_kaleidoscope.png" alt="shapes_kaleidoscope" width="80"> | ⭐⭐☆☆ | 5.5 | 5.6 | [Hugo ARNAL](https://github.com/hugoarnal) |
| [shapes_clock_of_clocks](shapes/shapes_clock_of_clocks.c) | <img src="shapes/shapes_clock_of_clocks.png" alt="shapes_clock_of_clocks" width="80"> | ⭐⭐☆☆ | 5.5 | 5.6-dev | [JP Mortiboys](https://github.com/themushroompirates) | | [shapes_clock_of_clocks](shapes/shapes_clock_of_clocks.c) | <img src="shapes/shapes_clock_of_clocks.png" alt="shapes_clock_of_clocks" width="80"> | ⭐⭐☆☆ | 5.5 | 5.6-dev | [JP Mortiboys](https://github.com/themushroompirates) |
| [shapes_math_sine_cosine](shapes/shapes_math_sine_cosine.c) | <img src="shapes/shapes_math_sine_cosine.png" alt="shapes_math_sine_cosine" width="80"> | ⭐⭐☆☆ | 5.6-dev | 5.6-dev | [Jopestpe](https://github.com/jopestpe) |
| [shapes_mouse_trail](shapes/shapes_mouse_trail.c) | <img src="shapes/shapes_mouse_trail.png" alt="shapes_mouse_trail" width="80"> | ⭐☆☆☆ | 5.6 | 5.6-dev | [Balamurugan R](https://github.com/Bala050814) | | [shapes_mouse_trail](shapes/shapes_mouse_trail.c) | <img src="shapes/shapes_mouse_trail.png" alt="shapes_mouse_trail" width="80"> | ⭐☆☆☆ | 5.6 | 5.6-dev | [Balamurugan R](https://github.com/Bala050814) |
| [shapes_simple_particles](shapes/shapes_simple_particles.c) | <img src="shapes/shapes_simple_particles.png" alt="shapes_simple_particles" width="80"> | ⭐⭐☆☆ | 5.6 | 5.6 | [Jordi Santonja](https://github.com/JordSant) | | [shapes_simple_particles](shapes/shapes_simple_particles.c) | <img src="shapes/shapes_simple_particles.png" alt="shapes_simple_particles" width="80"> | ⭐⭐☆☆ | 5.6 | 5.6 | [Jordi Santonja](https://github.com/JordSant) |
| [shapes_starfield_effect](shapes/shapes_starfield_effect.c) | <img src="shapes/shapes_starfield_effect.png" alt="shapes_starfield_effect" width="80"> | ⭐⭐☆☆ | 5.5 | 5.6-dev | [JP Mortiboys](https://github.com/themushroompirates) | | [shapes_starfield_effect](shapes/shapes_starfield_effect.c) | <img src="shapes/shapes_starfield_effect.png" alt="shapes_starfield_effect" width="80"> | ⭐⭐☆☆ | 5.5 | 5.6-dev | [JP Mortiboys](https://github.com/themushroompirates) |
| [shapes_lines_drawing](shapes/shapes_lines_drawing.c) | <img src="shapes/shapes_lines_drawing.png" alt="shapes_lines_drawing" width="80"> | ⭐☆☆☆ | 5.6-dev | 5.6 | [Robin](https://github.com/RobinsAviary) |
| [shapes_math_angle_rotation](shapes/shapes_math_angle_rotation.c) | <img src="shapes/shapes_math_angle_rotation.png" alt="shapes_math_angle_rotation" width="80"> | ⭐☆☆☆ | 5.6-dev | 5.6 | [Kris](https://github.com/krispy-snacc) |
| [shapes_rlgl_color_wheel](shapes/shapes_rlgl_color_wheel.c) | <img src="shapes/shapes_rlgl_color_wheel.png" alt="shapes_rlgl_color_wheel" width="80"> | ⭐⭐⭐☆ | 5.6-dev | 5.6-dev | [Robin](https://github.com/RobinsAviary) |
| [shapes_rlgl_triangle](shapes/shapes_rlgl_triangle.c) | <img src="shapes/shapes_rlgl_triangle.png" alt="shapes_rlgl_triangle" width="80"> | ⭐⭐☆☆ | 5.6-dev | 5.6-dev | [Robin](https://github.com/RobinsAviary) |
### category: textures [26] ### category: textures [28]
Examples using raylib textures functionality, including image/textures loading/generation and drawing, provided by raylib [textures](../src/rtextures.c) module. Examples using raylib textures functionality, including image/textures loading/generation and drawing, provided by raylib [textures](../src/rtextures.c) module.
@ -140,7 +147,9 @@ Examples using raylib textures functionality, including image/textures loading/g
| [textures_image_kernel](textures/textures_image_kernel.c) | <img src="textures/textures_image_kernel.png" alt="textures_image_kernel" width="80"> | ⭐⭐⭐⭐️ | 1.3 | 1.3 | [Karim Salem](https://github.com/kimo-s) | | [textures_image_kernel](textures/textures_image_kernel.c) | <img src="textures/textures_image_kernel.png" alt="textures_image_kernel" width="80"> | ⭐⭐⭐⭐️ | 1.3 | 1.3 | [Karim Salem](https://github.com/kimo-s) |
| [textures_image_channel](textures/textures_image_channel.c) | <img src="textures/textures_image_channel.png" alt="textures_image_channel" width="80"> | ⭐⭐☆☆ | 5.5 | 5.5 | [Bruno Cabral](https://github.com/brccabral) | | [textures_image_channel](textures/textures_image_channel.c) | <img src="textures/textures_image_channel.png" alt="textures_image_channel" width="80"> | ⭐⭐☆☆ | 5.5 | 5.5 | [Bruno Cabral](https://github.com/brccabral) |
| [textures_image_rotate](textures/textures_image_rotate.c) | <img src="textures/textures_image_rotate.png" alt="textures_image_rotate" width="80"> | ⭐⭐☆☆ | 1.0 | 1.0 | [Ramon Santamaria](https://github.com/raysan5) | | [textures_image_rotate](textures/textures_image_rotate.c) | <img src="textures/textures_image_rotate.png" alt="textures_image_rotate" width="80"> | ⭐⭐☆☆ | 1.0 | 1.0 | [Ramon Santamaria](https://github.com/raysan5) |
| [textures_screen_buffer](textures/textures_screen_buffer.c) | <img src="textures/textures_screen_buffer.png" alt="textures_screen_buffer" width="80"> | ⭐⭐☆☆ | 5.5 | 5.5 | [Agnis Aldiņš](https://github.com/nezvers) |
| [textures_textured_curve](textures/textures_textured_curve.c) | <img src="textures/textures_textured_curve.png" alt="textures_textured_curve" width="80"> | ⭐⭐⭐☆ | 4.5 | 4.5 | [Jeffery Myers](https://github.com/JeffM2501) | | [textures_textured_curve](textures/textures_textured_curve.c) | <img src="textures/textures_textured_curve.png" alt="textures_textured_curve" width="80"> | ⭐⭐⭐☆ | 4.5 | 4.5 | [Jeffery Myers](https://github.com/JeffM2501) |
| [textures_sprite_stacking](textures/textures_sprite_stacking.c) | <img src="textures/textures_sprite_stacking.png" alt="textures_sprite_stacking" width="80"> | ⭐⭐☆☆ | 5.6-dev | 6.0 | [Robin](https://github.com/RobinsAviary) |
### category: text [15] ### category: text [15]
@ -164,7 +173,7 @@ Examples using raylib text functionality, including sprite fonts loading/generat
| [text_inline_styling](text/text_inline_styling.c) | <img src="text/text_inline_styling.png" alt="text_inline_styling" width="80"> | ⭐⭐⭐☆ | 5.6-dev | 5.6-dev | [Wagner Barongello](https://github.com/SultansOfCode) | | [text_inline_styling](text/text_inline_styling.c) | <img src="text/text_inline_styling.png" alt="text_inline_styling" width="80"> | ⭐⭐⭐☆ | 5.6-dev | 5.6-dev | [Wagner Barongello](https://github.com/SultansOfCode) |
| [text_words_alignment](text/text_words_alignment.c) | <img src="text/text_words_alignment.png" alt="text_words_alignment" width="80"> | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [JP Mortiboys](https://github.com/themushroompirates) | | [text_words_alignment](text/text_words_alignment.c) | <img src="text/text_words_alignment.png" alt="text_words_alignment" width="80"> | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [JP Mortiboys](https://github.com/themushroompirates) |
### category: models [25] ### category: models [27]
Examples using raylib models functionality, including models loading/generation and drawing, provided by raylib [models](../src/rmodels.c) module. Examples using raylib models functionality, including models loading/generation and drawing, provided by raylib [models](../src/rmodels.c) module.
@ -195,8 +204,10 @@ Examples using raylib models functionality, including models loading/generation
| [models_tesseract_view](models/models_tesseract_view.c) | <img src="models/models_tesseract_view.png" alt="models_tesseract_view" width="80"> | ⭐⭐☆☆ | 5.6-dev | 5.6-dev | [Timothy van der Valk](https://github.com/arceryz) | | [models_tesseract_view](models/models_tesseract_view.c) | <img src="models/models_tesseract_view.png" alt="models_tesseract_view" width="80"> | ⭐⭐☆☆ | 5.6-dev | 5.6-dev | [Timothy van der Valk](https://github.com/arceryz) |
| [models_basic_voxel](models/models_basic_voxel.c) | <img src="models/models_basic_voxel.png" alt="models_basic_voxel" width="80"> | ⭐⭐☆☆ | 5.5 | 5.5 | [Tim Little](https://github.com/timlittle) | | [models_basic_voxel](models/models_basic_voxel.c) | <img src="models/models_basic_voxel.png" alt="models_basic_voxel" width="80"> | ⭐⭐☆☆ | 5.5 | 5.5 | [Tim Little](https://github.com/timlittle) |
| [models_rotating_cube](models/models_rotating_cube.c) | <img src="models/models_rotating_cube.png" alt="models_rotating_cube" width="80"> | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Jopestpe](https://github.com/jopestpe) | | [models_rotating_cube](models/models_rotating_cube.c) | <img src="models/models_rotating_cube.png" alt="models_rotating_cube" width="80"> | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Jopestpe](https://github.com/jopestpe) |
| [models_decals](models/models_decals.c) | <img src="models/models_decals.png" alt="models_decals" width="80"> | ⭐⭐⭐⭐️ | 5.6-dev | 5.6-dev | [JP Mortiboys](https://github.com/themushroompirates) |
| [models_directional_billboard](models/models_directional_billboard.c) | <img src="models/models_directional_billboard.png" alt="models_directional_billboard" width="80"> | ⭐⭐☆☆ | 5.6-dev | 5.6 | [Robin](https://github.com/RobinsAviary) |
### category: shaders [31] ### category: shaders [32]
Examples using raylib shaders functionality, including shaders loading, parameters configuration and drawing using them (model shaders and postprocessing shaders). This functionality is directly provided by raylib [rlgl](../src/rlgl.c) module. Examples using raylib shaders functionality, including shaders loading, parameters configuration and drawing using them (model shaders and postprocessing shaders). This functionality is directly provided by raylib [rlgl](../src/rlgl.c) module.
@ -214,6 +225,8 @@ Examples using raylib shaders functionality, including shaders loading, paramete
| [shaders_texture_outline](shaders/shaders_texture_outline.c) | <img src="shaders/shaders_texture_outline.png" alt="shaders_texture_outline" width="80"> | ⭐⭐⭐☆ | 4.0 | 4.0 | [Serenity Skiff](https://github.com/GoldenThumbs) | | [shaders_texture_outline](shaders/shaders_texture_outline.c) | <img src="shaders/shaders_texture_outline.png" alt="shaders_texture_outline" width="80"> | ⭐⭐⭐☆ | 4.0 | 4.0 | [Serenity Skiff](https://github.com/GoldenThumbs) |
| [shaders_texture_waves](shaders/shaders_texture_waves.c) | <img src="shaders/shaders_texture_waves.png" alt="shaders_texture_waves" width="80"> | ⭐⭐☆☆ | 2.5 | 3.7 | [Anata](https://github.com/anatagawa) | | [shaders_texture_waves](shaders/shaders_texture_waves.c) | <img src="shaders/shaders_texture_waves.png" alt="shaders_texture_waves" width="80"> | ⭐⭐☆☆ | 2.5 | 3.7 | [Anata](https://github.com/anatagawa) |
| [shaders_julia_set](shaders/shaders_julia_set.c) | <img src="shaders/shaders_julia_set.png" alt="shaders_julia_set" width="80"> | ⭐⭐⭐☆ | 2.5 | 4.0 | [Josh Colclough](https://github.com/joshcol9232) | | [shaders_julia_set](shaders/shaders_julia_set.c) | <img src="shaders/shaders_julia_set.png" alt="shaders_julia_set" width="80"> | ⭐⭐⭐☆ | 2.5 | 4.0 | [Josh Colclough](https://github.com/joshcol9232) |
| [shaders_mandelbrot_set](shaders/shaders_mandelbrot_set.c) | <img src="shaders/shaders_mandelbrot_set.png" alt="shaders_mandelbrot_set" width="80"> | ⭐⭐⭐☆ | 5.6 | 5.6 | [Jordi Santonja](https://github.com/JordSant) |
| [shaders_color_correction](shaders/shaders_color_correction.c) | <img src="shaders/shaders_color_correction.png" alt="shaders_color_correction" width="80"> | ⭐⭐☆☆ | 5.6 | 5.6 | [Jordi Santonja](https://github.com/JordSant) |
| [shaders_eratosthenes_sieve](shaders/shaders_eratosthenes_sieve.c) | <img src="shaders/shaders_eratosthenes_sieve.png" alt="shaders_eratosthenes_sieve" width="80"> | ⭐⭐⭐☆ | 2.5 | 4.0 | [ProfJski](https://github.com/ProfJski) | | [shaders_eratosthenes_sieve](shaders/shaders_eratosthenes_sieve.c) | <img src="shaders/shaders_eratosthenes_sieve.png" alt="shaders_eratosthenes_sieve" width="80"> | ⭐⭐⭐☆ | 2.5 | 4.0 | [ProfJski](https://github.com/ProfJski) |
| [shaders_fog_rendering](shaders/shaders_fog_rendering.c) | <img src="shaders/shaders_fog_rendering.png" alt="shaders_fog_rendering" width="80"> | ⭐⭐⭐☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/chriscamacho) | | [shaders_fog_rendering](shaders/shaders_fog_rendering.c) | <img src="shaders/shaders_fog_rendering.png" alt="shaders_fog_rendering" width="80"> | ⭐⭐⭐☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/chriscamacho) |
| [shaders_simple_mask](shaders/shaders_simple_mask.c) | <img src="shaders/shaders_simple_mask.png" alt="shaders_simple_mask" width="80"> | ⭐⭐☆☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/chriscamacho) | | [shaders_simple_mask](shaders/shaders_simple_mask.c) | <img src="shaders/shaders_simple_mask.png" alt="shaders_simple_mask" width="80"> | ⭐⭐☆☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/chriscamacho) |
@ -232,9 +245,8 @@ Examples using raylib shaders functionality, including shaders loading, paramete
| [shaders_lightmap_rendering](shaders/shaders_lightmap_rendering.c) | <img src="shaders/shaders_lightmap_rendering.png" alt="shaders_lightmap_rendering" width="80"> | ⭐⭐⭐☆ | 4.5 | 4.5 | [Jussi Viitala](https://github.com/nullstare) | | [shaders_lightmap_rendering](shaders/shaders_lightmap_rendering.c) | <img src="shaders/shaders_lightmap_rendering.png" alt="shaders_lightmap_rendering" width="80"> | ⭐⭐⭐☆ | 4.5 | 4.5 | [Jussi Viitala](https://github.com/nullstare) |
| [shaders_rounded_rectangle](shaders/shaders_rounded_rectangle.c) | <img src="shaders/shaders_rounded_rectangle.png" alt="shaders_rounded_rectangle" width="80"> | ⭐⭐⭐☆ | 5.5 | 5.5 | [Anstro Pleuton](https://github.com/anstropleuton) | | [shaders_rounded_rectangle](shaders/shaders_rounded_rectangle.c) | <img src="shaders/shaders_rounded_rectangle.png" alt="shaders_rounded_rectangle" width="80"> | ⭐⭐⭐☆ | 5.5 | 5.5 | [Anstro Pleuton](https://github.com/anstropleuton) |
| [shaders_depth_rendering](shaders/shaders_depth_rendering.c) | <img src="shaders/shaders_depth_rendering.png" alt="shaders_depth_rendering" width="80"> | ⭐⭐⭐☆ | 5.6-dev | 5.6-dev | [Luís Almeida](https://github.com/luis605) | | [shaders_depth_rendering](shaders/shaders_depth_rendering.c) | <img src="shaders/shaders_depth_rendering.png" alt="shaders_depth_rendering" width="80"> | ⭐⭐⭐☆ | 5.6-dev | 5.6-dev | [Luís Almeida](https://github.com/luis605) |
| [shaders_mandelbrot_set](shaders/shaders_mandelbrot_set.c) | <img src="shaders/shaders_mandelbrot_set.png" alt="shaders_mandelbrot_set" width="80"> | ⭐⭐⭐☆ | 5.6 | 5.6 | [Jordi Santonja](https://github.com/JordSant) |
### category: audio [8] ### category: audio [9]
Examples using raylib audio functionality, including sound/music loading and playing. This functionality is provided by raylib [raudio](../src/raudio.c) module. Note this module can be used standalone independently of raylib. Examples using raylib audio functionality, including sound/music loading and playing. This functionality is provided by raylib [raudio](../src/raudio.c) module. Note this module can be used standalone independently of raylib.
@ -248,6 +260,7 @@ Examples using raylib audio functionality, including sound/music loading and pla
| [audio_stream_effects](audio/audio_stream_effects.c) | <img src="audio/audio_stream_effects.png" alt="audio_stream_effects" width="80"> | ⭐⭐⭐⭐️ | 4.2 | 5.0 | [Ramon Santamaria](https://github.com/raysan5) | | [audio_stream_effects](audio/audio_stream_effects.c) | <img src="audio/audio_stream_effects.png" alt="audio_stream_effects" width="80"> | ⭐⭐⭐⭐️ | 4.2 | 5.0 | [Ramon Santamaria](https://github.com/raysan5) |
| [audio_sound_multi](audio/audio_sound_multi.c) | <img src="audio/audio_sound_multi.png" alt="audio_sound_multi" width="80"> | ⭐⭐☆☆ | 5.0 | 5.0 | [Jeffery Myers](https://github.com/JeffM2501) | | [audio_sound_multi](audio/audio_sound_multi.c) | <img src="audio/audio_sound_multi.png" alt="audio_sound_multi" width="80"> | ⭐⭐☆☆ | 5.0 | 5.0 | [Jeffery Myers](https://github.com/JeffM2501) |
| [audio_sound_positioning](audio/audio_sound_positioning.c) | <img src="audio/audio_sound_positioning.png" alt="audio_sound_positioning" width="80"> | ⭐⭐☆☆ | 5.5 | 5.5 | [Le Juez Victor](https://github.com/Bigfoot71) | | [audio_sound_positioning](audio/audio_sound_positioning.c) | <img src="audio/audio_sound_positioning.png" alt="audio_sound_positioning" width="80"> | ⭐⭐☆☆ | 5.5 | 5.5 | [Le Juez Victor](https://github.com/Bigfoot71) |
| [audio_spectrum_visualizer](audio/audio_spectrum_visualizer.c) | <img src="audio/audio_spectrum_visualizer.png" alt="audio_spectrum_visualizer" width="80"> | ⭐⭐⭐☆ | 6.0 | 5.6-dev | [IANN](https://github.com/meisei4) |
### category: others [6] ### category: others [6]
@ -263,4 +276,4 @@ Examples showing raylib misc functionality that does not fit in other categories
| [web_basic_window](others/web_basic_window.c) | <img src="others/web_basic_window.png" alt="web_basic_window" width="80"> | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) | | [web_basic_window](others/web_basic_window.c) | <img src="others/web_basic_window.png" alt="web_basic_window" width="80"> | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) |
Some example missing? As always, contributions are welcome, feel free to send new examples! Some example missing? As always, contributions are welcome, feel free to send new examples!
Here is an[examples template](examples_template.c) with instructions to start with! Here is an [examples template](examples_template.c) with instructions to start with!

View File

@ -36,6 +36,12 @@ int main(void)
float timePlayed = 0.0f; // Time played normalized [0.0f..1.0f] float timePlayed = 0.0f; // Time played normalized [0.0f..1.0f]
bool pause = false; // Music playing paused bool pause = false; // Music playing paused
float pan = 0.0f; // Default audio pan center [-1.0f..1.0f]
SetMusicPan(music, pan);
float volume = 0.8f; // Default audio volume [0.0f..1.0f]
SetMusicVolume(music, volume);
SetTargetFPS(30); // Set our game to run at 30 frames-per-second SetTargetFPS(30); // Set our game to run at 30 frames-per-second
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
@ -62,6 +68,34 @@ int main(void)
else ResumeMusicStream(music); else ResumeMusicStream(music);
} }
// Set audio pan
if (IsKeyDown(KEY_LEFT))
{
pan -= 0.05f;
if (pan < -1.0f) pan = -1.0f;
SetMusicPan(music, pan);
}
else if (IsKeyDown(KEY_RIGHT))
{
pan += 0.05f;
if (pan > 1.0f) pan = 1.0f;
SetMusicPan(music, pan);
}
// Set audio volume
if (IsKeyDown(KEY_DOWN))
{
volume -= 0.05f;
if (volume < 0.0f) volume = 0.0f;
SetMusicVolume(music, volume);
}
else if (IsKeyDown(KEY_UP))
{
volume += 0.05f;
if (volume > 1.0f) volume = 1.0f;
SetMusicVolume(music, volume);
}
// Get normalized time played for current music stream // Get normalized time played for current music stream
timePlayed = GetMusicTimePlayed(music)/GetMusicTimeLength(music); timePlayed = GetMusicTimePlayed(music)/GetMusicTimeLength(music);
@ -76,6 +110,11 @@ int main(void)
DrawText("MUSIC SHOULD BE PLAYING!", 255, 150, 20, LIGHTGRAY); DrawText("MUSIC SHOULD BE PLAYING!", 255, 150, 20, LIGHTGRAY);
DrawText("LEFT-RIGHT for PAN CONTROL", 320, 74, 10, DARKBLUE);
DrawRectangle(300, 100, 200, 12, LIGHTGRAY);
DrawRectangleLines(300, 100, 200, 12, GRAY);
DrawRectangle(300 + (pan + 1.0)/2.0f*200 - 5, 92, 10, 28, DARKGRAY);
DrawRectangle(200, 200, 400, 12, LIGHTGRAY); DrawRectangle(200, 200, 400, 12, LIGHTGRAY);
DrawRectangle(200, 200, (int)(timePlayed*400.0f), 12, MAROON); DrawRectangle(200, 200, (int)(timePlayed*400.0f), 12, MAROON);
DrawRectangleLines(200, 200, 400, 12, GRAY); DrawRectangleLines(200, 200, 400, 12, GRAY);
@ -83,6 +122,11 @@ int main(void)
DrawText("PRESS SPACE TO RESTART MUSIC", 215, 250, 20, LIGHTGRAY); DrawText("PRESS SPACE TO RESTART MUSIC", 215, 250, 20, LIGHTGRAY);
DrawText("PRESS P TO PAUSE/RESUME MUSIC", 208, 280, 20, LIGHTGRAY); DrawText("PRESS P TO PAUSE/RESUME MUSIC", 208, 280, 20, LIGHTGRAY);
DrawText("UP-DOWN for VOLUME CONTROL", 320, 334, 10, DARKGREEN);
DrawRectangle(300, 360, 200, 12, LIGHTGRAY);
DrawRectangleLines(300, 360, 200, 12, GRAY);
DrawRectangle(300 + volume*200 - 5, 352, 10, 28, DARKGRAY);
EndDrawing(); EndDrawing();
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
} }

View File

@ -166,7 +166,7 @@ int main(void)
memcpy(writeBuf + writeCursor, data + readCursor, writeLength*sizeof(short)); memcpy(writeBuf + writeCursor, data + readCursor, writeLength*sizeof(short));
// Update cursors and loop audio // Update cursors and loop audio
readCursor = (readCursor + writeLength) % waveLength; readCursor = (readCursor + writeLength)%waveLength;
writeCursor += writeLength; writeCursor += writeLength;
} }

View File

@ -69,6 +69,7 @@ int main(void)
}; };
SetSoundPosition(camera, sound, spherePos, 20.0f); SetSoundPosition(camera, sound, spherePos, 20.0f);
if (!IsSoundPlaying(sound)) PlaySound(sound); if (!IsSoundPlaying(sound)) PlaySound(sound);
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -94,6 +95,8 @@ int main(void)
CloseWindow(); // Close window and OpenGL context CloseWindow(); // Close window and OpenGL context
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
return 0;
} }
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------

View File

@ -0,0 +1,285 @@
/*******************************************************************************************
*
* raylib [audio] example - spectrum visualizer
*
* Example complexity rating: [] 3/4
*
* Example originally created with raylib 6.0, last time updated with raylib 5.6-dev
*
* Inspired by Inigo Quilez's https://www.shadertoy.com/
* Resources/specification: https://gist.github.com/soulthreads/2efe50da4be1fb5f7ab60ff14ca434b8
*
* Example created by created by IANN (@meisei4) reviewed by Ramon Santamaria (@raysan5)
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
* Copyright (c) 2025 IANN (@meisei4)
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
#include <math.h>
#include <stdlib.h>
#include <string.h>
#if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330
#else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100
#endif
#define MONO 1
#define SAMPLE_RATE 44100
#define SAMPLE_RATE_F 44100.0f
#define FFT_WINDOW_SIZE 1024
#define BUFFER_SIZE 512
#define PER_SAMPLE_BIT_DEPTH 16
#define AUDIO_STREAM_RING_BUFFER_SIZE (FFT_WINDOW_SIZE*2)
#define EFFECTIVE_SAMPLE_RATE (SAMPLE_RATE_F*0.5f)
#define WINDOW_TIME ((double)FFT_WINDOW_SIZE/(double)EFFECTIVE_SAMPLE_RATE)
#define FFT_HISTORICAL_SMOOTHING_DUR 2.0f
#define MIN_DECIBELS (-100.0f) // https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode/minDecibels
#define MAX_DECIBELS (-30.0f) // https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode/maxDecibels
#define INVERSE_DECIBEL_RANGE (1.0f/(MAX_DECIBELS - MIN_DECIBELS))
#define DB_TO_LINEAR_SCALE (20.0f/2.302585092994046f)
#define SMOOTHING_TIME_CONSTANT 0.8f // https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode/smoothingTimeConstant
#define TEXTURE_HEIGHT 1
#define FFT_ROW 0
#define UNUSED_CHANNEL 0.0f
typedef struct FFTComplex { float real, imaginary; } FFTComplex;
typedef struct FFTData {
FFTComplex *spectrum;
FFTComplex *workBuffer;
float *prevMagnitudes;
float (*fftHistory)[BUFFER_SIZE];
int fftHistoryLen;
int historyPos;
double lastFftTime;
float tapbackPos;
} FFTData;
static void CaptureFrame(FFTData *fftData, const float *audioSamples);
static void RenderFrame(const FFTData *fftData, Image *fftImage);
static void CooleyTukeyFFTSlow(FFTComplex *spectrum, int n);
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//----------------------------------------------------------------------------------- ---
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [audio] example - spectrum visualizer");
Image fftImage = GenImageColor(BUFFER_SIZE, TEXTURE_HEIGHT, WHITE);
Texture2D fftTexture = LoadTextureFromImage(fftImage);
RenderTexture2D bufferA = LoadRenderTexture(screenWidth, screenHeight);
Vector2 iResolution = { (float)screenWidth, (float)screenHeight };
Shader shader = LoadShader(0, TextFormat("resources/shaders/glsl%i/fft.fs", GLSL_VERSION));
int iResolutionLocation = GetShaderLocation(shader, "iResolution");
int iChannel0Location = GetShaderLocation(shader, "iChannel0");
SetShaderValue(shader, iResolutionLocation, &iResolution, SHADER_UNIFORM_VEC2);
SetShaderValueTexture(shader, iChannel0Location, fftTexture);
InitAudioDevice();
SetAudioStreamBufferSizeDefault(AUDIO_STREAM_RING_BUFFER_SIZE);
// WARNING: Memory out-of-bounds on PLATFORM_WEB
Wave wav = LoadWave("resources/country.mp3");
WaveFormat(&wav, SAMPLE_RATE, PER_SAMPLE_BIT_DEPTH, MONO);
AudioStream audioStream = LoadAudioStream(SAMPLE_RATE, PER_SAMPLE_BIT_DEPTH, MONO);
PlayAudioStream(audioStream);
int fftHistoryLen = (int)ceilf(FFT_HISTORICAL_SMOOTHING_DUR/WINDOW_TIME) + 1;
FFTData fft = {
.spectrum = RL_CALLOC(sizeof(FFTComplex), FFT_WINDOW_SIZE),
.workBuffer = RL_CALLOC(sizeof(FFTComplex), FFT_WINDOW_SIZE),
.prevMagnitudes = RL_CALLOC(BUFFER_SIZE, sizeof(float)),
.fftHistory = RL_CALLOC(fftHistoryLen, sizeof(float[BUFFER_SIZE])),
.fftHistoryLen = fftHistoryLen,
.historyPos = 0,
.lastFftTime = 0.0,
.tapbackPos = 0.01f
};
size_t wavCursor = 0;
const short *wavPCM16 = wav.data;
short chunkSamples[AUDIO_STREAM_RING_BUFFER_SIZE] = { 0 };
float audioSamples[FFT_WINDOW_SIZE] = { 0 };
SetTargetFPS(60);
//----------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
while (IsAudioStreamProcessed(audioStream))
{
for (int i = 0; i < AUDIO_STREAM_RING_BUFFER_SIZE; i++)
{
int left = (wav.channels == 2)? wavPCM16[wavCursor*2 + 0] : wavPCM16[wavCursor];
int right = (wav.channels == 2)? wavPCM16[wavCursor*2 + 1] : left;
chunkSamples[i] = (short)((left + right)/2);
if (++wavCursor >= wav.frameCount) wavCursor = 0;
}
UpdateAudioStream(audioStream, chunkSamples, AUDIO_STREAM_RING_BUFFER_SIZE);
for (int i = 0; i < FFT_WINDOW_SIZE; i++) audioSamples[i] = (chunkSamples[i*2] + chunkSamples[i*2 + 1])*0.5f/32767.0f;
}
CaptureFrame(&fft, audioSamples);
RenderFrame(&fft, &fftImage);
UpdateTexture(fftTexture, fftImage.data);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginShaderMode(shader);
SetShaderValueTexture(shader, iChannel0Location, fftTexture);
DrawTextureRec(bufferA.texture,
(Rectangle){ 0, 0, (float)screenWidth, (float)-screenHeight },
(Vector2){ 0, 0 }, WHITE);
EndShaderMode();
EndDrawing();
//------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadShader(shader);
UnloadRenderTexture(bufferA);
UnloadTexture(fftTexture);
UnloadImage(fftImage);
UnloadAudioStream(audioStream);
UnloadWave(wav);
CloseAudioDevice();
RL_FREE(fft.spectrum);
RL_FREE(fft.workBuffer);
RL_FREE(fft.prevMagnitudes);
RL_FREE(fft.fftHistory);
CloseWindow(); // Close window and OpenGL context
//----------------------------------------------------------------------------------
return 0;
}
// CooleyTukey FFT https://en.wikipedia.org/wiki/Cooley%E2%80%93Tukey_FFT_algorithm#Data_reordering,_bit_reversal,_and_in-place_algorithms
static void CooleyTukeyFFTSlow(FFTComplex *spectrum, int n)
{
int j = 0;
for (int i = 1; i < n - 1; i++)
{
int bit = n >> 1;
while (j >= bit)
{
j -= bit;
bit >>= 1;
}
j += bit;
if (i < j)
{
FFTComplex temp = spectrum[i];
spectrum[i] = spectrum[j];
spectrum[j] = temp;
}
}
for (int len = 2; len <= n; len <<= 1)
{
float angle = -2.0f*PI/len;
FFTComplex twiddleUnit = { cosf(angle), sinf(angle) };
for (int i = 0; i < n; i += len)
{
FFTComplex twiddleCurrent = { 1.0f, 0.0f };
for (int j = 0; j < len/2; j++)
{
FFTComplex even = spectrum[i + j];
FFTComplex odd = spectrum[i + j + len/2];
FFTComplex twiddledOdd = {
odd.real*twiddleCurrent.real - odd.imaginary*twiddleCurrent.imaginary,
odd.real*twiddleCurrent.imaginary + odd.imaginary*twiddleCurrent.real
};
spectrum[i + j].real = even.real + twiddledOdd.real;
spectrum[i + j].imaginary = even.imaginary + twiddledOdd.imaginary;
spectrum[i + j + len/2].real = even.real - twiddledOdd.real;
spectrum[i + j + len/2].imaginary = even.imaginary - twiddledOdd.imaginary;
float twiddleRealNext = twiddleCurrent.real*twiddleUnit.real - twiddleCurrent.imaginary*twiddleUnit.imaginary;
twiddleCurrent.imaginary = twiddleCurrent.real*twiddleUnit.imaginary + twiddleCurrent.imaginary*twiddleUnit.real;
twiddleCurrent.real = twiddleRealNext;
}
}
}
}
static void CaptureFrame(FFTData *fftData, const float *audioSamples)
{
for (int i = 0; i < FFT_WINDOW_SIZE; i++)
{
float x = (2.0f*PI*i)/(FFT_WINDOW_SIZE - 1.0f);
float blackmanWeight = 0.42f - 0.5f*cosf(x) + 0.08f*cosf(2.0f*x); // https://en.wikipedia.org/wiki/Window_function#Blackman_window
fftData->workBuffer[i].real = audioSamples[i]*blackmanWeight;
fftData->workBuffer[i].imaginary = 0.0f;
}
CooleyTukeyFFTSlow(fftData->workBuffer, FFT_WINDOW_SIZE);
memcpy(fftData->spectrum, fftData->workBuffer, sizeof(FFTComplex)*FFT_WINDOW_SIZE);
float smoothedSpectrum[BUFFER_SIZE];
for (int bin = 0; bin < BUFFER_SIZE; bin++)
{
float re = fftData->workBuffer[bin].real;
float im = fftData->workBuffer[bin].imaginary;
float linearMagnitude = sqrtf(re*re + im*im)/FFT_WINDOW_SIZE;
float smoothedMagnitude = SMOOTHING_TIME_CONSTANT*fftData->prevMagnitudes[bin] + (1.0f - SMOOTHING_TIME_CONSTANT)*linearMagnitude;
fftData->prevMagnitudes[bin] = smoothedMagnitude;
float db = logf(fmaxf(smoothedMagnitude, 1e-40f))*DB_TO_LINEAR_SCALE;
float normalized = (db - MIN_DECIBELS)*INVERSE_DECIBEL_RANGE;
smoothedSpectrum[bin] = Clamp(normalized, 0.0f, 1.0f);
}
fftData->lastFftTime = GetTime();
memcpy(fftData->fftHistory[fftData->historyPos], smoothedSpectrum, sizeof(smoothedSpectrum));
fftData->historyPos = (fftData->historyPos + 1)%fftData->fftHistoryLen;
}
static void RenderFrame(const FFTData *fftData, Image *fftImage)
{
double framesSinceTapback = floor(fftData->tapbackPos/WINDOW_TIME);
framesSinceTapback = Clamp(framesSinceTapback, 0.0, fftData->fftHistoryLen - 1);
int historyPosition = (fftData->historyPos - 1 - (int)framesSinceTapback)%fftData->fftHistoryLen;
if (historyPosition < 0) historyPosition += fftData->fftHistoryLen;
const float *amplitude = fftData->fftHistory[historyPosition];
for (int bin = 0; bin < BUFFER_SIZE; bin++) ImageDrawPixel(fftImage, bin, FFT_ROW, ColorFromNormalized((Vector4){ amplitude[bin], UNUSED_CHANNEL, UNUSED_CHANNEL, UNUSED_CHANNEL }));
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,37 @@
#version 100
precision mediump float;
// Input vertex attributes (from vertex shader)
varying vec2 fragTexCoord;
varying vec4 fragColor;
// Input uniform values
uniform vec2 iResolution;
uniform sampler2D iChannel0;
const vec4 BLACK = vec4(0.0, 0.0, 0.0, 1.0);
const vec4 WHITE = vec4(1.0, 1.0, 1.0, 1.0);
const float FFT_ROW = 0.0;
const float NUM_OF_BINS = 512.0;
void main()
{
vec2 fragCoord = fragTexCoord*iResolution;
float cellWidth = iResolution.x/NUM_OF_BINS;
float binIndex = floor(fragCoord.x/cellWidth);
float localX = mod(fragCoord.x, cellWidth);
float barWidth = cellWidth - 1.0;
vec4 color = WHITE;
if (localX <= barWidth)
{
float sampleX = (binIndex + 0.5)/NUM_OF_BINS;
vec2 sampleCoord = vec2(sampleX, FFT_ROW);
float amplitude = texture2D(iChannel0, sampleCoord).r; // Only filled the red channel, all channels left open for alternative use
if (fragTexCoord.y < amplitude) color = BLACK;
}
gl_FragColor = color;
}

View File

@ -0,0 +1,35 @@
#version 120
// Input vertex attributes (from vertex shader)
varying vec2 fragTexCoord;
varying vec4 fragColor;
// Input uniform values
uniform vec2 iResolution;
uniform sampler2D iChannel0;
const vec4 BLACK = vec4(0.0, 0.0, 0.0, 1.0);
const vec4 WHITE = vec4(1.0, 1.0, 1.0, 1.0);
const float FFT_ROW = 0.0;
const float NUM_OF_BINS = 512.0;
void main()
{
vec2 fragCoord = fragTexCoord*iResolution;
float cellWidth = iResolution.x/NUM_OF_BINS;
float binIndex = floor(fragCoord.x/cellWidth);
float localX = mod(fragCoord.x, cellWidth);
float barWidth = cellWidth - 1.0;
vec4 color = WHITE;
if (localX <= barWidth)
{
float sampleX = (binIndex + 0.5)/NUM_OF_BINS;
vec2 sampleCoord = vec2(sampleX, FFT_ROW);
float amplitude = texture2D(iChannel0, sampleCoord).r; // Only filled the red channel, all channels left open for alternative use
if (fragTexCoord.y < amplitude) color = BLACK;
}
gl_FragColor = color;
}

View File

@ -0,0 +1,35 @@
#version 330
in vec2 fragTexCoord;
in vec4 fragColor;
out vec4 finalColor;
uniform vec2 iResolution;
uniform sampler2D iChannel0;
const vec4 BLACK = vec4(0.0, 0.0, 0.0, 1.0);
const vec4 WHITE = vec4(1.0, 1.0, 1.0, 1.0);
const float FFT_ROW = 0.0;
const float NUM_OF_BINS = 512.0;
void main()
{
vec2 fragCoord = fragTexCoord*iResolution;
float cellWidth = iResolution.x/NUM_OF_BINS;
float binIndex = floor(fragCoord.x/cellWidth);
float localX = mod(fragCoord.x, cellWidth);
float barWidth = cellWidth - 1.0;
vec4 color = WHITE;
if (localX <= barWidth)
{
float sampleX = (binIndex + 0.5)/NUM_OF_BINS;
vec2 sampleCoord = vec2(sampleX, FFT_ROW);
float amplitude = texture(iChannel0, sampleCoord).r; // Only filled the red channel, all channels left open for alternative use
if (fragTexCoord.y < amplitude) color = BLACK;
}
finalColor = color;
}

View File

@ -23,7 +23,7 @@
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Program main entry point // Program main entry point
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
int main () int main(void)
{ {
// Initialization // Initialization
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
@ -35,9 +35,9 @@ int main ()
Camera2D camera = { 0 }; Camera2D camera = { 0 };
camera.zoom = 1.0f; camera.zoom = 1.0f;
int zoomMode = 0; // 0-Mouse Wheel, 1-Mouse Move int zoomMode = 0; // 0-Mouse Wheel, 1-Mouse Move
SetTargetFPS(60); // Set our game to run at 60 frames-per-second SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
// Main game loop // Main game loop
@ -93,6 +93,7 @@ int main ()
// under the cursor to the screen space point under the cursor at any zoom // under the cursor to the screen space point under the cursor at any zoom
camera.target = mouseWorldPos; camera.target = mouseWorldPos;
} }
if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT)) if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT))
{ {
// Zoom increment // Zoom increment
@ -110,7 +111,6 @@ int main ()
ClearBackground(RAYWHITE); ClearBackground(RAYWHITE);
BeginMode2D(camera); BeginMode2D(camera);
// Draw the 3d grid, rotated 90 degrees and centered around 0,0 // Draw the 3d grid, rotated 90 degrees and centered around 0,0
// just so we have something in the XY plane // just so we have something in the XY plane
rlPushMatrix(); rlPushMatrix();
@ -121,7 +121,6 @@ int main ()
// Draw a reference circle // Draw a reference circle
DrawCircle(GetScreenWidth()/2, GetScreenHeight()/2, 50, MAROON); DrawCircle(GetScreenWidth()/2, GetScreenHeight()/2, 50, MAROON);
EndMode2D(); EndMode2D();
// Draw mouse reference // Draw mouse reference
@ -142,5 +141,6 @@ int main ()
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context CloseWindow(); // Close window and OpenGL context
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
return 0; return 0;
} }

View File

@ -6,12 +6,12 @@
* *
* Example originally created with raylib 5.5, last time updated with raylib 5.5 * Example originally created with raylib 5.5, last time updated with raylib 5.5
* *
* Example contributed by Agnis Aldins (@nezvers) and reviewed by Ramon Santamaria (@raysan5) * Example contributed by Agnis Aldiņš (@nezvers) and reviewed by Ramon Santamaria (@raysan5)
* *
* 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
* *
* Copyright (c) 2025 Agnis Aldins (@nezvers) * Copyright (c) 2025 Agnis Aldiņš (@nezvers)
* *
********************************************************************************************/ ********************************************************************************************/

View File

@ -2,22 +2,23 @@
* *
* raylib [core] example - clipboard text * raylib [core] example - clipboard text
* *
* Example complexity rating: [] 1/4
*
* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev * Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
* *
* Example contributed by Robin (@RobinsAviary) and reviewed by Ramon Santamaria (@raysan5) * Example contributed by Ananth S (@Ananth1839) and reviewed by Ramon Santamaria (@raysan5)
* *
* 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
* *
* Copyright (c) 2025 Robin (@RobinsAviary) * Copyright (c) 2025 Ananth S (@Ananth1839)
* *
********************************************************************************************/ ********************************************************************************************/
#include "raylib.h" #include "raylib.h"
#include <stdio.h> #define RAYGUI_IMPLEMENTATION
#include "raygui.h"
#define MAX_TEXT_SAMPLES 5
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Program main entry point // Program main entry point
@ -31,28 +32,32 @@ int main(void)
InitWindow(screenWidth, screenHeight, "raylib [core] example - clipboard text"); InitWindow(screenWidth, screenHeight, "raylib [core] example - clipboard text");
const char* clipboardText = NULL; // Define some sample texts
const char *sampleTexts[MAX_TEXT_SAMPLES] = {
"Hello from raylib!",
"The quick brown fox jumps over the lazy dog",
"Clipboard operations are useful!",
"raylib is a simple and easy-to-use library",
"Copy and paste me!"
};
// List of text the user can switch through and copy const char *clipboardText = NULL;
const char* copyableText[] = {"raylib is fun", "hello, clipboard!", "potato chips"}; char inputBuffer[256] = "Hello from raylib!"; // Random initial string
unsigned int textIndex = 0; // UI required variables
bool textBoxEditMode = false;
const char* popupText = NULL; bool btnCutPressed = false;
bool btnCopyPressed = false;
bool btnPastePressed = false;
bool btnClearPressed = false;
bool btnRandomPressed = false;
// Initialize timers // Set UI style
// The amount of time the pop-up text is on screen, before fading GuiSetStyle(DEFAULT, TEXT_SIZE, 20);
const float maxTime = 3.0f; GuiSetIconScale(2);
float textTimer = 0.0f;
// The length of time text is offset SetTargetFPS(60); // Set our game to run at 60 frames-per-second
const float animMaxTime = 0.1f;
float pasteAnim = 0.0f;
float copyAnim = 0.0f;
int copyAnimMult = 1;
float textAnim = 0.0f;
float textAlpha = 0.0f;
// Offset amount for animations
const int offsetAmount = -4;
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
// Main game loop // Main game loop
@ -60,95 +65,55 @@ int main(void)
{ {
// Update // Update
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Check if the user has pressed the copy/paste key combinations // Handle button interactions
bool pastePressed = (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_V)); if (btnCutPressed)
bool copyPressed = (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_C));
// Update animation timers
if (textTimer > 0) textTimer -= GetFrameTime();
if (pasteAnim > 0) pasteAnim -= GetFrameTime();
if (copyAnim > 0) copyAnim -= GetFrameTime();
if (textAnim > 0) textAnim -= GetFrameTime();
// React to the user pressing paste
if (pastePressed)
{ {
// Most operating systems hide this information until the user presses Ctrl-V on the window. SetClipboardText(inputBuffer);
clipboardText = GetClipboardText();
inputBuffer[0] = '\0'; // Quick solution to clear text
//memset(inputBuffer, 0, 256); // Clear full buffer properly
}
// Check to see if the clipboard contains an image if (btnCopyPressed)
// This function does nothing outside of Windows, as it directly calls the Windows API {
Image image = GetClipboardImage(); SetClipboardText(inputBuffer); // Copy text to clipboard
clipboardText = GetClipboardText(); // Get text from clipboard
}
if (IsImageValid(image)) if (btnPastePressed)
{
// Paste text from clipboard
clipboardText = GetClipboardText();
if (clipboardText != NULL) TextCopy(inputBuffer, clipboardText);
}
if (btnClearPressed)
{
inputBuffer[0] = '\0'; // Quick solution to clear text
//memset(inputBuffer, 0, 256); // Clear full buffer properly
}
if (btnRandomPressed)
{
// Get random text from sample list
TextCopy(inputBuffer, sampleTexts[GetRandomValue(0, MAX_TEXT_SAMPLES - 1)]);
}
// Quick cut/copy/paste with keyboard shortcuts
if (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL))
{
if (IsKeyPressed(KEY_X))
{ {
// Unload the image SetClipboardText(inputBuffer);
UnloadImage(image); inputBuffer[0] = '\0'; // Quick solution to clear text
// Update visuals
popupText = "clipboard contains image";
} }
else
if (IsKeyPressed(KEY_C)) SetClipboardText(inputBuffer);
if (IsKeyPressed(KEY_V))
{ {
// Get text from the user's clipboard
clipboardText = GetClipboardText(); clipboardText = GetClipboardText();
if (clipboardText != NULL) TextCopy(inputBuffer, clipboardText);
// Update visuals
popupText = "text pasted";
pasteAnim = animMaxTime;
}
// Reset animation values
textTimer = maxTime;
textAnim = animMaxTime;
textAlpha = 1;
}
// React to the user pressing copy
if (copyPressed)
{
// Set the text on the user's clipboard
SetClipboardText(copyableText[textIndex]);
// Reset values
textTimer = maxTime;
textAnim = animMaxTime;
copyAnim = animMaxTime;
copyAnimMult = 1;
textAlpha = 1;
// Update the text that pops up at the bottom of the screen
popupText = "text copied";
}
// Switch to the next item in the list when the user presses up
if (IsKeyPressed(KEY_UP))
{
// Reset animation
copyAnim = animMaxTime;
copyAnimMult = 1;
textIndex += 1;
if (textIndex >= sizeof(copyableText) / sizeof(const char*)) // Length of array
{
// Loop back to the other end
textIndex = 0;
}
}
// Switch to the previous item in the list when the user presses down
if (IsKeyPressed(KEY_DOWN))
{
// Reset animation
copyAnim = animMaxTime;
copyAnimMult = -1;
if (textIndex == 0)
{
// Loop back to the other end
textIndex = (sizeof(copyableText) / sizeof(const char*)) - 1; // Length of array minus one
}
else
{
textIndex -= 1;
} }
} }
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -157,43 +122,32 @@ int main(void)
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
BeginDrawing(); BeginDrawing();
ClearBackground(RAYWHITE); ClearBackground(RAYWHITE);
// Draw the user's pasted text, if there is any yet // Draw instructions
if (clipboardText) GuiLabel((Rectangle){ 50, 20, 700, 36 }, "Use the BUTTONS or KEY SHORTCUTS:");
{ DrawText("[CTRL+X] - CUT | [CTRL+C] COPY | [CTRL+V] | PASTE", 50, 60, 20, MAROON);
// Offset animation
int offset = 0;
if (pasteAnim > 0) offset = offsetAmount;
// Draw the pasted text // Draw text box
DrawText("pasted clipboard:", 10, 10 + offset, 20, DARKGREEN); if (GuiTextBox((Rectangle){ 50, 120, 652, 40 }, inputBuffer, 256, textBoxEditMode)) textBoxEditMode = !textBoxEditMode;
DrawText(clipboardText, 10, 30 + offset, 20, DARKGRAY);
}
// Offset animation // Random text button
int textOffset = 0; btnRandomPressed = GuiButton((Rectangle){ 50 + 652 + 8, 120, 40, 40 }, "#77#");
if (copyAnim > 0) textOffset = offsetAmount;
// Draw copyable text and controls // Draw buttons
DrawText(copyableText[textIndex], 10, 330 + (textOffset * copyAnimMult), 20, MAROON); btnCutPressed = GuiButton((Rectangle){ 50, 180, 158, 40 }, "#17#CUT");
DrawText("up/down to change string, ctrl-c to copy, ctrl-v to paste", 10, 355, 20, DARKGRAY); btnCopyPressed = GuiButton((Rectangle){ 50 + 165, 180, 158, 40 }, "#16#COPY");
btnPastePressed = GuiButton((Rectangle){ 50 + 165*2, 180, 158, 40 }, "#18#PASTE");
btnClearPressed = GuiButton((Rectangle){ 50 + 165*3, 180, 158, 40 }, "#143#CLEAR");
// Alpha / Offset animation // Draw clipboard status
if (textAlpha > 0) GuiSetState(STATE_DISABLED);
{ GuiLabel((Rectangle){ 50, 260, 700, 40 }, "Clipboard current text data:");
// Offset animation GuiSetStyle(TEXTBOX, TEXT_READONLY, 1);
int offset = 0; GuiTextBox((Rectangle){ 50, 300, 700, 40 }, (char *)clipboardText, 256, false);
if (textAnim > 0) offset = offsetAmount; GuiSetStyle(TEXTBOX, TEXT_READONLY, 0);
// Draw pop up text GuiLabel((Rectangle){ 50, 360, 700, 40 }, "Try copying text from other applications and pasting here!");
DrawText(popupText, 10, 425 + offset, 20, ColorAlpha(DARKGREEN, textAlpha)); GuiSetState(STATE_NORMAL);
// Fade-out animation
if (textTimer < 0)
{
textAlpha -= GetFrameTime();
}
}
EndDrawing(); EndDrawing();
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -0,0 +1,143 @@
/*******************************************************************************************
*
* raylib [core] example - compute hash
*
* Example complexity rating: [] 2/4
*
* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
* Copyright (c) 2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#define RAYGUI_IMPLEMENTATION
#include "raygui.h"
//----------------------------------------------------------------------------------
// Module Functions Declaration
//----------------------------------------------------------------------------------
static char *GetDataAsHexText(const unsigned int *data, int dataSize);
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - compute hash");
// UI controls variables
char textInput[96] = "The quick brown fox jumps over the lazy dog.";
bool textBoxEditMode = false;
bool btnComputeHashes = false;
// Data hash values
unsigned int hashCRC32 = 0;
unsigned int *hashMD5 = NULL;
unsigned int *hashSHA1 = NULL;
unsigned int *hashSHA256 = NULL;
// Base64 encoded data
char *base64Text = NULL;
int base64TextSize = 0;
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
if (btnComputeHashes)
{
int textInputLen = strlen(textInput);
// Encode data to Base64 string (includes NULL terminator), memory must be MemFree()
base64Text = EncodeDataBase64((unsigned char *)textInput, textInputLen, &base64TextSize);
hashCRC32 = ComputeCRC32((unsigned char *)textInput, textInputLen); // Compute CRC32 hash code (4 bytes)
hashMD5 = ComputeMD5((unsigned char *)textInput, textInputLen); // Compute MD5 hash code, returns static int[4] (16 bytes)
hashSHA1 = ComputeSHA1((unsigned char *)textInput, textInputLen); // Compute SHA1 hash code, returns static int[5] (20 bytes)
hashSHA256 = ComputeSHA256((unsigned char *)textInput, textInputLen); // Compute SHA256 hash code, returns static int[8] (32 bytes)
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
GuiSetStyle(DEFAULT, TEXT_SIZE, 20);
GuiSetStyle(DEFAULT, TEXT_SPACING, 2);
GuiLabel((Rectangle){ 40, 26, 720, 32 }, "INPUT DATA (TEXT):");
GuiSetStyle(DEFAULT, TEXT_SPACING, 1);
GuiSetStyle(DEFAULT, TEXT_SIZE, 10);
if (GuiTextBox((Rectangle){ 40, 64, 720, 32 }, textInput, 95, textBoxEditMode)) textBoxEditMode = !textBoxEditMode;
btnComputeHashes = GuiButton((Rectangle){ 40, 64 + 40, 720, 32 }, "COMPUTE INPUT DATA HASHES");
GuiSetStyle(DEFAULT, TEXT_SIZE, 20);
GuiSetStyle(DEFAULT, TEXT_SPACING, 2);
GuiLabel((Rectangle){ 40, 160, 720, 32 }, "INPUT DATA HASH VALUES:");
GuiSetStyle(DEFAULT, TEXT_SPACING, 1);
GuiSetStyle(DEFAULT, TEXT_SIZE, 10);
GuiSetStyle(TEXTBOX, TEXT_READONLY, 1);
GuiLabel((Rectangle){ 40, 200, 120, 32 }, "CRC32 [32 bit]:");
GuiTextBox((Rectangle){ 40 + 120, 200, 720 - 120, 32 }, GetDataAsHexText(&hashCRC32, 1), 120, false);
GuiLabel((Rectangle){ 40, 200 + 36, 120, 32 }, "MD5 [128 bit]:");
GuiTextBox((Rectangle){ 40 + 120, 200 + 36, 720 - 120, 32 }, GetDataAsHexText(hashMD5, 4), 120, false);
GuiLabel((Rectangle){ 40, 200 + 36*2, 120, 32 }, "SHA1 [160 bit]:");
GuiTextBox((Rectangle){ 40 + 120, 200 + 36*2, 720 - 120, 32 }, GetDataAsHexText(hashSHA1, 5), 120, false);
GuiLabel((Rectangle){ 40, 200 + 36*3, 120, 32 }, "SHA256 [256 bit]:");
GuiTextBox((Rectangle){ 40 + 120, 200 + 36*3, 720 - 120, 32 }, GetDataAsHexText(hashSHA256, 8), 120, false);
GuiSetState(STATE_FOCUSED);
GuiLabel((Rectangle){ 40, 200 + 36*5 - 30, 320, 32 }, "BONUS - BAS64 ENCODED STRING:");
GuiSetState(STATE_NORMAL);
GuiLabel((Rectangle){ 40, 200 + 36*5, 120, 32 }, "BASE64 ENCODING:");
GuiTextBox((Rectangle){ 40 + 120, 200 + 36*5, 720 - 120, 32 }, base64Text, 120, false);
GuiSetStyle(TEXTBOX, TEXT_READONLY, 0);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
MemFree(base64Text); // Free Base64 text data
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
static char *GetDataAsHexText(const unsigned int *data, int dataSize)
{
static char text[128] = { 0 };
memset(text, 0, 128);
if ((data != NULL) && (dataSize > 0) && (dataSize < ((128/8) - 1)))
{
for (int i = 0; i < dataSize; i++) TextCopy(text + i*8, TextFormat("%08X", data[i]));
}
else TextCopy(text, "00000000");
return text;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -17,11 +17,11 @@
#include "raylib.h" #include "raylib.h"
#include <stdio.h> // Required for: fopen(), fclose(), fputc(), fwrite(), printf(), fprintf(), funopen() #include <stdio.h> // Required for: printf(), vprintf(), fprintf()
#include <time.h> // Required for: time_t, tm, time(), localtime(), strftime() #include <time.h> // Required for: time_t, tm, time(), localtime(), strftime()
// Custom logging function // Custom logging function
void CustomLog(int msgType, const char *text, va_list args) void CustomTraceLog(int msgType, const char *text, va_list args)
{ {
char timeStr[64] = { 0 }; char timeStr[64] = { 0 };
time_t now = time(NULL); time_t now = time(NULL);
@ -54,7 +54,7 @@ int main(void)
const int screenHeight = 450; const int screenHeight = 450;
// Set custom logger // Set custom logger
SetTraceLogCallback(CustomLog); SetTraceLogCallback(CustomTraceLog);
InitWindow(screenWidth, screenHeight, "raylib [core] example - custom logging"); InitWindow(screenWidth, screenHeight, "raylib [core] example - custom logging");

View File

@ -20,9 +20,7 @@
#define RAYGUI_IMPLEMENTATION #define RAYGUI_IMPLEMENTATION
#include "raygui.h" // Required for GUI controls #include "raygui.h" // Required for GUI controls
#include <string.h> // Required for: strcpy() #define MAX_FILEPATH_SIZE 1024
#define MAX_FILEPATH_SIZE 2048
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Program main entry point // Program main entry point
@ -53,12 +51,10 @@ int main(void)
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
if (btnBackPressed) if (btnBackPressed)
{ {
strcpy(directory, GetPrevDirectoryPath(directory)); TextCopy(directory, GetPrevDirectoryPath(directory));
UnloadDirectoryFiles(files); UnloadDirectoryFiles(files);
files = LoadDirectoryFiles(directory); files = LoadDirectoryFiles(directory);
} }
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Draw // Draw
@ -68,19 +64,20 @@ int main(void)
DrawText(directory, 100, 40, 20, DARKGRAY); DrawText(directory, 100, 40, 20, DARKGRAY);
btnBackPressed = GuiButton((Rectangle){ 40.0f, 40.0f, 20, 20 }, "<"); btnBackPressed = GuiButton((Rectangle){ 40.0f, 38.0f, 48, 24 }, "<");
for (int i = 0; i < (int)files.count; i++) for (int i = 0; i < (int)files.count; i++)
{ {
Color color = Fade(LIGHTGRAY, 0.3f); Color color = Fade(LIGHTGRAY, 0.3f);
if (!IsPathFile(files.paths[i])) if (!IsPathFile(files.paths[i]) && DirectoryExists(files.paths[i]))
{ {
if (GuiButton((Rectangle){0.0f, 85.0f + 40.0f*(float)i, screenWidth, 40}, "")) if (GuiButton((Rectangle){0.0f, 85.0f + 40.0f*(float)i, screenWidth, 40}, ""))
{ {
strcpy(directory, files.paths[i]); TextCopy(directory, files.paths[i]);
UnloadDirectoryFiles(files); UnloadDirectoryFiles(files);
files = LoadDirectoryFiles(directory); files = LoadDirectoryFiles(directory);
continue;
} }
} }

View File

@ -27,9 +27,10 @@ int main(void)
const int screenWidth = 800; const int screenWidth = 800;
const int screenHeight = 450; const int screenHeight = 450;
SetConfigFlags(FLAG_WINDOW_HIGHDPI | FLAG_WINDOW_RESIZABLE);
InitWindow(screenWidth, screenHeight, "raylib [core] example - highdpi testbed"); InitWindow(screenWidth, screenHeight, "raylib [core] example - highdpi testbed");
// TODO: Load resources / Initialize variables at this point int gridSpacing = 40; // Grid spacing in pixels
SetTargetFPS(60); SetTargetFPS(60);
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
@ -48,11 +49,12 @@ int main(void)
ClearBackground(RAYWHITE); ClearBackground(RAYWHITE);
// TODO: Draw everything that requires to be drawn at this point // Draw grid
for (int h = 0; h < 20; h++) DrawLine(0, h*gridSpacing, GetRenderWidth(), h*gridSpacing, LIGHTGRAY);
for (int v = 0; v < 40; v++) DrawLine(v*gridSpacing, 0, v*gridSpacing, GetScreenHeight(), LIGHTGRAY);
DrawLineEx((Vector2){ 0, 0 }, (Vector2){ screenWidth, screenHeight }, 2.0f, RED); // Draw UI info
DrawLineEx((Vector2){ 0, screenHeight }, (Vector2){ screenWidth, 0 }, 2.0f, RED); DrawText(TextFormat("SCREEN SIZE: %ix%i", GetScreenWidth(), GetScreenHeight()), 10, 10, 20, BLACK);
DrawText("example base code template", 260, 400, 20, LIGHTGRAY);
EndDrawing(); EndDrawing();
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------

View File

@ -71,6 +71,7 @@ int main(void)
// Set default actions // Set default actions
char actionSet = 0; char actionSet = 0;
SetActionsDefault(); SetActionsDefault();
bool releaseAction = false;
Vector2 position = (Vector2){ 400.0f, 200.0f }; Vector2 position = (Vector2){ 400.0f, 200.0f };
Vector2 size = (Vector2){ 40.0f, 40.0f }; Vector2 size = (Vector2){ 40.0f, 40.0f };
@ -83,7 +84,8 @@ int main(void)
{ {
// Update // Update
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
gamepadIndex = 0; // set this to gamepad being checked gamepadIndex = 0; // Set gamepad being checked
if (IsActionDown(ACTION_UP)) position.y -= 2; if (IsActionDown(ACTION_UP)) position.y -= 2;
if (IsActionDown(ACTION_DOWN)) position.y += 2; if (IsActionDown(ACTION_DOWN)) position.y += 2;
if (IsActionDown(ACTION_LEFT)) position.x -= 2; if (IsActionDown(ACTION_LEFT)) position.x -= 2;
@ -94,6 +96,10 @@ int main(void)
position.y = (screenHeight-size.y)/2; position.y = (screenHeight-size.y)/2;
} }
// Register release action for one frame
releaseAction = false;
if (IsActionReleased(ACTION_FIRE)) releaseAction = true;
// Switch control scheme by pressing TAB // Switch control scheme by pressing TAB
if (IsKeyPressed(KEY_TAB)) if (IsKeyPressed(KEY_TAB))
{ {
@ -109,7 +115,7 @@ int main(void)
ClearBackground(GRAY); ClearBackground(GRAY);
DrawRectangleV(position, size, RED); DrawRectangleV(position, size, releaseAction? BLUE : RED);
DrawText((actionSet == 0)? "Current input set: WASD (default)" : "Current input set: Cursor", 10, 10, 20, WHITE); DrawText((actionSet == 0)? "Current input set: WASD (default)" : "Current input set: Cursor", 10, 10, 20, WHITE);
DrawText("Use TAB key to toggles Actions keyset", 10, 50, 20, GREEN); DrawText("Use TAB key to toggles Actions keyset", 10, 50, 20, GREEN);

View File

@ -51,6 +51,8 @@ int main(void)
const float leftTriggerDeadzone = -0.9f; const float leftTriggerDeadzone = -0.9f;
const float rightTriggerDeadzone = -0.9f; const float rightTriggerDeadzone = -0.9f;
Rectangle vibrateButton = { 0 };
SetTargetFPS(60); // Set our game to run at 60 frames-per-second SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
@ -61,7 +63,12 @@ int main(void)
{ {
// Update // Update
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// ... if (IsKeyPressed(KEY_LEFT) && gamepad > 0) gamepad--;
if (IsKeyPressed(KEY_RIGHT)) gamepad++;
Vector2 mousePosition = GetMousePosition();
vibrateButton = (Rectangle){ 10, 70 + 20*GetGamepadAxisCount(gamepad) + 20, 75, 24 };
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && CheckCollisionPointRec(mousePosition, vibrateButton)) SetGamepadVibration(gamepad, 1.0, 1.0, 1.0);
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Draw // Draw
@ -70,9 +77,6 @@ int main(void)
ClearBackground(RAYWHITE); ClearBackground(RAYWHITE);
if (IsKeyPressed(KEY_LEFT) && gamepad > 0) gamepad--;
if (IsKeyPressed(KEY_RIGHT)) gamepad++;
if (IsGamepadAvailable(gamepad)) if (IsGamepadAvailable(gamepad))
{ {
DrawText(TextFormat("GP%d: %s", gamepad, GetGamepadName(gamepad)), 10, 10, 10, BLACK); DrawText(TextFormat("GP%d: %s", gamepad, GetGamepadName(gamepad)), 10, 10, 10, BLACK);
@ -93,7 +97,8 @@ int main(void)
if (leftTrigger < leftTriggerDeadzone) leftTrigger = -1.0f; if (leftTrigger < leftTriggerDeadzone) leftTrigger = -1.0f;
if (rightTrigger < rightTriggerDeadzone) rightTrigger = -1.0f; if (rightTrigger < rightTriggerDeadzone) rightTrigger = -1.0f;
if (TextFindIndex(TextToLower(GetGamepadName(gamepad)), XBOX_ALIAS_1) > -1 || TextFindIndex(TextToLower(GetGamepadName(gamepad)), XBOX_ALIAS_2) > -1) if ((TextFindIndex(TextToLower(GetGamepadName(gamepad)), XBOX_ALIAS_1) > -1) ||
(TextFindIndex(TextToLower(GetGamepadName(gamepad)), XBOX_ALIAS_2) > -1))
{ {
DrawTexture(texXboxPad, 0, 0, DARKGRAY); DrawTexture(texXboxPad, 0, 0, DARKGRAY);
@ -125,16 +130,14 @@ int main(void)
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_THUMB)) leftGamepadColor = RED; if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_THUMB)) leftGamepadColor = RED;
DrawCircle(259, 152, 39, BLACK); DrawCircle(259, 152, 39, BLACK);
DrawCircle(259, 152, 34, LIGHTGRAY); DrawCircle(259, 152, 34, LIGHTGRAY);
DrawCircle(259 + (int)(leftStickX*20), DrawCircle(259 + (int)(leftStickX*20), 152 + (int)(leftStickY*20), 25, leftGamepadColor);
152 + (int)(leftStickY*20), 25, leftGamepadColor);
// Draw axis: right joystick // Draw axis: right joystick
Color rightGamepadColor = BLACK; Color rightGamepadColor = BLACK;
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_THUMB)) rightGamepadColor = RED; if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_THUMB)) rightGamepadColor = RED;
DrawCircle(461, 237, 38, BLACK); DrawCircle(461, 237, 38, BLACK);
DrawCircle(461, 237, 33, LIGHTGRAY); DrawCircle(461, 237, 33, LIGHTGRAY);
DrawCircle(461 + (int)(rightStickX*20), DrawCircle(461 + (int)(rightStickX*20), 237 + (int)(rightStickY*20), 25, rightGamepadColor);
237 + (int)(rightStickY*20), 25, rightGamepadColor);
// Draw axis: left-right triggers // Draw axis: left-right triggers
DrawRectangle(170, 30, 15, 70, GRAY); DrawRectangle(170, 30, 15, 70, GRAY);
@ -177,16 +180,14 @@ int main(void)
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_THUMB)) leftGamepadColor = RED; if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_THUMB)) leftGamepadColor = RED;
DrawCircle(319, 255, 35, BLACK); DrawCircle(319, 255, 35, BLACK);
DrawCircle(319, 255, 31, LIGHTGRAY); DrawCircle(319, 255, 31, LIGHTGRAY);
DrawCircle(319 + (int)(leftStickX*20), DrawCircle(319 + (int)(leftStickX*20), 255 + (int)(leftStickY*20), 25, leftGamepadColor);
255 + (int)(leftStickY*20), 25, leftGamepadColor);
// Draw axis: right joystick // Draw axis: right joystick
Color rightGamepadColor = BLACK; Color rightGamepadColor = BLACK;
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_THUMB)) rightGamepadColor = RED; if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_THUMB)) rightGamepadColor = RED;
DrawCircle(475, 255, 35, BLACK); DrawCircle(475, 255, 35, BLACK);
DrawCircle(475, 255, 31, LIGHTGRAY); DrawCircle(475, 255, 31, LIGHTGRAY);
DrawCircle(475 + (int)(rightStickX*20), DrawCircle(475 + (int)(rightStickX*20), 255 + (int)(rightStickY*20), 25, rightGamepadColor);
255 + (int)(rightStickY*20), 25, rightGamepadColor);
// Draw axis: left-right triggers // Draw axis: left-right triggers
DrawRectangle(169, 48, 15, 70, GRAY); DrawRectangle(169, 48, 15, 70, GRAY);
@ -196,7 +197,6 @@ int main(void)
} }
else else
{ {
// Draw background: generic // Draw background: generic
DrawRectangleRounded((Rectangle){ 175, 110, 460, 220}, 0.3f, 16, DARKGRAY); DrawRectangleRounded((Rectangle){ 175, 110, 460, 220}, 0.3f, 16, DARKGRAY);
@ -237,23 +237,20 @@ int main(void)
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_THUMB)) leftGamepadColor = RED; if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_THUMB)) leftGamepadColor = RED;
DrawCircle(345, 260, 40, BLACK); DrawCircle(345, 260, 40, BLACK);
DrawCircle(345, 260, 35, LIGHTGRAY); DrawCircle(345, 260, 35, LIGHTGRAY);
DrawCircle(345 + (int)(leftStickX*20), DrawCircle(345 + (int)(leftStickX*20), 260 + (int)(leftStickY*20), 25, leftGamepadColor);
260 + (int)(leftStickY*20), 25, leftGamepadColor);
// Draw axis: right joystick // Draw axis: right joystick
Color rightGamepadColor = BLACK; Color rightGamepadColor = BLACK;
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_THUMB)) rightGamepadColor = RED; if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_THUMB)) rightGamepadColor = RED;
DrawCircle(465, 260, 40, BLACK); DrawCircle(465, 260, 40, BLACK);
DrawCircle(465, 260, 35, LIGHTGRAY); DrawCircle(465, 260, 35, LIGHTGRAY);
DrawCircle(465 + (int)(rightStickX*20), DrawCircle(465 + (int)(rightStickX*20), 260 + (int)(rightStickY*20), 25, rightGamepadColor);
260 + (int)(rightStickY*20), 25, rightGamepadColor);
// Draw axis: left-right triggers // Draw axis: left-right triggers
DrawRectangle(151, 110, 15, 70, GRAY); DrawRectangle(151, 110, 15, 70, GRAY);
DrawRectangle(644, 110, 15, 70, GRAY); DrawRectangle(644, 110, 15, 70, GRAY);
DrawRectangle(151, 110, 15, (int)(((1 + leftTrigger)/2)*70), RED); DrawRectangle(151, 110, 15, (int)(((1 + leftTrigger)/2)*70), RED);
DrawRectangle(644, 110, 15, (int)(((1 + rightTrigger)/2)*70), RED); DrawRectangle(644, 110, 15, (int)(((1 + rightTrigger)/2)*70), RED);
} }
DrawText(TextFormat("DETECTED AXIS [%i]:", GetGamepadAxisCount(gamepad)), 10, 50, 10, MAROON); DrawText(TextFormat("DETECTED AXIS [%i]:", GetGamepadAxisCount(gamepad)), 10, 50, 10, MAROON);
@ -263,13 +260,16 @@ int main(void)
DrawText(TextFormat("AXIS %i: %.02f", i, GetGamepadAxisMovement(gamepad, i)), 20, 70 + 20*i, 10, DARKGRAY); DrawText(TextFormat("AXIS %i: %.02f", i, GetGamepadAxisMovement(gamepad, i)), 20, 70 + 20*i, 10, DARKGRAY);
} }
// Draw vibrate button
DrawRectangleRec(vibrateButton, SKYBLUE);
DrawText("VIBRATE", vibrateButton.x + 14, vibrateButton.y + 1, 10, DARKGRAY);
if (GetGamepadButtonPressed() != GAMEPAD_BUTTON_UNKNOWN) DrawText(TextFormat("DETECTED BUTTON: %i", GetGamepadButtonPressed()), 10, 430, 10, RED); if (GetGamepadButtonPressed() != GAMEPAD_BUTTON_UNKNOWN) DrawText(TextFormat("DETECTED BUTTON: %i", GetGamepadButtonPressed()), 10, 430, 10, RED);
else DrawText("DETECTED BUTTON: NONE", 10, 430, 10, GRAY); else DrawText("DETECTED BUTTON: NONE", 10, 430, 10, GRAY);
} }
else else
{ {
DrawText(TextFormat("GP%d: NOT DETECTED", gamepad), 10, 10, 10, GRAY); DrawText(TextFormat("GP%d: NOT DETECTED", gamepad), 10, 10, 10, GRAY);
DrawTexture(texXboxPad, 0, 0, LIGHTGRAY); DrawTexture(texXboxPad, 0, 0, LIGHTGRAY);
} }

View File

@ -118,4 +118,6 @@ int main(void)
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context CloseWindow(); // Close window and OpenGL context
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
return 0;
} }

View File

@ -22,9 +22,9 @@
#define GESTURE_LOG_SIZE 20 #define GESTURE_LOG_SIZE 20
#define MAX_TOUCH_COUNT 32 #define MAX_TOUCH_COUNT 32
//---------------------------------------------------------------------------------- //------------------------------------------------------------------------------------
// Module Functions Declaration // Module Functions Declaration
//---------------------------------------------------------------------------------- //------------------------------------------------------------------------------------
static char const *GetGestureName(int gesture); // Get text string for gesture value static char const *GetGestureName(int gesture); // Get text string for gesture value
static Color GetGestureColor(int gesture); // Get color for gesture value static Color GetGestureColor(int gesture); // Get color for gesture value
@ -69,7 +69,6 @@ int main(void)
float angleLength = 90.0f; float angleLength = 90.0f;
float currentAngleDegrees = 0.0f; float currentAngleDegrees = 0.0f;
Vector2 finalVector = { 0.0f, 0.0f }; Vector2 finalVector = { 0.0f, 0.0f };
char currentAngleStr[7] = "";
Vector2 protractorPosition = { 266.0f, 315.0f }; Vector2 protractorPosition = { 266.0f, 315.0f };
SetTargetFPS(60); // Set our game to run at 60 frames-per-second SetTargetFPS(60); // Set our game to run at 60 frames-per-second
@ -203,7 +202,7 @@ int main(void)
DrawText("Log", (int)gestureLogPosition.x, (int)gestureLogPosition.y, 20, BLACK); DrawText("Log", (int)gestureLogPosition.x, (int)gestureLogPosition.y, 20, BLACK);
// Loop in both directions to print the gesture log array in the inverted order (and looping around if the index started somewhere in the middle) // Loop in both directions to print the gesture log array in the inverted order (and looping around if the index started somewhere in the middle)
for (i = 0, ii = gestureLogIndex; i < GESTURE_LOG_SIZE; i++, ii = (ii + 1) % GESTURE_LOG_SIZE) DrawText(gestureLog[ii], (int)gestureLogPosition.x, (int)gestureLogPosition.y + 410 - i*20, 20, (i == 0 ? gestureColor : LIGHTGRAY)); for (i = 0, ii = gestureLogIndex; i < GESTURE_LOG_SIZE; i++, ii = (ii + 1)%GESTURE_LOG_SIZE) DrawText(gestureLog[ii], (int)gestureLogPosition.x, (int)gestureLogPosition.y + 410 - i*20, 20, (i == 0 ? gestureColor : LIGHTGRAY));
Color logButton1Color, logButton2Color; Color logButton1Color, logButton2Color;
switch (logMode) switch (logMode)
{ {

View File

@ -40,14 +40,8 @@ int main(void)
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
if (IsKeyPressed(KEY_H)) if (IsKeyPressed(KEY_H))
{ {
if (IsCursorHidden()) if (IsCursorHidden()) ShowCursor();
{ else HideCursor();
ShowCursor();
}
else
{
HideCursor();
}
} }
ballPosition = GetMousePosition(); ballPosition = GetMousePosition();

View File

@ -46,7 +46,7 @@ int main(void)
// Clamp touch points available ( set the maximum touch points allowed ) // Clamp touch points available ( set the maximum touch points allowed )
if (tCount > MAX_TOUCH_POINTS) tCount = MAX_TOUCH_POINTS; if (tCount > MAX_TOUCH_POINTS) tCount = MAX_TOUCH_POINTS;
// Get touch points positions // Get touch points positions
for (int i = 0; i < tCount; ++i) touchPositions[i] = GetTouchPosition(i); for (int i = 0; i < tCount; i++) touchPositions[i] = GetTouchPosition(i);
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Draw // Draw
@ -55,7 +55,7 @@ int main(void)
ClearBackground(RAYWHITE); ClearBackground(RAYWHITE);
for (int i = 0; i < tCount; ++i) for (int i = 0; i < tCount; i++)
{ {
// Make sure point is not (0, 0) as this means there is no touch for it // Make sure point is not (0, 0) as this means there is no touch for it
if ((touchPositions[i].x > 0) && (touchPositions[i].y > 0)) if ((touchPositions[i].x > 0) && (touchPositions[i].y > 0))

View File

@ -40,10 +40,9 @@ int main(void)
const int screenWidth = 800; const int screenWidth = 800;
const int screenHeight = 450; const int screenHeight = 450;
MonitorInfo monitors[MAX_MONITORS] = { 0 };
InitWindow(screenWidth, screenHeight, "raylib [core] example - monitor detector"); InitWindow(screenWidth, screenHeight, "raylib [core] example - monitor detector");
MonitorInfo monitors[MAX_MONITORS] = { 0 };
int currentMonitorIndex = GetCurrentMonitor(); int currentMonitorIndex = GetCurrentMonitor();
int monitorCount = 0; int monitorCount = 0;
@ -55,7 +54,6 @@ int main(void)
{ {
// Update // Update
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Variables to find the max x and Y to calculate the scale // Variables to find the max x and Y to calculate the scale
int maxWidth = 1; int maxWidth = 1;
int maxHeight = 1; int maxHeight = 1;
@ -76,7 +74,8 @@ int main(void)
GetMonitorPhysicalHeight(i), GetMonitorPhysicalHeight(i),
GetMonitorRefreshRate(i) GetMonitorRefreshRate(i)
}; };
if (monitors[i].position.x < monitorOffsetX) monitorOffsetX = (int)monitors[i].position.x*-1;
if (monitors[i].position.x < monitorOffsetX) monitorOffsetX = -(int)monitors[i].position.x;
const int width = (int)monitors[i].position.x + monitors[i].width; const int width = (int)monitors[i].position.x + monitors[i].width;
const int height = (int)monitors[i].position.y + monitors[i].height; const int height = (int)monitors[i].position.y + monitors[i].height;
@ -85,25 +84,22 @@ int main(void)
if (maxHeight < height) maxHeight = height; if (maxHeight < height) maxHeight = height;
} }
if (IsKeyPressed(KEY_ENTER) && monitorCount > 1) if (IsKeyPressed(KEY_ENTER) && (monitorCount > 1))
{ {
currentMonitorIndex += 1; currentMonitorIndex += 1;
// Set index to 0 if the last one // Set index to 0 if the last one
if(currentMonitorIndex == monitorCount) currentMonitorIndex = 0; if (currentMonitorIndex == monitorCount) currentMonitorIndex = 0;
SetWindowMonitor(currentMonitorIndex); // Move window to currentMonitorIndex SetWindowMonitor(currentMonitorIndex); // Move window to currentMonitorIndex
} }
else else currentMonitorIndex = GetCurrentMonitor(); // Get currentMonitorIndex if manually moved
{
// Get currentMonitorIndex if manually moved
currentMonitorIndex = GetCurrentMonitor();
}
float monitorScale = 0.6f; float monitorScale = 0.6f;
if(maxHeight > maxWidth + monitorOffsetX) monitorScale *= ((float)screenHeight/(float)maxHeight); if (maxHeight > (maxWidth + monitorOffsetX)) monitorScale *= ((float)screenHeight/(float)maxHeight);
else monitorScale *= ((float)screenWidth/(float)(maxWidth + monitorOffsetX)); else monitorScale *= ((float)screenWidth/(float)(maxWidth + monitorOffsetX));
//----------------------------------------------------------------------------------
// Draw // Draw
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -120,10 +116,10 @@ int main(void)
{ {
// Calculate retangle position and size using monitorScale // Calculate retangle position and size using monitorScale
const Rectangle rec = (Rectangle){ const Rectangle rec = (Rectangle){
(monitors[i].position.x + monitorOffsetX) * monitorScale + 140, (monitors[i].position.x + monitorOffsetX)*monitorScale + 140,
monitors[i].position.y * monitorScale + 80, monitors[i].position.y*monitorScale + 80,
monitors[i].width * monitorScale, monitors[i].width*monitorScale,
monitors[i].height * monitorScale monitors[i].height*monitorScale
}; };
// Draw monitor name and information inside the rectangle // Draw monitor name and information inside the rectangle
@ -146,16 +142,11 @@ int main(void)
Vector2 windowPosition = (Vector2){ (GetWindowPosition().x + monitorOffsetX)*monitorScale + 140, GetWindowPosition().y*monitorScale + 80 }; Vector2 windowPosition = (Vector2){ (GetWindowPosition().x + monitorOffsetX)*monitorScale + 140, GetWindowPosition().y*monitorScale + 80 };
// Draw window position based on monitors // Draw window position based on monitors
DrawRectangleV(windowPosition, (Vector2){screenWidth * monitorScale, screenHeight * monitorScale}, Fade(GREEN, 0.5)); DrawRectangleV(windowPosition, (Vector2){screenWidth*monitorScale, screenHeight*monitorScale}, Fade(GREEN, 0.5));
} }
else else DrawRectangleLinesEx(rec, 5, GRAY);
{
DrawRectangleLinesEx(rec, 5, GRAY);
}
} }
EndDrawing(); EndDrawing();
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
} }

View File

@ -2,12 +2,10 @@
* *
* raylib [core] example - screen recording * raylib [core] example - screen recording
* *
* Example complexity rating: [] 1/4 * Example complexity rating: [] 2/4
* *
* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev * Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
* *
* Example contributed by Ramon Santamaria (@raysan5) and reviewed by Ramon Santamaria (@raysan5)
*
* 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
* *
@ -17,6 +15,16 @@
#include "raylib.h" #include "raylib.h"
// Using msf_gif library to record frames into GIF
#define MSF_GIF_IMPL
#include "msf_gif.h" // GIF recording functionality
#include <math.h> // Required for: sinf()
#define GIF_RECORD_FRAMERATE 5 // Record framerate, we get a frame every N frames
#define MAX_SINEWAVE_POINTS 256
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Program main entry point // Program main entry point
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
@ -29,7 +37,20 @@ int main(void)
InitWindow(screenWidth, screenHeight, "raylib [core] example - screen recording"); InitWindow(screenWidth, screenHeight, "raylib [core] example - screen recording");
// TODO: Load resources / Initialize variables at this point bool gifRecording = false; // GIF recording state
unsigned int gifFrameCounter = 0; // GIF frames counter
MsfGifState gifState = { 0 }; // MSGIF context state
Vector2 circlePosition = { 0.0f, screenHeight/2.0f };
float timeCounter = 0.0f;
// Get sine wave points for line drawing
Vector2 sinePoints[MAX_SINEWAVE_POINTS] = { 0 };
for (int i = 0; i < MAX_SINEWAVE_POINTS; i++)
{
sinePoints[i].x = i*GetScreenWidth()/180.0f;
sinePoints[i].y = screenHeight/2.0f + 150*sinf((2*PI/1.5f)*(1.0f/60.0f)*(float)i); // Calculate for 60 fps
}
SetTargetFPS(60); SetTargetFPS(60);
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
@ -39,7 +60,59 @@ int main(void)
{ {
// Update // Update
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// TODO: Update variables / Implement example logic at this point // Update circle sinusoidal movement
timeCounter += GetFrameTime();
circlePosition.x += GetScreenWidth()/180.0f;
circlePosition.y = screenHeight/2.0f + 150*sinf((2*PI/1.5f)*timeCounter);
if (circlePosition.x > screenWidth)
{
circlePosition.x = 0.0f;
circlePosition.y = screenHeight/2.0f;
timeCounter = 0.0f;
}
// Start-Stop GIF recording on CTRL+R
if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_R))
{
if (gifRecording)
{
// Stop current recording and save file
gifRecording = false;
MsfGifResult result = msf_gif_end(&gifState);
SaveFileData(TextFormat("%s/screenrecording.gif", GetApplicationDirectory()), result.data, (unsigned int)result.dataSize);
msf_gif_free(result);
TraceLog(LOG_INFO, "Finish animated GIF recording");
}
else
{
// Start a new recording
gifRecording = true;
gifFrameCounter = 0;
msf_gif_begin(&gifState, GetRenderWidth(), GetRenderHeight());
TraceLog(LOG_INFO, "Start animated GIF recording");
}
}
if (gifRecording)
{
gifFrameCounter++;
// NOTE: We record one gif frame depending on the desired gif framerate
if (gifFrameCounter > GIF_RECORD_FRAMERATE)
{
// Get image data for the current frame (from backbuffer)
// WARNING: This process is quite slow, it can generate stuttering
Image imScreen = LoadImageFromScreen();
// Add the frame to the gif recording, providing and "estimated" time for display in centiseconds
msf_gif_frame(&gifState, imScreen.data, (int)((1.0f/60.0f)*GIF_RECORD_FRAMERATE)/10, 16, imScreen.width*4);
gifFrameCounter = 0;
UnloadImage(imScreen); // Free image data
}
}
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Draw // Draw
@ -48,20 +121,43 @@ int main(void)
ClearBackground(RAYWHITE); ClearBackground(RAYWHITE);
// TODO: Draw everything that requires to be drawn at this point for (int i = 0; i < (MAX_SINEWAVE_POINTS - 1); i++)
{
DrawLineV(sinePoints[i], sinePoints[i + 1], MAROON);
DrawCircleV(sinePoints[i], 3, MAROON);
}
DrawLineEx((Vector2){ 0, 0 }, (Vector2){ screenWidth, screenHeight }, 2.0f, RED); DrawCircleV(circlePosition, 30, RED);
DrawLineEx((Vector2){ 0, screenHeight }, (Vector2){ screenWidth, 0 }, 2.0f, RED);
DrawText("example base code template", 260, 400, 20, LIGHTGRAY);
DrawFPS(10, 10);
/*
// Draw record indicator
// WARNING: If drawn here, it will appear in the recorded image,
// use a render texture instead for the recording and LoadImageFromTexture(rt.texture)
if (gifRecording)
{
// Display the recording indicator every half-second
if ((int)(GetTime()/0.5)%2 == 1)
{
DrawCircle(30, GetScreenHeight() - 20, 10, MAROON);
DrawText("GIF RECORDING", 50, GetScreenHeight() - 25, 10, RED);
}
}
*/
EndDrawing(); EndDrawing();
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
} }
// De-Initialization // De-Initialization
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
// If still recording a GIF on close window, just finish
// TODO: Unload all loaded resources at this point if (gifRecording)
{
MsfGifResult result = msf_gif_end(&gifState);
msf_gif_free(result);
gifRecording = false;
}
CloseWindow(); // Close window and OpenGL context CloseWindow(); // Close window and OpenGL context
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -19,6 +19,8 @@
#include "raymath.h" // Required for: Lerp() #include "raymath.h" // Required for: Lerp()
#include <string.h>
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Program main entry point // Program main entry point
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
@ -59,10 +61,11 @@ int main(void)
int lastSpace = 0; // Keeping track of last valid space to insert '\n' int lastSpace = 0; // Keeping track of last valid space to insert '\n'
int lastWrapStart = 0; // Keeping track of the start of this wrapped line. int lastWrapStart = 0; // Keeping track of the start of this wrapped line.
while (lines[i][j] != '\0') while (j <= strlen(lines[i]))
{ {
if (lines[i][j] == ' ') if (lines[i][j] == ' ' || lines[i][j] == '\0')
{ {
char before = lines[i][j];
// Making a C Style string by adding a '\0' at the required location so that we can use the MeasureText function // Making a C Style string by adding a '\0' at the required location so that we can use the MeasureText function
lines[i][j] = '\0'; lines[i][j] = '\0';
@ -75,7 +78,7 @@ int main(void)
lastWrapStart = lastSpace + 1; lastWrapStart = lastSpace + 1;
} }
lines[i][j] = ' '; // Resetting the space back if(before != '\0') lines[i][j] = ' '; // Resetting the space back
lastSpace = j; // Since we encountered a new space we update our last encountered space location lastSpace = j; // Since we encountered a new space we update our last encountered space location
} }
@ -88,16 +91,16 @@ int main(void)
for (int i = 0; i < lineCount; i++) for (int i = 0; i < lineCount; i++)
{ {
Vector2 size = MeasureTextEx(GetFontDefault(), lines[i], fontSize, 2); Vector2 size = MeasureTextEx(GetFontDefault(), lines[i], (float)fontSize, 2);
textHeight += size.y + 10; textHeight += (int)size.y + 10;
} }
// A simple scrollbar on the side to show how far we have red into the file // A simple scrollbar on the side to show how far we have read into the file
Rectangle scrollBar = { Rectangle scrollBar = {
.x = screenWidth - 5, .x = (float)screenWidth - 5,
.y = 0, .y = 0,
.width = 5, .width = 5,
.height = screenHeight*100/(textHeight - screenHeight) // Scrollbar height is just a percentage .height = screenHeight*100.0f/(textHeight - screenHeight) // Scrollbar height is just a percentage
}; };
SetTargetFPS(60); SetTargetFPS(60);
@ -115,10 +118,10 @@ int main(void)
// Ensuring that the camera does not scroll past all text // Ensuring that the camera does not scroll past all text
if (cam.target.y > textHeight - screenHeight + textTop) if (cam.target.y > textHeight - screenHeight + textTop)
cam.target.y = textHeight - screenHeight + textTop; cam.target.y = (float)textHeight - screenHeight + textTop;
// Computing the position of the scrollBar depending on the percentage of text covered // Computing the position of the scrollBar depending on the percentage of text covered
scrollBar.y = Lerp(textTop, screenHeight - scrollBar.height, (cam.target.y - textTop)/(textHeight - screenHeight)); scrollBar.y = Lerp((float)textTop, (float)screenHeight - scrollBar.height, (float)(cam.target.y - textTop)/(textHeight - screenHeight));
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Draw // Draw
@ -132,13 +135,19 @@ int main(void)
for (int i = 0, t = textTop; i < lineCount; i++) for (int i = 0, t = textTop; i < lineCount; i++)
{ {
// Each time we go through and calculate the height of the text to move the cursor appropriately // Each time we go through and calculate the height of the text to move the cursor appropriately
Vector2 size = MeasureTextEx(GetFontDefault(), lines[i], fontSize, 2); Vector2 size;
if(strcmp(lines[i], "")){
// Fix for empty line in the text file
size = MeasureTextEx( GetFontDefault(), lines[i], (float)fontSize, 2);
}else{
size = MeasureTextEx( GetFontDefault(), " ", (float)fontSize, 2);
}
DrawText(lines[i], 10, t, fontSize, RED); DrawText(lines[i], 10, t, fontSize, RED);
// Inserting extra space for real newlines, // Inserting extra space for real newlines,
// wrapped lines are rendered closer together // wrapped lines are rendered closer together
t += size.y + 10; t += (int)size.y + 10;
} }
EndMode2D(); EndMode2D();

View File

@ -187,7 +187,7 @@ int main(void)
if (lastUndoIndex > firstUndoIndex) if (lastUndoIndex > firstUndoIndex)
{ {
for (int i = firstUndoIndex; i < currentUndoIndex; i++) for (int i = firstUndoIndex; i < currentUndoIndex; i++)
DrawRectangleRec((Rectangle){gridPosition.x + states[i].cell.x * GRID_CELL_SIZE, gridPosition.y + states[i].cell.y * GRID_CELL_SIZE, DrawRectangleRec((Rectangle){gridPosition.x + states[i].cell.x*GRID_CELL_SIZE, gridPosition.y + states[i].cell.y*GRID_CELL_SIZE,
GRID_CELL_SIZE, GRID_CELL_SIZE }, LIGHTGRAY); GRID_CELL_SIZE, GRID_CELL_SIZE }, LIGHTGRAY);
} }
else if (firstUndoIndex > lastUndoIndex) else if (firstUndoIndex > lastUndoIndex)
@ -195,7 +195,7 @@ int main(void)
if ((currentUndoIndex < MAX_UNDO_STATES) && (currentUndoIndex > lastUndoIndex)) if ((currentUndoIndex < MAX_UNDO_STATES) && (currentUndoIndex > lastUndoIndex))
{ {
for (int i = firstUndoIndex; i < currentUndoIndex; i++) for (int i = firstUndoIndex; i < currentUndoIndex; i++)
DrawRectangleRec((Rectangle) { gridPosition.x + states[i].cell.x * GRID_CELL_SIZE, gridPosition.y + states[i].cell.y * GRID_CELL_SIZE, DrawRectangleRec((Rectangle) { gridPosition.x + states[i].cell.x*GRID_CELL_SIZE, gridPosition.y + states[i].cell.y*GRID_CELL_SIZE,
GRID_CELL_SIZE, GRID_CELL_SIZE }, LIGHTGRAY); GRID_CELL_SIZE, GRID_CELL_SIZE }, LIGHTGRAY);
} }
else else

View File

@ -0,0 +1,321 @@
/*******************************************************************************************
*
* raylib [core] example - viewport scaling
*
* Example complexity rating: [] 2/4
*
* Example originally created with raylib 5.5, last time updated with raylib 5.5
*
* Example contributed by Agnis Aldiņš (@nezvers) and reviewed by Ramon Santamaria (@raysan5)
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
* Copyright (c) 2025 Agnis Aldiņš (@nezvers)
*
********************************************************************************************/
#include "raylib.h"
#define RESOLUTION_COUNT 4 // For iteration purposes and teaching example
typedef enum {
// Only upscale, useful for pixel art
KEEP_ASPECT_INTEGER,
KEEP_HEIGHT_INTEGER,
KEEP_WIDTH_INTEGER,
// Can also downscale
KEEP_ASPECT,
KEEP_HEIGHT,
KEEP_WIDTH,
// For itteration purposes and as a teaching example
VIEWPORT_TYPE_COUNT,
} ViewportType;
// For displaying on GUI
const char *ViewportTypeNames[VIEWPORT_TYPE_COUNT] = {
"KEEP_ASPECT_INTEGER",
"KEEP_HEIGHT_INTEGER",
"KEEP_WIDTH_INTEGER",
"KEEP_ASPECT",
"KEEP_HEIGHT",
"KEEP_WIDTH",
};
//--------------------------------------------------------------------------------------
// Module Functions Declaration
//--------------------------------------------------------------------------------------
static void KeepAspectCenteredInteger(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect);
static void KeepHeightCenteredInteger(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect);
static void KeepWidthCenteredInteger(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect);
static void KeepAspectCentered(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect);
static void KeepHeightCentered(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect);
static void KeepWidthCentered(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect);
static void ResizeRenderSize(ViewportType viewportType, int *screenWidth, int *screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect, RenderTexture2D *target);
// Example how to calculate position on RenderTexture
static Vector2 Screen2RenderTexturePosition(Vector2 point, Rectangle *textureRect, Rectangle *scaledRect);
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//---------------------------------------------------------
int screenWidth = 800;
int screenHeight = 450;
SetConfigFlags(FLAG_WINDOW_RESIZABLE);
InitWindow(screenWidth, screenHeight, "raylib [core] example - viewport scaling");
// Preset resolutions that could be created by subdividing screen resolution
Vector2 resolutionList[RESOLUTION_COUNT] = {
(Vector2){ 64, 64 },
(Vector2){ 256, 240 },
(Vector2){ 320, 180 },
// 4K doesn't work with integer scaling but included for example purposes with non-integer scaling
(Vector2){ 3840, 2160 },
};
int resolutionIndex = 0;
int gameWidth = 64;
int gameHeight = 64;
RenderTexture2D target = (RenderTexture2D){ 0 };
Rectangle sourceRect = (Rectangle){ 0 };
Rectangle destRect = (Rectangle){ 0 };
ViewportType viewportType = KEEP_ASPECT_INTEGER;
ResizeRenderSize(viewportType, &screenWidth, &screenHeight, gameWidth, gameHeight, &sourceRect, &destRect, &target);
// Button rectangles
Rectangle decreaseResolutionButton = (Rectangle){ 200, 30, 10, 10 };
Rectangle increaseResolutionButton = (Rectangle){ 215, 30, 10, 10 };
Rectangle decreaseTypeButton = (Rectangle){ 200, 45, 10, 10 };
Rectangle increaseTypeButton = (Rectangle){ 215, 45, 10, 10 };
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
//----------------------------------------------------------------------------------
if (IsWindowResized()) ResizeRenderSize(viewportType, &screenWidth, &screenHeight, gameWidth, gameHeight, &sourceRect, &destRect, &target);
Vector2 mousePosition = GetMousePosition();
bool mousePressed = IsMouseButtonPressed(MOUSE_BUTTON_LEFT);
// Check buttons and rescale
if (CheckCollisionPointRec(mousePosition, decreaseResolutionButton) && mousePressed)
{
resolutionIndex = (resolutionIndex + RESOLUTION_COUNT - 1)%RESOLUTION_COUNT;
gameWidth = resolutionList[resolutionIndex].x;
gameHeight = resolutionList[resolutionIndex].y;
ResizeRenderSize(viewportType, &screenWidth, &screenHeight, gameWidth, gameHeight, &sourceRect, &destRect, &target);
}
if (CheckCollisionPointRec(mousePosition, increaseResolutionButton) && mousePressed)
{
resolutionIndex = (resolutionIndex + 1)%RESOLUTION_COUNT;
gameWidth = resolutionList[resolutionIndex].x;
gameHeight = resolutionList[resolutionIndex].y;
ResizeRenderSize(viewportType, &screenWidth, &screenHeight, gameWidth, gameHeight, &sourceRect, &destRect, &target);
}
if (CheckCollisionPointRec(mousePosition, decreaseTypeButton) && mousePressed)
{
viewportType = (viewportType + VIEWPORT_TYPE_COUNT - 1)%VIEWPORT_TYPE_COUNT;
ResizeRenderSize(viewportType, &screenWidth, &screenHeight, gameWidth, gameHeight, &sourceRect, &destRect, &target);
}
if (CheckCollisionPointRec(mousePosition, increaseTypeButton) && mousePressed)
{
viewportType = (viewportType + 1)%VIEWPORT_TYPE_COUNT;
ResizeRenderSize(viewportType, &screenWidth, &screenHeight, gameWidth, gameHeight, &sourceRect, &destRect, &target);
}
Vector2 textureMousePosition = Screen2RenderTexturePosition(mousePosition, &sourceRect, &destRect);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
// Draw our scene to the render texture
BeginTextureMode(target);
ClearBackground(WHITE);
DrawCircle(textureMousePosition.x, textureMousePosition.y, 20.0f, LIME);
EndTextureMode();
// Draw render texture to main framebuffer
BeginDrawing();
ClearBackground(BLACK);
// Draw our render texture with rotation applied
DrawTexturePro(target.texture, sourceRect, destRect, (Vector2){ 0.0f, 0.0f }, 0.0f, WHITE);
// Draw Native resolution (GUI or anything)
// Draw info box
Rectangle infoRect = (Rectangle){5, 5, 330, 105};
DrawRectangleRec(infoRect, Fade(LIGHTGRAY, 0.7f));
DrawRectangleLines(infoRect.x, infoRect.y, infoRect.width, infoRect.height, BLUE);
DrawText(TextFormat("Window Resolution: %d x %d", screenWidth, screenHeight), 15, 15, 10, BLACK);
DrawText(TextFormat("Game Resolution: %d x %d", gameWidth, gameHeight), 15, 30, 10, BLACK);
DrawText(TextFormat("Type: %s", ViewportTypeNames[viewportType]), 15, 45, 10, BLACK);
Vector2 scaleRatio = (Vector2){destRect.width/sourceRect.width, -destRect.height/sourceRect.height};
if (scaleRatio.x < 0.001f || scaleRatio.y < 0.001f) DrawText(TextFormat("Scale ratio: INVALID"), 15, 60, 10, BLACK);
else DrawText(TextFormat("Scale ratio: %.2f x %.2f", scaleRatio.x, scaleRatio.y), 15, 60, 10, BLACK);
DrawText(TextFormat("Source size: %.2f x %.2f", sourceRect.width, -sourceRect.height), 15, 75, 10, BLACK);
DrawText(TextFormat("Destination size: %.2f x %.2f", destRect.width, destRect.height), 15, 90, 10, BLACK);
// Draw buttons
DrawRectangleRec(decreaseTypeButton, SKYBLUE);
DrawRectangleRec(increaseTypeButton, SKYBLUE);
DrawRectangleRec(decreaseResolutionButton, SKYBLUE);
DrawRectangleRec(increaseResolutionButton, SKYBLUE);
DrawText("<", decreaseTypeButton.x + 3, decreaseTypeButton.y + 1, 10, BLACK);
DrawText(">", increaseTypeButton.x + 3, increaseTypeButton.y + 1, 10, BLACK);
DrawText("<", decreaseResolutionButton.x + 3, decreaseResolutionButton.y + 1, 10, BLACK);
DrawText(">", increaseResolutionButton.x + 3, increaseResolutionButton.y + 1, 10, BLACK);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//----------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//----------------------------------------------------------------------------------
return 0;
}
//--------------------------------------------------------------------------------------
// Module Functions Definition
//--------------------------------------------------------------------------------------
static void KeepAspectCenteredInteger(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect)
{
sourceRect->x = 0.0f;
sourceRect->y = (float)gameHeight;
sourceRect->width = (float)gameWidth;
sourceRect->height = (float)-gameHeight;
const int ratio_x = (screenWidth/gameWidth);
const int ratio_y = (screenHeight/gameHeight);
const float resizeRatio = (float)((ratio_x < ratio_y)? ratio_x : ratio_y);
destRect->x = (float)(int)((screenWidth - (gameWidth*resizeRatio))*0.5f);
destRect->y = (float)(int)((screenHeight - (gameHeight*resizeRatio))*0.5f);
destRect->width = (float)(int)(gameWidth*resizeRatio);
destRect->height = (float)(int)(gameHeight*resizeRatio);
}
static void KeepHeightCenteredInteger(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect)
{
const float resizeRatio = (float)(screenHeight/gameHeight);
sourceRect->x = 0.0f;
sourceRect->y = 0.0f;
sourceRect->width = (float)(int)(screenWidth/resizeRatio);
sourceRect->height = (float)-gameHeight;
destRect->x = (float)(int)((screenWidth - (sourceRect->width*resizeRatio))*0.5f);
destRect->y = (float)(int)((screenHeight - (gameHeight*resizeRatio))*0.5f);
destRect->width = (float)(int)(sourceRect->width*resizeRatio);
destRect->height = (float)(int)(gameHeight*resizeRatio);
}
static void KeepWidthCenteredInteger(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect)
{
const float resizeRatio = (float)(screenWidth/gameWidth);
sourceRect->x = 0.0f;
sourceRect->y = 0.0f;
sourceRect->width = (float)gameWidth;
sourceRect->height = (float)(int)(screenHeight/resizeRatio);
destRect->x = (float)(int)((screenWidth - (gameWidth*resizeRatio))*0.5f);
destRect->y = (float)(int)((screenHeight - (sourceRect->height*resizeRatio))*0.5f);
destRect->width = (float)(int)(gameWidth*resizeRatio);
destRect->height = (float)(int)(sourceRect->height*resizeRatio);
sourceRect->height *= -1.0f;
}
static void KeepAspectCentered(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect)
{
sourceRect->x = 0.0f;
sourceRect->y = (float)gameHeight;
sourceRect->width = (float)gameWidth;
sourceRect->height = (float)-gameHeight;
const float ratio_x = ((float)screenWidth/(float)gameWidth);
const float ratio_y = ((float)screenHeight/(float)gameHeight);
const float resizeRatio = (ratio_x < ratio_y ? ratio_x : ratio_y);
destRect->x = (float)(int)((screenWidth - (gameWidth*resizeRatio))*0.5f);
destRect->y = (float)(int)((screenHeight - (gameHeight*resizeRatio))*0.5f);
destRect->width = (float)(int)(gameWidth*resizeRatio);
destRect->height = (float)(int)(gameHeight*resizeRatio);
}
static void KeepHeightCentered(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect)
{
const float resizeRatio = ((float)screenHeight/(float)gameHeight);
sourceRect->x = 0.0f;
sourceRect->y = 0.0f;
sourceRect->width = (float)(int)((float)screenWidth/resizeRatio);
sourceRect->height = (float)-gameHeight;
destRect->x = (float)(int)((screenWidth - (sourceRect->width*resizeRatio))*0.5f);
destRect->y = (float)(int)((screenHeight - (gameHeight*resizeRatio))*0.5f);
destRect->width = (float)(int)(sourceRect->width*resizeRatio);
destRect->height = (float)(int)(gameHeight*resizeRatio);
}
static void KeepWidthCentered(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect)
{
const float resizeRatio = ((float)screenWidth/(float)gameWidth);
sourceRect->x = 0.0f;
sourceRect->y = 0.0f;
sourceRect->width = (float)gameWidth;
sourceRect->height = (float)(int)((float)screenHeight/resizeRatio);
destRect->x = (float)(int)((screenWidth - (gameWidth*resizeRatio))*0.5f);
destRect->y = (float)(int)((screenHeight - (sourceRect->height*resizeRatio))*0.5f);
destRect->width = (float)(int)(gameWidth*resizeRatio);
destRect->height = (float)(int)(sourceRect->height*resizeRatio);
sourceRect->height *= -1.f;
}
static void ResizeRenderSize(ViewportType viewportType, int *screenWidth, int *screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect, RenderTexture2D *target)
{
*screenWidth = GetScreenWidth();
*screenHeight = GetScreenHeight();
switch(viewportType)
{
case KEEP_ASPECT_INTEGER: KeepAspectCenteredInteger(*screenWidth, *screenHeight, gameWidth, gameHeight, sourceRect, destRect); break;
case KEEP_HEIGHT_INTEGER: KeepHeightCenteredInteger(*screenWidth, *screenHeight, gameWidth, gameHeight, sourceRect, destRect); break;
case KEEP_WIDTH_INTEGER: KeepWidthCenteredInteger(*screenWidth, *screenHeight, gameWidth, gameHeight, sourceRect, destRect); break;
case KEEP_ASPECT: KeepAspectCentered(*screenWidth, *screenHeight, gameWidth, gameHeight, sourceRect, destRect); break;
case KEEP_HEIGHT: KeepHeightCentered(*screenWidth, *screenHeight, gameWidth, gameHeight, sourceRect, destRect); break;
case KEEP_WIDTH: KeepWidthCentered(*screenWidth, *screenHeight, gameWidth, gameHeight, sourceRect, destRect); break;
default: break;
}
UnloadRenderTexture(*target);
*target = LoadRenderTexture(sourceRect->width, -sourceRect->height);
}
// Example how to calculate position on RenderTexture
static Vector2 Screen2RenderTexturePosition(Vector2 point, Rectangle *textureRect, Rectangle *scaledRect)
{
Vector2 relativePosition = {point.x - scaledRect->x, point.y - scaledRect->y};
Vector2 ratio = {textureRect->width/scaledRect->width, -textureRect->height/scaledRect->height};
return (Vector2){relativePosition.x*ratio.x, relativePosition.y*ratio.x};
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

@ -97,7 +97,8 @@ int main(void)
if (IsWindowState(FLAG_WINDOW_MINIMIZED)) if (IsWindowState(FLAG_WINDOW_MINIMIZED))
{ {
framesCounter++; framesCounter++;
if (framesCounter >= 240) { if (framesCounter >= 240)
{
RestoreWindow(); // Restore window after 3 seconds RestoreWindow(); // Restore window after 3 seconds
framesCounter = 0; framesCounter = 0;
} }

View File

@ -18,7 +18,7 @@
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Program main entry point // Program main entry point
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
int main() int main(void)
{ {
// Initialization // Initialization
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@ -25,7 +25,7 @@ core;core_3d_camera_mode;★☆☆☆;1.0;1.0;2014;2025;"Ramon Santamaria";@rays
core;core_3d_camera_free;★☆☆☆;1.3;1.3;2015;2025;"Ramon Santamaria";@raysan5 core;core_3d_camera_free;★☆☆☆;1.3;1.3;2015;2025;"Ramon Santamaria";@raysan5
core;core_3d_camera_first_person;★★☆☆;1.3;1.3;2015;2025;"Ramon Santamaria";@raysan5 core;core_3d_camera_first_person;★★☆☆;1.3;1.3;2015;2025;"Ramon Santamaria";@raysan5
core;core_3d_camera_split_screen;★★★☆;3.7;4.0;2021;2025;"Jeffery Myers";@JeffM2501 core;core_3d_camera_split_screen;★★★☆;3.7;4.0;2021;2025;"Jeffery Myers";@JeffM2501
core;core_3d_camera_fps;★★★☆;5.5;5.5;2025;2025;"Agnis Aldins";@nezvers core;core_3d_camera_fps;★★★☆;5.5;5.5;2025;2025;"Agnis Aldiņš";@nezvers
core;core_3d_picking;★★☆☆;1.3;4.0;2015;2025;"Ramon Santamaria";@raysan5 core;core_3d_picking;★★☆☆;1.3;4.0;2015;2025;"Ramon Santamaria";@raysan5
core;core_world_screen;★★☆☆;1.3;1.4;2015;2025;"Ramon Santamaria";@raysan5 core;core_world_screen;★★☆☆;1.3;1.4;2015;2025;"Ramon Santamaria";@raysan5
core;core_window_flags;★★★☆;3.5;3.5;2020;2025;"Ramon Santamaria";@raysan5 core;core_window_flags;★★★☆;3.5;3.5;2020;2025;"Ramon Santamaria";@raysan5
@ -46,12 +46,14 @@ core;core_automation_events;★★★☆;5.0;5.0;2023;2025;"Ramon Santamaria";@r
core;core_high_dpi;★★☆☆;5.0;5.5;2025;2025;"Jonathan Marler";@marler8997 core;core_high_dpi;★★☆☆;5.0;5.5;2025;2025;"Jonathan Marler";@marler8997
core;core_render_texture;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Ramon Santamaria";@raysan5 core;core_render_texture;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Ramon Santamaria";@raysan5
core;core_undo_redo;★★★☆;5.5;5.6;2025;2025;"Ramon Santamaria";@raysan5 core;core_undo_redo;★★★☆;5.5;5.6;2025;2025;"Ramon Santamaria";@raysan5
core;core_viewport_scaling;★★☆☆;5.5;5.5;2025;2025;"Agnis Aldiņš";@nezvers
core;core_input_actions;★★☆☆;5.5;5.6;2025;2025;"Jett";@JettMonstersGoBoom core;core_input_actions;★★☆☆;5.5;5.6;2025;2025;"Jett";@JettMonstersGoBoom
core;core_directory_files;★☆☆☆;5.5;5.6;2025;2025;"Hugo ARNAL";@hugoarnal core;core_directory_files;★☆☆☆;5.5;5.6;2025;2025;"Hugo ARNAL";@hugoarnal
core;core_highdpi_testbed;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Ramon Santamaria";@raysan5 core;core_highdpi_testbed;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Ramon Santamaria";@raysan5
core;core_screen_recording;★☆☆;5.6-dev;5.6-dev;2025;2025;"Ramon Santamaria";@raysan5 core;core_screen_recording;★☆☆;5.6-dev;5.6-dev;2025;2025;"Ramon Santamaria";@raysan5
core;core_clipboard_text;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Robin";@RobinsAviary core;core_clipboard_text;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Ananth S";@Ananth1839
core;core_text_file_loading;★☆☆☆;5.5;5.6;0;0;"Aanjishnu Bhattacharyya";@NimComPoo-04 core;core_text_file_loading;★☆☆☆;5.5;5.6;0;0;"Aanjishnu Bhattacharyya";@NimComPoo-04
core;core_compute_hash;★★☆☆;5.6-dev;5.6-dev;2025;2025;"Ramon Santamaria";@raysan5
shapes;shapes_basic_shapes;★☆☆☆;1.0;4.2;2014;2025;"Ramon Santamaria";@raysan5 shapes;shapes_basic_shapes;★☆☆☆;1.0;4.2;2014;2025;"Ramon Santamaria";@raysan5
shapes;shapes_bouncing_ball;★☆☆☆;2.5;2.5;2013;2025;"Ramon Santamaria";@raysan5 shapes;shapes_bouncing_ball;★☆☆☆;2.5;2.5;2013;2025;"Ramon Santamaria";@raysan5
shapes;shapes_bullet_hell;★☆☆☆;5.6;5.6;2025;2025;"Zero";@zerohorsepower shapes;shapes_bullet_hell;★☆☆☆;5.6;5.6;2025;2025;"Zero";@zerohorsepower
@ -80,9 +82,14 @@ shapes;shapes_vector_angle;★★☆☆;1.0;5.0;2023;2025;"Ramon Santamaria";@ra
shapes;shapes_pie_chart;★★★☆;5.5;5.6;2025;2025;"Gideon Serfontein";@GideonSerf shapes;shapes_pie_chart;★★★☆;5.5;5.6;2025;2025;"Gideon Serfontein";@GideonSerf
shapes;shapes_kaleidoscope;★★☆☆;5.5;5.6;2025;2025;"Hugo ARNAL";@hugoarnal shapes;shapes_kaleidoscope;★★☆☆;5.5;5.6;2025;2025;"Hugo ARNAL";@hugoarnal
shapes;shapes_clock_of_clocks;★★☆☆;5.5;5.6-dev;2025;2025;"JP Mortiboys";@themushroompirates shapes;shapes_clock_of_clocks;★★☆☆;5.5;5.6-dev;2025;2025;"JP Mortiboys";@themushroompirates
shapes;shapes_math_sine_cosine;★★☆☆;5.6-dev;5.6-dev;2025;2025;"Jopestpe";@jopestpe
shapes;shapes_mouse_trail;★☆☆☆;5.6;5.6-dev;2025;2025;"Balamurugan R";@Bala050814 shapes;shapes_mouse_trail;★☆☆☆;5.6;5.6-dev;2025;2025;"Balamurugan R";@Bala050814
shapes;shapes_simple_particles;★★☆☆;5.6;5.6;2025;2025;"Jordi Santonja";@JordSant shapes;shapes_simple_particles;★★☆☆;5.6;5.6;2025;2025;"Jordi Santonja";@JordSant
shapes;shapes_starfield_effect;★★☆☆;5.5;5.6-dev;2025;2025;"JP Mortiboys";@themushroompirates shapes;shapes_starfield_effect;★★☆☆;5.5;5.6-dev;2025;2025;"JP Mortiboys";@themushroompirates
shapes;shapes_lines_drawing;★☆☆☆;5.6-dev;5.6;2025;2025;"Robin";@RobinsAviary
shapes;shapes_math_angle_rotation;★☆☆☆;5.6-dev;5.6;2025;2025;"Kris";@krispy-snacc
shapes;shapes_rlgl_color_wheel;★★★☆;5.6-dev;5.6-dev;2025;2025;"Robin";@RobinsAviary
shapes;shapes_rlgl_triangle;★★☆☆;5.6-dev;5.6-dev;2025;2025;"Robin";@RobinsAviary
textures;textures_logo_raylib;★☆☆☆;1.0;1.0;2014;2025;"Ramon Santamaria";@raysan5 textures;textures_logo_raylib;★☆☆☆;1.0;1.0;2014;2025;"Ramon Santamaria";@raysan5
textures;textures_srcrec_dstrec;★★★☆;1.3;1.3;2015;2025;"Ramon Santamaria";@raysan5 textures;textures_srcrec_dstrec;★★★☆;1.3;1.3;2015;2025;"Ramon Santamaria";@raysan5
textures;textures_image_drawing;★★☆☆;1.4;1.4;2016;2025;"Ramon Santamaria";@raysan5 textures;textures_image_drawing;★★☆☆;1.4;1.4;2016;2025;"Ramon Santamaria";@raysan5
@ -108,7 +115,9 @@ textures;textures_gif_player;★★★☆;4.2;4.2;2021;2025;"Ramon Santamaria";@
textures;textures_image_kernel;★★★★;1.3;1.3;2015;2025;"Karim Salem";@kimo-s textures;textures_image_kernel;★★★★;1.3;1.3;2015;2025;"Karim Salem";@kimo-s
textures;textures_image_channel;★★☆☆;5.5;5.5;2024;2025;"Bruno Cabral";@brccabral textures;textures_image_channel;★★☆☆;5.5;5.5;2024;2025;"Bruno Cabral";@brccabral
textures;textures_image_rotate;★★☆☆;1.0;1.0;2014;2025;"Ramon Santamaria";@raysan5 textures;textures_image_rotate;★★☆☆;1.0;1.0;2014;2025;"Ramon Santamaria";@raysan5
textures;textures_screen_buffer;★★☆☆;5.5;5.5;2025;2025;"Agnis Aldiņš";@nezvers
textures;textures_textured_curve;★★★☆;4.5;4.5;2022;2025;"Jeffery Myers";@JeffM2501 textures;textures_textured_curve;★★★☆;4.5;4.5;2022;2025;"Jeffery Myers";@JeffM2501
textures;textures_sprite_stacking;★★☆☆;5.6-dev;6.0;2025;2025;"Robin";@RobinsAviary
text;text_sprite_fonts;★☆☆☆;1.7;3.7;2017;2025;"Ramon Santamaria";@raysan5 text;text_sprite_fonts;★☆☆☆;1.7;3.7;2017;2025;"Ramon Santamaria";@raysan5
text;text_font_spritefont;★☆☆☆;1.0;1.0;2014;2025;"Ramon Santamaria";@raysan5 text;text_font_spritefont;★☆☆☆;1.0;1.0;2014;2025;"Ramon Santamaria";@raysan5
text;text_font_filters;★★☆☆;1.3;4.2;2015;2025;"Ramon Santamaria";@raysan5 text;text_font_filters;★★☆☆;1.3;4.2;2015;2025;"Ramon Santamaria";@raysan5
@ -149,6 +158,8 @@ models;models_bone_socket;★★★★;4.5;4.5;2024;2025;"iP";@ipzaur
models;models_tesseract_view;★★☆☆;5.6-dev;5.6-dev;2024;2025;"Timothy van der Valk";@arceryz models;models_tesseract_view;★★☆☆;5.6-dev;5.6-dev;2024;2025;"Timothy van der Valk";@arceryz
models;models_basic_voxel;★★☆☆;5.5;5.5;2025;2025;"Tim Little";@timlittle models;models_basic_voxel;★★☆☆;5.5;5.5;2025;2025;"Tim Little";@timlittle
models;models_rotating_cube;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Jopestpe";@jopestpe models;models_rotating_cube;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Jopestpe";@jopestpe
models;models_decals;★★★★;5.6-dev;5.6-dev;2025;2025;"JP Mortiboys";@themushroompirates
models;models_directional_billboard;★★☆☆;5.6-dev;5.6;2025;2025;"Robin";@RobinsAviary
shaders;shaders_ascii_rendering;★★☆☆;5.5;5.6;2025;2025;"Maicon Santana";@maiconpintoabreu shaders;shaders_ascii_rendering;★★☆☆;5.5;5.6;2025;2025;"Maicon Santana";@maiconpintoabreu
shaders;shaders_basic_lighting;★★★★;3.0;4.2;2019;2025;"Chris Camacho";@chriscamacho shaders;shaders_basic_lighting;★★★★;3.0;4.2;2019;2025;"Chris Camacho";@chriscamacho
shaders;shaders_model_shader;★★☆☆;1.3;3.7;2014;2025;"Ramon Santamaria";@raysan5 shaders;shaders_model_shader;★★☆☆;1.3;3.7;2014;2025;"Ramon Santamaria";@raysan5
@ -162,6 +173,7 @@ shaders;shaders_texture_outline;★★★☆;4.0;4.0;2021;2025;"Serenity Skiff";
shaders;shaders_texture_waves;★★☆☆;2.5;3.7;2019;2025;"Anata";@anatagawa shaders;shaders_texture_waves;★★☆☆;2.5;3.7;2019;2025;"Anata";@anatagawa
shaders;shaders_julia_set;★★★☆;2.5;4.0;2019;2025;"Josh Colclough";@joshcol9232 shaders;shaders_julia_set;★★★☆;2.5;4.0;2019;2025;"Josh Colclough";@joshcol9232
shaders;shaders_mandelbrot_set;★★★☆;5.6;5.6;2025;2025;"Jordi Santonja";@JordSant shaders;shaders_mandelbrot_set;★★★☆;5.6;5.6;2025;2025;"Jordi Santonja";@JordSant
shaders;shaders_color_correction;★★☆☆;5.6;5.6;2025;2025;"Jordi Santonja";@JordSant
shaders;shaders_eratosthenes_sieve;★★★☆;2.5;4.0;2019;2025;"ProfJski";@ProfJski shaders;shaders_eratosthenes_sieve;★★★☆;2.5;4.0;2019;2025;"ProfJski";@ProfJski
shaders;shaders_fog_rendering;★★★☆;2.5;3.7;2019;2025;"Chris Camacho";@chriscamacho shaders;shaders_fog_rendering;★★★☆;2.5;3.7;2019;2025;"Chris Camacho";@chriscamacho
shaders;shaders_simple_mask;★★☆☆;2.5;3.7;2019;2025;"Chris Camacho";@chriscamacho shaders;shaders_simple_mask;★★☆☆;2.5;3.7;2019;2025;"Chris Camacho";@chriscamacho
@ -188,6 +200,7 @@ audio;audio_mixed_processor;★★★★;4.2;4.2;2023;2025;"hkc";@hatkidchan
audio;audio_stream_effects;★★★★;4.2;5.0;2022;2025;"Ramon Santamaria";@raysan5 audio;audio_stream_effects;★★★★;4.2;5.0;2022;2025;"Ramon Santamaria";@raysan5
audio;audio_sound_multi;★★☆☆;5.0;5.0;2023;2025;"Jeffery Myers";@JeffM2501 audio;audio_sound_multi;★★☆☆;5.0;5.0;2023;2025;"Jeffery Myers";@JeffM2501
audio;audio_sound_positioning;★★☆☆;5.5;5.5;2025;2025;"Le Juez Victor";@Bigfoot71 audio;audio_sound_positioning;★★☆☆;5.5;5.5;2025;2025;"Le Juez Victor";@Bigfoot71
audio;audio_spectrum_visualizer;★★★☆;6.0;5.6-dev;2025;2025;"IANN";@meisei4
others;rlgl_standalone;★★★★;1.6;4.0;2014;2025;"Ramon Santamaria";@raysan5 others;rlgl_standalone;★★★★;1.6;4.0;2014;2025;"Ramon Santamaria";@raysan5
others;rlgl_compute_shader;★★★★;4.0;4.0;2021;2025;"Teddy Astie";@tsnake41 others;rlgl_compute_shader;★★★★;4.0;4.0;2021;2025;"Teddy Astie";@tsnake41
others;easings_testbed;★★★☆;2.5;3.0;2019;2025;"Juan Miguel López";@flashback-fx others;easings_testbed;★★★☆;2.5;3.0;2019;2025;"Juan Miguel López";@flashback-fx

View File

@ -0,0 +1,605 @@
/*******************************************************************************************
*
* raylib [models] example - decals
*
* Example complexity rating: [] 4/4
*
* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
*
* Example contributed by JP Mortiboys (@themushroompirates) and reviewed by Ramon Santamaria (@raysan5)
* Based on previous work by @mrdoob
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
* Copyright (c) 2025 JP Mortiboys (@themushroompirates) and Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
#include <string.h> // Required for: memcpy()
#undef FLT_MAX
#define FLT_MAX 340282346638528859811704183484516925440.0f // Maximum value of a float, from bit pattern 01111111011111111111111111111111
#define MAX_DECALS 256
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
typedef struct MeshBuilder {
int vertexCount;
int vertexCapacity;
Vector3 *vertices;
Vector2 *uvs;
} MeshBuilder;
//------------------------------------------------------------------------------------
// Module Functions Declaration
//------------------------------------------------------------------------------------
static void AddTriangleToMeshBuilder(MeshBuilder *mb, Vector3 vertices[3]);
static void FreeMeshBuilder(MeshBuilder *mb);
static Mesh BuildMesh(MeshBuilder *mb);
static Mesh GenMeshDecal(Model inputModel, Matrix projection, float decalSize, float decalOffset);
static Vector3 ClipSegment(Vector3 v0, Vector3 v1, Vector3 p, float s);
#define FreeDecalMeshData() GenMeshDecal((Model){ .meshCount = -1.0f }, (Matrix){ 0 }, 0.0f, 0.0f)
static bool GuiButton(Rectangle rec, const char *label);
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
SetConfigFlags(FLAG_MSAA_4X_HINT);
InitWindow(screenWidth, screenHeight, "raylib [models] example - decals");
// Define the camera to look into our 3d world
Camera camera = { 0 };
camera.position = (Vector3){ 5.0f, 5.0f, 5.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.6f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
// Load character model
Model model = LoadModel("resources/models/obj/character.obj");
// Apply character skin
Texture2D modelTexture = LoadTexture("resources/models/obj/character_diffuse.png");
SetTextureFilter(modelTexture, TEXTURE_FILTER_BILINEAR);
model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = modelTexture;
BoundingBox modelBBox = GetMeshBoundingBox(model.meshes[0]); // Get mesh bounding box
camera.target = Vector3Lerp(modelBBox.min, modelBBox.max, 0.5f);
camera.position = Vector3Scale(modelBBox.max, 1.0f);
camera.position.x *= 0.1f;
float modelSize = fminf(
fminf(fabsf(modelBBox.max.x - modelBBox.min.x), fabsf(modelBBox.max.y - modelBBox.min.y)),
fabsf(modelBBox.max.z - modelBBox.min.z));
camera.position = (Vector3){ 0.0f, modelBBox.max.y*1.2f, modelSize*3.0f };
float decalSize = modelSize*0.25f;
float decalOffset = 0.01f;
Model placementCube = LoadModelFromMesh(GenMeshCube(decalSize, decalSize, decalSize));
placementCube.materials[0].maps[0].color = LIME;
Material decalMaterial = LoadMaterialDefault();
decalMaterial.maps[0].color = YELLOW;
Image decalImage = LoadImage("resources/raylib_logo.png");
ImageResizeNN(&decalImage, decalImage.width/4, decalImage.height/4);
Texture decalTexture = LoadTextureFromImage(decalImage);
UnloadImage(decalImage);
SetTextureFilter(decalTexture, TEXTURE_FILTER_BILINEAR);
decalMaterial.maps[MATERIAL_MAP_DIFFUSE].texture = decalTexture;
decalMaterial.maps[MATERIAL_MAP_DIFFUSE].color = RAYWHITE;
bool showModel = true;
Model decalModels[MAX_DECALS] = { 0 };
int decalCount = 0;
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
//----------------------------------------------------------------------------------
if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT)) UpdateCamera(&camera, CAMERA_THIRD_PERSON);
// Display information about closest hit
RayCollision collision = { 0 };
collision.distance = FLT_MAX;
collision.hit = false;
// Get mouse ray
Ray ray = GetScreenToWorldRay(GetMousePosition(), camera);
// Check ray collision against bounding box first, before trying the full ray-mesh test
RayCollision boxHitInfo = GetRayCollisionBox(ray, modelBBox);
if ((boxHitInfo.hit) && (decalCount < MAX_DECALS))
{
// Check ray collision against model meshes
RayCollision meshHitInfo = { 0 };
for (int m = 0; m < model.meshCount; m++)
{
// NOTE: We consider the model.transform for the collision check but
// it can be checked against any transform Matrix, used when checking against same
// model drawn multiple times with multiple transforms
meshHitInfo = GetRayCollisionMesh(ray, model.meshes[m], model.transform);
if (meshHitInfo.hit)
{
// Save the closest hit mesh
if (!collision.hit || (collision.distance > meshHitInfo.distance)) collision = meshHitInfo;
}
}
if (meshHitInfo.hit) collision = meshHitInfo;
}
// Add decal to mesh on hit point
if (collision.hit && IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && (decalCount < MAX_DECALS))
{
// Create the transformation to project the decal
Vector3 origin = Vector3Add(collision.point, Vector3Scale(collision.normal, 1.0f));
Matrix splat = MatrixLookAt(collision.point, origin, (Vector3){ 0.0f, 1.0f, 0.0f });
// Spin the placement around a bit
splat = MatrixMultiply(splat, MatrixRotateZ(DEG2RAD*((float)GetRandomValue(-180, 180))));
Mesh decalMesh = GenMeshDecal(model, splat, decalSize, decalOffset);
if (decalMesh.vertexCount > 0)
{
int decalIndex = decalCount++;
decalModels[decalIndex] = LoadModelFromMesh(decalMesh);
decalModels[decalIndex].materials[0].maps[0] = decalMaterial.maps[0];
}
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
// Draw the model at the origin and default scale
if (showModel) DrawModel(model, (Vector3){0.0f, 0.0f, 0.0f}, 1.0f, WHITE);
// Draw the decal models
for (int i = 0; i < decalCount; i++) DrawModel(decalModels[i], (Vector3){0}, 1.0f, WHITE);
// If we hit the mesh, draw the box for the decal
if (collision.hit)
{
Vector3 origin = Vector3Add(collision.point, Vector3Scale(collision.normal, 1.0f));
Matrix splat = MatrixLookAt(collision.point, origin, (Vector3){0,1,0});
placementCube.transform = MatrixInvert(splat);
DrawModel(placementCube, (Vector3){0}, 1.0f, Fade(WHITE, 0.5f));
}
DrawGrid(10, 10.0f);
EndMode3D();
float yPos = 10;
float x0 = GetScreenWidth() - 300;
float x1 = x0 + 100;
float x2 = x1 + 100;
DrawText("Vertices", x1, yPos, 10, LIME);
DrawText("Triangles", x2, yPos, 10, LIME);
yPos += 15;
int vertexCount = 0;
int triangleCount = 0;
for (int i = 0; i < model.meshCount; i++)
{
vertexCount += model.meshes[i].vertexCount;
triangleCount += model.meshes[i].triangleCount;
}
DrawText("Main model", x0, yPos, 10, LIME);
DrawText(TextFormat("%d", vertexCount), x1, yPos, 10, LIME);
DrawText(TextFormat("%d", triangleCount), x2, yPos, 10, LIME);
yPos += 15;
for (int i = 0; i < decalCount; i++)
{
if (i == 20)
{
DrawText("...", x0, yPos, 10, LIME);
yPos += 15;
}
if (i < 20)
{
DrawText(TextFormat("Decal #%d", i+1), x0, yPos, 10, LIME);
DrawText(TextFormat("%d", decalModels[i].meshes[0].vertexCount), x1, yPos, 10, LIME);
DrawText(TextFormat("%d", decalModels[i].meshes[0].triangleCount), x2, yPos, 10, LIME);
yPos += 15;
}
vertexCount += decalModels[i].meshes[0].vertexCount;
triangleCount += decalModels[i].meshes[0].triangleCount;
}
DrawText("TOTAL", x0, yPos, 10, LIME);
DrawText(TextFormat("%d", vertexCount), x1, yPos, 10, LIME);
DrawText(TextFormat("%d", triangleCount), x2, yPos, 10, LIME);
yPos += 15;
DrawText("Hold RMB to move camera", 10, 430, 10, GRAY);
DrawText("(c) Character model and texture from kenney.nl", screenWidth - 260, screenHeight - 20, 10, GRAY);
// UI elements
if (GuiButton((Rectangle){ 10, screenHeight - 100, 100, 60 }, showModel ? "Hide Model" : "Show Model")) showModel = !showModel;
if (GuiButton((Rectangle){ 10 + 110, screenHeight - 100, 100, 60 }, "Clear Decals"))
{
// Clear decals, unload all decal models
for (int i = 0; i < decalCount; i++) UnloadModel(decalModels[i]);
decalCount = 0;
}
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadModel(model);
UnloadTexture(modelTexture);
// Unload decal models
for (int i = 0; i < decalCount; i++) UnloadModel(decalModels[i]);
UnloadTexture(decalTexture);
FreeDecalMeshData(); // Free the data for decal generation
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
// Add triangles to mesh builder (dynamic array manager)
static void AddTriangleToMeshBuilder(MeshBuilder *mb, Vector3 vertices[3])
{
// Reallocate and copy if we need to
if (mb->vertexCapacity <= (mb->vertexCount + 3))
{
int newVertexCapacity = (1 + (mb->vertexCapacity/256))*256;
Vector3 *newVertices = (Vector3 *)MemAlloc(newVertexCapacity*sizeof(Vector3));
if (mb->vertexCapacity > 0)
{
memcpy(newVertices, mb->vertices, mb->vertexCount*sizeof(Vector3));
MemFree(mb->vertices);
}
mb->vertices = newVertices;
mb->vertexCapacity = newVertexCapacity;
}
// Add 3 vertices
int index = mb->vertexCount;
mb->vertexCount += 3;
for (int i = 0; i < 3; i++) mb->vertices[index+i] = vertices[i];
}
// Free mesh builder
static void FreeMeshBuilder(MeshBuilder *mb)
{
MemFree(mb->vertices);
if (mb->uvs) MemFree(mb->uvs);
*mb = (MeshBuilder){ 0 };
}
// Build a Mesh from MeshBuilder data
static Mesh BuildMesh(MeshBuilder *mb)
{
Mesh outMesh = { 0 };
outMesh.vertexCount = mb->vertexCount;
outMesh.triangleCount = mb->vertexCount/3;
outMesh.vertices = MemAlloc(outMesh.vertexCount*3*sizeof(float));
if (mb->uvs) outMesh.texcoords = MemAlloc(outMesh.vertexCount*2*sizeof(float));
for (int i = 0; i < mb->vertexCount; i++)
{
outMesh.vertices[3*i+0] = mb->vertices[i].x;
outMesh.vertices[3*i+1] = mb->vertices[i].y;
outMesh.vertices[3*i+2] = mb->vertices[i].z;
if (mb->uvs)
{
outMesh.texcoords[2*i+0] = mb->uvs[i].x;
outMesh.texcoords[2*i+1] = mb->uvs[i].y;
}
}
UploadMesh(&outMesh, false);
return outMesh;
}
// Clip segment
static Vector3 ClipSegment(Vector3 v0, Vector3 v1, Vector3 p, float s)
{
float d0 = Vector3DotProduct(v0, p) - s;
float d1 = Vector3DotProduct(v1, p) - s;
float s0 = d0/(d0 - d1);
Vector3 position = Vector3Lerp(v0, v1, s0);
return position;
}
// Generate mesh decals for provided model
static Mesh GenMeshDecal(Model target, Matrix projection, float decalSize, float decalOffset)
{
// We're going to use these to build up our decal meshes
// They'll resize automatically as we go, we'll free them at the end
static MeshBuilder meshBuilders[2] = { 0 };
// Ugly way of telling us to free the static MeshBuilder data
if (target.meshCount == -1)
{
FreeMeshBuilder(&meshBuilders[0]);
FreeMeshBuilder(&meshBuilders[1]);
return (Mesh){ 0 };
}
// We're going to need the inverse matrix
Matrix invProj = MatrixInvert(projection);
// Reset the mesh builders
meshBuilders[0].vertexCount = 0;
meshBuilders[1].vertexCount = 0;
// We'll be flip-flopping between the two mesh builders
// Reading from one and writing to the other, then swapping
int mbIndex = 0;
// First pass, just get any triangle inside the bounding box (for each mesh of the model)
for (int meshIndex = 0; meshIndex < target.meshCount; meshIndex++)
{
Mesh mesh = target.meshes[meshIndex];
for (int tri = 0; tri < mesh.triangleCount; tri++)
{
Vector3 vertices[3] = { 0 };
// The way we calculate the vertices of the mesh triangle
// depend on whether the mesh vertices are indexed or not
if (mesh.indices == 0)
{
for (int v = 0; v < 3; v++)
{
vertices[v] = (Vector3){
mesh.vertices[3*3*tri + 3*v + 0],
mesh.vertices[3*3*tri + 3*v + 1],
mesh.vertices[3*3*tri + 3*v + 2]
};
}
}
else
{
for (int v = 0; v < 3; v++)
{
vertices[v] = (Vector3){
mesh.vertices[ 3*mesh.indices[3*tri+0] + v],
mesh.vertices[ 3*mesh.indices[3*tri+1] + v],
mesh.vertices[ 3*mesh.indices[3*tri+2] + v]
};
}
}
// Transform all 3 vertices of the triangle
// and check if they are inside our decal box
int insideCount = 0;
for (int i = 0; i < 3; i++)
{
// To projection space
Vector3 v = Vector3Transform(vertices[i], projection);
if ((fabsf(v.x) < decalSize) || (fabsf(v.y) <= decalSize) || (fabsf(v.z) <= decalSize)) insideCount++;
// We need to keep the transformed vertex
vertices[i] = v;
}
// If any of them are inside, we add the triangle - we'll clip it later
if (insideCount > 0) AddTriangleToMeshBuilder(&meshBuilders[mbIndex], vertices);
}
}
// Clipping time! We need to clip against all 6 directions
Vector3 planes[6] = {
{ 1, 0, 0 },
{ -1, 0, 0 },
{ 0, 1, 0 },
{ 0, -1, 0 },
{ 0, 0, 1 },
{ 0, 0, -1 }
};
for (int face = 0; face < 6; face++)
{
// Swap current model builder (so we read from the one we just wrote to)
mbIndex = 1 - mbIndex;
MeshBuilder *inMesh = &meshBuilders[1 - mbIndex];
MeshBuilder *outMesh = &meshBuilders[mbIndex];
// Reset write builder
outMesh->vertexCount = 0;
float s = 0.5f*decalSize;
for (int i = 0; i < inMesh->vertexCount; i += 3)
{
Vector3 nV1, nV2, nV3, nV4;
float d1 = Vector3DotProduct(inMesh->vertices[ i + 0 ], planes[face] ) - s;
float d2 = Vector3DotProduct(inMesh->vertices[ i + 1 ], planes[face] ) - s;
float d3 = Vector3DotProduct(inMesh->vertices[ i + 2 ], planes[face] ) - s;
int v1Out = (d1 > 0);
int v2Out = (d2 > 0);
int v3Out = (d3 > 0);
// Calculate, how many vertices of the face lie outside of the clipping plane
int total = v1Out + v2Out + v3Out;
switch (total)
{
case 0:
{
// The entire face lies inside of the plane, no clipping needed
AddTriangleToMeshBuilder(outMesh, (Vector3[3]){inMesh->vertices[i], inMesh->vertices[i+1], inMesh->vertices[i+2]});
} break;
case 1:
{
// One vertex lies outside of the plane, perform clipping
if (v1Out)
{
nV1 = inMesh->vertices[i + 1];
nV2 = inMesh->vertices[i + 2];
nV3 = ClipSegment(inMesh->vertices[i], nV1, planes[face], s);
nV4 = ClipSegment(inMesh->vertices[i], nV2, planes[face], s);
}
if (v2Out)
{
nV1 = inMesh->vertices[i];
nV2 = inMesh->vertices[i + 2];
nV3 = ClipSegment(inMesh->vertices[i + 1], nV1, planes[face], s);
nV4 = ClipSegment(inMesh->vertices[i + 1], nV2, planes[face], s);
AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV3, nV2, nV1});
AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV2, nV3, nV4});
break;
}
if (v3Out)
{
nV1 = inMesh->vertices[i];
nV2 = inMesh->vertices[i + 1];
nV3 = ClipSegment(inMesh->vertices[i + 2], nV1, planes[face], s);
nV4 = ClipSegment(inMesh->vertices[i + 2], nV2, planes[face], s);
}
AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV1, nV2, nV3});
AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV4, nV3, nV2});
} break;
case 2:
{
// Two vertices lies outside of the plane, perform clipping
if (!v1Out)
{
nV1 = inMesh->vertices[i];
nV2 = ClipSegment(nV1, inMesh->vertices[i + 1], planes[face], s);
nV3 = ClipSegment(nV1, inMesh->vertices[i + 2], planes[face], s);
AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV1, nV2, nV3});
}
if (!v2Out)
{
nV1 = inMesh->vertices[i + 1];
nV2 = ClipSegment(nV1, inMesh->vertices[i + 2], planes[face], s);
nV3 = ClipSegment(nV1, inMesh->vertices[i], planes[face], s);
AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV1, nV2, nV3});
}
if (!v3Out)
{
nV1 = inMesh->vertices[i + 2];
nV2 = ClipSegment(nV1, inMesh->vertices[i], planes[face], s);
nV3 = ClipSegment(nV1, inMesh->vertices[i + 1], planes[face], s);
AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV1, nV2, nV3});
}
} break;
case 3: // The entire face lies outside of the plane, so let's discard the corresponding vertices
default: break;
}
}
}
// Now we just need to re-transform the vertices
MeshBuilder *theMesh = &meshBuilders[mbIndex];
// Allocate room for UVs
if (theMesh->vertexCount > 0)
{
theMesh->uvs = (Vector2 *)MemAlloc(sizeof(Vector2)*theMesh->vertexCount);
for (int i = 0; i < theMesh->vertexCount; i++)
{
// Calculate the UVs based on the projected coords
// They are clipped to (-decalSize .. decalSize) and we want them (0..1)
theMesh->uvs[i].x = (theMesh->vertices[i].x/decalSize + 0.5f);
theMesh->uvs[i].y = (theMesh->vertices[i].y/decalSize + 0.5f);
// Tiny nudge in the normal direction so it renders properly over the mesh
theMesh->vertices[i].z -= decalOffset;
// From projection space to world space
theMesh->vertices[i] = Vector3Transform(theMesh->vertices[i], invProj);
}
// Decal model data ready, create the mesh and return it
return BuildMesh(theMesh);
}
else
{
// Return a blank mesh as there's nothing to add
return (Mesh){ 0 };
}
}
// Button UI element
static bool GuiButton(Rectangle rec, const char *label)
{
Color bgColor = GRAY;
bool pressed = false;
if (CheckCollisionPointRec(GetMousePosition(), rec))
{
bgColor = LIGHTGRAY;
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) pressed = true;
}
DrawRectangleRec(rec, bgColor);
DrawRectangleLinesEx(rec, 2.0f, DARKGRAY);
float fontSize = 10.0f;
float textWidth = MeasureText(label, fontSize);
DrawText(label, (int)(rec.x + rec.width*0.5f - textWidth*0.5f), (int)(rec.y + rec.height*0.5f - fontSize*0.5f), fontSize, DARKGRAY);
return pressed;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

View File

@ -0,0 +1,116 @@
/*******************************************************************************************
*
* raylib [models] example - directional billboard
*
* Example complexity rating: [] 2/4
*
* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6
*
* Example contributed by Robin (@RobinsAviary) and reviewed by Ramon Santamaria (@raysan5)
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
* Copyright (c) 2025 Robin (@RobinsAviary)
* Killbot art by patvanmackelberg https://opengameart.org/content/killbot-8-directional under CC0
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
#include <stdlib.h>
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - directional billboard");
// Set up the camera
Camera camera = { 0 };
camera.position = (Vector3){ 2.0f, 1.0f, 2.0f }; // Starting position
camera.target = (Vector3){ 0.0f, 0.5f, 0.0f }; // Target position
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Up vector
camera.fovy = 45.0f; // FOV
camera.projection = CAMERA_PERSPECTIVE; // Projection type (Standard 3D perspective)
// Load billboard texture
Texture skillbot = LoadTexture("resources/skillbot.png");
// Timer to update animation
float anim_timer = 0.0f;
// Animation frame
unsigned int anim = 0;
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_ORBITAL);
// Update timer with delta time
anim_timer += GetFrameTime();
// Update frame index after a certain amount of time (half a second)
if (anim_timer > 0.5f)
{
anim_timer = 0.0f;
anim += 1;
}
// Reset frame index to zero on overflow
if (anim >= 4) anim = 0;
// Find the current direction frame based on the camera position to the billboard object
float dir = (float)floor(((Vector2Angle((Vector2){ 2.0f, 0.0f }, (Vector2){ camera.position.x, camera.position.z })/PI)*4.0f) + 0.25f);
// Correct frame index if angle is negative
if (dir < 0.0f)
{
dir = 8.0f - (float)abs((int)dir);
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
DrawGrid(10, 1.0f);
// Draw billboard pointing straight up to the sky, rotated relative to the camera and offset from the bottom
DrawBillboardPro(camera, skillbot, (Rectangle){ 0.0f + (anim*24.0f), 0.0f + (dir*24.0f), 24.0f, 24.0f }, Vector3Zero(), (Vector3){ 0.0f, 1.0f, 0.0f }, Vector2One(), (Vector2){ 0.5f, 0.0f }, 0, WHITE);
EndMode3D();
// Render various variables for reference
DrawText(TextFormat("animation: %d", anim), 10, 10, 20, DARKGRAY);
DrawText(TextFormat("direction frame: %.0f", dir), 10, 40, 20, DARKGRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
// Unload billboard texture
UnloadTexture(skillbot);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -35,171 +35,157 @@
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
int main(void) int main(void)
{ {
// Initialization // Initialization
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
const int screenWidth = 800; const int screenWidth = 800;
const int screenHeight = 450; const int screenHeight = 450;
const char *voxFileNames[] = { const char *voxFileNames[] = {
"resources/models/vox/chr_knight.vox", "resources/models/vox/chr_knight.vox",
"resources/models/vox/chr_sword.vox", "resources/models/vox/chr_sword.vox",
"resources/models/vox/monu9.vox", "resources/models/vox/monu9.vox",
"resources/models/vox/fez.vox" "resources/models/vox/fez.vox"
}; };
InitWindow(screenWidth, screenHeight, "raylib [models] example - loading vox"); InitWindow(screenWidth, screenHeight, "raylib [models] example - loading vox");
// Define the camera to look into our 3d world // Define the camera to look into our 3d world
Camera camera = { 0 }; Camera camera = { 0 };
camera.position = (Vector3){ 10.0f, 10.0f, 10.0f }; // Camera position camera.position = (Vector3){ 10.0f, 10.0f, 10.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) 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.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
// Load MagicaVoxel files // Load MagicaVoxel files
Model models[MAX_VOX_FILES] = { 0 }; Model models[MAX_VOX_FILES] = { 0 };
for (int i = 0; i < MAX_VOX_FILES; i++) for (int i = 0; i < MAX_VOX_FILES; i++)
{ {
// Load VOX file and measure time // Load VOX file and measure time
double t0 = GetTime()*1000.0; double t0 = GetTime()*1000.0;
models[i] = LoadModel(voxFileNames[i]); models[i] = LoadModel(voxFileNames[i]);
double t1 = GetTime()*1000.0; double t1 = GetTime()*1000.0;
TraceLog(LOG_WARNING, TextFormat("[%s] File loaded in %.3f ms", voxFileNames[i], t1 - t0)); TraceLog(LOG_INFO, TextFormat("[%s] Model file loaded in %.3f ms", voxFileNames[i], t1 - t0));
// Compute model translation matrix to center model on draw position (0, 0 , 0) // Compute model translation matrix to center model on draw position (0, 0 , 0)
BoundingBox bb = GetModelBoundingBox(models[i]); BoundingBox bb = GetModelBoundingBox(models[i]);
Vector3 center = { 0 }; Vector3 center = { 0 };
center.x = bb.min.x + (((bb.max.x - bb.min.x)/2)); center.x = bb.min.x + (((bb.max.x - bb.min.x)/2));
center.z = bb.min.z + (((bb.max.z - bb.min.z)/2)); center.z = bb.min.z + (((bb.max.z - bb.min.z)/2));
Matrix matTranslate = MatrixTranslate(-center.x, 0, -center.z); Matrix matTranslate = MatrixTranslate(-center.x, 0, -center.z);
models[i].transform = matTranslate; models[i].transform = matTranslate;
} }
int currentModel = 0; int currentModel = 0;
Vector3 modelpos = { 0 };
Vector3 camerarot = { 0 };
// Load voxel shader // Load voxel shader
Shader shader = LoadShader(TextFormat("resources/shaders/glsl%i/voxel_lighting.vs", GLSL_VERSION), Shader shader = LoadShader(TextFormat("resources/shaders/glsl%i/voxel_lighting.vs", GLSL_VERSION),
TextFormat("resources/shaders/glsl%i/voxel_lighting.fs", GLSL_VERSION)); TextFormat("resources/shaders/glsl%i/voxel_lighting.fs", GLSL_VERSION));
// Get some required shader locations // Get some required shader locations
shader.locs[SHADER_LOC_VECTOR_VIEW] = GetShaderLocation(shader, "viewPos"); shader.locs[SHADER_LOC_VECTOR_VIEW] = GetShaderLocation(shader, "viewPos");
// NOTE: "matModel" location name is automatically assigned on shader loading, // NOTE: "matModel" location name is automatically assigned on shader loading,
// no need to get the location again if using that uniform name // no need to get the location again if using that uniform name
//shader.locs[SHADER_LOC_MATRIX_MODEL] = GetShaderLocation(shader, "matModel"); //shader.locs[SHADER_LOC_MATRIX_MODEL] = GetShaderLocation(shader, "matModel");
// Ambient light level (some basic lighting) // Ambient light level (some basic lighting)
int ambientLoc = GetShaderLocation(shader, "ambient"); int ambientLoc = GetShaderLocation(shader, "ambient");
SetShaderValue(shader, ambientLoc, (float[4]) { 0.1f, 0.1f, 0.1f, 1.0f }, SHADER_UNIFORM_VEC4); SetShaderValue(shader, ambientLoc, (float[4]) { 0.1f, 0.1f, 0.1f, 1.0f }, SHADER_UNIFORM_VEC4);
// Assign out lighting shader to model // Assign out lighting shader to model
for (int i = 0; i < MAX_VOX_FILES; i++) for (int i = 0; i < MAX_VOX_FILES; i++)
{ {
Model m = models[i]; for (int j = 0; j < models[i].materialCount; j++) models[i].materials[j].shader = shader;
for (int j = 0; j < m.materialCount; j++) }
{
m.materials[j].shader = shader;
}
}
// Create lights // Create lights
Light lights[MAX_LIGHTS] = { 0 }; Light lights[MAX_LIGHTS] = { 0 };
lights[0] = CreateLight(LIGHT_POINT, (Vector3) { -20, 20, -20 }, Vector3Zero(), GRAY, shader); lights[0] = CreateLight(LIGHT_POINT, (Vector3) { -20, 20, -20 }, Vector3Zero(), GRAY, shader);
lights[1] = CreateLight(LIGHT_POINT, (Vector3) { 20, -20, 20 }, Vector3Zero(), GRAY, shader); lights[1] = CreateLight(LIGHT_POINT, (Vector3) { 20, -20, 20 }, Vector3Zero(), GRAY, shader);
lights[2] = CreateLight(LIGHT_POINT, (Vector3) { -20, 20, 20 }, Vector3Zero(), GRAY, shader); lights[2] = CreateLight(LIGHT_POINT, (Vector3) { -20, 20, 20 }, Vector3Zero(), GRAY, shader);
lights[3] = CreateLight(LIGHT_POINT, (Vector3) { 20, -20, -20 }, Vector3Zero(), GRAY, shader); lights[3] = CreateLight(LIGHT_POINT, (Vector3) { 20, -20, -20 }, Vector3Zero(), GRAY, shader);
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
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
//----------------------------------------------------------------------------------
if (IsMouseButtonDown(MOUSE_BUTTON_MIDDLE))
{
const Vector2 mouseDelta = GetMouseDelta();
camerarot.x = mouseDelta.x*0.05f;
camerarot.y = mouseDelta.y*0.05f;
}
else
{
camerarot.x = 0;
camerarot.y = 0;
}
//-------------------------------------------------------------------------------------- UpdateCameraPro(&camera,
Vector3 modelpos = { 0 }; (Vector3){ (IsKeyDown(KEY_W) || IsKeyDown(KEY_UP))*0.1f - (IsKeyDown(KEY_S) || IsKeyDown(KEY_DOWN))*0.1f, // Move forward-backward
Vector3 camerarot = { 0 }; (IsKeyDown(KEY_D) || IsKeyDown(KEY_RIGHT))*0.1f - (IsKeyDown(KEY_A) || IsKeyDown(KEY_LEFT))*0.1f, // Move right-left
0.0f }, // Move up-down
camerarot, // Camera rotation
GetMouseWheelMove()*-2.0f); // Move to target (zoom)
// Main game loop // Cycle between models on mouse click
while (!WindowShouldClose()) // Detect window close button or ESC key if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) currentModel = (currentModel + 1)%MAX_VOX_FILES;
{
// Update
//----------------------------------------------------------------------------------
if (IsMouseButtonDown(MOUSE_BUTTON_MIDDLE))
{
const Vector2 mouseDelta = GetMouseDelta();
camerarot.x = mouseDelta.x*0.05f;
camerarot.y = mouseDelta.y*0.05f;
}
else
{
camerarot.x = 0;
camerarot.y = 0;
}
UpdateCameraPro(&camera, // Update the shader with the camera view vector (points towards { 0.0f, 0.0f, 0.0f })
(Vector3) { float cameraPos[3] = { camera.position.x, camera.position.y, camera.position.z };
(IsKeyDown(KEY_W) || IsKeyDown(KEY_UP))*0.1f - // Move forward-backward SetShaderValue(shader, shader.locs[SHADER_LOC_VECTOR_VIEW], cameraPos, SHADER_UNIFORM_VEC3);
(IsKeyDown(KEY_S) || IsKeyDown(KEY_DOWN))*0.1f,
(IsKeyDown(KEY_D) || IsKeyDown(KEY_RIGHT))*0.1f - // Move right-left
(IsKeyDown(KEY_A) || IsKeyDown(KEY_LEFT))*0.1f,
0.0f // Move up-down
},
camerarot,
GetMouseWheelMove()*-2.0f); // Move to target (zoom)
// Cycle between models on mouse click // Update light values (actually, only enable/disable them)
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) currentModel = (currentModel + 1) % MAX_VOX_FILES; for (int i = 0; i < MAX_LIGHTS; i++) UpdateLightValues(shader, lights[i]);
//----------------------------------------------------------------------------------
// Update the shader with the camera view vector (points towards { 0.0f, 0.0f, 0.0f }) // Draw
float cameraPos[3] = { camera.position.x, camera.position.y, camera.position.z }; //----------------------------------------------------------------------------------
SetShaderValue(shader, shader.locs[SHADER_LOC_VECTOR_VIEW], cameraPos, SHADER_UNIFORM_VEC3); BeginDrawing();
// Update light values (actually, only enable/disable them) ClearBackground(RAYWHITE);
for (int i = 0; i < MAX_LIGHTS; i++) UpdateLightValues(shader, lights[i]);
//---------------------------------------------------------------------------------- // Draw 3D model
// Draw BeginMode3D(camera);
//---------------------------------------------------------------------------------- DrawModel(models[currentModel], modelpos, 1.0f, WHITE);
BeginDrawing(); DrawGrid(10, 1.0);
ClearBackground(RAYWHITE); // Draw spheres to show where the lights are
for (int i = 0; i < MAX_LIGHTS; i++)
{
if (lights[i].enabled) DrawSphereEx(lights[i].position, 0.2f, 8, 8, lights[i].color);
else DrawSphereWires(lights[i].position, 0.2f, 8, 8, ColorAlpha(lights[i].color, 0.3f));
}
EndMode3D();
// Draw 3D model // Display info
BeginMode3D(camera); DrawRectangle(10, 40, 340, 70, Fade(SKYBLUE, 0.5f));
DrawRectangleLines(10, 40, 340, 70, Fade(DARKBLUE, 0.5f));
DrawText("- MOUSE LEFT BUTTON: CYCLE VOX MODELS", 20, 50, 10, BLUE);
DrawText("- MOUSE MIDDLE BUTTON: ZOOM OR ROTATE CAMERA", 20, 70, 10, BLUE);
DrawText("- UP-DOWN-LEFT-RIGHT KEYS: MOVE CAMERA", 20, 90, 10, BLUE);
DrawText(TextFormat("Model file: %s", GetFileName(voxFileNames[currentModel])), 10, 10, 20, GRAY);
DrawModel(models[currentModel], modelpos, 1.0f, WHITE); EndDrawing();
DrawGrid(10, 1.0); //----------------------------------------------------------------------------------
}
// Draw spheres to show where the lights are // De-Initialization
for (int i = 0; i < MAX_LIGHTS; i++) //--------------------------------------------------------------------------------------
{ // Unload models data (GPU VRAM)
if (lights[i].enabled) DrawSphereEx(lights[i].position, 0.2f, 8, 8, lights[i].color); for (int i = 0; i < MAX_VOX_FILES; i++) UnloadModel(models[i]);
else DrawSphereWires(lights[i].position, 0.2f, 8, 8, ColorAlpha(lights[i].color, 0.3f));
}
EndMode3D(); CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
// Display info return 0;
DrawRectangle(10, 400, 340, 60, Fade(SKYBLUE, 0.5f));
DrawRectangleLines(10, 400, 340, 60, Fade(DARKBLUE, 0.5f));
DrawText("MOUSE LEFT BUTTON to CYCLE VOX MODELS", 40, 410, 10, BLUE);
DrawText("MOUSE MIDDLE BUTTON to ZOOM OR ROTATE CAMERA", 40, 420, 10, BLUE);
DrawText("UP-DOWN-LEFT-RIGHT KEYS to MOVE CAMERA", 40, 430, 10, BLUE);
DrawText(TextFormat("File: %s", GetFileName(voxFileNames[currentModel])), 10, 10, 20, GRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
// Unload models data (GPU VRAM)
for (int i = 0; i < MAX_VOX_FILES; i++) UnloadModel(models[i]);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
} }

View File

@ -32,7 +32,7 @@ static Mesh GenMeshPoints(int numPoints);
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Program main entry point // Program main entry point
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
int main() int main(void)
{ {
// Initialization // Initialization
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
@ -57,7 +57,7 @@ int main()
Mesh mesh = GenMeshPoints(numPoints); Mesh mesh = GenMeshPoints(numPoints);
Model model = LoadModelFromMesh(mesh); Model model = LoadModelFromMesh(mesh);
//SetTargetFPS(60); SetTargetFPS(60);
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
// Main game loop // Main game loop
@ -92,15 +92,12 @@ int main()
// Draw // Draw
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
BeginDrawing(); BeginDrawing();
ClearBackground(BLACK); ClearBackground(BLACK);
BeginMode3D(camera); BeginMode3D(camera);
// The new method only uploads the points once to the GPU // The new method only uploads the points once to the GPU
if (useDrawModelPoints) if (useDrawModelPoints) DrawModelPoints(model, position, 1.0f, WHITE);
{
DrawModelPoints(model, position, 1.0f, WHITE);
}
else else
{ {
// The old method must continually draw the "points" (lines) // The old method must continually draw the "points" (lines)
@ -124,17 +121,16 @@ int main()
// Draw a unit sphere for reference // Draw a unit sphere for reference
DrawSphereWires(position, 1.0f, 10, 10, YELLOW); DrawSphereWires(position, 1.0f, 10, 10, YELLOW);
EndMode3D(); EndMode3D();
// Draw UI text // Draw UI text
DrawText(TextFormat("Point Count: %d", numPoints), 20, screenHeight - 50, 40, WHITE); DrawText(TextFormat("Point Count: %d", numPoints), 10, screenHeight - 50, 40, WHITE);
DrawText("Up - increase points", 20, 70, 20, WHITE); DrawText("UP - Increase points", 10, 40, 20, WHITE);
DrawText("Down - decrease points", 20, 100, 20, WHITE); DrawText("DOWN - Decrease points", 10, 70, 20, WHITE);
DrawText("Space - drawing function", 20, 130, 20, WHITE); DrawText("SPACE - Drawing function", 10, 100, 20, WHITE);
if (useDrawModelPoints) DrawText("Using: DrawModelPoints()", 20, 160, 20, GREEN); if (useDrawModelPoints) DrawText("Using: DrawModelPoints()", 10, 130, 20, GREEN);
else DrawText("Using: DrawPoint3D()", 20, 160, 20, RED); else DrawText("Using: DrawPoint3D()", 10, 130, 20, RED);
DrawFPS(10, 10); DrawFPS(10, 10);

View File

@ -54,7 +54,8 @@ int main(void)
Mesh cube = GenMeshCube(1.0f, 1.0f, 1.0f); Mesh cube = GenMeshCube(1.0f, 1.0f, 1.0f);
Model skybox = LoadModelFromMesh(cube); Model skybox = LoadModelFromMesh(cube);
// Set this to true to use an HDR Texture, Note that raylib must be built with HDR Support for this to work SUPPORT_FILEFORMAT_HDR // Set this to true to use an HDR Texture
// NOTE: raylib must be built with HDR Support for this to work: SUPPORT_FILEFORMAT_HDR
bool useHDR = false; bool useHDR = false;
// Load skybox shader and set required locations // Load skybox shader and set required locations
@ -63,8 +64,8 @@ int main(void)
TextFormat("resources/shaders/glsl%i/skybox.fs", GLSL_VERSION)); TextFormat("resources/shaders/glsl%i/skybox.fs", GLSL_VERSION));
SetShaderValue(skybox.materials[0].shader, GetShaderLocation(skybox.materials[0].shader, "environmentMap"), (int[1]){ MATERIAL_MAP_CUBEMAP }, SHADER_UNIFORM_INT); SetShaderValue(skybox.materials[0].shader, GetShaderLocation(skybox.materials[0].shader, "environmentMap"), (int[1]){ MATERIAL_MAP_CUBEMAP }, SHADER_UNIFORM_INT);
SetShaderValue(skybox.materials[0].shader, GetShaderLocation(skybox.materials[0].shader, "doGamma"), (int[1]) { useHDR ? 1 : 0 }, SHADER_UNIFORM_INT); SetShaderValue(skybox.materials[0].shader, GetShaderLocation(skybox.materials[0].shader, "doGamma"), (int[1]){ useHDR? 1 : 0 }, SHADER_UNIFORM_INT);
SetShaderValue(skybox.materials[0].shader, GetShaderLocation(skybox.materials[0].shader, "vflipped"), (int[1]){ useHDR ? 1 : 0 }, SHADER_UNIFORM_INT); SetShaderValue(skybox.materials[0].shader, GetShaderLocation(skybox.materials[0].shader, "vflipped"), (int[1]){ useHDR? 1 : 0 }, SHADER_UNIFORM_INT);
// Load cubemap shader and setup required shader locations // Load cubemap shader and setup required shader locations
Shader shdrCubemap = LoadShader(TextFormat("resources/shaders/glsl%i/cubemap.vs", GLSL_VERSION), Shader shdrCubemap = LoadShader(TextFormat("resources/shaders/glsl%i/cubemap.vs", GLSL_VERSION),
@ -91,9 +92,11 @@ int main(void)
} }
else else
{ {
Image img = LoadImage("resources/skybox.png"); // TODO: WARNING: On PLATFORM_WEB it requires a big amount of memory to process input image
skybox.materials[0].maps[MATERIAL_MAP_CUBEMAP].texture = LoadTextureCubemap(img, CUBEMAP_LAYOUT_AUTO_DETECT); // CUBEMAP_LAYOUT_PANORAMA // and generate the required cubemap image to be passed to rlLoadTextureCubemap()
UnloadImage(img); Image image = LoadImage("resources/skybox.png");
skybox.materials[0].maps[MATERIAL_MAP_CUBEMAP].texture = LoadTextureCubemap(image, CUBEMAP_LAYOUT_AUTO_DETECT);
UnloadImage(image);
} }
DisableCursor(); // Limit cursor to relative movement inside the window DisableCursor(); // Limit cursor to relative movement inside the window
@ -132,9 +135,9 @@ int main(void)
} }
else else
{ {
Image img = LoadImage(droppedFiles.paths[0]); Image image = LoadImage(droppedFiles.paths[0]);
skybox.materials[0].maps[MATERIAL_MAP_CUBEMAP].texture = LoadTextureCubemap(img, CUBEMAP_LAYOUT_AUTO_DETECT); skybox.materials[0].maps[MATERIAL_MAP_CUBEMAP].texture = LoadTextureCubemap(image, CUBEMAP_LAYOUT_AUTO_DETECT);
UnloadImage(img); UnloadImage(image);
} }
TextCopy(skyboxFileName, droppedFiles.paths[0]); TextCopy(skyboxFileName, droppedFiles.paths[0]);

View File

@ -22,7 +22,7 @@
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Program main entry point // Program main entry point
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
int main() int main(void)
{ {
// Initialization // Initialization
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------

View File

@ -0,0 +1,12 @@
# Blender MTL File: 'None'
# Material Count: 1
newmtl skin
Ns 86.470579
Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.800000 0.800000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 0.000000
illum 9

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -36,7 +36,7 @@ void UpdateDrawFrame(void); // Update and Draw one frame
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Program main entry point // Program main entry point
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
int main() int main(void)
{ {
// Initialization // Initialization
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------

5987
examples/shaders/raygui.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -11,3 +11,6 @@
| texel_checker.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | Made with [UV Checker Map Maker](http://uvchecker.byvalle.com/) | | texel_checker.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | Made with [UV Checker Map Maker](http://uvchecker.byvalle.com/) |
| cubicmap.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - | | cubicmap.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - |
| spark_flame.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | Made with [EffectTextureMaker](https://mebiusbox.github.io/contents/EffectTextureMaker/) | | spark_flame.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | Made with [EffectTextureMaker](https://mebiusbox.github.io/contents/EffectTextureMaker/) |
| parrots.png | [Kodak set](http://r0k.us/graphics/kodak/) | ❔ | Original name: `kodim23.png` |
| cat.png | ❔ | ❔ | - |
| mandrill.png | ❔ | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | Mandrill (a.k.a. Baboon) |

Binary file not shown.

After

Width:  |  Height:  |  Size: 379 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 KiB

View File

@ -0,0 +1,34 @@
#version 100
precision mediump float;
// Input vertex attributes (from vertex shader)
varying vec2 fragTexCoord;
varying vec4 fragColor;
// Input uniform values
uniform sampler2D texture0;
uniform vec4 colDiffuse;
uniform float contrast;
uniform float saturation;
uniform float brightness;
void main()
{
// Get texel color
vec4 texel = texture2D(texture0, fragTexCoord);
// Apply contrast
texel.rgb = (texel.rgb - 0.5)*(contrast/100.0 + 1.0) + 0.5;
// Apply brightness
texel.rgb = texel.rgb + brightness/100.0;
// Apply saturation
float intensity = dot(texel.rgb, vec3(0.299, 0.587, 0.114));
texel.rgb = (texel.rgb - intensity)*saturation/100.0 + texel.rgb;
// Output resulting color
gl_FragColor = texel;
}

View File

@ -1,6 +1,7 @@
#version 100 #version 100
#extension GL_EXT_frag_depth : enable // Extension required for writing depth #extension GL_EXT_frag_depth : enable // Extension required for writing depth
precision mediump float; // Precision required for OpenGL ES2 (WebGL) precision mediump float; // Precision required for OpenGL ES2 (WebGL)
varying vec2 fragTexCoord; varying vec2 fragTexCoord;

View File

@ -2,6 +2,9 @@
#extension GL_EXT_frag_depth : enable //Extension required for writing depth #extension GL_EXT_frag_depth : enable //Extension required for writing depth
#extension GL_OES_standard_derivatives : enable //Extension used for fwidth() #extension GL_OES_standard_derivatives : enable //Extension used for fwidth()
#define ZERO 0
precision mediump float; // Precision required for OpenGL ES2 (WebGL) precision mediump float; // Precision required for OpenGL ES2 (WebGL)
// Input vertex attributes (from vertex shader) // Input vertex attributes (from vertex shader)
@ -17,8 +20,6 @@ uniform vec3 camPos;
uniform vec3 camDir; uniform vec3 camDir;
uniform vec2 screenCenter; uniform vec2 screenCenter;
#define ZERO 0
// SRC: https://learnopengl.com/Advanced-OpenGL/Depth-testing // SRC: https://learnopengl.com/Advanced-OpenGL/Depth-testing
float CalcDepth(in vec3 rd, in float Idist) float CalcDepth(in vec3 rd, in float Idist)
{ {
@ -128,7 +129,7 @@ float calcSoftshadow(in vec3 ro, in vec3 rd, in float mint, in float tmax)
float res = 1.0; float res = 1.0;
float t = mint; float t = mint;
for (int i=ZERO; i<24; i++) for (int i = ZERO; i < 24; i++)
{ {
float h = map(ro + rd*t).x; float h = map(ro + rd*t).x;
float s = clamp(8.0*h/t,0.0,1.0); float s = clamp(8.0*h/t,0.0,1.0);
@ -156,7 +157,7 @@ float calcAO(in vec3 pos, in vec3 nor)
{ {
float occ = 0.0; float occ = 0.0;
float sca = 1.0; float sca = 1.0;
for (int i=ZERO; i<5; i++) for (int i = ZERO; i < 5; i++)
{ {
float h = 0.01 + 0.12*float(i)/4.0; float h = 0.01 + 0.12*float(i)/4.0;
float d = map(pos + h*nor).x; float d = map(pos + h*nor).x;
@ -257,7 +258,8 @@ vec4 render(in vec3 ro, in vec3 rd)
return vec4(vec3(clamp(col,0.0,1.0)),t); return vec4(vec3(clamp(col,0.0,1.0)),t);
} }
vec3 CalcRayDir(vec2 nCoord){ vec3 CalcRayDir(vec2 nCoord)
{
vec3 horizontal = normalize(cross(camDir,vec3(.0 , 1.0, .0))); vec3 horizontal = normalize(cross(camDir,vec3(.0 , 1.0, .0)));
vec3 vertical = normalize(cross(horizontal,camDir)); vec3 vertical = normalize(cross(horizontal,camDir));
return normalize(camDir + horizontal*nCoord.x + vertical*nCoord.y); return normalize(camDir + horizontal*nCoord.x + vertical*nCoord.y);
@ -287,6 +289,7 @@ void main()
color = res.xyz; color = res.xyz;
depth = CalcDepth(rd,res.w); depth = CalcDepth(rd,res.w);
} }
gl_FragColor = vec4(color , 1.0); gl_FragColor = vec4(color , 1.0);
gl_FragDepthEXT = depth; gl_FragDepthEXT = depth;
} }

View File

@ -1,9 +1,9 @@
#version 100 #version 100
precision mediump float;
#extension GL_OES_standard_derivatives : enable #extension GL_OES_standard_derivatives : enable
precision mediump float;
// Input vertex attributes (from vertex shader) // Input vertex attributes (from vertex shader)
varying vec2 fragTexCoord; varying vec2 fragTexCoord;
varying vec4 fragColor; varying vec4 fragColor;

View File

@ -0,0 +1,31 @@
#version 120
// Input vertex attributes (from vertex shader)
varying vec2 fragTexCoord;
varying vec4 fragColor;
// Input uniform values
uniform sampler2D texture0;
uniform vec4 colDiffuse;
uniform float contrast;
uniform float saturation;
uniform float brightness;
void main()
{
vec4 texel = texture2D(texture0, fragTexCoord); // Get texel color
// Apply contrast
texel.rgb = (texel.rgb - 0.5)*(contrast/100.0 + 1.0) + 0.5;
// Apply brightness
texel.rgb = texel.rgb + brightness/100.0;
// Apply saturation
float intensity = dot(texel.rgb, vec3(0.299, 0.587, 0.114));
texel.rgb = (texel.rgb - intensity)*saturation/100.0 + texel.rgb;
// Output resulting color
gl_FragColor = texel;
}

View File

@ -0,0 +1,34 @@
#version 330
// Input vertex attributes (from vertex shader)
in vec2 fragTexCoord;
in vec4 fragColor;
// Input uniform values
uniform sampler2D texture0;
uniform vec4 colDiffuse;
uniform float contrast;
uniform float saturation;
uniform float brightness;
// Output fragment color
out vec4 finalColor;
void main()
{
vec4 texel = texture(texture0, fragTexCoord); // Get texel color
// Apply contrast
texel.rgb = (texel.rgb - 0.5f)*(contrast/100.0f + 1.0f) + 0.5f;
// Apply brightness
texel.rgb = texel.rgb + brightness/100.0f;
// Apply saturation
float intensity = dot(texel.rgb, vec3(0.299f, 0.587f, 0.114f));
texel.rgb = (texel.rgb - intensity)*saturation/100.0f + texel.rgb;
// Output resulting color
finalColor = texel;
}

View File

@ -9,7 +9,7 @@ uniform sampler2D texture0;
uniform vec4 colDiffuse; uniform vec4 colDiffuse;
// Output fragment color // Output fragment color
//out vec4 finalColor; out vec4 finalColor;
// NOTE: Add your custom variables here // NOTE: Add your custom variables here
@ -17,6 +17,6 @@ void main()
{ {
vec4 texelColor = texture(texture0, fragTexCoord); vec4 texelColor = texture(texture0, fragTexCoord);
gl_FragColor = texelColor*colDiffuse*fragColor; finalColor = texelColor*colDiffuse*fragColor;
gl_FragDepth = gl_FragCoord.z; gl_FragDepth = finalColor.z;
} }

View File

@ -1,5 +1,7 @@
# version 330 # version 330
#define ZERO 0
// Input vertex attributes (from vertex shader) // Input vertex attributes (from vertex shader)
in vec2 fragTexCoord; in vec2 fragTexCoord;
in vec4 fragColor; in vec4 fragColor;
@ -13,10 +15,12 @@ uniform vec3 camPos;
uniform vec3 camDir; uniform vec3 camDir;
uniform vec2 screenCenter; uniform vec2 screenCenter;
#define ZERO 0 // Output fragment color
out vec4 finalColor;
// https://learnopengl.com/Advanced-OpenGL/Depth-testing // https://learnopengl.com/Advanced-OpenGL/Depth-testing
float CalcDepth(in vec3 rd, in float Idist){ float CalcDepth(in vec3 rd, in float Idist)
{
float local_z = dot(normalize(camDir),rd)*Idist; float local_z = dot(normalize(camDir),rd)*Idist;
return (1.0/(local_z) - 1.0/0.01)/(1.0/1000.0 -1.0/0.01); return (1.0/(local_z) - 1.0/0.01)/(1.0/1000.0 -1.0/0.01);
} }
@ -26,15 +30,13 @@ float sdHorseshoe(in vec3 p, in vec2 c, in float r, in float le, vec2 w)
{ {
p.x = abs(p.x); p.x = abs(p.x);
float l = length(p.xy); float l = length(p.xy);
p.xy = mat2(-c.x, c.y, p.xy = mat2(-c.x, c.y, c.y, c.x)*p.xy;
c.y, c.x)*p.xy; p.xy = vec2(((p.y > 0.0) || (p.x > 0.0))? p.x : l*sign(-c.x), (p.x>0.0)? p.y : l);
p.xy = vec2((p.y>0.0 || p.x>0.0)?p.x:l*sign(-c.x), p.xy = vec2(p.x, abs(p.y - r)) - vec2(le, 0.0);
(p.x>0.0)?p.y:l);
p.xy = vec2(p.x,abs(p.y-r))-vec2(le,0.0);
vec2 q = vec2(length(max(p.xy,0.0)) + min(0.0,max(p.x,p.y)),p.z); vec2 q = vec2(length(max(p.xy, 0.0)) + min(0.0, max(p.x, p.y)), p.z);
vec2 d = abs(q) - w; vec2 d = abs(q) - w;
return min(max(d.x,d.y),0.0) + length(max(d,0.0)); return min(max(d.x, d.y), 0.0) + length(max(d, 0.0));
} }
// r = sphere's radius // r = sphere's radius
@ -44,17 +46,16 @@ float sdSixWayCutHollowSphere(vec3 p, float r, float h, float t)
{ {
// Six way symetry Transformation // Six way symetry Transformation
vec3 ap = abs(p); vec3 ap = abs(p);
if (ap.x < max(ap.y, ap.z)){ if (ap.x < max(ap.y, ap.z))
{
if (ap.y < ap.z) ap.xz = ap.zx; if (ap.y < ap.z) ap.xz = ap.zx;
else ap.xy = ap.yx; else ap.xy = ap.yx;
} }
vec2 q = vec2(length(ap.yz), ap.x); vec2 q = vec2(length(ap.yz), ap.x);
float w = sqrt(r*r-h*h); float w = sqrt(r*r-h*h);
return ((h*q.x<w*q.y) ? length(q-vec2(w,h)) : return ((h*q.x < w*q.y)? length(q - vec2(w, h)) : abs(length(q) - r)) - t;
abs(length(q)-r)) - t;
} }
// https://iquilezles.org/articles/boxfunctions // https://iquilezles.org/articles/boxfunctions
@ -65,44 +66,47 @@ vec2 iBox(in vec3 ro, in vec3 rd, in vec3 rad)
vec3 k = abs(m)*rad; vec3 k = abs(m)*rad;
vec3 t1 = -n - k; vec3 t1 = -n - k;
vec3 t2 = -n + k; vec3 t2 = -n + k;
return vec2(max(max(t1.x, t1.y), t1.z),
min(min(t2.x, t2.y), t2.z)); return vec2(max(max(t1.x, t1.y), t1.z), min(min(t2.x, t2.y), t2.z));
} }
vec2 opU(vec2 d1, vec2 d2) vec2 opU(vec2 d1, vec2 d2)
{ {
return (d1.x<d2.x) ? d1 : d2; return (d1.x < d2.x)? d1 : d2;
} }
vec2 map(in vec3 pos){ vec2 map(in vec3 pos)
vec2 res = vec2(sdHorseshoe( pos-vec3(-1.0,0.08, 1.0), vec2(cos(1.3),sin(1.3)), 0.2, 0.3, vec2(0.03,0.5)), 11.5) ; {
res = opU(res, vec2(sdSixWayCutHollowSphere( pos-vec3(0.0, 1.0, 0.0), 4.0, 3.5, 0.5), 4.5)) ; vec2 res = vec2(sdHorseshoe(pos - vec3(-1.0, 0.08, 1.0), vec2(cos(1.3), sin(1.3)), 0.2, 0.3, vec2(0.03,0.5)), 11.5);
res = opU(res, vec2(sdSixWayCutHollowSphere(pos-vec3(0.0, 1.0, 0.0), 4.0, 3.5, 0.5), 4.5));
return res; return res;
} }
// https://www.shadertoy.com/view/Xds3zN // https://www.shadertoy.com/view/Xds3zN
vec2 raycast(in vec3 ro, in vec3 rd){ vec2 raycast(in vec3 ro, in vec3 rd)
vec2 res = vec2(-1.0,-1.0); {
vec2 res = vec2(-1.0, -1.0);
float tmin = 1.0; float tmin = 1.0;
float tmax = 20.0; float tmax = 20.0;
// raytrace floor plane // raytrace floor plane
float tp1 = (-ro.y)/rd.y; float tp1 = (-ro.y)/rd.y;
if (tp1>0.0) if (tp1 > 0.0)
{ {
tmax = min(tmax, tp1); tmax = min(tmax, tp1);
res = vec2(tp1, 1.0); res = vec2(tp1, 1.0);
} }
float t = tmin; float t = tmin;
for (int i=0; i<70 ; i++) for (int i = 0; i < 70 ; i++)
{ {
if (t>tmax) break; if (t > tmax) break;
vec2 h = map(ro+rd*t); vec2 h = map(ro + rd*t);
if (abs(h.x)<(0.0001*t)) if (abs(h.x )< (0.0001*t))
{ {
res = vec2(t,h.y); res = vec2(t, h.y);
break; break;
} }
t += h.x; t += h.x;
@ -111,28 +115,28 @@ vec2 raycast(in vec3 ro, in vec3 rd){
return res; return res;
} }
// https://iquilezles.org/articles/rmshadows // https://iquilezles.org/articles/rmshadows
float calcSoftshadow(in vec3 ro, in vec3 rd, in float mint, in float tmax) float calcSoftshadow(in vec3 ro, in vec3 rd, in float mint, in float tmax)
{ {
// bounding volume // bounding volume
float tp = (0.8-ro.y)/rd.y; if (tp>0.0) tmax = min(tmax, tp); float tp = (0.8 - ro.y)/rd.y; if (tp > 0.0) tmax = min(tmax, tp);
float res = 1.0; float res = 1.0;
float t = mint; float t = mint;
for (int i=ZERO; i<24; i++) for (int i = ZERO; i < 24; i++)
{ {
float h = map(ro + rd*t).x; float h = map(ro + rd*t).x;
float s = clamp(8.0*h/t,0.0,1.0); float s = clamp(8.0*h/t, 0.0, 1.0);
res = min(res, s); res = min(res, s);
t += clamp(h, 0.01, 0.2); t += clamp(h, 0.01, 0.2);
if (res<0.004 || t>tmax) break; if ((res < 0.004) || (t > tmax)) break;
} }
res = clamp(res, 0.0, 1.0); res = clamp(res, 0.0, 1.0);
return res*res*(3.0-2.0*res); return res*res*(3.0-2.0*res);
} }
// https://iquilezles.org/articles/normalsSDF // https://iquilezles.org/articles/normalsSDF
vec3 calcNormal(in vec3 pos) vec3 calcNormal(in vec3 pos)
{ {
@ -148,7 +152,7 @@ float calcAO(in vec3 pos, in vec3 nor)
{ {
float occ = 0.0; float occ = 0.0;
float sca = 1.0; float sca = 1.0;
for (int i=ZERO; i<5; i++) for (int i = ZERO; i < 5; i++)
{ {
float h = 0.01 + 0.12*float(i)/4.0; float h = 0.01 + 0.12*float(i)/4.0;
float d = map(pos + h*nor).x; float d = map(pos + h*nor).x;
@ -156,6 +160,7 @@ float calcAO(in vec3 pos, in vec3 nor)
sca *= 0.95; sca *= 0.95;
if (occ>0.35) break; if (occ>0.35) break;
} }
return clamp(1.0 - 3.0*occ, 0.0, 1.0)*(0.5+0.5*nor.y); return clamp(1.0 - 3.0*occ, 0.0, 1.0)*(0.5+0.5*nor.y);
} }
@ -165,9 +170,9 @@ float checkersGradBox(in vec2 p)
// filter kernel // filter kernel
vec2 w = fwidth(p) + 0.001; vec2 w = fwidth(p) + 0.001;
// analytical integral (box filter) // analytical integral (box filter)
vec2 i = 2.0*(abs(fract((p-0.5*w)*0.5)-0.5)-abs(fract((p+0.5*w)*0.5)-0.5))/w; vec2 i = 2.0*(abs(fract((p - 0.5*w)*0.5)-0.5) - abs(fract((p + 0.5*w)*0.5) - 0.5))/w;
// xor pattern // xor pattern
return 0.5 - 0.5*i.x*i.y; return (0.5 - 0.5*i.x*i.y);
} }
// https://www.shadertoy.com/view/tdS3DG // https://www.shadertoy.com/view/tdS3DG
@ -180,7 +185,7 @@ vec4 render(in vec3 ro, in vec3 rd)
vec2 res = raycast(ro,rd); vec2 res = raycast(ro,rd);
float t = res.x; float t = res.x;
float m = res.y; float m = res.y;
if (m>-0.5) if (m > -0.5)
{ {
vec3 pos = ro + t*rd; vec3 pos = ro + t*rd;
vec3 nor = (m<1.5) ? vec3(0.0,1.0,0.0) : calcNormal(pos); vec3 nor = (m<1.5) ? vec3(0.0,1.0,0.0) : calcNormal(pos);
@ -190,7 +195,7 @@ vec4 render(in vec3 ro, in vec3 rd)
col = 0.2 + 0.2*sin(m*2.0 + vec3(0.0,1.0,2.0)); col = 0.2 + 0.2*sin(m*2.0 + vec3(0.0,1.0,2.0));
float ks = 1.0; float ks = 1.0;
if (m<1.5) if (m < 1.5)
{ {
float f = checkersGradBox(3.0*pos.xz); float f = checkersGradBox(3.0*pos.xz);
col = 0.15 + f*vec3(0.05); col = 0.15 + f*vec3(0.05);
@ -207,14 +212,14 @@ vec4 render(in vec3 ro, in vec3 rd)
vec3 lig = normalize(vec3(-0.5, 0.4, -0.6)); vec3 lig = normalize(vec3(-0.5, 0.4, -0.6));
vec3 hal = normalize(lig-rd); vec3 hal = normalize(lig-rd);
float dif = clamp(dot(nor, lig), 0.0, 1.0); float dif = clamp(dot(nor, lig), 0.0, 1.0);
//if (dif>0.0001) //if (dif>0.0001)
dif *= calcSoftshadow(pos, lig, 0.02, 2.5); dif *= calcSoftshadow(pos, lig, 0.02, 2.5);
float spe = pow(clamp(dot(nor, hal), 0.0, 1.0),16.0); float spe = pow(clamp(dot(nor, hal), 0.0, 1.0),16.0);
spe *= dif; spe *= dif;
spe *= 0.04+0.96*pow(clamp(1.0-dot(hal,lig),0.0,1.0),5.0); spe *= 0.04+0.96*pow(clamp(1.0-dot(hal,lig),0.0,1.0),5.0);
//spe *= 0.04+0.96*pow(clamp(1.0-sqrt(0.5*(1.0-dot(rd,lig))),0.0,1.0),5.0); //spe *= 0.04+0.96*pow(clamp(1.0-sqrt(0.5*(1.0-dot(rd,lig))),0.0,1.0),5.0);
lin += col*2.20*dif*vec3(1.30,1.00,0.70); lin += col*2.20*dif*vec3(1.30,1.00,0.70);
lin += 5.00*spe*vec3(1.30,1.00,0.70)*ks; lin += 5.00*spe*vec3(1.30,1.00,0.70)*ks;
} }
// sky // sky
{ {
@ -249,7 +254,8 @@ vec4 render(in vec3 ro, in vec3 rd)
return vec4(vec3(clamp(col,0.0,1.0)),t); return vec4(vec3(clamp(col,0.0,1.0)),t);
} }
vec3 CalcRayDir(vec2 nCoord){ vec3 CalcRayDir(vec2 nCoord)
{
vec3 horizontal = normalize(cross(camDir,vec3(.0 , 1.0, .0))); vec3 horizontal = normalize(cross(camDir,vec3(.0 , 1.0, .0)));
vec3 vertical = normalize(cross(horizontal,camDir)); vec3 vertical = normalize(cross(horizontal,camDir));
return normalize(camDir + horizontal*nCoord.x + vertical*nCoord.y); return normalize(camDir + horizontal*nCoord.x + vertical*nCoord.y);
@ -279,6 +285,7 @@ void main()
color = res.xyz; color = res.xyz;
depth = CalcDepth(rd,res.w); depth = CalcDepth(rd,res.w);
} }
gl_FragColor = vec4(color , 1.0);
finalColor = vec4(color , 1.0);
gl_FragDepth = depth; gl_FragDepth = depth;
} }

View File

@ -77,7 +77,7 @@ static void UpdateLight(Shader shader, Light light);
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Program main entry point // Program main entry point
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
int main() int main(void)
{ {
// Initialization // Initialization
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
@ -254,9 +254,9 @@ int main()
{ {
Color lightColor = (Color){ Color lightColor = (Color){
(unsigned char)(lights[i].color[0]*255), (unsigned char)(lights[i].color[0]*255),
(unsigned char)(lights[i].color[1] * 255), (unsigned char)(lights[i].color[1]*255),
(unsigned char)(lights[i].color[2] * 255), (unsigned char)(lights[i].color[2]*255),
(unsigned char)(lights[i].color[3] * 255) }; (unsigned char)(lights[i].color[3]*255) };
if (lights[i].enabled) DrawSphereEx(lights[i].position, 0.2f, 8, 8, lightColor); if (lights[i].enabled) DrawSphereEx(lights[i].position, 0.2f, 8, 8, lightColor);
else DrawSphereWires(lights[i].position, 0.2f, 8, 8, ColorAlpha(lightColor, 0.3f)); else DrawSphereWires(lights[i].position, 0.2f, 8, 8, ColorAlpha(lightColor, 0.3f));

View File

@ -0,0 +1,148 @@
/*******************************************************************************************
*
* raylib [shaders] example - color correction
*
* Example complexity rating: [] 2/4
*
* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support,
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version
*
* Example originally created with raylib 5.6, last time updated with raylib 5.6
*
* Example contributed by Jordi Santonja (@JordSant) and reviewed by Ramon Santamaria (@raysan5)
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
* Copyright (c) 2025 Jordi Santonja (@JordSant)
*
********************************************************************************************/
#include "raylib.h"
#define RAYGUI_IMPLEMENTATION
#include "raygui.h" // Required for GUI controls
#if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330
#else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100
#endif
#define MAX_TEXTURES 4
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - color correction");
Texture2D texture[MAX_TEXTURES] = {
LoadTexture("resources/parrots.png"),
LoadTexture("resources/cat.png"),
LoadTexture("resources/mandrill.png"),
LoadTexture("resources/fudesumi.png")
};
Shader shdrColorCorrection = LoadShader(0, TextFormat("resources/shaders/glsl%i/color_correction.fs", GLSL_VERSION));
int imageIndex = 0;
int resetButtonClicked = 0;
float contrast = 0.0f;
float saturation = 0.0f;
float brightness = 0.0f;
// Get shader locations
int contrastLoc = GetShaderLocation(shdrColorCorrection, "contrast");
int saturationLoc = GetShaderLocation(shdrColorCorrection, "saturation");
int brightnessLoc = GetShaderLocation(shdrColorCorrection, "brightness");
// Set shader values (they can be changed later)
SetShaderValue(shdrColorCorrection, contrastLoc, &contrast, SHADER_UNIFORM_FLOAT);
SetShaderValue(shdrColorCorrection, saturationLoc, &saturation, SHADER_UNIFORM_FLOAT);
SetShaderValue(shdrColorCorrection, brightnessLoc, &brightness, SHADER_UNIFORM_FLOAT);
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
//----------------------------------------------------------------------------------
// Select texture to draw
if (IsKeyPressed(KEY_ONE)) imageIndex = 0;
else if (IsKeyPressed(KEY_TWO)) imageIndex = 1;
else if (IsKeyPressed(KEY_THREE)) imageIndex = 2;
else if (IsKeyPressed(KEY_FOUR)) imageIndex = 3;
// Reset values to 0
if (IsKeyPressed(KEY_R) || resetButtonClicked)
{
contrast = 0.0f;
saturation = 0.0f;
brightness = 0.0f;
}
// Send the values to the shader
SetShaderValue(shdrColorCorrection, contrastLoc, &contrast, SHADER_UNIFORM_FLOAT);
SetShaderValue(shdrColorCorrection, saturationLoc, &saturation, SHADER_UNIFORM_FLOAT);
SetShaderValue(shdrColorCorrection, brightnessLoc, &brightness, SHADER_UNIFORM_FLOAT);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginShaderMode(shdrColorCorrection);
DrawTexture(texture[imageIndex], 580/2 - texture[imageIndex].width/2, GetScreenHeight()/2 - texture[imageIndex].height/2, WHITE);
EndShaderMode();
DrawLine(580, 0, 580, GetScreenHeight(), (Color){ 218, 218, 218, 255 });
DrawRectangle(580, 0, GetScreenWidth(), GetScreenHeight(), (Color){ 232, 232, 232, 255 });
// Draw UI info text
DrawText("Color Correction", 585, 40, 20, GRAY);
DrawText("Picture", 602, 75, 10, GRAY);
DrawText("Press [1] - [4] to Change Picture", 600, 230, 8, GRAY);
DrawText("Press [R] to Reset Values", 600, 250, 8, GRAY);
// Draw GUI controls
//------------------------------------------------------------------------------
GuiToggleGroup((Rectangle){ 645, 70, 20, 20 }, "1;2;3;4", &imageIndex);
GuiSliderBar((Rectangle){ 645, 100, 120, 20 }, "Contrast", TextFormat("%.0f", contrast), &contrast, -100.0f, 100.0f);
GuiSliderBar((Rectangle){ 645, 130, 120, 20 }, "Saturation", TextFormat("%.0f", saturation), &saturation, -100.0f, 100.0f);
GuiSliderBar((Rectangle){ 645, 160, 120, 20 }, "Brightness", TextFormat("%.0f", brightness), &brightness, -100.0f, 100.0f);
resetButtonClicked = GuiButton((Rectangle){ 645, 190, 40, 20 }, "Reset");
//------------------------------------------------------------------------------
DrawFPS(710, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
for (int i = 0; i < MAX_TEXTURES; i++) UnloadTexture(texture[i]);
UnloadShader(shdrColorCorrection);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 KiB

View File

@ -118,7 +118,7 @@ int main(void)
// Raymarch Scene // Raymarch Scene
rlEnableDepthTest(); // Manually enable Depth Test to handle multiple rendering methods rlEnableDepthTest(); // Manually enable Depth Test to handle multiple rendering methods
BeginShaderMode(shdrRaymarch); BeginShaderMode(shdrRaymarch);
DrawRectangleRec((Rectangle){0,0, (float)screenWidth, (float)screenHeight},WHITE); DrawRectangleRec((Rectangle){ 0,0, (float)screenWidth, (float)screenHeight },WHITE);
EndShaderMode(); EndShaderMode();
// Rasterize Scene // Rasterize Scene
@ -138,6 +138,7 @@ int main(void)
ClearBackground(RAYWHITE); ClearBackground(RAYWHITE);
DrawTextureRec(target.texture, (Rectangle) { 0, 0, (float)screenWidth, (float)-screenHeight }, (Vector2) { 0, 0 }, WHITE); DrawTextureRec(target.texture, (Rectangle) { 0, 0, (float)screenWidth, (float)-screenHeight }, (Vector2) { 0, 0 }, WHITE);
DrawFPS(10, 10); DrawFPS(10, 10);
EndDrawing(); EndDrawing();
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------

View File

@ -33,7 +33,7 @@
#define GLSL_VERSION 100 #define GLSL_VERSION 100
#endif #endif
#define MAP_SIZE 10 #define MAP_SIZE 16
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Program main entry point // Program main entry point
@ -88,8 +88,6 @@ int main(void)
RenderTexture lightmap = LoadRenderTexture(MAP_SIZE, MAP_SIZE); RenderTexture lightmap = LoadRenderTexture(MAP_SIZE, MAP_SIZE);
SetTextureFilter(lightmap.texture, TEXTURE_FILTER_TRILINEAR);
Material material = LoadMaterialDefault(); Material material = LoadMaterialDefault();
material.shader = shader; material.shader = shader;
material.maps[MATERIAL_MAP_ALBEDO].texture = texture; material.maps[MATERIAL_MAP_ALBEDO].texture = texture;
@ -103,30 +101,34 @@ int main(void)
DrawTexturePro( DrawTexturePro(
light, light,
(Rectangle){ 0, 0, (float)light.width, (float)light.height }, (Rectangle){ 0, 0, (float)light.width, (float)light.height },
(Rectangle){ 0, 0, 20, 20 }, (Rectangle){ 0, 0, 2.0f*MAP_SIZE, 2.0f*MAP_SIZE },
(Vector2){ 10.0, 10.0 }, (Vector2){ (float)MAP_SIZE, (float)MAP_SIZE },
0.0, 0.0,
RED RED
); );
DrawTexturePro( DrawTexturePro(
light, light,
(Rectangle){ 0, 0, (float)light.width, (float)light.height }, (Rectangle){ 0, 0, (float)light.width, (float)light.height },
(Rectangle){ 8, 4, 20, 20 }, (Rectangle){ (float)MAP_SIZE*0.8f, (float)MAP_SIZE/2.0f, 2.0f*MAP_SIZE, 2.0f*MAP_SIZE },
(Vector2){ 10.0, 10.0 }, (Vector2){ (float)MAP_SIZE, (float)MAP_SIZE },
0.0, 0.0,
BLUE BLUE
); );
DrawTexturePro( DrawTexturePro(
light, light,
(Rectangle){ 0, 0, (float)light.width, (float)light.height }, (Rectangle){ 0, 0, (float)light.width, (float)light.height },
(Rectangle){ 8, 8, 10, 10 }, (Rectangle){ (float)MAP_SIZE*0.8f, (float)MAP_SIZE*0.8f, (float)MAP_SIZE, (float)MAP_SIZE },
(Vector2){ 5.0, 5.0 }, (Vector2){ (float)MAP_SIZE/2.0f, (float)MAP_SIZE/2.0f },
0.0, 0.0,
GREEN GREEN
); );
BeginBlendMode(BLEND_ALPHA); BeginBlendMode(BLEND_ALPHA);
EndTextureMode(); EndTextureMode();
// NOTE: To enable trilinear filtering we need mipmaps available for texture
GenTextureMipmaps(&lightmap.texture);
SetTextureFilter(lightmap.texture, TEXTURE_FILTER_TRILINEAR);
SetTargetFPS(60); // Set our game to run at 60 frames-per-second SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
@ -141,24 +143,20 @@ int main(void)
// Draw // Draw
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
BeginDrawing(); BeginDrawing();
ClearBackground(RAYWHITE); ClearBackground(RAYWHITE);
BeginMode3D(camera); BeginMode3D(camera);
DrawMesh(mesh, material, MatrixIdentity()); DrawMesh(mesh, material, MatrixIdentity());
EndMode3D(); EndMode3D();
DrawFPS(10, 10); DrawTexturePro(lightmap.texture, (Rectangle){ 0, 0, -MAP_SIZE, -MAP_SIZE },
DrawTexturePro(
lightmap.texture,
(Rectangle){ 0, 0, -MAP_SIZE, -MAP_SIZE },
(Rectangle){ (float)GetRenderWidth() - MAP_SIZE*8 - 10, 10, (float)MAP_SIZE*8, (float)MAP_SIZE*8 }, (Rectangle){ (float)GetRenderWidth() - MAP_SIZE*8 - 10, 10, (float)MAP_SIZE*8, (float)MAP_SIZE*8 },
(Vector2){ 0.0, 0.0 }, (Vector2){ 0.0, 0.0 }, 0.0, WHITE);
0.0,
WHITE);
DrawText("lightmap", GetRenderWidth() - 66, 16 + MAP_SIZE*8, 10, GRAY); DrawText(TextFormat("LIGHTMAP: %ix%i pixels", MAP_SIZE, MAP_SIZE), GetRenderWidth() - 130, 20 + MAP_SIZE*8, 10, GREEN);
DrawText("10x10 pixels", GetRenderWidth() - 76, 30 + MAP_SIZE*8, 10, GRAY);
DrawFPS(10, 10);
EndDrawing(); EndDrawing();
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------

View File

@ -69,7 +69,7 @@ int main(void)
float offset[2] = { startingOffset[0], startingOffset[1] }; float offset[2] = { startingOffset[0], startingOffset[1] };
float zoom = startingZoom; float zoom = startingZoom;
// Depending on the zoom the mximum number of iterations must be adapted to get more detail as we zzoom in // Depending on the zoom the mximum number of iterations must be adapted to get more detail as we zzoom in
// The solution is not perfect, so a control has been added to increase/decrease the number of iterations with UP/DOWN keys // The solution is not perfect, so a control has been added to increase/decrease the number of iterations with UP/DOWN keys
#if defined(PLATFORM_DESKTOP) #if defined(PLATFORM_DESKTOP)
int maxIterations = 333; int maxIterations = 333;
float maxIterationsMultiplier = 166.5f; float maxIterationsMultiplier = 166.5f;
@ -134,8 +134,8 @@ int main(void)
if (IsKeyPressed(KEY_F1)) showControls = !showControls; // Toggle whether or not to show controls if (IsKeyPressed(KEY_F1)) showControls = !showControls; // Toggle whether or not to show controls
// Change number of max iterations with UP and DOWN keys // Change number of max iterations with UP and DOWN keys
// WARNING: Increasing the number of max iterations greatly impacts performance // WARNING: Increasing the number of max iterations greatly impacts performance
if (IsKeyPressed(KEY_UP)) if (IsKeyPressed(KEY_UP))
{ {
maxIterationsMultiplier *= 1.4f; maxIterationsMultiplier *= 1.4f;
@ -167,10 +167,10 @@ int main(void)
updateShader = true; updateShader = true;
} }
// In case a parameter has been changed, update the shader values // In case a parameter has been changed, update the shader values
if (updateShader) if (updateShader)
{ {
// As we zoom in, increase the number of max iterations to get more detail // As we zoom in, increase the number of max iterations to get more detail
// Aproximate formula, but it works-ish // Aproximate formula, but it works-ish
maxIterations = (int)(sqrtf(2.0f*sqrtf(fabsf(1.0f - sqrtf(37.5f*zoom))))*maxIterationsMultiplier); maxIterations = (int)(sqrtf(2.0f*sqrtf(fabsf(1.0f - sqrtf(37.5f*zoom))))*maxIterationsMultiplier);

File diff suppressed because it is too large Load Diff

View File

@ -107,7 +107,7 @@ int main(void)
float bulletDirection = baseDirection + (degreesPerRow*row); float bulletDirection = baseDirection + (degreesPerRow*row);
// Bullet speed * bullet direction, this will determine how much pixels will be incremented/decremented // Bullet speed*bullet direction, this will determine how much pixels will be incremented/decremented
// from the bullet position every frame. Since the bullets doesn't change its direction and speed, // from the bullet position every frame. Since the bullets doesn't change its direction and speed,
// only need to calculate it at the spawning time // only need to calculate it at the spawning time
// 0 degrees = right, 90 degrees = down, 180 degrees = left and 270 degrees = up, basically clockwise // 0 degrees = right, 90 degrees = down, 180 degrees = left and 270 degrees = up, basically clockwise

View File

@ -60,24 +60,16 @@ int main(void)
/* 8 */ { TL,HH,HH,TR, /* */ VV,TL,TR,VV,/* */ VV,BL,BR,VV,/* */ VV,TL,TR,VV,/* */ VV,BL,BR,VV,/* */ BL,HH,HH,BR }, /* 8 */ { TL,HH,HH,TR, /* */ VV,TL,TR,VV,/* */ VV,BL,BR,VV,/* */ VV,TL,TR,VV,/* */ VV,BL,BR,VV,/* */ BL,HH,HH,BR },
/* 9 */ { TL,HH,HH,TR, /* */ VV,TL,TR,VV,/* */ VV,BL,BR,VV,/* */ BL,HH,TR,VV,/* */ TL,HH,BR,VV,/* */ BL,HH,HH,BR }, /* 9 */ { TL,HH,HH,TR, /* */ VV,TL,TR,VV,/* */ VV,BL,BR,VV,/* */ BL,HH,TR,VV,/* */ TL,HH,BR,VV,/* */ BL,HH,HH,BR },
}; };
// Time for the hands to move to the new position (in seconds); this must be <1s // Time for the hands to move to the new position (in seconds); this must be <1s
const float handsMoveDuration = .5f; const float handsMoveDuration = 0.5f;
// We store the previous seconds value so we can see if the time has changed
int prevSeconds = -1; int prevSeconds = -1;
// This represents the real position where the hands are right now
Vector2 currentAngles[6][24] = { 0 }; Vector2 currentAngles[6][24] = { 0 };
// This is the position where the hands were moving from
Vector2 srcAngles[6][24] = { 0 }; Vector2 srcAngles[6][24] = { 0 };
// This is the position where the hands are moving to
Vector2 dstAngles[6][24] = { 0 }; Vector2 dstAngles[6][24] = { 0 };
// Current animation timer
float handsMoveTimer = 0.0f; float handsMoveTimer = 0.0f;
// 12 or 24 hour mode
int hourMode = 24; int hourMode = 24;
SetTargetFPS(60); // Set our game to run at 60 frames-per-second SetTargetFPS(60); // Set our game to run at 60 frames-per-second
@ -88,7 +80,6 @@ int main(void)
{ {
// Update // Update
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Get the current time // Get the current time
time_t rawtime; time_t rawtime;
struct tm *timeinfo; struct tm *timeinfo;
@ -96,30 +87,26 @@ int main(void)
time(&rawtime); time(&rawtime);
timeinfo = localtime(&rawtime); timeinfo = localtime(&rawtime);
if (timeinfo->tm_sec != prevSeconds) { if (timeinfo->tm_sec != prevSeconds)
{
// The time has changed, so we need to move the hands to the new positions // The time has changed, so we need to move the hands to the new positions
prevSeconds = timeinfo->tm_sec; prevSeconds = timeinfo->tm_sec;
// Format the current time so we can access the individual digits // Format the current time so we can access the individual digits
const char *clockDigits = TextFormat("%02d%02d%02d", timeinfo->tm_hour % hourMode, timeinfo->tm_min, timeinfo->tm_sec); const char *clockDigits = TextFormat("%02d%02d%02d", timeinfo->tm_hour%hourMode, timeinfo->tm_min, timeinfo->tm_sec);
// Fetch where we want all the hands to be // Fetch where we want all the hands to be
for (int digit = 0; digit < 6; digit++) { for (int digit = 0; digit < 6; digit++)
for (int cell = 0; cell < 24; cell++) { {
for (int cell = 0; cell < 24; cell++)
{
srcAngles[digit][cell] = currentAngles[digit][cell]; srcAngles[digit][cell] = currentAngles[digit][cell];
dstAngles[digit][cell] = digitAngles[ clockDigits[digit] - '0' ][cell]; dstAngles[digit][cell] = digitAngles[clockDigits[digit] - '0'][cell];
// Quick exception for 12h mode // Quick exception for 12h mode
if (digit == 0 && hourMode == 12 && clockDigits[0] == '0') { if ((digit == 0) && (hourMode == 12) && (clockDigits[0] == '0')) dstAngles[digit][cell] = ZZ;
dstAngles[digit][cell] = ZZ; if (srcAngles[digit][cell].x > dstAngles[digit][cell].x) srcAngles[digit][cell].x -= 360.0f;
} if (srcAngles[digit][cell].y > dstAngles[digit][cell].y) srcAngles[digit][cell].y -= 360.0f;
if (srcAngles[digit][cell].x > dstAngles[digit][cell].x) {
srcAngles[digit][cell].x -= 360.0f;
}
if (srcAngles[digit][cell].y > dstAngles[digit][cell].y) {
srcAngles[digit][cell].y -= 360.0f;
}
} }
} }
@ -128,37 +115,29 @@ int main(void)
} }
// Now let's animate all the hands if we need to // Now let's animate all the hands if we need to
if (handsMoveTimer < handsMoveDuration) { if (handsMoveTimer < handsMoveDuration)
{
// Increase the timer but don't go above the maximum // Increase the timer but don't go above the maximum
handsMoveTimer = Clamp(handsMoveTimer + GetFrameTime(), 0, handsMoveDuration); handsMoveTimer = Clamp(handsMoveTimer + GetFrameTime(), 0, handsMoveDuration);
// Calculate the % completion of the animation // Calculate the%completion of the animation
float t = handsMoveTimer / handsMoveDuration; float t = handsMoveTimer/handsMoveDuration;
// A little cheeky smoothstep // A little cheeky smoothstep
t = t * t * (3.0f - 2.0f * t); t = t*t*(3.0f - 2.0f*t);
for (int digit = 0; digit < 6; digit++) { for (int digit = 0; digit < 6; digit++)
for (int cell = 0; cell < 24; cell++) { {
for (int cell = 0; cell < 24; cell++)
{
currentAngles[digit][cell].x = Lerp(srcAngles[digit][cell].x, dstAngles[digit][cell].x, t); currentAngles[digit][cell].x = Lerp(srcAngles[digit][cell].x, dstAngles[digit][cell].x, t);
currentAngles[digit][cell].y = Lerp(srcAngles[digit][cell].y, dstAngles[digit][cell].y, t); currentAngles[digit][cell].y = Lerp(srcAngles[digit][cell].y, dstAngles[digit][cell].y, t);
} }
} }
if (handsMoveTimer == handsMoveDuration) {
// The animation has now finished
}
} }
// Handle input // Handle input
if (IsKeyPressed(KEY_SPACE)) hourMode = 36 - hourMode; // Toggle between 12 and 24 hour mode with space
// Toggle between 12 and 24 hour mode with space
if (IsKeyPressed(KEY_SPACE)) {
hourMode = 36 - hourMode;
}
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Draw // Draw
@ -171,19 +150,22 @@ int main(void)
float xOffset = 4.0f; float xOffset = 4.0f;
for (int digit = 0; digit < 6; digit++) { for (int digit = 0; digit < 6; digit++)
{
for (int row = 0; row < 6; row++) { for (int row = 0; row < 6; row++)
for (int col = 0; col < 4; col++) { {
for (int col = 0; col < 4; col++)
{
Vector2 centre = (Vector2){ Vector2 centre = (Vector2){
xOffset + col*(clockFaceSize+clockFaceSpacing) + clockFaceSize * .5f, xOffset + col*(clockFaceSize+clockFaceSpacing) + clockFaceSize*0.5f,
100 + row*(clockFaceSize+clockFaceSpacing) + clockFaceSize * .5f 100 + row*(clockFaceSize+clockFaceSpacing) + clockFaceSize*0.5f
}; };
DrawRing(centre, clockFaceSize * 0.5f - 2.0f, clockFaceSize * 0.5f, 0, 360, 24, DARKGRAY);
DrawRing(centre, clockFaceSize*0.5f - 2.0f, clockFaceSize*0.5f, 0, 360, 24, DARKGRAY);
// Big hand // Big hand
DrawRectanglePro( DrawRectanglePro(
(Rectangle){centre.x, centre.y, clockFaceSize*.5f+4.0f, 4.0f}, (Rectangle){centre.x, centre.y, clockFaceSize*0.5f+4.0f, 4.0f},
(Vector2){ 2.0f, 2.0f }, (Vector2){ 2.0f, 2.0f },
currentAngles[digit][row*4+col].x, currentAngles[digit][row*4+col].x,
handsColor handsColor
@ -191,7 +173,7 @@ int main(void)
// Little hand // Little hand
DrawRectanglePro( DrawRectanglePro(
(Rectangle){centre.x, centre.y, clockFaceSize*.5f+2.0f, 4.0f}, (Rectangle){centre.x, centre.y, clockFaceSize*0.5f+2.0f, 4.0f},
(Vector2){ 2.0f, 2.0f }, (Vector2){ 2.0f, 2.0f },
currentAngles[digit][row*4+col].y, currentAngles[digit][row*4+col].y,
handsColor handsColor
@ -199,27 +181,23 @@ int main(void)
} }
} }
xOffset += (clockFaceSize+clockFaceSpacing) * 4; xOffset += (clockFaceSize+clockFaceSpacing)*4;
if (digit % 2 == 1) { if (digit%2 == 1)
{
DrawRing((Vector2){xOffset + 4.0f, 160.0f}, 6.0f, 8.0f, 0.0f, 360.0f, 24, handsColor); DrawRing((Vector2){xOffset + 4.0f, 160.0f}, 6.0f, 8.0f, 0.0f, 360.0f, 24, handsColor);
DrawRing((Vector2){xOffset + 4.0f, 225.0f}, 6.0f, 8.0f, 0.0f, 360.0f, 24, handsColor); DrawRing((Vector2){xOffset + 4.0f, 225.0f}, 6.0f, 8.0f, 0.0f, 360.0f, 24, handsColor);
xOffset += sectionSpacing; xOffset += sectionSpacing;
} }
} }
DrawFPS(10, 10); DrawFPS(10, 10);
EndDrawing(); EndDrawing();
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
} }
// De-Initialization // De-Initialization
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context CloseWindow(); // Close window and OpenGL context
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------

View File

@ -284,11 +284,13 @@ static void DrawDisplaySegment(Vector2 center, int length, int thick, bool verti
if (!vertical) if (!vertical)
{ {
// Horizontal segment points // Horizontal segment points
// 3___________________________5 /*
// / \ 3___________________________5
// /1 x 6\ / \
// \ / /1 x 6\
// \2___________________________4/ \ /
\2___________________________4/
*/
Vector2 segmentPointsH[6] = { Vector2 segmentPointsH[6] = {
(Vector2){ center.x - length/2.0f - thick/2.0f, center.y }, // Point 1 (Vector2){ center.x - length/2.0f - thick/2.0f, center.y }, // Point 1
(Vector2){ center.x - length/2.0f, center.y + thick/2.0f }, // Point 2 (Vector2){ center.x - length/2.0f, center.y + thick/2.0f }, // Point 2

View File

@ -76,7 +76,7 @@ int main(void)
float step = dt/SIMULATION_STEPS, step2 = step*step; float step = dt/SIMULATION_STEPS, step2 = step*step;
// Update Physics - larger steps = better approximation // Update Physics - larger steps = better approximation
for (int i = 0; i < SIMULATION_STEPS; ++i) for (int i = 0; i < SIMULATION_STEPS; i++)
{ {
float delta = theta1 - theta2; float delta = theta1 - theta2;
float sinD = sinf(delta), cosD = cosf(delta), cos2D = cosf(2*delta); float sinD = sinf(delta), cosD = cosf(delta), cos2D = cosf(2*delta);

View File

@ -11,13 +11,29 @@
* 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
* *
* Copyright (c) 2025 Hugo ARNAL (@hugoarnal) * Copyright (c) 2025 Hugo ARNAL (@hugoarnal) and Ramon Santamaria (@raysan5)
* *
********************************************************************************************/ ********************************************************************************************/
#include "raylib.h" #include "raylib.h"
#include <string.h>
#define RAYGUI_IMPLEMENTATION
#include "raygui.h"
#include "raymath.h" #include "raymath.h"
#define MAX_DRAW_LINES 8192
// Line data type
typedef struct {
Vector2 start;
Vector2 end;
} Line;
// Lines array as a global static variable to be stored
// in heap and avoid potential stack overflow (on Web platform)
static Line lines[MAX_DRAW_LINES] = { 0 };
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Program main entry point // Program main entry point
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
@ -30,22 +46,31 @@ int main(void)
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - kaleidoscope"); InitWindow(screenWidth, screenHeight, "raylib [shapes] example - kaleidoscope");
// Line drawing properties
int symmetry = 6; int symmetry = 6;
float angle = 360.0f/(float)symmetry; float angle = 360.0f/(float)symmetry;
float thickness = 3.0f; float thickness = 3.0f;
Rectangle resetButtonRec = { screenWidth - 55, 5, 50, 25 };
Rectangle backButtonRec = { screenWidth - 55, screenHeight - 30, 25, 25 };
Rectangle nextButtonRec = { screenWidth - 30, screenHeight - 30, 25, 25 };
Vector2 mousePos = { 0 };
Vector2 prevMousePos = { 0 }; Vector2 prevMousePos = { 0 };
Vector2 scaleVector = { 1.0f, -1.0f };
SetTargetFPS(60);
ClearBackground(BLACK);
Vector2 offset = { (float)screenWidth/2.0f, (float)screenHeight/2.0f }; Vector2 offset = { (float)screenWidth/2.0f, (float)screenHeight/2.0f };
Camera2D camera = { 0 }; Camera2D camera = { 0 };
camera.target = (Vector2){ 0 }; camera.target = (Vector2){ 0 };
camera.offset = offset; camera.offset = offset;
camera.rotation = 0.0f; camera.rotation = 0.0f;
camera.zoom = 1.0f; camera.zoom = 1.0f;
Vector2 scaleVector = { 1.0f, -1.0f }; int currentLineCounter = 0;
int totalLineCounter = 0;
int resetButtonClicked = false;
int backButtonClicked = false;
int nextButtonClicked = false;
SetTargetFPS(20);
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
// Main game loop // Main game loop
@ -53,38 +78,93 @@ int main(void)
{ {
// Update // Update
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
Vector2 mousePos = GetMousePosition(); prevMousePos = mousePos;
mousePos = GetMousePosition();
Vector2 lineStart = Vector2Subtract(mousePos, offset); Vector2 lineStart = Vector2Subtract(mousePos, offset);
Vector2 lineEnd = Vector2Subtract(prevMousePos, offset); Vector2 lineEnd = Vector2Subtract(prevMousePos, offset);
if (
IsMouseButtonDown(MOUSE_LEFT_BUTTON)
&& (CheckCollisionPointRec(mousePos, resetButtonRec) == false)
&& (CheckCollisionPointRec(mousePos, backButtonRec) == false)
&& (CheckCollisionPointRec(mousePos, nextButtonRec) == false)
)
{
for (int s = 0; (s < symmetry) && (totalLineCounter < (MAX_DRAW_LINES - 1)); s++)
{
lineStart = Vector2Rotate(lineStart, angle*DEG2RAD);
lineEnd = Vector2Rotate(lineEnd, angle*DEG2RAD);
// Store mouse line
lines[totalLineCounter].start = lineStart;
lines[totalLineCounter].end = lineEnd;
// Store reflective line
lines[totalLineCounter + 1].start = Vector2Multiply(lineStart, scaleVector);
lines[totalLineCounter + 1].end = Vector2Multiply(lineEnd, scaleVector);
totalLineCounter += 2;
currentLineCounter = totalLineCounter;
}
}
if (resetButtonClicked)
{
memset(&lines, 0, sizeof(Line)*MAX_DRAW_LINES);
currentLineCounter = 0;
totalLineCounter = 0;
}
if (backButtonClicked && (currentLineCounter > 0))
{
currentLineCounter -= 1;
}
if (nextButtonClicked && (currentLineCounter < MAX_DRAW_LINES) && ((currentLineCounter + 1) <= totalLineCounter))
{
currentLineCounter += 1;
}
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Draw // Draw
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
BeginDrawing(); BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode2D(camera); BeginMode2D(camera);
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) {
for (int i = 0; i < symmetry; i++) {
lineStart = Vector2Rotate(lineStart, angle*DEG2RAD);
lineEnd = Vector2Rotate(lineEnd, angle*DEG2RAD);
DrawLineEx(lineStart, lineEnd, thickness, WHITE); for (int s = 0; s < symmetry; s++)
{
Vector2 reflectLineStart = Vector2Multiply(lineStart, scaleVector); for (int i = 0; i < currentLineCounter; i += 2)
Vector2 reflectLineEnd = Vector2Multiply(lineEnd, scaleVector); {
DrawLineEx(lines[i].start, lines[i].end, thickness, BLACK);
DrawLineEx(reflectLineStart, reflectLineEnd, thickness, WHITE); DrawLineEx(lines[i + 1].start, lines[i + 1].end, thickness, BLACK);
} }
} }
prevMousePos = mousePos;
EndMode2D(); EndMode2D();
if ((currentLineCounter - 1) < 0) GuiDisable();
backButtonClicked = GuiButton(backButtonRec, "<");
GuiEnable();
if ((currentLineCounter + 1) > totalLineCounter) GuiDisable();
nextButtonClicked = GuiButton(nextButtonRec, ">");
GuiEnable();
resetButtonClicked = GuiButton(resetButtonRec, "Reset");
DrawText(TextFormat("LINES: %i/%i", currentLineCounter, MAX_DRAW_LINES), 10, screenHeight - 30, 20, MAROON);
DrawFPS(10, 10);
EndDrawing(); EndDrawing();
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
} }
// De-Initialization // De-Initialization
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context CloseWindow(); // Close window and OpenGL context
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 81 KiB

View File

@ -11,11 +11,12 @@
* 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
* *
* Copyright (c) 2025-2025 Robin (@RobinsAviary) * Copyright (c) 2025 Robin (@RobinsAviary)
* *
********************************************************************************************/ ********************************************************************************************/
#include "raylib.h" #include "raylib.h"
#include "raymath.h" #include "raymath.h"
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
@ -23,124 +24,114 @@
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
int main(void) int main(void)
{ {
// Initialization // Initialization
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
const int screenWidth = 800; const int screenWidth = 800;
const int screenHeight = 450; const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - lines drawing"); InitWindow(screenWidth, screenHeight, "raylib [shapes] example - lines drawing");
// Hint text that shows before you click the screen // Hint text that shows before you click the screen
bool startText = true; bool startText = true;
// The mouse's position on the previous frame // The mouse's position on the previous frame
Vector2 mousePositionPrevious = GetMousePosition(); Vector2 mousePositionPrevious = GetMousePosition();
// The canvas to draw lines on // The canvas to draw lines on
RenderTexture canvas = LoadRenderTexture(screenWidth, screenHeight); RenderTexture canvas = LoadRenderTexture(screenWidth, screenHeight);
// The background color of the canvas // The line's thickness
const Color backgroundColor = RAYWHITE; float lineThickness = 8.0f;
// The lines hue (in HSV, from 0-360)
float lineHue = 0.0f;
// The line's thickness // Clear the canvas to the background color
float lineThickness = 8.0f; BeginTextureMode(canvas);
// The lines hue (in HSV, from 0-360) ClearBackground(RAYWHITE);
float lineHue = 0.0f; EndTextureMode();
// Clear the canvas to the background color SetTargetFPS(60);
BeginTextureMode(canvas); //--------------------------------------------------------------------------------------
ClearBackground(backgroundColor);
EndTextureMode();
//--------------------------------------------------------------------------------------
// Main game loop // Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key while (!WindowShouldClose()) // Detect window close button or ESC key
{ {
// Update // Update
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Disable the hint text once the user clicks // Disable the hint text once the user clicks
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && startText) if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && startText) startText = false;
{
startText = false;
}
// Clear the canvas when the user middle-clicks // Clear the canvas when the user middle-clicks
if (IsMouseButtonPressed(MOUSE_BUTTON_MIDDLE)) if (IsMouseButtonPressed(MOUSE_BUTTON_MIDDLE))
{ {
BeginTextureMode(canvas); BeginTextureMode(canvas);
ClearBackground(backgroundColor); ClearBackground(RAYWHITE);
EndTextureMode(); EndTextureMode();
} }
// Store whether the left and right buttons are down // Store whether the left and right buttons are down
bool leftButtonDown = IsMouseButtonDown(MOUSE_BUTTON_LEFT); bool leftButtonDown = IsMouseButtonDown(MOUSE_BUTTON_LEFT);
bool rightButtonDown = IsMouseButtonDown(MOUSE_BUTTON_RIGHT); bool rightButtonDown = IsMouseButtonDown(MOUSE_BUTTON_RIGHT);
if (leftButtonDown || rightButtonDown) if (leftButtonDown || rightButtonDown)
{ {
// The color for the line // The color for the line
Color drawColor; Color drawColor = WHITE;
if (leftButtonDown) if (leftButtonDown)
{ {
// Increase the hue value by the distance our cursor has moved since the last frame (divided by 3) // Increase the hue value by the distance our cursor has moved since the last frame (divided by 3)
lineHue += Vector2Distance(mousePositionPrevious, GetMousePosition())/3.0f; lineHue += Vector2Distance(mousePositionPrevious, GetMousePosition())/3.0f;
// While the hue is >=360, subtract it to bring it down into the range 0-360 // While the hue is >=360, subtract it to bring it down into the range 0-360
// This is more visually accurate than resetting to zero // This is more visually accurate than resetting to zero
while (lineHue >= 360.0f) while (lineHue >= 360.0f) lineHue -= 360.0f;
{
lineHue -= 360.0f;
}
// Create the final color // Create the final color
drawColor = ColorFromHSV(lineHue, 1.0f, 1.0f); drawColor = ColorFromHSV(lineHue, 1.0f, 1.0f);
} }
else if (rightButtonDown) else if (rightButtonDown) drawColor = RAYWHITE; // Use the background color as an "eraser"
{
// Use the background color as an "eraser"
drawColor = backgroundColor;
}
// Draw the line onto the canvas // Draw the line onto the canvas
BeginTextureMode(canvas); BeginTextureMode(canvas);
// Circles act as "caps", smoothing corners // Circles act as "caps", smoothing corners
DrawCircleV(mousePositionPrevious, lineThickness/2.0f, drawColor); DrawCircleV(mousePositionPrevious, lineThickness/2.0f, drawColor);
DrawCircleV(GetMousePosition(), lineThickness/2.0f, drawColor); DrawCircleV(GetMousePosition(), lineThickness/2.0f, drawColor);
DrawLineEx(mousePositionPrevious, GetMousePosition(), lineThickness, drawColor); DrawLineEx(mousePositionPrevious, GetMousePosition(), lineThickness, drawColor);
EndTextureMode(); EndTextureMode();
} }
// Update line thickness based on mousewheel // Update line thickness based on mousewheel
lineThickness += GetMouseWheelMove(); lineThickness += GetMouseWheelMove();
lineThickness = Clamp(lineThickness, 1.0, 500.0f); lineThickness = Clamp(lineThickness, 1.0, 500.0f);
// Update mouse's previous position // Update mouse's previous position
mousePositionPrevious = GetMousePosition(); mousePositionPrevious = GetMousePosition();
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Draw // Draw
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
BeginDrawing(); BeginDrawing();
// Draw the render texture to the screen, flipped vertically to make it appear top-side up
DrawTextureRec(canvas.texture, (Rectangle){ 0.0f, 0.0f, (float)canvas.texture.width,(float)-canvas.texture.height }, Vector2Zero(), WHITE);
// Draw the preview circle // Draw the render texture to the screen, flipped vertically to make it appear top-side up
if (!leftButtonDown) DrawCircleLinesV(GetMousePosition(), lineThickness/2.0f, (Color){ 127, 127, 127, 127 }); DrawTextureRec(canvas.texture, (Rectangle){ 0.0f, 0.0f, (float)canvas.texture.width,(float)-canvas.texture.height }, Vector2Zero(), WHITE);
// Draw the hint text // Draw the preview circle
if (startText) DrawText("try clicking and dragging!", 275, 215, 20, LIGHTGRAY); if (!leftButtonDown) DrawCircleLinesV(GetMousePosition(), lineThickness/2.0f, (Color){ 127, 127, 127, 127 });
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization // Draw the hint text
//-------------------------------------------------------------------------------------- if (startText) DrawText("try clicking and dragging!", 275, 215, 20, LIGHTGRAY);
// Unload the canvas render texture
UnloadRenderTexture(canvas);
CloseWindow(); // Close window and OpenGL context EndDrawing();
//-------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
}
return 0; // De-Initialization
//--------------------------------------------------------------------------------------
UnloadRenderTexture(canvas); // Unload the canvas render texture
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
} }

View File

@ -0,0 +1,105 @@
/*******************************************************************************************
*
* raylib [shapes] example - math angle rotation
*
* Example complexity rating: [] 1/4
*
* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6
*
* Example contributed by Kris (@krispy-snacc) and reviewed by Ramon Santamaria (@raysan5)
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
* Copyright (c) 2025 Kris (@krispy-snacc)
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h" // for DEG2RAD
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 720;
const int screenHeight = 400;
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - math angle rotation");
SetTargetFPS(60);
Vector2 center = { screenWidth/2.0f, screenHeight/2.0f };
const float lineLength = 150.0f;
// Predefined angles for fixed lines
int angles[] = { 0, 30, 60, 90 };
int numAngles = sizeof(angles)/sizeof(angles[0]);
float totalAngle = 0.0f; // Animated rotation angle
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose())
{
// Update
//----------------------------------------------------------------------------------
totalAngle += 1.0f; // degrees per frame
if (totalAngle >= 360.0f) totalAngle -= 360.0f;
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(WHITE);
DrawText("Fixed angles + rotating line", 10, 10, 20, LIGHTGRAY);
// Draw fixed-angle lines with colorful gradient
for (int i = 0; i < numAngles; i++)
{
float rad = angles[i]*DEG2RAD;
Vector2 end = { center.x + cosf(rad)*lineLength,
center.y + sinf(rad)*lineLength };
// Gradient color from green → cyan → blue → magenta
Color col;
switch(i)
{
case 0: col = GREEN; break;
case 1: col = ORANGE; break;
case 2: col = BLUE; break;
case 3: col = MAGENTA; break;
default: col = WHITE; break;
}
DrawLineEx(center, end, 5.0f, col);
// Draw angle label slightly offset along the line
Vector2 textPos = { center.x + cosf(rad)*(lineLength + 20),
center.y + sinf(rad)*(lineLength + 20) };
DrawText(TextFormat("%d°", angles[i]), (int)textPos.x, (int)textPos.y, 20, col);
}
// Draw animated rotating line with changing color
float animRad = totalAngle*DEG2RAD;
Vector2 animEnd = { center.x + cosf(animRad)*lineLength,
center.y + sinf(animRad)*lineLength };
// Cycle through HSV colors for animated line
Color animCol = ColorFromHSV(fmodf(totalAngle, 360.0f), 0.8f, 0.9f);
DrawLineEx(center, animEnd, 5.0f, animCol);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow();
//--------------------------------------------------------------------------------------
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

@ -0,0 +1,177 @@
/*******************************************************************************************
*
* raylib [shapes] example - math sine cosine
*
* Example complexity rating: [] 2/4
*
* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
*
* Example contributed by Jopestpe (@jopestpe) and reviewed by Ramon Santamaria (@raysan5)
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
* Copyright (c) 2025 Jopestpe (@jopestpe)
*
********************************************************************************************/
#include "raylib.h"
#include <math.h>
#include "raymath.h"
#define RAYGUI_IMPLEMENTATION
#include "raygui.h" // Required for GUI controls
// Wave points for sine/cosine visualization
#define WAVE_POINTS 36
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
SetConfigFlags(FLAG_MSAA_4X_HINT);
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - math sine cosine");
Vector2 sinePoints[WAVE_POINTS];
Vector2 cosPoints[WAVE_POINTS];
Vector2 center = { (screenWidth/2.0f) - 30.0f, screenHeight/2.0f };
Rectangle start = { 20.0f, screenHeight - 120.f , 200.0f, 100.0f};
float radius = 130.0f;
float angle = 0.0f;
bool pause = false;
for (int i = 0; i < WAVE_POINTS; i++)
{
float t = i/(float)(WAVE_POINTS - 1);
float currentAngle = t*360.0f*DEG2RAD;
sinePoints[i] = (Vector2){ start.x + t*start.width, start.y + start.height/2.0f - sinf(currentAngle)*(start.height/2.0f) };
cosPoints[i] = (Vector2){ start.x + t*start.width, start.y + start.height/2.0f - cosf(currentAngle)*(start.height/2.0f) };
}
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
//----------------------------------------------------------------------------------
float angleRad = angle*DEG2RAD;
float cosRad = cosf(angleRad);
float sinRad = sinf(angleRad);
Vector2 point = { center.x + cosRad*radius, center.y - sinRad*radius };
Vector2 limitMin = { center.x - radius, center.y - radius };
Vector2 limitMax = { center.x + radius, center.y + radius };
float complementary = 90.0f - angle;
float supplementary = 180.0f - angle;
float explementary = 360.0f - angle;
float tangent = Clamp(tanf(angleRad), -10.0f, 10.0f);
float cotangent = (fabsf(tangent) > 0.001f) ? Clamp(1.0f/tangent, -radius, radius) : 0.0f;
Vector2 tangentPoint = { center.x + radius, center.y - tangent*radius };
Vector2 cotangentPoint = { center.x + cotangent*radius, center.y - radius };
angle = Wrap(angle + (!pause ? 1.0f : 0.0f), 0.0f, 360.0f);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
// Cotangent (orange)
DrawLineEx((Vector2){ center.x , limitMin.y }, (Vector2){ cotangentPoint.x, limitMin.y }, 2.0f, ORANGE);
DrawLineDashed(center, cotangentPoint, 10.0f, 4.0f, ORANGE);
// Side background
DrawLine(580, 0, 580, GetScreenHeight(), (Color){ 218, 218, 218, 255 });
DrawRectangle(580, 0, GetScreenWidth(), GetScreenHeight(), (Color){ 232, 232, 232, 255 });
// Base circle and axes
DrawCircleLinesV(center, radius, GRAY);
DrawLineEx((Vector2){ center.x, limitMin.y }, (Vector2){ center.x, limitMax.y }, 1.0f, GRAY);
DrawLineEx((Vector2){ limitMin.x, center.y }, (Vector2){ limitMax.x, center.y }, 1.0f, GRAY);
// Wave graph axes
DrawLineEx((Vector2){ start.x , start.y }, (Vector2){ start.x , start.y + start.height }, 2.0f, GRAY);
DrawLineEx((Vector2){ start.x + start.width, start.y }, (Vector2){ start.x + start.width, start.y + start.height }, 2.0f, GRAY);
DrawLineEx((Vector2){ start.x, start.y + start.height/2 }, (Vector2){ start.x + start.width, start.y + start.height/2 }, 2.0f, GRAY);
// Wave graph axis labels
DrawText("1", start.x - 8, start.y, 6, GRAY);
DrawText("0", start.x - 8, start.y + start.height/2 - 6, 6, GRAY);
DrawText("-1", start.x - 12, start.y + start.height - 8, 6, GRAY);
DrawText("0", start.x - 2, start.y + start.height + 4, 6, GRAY);
DrawText("360", start.x + start.width - 8, start.y + start.height + 4, 6, GRAY);
// Sine (red - vertical)
DrawLineEx((Vector2){ center.x, center.y }, (Vector2){ center.x, point.y }, 2.0f, RED);
DrawLineDashed((Vector2){ point.x, center.y }, (Vector2){ point.x, point.y }, 10.0f, 4.0f, RED);
DrawText(TextFormat("Sine %.2f", sinRad), 640, 190, 6, RED);
DrawCircleV((Vector2){ start.x + (angle/360.0f)*start.width, start.y + ((-sinRad + 1)*start.height/2.0f) }, 4.0f, RED);
DrawSplineLinear(sinePoints, WAVE_POINTS, 1.0f, RED);
// Cosine (blue - horizontal)
DrawLineEx((Vector2){ center.x, center.y }, (Vector2){ point.x, center.y }, 2.0f, BLUE);
DrawLineDashed((Vector2){ center.x , point.y }, (Vector2){ point.x, point.y }, 10.0f, 4.0f, BLUE);
DrawText(TextFormat("Cosine %.2f", cosRad), 640, 210, 6, BLUE);
DrawCircleV((Vector2){ start.x + (angle/360.0f)*start.width, start.y + ((-cosRad + 1)*start.height/2.0f) }, 4.0f, BLUE);
DrawSplineLinear(cosPoints, WAVE_POINTS, 1.0f, BLUE);
// Tangent (purple)
DrawLineEx((Vector2){ limitMax.x , center.y }, (Vector2){ limitMax.x, tangentPoint.y }, 2.0f, PURPLE);
DrawLineDashed(center, tangentPoint, 10.0f, 4.0f, PURPLE);
DrawText(TextFormat("Tangent %.2f", tangent), 640, 230, 6, PURPLE);
// Cotangent (orange)
DrawText(TextFormat("Cotangent %.2f", cotangent), 640, 250, 6, ORANGE);
// Complementary angle (beige)
DrawCircleSectorLines(center, radius*0.6f , -angle, -90.0f , 36.0f, BEIGE);
DrawText(TextFormat("Complementary %0.f°",complementary), 640, 150, 6, BEIGE);
// Supplementary angle (darkblue)
DrawCircleSectorLines(center, radius*0.5f , -angle, -180.0f , 36.0f, DARKBLUE);
DrawText(TextFormat("Supplementary %0.f°",supplementary), 640, 130, 6, DARKBLUE);
// Explementary angle (pink)
DrawCircleSectorLines(center, radius*0.4f , -angle, -360.0f , 36.0f, PINK);
DrawText(TextFormat("Explementary %0.f°",explementary), 640, 170, 6, PINK);
// Current angle - arc (lime), radius (black), endpoint (black)
DrawCircleSectorLines(center, radius*0.7f , -angle, 0.0f, 36.0f, LIME);
DrawLineEx((Vector2){ center.x , center.y }, point, 2.0f, BLACK);
DrawCircleV(point, 4.0f, BLACK);
// Draw GUI controls
//------------------------------------------------------------------------------
GuiSetStyle(LABEL, TEXT_COLOR_NORMAL, ColorToInt(GRAY));
GuiToggle((Rectangle){ 640, 70, 120, 20}, TextFormat("Pause"), &pause);
GuiSetStyle(LABEL, TEXT_COLOR_NORMAL, ColorToInt(LIME));
GuiSliderBar((Rectangle){ 640, 40, 120, 20}, "Angle", TextFormat("%.0f°", angle), &angle, 0.0f, 360.0f);
// Angle values panel
GuiGroupBox((Rectangle){ 620, 110, 140, 170}, "Angle Values");
//------------------------------------------------------------------------------
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -71,7 +71,7 @@ int main(void)
if ((trailPositions[i].x != 0.0f) || (trailPositions[i].y != 0.0f)) if ((trailPositions[i].x != 0.0f) || (trailPositions[i].y != 0.0f))
{ {
// Calculate relative trail strength (ratio is near 1.0 for new, near 0.0 for old) // Calculate relative trail strength (ratio is near 1.0 for new, near 0.0 for old)
float ratio = (float)(MAX_TRAIL_LENGTH - i) / MAX_TRAIL_LENGTH; float ratio = (float)(MAX_TRAIL_LENGTH - i)/MAX_TRAIL_LENGTH;
// Fade effect: oldest positions are more transparent // Fade effect: oldest positions are more transparent
// Fade (color, alpha) - alpha is 0.5 to 1.0 based on ratio // Fade (color, alpha) - alpha is 0.5 to 1.0 based on ratio

View File

@ -184,7 +184,7 @@ static void DrawRectangleRoundedGradientH(Rectangle rec, float roundnessLeft, fl
} }
// End one even segments // End one even segments
if ( segments % 2) if ( segments%2)
{ {
rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height); rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
rlVertex2f(center.x, center.y); rlVertex2f(center.x, center.y);

View File

@ -112,7 +112,7 @@ int main(void)
GuiSliderBar((Rectangle){ 640, 40, 120, 20}, "Angle", TextFormat("%.0f", angle), &angle, 0, 180); GuiSliderBar((Rectangle){ 640, 40, 120, 20}, "Angle", TextFormat("%.0f", angle), &angle, 0, 180);
GuiSliderBar((Rectangle){ 640, 70, 120, 20 }, "Length", TextFormat("%.0f", length), &length, 12.0f, 240.0f); GuiSliderBar((Rectangle){ 640, 70, 120, 20 }, "Length", TextFormat("%.0f", length), &length, 12.0f, 240.0f);
GuiSliderBar((Rectangle){ 640, 100, 120, 20}, "Decay", TextFormat("%.2f", branchDecay), &branchDecay, 0.1f, 0.78f); GuiSliderBar((Rectangle){ 640, 100, 120, 20}, "Decay", TextFormat("%.2f", branchDecay), &branchDecay, 0.1f, 0.78f);
GuiSliderBar((Rectangle){ 640, 130, 120, 20 }, "Depth", TextFormat("%.0f", treeDepth), &treeDepth, 1.0f, 10.f); GuiSliderBar((Rectangle){ 640, 130, 120, 20 }, "Depth", TextFormat("%.0f", treeDepth), &treeDepth, 1.0f, 10.0f);
GuiSliderBar((Rectangle){ 640, 160, 120, 20}, "Thick", TextFormat("%.0f", thick), &thick, 1, 8); GuiSliderBar((Rectangle){ 640, 160, 120, 20}, "Thick", TextFormat("%.0f", thick), &thick, 1, 8);
GuiCheckBox((Rectangle){ 640, 190, 20, 20 }, "Bezier", &bezier); GuiCheckBox((Rectangle){ 640, 190, 20, 20 }, "Bezier", &bezier);
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@ -0,0 +1,274 @@
/*******************************************************************************************
*
* raylib [shapes] example - rlgl color wheel
*
* Example complexity rating: [] 3/4
*
* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
*
* Example contributed by Robin (@RobinsAviary) and reviewed by Ramon Santamaria (@raysan5)
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
* Copyright (c) 2025 Robin (@RobinsAviary)
*
********************************************************************************************/
#include "raylib.h"
#include "rlgl.h"
#include "raymath.h"
#include <stdlib.h>
#include <stdio.h>
#define RAYGUI_IMPLEMENTATION
#include "raygui.h"
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
// The minimum/maximum points the circle can have
const unsigned int pointsMin = 3;
const unsigned int pointsMax = 256;
// The current number of points and the radius of the circle
unsigned int triangleCount = 64;
float pointScale = 150.0f;
// Slider value, literally maps to value in HSV
float value = 1.0f;
// The center of the screen
Vector2 center = { (float)screenWidth/2.0f, (float)screenHeight/2.0f };
// The location of the color wheel
Vector2 circlePosition = center;
// The currently selected color
Color color = { 255, 255, 255, 255 };
// Indicates if the slider is being clicked
bool sliderClicked = false;
// Indicates if the current color going to be updated, as well as the handle position
bool settingColor = false;
// How the color wheel will be rendered
unsigned int renderType = RL_TRIANGLES;
// Enable anti-aliasing
SetConfigFlags(FLAG_MSAA_4X_HINT);
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - rlgl color wheel");
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
triangleCount += (unsigned int)GetMouseWheelMove();
triangleCount = (unsigned int)Clamp((float)triangleCount, (float)pointsMin, (float)pointsMax);
Rectangle sliderRectangle = { 42.0f, 16.0f + 64.0f + 45.0f, 64.0f, 16.0f };
Vector2 mousePosition = GetMousePosition();
// Checks if the user is hovering over the value slider
bool sliderHover = (mousePosition.x >= sliderRectangle.x && mousePosition.y >= sliderRectangle.y && mousePosition.x < sliderRectangle.x + sliderRectangle.width && mousePosition.y < sliderRectangle.y + sliderRectangle.height);
// Copy color as hex
if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyDown(KEY_C))
{
if (IsKeyPressed(KEY_C))
{
SetClipboardText(TextFormat("#%02X%02X%02X", color.r, color.g, color.b));
}
}
// Scale up the color wheel, adjusting the handle visually
if (IsKeyDown(KEY_UP))
{
pointScale *= 1.025f;
if (pointScale > (float)screenHeight/2.0f)
{
pointScale = (float)screenHeight/2.0f;
}
else
{
circlePosition = Vector2Add(Vector2Multiply(Vector2Subtract(circlePosition, center), (Vector2){ 1.025f, 1.025f }), center);
}
}
// Scale down the wheel, adjusting the handle visually
if (IsKeyDown(KEY_DOWN))
{
pointScale *= 0.975f;
if (pointScale < 32.0f)
{
pointScale = 32.0f;
}
else
{
circlePosition = Vector2Add(Vector2Multiply(Vector2Subtract(circlePosition, center), (Vector2){ 0.975f, 0.975f }), center);
}
float distance = Vector2Distance(center, circlePosition)/pointScale;
float angle = ((Vector2Angle((Vector2){ 0.0f, -pointScale }, Vector2Subtract(center, circlePosition))/PI + 1.0f)/2.0f);
if (distance > 1.0f)
{
circlePosition = Vector2Add((Vector2){ sinf(angle*(PI*2.0f))*pointScale, -cosf(angle*(PI*2.0f))*pointScale }, center);
}
}
// Checks if the user clicked on the color wheel
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && Vector2Distance(GetMousePosition(), center) <= pointScale + 10.0f)
{
settingColor = true;
}
// Update flag when mouse button is released
if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) settingColor = false;
// Check if the user clicked/released the slider for the color's value
if (sliderHover && IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) sliderClicked = true;
if (sliderClicked && IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) sliderClicked = false;
// Update render mode accordingly
if (IsKeyPressed(KEY_SPACE)) renderType = RL_LINES;
if (IsKeyReleased(KEY_SPACE)) renderType = RL_TRIANGLES;
// If the slider or the wheel was clicked, update the current color
if (settingColor || sliderClicked)
{
if (settingColor) circlePosition = GetMousePosition();
float distance = Vector2Distance(center, circlePosition)/pointScale;
float angle = ((Vector2Angle((Vector2){ 0.0f, -pointScale }, Vector2Subtract(center, circlePosition))/PI + 1.0f)/2.0f);
if (settingColor && distance > 1.0f) circlePosition = Vector2Add((Vector2){ sinf(angle*(PI*2.0f))*pointScale, -cosf(angle*(PI* 2.0f))*pointScale }, center);
float angle360 = angle*360.0f;
float valueActual = Clamp(distance, 0.0f, 1.0f);
color = ColorLerp((Color){ (int)(value*255.0f), (int)(value*255.0f), (int)(value*255.0f), 255 }, ColorFromHSV(angle360, Clamp(distance, 0.0f, 1.0f), 1.0f), valueActual);
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
// Begin rendering color wheel
rlBegin(renderType);
for (unsigned int i = 0; i < triangleCount; i++)
{
float angleOffset = ((PI*2.0f)/(float)triangleCount);
float angle = angleOffset*(float)i;
float angleOffsetCalculated = ((float)i + 1)*angleOffset;
Vector2 scale = (Vector2){ pointScale, pointScale };
Vector2 offset = Vector2Multiply((Vector2){ sinf(angle), -cosf(angle) }, scale);
Vector2 offset2 = Vector2Multiply((Vector2){ sinf(angleOffsetCalculated), -cosf(angleOffsetCalculated) }, scale);
Vector2 position = Vector2Add(center, offset);
Vector2 position2 = Vector2Add(center, offset2);
float angleNonRadian = (angle/(2.0f*PI))*360.0f;
float angleNonRadianOffset = (angleOffset/(2.0f*PI))*360.0f;
Color currentColor = ColorFromHSV(angleNonRadian, 1.0f, 1.0f);
Color offsetColor = ColorFromHSV(angleNonRadian + angleNonRadianOffset, 1.0f, 1.0f);
// Input vertices differently depending on mode
if (renderType == RL_TRIANGLES)
{
// RL_TRIANGLES expects three vertices per triangle
rlColor4ub(currentColor.r, currentColor.g, currentColor.b, currentColor.a);
rlVertex2f(position.x, position.y);
rlColor4f(value, value, value, 1.0f);
rlVertex2f(center.x, center.y);
rlColor4ub(offsetColor.r, offsetColor.g, offsetColor.b, offsetColor.a);
rlVertex2f(position2.x, position2.y);
}
else if (renderType == RL_LINES)
{
// RL_LINES expects two vertices per line
rlColor4ub(currentColor.r, currentColor.g, currentColor.b, currentColor.a);
rlVertex2f(position.x, position.y);
rlColor4ub(WHITE.r, WHITE.g, WHITE.b, WHITE.a);
rlVertex2f(center.x, center.y);
rlVertex2f(center.x, center.y);
rlColor4ub(offsetColor.r, offsetColor.g, offsetColor.b, offsetColor.a);
rlVertex2f(position2.x, position2.y);
rlVertex2f(position2.x, position2.y);
rlColor4ub(currentColor.r, currentColor.g, currentColor.b, currentColor.a);
rlVertex2f(position.x, position.y);
}
}
rlEnd();
// Make the handle slightly more visible overtop darker colors
Color handleColor = BLACK;
if (Vector2Distance(center, circlePosition)/pointScale <= 0.5f && value <= 0.5f)
{
handleColor = DARKGRAY;
}
// Draw the color handle
DrawCircleLinesV(circlePosition, 4.0f, handleColor);
// Draw the color in a preview, with a darkened outline.
DrawRectangleV((Vector2){ 8.0f, 8.0f }, (Vector2){ 64.0f, 64.0f }, color);
DrawRectangleLinesEx((Rectangle){ 8.0f, 8.0f, 64.0f, 64.0f }, 2.0f, ColorLerp(color, BLACK, 0.5f));
// Draw current color as hex and decimal
DrawText(TextFormat("#%02X%02X%02X\n(%d, %d, %d)", color.r, color.g, color.b, color.r, color.g, color.b), 8, 8 + 64 + 8, 20, DARKGRAY);
// Update the visuals for the copying text
Color copyColor = DARKGRAY;
unsigned int offset = 0;
if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyDown(KEY_C))
{
copyColor = DARKGREEN;
offset = 4;
}
// Draw the copying text
DrawText("press ctrl+c to copy!", 8, 425 - offset, 20, copyColor);
// Display the number of rendered triangles
DrawText(TextFormat("triangle count: %d", triangleCount), 8, 395, 20, DARKGRAY);
// Slider to change color's value
GuiSliderBar(sliderRectangle, "value: ", "", &value, 0.0f, 1.0f);
// Draw FPS next to outlined color preview
DrawFPS(64 + 16, 8);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

View File

@ -0,0 +1,169 @@
/*******************************************************************************************
*
* raylib [shapes] example - rlgl triangle
*
* Example complexity rating: [] 2/4
*
* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
*
* Example contributed by Robin (@RobinsAviary) and reviewed by Ramon Santamaria (@raysan5)
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
* Copyright (c) 2025 Robin (@RobinsAviary)
*
********************************************************************************************/
#include "raylib.h"
#include "rlgl.h"
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
SetConfigFlags(FLAG_MSAA_4X_HINT);
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - rlgl triangle");
// Starting postions and rendered triangle positions
Vector2 startingPositions[3] = {{ 400.0f, 150.0f }, { 300.0f, 300.0f }, { 500.0f, 300.0f }};
Vector2 trianglePositions[3] = { startingPositions[0], startingPositions[1], startingPositions[2] };
// Currently selected vertex, -1 means none
int triangleIndex = -1;
bool linesMode = false;
float handleRadius = 8.0f;
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
if (IsKeyPressed(KEY_SPACE)) linesMode = !linesMode;
// Check selected vertex
for (unsigned int i = 0; i < 3; i++)
{
// If the mouse is within the handle circle
if (CheckCollisionPointCircle(GetMousePosition(), trianglePositions[i], handleRadius) &&
IsMouseButtonDown(MOUSE_BUTTON_LEFT))
{
triangleIndex = i;
break;
}
}
// If the user has selected a vertex, offset it by the mouse's delta this frame
if (triangleIndex != -1)
{
Vector2 *position = &trianglePositions[triangleIndex];
Vector2 mouseDelta = GetMouseDelta();
position->x += mouseDelta.x;
position->y += mouseDelta.y;
}
// Reset index on release
if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) triangleIndex = -1;
// Enable/disable backface culling (2-sided triangles, slower to render)
if (IsKeyPressed(KEY_LEFT)) rlEnableBackfaceCulling();
if (IsKeyPressed(KEY_RIGHT)) rlDisableBackfaceCulling();
// Reset triangle vertices to starting positions and reset backface culling
if (IsKeyPressed(KEY_R))
{
trianglePositions[0] = startingPositions[0];
trianglePositions[1] = startingPositions[1];
trianglePositions[2] = startingPositions[2];
rlEnableBackfaceCulling();
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
if (linesMode)
{
// Draw triangle with lines
rlBegin(RL_LINES);
// Three lines, six points
// Define color for next vertex
rlColor4ub(255, 0, 0, 255);
// Define vertex
rlVertex2f(trianglePositions[0].x, trianglePositions[0].y);
rlColor4ub(0, 255, 0, 255);
rlVertex2f(trianglePositions[1].x, trianglePositions[1].y);
rlColor4ub(0, 255, 0, 255);
rlVertex2f(trianglePositions[1].x, trianglePositions[1].y);
rlColor4ub(0, 0, 255, 255);
rlVertex2f(trianglePositions[2].x, trianglePositions[2].y);
rlColor4ub(0, 0, 255, 255);
rlVertex2f(trianglePositions[2].x, trianglePositions[2].y);
rlColor4ub(255, 0, 0, 255);
rlVertex2f(trianglePositions[0].x, trianglePositions[0].y);
rlEnd();
}
else
{
// Draw triangle as a triangle
rlBegin(RL_TRIANGLES);
// One triangle, three points
// Define color for next vertex
rlColor4ub(255, 0, 0, 255);
// Define vertex
rlVertex2f(trianglePositions[0].x, trianglePositions[0].y);
rlColor4ub(0, 255, 0, 255);
rlVertex2f(trianglePositions[1].x, trianglePositions[1].y);
rlColor4ub(0, 0, 255, 255);
rlVertex2f(trianglePositions[2].x, trianglePositions[2].y);
rlEnd();
}
// Render the vertex handles, reacting to mouse movement/input
for (unsigned int i = 0; i < 3; i++)
{
// Draw handle fill focused by mouse
if (CheckCollisionPointCircle(GetMousePosition(), trianglePositions[i], handleRadius))
DrawCircleV(trianglePositions[i], handleRadius, ColorAlpha(DARKGRAY, 0.5f));
// Draw handle fill selected
if (i == triangleIndex) DrawCircleV(trianglePositions[i], handleRadius, DARKGRAY);
// Draw handle outline
DrawCircleLinesV(trianglePositions[i], handleRadius, BLACK);
}
// Draw controls
DrawText("SPACE: Toggle lines mode", 10, 10, 20, DARKGRAY);
DrawText("LEFT-RIGHT: Toggle backface culling", 10, 40, 20, DARKGRAY);
DrawText("MOUSE: Click and drag vertex points", 10, 70, 20, DARKGRAY);
DrawText("R: Reset triangle to start positions", 10, 100, 20, DARKGRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -36,7 +36,7 @@ static const char particleTypeNames[3][10] = { "WATER", "SMOKE", "FIRE" };
typedef struct Particle { typedef struct Particle {
ParticleType type; // Particle type (WATER, SMOKE, FIRE) ParticleType type; // Particle type (WATER, SMOKE, FIRE)
Vector2 position; // Particle position on screen Vector2 position; // Particle position on screen
Vector2 velocity; // Particle current speed and direction Vector2 velocity; // Particle current speed and direction
float radius; // Particle radius float radius; // Particle radius
Color color; // Particle color Color color; // Particle color
@ -45,9 +45,9 @@ typedef struct Particle {
} Particle; } Particle;
typedef struct CircularBuffer { typedef struct CircularBuffer {
int head; // Index for the next write int head; // Index for the next write
int tail; // Index for the next read int tail; // Index for the next read
Particle *buffer; // Particle buffer array Particle *buffer; // Particle buffer array
} CircularBuffer; } CircularBuffer;
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -73,12 +73,12 @@ int main(void)
// Definition of particles // Definition of particles
Particle *particles = (Particle*)RL_CALLOC(MAX_PARTICLES, sizeof(Particle)); // Particle array Particle *particles = (Particle*)RL_CALLOC(MAX_PARTICLES, sizeof(Particle)); // Particle array
CircularBuffer circularBuffer = { 0, 0, particles }; CircularBuffer circularBuffer = { 0, 0, particles };
// Particle emitter parameters // Particle emitter parameters
int emissionRate = -2; // Negative: on average every -X frames. Positive: particles per frame int emissionRate = -2; // Negative: on average every -X frames. Positive: particles per frame
ParticleType currentType = WATER; ParticleType currentType = WATER;
Vector2 emitterPosition = { screenWidth/2.0f, screenHeight/2.0f }; Vector2 emitterPosition = { screenWidth/2.0f, screenHeight/2.0f };
SetTargetFPS(60); // Set our game to run at 60 frames-per-second SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
@ -88,17 +88,17 @@ int main(void)
{ {
// Update // Update
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Emit new particles: when emissionRate is 1, emit every frame // Emit new particles: when emissionRate is 1, emit every frame
if (emissionRate < 0) if (emissionRate < 0)
{ {
if (rand()%(-emissionRate) == 0) EmitParticle(&circularBuffer, emitterPosition, currentType); if (rand()%(-emissionRate) == 0) EmitParticle(&circularBuffer, emitterPosition, currentType);
} }
else else
{ {
for (int i = 0; i <= emissionRate; ++i) EmitParticle(&circularBuffer, emitterPosition, currentType); for (int i = 0; i <= emissionRate; i++) EmitParticle(&circularBuffer, emitterPosition, currentType);
} }
// Update the parameters of each particle // Update the parameters of each particle
UpdateParticles(&circularBuffer, screenWidth, screenHeight); UpdateParticles(&circularBuffer, screenWidth, screenHeight);
// Remove dead particles from the circular buffer // Remove dead particles from the circular buffer
@ -112,7 +112,7 @@ int main(void)
if (IsKeyPressed(KEY_RIGHT)) (currentType == FIRE)? (currentType = WATER) : currentType++; if (IsKeyPressed(KEY_RIGHT)) (currentType == FIRE)? (currentType = WATER) : currentType++;
if (IsKeyPressed(KEY_LEFT)) (currentType == WATER)? (currentType = FIRE) : currentType--; if (IsKeyPressed(KEY_LEFT)) (currentType == WATER)? (currentType = FIRE) : currentType--;
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) emitterPosition = GetMousePosition(); if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) emitterPosition = GetMousePosition();
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Draw // Draw
@ -121,7 +121,7 @@ int main(void)
ClearBackground(RAYWHITE); ClearBackground(RAYWHITE);
// Call the function with a loop to draw all particles // Call the function with a loop to draw all particles
DrawParticles(&circularBuffer); DrawParticles(&circularBuffer);
// Draw UI and Instructions // Draw UI and Instructions
@ -133,7 +133,7 @@ int main(void)
DrawText("LEFT/RIGHT: Change Particle Type (Water, Smoke, Fire)", 15, 55, 10, BLACK); DrawText("LEFT/RIGHT: Change Particle Type (Water, Smoke, Fire)", 15, 55, 10, BLACK);
if (emissionRate < 0) DrawText(TextFormat("Particles every %d frames | Type: %s", -emissionRate, particleTypeNames[currentType]), 15, 95, 10, DARKGRAY); if (emissionRate < 0) DrawText(TextFormat("Particles every %d frames | Type: %s", -emissionRate, particleTypeNames[currentType]), 15, 95, 10, DARKGRAY);
else DrawText(TextFormat("%d Particles per frame | Type: %s", emissionRate + 1, particleTypeNames[currentType]), 15, 95, 10, DARKGRAY); else DrawText(TextFormat("%d Particles per frame | Type: %s", emissionRate + 1, particleTypeNames[currentType]), 15, 95, 10, DARKGRAY);
DrawFPS(screenWidth - 80, 10); DrawFPS(screenWidth - 80, 10);
@ -200,12 +200,12 @@ static Particle *AddToCircularBuffer(CircularBuffer *circularBuffer)
// Check if buffer full // Check if buffer full
if (((circularBuffer->head + 1)%MAX_PARTICLES) != circularBuffer->tail) if (((circularBuffer->head + 1)%MAX_PARTICLES) != circularBuffer->tail)
{ {
// Add new particle to the head position and advance head // Add new particle to the head position and advance head
particle = &circularBuffer->buffer[circularBuffer->head]; particle = &circularBuffer->buffer[circularBuffer->head];
circularBuffer->head = (circularBuffer->head + 1)%MAX_PARTICLES; circularBuffer->head = (circularBuffer->head + 1)%MAX_PARTICLES;
} }
return particle; return particle;
} }
static void UpdateParticles(CircularBuffer *circularBuffer, int screenWidth, int screenHeight) static void UpdateParticles(CircularBuffer *circularBuffer, int screenWidth, int screenHeight)
@ -213,7 +213,7 @@ static void UpdateParticles(CircularBuffer *circularBuffer, int screenWidth, int
for (int i = circularBuffer->tail; i != circularBuffer->head; i = (i + 1)%MAX_PARTICLES) for (int i = circularBuffer->tail; i != circularBuffer->head; i = (i + 1)%MAX_PARTICLES)
{ {
// Update particle life and positions // Update particle life and positions
circularBuffer->buffer[i].lifeTime += 1.0f/60.0f; // 60 FPS -> 1/60 seconds per frame circularBuffer->buffer[i].lifeTime += 1.0f/60.0f; // 60 FPS -> 1/60 seconds per frame
switch (circularBuffer->buffer[i].type) switch (circularBuffer->buffer[i].type)
{ {
@ -226,22 +226,22 @@ static void UpdateParticles(CircularBuffer *circularBuffer, int screenWidth, int
case SMOKE: case SMOKE:
{ {
circularBuffer->buffer[i].position.x += circularBuffer->buffer[i].velocity.x; circularBuffer->buffer[i].position.x += circularBuffer->buffer[i].velocity.x;
circularBuffer->buffer[i].velocity.y -= 0.05f; // Upwards circularBuffer->buffer[i].velocity.y -= 0.05f; // Upwards
circularBuffer->buffer[i].position.y += circularBuffer->buffer[i].velocity.y; circularBuffer->buffer[i].position.y += circularBuffer->buffer[i].velocity.y;
circularBuffer->buffer[i].radius += 0.5f; // Increment radius: smoke expands circularBuffer->buffer[i].radius += 0.5f; // Increment radius: smoke expands
circularBuffer->buffer[i].color.a -= 4; // Decrement alpha: smoke fades circularBuffer->buffer[i].color.a -= 4; // Decrement alpha: smoke fades
// If alpha transparent, particle dies // If alpha transparent, particle dies
if (circularBuffer->buffer[i].color.a < 4) circularBuffer->buffer[i].alive = false; if (circularBuffer->buffer[i].color.a < 4) circularBuffer->buffer[i].alive = false;
} break; } break;
case FIRE: case FIRE:
{ {
// Add a little horizontal oscillation to fire particles // Add a little horizontal oscillation to fire particles
circularBuffer->buffer[i].position.x += circularBuffer->buffer[i].velocity.x + cosf(circularBuffer->buffer[i].lifeTime*215.0f); circularBuffer->buffer[i].position.x += circularBuffer->buffer[i].velocity.x + cosf(circularBuffer->buffer[i].lifeTime*215.0f);
circularBuffer->buffer[i].velocity.y -= 0.05f; // Upwards circularBuffer->buffer[i].velocity.y -= 0.05f; // Upwards
circularBuffer->buffer[i].position.y += circularBuffer->buffer[i].velocity.y; circularBuffer->buffer[i].position.y += circularBuffer->buffer[i].velocity.y;
circularBuffer->buffer[i].radius -= 0.15f; // Decrement radius: fire shrinks circularBuffer->buffer[i].radius -= 0.15f; // Decrement radius: fire shrinks
circularBuffer->buffer[i].color.g -= 3; // Decrement green: fire turns reddish starting from yellow circularBuffer->buffer[i].color.g -= 3; // Decrement green: fire turns reddish starting from yellow
// If radius too small, particle dies // If radius too small, particle dies
if (circularBuffer->buffer[i].radius <= 0.02f) circularBuffer->buffer[i].alive = false; if (circularBuffer->buffer[i].radius <= 0.02f) circularBuffer->buffer[i].alive = false;
@ -249,9 +249,9 @@ static void UpdateParticles(CircularBuffer *circularBuffer, int screenWidth, int
default: break; default: break;
} }
// Disable particle when out of screen // Disable particle when out of screen
Vector2 center = circularBuffer->buffer[i].position; Vector2 center = circularBuffer->buffer[i].position;
float radius = circularBuffer->buffer[i].radius; float radius = circularBuffer->buffer[i].radius;
if ((center.x < -radius) || (center.x > (screenWidth + radius)) || if ((center.x < -radius) || (center.x > (screenWidth + radius)) ||
(center.y < -radius) || (center.y > (screenHeight + radius))) (center.y < -radius) || (center.y > (screenHeight + radius)))
@ -267,7 +267,7 @@ static void UpdateCircularBuffer(CircularBuffer *circularBuffer)
while ((circularBuffer->tail != circularBuffer->head) && !circularBuffer->buffer[circularBuffer->tail].alive) while ((circularBuffer->tail != circularBuffer->head) && !circularBuffer->buffer[circularBuffer->tail].alive)
{ {
circularBuffer->tail = (circularBuffer->tail + 1)%MAX_PARTICLES; circularBuffer->tail = (circularBuffer->tail + 1)%MAX_PARTICLES;
} }
} }
static void DrawParticles(CircularBuffer *circularBuffer) static void DrawParticles(CircularBuffer *circularBuffer)

View File

@ -34,7 +34,7 @@ int main(void)
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - triangle strip"); InitWindow(screenWidth, screenHeight, "raylib [shapes] example - triangle strip");
Vector2 points[122] = { 0 }; Vector2 points[122] = { 0 };
Vector2 center = { (screenWidth/2.0f) - 125.f, screenHeight/2.0f }; Vector2 center = { (screenWidth/2.0f) - 125.0f, screenHeight/2.0f };
float segments = 6.0f; float segments = 6.0f;
float insideRadius = 100.0f; float insideRadius = 100.0f;
float outsideRadius = 150.0f; float outsideRadius = 150.0f;
@ -92,7 +92,7 @@ int main(void)
// Draw GUI controls // Draw GUI controls
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
GuiSliderBar((Rectangle){ 640, 40, 120, 20}, "Segments", TextFormat("%.0f", segments), &segments, 6.0f, 60.f); GuiSliderBar((Rectangle){ 640, 40, 120, 20}, "Segments", TextFormat("%.0f", segments), &segments, 6.0f, 60.0f);
GuiCheckBox((Rectangle){ 640, 70, 20, 20 }, "Outline", &outline); GuiCheckBox((Rectangle){ 640, 70, 20, 20 }, "Outline", &outline);
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@ -231,7 +231,7 @@ int main(void)
if (multicolor) if (multicolor)
{ {
// Fill color array with random colors // Fill color array with random colors
for (int i = 0; i < TEXT_MAX_LAYERS; ++i) for (int i = 0; i < TEXT_MAX_LAYERS; i++)
{ {
multi[i] = GenerateRandomColor(0.5f, 0.8f); multi[i] = GenerateRandomColor(0.5f, 0.8f);
multi[i].a = GetRandomValue(0, 255); multi[i].a = GetRandomValue(0, 255);
@ -296,7 +296,7 @@ int main(void)
rlRotatef(90.0f, 1.0f, 0.0f, 0.0f); rlRotatef(90.0f, 1.0f, 0.0f, 0.0f);
rlRotatef(90.0f, 0.0f, 0.0f, -1.0f); rlRotatef(90.0f, 0.0f, 0.0f, -1.0f);
for (int i = 0; i < layers; ++i) for (int i = 0; i < layers; i++)
{ {
Color clr = light; Color clr = light;
if (multicolor) clr = multi[i]; if (multicolor) clr = multi[i];

View File

@ -9,7 +9,7 @@
* - TTF/OTF > Sprite font atlas is generated on loading, user can configure * - TTF/OTF > Sprite font atlas is generated on loading, user can configure
* some of the generation parameters (size, characters to include) * some of the generation parameters (size, characters to include)
* - BMFonts > Angel code font fileformat, sprite font image must be provided * - BMFonts > Angel code font fileformat, sprite font image must be provided
* together with the .fnt file, font generation cna not be configured * together with the .fnt file, font generation can not be configured
* - XNA Spritefont > Sprite font image, following XNA Spritefont conventions, * - XNA Spritefont > Sprite font image, following XNA Spritefont conventions,
* Characters in image must follow some spacing and order rules * Characters in image must follow some spacing and order rules
* *

View File

@ -186,7 +186,7 @@ static void DrawTextStyled(Font font, const char *text, Vector2 position, float
else increaseX += ((float)font.glyphs[index].advanceX*scaleFactor + spacing); else increaseX += ((float)font.glyphs[index].advanceX*scaleFactor + spacing);
// Draw background rectangle color (if required) // Draw background rectangle color (if required)
if (colBack.a > 0) DrawRectangleRec((Rectangle) { position.x + textOffsetX, position.y + textOffsetY - backRecPadding, increaseX, fontSize + 2 * backRecPadding }, colBack); if (colBack.a > 0) DrawRectangleRec((Rectangle) { position.x + textOffsetX, position.y + textOffsetY - backRecPadding, increaseX, fontSize + 2*backRecPadding }, colBack);
if ((codepoint != ' ') && (codepoint != '\t')) if ((codepoint != ' ') && (codepoint != '\t'))
{ {
@ -210,7 +210,7 @@ static Vector2 MeasureTextStyled(Font font, const char *text, float fontSize, fl
if ((font.texture.id == 0) || (text == NULL) || (text[0] == '\0')) return textSize; // Security check if ((font.texture.id == 0) || (text == NULL) || (text[0] == '\0')) return textSize; // Security check
int textLen = TextLength(text); // Get size in bytes of text int textLen = TextLength(text); // Get size in bytes of text
float textLineSpacing = fontSize*1.5f; //float textLineSpacing = fontSize*1.5f; // Not used...
float textWidth = 0.0f; float textWidth = 0.0f;
float textHeight = fontSize; float textHeight = fontSize;

View File

@ -210,7 +210,7 @@ int main(void)
// Draw random emojis in the background // Draw random emojis in the background
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
for (int i = 0; i < SIZEOF(emoji); ++i) for (int i = 0; i < SIZEOF(emoji); i++)
{ {
const char *txt = &emojiCodepoints[emoji[i].index]; const char *txt = &emojiCodepoints[emoji[i].index];
Rectangle emojiRect = { position.x, position.y, (float)fontEmoji.baseSize, (float)fontEmoji.baseSize }; Rectangle emojiRect = { position.x, position.y, (float)fontEmoji.baseSize, (float)fontEmoji.baseSize };
@ -316,7 +316,7 @@ static void RandomizeEmoji(void)
hovered = selected = -1; hovered = selected = -1;
int start = GetRandomValue(45, 360); int start = GetRandomValue(45, 360);
for (int i = 0; i < SIZEOF(emoji); ++i) for (int i = 0; i < SIZEOF(emoji); i++)
{ {
// 0-179 emoji codepoints (from emoji char array) each 4bytes + null char // 0-179 emoji codepoints (from emoji char array) each 4bytes + null char
emoji[i].index = GetRandomValue(0, 179)*5; emoji[i].index = GetRandomValue(0, 179)*5;

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