aboutsummaryrefslogtreecommitdiff
path: root/vendor/raylib-5.5_macos/include
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/raylib-5.5_macos/include')
-rw-r--r--vendor/raylib-5.5_macos/include/raylib.h1708
-rw-r--r--vendor/raylib-5.5_macos/include/raymath.h2941
-rw-r--r--vendor/raylib-5.5_macos/include/rlgl.h5262
3 files changed, 9911 insertions, 0 deletions
diff --git a/vendor/raylib-5.5_macos/include/raylib.h b/vendor/raylib-5.5_macos/include/raylib.h
new file mode 100644
index 0000000..a26b8ce
--- /dev/null
+++ b/vendor/raylib-5.5_macos/include/raylib.h
@@ -0,0 +1,1708 @@
1/**********************************************************************************************
2*
3* raylib v5.5 - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com)
4*
5* FEATURES:
6* - NO external dependencies, all required libraries included with raylib
7* - Multiplatform: Windows, Linux, FreeBSD, OpenBSD, NetBSD, DragonFly,
8* MacOS, Haiku, Android, Raspberry Pi, DRM native, HTML5.
9* - Written in plain C code (C99) in PascalCase/camelCase notation
10* - Hardware accelerated with OpenGL (1.1, 2.1, 3.3, 4.3, ES2, ES3 - choose at compile)
11* - Unique OpenGL abstraction layer (usable as standalone module): [rlgl]
12* - Multiple Fonts formats supported (TTF, OTF, FNT, BDF, Sprite fonts)
13* - Outstanding texture formats support, including compressed formats (DXT, ETC, ASTC)
14* - Full 3d support for 3d Shapes, Models, Billboards, Heightmaps and more!
15* - Flexible Materials system, supporting classic maps and PBR maps
16* - Animated 3D models supported (skeletal bones animation) (IQM, M3D, GLTF)
17* - Shaders support, including Model shaders and Postprocessing shaders
18* - Powerful math module for Vector, Matrix and Quaternion operations: [raymath]
19* - Audio loading and playing with streaming support (WAV, OGG, MP3, FLAC, QOA, XM, MOD)
20* - VR stereo rendering with configurable HMD device parameters
21* - Bindings to multiple programming languages available!
22*
23* NOTES:
24* - One default Font is loaded on InitWindow()->LoadFontDefault() [core, text]
25* - One default Texture2D is loaded on rlglInit(), 1x1 white pixel R8G8B8A8 [rlgl] (OpenGL 3.3 or ES2)
26* - One default Shader is loaded on rlglInit()->rlLoadShaderDefault() [rlgl] (OpenGL 3.3 or ES2)
27* - One default RenderBatch is loaded on rlglInit()->rlLoadRenderBatch() [rlgl] (OpenGL 3.3 or ES2)
28*
29* DEPENDENCIES (included):
30* [rcore][GLFW] rglfw (Camilla Löwy - github.com/glfw/glfw) for window/context management and input
31* [rcore][RGFW] rgfw (ColleagueRiley - github.com/ColleagueRiley/RGFW) for window/context management and input
32* [rlgl] glad/glad_gles2 (David Herberth - github.com/Dav1dde/glad) for OpenGL 3.3 extensions loading
33* [raudio] miniaudio (David Reid - github.com/mackron/miniaudio) for audio device/context management
34*
35* OPTIONAL DEPENDENCIES (included):
36* [rcore] msf_gif (Miles Fogle) for GIF recording
37* [rcore] sinfl (Micha Mettke) for DEFLATE decompression algorithm
38* [rcore] sdefl (Micha Mettke) for DEFLATE compression algorithm
39* [rcore] rprand (Ramon Snatamaria) for pseudo-random numbers generation
40* [rtextures] qoi (Dominic Szablewski - https://phoboslab.org) for QOI image manage
41* [rtextures] stb_image (Sean Barret) for images loading (BMP, TGA, PNG, JPEG, HDR...)
42* [rtextures] stb_image_write (Sean Barret) for image writing (BMP, TGA, PNG, JPG)
43* [rtextures] stb_image_resize2 (Sean Barret) for image resizing algorithms
44* [rtextures] stb_perlin (Sean Barret) for Perlin Noise image generation
45* [rtext] stb_truetype (Sean Barret) for ttf fonts loading
46* [rtext] stb_rect_pack (Sean Barret) for rectangles packing
47* [rmodels] par_shapes (Philip Rideout) for parametric 3d shapes generation
48* [rmodels] tinyobj_loader_c (Syoyo Fujita) for models loading (OBJ, MTL)
49* [rmodels] cgltf (Johannes Kuhlmann) for models loading (glTF)
50* [rmodels] m3d (bzt) for models loading (M3D, https://bztsrc.gitlab.io/model3d)
51* [rmodels] vox_loader (Johann Nadalutti) for models loading (VOX)
52* [raudio] dr_wav (David Reid) for WAV audio file loading
53* [raudio] dr_flac (David Reid) for FLAC audio file loading
54* [raudio] dr_mp3 (David Reid) for MP3 audio file loading
55* [raudio] stb_vorbis (Sean Barret) for OGG audio loading
56* [raudio] jar_xm (Joshua Reisenauer) for XM audio module loading
57* [raudio] jar_mod (Joshua Reisenauer) for MOD audio module loading
58* [raudio] qoa (Dominic Szablewski - https://phoboslab.org) for QOA audio manage
59*
60*
61* LICENSE: zlib/libpng
62*
63* raylib is licensed under an unmodified zlib/libpng license, which is an OSI-certified,
64* BSD-like license that allows static linking with closed source software:
65*
66* Copyright (c) 2013-2024 Ramon Santamaria (@raysan5)
67*
68* This software is provided "as-is", without any express or implied warranty. In no event
69* will the authors be held liable for any damages arising from the use of this software.
70*
71* Permission is granted to anyone to use this software for any purpose, including commercial
72* applications, and to alter it and redistribute it freely, subject to the following restrictions:
73*
74* 1. The origin of this software must not be misrepresented; you must not claim that you
75* wrote the original software. If you use this software in a product, an acknowledgment
76* in the product documentation would be appreciated but is not required.
77*
78* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
79* as being the original software.
80*
81* 3. This notice may not be removed or altered from any source distribution.
82*
83**********************************************************************************************/
84
85#ifndef RAYLIB_H
86#define RAYLIB_H
87
88#include <stdarg.h> // Required for: va_list - Only used by TraceLogCallback
89
90#define RAYLIB_VERSION_MAJOR 5
91#define RAYLIB_VERSION_MINOR 5
92#define RAYLIB_VERSION_PATCH 0
93#define RAYLIB_VERSION "5.5"
94
95// Function specifiers in case library is build/used as a shared library
96// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll
97// NOTE: visibility("default") attribute makes symbols "visible" when compiled with -fvisibility=hidden
98#if defined(_WIN32)
99 #if defined(__TINYC__)
100 #define __declspec(x) __attribute__((x))
101 #endif
102 #if defined(BUILD_LIBTYPE_SHARED)
103 #define RLAPI __declspec(dllexport) // We are building the library as a Win32 shared library (.dll)
104 #elif defined(USE_LIBTYPE_SHARED)
105 #define RLAPI __declspec(dllimport) // We are using the library as a Win32 shared library (.dll)
106 #endif
107#else
108 #if defined(BUILD_LIBTYPE_SHARED)
109 #define RLAPI __attribute__((visibility("default"))) // We are building as a Unix shared library (.so/.dylib)
110 #endif
111#endif
112
113#ifndef RLAPI
114 #define RLAPI // Functions defined as 'extern' by default (implicit specifiers)
115#endif
116
117//----------------------------------------------------------------------------------
118// Some basic Defines
119//----------------------------------------------------------------------------------
120#ifndef PI
121 #define PI 3.14159265358979323846f
122#endif
123#ifndef DEG2RAD
124 #define DEG2RAD (PI/180.0f)
125#endif
126#ifndef RAD2DEG
127 #define RAD2DEG (180.0f/PI)
128#endif
129
130// Allow custom memory allocators
131// NOTE: Require recompiling raylib sources
132#ifndef RL_MALLOC
133 #define RL_MALLOC(sz) malloc(sz)
134#endif
135#ifndef RL_CALLOC
136 #define RL_CALLOC(n,sz) calloc(n,sz)
137#endif
138#ifndef RL_REALLOC
139 #define RL_REALLOC(ptr,sz) realloc(ptr,sz)
140#endif
141#ifndef RL_FREE
142 #define RL_FREE(ptr) free(ptr)
143#endif
144
145// NOTE: MSVC C++ compiler does not support compound literals (C99 feature)
146// Plain structures in C++ (without constructors) can be initialized with { }
147// This is called aggregate initialization (C++11 feature)
148#if defined(__cplusplus)
149 #define CLITERAL(type) type
150#else
151 #define CLITERAL(type) (type)
152#endif
153
154// Some compilers (mostly macos clang) default to C++98,
155// where aggregate initialization can't be used
156// So, give a more clear error stating how to fix this
157#if !defined(_MSC_VER) && (defined(__cplusplus) && __cplusplus < 201103L)
158 #error "C++11 or later is required. Add -std=c++11"
159#endif
160
161// NOTE: We set some defines with some data types declared by raylib
162// Other modules (raymath, rlgl) also require some of those types, so,
163// to be able to use those other modules as standalone (not depending on raylib)
164// this defines are very useful for internal check and avoid type (re)definitions
165#define RL_COLOR_TYPE
166#define RL_RECTANGLE_TYPE
167#define RL_VECTOR2_TYPE
168#define RL_VECTOR3_TYPE
169#define RL_VECTOR4_TYPE
170#define RL_QUATERNION_TYPE
171#define RL_MATRIX_TYPE
172
173// Some Basic Colors
174// NOTE: Custom raylib color palette for amazing visuals on WHITE background
175#define LIGHTGRAY CLITERAL(Color){ 200, 200, 200, 255 } // Light Gray
176#define GRAY CLITERAL(Color){ 130, 130, 130, 255 } // Gray
177#define DARKGRAY CLITERAL(Color){ 80, 80, 80, 255 } // Dark Gray
178#define YELLOW CLITERAL(Color){ 253, 249, 0, 255 } // Yellow
179#define GOLD CLITERAL(Color){ 255, 203, 0, 255 } // Gold
180#define ORANGE CLITERAL(Color){ 255, 161, 0, 255 } // Orange
181#define PINK CLITERAL(Color){ 255, 109, 194, 255 } // Pink
182#define RED CLITERAL(Color){ 230, 41, 55, 255 } // Red
183#define MAROON CLITERAL(Color){ 190, 33, 55, 255 } // Maroon
184#define GREEN CLITERAL(Color){ 0, 228, 48, 255 } // Green
185#define LIME CLITERAL(Color){ 0, 158, 47, 255 } // Lime
186#define DARKGREEN CLITERAL(Color){ 0, 117, 44, 255 } // Dark Green
187#define SKYBLUE CLITERAL(Color){ 102, 191, 255, 255 } // Sky Blue
188#define BLUE CLITERAL(Color){ 0, 121, 241, 255 } // Blue
189#define DARKBLUE CLITERAL(Color){ 0, 82, 172, 255 } // Dark Blue
190#define PURPLE CLITERAL(Color){ 200, 122, 255, 255 } // Purple
191#define VIOLET CLITERAL(Color){ 135, 60, 190, 255 } // Violet
192#define DARKPURPLE CLITERAL(Color){ 112, 31, 126, 255 } // Dark Purple
193#define BEIGE CLITERAL(Color){ 211, 176, 131, 255 } // Beige
194#define BROWN CLITERAL(Color){ 127, 106, 79, 255 } // Brown
195#define DARKBROWN CLITERAL(Color){ 76, 63, 47, 255 } // Dark Brown
196
197#define WHITE CLITERAL(Color){ 255, 255, 255, 255 } // White
198#define BLACK CLITERAL(Color){ 0, 0, 0, 255 } // Black
199#define BLANK CLITERAL(Color){ 0, 0, 0, 0 } // Blank (Transparent)
200#define MAGENTA CLITERAL(Color){ 255, 0, 255, 255 } // Magenta
201#define RAYWHITE CLITERAL(Color){ 245, 245, 245, 255 } // My own White (raylib logo)
202
203//----------------------------------------------------------------------------------
204// Structures Definition
205//----------------------------------------------------------------------------------
206// Boolean type
207#if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
208 #include <stdbool.h>
209#elif !defined(__cplusplus) && !defined(bool)
210 typedef enum bool { false = 0, true = !false } bool;
211 #define RL_BOOL_TYPE
212#endif
213
214// Vector2, 2 components
215typedef struct Vector2 {
216 float x; // Vector x component
217 float y; // Vector y component
218} Vector2;
219
220// Vector3, 3 components
221typedef struct Vector3 {
222 float x; // Vector x component
223 float y; // Vector y component
224 float z; // Vector z component
225} Vector3;
226
227// Vector4, 4 components
228typedef struct Vector4 {
229 float x; // Vector x component
230 float y; // Vector y component
231 float z; // Vector z component
232 float w; // Vector w component
233} Vector4;
234
235// Quaternion, 4 components (Vector4 alias)
236typedef Vector4 Quaternion;
237
238// Matrix, 4x4 components, column major, OpenGL style, right-handed
239typedef struct Matrix {
240 float m0, m4, m8, m12; // Matrix first row (4 components)
241 float m1, m5, m9, m13; // Matrix second row (4 components)
242 float m2, m6, m10, m14; // Matrix third row (4 components)
243 float m3, m7, m11, m15; // Matrix fourth row (4 components)
244} Matrix;
245
246// Color, 4 components, R8G8B8A8 (32bit)
247typedef struct Color {
248 unsigned char r; // Color red value
249 unsigned char g; // Color green value
250 unsigned char b; // Color blue value
251 unsigned char a; // Color alpha value
252} Color;
253
254// Rectangle, 4 components
255typedef struct Rectangle {
256 float x; // Rectangle top-left corner position x
257 float y; // Rectangle top-left corner position y
258 float width; // Rectangle width
259 float height; // Rectangle height
260} Rectangle;
261
262// Image, pixel data stored in CPU memory (RAM)
263typedef struct Image {
264 void *data; // Image raw data
265 int width; // Image base width
266 int height; // Image base height
267 int mipmaps; // Mipmap levels, 1 by default
268 int format; // Data format (PixelFormat type)
269} Image;
270
271// Texture, tex data stored in GPU memory (VRAM)
272typedef struct Texture {
273 unsigned int id; // OpenGL texture id
274 int width; // Texture base width
275 int height; // Texture base height
276 int mipmaps; // Mipmap levels, 1 by default
277 int format; // Data format (PixelFormat type)
278} Texture;
279
280// Texture2D, same as Texture
281typedef Texture Texture2D;
282
283// TextureCubemap, same as Texture
284typedef Texture TextureCubemap;
285
286// RenderTexture, fbo for texture rendering
287typedef struct RenderTexture {
288 unsigned int id; // OpenGL framebuffer object id
289 Texture texture; // Color buffer attachment texture
290 Texture depth; // Depth buffer attachment texture
291} RenderTexture;
292
293// RenderTexture2D, same as RenderTexture
294typedef RenderTexture RenderTexture2D;
295
296// NPatchInfo, n-patch layout info
297typedef struct NPatchInfo {
298 Rectangle source; // Texture source rectangle
299 int left; // Left border offset
300 int top; // Top border offset
301 int right; // Right border offset
302 int bottom; // Bottom border offset
303 int layout; // Layout of the n-patch: 3x3, 1x3 or 3x1
304} NPatchInfo;
305
306// GlyphInfo, font characters glyphs info
307typedef struct GlyphInfo {
308 int value; // Character value (Unicode)
309 int offsetX; // Character offset X when drawing
310 int offsetY; // Character offset Y when drawing
311 int advanceX; // Character advance position X
312 Image image; // Character image data
313} GlyphInfo;
314
315// Font, font texture and GlyphInfo array data
316typedef struct Font {
317 int baseSize; // Base size (default chars height)
318 int glyphCount; // Number of glyph characters
319 int glyphPadding; // Padding around the glyph characters
320 Texture2D texture; // Texture atlas containing the glyphs
321 Rectangle *recs; // Rectangles in texture for the glyphs
322 GlyphInfo *glyphs; // Glyphs info data
323} Font;
324
325// Camera, defines position/orientation in 3d space
326typedef struct Camera3D {
327 Vector3 position; // Camera position
328 Vector3 target; // Camera target it looks-at
329 Vector3 up; // Camera up vector (rotation over its axis)
330 float fovy; // Camera field-of-view aperture in Y (degrees) in perspective, used as near plane width in orthographic
331 int projection; // Camera projection: CAMERA_PERSPECTIVE or CAMERA_ORTHOGRAPHIC
332} Camera3D;
333
334typedef Camera3D Camera; // Camera type fallback, defaults to Camera3D
335
336// Camera2D, defines position/orientation in 2d space
337typedef struct Camera2D {
338 Vector2 offset; // Camera offset (displacement from target)
339 Vector2 target; // Camera target (rotation and zoom origin)
340 float rotation; // Camera rotation in degrees
341 float zoom; // Camera zoom (scaling), should be 1.0f by default
342} Camera2D;
343
344// Mesh, vertex data and vao/vbo
345typedef struct Mesh {
346 int vertexCount; // Number of vertices stored in arrays
347 int triangleCount; // Number of triangles stored (indexed or not)
348
349 // Vertex attributes data
350 float *vertices; // Vertex position (XYZ - 3 components per vertex) (shader-location = 0)
351 float *texcoords; // Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1)
352 float *texcoords2; // Vertex texture second coordinates (UV - 2 components per vertex) (shader-location = 5)
353 float *normals; // Vertex normals (XYZ - 3 components per vertex) (shader-location = 2)
354 float *tangents; // Vertex tangents (XYZW - 4 components per vertex) (shader-location = 4)
355 unsigned char *colors; // Vertex colors (RGBA - 4 components per vertex) (shader-location = 3)
356 unsigned short *indices; // Vertex indices (in case vertex data comes indexed)
357
358 // Animation vertex data
359 float *animVertices; // Animated vertex positions (after bones transformations)
360 float *animNormals; // Animated normals (after bones transformations)
361 unsigned char *boneIds; // Vertex bone ids, max 255 bone ids, up to 4 bones influence by vertex (skinning) (shader-location = 6)
362 float *boneWeights; // Vertex bone weight, up to 4 bones influence by vertex (skinning) (shader-location = 7)
363 Matrix *boneMatrices; // Bones animated transformation matrices
364 int boneCount; // Number of bones
365
366 // OpenGL identifiers
367 unsigned int vaoId; // OpenGL Vertex Array Object id
368 unsigned int *vboId; // OpenGL Vertex Buffer Objects id (default vertex data)
369} Mesh;
370
371// Shader
372typedef struct Shader {
373 unsigned int id; // Shader program id
374 int *locs; // Shader locations array (RL_MAX_SHADER_LOCATIONS)
375} Shader;
376
377// MaterialMap
378typedef struct MaterialMap {
379 Texture2D texture; // Material map texture
380 Color color; // Material map color
381 float value; // Material map value
382} MaterialMap;
383
384// Material, includes shader and maps
385typedef struct Material {
386 Shader shader; // Material shader
387 MaterialMap *maps; // Material maps array (MAX_MATERIAL_MAPS)
388 float params[4]; // Material generic parameters (if required)
389} Material;
390
391// Transform, vertex transformation data
392typedef struct Transform {
393 Vector3 translation; // Translation
394 Quaternion rotation; // Rotation
395 Vector3 scale; // Scale
396} Transform;
397
398// Bone, skeletal animation bone
399typedef struct BoneInfo {
400 char name[32]; // Bone name
401 int parent; // Bone parent
402} BoneInfo;
403
404// Model, meshes, materials and animation data
405typedef struct Model {
406 Matrix transform; // Local transform matrix
407
408 int meshCount; // Number of meshes
409 int materialCount; // Number of materials
410 Mesh *meshes; // Meshes array
411 Material *materials; // Materials array
412 int *meshMaterial; // Mesh material number
413
414 // Animation data
415 int boneCount; // Number of bones
416 BoneInfo *bones; // Bones information (skeleton)
417 Transform *bindPose; // Bones base transformation (pose)
418} Model;
419
420// ModelAnimation
421typedef struct ModelAnimation {
422 int boneCount; // Number of bones
423 int frameCount; // Number of animation frames
424 BoneInfo *bones; // Bones information (skeleton)
425 Transform **framePoses; // Poses array by frame
426 char name[32]; // Animation name
427} ModelAnimation;
428
429// Ray, ray for raycasting
430typedef struct Ray {
431 Vector3 position; // Ray position (origin)
432 Vector3 direction; // Ray direction (normalized)
433} Ray;
434
435// RayCollision, ray hit information
436typedef struct RayCollision {
437 bool hit; // Did the ray hit something?
438 float distance; // Distance to the nearest hit
439 Vector3 point; // Point of the nearest hit
440 Vector3 normal; // Surface normal of hit
441} RayCollision;
442
443// BoundingBox
444typedef struct BoundingBox {
445 Vector3 min; // Minimum vertex box-corner
446 Vector3 max; // Maximum vertex box-corner
447} BoundingBox;
448
449// Wave, audio wave data
450typedef struct Wave {
451 unsigned int frameCount; // Total number of frames (considering channels)
452 unsigned int sampleRate; // Frequency (samples per second)
453 unsigned int sampleSize; // Bit depth (bits per sample): 8, 16, 32 (24 not supported)
454 unsigned int channels; // Number of channels (1-mono, 2-stereo, ...)
455 void *data; // Buffer data pointer
456} Wave;
457
458// Opaque structs declaration
459// NOTE: Actual structs are defined internally in raudio module
460typedef struct rAudioBuffer rAudioBuffer;
461typedef struct rAudioProcessor rAudioProcessor;
462
463// AudioStream, custom audio stream
464typedef struct AudioStream {
465 rAudioBuffer *buffer; // Pointer to internal data used by the audio system
466 rAudioProcessor *processor; // Pointer to internal data processor, useful for audio effects
467
468 unsigned int sampleRate; // Frequency (samples per second)
469 unsigned int sampleSize; // Bit depth (bits per sample): 8, 16, 32 (24 not supported)
470 unsigned int channels; // Number of channels (1-mono, 2-stereo, ...)
471} AudioStream;
472
473// Sound
474typedef struct Sound {
475 AudioStream stream; // Audio stream
476 unsigned int frameCount; // Total number of frames (considering channels)
477} Sound;
478
479// Music, audio stream, anything longer than ~10 seconds should be streamed
480typedef struct Music {
481 AudioStream stream; // Audio stream
482 unsigned int frameCount; // Total number of frames (considering channels)
483 bool looping; // Music looping enable
484
485 int ctxType; // Type of music context (audio filetype)
486 void *ctxData; // Audio context data, depends on type
487} Music;
488
489// VrDeviceInfo, Head-Mounted-Display device parameters
490typedef struct VrDeviceInfo {
491 int hResolution; // Horizontal resolution in pixels
492 int vResolution; // Vertical resolution in pixels
493 float hScreenSize; // Horizontal size in meters
494 float vScreenSize; // Vertical size in meters
495 float eyeToScreenDistance; // Distance between eye and display in meters
496 float lensSeparationDistance; // Lens separation distance in meters
497 float interpupillaryDistance; // IPD (distance between pupils) in meters
498 float lensDistortionValues[4]; // Lens distortion constant parameters
499 float chromaAbCorrection[4]; // Chromatic aberration correction parameters
500} VrDeviceInfo;
501
502// VrStereoConfig, VR stereo rendering configuration for simulator
503typedef struct VrStereoConfig {
504 Matrix projection[2]; // VR projection matrices (per eye)
505 Matrix viewOffset[2]; // VR view offset matrices (per eye)
506 float leftLensCenter[2]; // VR left lens center
507 float rightLensCenter[2]; // VR right lens center
508 float leftScreenCenter[2]; // VR left screen center
509 float rightScreenCenter[2]; // VR right screen center
510 float scale[2]; // VR distortion scale
511 float scaleIn[2]; // VR distortion scale in
512} VrStereoConfig;
513
514// File path list
515typedef struct FilePathList {
516 unsigned int capacity; // Filepaths max entries
517 unsigned int count; // Filepaths entries count
518 char **paths; // Filepaths entries
519} FilePathList;
520
521// Automation event
522typedef struct AutomationEvent {
523 unsigned int frame; // Event frame
524 unsigned int type; // Event type (AutomationEventType)
525 int params[4]; // Event parameters (if required)
526} AutomationEvent;
527
528// Automation event list
529typedef struct AutomationEventList {
530 unsigned int capacity; // Events max entries (MAX_AUTOMATION_EVENTS)
531 unsigned int count; // Events entries count
532 AutomationEvent *events; // Events entries
533} AutomationEventList;
534
535//----------------------------------------------------------------------------------
536// Enumerators Definition
537//----------------------------------------------------------------------------------
538// System/Window config flags
539// NOTE: Every bit registers one state (use it with bit masks)
540// By default all flags are set to 0
541typedef enum {
542 FLAG_VSYNC_HINT = 0x00000040, // Set to try enabling V-Sync on GPU
543 FLAG_FULLSCREEN_MODE = 0x00000002, // Set to run program in fullscreen
544 FLAG_WINDOW_RESIZABLE = 0x00000004, // Set to allow resizable window
545 FLAG_WINDOW_UNDECORATED = 0x00000008, // Set to disable window decoration (frame and buttons)
546 FLAG_WINDOW_HIDDEN = 0x00000080, // Set to hide window
547 FLAG_WINDOW_MINIMIZED = 0x00000200, // Set to minimize window (iconify)
548 FLAG_WINDOW_MAXIMIZED = 0x00000400, // Set to maximize window (expanded to monitor)
549 FLAG_WINDOW_UNFOCUSED = 0x00000800, // Set to window non focused
550 FLAG_WINDOW_TOPMOST = 0x00001000, // Set to window always on top
551 FLAG_WINDOW_ALWAYS_RUN = 0x00000100, // Set to allow windows running while minimized
552 FLAG_WINDOW_TRANSPARENT = 0x00000010, // Set to allow transparent framebuffer
553 FLAG_WINDOW_HIGHDPI = 0x00002000, // Set to support HighDPI
554 FLAG_WINDOW_MOUSE_PASSTHROUGH = 0x00004000, // Set to support mouse passthrough, only supported when FLAG_WINDOW_UNDECORATED
555 FLAG_BORDERLESS_WINDOWED_MODE = 0x00008000, // Set to run program in borderless windowed mode
556 FLAG_MSAA_4X_HINT = 0x00000020, // Set to try enabling MSAA 4X
557 FLAG_INTERLACED_HINT = 0x00010000 // Set to try enabling interlaced video format (for V3D)
558} ConfigFlags;
559
560// Trace log level
561// NOTE: Organized by priority level
562typedef enum {
563 LOG_ALL = 0, // Display all logs
564 LOG_TRACE, // Trace logging, intended for internal use only
565 LOG_DEBUG, // Debug logging, used for internal debugging, it should be disabled on release builds
566 LOG_INFO, // Info logging, used for program execution info
567 LOG_WARNING, // Warning logging, used on recoverable failures
568 LOG_ERROR, // Error logging, used on unrecoverable failures
569 LOG_FATAL, // Fatal logging, used to abort program: exit(EXIT_FAILURE)
570 LOG_NONE // Disable logging
571} TraceLogLevel;
572
573// Keyboard keys (US keyboard layout)
574// NOTE: Use GetKeyPressed() to allow redefining
575// required keys for alternative layouts
576typedef enum {
577 KEY_NULL = 0, // Key: NULL, used for no key pressed
578 // Alphanumeric keys
579 KEY_APOSTROPHE = 39, // Key: '
580 KEY_COMMA = 44, // Key: ,
581 KEY_MINUS = 45, // Key: -
582 KEY_PERIOD = 46, // Key: .
583 KEY_SLASH = 47, // Key: /
584 KEY_ZERO = 48, // Key: 0
585 KEY_ONE = 49, // Key: 1
586 KEY_TWO = 50, // Key: 2
587 KEY_THREE = 51, // Key: 3
588 KEY_FOUR = 52, // Key: 4
589 KEY_FIVE = 53, // Key: 5
590 KEY_SIX = 54, // Key: 6
591 KEY_SEVEN = 55, // Key: 7
592 KEY_EIGHT = 56, // Key: 8
593 KEY_NINE = 57, // Key: 9
594 KEY_SEMICOLON = 59, // Key: ;
595 KEY_EQUAL = 61, // Key: =
596 KEY_A = 65, // Key: A | a
597 KEY_B = 66, // Key: B | b
598 KEY_C = 67, // Key: C | c
599 KEY_D = 68, // Key: D | d
600 KEY_E = 69, // Key: E | e
601 KEY_F = 70, // Key: F | f
602 KEY_G = 71, // Key: G | g
603 KEY_H = 72, // Key: H | h
604 KEY_I = 73, // Key: I | i
605 KEY_J = 74, // Key: J | j
606 KEY_K = 75, // Key: K | k
607 KEY_L = 76, // Key: L | l
608 KEY_M = 77, // Key: M | m
609 KEY_N = 78, // Key: N | n
610 KEY_O = 79, // Key: O | o
611 KEY_P = 80, // Key: P | p
612 KEY_Q = 81, // Key: Q | q
613 KEY_R = 82, // Key: R | r
614 KEY_S = 83, // Key: S | s
615 KEY_T = 84, // Key: T | t
616 KEY_U = 85, // Key: U | u
617 KEY_V = 86, // Key: V | v
618 KEY_W = 87, // Key: W | w
619 KEY_X = 88, // Key: X | x
620 KEY_Y = 89, // Key: Y | y
621 KEY_Z = 90, // Key: Z | z
622 KEY_LEFT_BRACKET = 91, // Key: [
623 KEY_BACKSLASH = 92, // Key: '\'
624 KEY_RIGHT_BRACKET = 93, // Key: ]
625 KEY_GRAVE = 96, // Key: `
626 // Function keys
627 KEY_SPACE = 32, // Key: Space
628 KEY_ESCAPE = 256, // Key: Esc
629 KEY_ENTER = 257, // Key: Enter
630 KEY_TAB = 258, // Key: Tab
631 KEY_BACKSPACE = 259, // Key: Backspace
632 KEY_INSERT = 260, // Key: Ins
633 KEY_DELETE = 261, // Key: Del
634 KEY_RIGHT = 262, // Key: Cursor right
635 KEY_LEFT = 263, // Key: Cursor left
636 KEY_DOWN = 264, // Key: Cursor down
637 KEY_UP = 265, // Key: Cursor up
638 KEY_PAGE_UP = 266, // Key: Page up
639 KEY_PAGE_DOWN = 267, // Key: Page down
640 KEY_HOME = 268, // Key: Home
641 KEY_END = 269, // Key: End
642 KEY_CAPS_LOCK = 280, // Key: Caps lock
643 KEY_SCROLL_LOCK = 281, // Key: Scroll down
644 KEY_NUM_LOCK = 282, // Key: Num lock
645 KEY_PRINT_SCREEN = 283, // Key: Print screen
646 KEY_PAUSE = 284, // Key: Pause
647 KEY_F1 = 290, // Key: F1
648 KEY_F2 = 291, // Key: F2
649 KEY_F3 = 292, // Key: F3
650 KEY_F4 = 293, // Key: F4
651 KEY_F5 = 294, // Key: F5
652 KEY_F6 = 295, // Key: F6
653 KEY_F7 = 296, // Key: F7
654 KEY_F8 = 297, // Key: F8
655 KEY_F9 = 298, // Key: F9
656 KEY_F10 = 299, // Key: F10
657 KEY_F11 = 300, // Key: F11
658 KEY_F12 = 301, // Key: F12
659 KEY_LEFT_SHIFT = 340, // Key: Shift left
660 KEY_LEFT_CONTROL = 341, // Key: Control left
661 KEY_LEFT_ALT = 342, // Key: Alt left
662 KEY_LEFT_SUPER = 343, // Key: Super left
663 KEY_RIGHT_SHIFT = 344, // Key: Shift right
664 KEY_RIGHT_CONTROL = 345, // Key: Control right
665 KEY_RIGHT_ALT = 346, // Key: Alt right
666 KEY_RIGHT_SUPER = 347, // Key: Super right
667 KEY_KB_MENU = 348, // Key: KB menu
668 // Keypad keys
669 KEY_KP_0 = 320, // Key: Keypad 0
670 KEY_KP_1 = 321, // Key: Keypad 1
671 KEY_KP_2 = 322, // Key: Keypad 2
672 KEY_KP_3 = 323, // Key: Keypad 3
673 KEY_KP_4 = 324, // Key: Keypad 4
674 KEY_KP_5 = 325, // Key: Keypad 5
675 KEY_KP_6 = 326, // Key: Keypad 6
676 KEY_KP_7 = 327, // Key: Keypad 7
677 KEY_KP_8 = 328, // Key: Keypad 8
678 KEY_KP_9 = 329, // Key: Keypad 9
679 KEY_KP_DECIMAL = 330, // Key: Keypad .
680 KEY_KP_DIVIDE = 331, // Key: Keypad /
681 KEY_KP_MULTIPLY = 332, // Key: Keypad *
682 KEY_KP_SUBTRACT = 333, // Key: Keypad -
683 KEY_KP_ADD = 334, // Key: Keypad +
684 KEY_KP_ENTER = 335, // Key: Keypad Enter
685 KEY_KP_EQUAL = 336, // Key: Keypad =
686 // Android key buttons
687 KEY_BACK = 4, // Key: Android back button
688 KEY_MENU = 5, // Key: Android menu button
689 KEY_VOLUME_UP = 24, // Key: Android volume up button
690 KEY_VOLUME_DOWN = 25 // Key: Android volume down button
691} KeyboardKey;
692
693// Add backwards compatibility support for deprecated names
694#define MOUSE_LEFT_BUTTON MOUSE_BUTTON_LEFT
695#define MOUSE_RIGHT_BUTTON MOUSE_BUTTON_RIGHT
696#define MOUSE_MIDDLE_BUTTON MOUSE_BUTTON_MIDDLE
697
698// Mouse buttons
699typedef enum {
700 MOUSE_BUTTON_LEFT = 0, // Mouse button left
701 MOUSE_BUTTON_RIGHT = 1, // Mouse button right
702 MOUSE_BUTTON_MIDDLE = 2, // Mouse button middle (pressed wheel)
703 MOUSE_BUTTON_SIDE = 3, // Mouse button side (advanced mouse device)
704 MOUSE_BUTTON_EXTRA = 4, // Mouse button extra (advanced mouse device)
705 MOUSE_BUTTON_FORWARD = 5, // Mouse button forward (advanced mouse device)
706 MOUSE_BUTTON_BACK = 6, // Mouse button back (advanced mouse device)
707} MouseButton;
708
709// Mouse cursor
710typedef enum {
711 MOUSE_CURSOR_DEFAULT = 0, // Default pointer shape
712 MOUSE_CURSOR_ARROW = 1, // Arrow shape
713 MOUSE_CURSOR_IBEAM = 2, // Text writing cursor shape
714 MOUSE_CURSOR_CROSSHAIR = 3, // Cross shape
715 MOUSE_CURSOR_POINTING_HAND = 4, // Pointing hand cursor
716 MOUSE_CURSOR_RESIZE_EW = 5, // Horizontal resize/move arrow shape
717 MOUSE_CURSOR_RESIZE_NS = 6, // Vertical resize/move arrow shape
718 MOUSE_CURSOR_RESIZE_NWSE = 7, // Top-left to bottom-right diagonal resize/move arrow shape
719 MOUSE_CURSOR_RESIZE_NESW = 8, // The top-right to bottom-left diagonal resize/move arrow shape
720 MOUSE_CURSOR_RESIZE_ALL = 9, // The omnidirectional resize/move cursor shape
721 MOUSE_CURSOR_NOT_ALLOWED = 10 // The operation-not-allowed shape
722} MouseCursor;
723
724// Gamepad buttons
725typedef enum {
726 GAMEPAD_BUTTON_UNKNOWN = 0, // Unknown button, just for error checking
727 GAMEPAD_BUTTON_LEFT_FACE_UP, // Gamepad left DPAD up button
728 GAMEPAD_BUTTON_LEFT_FACE_RIGHT, // Gamepad left DPAD right button
729 GAMEPAD_BUTTON_LEFT_FACE_DOWN, // Gamepad left DPAD down button
730 GAMEPAD_BUTTON_LEFT_FACE_LEFT, // Gamepad left DPAD left button
731 GAMEPAD_BUTTON_RIGHT_FACE_UP, // Gamepad right button up (i.e. PS3: Triangle, Xbox: Y)
732 GAMEPAD_BUTTON_RIGHT_FACE_RIGHT, // Gamepad right button right (i.e. PS3: Circle, Xbox: B)
733 GAMEPAD_BUTTON_RIGHT_FACE_DOWN, // Gamepad right button down (i.e. PS3: Cross, Xbox: A)
734 GAMEPAD_BUTTON_RIGHT_FACE_LEFT, // Gamepad right button left (i.e. PS3: Square, Xbox: X)
735 GAMEPAD_BUTTON_LEFT_TRIGGER_1, // Gamepad top/back trigger left (first), it could be a trailing button
736 GAMEPAD_BUTTON_LEFT_TRIGGER_2, // Gamepad top/back trigger left (second), it could be a trailing button
737 GAMEPAD_BUTTON_RIGHT_TRIGGER_1, // Gamepad top/back trigger right (first), it could be a trailing button
738 GAMEPAD_BUTTON_RIGHT_TRIGGER_2, // Gamepad top/back trigger right (second), it could be a trailing button
739 GAMEPAD_BUTTON_MIDDLE_LEFT, // Gamepad center buttons, left one (i.e. PS3: Select)
740 GAMEPAD_BUTTON_MIDDLE, // Gamepad center buttons, middle one (i.e. PS3: PS, Xbox: XBOX)
741 GAMEPAD_BUTTON_MIDDLE_RIGHT, // Gamepad center buttons, right one (i.e. PS3: Start)
742 GAMEPAD_BUTTON_LEFT_THUMB, // Gamepad joystick pressed button left
743 GAMEPAD_BUTTON_RIGHT_THUMB // Gamepad joystick pressed button right
744} GamepadButton;
745
746// Gamepad axis
747typedef enum {
748 GAMEPAD_AXIS_LEFT_X = 0, // Gamepad left stick X axis
749 GAMEPAD_AXIS_LEFT_Y = 1, // Gamepad left stick Y axis
750 GAMEPAD_AXIS_RIGHT_X = 2, // Gamepad right stick X axis
751 GAMEPAD_AXIS_RIGHT_Y = 3, // Gamepad right stick Y axis
752 GAMEPAD_AXIS_LEFT_TRIGGER = 4, // Gamepad back trigger left, pressure level: [1..-1]
753 GAMEPAD_AXIS_RIGHT_TRIGGER = 5 // Gamepad back trigger right, pressure level: [1..-1]
754} GamepadAxis;
755
756// Material map index
757typedef enum {
758 MATERIAL_MAP_ALBEDO = 0, // Albedo material (same as: MATERIAL_MAP_DIFFUSE)
759 MATERIAL_MAP_METALNESS, // Metalness material (same as: MATERIAL_MAP_SPECULAR)
760 MATERIAL_MAP_NORMAL, // Normal material
761 MATERIAL_MAP_ROUGHNESS, // Roughness material
762 MATERIAL_MAP_OCCLUSION, // Ambient occlusion material
763 MATERIAL_MAP_EMISSION, // Emission material
764 MATERIAL_MAP_HEIGHT, // Heightmap material
765 MATERIAL_MAP_CUBEMAP, // Cubemap material (NOTE: Uses GL_TEXTURE_CUBE_MAP)
766 MATERIAL_MAP_IRRADIANCE, // Irradiance material (NOTE: Uses GL_TEXTURE_CUBE_MAP)
767 MATERIAL_MAP_PREFILTER, // Prefilter material (NOTE: Uses GL_TEXTURE_CUBE_MAP)
768 MATERIAL_MAP_BRDF // Brdf material
769} MaterialMapIndex;
770
771#define MATERIAL_MAP_DIFFUSE MATERIAL_MAP_ALBEDO
772#define MATERIAL_MAP_SPECULAR MATERIAL_MAP_METALNESS
773
774// Shader location index
775typedef enum {
776 SHADER_LOC_VERTEX_POSITION = 0, // Shader location: vertex attribute: position
777 SHADER_LOC_VERTEX_TEXCOORD01, // Shader location: vertex attribute: texcoord01
778 SHADER_LOC_VERTEX_TEXCOORD02, // Shader location: vertex attribute: texcoord02
779 SHADER_LOC_VERTEX_NORMAL, // Shader location: vertex attribute: normal
780 SHADER_LOC_VERTEX_TANGENT, // Shader location: vertex attribute: tangent
781 SHADER_LOC_VERTEX_COLOR, // Shader location: vertex attribute: color
782 SHADER_LOC_MATRIX_MVP, // Shader location: matrix uniform: model-view-projection
783 SHADER_LOC_MATRIX_VIEW, // Shader location: matrix uniform: view (camera transform)
784 SHADER_LOC_MATRIX_PROJECTION, // Shader location: matrix uniform: projection
785 SHADER_LOC_MATRIX_MODEL, // Shader location: matrix uniform: model (transform)
786 SHADER_LOC_MATRIX_NORMAL, // Shader location: matrix uniform: normal
787 SHADER_LOC_VECTOR_VIEW, // Shader location: vector uniform: view
788 SHADER_LOC_COLOR_DIFFUSE, // Shader location: vector uniform: diffuse color
789 SHADER_LOC_COLOR_SPECULAR, // Shader location: vector uniform: specular color
790 SHADER_LOC_COLOR_AMBIENT, // Shader location: vector uniform: ambient color
791 SHADER_LOC_MAP_ALBEDO, // Shader location: sampler2d texture: albedo (same as: SHADER_LOC_MAP_DIFFUSE)
792 SHADER_LOC_MAP_METALNESS, // Shader location: sampler2d texture: metalness (same as: SHADER_LOC_MAP_SPECULAR)
793 SHADER_LOC_MAP_NORMAL, // Shader location: sampler2d texture: normal
794 SHADER_LOC_MAP_ROUGHNESS, // Shader location: sampler2d texture: roughness
795 SHADER_LOC_MAP_OCCLUSION, // Shader location: sampler2d texture: occlusion
796 SHADER_LOC_MAP_EMISSION, // Shader location: sampler2d texture: emission
797 SHADER_LOC_MAP_HEIGHT, // Shader location: sampler2d texture: height
798 SHADER_LOC_MAP_CUBEMAP, // Shader location: samplerCube texture: cubemap
799 SHADER_LOC_MAP_IRRADIANCE, // Shader location: samplerCube texture: irradiance
800 SHADER_LOC_MAP_PREFILTER, // Shader location: samplerCube texture: prefilter
801 SHADER_LOC_MAP_BRDF, // Shader location: sampler2d texture: brdf
802 SHADER_LOC_VERTEX_BONEIDS, // Shader location: vertex attribute: boneIds
803 SHADER_LOC_VERTEX_BONEWEIGHTS, // Shader location: vertex attribute: boneWeights
804 SHADER_LOC_BONE_MATRICES // Shader location: array of matrices uniform: boneMatrices
805} ShaderLocationIndex;
806
807#define SHADER_LOC_MAP_DIFFUSE SHADER_LOC_MAP_ALBEDO
808#define SHADER_LOC_MAP_SPECULAR SHADER_LOC_MAP_METALNESS
809
810// Shader uniform data type
811typedef enum {
812 SHADER_UNIFORM_FLOAT = 0, // Shader uniform type: float
813 SHADER_UNIFORM_VEC2, // Shader uniform type: vec2 (2 float)
814 SHADER_UNIFORM_VEC3, // Shader uniform type: vec3 (3 float)
815 SHADER_UNIFORM_VEC4, // Shader uniform type: vec4 (4 float)
816 SHADER_UNIFORM_INT, // Shader uniform type: int
817 SHADER_UNIFORM_IVEC2, // Shader uniform type: ivec2 (2 int)
818 SHADER_UNIFORM_IVEC3, // Shader uniform type: ivec3 (3 int)
819 SHADER_UNIFORM_IVEC4, // Shader uniform type: ivec4 (4 int)
820 SHADER_UNIFORM_SAMPLER2D // Shader uniform type: sampler2d
821} ShaderUniformDataType;
822
823// Shader attribute data types
824typedef enum {
825 SHADER_ATTRIB_FLOAT = 0, // Shader attribute type: float
826 SHADER_ATTRIB_VEC2, // Shader attribute type: vec2 (2 float)
827 SHADER_ATTRIB_VEC3, // Shader attribute type: vec3 (3 float)
828 SHADER_ATTRIB_VEC4 // Shader attribute type: vec4 (4 float)
829} ShaderAttributeDataType;
830
831// Pixel formats
832// NOTE: Support depends on OpenGL version and platform
833typedef enum {
834 PIXELFORMAT_UNCOMPRESSED_GRAYSCALE = 1, // 8 bit per pixel (no alpha)
835 PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA, // 8*2 bpp (2 channels)
836 PIXELFORMAT_UNCOMPRESSED_R5G6B5, // 16 bpp
837 PIXELFORMAT_UNCOMPRESSED_R8G8B8, // 24 bpp
838 PIXELFORMAT_UNCOMPRESSED_R5G5B5A1, // 16 bpp (1 bit alpha)
839 PIXELFORMAT_UNCOMPRESSED_R4G4B4A4, // 16 bpp (4 bit alpha)
840 PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, // 32 bpp
841 PIXELFORMAT_UNCOMPRESSED_R32, // 32 bpp (1 channel - float)
842 PIXELFORMAT_UNCOMPRESSED_R32G32B32, // 32*3 bpp (3 channels - float)
843 PIXELFORMAT_UNCOMPRESSED_R32G32B32A32, // 32*4 bpp (4 channels - float)
844 PIXELFORMAT_UNCOMPRESSED_R16, // 16 bpp (1 channel - half float)
845 PIXELFORMAT_UNCOMPRESSED_R16G16B16, // 16*3 bpp (3 channels - half float)
846 PIXELFORMAT_UNCOMPRESSED_R16G16B16A16, // 16*4 bpp (4 channels - half float)
847 PIXELFORMAT_COMPRESSED_DXT1_RGB, // 4 bpp (no alpha)
848 PIXELFORMAT_COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha)
849 PIXELFORMAT_COMPRESSED_DXT3_RGBA, // 8 bpp
850 PIXELFORMAT_COMPRESSED_DXT5_RGBA, // 8 bpp
851 PIXELFORMAT_COMPRESSED_ETC1_RGB, // 4 bpp
852 PIXELFORMAT_COMPRESSED_ETC2_RGB, // 4 bpp
853 PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA, // 8 bpp
854 PIXELFORMAT_COMPRESSED_PVRT_RGB, // 4 bpp
855 PIXELFORMAT_COMPRESSED_PVRT_RGBA, // 4 bpp
856 PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA, // 8 bpp
857 PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA // 2 bpp
858} PixelFormat;
859
860// Texture parameters: filter mode
861// NOTE 1: Filtering considers mipmaps if available in the texture
862// NOTE 2: Filter is accordingly set for minification and magnification
863typedef enum {
864 TEXTURE_FILTER_POINT = 0, // No filter, just pixel approximation
865 TEXTURE_FILTER_BILINEAR, // Linear filtering
866 TEXTURE_FILTER_TRILINEAR, // Trilinear filtering (linear with mipmaps)
867 TEXTURE_FILTER_ANISOTROPIC_4X, // Anisotropic filtering 4x
868 TEXTURE_FILTER_ANISOTROPIC_8X, // Anisotropic filtering 8x
869 TEXTURE_FILTER_ANISOTROPIC_16X, // Anisotropic filtering 16x
870} TextureFilter;
871
872// Texture parameters: wrap mode
873typedef enum {
874 TEXTURE_WRAP_REPEAT = 0, // Repeats texture in tiled mode
875 TEXTURE_WRAP_CLAMP, // Clamps texture to edge pixel in tiled mode
876 TEXTURE_WRAP_MIRROR_REPEAT, // Mirrors and repeats the texture in tiled mode
877 TEXTURE_WRAP_MIRROR_CLAMP // Mirrors and clamps to border the texture in tiled mode
878} TextureWrap;
879
880// Cubemap layouts
881typedef enum {
882 CUBEMAP_LAYOUT_AUTO_DETECT = 0, // Automatically detect layout type
883 CUBEMAP_LAYOUT_LINE_VERTICAL, // Layout is defined by a vertical line with faces
884 CUBEMAP_LAYOUT_LINE_HORIZONTAL, // Layout is defined by a horizontal line with faces
885 CUBEMAP_LAYOUT_CROSS_THREE_BY_FOUR, // Layout is defined by a 3x4 cross with cubemap faces
886 CUBEMAP_LAYOUT_CROSS_FOUR_BY_THREE // Layout is defined by a 4x3 cross with cubemap faces
887} CubemapLayout;
888
889// Font type, defines generation method
890typedef enum {
891 FONT_DEFAULT = 0, // Default font generation, anti-aliased
892 FONT_BITMAP, // Bitmap font generation, no anti-aliasing
893 FONT_SDF // SDF font generation, requires external shader
894} FontType;
895
896// Color blending modes (pre-defined)
897typedef enum {
898 BLEND_ALPHA = 0, // Blend textures considering alpha (default)
899 BLEND_ADDITIVE, // Blend textures adding colors
900 BLEND_MULTIPLIED, // Blend textures multiplying colors
901 BLEND_ADD_COLORS, // Blend textures adding colors (alternative)
902 BLEND_SUBTRACT_COLORS, // Blend textures subtracting colors (alternative)
903 BLEND_ALPHA_PREMULTIPLY, // Blend premultiplied textures considering alpha
904 BLEND_CUSTOM, // Blend textures using custom src/dst factors (use rlSetBlendFactors())
905 BLEND_CUSTOM_SEPARATE // Blend textures using custom rgb/alpha separate src/dst factors (use rlSetBlendFactorsSeparate())
906} BlendMode;
907
908// Gesture
909// NOTE: Provided as bit-wise flags to enable only desired gestures
910typedef enum {
911 GESTURE_NONE = 0, // No gesture
912 GESTURE_TAP = 1, // Tap gesture
913 GESTURE_DOUBLETAP = 2, // Double tap gesture
914 GESTURE_HOLD = 4, // Hold gesture
915 GESTURE_DRAG = 8, // Drag gesture
916 GESTURE_SWIPE_RIGHT = 16, // Swipe right gesture
917 GESTURE_SWIPE_LEFT = 32, // Swipe left gesture
918 GESTURE_SWIPE_UP = 64, // Swipe up gesture
919 GESTURE_SWIPE_DOWN = 128, // Swipe down gesture
920 GESTURE_PINCH_IN = 256, // Pinch in gesture
921 GESTURE_PINCH_OUT = 512 // Pinch out gesture
922} Gesture;
923
924// Camera system modes
925typedef enum {
926 CAMERA_CUSTOM = 0, // Camera custom, controlled by user (UpdateCamera() does nothing)
927 CAMERA_FREE, // Camera free mode
928 CAMERA_ORBITAL, // Camera orbital, around target, zoom supported
929 CAMERA_FIRST_PERSON, // Camera first person
930 CAMERA_THIRD_PERSON // Camera third person
931} CameraMode;
932
933// Camera projection
934typedef enum {
935 CAMERA_PERSPECTIVE = 0, // Perspective projection
936 CAMERA_ORTHOGRAPHIC // Orthographic projection
937} CameraProjection;
938
939// N-patch layout
940typedef enum {
941 NPATCH_NINE_PATCH = 0, // Npatch layout: 3x3 tiles
942 NPATCH_THREE_PATCH_VERTICAL, // Npatch layout: 1x3 tiles
943 NPATCH_THREE_PATCH_HORIZONTAL // Npatch layout: 3x1 tiles
944} NPatchLayout;
945
946// Callbacks to hook some internal functions
947// WARNING: These callbacks are intended for advanced users
948typedef void (*TraceLogCallback)(int logLevel, const char *text, va_list args); // Logging: Redirect trace log messages
949typedef unsigned char *(*LoadFileDataCallback)(const char *fileName, int *dataSize); // FileIO: Load binary data
950typedef bool (*SaveFileDataCallback)(const char *fileName, void *data, int dataSize); // FileIO: Save binary data
951typedef char *(*LoadFileTextCallback)(const char *fileName); // FileIO: Load text data
952typedef bool (*SaveFileTextCallback)(const char *fileName, char *text); // FileIO: Save text data
953
954//------------------------------------------------------------------------------------
955// Global Variables Definition
956//------------------------------------------------------------------------------------
957// It's lonely here...
958
959//------------------------------------------------------------------------------------
960// Window and Graphics Device Functions (Module: core)
961//------------------------------------------------------------------------------------
962
963#if defined(__cplusplus)
964extern "C" { // Prevents name mangling of functions
965#endif
966
967// Window-related functions
968RLAPI void InitWindow(int width, int height, const char *title); // Initialize window and OpenGL context
969RLAPI void CloseWindow(void); // Close window and unload OpenGL context
970RLAPI bool WindowShouldClose(void); // Check if application should close (KEY_ESCAPE pressed or windows close icon clicked)
971RLAPI bool IsWindowReady(void); // Check if window has been initialized successfully
972RLAPI bool IsWindowFullscreen(void); // Check if window is currently fullscreen
973RLAPI bool IsWindowHidden(void); // Check if window is currently hidden
974RLAPI bool IsWindowMinimized(void); // Check if window is currently minimized
975RLAPI bool IsWindowMaximized(void); // Check if window is currently maximized
976RLAPI bool IsWindowFocused(void); // Check if window is currently focused
977RLAPI bool IsWindowResized(void); // Check if window has been resized last frame
978RLAPI bool IsWindowState(unsigned int flag); // Check if one specific window flag is enabled
979RLAPI void SetWindowState(unsigned int flags); // Set window configuration state using flags
980RLAPI void ClearWindowState(unsigned int flags); // Clear window configuration state flags
981RLAPI void ToggleFullscreen(void); // Toggle window state: fullscreen/windowed, resizes monitor to match window resolution
982RLAPI void ToggleBorderlessWindowed(void); // Toggle window state: borderless windowed, resizes window to match monitor resolution
983RLAPI void MaximizeWindow(void); // Set window state: maximized, if resizable
984RLAPI void MinimizeWindow(void); // Set window state: minimized, if resizable
985RLAPI void RestoreWindow(void); // Set window state: not minimized/maximized
986RLAPI void SetWindowIcon(Image image); // Set icon for window (single image, RGBA 32bit)
987RLAPI void SetWindowIcons(Image *images, int count); // Set icon for window (multiple images, RGBA 32bit)
988RLAPI void SetWindowTitle(const char *title); // Set title for window
989RLAPI void SetWindowPosition(int x, int y); // Set window position on screen
990RLAPI void SetWindowMonitor(int monitor); // Set monitor for the current window
991RLAPI void SetWindowMinSize(int width, int height); // Set window minimum dimensions (for FLAG_WINDOW_RESIZABLE)
992RLAPI void SetWindowMaxSize(int width, int height); // Set window maximum dimensions (for FLAG_WINDOW_RESIZABLE)
993RLAPI void SetWindowSize(int width, int height); // Set window dimensions
994RLAPI void SetWindowOpacity(float opacity); // Set window opacity [0.0f..1.0f]
995RLAPI void SetWindowFocused(void); // Set window focused
996RLAPI void *GetWindowHandle(void); // Get native window handle
997RLAPI int GetScreenWidth(void); // Get current screen width
998RLAPI int GetScreenHeight(void); // Get current screen height
999RLAPI int GetRenderWidth(void); // Get current render width (it considers HiDPI)
1000RLAPI int GetRenderHeight(void); // Get current render height (it considers HiDPI)
1001RLAPI int GetMonitorCount(void); // Get number of connected monitors
1002RLAPI int GetCurrentMonitor(void); // Get current monitor where window is placed
1003RLAPI Vector2 GetMonitorPosition(int monitor); // Get specified monitor position
1004RLAPI int GetMonitorWidth(int monitor); // Get specified monitor width (current video mode used by monitor)
1005RLAPI int GetMonitorHeight(int monitor); // Get specified monitor height (current video mode used by monitor)
1006RLAPI int GetMonitorPhysicalWidth(int monitor); // Get specified monitor physical width in millimetres
1007RLAPI int GetMonitorPhysicalHeight(int monitor); // Get specified monitor physical height in millimetres
1008RLAPI int GetMonitorRefreshRate(int monitor); // Get specified monitor refresh rate
1009RLAPI Vector2 GetWindowPosition(void); // Get window position XY on monitor
1010RLAPI Vector2 GetWindowScaleDPI(void); // Get window scale DPI factor
1011RLAPI const char *GetMonitorName(int monitor); // Get the human-readable, UTF-8 encoded name of the specified monitor
1012RLAPI void SetClipboardText(const char *text); // Set clipboard text content
1013RLAPI const char *GetClipboardText(void); // Get clipboard text content
1014RLAPI Image GetClipboardImage(void); // Get clipboard image content
1015RLAPI void EnableEventWaiting(void); // Enable waiting for events on EndDrawing(), no automatic event polling
1016RLAPI void DisableEventWaiting(void); // Disable waiting for events on EndDrawing(), automatic events polling
1017
1018// Cursor-related functions
1019RLAPI void ShowCursor(void); // Shows cursor
1020RLAPI void HideCursor(void); // Hides cursor
1021RLAPI bool IsCursorHidden(void); // Check if cursor is not visible
1022RLAPI void EnableCursor(void); // Enables cursor (unlock cursor)
1023RLAPI void DisableCursor(void); // Disables cursor (lock cursor)
1024RLAPI bool IsCursorOnScreen(void); // Check if cursor is on the screen
1025
1026// Drawing-related functions
1027RLAPI void ClearBackground(Color color); // Set background color (framebuffer clear color)
1028RLAPI void BeginDrawing(void); // Setup canvas (framebuffer) to start drawing
1029RLAPI void EndDrawing(void); // End canvas drawing and swap buffers (double buffering)
1030RLAPI void BeginMode2D(Camera2D camera); // Begin 2D mode with custom camera (2D)
1031RLAPI void EndMode2D(void); // Ends 2D mode with custom camera
1032RLAPI void BeginMode3D(Camera3D camera); // Begin 3D mode with custom camera (3D)
1033RLAPI void EndMode3D(void); // Ends 3D mode and returns to default 2D orthographic mode
1034RLAPI void BeginTextureMode(RenderTexture2D target); // Begin drawing to render texture
1035RLAPI void EndTextureMode(void); // Ends drawing to render texture
1036RLAPI void BeginShaderMode(Shader shader); // Begin custom shader drawing
1037RLAPI void EndShaderMode(void); // End custom shader drawing (use default shader)
1038RLAPI void BeginBlendMode(int mode); // Begin blending mode (alpha, additive, multiplied, subtract, custom)
1039RLAPI void EndBlendMode(void); // End blending mode (reset to default: alpha blending)
1040RLAPI void BeginScissorMode(int x, int y, int width, int height); // Begin scissor mode (define screen area for following drawing)
1041RLAPI void EndScissorMode(void); // End scissor mode
1042RLAPI void BeginVrStereoMode(VrStereoConfig config); // Begin stereo rendering (requires VR simulator)
1043RLAPI void EndVrStereoMode(void); // End stereo rendering (requires VR simulator)
1044
1045// VR stereo config functions for VR simulator
1046RLAPI VrStereoConfig LoadVrStereoConfig(VrDeviceInfo device); // Load VR stereo config for VR simulator device parameters
1047RLAPI void UnloadVrStereoConfig(VrStereoConfig config); // Unload VR stereo config
1048
1049// Shader management functions
1050// NOTE: Shader functionality is not available on OpenGL 1.1
1051RLAPI Shader LoadShader(const char *vsFileName, const char *fsFileName); // Load shader from files and bind default locations
1052RLAPI Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode); // Load shader from code strings and bind default locations
1053RLAPI bool IsShaderValid(Shader shader); // Check if a shader is valid (loaded on GPU)
1054RLAPI int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location
1055RLAPI int GetShaderLocationAttrib(Shader shader, const char *attribName); // Get shader attribute location
1056RLAPI void SetShaderValue(Shader shader, int locIndex, const void *value, int uniformType); // Set shader uniform value
1057RLAPI void SetShaderValueV(Shader shader, int locIndex, const void *value, int uniformType, int count); // Set shader uniform value vector
1058RLAPI void SetShaderValueMatrix(Shader shader, int locIndex, Matrix mat); // Set shader uniform value (matrix 4x4)
1059RLAPI void SetShaderValueTexture(Shader shader, int locIndex, Texture2D texture); // Set shader uniform value for texture (sampler2d)
1060RLAPI void UnloadShader(Shader shader); // Unload shader from GPU memory (VRAM)
1061
1062// Screen-space-related functions
1063#define GetMouseRay GetScreenToWorldRay // Compatibility hack for previous raylib versions
1064RLAPI Ray GetScreenToWorldRay(Vector2 position, Camera camera); // Get a ray trace from screen position (i.e mouse)
1065RLAPI Ray GetScreenToWorldRayEx(Vector2 position, Camera camera, int width, int height); // Get a ray trace from screen position (i.e mouse) in a viewport
1066RLAPI Vector2 GetWorldToScreen(Vector3 position, Camera camera); // Get the screen space position for a 3d world space position
1067RLAPI Vector2 GetWorldToScreenEx(Vector3 position, Camera camera, int width, int height); // Get size position for a 3d world space position
1068RLAPI Vector2 GetWorldToScreen2D(Vector2 position, Camera2D camera); // Get the screen space position for a 2d camera world space position
1069RLAPI Vector2 GetScreenToWorld2D(Vector2 position, Camera2D camera); // Get the world space position for a 2d camera screen space position
1070RLAPI Matrix GetCameraMatrix(Camera camera); // Get camera transform matrix (view matrix)
1071RLAPI Matrix GetCameraMatrix2D(Camera2D camera); // Get camera 2d transform matrix
1072
1073// Timing-related functions
1074RLAPI void SetTargetFPS(int fps); // Set target FPS (maximum)
1075RLAPI float GetFrameTime(void); // Get time in seconds for last frame drawn (delta time)
1076RLAPI double GetTime(void); // Get elapsed time in seconds since InitWindow()
1077RLAPI int GetFPS(void); // Get current FPS
1078
1079// Custom frame control functions
1080// NOTE: Those functions are intended for advanced users that want full control over the frame processing
1081// By default EndDrawing() does this job: draws everything + SwapScreenBuffer() + manage frame timing + PollInputEvents()
1082// To avoid that behaviour and control frame processes manually, enable in config.h: SUPPORT_CUSTOM_FRAME_CONTROL
1083RLAPI void SwapScreenBuffer(void); // Swap back buffer with front buffer (screen drawing)
1084RLAPI void PollInputEvents(void); // Register all input events
1085RLAPI void WaitTime(double seconds); // Wait for some time (halt program execution)
1086
1087// Random values generation functions
1088RLAPI void SetRandomSeed(unsigned int seed); // Set the seed for the random number generator
1089RLAPI int GetRandomValue(int min, int max); // Get a random value between min and max (both included)
1090RLAPI int *LoadRandomSequence(unsigned int count, int min, int max); // Load random values sequence, no values repeated
1091RLAPI void UnloadRandomSequence(int *sequence); // Unload random values sequence
1092
1093// Misc. functions
1094RLAPI void TakeScreenshot(const char *fileName); // Takes a screenshot of current screen (filename extension defines format)
1095RLAPI void SetConfigFlags(unsigned int flags); // Setup init configuration flags (view FLAGS)
1096RLAPI void OpenURL(const char *url); // Open URL with default system browser (if available)
1097
1098// NOTE: Following functions implemented in module [utils]
1099//------------------------------------------------------------------
1100RLAPI void TraceLog(int logLevel, const char *text, ...); // Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR...)
1101RLAPI void SetTraceLogLevel(int logLevel); // Set the current threshold (minimum) log level
1102RLAPI void *MemAlloc(unsigned int size); // Internal memory allocator
1103RLAPI void *MemRealloc(void *ptr, unsigned int size); // Internal memory reallocator
1104RLAPI void MemFree(void *ptr); // Internal memory free
1105
1106// Set custom callbacks
1107// WARNING: Callbacks setup is intended for advanced users
1108RLAPI void SetTraceLogCallback(TraceLogCallback callback); // Set custom trace log
1109RLAPI void SetLoadFileDataCallback(LoadFileDataCallback callback); // Set custom file binary data loader
1110RLAPI void SetSaveFileDataCallback(SaveFileDataCallback callback); // Set custom file binary data saver
1111RLAPI void SetLoadFileTextCallback(LoadFileTextCallback callback); // Set custom file text data loader
1112RLAPI void SetSaveFileTextCallback(SaveFileTextCallback callback); // Set custom file text data saver
1113
1114// Files management functions
1115RLAPI unsigned char *LoadFileData(const char *fileName, int *dataSize); // Load file data as byte array (read)
1116RLAPI void UnloadFileData(unsigned char *data); // Unload file data allocated by LoadFileData()
1117RLAPI bool SaveFileData(const char *fileName, void *data, int dataSize); // Save data to file from byte array (write), returns true on success
1118RLAPI bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileName); // Export data to code (.h), returns true on success
1119RLAPI char *LoadFileText(const char *fileName); // Load text data from file (read), returns a '\0' terminated string
1120RLAPI void UnloadFileText(char *text); // Unload file text data allocated by LoadFileText()
1121RLAPI bool SaveFileText(const char *fileName, char *text); // Save text data to file (write), string must be '\0' terminated, returns true on success
1122//------------------------------------------------------------------
1123
1124// File system functions
1125RLAPI bool FileExists(const char *fileName); // Check if file exists
1126RLAPI bool DirectoryExists(const char *dirPath); // Check if a directory path exists
1127RLAPI bool IsFileExtension(const char *fileName, const char *ext); // Check file extension (including point: .png, .wav)
1128RLAPI int GetFileLength(const char *fileName); // Get file length in bytes (NOTE: GetFileSize() conflicts with windows.h)
1129RLAPI const char *GetFileExtension(const char *fileName); // Get pointer to extension for a filename string (includes dot: '.png')
1130RLAPI const char *GetFileName(const char *filePath); // Get pointer to filename for a path string
1131RLAPI const char *GetFileNameWithoutExt(const char *filePath); // Get filename string without extension (uses static string)
1132RLAPI const char *GetDirectoryPath(const char *filePath); // Get full path for a given fileName with path (uses static string)
1133RLAPI const char *GetPrevDirectoryPath(const char *dirPath); // Get previous directory path for a given path (uses static string)
1134RLAPI const char *GetWorkingDirectory(void); // Get current working directory (uses static string)
1135RLAPI const char *GetApplicationDirectory(void); // Get the directory of the running application (uses static string)
1136RLAPI int MakeDirectory(const char *dirPath); // Create directories (including full path requested), returns 0 on success
1137RLAPI bool ChangeDirectory(const char *dir); // Change working directory, return true on success
1138RLAPI bool IsPathFile(const char *path); // Check if a given path is a file or a directory
1139RLAPI bool IsFileNameValid(const char *fileName); // Check if fileName is valid for the platform/OS
1140RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths
1141RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result
1142RLAPI void UnloadDirectoryFiles(FilePathList files); // Unload filepaths
1143RLAPI bool IsFileDropped(void); // Check if a file has been dropped into window
1144RLAPI FilePathList LoadDroppedFiles(void); // Load dropped filepaths
1145RLAPI void UnloadDroppedFiles(FilePathList files); // Unload dropped filepaths
1146RLAPI long GetFileModTime(const char *fileName); // Get file modification time (last write time)
1147
1148// Compression/Encoding functionality
1149RLAPI unsigned char *CompressData(const unsigned char *data, int dataSize, int *compDataSize); // Compress data (DEFLATE algorithm), memory must be MemFree()
1150RLAPI unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // Decompress data (DEFLATE algorithm), memory must be MemFree()
1151RLAPI char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize); // Encode data to Base64 string, memory must be MemFree()
1152RLAPI unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize); // Decode Base64 string data, memory must be MemFree()
1153RLAPI unsigned int ComputeCRC32(unsigned char *data, int dataSize); // Compute CRC32 hash code
1154RLAPI unsigned int *ComputeMD5(unsigned char *data, int dataSize); // Compute MD5 hash code, returns static int[4] (16 bytes)
1155RLAPI unsigned int *ComputeSHA1(unsigned char *data, int dataSize); // Compute SHA1 hash code, returns static int[5] (20 bytes)
1156
1157
1158// Automation events functionality
1159RLAPI AutomationEventList LoadAutomationEventList(const char *fileName); // Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS
1160RLAPI void UnloadAutomationEventList(AutomationEventList list); // Unload automation events list from file
1161RLAPI bool ExportAutomationEventList(AutomationEventList list, const char *fileName); // Export automation events list as text file
1162RLAPI void SetAutomationEventList(AutomationEventList *list); // Set automation event list to record to
1163RLAPI void SetAutomationEventBaseFrame(int frame); // Set automation event internal base frame to start recording
1164RLAPI void StartAutomationEventRecording(void); // Start recording automation events (AutomationEventList must be set)
1165RLAPI void StopAutomationEventRecording(void); // Stop recording automation events
1166RLAPI void PlayAutomationEvent(AutomationEvent event); // Play a recorded automation event
1167
1168//------------------------------------------------------------------------------------
1169// Input Handling Functions (Module: core)
1170//------------------------------------------------------------------------------------
1171
1172// Input-related functions: keyboard
1173RLAPI bool IsKeyPressed(int key); // Check if a key has been pressed once
1174RLAPI bool IsKeyPressedRepeat(int key); // Check if a key has been pressed again
1175RLAPI bool IsKeyDown(int key); // Check if a key is being pressed
1176RLAPI bool IsKeyReleased(int key); // Check if a key has been released once
1177RLAPI bool IsKeyUp(int key); // Check if a key is NOT being pressed
1178RLAPI int GetKeyPressed(void); // Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty
1179RLAPI int GetCharPressed(void); // Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty
1180RLAPI void SetExitKey(int key); // Set a custom key to exit program (default is ESC)
1181
1182// Input-related functions: gamepads
1183RLAPI bool IsGamepadAvailable(int gamepad); // Check if a gamepad is available
1184RLAPI const char *GetGamepadName(int gamepad); // Get gamepad internal name id
1185RLAPI bool IsGamepadButtonPressed(int gamepad, int button); // Check if a gamepad button has been pressed once
1186RLAPI bool IsGamepadButtonDown(int gamepad, int button); // Check if a gamepad button is being pressed
1187RLAPI bool IsGamepadButtonReleased(int gamepad, int button); // Check if a gamepad button has been released once
1188RLAPI bool IsGamepadButtonUp(int gamepad, int button); // Check if a gamepad button is NOT being pressed
1189RLAPI int GetGamepadButtonPressed(void); // Get the last gamepad button pressed
1190RLAPI int GetGamepadAxisCount(int gamepad); // Get gamepad axis count for a gamepad
1191RLAPI float GetGamepadAxisMovement(int gamepad, int axis); // Get axis movement value for a gamepad axis
1192RLAPI int SetGamepadMappings(const char *mappings); // Set internal gamepad mappings (SDL_GameControllerDB)
1193RLAPI void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration); // Set gamepad vibration for both motors (duration in seconds)
1194
1195// Input-related functions: mouse
1196RLAPI bool IsMouseButtonPressed(int button); // Check if a mouse button has been pressed once
1197RLAPI bool IsMouseButtonDown(int button); // Check if a mouse button is being pressed
1198RLAPI bool IsMouseButtonReleased(int button); // Check if a mouse button has been released once
1199RLAPI bool IsMouseButtonUp(int button); // Check if a mouse button is NOT being pressed
1200RLAPI int GetMouseX(void); // Get mouse position X
1201RLAPI int GetMouseY(void); // Get mouse position Y
1202RLAPI Vector2 GetMousePosition(void); // Get mouse position XY
1203RLAPI Vector2 GetMouseDelta(void); // Get mouse delta between frames
1204RLAPI void SetMousePosition(int x, int y); // Set mouse position XY
1205RLAPI void SetMouseOffset(int offsetX, int offsetY); // Set mouse offset
1206RLAPI void SetMouseScale(float scaleX, float scaleY); // Set mouse scaling
1207RLAPI float GetMouseWheelMove(void); // Get mouse wheel movement for X or Y, whichever is larger
1208RLAPI Vector2 GetMouseWheelMoveV(void); // Get mouse wheel movement for both X and Y
1209RLAPI void SetMouseCursor(int cursor); // Set mouse cursor
1210
1211// Input-related functions: touch
1212RLAPI int GetTouchX(void); // Get touch position X for touch point 0 (relative to screen size)
1213RLAPI int GetTouchY(void); // Get touch position Y for touch point 0 (relative to screen size)
1214RLAPI Vector2 GetTouchPosition(int index); // Get touch position XY for a touch point index (relative to screen size)
1215RLAPI int GetTouchPointId(int index); // Get touch point identifier for given index
1216RLAPI int GetTouchPointCount(void); // Get number of touch points
1217
1218//------------------------------------------------------------------------------------
1219// Gestures and Touch Handling Functions (Module: rgestures)
1220//------------------------------------------------------------------------------------
1221RLAPI void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags
1222RLAPI bool IsGestureDetected(unsigned int gesture); // Check if a gesture have been detected
1223RLAPI int GetGestureDetected(void); // Get latest detected gesture
1224RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in seconds
1225RLAPI Vector2 GetGestureDragVector(void); // Get gesture drag vector
1226RLAPI float GetGestureDragAngle(void); // Get gesture drag angle
1227RLAPI Vector2 GetGesturePinchVector(void); // Get gesture pinch delta
1228RLAPI float GetGesturePinchAngle(void); // Get gesture pinch angle
1229
1230//------------------------------------------------------------------------------------
1231// Camera System Functions (Module: rcamera)
1232//------------------------------------------------------------------------------------
1233RLAPI void UpdateCamera(Camera *camera, int mode); // Update camera position for selected mode
1234RLAPI void UpdateCameraPro(Camera *camera, Vector3 movement, Vector3 rotation, float zoom); // Update camera movement/rotation
1235
1236//------------------------------------------------------------------------------------
1237// Basic Shapes Drawing Functions (Module: shapes)
1238//------------------------------------------------------------------------------------
1239// Set texture and rectangle to be used on shapes drawing
1240// NOTE: It can be useful when using basic shapes and one single font,
1241// defining a font char white rectangle would allow drawing everything in a single draw call
1242RLAPI void SetShapesTexture(Texture2D texture, Rectangle source); // Set texture and rectangle to be used on shapes drawing
1243RLAPI Texture2D GetShapesTexture(void); // Get texture that is used for shapes drawing
1244RLAPI Rectangle GetShapesTextureRectangle(void); // Get texture source rectangle that is used for shapes drawing
1245
1246// Basic shapes drawing functions
1247RLAPI void DrawPixel(int posX, int posY, Color color); // Draw a pixel using geometry [Can be slow, use with care]
1248RLAPI void DrawPixelV(Vector2 position, Color color); // Draw a pixel using geometry (Vector version) [Can be slow, use with care]
1249RLAPI void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color); // Draw a line
1250RLAPI void DrawLineV(Vector2 startPos, Vector2 endPos, Color color); // Draw a line (using gl lines)
1251RLAPI void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line (using triangles/quads)
1252RLAPI void DrawLineStrip(const Vector2 *points, int pointCount, Color color); // Draw lines sequence (using gl lines)
1253RLAPI void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw line segment cubic-bezier in-out interpolation
1254RLAPI void DrawCircle(int centerX, int centerY, float radius, Color color); // Draw a color-filled circle
1255RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw a piece of a circle
1256RLAPI void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw circle sector outline
1257RLAPI void DrawCircleGradient(int centerX, int centerY, float radius, Color inner, Color outer); // Draw a gradient-filled circle
1258RLAPI void DrawCircleV(Vector2 center, float radius, Color color); // Draw a color-filled circle (Vector version)
1259RLAPI void DrawCircleLines(int centerX, int centerY, float radius, Color color); // Draw circle outline
1260RLAPI void DrawCircleLinesV(Vector2 center, float radius, Color color); // Draw circle outline (Vector version)
1261RLAPI void DrawEllipse(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse
1262RLAPI void DrawEllipseLines(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse outline
1263RLAPI void DrawRing(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color); // Draw ring
1264RLAPI void DrawRingLines(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color); // Draw ring outline
1265RLAPI void DrawRectangle(int posX, int posY, int width, int height, Color color); // Draw a color-filled rectangle
1266RLAPI void DrawRectangleV(Vector2 position, Vector2 size, Color color); // Draw a color-filled rectangle (Vector version)
1267RLAPI void DrawRectangleRec(Rectangle rec, Color color); // Draw a color-filled rectangle
1268RLAPI void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color); // Draw a color-filled rectangle with pro parameters
1269RLAPI void DrawRectangleGradientV(int posX, int posY, int width, int height, Color top, Color bottom); // Draw a vertical-gradient-filled rectangle
1270RLAPI void DrawRectangleGradientH(int posX, int posY, int width, int height, Color left, Color right); // Draw a horizontal-gradient-filled rectangle
1271RLAPI void DrawRectangleGradientEx(Rectangle rec, Color topLeft, Color bottomLeft, Color topRight, Color bottomRight); // Draw a gradient-filled rectangle with custom vertex colors
1272RLAPI void DrawRectangleLines(int posX, int posY, int width, int height, Color color); // Draw rectangle outline
1273RLAPI void DrawRectangleLinesEx(Rectangle rec, float lineThick, Color color); // Draw rectangle outline with extended parameters
1274RLAPI void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color color); // Draw rectangle with rounded edges
1275RLAPI void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, Color color); // Draw rectangle lines with rounded edges
1276RLAPI void DrawRectangleRoundedLinesEx(Rectangle rec, float roundness, int segments, float lineThick, Color color); // Draw rectangle with rounded edges outline
1277RLAPI void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw a color-filled triangle (vertex in counter-clockwise order!)
1278RLAPI void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline (vertex in counter-clockwise order!)
1279RLAPI void DrawTriangleFan(const Vector2 *points, int pointCount, Color color); // Draw a triangle fan defined by points (first vertex is the center)
1280RLAPI void DrawTriangleStrip(const Vector2 *points, int pointCount, Color color); // Draw a triangle strip defined by points
1281RLAPI void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a regular polygon (Vector version)
1282RLAPI void DrawPolyLines(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a polygon outline of n sides
1283RLAPI void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, float lineThick, Color color); // Draw a polygon outline of n sides with extended parameters
1284
1285// Splines drawing functions
1286RLAPI void DrawSplineLinear(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Linear, minimum 2 points
1287RLAPI void DrawSplineBasis(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: B-Spline, minimum 4 points
1288RLAPI void DrawSplineCatmullRom(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Catmull-Rom, minimum 4 points
1289RLAPI void DrawSplineBezierQuadratic(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Quadratic Bezier, minimum 3 points (1 control point): [p1, c2, p3, c4...]
1290RLAPI void DrawSplineBezierCubic(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Cubic Bezier, minimum 4 points (2 control points): [p1, c2, c3, p4, c5, c6...]
1291RLAPI void DrawSplineSegmentLinear(Vector2 p1, Vector2 p2, float thick, Color color); // Draw spline segment: Linear, 2 points
1292RLAPI void DrawSplineSegmentBasis(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float thick, Color color); // Draw spline segment: B-Spline, 4 points
1293RLAPI void DrawSplineSegmentCatmullRom(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float thick, Color color); // Draw spline segment: Catmull-Rom, 4 points
1294RLAPI void DrawSplineSegmentBezierQuadratic(Vector2 p1, Vector2 c2, Vector2 p3, float thick, Color color); // Draw spline segment: Quadratic Bezier, 2 points, 1 control point
1295RLAPI void DrawSplineSegmentBezierCubic(Vector2 p1, Vector2 c2, Vector2 c3, Vector2 p4, float thick, Color color); // Draw spline segment: Cubic Bezier, 2 points, 2 control points
1296
1297// Spline segment point evaluation functions, for a given t [0.0f .. 1.0f]
1298RLAPI Vector2 GetSplinePointLinear(Vector2 startPos, Vector2 endPos, float t); // Get (evaluate) spline point: Linear
1299RLAPI Vector2 GetSplinePointBasis(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float t); // Get (evaluate) spline point: B-Spline
1300RLAPI Vector2 GetSplinePointCatmullRom(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float t); // Get (evaluate) spline point: Catmull-Rom
1301RLAPI Vector2 GetSplinePointBezierQuad(Vector2 p1, Vector2 c2, Vector2 p3, float t); // Get (evaluate) spline point: Quadratic Bezier
1302RLAPI Vector2 GetSplinePointBezierCubic(Vector2 p1, Vector2 c2, Vector2 c3, Vector2 p4, float t); // Get (evaluate) spline point: Cubic Bezier
1303
1304// Basic shapes collision detection functions
1305RLAPI bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2); // Check collision between two rectangles
1306RLAPI bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, float radius2); // Check collision between two circles
1307RLAPI bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec); // Check collision between circle and rectangle
1308RLAPI bool CheckCollisionCircleLine(Vector2 center, float radius, Vector2 p1, Vector2 p2); // Check if circle collides with a line created betweeen two points [p1] and [p2]
1309RLAPI bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if point is inside rectangle
1310RLAPI bool CheckCollisionPointCircle(Vector2 point, Vector2 center, float radius); // Check if point is inside circle
1311RLAPI bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2 p3); // Check if point is inside a triangle
1312RLAPI bool CheckCollisionPointLine(Vector2 point, Vector2 p1, Vector2 p2, int threshold); // Check if point belongs to line created between two points [p1] and [p2] with defined margin in pixels [threshold]
1313RLAPI bool CheckCollisionPointPoly(Vector2 point, const Vector2 *points, int pointCount); // Check if point is within a polygon described by array of vertices
1314RLAPI bool CheckCollisionLines(Vector2 startPos1, Vector2 endPos1, Vector2 startPos2, Vector2 endPos2, Vector2 *collisionPoint); // Check the collision between two lines defined by two points each, returns collision point by reference
1315RLAPI Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2); // Get collision rectangle for two rectangles collision
1316
1317//------------------------------------------------------------------------------------
1318// Texture Loading and Drawing Functions (Module: textures)
1319//------------------------------------------------------------------------------------
1320
1321// Image loading functions
1322// NOTE: These functions do not require GPU access
1323RLAPI Image LoadImage(const char *fileName); // Load image from file into CPU memory (RAM)
1324RLAPI Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize); // Load image from RAW file data
1325RLAPI Image LoadImageAnim(const char *fileName, int *frames); // Load image sequence from file (frames appended to image.data)
1326RLAPI Image LoadImageAnimFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int *frames); // Load image sequence from memory buffer
1327RLAPI Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load image from memory buffer, fileType refers to extension: i.e. '.png'
1328RLAPI Image LoadImageFromTexture(Texture2D texture); // Load image from GPU texture data
1329RLAPI Image LoadImageFromScreen(void); // Load image from screen buffer and (screenshot)
1330RLAPI bool IsImageValid(Image image); // Check if an image is valid (data and parameters)
1331RLAPI void UnloadImage(Image image); // Unload image from CPU memory (RAM)
1332RLAPI bool ExportImage(Image image, const char *fileName); // Export image data to file, returns true on success
1333RLAPI unsigned char *ExportImageToMemory(Image image, const char *fileType, int *fileSize); // Export image to memory buffer
1334RLAPI bool ExportImageAsCode(Image image, const char *fileName); // Export image as code file defining an array of bytes, returns true on success
1335
1336// Image generation functions
1337RLAPI Image GenImageColor(int width, int height, Color color); // Generate image: plain color
1338RLAPI Image GenImageGradientLinear(int width, int height, int direction, Color start, Color end); // Generate image: linear gradient, direction in degrees [0..360], 0=Vertical gradient
1339RLAPI Image GenImageGradientRadial(int width, int height, float density, Color inner, Color outer); // Generate image: radial gradient
1340RLAPI Image GenImageGradientSquare(int width, int height, float density, Color inner, Color outer); // Generate image: square gradient
1341RLAPI Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2); // Generate image: checked
1342RLAPI Image GenImageWhiteNoise(int width, int height, float factor); // Generate image: white noise
1343RLAPI Image GenImagePerlinNoise(int width, int height, int offsetX, int offsetY, float scale); // Generate image: perlin noise
1344RLAPI Image GenImageCellular(int width, int height, int tileSize); // Generate image: cellular algorithm, bigger tileSize means bigger cells
1345RLAPI Image GenImageText(int width, int height, const char *text); // Generate image: grayscale image from text data
1346
1347// Image manipulation functions
1348RLAPI Image ImageCopy(Image image); // Create an image duplicate (useful for transformations)
1349RLAPI Image ImageFromImage(Image image, Rectangle rec); // Create an image from another image piece
1350RLAPI Image ImageFromChannel(Image image, int selectedChannel); // Create an image from a selected channel of another image (GRAYSCALE)
1351RLAPI Image ImageText(const char *text, int fontSize, Color color); // Create an image from text (default font)
1352RLAPI Image ImageTextEx(Font font, const char *text, float fontSize, float spacing, Color tint); // Create an image from text (custom sprite font)
1353RLAPI void ImageFormat(Image *image, int newFormat); // Convert image data to desired format
1354RLAPI void ImageToPOT(Image *image, Color fill); // Convert image to POT (power-of-two)
1355RLAPI void ImageCrop(Image *image, Rectangle crop); // Crop an image to a defined rectangle
1356RLAPI void ImageAlphaCrop(Image *image, float threshold); // Crop image depending on alpha value
1357RLAPI void ImageAlphaClear(Image *image, Color color, float threshold); // Clear alpha channel to desired color
1358RLAPI void ImageAlphaMask(Image *image, Image alphaMask); // Apply alpha mask to image
1359RLAPI void ImageAlphaPremultiply(Image *image); // Premultiply alpha channel
1360RLAPI void ImageBlurGaussian(Image *image, int blurSize); // Apply Gaussian blur using a box blur approximation
1361RLAPI void ImageKernelConvolution(Image *image, const float *kernel, int kernelSize); // Apply custom square convolution kernel to image
1362RLAPI void ImageResize(Image *image, int newWidth, int newHeight); // Resize image (Bicubic scaling algorithm)
1363RLAPI void ImageResizeNN(Image *image, int newWidth,int newHeight); // Resize image (Nearest-Neighbor scaling algorithm)
1364RLAPI void ImageResizeCanvas(Image *image, int newWidth, int newHeight, int offsetX, int offsetY, Color fill); // Resize canvas and fill with color
1365RLAPI void ImageMipmaps(Image *image); // Compute all mipmap levels for a provided image
1366RLAPI void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp); // Dither image data to 16bpp or lower (Floyd-Steinberg dithering)
1367RLAPI void ImageFlipVertical(Image *image); // Flip image vertically
1368RLAPI void ImageFlipHorizontal(Image *image); // Flip image horizontally
1369RLAPI void ImageRotate(Image *image, int degrees); // Rotate image by input angle in degrees (-359 to 359)
1370RLAPI void ImageRotateCW(Image *image); // Rotate image clockwise 90deg
1371RLAPI void ImageRotateCCW(Image *image); // Rotate image counter-clockwise 90deg
1372RLAPI void ImageColorTint(Image *image, Color color); // Modify image color: tint
1373RLAPI void ImageColorInvert(Image *image); // Modify image color: invert
1374RLAPI void ImageColorGrayscale(Image *image); // Modify image color: grayscale
1375RLAPI void ImageColorContrast(Image *image, float contrast); // Modify image color: contrast (-100 to 100)
1376RLAPI void ImageColorBrightness(Image *image, int brightness); // Modify image color: brightness (-255 to 255)
1377RLAPI void ImageColorReplace(Image *image, Color color, Color replace); // Modify image color: replace color
1378RLAPI Color *LoadImageColors(Image image); // Load color data from image as a Color array (RGBA - 32bit)
1379RLAPI Color *LoadImagePalette(Image image, int maxPaletteSize, int *colorCount); // Load colors palette from image as a Color array (RGBA - 32bit)
1380RLAPI void UnloadImageColors(Color *colors); // Unload color data loaded with LoadImageColors()
1381RLAPI void UnloadImagePalette(Color *colors); // Unload colors palette loaded with LoadImagePalette()
1382RLAPI Rectangle GetImageAlphaBorder(Image image, float threshold); // Get image alpha border rectangle
1383RLAPI Color GetImageColor(Image image, int x, int y); // Get image pixel color at (x, y) position
1384
1385// Image drawing functions
1386// NOTE: Image software-rendering functions (CPU)
1387RLAPI void ImageClearBackground(Image *dst, Color color); // Clear image background with given color
1388RLAPI void ImageDrawPixel(Image *dst, int posX, int posY, Color color); // Draw pixel within an image
1389RLAPI void ImageDrawPixelV(Image *dst, Vector2 position, Color color); // Draw pixel within an image (Vector version)
1390RLAPI void ImageDrawLine(Image *dst, int startPosX, int startPosY, int endPosX, int endPosY, Color color); // Draw line within an image
1391RLAPI void ImageDrawLineV(Image *dst, Vector2 start, Vector2 end, Color color); // Draw line within an image (Vector version)
1392RLAPI void ImageDrawLineEx(Image *dst, Vector2 start, Vector2 end, int thick, Color color); // Draw a line defining thickness within an image
1393RLAPI void ImageDrawCircle(Image *dst, int centerX, int centerY, int radius, Color color); // Draw a filled circle within an image
1394RLAPI void ImageDrawCircleV(Image *dst, Vector2 center, int radius, Color color); // Draw a filled circle within an image (Vector version)
1395RLAPI void ImageDrawCircleLines(Image *dst, int centerX, int centerY, int radius, Color color); // Draw circle outline within an image
1396RLAPI void ImageDrawCircleLinesV(Image *dst, Vector2 center, int radius, Color color); // Draw circle outline within an image (Vector version)
1397RLAPI void ImageDrawRectangle(Image *dst, int posX, int posY, int width, int height, Color color); // Draw rectangle within an image
1398RLAPI void ImageDrawRectangleV(Image *dst, Vector2 position, Vector2 size, Color color); // Draw rectangle within an image (Vector version)
1399RLAPI void ImageDrawRectangleRec(Image *dst, Rectangle rec, Color color); // Draw rectangle within an image
1400RLAPI void ImageDrawRectangleLines(Image *dst, Rectangle rec, int thick, Color color); // Draw rectangle lines within an image
1401RLAPI void ImageDrawTriangle(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle within an image
1402RLAPI void ImageDrawTriangleEx(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color c1, Color c2, Color c3); // Draw triangle with interpolated colors within an image
1403RLAPI void ImageDrawTriangleLines(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline within an image
1404RLAPI void ImageDrawTriangleFan(Image *dst, Vector2 *points, int pointCount, Color color); // Draw a triangle fan defined by points within an image (first vertex is the center)
1405RLAPI void ImageDrawTriangleStrip(Image *dst, Vector2 *points, int pointCount, Color color); // Draw a triangle strip defined by points within an image
1406RLAPI void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec, Color tint); // Draw a source image within a destination image (tint applied to source)
1407RLAPI void ImageDrawText(Image *dst, const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font) within an image (destination)
1408RLAPI void ImageDrawTextEx(Image *dst, Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text (custom sprite font) within an image (destination)
1409
1410// Texture loading functions
1411// NOTE: These functions require GPU access
1412RLAPI Texture2D LoadTexture(const char *fileName); // Load texture from file into GPU memory (VRAM)
1413RLAPI Texture2D LoadTextureFromImage(Image image); // Load texture from image data
1414RLAPI TextureCubemap LoadTextureCubemap(Image image, int layout); // Load cubemap from image, multiple image cubemap layouts supported
1415RLAPI RenderTexture2D LoadRenderTexture(int width, int height); // Load texture for rendering (framebuffer)
1416RLAPI bool IsTextureValid(Texture2D texture); // Check if a texture is valid (loaded in GPU)
1417RLAPI void UnloadTexture(Texture2D texture); // Unload texture from GPU memory (VRAM)
1418RLAPI bool IsRenderTextureValid(RenderTexture2D target); // Check if a render texture is valid (loaded in GPU)
1419RLAPI void UnloadRenderTexture(RenderTexture2D target); // Unload render texture from GPU memory (VRAM)
1420RLAPI void UpdateTexture(Texture2D texture, const void *pixels); // Update GPU texture with new data
1421RLAPI void UpdateTextureRec(Texture2D texture, Rectangle rec, const void *pixels); // Update GPU texture rectangle with new data
1422
1423// Texture configuration functions
1424RLAPI void GenTextureMipmaps(Texture2D *texture); // Generate GPU mipmaps for a texture
1425RLAPI void SetTextureFilter(Texture2D texture, int filter); // Set texture scaling filter mode
1426RLAPI void SetTextureWrap(Texture2D texture, int wrap); // Set texture wrapping mode
1427
1428// Texture drawing functions
1429RLAPI void DrawTexture(Texture2D texture, int posX, int posY, Color tint); // Draw a Texture2D
1430RLAPI void DrawTextureV(Texture2D texture, Vector2 position, Color tint); // Draw a Texture2D with position defined as Vector2
1431RLAPI void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint); // Draw a Texture2D with extended parameters
1432RLAPI void DrawTextureRec(Texture2D texture, Rectangle source, Vector2 position, Color tint); // Draw a part of a texture defined by a rectangle
1433RLAPI void DrawTexturePro(Texture2D texture, Rectangle source, Rectangle dest, Vector2 origin, float rotation, Color tint); // Draw a part of a texture defined by a rectangle with 'pro' parameters
1434RLAPI void DrawTextureNPatch(Texture2D texture, NPatchInfo nPatchInfo, Rectangle dest, Vector2 origin, float rotation, Color tint); // Draws a texture (or part of it) that stretches or shrinks nicely
1435
1436// Color/pixel related functions
1437RLAPI bool ColorIsEqual(Color col1, Color col2); // Check if two colors are equal
1438RLAPI Color Fade(Color color, float alpha); // Get color with alpha applied, alpha goes from 0.0f to 1.0f
1439RLAPI int ColorToInt(Color color); // Get hexadecimal value for a Color (0xRRGGBBAA)
1440RLAPI Vector4 ColorNormalize(Color color); // Get Color normalized as float [0..1]
1441RLAPI Color ColorFromNormalized(Vector4 normalized); // Get Color from normalized values [0..1]
1442RLAPI Vector3 ColorToHSV(Color color); // Get HSV values for a Color, hue [0..360], saturation/value [0..1]
1443RLAPI Color ColorFromHSV(float hue, float saturation, float value); // Get a Color from HSV values, hue [0..360], saturation/value [0..1]
1444RLAPI Color ColorTint(Color color, Color tint); // Get color multiplied with another color
1445RLAPI Color ColorBrightness(Color color, float factor); // Get color with brightness correction, brightness factor goes from -1.0f to 1.0f
1446RLAPI Color ColorContrast(Color color, float contrast); // Get color with contrast correction, contrast values between -1.0f and 1.0f
1447RLAPI Color ColorAlpha(Color color, float alpha); // Get color with alpha applied, alpha goes from 0.0f to 1.0f
1448RLAPI Color ColorAlphaBlend(Color dst, Color src, Color tint); // Get src alpha-blended into dst color with tint
1449RLAPI Color ColorLerp(Color color1, Color color2, float factor); // Get color lerp interpolation between two colors, factor [0.0f..1.0f]
1450RLAPI Color GetColor(unsigned int hexValue); // Get Color structure from hexadecimal value
1451RLAPI Color GetPixelColor(void *srcPtr, int format); // Get Color from a source pixel pointer of certain format
1452RLAPI void SetPixelColor(void *dstPtr, Color color, int format); // Set color formatted into destination pixel pointer
1453RLAPI int GetPixelDataSize(int width, int height, int format); // Get pixel data size in bytes for certain format
1454
1455//------------------------------------------------------------------------------------
1456// Font Loading and Text Drawing Functions (Module: text)
1457//------------------------------------------------------------------------------------
1458
1459// Font loading/unloading functions
1460RLAPI Font GetFontDefault(void); // Get the default Font
1461RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM)
1462RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height
1463RLAPI Font LoadFontFromImage(Image image, Color key, int firstChar); // Load font from Image (XNA style)
1464RLAPI Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf'
1465RLAPI bool IsFontValid(Font font); // Check if a font is valid (font data loaded, WARNING: GPU texture not checked)
1466RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount, int type); // Load font data for further use
1467RLAPI Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyphCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info
1468RLAPI void UnloadFontData(GlyphInfo *glyphs, int glyphCount); // Unload font chars info data (RAM)
1469RLAPI void UnloadFont(Font font); // Unload font from GPU memory (VRAM)
1470RLAPI bool ExportFontAsCode(Font font, const char *fileName); // Export font as code file, returns true on success
1471
1472// Text drawing functions
1473RLAPI void DrawFPS(int posX, int posY); // Draw current FPS
1474RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font)
1475RLAPI void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using font and additional parameters
1476RLAPI void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint); // Draw text using Font and pro parameters (rotation)
1477RLAPI void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSize, Color tint); // Draw one character (codepoint)
1478RLAPI void DrawTextCodepoints(Font font, const int *codepoints, int codepointCount, Vector2 position, float fontSize, float spacing, Color tint); // Draw multiple character (codepoint)
1479
1480// Text font info functions
1481RLAPI void SetTextLineSpacing(int spacing); // Set vertical line spacing when drawing with line-breaks
1482RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font
1483RLAPI Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing); // Measure string size for Font
1484RLAPI int GetGlyphIndex(Font font, int codepoint); // Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found
1485RLAPI GlyphInfo GetGlyphInfo(Font font, int codepoint); // Get glyph font info data for a codepoint (unicode character), fallback to '?' if not found
1486RLAPI Rectangle GetGlyphAtlasRec(Font font, int codepoint); // Get glyph rectangle in font atlas for a codepoint (unicode character), fallback to '?' if not found
1487
1488// Text codepoints management functions (unicode characters)
1489RLAPI char *LoadUTF8(const int *codepoints, int length); // Load UTF-8 text encoded from codepoints array
1490RLAPI void UnloadUTF8(char *text); // Unload UTF-8 text encoded from codepoints array
1491RLAPI int *LoadCodepoints(const char *text, int *count); // Load all codepoints from a UTF-8 text string, codepoints count returned by parameter
1492RLAPI void UnloadCodepoints(int *codepoints); // Unload codepoints data from memory
1493RLAPI int GetCodepointCount(const char *text); // Get total number of codepoints in a UTF-8 encoded string
1494RLAPI int GetCodepoint(const char *text, int *codepointSize); // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
1495RLAPI int GetCodepointNext(const char *text, int *codepointSize); // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
1496RLAPI int GetCodepointPrevious(const char *text, int *codepointSize); // Get previous codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
1497RLAPI const char *CodepointToUTF8(int codepoint, int *utf8Size); // Encode one codepoint into UTF-8 byte array (array length returned as parameter)
1498
1499// Text strings management functions (no UTF-8 strings, only byte chars)
1500// NOTE: Some strings allocate memory internally for returned strings, just be careful!
1501RLAPI int TextCopy(char *dst, const char *src); // Copy one string to another, returns bytes copied
1502RLAPI bool TextIsEqual(const char *text1, const char *text2); // Check if two text string are equal
1503RLAPI unsigned int TextLength(const char *text); // Get text length, checks for '\0' ending
1504RLAPI const char *TextFormat(const char *text, ...); // Text formatting with variables (sprintf() style)
1505RLAPI const char *TextSubtext(const char *text, int position, int length); // Get a piece of a text string
1506RLAPI char *TextReplace(const char *text, const char *replace, const char *by); // Replace text string (WARNING: memory must be freed!)
1507RLAPI char *TextInsert(const char *text, const char *insert, int position); // Insert text in a position (WARNING: memory must be freed!)
1508RLAPI const char *TextJoin(const char **textList, int count, const char *delimiter); // Join text strings with delimiter
1509RLAPI const char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings
1510RLAPI void TextAppend(char *text, const char *append, int *position); // Append text at specific position and move cursor!
1511RLAPI int TextFindIndex(const char *text, const char *find); // Find first text occurrence within a string
1512RLAPI const char *TextToUpper(const char *text); // Get upper case version of provided string
1513RLAPI const char *TextToLower(const char *text); // Get lower case version of provided string
1514RLAPI const char *TextToPascal(const char *text); // Get Pascal case notation version of provided string
1515RLAPI const char *TextToSnake(const char *text); // Get Snake case notation version of provided string
1516RLAPI const char *TextToCamel(const char *text); // Get Camel case notation version of provided string
1517
1518RLAPI int TextToInteger(const char *text); // Get integer value from text (negative values not supported)
1519RLAPI float TextToFloat(const char *text); // Get float value from text (negative values not supported)
1520
1521//------------------------------------------------------------------------------------
1522// Basic 3d Shapes Drawing Functions (Module: models)
1523//------------------------------------------------------------------------------------
1524
1525// Basic geometric 3D shapes drawing functions
1526RLAPI void DrawLine3D(Vector3 startPos, Vector3 endPos, Color color); // Draw a line in 3D world space
1527RLAPI void DrawPoint3D(Vector3 position, Color color); // Draw a point in 3D space, actually a small line
1528RLAPI void DrawCircle3D(Vector3 center, float radius, Vector3 rotationAxis, float rotationAngle, Color color); // Draw a circle in 3D world space
1529RLAPI void DrawTriangle3D(Vector3 v1, Vector3 v2, Vector3 v3, Color color); // Draw a color-filled triangle (vertex in counter-clockwise order!)
1530RLAPI void DrawTriangleStrip3D(const Vector3 *points, int pointCount, Color color); // Draw a triangle strip defined by points
1531RLAPI void DrawCube(Vector3 position, float width, float height, float length, Color color); // Draw cube
1532RLAPI void DrawCubeV(Vector3 position, Vector3 size, Color color); // Draw cube (Vector version)
1533RLAPI void DrawCubeWires(Vector3 position, float width, float height, float length, Color color); // Draw cube wires
1534RLAPI void DrawCubeWiresV(Vector3 position, Vector3 size, Color color); // Draw cube wires (Vector version)
1535RLAPI void DrawSphere(Vector3 centerPos, float radius, Color color); // Draw sphere
1536RLAPI void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color color); // Draw sphere with extended parameters
1537RLAPI void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Color color); // Draw sphere wires
1538RLAPI void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone
1539RLAPI void DrawCylinderEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color); // Draw a cylinder with base at startPos and top at endPos
1540RLAPI void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone wires
1541RLAPI void DrawCylinderWiresEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color); // Draw a cylinder wires with base at startPos and top at endPos
1542RLAPI void DrawCapsule(Vector3 startPos, Vector3 endPos, float radius, int slices, int rings, Color color); // Draw a capsule with the center of its sphere caps at startPos and endPos
1543RLAPI void DrawCapsuleWires(Vector3 startPos, Vector3 endPos, float radius, int slices, int rings, Color color); // Draw capsule wireframe with the center of its sphere caps at startPos and endPos
1544RLAPI void DrawPlane(Vector3 centerPos, Vector2 size, Color color); // Draw a plane XZ
1545RLAPI void DrawRay(Ray ray, Color color); // Draw a ray line
1546RLAPI void DrawGrid(int slices, float spacing); // Draw a grid (centered at (0, 0, 0))
1547
1548//------------------------------------------------------------------------------------
1549// Model 3d Loading and Drawing Functions (Module: models)
1550//------------------------------------------------------------------------------------
1551
1552// Model management functions
1553RLAPI Model LoadModel(const char *fileName); // Load model from files (meshes and materials)
1554RLAPI Model LoadModelFromMesh(Mesh mesh); // Load model from generated mesh (default material)
1555RLAPI bool IsModelValid(Model model); // Check if a model is valid (loaded in GPU, VAO/VBOs)
1556RLAPI void UnloadModel(Model model); // Unload model (including meshes) from memory (RAM and/or VRAM)
1557RLAPI BoundingBox GetModelBoundingBox(Model model); // Compute model bounding box limits (considers all meshes)
1558
1559// Model drawing functions
1560RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set)
1561RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters
1562RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set)
1563RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters
1564RLAPI void DrawModelPoints(Model model, Vector3 position, float scale, Color tint); // Draw a model as points
1565RLAPI void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model as points with extended parameters
1566RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires)
1567RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint); // Draw a billboard texture
1568RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by source
1569RLAPI void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector3 up, Vector2 size, Vector2 origin, float rotation, Color tint); // Draw a billboard texture defined by source and rotation
1570
1571// Mesh management functions
1572RLAPI void UploadMesh(Mesh *mesh, bool dynamic); // Upload mesh vertex data in GPU and provide VAO/VBO ids
1573RLAPI void UpdateMeshBuffer(Mesh mesh, int index, const void *data, int dataSize, int offset); // Update mesh vertex data in GPU for a specific buffer index
1574RLAPI void UnloadMesh(Mesh mesh); // Unload mesh data from CPU and GPU
1575RLAPI void DrawMesh(Mesh mesh, Material material, Matrix transform); // Draw a 3d mesh with material and transform
1576RLAPI void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, int instances); // Draw multiple mesh instances with material and different transforms
1577RLAPI BoundingBox GetMeshBoundingBox(Mesh mesh); // Compute mesh bounding box limits
1578RLAPI void GenMeshTangents(Mesh *mesh); // Compute mesh tangents
1579RLAPI bool ExportMesh(Mesh mesh, const char *fileName); // Export mesh data to file, returns true on success
1580RLAPI bool ExportMeshAsCode(Mesh mesh, const char *fileName); // Export mesh as code file (.h) defining multiple arrays of vertex attributes
1581
1582// Mesh generation functions
1583RLAPI Mesh GenMeshPoly(int sides, float radius); // Generate polygonal mesh
1584RLAPI Mesh GenMeshPlane(float width, float length, int resX, int resZ); // Generate plane mesh (with subdivisions)
1585RLAPI Mesh GenMeshCube(float width, float height, float length); // Generate cuboid mesh
1586RLAPI Mesh GenMeshSphere(float radius, int rings, int slices); // Generate sphere mesh (standard sphere)
1587RLAPI Mesh GenMeshHemiSphere(float radius, int rings, int slices); // Generate half-sphere mesh (no bottom cap)
1588RLAPI Mesh GenMeshCylinder(float radius, float height, int slices); // Generate cylinder mesh
1589RLAPI Mesh GenMeshCone(float radius, float height, int slices); // Generate cone/pyramid mesh
1590RLAPI Mesh GenMeshTorus(float radius, float size, int radSeg, int sides); // Generate torus mesh
1591RLAPI Mesh GenMeshKnot(float radius, float size, int radSeg, int sides); // Generate trefoil knot mesh
1592RLAPI Mesh GenMeshHeightmap(Image heightmap, Vector3 size); // Generate heightmap mesh from image data
1593RLAPI Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize); // Generate cubes-based map mesh from image data
1594
1595// Material loading/unloading functions
1596RLAPI Material *LoadMaterials(const char *fileName, int *materialCount); // Load materials from model file
1597RLAPI Material LoadMaterialDefault(void); // Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps)
1598RLAPI bool IsMaterialValid(Material material); // Check if a material is valid (shader assigned, map textures loaded in GPU)
1599RLAPI void UnloadMaterial(Material material); // Unload material from GPU memory (VRAM)
1600RLAPI void SetMaterialTexture(Material *material, int mapType, Texture2D texture); // Set texture for a material map type (MATERIAL_MAP_DIFFUSE, MATERIAL_MAP_SPECULAR...)
1601RLAPI void SetModelMeshMaterial(Model *model, int meshId, int materialId); // Set material for a mesh
1602
1603// Model animations loading/unloading functions
1604RLAPI ModelAnimation *LoadModelAnimations(const char *fileName, int *animCount); // Load model animations from file
1605RLAPI void UpdateModelAnimation(Model model, ModelAnimation anim, int frame); // Update model animation pose (CPU)
1606RLAPI void UpdateModelAnimationBones(Model model, ModelAnimation anim, int frame); // Update model animation mesh bone matrices (GPU skinning)
1607RLAPI void UnloadModelAnimation(ModelAnimation anim); // Unload animation data
1608RLAPI void UnloadModelAnimations(ModelAnimation *animations, int animCount); // Unload animation array data
1609RLAPI bool IsModelAnimationValid(Model model, ModelAnimation anim); // Check model animation skeleton match
1610
1611// Collision detection functions
1612RLAPI bool CheckCollisionSpheres(Vector3 center1, float radius1, Vector3 center2, float radius2); // Check collision between two spheres
1613RLAPI bool CheckCollisionBoxes(BoundingBox box1, BoundingBox box2); // Check collision between two bounding boxes
1614RLAPI bool CheckCollisionBoxSphere(BoundingBox box, Vector3 center, float radius); // Check collision between box and sphere
1615RLAPI RayCollision GetRayCollisionSphere(Ray ray, Vector3 center, float radius); // Get collision info between ray and sphere
1616RLAPI RayCollision GetRayCollisionBox(Ray ray, BoundingBox box); // Get collision info between ray and box
1617RLAPI RayCollision GetRayCollisionMesh(Ray ray, Mesh mesh, Matrix transform); // Get collision info between ray and mesh
1618RLAPI RayCollision GetRayCollisionTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3); // Get collision info between ray and triangle
1619RLAPI RayCollision GetRayCollisionQuad(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4); // Get collision info between ray and quad
1620
1621//------------------------------------------------------------------------------------
1622// Audio Loading and Playing Functions (Module: audio)
1623//------------------------------------------------------------------------------------
1624typedef void (*AudioCallback)(void *bufferData, unsigned int frames);
1625
1626// Audio device management functions
1627RLAPI void InitAudioDevice(void); // Initialize audio device and context
1628RLAPI void CloseAudioDevice(void); // Close the audio device and context
1629RLAPI bool IsAudioDeviceReady(void); // Check if audio device has been initialized successfully
1630RLAPI void SetMasterVolume(float volume); // Set master volume (listener)
1631RLAPI float GetMasterVolume(void); // Get master volume (listener)
1632
1633// Wave/Sound loading/unloading functions
1634RLAPI Wave LoadWave(const char *fileName); // Load wave data from file
1635RLAPI Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load wave from memory buffer, fileType refers to extension: i.e. '.wav'
1636RLAPI bool IsWaveValid(Wave wave); // Checks if wave data is valid (data loaded and parameters)
1637RLAPI Sound LoadSound(const char *fileName); // Load sound from file
1638RLAPI Sound LoadSoundFromWave(Wave wave); // Load sound from wave data
1639RLAPI Sound LoadSoundAlias(Sound source); // Create a new sound that shares the same sample data as the source sound, does not own the sound data
1640RLAPI bool IsSoundValid(Sound sound); // Checks if a sound is valid (data loaded and buffers initialized)
1641RLAPI void UpdateSound(Sound sound, const void *data, int sampleCount); // Update sound buffer with new data
1642RLAPI void UnloadWave(Wave wave); // Unload wave data
1643RLAPI void UnloadSound(Sound sound); // Unload sound
1644RLAPI void UnloadSoundAlias(Sound alias); // Unload a sound alias (does not deallocate sample data)
1645RLAPI bool ExportWave(Wave wave, const char *fileName); // Export wave data to file, returns true on success
1646RLAPI bool ExportWaveAsCode(Wave wave, const char *fileName); // Export wave sample data to code (.h), returns true on success
1647
1648// Wave/Sound management functions
1649RLAPI void PlaySound(Sound sound); // Play a sound
1650RLAPI void StopSound(Sound sound); // Stop playing a sound
1651RLAPI void PauseSound(Sound sound); // Pause a sound
1652RLAPI void ResumeSound(Sound sound); // Resume a paused sound
1653RLAPI bool IsSoundPlaying(Sound sound); // Check if a sound is currently playing
1654RLAPI void SetSoundVolume(Sound sound, float volume); // Set volume for a sound (1.0 is max level)
1655RLAPI void SetSoundPitch(Sound sound, float pitch); // Set pitch for a sound (1.0 is base level)
1656RLAPI void SetSoundPan(Sound sound, float pan); // Set pan for a sound (0.5 is center)
1657RLAPI Wave WaveCopy(Wave wave); // Copy a wave to a new wave
1658RLAPI void WaveCrop(Wave *wave, int initFrame, int finalFrame); // Crop a wave to defined frames range
1659RLAPI void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels); // Convert wave data to desired format
1660RLAPI float *LoadWaveSamples(Wave wave); // Load samples data from wave as a 32bit float data array
1661RLAPI void UnloadWaveSamples(float *samples); // Unload samples data loaded with LoadWaveSamples()
1662
1663// Music management functions
1664RLAPI Music LoadMusicStream(const char *fileName); // Load music stream from file
1665RLAPI Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data, int dataSize); // Load music stream from data
1666RLAPI bool IsMusicValid(Music music); // Checks if a music stream is valid (context and buffers initialized)
1667RLAPI void UnloadMusicStream(Music music); // Unload music stream
1668RLAPI void PlayMusicStream(Music music); // Start music playing
1669RLAPI bool IsMusicStreamPlaying(Music music); // Check if music is playing
1670RLAPI void UpdateMusicStream(Music music); // Updates buffers for music streaming
1671RLAPI void StopMusicStream(Music music); // Stop music playing
1672RLAPI void PauseMusicStream(Music music); // Pause music playing
1673RLAPI void ResumeMusicStream(Music music); // Resume playing paused music
1674RLAPI void SeekMusicStream(Music music, float position); // Seek music to a position (in seconds)
1675RLAPI void SetMusicVolume(Music music, float volume); // Set volume for music (1.0 is max level)
1676RLAPI void SetMusicPitch(Music music, float pitch); // Set pitch for a music (1.0 is base level)
1677RLAPI void SetMusicPan(Music music, float pan); // Set pan for a music (0.5 is center)
1678RLAPI float GetMusicTimeLength(Music music); // Get music time length (in seconds)
1679RLAPI float GetMusicTimePlayed(Music music); // Get current music time played (in seconds)
1680
1681// AudioStream management functions
1682RLAPI AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, unsigned int channels); // Load audio stream (to stream raw audio pcm data)
1683RLAPI bool IsAudioStreamValid(AudioStream stream); // Checks if an audio stream is valid (buffers initialized)
1684RLAPI void UnloadAudioStream(AudioStream stream); // Unload audio stream and free memory
1685RLAPI void UpdateAudioStream(AudioStream stream, const void *data, int frameCount); // Update audio stream buffers with data
1686RLAPI bool IsAudioStreamProcessed(AudioStream stream); // Check if any audio stream buffers requires refill
1687RLAPI void PlayAudioStream(AudioStream stream); // Play audio stream
1688RLAPI void PauseAudioStream(AudioStream stream); // Pause audio stream
1689RLAPI void ResumeAudioStream(AudioStream stream); // Resume audio stream
1690RLAPI bool IsAudioStreamPlaying(AudioStream stream); // Check if audio stream is playing
1691RLAPI void StopAudioStream(AudioStream stream); // Stop audio stream
1692RLAPI void SetAudioStreamVolume(AudioStream stream, float volume); // Set volume for audio stream (1.0 is max level)
1693RLAPI void SetAudioStreamPitch(AudioStream stream, float pitch); // Set pitch for audio stream (1.0 is base level)
1694RLAPI void SetAudioStreamPan(AudioStream stream, float pan); // Set pan for audio stream (0.5 is centered)
1695RLAPI void SetAudioStreamBufferSizeDefault(int size); // Default size for new audio streams
1696RLAPI void SetAudioStreamCallback(AudioStream stream, AudioCallback callback); // Audio thread callback to request new data
1697
1698RLAPI void AttachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Attach audio stream processor to stream, receives the samples as 'float'
1699RLAPI void DetachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Detach audio stream processor from stream
1700
1701RLAPI void AttachAudioMixedProcessor(AudioCallback processor); // Attach audio stream processor to the entire audio pipeline, receives the samples as 'float'
1702RLAPI void DetachAudioMixedProcessor(AudioCallback processor); // Detach audio stream processor from the entire audio pipeline
1703
1704#if defined(__cplusplus)
1705}
1706#endif
1707
1708#endif // RAYLIB_H
diff --git a/vendor/raylib-5.5_macos/include/raymath.h b/vendor/raylib-5.5_macos/include/raymath.h
new file mode 100644
index 0000000..e522113
--- /dev/null
+++ b/vendor/raylib-5.5_macos/include/raymath.h
@@ -0,0 +1,2941 @@
1/**********************************************************************************************
2*
3* raymath v2.0 - Math functions to work with Vector2, Vector3, Matrix and Quaternions
4*
5* CONVENTIONS:
6* - Matrix structure is defined as row-major (memory layout) but parameters naming AND all
7* math operations performed by the library consider the structure as it was column-major
8* It is like transposed versions of the matrices are used for all the maths
9* It benefits some functions making them cache-friendly and also avoids matrix
10* transpositions sometimes required by OpenGL
11* Example: In memory order, row0 is [m0 m4 m8 m12] but in semantic math row0 is [m0 m1 m2 m3]
12* - Functions are always self-contained, no function use another raymath function inside,
13* required code is directly re-implemented inside
14* - Functions input parameters are always received by value (2 unavoidable exceptions)
15* - Functions use always a "result" variable for return (except C++ operators)
16* - Functions are always defined inline
17* - Angles are always in radians (DEG2RAD/RAD2DEG macros provided for convenience)
18* - No compound literals used to make sure libray is compatible with C++
19*
20* CONFIGURATION:
21* #define RAYMATH_IMPLEMENTATION
22* Generates the implementation of the library into the included file.
23* If not defined, the library is in header only mode and can be included in other headers
24* or source files without problems. But only ONE file should hold the implementation.
25*
26* #define RAYMATH_STATIC_INLINE
27* Define static inline functions code, so #include header suffices for use.
28* This may use up lots of memory.
29*
30* #define RAYMATH_DISABLE_CPP_OPERATORS
31* Disables C++ operator overloads for raymath types.
32*
33* LICENSE: zlib/libpng
34*
35* Copyright (c) 2015-2024 Ramon Santamaria (@raysan5)
36*
37* This software is provided "as-is", without any express or implied warranty. In no event
38* will the authors be held liable for any damages arising from the use of this software.
39*
40* Permission is granted to anyone to use this software for any purpose, including commercial
41* applications, and to alter it and redistribute it freely, subject to the following restrictions:
42*
43* 1. The origin of this software must not be misrepresented; you must not claim that you
44* wrote the original software. If you use this software in a product, an acknowledgment
45* in the product documentation would be appreciated but is not required.
46*
47* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
48* as being the original software.
49*
50* 3. This notice may not be removed or altered from any source distribution.
51*
52**********************************************************************************************/
53
54#ifndef RAYMATH_H
55#define RAYMATH_H
56
57#if defined(RAYMATH_IMPLEMENTATION) && defined(RAYMATH_STATIC_INLINE)
58 #error "Specifying both RAYMATH_IMPLEMENTATION and RAYMATH_STATIC_INLINE is contradictory"
59#endif
60
61// Function specifiers definition
62#if defined(RAYMATH_IMPLEMENTATION)
63 #if defined(_WIN32) && defined(BUILD_LIBTYPE_SHARED)
64 #define RMAPI __declspec(dllexport) extern inline // We are building raylib as a Win32 shared library (.dll)
65 #elif defined(BUILD_LIBTYPE_SHARED)
66 #define RMAPI __attribute__((visibility("default"))) // We are building raylib as a Unix shared library (.so/.dylib)
67 #elif defined(_WIN32) && defined(USE_LIBTYPE_SHARED)
68 #define RMAPI __declspec(dllimport) // We are using raylib as a Win32 shared library (.dll)
69 #else
70 #define RMAPI extern inline // Provide external definition
71 #endif
72#elif defined(RAYMATH_STATIC_INLINE)
73 #define RMAPI static inline // Functions may be inlined, no external out-of-line definition
74#else
75 #if defined(__TINYC__)
76 #define RMAPI static inline // plain inline not supported by tinycc (See issue #435)
77 #else
78 #define RMAPI inline // Functions may be inlined or external definition used
79 #endif
80#endif
81
82
83//----------------------------------------------------------------------------------
84// Defines and Macros
85//----------------------------------------------------------------------------------
86#ifndef PI
87 #define PI 3.14159265358979323846f
88#endif
89
90#ifndef EPSILON
91 #define EPSILON 0.000001f
92#endif
93
94#ifndef DEG2RAD
95 #define DEG2RAD (PI/180.0f)
96#endif
97
98#ifndef RAD2DEG
99 #define RAD2DEG (180.0f/PI)
100#endif
101
102// Get float vector for Matrix
103#ifndef MatrixToFloat
104 #define MatrixToFloat(mat) (MatrixToFloatV(mat).v)
105#endif
106
107// Get float vector for Vector3
108#ifndef Vector3ToFloat
109 #define Vector3ToFloat(vec) (Vector3ToFloatV(vec).v)
110#endif
111
112//----------------------------------------------------------------------------------
113// Types and Structures Definition
114//----------------------------------------------------------------------------------
115#if !defined(RL_VECTOR2_TYPE)
116// Vector2 type
117typedef struct Vector2 {
118 float x;
119 float y;
120} Vector2;
121#define RL_VECTOR2_TYPE
122#endif
123
124#if !defined(RL_VECTOR3_TYPE)
125// Vector3 type
126typedef struct Vector3 {
127 float x;
128 float y;
129 float z;
130} Vector3;
131#define RL_VECTOR3_TYPE
132#endif
133
134#if !defined(RL_VECTOR4_TYPE)
135// Vector4 type
136typedef struct Vector4 {
137 float x;
138 float y;
139 float z;
140 float w;
141} Vector4;
142#define RL_VECTOR4_TYPE
143#endif
144
145#if !defined(RL_QUATERNION_TYPE)
146// Quaternion type
147typedef Vector4 Quaternion;
148#define RL_QUATERNION_TYPE
149#endif
150
151#if !defined(RL_MATRIX_TYPE)
152// Matrix type (OpenGL style 4x4 - right handed, column major)
153typedef struct Matrix {
154 float m0, m4, m8, m12; // Matrix first row (4 components)
155 float m1, m5, m9, m13; // Matrix second row (4 components)
156 float m2, m6, m10, m14; // Matrix third row (4 components)
157 float m3, m7, m11, m15; // Matrix fourth row (4 components)
158} Matrix;
159#define RL_MATRIX_TYPE
160#endif
161
162// NOTE: Helper types to be used instead of array return types for *ToFloat functions
163typedef struct float3 {
164 float v[3];
165} float3;
166
167typedef struct float16 {
168 float v[16];
169} float16;
170
171#include <math.h> // Required for: sinf(), cosf(), tan(), atan2f(), sqrtf(), floor(), fminf(), fmaxf(), fabsf()
172
173//----------------------------------------------------------------------------------
174// Module Functions Definition - Utils math
175//----------------------------------------------------------------------------------
176
177// Clamp float value
178RMAPI float Clamp(float value, float min, float max)
179{
180 float result = (value < min)? min : value;
181
182 if (result > max) result = max;
183
184 return result;
185}
186
187// Calculate linear interpolation between two floats
188RMAPI float Lerp(float start, float end, float amount)
189{
190 float result = start + amount*(end - start);
191
192 return result;
193}
194
195// Normalize input value within input range
196RMAPI float Normalize(float value, float start, float end)
197{
198 float result = (value - start)/(end - start);
199
200 return result;
201}
202
203// Remap input value within input range to output range
204RMAPI float Remap(float value, float inputStart, float inputEnd, float outputStart, float outputEnd)
205{
206 float result = (value - inputStart)/(inputEnd - inputStart)*(outputEnd - outputStart) + outputStart;
207
208 return result;
209}
210
211// Wrap input value from min to max
212RMAPI float Wrap(float value, float min, float max)
213{
214 float result = value - (max - min)*floorf((value - min)/(max - min));
215
216 return result;
217}
218
219// Check whether two given floats are almost equal
220RMAPI int FloatEquals(float x, float y)
221{
222#if !defined(EPSILON)
223 #define EPSILON 0.000001f
224#endif
225
226 int result = (fabsf(x - y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(x), fabsf(y))));
227
228 return result;
229}
230
231//----------------------------------------------------------------------------------
232// Module Functions Definition - Vector2 math
233//----------------------------------------------------------------------------------
234
235// Vector with components value 0.0f
236RMAPI Vector2 Vector2Zero(void)
237{
238 Vector2 result = { 0.0f, 0.0f };
239
240 return result;
241}
242
243// Vector with components value 1.0f
244RMAPI Vector2 Vector2One(void)
245{
246 Vector2 result = { 1.0f, 1.0f };
247
248 return result;
249}
250
251// Add two vectors (v1 + v2)
252RMAPI Vector2 Vector2Add(Vector2 v1, Vector2 v2)
253{
254 Vector2 result = { v1.x + v2.x, v1.y + v2.y };
255
256 return result;
257}
258
259// Add vector and float value
260RMAPI Vector2 Vector2AddValue(Vector2 v, float add)
261{
262 Vector2 result = { v.x + add, v.y + add };
263
264 return result;
265}
266
267// Subtract two vectors (v1 - v2)
268RMAPI Vector2 Vector2Subtract(Vector2 v1, Vector2 v2)
269{
270 Vector2 result = { v1.x - v2.x, v1.y - v2.y };
271
272 return result;
273}
274
275// Subtract vector by float value
276RMAPI Vector2 Vector2SubtractValue(Vector2 v, float sub)
277{
278 Vector2 result = { v.x - sub, v.y - sub };
279
280 return result;
281}
282
283// Calculate vector length
284RMAPI float Vector2Length(Vector2 v)
285{
286 float result = sqrtf((v.x*v.x) + (v.y*v.y));
287
288 return result;
289}
290
291// Calculate vector square length
292RMAPI float Vector2LengthSqr(Vector2 v)
293{
294 float result = (v.x*v.x) + (v.y*v.y);
295
296 return result;
297}
298
299// Calculate two vectors dot product
300RMAPI float Vector2DotProduct(Vector2 v1, Vector2 v2)
301{
302 float result = (v1.x*v2.x + v1.y*v2.y);
303
304 return result;
305}
306
307// Calculate distance between two vectors
308RMAPI float Vector2Distance(Vector2 v1, Vector2 v2)
309{
310 float result = sqrtf((v1.x - v2.x)*(v1.x - v2.x) + (v1.y - v2.y)*(v1.y - v2.y));
311
312 return result;
313}
314
315// Calculate square distance between two vectors
316RMAPI float Vector2DistanceSqr(Vector2 v1, Vector2 v2)
317{
318 float result = ((v1.x - v2.x)*(v1.x - v2.x) + (v1.y - v2.y)*(v1.y - v2.y));
319
320 return result;
321}
322
323// Calculate angle between two vectors
324// NOTE: Angle is calculated from origin point (0, 0)
325RMAPI float Vector2Angle(Vector2 v1, Vector2 v2)
326{
327 float result = 0.0f;
328
329 float dot = v1.x*v2.x + v1.y*v2.y;
330 float det = v1.x*v2.y - v1.y*v2.x;
331
332 result = atan2f(det, dot);
333
334 return result;
335}
336
337// Calculate angle defined by a two vectors line
338// NOTE: Parameters need to be normalized
339// Current implementation should be aligned with glm::angle
340RMAPI float Vector2LineAngle(Vector2 start, Vector2 end)
341{
342 float result = 0.0f;
343
344 // TODO(10/9/2023): Currently angles move clockwise, determine if this is wanted behavior
345 result = -atan2f(end.y - start.y, end.x - start.x);
346
347 return result;
348}
349
350// Scale vector (multiply by value)
351RMAPI Vector2 Vector2Scale(Vector2 v, float scale)
352{
353 Vector2 result = { v.x*scale, v.y*scale };
354
355 return result;
356}
357
358// Multiply vector by vector
359RMAPI Vector2 Vector2Multiply(Vector2 v1, Vector2 v2)
360{
361 Vector2 result = { v1.x*v2.x, v1.y*v2.y };
362
363 return result;
364}
365
366// Negate vector
367RMAPI Vector2 Vector2Negate(Vector2 v)
368{
369 Vector2 result = { -v.x, -v.y };
370
371 return result;
372}
373
374// Divide vector by vector
375RMAPI Vector2 Vector2Divide(Vector2 v1, Vector2 v2)
376{
377 Vector2 result = { v1.x/v2.x, v1.y/v2.y };
378
379 return result;
380}
381
382// Normalize provided vector
383RMAPI Vector2 Vector2Normalize(Vector2 v)
384{
385 Vector2 result = { 0 };
386 float length = sqrtf((v.x*v.x) + (v.y*v.y));
387
388 if (length > 0)
389 {
390 float ilength = 1.0f/length;
391 result.x = v.x*ilength;
392 result.y = v.y*ilength;
393 }
394
395 return result;
396}
397
398// Transforms a Vector2 by a given Matrix
399RMAPI Vector2 Vector2Transform(Vector2 v, Matrix mat)
400{
401 Vector2 result = { 0 };
402
403 float x = v.x;
404 float y = v.y;
405 float z = 0;
406
407 result.x = mat.m0*x + mat.m4*y + mat.m8*z + mat.m12;
408 result.y = mat.m1*x + mat.m5*y + mat.m9*z + mat.m13;
409
410 return result;
411}
412
413// Calculate linear interpolation between two vectors
414RMAPI Vector2 Vector2Lerp(Vector2 v1, Vector2 v2, float amount)
415{
416 Vector2 result = { 0 };
417
418 result.x = v1.x + amount*(v2.x - v1.x);
419 result.y = v1.y + amount*(v2.y - v1.y);
420
421 return result;
422}
423
424// Calculate reflected vector to normal
425RMAPI Vector2 Vector2Reflect(Vector2 v, Vector2 normal)
426{
427 Vector2 result = { 0 };
428
429 float dotProduct = (v.x*normal.x + v.y*normal.y); // Dot product
430
431 result.x = v.x - (2.0f*normal.x)*dotProduct;
432 result.y = v.y - (2.0f*normal.y)*dotProduct;
433
434 return result;
435}
436
437// Get min value for each pair of components
438RMAPI Vector2 Vector2Min(Vector2 v1, Vector2 v2)
439{
440 Vector2 result = { 0 };
441
442 result.x = fminf(v1.x, v2.x);
443 result.y = fminf(v1.y, v2.y);
444
445 return result;
446}
447
448// Get max value for each pair of components
449RMAPI Vector2 Vector2Max(Vector2 v1, Vector2 v2)
450{
451 Vector2 result = { 0 };
452
453 result.x = fmaxf(v1.x, v2.x);
454 result.y = fmaxf(v1.y, v2.y);
455
456 return result;
457}
458
459// Rotate vector by angle
460RMAPI Vector2 Vector2Rotate(Vector2 v, float angle)
461{
462 Vector2 result = { 0 };
463
464 float cosres = cosf(angle);
465 float sinres = sinf(angle);
466
467 result.x = v.x*cosres - v.y*sinres;
468 result.y = v.x*sinres + v.y*cosres;
469
470 return result;
471}
472
473// Move Vector towards target
474RMAPI Vector2 Vector2MoveTowards(Vector2 v, Vector2 target, float maxDistance)
475{
476 Vector2 result = { 0 };
477
478 float dx = target.x - v.x;
479 float dy = target.y - v.y;
480 float value = (dx*dx) + (dy*dy);
481
482 if ((value == 0) || ((maxDistance >= 0) && (value <= maxDistance*maxDistance))) return target;
483
484 float dist = sqrtf(value);
485
486 result.x = v.x + dx/dist*maxDistance;
487 result.y = v.y + dy/dist*maxDistance;
488
489 return result;
490}
491
492// Invert the given vector
493RMAPI Vector2 Vector2Invert(Vector2 v)
494{
495 Vector2 result = { 1.0f/v.x, 1.0f/v.y };
496
497 return result;
498}
499
500// Clamp the components of the vector between
501// min and max values specified by the given vectors
502RMAPI Vector2 Vector2Clamp(Vector2 v, Vector2 min, Vector2 max)
503{
504 Vector2 result = { 0 };
505
506 result.x = fminf(max.x, fmaxf(min.x, v.x));
507 result.y = fminf(max.y, fmaxf(min.y, v.y));
508
509 return result;
510}
511
512// Clamp the magnitude of the vector between two min and max values
513RMAPI Vector2 Vector2ClampValue(Vector2 v, float min, float max)
514{
515 Vector2 result = v;
516
517 float length = (v.x*v.x) + (v.y*v.y);
518 if (length > 0.0f)
519 {
520 length = sqrtf(length);
521
522 float scale = 1; // By default, 1 as the neutral element.
523 if (length < min)
524 {
525 scale = min/length;
526 }
527 else if (length > max)
528 {
529 scale = max/length;
530 }
531
532 result.x = v.x*scale;
533 result.y = v.y*scale;
534 }
535
536 return result;
537}
538
539// Check whether two given vectors are almost equal
540RMAPI int Vector2Equals(Vector2 p, Vector2 q)
541{
542#if !defined(EPSILON)
543 #define EPSILON 0.000001f
544#endif
545
546 int result = ((fabsf(p.x - q.x)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) &&
547 ((fabsf(p.y - q.y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y)))));
548
549 return result;
550}
551
552// Compute the direction of a refracted ray
553// v: normalized direction of the incoming ray
554// n: normalized normal vector of the interface of two optical media
555// r: ratio of the refractive index of the medium from where the ray comes
556// to the refractive index of the medium on the other side of the surface
557RMAPI Vector2 Vector2Refract(Vector2 v, Vector2 n, float r)
558{
559 Vector2 result = { 0 };
560
561 float dot = v.x*n.x + v.y*n.y;
562 float d = 1.0f - r*r*(1.0f - dot*dot);
563
564 if (d >= 0.0f)
565 {
566 d = sqrtf(d);
567 v.x = r*v.x - (r*dot + d)*n.x;
568 v.y = r*v.y - (r*dot + d)*n.y;
569
570 result = v;
571 }
572
573 return result;
574}
575
576
577//----------------------------------------------------------------------------------
578// Module Functions Definition - Vector3 math
579//----------------------------------------------------------------------------------
580
581// Vector with components value 0.0f
582RMAPI Vector3 Vector3Zero(void)
583{
584 Vector3 result = { 0.0f, 0.0f, 0.0f };
585
586 return result;
587}
588
589// Vector with components value 1.0f
590RMAPI Vector3 Vector3One(void)
591{
592 Vector3 result = { 1.0f, 1.0f, 1.0f };
593
594 return result;
595}
596
597// Add two vectors
598RMAPI Vector3 Vector3Add(Vector3 v1, Vector3 v2)
599{
600 Vector3 result = { v1.x + v2.x, v1.y + v2.y, v1.z + v2.z };
601
602 return result;
603}
604
605// Add vector and float value
606RMAPI Vector3 Vector3AddValue(Vector3 v, float add)
607{
608 Vector3 result = { v.x + add, v.y + add, v.z + add };
609
610 return result;
611}
612
613// Subtract two vectors
614RMAPI Vector3 Vector3Subtract(Vector3 v1, Vector3 v2)
615{
616 Vector3 result = { v1.x - v2.x, v1.y - v2.y, v1.z - v2.z };
617
618 return result;
619}
620
621// Subtract vector by float value
622RMAPI Vector3 Vector3SubtractValue(Vector3 v, float sub)
623{
624 Vector3 result = { v.x - sub, v.y - sub, v.z - sub };
625
626 return result;
627}
628
629// Multiply vector by scalar
630RMAPI Vector3 Vector3Scale(Vector3 v, float scalar)
631{
632 Vector3 result = { v.x*scalar, v.y*scalar, v.z*scalar };
633
634 return result;
635}
636
637// Multiply vector by vector
638RMAPI Vector3 Vector3Multiply(Vector3 v1, Vector3 v2)
639{
640 Vector3 result = { v1.x*v2.x, v1.y*v2.y, v1.z*v2.z };
641
642 return result;
643}
644
645// Calculate two vectors cross product
646RMAPI Vector3 Vector3CrossProduct(Vector3 v1, Vector3 v2)
647{
648 Vector3 result = { v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x };
649
650 return result;
651}
652
653// Calculate one vector perpendicular vector
654RMAPI Vector3 Vector3Perpendicular(Vector3 v)
655{
656 Vector3 result = { 0 };
657
658 float min = fabsf(v.x);
659 Vector3 cardinalAxis = {1.0f, 0.0f, 0.0f};
660
661 if (fabsf(v.y) < min)
662 {
663 min = fabsf(v.y);
664 Vector3 tmp = {0.0f, 1.0f, 0.0f};
665 cardinalAxis = tmp;
666 }
667
668 if (fabsf(v.z) < min)
669 {
670 Vector3 tmp = {0.0f, 0.0f, 1.0f};
671 cardinalAxis = tmp;
672 }
673
674 // Cross product between vectors
675 result.x = v.y*cardinalAxis.z - v.z*cardinalAxis.y;
676 result.y = v.z*cardinalAxis.x - v.x*cardinalAxis.z;
677 result.z = v.x*cardinalAxis.y - v.y*cardinalAxis.x;
678
679 return result;
680}
681
682// Calculate vector length
683RMAPI float Vector3Length(const Vector3 v)
684{
685 float result = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z);
686
687 return result;
688}
689
690// Calculate vector square length
691RMAPI float Vector3LengthSqr(const Vector3 v)
692{
693 float result = v.x*v.x + v.y*v.y + v.z*v.z;
694
695 return result;
696}
697
698// Calculate two vectors dot product
699RMAPI float Vector3DotProduct(Vector3 v1, Vector3 v2)
700{
701 float result = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z);
702
703 return result;
704}
705
706// Calculate distance between two vectors
707RMAPI float Vector3Distance(Vector3 v1, Vector3 v2)
708{
709 float result = 0.0f;
710
711 float dx = v2.x - v1.x;
712 float dy = v2.y - v1.y;
713 float dz = v2.z - v1.z;
714 result = sqrtf(dx*dx + dy*dy + dz*dz);
715
716 return result;
717}
718
719// Calculate square distance between two vectors
720RMAPI float Vector3DistanceSqr(Vector3 v1, Vector3 v2)
721{
722 float result = 0.0f;
723
724 float dx = v2.x - v1.x;
725 float dy = v2.y - v1.y;
726 float dz = v2.z - v1.z;
727 result = dx*dx + dy*dy + dz*dz;
728
729 return result;
730}
731
732// Calculate angle between two vectors
733RMAPI float Vector3Angle(Vector3 v1, Vector3 v2)
734{
735 float result = 0.0f;
736
737 Vector3 cross = { v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x };
738 float len = sqrtf(cross.x*cross.x + cross.y*cross.y + cross.z*cross.z);
739 float dot = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z);
740 result = atan2f(len, dot);
741
742 return result;
743}
744
745// Negate provided vector (invert direction)
746RMAPI Vector3 Vector3Negate(Vector3 v)
747{
748 Vector3 result = { -v.x, -v.y, -v.z };
749
750 return result;
751}
752
753// Divide vector by vector
754RMAPI Vector3 Vector3Divide(Vector3 v1, Vector3 v2)
755{
756 Vector3 result = { v1.x/v2.x, v1.y/v2.y, v1.z/v2.z };
757
758 return result;
759}
760
761// Normalize provided vector
762RMAPI Vector3 Vector3Normalize(Vector3 v)
763{
764 Vector3 result = v;
765
766 float length = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z);
767 if (length != 0.0f)
768 {
769 float ilength = 1.0f/length;
770
771 result.x *= ilength;
772 result.y *= ilength;
773 result.z *= ilength;
774 }
775
776 return result;
777}
778
779//Calculate the projection of the vector v1 on to v2
780RMAPI Vector3 Vector3Project(Vector3 v1, Vector3 v2)
781{
782 Vector3 result = { 0 };
783
784 float v1dv2 = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z);
785 float v2dv2 = (v2.x*v2.x + v2.y*v2.y + v2.z*v2.z);
786
787 float mag = v1dv2/v2dv2;
788
789 result.x = v2.x*mag;
790 result.y = v2.y*mag;
791 result.z = v2.z*mag;
792
793 return result;
794}
795
796//Calculate the rejection of the vector v1 on to v2
797RMAPI Vector3 Vector3Reject(Vector3 v1, Vector3 v2)
798{
799 Vector3 result = { 0 };
800
801 float v1dv2 = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z);
802 float v2dv2 = (v2.x*v2.x + v2.y*v2.y + v2.z*v2.z);
803
804 float mag = v1dv2/v2dv2;
805
806 result.x = v1.x - (v2.x*mag);
807 result.y = v1.y - (v2.y*mag);
808 result.z = v1.z - (v2.z*mag);
809
810 return result;
811}
812
813// Orthonormalize provided vectors
814// Makes vectors normalized and orthogonal to each other
815// Gram-Schmidt function implementation
816RMAPI void Vector3OrthoNormalize(Vector3 *v1, Vector3 *v2)
817{
818 float length = 0.0f;
819 float ilength = 0.0f;
820
821 // Vector3Normalize(*v1);
822 Vector3 v = *v1;
823 length = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z);
824 if (length == 0.0f) length = 1.0f;
825 ilength = 1.0f/length;
826 v1->x *= ilength;
827 v1->y *= ilength;
828 v1->z *= ilength;
829
830 // Vector3CrossProduct(*v1, *v2)
831 Vector3 vn1 = { v1->y*v2->z - v1->z*v2->y, v1->z*v2->x - v1->x*v2->z, v1->x*v2->y - v1->y*v2->x };
832
833 // Vector3Normalize(vn1);
834 v = vn1;
835 length = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z);
836 if (length == 0.0f) length = 1.0f;
837 ilength = 1.0f/length;
838 vn1.x *= ilength;
839 vn1.y *= ilength;
840 vn1.z *= ilength;
841
842 // Vector3CrossProduct(vn1, *v1)
843 Vector3 vn2 = { vn1.y*v1->z - vn1.z*v1->y, vn1.z*v1->x - vn1.x*v1->z, vn1.x*v1->y - vn1.y*v1->x };
844
845 *v2 = vn2;
846}
847
848// Transforms a Vector3 by a given Matrix
849RMAPI Vector3 Vector3Transform(Vector3 v, Matrix mat)
850{
851 Vector3 result = { 0 };
852
853 float x = v.x;
854 float y = v.y;
855 float z = v.z;
856
857 result.x = mat.m0*x + mat.m4*y + mat.m8*z + mat.m12;
858 result.y = mat.m1*x + mat.m5*y + mat.m9*z + mat.m13;
859 result.z = mat.m2*x + mat.m6*y + mat.m10*z + mat.m14;
860
861 return result;
862}
863
864// Transform a vector by quaternion rotation
865RMAPI Vector3 Vector3RotateByQuaternion(Vector3 v, Quaternion q)
866{
867 Vector3 result = { 0 };
868
869 result.x = v.x*(q.x*q.x + q.w*q.w - q.y*q.y - q.z*q.z) + v.y*(2*q.x*q.y - 2*q.w*q.z) + v.z*(2*q.x*q.z + 2*q.w*q.y);
870 result.y = v.x*(2*q.w*q.z + 2*q.x*q.y) + v.y*(q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z) + v.z*(-2*q.w*q.x + 2*q.y*q.z);
871 result.z = v.x*(-2*q.w*q.y + 2*q.x*q.z) + v.y*(2*q.w*q.x + 2*q.y*q.z)+ v.z*(q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z);
872
873 return result;
874}
875
876// Rotates a vector around an axis
877RMAPI Vector3 Vector3RotateByAxisAngle(Vector3 v, Vector3 axis, float angle)
878{
879 // Using Euler-Rodrigues Formula
880 // Ref.: https://en.wikipedia.org/w/index.php?title=Euler%E2%80%93Rodrigues_formula
881
882 Vector3 result = v;
883
884 // Vector3Normalize(axis);
885 float length = sqrtf(axis.x*axis.x + axis.y*axis.y + axis.z*axis.z);
886 if (length == 0.0f) length = 1.0f;
887 float ilength = 1.0f/length;
888 axis.x *= ilength;
889 axis.y *= ilength;
890 axis.z *= ilength;
891
892 angle /= 2.0f;
893 float a = sinf(angle);
894 float b = axis.x*a;
895 float c = axis.y*a;
896 float d = axis.z*a;
897 a = cosf(angle);
898 Vector3 w = { b, c, d };
899
900 // Vector3CrossProduct(w, v)
901 Vector3 wv = { w.y*v.z - w.z*v.y, w.z*v.x - w.x*v.z, w.x*v.y - w.y*v.x };
902
903 // Vector3CrossProduct(w, wv)
904 Vector3 wwv = { w.y*wv.z - w.z*wv.y, w.z*wv.x - w.x*wv.z, w.x*wv.y - w.y*wv.x };
905
906 // Vector3Scale(wv, 2*a)
907 a *= 2;
908 wv.x *= a;
909 wv.y *= a;
910 wv.z *= a;
911
912 // Vector3Scale(wwv, 2)
913 wwv.x *= 2;
914 wwv.y *= 2;
915 wwv.z *= 2;
916
917 result.x += wv.x;
918 result.y += wv.y;
919 result.z += wv.z;
920
921 result.x += wwv.x;
922 result.y += wwv.y;
923 result.z += wwv.z;
924
925 return result;
926}
927
928// Move Vector towards target
929RMAPI Vector3 Vector3MoveTowards(Vector3 v, Vector3 target, float maxDistance)
930{
931 Vector3 result = { 0 };
932
933 float dx = target.x - v.x;
934 float dy = target.y - v.y;
935 float dz = target.z - v.z;
936 float value = (dx*dx) + (dy*dy) + (dz*dz);
937
938 if ((value == 0) || ((maxDistance >= 0) && (value <= maxDistance*maxDistance))) return target;
939
940 float dist = sqrtf(value);
941
942 result.x = v.x + dx/dist*maxDistance;
943 result.y = v.y + dy/dist*maxDistance;
944 result.z = v.z + dz/dist*maxDistance;
945
946 return result;
947}
948
949// Calculate linear interpolation between two vectors
950RMAPI Vector3 Vector3Lerp(Vector3 v1, Vector3 v2, float amount)
951{
952 Vector3 result = { 0 };
953
954 result.x = v1.x + amount*(v2.x - v1.x);
955 result.y = v1.y + amount*(v2.y - v1.y);
956 result.z = v1.z + amount*(v2.z - v1.z);
957
958 return result;
959}
960
961// Calculate cubic hermite interpolation between two vectors and their tangents
962// as described in the GLTF 2.0 specification: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#interpolation-cubic
963RMAPI Vector3 Vector3CubicHermite(Vector3 v1, Vector3 tangent1, Vector3 v2, Vector3 tangent2, float amount)
964{
965 Vector3 result = { 0 };
966
967 float amountPow2 = amount*amount;
968 float amountPow3 = amount*amount*amount;
969
970 result.x = (2*amountPow3 - 3*amountPow2 + 1)*v1.x + (amountPow3 - 2*amountPow2 + amount)*tangent1.x + (-2*amountPow3 + 3*amountPow2)*v2.x + (amountPow3 - amountPow2)*tangent2.x;
971 result.y = (2*amountPow3 - 3*amountPow2 + 1)*v1.y + (amountPow3 - 2*amountPow2 + amount)*tangent1.y + (-2*amountPow3 + 3*amountPow2)*v2.y + (amountPow3 - amountPow2)*tangent2.y;
972 result.z = (2*amountPow3 - 3*amountPow2 + 1)*v1.z + (amountPow3 - 2*amountPow2 + amount)*tangent1.z + (-2*amountPow3 + 3*amountPow2)*v2.z + (amountPow3 - amountPow2)*tangent2.z;
973
974 return result;
975}
976
977// Calculate reflected vector to normal
978RMAPI Vector3 Vector3Reflect(Vector3 v, Vector3 normal)
979{
980 Vector3 result = { 0 };
981
982 // I is the original vector
983 // N is the normal of the incident plane
984 // R = I - (2*N*(DotProduct[I, N]))
985
986 float dotProduct = (v.x*normal.x + v.y*normal.y + v.z*normal.z);
987
988 result.x = v.x - (2.0f*normal.x)*dotProduct;
989 result.y = v.y - (2.0f*normal.y)*dotProduct;
990 result.z = v.z - (2.0f*normal.z)*dotProduct;
991
992 return result;
993}
994
995// Get min value for each pair of components
996RMAPI Vector3 Vector3Min(Vector3 v1, Vector3 v2)
997{
998 Vector3 result = { 0 };
999
1000 result.x = fminf(v1.x, v2.x);
1001 result.y = fminf(v1.y, v2.y);
1002 result.z = fminf(v1.z, v2.z);
1003
1004 return result;
1005}
1006
1007// Get max value for each pair of components
1008RMAPI Vector3 Vector3Max(Vector3 v1, Vector3 v2)
1009{
1010 Vector3 result = { 0 };
1011
1012 result.x = fmaxf(v1.x, v2.x);
1013 result.y = fmaxf(v1.y, v2.y);
1014 result.z = fmaxf(v1.z, v2.z);
1015
1016 return result;
1017}
1018
1019// Compute barycenter coordinates (u, v, w) for point p with respect to triangle (a, b, c)
1020// NOTE: Assumes P is on the plane of the triangle
1021RMAPI Vector3 Vector3Barycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c)
1022{
1023 Vector3 result = { 0 };
1024
1025 Vector3 v0 = { b.x - a.x, b.y - a.y, b.z - a.z }; // Vector3Subtract(b, a)
1026 Vector3 v1 = { c.x - a.x, c.y - a.y, c.z - a.z }; // Vector3Subtract(c, a)
1027 Vector3 v2 = { p.x - a.x, p.y - a.y, p.z - a.z }; // Vector3Subtract(p, a)
1028 float d00 = (v0.x*v0.x + v0.y*v0.y + v0.z*v0.z); // Vector3DotProduct(v0, v0)
1029 float d01 = (v0.x*v1.x + v0.y*v1.y + v0.z*v1.z); // Vector3DotProduct(v0, v1)
1030 float d11 = (v1.x*v1.x + v1.y*v1.y + v1.z*v1.z); // Vector3DotProduct(v1, v1)
1031 float d20 = (v2.x*v0.x + v2.y*v0.y + v2.z*v0.z); // Vector3DotProduct(v2, v0)
1032 float d21 = (v2.x*v1.x + v2.y*v1.y + v2.z*v1.z); // Vector3DotProduct(v2, v1)
1033
1034 float denom = d00*d11 - d01*d01;
1035
1036 result.y = (d11*d20 - d01*d21)/denom;
1037 result.z = (d00*d21 - d01*d20)/denom;
1038 result.x = 1.0f - (result.z + result.y);
1039
1040 return result;
1041}
1042
1043// Projects a Vector3 from screen space into object space
1044// NOTE: We are avoiding calling other raymath functions despite available
1045RMAPI Vector3 Vector3Unproject(Vector3 source, Matrix projection, Matrix view)
1046{
1047 Vector3 result = { 0 };
1048
1049 // Calculate unprojected matrix (multiply view matrix by projection matrix) and invert it
1050 Matrix matViewProj = { // MatrixMultiply(view, projection);
1051 view.m0*projection.m0 + view.m1*projection.m4 + view.m2*projection.m8 + view.m3*projection.m12,
1052 view.m0*projection.m1 + view.m1*projection.m5 + view.m2*projection.m9 + view.m3*projection.m13,
1053 view.m0*projection.m2 + view.m1*projection.m6 + view.m2*projection.m10 + view.m3*projection.m14,
1054 view.m0*projection.m3 + view.m1*projection.m7 + view.m2*projection.m11 + view.m3*projection.m15,
1055 view.m4*projection.m0 + view.m5*projection.m4 + view.m6*projection.m8 + view.m7*projection.m12,
1056 view.m4*projection.m1 + view.m5*projection.m5 + view.m6*projection.m9 + view.m7*projection.m13,
1057 view.m4*projection.m2 + view.m5*projection.m6 + view.m6*projection.m10 + view.m7*projection.m14,
1058 view.m4*projection.m3 + view.m5*projection.m7 + view.m6*projection.m11 + view.m7*projection.m15,
1059 view.m8*projection.m0 + view.m9*projection.m4 + view.m10*projection.m8 + view.m11*projection.m12,
1060 view.m8*projection.m1 + view.m9*projection.m5 + view.m10*projection.m9 + view.m11*projection.m13,
1061 view.m8*projection.m2 + view.m9*projection.m6 + view.m10*projection.m10 + view.m11*projection.m14,
1062 view.m8*projection.m3 + view.m9*projection.m7 + view.m10*projection.m11 + view.m11*projection.m15,
1063 view.m12*projection.m0 + view.m13*projection.m4 + view.m14*projection.m8 + view.m15*projection.m12,
1064 view.m12*projection.m1 + view.m13*projection.m5 + view.m14*projection.m9 + view.m15*projection.m13,
1065 view.m12*projection.m2 + view.m13*projection.m6 + view.m14*projection.m10 + view.m15*projection.m14,
1066 view.m12*projection.m3 + view.m13*projection.m7 + view.m14*projection.m11 + view.m15*projection.m15 };
1067
1068 // Calculate inverted matrix -> MatrixInvert(matViewProj);
1069 // Cache the matrix values (speed optimization)
1070 float a00 = matViewProj.m0, a01 = matViewProj.m1, a02 = matViewProj.m2, a03 = matViewProj.m3;
1071 float a10 = matViewProj.m4, a11 = matViewProj.m5, a12 = matViewProj.m6, a13 = matViewProj.m7;
1072 float a20 = matViewProj.m8, a21 = matViewProj.m9, a22 = matViewProj.m10, a23 = matViewProj.m11;
1073 float a30 = matViewProj.m12, a31 = matViewProj.m13, a32 = matViewProj.m14, a33 = matViewProj.m15;
1074
1075 float b00 = a00*a11 - a01*a10;
1076 float b01 = a00*a12 - a02*a10;
1077 float b02 = a00*a13 - a03*a10;
1078 float b03 = a01*a12 - a02*a11;
1079 float b04 = a01*a13 - a03*a11;
1080 float b05 = a02*a13 - a03*a12;
1081 float b06 = a20*a31 - a21*a30;
1082 float b07 = a20*a32 - a22*a30;
1083 float b08 = a20*a33 - a23*a30;
1084 float b09 = a21*a32 - a22*a31;
1085 float b10 = a21*a33 - a23*a31;
1086 float b11 = a22*a33 - a23*a32;
1087
1088 // Calculate the invert determinant (inlined to avoid double-caching)
1089 float invDet = 1.0f/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06);
1090
1091 Matrix matViewProjInv = {
1092 (a11*b11 - a12*b10 + a13*b09)*invDet,
1093 (-a01*b11 + a02*b10 - a03*b09)*invDet,
1094 (a31*b05 - a32*b04 + a33*b03)*invDet,
1095 (-a21*b05 + a22*b04 - a23*b03)*invDet,
1096 (-a10*b11 + a12*b08 - a13*b07)*invDet,
1097 (a00*b11 - a02*b08 + a03*b07)*invDet,
1098 (-a30*b05 + a32*b02 - a33*b01)*invDet,
1099 (a20*b05 - a22*b02 + a23*b01)*invDet,
1100 (a10*b10 - a11*b08 + a13*b06)*invDet,
1101 (-a00*b10 + a01*b08 - a03*b06)*invDet,
1102 (a30*b04 - a31*b02 + a33*b00)*invDet,
1103 (-a20*b04 + a21*b02 - a23*b00)*invDet,
1104 (-a10*b09 + a11*b07 - a12*b06)*invDet,
1105 (a00*b09 - a01*b07 + a02*b06)*invDet,
1106 (-a30*b03 + a31*b01 - a32*b00)*invDet,
1107 (a20*b03 - a21*b01 + a22*b00)*invDet };
1108
1109 // Create quaternion from source point
1110 Quaternion quat = { source.x, source.y, source.z, 1.0f };
1111
1112 // Multiply quat point by unprojecte matrix
1113 Quaternion qtransformed = { // QuaternionTransform(quat, matViewProjInv)
1114 matViewProjInv.m0*quat.x + matViewProjInv.m4*quat.y + matViewProjInv.m8*quat.z + matViewProjInv.m12*quat.w,
1115 matViewProjInv.m1*quat.x + matViewProjInv.m5*quat.y + matViewProjInv.m9*quat.z + matViewProjInv.m13*quat.w,
1116 matViewProjInv.m2*quat.x + matViewProjInv.m6*quat.y + matViewProjInv.m10*quat.z + matViewProjInv.m14*quat.w,
1117 matViewProjInv.m3*quat.x + matViewProjInv.m7*quat.y + matViewProjInv.m11*quat.z + matViewProjInv.m15*quat.w };
1118
1119 // Normalized world points in vectors
1120 result.x = qtransformed.x/qtransformed.w;
1121 result.y = qtransformed.y/qtransformed.w;
1122 result.z = qtransformed.z/qtransformed.w;
1123
1124 return result;
1125}
1126
1127// Get Vector3 as float array
1128RMAPI float3 Vector3ToFloatV(Vector3 v)
1129{
1130 float3 buffer = { 0 };
1131
1132 buffer.v[0] = v.x;
1133 buffer.v[1] = v.y;
1134 buffer.v[2] = v.z;
1135
1136 return buffer;
1137}
1138
1139// Invert the given vector
1140RMAPI Vector3 Vector3Invert(Vector3 v)
1141{
1142 Vector3 result = { 1.0f/v.x, 1.0f/v.y, 1.0f/v.z };
1143
1144 return result;
1145}
1146
1147// Clamp the components of the vector between
1148// min and max values specified by the given vectors
1149RMAPI Vector3 Vector3Clamp(Vector3 v, Vector3 min, Vector3 max)
1150{
1151 Vector3 result = { 0 };
1152
1153 result.x = fminf(max.x, fmaxf(min.x, v.x));
1154 result.y = fminf(max.y, fmaxf(min.y, v.y));
1155 result.z = fminf(max.z, fmaxf(min.z, v.z));
1156
1157 return result;
1158}
1159
1160// Clamp the magnitude of the vector between two values
1161RMAPI Vector3 Vector3ClampValue(Vector3 v, float min, float max)
1162{
1163 Vector3 result = v;
1164
1165 float length = (v.x*v.x) + (v.y*v.y) + (v.z*v.z);
1166 if (length > 0.0f)
1167 {
1168 length = sqrtf(length);
1169
1170 float scale = 1; // By default, 1 as the neutral element.
1171 if (length < min)
1172 {
1173 scale = min/length;
1174 }
1175 else if (length > max)
1176 {
1177 scale = max/length;
1178 }
1179
1180 result.x = v.x*scale;
1181 result.y = v.y*scale;
1182 result.z = v.z*scale;
1183 }
1184
1185 return result;
1186}
1187
1188// Check whether two given vectors are almost equal
1189RMAPI int Vector3Equals(Vector3 p, Vector3 q)
1190{
1191#if !defined(EPSILON)
1192 #define EPSILON 0.000001f
1193#endif
1194
1195 int result = ((fabsf(p.x - q.x)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) &&
1196 ((fabsf(p.y - q.y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y))))) &&
1197 ((fabsf(p.z - q.z)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.z), fabsf(q.z)))));
1198
1199 return result;
1200}
1201
1202// Compute the direction of a refracted ray
1203// v: normalized direction of the incoming ray
1204// n: normalized normal vector of the interface of two optical media
1205// r: ratio of the refractive index of the medium from where the ray comes
1206// to the refractive index of the medium on the other side of the surface
1207RMAPI Vector3 Vector3Refract(Vector3 v, Vector3 n, float r)
1208{
1209 Vector3 result = { 0 };
1210
1211 float dot = v.x*n.x + v.y*n.y + v.z*n.z;
1212 float d = 1.0f - r*r*(1.0f - dot*dot);
1213
1214 if (d >= 0.0f)
1215 {
1216 d = sqrtf(d);
1217 v.x = r*v.x - (r*dot + d)*n.x;
1218 v.y = r*v.y - (r*dot + d)*n.y;
1219 v.z = r*v.z - (r*dot + d)*n.z;
1220
1221 result = v;
1222 }
1223
1224 return result;
1225}
1226
1227
1228//----------------------------------------------------------------------------------
1229// Module Functions Definition - Vector4 math
1230//----------------------------------------------------------------------------------
1231
1232RMAPI Vector4 Vector4Zero(void)
1233{
1234 Vector4 result = { 0.0f, 0.0f, 0.0f, 0.0f };
1235 return result;
1236}
1237
1238RMAPI Vector4 Vector4One(void)
1239{
1240 Vector4 result = { 1.0f, 1.0f, 1.0f, 1.0f };
1241 return result;
1242}
1243
1244RMAPI Vector4 Vector4Add(Vector4 v1, Vector4 v2)
1245{
1246 Vector4 result = {
1247 v1.x + v2.x,
1248 v1.y + v2.y,
1249 v1.z + v2.z,
1250 v1.w + v2.w
1251 };
1252 return result;
1253}
1254
1255RMAPI Vector4 Vector4AddValue(Vector4 v, float add)
1256{
1257 Vector4 result = {
1258 v.x + add,
1259 v.y + add,
1260 v.z + add,
1261 v.w + add
1262 };
1263 return result;
1264}
1265
1266RMAPI Vector4 Vector4Subtract(Vector4 v1, Vector4 v2)
1267{
1268 Vector4 result = {
1269 v1.x - v2.x,
1270 v1.y - v2.y,
1271 v1.z - v2.z,
1272 v1.w - v2.w
1273 };
1274 return result;
1275}
1276
1277RMAPI Vector4 Vector4SubtractValue(Vector4 v, float add)
1278{
1279 Vector4 result = {
1280 v.x - add,
1281 v.y - add,
1282 v.z - add,
1283 v.w - add
1284 };
1285 return result;
1286}
1287
1288RMAPI float Vector4Length(Vector4 v)
1289{
1290 float result = sqrtf((v.x*v.x) + (v.y*v.y) + (v.z*v.z) + (v.w*v.w));
1291 return result;
1292}
1293
1294RMAPI float Vector4LengthSqr(Vector4 v)
1295{
1296 float result = (v.x*v.x) + (v.y*v.y) + (v.z*v.z) + (v.w*v.w);
1297 return result;
1298}
1299
1300RMAPI float Vector4DotProduct(Vector4 v1, Vector4 v2)
1301{
1302 float result = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z + v1.w*v2.w);
1303 return result;
1304}
1305
1306// Calculate distance between two vectors
1307RMAPI float Vector4Distance(Vector4 v1, Vector4 v2)
1308{
1309 float result = sqrtf(
1310 (v1.x - v2.x)*(v1.x - v2.x) + (v1.y - v2.y)*(v1.y - v2.y) +
1311 (v1.z - v2.z)*(v1.z - v2.z) + (v1.w - v2.w)*(v1.w - v2.w));
1312 return result;
1313}
1314
1315// Calculate square distance between two vectors
1316RMAPI float Vector4DistanceSqr(Vector4 v1, Vector4 v2)
1317{
1318 float result =
1319 (v1.x - v2.x)*(v1.x - v2.x) + (v1.y - v2.y)*(v1.y - v2.y) +
1320 (v1.z - v2.z)*(v1.z - v2.z) + (v1.w - v2.w)*(v1.w - v2.w);
1321
1322 return result;
1323}
1324
1325RMAPI Vector4 Vector4Scale(Vector4 v, float scale)
1326{
1327 Vector4 result = { v.x*scale, v.y*scale, v.z*scale, v.w*scale };
1328 return result;
1329}
1330
1331// Multiply vector by vector
1332RMAPI Vector4 Vector4Multiply(Vector4 v1, Vector4 v2)
1333{
1334 Vector4 result = { v1.x*v2.x, v1.y*v2.y, v1.z*v2.z, v1.w*v2.w };
1335 return result;
1336}
1337
1338// Negate vector
1339RMAPI Vector4 Vector4Negate(Vector4 v)
1340{
1341 Vector4 result = { -v.x, -v.y, -v.z, -v.w };
1342 return result;
1343}
1344
1345// Divide vector by vector
1346RMAPI Vector4 Vector4Divide(Vector4 v1, Vector4 v2)
1347{
1348 Vector4 result = { v1.x/v2.x, v1.y/v2.y, v1.z/v2.z, v1.w/v2.w };
1349 return result;
1350}
1351
1352// Normalize provided vector
1353RMAPI Vector4 Vector4Normalize(Vector4 v)
1354{
1355 Vector4 result = { 0 };
1356 float length = sqrtf((v.x*v.x) + (v.y*v.y) + (v.z*v.z) + (v.w*v.w));
1357
1358 if (length > 0)
1359 {
1360 float ilength = 1.0f/length;
1361 result.x = v.x*ilength;
1362 result.y = v.y*ilength;
1363 result.z = v.z*ilength;
1364 result.w = v.w*ilength;
1365 }
1366
1367 return result;
1368}
1369
1370// Get min value for each pair of components
1371RMAPI Vector4 Vector4Min(Vector4 v1, Vector4 v2)
1372{
1373 Vector4 result = { 0 };
1374
1375 result.x = fminf(v1.x, v2.x);
1376 result.y = fminf(v1.y, v2.y);
1377 result.z = fminf(v1.z, v2.z);
1378 result.w = fminf(v1.w, v2.w);
1379
1380 return result;
1381}
1382
1383// Get max value for each pair of components
1384RMAPI Vector4 Vector4Max(Vector4 v1, Vector4 v2)
1385{
1386 Vector4 result = { 0 };
1387
1388 result.x = fmaxf(v1.x, v2.x);
1389 result.y = fmaxf(v1.y, v2.y);
1390 result.z = fmaxf(v1.z, v2.z);
1391 result.w = fmaxf(v1.w, v2.w);
1392
1393 return result;
1394}
1395
1396// Calculate linear interpolation between two vectors
1397RMAPI Vector4 Vector4Lerp(Vector4 v1, Vector4 v2, float amount)
1398{
1399 Vector4 result = { 0 };
1400
1401 result.x = v1.x + amount*(v2.x - v1.x);
1402 result.y = v1.y + amount*(v2.y - v1.y);
1403 result.z = v1.z + amount*(v2.z - v1.z);
1404 result.w = v1.w + amount*(v2.w - v1.w);
1405
1406 return result;
1407}
1408
1409// Move Vector towards target
1410RMAPI Vector4 Vector4MoveTowards(Vector4 v, Vector4 target, float maxDistance)
1411{
1412 Vector4 result = { 0 };
1413
1414 float dx = target.x - v.x;
1415 float dy = target.y - v.y;
1416 float dz = target.z - v.z;
1417 float dw = target.w - v.w;
1418 float value = (dx*dx) + (dy*dy) + (dz*dz) + (dw*dw);
1419
1420 if ((value == 0) || ((maxDistance >= 0) && (value <= maxDistance*maxDistance))) return target;
1421
1422 float dist = sqrtf(value);
1423
1424 result.x = v.x + dx/dist*maxDistance;
1425 result.y = v.y + dy/dist*maxDistance;
1426 result.z = v.z + dz/dist*maxDistance;
1427 result.w = v.w + dw/dist*maxDistance;
1428
1429 return result;
1430}
1431
1432// Invert the given vector
1433RMAPI Vector4 Vector4Invert(Vector4 v)
1434{
1435 Vector4 result = { 1.0f/v.x, 1.0f/v.y, 1.0f/v.z, 1.0f/v.w };
1436 return result;
1437}
1438
1439// Check whether two given vectors are almost equal
1440RMAPI int Vector4Equals(Vector4 p, Vector4 q)
1441{
1442#if !defined(EPSILON)
1443 #define EPSILON 0.000001f
1444#endif
1445
1446 int result = ((fabsf(p.x - q.x)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) &&
1447 ((fabsf(p.y - q.y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y))))) &&
1448 ((fabsf(p.z - q.z)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.z), fabsf(q.z))))) &&
1449 ((fabsf(p.w - q.w)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.w), fabsf(q.w)))));
1450 return result;
1451}
1452
1453
1454//----------------------------------------------------------------------------------
1455// Module Functions Definition - Matrix math
1456//----------------------------------------------------------------------------------
1457
1458// Compute matrix determinant
1459RMAPI float MatrixDeterminant(Matrix mat)
1460{
1461 float result = 0.0f;
1462
1463 // Cache the matrix values (speed optimization)
1464 float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3;
1465 float a10 = mat.m4, a11 = mat.m5, a12 = mat.m6, a13 = mat.m7;
1466 float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11;
1467 float a30 = mat.m12, a31 = mat.m13, a32 = mat.m14, a33 = mat.m15;
1468
1469 result = a30*a21*a12*a03 - a20*a31*a12*a03 - a30*a11*a22*a03 + a10*a31*a22*a03 +
1470 a20*a11*a32*a03 - a10*a21*a32*a03 - a30*a21*a02*a13 + a20*a31*a02*a13 +
1471 a30*a01*a22*a13 - a00*a31*a22*a13 - a20*a01*a32*a13 + a00*a21*a32*a13 +
1472 a30*a11*a02*a23 - a10*a31*a02*a23 - a30*a01*a12*a23 + a00*a31*a12*a23 +
1473 a10*a01*a32*a23 - a00*a11*a32*a23 - a20*a11*a02*a33 + a10*a21*a02*a33 +
1474 a20*a01*a12*a33 - a00*a21*a12*a33 - a10*a01*a22*a33 + a00*a11*a22*a33;
1475
1476 return result;
1477}
1478
1479// Get the trace of the matrix (sum of the values along the diagonal)
1480RMAPI float MatrixTrace(Matrix mat)
1481{
1482 float result = (mat.m0 + mat.m5 + mat.m10 + mat.m15);
1483
1484 return result;
1485}
1486
1487// Transposes provided matrix
1488RMAPI Matrix MatrixTranspose(Matrix mat)
1489{
1490 Matrix result = { 0 };
1491
1492 result.m0 = mat.m0;
1493 result.m1 = mat.m4;
1494 result.m2 = mat.m8;
1495 result.m3 = mat.m12;
1496 result.m4 = mat.m1;
1497 result.m5 = mat.m5;
1498 result.m6 = mat.m9;
1499 result.m7 = mat.m13;
1500 result.m8 = mat.m2;
1501 result.m9 = mat.m6;
1502 result.m10 = mat.m10;
1503 result.m11 = mat.m14;
1504 result.m12 = mat.m3;
1505 result.m13 = mat.m7;
1506 result.m14 = mat.m11;
1507 result.m15 = mat.m15;
1508
1509 return result;
1510}
1511
1512// Invert provided matrix
1513RMAPI Matrix MatrixInvert(Matrix mat)
1514{
1515 Matrix result = { 0 };
1516
1517 // Cache the matrix values (speed optimization)
1518 float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3;
1519 float a10 = mat.m4, a11 = mat.m5, a12 = mat.m6, a13 = mat.m7;
1520 float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11;
1521 float a30 = mat.m12, a31 = mat.m13, a32 = mat.m14, a33 = mat.m15;
1522
1523 float b00 = a00*a11 - a01*a10;
1524 float b01 = a00*a12 - a02*a10;
1525 float b02 = a00*a13 - a03*a10;
1526 float b03 = a01*a12 - a02*a11;
1527 float b04 = a01*a13 - a03*a11;
1528 float b05 = a02*a13 - a03*a12;
1529 float b06 = a20*a31 - a21*a30;
1530 float b07 = a20*a32 - a22*a30;
1531 float b08 = a20*a33 - a23*a30;
1532 float b09 = a21*a32 - a22*a31;
1533 float b10 = a21*a33 - a23*a31;
1534 float b11 = a22*a33 - a23*a32;
1535
1536 // Calculate the invert determinant (inlined to avoid double-caching)
1537 float invDet = 1.0f/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06);
1538
1539 result.m0 = (a11*b11 - a12*b10 + a13*b09)*invDet;
1540 result.m1 = (-a01*b11 + a02*b10 - a03*b09)*invDet;
1541 result.m2 = (a31*b05 - a32*b04 + a33*b03)*invDet;
1542 result.m3 = (-a21*b05 + a22*b04 - a23*b03)*invDet;
1543 result.m4 = (-a10*b11 + a12*b08 - a13*b07)*invDet;
1544 result.m5 = (a00*b11 - a02*b08 + a03*b07)*invDet;
1545 result.m6 = (-a30*b05 + a32*b02 - a33*b01)*invDet;
1546 result.m7 = (a20*b05 - a22*b02 + a23*b01)*invDet;
1547 result.m8 = (a10*b10 - a11*b08 + a13*b06)*invDet;
1548 result.m9 = (-a00*b10 + a01*b08 - a03*b06)*invDet;
1549 result.m10 = (a30*b04 - a31*b02 + a33*b00)*invDet;
1550 result.m11 = (-a20*b04 + a21*b02 - a23*b00)*invDet;
1551 result.m12 = (-a10*b09 + a11*b07 - a12*b06)*invDet;
1552 result.m13 = (a00*b09 - a01*b07 + a02*b06)*invDet;
1553 result.m14 = (-a30*b03 + a31*b01 - a32*b00)*invDet;
1554 result.m15 = (a20*b03 - a21*b01 + a22*b00)*invDet;
1555
1556 return result;
1557}
1558
1559// Get identity matrix
1560RMAPI Matrix MatrixIdentity(void)
1561{
1562 Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f,
1563 0.0f, 1.0f, 0.0f, 0.0f,
1564 0.0f, 0.0f, 1.0f, 0.0f,
1565 0.0f, 0.0f, 0.0f, 1.0f };
1566
1567 return result;
1568}
1569
1570// Add two matrices
1571RMAPI Matrix MatrixAdd(Matrix left, Matrix right)
1572{
1573 Matrix result = { 0 };
1574
1575 result.m0 = left.m0 + right.m0;
1576 result.m1 = left.m1 + right.m1;
1577 result.m2 = left.m2 + right.m2;
1578 result.m3 = left.m3 + right.m3;
1579 result.m4 = left.m4 + right.m4;
1580 result.m5 = left.m5 + right.m5;
1581 result.m6 = left.m6 + right.m6;
1582 result.m7 = left.m7 + right.m7;
1583 result.m8 = left.m8 + right.m8;
1584 result.m9 = left.m9 + right.m9;
1585 result.m10 = left.m10 + right.m10;
1586 result.m11 = left.m11 + right.m11;
1587 result.m12 = left.m12 + right.m12;
1588 result.m13 = left.m13 + right.m13;
1589 result.m14 = left.m14 + right.m14;
1590 result.m15 = left.m15 + right.m15;
1591
1592 return result;
1593}
1594
1595// Subtract two matrices (left - right)
1596RMAPI Matrix MatrixSubtract(Matrix left, Matrix right)
1597{
1598 Matrix result = { 0 };
1599
1600 result.m0 = left.m0 - right.m0;
1601 result.m1 = left.m1 - right.m1;
1602 result.m2 = left.m2 - right.m2;
1603 result.m3 = left.m3 - right.m3;
1604 result.m4 = left.m4 - right.m4;
1605 result.m5 = left.m5 - right.m5;
1606 result.m6 = left.m6 - right.m6;
1607 result.m7 = left.m7 - right.m7;
1608 result.m8 = left.m8 - right.m8;
1609 result.m9 = left.m9 - right.m9;
1610 result.m10 = left.m10 - right.m10;
1611 result.m11 = left.m11 - right.m11;
1612 result.m12 = left.m12 - right.m12;
1613 result.m13 = left.m13 - right.m13;
1614 result.m14 = left.m14 - right.m14;
1615 result.m15 = left.m15 - right.m15;
1616
1617 return result;
1618}
1619
1620// Get two matrix multiplication
1621// NOTE: When multiplying matrices... the order matters!
1622RMAPI Matrix MatrixMultiply(Matrix left, Matrix right)
1623{
1624 Matrix result = { 0 };
1625
1626 result.m0 = left.m0*right.m0 + left.m1*right.m4 + left.m2*right.m8 + left.m3*right.m12;
1627 result.m1 = left.m0*right.m1 + left.m1*right.m5 + left.m2*right.m9 + left.m3*right.m13;
1628 result.m2 = left.m0*right.m2 + left.m1*right.m6 + left.m2*right.m10 + left.m3*right.m14;
1629 result.m3 = left.m0*right.m3 + left.m1*right.m7 + left.m2*right.m11 + left.m3*right.m15;
1630 result.m4 = left.m4*right.m0 + left.m5*right.m4 + left.m6*right.m8 + left.m7*right.m12;
1631 result.m5 = left.m4*right.m1 + left.m5*right.m5 + left.m6*right.m9 + left.m7*right.m13;
1632 result.m6 = left.m4*right.m2 + left.m5*right.m6 + left.m6*right.m10 + left.m7*right.m14;
1633 result.m7 = left.m4*right.m3 + left.m5*right.m7 + left.m6*right.m11 + left.m7*right.m15;
1634 result.m8 = left.m8*right.m0 + left.m9*right.m4 + left.m10*right.m8 + left.m11*right.m12;
1635 result.m9 = left.m8*right.m1 + left.m9*right.m5 + left.m10*right.m9 + left.m11*right.m13;
1636 result.m10 = left.m8*right.m2 + left.m9*right.m6 + left.m10*right.m10 + left.m11*right.m14;
1637 result.m11 = left.m8*right.m3 + left.m9*right.m7 + left.m10*right.m11 + left.m11*right.m15;
1638 result.m12 = left.m12*right.m0 + left.m13*right.m4 + left.m14*right.m8 + left.m15*right.m12;
1639 result.m13 = left.m12*right.m1 + left.m13*right.m5 + left.m14*right.m9 + left.m15*right.m13;
1640 result.m14 = left.m12*right.m2 + left.m13*right.m6 + left.m14*right.m10 + left.m15*right.m14;
1641 result.m15 = left.m12*right.m3 + left.m13*right.m7 + left.m14*right.m11 + left.m15*right.m15;
1642
1643 return result;
1644}
1645
1646// Get translation matrix
1647RMAPI Matrix MatrixTranslate(float x, float y, float z)
1648{
1649 Matrix result = { 1.0f, 0.0f, 0.0f, x,
1650 0.0f, 1.0f, 0.0f, y,
1651 0.0f, 0.0f, 1.0f, z,
1652 0.0f, 0.0f, 0.0f, 1.0f };
1653
1654 return result;
1655}
1656
1657// Create rotation matrix from axis and angle
1658// NOTE: Angle should be provided in radians
1659RMAPI Matrix MatrixRotate(Vector3 axis, float angle)
1660{
1661 Matrix result = { 0 };
1662
1663 float x = axis.x, y = axis.y, z = axis.z;
1664
1665 float lengthSquared = x*x + y*y + z*z;
1666
1667 if ((lengthSquared != 1.0f) && (lengthSquared != 0.0f))
1668 {
1669 float ilength = 1.0f/sqrtf(lengthSquared);
1670 x *= ilength;
1671 y *= ilength;
1672 z *= ilength;
1673 }
1674
1675 float sinres = sinf(angle);
1676 float cosres = cosf(angle);
1677 float t = 1.0f - cosres;
1678
1679 result.m0 = x*x*t + cosres;
1680 result.m1 = y*x*t + z*sinres;
1681 result.m2 = z*x*t - y*sinres;
1682 result.m3 = 0.0f;
1683
1684 result.m4 = x*y*t - z*sinres;
1685 result.m5 = y*y*t + cosres;
1686 result.m6 = z*y*t + x*sinres;
1687 result.m7 = 0.0f;
1688
1689 result.m8 = x*z*t + y*sinres;
1690 result.m9 = y*z*t - x*sinres;
1691 result.m10 = z*z*t + cosres;
1692 result.m11 = 0.0f;
1693
1694 result.m12 = 0.0f;
1695 result.m13 = 0.0f;
1696 result.m14 = 0.0f;
1697 result.m15 = 1.0f;
1698
1699 return result;
1700}
1701
1702// Get x-rotation matrix
1703// NOTE: Angle must be provided in radians
1704RMAPI Matrix MatrixRotateX(float angle)
1705{
1706 Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f,
1707 0.0f, 1.0f, 0.0f, 0.0f,
1708 0.0f, 0.0f, 1.0f, 0.0f,
1709 0.0f, 0.0f, 0.0f, 1.0f }; // MatrixIdentity()
1710
1711 float cosres = cosf(angle);
1712 float sinres = sinf(angle);
1713
1714 result.m5 = cosres;
1715 result.m6 = sinres;
1716 result.m9 = -sinres;
1717 result.m10 = cosres;
1718
1719 return result;
1720}
1721
1722// Get y-rotation matrix
1723// NOTE: Angle must be provided in radians
1724RMAPI Matrix MatrixRotateY(float angle)
1725{
1726 Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f,
1727 0.0f, 1.0f, 0.0f, 0.0f,
1728 0.0f, 0.0f, 1.0f, 0.0f,
1729 0.0f, 0.0f, 0.0f, 1.0f }; // MatrixIdentity()
1730
1731 float cosres = cosf(angle);
1732 float sinres = sinf(angle);
1733
1734 result.m0 = cosres;
1735 result.m2 = -sinres;
1736 result.m8 = sinres;
1737 result.m10 = cosres;
1738
1739 return result;
1740}
1741
1742// Get z-rotation matrix
1743// NOTE: Angle must be provided in radians
1744RMAPI Matrix MatrixRotateZ(float angle)
1745{
1746 Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f,
1747 0.0f, 1.0f, 0.0f, 0.0f,
1748 0.0f, 0.0f, 1.0f, 0.0f,
1749 0.0f, 0.0f, 0.0f, 1.0f }; // MatrixIdentity()
1750
1751 float cosres = cosf(angle);
1752 float sinres = sinf(angle);
1753
1754 result.m0 = cosres;
1755 result.m1 = sinres;
1756 result.m4 = -sinres;
1757 result.m5 = cosres;
1758
1759 return result;
1760}
1761
1762
1763// Get xyz-rotation matrix
1764// NOTE: Angle must be provided in radians
1765RMAPI Matrix MatrixRotateXYZ(Vector3 angle)
1766{
1767 Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f,
1768 0.0f, 1.0f, 0.0f, 0.0f,
1769 0.0f, 0.0f, 1.0f, 0.0f,
1770 0.0f, 0.0f, 0.0f, 1.0f }; // MatrixIdentity()
1771
1772 float cosz = cosf(-angle.z);
1773 float sinz = sinf(-angle.z);
1774 float cosy = cosf(-angle.y);
1775 float siny = sinf(-angle.y);
1776 float cosx = cosf(-angle.x);
1777 float sinx = sinf(-angle.x);
1778
1779 result.m0 = cosz*cosy;
1780 result.m1 = (cosz*siny*sinx) - (sinz*cosx);
1781 result.m2 = (cosz*siny*cosx) + (sinz*sinx);
1782
1783 result.m4 = sinz*cosy;
1784 result.m5 = (sinz*siny*sinx) + (cosz*cosx);
1785 result.m6 = (sinz*siny*cosx) - (cosz*sinx);
1786
1787 result.m8 = -siny;
1788 result.m9 = cosy*sinx;
1789 result.m10= cosy*cosx;
1790
1791 return result;
1792}
1793
1794// Get zyx-rotation matrix
1795// NOTE: Angle must be provided in radians
1796RMAPI Matrix MatrixRotateZYX(Vector3 angle)
1797{
1798 Matrix result = { 0 };
1799
1800 float cz = cosf(angle.z);
1801 float sz = sinf(angle.z);
1802 float cy = cosf(angle.y);
1803 float sy = sinf(angle.y);
1804 float cx = cosf(angle.x);
1805 float sx = sinf(angle.x);
1806
1807 result.m0 = cz*cy;
1808 result.m4 = cz*sy*sx - cx*sz;
1809 result.m8 = sz*sx + cz*cx*sy;
1810 result.m12 = 0;
1811
1812 result.m1 = cy*sz;
1813 result.m5 = cz*cx + sz*sy*sx;
1814 result.m9 = cx*sz*sy - cz*sx;
1815 result.m13 = 0;
1816
1817 result.m2 = -sy;
1818 result.m6 = cy*sx;
1819 result.m10 = cy*cx;
1820 result.m14 = 0;
1821
1822 result.m3 = 0;
1823 result.m7 = 0;
1824 result.m11 = 0;
1825 result.m15 = 1;
1826
1827 return result;
1828}
1829
1830// Get scaling matrix
1831RMAPI Matrix MatrixScale(float x, float y, float z)
1832{
1833 Matrix result = { x, 0.0f, 0.0f, 0.0f,
1834 0.0f, y, 0.0f, 0.0f,
1835 0.0f, 0.0f, z, 0.0f,
1836 0.0f, 0.0f, 0.0f, 1.0f };
1837
1838 return result;
1839}
1840
1841// Get perspective projection matrix
1842RMAPI Matrix MatrixFrustum(double left, double right, double bottom, double top, double nearPlane, double farPlane)
1843{
1844 Matrix result = { 0 };
1845
1846 float rl = (float)(right - left);
1847 float tb = (float)(top - bottom);
1848 float fn = (float)(farPlane - nearPlane);
1849
1850 result.m0 = ((float)nearPlane*2.0f)/rl;
1851 result.m1 = 0.0f;
1852 result.m2 = 0.0f;
1853 result.m3 = 0.0f;
1854
1855 result.m4 = 0.0f;
1856 result.m5 = ((float)nearPlane*2.0f)/tb;
1857 result.m6 = 0.0f;
1858 result.m7 = 0.0f;
1859
1860 result.m8 = ((float)right + (float)left)/rl;
1861 result.m9 = ((float)top + (float)bottom)/tb;
1862 result.m10 = -((float)farPlane + (float)nearPlane)/fn;
1863 result.m11 = -1.0f;
1864
1865 result.m12 = 0.0f;
1866 result.m13 = 0.0f;
1867 result.m14 = -((float)farPlane*(float)nearPlane*2.0f)/fn;
1868 result.m15 = 0.0f;
1869
1870 return result;
1871}
1872
1873// Get perspective projection matrix
1874// NOTE: Fovy angle must be provided in radians
1875RMAPI Matrix MatrixPerspective(double fovY, double aspect, double nearPlane, double farPlane)
1876{
1877 Matrix result = { 0 };
1878
1879 double top = nearPlane*tan(fovY*0.5);
1880 double bottom = -top;
1881 double right = top*aspect;
1882 double left = -right;
1883
1884 // MatrixFrustum(-right, right, -top, top, near, far);
1885 float rl = (float)(right - left);
1886 float tb = (float)(top - bottom);
1887 float fn = (float)(farPlane - nearPlane);
1888
1889 result.m0 = ((float)nearPlane*2.0f)/rl;
1890 result.m5 = ((float)nearPlane*2.0f)/tb;
1891 result.m8 = ((float)right + (float)left)/rl;
1892 result.m9 = ((float)top + (float)bottom)/tb;
1893 result.m10 = -((float)farPlane + (float)nearPlane)/fn;
1894 result.m11 = -1.0f;
1895 result.m14 = -((float)farPlane*(float)nearPlane*2.0f)/fn;
1896
1897 return result;
1898}
1899
1900// Get orthographic projection matrix
1901RMAPI Matrix MatrixOrtho(double left, double right, double bottom, double top, double nearPlane, double farPlane)
1902{
1903 Matrix result = { 0 };
1904
1905 float rl = (float)(right - left);
1906 float tb = (float)(top - bottom);
1907 float fn = (float)(farPlane - nearPlane);
1908
1909 result.m0 = 2.0f/rl;
1910 result.m1 = 0.0f;
1911 result.m2 = 0.0f;
1912 result.m3 = 0.0f;
1913 result.m4 = 0.0f;
1914 result.m5 = 2.0f/tb;
1915 result.m6 = 0.0f;
1916 result.m7 = 0.0f;
1917 result.m8 = 0.0f;
1918 result.m9 = 0.0f;
1919 result.m10 = -2.0f/fn;
1920 result.m11 = 0.0f;
1921 result.m12 = -((float)left + (float)right)/rl;
1922 result.m13 = -((float)top + (float)bottom)/tb;
1923 result.m14 = -((float)farPlane + (float)nearPlane)/fn;
1924 result.m15 = 1.0f;
1925
1926 return result;
1927}
1928
1929// Get camera look-at matrix (view matrix)
1930RMAPI Matrix MatrixLookAt(Vector3 eye, Vector3 target, Vector3 up)
1931{
1932 Matrix result = { 0 };
1933
1934 float length = 0.0f;
1935 float ilength = 0.0f;
1936
1937 // Vector3Subtract(eye, target)
1938 Vector3 vz = { eye.x - target.x, eye.y - target.y, eye.z - target.z };
1939
1940 // Vector3Normalize(vz)
1941 Vector3 v = vz;
1942 length = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z);
1943 if (length == 0.0f) length = 1.0f;
1944 ilength = 1.0f/length;
1945 vz.x *= ilength;
1946 vz.y *= ilength;
1947 vz.z *= ilength;
1948
1949 // Vector3CrossProduct(up, vz)
1950 Vector3 vx = { up.y*vz.z - up.z*vz.y, up.z*vz.x - up.x*vz.z, up.x*vz.y - up.y*vz.x };
1951
1952 // Vector3Normalize(x)
1953 v = vx;
1954 length = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z);
1955 if (length == 0.0f) length = 1.0f;
1956 ilength = 1.0f/length;
1957 vx.x *= ilength;
1958 vx.y *= ilength;
1959 vx.z *= ilength;
1960
1961 // Vector3CrossProduct(vz, vx)
1962 Vector3 vy = { vz.y*vx.z - vz.z*vx.y, vz.z*vx.x - vz.x*vx.z, vz.x*vx.y - vz.y*vx.x };
1963
1964 result.m0 = vx.x;
1965 result.m1 = vy.x;
1966 result.m2 = vz.x;
1967 result.m3 = 0.0f;
1968 result.m4 = vx.y;
1969 result.m5 = vy.y;
1970 result.m6 = vz.y;
1971 result.m7 = 0.0f;
1972 result.m8 = vx.z;
1973 result.m9 = vy.z;
1974 result.m10 = vz.z;
1975 result.m11 = 0.0f;
1976 result.m12 = -(vx.x*eye.x + vx.y*eye.y + vx.z*eye.z); // Vector3DotProduct(vx, eye)
1977 result.m13 = -(vy.x*eye.x + vy.y*eye.y + vy.z*eye.z); // Vector3DotProduct(vy, eye)
1978 result.m14 = -(vz.x*eye.x + vz.y*eye.y + vz.z*eye.z); // Vector3DotProduct(vz, eye)
1979 result.m15 = 1.0f;
1980
1981 return result;
1982}
1983
1984// Get float array of matrix data
1985RMAPI float16 MatrixToFloatV(Matrix mat)
1986{
1987 float16 result = { 0 };
1988
1989 result.v[0] = mat.m0;
1990 result.v[1] = mat.m1;
1991 result.v[2] = mat.m2;
1992 result.v[3] = mat.m3;
1993 result.v[4] = mat.m4;
1994 result.v[5] = mat.m5;
1995 result.v[6] = mat.m6;
1996 result.v[7] = mat.m7;
1997 result.v[8] = mat.m8;
1998 result.v[9] = mat.m9;
1999 result.v[10] = mat.m10;
2000 result.v[11] = mat.m11;
2001 result.v[12] = mat.m12;
2002 result.v[13] = mat.m13;
2003 result.v[14] = mat.m14;
2004 result.v[15] = mat.m15;
2005
2006 return result;
2007}
2008
2009//----------------------------------------------------------------------------------
2010// Module Functions Definition - Quaternion math
2011//----------------------------------------------------------------------------------
2012
2013// Add two quaternions
2014RMAPI Quaternion QuaternionAdd(Quaternion q1, Quaternion q2)
2015{
2016 Quaternion result = {q1.x + q2.x, q1.y + q2.y, q1.z + q2.z, q1.w + q2.w};
2017
2018 return result;
2019}
2020
2021// Add quaternion and float value
2022RMAPI Quaternion QuaternionAddValue(Quaternion q, float add)
2023{
2024 Quaternion result = {q.x + add, q.y + add, q.z + add, q.w + add};
2025
2026 return result;
2027}
2028
2029// Subtract two quaternions
2030RMAPI Quaternion QuaternionSubtract(Quaternion q1, Quaternion q2)
2031{
2032 Quaternion result = {q1.x - q2.x, q1.y - q2.y, q1.z - q2.z, q1.w - q2.w};
2033
2034 return result;
2035}
2036
2037// Subtract quaternion and float value
2038RMAPI Quaternion QuaternionSubtractValue(Quaternion q, float sub)
2039{
2040 Quaternion result = {q.x - sub, q.y - sub, q.z - sub, q.w - sub};
2041
2042 return result;
2043}
2044
2045// Get identity quaternion
2046RMAPI Quaternion QuaternionIdentity(void)
2047{
2048 Quaternion result = { 0.0f, 0.0f, 0.0f, 1.0f };
2049
2050 return result;
2051}
2052
2053// Computes the length of a quaternion
2054RMAPI float QuaternionLength(Quaternion q)
2055{
2056 float result = sqrtf(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w);
2057
2058 return result;
2059}
2060
2061// Normalize provided quaternion
2062RMAPI Quaternion QuaternionNormalize(Quaternion q)
2063{
2064 Quaternion result = { 0 };
2065
2066 float length = sqrtf(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w);
2067 if (length == 0.0f) length = 1.0f;
2068 float ilength = 1.0f/length;
2069
2070 result.x = q.x*ilength;
2071 result.y = q.y*ilength;
2072 result.z = q.z*ilength;
2073 result.w = q.w*ilength;
2074
2075 return result;
2076}
2077
2078// Invert provided quaternion
2079RMAPI Quaternion QuaternionInvert(Quaternion q)
2080{
2081 Quaternion result = q;
2082
2083 float lengthSq = q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w;
2084
2085 if (lengthSq != 0.0f)
2086 {
2087 float invLength = 1.0f/lengthSq;
2088
2089 result.x *= -invLength;
2090 result.y *= -invLength;
2091 result.z *= -invLength;
2092 result.w *= invLength;
2093 }
2094
2095 return result;
2096}
2097
2098// Calculate two quaternion multiplication
2099RMAPI Quaternion QuaternionMultiply(Quaternion q1, Quaternion q2)
2100{
2101 Quaternion result = { 0 };
2102
2103 float qax = q1.x, qay = q1.y, qaz = q1.z, qaw = q1.w;
2104 float qbx = q2.x, qby = q2.y, qbz = q2.z, qbw = q2.w;
2105
2106 result.x = qax*qbw + qaw*qbx + qay*qbz - qaz*qby;
2107 result.y = qay*qbw + qaw*qby + qaz*qbx - qax*qbz;
2108 result.z = qaz*qbw + qaw*qbz + qax*qby - qay*qbx;
2109 result.w = qaw*qbw - qax*qbx - qay*qby - qaz*qbz;
2110
2111 return result;
2112}
2113
2114// Scale quaternion by float value
2115RMAPI Quaternion QuaternionScale(Quaternion q, float mul)
2116{
2117 Quaternion result = { 0 };
2118
2119 result.x = q.x*mul;
2120 result.y = q.y*mul;
2121 result.z = q.z*mul;
2122 result.w = q.w*mul;
2123
2124 return result;
2125}
2126
2127// Divide two quaternions
2128RMAPI Quaternion QuaternionDivide(Quaternion q1, Quaternion q2)
2129{
2130 Quaternion result = { q1.x/q2.x, q1.y/q2.y, q1.z/q2.z, q1.w/q2.w };
2131
2132 return result;
2133}
2134
2135// Calculate linear interpolation between two quaternions
2136RMAPI Quaternion QuaternionLerp(Quaternion q1, Quaternion q2, float amount)
2137{
2138 Quaternion result = { 0 };
2139
2140 result.x = q1.x + amount*(q2.x - q1.x);
2141 result.y = q1.y + amount*(q2.y - q1.y);
2142 result.z = q1.z + amount*(q2.z - q1.z);
2143 result.w = q1.w + amount*(q2.w - q1.w);
2144
2145 return result;
2146}
2147
2148// Calculate slerp-optimized interpolation between two quaternions
2149RMAPI Quaternion QuaternionNlerp(Quaternion q1, Quaternion q2, float amount)
2150{
2151 Quaternion result = { 0 };
2152
2153 // QuaternionLerp(q1, q2, amount)
2154 result.x = q1.x + amount*(q2.x - q1.x);
2155 result.y = q1.y + amount*(q2.y - q1.y);
2156 result.z = q1.z + amount*(q2.z - q1.z);
2157 result.w = q1.w + amount*(q2.w - q1.w);
2158
2159 // QuaternionNormalize(q);
2160 Quaternion q = result;
2161 float length = sqrtf(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w);
2162 if (length == 0.0f) length = 1.0f;
2163 float ilength = 1.0f/length;
2164
2165 result.x = q.x*ilength;
2166 result.y = q.y*ilength;
2167 result.z = q.z*ilength;
2168 result.w = q.w*ilength;
2169
2170 return result;
2171}
2172
2173// Calculates spherical linear interpolation between two quaternions
2174RMAPI Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount)
2175{
2176 Quaternion result = { 0 };
2177
2178#if !defined(EPSILON)
2179 #define EPSILON 0.000001f
2180#endif
2181
2182 float cosHalfTheta = q1.x*q2.x + q1.y*q2.y + q1.z*q2.z + q1.w*q2.w;
2183
2184 if (cosHalfTheta < 0)
2185 {
2186 q2.x = -q2.x; q2.y = -q2.y; q2.z = -q2.z; q2.w = -q2.w;
2187 cosHalfTheta = -cosHalfTheta;
2188 }
2189
2190 if (fabsf(cosHalfTheta) >= 1.0f) result = q1;
2191 else if (cosHalfTheta > 0.95f) result = QuaternionNlerp(q1, q2, amount);
2192 else
2193 {
2194 float halfTheta = acosf(cosHalfTheta);
2195 float sinHalfTheta = sqrtf(1.0f - cosHalfTheta*cosHalfTheta);
2196
2197 if (fabsf(sinHalfTheta) < EPSILON)
2198 {
2199 result.x = (q1.x*0.5f + q2.x*0.5f);
2200 result.y = (q1.y*0.5f + q2.y*0.5f);
2201 result.z = (q1.z*0.5f + q2.z*0.5f);
2202 result.w = (q1.w*0.5f + q2.w*0.5f);
2203 }
2204 else
2205 {
2206 float ratioA = sinf((1 - amount)*halfTheta)/sinHalfTheta;
2207 float ratioB = sinf(amount*halfTheta)/sinHalfTheta;
2208
2209 result.x = (q1.x*ratioA + q2.x*ratioB);
2210 result.y = (q1.y*ratioA + q2.y*ratioB);
2211 result.z = (q1.z*ratioA + q2.z*ratioB);
2212 result.w = (q1.w*ratioA + q2.w*ratioB);
2213 }
2214 }
2215
2216 return result;
2217}
2218
2219// Calculate quaternion cubic spline interpolation using Cubic Hermite Spline algorithm
2220// as described in the GLTF 2.0 specification: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#interpolation-cubic
2221RMAPI Quaternion QuaternionCubicHermiteSpline(Quaternion q1, Quaternion outTangent1, Quaternion q2, Quaternion inTangent2, float t)
2222{
2223 float t2 = t*t;
2224 float t3 = t2*t;
2225 float h00 = 2*t3 - 3*t2 + 1;
2226 float h10 = t3 - 2*t2 + t;
2227 float h01 = -2*t3 + 3*t2;
2228 float h11 = t3 - t2;
2229
2230 Quaternion p0 = QuaternionScale(q1, h00);
2231 Quaternion m0 = QuaternionScale(outTangent1, h10);
2232 Quaternion p1 = QuaternionScale(q2, h01);
2233 Quaternion m1 = QuaternionScale(inTangent2, h11);
2234
2235 Quaternion result = { 0 };
2236
2237 result = QuaternionAdd(p0, m0);
2238 result = QuaternionAdd(result, p1);
2239 result = QuaternionAdd(result, m1);
2240 result = QuaternionNormalize(result);
2241
2242 return result;
2243}
2244
2245// Calculate quaternion based on the rotation from one vector to another
2246RMAPI Quaternion QuaternionFromVector3ToVector3(Vector3 from, Vector3 to)
2247{
2248 Quaternion result = { 0 };
2249
2250 float cos2Theta = (from.x*to.x + from.y*to.y + from.z*to.z); // Vector3DotProduct(from, to)
2251 Vector3 cross = { from.y*to.z - from.z*to.y, from.z*to.x - from.x*to.z, from.x*to.y - from.y*to.x }; // Vector3CrossProduct(from, to)
2252
2253 result.x = cross.x;
2254 result.y = cross.y;
2255 result.z = cross.z;
2256 result.w = 1.0f + cos2Theta;
2257
2258 // QuaternionNormalize(q);
2259 // NOTE: Normalize to essentially nlerp the original and identity to 0.5
2260 Quaternion q = result;
2261 float length = sqrtf(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w);
2262 if (length == 0.0f) length = 1.0f;
2263 float ilength = 1.0f/length;
2264
2265 result.x = q.x*ilength;
2266 result.y = q.y*ilength;
2267 result.z = q.z*ilength;
2268 result.w = q.w*ilength;
2269
2270 return result;
2271}
2272
2273// Get a quaternion for a given rotation matrix
2274RMAPI Quaternion QuaternionFromMatrix(Matrix mat)
2275{
2276 Quaternion result = { 0 };
2277
2278 float fourWSquaredMinus1 = mat.m0 + mat.m5 + mat.m10;
2279 float fourXSquaredMinus1 = mat.m0 - mat.m5 - mat.m10;
2280 float fourYSquaredMinus1 = mat.m5 - mat.m0 - mat.m10;
2281 float fourZSquaredMinus1 = mat.m10 - mat.m0 - mat.m5;
2282
2283 int biggestIndex = 0;
2284 float fourBiggestSquaredMinus1 = fourWSquaredMinus1;
2285 if (fourXSquaredMinus1 > fourBiggestSquaredMinus1)
2286 {
2287 fourBiggestSquaredMinus1 = fourXSquaredMinus1;
2288 biggestIndex = 1;
2289 }
2290
2291 if (fourYSquaredMinus1 > fourBiggestSquaredMinus1)
2292 {
2293 fourBiggestSquaredMinus1 = fourYSquaredMinus1;
2294 biggestIndex = 2;
2295 }
2296
2297 if (fourZSquaredMinus1 > fourBiggestSquaredMinus1)
2298 {
2299 fourBiggestSquaredMinus1 = fourZSquaredMinus1;
2300 biggestIndex = 3;
2301 }
2302
2303 float biggestVal = sqrtf(fourBiggestSquaredMinus1 + 1.0f)*0.5f;
2304 float mult = 0.25f/biggestVal;
2305
2306 switch (biggestIndex)
2307 {
2308 case 0:
2309 result.w = biggestVal;
2310 result.x = (mat.m6 - mat.m9)*mult;
2311 result.y = (mat.m8 - mat.m2)*mult;
2312 result.z = (mat.m1 - mat.m4)*mult;
2313 break;
2314 case 1:
2315 result.x = biggestVal;
2316 result.w = (mat.m6 - mat.m9)*mult;
2317 result.y = (mat.m1 + mat.m4)*mult;
2318 result.z = (mat.m8 + mat.m2)*mult;
2319 break;
2320 case 2:
2321 result.y = biggestVal;
2322 result.w = (mat.m8 - mat.m2)*mult;
2323 result.x = (mat.m1 + mat.m4)*mult;
2324 result.z = (mat.m6 + mat.m9)*mult;
2325 break;
2326 case 3:
2327 result.z = biggestVal;
2328 result.w = (mat.m1 - mat.m4)*mult;
2329 result.x = (mat.m8 + mat.m2)*mult;
2330 result.y = (mat.m6 + mat.m9)*mult;
2331 break;
2332 }
2333
2334 return result;
2335}
2336
2337// Get a matrix for a given quaternion
2338RMAPI Matrix QuaternionToMatrix(Quaternion q)
2339{
2340 Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f,
2341 0.0f, 1.0f, 0.0f, 0.0f,
2342 0.0f, 0.0f, 1.0f, 0.0f,
2343 0.0f, 0.0f, 0.0f, 1.0f }; // MatrixIdentity()
2344
2345 float a2 = q.x*q.x;
2346 float b2 = q.y*q.y;
2347 float c2 = q.z*q.z;
2348 float ac = q.x*q.z;
2349 float ab = q.x*q.y;
2350 float bc = q.y*q.z;
2351 float ad = q.w*q.x;
2352 float bd = q.w*q.y;
2353 float cd = q.w*q.z;
2354
2355 result.m0 = 1 - 2*(b2 + c2);
2356 result.m1 = 2*(ab + cd);
2357 result.m2 = 2*(ac - bd);
2358
2359 result.m4 = 2*(ab - cd);
2360 result.m5 = 1 - 2*(a2 + c2);
2361 result.m6 = 2*(bc + ad);
2362
2363 result.m8 = 2*(ac + bd);
2364 result.m9 = 2*(bc - ad);
2365 result.m10 = 1 - 2*(a2 + b2);
2366
2367 return result;
2368}
2369
2370// Get rotation quaternion for an angle and axis
2371// NOTE: Angle must be provided in radians
2372RMAPI Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle)
2373{
2374 Quaternion result = { 0.0f, 0.0f, 0.0f, 1.0f };
2375
2376 float axisLength = sqrtf(axis.x*axis.x + axis.y*axis.y + axis.z*axis.z);
2377
2378 if (axisLength != 0.0f)
2379 {
2380 angle *= 0.5f;
2381
2382 float length = 0.0f;
2383 float ilength = 0.0f;
2384
2385 // Vector3Normalize(axis)
2386 length = axisLength;
2387 if (length == 0.0f) length = 1.0f;
2388 ilength = 1.0f/length;
2389 axis.x *= ilength;
2390 axis.y *= ilength;
2391 axis.z *= ilength;
2392
2393 float sinres = sinf(angle);
2394 float cosres = cosf(angle);
2395
2396 result.x = axis.x*sinres;
2397 result.y = axis.y*sinres;
2398 result.z = axis.z*sinres;
2399 result.w = cosres;
2400
2401 // QuaternionNormalize(q);
2402 Quaternion q = result;
2403 length = sqrtf(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w);
2404 if (length == 0.0f) length = 1.0f;
2405 ilength = 1.0f/length;
2406 result.x = q.x*ilength;
2407 result.y = q.y*ilength;
2408 result.z = q.z*ilength;
2409 result.w = q.w*ilength;
2410 }
2411
2412 return result;
2413}
2414
2415// Get the rotation angle and axis for a given quaternion
2416RMAPI void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle)
2417{
2418 if (fabsf(q.w) > 1.0f)
2419 {
2420 // QuaternionNormalize(q);
2421 float length = sqrtf(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w);
2422 if (length == 0.0f) length = 1.0f;
2423 float ilength = 1.0f/length;
2424
2425 q.x = q.x*ilength;
2426 q.y = q.y*ilength;
2427 q.z = q.z*ilength;
2428 q.w = q.w*ilength;
2429 }
2430
2431 Vector3 resAxis = { 0.0f, 0.0f, 0.0f };
2432 float resAngle = 2.0f*acosf(q.w);
2433 float den = sqrtf(1.0f - q.w*q.w);
2434
2435 if (den > EPSILON)
2436 {
2437 resAxis.x = q.x/den;
2438 resAxis.y = q.y/den;
2439 resAxis.z = q.z/den;
2440 }
2441 else
2442 {
2443 // This occurs when the angle is zero.
2444 // Not a problem: just set an arbitrary normalized axis.
2445 resAxis.x = 1.0f;
2446 }
2447
2448 *outAxis = resAxis;
2449 *outAngle = resAngle;
2450}
2451
2452// Get the quaternion equivalent to Euler angles
2453// NOTE: Rotation order is ZYX
2454RMAPI Quaternion QuaternionFromEuler(float pitch, float yaw, float roll)
2455{
2456 Quaternion result = { 0 };
2457
2458 float x0 = cosf(pitch*0.5f);
2459 float x1 = sinf(pitch*0.5f);
2460 float y0 = cosf(yaw*0.5f);
2461 float y1 = sinf(yaw*0.5f);
2462 float z0 = cosf(roll*0.5f);
2463 float z1 = sinf(roll*0.5f);
2464
2465 result.x = x1*y0*z0 - x0*y1*z1;
2466 result.y = x0*y1*z0 + x1*y0*z1;
2467 result.z = x0*y0*z1 - x1*y1*z0;
2468 result.w = x0*y0*z0 + x1*y1*z1;
2469
2470 return result;
2471}
2472
2473// Get the Euler angles equivalent to quaternion (roll, pitch, yaw)
2474// NOTE: Angles are returned in a Vector3 struct in radians
2475RMAPI Vector3 QuaternionToEuler(Quaternion q)
2476{
2477 Vector3 result = { 0 };
2478
2479 // Roll (x-axis rotation)
2480 float x0 = 2.0f*(q.w*q.x + q.y*q.z);
2481 float x1 = 1.0f - 2.0f*(q.x*q.x + q.y*q.y);
2482 result.x = atan2f(x0, x1);
2483
2484 // Pitch (y-axis rotation)
2485 float y0 = 2.0f*(q.w*q.y - q.z*q.x);
2486 y0 = y0 > 1.0f ? 1.0f : y0;
2487 y0 = y0 < -1.0f ? -1.0f : y0;
2488 result.y = asinf(y0);
2489
2490 // Yaw (z-axis rotation)
2491 float z0 = 2.0f*(q.w*q.z + q.x*q.y);
2492 float z1 = 1.0f - 2.0f*(q.y*q.y + q.z*q.z);
2493 result.z = atan2f(z0, z1);
2494
2495 return result;
2496}
2497
2498// Transform a quaternion given a transformation matrix
2499RMAPI Quaternion QuaternionTransform(Quaternion q, Matrix mat)
2500{
2501 Quaternion result = { 0 };
2502
2503 result.x = mat.m0*q.x + mat.m4*q.y + mat.m8*q.z + mat.m12*q.w;
2504 result.y = mat.m1*q.x + mat.m5*q.y + mat.m9*q.z + mat.m13*q.w;
2505 result.z = mat.m2*q.x + mat.m6*q.y + mat.m10*q.z + mat.m14*q.w;
2506 result.w = mat.m3*q.x + mat.m7*q.y + mat.m11*q.z + mat.m15*q.w;
2507
2508 return result;
2509}
2510
2511// Check whether two given quaternions are almost equal
2512RMAPI int QuaternionEquals(Quaternion p, Quaternion q)
2513{
2514#if !defined(EPSILON)
2515 #define EPSILON 0.000001f
2516#endif
2517
2518 int result = (((fabsf(p.x - q.x)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) &&
2519 ((fabsf(p.y - q.y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y))))) &&
2520 ((fabsf(p.z - q.z)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.z), fabsf(q.z))))) &&
2521 ((fabsf(p.w - q.w)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.w), fabsf(q.w)))))) ||
2522 (((fabsf(p.x + q.x)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) &&
2523 ((fabsf(p.y + q.y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y))))) &&
2524 ((fabsf(p.z + q.z)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.z), fabsf(q.z))))) &&
2525 ((fabsf(p.w + q.w)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.w), fabsf(q.w))))));
2526
2527 return result;
2528}
2529
2530// Decompose a transformation matrix into its rotational, translational and scaling components
2531RMAPI void MatrixDecompose(Matrix mat, Vector3 *translation, Quaternion *rotation, Vector3 *scale)
2532{
2533 // Extract translation.
2534 translation->x = mat.m12;
2535 translation->y = mat.m13;
2536 translation->z = mat.m14;
2537
2538 // Extract upper-left for determinant computation
2539 const float a = mat.m0;
2540 const float b = mat.m4;
2541 const float c = mat.m8;
2542 const float d = mat.m1;
2543 const float e = mat.m5;
2544 const float f = mat.m9;
2545 const float g = mat.m2;
2546 const float h = mat.m6;
2547 const float i = mat.m10;
2548 const float A = e*i - f*h;
2549 const float B = f*g - d*i;
2550 const float C = d*h - e*g;
2551
2552 // Extract scale
2553 const float det = a*A + b*B + c*C;
2554 Vector3 abc = { a, b, c };
2555 Vector3 def = { d, e, f };
2556 Vector3 ghi = { g, h, i };
2557
2558 float scalex = Vector3Length(abc);
2559 float scaley = Vector3Length(def);
2560 float scalez = Vector3Length(ghi);
2561 Vector3 s = { scalex, scaley, scalez };
2562
2563 if (det < 0) s = Vector3Negate(s);
2564
2565 *scale = s;
2566
2567 // Remove scale from the matrix if it is not close to zero
2568 Matrix clone = mat;
2569 if (!FloatEquals(det, 0))
2570 {
2571 clone.m0 /= s.x;
2572 clone.m4 /= s.x;
2573 clone.m8 /= s.x;
2574 clone.m1 /= s.y;
2575 clone.m5 /= s.y;
2576 clone.m9 /= s.y;
2577 clone.m2 /= s.z;
2578 clone.m6 /= s.z;
2579 clone.m10 /= s.z;
2580
2581 // Extract rotation
2582 *rotation = QuaternionFromMatrix(clone);
2583 }
2584 else
2585 {
2586 // Set to identity if close to zero
2587 *rotation = QuaternionIdentity();
2588 }
2589}
2590
2591#if defined(__cplusplus) && !defined(RAYMATH_DISABLE_CPP_OPERATORS)
2592
2593// Optional C++ math operators
2594//-------------------------------------------------------------------------------
2595
2596// Vector2 operators
2597static constexpr Vector2 Vector2Zeros = { 0, 0 };
2598static constexpr Vector2 Vector2Ones = { 1, 1 };
2599static constexpr Vector2 Vector2UnitX = { 1, 0 };
2600static constexpr Vector2 Vector2UnitY = { 0, 1 };
2601
2602inline Vector2 operator + (const Vector2& lhs, const Vector2& rhs)
2603{
2604 return Vector2Add(lhs, rhs);
2605}
2606
2607inline const Vector2& operator += (Vector2& lhs, const Vector2& rhs)
2608{
2609 lhs = Vector2Add(lhs, rhs);
2610 return lhs;
2611}
2612
2613inline Vector2 operator - (const Vector2& lhs, const Vector2& rhs)
2614{
2615 return Vector2Subtract(lhs, rhs);
2616}
2617
2618inline const Vector2& operator -= (Vector2& lhs, const Vector2& rhs)
2619{
2620 lhs = Vector2Subtract(lhs, rhs);
2621 return lhs;
2622}
2623
2624inline Vector2 operator * (const Vector2& lhs, const float& rhs)
2625{
2626 return Vector2Scale(lhs, rhs);
2627}
2628
2629inline const Vector2& operator *= (Vector2& lhs, const float& rhs)
2630{
2631 lhs = Vector2Scale(lhs, rhs);
2632 return lhs;
2633}
2634
2635inline Vector2 operator * (const Vector2& lhs, const Vector2& rhs)
2636{
2637 return Vector2Multiply(lhs, rhs);
2638}
2639
2640inline const Vector2& operator *= (Vector2& lhs, const Vector2& rhs)
2641{
2642 lhs = Vector2Multiply(lhs, rhs);
2643 return lhs;
2644}
2645
2646inline Vector2 operator * (const Vector2& lhs, const Matrix& rhs)
2647{
2648 return Vector2Transform(lhs, rhs);
2649}
2650
2651inline const Vector2& operator -= (Vector2& lhs, const Matrix& rhs)
2652{
2653 lhs = Vector2Transform(lhs, rhs);
2654 return lhs;
2655}
2656
2657inline Vector2 operator / (const Vector2& lhs, const float& rhs)
2658{
2659 return Vector2Scale(lhs, 1.0f / rhs);
2660}
2661
2662inline const Vector2& operator /= (Vector2& lhs, const float& rhs)
2663{
2664 lhs = Vector2Scale(lhs, rhs);
2665 return lhs;
2666}
2667
2668inline Vector2 operator / (const Vector2& lhs, const Vector2& rhs)
2669{
2670 return Vector2Divide(lhs, rhs);
2671}
2672
2673inline const Vector2& operator /= (Vector2& lhs, const Vector2& rhs)
2674{
2675 lhs = Vector2Divide(lhs, rhs);
2676 return lhs;
2677}
2678
2679inline bool operator == (const Vector2& lhs, const Vector2& rhs)
2680{
2681 return FloatEquals(lhs.x, rhs.x) && FloatEquals(lhs.y, rhs.y);
2682}
2683
2684inline bool operator != (const Vector2& lhs, const Vector2& rhs)
2685{
2686 return !FloatEquals(lhs.x, rhs.x) || !FloatEquals(lhs.y, rhs.y);
2687}
2688
2689// Vector3 operators
2690static constexpr Vector3 Vector3Zeros = { 0, 0, 0 };
2691static constexpr Vector3 Vector3Ones = { 1, 1, 1 };
2692static constexpr Vector3 Vector3UnitX = { 1, 0, 0 };
2693static constexpr Vector3 Vector3UnitY = { 0, 1, 0 };
2694static constexpr Vector3 Vector3UnitZ = { 0, 0, 1 };
2695
2696inline Vector3 operator + (const Vector3& lhs, const Vector3& rhs)
2697{
2698 return Vector3Add(lhs, rhs);
2699}
2700
2701inline const Vector3& operator += (Vector3& lhs, const Vector3& rhs)
2702{
2703 lhs = Vector3Add(lhs, rhs);
2704 return lhs;
2705}
2706
2707inline Vector3 operator - (const Vector3& lhs, const Vector3& rhs)
2708{
2709 return Vector3Subtract(lhs, rhs);
2710}
2711
2712inline const Vector3& operator -= (Vector3& lhs, const Vector3& rhs)
2713{
2714 lhs = Vector3Subtract(lhs, rhs);
2715 return lhs;
2716}
2717
2718inline Vector3 operator * (const Vector3& lhs, const float& rhs)
2719{
2720 return Vector3Scale(lhs, rhs);
2721}
2722
2723inline const Vector3& operator *= (Vector3& lhs, const float& rhs)
2724{
2725 lhs = Vector3Scale(lhs, rhs);
2726 return lhs;
2727}
2728
2729inline Vector3 operator * (const Vector3& lhs, const Vector3& rhs)
2730{
2731 return Vector3Multiply(lhs, rhs);
2732}
2733
2734inline const Vector3& operator *= (Vector3& lhs, const Vector3& rhs)
2735{
2736 lhs = Vector3Multiply(lhs, rhs);
2737 return lhs;
2738}
2739
2740inline Vector3 operator * (const Vector3& lhs, const Matrix& rhs)
2741{
2742 return Vector3Transform(lhs, rhs);
2743}
2744
2745inline const Vector3& operator -= (Vector3& lhs, const Matrix& rhs)
2746{
2747 lhs = Vector3Transform(lhs, rhs);
2748 return lhs;
2749}
2750
2751inline Vector3 operator / (const Vector3& lhs, const float& rhs)
2752{
2753 return Vector3Scale(lhs, 1.0f / rhs);
2754}
2755
2756inline const Vector3& operator /= (Vector3& lhs, const float& rhs)
2757{
2758 lhs = Vector3Scale(lhs, rhs);
2759 return lhs;
2760}
2761
2762inline Vector3 operator / (const Vector3& lhs, const Vector3& rhs)
2763{
2764 return Vector3Divide(lhs, rhs);
2765}
2766
2767inline const Vector3& operator /= (Vector3& lhs, const Vector3& rhs)
2768{
2769 lhs = Vector3Divide(lhs, rhs);
2770 return lhs;
2771}
2772
2773inline bool operator == (const Vector3& lhs, const Vector3& rhs)
2774{
2775 return FloatEquals(lhs.x, rhs.x) && FloatEquals(lhs.y, rhs.y) && FloatEquals(lhs.z, rhs.z);
2776}
2777
2778inline bool operator != (const Vector3& lhs, const Vector3& rhs)
2779{
2780 return !FloatEquals(lhs.x, rhs.x) || !FloatEquals(lhs.y, rhs.y) || !FloatEquals(lhs.z, rhs.z);
2781}
2782
2783// Vector4 operators
2784static constexpr Vector4 Vector4Zeros = { 0, 0, 0, 0 };
2785static constexpr Vector4 Vector4Ones = { 1, 1, 1, 1 };
2786static constexpr Vector4 Vector4UnitX = { 1, 0, 0, 0 };
2787static constexpr Vector4 Vector4UnitY = { 0, 1, 0, 0 };
2788static constexpr Vector4 Vector4UnitZ = { 0, 0, 1, 0 };
2789static constexpr Vector4 Vector4UnitW = { 0, 0, 0, 1 };
2790
2791inline Vector4 operator + (const Vector4& lhs, const Vector4& rhs)
2792{
2793 return Vector4Add(lhs, rhs);
2794}
2795
2796inline const Vector4& operator += (Vector4& lhs, const Vector4& rhs)
2797{
2798 lhs = Vector4Add(lhs, rhs);
2799 return lhs;
2800}
2801
2802inline Vector4 operator - (const Vector4& lhs, const Vector4& rhs)
2803{
2804 return Vector4Subtract(lhs, rhs);
2805}
2806
2807inline const Vector4& operator -= (Vector4& lhs, const Vector4& rhs)
2808{
2809 lhs = Vector4Subtract(lhs, rhs);
2810 return lhs;
2811}
2812
2813inline Vector4 operator * (const Vector4& lhs, const float& rhs)
2814{
2815 return Vector4Scale(lhs, rhs);
2816}
2817
2818inline const Vector4& operator *= (Vector4& lhs, const float& rhs)
2819{
2820 lhs = Vector4Scale(lhs, rhs);
2821 return lhs;
2822}
2823
2824inline Vector4 operator * (const Vector4& lhs, const Vector4& rhs)
2825{
2826 return Vector4Multiply(lhs, rhs);
2827}
2828
2829inline const Vector4& operator *= (Vector4& lhs, const Vector4& rhs)
2830{
2831 lhs = Vector4Multiply(lhs, rhs);
2832 return lhs;
2833}
2834
2835inline Vector4 operator / (const Vector4& lhs, const float& rhs)
2836{
2837 return Vector4Scale(lhs, 1.0f / rhs);
2838}
2839
2840inline const Vector4& operator /= (Vector4& lhs, const float& rhs)
2841{
2842 lhs = Vector4Scale(lhs, rhs);
2843 return lhs;
2844}
2845
2846inline Vector4 operator / (const Vector4& lhs, const Vector4& rhs)
2847{
2848 return Vector4Divide(lhs, rhs);
2849}
2850
2851inline const Vector4& operator /= (Vector4& lhs, const Vector4& rhs)
2852{
2853 lhs = Vector4Divide(lhs, rhs);
2854 return lhs;
2855}
2856
2857inline bool operator == (const Vector4& lhs, const Vector4& rhs)
2858{
2859 return FloatEquals(lhs.x, rhs.x) && FloatEquals(lhs.y, rhs.y) && FloatEquals(lhs.z, rhs.z) && FloatEquals(lhs.w, rhs.w);
2860}
2861
2862inline bool operator != (const Vector4& lhs, const Vector4& rhs)
2863{
2864 return !FloatEquals(lhs.x, rhs.x) || !FloatEquals(lhs.y, rhs.y) || !FloatEquals(lhs.z, rhs.z) || !FloatEquals(lhs.w, rhs.w);
2865}
2866
2867// Quaternion operators
2868static constexpr Quaternion QuaternionZeros = { 0, 0, 0, 0 };
2869static constexpr Quaternion QuaternionOnes = { 1, 1, 1, 1 };
2870static constexpr Quaternion QuaternionUnitX = { 0, 0, 0, 1 };
2871
2872inline Quaternion operator + (const Quaternion& lhs, const float& rhs)
2873{
2874 return QuaternionAddValue(lhs, rhs);
2875}
2876
2877inline const Quaternion& operator += (Quaternion& lhs, const float& rhs)
2878{
2879 lhs = QuaternionAddValue(lhs, rhs);
2880 return lhs;
2881}
2882
2883inline Quaternion operator - (const Quaternion& lhs, const float& rhs)
2884{
2885 return QuaternionSubtractValue(lhs, rhs);
2886}
2887
2888inline const Quaternion& operator -= (Quaternion& lhs, const float& rhs)
2889{
2890 lhs = QuaternionSubtractValue(lhs, rhs);
2891 return lhs;
2892}
2893
2894inline Quaternion operator * (const Quaternion& lhs, const Matrix& rhs)
2895{
2896 return QuaternionTransform(lhs, rhs);
2897}
2898
2899inline const Quaternion& operator *= (Quaternion& lhs, const Matrix& rhs)
2900{
2901 lhs = QuaternionTransform(lhs, rhs);
2902 return lhs;
2903}
2904
2905// Matrix operators
2906inline Matrix operator + (const Matrix& lhs, const Matrix& rhs)
2907{
2908 return MatrixAdd(lhs, rhs);
2909}
2910
2911inline const Matrix& operator += (Matrix& lhs, const Matrix& rhs)
2912{
2913 lhs = MatrixAdd(lhs, rhs);
2914 return lhs;
2915}
2916
2917inline Matrix operator - (const Matrix& lhs, const Matrix& rhs)
2918{
2919 return MatrixSubtract(lhs, rhs);
2920}
2921
2922inline const Matrix& operator -= (Matrix& lhs, const Matrix& rhs)
2923{
2924 lhs = MatrixSubtract(lhs, rhs);
2925 return lhs;
2926}
2927
2928inline Matrix operator * (const Matrix& lhs, const Matrix& rhs)
2929{
2930 return MatrixMultiply(lhs, rhs);
2931}
2932
2933inline const Matrix& operator *= (Matrix& lhs, const Matrix& rhs)
2934{
2935 lhs = MatrixMultiply(lhs, rhs);
2936 return lhs;
2937}
2938//-------------------------------------------------------------------------------
2939#endif // C++ operators
2940
2941#endif // RAYMATH_H
diff --git a/vendor/raylib-5.5_macos/include/rlgl.h b/vendor/raylib-5.5_macos/include/rlgl.h
new file mode 100644
index 0000000..756656e
--- /dev/null
+++ b/vendor/raylib-5.5_macos/include/rlgl.h
@@ -0,0 +1,5262 @@
1/**********************************************************************************************
2*
3* rlgl v5.0 - A multi-OpenGL abstraction layer with an immediate-mode style API
4*
5* DESCRIPTION:
6* An abstraction layer for multiple OpenGL versions (1.1, 2.1, 3.3 Core, 4.3 Core, ES 2.0)
7* that provides a pseudo-OpenGL 1.1 immediate-mode style API (rlVertex, rlTranslate, rlRotate...)
8*
9* ADDITIONAL NOTES:
10* When choosing an OpenGL backend different than OpenGL 1.1, some internal buffer are
11* initialized on rlglInit() to accumulate vertex data
12*
13* When an internal state change is required all the stored vertex data is renderer in batch,
14* additionally, rlDrawRenderBatchActive() could be called to force flushing of the batch
15*
16* Some resources are also loaded for convenience, here the complete list:
17* - Default batch (RLGL.defaultBatch): RenderBatch system to accumulate vertex data
18* - Default texture (RLGL.defaultTextureId): 1x1 white pixel R8G8B8A8
19* - Default shader (RLGL.State.defaultShaderId, RLGL.State.defaultShaderLocs)
20*
21* Internal buffer (and resources) must be manually unloaded calling rlglClose()
22*
23* CONFIGURATION:
24* #define GRAPHICS_API_OPENGL_11
25* #define GRAPHICS_API_OPENGL_21
26* #define GRAPHICS_API_OPENGL_33
27* #define GRAPHICS_API_OPENGL_43
28* #define GRAPHICS_API_OPENGL_ES2
29* #define GRAPHICS_API_OPENGL_ES3
30* Use selected OpenGL graphics backend, should be supported by platform
31* Those preprocessor defines are only used on rlgl module, if OpenGL version is
32* required by any other module, use rlGetVersion() to check it
33*
34* #define RLGL_IMPLEMENTATION
35* Generates the implementation of the library into the included file
36* If not defined, the library is in header only mode and can be included in other headers
37* or source files without problems. But only ONE file should hold the implementation
38*
39* #define RLGL_RENDER_TEXTURES_HINT
40* Enable framebuffer objects (fbo) support (enabled by default)
41* Some GPUs could not support them despite the OpenGL version
42*
43* #define RLGL_SHOW_GL_DETAILS_INFO
44* Show OpenGL extensions and capabilities detailed logs on init
45*
46* #define RLGL_ENABLE_OPENGL_DEBUG_CONTEXT
47* Enable debug context (only available on OpenGL 4.3)
48*
49* rlgl capabilities could be customized just defining some internal
50* values before library inclusion (default values listed):
51*
52* #define RL_DEFAULT_BATCH_BUFFER_ELEMENTS 8192 // Default internal render batch elements limits
53* #define RL_DEFAULT_BATCH_BUFFERS 1 // Default number of batch buffers (multi-buffering)
54* #define RL_DEFAULT_BATCH_DRAWCALLS 256 // Default number of batch draw calls (by state changes: mode, texture)
55* #define RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS 4 // Maximum number of textures units that can be activated on batch drawing (SetShaderValueTexture())
56*
57* #define RL_MAX_MATRIX_STACK_SIZE 32 // Maximum size of internal Matrix stack
58* #define RL_MAX_SHADER_LOCATIONS 32 // Maximum number of shader locations supported
59* #define RL_CULL_DISTANCE_NEAR 0.01 // Default projection matrix near cull distance
60* #define RL_CULL_DISTANCE_FAR 1000.0 // Default projection matrix far cull distance
61*
62* When loading a shader, the following vertex attributes and uniform
63* location names are tried to be set automatically:
64*
65* #define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION "vertexPosition" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION
66* #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD "vertexTexCoord" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD
67* #define RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL "vertexNormal" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL
68* #define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR "vertexColor" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR
69* #define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT "vertexTangent" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT
70* #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2
71* #define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS "vertexBoneIds" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS
72* #define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS "vertexBoneWeights" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS
73* #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix
74* #define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW "matView" // view matrix
75* #define RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION "matProjection" // projection matrix
76* #define RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL "matModel" // model matrix
77* #define RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL "matNormal" // normal matrix (transpose(inverse(matModelView)))
78* #define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color)
79* #define RL_DEFAULT_SHADER_UNIFORM_NAME_BONE_MATRICES "boneMatrices" // bone matrices
80* #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0)
81* #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1 "texture1" // texture1 (texture slot active 1)
82* #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 "texture2" // texture2 (texture slot active 2)
83*
84* DEPENDENCIES:
85* - OpenGL libraries (depending on platform and OpenGL version selected)
86* - GLAD OpenGL extensions loading library (only for OpenGL 3.3 Core, 4.3 Core)
87*
88*
89* LICENSE: zlib/libpng
90*
91* Copyright (c) 2014-2024 Ramon Santamaria (@raysan5)
92*
93* This software is provided "as-is", without any express or implied warranty. In no event
94* will the authors be held liable for any damages arising from the use of this software.
95*
96* Permission is granted to anyone to use this software for any purpose, including commercial
97* applications, and to alter it and redistribute it freely, subject to the following restrictions:
98*
99* 1. The origin of this software must not be misrepresented; you must not claim that you
100* wrote the original software. If you use this software in a product, an acknowledgment
101* in the product documentation would be appreciated but is not required.
102*
103* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
104* as being the original software.
105*
106* 3. This notice may not be removed or altered from any source distribution.
107*
108**********************************************************************************************/
109
110#ifndef RLGL_H
111#define RLGL_H
112
113#define RLGL_VERSION "5.0"
114
115// Function specifiers in case library is build/used as a shared library
116// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll
117// NOTE: visibility(default) attribute makes symbols "visible" when compiled with -fvisibility=hidden
118#if defined(_WIN32) && defined(BUILD_LIBTYPE_SHARED)
119 #define RLAPI __declspec(dllexport) // We are building the library as a Win32 shared library (.dll)
120#elif defined(BUILD_LIBTYPE_SHARED)
121 #define RLAPI __attribute__((visibility("default"))) // We are building the library as a Unix shared library (.so/.dylib)
122#elif defined(_WIN32) && defined(USE_LIBTYPE_SHARED)
123 #define RLAPI __declspec(dllimport) // We are using the library as a Win32 shared library (.dll)
124#endif
125
126// Function specifiers definition
127#ifndef RLAPI
128 #define RLAPI // Functions defined as 'extern' by default (implicit specifiers)
129#endif
130
131// Support TRACELOG macros
132#ifndef TRACELOG
133 #define TRACELOG(level, ...) (void)0
134 #define TRACELOGD(...) (void)0
135#endif
136
137// Allow custom memory allocators
138#ifndef RL_MALLOC
139 #define RL_MALLOC(sz) malloc(sz)
140#endif
141#ifndef RL_CALLOC
142 #define RL_CALLOC(n,sz) calloc(n,sz)
143#endif
144#ifndef RL_REALLOC
145 #define RL_REALLOC(n,sz) realloc(n,sz)
146#endif
147#ifndef RL_FREE
148 #define RL_FREE(p) free(p)
149#endif
150
151// Security check in case no GRAPHICS_API_OPENGL_* defined
152#if !defined(GRAPHICS_API_OPENGL_11) && \
153 !defined(GRAPHICS_API_OPENGL_21) && \
154 !defined(GRAPHICS_API_OPENGL_33) && \
155 !defined(GRAPHICS_API_OPENGL_43) && \
156 !defined(GRAPHICS_API_OPENGL_ES2) && \
157 !defined(GRAPHICS_API_OPENGL_ES3)
158 #define GRAPHICS_API_OPENGL_33
159#endif
160
161// Security check in case multiple GRAPHICS_API_OPENGL_* defined
162#if defined(GRAPHICS_API_OPENGL_11)
163 #if defined(GRAPHICS_API_OPENGL_21)
164 #undef GRAPHICS_API_OPENGL_21
165 #endif
166 #if defined(GRAPHICS_API_OPENGL_33)
167 #undef GRAPHICS_API_OPENGL_33
168 #endif
169 #if defined(GRAPHICS_API_OPENGL_43)
170 #undef GRAPHICS_API_OPENGL_43
171 #endif
172 #if defined(GRAPHICS_API_OPENGL_ES2)
173 #undef GRAPHICS_API_OPENGL_ES2
174 #endif
175#endif
176
177// OpenGL 2.1 uses most of OpenGL 3.3 Core functionality
178// WARNING: Specific parts are checked with #if defines
179#if defined(GRAPHICS_API_OPENGL_21)
180 #define GRAPHICS_API_OPENGL_33
181#endif
182
183// OpenGL 4.3 uses OpenGL 3.3 Core functionality
184#if defined(GRAPHICS_API_OPENGL_43)
185 #define GRAPHICS_API_OPENGL_33
186#endif
187
188// OpenGL ES 3.0 uses OpenGL ES 2.0 functionality (and more)
189#if defined(GRAPHICS_API_OPENGL_ES3)
190 #define GRAPHICS_API_OPENGL_ES2
191#endif
192
193// Support framebuffer objects by default
194// NOTE: Some driver implementation do not support it, despite they should
195#define RLGL_RENDER_TEXTURES_HINT
196
197//----------------------------------------------------------------------------------
198// Defines and Macros
199//----------------------------------------------------------------------------------
200
201// Default internal render batch elements limits
202#ifndef RL_DEFAULT_BATCH_BUFFER_ELEMENTS
203 #if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
204 // This is the maximum amount of elements (quads) per batch
205 // NOTE: Be careful with text, every letter maps to a quad
206 #define RL_DEFAULT_BATCH_BUFFER_ELEMENTS 8192
207 #endif
208 #if defined(GRAPHICS_API_OPENGL_ES2)
209 // We reduce memory sizes for embedded systems (RPI and HTML5)
210 // NOTE: On HTML5 (emscripten) this is allocated on heap,
211 // by default it's only 16MB!...just take care...
212 #define RL_DEFAULT_BATCH_BUFFER_ELEMENTS 2048
213 #endif
214#endif
215#ifndef RL_DEFAULT_BATCH_BUFFERS
216 #define RL_DEFAULT_BATCH_BUFFERS 1 // Default number of batch buffers (multi-buffering)
217#endif
218#ifndef RL_DEFAULT_BATCH_DRAWCALLS
219 #define RL_DEFAULT_BATCH_DRAWCALLS 256 // Default number of batch draw calls (by state changes: mode, texture)
220#endif
221#ifndef RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS
222 #define RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS 4 // Maximum number of textures units that can be activated on batch drawing (SetShaderValueTexture())
223#endif
224
225// Internal Matrix stack
226#ifndef RL_MAX_MATRIX_STACK_SIZE
227 #define RL_MAX_MATRIX_STACK_SIZE 32 // Maximum size of Matrix stack
228#endif
229
230// Shader limits
231#ifndef RL_MAX_SHADER_LOCATIONS
232 #define RL_MAX_SHADER_LOCATIONS 32 // Maximum number of shader locations supported
233#endif
234
235// Projection matrix culling
236#ifndef RL_CULL_DISTANCE_NEAR
237 #define RL_CULL_DISTANCE_NEAR 0.01 // Default near cull distance
238#endif
239#ifndef RL_CULL_DISTANCE_FAR
240 #define RL_CULL_DISTANCE_FAR 1000.0 // Default far cull distance
241#endif
242
243// Texture parameters (equivalent to OpenGL defines)
244#define RL_TEXTURE_WRAP_S 0x2802 // GL_TEXTURE_WRAP_S
245#define RL_TEXTURE_WRAP_T 0x2803 // GL_TEXTURE_WRAP_T
246#define RL_TEXTURE_MAG_FILTER 0x2800 // GL_TEXTURE_MAG_FILTER
247#define RL_TEXTURE_MIN_FILTER 0x2801 // GL_TEXTURE_MIN_FILTER
248
249#define RL_TEXTURE_FILTER_NEAREST 0x2600 // GL_NEAREST
250#define RL_TEXTURE_FILTER_LINEAR 0x2601 // GL_LINEAR
251#define RL_TEXTURE_FILTER_MIP_NEAREST 0x2700 // GL_NEAREST_MIPMAP_NEAREST
252#define RL_TEXTURE_FILTER_NEAREST_MIP_LINEAR 0x2702 // GL_NEAREST_MIPMAP_LINEAR
253#define RL_TEXTURE_FILTER_LINEAR_MIP_NEAREST 0x2701 // GL_LINEAR_MIPMAP_NEAREST
254#define RL_TEXTURE_FILTER_MIP_LINEAR 0x2703 // GL_LINEAR_MIPMAP_LINEAR
255#define RL_TEXTURE_FILTER_ANISOTROPIC 0x3000 // Anisotropic filter (custom identifier)
256#define RL_TEXTURE_MIPMAP_BIAS_RATIO 0x4000 // Texture mipmap bias, percentage ratio (custom identifier)
257
258#define RL_TEXTURE_WRAP_REPEAT 0x2901 // GL_REPEAT
259#define RL_TEXTURE_WRAP_CLAMP 0x812F // GL_CLAMP_TO_EDGE
260#define RL_TEXTURE_WRAP_MIRROR_REPEAT 0x8370 // GL_MIRRORED_REPEAT
261#define RL_TEXTURE_WRAP_MIRROR_CLAMP 0x8742 // GL_MIRROR_CLAMP_EXT
262
263// Matrix modes (equivalent to OpenGL)
264#define RL_MODELVIEW 0x1700 // GL_MODELVIEW
265#define RL_PROJECTION 0x1701 // GL_PROJECTION
266#define RL_TEXTURE 0x1702 // GL_TEXTURE
267
268// Primitive assembly draw modes
269#define RL_LINES 0x0001 // GL_LINES
270#define RL_TRIANGLES 0x0004 // GL_TRIANGLES
271#define RL_QUADS 0x0007 // GL_QUADS
272
273// GL equivalent data types
274#define RL_UNSIGNED_BYTE 0x1401 // GL_UNSIGNED_BYTE
275#define RL_FLOAT 0x1406 // GL_FLOAT
276
277// GL buffer usage hint
278#define RL_STREAM_DRAW 0x88E0 // GL_STREAM_DRAW
279#define RL_STREAM_READ 0x88E1 // GL_STREAM_READ
280#define RL_STREAM_COPY 0x88E2 // GL_STREAM_COPY
281#define RL_STATIC_DRAW 0x88E4 // GL_STATIC_DRAW
282#define RL_STATIC_READ 0x88E5 // GL_STATIC_READ
283#define RL_STATIC_COPY 0x88E6 // GL_STATIC_COPY
284#define RL_DYNAMIC_DRAW 0x88E8 // GL_DYNAMIC_DRAW
285#define RL_DYNAMIC_READ 0x88E9 // GL_DYNAMIC_READ
286#define RL_DYNAMIC_COPY 0x88EA // GL_DYNAMIC_COPY
287
288// GL Shader type
289#define RL_FRAGMENT_SHADER 0x8B30 // GL_FRAGMENT_SHADER
290#define RL_VERTEX_SHADER 0x8B31 // GL_VERTEX_SHADER
291#define RL_COMPUTE_SHADER 0x91B9 // GL_COMPUTE_SHADER
292
293// GL blending factors
294#define RL_ZERO 0 // GL_ZERO
295#define RL_ONE 1 // GL_ONE
296#define RL_SRC_COLOR 0x0300 // GL_SRC_COLOR
297#define RL_ONE_MINUS_SRC_COLOR 0x0301 // GL_ONE_MINUS_SRC_COLOR
298#define RL_SRC_ALPHA 0x0302 // GL_SRC_ALPHA
299#define RL_ONE_MINUS_SRC_ALPHA 0x0303 // GL_ONE_MINUS_SRC_ALPHA
300#define RL_DST_ALPHA 0x0304 // GL_DST_ALPHA
301#define RL_ONE_MINUS_DST_ALPHA 0x0305 // GL_ONE_MINUS_DST_ALPHA
302#define RL_DST_COLOR 0x0306 // GL_DST_COLOR
303#define RL_ONE_MINUS_DST_COLOR 0x0307 // GL_ONE_MINUS_DST_COLOR
304#define RL_SRC_ALPHA_SATURATE 0x0308 // GL_SRC_ALPHA_SATURATE
305#define RL_CONSTANT_COLOR 0x8001 // GL_CONSTANT_COLOR
306#define RL_ONE_MINUS_CONSTANT_COLOR 0x8002 // GL_ONE_MINUS_CONSTANT_COLOR
307#define RL_CONSTANT_ALPHA 0x8003 // GL_CONSTANT_ALPHA
308#define RL_ONE_MINUS_CONSTANT_ALPHA 0x8004 // GL_ONE_MINUS_CONSTANT_ALPHA
309
310// GL blending functions/equations
311#define RL_FUNC_ADD 0x8006 // GL_FUNC_ADD
312#define RL_MIN 0x8007 // GL_MIN
313#define RL_MAX 0x8008 // GL_MAX
314#define RL_FUNC_SUBTRACT 0x800A // GL_FUNC_SUBTRACT
315#define RL_FUNC_REVERSE_SUBTRACT 0x800B // GL_FUNC_REVERSE_SUBTRACT
316#define RL_BLEND_EQUATION 0x8009 // GL_BLEND_EQUATION
317#define RL_BLEND_EQUATION_RGB 0x8009 // GL_BLEND_EQUATION_RGB // (Same as BLEND_EQUATION)
318#define RL_BLEND_EQUATION_ALPHA 0x883D // GL_BLEND_EQUATION_ALPHA
319#define RL_BLEND_DST_RGB 0x80C8 // GL_BLEND_DST_RGB
320#define RL_BLEND_SRC_RGB 0x80C9 // GL_BLEND_SRC_RGB
321#define RL_BLEND_DST_ALPHA 0x80CA // GL_BLEND_DST_ALPHA
322#define RL_BLEND_SRC_ALPHA 0x80CB // GL_BLEND_SRC_ALPHA
323#define RL_BLEND_COLOR 0x8005 // GL_BLEND_COLOR
324
325#define RL_READ_FRAMEBUFFER 0x8CA8 // GL_READ_FRAMEBUFFER
326#define RL_DRAW_FRAMEBUFFER 0x8CA9 // GL_DRAW_FRAMEBUFFER
327
328// Default shader vertex attribute locations
329#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION
330 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION 0
331#endif
332#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD
333 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD 1
334#endif
335#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL
336 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL 2
337#endif
338#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR
339 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR 3
340#endif
341 #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT
342#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT 4
343#endif
344#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2
345 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 5
346#endif
347#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES
348 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES 6
349#endif
350#ifdef RL_SUPPORT_MESH_GPU_SKINNING
351#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS
352 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS 7
353#endif
354#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS
355 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS 8
356#endif
357#endif
358
359//----------------------------------------------------------------------------------
360// Types and Structures Definition
361//----------------------------------------------------------------------------------
362#if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
363 #include <stdbool.h>
364#elif !defined(__cplusplus) && !defined(bool) && !defined(RL_BOOL_TYPE)
365 // Boolean type
366typedef enum bool { false = 0, true = !false } bool;
367#endif
368
369#if !defined(RL_MATRIX_TYPE)
370// Matrix, 4x4 components, column major, OpenGL style, right handed
371typedef struct Matrix {
372 float m0, m4, m8, m12; // Matrix first row (4 components)
373 float m1, m5, m9, m13; // Matrix second row (4 components)
374 float m2, m6, m10, m14; // Matrix third row (4 components)
375 float m3, m7, m11, m15; // Matrix fourth row (4 components)
376} Matrix;
377#define RL_MATRIX_TYPE
378#endif
379
380// Dynamic vertex buffers (position + texcoords + colors + indices arrays)
381typedef struct rlVertexBuffer {
382 int elementCount; // Number of elements in the buffer (QUADS)
383
384 float *vertices; // Vertex position (XYZ - 3 components per vertex) (shader-location = 0)
385 float *texcoords; // Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1)
386 float *normals; // Vertex normal (XYZ - 3 components per vertex) (shader-location = 2)
387 unsigned char *colors; // Vertex colors (RGBA - 4 components per vertex) (shader-location = 3)
388#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
389 unsigned int *indices; // Vertex indices (in case vertex data comes indexed) (6 indices per quad)
390#endif
391#if defined(GRAPHICS_API_OPENGL_ES2)
392 unsigned short *indices; // Vertex indices (in case vertex data comes indexed) (6 indices per quad)
393#endif
394 unsigned int vaoId; // OpenGL Vertex Array Object id
395 unsigned int vboId[5]; // OpenGL Vertex Buffer Objects id (5 types of vertex data)
396} rlVertexBuffer;
397
398// Draw call type
399// NOTE: Only texture changes register a new draw, other state-change-related elements are not
400// used at this moment (vaoId, shaderId, matrices), raylib just forces a batch draw call if any
401// of those state-change happens (this is done in core module)
402typedef struct rlDrawCall {
403 int mode; // Drawing mode: LINES, TRIANGLES, QUADS
404 int vertexCount; // Number of vertex of the draw
405 int vertexAlignment; // Number of vertex required for index alignment (LINES, TRIANGLES)
406 //unsigned int vaoId; // Vertex array id to be used on the draw -> Using RLGL.currentBatch->vertexBuffer.vaoId
407 //unsigned int shaderId; // Shader id to be used on the draw -> Using RLGL.currentShaderId
408 unsigned int textureId; // Texture id to be used on the draw -> Use to create new draw call if changes
409
410 //Matrix projection; // Projection matrix for this draw -> Using RLGL.projection by default
411 //Matrix modelview; // Modelview matrix for this draw -> Using RLGL.modelview by default
412} rlDrawCall;
413
414// rlRenderBatch type
415typedef struct rlRenderBatch {
416 int bufferCount; // Number of vertex buffers (multi-buffering support)
417 int currentBuffer; // Current buffer tracking in case of multi-buffering
418 rlVertexBuffer *vertexBuffer; // Dynamic buffer(s) for vertex data
419
420 rlDrawCall *draws; // Draw calls array, depends on textureId
421 int drawCounter; // Draw calls counter
422 float currentDepth; // Current depth value for next draw
423} rlRenderBatch;
424
425// OpenGL version
426typedef enum {
427 RL_OPENGL_11 = 1, // OpenGL 1.1
428 RL_OPENGL_21, // OpenGL 2.1 (GLSL 120)
429 RL_OPENGL_33, // OpenGL 3.3 (GLSL 330)
430 RL_OPENGL_43, // OpenGL 4.3 (using GLSL 330)
431 RL_OPENGL_ES_20, // OpenGL ES 2.0 (GLSL 100)
432 RL_OPENGL_ES_30 // OpenGL ES 3.0 (GLSL 300 es)
433} rlGlVersion;
434
435// Trace log level
436// NOTE: Organized by priority level
437typedef enum {
438 RL_LOG_ALL = 0, // Display all logs
439 RL_LOG_TRACE, // Trace logging, intended for internal use only
440 RL_LOG_DEBUG, // Debug logging, used for internal debugging, it should be disabled on release builds
441 RL_LOG_INFO, // Info logging, used for program execution info
442 RL_LOG_WARNING, // Warning logging, used on recoverable failures
443 RL_LOG_ERROR, // Error logging, used on unrecoverable failures
444 RL_LOG_FATAL, // Fatal logging, used to abort program: exit(EXIT_FAILURE)
445 RL_LOG_NONE // Disable logging
446} rlTraceLogLevel;
447
448// Texture pixel formats
449// NOTE: Support depends on OpenGL version
450typedef enum {
451 RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE = 1, // 8 bit per pixel (no alpha)
452 RL_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA, // 8*2 bpp (2 channels)
453 RL_PIXELFORMAT_UNCOMPRESSED_R5G6B5, // 16 bpp
454 RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8, // 24 bpp
455 RL_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1, // 16 bpp (1 bit alpha)
456 RL_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4, // 16 bpp (4 bit alpha)
457 RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, // 32 bpp
458 RL_PIXELFORMAT_UNCOMPRESSED_R32, // 32 bpp (1 channel - float)
459 RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32, // 32*3 bpp (3 channels - float)
460 RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32, // 32*4 bpp (4 channels - float)
461 RL_PIXELFORMAT_UNCOMPRESSED_R16, // 16 bpp (1 channel - half float)
462 RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16, // 16*3 bpp (3 channels - half float)
463 RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16, // 16*4 bpp (4 channels - half float)
464 RL_PIXELFORMAT_COMPRESSED_DXT1_RGB, // 4 bpp (no alpha)
465 RL_PIXELFORMAT_COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha)
466 RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA, // 8 bpp
467 RL_PIXELFORMAT_COMPRESSED_DXT5_RGBA, // 8 bpp
468 RL_PIXELFORMAT_COMPRESSED_ETC1_RGB, // 4 bpp
469 RL_PIXELFORMAT_COMPRESSED_ETC2_RGB, // 4 bpp
470 RL_PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA, // 8 bpp
471 RL_PIXELFORMAT_COMPRESSED_PVRT_RGB, // 4 bpp
472 RL_PIXELFORMAT_COMPRESSED_PVRT_RGBA, // 4 bpp
473 RL_PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA, // 8 bpp
474 RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA // 2 bpp
475} rlPixelFormat;
476
477// Texture parameters: filter mode
478// NOTE 1: Filtering considers mipmaps if available in the texture
479// NOTE 2: Filter is accordingly set for minification and magnification
480typedef enum {
481 RL_TEXTURE_FILTER_POINT = 0, // No filter, just pixel approximation
482 RL_TEXTURE_FILTER_BILINEAR, // Linear filtering
483 RL_TEXTURE_FILTER_TRILINEAR, // Trilinear filtering (linear with mipmaps)
484 RL_TEXTURE_FILTER_ANISOTROPIC_4X, // Anisotropic filtering 4x
485 RL_TEXTURE_FILTER_ANISOTROPIC_8X, // Anisotropic filtering 8x
486 RL_TEXTURE_FILTER_ANISOTROPIC_16X, // Anisotropic filtering 16x
487} rlTextureFilter;
488
489// Color blending modes (pre-defined)
490typedef enum {
491 RL_BLEND_ALPHA = 0, // Blend textures considering alpha (default)
492 RL_BLEND_ADDITIVE, // Blend textures adding colors
493 RL_BLEND_MULTIPLIED, // Blend textures multiplying colors
494 RL_BLEND_ADD_COLORS, // Blend textures adding colors (alternative)
495 RL_BLEND_SUBTRACT_COLORS, // Blend textures subtracting colors (alternative)
496 RL_BLEND_ALPHA_PREMULTIPLY, // Blend premultiplied textures considering alpha
497 RL_BLEND_CUSTOM, // Blend textures using custom src/dst factors (use rlSetBlendFactors())
498 RL_BLEND_CUSTOM_SEPARATE // Blend textures using custom src/dst factors (use rlSetBlendFactorsSeparate())
499} rlBlendMode;
500
501// Shader location point type
502typedef enum {
503 RL_SHADER_LOC_VERTEX_POSITION = 0, // Shader location: vertex attribute: position
504 RL_SHADER_LOC_VERTEX_TEXCOORD01, // Shader location: vertex attribute: texcoord01
505 RL_SHADER_LOC_VERTEX_TEXCOORD02, // Shader location: vertex attribute: texcoord02
506 RL_SHADER_LOC_VERTEX_NORMAL, // Shader location: vertex attribute: normal
507 RL_SHADER_LOC_VERTEX_TANGENT, // Shader location: vertex attribute: tangent
508 RL_SHADER_LOC_VERTEX_COLOR, // Shader location: vertex attribute: color
509 RL_SHADER_LOC_MATRIX_MVP, // Shader location: matrix uniform: model-view-projection
510 RL_SHADER_LOC_MATRIX_VIEW, // Shader location: matrix uniform: view (camera transform)
511 RL_SHADER_LOC_MATRIX_PROJECTION, // Shader location: matrix uniform: projection
512 RL_SHADER_LOC_MATRIX_MODEL, // Shader location: matrix uniform: model (transform)
513 RL_SHADER_LOC_MATRIX_NORMAL, // Shader location: matrix uniform: normal
514 RL_SHADER_LOC_VECTOR_VIEW, // Shader location: vector uniform: view
515 RL_SHADER_LOC_COLOR_DIFFUSE, // Shader location: vector uniform: diffuse color
516 RL_SHADER_LOC_COLOR_SPECULAR, // Shader location: vector uniform: specular color
517 RL_SHADER_LOC_COLOR_AMBIENT, // Shader location: vector uniform: ambient color
518 RL_SHADER_LOC_MAP_ALBEDO, // Shader location: sampler2d texture: albedo (same as: RL_SHADER_LOC_MAP_DIFFUSE)
519 RL_SHADER_LOC_MAP_METALNESS, // Shader location: sampler2d texture: metalness (same as: RL_SHADER_LOC_MAP_SPECULAR)
520 RL_SHADER_LOC_MAP_NORMAL, // Shader location: sampler2d texture: normal
521 RL_SHADER_LOC_MAP_ROUGHNESS, // Shader location: sampler2d texture: roughness
522 RL_SHADER_LOC_MAP_OCCLUSION, // Shader location: sampler2d texture: occlusion
523 RL_SHADER_LOC_MAP_EMISSION, // Shader location: sampler2d texture: emission
524 RL_SHADER_LOC_MAP_HEIGHT, // Shader location: sampler2d texture: height
525 RL_SHADER_LOC_MAP_CUBEMAP, // Shader location: samplerCube texture: cubemap
526 RL_SHADER_LOC_MAP_IRRADIANCE, // Shader location: samplerCube texture: irradiance
527 RL_SHADER_LOC_MAP_PREFILTER, // Shader location: samplerCube texture: prefilter
528 RL_SHADER_LOC_MAP_BRDF // Shader location: sampler2d texture: brdf
529} rlShaderLocationIndex;
530
531#define RL_SHADER_LOC_MAP_DIFFUSE RL_SHADER_LOC_MAP_ALBEDO
532#define RL_SHADER_LOC_MAP_SPECULAR RL_SHADER_LOC_MAP_METALNESS
533
534// Shader uniform data type
535typedef enum {
536 RL_SHADER_UNIFORM_FLOAT = 0, // Shader uniform type: float
537 RL_SHADER_UNIFORM_VEC2, // Shader uniform type: vec2 (2 float)
538 RL_SHADER_UNIFORM_VEC3, // Shader uniform type: vec3 (3 float)
539 RL_SHADER_UNIFORM_VEC4, // Shader uniform type: vec4 (4 float)
540 RL_SHADER_UNIFORM_INT, // Shader uniform type: int
541 RL_SHADER_UNIFORM_IVEC2, // Shader uniform type: ivec2 (2 int)
542 RL_SHADER_UNIFORM_IVEC3, // Shader uniform type: ivec3 (3 int)
543 RL_SHADER_UNIFORM_IVEC4, // Shader uniform type: ivec4 (4 int)
544 RL_SHADER_UNIFORM_UINT, // Shader uniform type: unsigned int
545 RL_SHADER_UNIFORM_UIVEC2, // Shader uniform type: uivec2 (2 unsigned int)
546 RL_SHADER_UNIFORM_UIVEC3, // Shader uniform type: uivec3 (3 unsigned int)
547 RL_SHADER_UNIFORM_UIVEC4, // Shader uniform type: uivec4 (4 unsigned int)
548 RL_SHADER_UNIFORM_SAMPLER2D // Shader uniform type: sampler2d
549} rlShaderUniformDataType;
550
551// Shader attribute data types
552typedef enum {
553 RL_SHADER_ATTRIB_FLOAT = 0, // Shader attribute type: float
554 RL_SHADER_ATTRIB_VEC2, // Shader attribute type: vec2 (2 float)
555 RL_SHADER_ATTRIB_VEC3, // Shader attribute type: vec3 (3 float)
556 RL_SHADER_ATTRIB_VEC4 // Shader attribute type: vec4 (4 float)
557} rlShaderAttributeDataType;
558
559// Framebuffer attachment type
560// NOTE: By default up to 8 color channels defined, but it can be more
561typedef enum {
562 RL_ATTACHMENT_COLOR_CHANNEL0 = 0, // Framebuffer attachment type: color 0
563 RL_ATTACHMENT_COLOR_CHANNEL1 = 1, // Framebuffer attachment type: color 1
564 RL_ATTACHMENT_COLOR_CHANNEL2 = 2, // Framebuffer attachment type: color 2
565 RL_ATTACHMENT_COLOR_CHANNEL3 = 3, // Framebuffer attachment type: color 3
566 RL_ATTACHMENT_COLOR_CHANNEL4 = 4, // Framebuffer attachment type: color 4
567 RL_ATTACHMENT_COLOR_CHANNEL5 = 5, // Framebuffer attachment type: color 5
568 RL_ATTACHMENT_COLOR_CHANNEL6 = 6, // Framebuffer attachment type: color 6
569 RL_ATTACHMENT_COLOR_CHANNEL7 = 7, // Framebuffer attachment type: color 7
570 RL_ATTACHMENT_DEPTH = 100, // Framebuffer attachment type: depth
571 RL_ATTACHMENT_STENCIL = 200, // Framebuffer attachment type: stencil
572} rlFramebufferAttachType;
573
574// Framebuffer texture attachment type
575typedef enum {
576 RL_ATTACHMENT_CUBEMAP_POSITIVE_X = 0, // Framebuffer texture attachment type: cubemap, +X side
577 RL_ATTACHMENT_CUBEMAP_NEGATIVE_X = 1, // Framebuffer texture attachment type: cubemap, -X side
578 RL_ATTACHMENT_CUBEMAP_POSITIVE_Y = 2, // Framebuffer texture attachment type: cubemap, +Y side
579 RL_ATTACHMENT_CUBEMAP_NEGATIVE_Y = 3, // Framebuffer texture attachment type: cubemap, -Y side
580 RL_ATTACHMENT_CUBEMAP_POSITIVE_Z = 4, // Framebuffer texture attachment type: cubemap, +Z side
581 RL_ATTACHMENT_CUBEMAP_NEGATIVE_Z = 5, // Framebuffer texture attachment type: cubemap, -Z side
582 RL_ATTACHMENT_TEXTURE2D = 100, // Framebuffer texture attachment type: texture2d
583 RL_ATTACHMENT_RENDERBUFFER = 200, // Framebuffer texture attachment type: renderbuffer
584} rlFramebufferAttachTextureType;
585
586// Face culling mode
587typedef enum {
588 RL_CULL_FACE_FRONT = 0,
589 RL_CULL_FACE_BACK
590} rlCullMode;
591
592//------------------------------------------------------------------------------------
593// Functions Declaration - Matrix operations
594//------------------------------------------------------------------------------------
595
596#if defined(__cplusplus)
597extern "C" { // Prevents name mangling of functions
598#endif
599
600RLAPI void rlMatrixMode(int mode); // Choose the current matrix to be transformed
601RLAPI void rlPushMatrix(void); // Push the current matrix to stack
602RLAPI void rlPopMatrix(void); // Pop latest inserted matrix from stack
603RLAPI void rlLoadIdentity(void); // Reset current matrix to identity matrix
604RLAPI void rlTranslatef(float x, float y, float z); // Multiply the current matrix by a translation matrix
605RLAPI void rlRotatef(float angle, float x, float y, float z); // Multiply the current matrix by a rotation matrix
606RLAPI void rlScalef(float x, float y, float z); // Multiply the current matrix by a scaling matrix
607RLAPI void rlMultMatrixf(const float *matf); // Multiply the current matrix by another matrix
608RLAPI void rlFrustum(double left, double right, double bottom, double top, double znear, double zfar);
609RLAPI void rlOrtho(double left, double right, double bottom, double top, double znear, double zfar);
610RLAPI void rlViewport(int x, int y, int width, int height); // Set the viewport area
611RLAPI void rlSetClipPlanes(double nearPlane, double farPlane); // Set clip planes distances
612RLAPI double rlGetCullDistanceNear(void); // Get cull plane distance near
613RLAPI double rlGetCullDistanceFar(void); // Get cull plane distance far
614
615//------------------------------------------------------------------------------------
616// Functions Declaration - Vertex level operations
617//------------------------------------------------------------------------------------
618RLAPI void rlBegin(int mode); // Initialize drawing mode (how to organize vertex)
619RLAPI void rlEnd(void); // Finish vertex providing
620RLAPI void rlVertex2i(int x, int y); // Define one vertex (position) - 2 int
621RLAPI void rlVertex2f(float x, float y); // Define one vertex (position) - 2 float
622RLAPI void rlVertex3f(float x, float y, float z); // Define one vertex (position) - 3 float
623RLAPI void rlTexCoord2f(float x, float y); // Define one vertex (texture coordinate) - 2 float
624RLAPI void rlNormal3f(float x, float y, float z); // Define one vertex (normal) - 3 float
625RLAPI void rlColor4ub(unsigned char r, unsigned char g, unsigned char b, unsigned char a); // Define one vertex (color) - 4 byte
626RLAPI void rlColor3f(float x, float y, float z); // Define one vertex (color) - 3 float
627RLAPI void rlColor4f(float x, float y, float z, float w); // Define one vertex (color) - 4 float
628
629//------------------------------------------------------------------------------------
630// Functions Declaration - OpenGL style functions (common to 1.1, 3.3+, ES2)
631// NOTE: This functions are used to completely abstract raylib code from OpenGL layer,
632// some of them are direct wrappers over OpenGL calls, some others are custom
633//------------------------------------------------------------------------------------
634
635// Vertex buffers state
636RLAPI bool rlEnableVertexArray(unsigned int vaoId); // Enable vertex array (VAO, if supported)
637RLAPI void rlDisableVertexArray(void); // Disable vertex array (VAO, if supported)
638RLAPI void rlEnableVertexBuffer(unsigned int id); // Enable vertex buffer (VBO)
639RLAPI void rlDisableVertexBuffer(void); // Disable vertex buffer (VBO)
640RLAPI void rlEnableVertexBufferElement(unsigned int id); // Enable vertex buffer element (VBO element)
641RLAPI void rlDisableVertexBufferElement(void); // Disable vertex buffer element (VBO element)
642RLAPI void rlEnableVertexAttribute(unsigned int index); // Enable vertex attribute index
643RLAPI void rlDisableVertexAttribute(unsigned int index); // Disable vertex attribute index
644#if defined(GRAPHICS_API_OPENGL_11)
645RLAPI void rlEnableStatePointer(int vertexAttribType, void *buffer); // Enable attribute state pointer
646RLAPI void rlDisableStatePointer(int vertexAttribType); // Disable attribute state pointer
647#endif
648
649// Textures state
650RLAPI void rlActiveTextureSlot(int slot); // Select and active a texture slot
651RLAPI void rlEnableTexture(unsigned int id); // Enable texture
652RLAPI void rlDisableTexture(void); // Disable texture
653RLAPI void rlEnableTextureCubemap(unsigned int id); // Enable texture cubemap
654RLAPI void rlDisableTextureCubemap(void); // Disable texture cubemap
655RLAPI void rlTextureParameters(unsigned int id, int param, int value); // Set texture parameters (filter, wrap)
656RLAPI void rlCubemapParameters(unsigned int id, int param, int value); // Set cubemap parameters (filter, wrap)
657
658// Shader state
659RLAPI void rlEnableShader(unsigned int id); // Enable shader program
660RLAPI void rlDisableShader(void); // Disable shader program
661
662// Framebuffer state
663RLAPI void rlEnableFramebuffer(unsigned int id); // Enable render texture (fbo)
664RLAPI void rlDisableFramebuffer(void); // Disable render texture (fbo), return to default framebuffer
665RLAPI unsigned int rlGetActiveFramebuffer(void); // Get the currently active render texture (fbo), 0 for default framebuffer
666RLAPI void rlActiveDrawBuffers(int count); // Activate multiple draw color buffers
667RLAPI void rlBlitFramebuffer(int srcX, int srcY, int srcWidth, int srcHeight, int dstX, int dstY, int dstWidth, int dstHeight, int bufferMask); // Blit active framebuffer to main framebuffer
668RLAPI void rlBindFramebuffer(unsigned int target, unsigned int framebuffer); // Bind framebuffer (FBO)
669
670// General render state
671RLAPI void rlEnableColorBlend(void); // Enable color blending
672RLAPI void rlDisableColorBlend(void); // Disable color blending
673RLAPI void rlEnableDepthTest(void); // Enable depth test
674RLAPI void rlDisableDepthTest(void); // Disable depth test
675RLAPI void rlEnableDepthMask(void); // Enable depth write
676RLAPI void rlDisableDepthMask(void); // Disable depth write
677RLAPI void rlEnableBackfaceCulling(void); // Enable backface culling
678RLAPI void rlDisableBackfaceCulling(void); // Disable backface culling
679RLAPI void rlColorMask(bool r, bool g, bool b, bool a); // Color mask control
680RLAPI void rlSetCullFace(int mode); // Set face culling mode
681RLAPI void rlEnableScissorTest(void); // Enable scissor test
682RLAPI void rlDisableScissorTest(void); // Disable scissor test
683RLAPI void rlScissor(int x, int y, int width, int height); // Scissor test
684RLAPI void rlEnableWireMode(void); // Enable wire mode
685RLAPI void rlEnablePointMode(void); // Enable point mode
686RLAPI void rlDisableWireMode(void); // Disable wire (and point) mode
687RLAPI void rlSetLineWidth(float width); // Set the line drawing width
688RLAPI float rlGetLineWidth(void); // Get the line drawing width
689RLAPI void rlEnableSmoothLines(void); // Enable line aliasing
690RLAPI void rlDisableSmoothLines(void); // Disable line aliasing
691RLAPI void rlEnableStereoRender(void); // Enable stereo rendering
692RLAPI void rlDisableStereoRender(void); // Disable stereo rendering
693RLAPI bool rlIsStereoRenderEnabled(void); // Check if stereo render is enabled
694
695RLAPI void rlClearColor(unsigned char r, unsigned char g, unsigned char b, unsigned char a); // Clear color buffer with color
696RLAPI void rlClearScreenBuffers(void); // Clear used screen buffers (color and depth)
697RLAPI void rlCheckErrors(void); // Check and log OpenGL error codes
698RLAPI void rlSetBlendMode(int mode); // Set blending mode
699RLAPI void rlSetBlendFactors(int glSrcFactor, int glDstFactor, int glEquation); // Set blending mode factor and equation (using OpenGL factors)
700RLAPI void rlSetBlendFactorsSeparate(int glSrcRGB, int glDstRGB, int glSrcAlpha, int glDstAlpha, int glEqRGB, int glEqAlpha); // Set blending mode factors and equations separately (using OpenGL factors)
701
702//------------------------------------------------------------------------------------
703// Functions Declaration - rlgl functionality
704//------------------------------------------------------------------------------------
705// rlgl initialization functions
706RLAPI void rlglInit(int width, int height); // Initialize rlgl (buffers, shaders, textures, states)
707RLAPI void rlglClose(void); // De-initialize rlgl (buffers, shaders, textures)
708RLAPI void rlLoadExtensions(void *loader); // Load OpenGL extensions (loader function required)
709RLAPI int rlGetVersion(void); // Get current OpenGL version
710RLAPI void rlSetFramebufferWidth(int width); // Set current framebuffer width
711RLAPI int rlGetFramebufferWidth(void); // Get default framebuffer width
712RLAPI void rlSetFramebufferHeight(int height); // Set current framebuffer height
713RLAPI int rlGetFramebufferHeight(void); // Get default framebuffer height
714
715RLAPI unsigned int rlGetTextureIdDefault(void); // Get default texture id
716RLAPI unsigned int rlGetShaderIdDefault(void); // Get default shader id
717RLAPI int *rlGetShaderLocsDefault(void); // Get default shader locations
718
719// Render batch management
720// NOTE: rlgl provides a default render batch to behave like OpenGL 1.1 immediate mode
721// but this render batch API is exposed in case of custom batches are required
722RLAPI rlRenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements); // Load a render batch system
723RLAPI void rlUnloadRenderBatch(rlRenderBatch batch); // Unload render batch system
724RLAPI void rlDrawRenderBatch(rlRenderBatch *batch); // Draw render batch data (Update->Draw->Reset)
725RLAPI void rlSetRenderBatchActive(rlRenderBatch *batch); // Set the active render batch for rlgl (NULL for default internal)
726RLAPI void rlDrawRenderBatchActive(void); // Update and draw internal render batch
727RLAPI bool rlCheckRenderBatchLimit(int vCount); // Check internal buffer overflow for a given number of vertex
728
729RLAPI void rlSetTexture(unsigned int id); // Set current texture for render batch and check buffers limits
730
731//------------------------------------------------------------------------------------------------------------------------
732
733// Vertex buffers management
734RLAPI unsigned int rlLoadVertexArray(void); // Load vertex array (vao) if supported
735RLAPI unsigned int rlLoadVertexBuffer(const void *buffer, int size, bool dynamic); // Load a vertex buffer object
736RLAPI unsigned int rlLoadVertexBufferElement(const void *buffer, int size, bool dynamic); // Load vertex buffer elements object
737RLAPI void rlUpdateVertexBuffer(unsigned int bufferId, const void *data, int dataSize, int offset); // Update vertex buffer object data on GPU buffer
738RLAPI void rlUpdateVertexBufferElements(unsigned int id, const void *data, int dataSize, int offset); // Update vertex buffer elements data on GPU buffer
739RLAPI void rlUnloadVertexArray(unsigned int vaoId); // Unload vertex array (vao)
740RLAPI void rlUnloadVertexBuffer(unsigned int vboId); // Unload vertex buffer object
741RLAPI void rlSetVertexAttribute(unsigned int index, int compSize, int type, bool normalized, int stride, int offset); // Set vertex attribute data configuration
742RLAPI void rlSetVertexAttributeDivisor(unsigned int index, int divisor); // Set vertex attribute data divisor
743RLAPI void rlSetVertexAttributeDefault(int locIndex, const void *value, int attribType, int count); // Set vertex attribute default value, when attribute to provided
744RLAPI void rlDrawVertexArray(int offset, int count); // Draw vertex array (currently active vao)
745RLAPI void rlDrawVertexArrayElements(int offset, int count, const void *buffer); // Draw vertex array elements
746RLAPI void rlDrawVertexArrayInstanced(int offset, int count, int instances); // Draw vertex array (currently active vao) with instancing
747RLAPI void rlDrawVertexArrayElementsInstanced(int offset, int count, const void *buffer, int instances); // Draw vertex array elements with instancing
748
749// Textures management
750RLAPI unsigned int rlLoadTexture(const void *data, int width, int height, int format, int mipmapCount); // Load texture data
751RLAPI unsigned int rlLoadTextureDepth(int width, int height, bool useRenderBuffer); // Load depth texture/renderbuffer (to be attached to fbo)
752RLAPI unsigned int rlLoadTextureCubemap(const void *data, int size, int format, int mipmapCount); // Load texture cubemap data
753RLAPI void rlUpdateTexture(unsigned int id, int offsetX, int offsetY, int width, int height, int format, const void *data); // Update texture with new data on GPU
754RLAPI void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned int *glFormat, unsigned int *glType); // Get OpenGL internal formats
755RLAPI const char *rlGetPixelFormatName(unsigned int format); // Get name string for pixel format
756RLAPI void rlUnloadTexture(unsigned int id); // Unload texture from GPU memory
757RLAPI void rlGenTextureMipmaps(unsigned int id, int width, int height, int format, int *mipmaps); // Generate mipmap data for selected texture
758RLAPI void *rlReadTexturePixels(unsigned int id, int width, int height, int format); // Read texture pixel data
759RLAPI unsigned char *rlReadScreenPixels(int width, int height); // Read screen pixel data (color buffer)
760
761// Framebuffer management (fbo)
762RLAPI unsigned int rlLoadFramebuffer(void); // Load an empty framebuffer
763RLAPI void rlFramebufferAttach(unsigned int fboId, unsigned int texId, int attachType, int texType, int mipLevel); // Attach texture/renderbuffer to a framebuffer
764RLAPI bool rlFramebufferComplete(unsigned int id); // Verify framebuffer is complete
765RLAPI void rlUnloadFramebuffer(unsigned int id); // Delete framebuffer from GPU
766
767// Shaders management
768RLAPI unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode); // Load shader from code strings
769RLAPI unsigned int rlCompileShader(const char *shaderCode, int type); // Compile custom shader and return shader id (type: RL_VERTEX_SHADER, RL_FRAGMENT_SHADER, RL_COMPUTE_SHADER)
770RLAPI unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId); // Load custom shader program
771RLAPI void rlUnloadShaderProgram(unsigned int id); // Unload shader program
772RLAPI int rlGetLocationUniform(unsigned int shaderId, const char *uniformName); // Get shader location uniform
773RLAPI int rlGetLocationAttrib(unsigned int shaderId, const char *attribName); // Get shader location attribute
774RLAPI void rlSetUniform(int locIndex, const void *value, int uniformType, int count); // Set shader value uniform
775RLAPI void rlSetUniformMatrix(int locIndex, Matrix mat); // Set shader value matrix
776RLAPI void rlSetUniformMatrices(int locIndex, const Matrix *mat, int count); // Set shader value matrices
777RLAPI void rlSetUniformSampler(int locIndex, unsigned int textureId); // Set shader value sampler
778RLAPI void rlSetShader(unsigned int id, int *locs); // Set shader currently active (id and locations)
779
780// Compute shader management
781RLAPI unsigned int rlLoadComputeShaderProgram(unsigned int shaderId); // Load compute shader program
782RLAPI void rlComputeShaderDispatch(unsigned int groupX, unsigned int groupY, unsigned int groupZ); // Dispatch compute shader (equivalent to *draw* for graphics pipeline)
783
784// Shader buffer storage object management (ssbo)
785RLAPI unsigned int rlLoadShaderBuffer(unsigned int size, const void *data, int usageHint); // Load shader storage buffer object (SSBO)
786RLAPI void rlUnloadShaderBuffer(unsigned int ssboId); // Unload shader storage buffer object (SSBO)
787RLAPI void rlUpdateShaderBuffer(unsigned int id, const void *data, unsigned int dataSize, unsigned int offset); // Update SSBO buffer data
788RLAPI void rlBindShaderBuffer(unsigned int id, unsigned int index); // Bind SSBO buffer
789RLAPI void rlReadShaderBuffer(unsigned int id, void *dest, unsigned int count, unsigned int offset); // Read SSBO buffer data (GPU->CPU)
790RLAPI void rlCopyShaderBuffer(unsigned int destId, unsigned int srcId, unsigned int destOffset, unsigned int srcOffset, unsigned int count); // Copy SSBO data between buffers
791RLAPI unsigned int rlGetShaderBufferSize(unsigned int id); // Get SSBO buffer size
792
793// Buffer management
794RLAPI void rlBindImageTexture(unsigned int id, unsigned int index, int format, bool readonly); // Bind image texture
795
796// Matrix state management
797RLAPI Matrix rlGetMatrixModelview(void); // Get internal modelview matrix
798RLAPI Matrix rlGetMatrixProjection(void); // Get internal projection matrix
799RLAPI Matrix rlGetMatrixTransform(void); // Get internal accumulated transform matrix
800RLAPI Matrix rlGetMatrixProjectionStereo(int eye); // Get internal projection matrix for stereo render (selected eye)
801RLAPI Matrix rlGetMatrixViewOffsetStereo(int eye); // Get internal view offset matrix for stereo render (selected eye)
802RLAPI void rlSetMatrixProjection(Matrix proj); // Set a custom projection matrix (replaces internal projection matrix)
803RLAPI void rlSetMatrixModelview(Matrix view); // Set a custom modelview matrix (replaces internal modelview matrix)
804RLAPI void rlSetMatrixProjectionStereo(Matrix right, Matrix left); // Set eyes projection matrices for stereo rendering
805RLAPI void rlSetMatrixViewOffsetStereo(Matrix right, Matrix left); // Set eyes view offsets matrices for stereo rendering
806
807// Quick and dirty cube/quad buffers load->draw->unload
808RLAPI void rlLoadDrawCube(void); // Load and draw a cube
809RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
810
811#if defined(__cplusplus)
812}
813#endif
814
815#endif // RLGL_H
816
817/***********************************************************************************
818*
819* RLGL IMPLEMENTATION
820*
821************************************************************************************/
822
823#if defined(RLGL_IMPLEMENTATION)
824
825// Expose OpenGL functions from glad in raylib
826#if defined(BUILD_LIBTYPE_SHARED)
827 #define GLAD_API_CALL_EXPORT
828 #define GLAD_API_CALL_EXPORT_BUILD
829#endif
830
831#if defined(GRAPHICS_API_OPENGL_11)
832 #if defined(__APPLE__)
833 #include <OpenGL/gl.h> // OpenGL 1.1 library for OSX
834 #include <OpenGL/glext.h> // OpenGL extensions library
835 #else
836 // APIENTRY for OpenGL function pointer declarations is required
837 #if !defined(APIENTRY)
838 #if defined(_WIN32)
839 #define APIENTRY __stdcall
840 #else
841 #define APIENTRY
842 #endif
843 #endif
844 // WINGDIAPI definition. Some Windows OpenGL headers need it
845 #if !defined(WINGDIAPI) && defined(_WIN32)
846 #define WINGDIAPI __declspec(dllimport)
847 #endif
848
849 #include <GL/gl.h> // OpenGL 1.1 library
850 #endif
851#endif
852
853#if defined(GRAPHICS_API_OPENGL_33)
854 #define GLAD_MALLOC RL_MALLOC
855 #define GLAD_FREE RL_FREE
856
857 #define GLAD_GL_IMPLEMENTATION
858 #include "external/glad.h" // GLAD extensions loading library, includes OpenGL headers
859#endif
860
861#if defined(GRAPHICS_API_OPENGL_ES3)
862 #include <GLES3/gl3.h> // OpenGL ES 3.0 library
863 #define GL_GLEXT_PROTOTYPES
864 #include <GLES2/gl2ext.h> // OpenGL ES 2.0 extensions library
865#elif defined(GRAPHICS_API_OPENGL_ES2)
866 // NOTE: OpenGL ES 2.0 can be enabled on Desktop platforms,
867 // in that case, functions are loaded from a custom glad for OpenGL ES 2.0
868 #if defined(PLATFORM_DESKTOP_GLFW) || defined(PLATFORM_DESKTOP_SDL)
869 #define GLAD_GLES2_IMPLEMENTATION
870 #include "external/glad_gles2.h"
871 #else
872 #define GL_GLEXT_PROTOTYPES
873 //#include <EGL/egl.h> // EGL library -> not required, platform layer
874 #include <GLES2/gl2.h> // OpenGL ES 2.0 library
875 #include <GLES2/gl2ext.h> // OpenGL ES 2.0 extensions library
876 #endif
877
878 // It seems OpenGL ES 2.0 instancing entry points are not defined on Raspberry Pi
879 // provided headers (despite being defined in official Khronos GLES2 headers)
880 #if defined(PLATFORM_DRM)
881 typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount);
882 typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
883 typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISOREXTPROC) (GLuint index, GLuint divisor);
884 #endif
885#endif
886
887#include <stdlib.h> // Required for: malloc(), free()
888#include <string.h> // Required for: strcmp(), strlen() [Used in rlglInit(), on extensions loading]
889#include <math.h> // Required for: sqrtf(), sinf(), cosf(), floor(), log()
890
891//----------------------------------------------------------------------------------
892// Defines and Macros
893//----------------------------------------------------------------------------------
894#ifndef PI
895 #define PI 3.14159265358979323846f
896#endif
897#ifndef DEG2RAD
898 #define DEG2RAD (PI/180.0f)
899#endif
900#ifndef RAD2DEG
901 #define RAD2DEG (180.0f/PI)
902#endif
903
904#ifndef GL_SHADING_LANGUAGE_VERSION
905 #define GL_SHADING_LANGUAGE_VERSION 0x8B8C
906#endif
907
908#ifndef GL_COMPRESSED_RGB_S3TC_DXT1_EXT
909 #define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
910#endif
911#ifndef GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
912 #define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
913#endif
914#ifndef GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
915 #define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
916#endif
917#ifndef GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
918 #define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
919#endif
920#ifndef GL_ETC1_RGB8_OES
921 #define GL_ETC1_RGB8_OES 0x8D64
922#endif
923#ifndef GL_COMPRESSED_RGB8_ETC2
924 #define GL_COMPRESSED_RGB8_ETC2 0x9274
925#endif
926#ifndef GL_COMPRESSED_RGBA8_ETC2_EAC
927 #define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
928#endif
929#ifndef GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
930 #define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00
931#endif
932#ifndef GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
933 #define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02
934#endif
935#ifndef GL_COMPRESSED_RGBA_ASTC_4x4_KHR
936 #define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93b0
937#endif
938#ifndef GL_COMPRESSED_RGBA_ASTC_8x8_KHR
939 #define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93b7
940#endif
941
942#ifndef GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT
943 #define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
944#endif
945#ifndef GL_TEXTURE_MAX_ANISOTROPY_EXT
946 #define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
947#endif
948
949#ifndef GL_PROGRAM_POINT_SIZE
950 #define GL_PROGRAM_POINT_SIZE 0x8642
951#endif
952
953#ifndef GL_LINE_WIDTH
954 #define GL_LINE_WIDTH 0x0B21
955#endif
956
957#if defined(GRAPHICS_API_OPENGL_11)
958 #define GL_UNSIGNED_SHORT_5_6_5 0x8363
959 #define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
960 #define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
961#endif
962
963#if defined(GRAPHICS_API_OPENGL_21)
964 #define GL_LUMINANCE 0x1909
965 #define GL_LUMINANCE_ALPHA 0x190A
966#endif
967
968#if defined(GRAPHICS_API_OPENGL_ES2)
969 #define glClearDepth glClearDepthf
970 #if !defined(GRAPHICS_API_OPENGL_ES3)
971 #define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER
972 #define GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER
973 #endif
974#endif
975
976// Default shader vertex attribute names to set location points
977#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION
978 #define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION "vertexPosition" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION
979#endif
980#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD
981 #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD "vertexTexCoord" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD
982#endif
983#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL
984 #define RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL "vertexNormal" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL
985#endif
986#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR
987 #define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR "vertexColor" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR
988#endif
989#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT
990 #define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT "vertexTangent" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT
991#endif
992#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2
993 #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2
994#endif
995#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS
996 #define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS "vertexBoneIds" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS
997#endif
998#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS
999 #define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS "vertexBoneWeights" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS
1000#endif
1001
1002#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_MVP
1003 #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix
1004#endif
1005#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW
1006 #define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW "matView" // view matrix
1007#endif
1008#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION
1009 #define RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION "matProjection" // projection matrix
1010#endif
1011#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL
1012 #define RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL "matModel" // model matrix
1013#endif
1014#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL
1015 #define RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL "matNormal" // normal matrix (transpose(inverse(matModelView))
1016#endif
1017#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR
1018 #define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color)
1019#endif
1020#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_BONE_MATRICES
1021 #define RL_DEFAULT_SHADER_UNIFORM_NAME_BONE_MATRICES "boneMatrices" // bone matrices
1022#endif
1023#ifndef RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0
1024 #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0)
1025#endif
1026#ifndef RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1
1027 #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1 "texture1" // texture1 (texture slot active 1)
1028#endif
1029#ifndef RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2
1030 #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 "texture2" // texture2 (texture slot active 2)
1031#endif
1032
1033//----------------------------------------------------------------------------------
1034// Types and Structures Definition
1035//----------------------------------------------------------------------------------
1036#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
1037typedef struct rlglData {
1038 rlRenderBatch *currentBatch; // Current render batch
1039 rlRenderBatch defaultBatch; // Default internal render batch
1040
1041 struct {
1042 int vertexCounter; // Current active render batch vertex counter (generic, used for all batches)
1043 float texcoordx, texcoordy; // Current active texture coordinate (added on glVertex*())
1044 float normalx, normaly, normalz; // Current active normal (added on glVertex*())
1045 unsigned char colorr, colorg, colorb, colora; // Current active color (added on glVertex*())
1046
1047 int currentMatrixMode; // Current matrix mode
1048 Matrix *currentMatrix; // Current matrix pointer
1049 Matrix modelview; // Default modelview matrix
1050 Matrix projection; // Default projection matrix
1051 Matrix transform; // Transform matrix to be used with rlTranslate, rlRotate, rlScale
1052 bool transformRequired; // Require transform matrix application to current draw-call vertex (if required)
1053 Matrix stack[RL_MAX_MATRIX_STACK_SIZE];// Matrix stack for push/pop
1054 int stackCounter; // Matrix stack counter
1055
1056 unsigned int defaultTextureId; // Default texture used on shapes/poly drawing (required by shader)
1057 unsigned int activeTextureId[RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS]; // Active texture ids to be enabled on batch drawing (0 active by default)
1058 unsigned int defaultVShaderId; // Default vertex shader id (used by default shader program)
1059 unsigned int defaultFShaderId; // Default fragment shader id (used by default shader program)
1060 unsigned int defaultShaderId; // Default shader program id, supports vertex color and diffuse texture
1061 int *defaultShaderLocs; // Default shader locations pointer to be used on rendering
1062 unsigned int currentShaderId; // Current shader id to be used on rendering (by default, defaultShaderId)
1063 int *currentShaderLocs; // Current shader locations pointer to be used on rendering (by default, defaultShaderLocs)
1064
1065 bool stereoRender; // Stereo rendering flag
1066 Matrix projectionStereo[2]; // VR stereo rendering eyes projection matrices
1067 Matrix viewOffsetStereo[2]; // VR stereo rendering eyes view offset matrices
1068
1069 // Blending variables
1070 int currentBlendMode; // Blending mode active
1071 int glBlendSrcFactor; // Blending source factor
1072 int glBlendDstFactor; // Blending destination factor
1073 int glBlendEquation; // Blending equation
1074 int glBlendSrcFactorRGB; // Blending source RGB factor
1075 int glBlendDestFactorRGB; // Blending destination RGB factor
1076 int glBlendSrcFactorAlpha; // Blending source alpha factor
1077 int glBlendDestFactorAlpha; // Blending destination alpha factor
1078 int glBlendEquationRGB; // Blending equation for RGB
1079 int glBlendEquationAlpha; // Blending equation for alpha
1080 bool glCustomBlendModeModified; // Custom blending factor and equation modification status
1081
1082 int framebufferWidth; // Current framebuffer width
1083 int framebufferHeight; // Current framebuffer height
1084
1085 } State; // Renderer state
1086 struct {
1087 bool vao; // VAO support (OpenGL ES2 could not support VAO extension) (GL_ARB_vertex_array_object)
1088 bool instancing; // Instancing supported (GL_ANGLE_instanced_arrays, GL_EXT_draw_instanced + GL_EXT_instanced_arrays)
1089 bool texNPOT; // NPOT textures full support (GL_ARB_texture_non_power_of_two, GL_OES_texture_npot)
1090 bool texDepth; // Depth textures supported (GL_ARB_depth_texture, GL_OES_depth_texture)
1091 bool texDepthWebGL; // Depth textures supported WebGL specific (GL_WEBGL_depth_texture)
1092 bool texFloat32; // float textures support (32 bit per channel) (GL_OES_texture_float)
1093 bool texFloat16; // half float textures support (16 bit per channel) (GL_OES_texture_half_float)
1094 bool texCompDXT; // DDS texture compression support (GL_EXT_texture_compression_s3tc, GL_WEBGL_compressed_texture_s3tc, GL_WEBKIT_WEBGL_compressed_texture_s3tc)
1095 bool texCompETC1; // ETC1 texture compression support (GL_OES_compressed_ETC1_RGB8_texture, GL_WEBGL_compressed_texture_etc1)
1096 bool texCompETC2; // ETC2/EAC texture compression support (GL_ARB_ES3_compatibility)
1097 bool texCompPVRT; // PVR texture compression support (GL_IMG_texture_compression_pvrtc)
1098 bool texCompASTC; // ASTC texture compression support (GL_KHR_texture_compression_astc_hdr, GL_KHR_texture_compression_astc_ldr)
1099 bool texMirrorClamp; // Clamp mirror wrap mode supported (GL_EXT_texture_mirror_clamp)
1100 bool texAnisoFilter; // Anisotropic texture filtering support (GL_EXT_texture_filter_anisotropic)
1101 bool computeShader; // Compute shaders support (GL_ARB_compute_shader)
1102 bool ssbo; // Shader storage buffer object support (GL_ARB_shader_storage_buffer_object)
1103
1104 float maxAnisotropyLevel; // Maximum anisotropy level supported (minimum is 2.0f)
1105 int maxDepthBits; // Maximum bits for depth component
1106
1107 } ExtSupported; // Extensions supported flags
1108} rlglData;
1109
1110typedef void *(*rlglLoadProc)(const char *name); // OpenGL extension functions loader signature (same as GLADloadproc)
1111
1112#endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
1113
1114//----------------------------------------------------------------------------------
1115// Global Variables Definition
1116//----------------------------------------------------------------------------------
1117static double rlCullDistanceNear = RL_CULL_DISTANCE_NEAR;
1118static double rlCullDistanceFar = RL_CULL_DISTANCE_FAR;
1119
1120#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
1121static rlglData RLGL = { 0 };
1122#endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
1123
1124#if defined(GRAPHICS_API_OPENGL_ES2) && !defined(GRAPHICS_API_OPENGL_ES3)
1125// NOTE: VAO functionality is exposed through extensions (OES)
1126static PFNGLGENVERTEXARRAYSOESPROC glGenVertexArrays = NULL;
1127static PFNGLBINDVERTEXARRAYOESPROC glBindVertexArray = NULL;
1128static PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArrays = NULL;
1129
1130// NOTE: Instancing functionality could also be available through extension
1131static PFNGLDRAWARRAYSINSTANCEDEXTPROC glDrawArraysInstanced = NULL;
1132static PFNGLDRAWELEMENTSINSTANCEDEXTPROC glDrawElementsInstanced = NULL;
1133static PFNGLVERTEXATTRIBDIVISOREXTPROC glVertexAttribDivisor = NULL;
1134#endif
1135
1136//----------------------------------------------------------------------------------
1137// Module specific Functions Declaration
1138//----------------------------------------------------------------------------------
1139#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
1140static void rlLoadShaderDefault(void); // Load default shader
1141static void rlUnloadShaderDefault(void); // Unload default shader
1142#if defined(RLGL_SHOW_GL_DETAILS_INFO)
1143static const char *rlGetCompressedFormatName(int format); // Get compressed format official GL identifier name
1144#endif // RLGL_SHOW_GL_DETAILS_INFO
1145#endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
1146
1147static int rlGetPixelDataSize(int width, int height, int format); // Get pixel data size in bytes (image or texture)
1148
1149// Auxiliar matrix math functions
1150typedef struct rl_float16 {
1151 float v[16];
1152} rl_float16;
1153static rl_float16 rlMatrixToFloatV(Matrix mat); // Get float array of matrix data
1154#define rlMatrixToFloat(mat) (rlMatrixToFloatV(mat).v) // Get float vector for Matrix
1155static Matrix rlMatrixIdentity(void); // Get identity matrix
1156static Matrix rlMatrixMultiply(Matrix left, Matrix right); // Multiply two matrices
1157static Matrix rlMatrixTranspose(Matrix mat); // Transposes provided matrix
1158static Matrix rlMatrixInvert(Matrix mat); // Invert provided matrix
1159
1160//----------------------------------------------------------------------------------
1161// Module Functions Definition - Matrix operations
1162//----------------------------------------------------------------------------------
1163
1164#if defined(GRAPHICS_API_OPENGL_11)
1165// Fallback to OpenGL 1.1 function calls
1166//---------------------------------------
1167void rlMatrixMode(int mode)
1168{
1169 switch (mode)
1170 {
1171 case RL_PROJECTION: glMatrixMode(GL_PROJECTION); break;
1172 case RL_MODELVIEW: glMatrixMode(GL_MODELVIEW); break;
1173 case RL_TEXTURE: glMatrixMode(GL_TEXTURE); break;
1174 default: break;
1175 }
1176}
1177
1178void rlFrustum(double left, double right, double bottom, double top, double znear, double zfar)
1179{
1180 glFrustum(left, right, bottom, top, znear, zfar);
1181}
1182
1183void rlOrtho(double left, double right, double bottom, double top, double znear, double zfar)
1184{
1185 glOrtho(left, right, bottom, top, znear, zfar);
1186}
1187
1188void rlPushMatrix(void) { glPushMatrix(); }
1189void rlPopMatrix(void) { glPopMatrix(); }
1190void rlLoadIdentity(void) { glLoadIdentity(); }
1191void rlTranslatef(float x, float y, float z) { glTranslatef(x, y, z); }
1192void rlRotatef(float angle, float x, float y, float z) { glRotatef(angle, x, y, z); }
1193void rlScalef(float x, float y, float z) { glScalef(x, y, z); }
1194void rlMultMatrixf(const float *matf) { glMultMatrixf(matf); }
1195#endif
1196#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
1197// Choose the current matrix to be transformed
1198void rlMatrixMode(int mode)
1199{
1200 if (mode == RL_PROJECTION) RLGL.State.currentMatrix = &RLGL.State.projection;
1201 else if (mode == RL_MODELVIEW) RLGL.State.currentMatrix = &RLGL.State.modelview;
1202 //else if (mode == RL_TEXTURE) // Not supported
1203
1204 RLGL.State.currentMatrixMode = mode;
1205}
1206
1207// Push the current matrix into RLGL.State.stack
1208void rlPushMatrix(void)
1209{
1210 if (RLGL.State.stackCounter >= RL_MAX_MATRIX_STACK_SIZE) TRACELOG(RL_LOG_ERROR, "RLGL: Matrix stack overflow (RL_MAX_MATRIX_STACK_SIZE)");
1211
1212 if (RLGL.State.currentMatrixMode == RL_MODELVIEW)
1213 {
1214 RLGL.State.transformRequired = true;
1215 RLGL.State.currentMatrix = &RLGL.State.transform;
1216 }
1217
1218 RLGL.State.stack[RLGL.State.stackCounter] = *RLGL.State.currentMatrix;
1219 RLGL.State.stackCounter++;
1220}
1221
1222// Pop lattest inserted matrix from RLGL.State.stack
1223void rlPopMatrix(void)
1224{
1225 if (RLGL.State.stackCounter > 0)
1226 {
1227 Matrix mat = RLGL.State.stack[RLGL.State.stackCounter - 1];
1228 *RLGL.State.currentMatrix = mat;
1229 RLGL.State.stackCounter--;
1230 }
1231
1232 if ((RLGL.State.stackCounter == 0) && (RLGL.State.currentMatrixMode == RL_MODELVIEW))
1233 {
1234 RLGL.State.currentMatrix = &RLGL.State.modelview;
1235 RLGL.State.transformRequired = false;
1236 }
1237}
1238
1239// Reset current matrix to identity matrix
1240void rlLoadIdentity(void)
1241{
1242 *RLGL.State.currentMatrix = rlMatrixIdentity();
1243}
1244
1245// Multiply the current matrix by a translation matrix
1246void rlTranslatef(float x, float y, float z)
1247{
1248 Matrix matTranslation = {
1249 1.0f, 0.0f, 0.0f, x,
1250 0.0f, 1.0f, 0.0f, y,
1251 0.0f, 0.0f, 1.0f, z,
1252 0.0f, 0.0f, 0.0f, 1.0f
1253 };
1254
1255 // NOTE: We transpose matrix with multiplication order
1256 *RLGL.State.currentMatrix = rlMatrixMultiply(matTranslation, *RLGL.State.currentMatrix);
1257}
1258
1259// Multiply the current matrix by a rotation matrix
1260// NOTE: The provided angle must be in degrees
1261void rlRotatef(float angle, float x, float y, float z)
1262{
1263 Matrix matRotation = rlMatrixIdentity();
1264
1265 // Axis vector (x, y, z) normalization
1266 float lengthSquared = x*x + y*y + z*z;
1267 if ((lengthSquared != 1.0f) && (lengthSquared != 0.0f))
1268 {
1269 float inverseLength = 1.0f/sqrtf(lengthSquared);
1270 x *= inverseLength;
1271 y *= inverseLength;
1272 z *= inverseLength;
1273 }
1274
1275 // Rotation matrix generation
1276 float sinres = sinf(DEG2RAD*angle);
1277 float cosres = cosf(DEG2RAD*angle);
1278 float t = 1.0f - cosres;
1279
1280 matRotation.m0 = x*x*t + cosres;
1281 matRotation.m1 = y*x*t + z*sinres;
1282 matRotation.m2 = z*x*t - y*sinres;
1283 matRotation.m3 = 0.0f;
1284
1285 matRotation.m4 = x*y*t - z*sinres;
1286 matRotation.m5 = y*y*t + cosres;
1287 matRotation.m6 = z*y*t + x*sinres;
1288 matRotation.m7 = 0.0f;
1289
1290 matRotation.m8 = x*z*t + y*sinres;
1291 matRotation.m9 = y*z*t - x*sinres;
1292 matRotation.m10 = z*z*t + cosres;
1293 matRotation.m11 = 0.0f;
1294
1295 matRotation.m12 = 0.0f;
1296 matRotation.m13 = 0.0f;
1297 matRotation.m14 = 0.0f;
1298 matRotation.m15 = 1.0f;
1299
1300 // NOTE: We transpose matrix with multiplication order
1301 *RLGL.State.currentMatrix = rlMatrixMultiply(matRotation, *RLGL.State.currentMatrix);
1302}
1303
1304// Multiply the current matrix by a scaling matrix
1305void rlScalef(float x, float y, float z)
1306{
1307 Matrix matScale = {
1308 x, 0.0f, 0.0f, 0.0f,
1309 0.0f, y, 0.0f, 0.0f,
1310 0.0f, 0.0f, z, 0.0f,
1311 0.0f, 0.0f, 0.0f, 1.0f
1312 };
1313
1314 // NOTE: We transpose matrix with multiplication order
1315 *RLGL.State.currentMatrix = rlMatrixMultiply(matScale, *RLGL.State.currentMatrix);
1316}
1317
1318// Multiply the current matrix by another matrix
1319void rlMultMatrixf(const float *matf)
1320{
1321 // Matrix creation from array
1322 Matrix mat = { matf[0], matf[4], matf[8], matf[12],
1323 matf[1], matf[5], matf[9], matf[13],
1324 matf[2], matf[6], matf[10], matf[14],
1325 matf[3], matf[7], matf[11], matf[15] };
1326
1327 *RLGL.State.currentMatrix = rlMatrixMultiply(mat, *RLGL.State.currentMatrix);
1328}
1329
1330// Multiply the current matrix by a perspective matrix generated by parameters
1331void rlFrustum(double left, double right, double bottom, double top, double znear, double zfar)
1332{
1333 Matrix matFrustum = { 0 };
1334
1335 float rl = (float)(right - left);
1336 float tb = (float)(top - bottom);
1337 float fn = (float)(zfar - znear);
1338
1339 matFrustum.m0 = ((float) znear*2.0f)/rl;
1340 matFrustum.m1 = 0.0f;
1341 matFrustum.m2 = 0.0f;
1342 matFrustum.m3 = 0.0f;
1343
1344 matFrustum.m4 = 0.0f;
1345 matFrustum.m5 = ((float) znear*2.0f)/tb;
1346 matFrustum.m6 = 0.0f;
1347 matFrustum.m7 = 0.0f;
1348
1349 matFrustum.m8 = ((float)right + (float)left)/rl;
1350 matFrustum.m9 = ((float)top + (float)bottom)/tb;
1351 matFrustum.m10 = -((float)zfar + (float)znear)/fn;
1352 matFrustum.m11 = -1.0f;
1353
1354 matFrustum.m12 = 0.0f;
1355 matFrustum.m13 = 0.0f;
1356 matFrustum.m14 = -((float)zfar*(float)znear*2.0f)/fn;
1357 matFrustum.m15 = 0.0f;
1358
1359 *RLGL.State.currentMatrix = rlMatrixMultiply(*RLGL.State.currentMatrix, matFrustum);
1360}
1361
1362// Multiply the current matrix by an orthographic matrix generated by parameters
1363void rlOrtho(double left, double right, double bottom, double top, double znear, double zfar)
1364{
1365 // NOTE: If left-right and top-botton values are equal it could create a division by zero,
1366 // response to it is platform/compiler dependant
1367 Matrix matOrtho = { 0 };
1368
1369 float rl = (float)(right - left);
1370 float tb = (float)(top - bottom);
1371 float fn = (float)(zfar - znear);
1372
1373 matOrtho.m0 = 2.0f/rl;
1374 matOrtho.m1 = 0.0f;
1375 matOrtho.m2 = 0.0f;
1376 matOrtho.m3 = 0.0f;
1377 matOrtho.m4 = 0.0f;
1378 matOrtho.m5 = 2.0f/tb;
1379 matOrtho.m6 = 0.0f;
1380 matOrtho.m7 = 0.0f;
1381 matOrtho.m8 = 0.0f;
1382 matOrtho.m9 = 0.0f;
1383 matOrtho.m10 = -2.0f/fn;
1384 matOrtho.m11 = 0.0f;
1385 matOrtho.m12 = -((float)left + (float)right)/rl;
1386 matOrtho.m13 = -((float)top + (float)bottom)/tb;
1387 matOrtho.m14 = -((float)zfar + (float)znear)/fn;
1388 matOrtho.m15 = 1.0f;
1389
1390 *RLGL.State.currentMatrix = rlMatrixMultiply(*RLGL.State.currentMatrix, matOrtho);
1391}
1392#endif
1393
1394// Set the viewport area (transformation from normalized device coordinates to window coordinates)
1395// NOTE: We store current viewport dimensions
1396void rlViewport(int x, int y, int width, int height)
1397{
1398 glViewport(x, y, width, height);
1399}
1400
1401// Set clip planes distances
1402void rlSetClipPlanes(double nearPlane, double farPlane)
1403{
1404 rlCullDistanceNear = nearPlane;
1405 rlCullDistanceFar = farPlane;
1406}
1407
1408// Get cull plane distance near
1409double rlGetCullDistanceNear(void)
1410{
1411 return rlCullDistanceNear;
1412}
1413
1414// Get cull plane distance far
1415double rlGetCullDistanceFar(void)
1416{
1417 return rlCullDistanceFar;
1418}
1419
1420//----------------------------------------------------------------------------------
1421// Module Functions Definition - Vertex level operations
1422//----------------------------------------------------------------------------------
1423#if defined(GRAPHICS_API_OPENGL_11)
1424// Fallback to OpenGL 1.1 function calls
1425//---------------------------------------
1426void rlBegin(int mode)
1427{
1428 switch (mode)
1429 {
1430 case RL_LINES: glBegin(GL_LINES); break;
1431 case RL_TRIANGLES: glBegin(GL_TRIANGLES); break;
1432 case RL_QUADS: glBegin(GL_QUADS); break;
1433 default: break;
1434 }
1435}
1436
1437void rlEnd(void) { glEnd(); }
1438void rlVertex2i(int x, int y) { glVertex2i(x, y); }
1439void rlVertex2f(float x, float y) { glVertex2f(x, y); }
1440void rlVertex3f(float x, float y, float z) { glVertex3f(x, y, z); }
1441void rlTexCoord2f(float x, float y) { glTexCoord2f(x, y); }
1442void rlNormal3f(float x, float y, float z) { glNormal3f(x, y, z); }
1443void rlColor4ub(unsigned char r, unsigned char g, unsigned char b, unsigned char a) { glColor4ub(r, g, b, a); }
1444void rlColor3f(float x, float y, float z) { glColor3f(x, y, z); }
1445void rlColor4f(float x, float y, float z, float w) { glColor4f(x, y, z, w); }
1446#endif
1447#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
1448// Initialize drawing mode (how to organize vertex)
1449void rlBegin(int mode)
1450{
1451 // Draw mode can be RL_LINES, RL_TRIANGLES and RL_QUADS
1452 // NOTE: In all three cases, vertex are accumulated over default internal vertex buffer
1453 if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode != mode)
1454 {
1455 if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount > 0)
1456 {
1457 // Make sure current RLGL.currentBatch->draws[i].vertexCount is aligned a multiple of 4,
1458 // that way, following QUADS drawing will keep aligned with index processing
1459 // It implies adding some extra alignment vertex at the end of the draw,
1460 // those vertex are not processed but they are considered as an additional offset
1461 // for the next set of vertex to be drawn
1462 if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode == RL_LINES) RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount < 4)? RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount : RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount%4);
1463 else if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode == RL_TRIANGLES) RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount < 4)? 1 : (4 - (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount%4)));
1464 else RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment = 0;
1465
1466 if (!rlCheckRenderBatchLimit(RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment))
1467 {
1468 RLGL.State.vertexCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment;
1469 RLGL.currentBatch->drawCounter++;
1470 }
1471 }
1472
1473 if (RLGL.currentBatch->drawCounter >= RL_DEFAULT_BATCH_DRAWCALLS) rlDrawRenderBatch(RLGL.currentBatch);
1474
1475 RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode = mode;
1476 RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount = 0;
1477 RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].textureId = RLGL.State.defaultTextureId;
1478 }
1479}
1480
1481// Finish vertex providing
1482void rlEnd(void)
1483{
1484 // NOTE: Depth increment is dependant on rlOrtho(): z-near and z-far values,
1485 // as well as depth buffer bit-depth (16bit or 24bit or 32bit)
1486 // Correct increment formula would be: depthInc = (zfar - znear)/pow(2, bits)
1487 RLGL.currentBatch->currentDepth += (1.0f/20000.0f);
1488}
1489
1490// Define one vertex (position)
1491// NOTE: Vertex position data is the basic information required for drawing
1492void rlVertex3f(float x, float y, float z)
1493{
1494 float tx = x;
1495 float ty = y;
1496 float tz = z;
1497
1498 // Transform provided vector if required
1499 if (RLGL.State.transformRequired)
1500 {
1501 tx = RLGL.State.transform.m0*x + RLGL.State.transform.m4*y + RLGL.State.transform.m8*z + RLGL.State.transform.m12;
1502 ty = RLGL.State.transform.m1*x + RLGL.State.transform.m5*y + RLGL.State.transform.m9*z + RLGL.State.transform.m13;
1503 tz = RLGL.State.transform.m2*x + RLGL.State.transform.m6*y + RLGL.State.transform.m10*z + RLGL.State.transform.m14;
1504 }
1505
1506 // WARNING: We can't break primitives when launching a new batch
1507 // RL_LINES comes in pairs, RL_TRIANGLES come in groups of 3 vertices and RL_QUADS come in groups of 4 vertices
1508 // We must check current draw.mode when a new vertex is required and finish the batch only if the draw.mode draw.vertexCount is %2, %3 or %4
1509 if (RLGL.State.vertexCounter > (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementCount*4 - 4))
1510 {
1511 if ((RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode == RL_LINES) &&
1512 (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount%2 == 0))
1513 {
1514 // Reached the maximum number of vertices for RL_LINES drawing
1515 // Launch a draw call but keep current state for next vertices comming
1516 // NOTE: We add +1 vertex to the check for security
1517 rlCheckRenderBatchLimit(2 + 1);
1518 }
1519 else if ((RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode == RL_TRIANGLES) &&
1520 (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount%3 == 0))
1521 {
1522 rlCheckRenderBatchLimit(3 + 1);
1523 }
1524 else if ((RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode == RL_QUADS) &&
1525 (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount%4 == 0))
1526 {
1527 rlCheckRenderBatchLimit(4 + 1);
1528 }
1529 }
1530
1531 // Add vertices
1532 RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vertices[3*RLGL.State.vertexCounter] = tx;
1533 RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vertices[3*RLGL.State.vertexCounter + 1] = ty;
1534 RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vertices[3*RLGL.State.vertexCounter + 2] = tz;
1535
1536 // Add current texcoord
1537 RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].texcoords[2*RLGL.State.vertexCounter] = RLGL.State.texcoordx;
1538 RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].texcoords[2*RLGL.State.vertexCounter + 1] = RLGL.State.texcoordy;
1539
1540 // Add current normal
1541 RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].normals[3*RLGL.State.vertexCounter] = RLGL.State.normalx;
1542 RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].normals[3*RLGL.State.vertexCounter + 1] = RLGL.State.normaly;
1543 RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].normals[3*RLGL.State.vertexCounter + 2] = RLGL.State.normalz;
1544
1545 // Add current color
1546 RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.State.vertexCounter] = RLGL.State.colorr;
1547 RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.State.vertexCounter + 1] = RLGL.State.colorg;
1548 RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.State.vertexCounter + 2] = RLGL.State.colorb;
1549 RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.State.vertexCounter + 3] = RLGL.State.colora;
1550
1551 RLGL.State.vertexCounter++;
1552 RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount++;
1553}
1554
1555// Define one vertex (position)
1556void rlVertex2f(float x, float y)
1557{
1558 rlVertex3f(x, y, RLGL.currentBatch->currentDepth);
1559}
1560
1561// Define one vertex (position)
1562void rlVertex2i(int x, int y)
1563{
1564 rlVertex3f((float)x, (float)y, RLGL.currentBatch->currentDepth);
1565}
1566
1567// Define one vertex (texture coordinate)
1568// NOTE: Texture coordinates are limited to QUADS only
1569void rlTexCoord2f(float x, float y)
1570{
1571 RLGL.State.texcoordx = x;
1572 RLGL.State.texcoordy = y;
1573}
1574
1575// Define one vertex (normal)
1576// NOTE: Normals limited to TRIANGLES only?
1577void rlNormal3f(float x, float y, float z)
1578{
1579 float normalx = x;
1580 float normaly = y;
1581 float normalz = z;
1582 if (RLGL.State.transformRequired)
1583 {
1584 normalx = RLGL.State.transform.m0*x + RLGL.State.transform.m4*y + RLGL.State.transform.m8*z;
1585 normaly = RLGL.State.transform.m1*x + RLGL.State.transform.m5*y + RLGL.State.transform.m9*z;
1586 normalz = RLGL.State.transform.m2*x + RLGL.State.transform.m6*y + RLGL.State.transform.m10*z;
1587 }
1588 float length = sqrtf(normalx*normalx + normaly*normaly + normalz*normalz);
1589 if (length != 0.0f)
1590 {
1591 float ilength = 1.0f/length;
1592 normalx *= ilength;
1593 normaly *= ilength;
1594 normalz *= ilength;
1595 }
1596 RLGL.State.normalx = normalx;
1597 RLGL.State.normaly = normaly;
1598 RLGL.State.normalz = normalz;
1599}
1600
1601// Define one vertex (color)
1602void rlColor4ub(unsigned char x, unsigned char y, unsigned char z, unsigned char w)
1603{
1604 RLGL.State.colorr = x;
1605 RLGL.State.colorg = y;
1606 RLGL.State.colorb = z;
1607 RLGL.State.colora = w;
1608}
1609
1610// Define one vertex (color)
1611void rlColor4f(float r, float g, float b, float a)
1612{
1613 rlColor4ub((unsigned char)(r*255), (unsigned char)(g*255), (unsigned char)(b*255), (unsigned char)(a*255));
1614}
1615
1616// Define one vertex (color)
1617void rlColor3f(float x, float y, float z)
1618{
1619 rlColor4ub((unsigned char)(x*255), (unsigned char)(y*255), (unsigned char)(z*255), 255);
1620}
1621
1622#endif
1623
1624//--------------------------------------------------------------------------------------
1625// Module Functions Definition - OpenGL style functions (common to 1.1, 3.3+, ES2)
1626//--------------------------------------------------------------------------------------
1627
1628// Set current texture to use
1629void rlSetTexture(unsigned int id)
1630{
1631 if (id == 0)
1632 {
1633#if defined(GRAPHICS_API_OPENGL_11)
1634 rlDisableTexture();
1635#else
1636 // NOTE: If quads batch limit is reached, we force a draw call and next batch starts
1637 if (RLGL.State.vertexCounter >=
1638 RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementCount*4)
1639 {
1640 rlDrawRenderBatch(RLGL.currentBatch);
1641 }
1642#endif
1643 }
1644 else
1645 {
1646#if defined(GRAPHICS_API_OPENGL_11)
1647 rlEnableTexture(id);
1648#else
1649 if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].textureId != id)
1650 {
1651 if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount > 0)
1652 {
1653 // Make sure current RLGL.currentBatch->draws[i].vertexCount is aligned a multiple of 4,
1654 // that way, following QUADS drawing will keep aligned with index processing
1655 // It implies adding some extra alignment vertex at the end of the draw,
1656 // those vertex are not processed but they are considered as an additional offset
1657 // for the next set of vertex to be drawn
1658 if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode == RL_LINES) RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount < 4)? RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount : RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount%4);
1659 else if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode == RL_TRIANGLES) RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount < 4)? 1 : (4 - (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount%4)));
1660 else RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment = 0;
1661
1662 if (!rlCheckRenderBatchLimit(RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment))
1663 {
1664 RLGL.State.vertexCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment;
1665
1666 RLGL.currentBatch->drawCounter++;
1667 }
1668 }
1669
1670 if (RLGL.currentBatch->drawCounter >= RL_DEFAULT_BATCH_DRAWCALLS) rlDrawRenderBatch(RLGL.currentBatch);
1671
1672 RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].textureId = id;
1673 RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount = 0;
1674 }
1675#endif
1676 }
1677}
1678
1679// Select and active a texture slot
1680void rlActiveTextureSlot(int slot)
1681{
1682#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
1683 glActiveTexture(GL_TEXTURE0 + slot);
1684#endif
1685}
1686
1687// Enable texture
1688void rlEnableTexture(unsigned int id)
1689{
1690#if defined(GRAPHICS_API_OPENGL_11)
1691 glEnable(GL_TEXTURE_2D);
1692#endif
1693 glBindTexture(GL_TEXTURE_2D, id);
1694}
1695
1696// Disable texture
1697void rlDisableTexture(void)
1698{
1699#if defined(GRAPHICS_API_OPENGL_11)
1700 glDisable(GL_TEXTURE_2D);
1701#endif
1702 glBindTexture(GL_TEXTURE_2D, 0);
1703}
1704
1705// Enable texture cubemap
1706void rlEnableTextureCubemap(unsigned int id)
1707{
1708#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
1709 glBindTexture(GL_TEXTURE_CUBE_MAP, id);
1710#endif
1711}
1712
1713// Disable texture cubemap
1714void rlDisableTextureCubemap(void)
1715{
1716#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
1717 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
1718#endif
1719}
1720
1721// Set texture parameters (wrap mode/filter mode)
1722void rlTextureParameters(unsigned int id, int param, int value)
1723{
1724 glBindTexture(GL_TEXTURE_2D, id);
1725
1726#if !defined(GRAPHICS_API_OPENGL_11)
1727 // Reset anisotropy filter, in case it was set
1728 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
1729#endif
1730
1731 switch (param)
1732 {
1733 case RL_TEXTURE_WRAP_S:
1734 case RL_TEXTURE_WRAP_T:
1735 {
1736 if (value == RL_TEXTURE_WRAP_MIRROR_CLAMP)
1737 {
1738#if !defined(GRAPHICS_API_OPENGL_11)
1739 if (RLGL.ExtSupported.texMirrorClamp) glTexParameteri(GL_TEXTURE_2D, param, value);
1740 else TRACELOG(RL_LOG_WARNING, "GL: Clamp mirror wrap mode not supported (GL_MIRROR_CLAMP_EXT)");
1741#endif
1742 }
1743 else glTexParameteri(GL_TEXTURE_2D, param, value);
1744
1745 } break;
1746 case RL_TEXTURE_MAG_FILTER:
1747 case RL_TEXTURE_MIN_FILTER: glTexParameteri(GL_TEXTURE_2D, param, value); break;
1748 case RL_TEXTURE_FILTER_ANISOTROPIC:
1749 {
1750#if !defined(GRAPHICS_API_OPENGL_11)
1751 if (value <= RLGL.ExtSupported.maxAnisotropyLevel) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value);
1752 else if (RLGL.ExtSupported.maxAnisotropyLevel > 0.0f)
1753 {
1754 TRACELOG(RL_LOG_WARNING, "GL: Maximum anisotropic filter level supported is %iX", id, (int)RLGL.ExtSupported.maxAnisotropyLevel);
1755 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value);
1756 }
1757 else TRACELOG(RL_LOG_WARNING, "GL: Anisotropic filtering not supported");
1758#endif
1759 } break;
1760#if defined(GRAPHICS_API_OPENGL_33)
1761 case RL_TEXTURE_MIPMAP_BIAS_RATIO: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, value/100.0f);
1762#endif
1763 default: break;
1764 }
1765
1766 glBindTexture(GL_TEXTURE_2D, 0);
1767}
1768
1769// Set cubemap parameters (wrap mode/filter mode)
1770void rlCubemapParameters(unsigned int id, int param, int value)
1771{
1772#if !defined(GRAPHICS_API_OPENGL_11)
1773 glBindTexture(GL_TEXTURE_CUBE_MAP, id);
1774
1775 // Reset anisotropy filter, in case it was set
1776 glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
1777
1778 switch (param)
1779 {
1780 case RL_TEXTURE_WRAP_S:
1781 case RL_TEXTURE_WRAP_T:
1782 {
1783 if (value == RL_TEXTURE_WRAP_MIRROR_CLAMP)
1784 {
1785 if (RLGL.ExtSupported.texMirrorClamp) glTexParameteri(GL_TEXTURE_CUBE_MAP, param, value);
1786 else TRACELOG(RL_LOG_WARNING, "GL: Clamp mirror wrap mode not supported (GL_MIRROR_CLAMP_EXT)");
1787 }
1788 else glTexParameteri(GL_TEXTURE_CUBE_MAP, param, value);
1789
1790 } break;
1791 case RL_TEXTURE_MAG_FILTER:
1792 case RL_TEXTURE_MIN_FILTER: glTexParameteri(GL_TEXTURE_CUBE_MAP, param, value); break;
1793 case RL_TEXTURE_FILTER_ANISOTROPIC:
1794 {
1795 if (value <= RLGL.ExtSupported.maxAnisotropyLevel) glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value);
1796 else if (RLGL.ExtSupported.maxAnisotropyLevel > 0.0f)
1797 {
1798 TRACELOG(RL_LOG_WARNING, "GL: Maximum anisotropic filter level supported is %iX", id, (int)RLGL.ExtSupported.maxAnisotropyLevel);
1799 glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value);
1800 }
1801 else TRACELOG(RL_LOG_WARNING, "GL: Anisotropic filtering not supported");
1802 } break;
1803#if defined(GRAPHICS_API_OPENGL_33)
1804 case RL_TEXTURE_MIPMAP_BIAS_RATIO: glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_LOD_BIAS, value/100.0f);
1805#endif
1806 default: break;
1807 }
1808
1809 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
1810#endif
1811}
1812
1813// Enable shader program
1814void rlEnableShader(unsigned int id)
1815{
1816#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2))
1817 glUseProgram(id);
1818#endif
1819}
1820
1821// Disable shader program
1822void rlDisableShader(void)
1823{
1824#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2))
1825 glUseProgram(0);
1826#endif
1827}
1828
1829// Enable rendering to texture (fbo)
1830void rlEnableFramebuffer(unsigned int id)
1831{
1832#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(RLGL_RENDER_TEXTURES_HINT)
1833 glBindFramebuffer(GL_FRAMEBUFFER, id);
1834#endif
1835}
1836
1837// return the active render texture (fbo)
1838unsigned int rlGetActiveFramebuffer(void)
1839{
1840 GLint fboId = 0;
1841#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES3)) && defined(RLGL_RENDER_TEXTURES_HINT)
1842 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &fboId);
1843#endif
1844 return fboId;
1845}
1846
1847// Disable rendering to texture
1848void rlDisableFramebuffer(void)
1849{
1850#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(RLGL_RENDER_TEXTURES_HINT)
1851 glBindFramebuffer(GL_FRAMEBUFFER, 0);
1852#endif
1853}
1854
1855// Blit active framebuffer to main framebuffer
1856void rlBlitFramebuffer(int srcX, int srcY, int srcWidth, int srcHeight, int dstX, int dstY, int dstWidth, int dstHeight, int bufferMask)
1857{
1858#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES3)) && defined(RLGL_RENDER_TEXTURES_HINT)
1859 glBlitFramebuffer(srcX, srcY, srcWidth, srcHeight, dstX, dstY, dstWidth, dstHeight, bufferMask, GL_NEAREST);
1860#endif
1861}
1862
1863// Bind framebuffer object (fbo)
1864void rlBindFramebuffer(unsigned int target, unsigned int framebuffer)
1865{
1866#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(RLGL_RENDER_TEXTURES_HINT)
1867 glBindFramebuffer(target, framebuffer);
1868#endif
1869}
1870
1871// Activate multiple draw color buffers
1872// NOTE: One color buffer is always active by default
1873void rlActiveDrawBuffers(int count)
1874{
1875#if ((defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES3)) && defined(RLGL_RENDER_TEXTURES_HINT))
1876 // NOTE: Maximum number of draw buffers supported is implementation dependant,
1877 // it can be queried with glGet*() but it must be at least 8
1878 //GLint maxDrawBuffers = 0;
1879 //glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
1880
1881 if (count > 0)
1882 {
1883 if (count > 8) TRACELOG(LOG_WARNING, "GL: Max color buffers limited to 8");
1884 else
1885 {
1886 unsigned int buffers[8] = {
1887#if defined(GRAPHICS_API_OPENGL_ES3)
1888 GL_COLOR_ATTACHMENT0_EXT,
1889 GL_COLOR_ATTACHMENT1_EXT,
1890 GL_COLOR_ATTACHMENT2_EXT,
1891 GL_COLOR_ATTACHMENT3_EXT,
1892 GL_COLOR_ATTACHMENT4_EXT,
1893 GL_COLOR_ATTACHMENT5_EXT,
1894 GL_COLOR_ATTACHMENT6_EXT,
1895 GL_COLOR_ATTACHMENT7_EXT,
1896#else
1897 GL_COLOR_ATTACHMENT0,
1898 GL_COLOR_ATTACHMENT1,
1899 GL_COLOR_ATTACHMENT2,
1900 GL_COLOR_ATTACHMENT3,
1901 GL_COLOR_ATTACHMENT4,
1902 GL_COLOR_ATTACHMENT5,
1903 GL_COLOR_ATTACHMENT6,
1904 GL_COLOR_ATTACHMENT7,
1905#endif
1906 };
1907
1908#if defined(GRAPHICS_API_OPENGL_ES3)
1909 glDrawBuffersEXT(count, buffers);
1910#else
1911 glDrawBuffers(count, buffers);
1912#endif
1913 }
1914 }
1915 else TRACELOG(LOG_WARNING, "GL: One color buffer active by default");
1916#endif
1917}
1918
1919//----------------------------------------------------------------------------------
1920// General render state configuration
1921//----------------------------------------------------------------------------------
1922
1923// Enable color blending
1924void rlEnableColorBlend(void) { glEnable(GL_BLEND); }
1925
1926// Disable color blending
1927void rlDisableColorBlend(void) { glDisable(GL_BLEND); }
1928
1929// Enable depth test
1930void rlEnableDepthTest(void) { glEnable(GL_DEPTH_TEST); }
1931
1932// Disable depth test
1933void rlDisableDepthTest(void) { glDisable(GL_DEPTH_TEST); }
1934
1935// Enable depth write
1936void rlEnableDepthMask(void) { glDepthMask(GL_TRUE); }
1937
1938// Disable depth write
1939void rlDisableDepthMask(void) { glDepthMask(GL_FALSE); }
1940
1941// Enable backface culling
1942void rlEnableBackfaceCulling(void) { glEnable(GL_CULL_FACE); }
1943
1944// Disable backface culling
1945void rlDisableBackfaceCulling(void) { glDisable(GL_CULL_FACE); }
1946
1947// Set color mask active for screen read/draw
1948void rlColorMask(bool r, bool g, bool b, bool a) { glColorMask(r, g, b, a); }
1949
1950// Set face culling mode
1951void rlSetCullFace(int mode)
1952{
1953 switch (mode)
1954 {
1955 case RL_CULL_FACE_BACK: glCullFace(GL_BACK); break;
1956 case RL_CULL_FACE_FRONT: glCullFace(GL_FRONT); break;
1957 default: break;
1958 }
1959}
1960
1961// Enable scissor test
1962void rlEnableScissorTest(void) { glEnable(GL_SCISSOR_TEST); }
1963
1964// Disable scissor test
1965void rlDisableScissorTest(void) { glDisable(GL_SCISSOR_TEST); }
1966
1967// Scissor test
1968void rlScissor(int x, int y, int width, int height) { glScissor(x, y, width, height); }
1969
1970// Enable wire mode
1971void rlEnableWireMode(void)
1972{
1973#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
1974 // NOTE: glPolygonMode() not available on OpenGL ES
1975 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1976#endif
1977}
1978
1979// Enable point mode
1980void rlEnablePointMode(void)
1981{
1982#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
1983 // NOTE: glPolygonMode() not available on OpenGL ES
1984 glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
1985 glEnable(GL_PROGRAM_POINT_SIZE);
1986#endif
1987}
1988
1989// Disable wire mode
1990void rlDisableWireMode(void)
1991{
1992#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
1993 // NOTE: glPolygonMode() not available on OpenGL ES
1994 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1995#endif
1996}
1997
1998// Set the line drawing width
1999void rlSetLineWidth(float width) { glLineWidth(width); }
2000
2001// Get the line drawing width
2002float rlGetLineWidth(void)
2003{
2004 float width = 0;
2005 glGetFloatv(GL_LINE_WIDTH, &width);
2006 return width;
2007}
2008
2009// Enable line aliasing
2010void rlEnableSmoothLines(void)
2011{
2012#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_11)
2013 glEnable(GL_LINE_SMOOTH);
2014#endif
2015}
2016
2017// Disable line aliasing
2018void rlDisableSmoothLines(void)
2019{
2020#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_11)
2021 glDisable(GL_LINE_SMOOTH);
2022#endif
2023}
2024
2025// Enable stereo rendering
2026void rlEnableStereoRender(void)
2027{
2028#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2))
2029 RLGL.State.stereoRender = true;
2030#endif
2031}
2032
2033// Disable stereo rendering
2034void rlDisableStereoRender(void)
2035{
2036#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2))
2037 RLGL.State.stereoRender = false;
2038#endif
2039}
2040
2041// Check if stereo render is enabled
2042bool rlIsStereoRenderEnabled(void)
2043{
2044#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2))
2045 return RLGL.State.stereoRender;
2046#else
2047 return false;
2048#endif
2049}
2050
2051// Clear color buffer with color
2052void rlClearColor(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
2053{
2054 // Color values clamp to 0.0f(0) and 1.0f(255)
2055 float cr = (float)r/255;
2056 float cg = (float)g/255;
2057 float cb = (float)b/255;
2058 float ca = (float)a/255;
2059
2060 glClearColor(cr, cg, cb, ca);
2061}
2062
2063// Clear used screen buffers (color and depth)
2064void rlClearScreenBuffers(void)
2065{
2066 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear used buffers: Color and Depth (Depth is used for 3D)
2067 //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // Stencil buffer not used...
2068}
2069
2070// Check and log OpenGL error codes
2071void rlCheckErrors(void)
2072{
2073#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
2074 int check = 1;
2075 while (check)
2076 {
2077 const GLenum err = glGetError();
2078 switch (err)
2079 {
2080 case GL_NO_ERROR: check = 0; break;
2081 case 0x0500: TRACELOG(RL_LOG_WARNING, "GL: Error detected: GL_INVALID_ENUM"); break;
2082 case 0x0501: TRACELOG(RL_LOG_WARNING, "GL: Error detected: GL_INVALID_VALUE"); break;
2083 case 0x0502: TRACELOG(RL_LOG_WARNING, "GL: Error detected: GL_INVALID_OPERATION"); break;
2084 case 0x0503: TRACELOG(RL_LOG_WARNING, "GL: Error detected: GL_STACK_OVERFLOW"); break;
2085 case 0x0504: TRACELOG(RL_LOG_WARNING, "GL: Error detected: GL_STACK_UNDERFLOW"); break;
2086 case 0x0505: TRACELOG(RL_LOG_WARNING, "GL: Error detected: GL_OUT_OF_MEMORY"); break;
2087 case 0x0506: TRACELOG(RL_LOG_WARNING, "GL: Error detected: GL_INVALID_FRAMEBUFFER_OPERATION"); break;
2088 default: TRACELOG(RL_LOG_WARNING, "GL: Error detected: Unknown error code: %x", err); break;
2089 }
2090 }
2091#endif
2092}
2093
2094// Set blend mode
2095void rlSetBlendMode(int mode)
2096{
2097#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
2098 if ((RLGL.State.currentBlendMode != mode) || ((mode == RL_BLEND_CUSTOM || mode == RL_BLEND_CUSTOM_SEPARATE) && RLGL.State.glCustomBlendModeModified))
2099 {
2100 rlDrawRenderBatch(RLGL.currentBatch);
2101
2102 switch (mode)
2103 {
2104 case RL_BLEND_ALPHA: glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendEquation(GL_FUNC_ADD); break;
2105 case RL_BLEND_ADDITIVE: glBlendFunc(GL_SRC_ALPHA, GL_ONE); glBlendEquation(GL_FUNC_ADD); break;
2106 case RL_BLEND_MULTIPLIED: glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); glBlendEquation(GL_FUNC_ADD); break;
2107 case RL_BLEND_ADD_COLORS: glBlendFunc(GL_ONE, GL_ONE); glBlendEquation(GL_FUNC_ADD); break;
2108 case RL_BLEND_SUBTRACT_COLORS: glBlendFunc(GL_ONE, GL_ONE); glBlendEquation(GL_FUNC_SUBTRACT); break;
2109 case RL_BLEND_ALPHA_PREMULTIPLY: glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glBlendEquation(GL_FUNC_ADD); break;
2110 case RL_BLEND_CUSTOM:
2111 {
2112 // NOTE: Using GL blend src/dst factors and GL equation configured with rlSetBlendFactors()
2113 glBlendFunc(RLGL.State.glBlendSrcFactor, RLGL.State.glBlendDstFactor); glBlendEquation(RLGL.State.glBlendEquation);
2114
2115 } break;
2116 case RL_BLEND_CUSTOM_SEPARATE:
2117 {
2118 // NOTE: Using GL blend src/dst factors and GL equation configured with rlSetBlendFactorsSeparate()
2119 glBlendFuncSeparate(RLGL.State.glBlendSrcFactorRGB, RLGL.State.glBlendDestFactorRGB, RLGL.State.glBlendSrcFactorAlpha, RLGL.State.glBlendDestFactorAlpha);
2120 glBlendEquationSeparate(RLGL.State.glBlendEquationRGB, RLGL.State.glBlendEquationAlpha);
2121
2122 } break;
2123 default: break;
2124 }
2125
2126 RLGL.State.currentBlendMode = mode;
2127 RLGL.State.glCustomBlendModeModified = false;
2128 }
2129#endif
2130}
2131
2132// Set blending mode factor and equation
2133void rlSetBlendFactors(int glSrcFactor, int glDstFactor, int glEquation)
2134{
2135#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
2136 if ((RLGL.State.glBlendSrcFactor != glSrcFactor) ||
2137 (RLGL.State.glBlendDstFactor != glDstFactor) ||
2138 (RLGL.State.glBlendEquation != glEquation))
2139 {
2140 RLGL.State.glBlendSrcFactor = glSrcFactor;
2141 RLGL.State.glBlendDstFactor = glDstFactor;
2142 RLGL.State.glBlendEquation = glEquation;
2143
2144 RLGL.State.glCustomBlendModeModified = true;
2145 }
2146#endif
2147}
2148
2149// Set blending mode factor and equation separately for RGB and alpha
2150void rlSetBlendFactorsSeparate(int glSrcRGB, int glDstRGB, int glSrcAlpha, int glDstAlpha, int glEqRGB, int glEqAlpha)
2151{
2152#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
2153 if ((RLGL.State.glBlendSrcFactorRGB != glSrcRGB) ||
2154 (RLGL.State.glBlendDestFactorRGB != glDstRGB) ||
2155 (RLGL.State.glBlendSrcFactorAlpha != glSrcAlpha) ||
2156 (RLGL.State.glBlendDestFactorAlpha != glDstAlpha) ||
2157 (RLGL.State.glBlendEquationRGB != glEqRGB) ||
2158 (RLGL.State.glBlendEquationAlpha != glEqAlpha))
2159 {
2160 RLGL.State.glBlendSrcFactorRGB = glSrcRGB;
2161 RLGL.State.glBlendDestFactorRGB = glDstRGB;
2162 RLGL.State.glBlendSrcFactorAlpha = glSrcAlpha;
2163 RLGL.State.glBlendDestFactorAlpha = glDstAlpha;
2164 RLGL.State.glBlendEquationRGB = glEqRGB;
2165 RLGL.State.glBlendEquationAlpha = glEqAlpha;
2166
2167 RLGL.State.glCustomBlendModeModified = true;
2168 }
2169#endif
2170}
2171
2172//----------------------------------------------------------------------------------
2173// Module Functions Definition - OpenGL Debug
2174//----------------------------------------------------------------------------------
2175#if defined(RLGL_ENABLE_OPENGL_DEBUG_CONTEXT) && defined(GRAPHICS_API_OPENGL_43)
2176static void GLAPIENTRY rlDebugMessageCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam)
2177{
2178 // Ignore non-significant error/warning codes (NVidia drivers)
2179 // NOTE: Here there are the details with a sample output:
2180 // - #131169 - Framebuffer detailed info: The driver allocated storage for renderbuffer 2. (severity: low)
2181 // - #131185 - Buffer detailed info: Buffer object 1 (bound to GL_ELEMENT_ARRAY_BUFFER_ARB, usage hint is GL_ENUM_88e4)
2182 // will use VIDEO memory as the source for buffer object operations. (severity: low)
2183 // - #131218 - Program/shader state performance warning: Vertex shader in program 7 is being recompiled based on GL state. (severity: medium)
2184 // - #131204 - Texture state usage warning: The texture object (0) bound to texture image unit 0 does not have
2185 // a defined base level and cannot be used for texture mapping. (severity: low)
2186 if ((id == 131169) || (id == 131185) || (id == 131218) || (id == 131204)) return;
2187
2188 const char *msgSource = NULL;
2189 switch (source)
2190 {
2191 case GL_DEBUG_SOURCE_API: msgSource = "API"; break;
2192 case GL_DEBUG_SOURCE_WINDOW_SYSTEM: msgSource = "WINDOW_SYSTEM"; break;
2193 case GL_DEBUG_SOURCE_SHADER_COMPILER: msgSource = "SHADER_COMPILER"; break;
2194 case GL_DEBUG_SOURCE_THIRD_PARTY: msgSource = "THIRD_PARTY"; break;
2195 case GL_DEBUG_SOURCE_APPLICATION: msgSource = "APPLICATION"; break;
2196 case GL_DEBUG_SOURCE_OTHER: msgSource = "OTHER"; break;
2197 default: break;
2198 }
2199
2200 const char *msgType = NULL;
2201 switch (type)
2202 {
2203 case GL_DEBUG_TYPE_ERROR: msgType = "ERROR"; break;
2204 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: msgType = "DEPRECATED_BEHAVIOR"; break;
2205 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: msgType = "UNDEFINED_BEHAVIOR"; break;
2206 case GL_DEBUG_TYPE_PORTABILITY: msgType = "PORTABILITY"; break;
2207 case GL_DEBUG_TYPE_PERFORMANCE: msgType = "PERFORMANCE"; break;
2208 case GL_DEBUG_TYPE_MARKER: msgType = "MARKER"; break;
2209 case GL_DEBUG_TYPE_PUSH_GROUP: msgType = "PUSH_GROUP"; break;
2210 case GL_DEBUG_TYPE_POP_GROUP: msgType = "POP_GROUP"; break;
2211 case GL_DEBUG_TYPE_OTHER: msgType = "OTHER"; break;
2212 default: break;
2213 }
2214
2215 const char *msgSeverity = "DEFAULT";
2216 switch (severity)
2217 {
2218 case GL_DEBUG_SEVERITY_LOW: msgSeverity = "LOW"; break;
2219 case GL_DEBUG_SEVERITY_MEDIUM: msgSeverity = "MEDIUM"; break;
2220 case GL_DEBUG_SEVERITY_HIGH: msgSeverity = "HIGH"; break;
2221 case GL_DEBUG_SEVERITY_NOTIFICATION: msgSeverity = "NOTIFICATION"; break;
2222 default: break;
2223 }
2224
2225 TRACELOG(LOG_WARNING, "GL: OpenGL debug message: %s", message);
2226 TRACELOG(LOG_WARNING, " > Type: %s", msgType);
2227 TRACELOG(LOG_WARNING, " > Source = %s", msgSource);
2228 TRACELOG(LOG_WARNING, " > Severity = %s", msgSeverity);
2229}
2230#endif
2231
2232//----------------------------------------------------------------------------------
2233// Module Functions Definition - rlgl functionality
2234//----------------------------------------------------------------------------------
2235
2236// Initialize rlgl: OpenGL extensions, default buffers/shaders/textures, OpenGL states
2237void rlglInit(int width, int height)
2238{
2239 // Enable OpenGL debug context if required
2240#if defined(RLGL_ENABLE_OPENGL_DEBUG_CONTEXT) && defined(GRAPHICS_API_OPENGL_43)
2241 if ((glDebugMessageCallback != NULL) && (glDebugMessageControl != NULL))
2242 {
2243 glDebugMessageCallback(rlDebugMessageCallback, 0);
2244 // glDebugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DEBUG_SEVERITY_HIGH, 0, 0, GL_TRUE);
2245
2246 // Debug context options:
2247 // - GL_DEBUG_OUTPUT - Faster version but not useful for breakpoints
2248 // - GL_DEBUG_OUTPUT_SYNCHRONUS - Callback is in sync with errors, so a breakpoint can be placed on the callback in order to get a stacktrace for the GL error
2249 glEnable(GL_DEBUG_OUTPUT);
2250 glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
2251 }
2252#endif
2253
2254#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
2255 // Init default white texture
2256 unsigned char pixels[4] = { 255, 255, 255, 255 }; // 1 pixel RGBA (4 bytes)
2257 RLGL.State.defaultTextureId = rlLoadTexture(pixels, 1, 1, RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, 1);
2258
2259 if (RLGL.State.defaultTextureId != 0) TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Default texture loaded successfully", RLGL.State.defaultTextureId);
2260 else TRACELOG(RL_LOG_WARNING, "TEXTURE: Failed to load default texture");
2261
2262 // Init default Shader (customized for GL 3.3 and ES2)
2263 // Loaded: RLGL.State.defaultShaderId + RLGL.State.defaultShaderLocs
2264 rlLoadShaderDefault();
2265 RLGL.State.currentShaderId = RLGL.State.defaultShaderId;
2266 RLGL.State.currentShaderLocs = RLGL.State.defaultShaderLocs;
2267
2268 // Init default vertex arrays buffers
2269 // Simulate that the default shader has the location RL_SHADER_LOC_VERTEX_NORMAL to bind the normal buffer for the default render batch
2270 RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_NORMAL] = RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL;
2271 RLGL.defaultBatch = rlLoadRenderBatch(RL_DEFAULT_BATCH_BUFFERS, RL_DEFAULT_BATCH_BUFFER_ELEMENTS);
2272 RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_NORMAL] = -1;
2273 RLGL.currentBatch = &RLGL.defaultBatch;
2274
2275 // Init stack matrices (emulating OpenGL 1.1)
2276 for (int i = 0; i < RL_MAX_MATRIX_STACK_SIZE; i++) RLGL.State.stack[i] = rlMatrixIdentity();
2277
2278 // Init internal matrices
2279 RLGL.State.transform = rlMatrixIdentity();
2280 RLGL.State.projection = rlMatrixIdentity();
2281 RLGL.State.modelview = rlMatrixIdentity();
2282 RLGL.State.currentMatrix = &RLGL.State.modelview;
2283#endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
2284
2285 // Initialize OpenGL default states
2286 //----------------------------------------------------------
2287 // Init state: Depth test
2288 glDepthFunc(GL_LEQUAL); // Type of depth testing to apply
2289 glDisable(GL_DEPTH_TEST); // Disable depth testing for 2D (only used for 3D)
2290
2291 // Init state: Blending mode
2292 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Color blending function (how colors are mixed)
2293 glEnable(GL_BLEND); // Enable color blending (required to work with transparencies)
2294
2295 // Init state: Culling
2296 // NOTE: All shapes/models triangles are drawn CCW
2297 glCullFace(GL_BACK); // Cull the back face (default)
2298 glFrontFace(GL_CCW); // Front face are defined counter clockwise (default)
2299 glEnable(GL_CULL_FACE); // Enable backface culling
2300
2301 // Init state: Cubemap seamless
2302#if defined(GRAPHICS_API_OPENGL_33)
2303 glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); // Seamless cubemaps (not supported on OpenGL ES 2.0)
2304#endif
2305
2306#if defined(GRAPHICS_API_OPENGL_11)
2307 // Init state: Color hints (deprecated in OpenGL 3.0+)
2308 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Improve quality of color and texture coordinate interpolation
2309 glShadeModel(GL_SMOOTH); // Smooth shading between vertex (vertex colors interpolation)
2310#endif
2311
2312#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
2313 // Store screen size into global variables
2314 RLGL.State.framebufferWidth = width;
2315 RLGL.State.framebufferHeight = height;
2316
2317 TRACELOG(RL_LOG_INFO, "RLGL: Default OpenGL state initialized successfully");
2318 //----------------------------------------------------------
2319#endif
2320
2321 // Init state: Color/Depth buffers clear
2322 glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set clear color (black)
2323 glClearDepth(1.0f); // Set clear depth value (default)
2324 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear color and depth buffers (depth buffer required for 3D)
2325}
2326
2327// Vertex Buffer Object deinitialization (memory free)
2328void rlglClose(void)
2329{
2330#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
2331 rlUnloadRenderBatch(RLGL.defaultBatch);
2332
2333 rlUnloadShaderDefault(); // Unload default shader
2334
2335 glDeleteTextures(1, &RLGL.State.defaultTextureId); // Unload default texture
2336 TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Default texture unloaded successfully", RLGL.State.defaultTextureId);
2337#endif
2338}
2339
2340// Load OpenGL extensions
2341// NOTE: External loader function must be provided
2342void rlLoadExtensions(void *loader)
2343{
2344#if defined(GRAPHICS_API_OPENGL_33) // Also defined for GRAPHICS_API_OPENGL_21
2345 // NOTE: glad is generated and contains only required OpenGL 3.3 Core extensions (and lower versions)
2346 if (gladLoadGL((GLADloadfunc)loader) == 0) TRACELOG(RL_LOG_WARNING, "GLAD: Cannot load OpenGL extensions");
2347 else TRACELOG(RL_LOG_INFO, "GLAD: OpenGL extensions loaded successfully");
2348
2349 // Get number of supported extensions
2350 GLint numExt = 0;
2351 glGetIntegerv(GL_NUM_EXTENSIONS, &numExt);
2352 TRACELOG(RL_LOG_INFO, "GL: Supported extensions count: %i", numExt);
2353
2354#if defined(RLGL_SHOW_GL_DETAILS_INFO)
2355 // Get supported extensions list
2356 // WARNING: glGetStringi() not available on OpenGL 2.1
2357 TRACELOG(RL_LOG_INFO, "GL: OpenGL extensions:");
2358 for (int i = 0; i < numExt; i++) TRACELOG(RL_LOG_INFO, " %s", glGetStringi(GL_EXTENSIONS, i));
2359#endif
2360
2361#if defined(GRAPHICS_API_OPENGL_21)
2362 // Register supported extensions flags
2363 // Optional OpenGL 2.1 extensions
2364 RLGL.ExtSupported.vao = GLAD_GL_ARB_vertex_array_object;
2365 RLGL.ExtSupported.instancing = (GLAD_GL_EXT_draw_instanced && GLAD_GL_ARB_instanced_arrays);
2366 RLGL.ExtSupported.texNPOT = GLAD_GL_ARB_texture_non_power_of_two;
2367 RLGL.ExtSupported.texFloat32 = GLAD_GL_ARB_texture_float;
2368 RLGL.ExtSupported.texFloat16 = GLAD_GL_ARB_texture_float;
2369 RLGL.ExtSupported.texDepth = GLAD_GL_ARB_depth_texture;
2370 RLGL.ExtSupported.maxDepthBits = 32;
2371 RLGL.ExtSupported.texAnisoFilter = GLAD_GL_EXT_texture_filter_anisotropic;
2372 RLGL.ExtSupported.texMirrorClamp = GLAD_GL_EXT_texture_mirror_clamp;
2373#else
2374 // Register supported extensions flags
2375 // OpenGL 3.3 extensions supported by default (core)
2376 RLGL.ExtSupported.vao = true;
2377 RLGL.ExtSupported.instancing = true;
2378 RLGL.ExtSupported.texNPOT = true;
2379 RLGL.ExtSupported.texFloat32 = true;
2380 RLGL.ExtSupported.texFloat16 = true;
2381 RLGL.ExtSupported.texDepth = true;
2382 RLGL.ExtSupported.maxDepthBits = 32;
2383 RLGL.ExtSupported.texAnisoFilter = true;
2384 RLGL.ExtSupported.texMirrorClamp = true;
2385#endif
2386
2387 // Optional OpenGL 3.3 extensions
2388 RLGL.ExtSupported.texCompASTC = GLAD_GL_KHR_texture_compression_astc_hdr && GLAD_GL_KHR_texture_compression_astc_ldr;
2389 RLGL.ExtSupported.texCompDXT = GLAD_GL_EXT_texture_compression_s3tc; // Texture compression: DXT
2390 RLGL.ExtSupported.texCompETC2 = GLAD_GL_ARB_ES3_compatibility; // Texture compression: ETC2/EAC
2391 #if defined(GRAPHICS_API_OPENGL_43)
2392 RLGL.ExtSupported.computeShader = GLAD_GL_ARB_compute_shader;
2393 RLGL.ExtSupported.ssbo = GLAD_GL_ARB_shader_storage_buffer_object;
2394 #endif
2395
2396#endif // GRAPHICS_API_OPENGL_33
2397
2398#if defined(GRAPHICS_API_OPENGL_ES3)
2399 // Register supported extensions flags
2400 // OpenGL ES 3.0 extensions supported by default (or it should be)
2401 RLGL.ExtSupported.vao = true;
2402 RLGL.ExtSupported.instancing = true;
2403 RLGL.ExtSupported.texNPOT = true;
2404 RLGL.ExtSupported.texFloat32 = true;
2405 RLGL.ExtSupported.texFloat16 = true;
2406 RLGL.ExtSupported.texDepth = true;
2407 RLGL.ExtSupported.texDepthWebGL = true;
2408 RLGL.ExtSupported.maxDepthBits = 24;
2409 RLGL.ExtSupported.texAnisoFilter = true;
2410 RLGL.ExtSupported.texMirrorClamp = true;
2411 // TODO: Check for additional OpenGL ES 3.0 supported extensions:
2412 //RLGL.ExtSupported.texCompDXT = true;
2413 //RLGL.ExtSupported.texCompETC1 = true;
2414 //RLGL.ExtSupported.texCompETC2 = true;
2415 //RLGL.ExtSupported.texCompPVRT = true;
2416 //RLGL.ExtSupported.texCompASTC = true;
2417 //RLGL.ExtSupported.maxAnisotropyLevel = true;
2418 //RLGL.ExtSupported.computeShader = true;
2419 //RLGL.ExtSupported.ssbo = true;
2420
2421#elif defined(GRAPHICS_API_OPENGL_ES2)
2422
2423 #if defined(PLATFORM_DESKTOP_GLFW) || defined(PLATFORM_DESKTOP_SDL)
2424 // TODO: Support GLAD loader for OpenGL ES 3.0
2425 if (gladLoadGLES2((GLADloadfunc)loader) == 0) TRACELOG(RL_LOG_WARNING, "GLAD: Cannot load OpenGL ES2.0 functions");
2426 else TRACELOG(RL_LOG_INFO, "GLAD: OpenGL ES 2.0 loaded successfully");
2427 #endif
2428
2429 // Get supported extensions list
2430 GLint numExt = 0;
2431 const char **extList = RL_MALLOC(512*sizeof(const char *)); // Allocate 512 strings pointers (2 KB)
2432 const char *extensions = (const char *)glGetString(GL_EXTENSIONS); // One big const string
2433
2434 // NOTE: We have to duplicate string because glGetString() returns a const string
2435 int size = strlen(extensions) + 1; // Get extensions string size in bytes
2436 char *extensionsDup = (char *)RL_CALLOC(size, sizeof(char));
2437 strcpy(extensionsDup, extensions);
2438 extList[numExt] = extensionsDup;
2439
2440 for (int i = 0; i < size; i++)
2441 {
2442 if (extensionsDup[i] == ' ')
2443 {
2444 extensionsDup[i] = '\0';
2445 numExt++;
2446 extList[numExt] = &extensionsDup[i + 1];
2447 }
2448 }
2449
2450 TRACELOG(RL_LOG_INFO, "GL: Supported extensions count: %i", numExt);
2451
2452#if defined(RLGL_SHOW_GL_DETAILS_INFO)
2453 TRACELOG(RL_LOG_INFO, "GL: OpenGL extensions:");
2454 for (int i = 0; i < numExt; i++) TRACELOG(RL_LOG_INFO, " %s", extList[i]);
2455#endif
2456
2457 // Check required extensions
2458 for (int i = 0; i < numExt; i++)
2459 {
2460 // Check VAO support
2461 // NOTE: Only check on OpenGL ES, OpenGL 3.3 has VAO support as core feature
2462 if (strcmp(extList[i], (const char *)"GL_OES_vertex_array_object") == 0)
2463 {
2464 // The extension is supported by our hardware and driver, try to get related functions pointers
2465 // NOTE: emscripten does not support VAOs natively, it uses emulation and it reduces overall performance...
2466 glGenVertexArrays = (PFNGLGENVERTEXARRAYSOESPROC)((rlglLoadProc)loader)("glGenVertexArraysOES");
2467 glBindVertexArray = (PFNGLBINDVERTEXARRAYOESPROC)((rlglLoadProc)loader)("glBindVertexArrayOES");
2468 glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSOESPROC)((rlglLoadProc)loader)("glDeleteVertexArraysOES");
2469 //glIsVertexArray = (PFNGLISVERTEXARRAYOESPROC)loader("glIsVertexArrayOES"); // NOTE: Fails in WebGL, omitted
2470
2471 if ((glGenVertexArrays != NULL) && (glBindVertexArray != NULL) && (glDeleteVertexArrays != NULL)) RLGL.ExtSupported.vao = true;
2472 }
2473
2474 // Check instanced rendering support
2475 if (strstr(extList[i], (const char*)"instanced_arrays") != NULL) // Broad check for instanced_arrays
2476 {
2477 // Specific check
2478 if (strcmp(extList[i], (const char *)"GL_ANGLE_instanced_arrays") == 0) // ANGLE
2479 {
2480 glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedANGLE");
2481 glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedANGLE");
2482 glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorANGLE");
2483 }
2484 else if (strcmp(extList[i], (const char *)"GL_EXT_instanced_arrays") == 0) // EXT
2485 {
2486 glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedEXT");
2487 glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedEXT");
2488 glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorEXT");
2489 }
2490 else if (strcmp(extList[i], (const char *)"GL_NV_instanced_arrays") == 0) // NVIDIA GLES
2491 {
2492 glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedNV");
2493 glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedNV");
2494 glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorNV");
2495 }
2496
2497 // The feature will only be marked as supported if the elements from GL_XXX_instanced_arrays are present
2498 if ((glDrawArraysInstanced != NULL) && (glDrawElementsInstanced != NULL) && (glVertexAttribDivisor != NULL)) RLGL.ExtSupported.instancing = true;
2499 }
2500 else if (strstr(extList[i], (const char *)"draw_instanced") != NULL)
2501 {
2502 // GL_ANGLE_draw_instanced doesn't exist
2503 if (strcmp(extList[i], (const char *)"GL_EXT_draw_instanced") == 0)
2504 {
2505 glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedEXT");
2506 glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedEXT");
2507 }
2508 else if (strcmp(extList[i], (const char*)"GL_NV_draw_instanced") == 0)
2509 {
2510 glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedNV");
2511 glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedNV");
2512 }
2513
2514 // But the functions will at least be loaded if only GL_XX_EXT_draw_instanced exist
2515 if ((glDrawArraysInstanced != NULL) && (glDrawElementsInstanced != NULL) && (glVertexAttribDivisor != NULL)) RLGL.ExtSupported.instancing = true;
2516 }
2517
2518 // Check NPOT textures support
2519 // NOTE: Only check on OpenGL ES, OpenGL 3.3 has NPOT textures full support as core feature
2520 if (strcmp(extList[i], (const char *)"GL_OES_texture_npot") == 0) RLGL.ExtSupported.texNPOT = true;
2521
2522 // Check texture float support
2523 if (strcmp(extList[i], (const char *)"GL_OES_texture_float") == 0) RLGL.ExtSupported.texFloat32 = true;
2524 if (strcmp(extList[i], (const char *)"GL_OES_texture_half_float") == 0) RLGL.ExtSupported.texFloat16 = true;
2525
2526 // Check depth texture support
2527 if (strcmp(extList[i], (const char *)"GL_OES_depth_texture") == 0) RLGL.ExtSupported.texDepth = true;
2528 if (strcmp(extList[i], (const char *)"GL_WEBGL_depth_texture") == 0) RLGL.ExtSupported.texDepthWebGL = true; // WebGL requires unsized internal format
2529 if (RLGL.ExtSupported.texDepthWebGL) RLGL.ExtSupported.texDepth = true;
2530
2531 if (strcmp(extList[i], (const char *)"GL_OES_depth24") == 0) RLGL.ExtSupported.maxDepthBits = 24; // Not available on WebGL
2532 if (strcmp(extList[i], (const char *)"GL_OES_depth32") == 0) RLGL.ExtSupported.maxDepthBits = 32; // Not available on WebGL
2533
2534 // Check texture compression support: DXT
2535 if ((strcmp(extList[i], (const char *)"GL_EXT_texture_compression_s3tc") == 0) ||
2536 (strcmp(extList[i], (const char *)"GL_WEBGL_compressed_texture_s3tc") == 0) ||
2537 (strcmp(extList[i], (const char *)"GL_WEBKIT_WEBGL_compressed_texture_s3tc") == 0)) RLGL.ExtSupported.texCompDXT = true;
2538
2539 // Check texture compression support: ETC1
2540 if ((strcmp(extList[i], (const char *)"GL_OES_compressed_ETC1_RGB8_texture") == 0) ||
2541 (strcmp(extList[i], (const char *)"GL_WEBGL_compressed_texture_etc1") == 0)) RLGL.ExtSupported.texCompETC1 = true;
2542
2543 // Check texture compression support: ETC2/EAC
2544 if (strcmp(extList[i], (const char *)"GL_ARB_ES3_compatibility") == 0) RLGL.ExtSupported.texCompETC2 = true;
2545
2546 // Check texture compression support: PVR
2547 if (strcmp(extList[i], (const char *)"GL_IMG_texture_compression_pvrtc") == 0) RLGL.ExtSupported.texCompPVRT = true;
2548
2549 // Check texture compression support: ASTC
2550 if (strcmp(extList[i], (const char *)"GL_KHR_texture_compression_astc_hdr") == 0) RLGL.ExtSupported.texCompASTC = true;
2551
2552 // Check anisotropic texture filter support
2553 if (strcmp(extList[i], (const char *)"GL_EXT_texture_filter_anisotropic") == 0) RLGL.ExtSupported.texAnisoFilter = true;
2554
2555 // Check clamp mirror wrap mode support
2556 if (strcmp(extList[i], (const char *)"GL_EXT_texture_mirror_clamp") == 0) RLGL.ExtSupported.texMirrorClamp = true;
2557 }
2558
2559 // Free extensions pointers
2560 RL_FREE(extList);
2561 RL_FREE(extensionsDup); // Duplicated string must be deallocated
2562#endif // GRAPHICS_API_OPENGL_ES2
2563
2564 // Check OpenGL information and capabilities
2565 //------------------------------------------------------------------------------
2566 // Show current OpenGL and GLSL version
2567 TRACELOG(RL_LOG_INFO, "GL: OpenGL device information:");
2568 TRACELOG(RL_LOG_INFO, " > Vendor: %s", glGetString(GL_VENDOR));
2569 TRACELOG(RL_LOG_INFO, " > Renderer: %s", glGetString(GL_RENDERER));
2570 TRACELOG(RL_LOG_INFO, " > Version: %s", glGetString(GL_VERSION));
2571 TRACELOG(RL_LOG_INFO, " > GLSL: %s", glGetString(GL_SHADING_LANGUAGE_VERSION));
2572
2573#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
2574 // NOTE: Anisotropy levels capability is an extension
2575 #ifndef GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT
2576 #define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
2577 #endif
2578 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &RLGL.ExtSupported.maxAnisotropyLevel);
2579
2580#if defined(RLGL_SHOW_GL_DETAILS_INFO)
2581 // Show some OpenGL GPU capabilities
2582 TRACELOG(RL_LOG_INFO, "GL: OpenGL capabilities:");
2583 GLint capability = 0;
2584 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &capability);
2585 TRACELOG(RL_LOG_INFO, " GL_MAX_TEXTURE_SIZE: %i", capability);
2586 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &capability);
2587 TRACELOG(RL_LOG_INFO, " GL_MAX_CUBE_MAP_TEXTURE_SIZE: %i", capability);
2588 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &capability);
2589 TRACELOG(RL_LOG_INFO, " GL_MAX_TEXTURE_IMAGE_UNITS: %i", capability);
2590 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &capability);
2591 TRACELOG(RL_LOG_INFO, " GL_MAX_VERTEX_ATTRIBS: %i", capability);
2592 #if !defined(GRAPHICS_API_OPENGL_ES2)
2593 glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &capability);
2594 TRACELOG(RL_LOG_INFO, " GL_MAX_UNIFORM_BLOCK_SIZE: %i", capability);
2595 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &capability);
2596 TRACELOG(RL_LOG_INFO, " GL_MAX_DRAW_BUFFERS: %i", capability);
2597 if (RLGL.ExtSupported.texAnisoFilter) TRACELOG(RL_LOG_INFO, " GL_MAX_TEXTURE_MAX_ANISOTROPY: %.0f", RLGL.ExtSupported.maxAnisotropyLevel);
2598 #endif
2599 glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &capability);
2600 TRACELOG(RL_LOG_INFO, " GL_NUM_COMPRESSED_TEXTURE_FORMATS: %i", capability);
2601 GLint *compFormats = (GLint *)RL_CALLOC(capability, sizeof(GLint));
2602 glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, compFormats);
2603 for (int i = 0; i < capability; i++) TRACELOG(RL_LOG_INFO, " %s", rlGetCompressedFormatName(compFormats[i]));
2604 RL_FREE(compFormats);
2605
2606#if defined(GRAPHICS_API_OPENGL_43)
2607 glGetIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &capability);
2608 TRACELOG(RL_LOG_INFO, " GL_MAX_VERTEX_ATTRIB_BINDINGS: %i", capability);
2609 glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, &capability);
2610 TRACELOG(RL_LOG_INFO, " GL_MAX_UNIFORM_LOCATIONS: %i", capability);
2611#endif // GRAPHICS_API_OPENGL_43
2612#else // RLGL_SHOW_GL_DETAILS_INFO
2613
2614 // Show some basic info about GL supported features
2615 if (RLGL.ExtSupported.vao) TRACELOG(RL_LOG_INFO, "GL: VAO extension detected, VAO functions loaded successfully");
2616 else TRACELOG(RL_LOG_WARNING, "GL: VAO extension not found, VAO not supported");
2617 if (RLGL.ExtSupported.texNPOT) TRACELOG(RL_LOG_INFO, "GL: NPOT textures extension detected, full NPOT textures supported");
2618 else TRACELOG(RL_LOG_WARNING, "GL: NPOT textures extension not found, limited NPOT support (no-mipmaps, no-repeat)");
2619 if (RLGL.ExtSupported.texCompDXT) TRACELOG(RL_LOG_INFO, "GL: DXT compressed textures supported");
2620 if (RLGL.ExtSupported.texCompETC1) TRACELOG(RL_LOG_INFO, "GL: ETC1 compressed textures supported");
2621 if (RLGL.ExtSupported.texCompETC2) TRACELOG(RL_LOG_INFO, "GL: ETC2/EAC compressed textures supported");
2622 if (RLGL.ExtSupported.texCompPVRT) TRACELOG(RL_LOG_INFO, "GL: PVRT compressed textures supported");
2623 if (RLGL.ExtSupported.texCompASTC) TRACELOG(RL_LOG_INFO, "GL: ASTC compressed textures supported");
2624 if (RLGL.ExtSupported.computeShader) TRACELOG(RL_LOG_INFO, "GL: Compute shaders supported");
2625 if (RLGL.ExtSupported.ssbo) TRACELOG(RL_LOG_INFO, "GL: Shader storage buffer objects supported");
2626#endif // RLGL_SHOW_GL_DETAILS_INFO
2627
2628#endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
2629}
2630
2631// Get current OpenGL version
2632int rlGetVersion(void)
2633{
2634 int glVersion = 0;
2635#if defined(GRAPHICS_API_OPENGL_11)
2636 glVersion = RL_OPENGL_11;
2637#endif
2638#if defined(GRAPHICS_API_OPENGL_21)
2639 glVersion = RL_OPENGL_21;
2640#elif defined(GRAPHICS_API_OPENGL_43)
2641 glVersion = RL_OPENGL_43;
2642#elif defined(GRAPHICS_API_OPENGL_33)
2643 glVersion = RL_OPENGL_33;
2644#endif
2645#if defined(GRAPHICS_API_OPENGL_ES3)
2646 glVersion = RL_OPENGL_ES_30;
2647#elif defined(GRAPHICS_API_OPENGL_ES2)
2648 glVersion = RL_OPENGL_ES_20;
2649#endif
2650
2651 return glVersion;
2652}
2653
2654// Set current framebuffer width
2655void rlSetFramebufferWidth(int width)
2656{
2657#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
2658 RLGL.State.framebufferWidth = width;
2659#endif
2660}
2661
2662// Set current framebuffer height
2663void rlSetFramebufferHeight(int height)
2664{
2665#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
2666 RLGL.State.framebufferHeight = height;
2667#endif
2668}
2669
2670// Get default framebuffer width
2671int rlGetFramebufferWidth(void)
2672{
2673 int width = 0;
2674#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
2675 width = RLGL.State.framebufferWidth;
2676#endif
2677 return width;
2678}
2679
2680// Get default framebuffer height
2681int rlGetFramebufferHeight(void)
2682{
2683 int height = 0;
2684#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
2685 height = RLGL.State.framebufferHeight;
2686#endif
2687 return height;
2688}
2689
2690// Get default internal texture (white texture)
2691// NOTE: Default texture is a 1x1 pixel UNCOMPRESSED_R8G8B8A8
2692unsigned int rlGetTextureIdDefault(void)
2693{
2694 unsigned int id = 0;
2695#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
2696 id = RLGL.State.defaultTextureId;
2697#endif
2698 return id;
2699}
2700
2701// Get default shader id
2702unsigned int rlGetShaderIdDefault(void)
2703{
2704 unsigned int id = 0;
2705#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
2706 id = RLGL.State.defaultShaderId;
2707#endif
2708 return id;
2709}
2710
2711// Get default shader locs
2712int *rlGetShaderLocsDefault(void)
2713{
2714 int *locs = NULL;
2715#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
2716 locs = RLGL.State.defaultShaderLocs;
2717#endif
2718 return locs;
2719}
2720
2721// Render batch management
2722//------------------------------------------------------------------------------------------------
2723// Load render batch
2724rlRenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements)
2725{
2726 rlRenderBatch batch = { 0 };
2727
2728#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
2729 // Initialize CPU (RAM) vertex buffers (position, texcoord, color data and indexes)
2730 //--------------------------------------------------------------------------------------------
2731 batch.vertexBuffer = (rlVertexBuffer *)RL_MALLOC(numBuffers*sizeof(rlVertexBuffer));
2732
2733 for (int i = 0; i < numBuffers; i++)
2734 {
2735 batch.vertexBuffer[i].elementCount = bufferElements;
2736
2737 batch.vertexBuffer[i].vertices = (float *)RL_MALLOC(bufferElements*3*4*sizeof(float)); // 3 float by vertex, 4 vertex by quad
2738 batch.vertexBuffer[i].texcoords = (float *)RL_MALLOC(bufferElements*2*4*sizeof(float)); // 2 float by texcoord, 4 texcoord by quad
2739 batch.vertexBuffer[i].normals = (float *)RL_MALLOC(bufferElements*3*4*sizeof(float)); // 3 float by vertex, 4 vertex by quad
2740 batch.vertexBuffer[i].colors = (unsigned char *)RL_MALLOC(bufferElements*4*4*sizeof(unsigned char)); // 4 float by color, 4 colors by quad
2741#if defined(GRAPHICS_API_OPENGL_33)
2742 batch.vertexBuffer[i].indices = (unsigned int *)RL_MALLOC(bufferElements*6*sizeof(unsigned int)); // 6 int by quad (indices)
2743#endif
2744#if defined(GRAPHICS_API_OPENGL_ES2)
2745 batch.vertexBuffer[i].indices = (unsigned short *)RL_MALLOC(bufferElements*6*sizeof(unsigned short)); // 6 int by quad (indices)
2746#endif
2747
2748 for (int j = 0; j < (3*4*bufferElements); j++) batch.vertexBuffer[i].vertices[j] = 0.0f;
2749 for (int j = 0; j < (2*4*bufferElements); j++) batch.vertexBuffer[i].texcoords[j] = 0.0f;
2750 for (int j = 0; j < (3*4*bufferElements); j++) batch.vertexBuffer[i].normals[j] = 0.0f;
2751 for (int j = 0; j < (4*4*bufferElements); j++) batch.vertexBuffer[i].colors[j] = 0;
2752
2753 int k = 0;
2754
2755 // Indices can be initialized right now
2756 for (int j = 0; j < (6*bufferElements); j += 6)
2757 {
2758 batch.vertexBuffer[i].indices[j] = 4*k;
2759 batch.vertexBuffer[i].indices[j + 1] = 4*k + 1;
2760 batch.vertexBuffer[i].indices[j + 2] = 4*k + 2;
2761 batch.vertexBuffer[i].indices[j + 3] = 4*k;
2762 batch.vertexBuffer[i].indices[j + 4] = 4*k + 2;
2763 batch.vertexBuffer[i].indices[j + 5] = 4*k + 3;
2764
2765 k++;
2766 }
2767
2768 RLGL.State.vertexCounter = 0;
2769 }
2770
2771 TRACELOG(RL_LOG_INFO, "RLGL: Render batch vertex buffers loaded successfully in RAM (CPU)");
2772 //--------------------------------------------------------------------------------------------
2773
2774 // Upload to GPU (VRAM) vertex data and initialize VAOs/VBOs
2775 //--------------------------------------------------------------------------------------------
2776 for (int i = 0; i < numBuffers; i++)
2777 {
2778 if (RLGL.ExtSupported.vao)
2779 {
2780 // Initialize Quads VAO
2781 glGenVertexArrays(1, &batch.vertexBuffer[i].vaoId);
2782 glBindVertexArray(batch.vertexBuffer[i].vaoId);
2783 }
2784
2785 // Quads - Vertex buffers binding and attributes enable
2786 // Vertex position buffer (shader-location = 0)
2787 glGenBuffers(1, &batch.vertexBuffer[i].vboId[0]);
2788 glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[0]);
2789 glBufferData(GL_ARRAY_BUFFER, bufferElements*3*4*sizeof(float), batch.vertexBuffer[i].vertices, GL_DYNAMIC_DRAW);
2790 glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_POSITION]);
2791 glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0);
2792
2793 // Vertex texcoord buffer (shader-location = 1)
2794 glGenBuffers(1, &batch.vertexBuffer[i].vboId[1]);
2795 glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[1]);
2796 glBufferData(GL_ARRAY_BUFFER, bufferElements*2*4*sizeof(float), batch.vertexBuffer[i].texcoords, GL_DYNAMIC_DRAW);
2797 glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_TEXCOORD01]);
2798 glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0);
2799
2800 // Vertex normal buffer (shader-location = 2)
2801 glGenBuffers(1, &batch.vertexBuffer[i].vboId[2]);
2802 glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[2]);
2803 glBufferData(GL_ARRAY_BUFFER, bufferElements*3*4*sizeof(float), batch.vertexBuffer[i].normals, GL_DYNAMIC_DRAW);
2804 glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_NORMAL]);
2805 glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_NORMAL], 3, GL_FLOAT, 0, 0, 0);
2806
2807 // Vertex color buffer (shader-location = 3)
2808 glGenBuffers(1, &batch.vertexBuffer[i].vboId[3]);
2809 glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[3]);
2810 glBufferData(GL_ARRAY_BUFFER, bufferElements*4*4*sizeof(unsigned char), batch.vertexBuffer[i].colors, GL_DYNAMIC_DRAW);
2811 glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_COLOR]);
2812 glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
2813
2814 // Fill index buffer
2815 glGenBuffers(1, &batch.vertexBuffer[i].vboId[4]);
2816 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[4]);
2817#if defined(GRAPHICS_API_OPENGL_33)
2818 glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufferElements*6*sizeof(int), batch.vertexBuffer[i].indices, GL_STATIC_DRAW);
2819#endif
2820#if defined(GRAPHICS_API_OPENGL_ES2)
2821 glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufferElements*6*sizeof(short), batch.vertexBuffer[i].indices, GL_STATIC_DRAW);
2822#endif
2823 }
2824
2825 TRACELOG(RL_LOG_INFO, "RLGL: Render batch vertex buffers loaded successfully in VRAM (GPU)");
2826
2827 // Unbind the current VAO
2828 if (RLGL.ExtSupported.vao) glBindVertexArray(0);
2829 //--------------------------------------------------------------------------------------------
2830
2831 // Init draw calls tracking system
2832 //--------------------------------------------------------------------------------------------
2833 batch.draws = (rlDrawCall *)RL_MALLOC(RL_DEFAULT_BATCH_DRAWCALLS*sizeof(rlDrawCall));
2834
2835 for (int i = 0; i < RL_DEFAULT_BATCH_DRAWCALLS; i++)
2836 {
2837 batch.draws[i].mode = RL_QUADS;
2838 batch.draws[i].vertexCount = 0;
2839 batch.draws[i].vertexAlignment = 0;
2840 //batch.draws[i].vaoId = 0;
2841 //batch.draws[i].shaderId = 0;
2842 batch.draws[i].textureId = RLGL.State.defaultTextureId;
2843 //batch.draws[i].RLGL.State.projection = rlMatrixIdentity();
2844 //batch.draws[i].RLGL.State.modelview = rlMatrixIdentity();
2845 }
2846
2847 batch.bufferCount = numBuffers; // Record buffer count
2848 batch.drawCounter = 1; // Reset draws counter
2849 batch.currentDepth = -1.0f; // Reset depth value
2850 //--------------------------------------------------------------------------------------------
2851#endif
2852
2853 return batch;
2854}
2855
2856// Unload default internal buffers vertex data from CPU and GPU
2857void rlUnloadRenderBatch(rlRenderBatch batch)
2858{
2859#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
2860 // Unbind everything
2861 glBindBuffer(GL_ARRAY_BUFFER, 0);
2862 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2863
2864 // Unload all vertex buffers data
2865 for (int i = 0; i < batch.bufferCount; i++)
2866 {
2867 // Unbind VAO attribs data
2868 if (RLGL.ExtSupported.vao)
2869 {
2870 glBindVertexArray(batch.vertexBuffer[i].vaoId);
2871 glDisableVertexAttribArray(RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION);
2872 glDisableVertexAttribArray(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD);
2873 glDisableVertexAttribArray(RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL);
2874 glDisableVertexAttribArray(RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR);
2875 glBindVertexArray(0);
2876 }
2877
2878 // Delete VBOs from GPU (VRAM)
2879 glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[0]);
2880 glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[1]);
2881 glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[2]);
2882 glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[3]);
2883 glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[4]);
2884
2885 // Delete VAOs from GPU (VRAM)
2886 if (RLGL.ExtSupported.vao) glDeleteVertexArrays(1, &batch.vertexBuffer[i].vaoId);
2887
2888 // Free vertex arrays memory from CPU (RAM)
2889 RL_FREE(batch.vertexBuffer[i].vertices);
2890 RL_FREE(batch.vertexBuffer[i].texcoords);
2891 RL_FREE(batch.vertexBuffer[i].normals);
2892 RL_FREE(batch.vertexBuffer[i].colors);
2893 RL_FREE(batch.vertexBuffer[i].indices);
2894 }
2895
2896 // Unload arrays
2897 RL_FREE(batch.vertexBuffer);
2898 RL_FREE(batch.draws);
2899#endif
2900}
2901
2902// Draw render batch
2903// NOTE: We require a pointer to reset batch and increase current buffer (multi-buffer)
2904void rlDrawRenderBatch(rlRenderBatch *batch)
2905{
2906#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
2907 // Update batch vertex buffers
2908 //------------------------------------------------------------------------------------------------------------
2909 // NOTE: If there is not vertex data, buffers doesn't need to be updated (vertexCount > 0)
2910 // TODO: If no data changed on the CPU arrays --> No need to re-update GPU arrays (use a change detector flag?)
2911 if (RLGL.State.vertexCounter > 0)
2912 {
2913 // Activate elements VAO
2914 if (RLGL.ExtSupported.vao) glBindVertexArray(batch->vertexBuffer[batch->currentBuffer].vaoId);
2915
2916 // Vertex positions buffer
2917 glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[0]);
2918 glBufferSubData(GL_ARRAY_BUFFER, 0, RLGL.State.vertexCounter*3*sizeof(float), batch->vertexBuffer[batch->currentBuffer].vertices);
2919 //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*batch->vertexBuffer[batch->currentBuffer].elementCount, batch->vertexBuffer[batch->currentBuffer].vertices, GL_DYNAMIC_DRAW); // Update all buffer
2920
2921 // Texture coordinates buffer
2922 glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[1]);
2923 glBufferSubData(GL_ARRAY_BUFFER, 0, RLGL.State.vertexCounter*2*sizeof(float), batch->vertexBuffer[batch->currentBuffer].texcoords);
2924 //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*batch->vertexBuffer[batch->currentBuffer].elementCount, batch->vertexBuffer[batch->currentBuffer].texcoords, GL_DYNAMIC_DRAW); // Update all buffer
2925
2926 // Normals buffer
2927 glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[2]);
2928 glBufferSubData(GL_ARRAY_BUFFER, 0, RLGL.State.vertexCounter*3*sizeof(float), batch->vertexBuffer[batch->currentBuffer].normals);
2929 //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*batch->vertexBuffer[batch->currentBuffer].elementCount, batch->vertexBuffer[batch->currentBuffer].normals, GL_DYNAMIC_DRAW); // Update all buffer
2930
2931 // Colors buffer
2932 glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[3]);
2933 glBufferSubData(GL_ARRAY_BUFFER, 0, RLGL.State.vertexCounter*4*sizeof(unsigned char), batch->vertexBuffer[batch->currentBuffer].colors);
2934 //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*4*batch->vertexBuffer[batch->currentBuffer].elementCount, batch->vertexBuffer[batch->currentBuffer].colors, GL_DYNAMIC_DRAW); // Update all buffer
2935
2936 // NOTE: glMapBuffer() causes sync issue
2937 // If GPU is working with this buffer, glMapBuffer() will wait(stall) until GPU to finish its job
2938 // To avoid waiting (idle), you can call first glBufferData() with NULL pointer before glMapBuffer()
2939 // If you do that, the previous data in PBO will be discarded and glMapBuffer() returns a new
2940 // allocated pointer immediately even if GPU is still working with the previous data
2941
2942 // Another option: map the buffer object into client's memory
2943 // Probably this code could be moved somewhere else...
2944 // batch->vertexBuffer[batch->currentBuffer].vertices = (float *)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);
2945 // if (batch->vertexBuffer[batch->currentBuffer].vertices)
2946 // {
2947 // Update vertex data
2948 // }
2949 // glUnmapBuffer(GL_ARRAY_BUFFER);
2950
2951 // Unbind the current VAO
2952 if (RLGL.ExtSupported.vao) glBindVertexArray(0);
2953 }
2954 //------------------------------------------------------------------------------------------------------------
2955
2956 // Draw batch vertex buffers (considering VR stereo if required)
2957 //------------------------------------------------------------------------------------------------------------
2958 Matrix matProjection = RLGL.State.projection;
2959 Matrix matModelView = RLGL.State.modelview;
2960
2961 int eyeCount = 1;
2962 if (RLGL.State.stereoRender) eyeCount = 2;
2963
2964 for (int eye = 0; eye < eyeCount; eye++)
2965 {
2966 if (eyeCount == 2)
2967 {
2968 // Setup current eye viewport (half screen width)
2969 rlViewport(eye*RLGL.State.framebufferWidth/2, 0, RLGL.State.framebufferWidth/2, RLGL.State.framebufferHeight);
2970
2971 // Set current eye view offset to modelview matrix
2972 rlSetMatrixModelview(rlMatrixMultiply(matModelView, RLGL.State.viewOffsetStereo[eye]));
2973 // Set current eye projection matrix
2974 rlSetMatrixProjection(RLGL.State.projectionStereo[eye]);
2975 }
2976
2977 // Draw buffers
2978 if (RLGL.State.vertexCounter > 0)
2979 {
2980 // Set current shader and upload current MVP matrix
2981 glUseProgram(RLGL.State.currentShaderId);
2982
2983 // Create modelview-projection matrix and upload to shader
2984 Matrix matMVP = rlMatrixMultiply(RLGL.State.modelview, RLGL.State.projection);
2985 glUniformMatrix4fv(RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_MVP], 1, false, rlMatrixToFloat(matMVP));
2986
2987 if (RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_PROJECTION] != -1)
2988 {
2989 glUniformMatrix4fv(RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_PROJECTION], 1, false, rlMatrixToFloat(RLGL.State.projection));
2990 }
2991
2992 // WARNING: For the following setup of the view, model, and normal matrices, it is expected that
2993 // transformations and rendering occur between rlPushMatrix() and rlPopMatrix()
2994
2995 if (RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_VIEW] != -1)
2996 {
2997 glUniformMatrix4fv(RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_VIEW], 1, false, rlMatrixToFloat(RLGL.State.modelview));
2998 }
2999
3000 if (RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_MODEL] != -1)
3001 {
3002 glUniformMatrix4fv(RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_MODEL], 1, false, rlMatrixToFloat(RLGL.State.transform));
3003 }
3004
3005 if (RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_NORMAL] != -1)
3006 {
3007 glUniformMatrix4fv(RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_NORMAL], 1, false, rlMatrixToFloat(rlMatrixTranspose(rlMatrixInvert(RLGL.State.transform))));
3008 }
3009
3010 if (RLGL.ExtSupported.vao) glBindVertexArray(batch->vertexBuffer[batch->currentBuffer].vaoId);
3011 else
3012 {
3013 // Bind vertex attrib: position (shader-location = 0)
3014 glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[0]);
3015 glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0);
3016 glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_POSITION]);
3017
3018 // Bind vertex attrib: texcoord (shader-location = 1)
3019 glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[1]);
3020 glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0);
3021 glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_TEXCOORD01]);
3022
3023 // Bind vertex attrib: normal (shader-location = 2)
3024 glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[2]);
3025 glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_NORMAL], 3, GL_FLOAT, 0, 0, 0);
3026 glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_NORMAL]);
3027
3028 // Bind vertex attrib: color (shader-location = 3)
3029 glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[3]);
3030 glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
3031 glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_COLOR]);
3032
3033 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[4]);
3034 }
3035
3036 // Setup some default shader values
3037 glUniform4f(RLGL.State.currentShaderLocs[RL_SHADER_LOC_COLOR_DIFFUSE], 1.0f, 1.0f, 1.0f, 1.0f);
3038 glUniform1i(RLGL.State.currentShaderLocs[RL_SHADER_LOC_MAP_DIFFUSE], 0); // Active default sampler2D: texture0
3039
3040 // Activate additional sampler textures
3041 // Those additional textures will be common for all draw calls of the batch
3042 for (int i = 0; i < RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS; i++)
3043 {
3044 if (RLGL.State.activeTextureId[i] > 0)
3045 {
3046 glActiveTexture(GL_TEXTURE0 + 1 + i);
3047 glBindTexture(GL_TEXTURE_2D, RLGL.State.activeTextureId[i]);
3048 }
3049 }
3050
3051 // Activate default sampler2D texture0 (one texture is always active for default batch shader)
3052 // NOTE: Batch system accumulates calls by texture0 changes, additional textures are enabled for all the draw calls
3053 glActiveTexture(GL_TEXTURE0);
3054
3055 for (int i = 0, vertexOffset = 0; i < batch->drawCounter; i++)
3056 {
3057 // Bind current draw call texture, activated as GL_TEXTURE0 and Bound to sampler2D texture0 by default
3058 glBindTexture(GL_TEXTURE_2D, batch->draws[i].textureId);
3059
3060 if ((batch->draws[i].mode == RL_LINES) || (batch->draws[i].mode == RL_TRIANGLES)) glDrawArrays(batch->draws[i].mode, vertexOffset, batch->draws[i].vertexCount);
3061 else
3062 {
3063 #if defined(GRAPHICS_API_OPENGL_33)
3064 // We need to define the number of indices to be processed: elementCount*6
3065 // NOTE: The final parameter tells the GPU the offset in bytes from the
3066 // start of the index buffer to the location of the first index to process
3067 glDrawElements(GL_TRIANGLES, batch->draws[i].vertexCount/4*6, GL_UNSIGNED_INT, (GLvoid *)(vertexOffset/4*6*sizeof(GLuint)));
3068 #endif
3069 #if defined(GRAPHICS_API_OPENGL_ES2)
3070 glDrawElements(GL_TRIANGLES, batch->draws[i].vertexCount/4*6, GL_UNSIGNED_SHORT, (GLvoid *)(vertexOffset/4*6*sizeof(GLushort)));
3071 #endif
3072 }
3073
3074 vertexOffset += (batch->draws[i].vertexCount + batch->draws[i].vertexAlignment);
3075 }
3076
3077 if (!RLGL.ExtSupported.vao)
3078 {
3079 glBindBuffer(GL_ARRAY_BUFFER, 0);
3080 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
3081 }
3082
3083 glBindTexture(GL_TEXTURE_2D, 0); // Unbind textures
3084 }
3085
3086 if (RLGL.ExtSupported.vao) glBindVertexArray(0); // Unbind VAO
3087
3088 glUseProgram(0); // Unbind shader program
3089 }
3090
3091 // Restore viewport to default measures
3092 if (eyeCount == 2) rlViewport(0, 0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight);
3093 //------------------------------------------------------------------------------------------------------------
3094
3095 // Reset batch buffers
3096 //------------------------------------------------------------------------------------------------------------
3097 // Reset vertex counter for next frame
3098 RLGL.State.vertexCounter = 0;
3099
3100 // Reset depth for next draw
3101 batch->currentDepth = -1.0f;
3102
3103 // Restore projection/modelview matrices
3104 RLGL.State.projection = matProjection;
3105 RLGL.State.modelview = matModelView;
3106
3107 // Reset RLGL.currentBatch->draws array
3108 for (int i = 0; i < RL_DEFAULT_BATCH_DRAWCALLS; i++)
3109 {
3110 batch->draws[i].mode = RL_QUADS;
3111 batch->draws[i].vertexCount = 0;
3112 batch->draws[i].textureId = RLGL.State.defaultTextureId;
3113 }
3114
3115 // Reset active texture units for next batch
3116 for (int i = 0; i < RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS; i++) RLGL.State.activeTextureId[i] = 0;
3117
3118 // Reset draws counter to one draw for the batch
3119 batch->drawCounter = 1;
3120 //------------------------------------------------------------------------------------------------------------
3121
3122 // Change to next buffer in the list (in case of multi-buffering)
3123 batch->currentBuffer++;
3124 if (batch->currentBuffer >= batch->bufferCount) batch->currentBuffer = 0;
3125#endif
3126}
3127
3128// Set the active render batch for rlgl
3129void rlSetRenderBatchActive(rlRenderBatch *batch)
3130{
3131#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
3132 rlDrawRenderBatch(RLGL.currentBatch);
3133
3134 if (batch != NULL) RLGL.currentBatch = batch;
3135 else RLGL.currentBatch = &RLGL.defaultBatch;
3136#endif
3137}
3138
3139// Update and draw internal render batch
3140void rlDrawRenderBatchActive(void)
3141{
3142#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
3143 rlDrawRenderBatch(RLGL.currentBatch); // NOTE: Stereo rendering is checked inside
3144#endif
3145}
3146
3147// Check internal buffer overflow for a given number of vertex
3148// and force a rlRenderBatch draw call if required
3149bool rlCheckRenderBatchLimit(int vCount)
3150{
3151 bool overflow = false;
3152
3153#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
3154 if ((RLGL.State.vertexCounter + vCount) >=
3155 (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementCount*4))
3156 {
3157 overflow = true;
3158
3159 // Store current primitive drawing mode and texture id
3160 int currentMode = RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode;
3161 int currentTexture = RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].textureId;
3162
3163 rlDrawRenderBatch(RLGL.currentBatch); // NOTE: Stereo rendering is checked inside
3164
3165 // Restore state of last batch so we can continue adding vertices
3166 RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode = currentMode;
3167 RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].textureId = currentTexture;
3168 }
3169#endif
3170
3171 return overflow;
3172}
3173
3174// Textures data management
3175//-----------------------------------------------------------------------------------------
3176// Convert image data to OpenGL texture (returns OpenGL valid Id)
3177unsigned int rlLoadTexture(const void *data, int width, int height, int format, int mipmapCount)
3178{
3179 unsigned int id = 0;
3180
3181 glBindTexture(GL_TEXTURE_2D, 0); // Free any old binding
3182
3183 // Check texture format support by OpenGL 1.1 (compressed textures not supported)
3184#if defined(GRAPHICS_API_OPENGL_11)
3185 if (format >= RL_PIXELFORMAT_COMPRESSED_DXT1_RGB)
3186 {
3187 TRACELOG(RL_LOG_WARNING, "GL: OpenGL 1.1 does not support GPU compressed texture formats");
3188 return id;
3189 }
3190#else
3191 if ((!RLGL.ExtSupported.texCompDXT) && ((format == RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) || (format == RL_PIXELFORMAT_COMPRESSED_DXT1_RGBA) ||
3192 (format == RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA) || (format == RL_PIXELFORMAT_COMPRESSED_DXT5_RGBA)))
3193 {
3194 TRACELOG(RL_LOG_WARNING, "GL: DXT compressed texture format not supported");
3195 return id;
3196 }
3197#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
3198 if ((!RLGL.ExtSupported.texCompETC1) && (format == RL_PIXELFORMAT_COMPRESSED_ETC1_RGB))
3199 {
3200 TRACELOG(RL_LOG_WARNING, "GL: ETC1 compressed texture format not supported");
3201 return id;
3202 }
3203
3204 if ((!RLGL.ExtSupported.texCompETC2) && ((format == RL_PIXELFORMAT_COMPRESSED_ETC2_RGB) || (format == RL_PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA)))
3205 {
3206 TRACELOG(RL_LOG_WARNING, "GL: ETC2 compressed texture format not supported");
3207 return id;
3208 }
3209
3210 if ((!RLGL.ExtSupported.texCompPVRT) && ((format == RL_PIXELFORMAT_COMPRESSED_PVRT_RGB) || (format == RL_PIXELFORMAT_COMPRESSED_PVRT_RGBA)))
3211 {
3212 TRACELOG(RL_LOG_WARNING, "GL: PVRT compressed texture format not supported");
3213 return id;
3214 }
3215
3216 if ((!RLGL.ExtSupported.texCompASTC) && ((format == RL_PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA) || (format == RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA)))
3217 {
3218 TRACELOG(RL_LOG_WARNING, "GL: ASTC compressed texture format not supported");
3219 return id;
3220 }
3221#endif
3222#endif // GRAPHICS_API_OPENGL_11
3223
3224 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
3225
3226 glGenTextures(1, &id); // Generate texture id
3227
3228 glBindTexture(GL_TEXTURE_2D, id);
3229
3230 int mipWidth = width;
3231 int mipHeight = height;
3232 int mipOffset = 0; // Mipmap data offset, only used for tracelog
3233
3234 // NOTE: Added pointer math separately from function to avoid UBSAN complaining
3235 unsigned char *dataPtr = NULL;
3236 if (data != NULL) dataPtr = (unsigned char *)data;
3237
3238 // Load the different mipmap levels
3239 for (int i = 0; i < mipmapCount; i++)
3240 {
3241 unsigned int mipSize = rlGetPixelDataSize(mipWidth, mipHeight, format);
3242
3243 unsigned int glInternalFormat, glFormat, glType;
3244 rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType);
3245
3246 TRACELOGD("TEXTURE: Load mipmap level %i (%i x %i), size: %i, offset: %i", i, mipWidth, mipHeight, mipSize, mipOffset);
3247
3248 if (glInternalFormat != 0)
3249 {
3250 if (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) glTexImage2D(GL_TEXTURE_2D, i, glInternalFormat, mipWidth, mipHeight, 0, glFormat, glType, dataPtr);
3251#if !defined(GRAPHICS_API_OPENGL_11)
3252 else glCompressedTexImage2D(GL_TEXTURE_2D, i, glInternalFormat, mipWidth, mipHeight, 0, mipSize, dataPtr);
3253#endif
3254
3255#if defined(GRAPHICS_API_OPENGL_33)
3256 if (format == RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE)
3257 {
3258 GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_ONE };
3259 glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
3260 }
3261 else if (format == RL_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA)
3262 {
3263#if defined(GRAPHICS_API_OPENGL_21)
3264 GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_ALPHA };
3265#elif defined(GRAPHICS_API_OPENGL_33)
3266 GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_GREEN };
3267#endif
3268 glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
3269 }
3270#endif
3271 }
3272
3273 mipWidth /= 2;
3274 mipHeight /= 2;
3275 mipOffset += mipSize; // Increment offset position to next mipmap
3276 if (data != NULL) dataPtr += mipSize; // Increment data pointer to next mipmap
3277
3278 // Security check for NPOT textures
3279 if (mipWidth < 1) mipWidth = 1;
3280 if (mipHeight < 1) mipHeight = 1;
3281 }
3282
3283 // Texture parameters configuration
3284 // NOTE: glTexParameteri does NOT affect texture uploading, just the way it's used
3285#if defined(GRAPHICS_API_OPENGL_ES2)
3286 // NOTE: OpenGL ES 2.0 with no GL_OES_texture_npot support (i.e. WebGL) has limited NPOT support, so CLAMP_TO_EDGE must be used
3287 if (RLGL.ExtSupported.texNPOT)
3288 {
3289 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture to repeat on x-axis
3290 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Set texture to repeat on y-axis
3291 }
3292 else
3293 {
3294 // NOTE: If using negative texture coordinates (LoadOBJ()), it does not work!
3295 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // Set texture to clamp on x-axis
3296 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // Set texture to clamp on y-axis
3297 }
3298#else
3299 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture to repeat on x-axis
3300 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Set texture to repeat on y-axis
3301#endif
3302
3303 // Magnification and minification filters
3304 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Alternative: GL_LINEAR
3305 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Alternative: GL_LINEAR
3306
3307#if defined(GRAPHICS_API_OPENGL_33)
3308 if (mipmapCount > 1)
3309 {
3310 // Activate Trilinear filtering if mipmaps are available
3311 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3312 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
3313 }
3314#endif
3315
3316 // At this point we have the texture loaded in GPU and texture parameters configured
3317
3318 // NOTE: If mipmaps were not in data, they are not generated automatically
3319
3320 // Unbind current texture
3321 glBindTexture(GL_TEXTURE_2D, 0);
3322
3323 if (id > 0) TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Texture loaded successfully (%ix%i | %s | %i mipmaps)", id, width, height, rlGetPixelFormatName(format), mipmapCount);
3324 else TRACELOG(RL_LOG_WARNING, "TEXTURE: Failed to load texture");
3325
3326 return id;
3327}
3328
3329// Load depth texture/renderbuffer (to be attached to fbo)
3330// WARNING: OpenGL ES 2.0 requires GL_OES_depth_texture and WebGL requires WEBGL_depth_texture extensions
3331unsigned int rlLoadTextureDepth(int width, int height, bool useRenderBuffer)
3332{
3333 unsigned int id = 0;
3334
3335#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
3336 // In case depth textures not supported, we force renderbuffer usage
3337 if (!RLGL.ExtSupported.texDepth) useRenderBuffer = true;
3338
3339 // NOTE: We let the implementation to choose the best bit-depth
3340 // Possible formats: GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT32 and GL_DEPTH_COMPONENT32F
3341 unsigned int glInternalFormat = GL_DEPTH_COMPONENT;
3342
3343#if (defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_ES3))
3344 // WARNING: WebGL platform requires unsized internal format definition (GL_DEPTH_COMPONENT)
3345 // while other platforms using OpenGL ES 2.0 require/support sized internal formats depending on the GPU capabilities
3346 if (!RLGL.ExtSupported.texDepthWebGL || useRenderBuffer)
3347 {
3348 if (RLGL.ExtSupported.maxDepthBits == 32) glInternalFormat = GL_DEPTH_COMPONENT32_OES;
3349 else if (RLGL.ExtSupported.maxDepthBits == 24) glInternalFormat = GL_DEPTH_COMPONENT24_OES;
3350 else glInternalFormat = GL_DEPTH_COMPONENT16;
3351 }
3352#endif
3353
3354 if (!useRenderBuffer && RLGL.ExtSupported.texDepth)
3355 {
3356 glGenTextures(1, &id);
3357 glBindTexture(GL_TEXTURE_2D, id);
3358 glTexImage2D(GL_TEXTURE_2D, 0, glInternalFormat, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
3359
3360 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3361 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3362 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3363 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3364
3365 glBindTexture(GL_TEXTURE_2D, 0);
3366
3367 TRACELOG(RL_LOG_INFO, "TEXTURE: Depth texture loaded successfully");
3368 }
3369 else
3370 {
3371 // Create the renderbuffer that will serve as the depth attachment for the framebuffer
3372 // NOTE: A renderbuffer is simpler than a texture and could offer better performance on embedded devices
3373 glGenRenderbuffers(1, &id);
3374 glBindRenderbuffer(GL_RENDERBUFFER, id);
3375 glRenderbufferStorage(GL_RENDERBUFFER, glInternalFormat, width, height);
3376
3377 glBindRenderbuffer(GL_RENDERBUFFER, 0);
3378
3379 TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Depth renderbuffer loaded successfully (%i bits)", id, (RLGL.ExtSupported.maxDepthBits >= 24)? RLGL.ExtSupported.maxDepthBits : 16);
3380 }
3381#endif
3382
3383 return id;
3384}
3385
3386// Load texture cubemap
3387// NOTE: Cubemap data is expected to be 6 images in a single data array (one after the other),
3388// expected the following convention: +X, -X, +Y, -Y, +Z, -Z
3389unsigned int rlLoadTextureCubemap(const void *data, int size, int format, int mipmapCount)
3390{
3391 unsigned int id = 0;
3392
3393#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
3394 int mipSize = size;
3395
3396 // NOTE: Added pointer math separately from function to avoid UBSAN complaining
3397 unsigned char *dataPtr = NULL;
3398 if (data != NULL) dataPtr = (unsigned char *)data;
3399
3400 unsigned int dataSize = rlGetPixelDataSize(size, size, format);
3401
3402 glGenTextures(1, &id);
3403 glBindTexture(GL_TEXTURE_CUBE_MAP, id);
3404
3405 unsigned int glInternalFormat, glFormat, glType;
3406 rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType);
3407
3408 if (glInternalFormat != 0)
3409 {
3410 // Load cubemap faces/mipmaps
3411 for (int i = 0; i < 6*mipmapCount; i++)
3412 {
3413 int mipmapLevel = i/6;
3414 int face = i%6;
3415
3416 if (data == NULL)
3417 {
3418 if (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB)
3419 {
3420 if ((format == RL_PIXELFORMAT_UNCOMPRESSED_R32) ||
3421 (format == RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32) ||
3422 (format == RL_PIXELFORMAT_UNCOMPRESSED_R16) ||
3423 (format == RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16)) TRACELOG(RL_LOG_WARNING, "TEXTURES: Cubemap requested format not supported");
3424 else glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mipmapLevel, glInternalFormat, mipSize, mipSize, 0, glFormat, glType, NULL);
3425 }
3426 else TRACELOG(RL_LOG_WARNING, "TEXTURES: Empty cubemap creation does not support compressed format");
3427 }
3428 else
3429 {
3430 if (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mipmapLevel, glInternalFormat, mipSize, mipSize, 0, glFormat, glType, (unsigned char *)dataPtr + face*dataSize);
3431 else glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mipmapLevel, glInternalFormat, mipSize, mipSize, 0, dataSize, (unsigned char *)dataPtr + face*dataSize);
3432 }
3433
3434#if defined(GRAPHICS_API_OPENGL_33)
3435 if (format == RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE)
3436 {
3437 GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_ONE };
3438 glTexParameteriv(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
3439 }
3440 else if (format == RL_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA)
3441 {
3442#if defined(GRAPHICS_API_OPENGL_21)
3443 GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_ALPHA };
3444#elif defined(GRAPHICS_API_OPENGL_33)
3445 GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_GREEN };
3446#endif
3447 glTexParameteriv(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
3448 }
3449#endif
3450 if (face == 5)
3451 {
3452 mipSize /= 2;
3453 if (data != NULL) dataPtr += dataSize*6; // Increment data pointer to next mipmap
3454
3455 // Security check for NPOT textures
3456 if (mipSize < 1) mipSize = 1;
3457
3458 dataSize = rlGetPixelDataSize(mipSize, mipSize, format);
3459 }
3460 }
3461 }
3462
3463 // Set cubemap texture sampling parameters
3464 if (mipmapCount > 1) glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
3465 else glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3466
3467 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3468 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3469 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3470#if defined(GRAPHICS_API_OPENGL_33)
3471 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); // Flag not supported on OpenGL ES 2.0
3472#endif
3473
3474 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
3475#endif
3476
3477 if (id > 0) TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Cubemap texture loaded successfully (%ix%i)", id, size, size);
3478 else TRACELOG(RL_LOG_WARNING, "TEXTURE: Failed to load cubemap texture");
3479
3480 return id;
3481}
3482
3483// Update already loaded texture in GPU with new data
3484// NOTE: We don't know safely if internal texture format is the expected one...
3485void rlUpdateTexture(unsigned int id, int offsetX, int offsetY, int width, int height, int format, const void *data)
3486{
3487 glBindTexture(GL_TEXTURE_2D, id);
3488
3489 unsigned int glInternalFormat, glFormat, glType;
3490 rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType);
3491
3492 if ((glInternalFormat != 0) && (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB))
3493 {
3494 glTexSubImage2D(GL_TEXTURE_2D, 0, offsetX, offsetY, width, height, glFormat, glType, data);
3495 }
3496 else TRACELOG(RL_LOG_WARNING, "TEXTURE: [ID %i] Failed to update for current texture format (%i)", id, format);
3497}
3498
3499// Get OpenGL internal formats and data type from raylib PixelFormat
3500void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned int *glFormat, unsigned int *glType)
3501{
3502 *glInternalFormat = 0;
3503 *glFormat = 0;
3504 *glType = 0;
3505
3506 switch (format)
3507 {
3508 #if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_21) || defined(GRAPHICS_API_OPENGL_ES2)
3509 // NOTE: on OpenGL ES 2.0 (WebGL), internalFormat must match format and options allowed are: GL_LUMINANCE, GL_RGB, GL_RGBA
3510 case RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_UNSIGNED_BYTE; break;
3511 case RL_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: *glInternalFormat = GL_LUMINANCE_ALPHA; *glFormat = GL_LUMINANCE_ALPHA; *glType = GL_UNSIGNED_BYTE; break;
3512 case RL_PIXELFORMAT_UNCOMPRESSED_R5G6B5: *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_UNSIGNED_SHORT_5_6_5; break;
3513 case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8: *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_UNSIGNED_BYTE; break;
3514 case RL_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_SHORT_5_5_5_1; break;
3515 case RL_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_SHORT_4_4_4_4; break;
3516 case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_BYTE; break;
3517 #if !defined(GRAPHICS_API_OPENGL_11)
3518 #if defined(GRAPHICS_API_OPENGL_ES3)
3519 case RL_PIXELFORMAT_UNCOMPRESSED_R32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_R32F_EXT; *glFormat = GL_RED_EXT; *glType = GL_FLOAT; break;
3520 case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGB32F_EXT; *glFormat = GL_RGB; *glType = GL_FLOAT; break;
3521 case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGBA32F_EXT; *glFormat = GL_RGBA; *glType = GL_FLOAT; break;
3522 case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_R16F_EXT; *glFormat = GL_RED_EXT; *glType = GL_HALF_FLOAT; break;
3523 case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB16F_EXT; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT; break;
3524 case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA16F_EXT; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT; break;
3525 #else
3526 case RL_PIXELFORMAT_UNCOMPRESSED_R32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
3527 case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
3528 case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
3529 #if defined(GRAPHICS_API_OPENGL_21)
3530 case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_HALF_FLOAT_ARB; break;
3531 case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT_ARB; break;
3532 case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT_ARB; break;
3533 #else // defined(GRAPHICS_API_OPENGL_ES2)
3534 case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
3535 case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
3536 case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
3537 #endif
3538 #endif
3539 #endif
3540 #elif defined(GRAPHICS_API_OPENGL_33)
3541 case RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: *glInternalFormat = GL_R8; *glFormat = GL_RED; *glType = GL_UNSIGNED_BYTE; break;
3542 case RL_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: *glInternalFormat = GL_RG8; *glFormat = GL_RG; *glType = GL_UNSIGNED_BYTE; break;
3543 case RL_PIXELFORMAT_UNCOMPRESSED_R5G6B5: *glInternalFormat = GL_RGB565; *glFormat = GL_RGB; *glType = GL_UNSIGNED_SHORT_5_6_5; break;
3544 case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8: *glInternalFormat = GL_RGB8; *glFormat = GL_RGB; *glType = GL_UNSIGNED_BYTE; break;
3545 case RL_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: *glInternalFormat = GL_RGB5_A1; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_SHORT_5_5_5_1; break;
3546 case RL_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: *glInternalFormat = GL_RGBA4; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_SHORT_4_4_4_4; break;
3547 case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: *glInternalFormat = GL_RGBA8; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_BYTE; break;
3548 case RL_PIXELFORMAT_UNCOMPRESSED_R32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_R32F; *glFormat = GL_RED; *glType = GL_FLOAT; break;
3549 case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGB32F; *glFormat = GL_RGB; *glType = GL_FLOAT; break;
3550 case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGBA32F; *glFormat = GL_RGBA; *glType = GL_FLOAT; break;
3551 case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_R16F; *glFormat = GL_RED; *glType = GL_HALF_FLOAT; break;
3552 case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB16F; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT; break;
3553 case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA16F; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT; break;
3554 #endif
3555 #if !defined(GRAPHICS_API_OPENGL_11)
3556 case RL_PIXELFORMAT_COMPRESSED_DXT1_RGB: if (RLGL.ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; break;
3557 case RL_PIXELFORMAT_COMPRESSED_DXT1_RGBA: if (RLGL.ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; break;
3558 case RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA: if (RLGL.ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break;
3559 case RL_PIXELFORMAT_COMPRESSED_DXT5_RGBA: if (RLGL.ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break;
3560 case RL_PIXELFORMAT_COMPRESSED_ETC1_RGB: if (RLGL.ExtSupported.texCompETC1) *glInternalFormat = GL_ETC1_RGB8_OES; break; // NOTE: Requires OpenGL ES 2.0 or OpenGL 4.3
3561 case RL_PIXELFORMAT_COMPRESSED_ETC2_RGB: if (RLGL.ExtSupported.texCompETC2) *glInternalFormat = GL_COMPRESSED_RGB8_ETC2; break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3
3562 case RL_PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA: if (RLGL.ExtSupported.texCompETC2) *glInternalFormat = GL_COMPRESSED_RGBA8_ETC2_EAC; break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3
3563 case RL_PIXELFORMAT_COMPRESSED_PVRT_RGB: if (RLGL.ExtSupported.texCompPVRT) *glInternalFormat = GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG; break; // NOTE: Requires PowerVR GPU
3564 case RL_PIXELFORMAT_COMPRESSED_PVRT_RGBA: if (RLGL.ExtSupported.texCompPVRT) *glInternalFormat = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; break; // NOTE: Requires PowerVR GPU
3565 case RL_PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA: if (RLGL.ExtSupported.texCompASTC) *glInternalFormat = GL_COMPRESSED_RGBA_ASTC_4x4_KHR; break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3
3566 case RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: if (RLGL.ExtSupported.texCompASTC) *glInternalFormat = GL_COMPRESSED_RGBA_ASTC_8x8_KHR; break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3
3567 #endif
3568 default: TRACELOG(RL_LOG_WARNING, "TEXTURE: Current format not supported (%i)", format); break;
3569 }
3570}
3571
3572// Unload texture from GPU memory
3573void rlUnloadTexture(unsigned int id)
3574{
3575 glDeleteTextures(1, &id);
3576}
3577
3578// Generate mipmap data for selected texture
3579// NOTE: Only supports GPU mipmap generation
3580void rlGenTextureMipmaps(unsigned int id, int width, int height, int format, int *mipmaps)
3581{
3582#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
3583 glBindTexture(GL_TEXTURE_2D, id);
3584
3585 // Check if texture is power-of-two (POT)
3586 bool texIsPOT = false;
3587
3588 if (((width > 0) && ((width & (width - 1)) == 0)) &&
3589 ((height > 0) && ((height & (height - 1)) == 0))) texIsPOT = true;
3590
3591 if ((texIsPOT) || (RLGL.ExtSupported.texNPOT))
3592 {
3593 //glHint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE); // Hint for mipmaps generation algorithm: GL_FASTEST, GL_NICEST, GL_DONT_CARE
3594 glGenerateMipmap(GL_TEXTURE_2D); // Generate mipmaps automatically
3595
3596 #define MIN(a,b) (((a)<(b))? (a):(b))
3597 #define MAX(a,b) (((a)>(b))? (a):(b))
3598
3599 *mipmaps = 1 + (int)floor(log(MAX(width, height))/log(2));
3600 TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Mipmaps generated automatically, total: %i", id, *mipmaps);
3601 }
3602 else TRACELOG(RL_LOG_WARNING, "TEXTURE: [ID %i] Failed to generate mipmaps", id);
3603
3604 glBindTexture(GL_TEXTURE_2D, 0);
3605#else
3606 TRACELOG(RL_LOG_WARNING, "TEXTURE: [ID %i] GPU mipmap generation not supported", id);
3607#endif
3608}
3609
3610// Read texture pixel data
3611void *rlReadTexturePixels(unsigned int id, int width, int height, int format)
3612{
3613 void *pixels = NULL;
3614
3615#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
3616 glBindTexture(GL_TEXTURE_2D, id);
3617
3618 // NOTE: Using texture id, we can retrieve some texture info (but not on OpenGL ES 2.0)
3619 // Possible texture info: GL_TEXTURE_RED_SIZE, GL_TEXTURE_GREEN_SIZE, GL_TEXTURE_BLUE_SIZE, GL_TEXTURE_ALPHA_SIZE
3620 //int width, height, format;
3621 //glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
3622 //glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
3623 //glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &format);
3624
3625 // NOTE: Each row written to or read from by OpenGL pixel operations like glGetTexImage are aligned to a 4 byte boundary by default, which may add some padding
3626 // Use glPixelStorei to modify padding with the GL_[UN]PACK_ALIGNMENT setting
3627 // GL_PACK_ALIGNMENT affects operations that read from OpenGL memory (glReadPixels, glGetTexImage, etc.)
3628 // GL_UNPACK_ALIGNMENT affects operations that write to OpenGL memory (glTexImage, etc.)
3629 glPixelStorei(GL_PACK_ALIGNMENT, 1);
3630
3631 unsigned int glInternalFormat, glFormat, glType;
3632 rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType);
3633 unsigned int size = rlGetPixelDataSize(width, height, format);
3634
3635 if ((glInternalFormat != 0) && (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB))
3636 {
3637 pixels = RL_MALLOC(size);
3638 glGetTexImage(GL_TEXTURE_2D, 0, glFormat, glType, pixels);
3639 }
3640 else TRACELOG(RL_LOG_WARNING, "TEXTURE: [ID %i] Data retrieval not suported for pixel format (%i)", id, format);
3641
3642 glBindTexture(GL_TEXTURE_2D, 0);
3643#endif
3644
3645#if defined(GRAPHICS_API_OPENGL_ES2)
3646 // glGetTexImage() is not available on OpenGL ES 2.0
3647 // Texture width and height are required on OpenGL ES 2.0, there is no way to get it from texture id
3648 // Two possible Options:
3649 // 1 - Bind texture to color fbo attachment and glReadPixels()
3650 // 2 - Create an fbo, activate it, render quad with texture, glReadPixels()
3651 // We are using Option 1, just need to care for texture format on retrieval
3652 // NOTE: This behaviour could be conditioned by graphic driver...
3653 unsigned int fboId = rlLoadFramebuffer();
3654
3655 glBindFramebuffer(GL_FRAMEBUFFER, fboId);
3656 glBindTexture(GL_TEXTURE_2D, 0);
3657
3658 // Attach our texture to FBO
3659 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, id, 0);
3660
3661 // We read data as RGBA because FBO texture is configured as RGBA, despite binding another texture format
3662 pixels = (unsigned char *)RL_MALLOC(rlGetPixelDataSize(width, height, RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8));
3663 glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
3664
3665 glBindFramebuffer(GL_FRAMEBUFFER, 0);
3666
3667 // Clean up temporal fbo
3668 rlUnloadFramebuffer(fboId);
3669#endif
3670
3671 return pixels;
3672}
3673
3674// Read screen pixel data (color buffer)
3675unsigned char *rlReadScreenPixels(int width, int height)
3676{
3677 unsigned char *screenData = (unsigned char *)RL_CALLOC(width*height*4, sizeof(unsigned char));
3678
3679 // NOTE 1: glReadPixels returns image flipped vertically -> (0,0) is the bottom left corner of the framebuffer
3680 // NOTE 2: We are getting alpha channel! Be careful, it can be transparent if not cleared properly!
3681 glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, screenData);
3682
3683 // Flip image vertically!
3684 unsigned char *imgData = (unsigned char *)RL_MALLOC(width*height*4*sizeof(unsigned char));
3685
3686 for (int y = height - 1; y >= 0; y--)
3687 {
3688 for (int x = 0; x < (width*4); x++)
3689 {
3690 imgData[((height - 1) - y)*width*4 + x] = screenData[(y*width*4) + x]; // Flip line
3691
3692 // Set alpha component value to 255 (no trasparent image retrieval)
3693 // NOTE: Alpha value has already been applied to RGB in framebuffer, we don't need it!
3694 if (((x + 1)%4) == 0) imgData[((height - 1) - y)*width*4 + x] = 255;
3695 }
3696 }
3697
3698 RL_FREE(screenData);
3699
3700 return imgData; // NOTE: image data should be freed
3701}
3702
3703// Framebuffer management (fbo)
3704//-----------------------------------------------------------------------------------------
3705// Load a framebuffer to be used for rendering
3706// NOTE: No textures attached
3707unsigned int rlLoadFramebuffer(void)
3708{
3709 unsigned int fboId = 0;
3710
3711#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(RLGL_RENDER_TEXTURES_HINT)
3712 glGenFramebuffers(1, &fboId); // Create the framebuffer object
3713 glBindFramebuffer(GL_FRAMEBUFFER, 0); // Unbind any framebuffer
3714#endif
3715
3716 return fboId;
3717}
3718
3719// Attach color buffer texture to an fbo (unloads previous attachment)
3720// NOTE: Attach type: 0-Color, 1-Depth renderbuffer, 2-Depth texture
3721void rlFramebufferAttach(unsigned int fboId, unsigned int texId, int attachType, int texType, int mipLevel)
3722{
3723#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(RLGL_RENDER_TEXTURES_HINT)
3724 glBindFramebuffer(GL_FRAMEBUFFER, fboId);
3725
3726 switch (attachType)
3727 {
3728 case RL_ATTACHMENT_COLOR_CHANNEL0:
3729 case RL_ATTACHMENT_COLOR_CHANNEL1:
3730 case RL_ATTACHMENT_COLOR_CHANNEL2:
3731 case RL_ATTACHMENT_COLOR_CHANNEL3:
3732 case RL_ATTACHMENT_COLOR_CHANNEL4:
3733 case RL_ATTACHMENT_COLOR_CHANNEL5:
3734 case RL_ATTACHMENT_COLOR_CHANNEL6:
3735 case RL_ATTACHMENT_COLOR_CHANNEL7:
3736 {
3737 if (texType == RL_ATTACHMENT_TEXTURE2D) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + attachType, GL_TEXTURE_2D, texId, mipLevel);
3738 else if (texType == RL_ATTACHMENT_RENDERBUFFER) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + attachType, GL_RENDERBUFFER, texId);
3739 else if (texType >= RL_ATTACHMENT_CUBEMAP_POSITIVE_X) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + attachType, GL_TEXTURE_CUBE_MAP_POSITIVE_X + texType, texId, mipLevel);
3740
3741 } break;
3742 case RL_ATTACHMENT_DEPTH:
3743 {
3744 if (texType == RL_ATTACHMENT_TEXTURE2D) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, texId, mipLevel);
3745 else if (texType == RL_ATTACHMENT_RENDERBUFFER) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, texId);
3746
3747 } break;
3748 case RL_ATTACHMENT_STENCIL:
3749 {
3750 if (texType == RL_ATTACHMENT_TEXTURE2D) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, texId, mipLevel);
3751 else if (texType == RL_ATTACHMENT_RENDERBUFFER) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, texId);
3752
3753 } break;
3754 default: break;
3755 }
3756
3757 glBindFramebuffer(GL_FRAMEBUFFER, 0);
3758#endif
3759}
3760
3761// Verify render texture is complete
3762bool rlFramebufferComplete(unsigned int id)
3763{
3764 bool result = false;
3765
3766#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(RLGL_RENDER_TEXTURES_HINT)
3767 glBindFramebuffer(GL_FRAMEBUFFER, id);
3768
3769 GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
3770
3771 if (status != GL_FRAMEBUFFER_COMPLETE)
3772 {
3773 switch (status)
3774 {
3775 case GL_FRAMEBUFFER_UNSUPPORTED: TRACELOG(RL_LOG_WARNING, "FBO: [ID %i] Framebuffer is unsupported", id); break;
3776 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: TRACELOG(RL_LOG_WARNING, "FBO: [ID %i] Framebuffer has incomplete attachment", id); break;
3777#if defined(GRAPHICS_API_OPENGL_ES2)
3778 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: TRACELOG(RL_LOG_WARNING, "FBO: [ID %i] Framebuffer has incomplete dimensions", id); break;
3779#endif
3780 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: TRACELOG(RL_LOG_WARNING, "FBO: [ID %i] Framebuffer has a missing attachment", id); break;
3781 default: break;
3782 }
3783 }
3784
3785 glBindFramebuffer(GL_FRAMEBUFFER, 0);
3786
3787 result = (status == GL_FRAMEBUFFER_COMPLETE);
3788#endif
3789
3790 return result;
3791}
3792
3793// Unload framebuffer from GPU memory
3794// NOTE: All attached textures/cubemaps/renderbuffers are also deleted
3795void rlUnloadFramebuffer(unsigned int id)
3796{
3797#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(RLGL_RENDER_TEXTURES_HINT)
3798 // Query depth attachment to automatically delete texture/renderbuffer
3799 int depthType = 0, depthId = 0;
3800 glBindFramebuffer(GL_FRAMEBUFFER, id); // Bind framebuffer to query depth texture type
3801 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &depthType);
3802
3803 // TODO: Review warning retrieving object name in WebGL
3804 // WARNING: WebGL: INVALID_ENUM: getFramebufferAttachmentParameter: invalid parameter name
3805 // https://registry.khronos.org/webgl/specs/latest/1.0/
3806 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &depthId);
3807
3808 unsigned int depthIdU = (unsigned int)depthId;
3809 if (depthType == GL_RENDERBUFFER) glDeleteRenderbuffers(1, &depthIdU);
3810 else if (depthType == GL_TEXTURE) glDeleteTextures(1, &depthIdU);
3811
3812 // NOTE: If a texture object is deleted while its image is attached to the *currently bound* framebuffer,
3813 // the texture image is automatically detached from the currently bound framebuffer
3814
3815 glBindFramebuffer(GL_FRAMEBUFFER, 0);
3816 glDeleteFramebuffers(1, &id);
3817
3818 TRACELOG(RL_LOG_INFO, "FBO: [ID %i] Unloaded framebuffer from VRAM (GPU)", id);
3819#endif
3820}
3821
3822// Vertex data management
3823//-----------------------------------------------------------------------------------------
3824// Load a new attributes buffer
3825unsigned int rlLoadVertexBuffer(const void *buffer, int size, bool dynamic)
3826{
3827 unsigned int id = 0;
3828
3829#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
3830 glGenBuffers(1, &id);
3831 glBindBuffer(GL_ARRAY_BUFFER, id);
3832 glBufferData(GL_ARRAY_BUFFER, size, buffer, dynamic? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
3833#endif
3834
3835 return id;
3836}
3837
3838// Load a new attributes element buffer
3839unsigned int rlLoadVertexBufferElement(const void *buffer, int size, bool dynamic)
3840{
3841 unsigned int id = 0;
3842
3843#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
3844 glGenBuffers(1, &id);
3845 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, id);
3846 glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, buffer, dynamic? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
3847#endif
3848
3849 return id;
3850}
3851
3852// Enable vertex buffer (VBO)
3853void rlEnableVertexBuffer(unsigned int id)
3854{
3855#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
3856 glBindBuffer(GL_ARRAY_BUFFER, id);
3857#endif
3858}
3859
3860// Disable vertex buffer (VBO)
3861void rlDisableVertexBuffer(void)
3862{
3863#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
3864 glBindBuffer(GL_ARRAY_BUFFER, 0);
3865#endif
3866}
3867
3868// Enable vertex buffer element (VBO element)
3869void rlEnableVertexBufferElement(unsigned int id)
3870{
3871#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
3872 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, id);
3873#endif
3874}
3875
3876// Disable vertex buffer element (VBO element)
3877void rlDisableVertexBufferElement(void)
3878{
3879#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
3880 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
3881#endif
3882}
3883
3884// Update vertex buffer with new data
3885// NOTE: dataSize and offset must be provided in bytes
3886void rlUpdateVertexBuffer(unsigned int id, const void *data, int dataSize, int offset)
3887{
3888#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
3889 glBindBuffer(GL_ARRAY_BUFFER, id);
3890 glBufferSubData(GL_ARRAY_BUFFER, offset, dataSize, data);
3891#endif
3892}
3893
3894// Update vertex buffer elements with new data
3895// NOTE: dataSize and offset must be provided in bytes
3896void rlUpdateVertexBufferElements(unsigned int id, const void *data, int dataSize, int offset)
3897{
3898#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
3899 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, id);
3900 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset, dataSize, data);
3901#endif
3902}
3903
3904// Enable vertex array object (VAO)
3905bool rlEnableVertexArray(unsigned int vaoId)
3906{
3907 bool result = false;
3908#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
3909 if (RLGL.ExtSupported.vao)
3910 {
3911 glBindVertexArray(vaoId);
3912 result = true;
3913 }
3914#endif
3915 return result;
3916}
3917
3918// Disable vertex array object (VAO)
3919void rlDisableVertexArray(void)
3920{
3921#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
3922 if (RLGL.ExtSupported.vao) glBindVertexArray(0);
3923#endif
3924}
3925
3926// Enable vertex attribute index
3927void rlEnableVertexAttribute(unsigned int index)
3928{
3929#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
3930 glEnableVertexAttribArray(index);
3931#endif
3932}
3933
3934// Disable vertex attribute index
3935void rlDisableVertexAttribute(unsigned int index)
3936{
3937#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
3938 glDisableVertexAttribArray(index);
3939#endif
3940}
3941
3942// Draw vertex array
3943void rlDrawVertexArray(int offset, int count)
3944{
3945 glDrawArrays(GL_TRIANGLES, offset, count);
3946}
3947
3948// Draw vertex array elements
3949void rlDrawVertexArrayElements(int offset, int count, const void *buffer)
3950{
3951 // NOTE: Added pointer math separately from function to avoid UBSAN complaining
3952 unsigned short *bufferPtr = (unsigned short *)buffer;
3953 if (offset > 0) bufferPtr += offset;
3954
3955 glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, (const unsigned short *)bufferPtr);
3956}
3957
3958// Draw vertex array instanced
3959void rlDrawVertexArrayInstanced(int offset, int count, int instances)
3960{
3961#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
3962 glDrawArraysInstanced(GL_TRIANGLES, 0, count, instances);
3963#endif
3964}
3965
3966// Draw vertex array elements instanced
3967void rlDrawVertexArrayElementsInstanced(int offset, int count, const void *buffer, int instances)
3968{
3969#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
3970 // NOTE: Added pointer math separately from function to avoid UBSAN complaining
3971 unsigned short *bufferPtr = (unsigned short *)buffer;
3972 if (offset > 0) bufferPtr += offset;
3973
3974 glDrawElementsInstanced(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, (const unsigned short *)bufferPtr, instances);
3975#endif
3976}
3977
3978#if defined(GRAPHICS_API_OPENGL_11)
3979// Enable vertex state pointer
3980void rlEnableStatePointer(int vertexAttribType, void *buffer)
3981{
3982 if (buffer != NULL) glEnableClientState(vertexAttribType);
3983 switch (vertexAttribType)
3984 {
3985 case GL_VERTEX_ARRAY: glVertexPointer(3, GL_FLOAT, 0, buffer); break;
3986 case GL_TEXTURE_COORD_ARRAY: glTexCoordPointer(2, GL_FLOAT, 0, buffer); break;
3987 case GL_NORMAL_ARRAY: if (buffer != NULL) glNormalPointer(GL_FLOAT, 0, buffer); break;
3988 case GL_COLOR_ARRAY: if (buffer != NULL) glColorPointer(4, GL_UNSIGNED_BYTE, 0, buffer); break;
3989 //case GL_INDEX_ARRAY: if (buffer != NULL) glIndexPointer(GL_SHORT, 0, buffer); break; // Indexed colors
3990 default: break;
3991 }
3992}
3993
3994// Disable vertex state pointer
3995void rlDisableStatePointer(int vertexAttribType)
3996{
3997 glDisableClientState(vertexAttribType);
3998}
3999#endif
4000
4001// Load vertex array object (VAO)
4002unsigned int rlLoadVertexArray(void)
4003{
4004 unsigned int vaoId = 0;
4005#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
4006 if (RLGL.ExtSupported.vao)
4007 {
4008 glGenVertexArrays(1, &vaoId);
4009 }
4010#endif
4011 return vaoId;
4012}
4013
4014// Set vertex attribute
4015void rlSetVertexAttribute(unsigned int index, int compSize, int type, bool normalized, int stride, int offset)
4016{
4017#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
4018 // NOTE: Data type could be: GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT
4019 // Additional types (depends on OpenGL version or extensions):
4020 // - GL_HALF_FLOAT, GL_FLOAT, GL_DOUBLE, GL_FIXED,
4021 // - GL_INT_2_10_10_10_REV, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT_10F_11F_11F_REV
4022
4023 size_t offsetNative = offset;
4024 glVertexAttribPointer(index, compSize, type, normalized, stride, (void *)offsetNative);
4025#endif
4026}
4027
4028// Set vertex attribute divisor
4029void rlSetVertexAttributeDivisor(unsigned int index, int divisor)
4030{
4031#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
4032 glVertexAttribDivisor(index, divisor);
4033#endif
4034}
4035
4036// Unload vertex array object (VAO)
4037void rlUnloadVertexArray(unsigned int vaoId)
4038{
4039#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
4040 if (RLGL.ExtSupported.vao)
4041 {
4042 glBindVertexArray(0);
4043 glDeleteVertexArrays(1, &vaoId);
4044 TRACELOG(RL_LOG_INFO, "VAO: [ID %i] Unloaded vertex array data from VRAM (GPU)", vaoId);
4045 }
4046#endif
4047}
4048
4049// Unload vertex buffer (VBO)
4050void rlUnloadVertexBuffer(unsigned int vboId)
4051{
4052#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
4053 glDeleteBuffers(1, &vboId);
4054 //TRACELOG(RL_LOG_INFO, "VBO: Unloaded vertex data from VRAM (GPU)");
4055#endif
4056}
4057
4058// Shaders management
4059//-----------------------------------------------------------------------------------------------
4060// Load shader from code strings
4061// NOTE: If shader string is NULL, using default vertex/fragment shaders
4062unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode)
4063{
4064 unsigned int id = 0;
4065
4066#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
4067 unsigned int vertexShaderId = 0;
4068 unsigned int fragmentShaderId = 0;
4069
4070 // Compile vertex shader (if provided)
4071 // NOTE: If not vertex shader is provided, use default one
4072 if (vsCode != NULL) vertexShaderId = rlCompileShader(vsCode, GL_VERTEX_SHADER);
4073 else vertexShaderId = RLGL.State.defaultVShaderId;
4074
4075 // Compile fragment shader (if provided)
4076 // NOTE: If not vertex shader is provided, use default one
4077 if (fsCode != NULL) fragmentShaderId = rlCompileShader(fsCode, GL_FRAGMENT_SHADER);
4078 else fragmentShaderId = RLGL.State.defaultFShaderId;
4079
4080 // In case vertex and fragment shader are the default ones, no need to recompile, we can just assign the default shader program id
4081 if ((vertexShaderId == RLGL.State.defaultVShaderId) && (fragmentShaderId == RLGL.State.defaultFShaderId)) id = RLGL.State.defaultShaderId;
4082 else if ((vertexShaderId > 0) && (fragmentShaderId > 0))
4083 {
4084 // One of or both shader are new, we need to compile a new shader program
4085 id = rlLoadShaderProgram(vertexShaderId, fragmentShaderId);
4086
4087 // We can detach and delete vertex/fragment shaders (if not default ones)
4088 // NOTE: We detach shader before deletion to make sure memory is freed
4089 if (vertexShaderId != RLGL.State.defaultVShaderId)
4090 {
4091 // WARNING: Shader program linkage could fail and returned id is 0
4092 if (id > 0) glDetachShader(id, vertexShaderId);
4093 glDeleteShader(vertexShaderId);
4094 }
4095 if (fragmentShaderId != RLGL.State.defaultFShaderId)
4096 {
4097 // WARNING: Shader program linkage could fail and returned id is 0
4098 if (id > 0) glDetachShader(id, fragmentShaderId);
4099 glDeleteShader(fragmentShaderId);
4100 }
4101
4102 // In case shader program loading failed, we assign default shader
4103 if (id == 0)
4104 {
4105 // In case shader loading fails, we return the default shader
4106 TRACELOG(RL_LOG_WARNING, "SHADER: Failed to load custom shader code, using default shader");
4107 id = RLGL.State.defaultShaderId;
4108 }
4109 /*
4110 else
4111 {
4112 // Get available shader uniforms
4113 // NOTE: This information is useful for debug...
4114 int uniformCount = -1;
4115 glGetProgramiv(id, GL_ACTIVE_UNIFORMS, &uniformCount);
4116
4117 for (int i = 0; i < uniformCount; i++)
4118 {
4119 int namelen = -1;
4120 int num = -1;
4121 char name[256] = { 0 }; // Assume no variable names longer than 256
4122 GLenum type = GL_ZERO;
4123
4124 // Get the name of the uniforms
4125 glGetActiveUniform(id, i, sizeof(name) - 1, &namelen, &num, &type, name);
4126
4127 name[namelen] = 0;
4128 TRACELOGD("SHADER: [ID %i] Active uniform (%s) set at location: %i", id, name, glGetUniformLocation(id, name));
4129 }
4130 }
4131 */
4132 }
4133#endif
4134
4135 return id;
4136}
4137
4138// Compile custom shader and return shader id
4139unsigned int rlCompileShader(const char *shaderCode, int type)
4140{
4141 unsigned int shader = 0;
4142
4143#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
4144 shader = glCreateShader(type);
4145 glShaderSource(shader, 1, &shaderCode, NULL);
4146
4147 GLint success = 0;
4148 glCompileShader(shader);
4149 glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
4150
4151 if (success == GL_FALSE)
4152 {
4153 switch (type)
4154 {
4155 case GL_VERTEX_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to compile vertex shader code", shader); break;
4156 case GL_FRAGMENT_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to compile fragment shader code", shader); break;
4157 //case GL_GEOMETRY_SHADER:
4158 #if defined(GRAPHICS_API_OPENGL_43)
4159 case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to compile compute shader code", shader); break;
4160 #elif defined(GRAPHICS_API_OPENGL_33)
4161 case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: Compute shaders not enabled. Define GRAPHICS_API_OPENGL_43", shader); break;
4162 #endif
4163 default: break;
4164 }
4165
4166 int maxLength = 0;
4167 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
4168
4169 if (maxLength > 0)
4170 {
4171 int length = 0;
4172 char *log = (char *)RL_CALLOC(maxLength, sizeof(char));
4173 glGetShaderInfoLog(shader, maxLength, &length, log);
4174 TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Compile error: %s", shader, log);
4175 RL_FREE(log);
4176 }
4177
4178 shader = 0;
4179 }
4180 else
4181 {
4182 switch (type)
4183 {
4184 case GL_VERTEX_SHADER: TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Vertex shader compiled successfully", shader); break;
4185 case GL_FRAGMENT_SHADER: TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Fragment shader compiled successfully", shader); break;
4186 //case GL_GEOMETRY_SHADER:
4187 #if defined(GRAPHICS_API_OPENGL_43)
4188 case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Compute shader compiled successfully", shader); break;
4189 #elif defined(GRAPHICS_API_OPENGL_33)
4190 case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: Compute shaders not enabled. Define GRAPHICS_API_OPENGL_43", shader); break;
4191 #endif
4192 default: break;
4193 }
4194 }
4195#endif
4196
4197 return shader;
4198}
4199
4200// Load custom shader strings and return program id
4201unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId)
4202{
4203 unsigned int program = 0;
4204
4205#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
4206 GLint success = 0;
4207 program = glCreateProgram();
4208
4209 glAttachShader(program, vShaderId);
4210 glAttachShader(program, fShaderId);
4211
4212 // NOTE: Default attribute shader locations must be Bound before linking
4213 glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION, RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION);
4214 glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD);
4215 glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL, RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL);
4216 glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR, RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR);
4217 glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT, RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT);
4218 glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2);
4219
4220#ifdef RL_SUPPORT_MESH_GPU_SKINNING
4221 glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS);
4222 glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS);
4223#endif
4224
4225 // NOTE: If some attrib name is no found on the shader, it locations becomes -1
4226
4227 glLinkProgram(program);
4228
4229 // NOTE: All uniform variables are intitialised to 0 when a program links
4230
4231 glGetProgramiv(program, GL_LINK_STATUS, &success);
4232
4233 if (success == GL_FALSE)
4234 {
4235 TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to link shader program", program);
4236
4237 int maxLength = 0;
4238 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
4239
4240 if (maxLength > 0)
4241 {
4242 int length = 0;
4243 char *log = (char *)RL_CALLOC(maxLength, sizeof(char));
4244 glGetProgramInfoLog(program, maxLength, &length, log);
4245 TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Link error: %s", program, log);
4246 RL_FREE(log);
4247 }
4248
4249 glDeleteProgram(program);
4250
4251 program = 0;
4252 }
4253 else
4254 {
4255 // Get the size of compiled shader program (not available on OpenGL ES 2.0)
4256 // NOTE: If GL_LINK_STATUS is GL_FALSE, program binary length is zero
4257 //GLint binarySize = 0;
4258 //glGetProgramiv(id, GL_PROGRAM_BINARY_LENGTH, &binarySize);
4259
4260 TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Program shader loaded successfully", program);
4261 }
4262#endif
4263 return program;
4264}
4265
4266// Unload shader program
4267void rlUnloadShaderProgram(unsigned int id)
4268{
4269#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
4270 glDeleteProgram(id);
4271
4272 TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Unloaded shader program data from VRAM (GPU)", id);
4273#endif
4274}
4275
4276// Get shader location uniform
4277int rlGetLocationUniform(unsigned int shaderId, const char *uniformName)
4278{
4279 int location = -1;
4280#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
4281 location = glGetUniformLocation(shaderId, uniformName);
4282
4283 //if (location == -1) TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to find shader uniform: %s", shaderId, uniformName);
4284 //else TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Shader uniform (%s) set at location: %i", shaderId, uniformName, location);
4285#endif
4286 return location;
4287}
4288
4289// Get shader location attribute
4290int rlGetLocationAttrib(unsigned int shaderId, const char *attribName)
4291{
4292 int location = -1;
4293#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
4294 location = glGetAttribLocation(shaderId, attribName);
4295
4296 //if (location == -1) TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to find shader attribute: %s", shaderId, attribName);
4297 //else TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Shader attribute (%s) set at location: %i", shaderId, attribName, location);
4298#endif
4299 return location;
4300}
4301
4302// Set shader value uniform
4303void rlSetUniform(int locIndex, const void *value, int uniformType, int count)
4304{
4305#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
4306 switch (uniformType)
4307 {
4308 case RL_SHADER_UNIFORM_FLOAT: glUniform1fv(locIndex, count, (float *)value); break;
4309 case RL_SHADER_UNIFORM_VEC2: glUniform2fv(locIndex, count, (float *)value); break;
4310 case RL_SHADER_UNIFORM_VEC3: glUniform3fv(locIndex, count, (float *)value); break;
4311 case RL_SHADER_UNIFORM_VEC4: glUniform4fv(locIndex, count, (float *)value); break;
4312 case RL_SHADER_UNIFORM_INT: glUniform1iv(locIndex, count, (int *)value); break;
4313 case RL_SHADER_UNIFORM_IVEC2: glUniform2iv(locIndex, count, (int *)value); break;
4314 case RL_SHADER_UNIFORM_IVEC3: glUniform3iv(locIndex, count, (int *)value); break;
4315 case RL_SHADER_UNIFORM_IVEC4: glUniform4iv(locIndex, count, (int *)value); break;
4316 #if !defined(GRAPHICS_API_OPENGL_ES2)
4317 case RL_SHADER_UNIFORM_UINT: glUniform1uiv(locIndex, count, (unsigned int *)value); break;
4318 case RL_SHADER_UNIFORM_UIVEC2: glUniform2uiv(locIndex, count, (unsigned int *)value); break;
4319 case RL_SHADER_UNIFORM_UIVEC3: glUniform3uiv(locIndex, count, (unsigned int *)value); break;
4320 case RL_SHADER_UNIFORM_UIVEC4: glUniform4uiv(locIndex, count, (unsigned int *)value); break;
4321 #endif
4322 case RL_SHADER_UNIFORM_SAMPLER2D: glUniform1iv(locIndex, count, (int *)value); break;
4323 default: TRACELOG(RL_LOG_WARNING, "SHADER: Failed to set uniform value, data type not recognized");
4324
4325 // TODO: Support glUniform1uiv(), glUniform2uiv(), glUniform3uiv(), glUniform4uiv()
4326 }
4327#endif
4328}
4329
4330// Set shader value attribute
4331void rlSetVertexAttributeDefault(int locIndex, const void *value, int attribType, int count)
4332{
4333#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
4334 switch (attribType)
4335 {
4336 case RL_SHADER_ATTRIB_FLOAT: if (count == 1) glVertexAttrib1fv(locIndex, (float *)value); break;
4337 case RL_SHADER_ATTRIB_VEC2: if (count == 2) glVertexAttrib2fv(locIndex, (float *)value); break;
4338 case RL_SHADER_ATTRIB_VEC3: if (count == 3) glVertexAttrib3fv(locIndex, (float *)value); break;
4339 case RL_SHADER_ATTRIB_VEC4: if (count == 4) glVertexAttrib4fv(locIndex, (float *)value); break;
4340 default: TRACELOG(RL_LOG_WARNING, "SHADER: Failed to set attrib default value, data type not recognized");
4341 }
4342#endif
4343}
4344
4345// Set shader value uniform matrix
4346void rlSetUniformMatrix(int locIndex, Matrix mat)
4347{
4348#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
4349 float matfloat[16] = {
4350 mat.m0, mat.m1, mat.m2, mat.m3,
4351 mat.m4, mat.m5, mat.m6, mat.m7,
4352 mat.m8, mat.m9, mat.m10, mat.m11,
4353 mat.m12, mat.m13, mat.m14, mat.m15
4354 };
4355 glUniformMatrix4fv(locIndex, 1, false, matfloat);
4356#endif
4357}
4358
4359// Set shader value uniform matrix
4360void rlSetUniformMatrices(int locIndex, const Matrix *matrices, int count)
4361{
4362#if defined(GRAPHICS_API_OPENGL_33)
4363 glUniformMatrix4fv(locIndex, count, true, (const float *)matrices);
4364#elif defined(GRAPHICS_API_OPENGL_ES2)
4365 // WARNING: WebGL does not support Matrix transpose ("true" parameter)
4366 // REF: https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/uniformMatrix
4367 glUniformMatrix4fv(locIndex, count, false, (const float *)matrices);
4368#endif
4369}
4370
4371// Set shader value uniform sampler
4372void rlSetUniformSampler(int locIndex, unsigned int textureId)
4373{
4374#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
4375 // Check if texture is already active
4376 for (int i = 0; i < RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS; i++)
4377 {
4378 if (RLGL.State.activeTextureId[i] == textureId)
4379 {
4380 glUniform1i(locIndex, 1 + i);
4381 return;
4382 }
4383 }
4384
4385 // Register a new active texture for the internal batch system
4386 // NOTE: Default texture is always activated as GL_TEXTURE0
4387 for (int i = 0; i < RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS; i++)
4388 {
4389 if (RLGL.State.activeTextureId[i] == 0)
4390 {
4391 glUniform1i(locIndex, 1 + i); // Activate new texture unit
4392 RLGL.State.activeTextureId[i] = textureId; // Save texture id for binding on drawing
4393 break;
4394 }
4395 }
4396#endif
4397}
4398
4399// Set shader currently active (id and locations)
4400void rlSetShader(unsigned int id, int *locs)
4401{
4402#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
4403 if (RLGL.State.currentShaderId != id)
4404 {
4405 rlDrawRenderBatch(RLGL.currentBatch);
4406 RLGL.State.currentShaderId = id;
4407 RLGL.State.currentShaderLocs = locs;
4408 }
4409#endif
4410}
4411
4412// Load compute shader program
4413unsigned int rlLoadComputeShaderProgram(unsigned int shaderId)
4414{
4415 unsigned int program = 0;
4416
4417#if defined(GRAPHICS_API_OPENGL_43)
4418 GLint success = 0;
4419 program = glCreateProgram();
4420 glAttachShader(program, shaderId);
4421 glLinkProgram(program);
4422
4423 // NOTE: All uniform variables are intitialised to 0 when a program links
4424
4425 glGetProgramiv(program, GL_LINK_STATUS, &success);
4426
4427 if (success == GL_FALSE)
4428 {
4429 TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to link compute shader program", program);
4430
4431 int maxLength = 0;
4432 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
4433
4434 if (maxLength > 0)
4435 {
4436 int length = 0;
4437 char *log = (char *)RL_CALLOC(maxLength, sizeof(char));
4438 glGetProgramInfoLog(program, maxLength, &length, log);
4439 TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Link error: %s", program, log);
4440 RL_FREE(log);
4441 }
4442
4443 glDeleteProgram(program);
4444
4445 program = 0;
4446 }
4447 else
4448 {
4449 // Get the size of compiled shader program (not available on OpenGL ES 2.0)
4450 // NOTE: If GL_LINK_STATUS is GL_FALSE, program binary length is zero
4451 //GLint binarySize = 0;
4452 //glGetProgramiv(id, GL_PROGRAM_BINARY_LENGTH, &binarySize);
4453
4454 TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Compute shader program loaded successfully", program);
4455 }
4456#else
4457 TRACELOG(RL_LOG_WARNING, "SHADER: Compute shaders not enabled. Define GRAPHICS_API_OPENGL_43");
4458#endif
4459
4460 return program;
4461}
4462
4463// Dispatch compute shader (equivalent to *draw* for graphics pilepine)
4464void rlComputeShaderDispatch(unsigned int groupX, unsigned int groupY, unsigned int groupZ)
4465{
4466#if defined(GRAPHICS_API_OPENGL_43)
4467 glDispatchCompute(groupX, groupY, groupZ);
4468#endif
4469}
4470
4471// Load shader storage buffer object (SSBO)
4472unsigned int rlLoadShaderBuffer(unsigned int size, const void *data, int usageHint)
4473{
4474 unsigned int ssbo = 0;
4475
4476#if defined(GRAPHICS_API_OPENGL_43)
4477 glGenBuffers(1, &ssbo);
4478 glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
4479 glBufferData(GL_SHADER_STORAGE_BUFFER, size, data, usageHint? usageHint : RL_STREAM_COPY);
4480 if (data == NULL) glClearBufferData(GL_SHADER_STORAGE_BUFFER, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, NULL); // Clear buffer data to 0
4481 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
4482#else
4483 TRACELOG(RL_LOG_WARNING, "SSBO: SSBO not enabled. Define GRAPHICS_API_OPENGL_43");
4484#endif
4485
4486 return ssbo;
4487}
4488
4489// Unload shader storage buffer object (SSBO)
4490void rlUnloadShaderBuffer(unsigned int ssboId)
4491{
4492#if defined(GRAPHICS_API_OPENGL_43)
4493 glDeleteBuffers(1, &ssboId);
4494#else
4495 TRACELOG(RL_LOG_WARNING, "SSBO: SSBO not enabled. Define GRAPHICS_API_OPENGL_43");
4496#endif
4497
4498}
4499
4500// Update SSBO buffer data
4501void rlUpdateShaderBuffer(unsigned int id, const void *data, unsigned int dataSize, unsigned int offset)
4502{
4503#if defined(GRAPHICS_API_OPENGL_43)
4504 glBindBuffer(GL_SHADER_STORAGE_BUFFER, id);
4505 glBufferSubData(GL_SHADER_STORAGE_BUFFER, offset, dataSize, data);
4506#endif
4507}
4508
4509// Get SSBO buffer size
4510unsigned int rlGetShaderBufferSize(unsigned int id)
4511{
4512#if defined(GRAPHICS_API_OPENGL_43)
4513 GLint64 size = 0;
4514 glBindBuffer(GL_SHADER_STORAGE_BUFFER, id);
4515 glGetBufferParameteri64v(GL_SHADER_STORAGE_BUFFER, GL_BUFFER_SIZE, &size);
4516 return (size > 0)? (unsigned int)size : 0;
4517#else
4518 return 0;
4519#endif
4520}
4521
4522// Read SSBO buffer data (GPU->CPU)
4523void rlReadShaderBuffer(unsigned int id, void *dest, unsigned int count, unsigned int offset)
4524{
4525#if defined(GRAPHICS_API_OPENGL_43)
4526 glBindBuffer(GL_SHADER_STORAGE_BUFFER, id);
4527 glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, offset, count, dest);
4528#endif
4529}
4530
4531// Bind SSBO buffer
4532void rlBindShaderBuffer(unsigned int id, unsigned int index)
4533{
4534#if defined(GRAPHICS_API_OPENGL_43)
4535 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, index, id);
4536#endif
4537}
4538
4539// Copy SSBO buffer data
4540void rlCopyShaderBuffer(unsigned int destId, unsigned int srcId, unsigned int destOffset, unsigned int srcOffset, unsigned int count)
4541{
4542#if defined(GRAPHICS_API_OPENGL_43)
4543 glBindBuffer(GL_COPY_READ_BUFFER, srcId);
4544 glBindBuffer(GL_COPY_WRITE_BUFFER, destId);
4545 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, srcOffset, destOffset, count);
4546#endif
4547}
4548
4549// Bind image texture
4550void rlBindImageTexture(unsigned int id, unsigned int index, int format, bool readonly)
4551{
4552#if defined(GRAPHICS_API_OPENGL_43)
4553 unsigned int glInternalFormat = 0, glFormat = 0, glType = 0;
4554
4555 rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType);
4556 glBindImageTexture(index, id, 0, 0, 0, readonly? GL_READ_ONLY : GL_READ_WRITE, glInternalFormat);
4557#else
4558 TRACELOG(RL_LOG_WARNING, "TEXTURE: Image texture binding not enabled. Define GRAPHICS_API_OPENGL_43");
4559#endif
4560}
4561
4562// Matrix state management
4563//-----------------------------------------------------------------------------------------
4564// Get internal modelview matrix
4565Matrix rlGetMatrixModelview(void)
4566{
4567 Matrix matrix = rlMatrixIdentity();
4568#if defined(GRAPHICS_API_OPENGL_11)
4569 float mat[16];
4570 glGetFloatv(GL_MODELVIEW_MATRIX, mat);
4571 matrix.m0 = mat[0];
4572 matrix.m1 = mat[1];
4573 matrix.m2 = mat[2];
4574 matrix.m3 = mat[3];
4575 matrix.m4 = mat[4];
4576 matrix.m5 = mat[5];
4577 matrix.m6 = mat[6];
4578 matrix.m7 = mat[7];
4579 matrix.m8 = mat[8];
4580 matrix.m9 = mat[9];
4581 matrix.m10 = mat[10];
4582 matrix.m11 = mat[11];
4583 matrix.m12 = mat[12];
4584 matrix.m13 = mat[13];
4585 matrix.m14 = mat[14];
4586 matrix.m15 = mat[15];
4587#else
4588 matrix = RLGL.State.modelview;
4589#endif
4590 return matrix;
4591}
4592
4593// Get internal projection matrix
4594Matrix rlGetMatrixProjection(void)
4595{
4596#if defined(GRAPHICS_API_OPENGL_11)
4597 float mat[16];
4598 glGetFloatv(GL_PROJECTION_MATRIX,mat);
4599 Matrix m;
4600 m.m0 = mat[0];
4601 m.m1 = mat[1];
4602 m.m2 = mat[2];
4603 m.m3 = mat[3];
4604 m.m4 = mat[4];
4605 m.m5 = mat[5];
4606 m.m6 = mat[6];
4607 m.m7 = mat[7];
4608 m.m8 = mat[8];
4609 m.m9 = mat[9];
4610 m.m10 = mat[10];
4611 m.m11 = mat[11];
4612 m.m12 = mat[12];
4613 m.m13 = mat[13];
4614 m.m14 = mat[14];
4615 m.m15 = mat[15];
4616 return m;
4617#else
4618 return RLGL.State.projection;
4619#endif
4620}
4621
4622// Get internal accumulated transform matrix
4623Matrix rlGetMatrixTransform(void)
4624{
4625 Matrix mat = rlMatrixIdentity();
4626#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
4627 // TODO: Consider possible transform matrices in the RLGL.State.stack
4628 // Is this the right order? or should we start with the first stored matrix instead of the last one?
4629 //Matrix matStackTransform = rlMatrixIdentity();
4630 //for (int i = RLGL.State.stackCounter; i > 0; i--) matStackTransform = rlMatrixMultiply(RLGL.State.stack[i], matStackTransform);
4631 mat = RLGL.State.transform;
4632#endif
4633 return mat;
4634}
4635
4636// Get internal projection matrix for stereo render (selected eye)
4637Matrix rlGetMatrixProjectionStereo(int eye)
4638{
4639 Matrix mat = rlMatrixIdentity();
4640#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
4641 mat = RLGL.State.projectionStereo[eye];
4642#endif
4643 return mat;
4644}
4645
4646// Get internal view offset matrix for stereo render (selected eye)
4647Matrix rlGetMatrixViewOffsetStereo(int eye)
4648{
4649 Matrix mat = rlMatrixIdentity();
4650#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
4651 mat = RLGL.State.viewOffsetStereo[eye];
4652#endif
4653 return mat;
4654}
4655
4656// Set a custom modelview matrix (replaces internal modelview matrix)
4657void rlSetMatrixModelview(Matrix view)
4658{
4659#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
4660 RLGL.State.modelview = view;
4661#endif
4662}
4663
4664// Set a custom projection matrix (replaces internal projection matrix)
4665void rlSetMatrixProjection(Matrix projection)
4666{
4667#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
4668 RLGL.State.projection = projection;
4669#endif
4670}
4671
4672// Set eyes projection matrices for stereo rendering
4673void rlSetMatrixProjectionStereo(Matrix right, Matrix left)
4674{
4675#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
4676 RLGL.State.projectionStereo[0] = right;
4677 RLGL.State.projectionStereo[1] = left;
4678#endif
4679}
4680
4681// Set eyes view offsets matrices for stereo rendering
4682void rlSetMatrixViewOffsetStereo(Matrix right, Matrix left)
4683{
4684#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
4685 RLGL.State.viewOffsetStereo[0] = right;
4686 RLGL.State.viewOffsetStereo[1] = left;
4687#endif
4688}
4689
4690// Load and draw a quad in NDC
4691void rlLoadDrawQuad(void)
4692{
4693#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
4694 unsigned int quadVAO = 0;
4695 unsigned int quadVBO = 0;
4696
4697 float vertices[] = {
4698 // Positions Texcoords
4699 -1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
4700 -1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
4701 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
4702 1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
4703 };
4704
4705 // Gen VAO to contain VBO
4706 glGenVertexArrays(1, &quadVAO);
4707 glBindVertexArray(quadVAO);
4708
4709 // Gen and fill vertex buffer (VBO)
4710 glGenBuffers(1, &quadVBO);
4711 glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
4712 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices, GL_STATIC_DRAW);
4713
4714 // Bind vertex attributes (position, texcoords)
4715 glEnableVertexAttribArray(RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION);
4716 glVertexAttribPointer(RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION, 3, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void *)0); // Positions
4717 glEnableVertexAttribArray(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD);
4718 glVertexAttribPointer(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void *)(3*sizeof(float))); // Texcoords
4719
4720 // Draw quad
4721 glBindVertexArray(quadVAO);
4722 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4723 glBindVertexArray(0);
4724
4725 // Delete buffers (VBO and VAO)
4726 glDeleteBuffers(1, &quadVBO);
4727 glDeleteVertexArrays(1, &quadVAO);
4728#endif
4729}
4730
4731// Load and draw a cube in NDC
4732void rlLoadDrawCube(void)
4733{
4734#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
4735 unsigned int cubeVAO = 0;
4736 unsigned int cubeVBO = 0;
4737
4738 float vertices[] = {
4739 // Positions Normals Texcoords
4740 -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
4741 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f,
4742 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f,
4743 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f,
4744 -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
4745 -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f,
4746 -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
4747 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f,
4748 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
4749 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
4750 -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,
4751 -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
4752 -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
4753 -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
4754 -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
4755 -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
4756 -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
4757 -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
4758 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
4759 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
4760 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
4761 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
4762 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
4763 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
4764 -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f,
4765 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f,
4766 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f,
4767 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f,
4768 -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f,
4769 -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f,
4770 -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
4771 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
4772 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,
4773 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
4774 -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
4775 -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f
4776 };
4777
4778 // Gen VAO to contain VBO
4779 glGenVertexArrays(1, &cubeVAO);
4780 glBindVertexArray(cubeVAO);
4781
4782 // Gen and fill vertex buffer (VBO)
4783 glGenBuffers(1, &cubeVBO);
4784 glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
4785 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
4786
4787 // Bind vertex attributes (position, normals, texcoords)
4788 glBindVertexArray(cubeVAO);
4789 glEnableVertexAttribArray(RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION);
4790 glVertexAttribPointer(RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION, 3, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)0); // Positions
4791 glEnableVertexAttribArray(RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL);
4792 glVertexAttribPointer(RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL, 3, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)(3*sizeof(float))); // Normals
4793 glEnableVertexAttribArray(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD);
4794 glVertexAttribPointer(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)(6*sizeof(float))); // Texcoords
4795 glBindBuffer(GL_ARRAY_BUFFER, 0);
4796 glBindVertexArray(0);
4797
4798 // Draw cube
4799 glBindVertexArray(cubeVAO);
4800 glDrawArrays(GL_TRIANGLES, 0, 36);
4801 glBindVertexArray(0);
4802
4803 // Delete VBO and VAO
4804 glDeleteBuffers(1, &cubeVBO);
4805 glDeleteVertexArrays(1, &cubeVAO);
4806#endif
4807}
4808
4809// Get name string for pixel format
4810const char *rlGetPixelFormatName(unsigned int format)
4811{
4812 switch (format)
4813 {
4814 case RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: return "GRAYSCALE"; break; // 8 bit per pixel (no alpha)
4815 case RL_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: return "GRAY_ALPHA"; break; // 8*2 bpp (2 channels)
4816 case RL_PIXELFORMAT_UNCOMPRESSED_R5G6B5: return "R5G6B5"; break; // 16 bpp
4817 case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8: return "R8G8B8"; break; // 24 bpp
4818 case RL_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: return "R5G5B5A1"; break; // 16 bpp (1 bit alpha)
4819 case RL_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: return "R4G4B4A4"; break; // 16 bpp (4 bit alpha)
4820 case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: return "R8G8B8A8"; break; // 32 bpp
4821 case RL_PIXELFORMAT_UNCOMPRESSED_R32: return "R32"; break; // 32 bpp (1 channel - float)
4822 case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32: return "R32G32B32"; break; // 32*3 bpp (3 channels - float)
4823 case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: return "R32G32B32A32"; break; // 32*4 bpp (4 channels - float)
4824 case RL_PIXELFORMAT_UNCOMPRESSED_R16: return "R16"; break; // 16 bpp (1 channel - half float)
4825 case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: return "R16G16B16"; break; // 16*3 bpp (3 channels - half float)
4826 case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: return "R16G16B16A16"; break; // 16*4 bpp (4 channels - half float)
4827 case RL_PIXELFORMAT_COMPRESSED_DXT1_RGB: return "DXT1_RGB"; break; // 4 bpp (no alpha)
4828 case RL_PIXELFORMAT_COMPRESSED_DXT1_RGBA: return "DXT1_RGBA"; break; // 4 bpp (1 bit alpha)
4829 case RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA: return "DXT3_RGBA"; break; // 8 bpp
4830 case RL_PIXELFORMAT_COMPRESSED_DXT5_RGBA: return "DXT5_RGBA"; break; // 8 bpp
4831 case RL_PIXELFORMAT_COMPRESSED_ETC1_RGB: return "ETC1_RGB"; break; // 4 bpp
4832 case RL_PIXELFORMAT_COMPRESSED_ETC2_RGB: return "ETC2_RGB"; break; // 4 bpp
4833 case RL_PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA: return "ETC2_RGBA"; break; // 8 bpp
4834 case RL_PIXELFORMAT_COMPRESSED_PVRT_RGB: return "PVRT_RGB"; break; // 4 bpp
4835 case RL_PIXELFORMAT_COMPRESSED_PVRT_RGBA: return "PVRT_RGBA"; break; // 4 bpp
4836 case RL_PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA: return "ASTC_4x4_RGBA"; break; // 8 bpp
4837 case RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: return "ASTC_8x8_RGBA"; break; // 2 bpp
4838 default: return "UNKNOWN"; break;
4839 }
4840}
4841
4842//----------------------------------------------------------------------------------
4843// Module specific Functions Definition
4844//----------------------------------------------------------------------------------
4845#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
4846// Load default shader (just vertex positioning and texture coloring)
4847// NOTE: This shader program is used for internal buffers
4848// NOTE: Loaded: RLGL.State.defaultShaderId, RLGL.State.defaultShaderLocs
4849static void rlLoadShaderDefault(void)
4850{
4851 RLGL.State.defaultShaderLocs = (int *)RL_CALLOC(RL_MAX_SHADER_LOCATIONS, sizeof(int));
4852
4853 // NOTE: All locations must be reseted to -1 (no location)
4854 for (int i = 0; i < RL_MAX_SHADER_LOCATIONS; i++) RLGL.State.defaultShaderLocs[i] = -1;
4855
4856 // Vertex shader directly defined, no external file required
4857 const char *defaultVShaderCode =
4858#if defined(GRAPHICS_API_OPENGL_21)
4859 "#version 120 \n"
4860 "attribute vec3 vertexPosition; \n"
4861 "attribute vec2 vertexTexCoord; \n"
4862 "attribute vec4 vertexColor; \n"
4863 "varying vec2 fragTexCoord; \n"
4864 "varying vec4 fragColor; \n"
4865#elif defined(GRAPHICS_API_OPENGL_33)
4866 "#version 330 \n"
4867 "in vec3 vertexPosition; \n"
4868 "in vec2 vertexTexCoord; \n"
4869 "in vec4 vertexColor; \n"
4870 "out vec2 fragTexCoord; \n"
4871 "out vec4 fragColor; \n"
4872#endif
4873
4874#if defined(GRAPHICS_API_OPENGL_ES3)
4875 "#version 300 es \n"
4876 "precision mediump float; \n" // Precision required for OpenGL ES3 (WebGL 2) (on some browsers)
4877 "in vec3 vertexPosition; \n"
4878 "in vec2 vertexTexCoord; \n"
4879 "in vec4 vertexColor; \n"
4880 "out vec2 fragTexCoord; \n"
4881 "out vec4 fragColor; \n"
4882#elif defined(GRAPHICS_API_OPENGL_ES2)
4883 "#version 100 \n"
4884 "precision mediump float; \n" // Precision required for OpenGL ES2 (WebGL) (on some browsers)
4885 "attribute vec3 vertexPosition; \n"
4886 "attribute vec2 vertexTexCoord; \n"
4887 "attribute vec4 vertexColor; \n"
4888 "varying vec2 fragTexCoord; \n"
4889 "varying vec4 fragColor; \n"
4890#endif
4891
4892 "uniform mat4 mvp; \n"
4893 "void main() \n"
4894 "{ \n"
4895 " fragTexCoord = vertexTexCoord; \n"
4896 " fragColor = vertexColor; \n"
4897 " gl_Position = mvp*vec4(vertexPosition, 1.0); \n"
4898 "} \n";
4899
4900 // Fragment shader directly defined, no external file required
4901 const char *defaultFShaderCode =
4902#if defined(GRAPHICS_API_OPENGL_21)
4903 "#version 120 \n"
4904 "varying vec2 fragTexCoord; \n"
4905 "varying vec4 fragColor; \n"
4906 "uniform sampler2D texture0; \n"
4907 "uniform vec4 colDiffuse; \n"
4908 "void main() \n"
4909 "{ \n"
4910 " vec4 texelColor = texture2D(texture0, fragTexCoord); \n"
4911 " gl_FragColor = texelColor*colDiffuse*fragColor; \n"
4912 "} \n";
4913#elif defined(GRAPHICS_API_OPENGL_33)
4914 "#version 330 \n"
4915 "in vec2 fragTexCoord; \n"
4916 "in vec4 fragColor; \n"
4917 "out vec4 finalColor; \n"
4918 "uniform sampler2D texture0; \n"
4919 "uniform vec4 colDiffuse; \n"
4920 "void main() \n"
4921 "{ \n"
4922 " vec4 texelColor = texture(texture0, fragTexCoord); \n"
4923 " finalColor = texelColor*colDiffuse*fragColor; \n"
4924 "} \n";
4925#endif
4926
4927#if defined(GRAPHICS_API_OPENGL_ES3)
4928 "#version 300 es \n"
4929 "precision mediump float; \n" // Precision required for OpenGL ES3 (WebGL 2)
4930 "in vec2 fragTexCoord; \n"
4931 "in vec4 fragColor; \n"
4932 "out vec4 finalColor; \n"
4933 "uniform sampler2D texture0; \n"
4934 "uniform vec4 colDiffuse; \n"
4935 "void main() \n"
4936 "{ \n"
4937 " vec4 texelColor = texture(texture0, fragTexCoord); \n"
4938 " finalColor = texelColor*colDiffuse*fragColor; \n"
4939 "} \n";
4940#elif defined(GRAPHICS_API_OPENGL_ES2)
4941 "#version 100 \n"
4942 "precision mediump float; \n" // Precision required for OpenGL ES2 (WebGL)
4943 "varying vec2 fragTexCoord; \n"
4944 "varying vec4 fragColor; \n"
4945 "uniform sampler2D texture0; \n"
4946 "uniform vec4 colDiffuse; \n"
4947 "void main() \n"
4948 "{ \n"
4949 " vec4 texelColor = texture2D(texture0, fragTexCoord); \n"
4950 " gl_FragColor = texelColor*colDiffuse*fragColor; \n"
4951 "} \n";
4952#endif
4953
4954 // NOTE: Compiled vertex/fragment shaders are not deleted,
4955 // they are kept for re-use as default shaders in case some shader loading fails
4956 RLGL.State.defaultVShaderId = rlCompileShader(defaultVShaderCode, GL_VERTEX_SHADER); // Compile default vertex shader
4957 RLGL.State.defaultFShaderId = rlCompileShader(defaultFShaderCode, GL_FRAGMENT_SHADER); // Compile default fragment shader
4958
4959 RLGL.State.defaultShaderId = rlLoadShaderProgram(RLGL.State.defaultVShaderId, RLGL.State.defaultFShaderId);
4960
4961 if (RLGL.State.defaultShaderId > 0)
4962 {
4963 TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Default shader loaded successfully", RLGL.State.defaultShaderId);
4964
4965 // Set default shader locations: attributes locations
4966 RLGL.State.defaultShaderLocs[RL_SHADER_LOC_VERTEX_POSITION] = glGetAttribLocation(RLGL.State.defaultShaderId, RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION);
4967 RLGL.State.defaultShaderLocs[RL_SHADER_LOC_VERTEX_TEXCOORD01] = glGetAttribLocation(RLGL.State.defaultShaderId, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD);
4968 RLGL.State.defaultShaderLocs[RL_SHADER_LOC_VERTEX_COLOR] = glGetAttribLocation(RLGL.State.defaultShaderId, RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR);
4969
4970 // Set default shader locations: uniform locations
4971 RLGL.State.defaultShaderLocs[RL_SHADER_LOC_MATRIX_MVP] = glGetUniformLocation(RLGL.State.defaultShaderId, RL_DEFAULT_SHADER_UNIFORM_NAME_MVP);
4972 RLGL.State.defaultShaderLocs[RL_SHADER_LOC_COLOR_DIFFUSE] = glGetUniformLocation(RLGL.State.defaultShaderId, RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR);
4973 RLGL.State.defaultShaderLocs[RL_SHADER_LOC_MAP_DIFFUSE] = glGetUniformLocation(RLGL.State.defaultShaderId, RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0);
4974 }
4975 else TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to load default shader", RLGL.State.defaultShaderId);
4976}
4977
4978// Unload default shader
4979// NOTE: Unloads: RLGL.State.defaultShaderId, RLGL.State.defaultShaderLocs
4980static void rlUnloadShaderDefault(void)
4981{
4982 glUseProgram(0);
4983
4984 glDetachShader(RLGL.State.defaultShaderId, RLGL.State.defaultVShaderId);
4985 glDetachShader(RLGL.State.defaultShaderId, RLGL.State.defaultFShaderId);
4986 glDeleteShader(RLGL.State.defaultVShaderId);
4987 glDeleteShader(RLGL.State.defaultFShaderId);
4988
4989 glDeleteProgram(RLGL.State.defaultShaderId);
4990
4991 RL_FREE(RLGL.State.defaultShaderLocs);
4992
4993 TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Default shader unloaded successfully", RLGL.State.defaultShaderId);
4994}
4995
4996#if defined(RLGL_SHOW_GL_DETAILS_INFO)
4997// Get compressed format official GL identifier name
4998static const char *rlGetCompressedFormatName(int format)
4999{
5000 switch (format)
5001 {
5002 // GL_EXT_texture_compression_s3tc
5003 case 0x83F0: return "GL_COMPRESSED_RGB_S3TC_DXT1_EXT"; break;
5004 case 0x83F1: return "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT"; break;
5005 case 0x83F2: return "GL_COMPRESSED_RGBA_S3TC_DXT3_EXT"; break;
5006 case 0x83F3: return "GL_COMPRESSED_RGBA_S3TC_DXT5_EXT"; break;
5007 // GL_3DFX_texture_compression_FXT1
5008 case 0x86B0: return "GL_COMPRESSED_RGB_FXT1_3DFX"; break;
5009 case 0x86B1: return "GL_COMPRESSED_RGBA_FXT1_3DFX"; break;
5010 // GL_IMG_texture_compression_pvrtc
5011 case 0x8C00: return "GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG"; break;
5012 case 0x8C01: return "GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG"; break;
5013 case 0x8C02: return "GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG"; break;
5014 case 0x8C03: return "GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG"; break;
5015 // GL_OES_compressed_ETC1_RGB8_texture
5016 case 0x8D64: return "GL_ETC1_RGB8_OES"; break;
5017 // GL_ARB_texture_compression_rgtc
5018 case 0x8DBB: return "GL_COMPRESSED_RED_RGTC1"; break;
5019 case 0x8DBC: return "GL_COMPRESSED_SIGNED_RED_RGTC1"; break;
5020 case 0x8DBD: return "GL_COMPRESSED_RG_RGTC2"; break;
5021 case 0x8DBE: return "GL_COMPRESSED_SIGNED_RG_RGTC2"; break;
5022 // GL_ARB_texture_compression_bptc
5023 case 0x8E8C: return "GL_COMPRESSED_RGBA_BPTC_UNORM_ARB"; break;
5024 case 0x8E8D: return "GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB"; break;
5025 case 0x8E8E: return "GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB"; break;
5026 case 0x8E8F: return "GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB"; break;
5027 // GL_ARB_ES3_compatibility
5028 case 0x9274: return "GL_COMPRESSED_RGB8_ETC2"; break;
5029 case 0x9275: return "GL_COMPRESSED_SRGB8_ETC2"; break;
5030 case 0x9276: return "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2"; break;
5031 case 0x9277: return "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2"; break;
5032 case 0x9278: return "GL_COMPRESSED_RGBA8_ETC2_EAC"; break;
5033 case 0x9279: return "GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC"; break;
5034 case 0x9270: return "GL_COMPRESSED_R11_EAC"; break;
5035 case 0x9271: return "GL_COMPRESSED_SIGNED_R11_EAC"; break;
5036 case 0x9272: return "GL_COMPRESSED_RG11_EAC"; break;
5037 case 0x9273: return "GL_COMPRESSED_SIGNED_RG11_EAC"; break;
5038 // GL_KHR_texture_compression_astc_hdr
5039 case 0x93B0: return "GL_COMPRESSED_RGBA_ASTC_4x4_KHR"; break;
5040 case 0x93B1: return "GL_COMPRESSED_RGBA_ASTC_5x4_KHR"; break;
5041 case 0x93B2: return "GL_COMPRESSED_RGBA_ASTC_5x5_KHR"; break;
5042 case 0x93B3: return "GL_COMPRESSED_RGBA_ASTC_6x5_KHR"; break;
5043 case 0x93B4: return "GL_COMPRESSED_RGBA_ASTC_6x6_KHR"; break;
5044 case 0x93B5: return "GL_COMPRESSED_RGBA_ASTC_8x5_KHR"; break;
5045 case 0x93B6: return "GL_COMPRESSED_RGBA_ASTC_8x6_KHR"; break;
5046 case 0x93B7: return "GL_COMPRESSED_RGBA_ASTC_8x8_KHR"; break;
5047 case 0x93B8: return "GL_COMPRESSED_RGBA_ASTC_10x5_KHR"; break;
5048 case 0x93B9: return "GL_COMPRESSED_RGBA_ASTC_10x6_KHR"; break;
5049 case 0x93BA: return "GL_COMPRESSED_RGBA_ASTC_10x8_KHR"; break;
5050 case 0x93BB: return "GL_COMPRESSED_RGBA_ASTC_10x10_KHR"; break;
5051 case 0x93BC: return "GL_COMPRESSED_RGBA_ASTC_12x10_KHR"; break;
5052 case 0x93BD: return "GL_COMPRESSED_RGBA_ASTC_12x12_KHR"; break;
5053 case 0x93D0: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR"; break;
5054 case 0x93D1: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR"; break;
5055 case 0x93D2: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR"; break;
5056 case 0x93D3: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR"; break;
5057 case 0x93D4: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR"; break;
5058 case 0x93D5: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR"; break;
5059 case 0x93D6: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR"; break;
5060 case 0x93D7: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR"; break;
5061 case 0x93D8: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR"; break;
5062 case 0x93D9: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR"; break;
5063 case 0x93DA: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR"; break;
5064 case 0x93DB: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR"; break;
5065 case 0x93DC: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR"; break;
5066 case 0x93DD: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR"; break;
5067 default: return "GL_COMPRESSED_UNKNOWN"; break;
5068 }
5069}
5070#endif // RLGL_SHOW_GL_DETAILS_INFO
5071
5072#endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
5073
5074// Get pixel data size in bytes (image or texture)
5075// NOTE: Size depends on pixel format
5076static int rlGetPixelDataSize(int width, int height, int format)
5077{
5078 int dataSize = 0; // Size in bytes
5079 int bpp = 0; // Bits per pixel
5080
5081 switch (format)
5082 {
5083 case RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: bpp = 8; break;
5084 case RL_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA:
5085 case RL_PIXELFORMAT_UNCOMPRESSED_R5G6B5:
5086 case RL_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1:
5087 case RL_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: bpp = 16; break;
5088 case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: bpp = 32; break;
5089 case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8: bpp = 24; break;
5090 case RL_PIXELFORMAT_UNCOMPRESSED_R32: bpp = 32; break;
5091 case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32: bpp = 32*3; break;
5092 case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: bpp = 32*4; break;
5093 case RL_PIXELFORMAT_UNCOMPRESSED_R16: bpp = 16; break;
5094 case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: bpp = 16*3; break;
5095 case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: bpp = 16*4; break;
5096 case RL_PIXELFORMAT_COMPRESSED_DXT1_RGB:
5097 case RL_PIXELFORMAT_COMPRESSED_DXT1_RGBA:
5098 case RL_PIXELFORMAT_COMPRESSED_ETC1_RGB:
5099 case RL_PIXELFORMAT_COMPRESSED_ETC2_RGB:
5100 case RL_PIXELFORMAT_COMPRESSED_PVRT_RGB:
5101 case RL_PIXELFORMAT_COMPRESSED_PVRT_RGBA: bpp = 4; break;
5102 case RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA:
5103 case RL_PIXELFORMAT_COMPRESSED_DXT5_RGBA:
5104 case RL_PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA:
5105 case RL_PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA: bpp = 8; break;
5106 case RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: bpp = 2; break;
5107 default: break;
5108 }
5109
5110 double bytesPerPixel = (double)bpp/8.0;
5111 dataSize = (int)(bytesPerPixel*width*height); // Total data size in bytes
5112
5113 // Most compressed formats works on 4x4 blocks,
5114 // if texture is smaller, minimum dataSize is 8 or 16
5115 if ((width < 4) && (height < 4))
5116 {
5117 if ((format >= RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) && (format < RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA)) dataSize = 8;
5118 else if ((format >= RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA) && (format < RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA)) dataSize = 16;
5119 }
5120
5121 return dataSize;
5122}
5123
5124// Auxiliar math functions
5125
5126// Get float array of matrix data
5127static rl_float16 rlMatrixToFloatV(Matrix mat)
5128{
5129 rl_float16 result = { 0 };
5130
5131 result.v[0] = mat.m0;
5132 result.v[1] = mat.m1;
5133 result.v[2] = mat.m2;
5134 result.v[3] = mat.m3;
5135 result.v[4] = mat.m4;
5136 result.v[5] = mat.m5;
5137 result.v[6] = mat.m6;
5138 result.v[7] = mat.m7;
5139 result.v[8] = mat.m8;
5140 result.v[9] = mat.m9;
5141 result.v[10] = mat.m10;
5142 result.v[11] = mat.m11;
5143 result.v[12] = mat.m12;
5144 result.v[13] = mat.m13;
5145 result.v[14] = mat.m14;
5146 result.v[15] = mat.m15;
5147
5148 return result;
5149}
5150
5151// Get identity matrix
5152static Matrix rlMatrixIdentity(void)
5153{
5154 Matrix result = {
5155 1.0f, 0.0f, 0.0f, 0.0f,
5156 0.0f, 1.0f, 0.0f, 0.0f,
5157 0.0f, 0.0f, 1.0f, 0.0f,
5158 0.0f, 0.0f, 0.0f, 1.0f
5159 };
5160
5161 return result;
5162}
5163
5164// Get two matrix multiplication
5165// NOTE: When multiplying matrices... the order matters!
5166static Matrix rlMatrixMultiply(Matrix left, Matrix right)
5167{
5168 Matrix result = { 0 };
5169
5170 result.m0 = left.m0*right.m0 + left.m1*right.m4 + left.m2*right.m8 + left.m3*right.m12;
5171 result.m1 = left.m0*right.m1 + left.m1*right.m5 + left.m2*right.m9 + left.m3*right.m13;
5172 result.m2 = left.m0*right.m2 + left.m1*right.m6 + left.m2*right.m10 + left.m3*right.m14;
5173 result.m3 = left.m0*right.m3 + left.m1*right.m7 + left.m2*right.m11 + left.m3*right.m15;
5174 result.m4 = left.m4*right.m0 + left.m5*right.m4 + left.m6*right.m8 + left.m7*right.m12;
5175 result.m5 = left.m4*right.m1 + left.m5*right.m5 + left.m6*right.m9 + left.m7*right.m13;
5176 result.m6 = left.m4*right.m2 + left.m5*right.m6 + left.m6*right.m10 + left.m7*right.m14;
5177 result.m7 = left.m4*right.m3 + left.m5*right.m7 + left.m6*right.m11 + left.m7*right.m15;
5178 result.m8 = left.m8*right.m0 + left.m9*right.m4 + left.m10*right.m8 + left.m11*right.m12;
5179 result.m9 = left.m8*right.m1 + left.m9*right.m5 + left.m10*right.m9 + left.m11*right.m13;
5180 result.m10 = left.m8*right.m2 + left.m9*right.m6 + left.m10*right.m10 + left.m11*right.m14;
5181 result.m11 = left.m8*right.m3 + left.m9*right.m7 + left.m10*right.m11 + left.m11*right.m15;
5182 result.m12 = left.m12*right.m0 + left.m13*right.m4 + left.m14*right.m8 + left.m15*right.m12;
5183 result.m13 = left.m12*right.m1 + left.m13*right.m5 + left.m14*right.m9 + left.m15*right.m13;
5184 result.m14 = left.m12*right.m2 + left.m13*right.m6 + left.m14*right.m10 + left.m15*right.m14;
5185 result.m15 = left.m12*right.m3 + left.m13*right.m7 + left.m14*right.m11 + left.m15*right.m15;
5186
5187 return result;
5188}
5189
5190// Transposes provided matrix
5191static Matrix rlMatrixTranspose(Matrix mat)
5192{
5193 Matrix result = { 0 };
5194
5195 result.m0 = mat.m0;
5196 result.m1 = mat.m4;
5197 result.m2 = mat.m8;
5198 result.m3 = mat.m12;
5199 result.m4 = mat.m1;
5200 result.m5 = mat.m5;
5201 result.m6 = mat.m9;
5202 result.m7 = mat.m13;
5203 result.m8 = mat.m2;
5204 result.m9 = mat.m6;
5205 result.m10 = mat.m10;
5206 result.m11 = mat.m14;
5207 result.m12 = mat.m3;
5208 result.m13 = mat.m7;
5209 result.m14 = mat.m11;
5210 result.m15 = mat.m15;
5211
5212 return result;
5213}
5214
5215// Invert provided matrix
5216static Matrix rlMatrixInvert(Matrix mat)
5217{
5218 Matrix result = { 0 };
5219
5220 // Cache the matrix values (speed optimization)
5221 float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3;
5222 float a10 = mat.m4, a11 = mat.m5, a12 = mat.m6, a13 = mat.m7;
5223 float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11;
5224 float a30 = mat.m12, a31 = mat.m13, a32 = mat.m14, a33 = mat.m15;
5225
5226 float b00 = a00*a11 - a01*a10;
5227 float b01 = a00*a12 - a02*a10;
5228 float b02 = a00*a13 - a03*a10;
5229 float b03 = a01*a12 - a02*a11;
5230 float b04 = a01*a13 - a03*a11;
5231 float b05 = a02*a13 - a03*a12;
5232 float b06 = a20*a31 - a21*a30;
5233 float b07 = a20*a32 - a22*a30;
5234 float b08 = a20*a33 - a23*a30;
5235 float b09 = a21*a32 - a22*a31;
5236 float b10 = a21*a33 - a23*a31;
5237 float b11 = a22*a33 - a23*a32;
5238
5239 // Calculate the invert determinant (inlined to avoid double-caching)
5240 float invDet = 1.0f/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06);
5241
5242 result.m0 = (a11*b11 - a12*b10 + a13*b09)*invDet;
5243 result.m1 = (-a01*b11 + a02*b10 - a03*b09)*invDet;
5244 result.m2 = (a31*b05 - a32*b04 + a33*b03)*invDet;
5245 result.m3 = (-a21*b05 + a22*b04 - a23*b03)*invDet;
5246 result.m4 = (-a10*b11 + a12*b08 - a13*b07)*invDet;
5247 result.m5 = (a00*b11 - a02*b08 + a03*b07)*invDet;
5248 result.m6 = (-a30*b05 + a32*b02 - a33*b01)*invDet;
5249 result.m7 = (a20*b05 - a22*b02 + a23*b01)*invDet;
5250 result.m8 = (a10*b10 - a11*b08 + a13*b06)*invDet;
5251 result.m9 = (-a00*b10 + a01*b08 - a03*b06)*invDet;
5252 result.m10 = (a30*b04 - a31*b02 + a33*b00)*invDet;
5253 result.m11 = (-a20*b04 + a21*b02 - a23*b00)*invDet;
5254 result.m12 = (-a10*b09 + a11*b07 - a12*b06)*invDet;
5255 result.m13 = (a00*b09 - a01*b07 + a02*b06)*invDet;
5256 result.m14 = (-a30*b03 + a31*b01 - a32*b00)*invDet;
5257 result.m15 = (a20*b03 - a21*b01 + a22*b00)*invDet;
5258
5259 return result;
5260}
5261
5262#endif // RLGL_IMPLEMENTATION