Merge branch 'raysan5:master' into master
4
.github/workflows/parse_api.yml
vendored
|
|
@ -22,7 +22,7 @@ jobs:
|
|||
- name: Diff parse files
|
||||
id: diff
|
||||
run: |
|
||||
git add -N tools/rlparser
|
||||
git add -N tools/rlparser/output
|
||||
git diff --name-only --exit-code
|
||||
continue-on-error: true
|
||||
|
||||
|
|
@ -32,6 +32,6 @@ jobs:
|
|||
set -x
|
||||
git config user.name "github-actions[bot]"
|
||||
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 push
|
||||
|
|
|
|||
8
.gitignore
vendored
|
|
@ -62,10 +62,15 @@ packages/
|
|||
emsdk
|
||||
|
||||
# Ignore wasm data in examples/
|
||||
examples/**/*
|
||||
!examples/**/*.*
|
||||
!examples/**/*/
|
||||
examples/**/*.exe
|
||||
examples/**/*.wasm
|
||||
examples/**/*.data
|
||||
examples/**/*.js
|
||||
examples/**/*.html
|
||||
examples/**/logs/*
|
||||
|
||||
# Ignore files build by xcode
|
||||
*.mode*v*
|
||||
|
|
@ -115,7 +120,8 @@ build-*/
|
|||
docgen_tmp/
|
||||
|
||||
# Tools stuff
|
||||
tools/parser/raylib_parser
|
||||
tools/parser/rlparser.exe
|
||||
tools/parser/rlparser
|
||||
tools/rexm/rexm.exe
|
||||
tools/rexm/rexm
|
||||
|
||||
|
|
|
|||
|
|
@ -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 |
|
||||
| [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 |
|
||||
| [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-freebasic](https://github.com/WIITD/raylib-freebasic) | **5.0** | [FreeBASIC](https://www.freebasic.net) | MIT |
|
||||
| [raylib.f](https://github.com/cthulhuology/raylib.f) | **5.5** | [Forth](https://forth.com) | Zlib |
|
||||
| [fortran-raylib](https://github.com/interkosmos/fortran-raylib) | **5.5** | [Fortran](https://fortran-lang.org) | ISC |
|
||||
| [raylib-go](https://github.com/gen2brain/raylib-go) | **5.5** | [Go](https://golang.org) | Zlib |
|
||||
| [raylib-guile](https://github.com/petelliott/raylib-guile) | **auto** | [Guile](https://www.gnu.org/software/guile) | Zlib |
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
// Be careful with the switch formatting!
|
||||
|
|
|
|||
|
|
@ -231,7 +231,7 @@ endif
|
|||
# -Wno-missing-braces ignore invalid warning (GCC bug 53119)
|
||||
# -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
|
||||
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)
|
||||
CFLAGS += -g -D_DEBUG
|
||||
|
|
@ -486,7 +486,19 @@ endif
|
|||
ifeq ($(TARGET_PLATFORM),PLATFORM_DRM)
|
||||
# Libraries for DRM compiling
|
||||
# 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
|
||||
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW))
|
||||
# Libraries for web (HTML5) compiling
|
||||
|
|
@ -513,6 +525,7 @@ CORE = \
|
|||
core/core_basic_screen_manager \
|
||||
core/core_basic_window \
|
||||
core/core_clipboard_text \
|
||||
core/core_compute_hash \
|
||||
core/core_custom_frame_control \
|
||||
core/core_custom_logging \
|
||||
core/core_delta_time \
|
||||
|
|
@ -539,6 +552,7 @@ CORE = \
|
|||
core/core_storage_values \
|
||||
core/core_text_file_loading \
|
||||
core/core_undo_redo \
|
||||
core/core_viewport_scaling \
|
||||
core/core_vr_simulator \
|
||||
core/core_window_flags \
|
||||
core/core_window_letterbox \
|
||||
|
|
@ -562,14 +576,19 @@ SHAPES = \
|
|||
shapes/shapes_following_eyes \
|
||||
shapes/shapes_kaleidoscope \
|
||||
shapes/shapes_lines_bezier \
|
||||
shapes/shapes_lines_drawing \
|
||||
shapes/shapes_logo_raylib \
|
||||
shapes/shapes_logo_raylib_anim \
|
||||
shapes/shapes_math_angle_rotation \
|
||||
shapes/shapes_math_sine_cosine \
|
||||
shapes/shapes_mouse_trail \
|
||||
shapes/shapes_pie_chart \
|
||||
shapes/shapes_rectangle_advanced \
|
||||
shapes/shapes_rectangle_scaling \
|
||||
shapes/shapes_recursive_tree \
|
||||
shapes/shapes_ring_drawing \
|
||||
shapes/shapes_rlgl_color_wheel \
|
||||
shapes/shapes_rlgl_triangle \
|
||||
shapes/shapes_rounded_rectangle_drawing \
|
||||
shapes/shapes_simple_particles \
|
||||
shapes/shapes_splines_drawing \
|
||||
|
|
@ -598,9 +617,11 @@ TEXTURES = \
|
|||
textures/textures_particles_blending \
|
||||
textures/textures_polygon_drawing \
|
||||
textures/textures_raw_data \
|
||||
textures/textures_screen_buffer \
|
||||
textures/textures_sprite_animation \
|
||||
textures/textures_sprite_button \
|
||||
textures/textures_sprite_explosion \
|
||||
textures/textures_sprite_stacking \
|
||||
textures/textures_srcrec_dstrec \
|
||||
textures/textures_textured_curve \
|
||||
textures/textures_tiled_drawing \
|
||||
|
|
@ -631,6 +652,8 @@ MODELS = \
|
|||
models/models_bone_socket \
|
||||
models/models_box_collisions \
|
||||
models/models_cubicmap_rendering \
|
||||
models/models_decals \
|
||||
models/models_directional_billboard \
|
||||
models/models_first_person_maze \
|
||||
models/models_geometric_shapes \
|
||||
models/models_heightmap_rendering \
|
||||
|
|
@ -654,6 +677,7 @@ SHADERS = \
|
|||
shaders/shaders_ascii_rendering \
|
||||
shaders/shaders_basic_lighting \
|
||||
shaders/shaders_basic_pbr \
|
||||
shaders/shaders_color_correction \
|
||||
shaders/shaders_custom_uniform \
|
||||
shaders/shaders_deferred_rendering \
|
||||
shaders/shaders_depth_rendering \
|
||||
|
|
@ -691,6 +715,7 @@ AUDIO = \
|
|||
audio/audio_sound_loading \
|
||||
audio/audio_sound_multi \
|
||||
audio/audio_sound_positioning \
|
||||
audio/audio_spectrum_visualizer \
|
||||
audio/audio_stream_effects
|
||||
|
||||
OTHERS = \
|
||||
|
|
|
|||
|
|
@ -513,6 +513,7 @@ CORE = \
|
|||
core/core_basic_screen_manager \
|
||||
core/core_basic_window \
|
||||
core/core_clipboard_text \
|
||||
core/core_compute_hash \
|
||||
core/core_custom_frame_control \
|
||||
core/core_custom_logging \
|
||||
core/core_delta_time \
|
||||
|
|
@ -539,6 +540,7 @@ CORE = \
|
|||
core/core_storage_values \
|
||||
core/core_text_file_loading \
|
||||
core/core_undo_redo \
|
||||
core/core_viewport_scaling \
|
||||
core/core_vr_simulator \
|
||||
core/core_window_flags \
|
||||
core/core_window_letterbox \
|
||||
|
|
@ -562,14 +564,19 @@ SHAPES = \
|
|||
shapes/shapes_following_eyes \
|
||||
shapes/shapes_kaleidoscope \
|
||||
shapes/shapes_lines_bezier \
|
||||
shapes/shapes_lines_drawing \
|
||||
shapes/shapes_logo_raylib \
|
||||
shapes/shapes_logo_raylib_anim \
|
||||
shapes/shapes_math_angle_rotation \
|
||||
shapes/shapes_math_sine_cosine \
|
||||
shapes/shapes_mouse_trail \
|
||||
shapes/shapes_pie_chart \
|
||||
shapes/shapes_rectangle_advanced \
|
||||
shapes/shapes_rectangle_scaling \
|
||||
shapes/shapes_recursive_tree \
|
||||
shapes/shapes_ring_drawing \
|
||||
shapes/shapes_rlgl_color_wheel \
|
||||
shapes/shapes_rlgl_triangle \
|
||||
shapes/shapes_rounded_rectangle_drawing \
|
||||
shapes/shapes_simple_particles \
|
||||
shapes/shapes_splines_drawing \
|
||||
|
|
@ -598,9 +605,11 @@ TEXTURES = \
|
|||
textures/textures_particles_blending \
|
||||
textures/textures_polygon_drawing \
|
||||
textures/textures_raw_data \
|
||||
textures/textures_screen_buffer \
|
||||
textures/textures_sprite_animation \
|
||||
textures/textures_sprite_button \
|
||||
textures/textures_sprite_explosion \
|
||||
textures/textures_sprite_stacking \
|
||||
textures/textures_srcrec_dstrec \
|
||||
textures/textures_textured_curve \
|
||||
textures/textures_tiled_drawing \
|
||||
|
|
@ -631,6 +640,8 @@ MODELS = \
|
|||
models/models_bone_socket \
|
||||
models/models_box_collisions \
|
||||
models/models_cubicmap_rendering \
|
||||
models/models_decals \
|
||||
models/models_directional_billboard \
|
||||
models/models_first_person_maze \
|
||||
models/models_geometric_shapes \
|
||||
models/models_heightmap_rendering \
|
||||
|
|
@ -654,6 +665,7 @@ SHADERS = \
|
|||
shaders/shaders_ascii_rendering \
|
||||
shaders/shaders_basic_lighting \
|
||||
shaders/shaders_basic_pbr \
|
||||
shaders/shaders_color_correction \
|
||||
shaders/shaders_custom_uniform \
|
||||
shaders/shaders_deferred_rendering \
|
||||
shaders/shaders_depth_rendering \
|
||||
|
|
@ -691,6 +703,7 @@ AUDIO = \
|
|||
audio/audio_sound_loading \
|
||||
audio/audio_sound_multi \
|
||||
audio/audio_sound_positioning \
|
||||
audio/audio_spectrum_visualizer \
|
||||
audio/audio_stream_effects
|
||||
|
||||
# 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
|
||||
$(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
|
||||
$(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
|
||||
$(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
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
|
||||
--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
|
||||
$(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
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
|
||||
|
||||
shapes/shapes_logo_raylib_anim: shapes/shapes_logo_raylib_anim.c
|
||||
$(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
|
||||
$(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
|
||||
$(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
|
||||
$(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
|
||||
$(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
|
||||
$(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) \
|
||||
--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
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
|
||||
--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/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
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
|
||||
--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_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
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
|
||||
--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_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
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
|
||||
--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) \
|
||||
--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
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
|
||||
--preload-file audio/resources/country.mp3@resources/country.mp3
|
||||
|
|
|
|||
|
|
@ -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 [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 |
|
||||
|-----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------|
|
||||
|
|
@ -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_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_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_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) |
|
||||
|
|
@ -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_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_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_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_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_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 | [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_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.
|
||||
|
||||
|
|
@ -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_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_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_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_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.
|
||||
|
||||
|
|
@ -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_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_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_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]
|
||||
|
||||
|
|
@ -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_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.
|
||||
|
||||
|
|
@ -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_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_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.
|
||||
|
||||
|
|
@ -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_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_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_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) |
|
||||
|
|
@ -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_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_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.
|
||||
|
||||
|
|
@ -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_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_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]
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,12 @@ int main(void)
|
|||
float timePlayed = 0.0f; // Time played normalized [0.0f..1.0f]
|
||||
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
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -62,6 +68,34 @@ int main(void)
|
|||
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
|
||||
timePlayed = GetMusicTimePlayed(music)/GetMusicTimeLength(music);
|
||||
|
||||
|
|
@ -76,6 +110,11 @@ int main(void)
|
|||
|
||||
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, (int)(timePlayed*400.0f), 12, MAROON);
|
||||
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 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();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ int main(void)
|
|||
};
|
||||
|
||||
SetSoundPosition(camera, sound, spherePos, 20.0f);
|
||||
|
||||
if (!IsSoundPlaying(sound)) PlaySound(sound);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -94,6 +95,8 @@ int main(void)
|
|||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
|
|
|
|||
285
examples/audio/audio_spectrum_visualizer.c
Normal 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;
|
||||
}
|
||||
|
||||
// Cooley–Tukey 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 }));
|
||||
}
|
||||
BIN
examples/audio/audio_spectrum_visualizer.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
37
examples/audio/resources/shaders/glsl100/fft.fs
Normal 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;
|
||||
}
|
||||
35
examples/audio/resources/shaders/glsl120/fft.fs
Normal 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;
|
||||
}
|
||||
35
examples/audio/resources/shaders/glsl330/fft.fs
Normal 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;
|
||||
}
|
||||
|
|
@ -23,7 +23,7 @@
|
|||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main ()
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
|
@ -93,6 +93,7 @@ int main ()
|
|||
// under the cursor to the screen space point under the cursor at any zoom
|
||||
camera.target = mouseWorldPos;
|
||||
}
|
||||
|
||||
if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT))
|
||||
{
|
||||
// Zoom increment
|
||||
|
|
@ -110,7 +111,6 @@ int main ()
|
|||
ClearBackground(RAYWHITE);
|
||||
|
||||
BeginMode2D(camera);
|
||||
|
||||
// Draw the 3d grid, rotated 90 degrees and centered around 0,0
|
||||
// just so we have something in the XY plane
|
||||
rlPushMatrix();
|
||||
|
|
@ -121,7 +121,6 @@ int main ()
|
|||
|
||||
// Draw a reference circle
|
||||
DrawCircle(GetScreenWidth()/2, GetScreenHeight()/2, 50, MAROON);
|
||||
|
||||
EndMode2D();
|
||||
|
||||
// Draw mouse reference
|
||||
|
|
@ -142,5 +141,6 @@ int main ()
|
|||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,12 +6,12 @@
|
|||
*
|
||||
* 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,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2025 Agnis Aldins (@nezvers)
|
||||
* Copyright (c) 2025 Agnis Aldiņš (@nezvers)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
|
|
|
|||
|
|
@ -2,22 +2,23 @@
|
|||
*
|
||||
* 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 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,
|
||||
* 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 <stdio.h>
|
||||
#define RAYGUI_IMPLEMENTATION
|
||||
#include "raygui.h"
|
||||
|
||||
#define MAX_TEXT_SAMPLES 5
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
|
|
@ -31,28 +32,32 @@ int main(void)
|
|||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - clipboard text");
|
||||
|
||||
// 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!"
|
||||
};
|
||||
|
||||
const char *clipboardText = NULL;
|
||||
char inputBuffer[256] = "Hello from raylib!"; // Random initial string
|
||||
|
||||
// List of text the user can switch through and copy
|
||||
const char* copyableText[] = {"raylib is fun", "hello, clipboard!", "potato chips"};
|
||||
// UI required variables
|
||||
bool textBoxEditMode = false;
|
||||
|
||||
unsigned int textIndex = 0;
|
||||
bool btnCutPressed = false;
|
||||
bool btnCopyPressed = false;
|
||||
bool btnPastePressed = false;
|
||||
bool btnClearPressed = false;
|
||||
bool btnRandomPressed = false;
|
||||
|
||||
const char* popupText = NULL;
|
||||
// Set UI style
|
||||
GuiSetStyle(DEFAULT, TEXT_SIZE, 20);
|
||||
GuiSetIconScale(2);
|
||||
|
||||
// Initialize timers
|
||||
// The amount of time the pop-up text is on screen, before fading
|
||||
const float maxTime = 3.0f;
|
||||
float textTimer = 0.0f;
|
||||
// The length of time text is offset
|
||||
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;
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
|
|
@ -60,95 +65,55 @@ int main(void)
|
|||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// Check if the user has pressed the copy/paste key combinations
|
||||
bool pastePressed = (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_V));
|
||||
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)
|
||||
// Handle button interactions
|
||||
if (btnCutPressed)
|
||||
{
|
||||
// Most operating systems hide this information until the user presses Ctrl-V on the window.
|
||||
|
||||
// Check to see if the clipboard contains an image
|
||||
// This function does nothing outside of Windows, as it directly calls the Windows API
|
||||
Image image = GetClipboardImage();
|
||||
|
||||
if (IsImageValid(image))
|
||||
{
|
||||
// Unload the image
|
||||
UnloadImage(image);
|
||||
// Update visuals
|
||||
popupText = "clipboard contains image";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get text from the user's clipboard
|
||||
SetClipboardText(inputBuffer);
|
||||
clipboardText = GetClipboardText();
|
||||
|
||||
// Update visuals
|
||||
popupText = "text pasted";
|
||||
pasteAnim = animMaxTime;
|
||||
inputBuffer[0] = '\0'; // Quick solution to clear text
|
||||
//memset(inputBuffer, 0, 256); // Clear full buffer properly
|
||||
}
|
||||
|
||||
// Reset animation values
|
||||
textTimer = maxTime;
|
||||
textAnim = animMaxTime;
|
||||
textAlpha = 1;
|
||||
if (btnCopyPressed)
|
||||
{
|
||||
SetClipboardText(inputBuffer); // Copy text to clipboard
|
||||
clipboardText = GetClipboardText(); // Get text from clipboard
|
||||
}
|
||||
|
||||
// React to the user pressing copy
|
||||
if (copyPressed)
|
||||
if (btnPastePressed)
|
||||
{
|
||||
// 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";
|
||||
// Paste text from clipboard
|
||||
clipboardText = GetClipboardText();
|
||||
if (clipboardText != NULL) TextCopy(inputBuffer, clipboardText);
|
||||
}
|
||||
|
||||
// Switch to the next item in the list when the user presses up
|
||||
if (IsKeyPressed(KEY_UP))
|
||||
if (btnClearPressed)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
inputBuffer[0] = '\0'; // Quick solution to clear text
|
||||
//memset(inputBuffer, 0, 256); // Clear full buffer properly
|
||||
}
|
||||
|
||||
// Switch to the previous item in the list when the user presses down
|
||||
if (IsKeyPressed(KEY_DOWN))
|
||||
if (btnRandomPressed)
|
||||
{
|
||||
// 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
|
||||
// Get random text from sample list
|
||||
TextCopy(inputBuffer, sampleTexts[GetRandomValue(0, MAX_TEXT_SAMPLES - 1)]);
|
||||
}
|
||||
else
|
||||
|
||||
// Quick cut/copy/paste with keyboard shortcuts
|
||||
if (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL))
|
||||
{
|
||||
textIndex -= 1;
|
||||
if (IsKeyPressed(KEY_X))
|
||||
{
|
||||
SetClipboardText(inputBuffer);
|
||||
inputBuffer[0] = '\0'; // Quick solution to clear text
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KEY_C)) SetClipboardText(inputBuffer);
|
||||
|
||||
if (IsKeyPressed(KEY_V))
|
||||
{
|
||||
clipboardText = GetClipboardText();
|
||||
if (clipboardText != NULL) TextCopy(inputBuffer, clipboardText);
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
|
@ -159,41 +124,30 @@ int main(void)
|
|||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
// Draw the user's pasted text, if there is any yet
|
||||
if (clipboardText)
|
||||
{
|
||||
// Offset animation
|
||||
int offset = 0;
|
||||
if (pasteAnim > 0) offset = offsetAmount;
|
||||
// Draw instructions
|
||||
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);
|
||||
|
||||
// Draw the pasted text
|
||||
DrawText("pasted clipboard:", 10, 10 + offset, 20, DARKGREEN);
|
||||
DrawText(clipboardText, 10, 30 + offset, 20, DARKGRAY);
|
||||
}
|
||||
// Draw text box
|
||||
if (GuiTextBox((Rectangle){ 50, 120, 652, 40 }, inputBuffer, 256, textBoxEditMode)) textBoxEditMode = !textBoxEditMode;
|
||||
|
||||
// Offset animation
|
||||
int textOffset = 0;
|
||||
if (copyAnim > 0) textOffset = offsetAmount;
|
||||
// Random text button
|
||||
btnRandomPressed = GuiButton((Rectangle){ 50 + 652 + 8, 120, 40, 40 }, "#77#");
|
||||
|
||||
// Draw copyable text and controls
|
||||
DrawText(copyableText[textIndex], 10, 330 + (textOffset * copyAnimMult), 20, MAROON);
|
||||
DrawText("up/down to change string, ctrl-c to copy, ctrl-v to paste", 10, 355, 20, DARKGRAY);
|
||||
// Draw buttons
|
||||
btnCutPressed = GuiButton((Rectangle){ 50, 180, 158, 40 }, "#17#CUT");
|
||||
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
|
||||
if (textAlpha > 0)
|
||||
{
|
||||
// Offset animation
|
||||
int offset = 0;
|
||||
if (textAnim > 0) offset = offsetAmount;
|
||||
// Draw pop up text
|
||||
DrawText(popupText, 10, 425 + offset, 20, ColorAlpha(DARKGREEN, textAlpha));
|
||||
|
||||
// Fade-out animation
|
||||
if (textTimer < 0)
|
||||
{
|
||||
textAlpha -= GetFrameTime();
|
||||
}
|
||||
}
|
||||
// Draw clipboard status
|
||||
GuiSetState(STATE_DISABLED);
|
||||
GuiLabel((Rectangle){ 50, 260, 700, 40 }, "Clipboard current text data:");
|
||||
GuiSetStyle(TEXTBOX, TEXT_READONLY, 1);
|
||||
GuiTextBox((Rectangle){ 50, 300, 700, 40 }, (char *)clipboardText, 256, false);
|
||||
GuiSetStyle(TEXTBOX, TEXT_READONLY, 0);
|
||||
GuiLabel((Rectangle){ 50, 360, 700, 40 }, "Try copying text from other applications and pasting here!");
|
||||
GuiSetState(STATE_NORMAL);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 17 KiB |
143
examples/core/core_compute_hash.c
Normal 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;
|
||||
}
|
||||
BIN
examples/core/core_compute_hash.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
|
|
@ -17,11 +17,11 @@
|
|||
|
||||
#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()
|
||||
|
||||
// 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 };
|
||||
time_t now = time(NULL);
|
||||
|
|
@ -54,7 +54,7 @@ int main(void)
|
|||
const int screenHeight = 450;
|
||||
|
||||
// Set custom logger
|
||||
SetTraceLogCallback(CustomLog);
|
||||
SetTraceLogCallback(CustomTraceLog);
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - custom logging");
|
||||
|
||||
|
|
|
|||
|
|
@ -20,9 +20,7 @@
|
|||
#define RAYGUI_IMPLEMENTATION
|
||||
#include "raygui.h" // Required for GUI controls
|
||||
|
||||
#include <string.h> // Required for: strcpy()
|
||||
|
||||
#define MAX_FILEPATH_SIZE 2048
|
||||
#define MAX_FILEPATH_SIZE 1024
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
|
|
@ -53,12 +51,10 @@ int main(void)
|
|||
//----------------------------------------------------------------------------------
|
||||
if (btnBackPressed)
|
||||
{
|
||||
strcpy(directory, GetPrevDirectoryPath(directory));
|
||||
TextCopy(directory, GetPrevDirectoryPath(directory));
|
||||
UnloadDirectoryFiles(files);
|
||||
files = LoadDirectoryFiles(directory);
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
|
|
@ -68,19 +64,20 @@ int main(void)
|
|||
|
||||
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++)
|
||||
{
|
||||
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}, ""))
|
||||
{
|
||||
strcpy(directory, files.paths[i]);
|
||||
TextCopy(directory, files.paths[i]);
|
||||
UnloadDirectoryFiles(files);
|
||||
files = LoadDirectoryFiles(directory);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,9 +27,10 @@ int main(void)
|
|||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
SetConfigFlags(FLAG_WINDOW_HIGHDPI | FLAG_WINDOW_RESIZABLE);
|
||||
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);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
|
@ -48,11 +49,12 @@ int main(void)
|
|||
|
||||
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);
|
||||
DrawLineEx((Vector2){ 0, screenHeight }, (Vector2){ screenWidth, 0 }, 2.0f, RED);
|
||||
DrawText("example base code template", 260, 400, 20, LIGHTGRAY);
|
||||
// Draw UI info
|
||||
DrawText(TextFormat("SCREEN SIZE: %ix%i", GetScreenWidth(), GetScreenHeight()), 10, 10, 20, BLACK);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ int main(void)
|
|||
// Set default actions
|
||||
char actionSet = 0;
|
||||
SetActionsDefault();
|
||||
bool releaseAction = false;
|
||||
|
||||
Vector2 position = (Vector2){ 400.0f, 200.0f };
|
||||
Vector2 size = (Vector2){ 40.0f, 40.0f };
|
||||
|
|
@ -83,7 +84,8 @@ int main(void)
|
|||
{
|
||||
// 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_DOWN)) position.y += 2;
|
||||
if (IsActionDown(ACTION_LEFT)) position.x -= 2;
|
||||
|
|
@ -94,6 +96,10 @@ int main(void)
|
|||
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
|
||||
if (IsKeyPressed(KEY_TAB))
|
||||
{
|
||||
|
|
@ -109,7 +115,7 @@ int main(void)
|
|||
|
||||
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("Use TAB key to toggles Actions keyset", 10, 50, 20, GREEN);
|
||||
|
|
|
|||
|
|
@ -51,6 +51,8 @@ int main(void)
|
|||
const float leftTriggerDeadzone = -0.9f;
|
||||
const float rightTriggerDeadzone = -0.9f;
|
||||
|
||||
Rectangle vibrateButton = { 0 };
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -61,7 +63,12 @@ int main(void)
|
|||
{
|
||||
// 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
|
||||
|
|
@ -70,9 +77,6 @@ int main(void)
|
|||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
if (IsKeyPressed(KEY_LEFT) && gamepad > 0) gamepad--;
|
||||
if (IsKeyPressed(KEY_RIGHT)) gamepad++;
|
||||
|
||||
if (IsGamepadAvailable(gamepad))
|
||||
{
|
||||
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 (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);
|
||||
|
||||
|
|
@ -125,16 +130,14 @@ int main(void)
|
|||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_THUMB)) leftGamepadColor = RED;
|
||||
DrawCircle(259, 152, 39, BLACK);
|
||||
DrawCircle(259, 152, 34, LIGHTGRAY);
|
||||
DrawCircle(259 + (int)(leftStickX*20),
|
||||
152 + (int)(leftStickY*20), 25, leftGamepadColor);
|
||||
DrawCircle(259 + (int)(leftStickX*20), 152 + (int)(leftStickY*20), 25, leftGamepadColor);
|
||||
|
||||
// Draw axis: right joystick
|
||||
Color rightGamepadColor = BLACK;
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_THUMB)) rightGamepadColor = RED;
|
||||
DrawCircle(461, 237, 38, BLACK);
|
||||
DrawCircle(461, 237, 33, LIGHTGRAY);
|
||||
DrawCircle(461 + (int)(rightStickX*20),
|
||||
237 + (int)(rightStickY*20), 25, rightGamepadColor);
|
||||
DrawCircle(461 + (int)(rightStickX*20), 237 + (int)(rightStickY*20), 25, rightGamepadColor);
|
||||
|
||||
// Draw axis: left-right triggers
|
||||
DrawRectangle(170, 30, 15, 70, GRAY);
|
||||
|
|
@ -177,16 +180,14 @@ int main(void)
|
|||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_THUMB)) leftGamepadColor = RED;
|
||||
DrawCircle(319, 255, 35, BLACK);
|
||||
DrawCircle(319, 255, 31, LIGHTGRAY);
|
||||
DrawCircle(319 + (int)(leftStickX*20),
|
||||
255 + (int)(leftStickY*20), 25, leftGamepadColor);
|
||||
DrawCircle(319 + (int)(leftStickX*20), 255 + (int)(leftStickY*20), 25, leftGamepadColor);
|
||||
|
||||
// Draw axis: right joystick
|
||||
Color rightGamepadColor = BLACK;
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_THUMB)) rightGamepadColor = RED;
|
||||
DrawCircle(475, 255, 35, BLACK);
|
||||
DrawCircle(475, 255, 31, LIGHTGRAY);
|
||||
DrawCircle(475 + (int)(rightStickX*20),
|
||||
255 + (int)(rightStickY*20), 25, rightGamepadColor);
|
||||
DrawCircle(475 + (int)(rightStickX*20), 255 + (int)(rightStickY*20), 25, rightGamepadColor);
|
||||
|
||||
// Draw axis: left-right triggers
|
||||
DrawRectangle(169, 48, 15, 70, GRAY);
|
||||
|
|
@ -196,7 +197,6 @@ int main(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
|
||||
// Draw background: generic
|
||||
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;
|
||||
DrawCircle(345, 260, 40, BLACK);
|
||||
DrawCircle(345, 260, 35, LIGHTGRAY);
|
||||
DrawCircle(345 + (int)(leftStickX*20),
|
||||
260 + (int)(leftStickY*20), 25, leftGamepadColor);
|
||||
DrawCircle(345 + (int)(leftStickX*20), 260 + (int)(leftStickY*20), 25, leftGamepadColor);
|
||||
|
||||
// Draw axis: right joystick
|
||||
Color rightGamepadColor = BLACK;
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_THUMB)) rightGamepadColor = RED;
|
||||
DrawCircle(465, 260, 40, BLACK);
|
||||
DrawCircle(465, 260, 35, LIGHTGRAY);
|
||||
DrawCircle(465 + (int)(rightStickX*20),
|
||||
260 + (int)(rightStickY*20), 25, rightGamepadColor);
|
||||
DrawCircle(465 + (int)(rightStickX*20), 260 + (int)(rightStickY*20), 25, rightGamepadColor);
|
||||
|
||||
// Draw axis: left-right triggers
|
||||
DrawRectangle(151, 110, 15, 70, GRAY);
|
||||
DrawRectangle(644, 110, 15, 70, GRAY);
|
||||
DrawRectangle(151, 110, 15, (int)(((1 + leftTrigger)/2)*70), RED);
|
||||
DrawRectangle(644, 110, 15, (int)(((1 + rightTrigger)/2)*70), RED);
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
else DrawText("DETECTED BUTTON: NONE", 10, 430, 10, GRAY);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawText(TextFormat("GP%d: NOT DETECTED", gamepad), 10, 10, 10, GRAY);
|
||||
|
||||
DrawTexture(texXboxPad, 0, 0, LIGHTGRAY);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -118,4 +118,6 @@ int main(void)
|
|||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -22,9 +22,9 @@
|
|||
#define GESTURE_LOG_SIZE 20
|
||||
#define MAX_TOUCH_COUNT 32
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
// Module Functions Declaration
|
||||
//----------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------
|
||||
static char const *GetGestureName(int gesture); // Get text string 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 currentAngleDegrees = 0.0f;
|
||||
Vector2 finalVector = { 0.0f, 0.0f };
|
||||
char currentAngleStr[7] = "";
|
||||
Vector2 protractorPosition = { 266.0f, 315.0f };
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
|
|
|
|||
|
|
@ -40,14 +40,8 @@ int main(void)
|
|||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyPressed(KEY_H))
|
||||
{
|
||||
if (IsCursorHidden())
|
||||
{
|
||||
ShowCursor();
|
||||
}
|
||||
else
|
||||
{
|
||||
HideCursor();
|
||||
}
|
||||
if (IsCursorHidden()) ShowCursor();
|
||||
else HideCursor();
|
||||
}
|
||||
|
||||
ballPosition = GetMousePosition();
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ int main(void)
|
|||
// Clamp touch points available ( set the maximum touch points allowed )
|
||||
if (tCount > MAX_TOUCH_POINTS) tCount = MAX_TOUCH_POINTS;
|
||||
// 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
|
||||
|
|
@ -55,7 +55,7 @@ int main(void)
|
|||
|
||||
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
|
||||
if ((touchPositions[i].x > 0) && (touchPositions[i].y > 0))
|
||||
|
|
|
|||
|
|
@ -40,10 +40,9 @@ int main(void)
|
|||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
MonitorInfo monitors[MAX_MONITORS] = { 0 };
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - monitor detector");
|
||||
|
||||
MonitorInfo monitors[MAX_MONITORS] = { 0 };
|
||||
int currentMonitorIndex = GetCurrentMonitor();
|
||||
int monitorCount = 0;
|
||||
|
||||
|
|
@ -55,7 +54,6 @@ int main(void)
|
|||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Variables to find the max x and Y to calculate the scale
|
||||
int maxWidth = 1;
|
||||
int maxHeight = 1;
|
||||
|
|
@ -76,7 +74,8 @@ int main(void)
|
|||
GetMonitorPhysicalHeight(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 height = (int)monitors[i].position.y + monitors[i].height;
|
||||
|
|
@ -85,7 +84,7 @@ int main(void)
|
|||
if (maxHeight < height) maxHeight = height;
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KEY_ENTER) && monitorCount > 1)
|
||||
if (IsKeyPressed(KEY_ENTER) && (monitorCount > 1))
|
||||
{
|
||||
currentMonitorIndex += 1;
|
||||
|
||||
|
|
@ -94,16 +93,13 @@ int main(void)
|
|||
|
||||
SetWindowMonitor(currentMonitorIndex); // Move window to currentMonitorIndex
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get currentMonitorIndex if manually moved
|
||||
currentMonitorIndex = GetCurrentMonitor();
|
||||
}
|
||||
else currentMonitorIndex = GetCurrentMonitor(); // Get currentMonitorIndex if manually moved
|
||||
|
||||
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));
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
|
|
@ -148,14 +144,9 @@ int main(void)
|
|||
// Draw window position based on monitors
|
||||
DrawRectangleV(windowPosition, (Vector2){screenWidth*monitorScale, screenHeight*monitorScale}, Fade(GREEN, 0.5));
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawRectangleLinesEx(rec, 5, GRAY);
|
||||
else DrawRectangleLinesEx(rec, 5, GRAY);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,12 +2,10 @@
|
|||
*
|
||||
* 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 contributed by Ramon Santamaria (@raysan5) 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
|
||||
*
|
||||
|
|
@ -17,6 +15,16 @@
|
|||
|
||||
#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
|
||||
//------------------------------------------------------------------------------------
|
||||
|
|
@ -29,7 +37,20 @@ int main(void)
|
|||
|
||||
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);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
|
@ -39,7 +60,59 @@ int main(void)
|
|||
{
|
||||
// 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
|
||||
|
|
@ -48,20 +121,43 @@ int main(void)
|
|||
|
||||
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);
|
||||
DrawLineEx((Vector2){ 0, screenHeight }, (Vector2){ screenWidth, 0 }, 2.0f, RED);
|
||||
DrawText("example base code template", 260, 400, 20, LIGHTGRAY);
|
||||
DrawCircleV(circlePosition, 30, RED);
|
||||
|
||||
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();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// TODO: Unload all loaded resources at this point
|
||||
// If still recording a GIF on close window, just finish
|
||||
if (gifRecording)
|
||||
{
|
||||
MsfGifResult result = msf_gif_end(&gifState);
|
||||
msf_gif_free(result);
|
||||
gifRecording = false;
|
||||
}
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#include "raymath.h" // Required for: Lerp()
|
||||
|
||||
#include <string.h>
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
|
|
@ -59,10 +61,11 @@ int main(void)
|
|||
int lastSpace = 0; // Keeping track of last valid space to insert '\n'
|
||||
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
|
||||
lines[i][j] = '\0';
|
||||
|
||||
|
|
@ -75,7 +78,7 @@ int main(void)
|
|||
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
|
||||
}
|
||||
|
||||
|
|
@ -88,16 +91,16 @@ int main(void)
|
|||
|
||||
for (int i = 0; i < lineCount; i++)
|
||||
{
|
||||
Vector2 size = MeasureTextEx(GetFontDefault(), lines[i], fontSize, 2);
|
||||
textHeight += size.y + 10;
|
||||
Vector2 size = MeasureTextEx(GetFontDefault(), lines[i], (float)fontSize, 2);
|
||||
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 = {
|
||||
.x = screenWidth - 5,
|
||||
.x = (float)screenWidth - 5,
|
||||
.y = 0,
|
||||
.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);
|
||||
|
|
@ -115,10 +118,10 @@ int main(void)
|
|||
|
||||
// Ensuring that the camera does not scroll past all text
|
||||
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
|
||||
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
|
||||
|
|
@ -132,13 +135,19 @@ int main(void)
|
|||
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
|
||||
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);
|
||||
|
||||
// Inserting extra space for real newlines,
|
||||
// wrapped lines are rendered closer together
|
||||
t += size.y + 10;
|
||||
t += (int)size.y + 10;
|
||||
}
|
||||
EndMode2D();
|
||||
|
||||
|
|
|
|||
321
examples/core/core_viewport_scaling.c
Normal 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};
|
||||
}
|
||||
BIN
examples/core/core_viewport_scaling.png
Normal file
|
After Width: | Height: | Size: 8.5 KiB |
|
|
@ -97,7 +97,8 @@ int main(void)
|
|||
if (IsWindowState(FLAG_WINDOW_MINIMIZED))
|
||||
{
|
||||
framesCounter++;
|
||||
if (framesCounter >= 240) {
|
||||
if (framesCounter >= 240)
|
||||
{
|
||||
RestoreWindow(); // Restore window after 3 seconds
|
||||
framesCounter = 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main()
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -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_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_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_world_screen;★★☆☆;1.3;1.4;2015;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_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_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_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_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_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;"Ananth S";@Ananth1839
|
||||
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_bouncing_ball;★☆☆☆;2.5;2.5;2013;2025;"Ramon Santamaria";@raysan5
|
||||
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_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_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_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_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_srcrec_dstrec;★★★☆;1.3;1.3;2015;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_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_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_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_font_spritefont;★☆☆☆;1.0;1.0;2014;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_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_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_basic_lighting;★★★★;3.0;4.2;2019;2025;"Chris Camacho";@chriscamacho
|
||||
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_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_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_fog_rendering;★★★☆;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_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_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_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
|
||||
|
|
|
|||
605
examples/models/models_decals.c
Normal 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;
|
||||
}
|
||||
BIN
examples/models/models_decals.png
Normal file
|
After Width: | Height: | Size: 66 KiB |
116
examples/models/models_directional_billboard.c
Normal 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;
|
||||
}
|
||||
BIN
examples/models/models_directional_billboard.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
|
|
@ -67,7 +67,7 @@ int main(void)
|
|||
models[i] = LoadModel(voxFileNames[i]);
|
||||
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)
|
||||
BoundingBox bb = GetModelBoundingBox(models[i]);
|
||||
|
|
@ -80,6 +80,8 @@ int main(void)
|
|||
}
|
||||
|
||||
int currentModel = 0;
|
||||
Vector3 modelpos = { 0 };
|
||||
Vector3 camerarot = { 0 };
|
||||
|
||||
// Load voxel shader
|
||||
Shader shader = LoadShader(TextFormat("resources/shaders/glsl%i/voxel_lighting.vs", GLSL_VERSION),
|
||||
|
|
@ -98,11 +100,7 @@ int main(void)
|
|||
// Assign out lighting shader to model
|
||||
for (int i = 0; i < MAX_VOX_FILES; i++)
|
||||
{
|
||||
Model m = models[i];
|
||||
for (int j = 0; j < m.materialCount; j++)
|
||||
{
|
||||
m.materials[j].shader = shader;
|
||||
}
|
||||
for (int j = 0; j < models[i].materialCount; j++) models[i].materials[j].shader = shader;
|
||||
}
|
||||
|
||||
// Create lights
|
||||
|
|
@ -112,12 +110,8 @@ int main(void)
|
|||
lights[2] = 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
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
Vector3 modelpos = { 0 };
|
||||
Vector3 camerarot = { 0 };
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
|
|
@ -137,14 +131,10 @@ int main(void)
|
|||
}
|
||||
|
||||
UpdateCameraPro(&camera,
|
||||
(Vector3) {
|
||||
(IsKeyDown(KEY_W) || IsKeyDown(KEY_UP))*0.1f - // Move forward-backward
|
||||
(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,
|
||||
(Vector3){ (IsKeyDown(KEY_W) || IsKeyDown(KEY_UP))*0.1f - (IsKeyDown(KEY_S) || IsKeyDown(KEY_DOWN))*0.1f, // Move forward-backward
|
||||
(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)
|
||||
|
||||
// Cycle between models on mouse click
|
||||
|
|
@ -156,8 +146,8 @@ int main(void)
|
|||
|
||||
// Update light values (actually, only enable/disable them)
|
||||
for (int i = 0; i < MAX_LIGHTS; i++) UpdateLightValues(shader, lights[i]);
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
|
@ -166,7 +156,6 @@ int main(void)
|
|||
|
||||
// Draw 3D model
|
||||
BeginMode3D(camera);
|
||||
|
||||
DrawModel(models[currentModel], modelpos, 1.0f, WHITE);
|
||||
DrawGrid(10, 1.0);
|
||||
|
||||
|
|
@ -176,16 +165,15 @@ int main(void)
|
|||
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();
|
||||
|
||||
// Display info
|
||||
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);
|
||||
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);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
|
|
@ -201,5 +189,3 @@ int main(void)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ static Mesh GenMeshPoints(int numPoints);
|
|||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main()
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
|
@ -57,7 +57,7 @@ int main()
|
|||
Mesh mesh = GenMeshPoints(numPoints);
|
||||
Model model = LoadModelFromMesh(mesh);
|
||||
|
||||
//SetTargetFPS(60);
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
|
|
@ -92,15 +92,12 @@ int main()
|
|||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(BLACK);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
// The new method only uploads the points once to the GPU
|
||||
if (useDrawModelPoints)
|
||||
{
|
||||
DrawModelPoints(model, position, 1.0f, WHITE);
|
||||
}
|
||||
if (useDrawModelPoints) DrawModelPoints(model, position, 1.0f, WHITE);
|
||||
else
|
||||
{
|
||||
// The old method must continually draw the "points" (lines)
|
||||
|
|
@ -124,17 +121,16 @@ int main()
|
|||
|
||||
// Draw a unit sphere for reference
|
||||
DrawSphereWires(position, 1.0f, 10, 10, YELLOW);
|
||||
|
||||
EndMode3D();
|
||||
|
||||
// Draw UI text
|
||||
DrawText(TextFormat("Point Count: %d", numPoints), 20, screenHeight - 50, 40, WHITE);
|
||||
DrawText("Up - increase points", 20, 70, 20, WHITE);
|
||||
DrawText("Down - decrease points", 20, 100, 20, WHITE);
|
||||
DrawText("Space - drawing function", 20, 130, 20, WHITE);
|
||||
DrawText(TextFormat("Point Count: %d", numPoints), 10, screenHeight - 50, 40, WHITE);
|
||||
DrawText("UP - Increase points", 10, 40, 20, WHITE);
|
||||
DrawText("DOWN - Decrease points", 10, 70, 20, WHITE);
|
||||
DrawText("SPACE - Drawing function", 10, 100, 20, WHITE);
|
||||
|
||||
if (useDrawModelPoints) DrawText("Using: DrawModelPoints()", 20, 160, 20, GREEN);
|
||||
else DrawText("Using: DrawPoint3D()", 20, 160, 20, RED);
|
||||
if (useDrawModelPoints) DrawText("Using: DrawModelPoints()", 10, 130, 20, GREEN);
|
||||
else DrawText("Using: DrawPoint3D()", 10, 130, 20, RED);
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,8 @@ int main(void)
|
|||
Mesh cube = GenMeshCube(1.0f, 1.0f, 1.0f);
|
||||
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;
|
||||
|
||||
// Load skybox shader and set required locations
|
||||
|
|
@ -91,9 +92,11 @@ int main(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
Image img = LoadImage("resources/skybox.png");
|
||||
skybox.materials[0].maps[MATERIAL_MAP_CUBEMAP].texture = LoadTextureCubemap(img, CUBEMAP_LAYOUT_AUTO_DETECT); // CUBEMAP_LAYOUT_PANORAMA
|
||||
UnloadImage(img);
|
||||
// TODO: WARNING: On PLATFORM_WEB it requires a big amount of memory to process input image
|
||||
// and generate the required cubemap image to be passed to rlLoadTextureCubemap()
|
||||
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
|
||||
|
|
@ -132,9 +135,9 @@ int main(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
Image img = LoadImage(droppedFiles.paths[0]);
|
||||
skybox.materials[0].maps[MATERIAL_MAP_CUBEMAP].texture = LoadTextureCubemap(img, CUBEMAP_LAYOUT_AUTO_DETECT);
|
||||
UnloadImage(img);
|
||||
Image image = LoadImage(droppedFiles.paths[0]);
|
||||
skybox.materials[0].maps[MATERIAL_MAP_CUBEMAP].texture = LoadTextureCubemap(image, CUBEMAP_LAYOUT_AUTO_DETECT);
|
||||
UnloadImage(image);
|
||||
}
|
||||
|
||||
TextCopy(skyboxFileName, droppedFiles.paths[0]);
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main()
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
|
|
|||
12
examples/models/resources/models/obj/character.mtl
Normal 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
|
||||
3454
examples/models/resources/models/obj/character.obj
Normal file
BIN
examples/models/resources/models/obj/character_diffuse.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
examples/models/resources/raylib_logo.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
examples/models/resources/skillbot.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
|
|
@ -36,7 +36,7 @@ void UpdateDrawFrame(void); // Update and Draw one frame
|
|||
//----------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//----------------------------------------------------------------------------------
|
||||
int main()
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
|
|
|||
5987
examples/shaders/raygui.h
Normal 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/) |
|
||||
| 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/) |
|
||||
| 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) |
|
||||
BIN
examples/shaders/resources/cat.png
Normal file
|
After Width: | Height: | Size: 379 KiB |
BIN
examples/shaders/resources/mandrill.png
Normal file
|
After Width: | Height: | Size: 193 KiB |
BIN
examples/shaders/resources/parrots.png
Normal file
|
After Width: | Height: | Size: 288 KiB |
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
#version 100
|
||||
|
||||
#extension GL_EXT_frag_depth : enable // Extension required for writing depth
|
||||
|
||||
precision mediump float; // Precision required for OpenGL ES2 (WebGL)
|
||||
|
||||
varying vec2 fragTexCoord;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
#extension GL_EXT_frag_depth : enable //Extension required for writing depth
|
||||
#extension GL_OES_standard_derivatives : enable //Extension used for fwidth()
|
||||
|
||||
#define ZERO 0
|
||||
|
||||
precision mediump float; // Precision required for OpenGL ES2 (WebGL)
|
||||
|
||||
// Input vertex attributes (from vertex shader)
|
||||
|
|
@ -17,8 +20,6 @@ uniform vec3 camPos;
|
|||
uniform vec3 camDir;
|
||||
uniform vec2 screenCenter;
|
||||
|
||||
#define ZERO 0
|
||||
|
||||
// SRC: https://learnopengl.com/Advanced-OpenGL/Depth-testing
|
||||
float CalcDepth(in vec3 rd, in float Idist)
|
||||
{
|
||||
|
|
@ -257,7 +258,8 @@ vec4 render(in vec3 ro, in vec3 rd)
|
|||
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 vertical = normalize(cross(horizontal,camDir));
|
||||
return normalize(camDir + horizontal*nCoord.x + vertical*nCoord.y);
|
||||
|
|
@ -287,6 +289,7 @@ void main()
|
|||
color = res.xyz;
|
||||
depth = CalcDepth(rd,res.w);
|
||||
}
|
||||
|
||||
gl_FragColor = vec4(color , 1.0);
|
||||
gl_FragDepthEXT = depth;
|
||||
}
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
#version 100
|
||||
|
||||
precision mediump float;
|
||||
|
||||
#extension GL_OES_standard_derivatives : enable
|
||||
|
||||
precision mediump float;
|
||||
|
||||
// Input vertex attributes (from vertex shader)
|
||||
varying vec2 fragTexCoord;
|
||||
varying vec4 fragColor;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@ uniform sampler2D texture0;
|
|||
uniform vec4 colDiffuse;
|
||||
|
||||
// Output fragment color
|
||||
//out vec4 finalColor;
|
||||
out vec4 finalColor;
|
||||
|
||||
// NOTE: Add your custom variables here
|
||||
|
||||
|
|
@ -17,6 +17,6 @@ void main()
|
|||
{
|
||||
vec4 texelColor = texture(texture0, fragTexCoord);
|
||||
|
||||
gl_FragColor = texelColor*colDiffuse*fragColor;
|
||||
gl_FragDepth = gl_FragCoord.z;
|
||||
finalColor = texelColor*colDiffuse*fragColor;
|
||||
gl_FragDepth = finalColor.z;
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
# version 330
|
||||
|
||||
#define ZERO 0
|
||||
|
||||
// Input vertex attributes (from vertex shader)
|
||||
in vec2 fragTexCoord;
|
||||
in vec4 fragColor;
|
||||
|
|
@ -13,10 +15,12 @@ uniform vec3 camPos;
|
|||
uniform vec3 camDir;
|
||||
uniform vec2 screenCenter;
|
||||
|
||||
#define ZERO 0
|
||||
// Output fragment color
|
||||
out vec4 finalColor;
|
||||
|
||||
// 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;
|
||||
return (1.0/(local_z) - 1.0/0.01)/(1.0/1000.0 -1.0/0.01);
|
||||
}
|
||||
|
|
@ -26,10 +30,8 @@ float sdHorseshoe(in vec3 p, in vec2 c, in float r, in float le, vec2 w)
|
|||
{
|
||||
p.x = abs(p.x);
|
||||
float l = length(p.xy);
|
||||
p.xy = mat2(-c.x, c.y,
|
||||
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 = mat2(-c.x, c.y, 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.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);
|
||||
|
|
@ -44,17 +46,16 @@ float sdSixWayCutHollowSphere(vec3 p, float r, float h, float t)
|
|||
{
|
||||
// Six way symetry Transformation
|
||||
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;
|
||||
else ap.xy = ap.yx;
|
||||
}
|
||||
|
||||
vec2 q = vec2(length(ap.yz), ap.x);
|
||||
|
||||
float w = sqrt(r*r-h*h);
|
||||
|
||||
return ((h*q.x<w*q.y) ? length(q-vec2(w,h)) :
|
||||
abs(length(q)-r)) - t;
|
||||
return ((h*q.x < w*q.y)? length(q - vec2(w, h)) : abs(length(q) - r)) - t;
|
||||
}
|
||||
|
||||
// https://iquilezles.org/articles/boxfunctions
|
||||
|
|
@ -65,8 +66,8 @@ vec2 iBox(in vec3 ro, in vec3 rd, in vec3 rad)
|
|||
vec3 k = abs(m)*rad;
|
||||
vec3 t1 = -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)
|
||||
|
|
@ -74,14 +75,17 @@ vec2 opU(vec2 d1, vec2 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));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
float tmin = 1.0;
|
||||
|
|
@ -111,7 +115,6 @@ vec2 raycast(in vec3 ro, in vec3 rd){
|
|||
return res;
|
||||
}
|
||||
|
||||
|
||||
// https://iquilezles.org/articles/rmshadows
|
||||
float calcSoftshadow(in vec3 ro, in vec3 rd, in float mint, in float tmax)
|
||||
{
|
||||
|
|
@ -126,12 +129,13 @@ float calcSoftshadow(in vec3 ro, in vec3 rd, in float mint, in float tmax)
|
|||
float s = clamp(8.0*h/t, 0.0, 1.0);
|
||||
res = min(res, s);
|
||||
t += clamp(h, 0.01, 0.2);
|
||||
if (res<0.004 || t>tmax) break;
|
||||
}
|
||||
res = clamp(res, 0.0, 1.0);
|
||||
return res*res*(3.0-2.0*res);
|
||||
if ((res < 0.004) || (t > tmax)) break;
|
||||
}
|
||||
|
||||
res = clamp(res, 0.0, 1.0);
|
||||
|
||||
return res*res*(3.0-2.0*res);
|
||||
}
|
||||
|
||||
// https://iquilezles.org/articles/normalsSDF
|
||||
vec3 calcNormal(in vec3 pos)
|
||||
|
|
@ -156,6 +160,7 @@ float calcAO(in vec3 pos, in vec3 nor)
|
|||
sca *= 0.95;
|
||||
if (occ>0.35) break;
|
||||
}
|
||||
|
||||
return clamp(1.0 - 3.0*occ, 0.0, 1.0)*(0.5+0.5*nor.y);
|
||||
}
|
||||
|
||||
|
|
@ -167,7 +172,7 @@ float checkersGradBox(in vec2 p)
|
|||
// 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;
|
||||
// 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
|
||||
|
|
@ -249,7 +254,8 @@ vec4 render(in vec3 ro, in vec3 rd)
|
|||
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 vertical = normalize(cross(horizontal,camDir));
|
||||
return normalize(camDir + horizontal*nCoord.x + vertical*nCoord.y);
|
||||
|
|
@ -279,6 +285,7 @@ void main()
|
|||
color = res.xyz;
|
||||
depth = CalcDepth(rd,res.w);
|
||||
}
|
||||
gl_FragColor = vec4(color , 1.0);
|
||||
|
||||
finalColor = vec4(color , 1.0);
|
||||
gl_FragDepth = depth;
|
||||
}
|
||||
|
|
@ -77,7 +77,7 @@ static void UpdateLight(Shader shader, Light light);
|
|||
//----------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//----------------------------------------------------------------------------------
|
||||
int main()
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
|
|
|||
148
examples/shaders/shaders_color_correction.c
Normal 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;
|
||||
}
|
||||
BIN
examples/shaders/shaders_color_correction.png
Normal file
|
After Width: | Height: | Size: 305 KiB |
|
|
@ -138,6 +138,7 @@ int main(void)
|
|||
ClearBackground(RAYWHITE);
|
||||
|
||||
DrawTextureRec(target.texture, (Rectangle) { 0, 0, (float)screenWidth, (float)-screenHeight }, (Vector2) { 0, 0 }, WHITE);
|
||||
|
||||
DrawFPS(10, 10);
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
#define GLSL_VERSION 100
|
||||
#endif
|
||||
|
||||
#define MAP_SIZE 10
|
||||
#define MAP_SIZE 16
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
|
|
@ -88,8 +88,6 @@ int main(void)
|
|||
|
||||
RenderTexture lightmap = LoadRenderTexture(MAP_SIZE, MAP_SIZE);
|
||||
|
||||
SetTextureFilter(lightmap.texture, TEXTURE_FILTER_TRILINEAR);
|
||||
|
||||
Material material = LoadMaterialDefault();
|
||||
material.shader = shader;
|
||||
material.maps[MATERIAL_MAP_ALBEDO].texture = texture;
|
||||
|
|
@ -103,30 +101,34 @@ int main(void)
|
|||
DrawTexturePro(
|
||||
light,
|
||||
(Rectangle){ 0, 0, (float)light.width, (float)light.height },
|
||||
(Rectangle){ 0, 0, 20, 20 },
|
||||
(Vector2){ 10.0, 10.0 },
|
||||
(Rectangle){ 0, 0, 2.0f*MAP_SIZE, 2.0f*MAP_SIZE },
|
||||
(Vector2){ (float)MAP_SIZE, (float)MAP_SIZE },
|
||||
0.0,
|
||||
RED
|
||||
);
|
||||
DrawTexturePro(
|
||||
light,
|
||||
(Rectangle){ 0, 0, (float)light.width, (float)light.height },
|
||||
(Rectangle){ 8, 4, 20, 20 },
|
||||
(Vector2){ 10.0, 10.0 },
|
||||
(Rectangle){ (float)MAP_SIZE*0.8f, (float)MAP_SIZE/2.0f, 2.0f*MAP_SIZE, 2.0f*MAP_SIZE },
|
||||
(Vector2){ (float)MAP_SIZE, (float)MAP_SIZE },
|
||||
0.0,
|
||||
BLUE
|
||||
);
|
||||
DrawTexturePro(
|
||||
light,
|
||||
(Rectangle){ 0, 0, (float)light.width, (float)light.height },
|
||||
(Rectangle){ 8, 8, 10, 10 },
|
||||
(Vector2){ 5.0, 5.0 },
|
||||
(Rectangle){ (float)MAP_SIZE*0.8f, (float)MAP_SIZE*0.8f, (float)MAP_SIZE, (float)MAP_SIZE },
|
||||
(Vector2){ (float)MAP_SIZE/2.0f, (float)MAP_SIZE/2.0f },
|
||||
0.0,
|
||||
GREEN
|
||||
);
|
||||
BeginBlendMode(BLEND_ALPHA);
|
||||
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
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -141,24 +143,20 @@ int main(void)
|
|||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
BeginMode3D(camera);
|
||||
DrawMesh(mesh, material, MatrixIdentity());
|
||||
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 },
|
||||
(Vector2){ 0.0, 0.0 },
|
||||
0.0,
|
||||
WHITE);
|
||||
(Vector2){ 0.0, 0.0 }, 0.0, WHITE);
|
||||
|
||||
DrawText("lightmap", GetRenderWidth() - 66, 16 + MAP_SIZE*8, 10, GRAY);
|
||||
DrawText("10x10 pixels", GetRenderWidth() - 76, 30 + MAP_SIZE*8, 10, GRAY);
|
||||
DrawText(TextFormat("LIGHTMAP: %ix%i pixels", MAP_SIZE, MAP_SIZE), GetRenderWidth() - 130, 20 + MAP_SIZE*8, 10, GREEN);
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -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 },
|
||||
/* 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
|
||||
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;
|
||||
|
||||
// This represents the real position where the hands are right now
|
||||
Vector2 currentAngles[6][24] = { 0 };
|
||||
|
||||
// This is the position where the hands were moving from
|
||||
Vector2 srcAngles[6][24] = { 0 };
|
||||
// This is the position where the hands are moving to
|
||||
Vector2 dstAngles[6][24] = { 0 };
|
||||
|
||||
// Current animation timer
|
||||
float handsMoveTimer = 0.0f;
|
||||
|
||||
// 12 or 24 hour mode
|
||||
int hourMode = 24;
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
|
|
@ -88,7 +80,6 @@ int main(void)
|
|||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Get the current time
|
||||
time_t rawtime;
|
||||
struct tm *timeinfo;
|
||||
|
|
@ -96,7 +87,8 @@ int main(void)
|
|||
time(&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
|
||||
prevSeconds = timeinfo->tm_sec;
|
||||
|
||||
|
|
@ -104,22 +96,17 @@ int main(void)
|
|||
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
|
||||
for (int digit = 0; digit < 6; digit++) {
|
||||
for (int cell = 0; cell < 24; cell++) {
|
||||
for (int digit = 0; digit < 6; digit++)
|
||||
{
|
||||
for (int cell = 0; cell < 24; cell++)
|
||||
{
|
||||
srcAngles[digit][cell] = currentAngles[digit][cell];
|
||||
dstAngles[digit][cell] = digitAngles[clockDigits[digit] - '0'][cell];
|
||||
|
||||
// Quick exception for 12h mode
|
||||
if (digit == 0 && hourMode == 12 && clockDigits[0] == '0') {
|
||||
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 ((digit == 0) && (hourMode == 12) && (clockDigits[0] == '0')) 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -128,7 +115,8 @@ int main(void)
|
|||
}
|
||||
|
||||
// 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
|
||||
handsMoveTimer = Clamp(handsMoveTimer + GetFrameTime(), 0, handsMoveDuration);
|
||||
|
||||
|
|
@ -138,27 +126,18 @@ int main(void)
|
|||
// A little cheeky smoothstep
|
||||
t = t*t*(3.0f - 2.0f*t);
|
||||
|
||||
for (int digit = 0; digit < 6; digit++) {
|
||||
for (int cell = 0; cell < 24; cell++) {
|
||||
for (int digit = 0; digit < 6; digit++)
|
||||
{
|
||||
for (int cell = 0; cell < 24; cell++)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
if (handsMoveTimer == handsMoveDuration) {
|
||||
// The animation has now finished
|
||||
}
|
||||
}
|
||||
|
||||
// Handle input
|
||||
|
||||
// Toggle between 12 and 24 hour mode with space
|
||||
if (IsKeyPressed(KEY_SPACE)) {
|
||||
hourMode = 36 - hourMode;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (IsKeyPressed(KEY_SPACE)) hourMode = 36 - hourMode; // Toggle between 12 and 24 hour mode with space
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
|
|
@ -171,19 +150,22 @@ int main(void)
|
|||
|
||||
float xOffset = 4.0f;
|
||||
|
||||
for (int digit = 0; digit < 6; digit++) {
|
||||
|
||||
for (int row = 0; row < 6; row++) {
|
||||
for (int col = 0; col < 4; col++) {
|
||||
for (int digit = 0; digit < 6; digit++)
|
||||
{
|
||||
for (int row = 0; row < 6; row++)
|
||||
{
|
||||
for (int col = 0; col < 4; col++)
|
||||
{
|
||||
Vector2 centre = (Vector2){
|
||||
xOffset + col*(clockFaceSize+clockFaceSpacing) + clockFaceSize * .5f,
|
||||
100 + row*(clockFaceSize+clockFaceSpacing) + clockFaceSize * .5f
|
||||
xOffset + col*(clockFaceSize+clockFaceSpacing) + clockFaceSize*0.5f,
|
||||
100 + row*(clockFaceSize+clockFaceSpacing) + clockFaceSize*0.5f
|
||||
};
|
||||
|
||||
DrawRing(centre, clockFaceSize*0.5f - 2.0f, clockFaceSize*0.5f, 0, 360, 24, DARKGRAY);
|
||||
|
||||
// Big hand
|
||||
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 },
|
||||
currentAngles[digit][row*4+col].x,
|
||||
handsColor
|
||||
|
|
@ -191,7 +173,7 @@ int main(void)
|
|||
|
||||
// Little hand
|
||||
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 },
|
||||
currentAngles[digit][row*4+col].y,
|
||||
handsColor
|
||||
|
|
@ -200,26 +182,22 @@ int main(void)
|
|||
}
|
||||
|
||||
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, 225.0f}, 6.0f, 8.0f, 0.0f, 360.0f, 24, handsColor);
|
||||
|
||||
xOffset += sectionSpacing;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -284,11 +284,13 @@ static void DrawDisplaySegment(Vector2 center, int length, int thick, bool verti
|
|||
if (!vertical)
|
||||
{
|
||||
// Horizontal segment points
|
||||
// 3___________________________5
|
||||
// / \
|
||||
// /1 x 6\
|
||||
// \ /
|
||||
// \2___________________________4/
|
||||
/*
|
||||
3___________________________5
|
||||
/ \
|
||||
/1 x 6\
|
||||
\ /
|
||||
\2___________________________4/
|
||||
*/
|
||||
Vector2 segmentPointsH[6] = {
|
||||
(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
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ int main(void)
|
|||
float step = dt/SIMULATION_STEPS, step2 = step*step;
|
||||
|
||||
// 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 sinD = sinf(delta), cosD = cosf(delta), cos2D = cosf(2*delta);
|
||||
|
|
|
|||
|
|
@ -11,13 +11,29 @@
|
|||
* 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 Hugo ARNAL (@hugoarnal)
|
||||
* Copyright (c) 2025 Hugo ARNAL (@hugoarnal) and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
#include <string.h>
|
||||
|
||||
#define RAYGUI_IMPLEMENTATION
|
||||
#include "raygui.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
|
||||
//------------------------------------------------------------------------------------
|
||||
|
|
@ -30,22 +46,31 @@ int main(void)
|
|||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - kaleidoscope");
|
||||
|
||||
// Line drawing properties
|
||||
int symmetry = 6;
|
||||
float angle = 360.0f/(float)symmetry;
|
||||
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 };
|
||||
|
||||
SetTargetFPS(60);
|
||||
ClearBackground(BLACK);
|
||||
|
||||
Vector2 scaleVector = { 1.0f, -1.0f };
|
||||
Vector2 offset = { (float)screenWidth/2.0f, (float)screenHeight/2.0f };
|
||||
|
||||
Camera2D camera = { 0 };
|
||||
camera.target = (Vector2){ 0 };
|
||||
camera.offset = offset;
|
||||
camera.rotation = 0.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
|
||||
|
|
@ -53,38 +78,93 @@ int main(void)
|
|||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
Vector2 mousePos = GetMousePosition();
|
||||
prevMousePos = mousePos;
|
||||
mousePos = GetMousePosition();
|
||||
|
||||
Vector2 lineStart = Vector2Subtract(mousePos, 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
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
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);
|
||||
|
||||
Vector2 reflectLineStart = Vector2Multiply(lineStart, scaleVector);
|
||||
Vector2 reflectLineEnd = Vector2Multiply(lineEnd, scaleVector);
|
||||
|
||||
DrawLineEx(reflectLineStart, reflectLineEnd, thickness, WHITE);
|
||||
for (int s = 0; s < symmetry; s++)
|
||||
{
|
||||
for (int i = 0; i < currentLineCounter; i += 2)
|
||||
{
|
||||
DrawLineEx(lines[i].start, lines[i].end, thickness, BLACK);
|
||||
DrawLineEx(lines[i + 1].start, lines[i + 1].end, thickness, BLACK);
|
||||
}
|
||||
}
|
||||
|
||||
prevMousePos = mousePos;
|
||||
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();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 81 KiB |
|
|
@ -11,11 +11,12 @@
|
|||
* 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-2025 Robin (@RobinsAviary)
|
||||
* Copyright (c) 2025 Robin (@RobinsAviary)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#include "raymath.h"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
|
|
@ -39,9 +40,6 @@ int main(void)
|
|||
// The canvas to draw lines on
|
||||
RenderTexture canvas = LoadRenderTexture(screenWidth, screenHeight);
|
||||
|
||||
// The background color of the canvas
|
||||
const Color backgroundColor = RAYWHITE;
|
||||
|
||||
// The line's thickness
|
||||
float lineThickness = 8.0f;
|
||||
// The lines hue (in HSV, from 0-360)
|
||||
|
|
@ -49,8 +47,10 @@ int main(void)
|
|||
|
||||
// Clear the canvas to the background color
|
||||
BeginTextureMode(canvas);
|
||||
ClearBackground(backgroundColor);
|
||||
ClearBackground(RAYWHITE);
|
||||
EndTextureMode();
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
|
|
@ -59,16 +59,13 @@ int main(void)
|
|||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// Disable the hint text once the user clicks
|
||||
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && startText)
|
||||
{
|
||||
startText = false;
|
||||
}
|
||||
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && startText) startText = false;
|
||||
|
||||
// Clear the canvas when the user middle-clicks
|
||||
if (IsMouseButtonPressed(MOUSE_BUTTON_MIDDLE))
|
||||
{
|
||||
BeginTextureMode(canvas);
|
||||
ClearBackground(backgroundColor);
|
||||
ClearBackground(RAYWHITE);
|
||||
EndTextureMode();
|
||||
}
|
||||
|
||||
|
|
@ -79,7 +76,7 @@ int main(void)
|
|||
if (leftButtonDown || rightButtonDown)
|
||||
{
|
||||
// The color for the line
|
||||
Color drawColor;
|
||||
Color drawColor = WHITE;
|
||||
|
||||
if (leftButtonDown)
|
||||
{
|
||||
|
|
@ -88,19 +85,12 @@ int main(void)
|
|||
|
||||
// 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
|
||||
while (lineHue >= 360.0f)
|
||||
{
|
||||
lineHue -= 360.0f;
|
||||
}
|
||||
while (lineHue >= 360.0f) lineHue -= 360.0f;
|
||||
|
||||
// Create the final color
|
||||
drawColor = ColorFromHSV(lineHue, 1.0f, 1.0f);
|
||||
}
|
||||
else if (rightButtonDown)
|
||||
{
|
||||
// Use the background color as an "eraser"
|
||||
drawColor = backgroundColor;
|
||||
}
|
||||
else if (rightButtonDown) drawColor = RAYWHITE; // Use the background color as an "eraser"
|
||||
|
||||
// Draw the line onto the canvas
|
||||
BeginTextureMode(canvas);
|
||||
|
|
@ -122,6 +112,7 @@ int main(void)
|
|||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
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);
|
||||
|
||||
|
|
@ -130,14 +121,14 @@ int main(void)
|
|||
|
||||
// Draw the hint text
|
||||
if (startText) DrawText("try clicking and dragging!", 275, 215, 20, LIGHTGRAY);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Unload the canvas render texture
|
||||
UnloadRenderTexture(canvas);
|
||||
UnloadRenderTexture(canvas); // Unload the canvas render texture
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
|
|
|||
105
examples/shapes/shapes_math_angle_rotation.c
Normal 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;
|
||||
}
|
||||
BIN
examples/shapes/shapes_math_angle_rotation.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
177
examples/shapes/shapes_math_sine_cosine.c
Normal 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;
|
||||
}
|
||||
BIN
examples/shapes/shapes_math_sine_cosine.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
|
|
@ -112,7 +112,7 @@ int main(void)
|
|||
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, 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);
|
||||
GuiCheckBox((Rectangle){ 640, 190, 20, 20 }, "Bezier", &bezier);
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
|
|||
274
examples/shapes/shapes_rlgl_color_wheel.c
Normal 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;
|
||||
}
|
||||
BIN
examples/shapes/shapes_rlgl_color_wheel.png
Normal file
|
After Width: | Height: | Size: 67 KiB |
169
examples/shapes/shapes_rlgl_triangle.c
Normal 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;
|
||||
}
|
||||
BIN
examples/shapes/shapes_rlgl_triangle.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
|
|
@ -95,7 +95,7 @@ int main(void)
|
|||
}
|
||||
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
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ int main(void)
|
|||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - triangle strip");
|
||||
|
||||
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 insideRadius = 100.0f;
|
||||
float outsideRadius = 150.0f;
|
||||
|
|
@ -92,7 +92,7 @@ int main(void)
|
|||
|
||||
// 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);
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -231,7 +231,7 @@ int main(void)
|
|||
if (multicolor)
|
||||
{
|
||||
// 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].a = GetRandomValue(0, 255);
|
||||
|
|
@ -296,7 +296,7 @@ int main(void)
|
|||
rlRotatef(90.0f, 1.0f, 0.0f, 0.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;
|
||||
if (multicolor) clr = multi[i];
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
* - TTF/OTF > Sprite font atlas is generated on loading, user can configure
|
||||
* some of the generation parameters (size, characters to include)
|
||||
* - 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,
|
||||
* Characters in image must follow some spacing and order rules
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
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 textHeight = fontSize;
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ int main(void)
|
|||
|
||||
// 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];
|
||||
Rectangle emojiRect = { position.x, position.y, (float)fontEmoji.baseSize, (float)fontEmoji.baseSize };
|
||||
|
|
@ -316,7 +316,7 @@ static void RandomizeEmoji(void)
|
|||
hovered = selected = -1;
|
||||
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
|
||||
emoji[i].index = GetRandomValue(0, 179)*5;
|
||||
|
|
|
|||
|
|
@ -70,27 +70,32 @@ int main(void)
|
|||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
if (IsKeyPressed(KEY_LEFT)) {
|
||||
if (IsKeyPressed(KEY_LEFT))
|
||||
{
|
||||
hAlign = hAlign - 1;
|
||||
if (hAlign < 0) hAlign = 0;
|
||||
}
|
||||
if (IsKeyPressed(KEY_RIGHT)) {
|
||||
|
||||
if (IsKeyPressed(KEY_RIGHT))
|
||||
{
|
||||
hAlign = hAlign + 1;
|
||||
if (hAlign > 2) hAlign = 2;
|
||||
}
|
||||
if (IsKeyPressed(KEY_UP)) {
|
||||
|
||||
if (IsKeyPressed(KEY_UP))
|
||||
{
|
||||
vAlign = vAlign - 1;
|
||||
if (vAlign < 0) vAlign = 0;
|
||||
}
|
||||
if (IsKeyPressed(KEY_DOWN)) {
|
||||
|
||||
if (IsKeyPressed(KEY_DOWN))
|
||||
{
|
||||
vAlign = vAlign + 1;
|
||||
if (vAlign > 2) vAlign = 2;
|
||||
}
|
||||
|
||||
// One word per second
|
||||
wordIndex = (int)GetTime()%wordCount;
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
| explosion.png | [Unity Labs Paris](https://blogs.unity3d.com/2016/11/28/free-vfx-image-sequences-flipbooks/) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) |
|
||||
| parrots.png | [Kodak set](http://r0k.us/graphics/kodak/) | ❔ | Original name: `kodim23.png`
|
||||
| cat.png | ❔ | ❔ | - |
|
||||
| wabbit_alpha.png | ❔ | ❔ | - |
|
||||
| raybunny.png | [VoidSrc*](https://x.com/voidsrc) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - |
|
||||
| custom_jupiter_crash.png | [Brian Kent (AEnigma)](https://www.dafont.com/es/aenigma.d188) | [Freeware](https://www.dafont.com/es/jupiter-crash.font) | Atlas created by [@raysan5](https://github.com/raysan5) |
|
||||
| KAISG.ttf | [Dieter Steffmann](http://www.steffmann.de/wordpress/) | [Freeware](https://www.1001fonts.com/users/steffmann/) | [Kaiserzeit Gotisch](https://www.dafont.com/es/kaiserzeit-gotisch.font) font |
|
||||
| fudesumi.png | [Eiden Marsal](https://www.artstation.com/marshall_z) | [CC-BY-NC](https://creativecommons.org/licenses/by-nc/4.0/) | - |
|
||||
|
|
|
|||
BIN
examples/textures/resources/booth.png
Normal file
|
After Width: | Height: | Size: 62 KiB |
BIN
examples/textures/resources/raybunny.png
Normal file
|
After Width: | Height: | Size: 466 B |
|
Before Width: | Height: | Size: 496 B |
|
|
@ -45,7 +45,7 @@ int main(void)
|
|||
InitWindow(screenWidth, screenHeight, "raylib [textures] example - bunnymark");
|
||||
|
||||
// Load bunny texture
|
||||
Texture2D texBunny = LoadTexture("resources/wabbit_alpha.png");
|
||||
Texture2D texBunny = LoadTexture("resources/raybunny.png");
|
||||
|
||||
Bunny *bunnies = (Bunny *)malloc(MAX_BUNNIES*sizeof(Bunny)); // Bunnies array
|
||||
|
||||
|
|
|
|||