From 05eaafb79e6fa1bebff157e94563334d7ead700b Mon Sep 17 00:00:00 2001 From: jussi Date: Mon, 20 Nov 2023 21:04:53 +0200 Subject: Initial changes for Raylib 5.0 and some missing functions. --- include/audio.h | 6 + include/core.h | 42 ++++-- include/main.h | 13 +- include/raylib.h | 172 +++++++++++++++++------- include/raymath.h | 202 +++++++++++++++++----------- include/rlgl.h | 379 +++++++++++++++++++++++++++++++++++------------------ include/shapes.h | 2 - include/text.h | 1 + include/textures.h | 7 +- 9 files changed, 548 insertions(+), 276 deletions(-) (limited to 'include') diff --git a/include/audio.h b/include/audio.h index 09b5bb3..7367de8 100644 --- a/include/audio.h +++ b/include/audio.h @@ -1,15 +1,21 @@ #pragma once /* Audio device management functions. */ +int laudioInitAudioDevice( lua_State *L ); +int laudioCloseAudioDevice( lua_State *L ); +int laudioIsAudioDeviceReady( lua_State *L ); int laudioSetMasterVolume( lua_State *L ); +int laudioGetMasterVolume( lua_State *L ); /* Wave/Sound loading/unloading functions. */ int laudioLoadSound( lua_State *L ); int laudioLoadWave( lua_State *L ); int laudioIsWaveReady( lua_State *L ); int laudioLoadSoundFromWave( lua_State *L ); +int laudioLoadSoundAlias( lua_State *L ); int laudioIsSoundReady( lua_State *L ); int laudioUnloadWave( lua_State *L ); int laudioUnloadSound( lua_State *L ); +int laudioUnloadSoundAlias( lua_State *L ); int laudioExportWave( lua_State *L ); int laudioExportWaveAsCode( lua_State *L ); /* Wave/Sound management functions. */ diff --git a/include/core.h b/include/core.h index 4b61d5f..3d8d3c0 100644 --- a/include/core.h +++ b/include/core.h @@ -4,36 +4,44 @@ void unloadBuffer( Buffer *buffer ); /* Window-related functions. */ +int lcoreCloseWindow( lua_State *L ); int lcoreIsWindowReady( lua_State *L ); int lcoreIsWindowFullscreen( lua_State *L ); int lcoreIsWindowHidden( lua_State *L ); int lcoreIsWindowMinimized( lua_State *L ); int lcoreIsWindowMaximized( lua_State *L ); int lcoreIsWindowFocused( lua_State *L ); -int lcoreSetWindowMonitor( lua_State *L ); -int lcoreSetWindowPosition( lua_State *L ); -int lcoreSetWindowSize( lua_State *L ); -int lcoreSetWindowOpacity( lua_State *L ); -int lcoreGetWindowHandle( lua_State *L ); -int lcoreSetWindowMinSize( lua_State *L ); -int lcoreGetMonitorPosition( lua_State *L ); -int lcoreGetMonitorSize( lua_State *L ); -int lcoreGetWindowPosition( lua_State *L ); -int lcoreGetScreenSize( lua_State *L ); -int lcoreSetWindowState( lua_State *L ); +int lcoreIsWindowResized( lua_State *L ); int lcoreIsWindowState( lua_State *L ); +int lcoreSetWindowState( lua_State *L ); int lcoreClearWindowState( lua_State *L ); -int lcoreIsWindowResized( lua_State *L ); +int lcoreToggleFullscreen( lua_State *L ); +int lcoreToggleBorderlessWindowed( lua_State *L ); +int lcoreMaximizeWindow( lua_State *L ); +int lcoreMinimizeWindow( lua_State *L ); +int lcoreRestoreWindow( lua_State *L ); int lcoreSetWindowIcon( lua_State *L ); int lcoreSetWindowIcons( lua_State *L ); int lcoreSetWindowTitle( lua_State *L ); +int lcoreSetWindowPosition( lua_State *L ); +int lcoreSetWindowMonitor( lua_State *L ); +int lcoreSetWindowMinSize( lua_State *L ); +int lcoreSetWindowMaxSize( lua_State *L ); +int lcoreSetWindowSize( lua_State *L ); +int lcoreSetWindowOpacity( lua_State *L ); +int lcoreSetWindowFocused( lua_State *L ); +int lcoreGetWindowHandle( lua_State *L ); +int lcoreGetScreenSize( lua_State *L ); +int lcoreGetRenderSize( lua_State *L ); int lcoreGetMonitorCount( lua_State *L ); int lcoreGetCurrentMonitor( lua_State *L ); +int lcoreGetMonitorPosition( lua_State *L ); +int lcoreGetMonitorSize( lua_State *L ); int lcoreGetMonitorPhysicalSize( lua_State *L ); int lcoreGetMonitorRefreshRate( lua_State *L ); +int lcoreGetWindowPosition( lua_State *L ); int lcoreGetWindowScaleDPI( lua_State *L ); int lcoreGetMonitorName( lua_State *L ); -int lcoreCloseWindow( lua_State *L ); int lcoreSetClipboardText( lua_State *L ); int lcoreGetClipboardText( lua_State *L ); /* Cursor-related functions. */ @@ -85,6 +93,10 @@ int lcoreSetTargetFPS( lua_State *L ); int lcoreGetFPS( lua_State *L ); int lcoreGetFrameTime( lua_State *L ); int lcoreGetTime( lua_State *L ); +/* Random values generation functions. */ +int lcoreSetRandomSeed( lua_State *L ); +int lcoreGetRandomValue( lua_State *L ); +int lcoreLoadRandomSequence( lua_State *L ); /* Misc. functions */ int lcoreTakeScreenshot( lua_State *L ); int lcoreSetConfigFlags( lua_State *L ); @@ -107,6 +119,7 @@ int lcoreGetFileNameWithoutExt( lua_State *L ); int lcoreGetDirectoryPath( lua_State *L ); int lcoreGetPrevDirectoryPath( lua_State *L ); int lcoreGetWorkingDirectory( lua_State *L ); +int lcoreGetApplicationDirectory( lua_State *L ); int lcoreLoadDirectoryFiles( lua_State *L ); int lcoreLoadDirectoryFilesEx( lua_State *L ); int lcoreChangeDirectory( lua_State *L ); @@ -131,12 +144,13 @@ int lcoreGetKeyName( lua_State *L ); int lcoreGetKeyScancode( lua_State *L ); /* Input-related functions: gamepads. */ int lcoreIsGamepadAvailable( lua_State *L ); +int lcoreGetGamepadName( lua_State *L ); int lcoreIsGamepadButtonPressed( lua_State *L ); int lcoreIsGamepadButtonDown( lua_State *L ); int lcoreIsGamepadButtonReleased( lua_State *L ); int lcoreGetGamepadAxisCount( lua_State *L ); int lcoreGetGamepadAxisMovement( lua_State *L ); -int lcoreGetGamepadName( lua_State *L ); +int lcoreSetGamepadMappings( lua_State *L ); /* Input-related functions: mouse. */ int lcoreIsMouseButtonPressed( lua_State *L ); int lcoreIsMouseButtonDown( lua_State *L ); diff --git a/include/main.h b/include/main.h index e8759bb..4795121 100644 --- a/include/main.h +++ b/include/main.h @@ -3,14 +3,18 @@ #define STRING_LEN 1024 #define VERSION_MAJOR 0 -#define VERSION_MINOR 6 +#define VERSION_MINOR 7 #define VERSION_PATCH 0 -#define VERSION_DEV 0 +#define VERSION_DEV 1 -#include "glad.h" #include #include #include +#include + +#include "glad.h" +#include "glfw3.h" +#include "glfw3native.h" #ifdef SHARED #include @@ -28,9 +32,6 @@ #include "rcamera.h" #endif -#include "glfw3.h" -#include "glfw3native.h" -#include #ifdef LUAJIT #ifdef SHARED diff --git a/include/raylib.h b/include/raylib.h index 4cd9e43..1c4c4a0 100644 --- a/include/raylib.h +++ b/include/raylib.h @@ -1,6 +1,6 @@ /********************************************************************************************** * -* raylib v4.5 - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com) +* raylib v5.0 - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com) * * FEATURES: * - NO external dependencies, all required libraries included with raylib @@ -81,10 +81,10 @@ #include // Required for: va_list - Only used by TraceLogCallback -#define RAYLIB_VERSION_MAJOR 4 -#define RAYLIB_VERSION_MINOR 5 +#define RAYLIB_VERSION_MAJOR 5 +#define RAYLIB_VERSION_MINOR 0 #define RAYLIB_VERSION_PATCH 0 -#define RAYLIB_VERSION "4.5" +#define RAYLIB_VERSION "5.0" // Function specifiers in case library is build/used as a shared library (Windows) // NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll @@ -133,12 +133,20 @@ // NOTE: MSVC C++ compiler does not support compound literals (C99 feature) // Plain structures in C++ (without constructors) can be initialized with { } +// This is called aggregate initialization (C++11 feature) #if defined(__cplusplus) #define CLITERAL(type) type #else #define CLITERAL(type) (type) #endif +// Some compilers (mostly macos clang) default to C++98, +// where aggregate initialization can't be used +// So, give a more clear error stating how to fix this +#if !defined(_MSC_VER) && (defined(__cplusplus) && __cplusplus < 201103L) + #error "C++11 or later is required. Add -std=c++11" +#endif + // NOTE: We set some defines with some data types declared by raylib // Other modules (raymath, rlgl) also require some of those types, so, // to be able to use those other modules as standalone (not depending on raylib) @@ -402,6 +410,7 @@ typedef struct ModelAnimation { int frameCount; // Number of animation frames BoneInfo *bones; // Bones information (skeleton) Transform **framePoses; // Poses array by frame + char name[32]; // Animation name } ModelAnimation; // Ray, ray for raycasting @@ -497,6 +506,20 @@ typedef struct FilePathList { char **paths; // Filepaths entries } FilePathList; +// Automation event +typedef struct AutomationEvent { + unsigned int frame; // Event frame + unsigned int type; // Event type (AutomationEventType) + int params[4]; // Event parameters (if required) +} AutomationEvent; + +// Automation event list +typedef struct AutomationEventList { + unsigned int capacity; // Events max entries (MAX_AUTOMATION_EVENTS) + unsigned int count; // Events entries count + AutomationEvent *events; // Events entries +} AutomationEventList; + //---------------------------------------------------------------------------------- // Enumerators Definition //---------------------------------------------------------------------------------- @@ -517,6 +540,7 @@ typedef enum { FLAG_WINDOW_TRANSPARENT = 0x00000010, // Set to allow transparent framebuffer FLAG_WINDOW_HIGHDPI = 0x00002000, // Set to support HighDPI FLAG_WINDOW_MOUSE_PASSTHROUGH = 0x00004000, // Set to support mouse passthrough, only supported when FLAG_WINDOW_UNDECORATED + FLAG_BORDERLESS_WINDOWED_MODE = 0x00008000, // Set to run program in borderless windowed mode FLAG_MSAA_4X_HINT = 0x00000020, // Set to try enabling MSAA 4X FLAG_INTERLACED_HINT = 0x00010000 // Set to try enabling interlaced video format (for V3D) } ConfigFlags; @@ -802,6 +826,9 @@ typedef enum { PIXELFORMAT_UNCOMPRESSED_R32, // 32 bpp (1 channel - float) PIXELFORMAT_UNCOMPRESSED_R32G32B32, // 32*3 bpp (3 channels - float) PIXELFORMAT_UNCOMPRESSED_R32G32B32A32, // 32*4 bpp (4 channels - float) + PIXELFORMAT_UNCOMPRESSED_R16, // 16 bpp (1 channel - half float) + PIXELFORMAT_UNCOMPRESSED_R16G16B16, // 16*3 bpp (3 channels - half float) + PIXELFORMAT_UNCOMPRESSED_R16G16B16A16, // 16*4 bpp (4 channels - half float) PIXELFORMAT_COMPRESSED_DXT1_RGB, // 4 bpp (no alpha) PIXELFORMAT_COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha) PIXELFORMAT_COMPRESSED_DXT3_RGBA, // 8 bpp @@ -905,8 +932,8 @@ typedef enum { // Callbacks to hook some internal functions // WARNING: These callbacks are intended for advance users typedef void (*TraceLogCallback)(int logLevel, const char *text, va_list args); // Logging: Redirect trace log messages -typedef unsigned char *(*LoadFileDataCallback)(const char *fileName, unsigned int *bytesRead); // FileIO: Load binary data -typedef bool (*SaveFileDataCallback)(const char *fileName, void *data, unsigned int bytesToWrite); // FileIO: Save binary data +typedef unsigned char *(*LoadFileDataCallback)(const char *fileName, int *dataSize); // FileIO: Load binary data +typedef bool (*SaveFileDataCallback)(const char *fileName, void *data, int dataSize); // FileIO: Save binary data typedef char *(*LoadFileTextCallback)(const char *fileName); // FileIO: Load text data typedef bool (*SaveFileTextCallback)(const char *fileName, char *text); // FileIO: Save text data @@ -925,8 +952,8 @@ extern "C" { // Prevents name mangling of functions // Window-related functions RLAPI void InitWindow(int width, int height, const char *title); // Initialize window and OpenGL context -RLAPI bool WindowShouldClose(void); // Check if KEY_ESCAPE pressed or Close icon pressed RLAPI void CloseWindow(void); // Close window and unload OpenGL context +RLAPI bool WindowShouldClose(void); // Check if application should close (KEY_ESCAPE pressed or windows close icon clicked) RLAPI bool IsWindowReady(void); // Check if window has been initialized successfully RLAPI bool IsWindowFullscreen(void); // Check if window is currently fullscreen RLAPI bool IsWindowHidden(void); // Check if window is currently hidden (only PLATFORM_DESKTOP) @@ -938,17 +965,20 @@ RLAPI bool IsWindowState(unsigned int flag); // Check if on RLAPI void SetWindowState(unsigned int flags); // Set window configuration state using flags (only PLATFORM_DESKTOP) RLAPI void ClearWindowState(unsigned int flags); // Clear window configuration state flags RLAPI void ToggleFullscreen(void); // Toggle window state: fullscreen/windowed (only PLATFORM_DESKTOP) +RLAPI void ToggleBorderlessWindowed(void); // Toggle window state: borderless windowed (only PLATFORM_DESKTOP) RLAPI void MaximizeWindow(void); // Set window state: maximized, if resizable (only PLATFORM_DESKTOP) RLAPI void MinimizeWindow(void); // Set window state: minimized, if resizable (only PLATFORM_DESKTOP) RLAPI void RestoreWindow(void); // Set window state: not minimized/maximized (only PLATFORM_DESKTOP) RLAPI void SetWindowIcon(Image image); // Set icon for window (single image, RGBA 32bit, only PLATFORM_DESKTOP) RLAPI void SetWindowIcons(Image *images, int count); // Set icon for window (multiple images, RGBA 32bit, only PLATFORM_DESKTOP) -RLAPI void SetWindowTitle(const char *title); // Set title for window (only PLATFORM_DESKTOP) +RLAPI void SetWindowTitle(const char *title); // Set title for window (only PLATFORM_DESKTOP and PLATFORM_WEB) RLAPI void SetWindowPosition(int x, int y); // Set window position on screen (only PLATFORM_DESKTOP) -RLAPI void SetWindowMonitor(int monitor); // Set monitor for the current window (fullscreen mode) +RLAPI void SetWindowMonitor(int monitor); // Set monitor for the current window RLAPI void SetWindowMinSize(int width, int height); // Set window minimum dimensions (for FLAG_WINDOW_RESIZABLE) +RLAPI void SetWindowMaxSize(int width, int height); // Set window maximum dimensions (for FLAG_WINDOW_RESIZABLE) RLAPI void SetWindowSize(int width, int height); // Set window dimensions RLAPI void SetWindowOpacity(float opacity); // Set window opacity [0.0f..1.0f] (only PLATFORM_DESKTOP) +RLAPI void SetWindowFocused(void); // Set window focused (only PLATFORM_DESKTOP) RLAPI void *GetWindowHandle(void); // Get native window handle RLAPI int GetScreenWidth(void); // Get current screen width RLAPI int GetScreenHeight(void); // Get current screen height @@ -964,20 +994,12 @@ RLAPI int GetMonitorPhysicalHeight(int monitor); // Get specifi RLAPI int GetMonitorRefreshRate(int monitor); // Get specified monitor refresh rate RLAPI Vector2 GetWindowPosition(void); // Get window position XY on monitor RLAPI Vector2 GetWindowScaleDPI(void); // Get window scale DPI factor -RLAPI const char *GetMonitorName(int monitor); // Get the human-readable, UTF-8 encoded name of the primary monitor +RLAPI const char *GetMonitorName(int monitor); // Get the human-readable, UTF-8 encoded name of the specified monitor RLAPI void SetClipboardText(const char *text); // Set clipboard text content RLAPI const char *GetClipboardText(void); // Get clipboard text content RLAPI void EnableEventWaiting(void); // Enable waiting for events on EndDrawing(), no automatic event polling RLAPI void DisableEventWaiting(void); // Disable waiting for events on EndDrawing(), automatic events polling -// Custom frame control functions -// NOTE: Those functions are intended for advance users that want full control over the frame processing -// By default EndDrawing() does this job: draws everything + SwapScreenBuffer() + manage frame timing + PollInputEvents() -// To avoid that behaviour and control frame processes manually, enable in config.h: SUPPORT_CUSTOM_FRAME_CONTROL -RLAPI void SwapScreenBuffer(void); // Swap back buffer with front buffer (screen drawing) -RLAPI void PollInputEvents(void); // Register all input events -RLAPI void WaitTime(double seconds); // Wait for some time (halt program execution) - // Cursor-related functions RLAPI void ShowCursor(void); // Shows cursor RLAPI void HideCursor(void); // Hides cursor @@ -1033,24 +1055,37 @@ RLAPI Vector2 GetWorldToScreen2D(Vector2 position, Camera2D camera); // Get the // Timing-related functions RLAPI void SetTargetFPS(int fps); // Set target FPS (maximum) -RLAPI int GetFPS(void); // Get current FPS RLAPI float GetFrameTime(void); // Get time in seconds for last frame drawn (delta time) RLAPI double GetTime(void); // Get elapsed time in seconds since InitWindow() +RLAPI int GetFPS(void); // Get current FPS -// Misc. functions -RLAPI int GetRandomValue(int min, int max); // Get a random value between min and max (both included) +// Custom frame control functions +// NOTE: Those functions are intended for advance users that want full control over the frame processing +// By default EndDrawing() does this job: draws everything + SwapScreenBuffer() + manage frame timing + PollInputEvents() +// To avoid that behaviour and control frame processes manually, enable in config.h: SUPPORT_CUSTOM_FRAME_CONTROL +RLAPI void SwapScreenBuffer(void); // Swap back buffer with front buffer (screen drawing) +RLAPI void PollInputEvents(void); // Register all input events +RLAPI void WaitTime(double seconds); // Wait for some time (halt program execution) + +// Random values generation functions RLAPI void SetRandomSeed(unsigned int seed); // Set the seed for the random number generator +RLAPI int GetRandomValue(int min, int max); // Get a random value between min and max (both included) +RLAPI int *LoadRandomSequence(unsigned int count, int min, int max); // Load random values sequence, no values repeated +RLAPI void UnloadRandomSequence(int *sequence); // Unload random values sequence + +// Misc. functions RLAPI void TakeScreenshot(const char *fileName); // Takes a screenshot of current screen (filename extension defines format) RLAPI void SetConfigFlags(unsigned int flags); // Setup init configuration flags (view FLAGS) +RLAPI void OpenURL(const char *url); // Open URL with default system browser (if available) +// NOTE: Following functions implemented in module [utils] +//------------------------------------------------------------------ RLAPI void TraceLog(int logLevel, const char *text, ...); // Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR...) RLAPI void SetTraceLogLevel(int logLevel); // Set the current threshold (minimum) log level RLAPI void *MemAlloc(unsigned int size); // Internal memory allocator RLAPI void *MemRealloc(void *ptr, unsigned int size); // Internal memory reallocator RLAPI void MemFree(void *ptr); // Internal memory free -RLAPI void OpenURL(const char *url); // Open URL with default system browser (if available) - // Set custom callbacks // WARNING: Callbacks setup is intended for advance users RLAPI void SetTraceLogCallback(TraceLogCallback callback); // Set custom trace log @@ -1060,13 +1095,16 @@ RLAPI void SetLoadFileTextCallback(LoadFileTextCallback callback); // Set custom RLAPI void SetSaveFileTextCallback(SaveFileTextCallback callback); // Set custom file text data saver // Files management functions -RLAPI unsigned char *LoadFileData(const char *fileName, unsigned int *bytesRead); // Load file data as byte array (read) +RLAPI unsigned char *LoadFileData(const char *fileName, int *dataSize); // Load file data as byte array (read) RLAPI void UnloadFileData(unsigned char *data); // Unload file data allocated by LoadFileData() -RLAPI bool SaveFileData(const char *fileName, void *data, unsigned int bytesToWrite); // Save data to file from byte array (write), returns true on success -RLAPI bool ExportDataAsCode(const unsigned char *data, unsigned int size, const char *fileName); // Export data to code (.h), returns true on success +RLAPI bool SaveFileData(const char *fileName, void *data, int dataSize); // Save data to file from byte array (write), returns true on success +RLAPI bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileName); // Export data to code (.h), returns true on success RLAPI char *LoadFileText(const char *fileName); // Load text data from file (read), returns a '\0' terminated string RLAPI void UnloadFileText(char *text); // Unload file text data allocated by LoadFileText() RLAPI bool SaveFileText(const char *fileName, char *text); // Save text data to file (write), string must be '\0' terminated, returns true on success +//------------------------------------------------------------------ + +// File system functions RLAPI bool FileExists(const char *fileName); // Check if file exists RLAPI bool DirectoryExists(const char *dirPath); // Check if a directory path exists RLAPI bool IsFileExtension(const char *fileName, const char *ext); // Check file extension (including point: .png, .wav) @@ -1077,7 +1115,7 @@ RLAPI const char *GetFileNameWithoutExt(const char *filePath); // Get filenam RLAPI const char *GetDirectoryPath(const char *filePath); // Get full path for a given fileName with path (uses static string) RLAPI const char *GetPrevDirectoryPath(const char *dirPath); // Get previous directory path for a given path (uses static string) RLAPI const char *GetWorkingDirectory(void); // Get current working directory (uses static string) -RLAPI const char *GetApplicationDirectory(void); // Get the directory if the running application (uses static string) +RLAPI const char *GetApplicationDirectory(void); // Get the directory of the running application (uses static string) RLAPI bool ChangeDirectory(const char *dir); // Change working directory, return true on success RLAPI bool IsPathFile(const char *path); // Check if a given path is a file or a directory RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths @@ -1094,18 +1132,29 @@ RLAPI unsigned char *DecompressData(const unsigned char *compData, int compDataS RLAPI char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize); // Encode data to Base64 string, memory must be MemFree() RLAPI unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize); // Decode Base64 string data, memory must be MemFree() +// Automation events functionality +RLAPI AutomationEventList LoadAutomationEventList(const char *fileName); // Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS +RLAPI void UnloadAutomationEventList(AutomationEventList *list); // Unload automation events list from file +RLAPI bool ExportAutomationEventList(AutomationEventList list, const char *fileName); // Export automation events list as text file +RLAPI void SetAutomationEventList(AutomationEventList *list); // Set automation event list to record to +RLAPI void SetAutomationEventBaseFrame(int frame); // Set automation event internal base frame to start recording +RLAPI void StartAutomationEventRecording(void); // Start recording automation events (AutomationEventList must be set) +RLAPI void StopAutomationEventRecording(void); // Stop recording automation events +RLAPI void PlayAutomationEvent(AutomationEvent event); // Play a recorded automation event + //------------------------------------------------------------------------------------ // Input Handling Functions (Module: core) //------------------------------------------------------------------------------------ // Input-related functions: keyboard RLAPI bool IsKeyPressed(int key); // Check if a key has been pressed once +RLAPI bool IsKeyPressedRepeat(int key); // Check if a key has been pressed again (Only PLATFORM_DESKTOP) RLAPI bool IsKeyDown(int key); // Check if a key is being pressed RLAPI bool IsKeyReleased(int key); // Check if a key has been released once RLAPI bool IsKeyUp(int key); // Check if a key is NOT being pressed -RLAPI void SetExitKey(int key); // Set a custom key to exit program (default is ESC) RLAPI int GetKeyPressed(void); // Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty RLAPI int GetCharPressed(void); // Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty +RLAPI void SetExitKey(int key); // Set a custom key to exit program (default is ESC) // Input-related functions: gamepads RLAPI bool IsGamepadAvailable(int gamepad); // Check if a gamepad is available @@ -1146,7 +1195,7 @@ RLAPI int GetTouchPointCount(void); // Get number of t // Gestures and Touch Handling Functions (Module: rgestures) //------------------------------------------------------------------------------------ RLAPI void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags -RLAPI bool IsGestureDetected(int gesture); // Check if a gesture have been detected +RLAPI bool IsGestureDetected(unsigned int gesture); // Check if a gesture have been detected RLAPI int GetGestureDetected(void); // Get latest detected gesture RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds RLAPI Vector2 GetGestureDragVector(void); // Get gesture drag vector @@ -1172,18 +1221,17 @@ RLAPI void SetShapesTexture(Texture2D texture, Rectangle source); // Set t RLAPI void DrawPixel(int posX, int posY, Color color); // Draw a pixel RLAPI void DrawPixelV(Vector2 position, Color color); // Draw a pixel (Vector version) RLAPI void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color); // Draw a line -RLAPI void DrawLineV(Vector2 startPos, Vector2 endPos, Color color); // Draw a line (Vector version) -RLAPI void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line defining thickness -RLAPI void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line using cubic-bezier curves in-out -RLAPI void DrawLineBezierQuad(Vector2 startPos, Vector2 endPos, Vector2 controlPos, float thick, Color color); // Draw line using quadratic bezier curves with a control point -RLAPI void DrawLineBezierCubic(Vector2 startPos, Vector2 endPos, Vector2 startControlPos, Vector2 endControlPos, float thick, Color color); // Draw line using cubic bezier curves with 2 control points -RLAPI void DrawLineStrip(Vector2 *points, int pointCount, Color color); // Draw lines sequence +RLAPI void DrawLineV(Vector2 startPos, Vector2 endPos, Color color); // Draw a line (using gl lines) +RLAPI void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line (using triangles/quads) +RLAPI void DrawLineStrip(Vector2 *points, int pointCount, Color color); // Draw lines sequence (using gl lines) +RLAPI void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw line segment cubic-bezier in-out interpolation RLAPI void DrawCircle(int centerX, int centerY, float radius, Color color); // Draw a color-filled circle RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw a piece of a circle RLAPI void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw circle sector outline RLAPI void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2); // Draw a gradient-filled circle RLAPI void DrawCircleV(Vector2 center, float radius, Color color); // Draw a color-filled circle (Vector version) RLAPI void DrawCircleLines(int centerX, int centerY, float radius, Color color); // Draw circle outline +RLAPI void DrawCircleLinesV(Vector2 center, float radius, Color color); // Draw circle outline (Vector version) RLAPI void DrawEllipse(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse RLAPI void DrawEllipseLines(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse outline RLAPI void DrawRing(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color); // Draw ring @@ -1207,6 +1255,25 @@ RLAPI void DrawPoly(Vector2 center, int sides, float radius, float rotation, Col RLAPI void DrawPolyLines(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a polygon outline of n sides RLAPI void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, float lineThick, Color color); // Draw a polygon outline of n sides with extended parameters +// Splines drawing functions +RLAPI void DrawSplineLinear(Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Linear, minimum 2 points +RLAPI void DrawSplineBasis(Vector2 *points, int pointCount, float thick, Color color); // Draw spline: B-Spline, minimum 4 points +RLAPI void DrawSplineCatmullRom(Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Catmull-Rom, minimum 4 points +RLAPI void DrawSplineBezierQuadratic(Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Quadratic Bezier, minimum 3 points (1 control point): [p1, c2, p3, c4...] +RLAPI void DrawSplineBezierCubic(Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Cubic Bezier, minimum 4 points (2 control points): [p1, c2, c3, p4, c5, c6...] +RLAPI void DrawSplineSegmentLinear(Vector2 p1, Vector2 p2, float thick, Color color); // Draw spline segment: Linear, 2 points +RLAPI void DrawSplineSegmentBasis(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float thick, Color color); // Draw spline segment: B-Spline, 4 points +RLAPI void DrawSplineSegmentCatmullRom(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float thick, Color color); // Draw spline segment: Catmull-Rom, 4 points +RLAPI void DrawSplineSegmentBezierQuadratic(Vector2 p1, Vector2 c2, Vector2 p3, float thick, Color color); // Draw spline segment: Quadratic Bezier, 2 points, 1 control point +RLAPI void DrawSplineSegmentBezierCubic(Vector2 p1, Vector2 c2, Vector2 c3, Vector2 p4, float thick, Color color); // Draw spline segment: Cubic Bezier, 2 points, 2 control points + +// Spline segment point evaluation functions, for a given t [0.0f .. 1.0f] +RLAPI Vector2 GetSplinePointLinear(Vector2 startPos, Vector2 endPos, float t); // Get (evaluate) spline point: Linear +RLAPI Vector2 GetSplinePointBasis(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float t); // Get (evaluate) spline point: B-Spline +RLAPI Vector2 GetSplinePointCatmullRom(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float t); // Get (evaluate) spline point: Catmull-Rom +RLAPI Vector2 GetSplinePointBezierQuad(Vector2 p1, Vector2 c2, Vector2 p3, float t); // Get (evaluate) spline point: Quadratic Bezier +RLAPI Vector2 GetSplinePointBezierCubic(Vector2 p1, Vector2 c2, Vector2 c3, Vector2 p4, float t); // Get (evaluate) spline point: Cubic Bezier + // Basic shapes collision detection functions RLAPI bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2); // Check collision between two rectangles RLAPI bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, float radius2); // Check collision between two circles @@ -1227,6 +1294,7 @@ RLAPI Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2); // NOTE: These functions do not require GPU access RLAPI Image LoadImage(const char *fileName); // Load image from file into CPU memory (RAM) RLAPI Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize); // Load image from RAW file data +RLAPI Image LoadImageSvg(const char *fileNameOrString, int width, int height); // Load image from SVG file data or string with specified size RLAPI Image LoadImageAnim(const char *fileName, int *frames); // Load image sequence from file (frames appended to image.data) RLAPI Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load image from memory buffer, fileType refers to extension: i.e. '.png' RLAPI Image LoadImageFromTexture(Texture2D texture); // Load image from GPU texture data @@ -1234,13 +1302,14 @@ RLAPI Image LoadImageFromScreen(void); RLAPI bool IsImageReady(Image image); // Check if an image is ready RLAPI void UnloadImage(Image image); // Unload image from CPU memory (RAM) RLAPI bool ExportImage(Image image, const char *fileName); // Export image data to file, returns true on success +RLAPI unsigned char *ExportImageToMemory(Image image, const char *fileType, int *fileSize); // Export image to memory buffer RLAPI bool ExportImageAsCode(Image image, const char *fileName); // Export image as code file defining an array of bytes, returns true on success // Image generation functions RLAPI Image GenImageColor(int width, int height, Color color); // Generate image: plain color -RLAPI Image GenImageGradientV(int width, int height, Color top, Color bottom); // Generate image: vertical gradient -RLAPI Image GenImageGradientH(int width, int height, Color left, Color right); // Generate image: horizontal gradient +RLAPI Image GenImageGradientLinear(int width, int height, int direction, Color start, Color end); // Generate image: linear gradient, direction in degrees [0..360], 0=Vertical gradient RLAPI Image GenImageGradientRadial(int width, int height, float density, Color inner, Color outer); // Generate image: radial gradient +RLAPI Image GenImageGradientSquare(int width, int height, float density, Color inner, Color outer); // Generate image: square gradient RLAPI Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2); // Generate image: checked RLAPI Image GenImageWhiteNoise(int width, int height, float factor); // Generate image: white noise RLAPI Image GenImagePerlinNoise(int width, int height, int offsetX, int offsetY, float scale); // Generate image: perlin noise @@ -1267,6 +1336,7 @@ RLAPI void ImageMipmaps(Image *image); RLAPI void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp); // Dither image data to 16bpp or lower (Floyd-Steinberg dithering) RLAPI void ImageFlipVertical(Image *image); // Flip image vertically RLAPI void ImageFlipHorizontal(Image *image); // Flip image horizontally +RLAPI void ImageRotate(Image *image, int degrees); // Rotate image by input angle in degrees (-359 to 359) RLAPI void ImageRotateCW(Image *image); // Rotate image clockwise 90deg RLAPI void ImageRotateCCW(Image *image); // Rotate image counter-clockwise 90deg RLAPI void ImageColorTint(Image *image, Color color); // Modify image color: tint @@ -1309,7 +1379,7 @@ RLAPI TextureCubemap LoadTextureCubemap(Image image, int layout); RLAPI RenderTexture2D LoadRenderTexture(int width, int height); // Load texture for rendering (framebuffer) RLAPI bool IsTextureReady(Texture2D texture); // Check if a texture is ready RLAPI void UnloadTexture(Texture2D texture); // Unload texture from GPU memory (VRAM) -RLAPI bool IsRenderTextureReady(RenderTexture2D target); // Check if a render texture is ready +RLAPI bool IsRenderTextureReady(RenderTexture2D target); // Check if a render texture is ready RLAPI void UnloadRenderTexture(RenderTexture2D target); // Unload render texture from GPU memory (VRAM) RLAPI void UpdateTexture(Texture2D texture, const void *pixels); // Update GPU texture with new data RLAPI void UpdateTextureRec(Texture2D texture, Rectangle rec, const void *pixels); // Update GPU texture rectangle with new data @@ -1351,13 +1421,13 @@ RLAPI int GetPixelDataSize(int width, int height, int format); // G // Font loading/unloading functions RLAPI Font GetFontDefault(void); // Get the default Font RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM) -RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int glyphCount); // Load font from file with extended parameters, use NULL for fontChars and 0 for glyphCount to load the default character set +RLAPI 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 RLAPI Font LoadFontFromImage(Image image, Color key, int firstChar); // Load font from Image (XNA style) -RLAPI Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int glyphCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf' +RLAPI 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' RLAPI bool IsFontReady(Font font); // Check if a font is ready -RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int glyphCount, int type); // Load font data for further use -RLAPI Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **recs, int glyphCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info -RLAPI void UnloadFontData(GlyphInfo *chars, int glyphCount); // Unload font chars info data (RAM) +RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount, int type); // Load font data for further use +RLAPI Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyphCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info +RLAPI void UnloadFontData(GlyphInfo *glyphs, int glyphCount); // Unload font chars info data (RAM) RLAPI void UnloadFont(Font font); // Unload font from GPU memory (VRAM) RLAPI bool ExportFontAsCode(Font font, const char *fileName); // Export font as code file, returns true on success @@ -1367,9 +1437,10 @@ RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color co RLAPI void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using font and additional parameters RLAPI 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) RLAPI void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSize, Color tint); // Draw one character (codepoint) -RLAPI void DrawTextCodepoints(Font font, const int *codepoints, int count, Vector2 position, float fontSize, float spacing, Color tint); // Draw multiple character (codepoint) +RLAPI void DrawTextCodepoints(Font font, const int *codepoints, int codepointCount, Vector2 position, float fontSize, float spacing, Color tint); // Draw multiple character (codepoint) // Text font info functions +RLAPI void SetTextLineSpacing(int spacing); // Set vertical line spacing when drawing with line-breaks RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font RLAPI Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing); // Measure string size for Font RLAPI int GetGlyphIndex(Font font, int codepoint); // Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found @@ -1485,10 +1556,10 @@ RLAPI void SetMaterialTexture(Material *material, int mapType, Texture2D texture RLAPI void SetModelMeshMaterial(Model *model, int meshId, int materialId); // Set material for a mesh // Model animations loading/unloading functions -RLAPI ModelAnimation *LoadModelAnimations(const char *fileName, unsigned int *animCount); // Load model animations from file +RLAPI ModelAnimation *LoadModelAnimations(const char *fileName, int *animCount); // Load model animations from file RLAPI void UpdateModelAnimation(Model model, ModelAnimation anim, int frame); // Update model animation pose RLAPI void UnloadModelAnimation(ModelAnimation anim); // Unload animation data -RLAPI void UnloadModelAnimations(ModelAnimation *animations, unsigned int count); // Unload animation array data +RLAPI void UnloadModelAnimations(ModelAnimation *animations, int animCount); // Unload animation array data RLAPI bool IsModelAnimationValid(Model model, ModelAnimation anim); // Check model animation skeleton match // Collision detection functions @@ -1511,6 +1582,7 @@ RLAPI void InitAudioDevice(void); // Initial RLAPI void CloseAudioDevice(void); // Close the audio device and context RLAPI bool IsAudioDeviceReady(void); // Check if audio device has been initialized successfully RLAPI void SetMasterVolume(float volume); // Set master volume (listener) +RLAPI float GetMasterVolume(void); // Get master volume (listener) // Wave/Sound loading/unloading functions RLAPI Wave LoadWave(const char *fileName); // Load wave data from file @@ -1518,10 +1590,12 @@ RLAPI Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileDat RLAPI bool IsWaveReady(Wave wave); // Checks if wave data is ready RLAPI Sound LoadSound(const char *fileName); // Load sound from file RLAPI Sound LoadSoundFromWave(Wave wave); // Load sound from wave data +RLAPI Sound LoadSoundAlias(Sound source); // Create a new sound that shares the same sample data as the source sound, does not own the sound data RLAPI bool IsSoundReady(Sound sound); // Checks if a sound is ready RLAPI void UpdateSound(Sound sound, const void *data, int sampleCount); // Update sound buffer with new data RLAPI void UnloadWave(Wave wave); // Unload wave data RLAPI void UnloadSound(Sound sound); // Unload sound +RLAPI void UnloadSoundAlias(Sound alias); // Unload a sound alias (does not deallocate sample data) RLAPI bool ExportWave(Wave wave, const char *fileName); // Export wave data to file, returns true on success RLAPI bool ExportWaveAsCode(Wave wave, const char *fileName); // Export wave sample data to code (.h), returns true on success @@ -1573,12 +1647,12 @@ RLAPI void SetAudioStreamVolume(AudioStream stream, float volume); // Set vol RLAPI void SetAudioStreamPitch(AudioStream stream, float pitch); // Set pitch for audio stream (1.0 is base level) RLAPI void SetAudioStreamPan(AudioStream stream, float pan); // Set pan for audio stream (0.5 is centered) RLAPI void SetAudioStreamBufferSizeDefault(int size); // Default size for new audio streams -RLAPI void SetAudioStreamCallback(AudioStream stream, AudioCallback callback); // Audio thread callback to request new data +RLAPI void SetAudioStreamCallback(AudioStream stream, AudioCallback callback); // Audio thread callback to request new data -RLAPI void AttachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Attach audio stream processor to stream +RLAPI void AttachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Attach audio stream processor to stream, receives the samples as s RLAPI void DetachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Detach audio stream processor from stream -RLAPI void AttachAudioMixedProcessor(AudioCallback processor); // Attach audio stream processor to the entire audio pipeline +RLAPI void AttachAudioMixedProcessor(AudioCallback processor); // Attach audio stream processor to the entire audio pipeline, receives the samples as s RLAPI void DetachAudioMixedProcessor(AudioCallback processor); // Detach audio stream processor from the entire audio pipeline #if defined(__cplusplus) diff --git a/include/raymath.h b/include/raymath.h index 422a42e..ff60170 100644 --- a/include/raymath.h +++ b/include/raymath.h @@ -2,25 +2,30 @@ * * raymath v1.5 - Math functions to work with Vector2, Vector3, Matrix and Quaternions * -* CONFIGURATION: -* -* #define RAYMATH_IMPLEMENTATION -* Generates the implementation of the library into the included file. -* If not defined, the library is in header only mode and can be included in other headers -* or source files without problems. But only ONE file should hold the implementation. -* -* #define RAYMATH_STATIC_INLINE -* Define static inline functions code, so #include header suffices for use. -* This may use up lots of memory. -* * CONVENTIONS: -* +* - Matrix structure is defined as row-major (memory layout) but parameters naming AND all +* math operations performed by the library consider the structure as it was column-major +* It is like transposed versions of the matrices are used for all the maths +* It benefits some functions making them cache-friendly and also avoids matrix +* transpositions sometimes required by OpenGL +* Example: In memory order, row0 is [m0 m4 m8 m12] but in semantic math row0 is [m0 m1 m2 m3] * - Functions are always self-contained, no function use another raymath function inside, * required code is directly re-implemented inside * - Functions input parameters are always received by value (2 unavoidable exceptions) * - Functions use always a "result" variable for return * - Functions are always defined inline * - Angles are always in radians (DEG2RAD/RAD2DEG macros provided for convenience) +* - No compound literals used to make sure libray is compatible with C++ +* +* CONFIGURATION: +* #define RAYMATH_IMPLEMENTATION +* Generates the implementation of the library into the included file. +* If not defined, the library is in header only mode and can be included in other headers +* or source files without problems. But only ONE file should hold the implementation. +* +* #define RAYMATH_STATIC_INLINE +* Define static inline functions code, so #include header suffices for use. +* This may use up lots of memory. * * * LICENSE: zlib/libpng @@ -209,6 +214,10 @@ RMAPI float Wrap(float value, float min, float max) // Check whether two given floats are almost equal RMAPI int FloatEquals(float x, float y) { +#if !defined(EPSILON) + #define EPSILON 0.000001f +#endif + int result = (fabsf(x - y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(x), fabsf(y)))); return result; @@ -310,7 +319,12 @@ RMAPI float Vector2DistanceSqr(Vector2 v1, Vector2 v2) // NOTE: Angle is calculated from origin point (0, 0) RMAPI float Vector2Angle(Vector2 v1, Vector2 v2) { - float result = atan2f(v2.y - v1.y, v2.x - v1.x); + float result = 0.0f; + + float dot = v1.x*v2.x + v1.y*v2.y; + float det = v1.x*v2.y - v1.y*v2.x; + + result = atan2f(det, dot); return result; } @@ -322,17 +336,8 @@ RMAPI float Vector2LineAngle(Vector2 start, Vector2 end) { float result = 0.0f; - float dot = start.x*end.x + start.y*end.y; // Dot product - - float dotClamp = (dot < -1.0f)? -1.0f : dot; // Clamp - if (dotClamp > 1.0f) dotClamp = 1.0f; - - result = acosf(dotClamp); - - // Alternative implementation, more costly - //float v1Length = sqrtf((start.x*start.x) + (start.y*start.y)); - //float v2Length = sqrtf((end.x*end.x) + (end.y*end.y)); - //float result = -acosf((start.x*end.x + start.y*end.y)/(v1Length*v2Length)); + // TODO(10/9/2023): Currently angles move clockwise, determine if this is wanted behavior + result = -atan2f(end.y - start.y, end.x - start.x); return result; } @@ -507,6 +512,10 @@ RMAPI Vector2 Vector2ClampValue(Vector2 v, float min, float max) // Check whether two given vectors are almost equal RMAPI int Vector2Equals(Vector2 p, Vector2 q) { +#if !defined(EPSILON) + #define EPSILON 0.000001f +#endif + int result = ((fabsf(p.x - q.x)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) && ((fabsf(p.y - q.y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y))))); @@ -703,12 +712,48 @@ RMAPI Vector3 Vector3Normalize(Vector3 v) Vector3 result = v; float length = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z); - if (length == 0.0f) length = 1.0f; - float ilength = 1.0f/length; + if (length != 0.0f) + { + float ilength = 1.0f/length; - result.x *= ilength; - result.y *= ilength; - result.z *= ilength; + result.x *= ilength; + result.y *= ilength; + result.z *= ilength; + } + + return result; +} + +//Calculate the projection of the vector v1 on to v2 +RMAPI Vector3 Vector3Project(Vector3 v1, Vector3 v2) +{ + Vector3 result = { 0 }; + + float v1dv2 = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z); + float v2dv2 = (v2.x*v2.x + v2.y*v2.y + v2.z*v2.z); + + float mag = v1dv2/v2dv2; + + result.x = v2.x*mag; + result.y = v2.y*mag; + result.z = v2.z*mag; + + return result; +} + +//Calculate the rejection of the vector v1 on to v2 +RMAPI Vector3 Vector3Reject(Vector3 v1, Vector3 v2) +{ + Vector3 result = { 0 }; + + float v1dv2 = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z); + float v2dv2 = (v2.x*v2.x + v2.y*v2.y + v2.z*v2.z); + + float mag = v1dv2/v2dv2; + + result.x = v1.x - (v2.x*mag); + result.y = v1.y - (v2.y*mag); + result.z = v1.z - (v2.z*mag); return result; } @@ -785,7 +830,7 @@ RMAPI Vector3 Vector3RotateByAxisAngle(Vector3 v, Vector3 axis, float angle) Vector3 result = v; // Vector3Normalize(axis); - float length = sqrtf(axis.x * axis.x + axis.y * axis.y + axis.z * axis.z); + float length = sqrtf(axis.x*axis.x + axis.y*axis.y + axis.z*axis.z); if (length == 0.0f) length = 1.0f; float ilength = 1.0f / length; axis.x *= ilength; @@ -794,19 +839,19 @@ RMAPI Vector3 Vector3RotateByAxisAngle(Vector3 v, Vector3 axis, float angle) angle /= 2.0f; float a = sinf(angle); - float b = axis.x * a; - float c = axis.y * a; - float d = axis.z * a; + float b = axis.x*a; + float c = axis.y*a; + float d = axis.z*a; a = cosf(angle); Vector3 w = { b, c, d }; // Vector3CrossProduct(w, v) - 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 }; + 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 }; // Vector3CrossProduct(w, wv) - 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 }; + 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 }; - // Vector3Scale(wv, 2 * a) + // Vector3Scale(wv, 2*a) a *= 2; wv.x *= a; wv.y *= a; @@ -1055,19 +1100,22 @@ RMAPI Vector3 Vector3ClampValue(Vector3 v, float min, float max) // Check whether two given vectors are almost equal RMAPI int Vector3Equals(Vector3 p, Vector3 q) { +#if !defined(EPSILON) + #define EPSILON 0.000001f +#endif + int result = ((fabsf(p.x - q.x)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) && - ((fabsf(p.y - q.y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y))))) && - ((fabsf(p.z - q.z)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.z), fabsf(q.z))))); + ((fabsf(p.y - q.y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y))))) && + ((fabsf(p.z - q.z)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.z), fabsf(q.z))))); return result; } -// Compute the direction of a refracted ray where v specifies the -// normalized direction of the incoming ray, n specifies the -// normalized normal vector of the interface of two optical media, -// and r specifies the ratio of the refractive index of the medium -// from where the ray comes to the refractive index of the medium -// on the other side of the surface +// Compute the direction of a refracted ray +// v: normalized direction of the incoming ray +// n: normalized normal vector of the interface of two optical media +// r: ratio of the refractive index of the medium from where the ray comes +// to the refractive index of the medium on the other side of the surface RMAPI Vector3 Vector3Refract(Vector3 v, Vector3 n, float r) { Vector3 result = { 0 }; @@ -1509,11 +1557,11 @@ RMAPI Matrix MatrixFrustum(double left, double right, double bottom, double top, // Get perspective projection matrix // NOTE: Fovy angle must be provided in radians -RMAPI Matrix MatrixPerspective(double fovy, double aspect, double near, double far) +RMAPI Matrix MatrixPerspective(double fovY, double aspect, double nearPlane, double farPlane) { Matrix result = { 0 }; - double top = near*tan(fovy*0.5); + double top = nearPlane*tan(fovY*0.5); double bottom = -top; double right = top*aspect; double left = -right; @@ -1521,27 +1569,27 @@ RMAPI Matrix MatrixPerspective(double fovy, double aspect, double near, double f // MatrixFrustum(-right, right, -top, top, near, far); float rl = (float)(right - left); float tb = (float)(top - bottom); - float fn = (float)(far - near); + float fn = (float)(farPlane - nearPlane); - result.m0 = ((float)near*2.0f)/rl; - result.m5 = ((float)near*2.0f)/tb; + result.m0 = ((float)nearPlane*2.0f)/rl; + result.m5 = ((float)nearPlane*2.0f)/tb; result.m8 = ((float)right + (float)left)/rl; result.m9 = ((float)top + (float)bottom)/tb; - result.m10 = -((float)far + (float)near)/fn; + result.m10 = -((float)farPlane + (float)nearPlane)/fn; result.m11 = -1.0f; - result.m14 = -((float)far*(float)near*2.0f)/fn; + result.m14 = -((float)farPlane*(float)nearPlane*2.0f)/fn; return result; } // Get orthographic projection matrix -RMAPI Matrix MatrixOrtho(double left, double right, double bottom, double top, double near, double far) +RMAPI Matrix MatrixOrtho(double left, double right, double bottom, double top, double nearPlane, double farPlane) { Matrix result = { 0 }; float rl = (float)(right - left); float tb = (float)(top - bottom); - float fn = (float)(far - near); + float fn = (float)(farPlane - nearPlane); result.m0 = 2.0f/rl; result.m1 = 0.0f; @@ -1557,7 +1605,7 @@ RMAPI Matrix MatrixOrtho(double left, double right, double bottom, double top, d result.m11 = 0.0f; result.m12 = -((float)left + (float)right)/rl; result.m13 = -((float)top + (float)bottom)/tb; - result.m14 = -((float)far + (float)near)/fn; + result.m14 = -((float)farPlane + (float)nearPlane)/fn; result.m15 = 1.0f; return result; @@ -1812,6 +1860,10 @@ RMAPI Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount) { Quaternion result = { 0 }; +#if !defined(EPSILON) + #define EPSILON 0.000001f +#endif + float cosHalfTheta = q1.x*q2.x + q1.y*q2.y + q1.z*q2.z + q1.w*q2.w; if (cosHalfTheta < 0) @@ -1827,7 +1879,7 @@ RMAPI Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount) float halfTheta = acosf(cosHalfTheta); float sinHalfTheta = sqrtf(1.0f - cosHalfTheta*cosHalfTheta); - if (fabsf(sinHalfTheta) < 0.001f) + if (fabsf(sinHalfTheta) < EPSILON) { result.x = (q1.x*0.5f + q2.x*0.5f); result.y = (q1.y*0.5f + q2.y*0.5f); @@ -1882,9 +1934,9 @@ RMAPI Quaternion QuaternionFromMatrix(Matrix mat) { Quaternion result = { 0 }; - float fourWSquaredMinus1 = mat.m0 + mat.m5 + mat.m10; - float fourXSquaredMinus1 = mat.m0 - mat.m5 - mat.m10; - float fourYSquaredMinus1 = mat.m5 - mat.m0 - mat.m10; + float fourWSquaredMinus1 = mat.m0 + mat.m5 + mat.m10; + float fourXSquaredMinus1 = mat.m0 - mat.m5 - mat.m10; + float fourYSquaredMinus1 = mat.m5 - mat.m0 - mat.m10; float fourZSquaredMinus1 = mat.m10 - mat.m0 - mat.m5; int biggestIndex = 0; @@ -1907,34 +1959,34 @@ RMAPI Quaternion QuaternionFromMatrix(Matrix mat) biggestIndex = 3; } - float biggestVal = sqrtf(fourBiggestSquaredMinus1 + 1.0f) * 0.5f; + float biggestVal = sqrtf(fourBiggestSquaredMinus1 + 1.0f)*0.5f; float mult = 0.25f / biggestVal; switch (biggestIndex) { case 0: result.w = biggestVal; - result.x = (mat.m6 - mat.m9) * mult; - result.y = (mat.m8 - mat.m2) * mult; - result.z = (mat.m1 - mat.m4) * mult; + result.x = (mat.m6 - mat.m9)*mult; + result.y = (mat.m8 - mat.m2)*mult; + result.z = (mat.m1 - mat.m4)*mult; break; case 1: result.x = biggestVal; - result.w = (mat.m6 - mat.m9) * mult; - result.y = (mat.m1 + mat.m4) * mult; - result.z = (mat.m8 + mat.m2) * mult; + result.w = (mat.m6 - mat.m9)*mult; + result.y = (mat.m1 + mat.m4)*mult; + result.z = (mat.m8 + mat.m2)*mult; break; case 2: result.y = biggestVal; - result.w = (mat.m8 - mat.m2) * mult; - result.x = (mat.m1 + mat.m4) * mult; - result.z = (mat.m6 + mat.m9) * mult; + result.w = (mat.m8 - mat.m2)*mult; + result.x = (mat.m1 + mat.m4)*mult; + result.z = (mat.m6 + mat.m9)*mult; break; case 3: result.z = biggestVal; - result.w = (mat.m1 - mat.m4) * mult; - result.x = (mat.m8 + mat.m2) * mult; - result.y = (mat.m6 + mat.m9) * mult; + result.w = (mat.m1 - mat.m4)*mult; + result.x = (mat.m8 + mat.m2)*mult; + result.y = (mat.m6 + mat.m9)*mult; break; } @@ -2040,7 +2092,7 @@ RMAPI void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle float resAngle = 2.0f*acosf(q.w); float den = sqrtf(1.0f - q.w*q.w); - if (den > 0.0001f) + if (den > EPSILON) { resAxis.x = q.x/den; resAxis.y = q.y/den; @@ -2119,11 +2171,15 @@ RMAPI Quaternion QuaternionTransform(Quaternion q, Matrix mat) // Check whether two given quaternions are almost equal RMAPI int QuaternionEquals(Quaternion p, Quaternion q) { +#if !defined(EPSILON) + #define EPSILON 0.000001f +#endif + int result = (((fabsf(p.x - q.x)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) && ((fabsf(p.y - q.y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y))))) && ((fabsf(p.z - q.z)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.z), fabsf(q.z))))) && ((fabsf(p.w - q.w)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.w), fabsf(q.w)))))) || - (((fabsf(p.x + q.x)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) && + (((fabsf(p.x + q.x)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) && ((fabsf(p.y + q.y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y))))) && ((fabsf(p.z + q.z)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.z), fabsf(q.z))))) && ((fabsf(p.w + q.w)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.w), fabsf(q.w)))))); diff --git a/include/rlgl.h b/include/rlgl.h index 86208de..6cf9c7e 100644 --- a/include/rlgl.h +++ b/include/rlgl.h @@ -2,82 +2,83 @@ * * rlgl v4.5 - A multi-OpenGL abstraction layer with an immediate-mode style API * -* An abstraction layer for multiple OpenGL versions (1.1, 2.1, 3.3 Core, 4.3 Core, ES 2.0) -* that provides a pseudo-OpenGL 1.1 immediate-mode style API (rlVertex, rlTranslate, rlRotate...) +* DESCRIPTION: +* An abstraction layer for multiple OpenGL versions (1.1, 2.1, 3.3 Core, 4.3 Core, ES 2.0) +* that provides a pseudo-OpenGL 1.1 immediate-mode style API (rlVertex, rlTranslate, rlRotate...) * -* When choosing an OpenGL backend different than OpenGL 1.1, some internal buffer are -* initialized on rlglInit() to accumulate vertex data. +* ADDITIONAL NOTES: +* When choosing an OpenGL backend different than OpenGL 1.1, some internal buffer are +* initialized on rlglInit() to accumulate vertex data. * -* When an internal state change is required all the stored vertex data is renderer in batch, -* additionally, rlDrawRenderBatchActive() could be called to force flushing of the batch. +* When an internal state change is required all the stored vertex data is renderer in batch, +* additionally, rlDrawRenderBatchActive() could be called to force flushing of the batch. * -* Some additional resources are also loaded for convenience, here the complete list: -* - Default batch (RLGL.defaultBatch): RenderBatch system to accumulate vertex data -* - Default texture (RLGL.defaultTextureId): 1x1 white pixel R8G8B8A8 -* - Default shader (RLGL.State.defaultShaderId, RLGL.State.defaultShaderLocs) -* -* Internal buffer (and additional resources) must be manually unloaded calling rlglClose(). +* Some resources are also loaded for convenience, here the complete list: +* - Default batch (RLGL.defaultBatch): RenderBatch system to accumulate vertex data +* - Default texture (RLGL.defaultTextureId): 1x1 white pixel R8G8B8A8 +* - Default shader (RLGL.State.defaultShaderId, RLGL.State.defaultShaderLocs) * +* Internal buffer (and resources) must be manually unloaded calling rlglClose(). * * CONFIGURATION: +* #define GRAPHICS_API_OPENGL_11 +* #define GRAPHICS_API_OPENGL_21 +* #define GRAPHICS_API_OPENGL_33 +* #define GRAPHICS_API_OPENGL_43 +* #define GRAPHICS_API_OPENGL_ES2 +* #define GRAPHICS_API_OPENGL_ES3 +* Use selected OpenGL graphics backend, should be supported by platform +* Those preprocessor defines are only used on rlgl module, if OpenGL version is +* required by any other module, use rlGetVersion() to check it * -* #define GRAPHICS_API_OPENGL_11 -* #define GRAPHICS_API_OPENGL_21 -* #define GRAPHICS_API_OPENGL_33 -* #define GRAPHICS_API_OPENGL_43 -* #define GRAPHICS_API_OPENGL_ES2 -* Use selected OpenGL graphics backend, should be supported by platform -* Those preprocessor defines are only used on rlgl module, if OpenGL version is -* required by any other module, use rlGetVersion() to check it -* -* #define RLGL_IMPLEMENTATION -* Generates the implementation of the library into the included file. -* If not defined, the library is in header only mode and can be included in other headers -* or source files without problems. But only ONE file should hold the implementation. +* #define RLGL_IMPLEMENTATION +* Generates the implementation of the library into the included file. +* If not defined, the library is in header only mode and can be included in other headers +* or source files without problems. But only ONE file should hold the implementation. * -* #define RLGL_RENDER_TEXTURES_HINT -* Enable framebuffer objects (fbo) support (enabled by default) -* Some GPUs could not support them despite the OpenGL version +* #define RLGL_RENDER_TEXTURES_HINT +* Enable framebuffer objects (fbo) support (enabled by default) +* Some GPUs could not support them despite the OpenGL version * -* #define RLGL_SHOW_GL_DETAILS_INFO -* Show OpenGL extensions and capabilities detailed logs on init +* #define RLGL_SHOW_GL_DETAILS_INFO +* Show OpenGL extensions and capabilities detailed logs on init * -* #define RLGL_ENABLE_OPENGL_DEBUG_CONTEXT -* Enable debug context (only available on OpenGL 4.3) +* #define RLGL_ENABLE_OPENGL_DEBUG_CONTEXT +* Enable debug context (only available on OpenGL 4.3) * -* rlgl capabilities could be customized just defining some internal -* values before library inclusion (default values listed): +* rlgl capabilities could be customized just defining some internal +* values before library inclusion (default values listed): * -* #define RL_DEFAULT_BATCH_BUFFER_ELEMENTS 8192 // Default internal render batch elements limits -* #define RL_DEFAULT_BATCH_BUFFERS 1 // Default number of batch buffers (multi-buffering) -* #define RL_DEFAULT_BATCH_DRAWCALLS 256 // Default number of batch draw calls (by state changes: mode, texture) -* #define RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS 4 // Maximum number of textures units that can be activated on batch drawing (SetShaderValueTexture()) +* #define RL_DEFAULT_BATCH_BUFFER_ELEMENTS 8192 // Default internal render batch elements limits +* #define RL_DEFAULT_BATCH_BUFFERS 1 // Default number of batch buffers (multi-buffering) +* #define RL_DEFAULT_BATCH_DRAWCALLS 256 // Default number of batch draw calls (by state changes: mode, texture) +* #define RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS 4 // Maximum number of textures units that can be activated on batch drawing (SetShaderValueTexture()) * -* #define RL_MAX_MATRIX_STACK_SIZE 32 // Maximum size of internal Matrix stack -* #define RL_MAX_SHADER_LOCATIONS 32 // Maximum number of shader locations supported -* #define RL_CULL_DISTANCE_NEAR 0.01 // Default projection matrix near cull distance -* #define RL_CULL_DISTANCE_FAR 1000.0 // Default projection matrix far cull distance +* #define RL_MAX_MATRIX_STACK_SIZE 32 // Maximum size of internal Matrix stack +* #define RL_MAX_SHADER_LOCATIONS 32 // Maximum number of shader locations supported +* #define RL_CULL_DISTANCE_NEAR 0.01 // Default projection matrix near cull distance +* #define RL_CULL_DISTANCE_FAR 1000.0 // Default projection matrix far cull distance * -* When loading a shader, the following vertex attribute and uniform -* location names are tried to be set automatically: +* When loading a shader, the following vertex attributes and uniform +* location names are tried to be set automatically: * -* #define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION "vertexPosition" // Bound by default to shader location: 0 -* #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD "vertexTexCoord" // Bound by default to shader location: 1 -* #define RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL "vertexNormal" // Bound by default to shader location: 2 -* #define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR "vertexColor" // Bound by default to shader location: 3 -* #define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT "vertexTangent" // Bound by default to shader location: 4 -* #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix -* #define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW "matView" // view matrix -* #define RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION "matProjection" // projection matrix -* #define RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL "matModel" // model matrix -* #define RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL "matNormal" // normal matrix (transpose(inverse(matModelView)) -* #define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color) -* #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0) -* #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1 "texture1" // texture1 (texture slot active 1) -* #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 "texture2" // texture2 (texture slot active 2) +* #define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION "vertexPosition" // Bound by default to shader location: 0 +* #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD "vertexTexCoord" // Bound by default to shader location: 1 +* #define RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL "vertexNormal" // Bound by default to shader location: 2 +* #define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR "vertexColor" // Bound by default to shader location: 3 +* #define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT "vertexTangent" // Bound by default to shader location: 4 +* #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Bound by default to shader location: 5 +* #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix +* #define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW "matView" // view matrix +* #define RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION "matProjection" // projection matrix +* #define RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL "matModel" // model matrix +* #define RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL "matNormal" // normal matrix (transpose(inverse(matModelView)) +* #define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color) +* #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0) +* #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1 "texture1" // texture1 (texture slot active 1) +* #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 "texture2" // texture2 (texture slot active 2) * * DEPENDENCIES: -* * - OpenGL libraries (depending on platform and OpenGL version selected) * - GLAD OpenGL extensions loading library (only for OpenGL 3.3 Core, 4.3 Core) * @@ -148,7 +149,8 @@ !defined(GRAPHICS_API_OPENGL_21) && \ !defined(GRAPHICS_API_OPENGL_33) && \ !defined(GRAPHICS_API_OPENGL_43) && \ - !defined(GRAPHICS_API_OPENGL_ES2) + !defined(GRAPHICS_API_OPENGL_ES2) && \ + !defined(GRAPHICS_API_OPENGL_ES3) #define GRAPHICS_API_OPENGL_33 #endif @@ -179,6 +181,11 @@ #define GRAPHICS_API_OPENGL_33 #endif +// OpenGL ES 3.0 uses OpenGL ES 2.0 functionality (and more) +#if defined(GRAPHICS_API_OPENGL_ES3) + #define GRAPHICS_API_OPENGL_ES2 +#endif + // Support framebuffer objects by default // NOTE: Some driver implementation do not support it, despite they should #define RLGL_RENDER_TEXTURES_HINT @@ -383,7 +390,8 @@ typedef enum { RL_OPENGL_21, // OpenGL 2.1 (GLSL 120) RL_OPENGL_33, // OpenGL 3.3 (GLSL 330) RL_OPENGL_43, // OpenGL 4.3 (using GLSL 330) - RL_OPENGL_ES_20 // OpenGL ES 2.0 (GLSL 100) + RL_OPENGL_ES_20, // OpenGL ES 2.0 (GLSL 100) + RL_OPENGL_ES_30 // OpenGL ES 3.0 (GLSL 300 es) } rlGlVersion; // Trace log level @@ -412,6 +420,9 @@ typedef enum { RL_PIXELFORMAT_UNCOMPRESSED_R32, // 32 bpp (1 channel - float) RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32, // 32*3 bpp (3 channels - float) RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32, // 32*4 bpp (4 channels - float) + RL_PIXELFORMAT_UNCOMPRESSED_R16, // 16 bpp (1 channel - half float) + RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16, // 16*3 bpp (3 channels - half float) + RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16, // 16*4 bpp (4 channels - half float) RL_PIXELFORMAT_COMPRESSED_DXT1_RGB, // 4 bpp (no alpha) RL_PIXELFORMAT_COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha) RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA, // 8 bpp @@ -506,28 +517,28 @@ typedef enum { // Framebuffer attachment type // NOTE: By default up to 8 color channels defined, but it can be more typedef enum { - RL_ATTACHMENT_COLOR_CHANNEL0 = 0, // Framebuffer attachment type: color 0 - RL_ATTACHMENT_COLOR_CHANNEL1, // Framebuffer attachment type: color 1 - RL_ATTACHMENT_COLOR_CHANNEL2, // Framebuffer attachment type: color 2 - RL_ATTACHMENT_COLOR_CHANNEL3, // Framebuffer attachment type: color 3 - RL_ATTACHMENT_COLOR_CHANNEL4, // Framebuffer attachment type: color 4 - RL_ATTACHMENT_COLOR_CHANNEL5, // Framebuffer attachment type: color 5 - RL_ATTACHMENT_COLOR_CHANNEL6, // Framebuffer attachment type: color 6 - RL_ATTACHMENT_COLOR_CHANNEL7, // Framebuffer attachment type: color 7 - RL_ATTACHMENT_DEPTH = 100, // Framebuffer attachment type: depth - RL_ATTACHMENT_STENCIL = 200, // Framebuffer attachment type: stencil + RL_ATTACHMENT_COLOR_CHANNEL0 = 0, // Framebuffer attachment type: color 0 + RL_ATTACHMENT_COLOR_CHANNEL1 = 1, // Framebuffer attachment type: color 1 + RL_ATTACHMENT_COLOR_CHANNEL2 = 2, // Framebuffer attachment type: color 2 + RL_ATTACHMENT_COLOR_CHANNEL3 = 3, // Framebuffer attachment type: color 3 + RL_ATTACHMENT_COLOR_CHANNEL4 = 4, // Framebuffer attachment type: color 4 + RL_ATTACHMENT_COLOR_CHANNEL5 = 5, // Framebuffer attachment type: color 5 + RL_ATTACHMENT_COLOR_CHANNEL6 = 6, // Framebuffer attachment type: color 6 + RL_ATTACHMENT_COLOR_CHANNEL7 = 7, // Framebuffer attachment type: color 7 + RL_ATTACHMENT_DEPTH = 100, // Framebuffer attachment type: depth + RL_ATTACHMENT_STENCIL = 200, // Framebuffer attachment type: stencil } rlFramebufferAttachType; // Framebuffer texture attachment type typedef enum { - RL_ATTACHMENT_CUBEMAP_POSITIVE_X = 0, // Framebuffer texture attachment type: cubemap, +X side - RL_ATTACHMENT_CUBEMAP_NEGATIVE_X, // Framebuffer texture attachment type: cubemap, -X side - RL_ATTACHMENT_CUBEMAP_POSITIVE_Y, // Framebuffer texture attachment type: cubemap, +Y side - RL_ATTACHMENT_CUBEMAP_NEGATIVE_Y, // Framebuffer texture attachment type: cubemap, -Y side - RL_ATTACHMENT_CUBEMAP_POSITIVE_Z, // Framebuffer texture attachment type: cubemap, +Z side - RL_ATTACHMENT_CUBEMAP_NEGATIVE_Z, // Framebuffer texture attachment type: cubemap, -Z side - RL_ATTACHMENT_TEXTURE2D = 100, // Framebuffer texture attachment type: texture2d - RL_ATTACHMENT_RENDERBUFFER = 200, // Framebuffer texture attachment type: renderbuffer + RL_ATTACHMENT_CUBEMAP_POSITIVE_X = 0, // Framebuffer texture attachment type: cubemap, +X side + RL_ATTACHMENT_CUBEMAP_NEGATIVE_X = 1, // Framebuffer texture attachment type: cubemap, -X side + RL_ATTACHMENT_CUBEMAP_POSITIVE_Y = 2, // Framebuffer texture attachment type: cubemap, +Y side + RL_ATTACHMENT_CUBEMAP_NEGATIVE_Y = 3, // Framebuffer texture attachment type: cubemap, -Y side + RL_ATTACHMENT_CUBEMAP_POSITIVE_Z = 4, // Framebuffer texture attachment type: cubemap, +Z side + RL_ATTACHMENT_CUBEMAP_NEGATIVE_Z = 5, // Framebuffer texture attachment type: cubemap, -Z side + RL_ATTACHMENT_TEXTURE2D = 100, // Framebuffer texture attachment type: texture2d + RL_ATTACHMENT_RENDERBUFFER = 200, // Framebuffer texture attachment type: renderbuffer } rlFramebufferAttachTextureType; // Face culling mode @@ -607,6 +618,7 @@ RLAPI void rlDisableShader(void); // Disable shader progra RLAPI void rlEnableFramebuffer(unsigned int id); // Enable render texture (fbo) RLAPI void rlDisableFramebuffer(void); // Disable render texture (fbo), return to default framebuffer RLAPI void rlActiveDrawBuffers(int count); // Activate multiple draw color buffers +RLAPI void rlBlitFramebuffer(int srcX, int srcY, int srcWidth, int srcHeight, int dstX, int dstY, int dstWidth, int dstHeight, int bufferMask); // Blit active framebuffer to main framebuffer // General render state RLAPI void rlEnableColorBlend(void); // Enable color blending @@ -622,7 +634,8 @@ RLAPI void rlEnableScissorTest(void); // Enable scissor test RLAPI void rlDisableScissorTest(void); // Disable scissor test RLAPI void rlScissor(int x, int y, int width, int height); // Scissor test RLAPI void rlEnableWireMode(void); // Enable wire mode -RLAPI void rlDisableWireMode(void); // Disable wire mode +RLAPI void rlEnablePointMode(void); // Enable point mode +RLAPI void rlDisableWireMode(void); // Disable wire mode ( and point ) maybe rename RLAPI void rlSetLineWidth(float width); // Set the line drawing width RLAPI float rlGetLineWidth(void); // Get the line drawing width RLAPI void rlEnableSmoothLines(void); // Enable line aliasing @@ -787,13 +800,17 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad #define GLAD_FREE RL_FREE #define GLAD_GL_IMPLEMENTATION - #include "external/glad.h" // GLAD extensions loading library, includes OpenGL headers + #include "external/glad.h" // GLAD extensions loading library, includes OpenGL headers #endif -#if defined(GRAPHICS_API_OPENGL_ES2) +#if defined(GRAPHICS_API_OPENGL_ES3) + #include // OpenGL ES 3.0 library + #define GL_GLEXT_PROTOTYPES + #include // OpenGL ES 2.0 extensions library +#elif defined(GRAPHICS_API_OPENGL_ES2) // NOTE: OpenGL ES 2.0 can be enabled on PLATFORM_DESKTOP, // in that case, functions are loaded from a custom glad for OpenGL ES 2.0 - #if defined(PLATFORM_DESKTOP) + #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_DESKTOP_SDL) #define GLAD_GLES2_IMPLEMENTATION #include "external/glad_gles2.h" #else @@ -805,7 +822,7 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad // It seems OpenGL ES 2.0 instancing entry points are not defined on Raspberry Pi // provided headers (despite being defined in official Khronos GLES2 headers) - #if defined(PLATFORM_RPI) || defined(PLATFORM_DRM) + #if defined(PLATFORM_DRM) typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount); typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISOREXTPROC) (GLuint index, GLuint divisor); @@ -887,8 +904,10 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad #if defined(GRAPHICS_API_OPENGL_ES2) #define glClearDepth glClearDepthf - #define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER - #define GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER + #if !defined(GRAPHICS_API_OPENGL_ES3) + #define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER + #define GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER + #endif #endif // Default shader vertex attribute names to set location points @@ -999,6 +1018,7 @@ typedef struct rlglData { bool texDepth; // Depth textures supported (GL_ARB_depth_texture, GL_OES_depth_texture) bool texDepthWebGL; // Depth textures supported WebGL specific (GL_WEBGL_depth_texture) bool texFloat32; // float textures support (32 bit per channel) (GL_OES_texture_float) + bool texFloat16; // half float textures support (16 bit per channel) (GL_OES_texture_half_float) bool texCompDXT; // DDS texture compression support (GL_EXT_texture_compression_s3tc, GL_WEBGL_compressed_texture_s3tc, GL_WEBKIT_WEBGL_compressed_texture_s3tc) bool texCompETC1; // ETC1 texture compression support (GL_OES_compressed_ETC1_RGB8_texture, GL_WEBGL_compressed_texture_etc1) bool texCompETC2; // ETC2/EAC texture compression support (GL_ARB_ES3_compatibility) @@ -1026,7 +1046,7 @@ typedef void *(*rlglLoadProc)(const char *name); // OpenGL extension functions static rlglData RLGL = { 0 }; #endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2 -#if defined(GRAPHICS_API_OPENGL_ES2) +#if defined(GRAPHICS_API_OPENGL_ES2) && !defined(GRAPHICS_API_OPENGL_ES3) // NOTE: VAO functionality is exposed through extensions (OES) static PFNGLGENVERTEXARRAYSOESPROC glGenVertexArrays = NULL; static PFNGLBINDVERTEXARRAYOESPROC glBindVertexArray = NULL; @@ -1045,7 +1065,7 @@ static PFNGLVERTEXATTRIBDIVISOREXTPROC glVertexAttribDivisor = NULL; static void rlLoadShaderDefault(void); // Load default shader static void rlUnloadShaderDefault(void); // Unload default shader #if defined(RLGL_SHOW_GL_DETAILS_INFO) -static char *rlGetCompressedFormatName(int format); // Get compressed format official GL identifier name +static const char *rlGetCompressedFormatName(int format); // Get compressed format official GL identifier name #endif // RLGL_SHOW_GL_DETAILS_INFO #endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2 @@ -1416,8 +1436,7 @@ void rlVertex3f(float x, float y, float z) RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].texcoords[2*RLGL.State.vertexCounter] = RLGL.State.texcoordx; RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].texcoords[2*RLGL.State.vertexCounter + 1] = RLGL.State.texcoordy; - // TODO: Add current normal - // By default rlVertexBuffer type does not store normals + // WARNING: By default rlVertexBuffer struct does not store normals // Add current color RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.State.vertexCounter] = RLGL.State.colorr; @@ -1702,11 +1721,19 @@ void rlDisableFramebuffer(void) #endif } +// Blit active framebuffer to main framebuffer +void rlBlitFramebuffer(int srcX, int srcY, int srcWidth, int srcHeight, int dstX, int dstY, int dstWidth, int dstHeight, int bufferMask) +{ +#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES3)) && defined(RLGL_RENDER_TEXTURES_HINT) + glBlitFramebuffer(srcX, srcY, srcWidth, srcHeight, dstX, dstY, dstWidth, dstHeight, bufferMask, GL_NEAREST); +#endif +} + // Activate multiple draw color buffers // NOTE: One color buffer is always active by default void rlActiveDrawBuffers(int count) { -#if (defined(GRAPHICS_API_OPENGL_33) && defined(RLGL_RENDER_TEXTURES_HINT)) +#if ((defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES3)) && defined(RLGL_RENDER_TEXTURES_HINT)) // NOTE: Maximum number of draw buffers supported is implementation dependant, // it can be queried with glGet*() but it must be at least 8 //GLint maxDrawBuffers = 0; @@ -1718,6 +1745,16 @@ void rlActiveDrawBuffers(int count) else { unsigned int buffers[8] = { +#if defined(GRAPHICS_API_OPENGL_ES3) + GL_COLOR_ATTACHMENT0_EXT, + GL_COLOR_ATTACHMENT1_EXT, + GL_COLOR_ATTACHMENT2_EXT, + GL_COLOR_ATTACHMENT3_EXT, + GL_COLOR_ATTACHMENT4_EXT, + GL_COLOR_ATTACHMENT5_EXT, + GL_COLOR_ATTACHMENT6_EXT, + GL_COLOR_ATTACHMENT7_EXT, +#else GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, @@ -1726,9 +1763,14 @@ void rlActiveDrawBuffers(int count) GL_COLOR_ATTACHMENT5, GL_COLOR_ATTACHMENT6, GL_COLOR_ATTACHMENT7, +#endif }; +#if defined(GRAPHICS_API_OPENGL_ES3) + glDrawBuffersEXT(count, buffers); +#else glDrawBuffers(count, buffers); +#endif } } else TRACELOG(LOG_WARNING, "GL: One color buffer active by default"); @@ -1792,6 +1834,14 @@ void rlEnableWireMode(void) #endif } +void rlEnablePointMode(void) +{ +#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) + // NOTE: glPolygonMode() not available on OpenGL ES + glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); + glEnable(GL_PROGRAM_POINT_SIZE); +#endif +} // Disable wire mode void rlDisableWireMode(void) { @@ -2047,7 +2097,7 @@ void rlglInit(int width, int height) if ((glDebugMessageCallback != NULL) && (glDebugMessageControl != NULL)) { glDebugMessageCallback(rlDebugMessageCallback, 0); - // glDebugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DEBUG_SEVERITY_HIGH, 0, 0, GL_TRUE); // TODO: Filter message + // glDebugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DEBUG_SEVERITY_HIGH, 0, 0, GL_TRUE); // Debug context options: // - GL_DEBUG_OUTPUT - Faster version but not useful for breakpoints @@ -2168,6 +2218,7 @@ void rlLoadExtensions(void *loader) RLGL.ExtSupported.instancing = (GLAD_GL_EXT_draw_instanced && GLAD_GL_ARB_instanced_arrays); RLGL.ExtSupported.texNPOT = GLAD_GL_ARB_texture_non_power_of_two; RLGL.ExtSupported.texFloat32 = GLAD_GL_ARB_texture_float; + RLGL.ExtSupported.texFloat16 = GLAD_GL_ARB_texture_float; RLGL.ExtSupported.texDepth = GLAD_GL_ARB_depth_texture; RLGL.ExtSupported.maxDepthBits = 32; RLGL.ExtSupported.texAnisoFilter = GLAD_GL_EXT_texture_filter_anisotropic; @@ -2179,6 +2230,7 @@ void rlLoadExtensions(void *loader) RLGL.ExtSupported.instancing = true; RLGL.ExtSupported.texNPOT = true; RLGL.ExtSupported.texFloat32 = true; + RLGL.ExtSupported.texFloat16 = true; RLGL.ExtSupported.texDepth = true; RLGL.ExtSupported.maxDepthBits = 32; RLGL.ExtSupported.texAnisoFilter = true; @@ -2196,11 +2248,35 @@ void rlLoadExtensions(void *loader) #endif // GRAPHICS_API_OPENGL_33 -#if defined(GRAPHICS_API_OPENGL_ES2) - - #if defined(PLATFORM_DESKTOP) +#if defined(GRAPHICS_API_OPENGL_ES3) + // Register supported extensions flags + // OpenGL ES 3.0 extensions supported by default (or it should be) + RLGL.ExtSupported.vao = true; + RLGL.ExtSupported.instancing = true; + RLGL.ExtSupported.texNPOT = true; + RLGL.ExtSupported.texFloat32 = true; + RLGL.ExtSupported.texFloat16 = true; + RLGL.ExtSupported.texDepth = true; + RLGL.ExtSupported.texDepthWebGL = true; + RLGL.ExtSupported.maxDepthBits = 24; + RLGL.ExtSupported.texAnisoFilter = true; + RLGL.ExtSupported.texMirrorClamp = true; + // TODO: Check for additional OpenGL ES 3.0 supported extensions: + //RLGL.ExtSupported.texCompDXT = true; + //RLGL.ExtSupported.texCompETC1 = true; + //RLGL.ExtSupported.texCompETC2 = true; + //RLGL.ExtSupported.texCompPVRT = true; + //RLGL.ExtSupported.texCompASTC = true; + //RLGL.ExtSupported.maxAnisotropyLevel = true; + //RLGL.ExtSupported.computeShader = true; + //RLGL.ExtSupported.ssbo = true; + +#elif defined(GRAPHICS_API_OPENGL_ES2) + + #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_DESKTOP_SDL) + // TODO: Support GLAD loader for OpenGL ES 3.0 if (gladLoadGLES2((GLADloadfunc)loader) == 0) TRACELOG(RL_LOG_WARNING, "GLAD: Cannot load OpenGL ES2.0 functions"); - else TRACELOG(RL_LOG_INFO, "GLAD: OpenGL ES2.0 loaded successfully"); + else TRACELOG(RL_LOG_INFO, "GLAD: OpenGL ES 2.0 loaded successfully"); #endif // Get supported extensions list @@ -2276,6 +2352,7 @@ void rlLoadExtensions(void *loader) // Check texture float support if (strcmp(extList[i], (const char *)"GL_OES_texture_float") == 0) RLGL.ExtSupported.texFloat32 = true; + if (strcmp(extList[i], (const char *)"GL_OES_texture_half_float") == 0) RLGL.ExtSupported.texFloat16 = true; // Check depth texture support if (strcmp(extList[i], (const char *)"GL_OES_depth_texture") == 0) RLGL.ExtSupported.texDepth = true; @@ -2391,15 +2468,17 @@ int rlGetVersion(void) #endif #if defined(GRAPHICS_API_OPENGL_21) glVersion = RL_OPENGL_21; +#elif defined(GRAPHICS_API_OPENGL_43) + glVersion = RL_OPENGL_43; #elif defined(GRAPHICS_API_OPENGL_33) glVersion = RL_OPENGL_33; #endif -#if defined(GRAPHICS_API_OPENGL_43) - glVersion = RL_OPENGL_43; -#endif -#if defined(GRAPHICS_API_OPENGL_ES2) +#if defined(GRAPHICS_API_OPENGL_ES3) + glVersion = RL_OPENGL_ES_30; +#elif defined(GRAPHICS_API_OPENGL_ES2) glVersion = RL_OPENGL_ES_20; #endif + return glVersion; } @@ -2648,7 +2727,7 @@ void rlDrawRenderBatch(rlRenderBatch *batch) // Update batch vertex buffers //------------------------------------------------------------------------------------------------------------ // NOTE: If there is not vertex data, buffers doesn't need to be updated (vertexCount > 0) - // TODO: If no data changed on the CPU arrays --> No need to re-update GPU arrays (change flag required) + // TODO: If no data changed on the CPU arrays --> No need to re-update GPU arrays (use a change detector flag?) if (RLGL.State.vertexCounter > 0) { // Activate elements VAO @@ -2943,7 +3022,11 @@ unsigned int rlLoadTexture(const void *data, int width, int height, int format, int mipWidth = width; int mipHeight = height; - int mipOffset = 0; // Mipmap data offset + int mipOffset = 0; // Mipmap data offset, only used for tracelog + + // NOTE: Added pointer math separately from function to avoid UBSAN complaining + unsigned char *dataPtr = NULL; + if (data != NULL) dataPtr = (unsigned char *)data; // Load the different mipmap levels for (int i = 0; i < mipmapCount; i++) @@ -2955,11 +3038,11 @@ unsigned int rlLoadTexture(const void *data, int width, int height, int format, TRACELOGD("TEXTURE: Load mipmap level %i (%i x %i), size: %i, offset: %i", i, mipWidth, mipHeight, mipSize, mipOffset); - if (glInternalFormat != -1) + if (glInternalFormat != 0) { - if (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) glTexImage2D(GL_TEXTURE_2D, i, glInternalFormat, mipWidth, mipHeight, 0, glFormat, glType, (unsigned char *)data + mipOffset); + if (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) glTexImage2D(GL_TEXTURE_2D, i, glInternalFormat, mipWidth, mipHeight, 0, glFormat, glType, dataPtr); #if !defined(GRAPHICS_API_OPENGL_11) - else glCompressedTexImage2D(GL_TEXTURE_2D, i, glInternalFormat, mipWidth, mipHeight, 0, mipSize, (unsigned char *)data + mipOffset); + else glCompressedTexImage2D(GL_TEXTURE_2D, i, glInternalFormat, mipWidth, mipHeight, 0, mipSize, dataPtr); #endif #if defined(GRAPHICS_API_OPENGL_33) @@ -2982,7 +3065,8 @@ unsigned int rlLoadTexture(const void *data, int width, int height, int format, mipWidth /= 2; mipHeight /= 2; - mipOffset += mipSize; + mipOffset += mipSize; // Increment offset position to next mipmap + if (data != NULL) dataPtr += mipSize; // Increment data pointer to next mipmap // Security check for NPOT textures if (mipWidth < 1) mipWidth = 1; @@ -3049,7 +3133,7 @@ unsigned int rlLoadTextureDepth(int width, int height, bool useRenderBuffer) // Possible formats: GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT32 and GL_DEPTH_COMPONENT32F unsigned int glInternalFormat = GL_DEPTH_COMPONENT; -#if defined(GRAPHICS_API_OPENGL_ES2) +#if (defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_ES3)) // WARNING: WebGL platform requires unsized internal format definition (GL_DEPTH_COMPONENT) // while other platforms using OpenGL ES 2.0 require/support sized internal formats depending on the GPU capabilities if (!RLGL.ExtSupported.texDepthWebGL || useRenderBuffer) @@ -3108,7 +3192,7 @@ unsigned int rlLoadTextureCubemap(const void *data, int size, int format) unsigned int glInternalFormat, glFormat, glType; rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType); - if (glInternalFormat != -1) + if (glInternalFormat != 0) { // Load cubemap faces for (unsigned int i = 0; i < 6; i++) @@ -3117,13 +3201,9 @@ unsigned int rlLoadTextureCubemap(const void *data, int size, int format) { if (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) { - if (format == RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32) - { - // Instead of using a sized internal texture format (GL_RGB16F, GL_RGB32F), we let the driver to choose the better format for us (GL_RGB) - if (RLGL.ExtSupported.texFloat32) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, size, size, 0, GL_RGB, GL_FLOAT, NULL); - else TRACELOG(RL_LOG_WARNING, "TEXTURES: Cubemap requested format not supported"); - } - else if ((format == RL_PIXELFORMAT_UNCOMPRESSED_R32) || (format == RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32)) TRACELOG(RL_LOG_WARNING, "TEXTURES: Cubemap requested format not supported"); + if ((format == RL_PIXELFORMAT_UNCOMPRESSED_R32) || (format == RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32) + || (format == RL_PIXELFORMAT_UNCOMPRESSED_R16) || (format == RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16)) + TRACELOG(RL_LOG_WARNING, "TEXTURES: Cubemap requested format not supported"); else glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, size, size, 0, glFormat, glType, NULL); } else TRACELOG(RL_LOG_WARNING, "TEXTURES: Empty cubemap creation does not support compressed format"); @@ -3180,7 +3260,7 @@ void rlUpdateTexture(unsigned int id, int offsetX, int offsetY, int width, int h unsigned int glInternalFormat, glFormat, glType; rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType); - if ((glInternalFormat != -1) && (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB)) + if ((glInternalFormat != 0) && (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB)) { glTexSubImage2D(GL_TEXTURE_2D, 0, offsetX, offsetY, width, height, glFormat, glType, data); } @@ -3206,9 +3286,27 @@ void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned case RL_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_SHORT_4_4_4_4; break; case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_BYTE; break; #if !defined(GRAPHICS_API_OPENGL_11) - 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 - 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 - 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 + #if defined(GRAPHICS_API_OPENGL_ES3) + case RL_PIXELFORMAT_UNCOMPRESSED_R32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_R32F_EXT; *glFormat = GL_RED_EXT; *glType = GL_FLOAT; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGB32F_EXT; *glFormat = GL_RGB; *glType = GL_FLOAT; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGBA32F_EXT; *glFormat = GL_RGBA; *glType = GL_FLOAT; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_R16F_EXT; *glFormat = GL_RED_EXT; *glType = GL_HALF_FLOAT; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB16F_EXT; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA16F_EXT; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT; break; + #else + 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 + 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 + 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 + #if defined(GRAPHICS_API_OPENGL_21) + case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_HALF_FLOAT_ARB; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT_ARB; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT_ARB; break; + #else // defined(GRAPHICS_API_OPENGL_ES2) + 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 + 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 + 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 + #endif + #endif #endif #elif defined(GRAPHICS_API_OPENGL_33) case RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: *glInternalFormat = GL_R8; *glFormat = GL_RED; *glType = GL_UNSIGNED_BYTE; break; @@ -3221,6 +3319,9 @@ void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned case RL_PIXELFORMAT_UNCOMPRESSED_R32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_R32F; *glFormat = GL_RED; *glType = GL_FLOAT; break; case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGB32F; *glFormat = GL_RGB; *glType = GL_FLOAT; break; case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGBA32F; *glFormat = GL_RGBA; *glType = GL_FLOAT; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_R16F; *glFormat = GL_RED; *glType = GL_HALF_FLOAT; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB16F; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA16F; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT; break; #endif #if !defined(GRAPHICS_API_OPENGL_11) case RL_PIXELFORMAT_COMPRESSED_DXT1_RGB: if (RLGL.ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; break; @@ -3303,7 +3404,7 @@ void *rlReadTexturePixels(unsigned int id, int width, int height, int format) rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType); unsigned int size = rlGetPixelDataSize(width, height, format); - if ((glInternalFormat != -1) && (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB)) + if ((glInternalFormat != 0) && (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB)) { pixels = RL_MALLOC(size); glGetTexImage(GL_TEXTURE_2D, 0, glFormat, glType, pixels); @@ -3466,11 +3567,14 @@ bool rlFramebufferComplete(unsigned int id) void rlUnloadFramebuffer(unsigned int id) { #if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(RLGL_RENDER_TEXTURES_HINT) - // Query depth attachment to automatically delete texture/renderbuffer int depthType = 0, depthId = 0; glBindFramebuffer(GL_FRAMEBUFFER, id); // Bind framebuffer to query depth texture type glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &depthType); + + // TODO: Review warning retrieving object name in WebGL + // WARNING: WebGL: INVALID_ENUM: getFramebufferAttachmentParameter: invalid parameter name + // https://registry.khronos.org/webgl/specs/latest/1.0/ glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &depthId); unsigned int depthIdU = (unsigned int)depthId; @@ -3616,7 +3720,11 @@ void rlDrawVertexArray(int offset, int count) // Draw vertex array elements void rlDrawVertexArrayElements(int offset, int count, const void *buffer) { - glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, (const unsigned short *)buffer + offset); + // NOTE: Added pointer math separately from function to avoid UBSAN complaining + unsigned short *bufferPtr = (unsigned short *)buffer; + if (offset > 0) bufferPtr += offset; + + glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, (const unsigned short *)bufferPtr); } // Draw vertex array instanced @@ -3631,7 +3739,11 @@ void rlDrawVertexArrayInstanced(int offset, int count, int instances) void rlDrawVertexArrayElementsInstanced(int offset, int count, const void *buffer, int instances) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - glDrawElementsInstanced(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, (const unsigned short *)buffer + offset, instances); + // NOTE: Added pointer math separately from function to avoid UBSAN complaining + unsigned short *bufferPtr = (unsigned short *)buffer; + if (offset > 0) bufferPtr += offset; + + glDrawElementsInstanced(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, (const unsigned short *)bufferPtr, instances); #endif } @@ -3923,8 +4035,8 @@ int rlGetLocationUniform(unsigned int shaderId, const char *uniformName) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) location = glGetUniformLocation(shaderId, uniformName); - if (location == -1) TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to find shader uniform: %s", shaderId, uniformName); - else TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Shader uniform (%s) set at location: %i", shaderId, uniformName, location); + //if (location == -1) TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to find shader uniform: %s", shaderId, uniformName); + //else TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Shader uniform (%s) set at location: %i", shaderId, uniformName, location); #endif return location; } @@ -3936,8 +4048,8 @@ int rlGetLocationAttrib(unsigned int shaderId, const char *attribName) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) location = glGetAttribLocation(shaderId, attribName); - if (location == -1) TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to find shader attribute: %s", shaderId, attribName); - else TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Shader attribute (%s) set at location: %i", shaderId, attribName, location); + //if (location == -1) TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to find shader attribute: %s", shaderId, attribName); + //else TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Shader attribute (%s) set at location: %i", shaderId, attribName, location); #endif return location; } @@ -4091,7 +4203,7 @@ unsigned int rlLoadShaderBuffer(unsigned int size, const void *data, int usageHi glGenBuffers(1, &ssbo); glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo); glBufferData(GL_SHADER_STORAGE_BUFFER, size, data, usageHint? usageHint : RL_STREAM_COPY); - glClearBufferData(GL_SHADER_STORAGE_BUFFER, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, 0); + if (data == NULL) glClearBufferData(GL_SHADER_STORAGE_BUFFER, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, NULL); // Clear buffer data to 0 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); #endif @@ -4162,7 +4274,7 @@ void rlBindImageTexture(unsigned int id, unsigned int index, int format, bool re unsigned int glInternalFormat = 0, glFormat = 0, glType = 0; rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType); - glBindImageTexture(index, id, 0, 0, 0, readonly ? GL_READ_ONLY : GL_READ_WRITE, glInternalFormat); + glBindImageTexture(index, id, 0, 0, 0, readonly? GL_READ_ONLY : GL_READ_WRITE, glInternalFormat); #endif } @@ -4428,6 +4540,9 @@ const char *rlGetPixelFormatName(unsigned int format) case RL_PIXELFORMAT_UNCOMPRESSED_R32: return "R32"; break; // 32 bpp (1 channel - float) case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32: return "R32G32B32"; break; // 32*3 bpp (3 channels - float) case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: return "R32G32B32A32"; break; // 32*4 bpp (4 channels - float) + case RL_PIXELFORMAT_UNCOMPRESSED_R16: return "R16"; break; // 16 bpp (1 channel - half float) + case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: return "R16G16B16"; break; // 16*3 bpp (3 channels - half float) + case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: return "R16G16B16A16"; break; // 16*4 bpp (4 channels - half float) case RL_PIXELFORMAT_COMPRESSED_DXT1_RGB: return "DXT1_RGB"; break; // 4 bpp (no alpha) case RL_PIXELFORMAT_COMPRESSED_DXT1_RGBA: return "DXT1_RGBA"; break; // 4 bpp (1 bit alpha) case RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA: return "DXT3_RGBA"; break; // 8 bpp @@ -4476,6 +4591,7 @@ static void rlLoadShaderDefault(void) #endif #if defined(GRAPHICS_API_OPENGL_ES2) "#version 100 \n" + "precision mediump float; \n" // Precision required for OpenGL ES2 (WebGL) (on some browsers) "attribute vec3 vertexPosition; \n" "attribute vec2 vertexTexCoord; \n" "attribute vec4 vertexColor; \n" @@ -4574,7 +4690,7 @@ static void rlUnloadShaderDefault(void) #if defined(RLGL_SHOW_GL_DETAILS_INFO) // Get compressed format official GL identifier name -static char *rlGetCompressedFormatName(int format) +static const char *rlGetCompressedFormatName(int format) { switch (format) { @@ -4669,6 +4785,9 @@ static int rlGetPixelDataSize(int width, int height, int format) case RL_PIXELFORMAT_UNCOMPRESSED_R32: bpp = 32; break; case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32: bpp = 32*3; break; case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: bpp = 32*4; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R16: bpp = 16; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: bpp = 16*3; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: bpp = 16*4; break; case RL_PIXELFORMAT_COMPRESSED_DXT1_RGB: case RL_PIXELFORMAT_COMPRESSED_DXT1_RGBA: case RL_PIXELFORMAT_COMPRESSED_ETC1_RGB: diff --git a/include/shapes.h b/include/shapes.h index 3fde097..50fb156 100644 --- a/include/shapes.h +++ b/include/shapes.h @@ -5,8 +5,6 @@ int lshapesSetShapesTexture( lua_State *L ); int lshapesDrawPixel( lua_State *L ); int lshapesDrawLine( lua_State *L ); int lshapesDrawLineBezier( lua_State *L ); -int lshapesDrawLineBezierQuad( lua_State *L ); -int lshapesDrawLineBezierCubic( lua_State *L ); int lshapesDrawLineStrip( lua_State *L ); int lshapesDrawCircle( lua_State *L ); int lshapesDrawCircleSector( lua_State *L ); diff --git a/include/text.h b/include/text.h index a0b5c05..a38f979 100644 --- a/include/text.h +++ b/include/text.h @@ -17,6 +17,7 @@ int ltextDrawTextCodepoints( lua_State *L ); int ltextDrawTextBoxed( lua_State *L ); int ltextDrawTextBoxedTinted( lua_State *L ); /* Text font info functions. */ +int ltextSetTextLineSpacing( lua_State *L ); int ltextMeasureText( lua_State *L ); int ltextGetGlyphIndex( lua_State *L ); int ltextGetGlyphInfo( lua_State *L ); diff --git a/include/textures.h b/include/textures.h index 82cb1b9..efac9f2 100644 --- a/include/textures.h +++ b/include/textures.h @@ -3,6 +3,7 @@ /* Image loading functions. */ int ltexturesLoadImage( lua_State *L ); int ltexturesLoadImageRaw( lua_State *L ); +int ltexturesLoadImageSvg( lua_State *L ); int ltexturesLoadImageAnim( lua_State *L ); int ltexturesLoadImageFromMemory( lua_State *L ); int ltexturesLoadImageFromTexture( lua_State *L ); @@ -10,12 +11,13 @@ int ltexturesLoadImageFromScreen( lua_State *L ); int ltextureIsImageReady( lua_State *L ); int ltextureUnloadImage( lua_State *L ); int ltexturesExportImage( lua_State *L ); +int ltexturesExportImageToMemory( lua_State *L ); int ltexturesExportImageAsCode( lua_State *L ); /* Image generation functions. */ int ltexturesGenImageColor( lua_State *L ); -int ltexturesGenImageGradientV( lua_State *L ); -int ltexturesGenImageGradientH( lua_State *L ); +int ltexturesGenImageGradientLinear( lua_State *L ); int ltexturesGenImageGradientRadial( lua_State *L ); +int ltexturesGenImageGradientSquare( lua_State *L ); int ltexturesGenImageChecked( lua_State *L ); int ltexturesGenImageWhiteNoise( lua_State *L ); int ltexturesGenImagePerlinNoise( lua_State *L ); @@ -40,6 +42,7 @@ int ltexturesImageMipmaps( lua_State *L ); int ltexturesImageDither( lua_State *L ); int ltexturesImageFlipVertical( lua_State *L ); int ltexturesImageFlipHorizontal( lua_State *L ); +int ltexturesImageRotate( lua_State *L ); int ltexturesImageRotateCW( lua_State *L ); int ltexturesImageRotateCCW( lua_State *L ); int ltexturesImageColorTint( lua_State *L ); -- cgit v1.2.3