From 51c3bef4972047dc9927643fd1f1826970203f7d Mon Sep 17 00:00:00 2001 From: raysan5 Date: Fri, 1 May 2020 17:31:44 +0200 Subject: [PATCH 1/8] Review exposed #defines and allow user re-defining There are multiple #define values around raylib, usually not exposed for redefinition, just reviewed all of them to allow users redefining them on compile time if required. Also, multiple #define have been renamed and commented. --- src/camera.h | 6 +- src/core.c | 150 ++++++++++++++++++++++++++----------------------- src/gestures.h | 1 + src/models.c | 32 ++++++----- src/raudio.c | 33 ++++++----- src/raylib.h | 2 - src/rlgl.h | 80 ++++++++++++++------------ src/shapes.c | 67 ++++++++-------------- src/text.c | 101 +++++++++++++++++++-------------- src/textures.c | 18 +++--- src/utils.c | 14 +++-- 11 files changed, 267 insertions(+), 237 deletions(-) diff --git a/src/camera.h b/src/camera.h index f1ef42e91..31db38f0c 100644 --- a/src/camera.h +++ b/src/camera.h @@ -135,6 +135,9 @@ void SetCameraMoveControls(int frontKey, int backKey, #include // Required for: sinf(), cosf(), sqrtf() +//---------------------------------------------------------------------------------- +// Defines and Macros +//---------------------------------------------------------------------------------- #ifndef PI #define PI 3.14159265358979323846 #endif @@ -145,9 +148,6 @@ void SetCameraMoveControls(int frontKey, int backKey, #define RAD2DEG (180.0f/PI) #endif -//---------------------------------------------------------------------------------- -// Defines and Macros -//---------------------------------------------------------------------------------- // Camera mouse movement sensitivity #define CAMERA_MOUSE_MOVE_SENSITIVITY 0.003f #define CAMERA_MOUSE_SCROLL_SENSITIVITY 1.5f diff --git a/src/core.c b/src/core.c index 3e02cab12..b01f15138 100644 --- a/src/core.c +++ b/src/core.c @@ -113,36 +113,36 @@ * **********************************************************************************************/ -#include "raylib.h" // Declares module functions +#include "raylib.h" // Declares module functions // Check if config flags have been externally provided on compilation line #if !defined(EXTERNAL_CONFIG_FLAGS) - #include "config.h" // Defines module configuration flags + #include "config.h" // Defines module configuration flags #else #define RAYLIB_VERSION "3.0" #endif -#include "utils.h" // Required for: TRACELOG macros +#include "utils.h" // Required for: TRACELOG macros #if (defined(__linux__) || defined(PLATFORM_WEB)) && _POSIX_C_SOURCE < 199309L #undef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 199309L // Required for CLOCK_MONOTONIC if compiled with c99 without gnu ext. #endif -#define RAYMATH_IMPLEMENTATION // Define external out-of-line implementation of raymath here -#include "raymath.h" // Required for: Vector3 and Matrix functions +#define RAYMATH_IMPLEMENTATION // Define external out-of-line implementation of raymath here +#include "raymath.h" // Required for: Vector3 and Matrix functions #define RLGL_IMPLEMENTATION -#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2 +#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2 #if defined(SUPPORT_GESTURES_SYSTEM) #define GESTURES_IMPLEMENTATION - #include "gestures.h" // Gestures detection functionality + #include "gestures.h" // Gestures detection functionality #endif #if defined(SUPPORT_CAMERA_SYSTEM) #define CAMERA_IMPLEMENTATION - #include "camera.h" // Camera system functionality + #include "camera.h" // Camera system functionality #endif #if defined(SUPPORT_GIF_RECORDING) @@ -150,20 +150,16 @@ #define RGIF_FREE RL_FREE #define RGIF_IMPLEMENTATION - #include "external/rgif.h" // Support GIF recording + #include "external/rgif.h" // Support GIF recording #endif -#if defined(__APPLE__) - #define SUPPORT_HIGH_DPI // Force HighDPI support on macOS -#endif +#include // Required for: srand(), rand(), atexit() +#include // Required for: sprintf() [Used in OpenURL()] +#include // Required for: strrchr(), strcmp(), strlen() +#include // Required for: time() [Used in InitTimer()] +#include // Required for: tan() [Used in BeginMode3D()] -#include // Required for: srand(), rand(), atexit() -#include // Required for: sprintf() [Used in OpenURL()] -#include // Required for: strrchr(), strcmp(), strlen() -#include // Required for: time() [Used in InitTimer()] -#include // Required for: tan() [Used in BeginMode3D()] - -#include // Required for: stat() [Used in GetFileModTime()] +#include // Required for: stat() [Used in GetFileModTime()] #if (defined(PLATFORM_DESKTOP) || defined(PLATFORM_UWP)) && defined(_WIN32) && (defined(_MSC_VER) || defined(__TINYC__)) #define DIRENT_MALLOC RL_MALLOC @@ -203,65 +199,59 @@ #endif #elif defined(__linux__) - #include // Required for: timespec, nanosleep(), select() - POSIX + #include // Required for: timespec, nanosleep(), select() - POSIX - //#define GLFW_EXPOSE_NATIVE_X11 // WARNING: Exposing Xlib.h > X.h results in dup symbols for Font type + //#define GLFW_EXPOSE_NATIVE_X11 // WARNING: Exposing Xlib.h > X.h results in dup symbols for Font type //#define GLFW_EXPOSE_NATIVE_WAYLAND //#define GLFW_EXPOSE_NATIVE_MIR - #include // Required for: glfwGetX11Window() + #include // Required for: glfwGetX11Window() #elif defined(__APPLE__) - #include // Required for: usleep() + #include // Required for: usleep() - //#define GLFW_EXPOSE_NATIVE_COCOA // WARNING: Fails due to type redefinition - #include // Required for: glfwGetCocoaWindow() + //#define GLFW_EXPOSE_NATIVE_COCOA // WARNING: Fails due to type redefinition + #include // Required for: glfwGetCocoaWindow() #endif #endif -#if defined(__linux__) - #define MAX_FILEPATH_LENGTH 4096 // Use Linux PATH_MAX value -#else - #define MAX_FILEPATH_LENGTH 512 // Use common value -#endif - #if defined(PLATFORM_ANDROID) //#include // Android sensors functions (accelerometer, gyroscope, light...) #include // Defines AWINDOW_FLAG_FULLSCREEN and others #include // Defines basic app state struct and manages activity - #include // Khronos EGL library - Native platform display device control functions - #include // Khronos OpenGL ES 2.0 library + #include // EGL library - Native platform display device control functions + #include // OpenGL ES 2.0 library #endif #if defined(PLATFORM_RPI) - #include // POSIX file control definitions - open(), creat(), fcntl() - #include // POSIX standard function definitions - read(), close(), STDIN_FILENO - #include // POSIX terminal control definitions - tcgetattr(), tcsetattr() - #include // POSIX threads management (inputs reading) - #include // POSIX directory browsing - - #include // UNIX System call for device-specific input/output operations - ioctl() - #include // Linux: KDSKBMODE, K_MEDIUMRAM constants definition - #include // Linux: Keycodes constants definition (KEY_A, ...) - #include // Linux: Joystick support library - - #include "bcm_host.h" // Raspberry Pi VideoCore IV access functions - - #include "EGL/egl.h" // Khronos EGL library - Native platform display device control functions - #include "EGL/eglext.h" // Khronos EGL library - Extensions - #include "GLES2/gl2.h" // Khronos OpenGL ES 2.0 library + #include // POSIX file control definitions - open(), creat(), fcntl() + #include // POSIX standard function definitions - read(), close(), STDIN_FILENO + #include // POSIX terminal control definitions - tcgetattr(), tcsetattr() + #include // POSIX threads management (inputs reading) + #include // POSIX directory browsing + + #include // UNIX System call for device-specific input/output operations - ioctl() + #include // Linux: KDSKBMODE, K_MEDIUMRAM constants definition + #include // Linux: Keycodes constants definition (KEY_A, ...) + #include // Linux: Joystick support library + + #include "bcm_host.h" // Raspberry Pi VideoCore IV access functions + + #include "EGL/egl.h" // EGL library - Native platform display device control functions + #include "EGL/eglext.h" // EGL library - Extensions + #include "GLES2/gl2.h" // OpenGL ES 2.0 library #endif #if defined(PLATFORM_UWP) - #include "EGL/egl.h" // Khronos EGL library - Native platform display device control functions - #include "EGL/eglext.h" // Khronos EGL library - Extensions - #include "GLES2/gl2.h" // Khronos OpenGL ES 2.0 library - #include "uwp_events.h" // UWP bootstrapping functions + #include "EGL/egl.h" // EGL library - Native platform display device control functions + #include "EGL/eglext.h" // EGL library - Extensions + #include "GLES2/gl2.h" // OpenGL ES 2.0 library + #include "uwp_events.h" // UWP bootstrapping functions #endif #if defined(PLATFORM_WEB) - #define GLFW_INCLUDE_ES2 // GLFW3: Enable OpenGL ES 2.0 (translated to WebGL) - #include // GLFW3 library: Windows, OpenGL context and Input management - #include // Required for: timespec, nanosleep(), select() - POSIX + #define GLFW_INCLUDE_ES2 // GLFW3: Enable OpenGL ES 2.0 (translated to WebGL) + #include // GLFW3 library: Windows, OpenGL context and Input management + #include // Required for: timespec, nanosleep(), select() - POSIX #include // Emscripten library - LLVM to JavaScript compiler #include // Emscripten HTML5 library @@ -288,18 +278,36 @@ //#define DEFAULT_KEYBOARD_DEV "/dev/input/eventN" //#define DEFAULT_MOUSE_DEV "/dev/input/eventN" //#define DEFAULT_GAMEPAD_DEV "/dev/input/eventN" - - #define MOUSE_SENSITIVITY 0.8f #endif -#define MAX_GAMEPADS 4 // Max number of gamepads supported -#define MAX_GAMEPAD_AXIS 8 // Max number of axis supported (per gamepad) -#define MAX_GAMEPAD_BUTTONS 32 // Max bumber of buttons supported (per gamepad) +#ifndef MAX_FILEPATH_LENGTH + #if defined(__linux__) + #define MAX_FILEPATH_LENGTH 4096 // Maximum length for filepaths (Linux PATH_MAX default value) + #else + #define MAX_FILEPATH_LENGTH 512 // Maximum length supported for filepaths + #endif +#endif -#define MAX_CHARS_QUEUE 16 // Max number of characters in the input queue +#ifndef MAX_GAMEPADS + #define MAX_GAMEPADS 4 // Max number of gamepads supported +#endif +#ifndef MAX_GAMEPAD_AXIS + #define MAX_GAMEPAD_AXIS 8 // Max number of axis supported (per gamepad) +#endif +#ifndef MAX_GAMEPAD_BUTTONS + #define MAX_GAMEPAD_BUTTONS 32 // Max bumber of buttons supported (per gamepad) +#endif +#ifndef MAX_TOUCH_POINTS + #define MAX_TOUCH_POINTS 10 // Maximum number of touch points supported +#endif +#ifndef MAX_KEY_PRESSED_QUEUE + #define MAX_KEY_PRESSED_QUEUE 16 // Max number of characters in the key input queue +#endif #if defined(SUPPORT_DATA_STORAGE) - #define STORAGE_DATA_FILE "storage.data" + #ifndef STORAGE_DATA_FILE + #define STORAGE_DATA_FILE "storage.data" // Automatic storage filename + #endif #endif //---------------------------------------------------------------------------------- @@ -390,7 +398,7 @@ typedef struct CoreData { char currentKeyState[512]; // Registers current frame key state char previousKeyState[512]; // Registers previous frame key state - int keyPressedQueue[MAX_CHARS_QUEUE]; // Input characters queue + int keyPressedQueue[MAX_KEY_PRESSED_QUEUE]; // Input characters queue int keyPressedQueueCount; // Input characters queue count #if defined(PLATFORM_RPI) int defaultMode; // Default keyboard mode @@ -1400,7 +1408,7 @@ void BeginMode3D(Camera3D camera) double top = 0.01*tan(camera.fovy*0.5*DEG2RAD); double right = top*aspect; - rlFrustum(-right, right, -top, top, RL_NEAR_CULL_DISTANCE, RL_FAR_CULL_DISTANCE); + rlFrustum(-right, right, -top, top, RL_CULL_DISTANCE_NEAR, RL_CULL_DISTANCE_FAR); } else if (camera.type == CAMERA_ORTHOGRAPHIC) { @@ -1408,7 +1416,7 @@ void BeginMode3D(Camera3D camera) double top = camera.fovy/2.0; double right = top*aspect; - rlOrtho(-right, right, -top,top, RL_NEAR_CULL_DISTANCE, RL_FAR_CULL_DISTANCE); + rlOrtho(-right, right, -top,top, RL_CULL_DISTANCE_NEAR, RL_CULL_DISTANCE_FAR); } // NOTE: zNear and zFar values are important when computing depth buffer values @@ -1521,7 +1529,7 @@ Ray GetMouseRay(Vector2 mouse, Camera camera) if (camera.type == CAMERA_PERSPECTIVE) { // Calculate projection matrix from perspective - matProj = MatrixPerspective(camera.fovy*DEG2RAD, ((double)GetScreenWidth()/(double)GetScreenHeight()), RL_NEAR_CULL_DISTANCE, RL_FAR_CULL_DISTANCE); + matProj = MatrixPerspective(camera.fovy*DEG2RAD, ((double)GetScreenWidth()/(double)GetScreenHeight()), RL_CULL_DISTANCE_NEAR, RL_CULL_DISTANCE_FAR); } else if (camera.type == CAMERA_ORTHOGRAPHIC) { @@ -1605,7 +1613,7 @@ Vector2 GetWorldToScreenEx(Vector3 position, Camera camera, int width, int heigh if (camera.type == CAMERA_PERSPECTIVE) { // Calculate projection matrix from perspective - matProj = MatrixPerspective(camera.fovy * DEG2RAD, ((double)width/(double)height), RL_NEAR_CULL_DISTANCE, RL_FAR_CULL_DISTANCE); + matProj = MatrixPerspective(camera.fovy * DEG2RAD, ((double)width/(double)height), RL_CULL_DISTANCE_NEAR, RL_CULL_DISTANCE_FAR); } else if (camera.type == CAMERA_ORTHOGRAPHIC) { @@ -1614,7 +1622,7 @@ Vector2 GetWorldToScreenEx(Vector3 position, Camera camera, int width, int heigh double right = top*aspect; // Calculate projection matrix from orthographic - matProj = MatrixOrtho(-right, right, -top, top, RL_NEAR_CULL_DISTANCE, RL_FAR_CULL_DISTANCE); + matProj = MatrixOrtho(-right, right, -top, top, RL_CULL_DISTANCE_NEAR, RL_CULL_DISTANCE_FAR); } // Calculate view matrix from camera look at (and transpose it) @@ -3989,7 +3997,7 @@ static void CharCallback(GLFWwindow *window, unsigned int key) // Ref: https://www.glfw.org/docs/latest/input_guide.html#input_char // Check if there is space available in the queue - if (CORE.Input.Keyboard.keyPressedQueueCount < MAX_CHARS_QUEUE) + if (CORE.Input.Keyboard.keyPressedQueueCount < MAX_KEY_PRESSED_QUEUE) { // Add character to the queue CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = key; @@ -5261,7 +5269,7 @@ void UWPKeyDownEvent(int key, bool down, bool controlKey) void UWPKeyCharEvent(int key) { - if (CORE.Input.Keyboard.keyPressedQueueCount < MAX_CHARS_QUEUE) + if (CORE.Input.Keyboard.keyPressedQueueCount < MAX_KEY_PRESSED_QUEUE) { // Add character to the queue CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = key; diff --git a/src/gestures.h b/src/gestures.h index 9b3600db4..392ae6607 100644 --- a/src/gestures.h +++ b/src/gestures.h @@ -174,6 +174,7 @@ float GetGesturePinchAngle(void); // Get gesture pinch ang // Types and Structures Definition //---------------------------------------------------------------------------------- +// Gestures module state context typedef struct { int current; // Current detected gesture unsigned int enabledFlags; // Enabled gestures flags diff --git a/src/models.c b/src/models.c index 8b013ea5b..7e174caee 100644 --- a/src/models.c +++ b/src/models.c @@ -92,7 +92,9 @@ //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- -#define MAX_MESH_VBO 7 // Maximum number of vbo per mesh +#ifndef DEFAULT_MESH_VERTEX_BUFFERS + #define DEFAULT_MESH_VERTEX_BUFFERS 7 // Number of vertex buffers (VBO) per mesh +#endif //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -1224,7 +1226,7 @@ bool IsModelAnimationValid(Model model, ModelAnimation anim) Mesh GenMeshPoly(int sides, float radius) { Mesh mesh = { 0 }; - mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO, sizeof(unsigned int)); + mesh.vboId = (unsigned int *)RL_CALLOC(DEFAULT_MESH_VERTEX_BUFFERS, sizeof(unsigned int)); int vertexCount = sides*3; // Vertices definition @@ -1287,7 +1289,7 @@ Mesh GenMeshPoly(int sides, float radius) Mesh GenMeshPlane(float width, float length, int resX, int resZ) { Mesh mesh = { 0 }; - mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO, sizeof(unsigned int)); + mesh.vboId = (unsigned int *)RL_CALLOC(DEFAULT_MESH_VERTEX_BUFFERS, sizeof(unsigned int)); #define CUSTOM_MESH_GEN_PLANE #if defined(CUSTOM_MESH_GEN_PLANE) @@ -1390,7 +1392,7 @@ Mesh GenMeshPlane(float width, float length, int resX, int resZ) mesh.vertices = (float *)RL_MALLOC(plane->ntriangles*3*3*sizeof(float)); mesh.texcoords = (float *)RL_MALLOC(plane->ntriangles*3*2*sizeof(float)); mesh.normals = (float *)RL_MALLOC(plane->ntriangles*3*3*sizeof(float)); - mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO, sizeof(unsigned int)); + mesh.vboId = (unsigned int *)RL_CALLOC(DEFAULT_MESH_VERTEX_BUFFERS, sizeof(unsigned int)); mesh.vertexCount = plane->ntriangles*3; mesh.triangleCount = plane->ntriangles; @@ -1422,7 +1424,7 @@ Mesh GenMeshPlane(float width, float length, int resX, int resZ) Mesh GenMeshCube(float width, float height, float length) { Mesh mesh = { 0 }; - mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO, sizeof(unsigned int)); + mesh.vboId = (unsigned int *)RL_CALLOC(DEFAULT_MESH_VERTEX_BUFFERS, sizeof(unsigned int)); #define CUSTOM_MESH_GEN_CUBE #if defined(CUSTOM_MESH_GEN_CUBE) @@ -1588,7 +1590,7 @@ par_shapes_mesh* par_shapes_create_icosahedron(); // 20 sides polyhedron RLAPI Mesh GenMeshSphere(float radius, int rings, int slices) { Mesh mesh = { 0 }; - mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO, sizeof(unsigned int)); + mesh.vboId = (unsigned int *)RL_CALLOC(DEFAULT_MESH_VERTEX_BUFFERS, sizeof(unsigned int)); par_shapes_mesh *sphere = par_shapes_create_parametric_sphere(slices, rings); par_shapes_scale(sphere, radius, radius, radius); @@ -1627,7 +1629,7 @@ RLAPI Mesh GenMeshSphere(float radius, int rings, int slices) RLAPI Mesh GenMeshHemiSphere(float radius, int rings, int slices) { Mesh mesh = { 0 }; - mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO, sizeof(unsigned int)); + mesh.vboId = (unsigned int *)RL_CALLOC(DEFAULT_MESH_VERTEX_BUFFERS, sizeof(unsigned int)); par_shapes_mesh *sphere = par_shapes_create_hemisphere(slices, rings); par_shapes_scale(sphere, radius, radius, radius); @@ -1666,7 +1668,7 @@ RLAPI Mesh GenMeshHemiSphere(float radius, int rings, int slices) Mesh GenMeshCylinder(float radius, float height, int slices) { Mesh mesh = { 0 }; - mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO, sizeof(unsigned int)); + mesh.vboId = (unsigned int *)RL_CALLOC(DEFAULT_MESH_VERTEX_BUFFERS, sizeof(unsigned int)); // Instance a cylinder that sits on the Z=0 plane using the given tessellation // levels across the UV domain. Think of "slices" like a number of pizza @@ -1726,7 +1728,7 @@ Mesh GenMeshCylinder(float radius, float height, int slices) Mesh GenMeshTorus(float radius, float size, int radSeg, int sides) { Mesh mesh = { 0 }; - mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO, sizeof(unsigned int)); + mesh.vboId = (unsigned int *)RL_CALLOC(DEFAULT_MESH_VERTEX_BUFFERS, sizeof(unsigned int)); if (radius > 1.0f) radius = 1.0f; else if (radius < 0.1f) radius = 0.1f; @@ -1769,7 +1771,7 @@ Mesh GenMeshTorus(float radius, float size, int radSeg, int sides) Mesh GenMeshKnot(float radius, float size, int radSeg, int sides) { Mesh mesh = { 0 }; - mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO, sizeof(unsigned int)); + mesh.vboId = (unsigned int *)RL_CALLOC(DEFAULT_MESH_VERTEX_BUFFERS, sizeof(unsigned int)); if (radius > 3.0f) radius = 3.0f; else if (radius < 0.5f) radius = 0.5f; @@ -1813,7 +1815,7 @@ Mesh GenMeshHeightmap(Image heightmap, Vector3 size) #define GRAY_VALUE(c) ((c.r+c.g+c.b)/3) Mesh mesh = { 0 }; - mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO, sizeof(unsigned int)); + mesh.vboId = (unsigned int *)RL_CALLOC(DEFAULT_MESH_VERTEX_BUFFERS, sizeof(unsigned int)); int mapX = heightmap.width; int mapZ = heightmap.height; @@ -1947,7 +1949,7 @@ Mesh GenMeshHeightmap(Image heightmap, Vector3 size) Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize) { Mesh mesh = { 0 }; - mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO, sizeof(unsigned int)); + mesh.vboId = (unsigned int *)RL_CALLOC(DEFAULT_MESH_VERTEX_BUFFERS, sizeof(unsigned int)); Color *cubicmapPixels = GetImageData(cubicmap); @@ -2889,7 +2891,7 @@ static Model LoadOBJ(const char *fileName) mesh.vertices = (float *)RL_CALLOC(mesh.vertexCount*3, sizeof(float)); mesh.texcoords = (float *)RL_CALLOC(mesh.vertexCount*2, sizeof(float)); mesh.normals = (float *)RL_CALLOC(mesh.vertexCount*3, sizeof(float)); - mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO, sizeof(unsigned int)); + mesh.vboId = (unsigned int *)RL_CALLOC(DEFAULT_MESH_VERTEX_BUFFERS, sizeof(unsigned int)); int vCount = 0; int vtCount = 0; @@ -3161,7 +3163,7 @@ static Model LoadIQM(const char *fileName) model.meshes[i].animVertices = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float)); model.meshes[i].animNormals = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float)); - model.meshes[i].vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO, sizeof(unsigned int)); + model.meshes[i].vboId = (unsigned int *)RL_CALLOC(DEFAULT_MESH_VERTEX_BUFFERS, sizeof(unsigned int)); } // Triangles data processing @@ -3551,7 +3553,7 @@ static Model LoadGLTF(const char *fileName) model.materials = RL_MALLOC(model.materialCount*sizeof(Material)); model.meshMaterial = RL_MALLOC(model.meshCount*sizeof(int)); - for (int i = 0; i < model.meshCount; i++) model.meshes[i].vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO, sizeof(unsigned int)); + for (int i = 0; i < model.meshCount; i++) model.meshes[i].vboId = (unsigned int *)RL_CALLOC(DEFAULT_MESH_VERTEX_BUFFERS, sizeof(unsigned int)); for (int i = 0; i < model.materialCount - 1; i++) { diff --git a/src/raudio.c b/src/raudio.c index ce683c131..5224d516f 100644 --- a/src/raudio.c +++ b/src/raudio.c @@ -223,11 +223,18 @@ typedef struct tagBITMAPINFOHEADER { //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- -#define AUDIO_DEVICE_FORMAT ma_format_f32 -#define AUDIO_DEVICE_CHANNELS 2 -#define AUDIO_DEVICE_SAMPLE_RATE 44100 - -#define MAX_AUDIO_BUFFER_POOL_CHANNELS 16 +#ifndef AUDIO_DEVICE_FORMAT + #define AUDIO_DEVICE_FORMAT ma_format_f32 // Device output format (float-32bit) +#endif +#ifndef AUDIO_DEVICE_CHANNELS + #define AUDIO_DEVICE_CHANNELS 2 // Device output channels: stereo +#endif +#ifndef AUDIO_DEVICE_SAMPLE_RATE + #define AUDIO_DEVICE_SAMPLE_RATE 44100 // Device output sample rate +#endif +#ifndef MAX_AUDIO_BUFFER_POOL_CHANNELS + #define MAX_AUDIO_BUFFER_POOL_CHANNELS 16 // Audio pool channels +#endif //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -391,14 +398,14 @@ void InitAudioDevice(void) // NOTE: Using the default device. Format is floating point because it simplifies mixing. ma_device_config config = ma_device_config_init(ma_device_type_playback); config.playback.pDeviceID = NULL; // NULL for the default playback AUDIO.System.device. - config.playback.format = AUDIO_DEVICE_FORMAT; - config.playback.channels = AUDIO_DEVICE_CHANNELS; - config.capture.pDeviceID = NULL; // NULL for the default capture AUDIO.System.device. - config.capture.format = ma_format_s16; - config.capture.channels = 1; - config.sampleRate = AUDIO_DEVICE_SAMPLE_RATE; - config.dataCallback = OnSendAudioDataToDevice; - config.pUserData = NULL; + config.playback.format = AUDIO_DEVICE_FORMAT; + config.playback.channels = AUDIO_DEVICE_CHANNELS; + config.capture.pDeviceID = NULL; // NULL for the default capture AUDIO.System.device. + config.capture.format = ma_format_s16; + config.capture.channels = 1; + config.sampleRate = AUDIO_DEVICE_SAMPLE_RATE; + config.dataCallback = OnSendAudioDataToDevice; + config.pUserData = NULL; result = ma_device_init(&AUDIO.System.context, &config, &AUDIO.System.device); if (result != MA_SUCCESS) diff --git a/src/raylib.h b/src/raylib.h index 5c096f80f..4df397c8a 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -99,8 +99,6 @@ #define DEG2RAD (PI/180.0f) #define RAD2DEG (180.0f/PI) -#define MAX_TOUCH_POINTS 10 // Maximum number of touch points supported - // Allow custom memory allocators #ifndef RL_MALLOC #define RL_MALLOC(sz) malloc(sz) diff --git a/src/rlgl.h b/src/rlgl.h index 0960afeab..548709cf4 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -606,22 +606,22 @@ RLAPI int GetPixelDataSize(int width, int height, int format);// Get pixel data #if defined(RLGL_IMPLEMENTATION) #if defined(RLGL_STANDALONE) - #include // Required for: fopen(), fseek(), fread(), fclose() [LoadFileText] + #include // Required for: fopen(), fseek(), fread(), fclose() [LoadFileText] #else // Check if config flags have been externally provided on compilation line #if !defined(EXTERNAL_CONFIG_FLAGS) - #include "config.h" // Defines module configuration flags + #include "config.h" // Defines module configuration flags #endif - #include "raymath.h" // Required for: Vector3 and Matrix functions + #include "raymath.h" // Required for: Vector3 and Matrix functions #endif -#include // Required for: malloc(), free() -#include // Required for: strcmp(), strlen() [Used in rlglInit(), on extensions loading] -#include // Required for: atan2f(), fabs() +#include // Required for: malloc(), free() +#include // Required for: strcmp(), strlen() [Used in rlglInit(), on extensions loading] +#include // Required for: atan2f() #if defined(GRAPHICS_API_OPENGL_11) #if defined(__APPLE__) - #include // OpenGL 1.1 library for OSX + #include // OpenGL 1.1 library for OSX #include #else // APIENTRY for OpenGL function pointer declarations is required @@ -713,7 +713,6 @@ RLAPI int GetPixelDataSize(int width, int height, int format);// Get pixel data #ifndef GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT #define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF #endif - #ifndef GL_TEXTURE_MAX_ANISOTROPY_EXT #define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE #endif @@ -723,25 +722,36 @@ RLAPI int GetPixelDataSize(int width, int height, int format);// Get pixel data #define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 #define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 #endif - #if defined(GRAPHICS_API_OPENGL_21) #define GL_LUMINANCE 0x1909 #define GL_LUMINANCE_ALPHA 0x190A #endif #if defined(GRAPHICS_API_OPENGL_ES2) - #define glClearDepth glClearDepthf + #define glClearDepth glClearDepthf #define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER #define GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER #endif -// Default vertex attribute names on shader to set location points -#define DEFAULT_ATTRIB_POSITION_NAME "vertexPosition" // shader-location = 0 -#define DEFAULT_ATTRIB_TEXCOORD_NAME "vertexTexCoord" // shader-location = 1 -#define DEFAULT_ATTRIB_NORMAL_NAME "vertexNormal" // shader-location = 2 -#define DEFAULT_ATTRIB_COLOR_NAME "vertexColor" // shader-location = 3 -#define DEFAULT_ATTRIB_TANGENT_NAME "vertexTangent" // shader-location = 4 -#define DEFAULT_ATTRIB_TEXCOORD2_NAME "vertexTexCoord2" // shader-location = 5 +// Default shader vertex attribute names to set location points +#ifndef DEFAULT_SHADER_ATTRIB_NAME_POSITION + #define DEFAULT_SHADER_ATTRIB_NAME_POSITION "vertexPosition" // Binded by default to shader location: 0 +#endif +#ifndef DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD + #define DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD "vertexTexCoord" // Binded by default to shader location: 1 +#endif +#ifndef DEFAULT_SHADER_ATTRIB_NAME_NORMAL + #define DEFAULT_SHADER_ATTRIB_NAME_NORMAL "vertexNormal" // Binded by default to shader location: 2 +#endif +#ifndef DEFAULT_SHADER_ATTRIB_NAME_COLOR + #define DEFAULT_SHADER_ATTRIB_NAME_COLOR "vertexColor" // Binded by default to shader location: 3 +#endif +#ifndef DEFAULT_SHADER_ATTRIB_NAME_TANGENT + #define DEFAULT_SHADER_ATTRIB_NAME_TANGENT "vertexTangent" // Binded by default to shader location: 4 +#endif +#ifndef DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 + #define DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Binded by default to shader location: 5 +#endif //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -1386,7 +1396,7 @@ RLAPI void rlScissor(int x, int y, int width, int height) { glScissor(x, y, widt // Enable wire mode void rlEnableWireMode(void) { -#if defined (GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) +#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) // NOTE: glPolygonMode() not available on OpenGL ES glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); #endif @@ -1395,7 +1405,7 @@ void rlEnableWireMode(void) // Disable wire mode void rlDisableWireMode(void) { -#if defined (GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) +#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) // NOTE: glPolygonMode() not available on OpenGL ES glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); #endif @@ -3270,7 +3280,7 @@ Texture2D GenTextureCubemap(Shader shader, Texture2D map, int size) glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Create projection and different views for each face - Matrix fboProjection = MatrixPerspective(90.0*DEG2RAD, 1.0, RL_NEAR_CULL_DISTANCE, RL_FAR_CULL_DISTANCE); + Matrix fboProjection = MatrixPerspective(90.0*DEG2RAD, 1.0, RL_CULL_DISTANCE_NEAR, RL_CULL_DISTANCE_FAR); Matrix fboViews[6] = { MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ -1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), @@ -3348,7 +3358,7 @@ Texture2D GenTextureIrradiance(Shader shader, Texture2D cubemap, int size) glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Create projection (transposed) and different views for each face - Matrix fboProjection = MatrixPerspective(90.0*DEG2RAD, 1.0, RL_NEAR_CULL_DISTANCE, RL_FAR_CULL_DISTANCE); + Matrix fboProjection = MatrixPerspective(90.0*DEG2RAD, 1.0, RL_CULL_DISTANCE_NEAR, RL_CULL_DISTANCE_FAR); Matrix fboViews[6] = { MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ -1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), @@ -3429,7 +3439,7 @@ Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size) glGenerateMipmap(GL_TEXTURE_CUBE_MAP); // Create projection (transposed) and different views for each face - Matrix fboProjection = MatrixPerspective(90.0*DEG2RAD, 1.0, RL_NEAR_CULL_DISTANCE, RL_FAR_CULL_DISTANCE); + Matrix fboProjection = MatrixPerspective(90.0*DEG2RAD, 1.0, RL_CULL_DISTANCE_NEAR, RL_CULL_DISTANCE_FAR); Matrix fboViews[6] = { MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ -1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), @@ -3650,7 +3660,7 @@ void SetVrConfiguration(VrDeviceInfo hmd, Shader distortion) // Compute camera projection matrices float projOffset = 4.0f*lensShift; // Scaled to projection space coordinates [-1..1] - Matrix proj = MatrixPerspective(fovy, aspect, RL_NEAR_CULL_DISTANCE, RL_FAR_CULL_DISTANCE); + Matrix proj = MatrixPerspective(fovy, aspect, RL_CULL_DISTANCE_NEAR, RL_CULL_DISTANCE_FAR); RLGL.Vr.config.eyesProjection[0] = MatrixMultiply(proj, MatrixTranslate(projOffset, 0.0f, 0.0f)); RLGL.Vr.config.eyesProjection[1] = MatrixMultiply(proj, MatrixTranslate(-projOffset, 0.0f, 0.0f)); @@ -3857,12 +3867,12 @@ static unsigned int LoadShaderProgram(unsigned int vShaderId, unsigned int fShad glAttachShader(program, fShaderId); // NOTE: Default attribute shader locations must be binded before linking - glBindAttribLocation(program, 0, DEFAULT_ATTRIB_POSITION_NAME); - glBindAttribLocation(program, 1, DEFAULT_ATTRIB_TEXCOORD_NAME); - glBindAttribLocation(program, 2, DEFAULT_ATTRIB_NORMAL_NAME); - glBindAttribLocation(program, 3, DEFAULT_ATTRIB_COLOR_NAME); - glBindAttribLocation(program, 4, DEFAULT_ATTRIB_TANGENT_NAME); - glBindAttribLocation(program, 5, DEFAULT_ATTRIB_TEXCOORD2_NAME); + glBindAttribLocation(program, 0, DEFAULT_SHADER_ATTRIB_NAME_POSITION); + glBindAttribLocation(program, 1, DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD); + glBindAttribLocation(program, 2, DEFAULT_SHADER_ATTRIB_NAME_NORMAL); + glBindAttribLocation(program, 3, DEFAULT_SHADER_ATTRIB_NAME_COLOR); + glBindAttribLocation(program, 4, DEFAULT_SHADER_ATTRIB_NAME_TANGENT); + glBindAttribLocation(program, 5, DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2); // NOTE: If some attrib name is no found on the shader, it locations becomes -1 @@ -4014,12 +4024,12 @@ static void SetShaderDefaultLocations(Shader *shader) // vertex texcoord2 location = 5 // Get handles to GLSL input attibute locations - shader->locs[LOC_VERTEX_POSITION] = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_POSITION_NAME); - shader->locs[LOC_VERTEX_TEXCOORD01] = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_TEXCOORD_NAME); - shader->locs[LOC_VERTEX_TEXCOORD02] = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_TEXCOORD2_NAME); - shader->locs[LOC_VERTEX_NORMAL] = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_NORMAL_NAME); - shader->locs[LOC_VERTEX_TANGENT] = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_TANGENT_NAME); - shader->locs[LOC_VERTEX_COLOR] = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_COLOR_NAME); + shader->locs[LOC_VERTEX_POSITION] = glGetAttribLocation(shader->id, DEFAULT_SHADER_ATTRIB_NAME_POSITION); + shader->locs[LOC_VERTEX_TEXCOORD01] = glGetAttribLocation(shader->id, DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD); + shader->locs[LOC_VERTEX_TEXCOORD02] = glGetAttribLocation(shader->id, DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2); + shader->locs[LOC_VERTEX_NORMAL] = glGetAttribLocation(shader->id, DEFAULT_SHADER_ATTRIB_NAME_NORMAL); + shader->locs[LOC_VERTEX_TANGENT] = glGetAttribLocation(shader->id, DEFAULT_SHADER_ATTRIB_NAME_TANGENT); + shader->locs[LOC_VERTEX_COLOR] = glGetAttribLocation(shader->id, DEFAULT_SHADER_ATTRIB_NAME_COLOR); // Get handles to GLSL uniform locations (vertex shader) shader->locs[LOC_MATRIX_MVP] = glGetUniformLocation(shader->id, "mvp"); diff --git a/src/shapes.c b/src/shapes.c index 8b51af9aa..6b0a7f217 100644 --- a/src/shapes.c +++ b/src/shapes.c @@ -47,7 +47,12 @@ //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- -// Nop... + +// Error rate to calculate how many segments we need to draw a smooth circle, +// taken from https://stackoverflow.com/a/2244088 +#ifndef SMOOTH_CIRCLE_ERROR_RATE + #define SMOOTH_CIRCLE_ERROR_RATE 0.5f +#endif //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -155,17 +160,19 @@ void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color) // Draw line using cubic-bezier curves in-out void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color) { - #define LINE_DIVISIONS 24 // Bezier line divisions +#ifndef BEZIER_LINE_DIVISIONS + #define BEZIER_LINE_DIVISIONS 24 // Bezier line divisions +#endif Vector2 previous = startPos; Vector2 current; - for (int i = 1; i <= LINE_DIVISIONS; i++) + for (int i = 1; i <= BEZIER_LINE_DIVISIONS; i++) { // Cubic easing in-out // NOTE: Easing is calculated only for y position value - current.y = EaseCubicInOut((float)i, startPos.y, endPos.y - startPos.y, (float)LINE_DIVISIONS); - current.x = previous.x + (endPos.x - startPos.x)/ (float)LINE_DIVISIONS; + current.y = EaseCubicInOut((float)i, startPos.y, endPos.y - startPos.y, (float)BEZIER_LINE_DIVISIONS); + current.x = previous.x + (endPos.x - startPos.x)/ (float)BEZIER_LINE_DIVISIONS; DrawLineEx(previous, current, thick, color); @@ -214,11 +221,8 @@ void DrawCircleSector(Vector2 center, float radius, int startAngle, int endAngle if (segments < 4) { - // Calculate how many segments we need to draw a smooth circle, taken from https://stackoverflow.com/a/2244088 - #define CIRCLE_ERROR_RATE 0.5f - - // Calculate the maximum angle between segments based on the error rate. - float th = acosf(2*powf(1 - CIRCLE_ERROR_RATE/radius, 2) - 1); + // Calculate the maximum angle between segments based on the error rate (usually 0.5f) + float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/radius, 2) - 1); segments = (endAngle - startAngle)*ceilf(2*PI/th)/360; if (segments <= 0) segments = 4; @@ -306,13 +310,8 @@ void DrawCircleSectorLines(Vector2 center, float radius, int startAngle, int end if (segments < 4) { - // Calculate how many segments we need to draw a smooth circle, taken from https://stackoverflow.com/a/2244088 - #ifndef CIRCLE_ERROR_RATE - #define CIRCLE_ERROR_RATE 0.5f - #endif - - // Calculate the maximum angle between segments based on the error rate. - float th = acosf(2*powf(1 - CIRCLE_ERROR_RATE/radius, 2) - 1); + // Calculate the maximum angle between segments based on the error rate (usually 0.5f) + float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/radius, 2) - 1); segments = (endAngle - startAngle)*ceilf(2*PI/th)/360; if (segments <= 0) segments = 4; @@ -454,13 +453,8 @@ void DrawRing(Vector2 center, float innerRadius, float outerRadius, int startAng if (segments < 4) { - // Calculate how many segments we need to draw a smooth circle, taken from https://stackoverflow.com/a/2244088 - #ifndef CIRCLE_ERROR_RATE - #define CIRCLE_ERROR_RATE 0.5f - #endif - - // Calculate the maximum angle between segments based on the error rate. - float th = acosf(2*powf(1 - CIRCLE_ERROR_RATE/outerRadius, 2) - 1); + // Calculate the maximum angle between segments based on the error rate (usually 0.5f) + float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/outerRadius, 2) - 1); segments = (endAngle - startAngle)*ceilf(2*PI/th)/360; if (segments <= 0) segments = 4; @@ -550,13 +544,8 @@ void DrawRingLines(Vector2 center, float innerRadius, float outerRadius, int sta if (segments < 4) { - // Calculate how many segments we need to draw a smooth circle, taken from https://stackoverflow.com/a/2244088 - #ifndef CIRCLE_ERROR_RATE - #define CIRCLE_ERROR_RATE 0.5f - #endif - - // Calculate the maximum angle between segments based on the error rate. - float th = acosf(2*powf(1 - CIRCLE_ERROR_RATE/outerRadius, 2) - 1); + // Calculate the maximum angle between segments based on the error rate (usually 0.5f) + float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/outerRadius, 2) - 1); segments = (endAngle - startAngle)*ceilf(2*PI/th)/360; if (segments <= 0) segments = 4; @@ -764,12 +753,8 @@ void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color co // Calculate number of segments to use for the corners if (segments < 4) { - // Calculate how many segments we need to draw a smooth circle, taken from https://stackoverflow.com/a/2244088 - #ifndef CIRCLE_ERROR_RATE - #define CIRCLE_ERROR_RATE 0.5f - #endif - // Calculate the maximum angle between segments based on the error rate. - float th = acosf(2*powf(1 - CIRCLE_ERROR_RATE/radius, 2) - 1); + // Calculate the maximum angle between segments based on the error rate (usually 0.5f) + float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/radius, 2) - 1); segments = ceilf(2*PI/th)/4; if (segments <= 0) segments = 4; } @@ -988,12 +973,8 @@ void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, int // Calculate number of segments to use for the corners if (segments < 4) { - // Calculate how many segments we need to draw a smooth circle, taken from https://stackoverflow.com/a/2244088 - #ifndef CIRCLE_ERROR_RATE - #define CIRCLE_ERROR_RATE 0.5f - #endif - // Calculate the maximum angle between segments based on the error rate. - float th = acosf(2*powf(1 - CIRCLE_ERROR_RATE/radius, 2) - 1); + // Calculate the maximum angle between segments based on the error rate (usually 0.5f) + float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/radius, 2) - 1); segments = ceilf(2*PI/th)/2; if (segments <= 0) segments = 4; } diff --git a/src/text.c b/src/text.c index a16774baf..1bd8a0f88 100644 --- a/src/text.c +++ b/src/text.c @@ -16,7 +16,7 @@ * #define TEXTSPLIT_MAX_TEXT_BUFFER_LENGTH * TextSplit() function static buffer max size * -* #define TEXTSPLIT_MAX_SUBSTRINGS_COUNT +* #define MAX_TEXTSPLIT_COUNT * TextSplit() function static substrings pointers array (pointing to static buffer) * * @@ -73,17 +73,15 @@ //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- -#define MAX_TEXT_BUFFER_LENGTH 1024 // Size of internal static buffers used on some functions: - // TextFormat(), TextSubtext(), TextToUpper(), TextToLower(), TextToPascal() - -#define MAX_TEXT_UNICODE_CHARS 512 // Maximum number of unicode codepoints - -#if !defined(TEXTSPLIT_MAX_TEXT_BUFFER_LENGTH) - #define TEXTSPLIT_MAX_TEXT_BUFFER_LENGTH 1024 // Size of static buffer: TextSplit() +#ifndef MAX_TEXT_BUFFER_LENGTH + #define MAX_TEXT_BUFFER_LENGTH 1024 // Size of internal static buffers used on some functions: + // TextFormat(), TextSubtext(), TextToUpper(), TextToLower(), TextToPascal(), TextSplit() #endif - -#if !defined(TEXTSPLIT_MAX_SUBSTRINGS_COUNT) - #define TEXTSPLIT_MAX_SUBSTRINGS_COUNT 128 // Size of static pointers array: TextSplit() +#ifndef MAX_TEXT_UNICODE_CHARS + #define MAX_TEXT_UNICODE_CHARS 512 // Maximum number of unicode codepoints: GetCodepoints() +#endif +#ifndef MAX_TEXTSPLIT_COUNT + #define MAX_TEXTSPLIT_COUNT 128 // Maximum number of substrings to split: TextSplit() #endif //---------------------------------------------------------------------------------- @@ -295,15 +293,21 @@ Font GetFontDefault() // Load Font from file into GPU memory (VRAM) Font LoadFont(const char *fileName) { - // Default hardcoded values for ttf file loading - #define DEFAULT_TTF_FONTSIZE 32 // Font first character (32 - space) - #define DEFAULT_TTF_NUMCHARS 95 // ASCII 32..126 is 95 glyphs - #define DEFAULT_FIRST_CHAR 32 // Expected first char for image sprite font + // Default values for ttf font generation +#ifndef FONT_TTF_DEFAULT_SIZE + #define FONT_TTF_DEFAULT_SIZE 32 // TTF font generation default char size (char-height) +#endif +#ifndef FONT_TTF_DEFAULT_NUMCHARS + #define FONT_TTF_DEFAULT_NUMCHARS 95 // TTF font generation default charset: 95 glyphs (ASCII 32..126) +#endif +#ifndef FONT_TTF_DEFAULT_FIRST_CHAR + #define FONT_TTF_DEFAULT_FIRST_CHAR 32 // TTF font generation default first char for image sprite font (32-Space) +#endif Font font = { 0 }; #if defined(SUPPORT_FILEFORMAT_TTF) - if (IsFileExtension(fileName, ".ttf;.otf")) font = LoadFontEx(fileName, DEFAULT_TTF_FONTSIZE, NULL, DEFAULT_TTF_NUMCHARS); + if (IsFileExtension(fileName, ".ttf;.otf")) font = LoadFontEx(fileName, FONT_TTF_DEFAULT_SIZE, NULL, FONT_TTF_DEFAULT_NUMCHARS); else #endif #if defined(SUPPORT_FILEFORMAT_FNT) @@ -312,7 +316,7 @@ Font LoadFont(const char *fileName) #endif { Image image = LoadImage(fileName); - if (image.data != NULL) font = LoadFontFromImage(image, MAGENTA, DEFAULT_FIRST_CHAR); + if (image.data != NULL) font = LoadFontFromImage(image, MAGENTA, FONT_TTF_DEFAULT_FIRST_CHAR); UnloadImage(image); } @@ -363,6 +367,10 @@ Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int charsCou // Load an Image font file (XNA style) Font LoadFontFromImage(Image image, Color key, int firstChar) { +#ifndef MAX_GLYPHS_FROM_IMAGE + #define MAX_GLYPHS_FROM_IMAGE 256 // Maximum number of glyphs supported on image scan +#endif + #define COLOR_EQUAL(col1, col2) ((col1.r == col2.r)&&(col1.g == col2.g)&&(col1.b == col2.b)&&(col1.a == col2.a)) int charSpacing = 0; @@ -371,13 +379,10 @@ Font LoadFontFromImage(Image image, Color key, int firstChar) int x = 0; int y = 0; - // Default number of characters supported - #define MAX_FONTCHARS 256 - // We allocate a temporal arrays for chars data measures, // once we get the actual number of chars, we copy data to a sized arrays - int tempCharValues[MAX_FONTCHARS]; - Rectangle tempCharRecs[MAX_FONTCHARS]; + int tempCharValues[MAX_GLYPHS_FROM_IMAGE]; + Rectangle tempCharRecs[MAX_GLYPHS_FROM_IMAGE]; Color *pixels = GetImageData(image); @@ -483,11 +488,18 @@ CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int c { // NOTE: Using some SDF generation default values, // trades off precision with ability to handle *smaller* sizes - #define SDF_CHAR_PADDING 4 - #define SDF_ON_EDGE_VALUE 128 - #define SDF_PIXEL_DIST_SCALE 64.0f - - #define BITMAP_ALPHA_THRESHOLD 80 +#ifndef FONT_SDF_CHAR_PADDING + #define FONT_SDF_CHAR_PADDING 4 // SDF font generation char padding +#endif +#ifndef FONT_SDF_ON_EDGE_VALUE + #define FONT_SDF_ON_EDGE_VALUE 128 // SDF font generation on edge value +#endif +#ifndef FONT_SDF_PIXEL_DIST_SCALE + #define FONT_SDF_PIXEL_DIST_SCALE 64.0f // SDF font generation pixel distance scale +#endif +#ifndef FONT_BITMAP_ALPHA_THRESHOLD + #define FONT_BITMAP_ALPHA_THRESHOLD 80 // Bitmap (B&W) font generation alpha threshold +#endif CharInfo *chars = NULL; @@ -541,7 +553,7 @@ CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int c // stbtt_MakeCodepointBitmap() -- renders into bitmap you provide if (type != FONT_SDF) chars[i].image.data = stbtt_GetCodepointBitmap(&fontInfo, scaleFactor, scaleFactor, ch, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY); - else if (ch != 32) chars[i].image.data = stbtt_GetCodepointSDF(&fontInfo, scaleFactor, ch, SDF_CHAR_PADDING, SDF_ON_EDGE_VALUE, SDF_PIXEL_DIST_SCALE, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY); + else if (ch != 32) chars[i].image.data = stbtt_GetCodepointSDF(&fontInfo, scaleFactor, ch, FONT_SDF_CHAR_PADDING, FONT_SDF_ON_EDGE_VALUE, FONT_SDF_PIXEL_DIST_SCALE, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY); else chars[i].image.data = NULL; stbtt_GetCodepointHMetrics(&fontInfo, ch, &chars[i].advanceX, NULL); @@ -568,7 +580,7 @@ CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int c // NOTE: For optimum results, bitmap font should be generated at base pixel size for (int p = 0; p < chw*chh; p++) { - if (((unsigned char *)chars[i].image.data)[p] < BITMAP_ALPHA_THRESHOLD) ((unsigned char *)chars[i].image.data)[p] = 0; + if (((unsigned char *)chars[i].image.data)[p] < FONT_BITMAP_ALPHA_THRESHOLD) ((unsigned char *)chars[i].image.data)[p] = 0; else ((unsigned char *)chars[i].image.data)[p] = 255; } } @@ -1053,11 +1065,14 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing // Returns index position for a unicode character on spritefont int GetGlyphIndex(Font font, int codepoint) { -#define TEXT_CHARACTER_NOTFOUND 63 // Character: '?' +#ifndef GLYPH_NOTFOUND_CHAR_FALLBACK + #define GLYPH_NOTFOUND_CHAR_FALLBACK 63 // Character used if requested codepoint is not found: '?' +#endif -#define UNORDERED_CHARSET -#if defined(UNORDERED_CHARSET) - int index = TEXT_CHARACTER_NOTFOUND; +// Support charsets with any characters order +#define SUPPORT_UNORDERED_CHARSET +#if defined(SUPPORT_UNORDERED_CHARSET) + int index = GLYPH_NOTFOUND_CHAR_FALLBACK; for (int i = 0; i < font.charsCount; i++) { @@ -1128,8 +1143,10 @@ unsigned int TextLength(const char *text) // WARNING: String returned will expire after this function is called MAX_TEXTFORMAT_BUFFERS times const char *TextFormat(const char *text, ...) { - #define MAX_TEXTFORMAT_BUFFERS 4 - +#ifndef MAX_TEXTFORMAT_BUFFERS + #define MAX_TEXTFORMAT_BUFFERS 4 // Maximum number of static buffers for text formatting +#endif + // We create an array of buffers so strings don't expire until MAX_TEXTFORMAT_BUFFERS invocations static char buffers[MAX_TEXTFORMAT_BUFFERS][MAX_TEXT_BUFFER_LENGTH] = { 0 }; static int index = 0; @@ -1279,12 +1296,12 @@ const char **TextSplit(const char *text, char delimiter, int *count) // NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter) // inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated, // all used memory is static... it has some limitations: - // 1. Maximum number of possible split strings is set by TEXTSPLIT_MAX_SUBSTRINGS_COUNT - // 2. Maximum size of text to split is TEXTSPLIT_MAX_TEXT_BUFFER_LENGTH + // 1. Maximum number of possible split strings is set by MAX_TEXTSPLIT_COUNT + // 2. Maximum size of text to split is MAX_TEXT_BUFFER_LENGTH - static const char *result[TEXTSPLIT_MAX_SUBSTRINGS_COUNT] = { NULL }; - static char buffer[TEXTSPLIT_MAX_TEXT_BUFFER_LENGTH] = { 0 }; - memset(buffer, 0, TEXTSPLIT_MAX_TEXT_BUFFER_LENGTH); + static const char *result[MAX_TEXTSPLIT_COUNT] = { NULL }; + static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 }; + memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH); result[0] = buffer; int counter = 0; @@ -1294,7 +1311,7 @@ const char **TextSplit(const char *text, char delimiter, int *count) counter = 1; // Count how many substrings we have on text and point to every one - for (int i = 0; i < TEXTSPLIT_MAX_TEXT_BUFFER_LENGTH; i++) + for (int i = 0; i < MAX_TEXT_BUFFER_LENGTH; i++) { buffer[i] = text[i]; if (buffer[i] == '\0') break; @@ -1304,7 +1321,7 @@ const char **TextSplit(const char *text, char delimiter, int *count) result[counter] = buffer + i + 1; counter++; - if (counter == TEXTSPLIT_MAX_SUBSTRINGS_COUNT) break; + if (counter == MAX_TEXTSPLIT_COUNT) break; } } } diff --git a/src/textures.c b/src/textures.c index ba866dbc2..7df3a2582 100644 --- a/src/textures.c +++ b/src/textures.c @@ -148,7 +148,9 @@ //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- -// Nop... +#ifndef R5G5B5A1_ALPHA_THRESHOLD + #define R5G5B5A1_ALPHA_THRESHOLD 50 // Threshold over 255 to set alpha as 0 +#endif //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -832,7 +834,9 @@ void ExportImage(Image image, const char *fileName) // Export image as code file (.h) defining an array of bytes void ExportImageAsCode(Image image, const char *fileName) { - #define BYTES_TEXT_PER_LINE 20 +#ifndef TEXT_BYTES_PER_LINE + #define TEXT_BYTES_PER_LINE 20 +#endif FILE *txtFile = fopen(fileName, "wt"); @@ -863,7 +867,7 @@ void ExportImageAsCode(Image image, const char *fileName) fprintf(txtFile, "#define %s_FORMAT %i // raylib internal pixel format\n\n", varFileName, image.format); fprintf(txtFile, "static unsigned char %s_DATA[%i] = { ", varFileName, dataSize); - for (int i = 0; i < dataSize - 1; i++) fprintf(txtFile, ((i%BYTES_TEXT_PER_LINE == 0)? "0x%x,\n" : "0x%x, "), ((unsigned char *)image.data)[i]); + for (int i = 0; i < dataSize - 1; i++) fprintf(txtFile, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%x,\n" : "0x%x, "), ((unsigned char *)image.data)[i]); fprintf(txtFile, "0x%x };\n", ((unsigned char *)image.data)[dataSize - 1]); fclose(txtFile); @@ -1038,8 +1042,6 @@ void ImageFormat(Image *image, int newFormat) } break; case UNCOMPRESSED_R5G5B5A1: { - #define ALPHA_THRESHOLD 50 - image->data = (unsigned short *)RL_MALLOC(image->width*image->height*sizeof(unsigned short)); unsigned char r = 0; @@ -1052,7 +1054,7 @@ void ImageFormat(Image *image, int newFormat) r = (unsigned char)(round(pixels[i].x*31.0f)); g = (unsigned char)(round(pixels[i].y*31.0f)); b = (unsigned char)(round(pixels[i].z*31.0f)); - a = (pixels[i].w > ((float)ALPHA_THRESHOLD/255.0f))? 1 : 0; + a = (pixels[i].w > ((float)R5G5B5A1_ALPHA_THRESHOLD/255.0f))? 1 : 0; ((unsigned short *)image->data)[i] = (unsigned short)r << 11 | (unsigned short)g << 6 | (unsigned short)b << 1 | (unsigned short)a; } @@ -2049,15 +2051,13 @@ void ImageDrawPixel(Image *dst, int x, int y, Color color) } break; case UNCOMPRESSED_R5G5B5A1: { - #define PIXEL_ALPHA_THRESHOLD 50 - // NOTE: Calculate R5G5B5A1 equivalent color Vector4 coln = { (float)color.r/255.0f, (float)color.g/255.0f, (float)color.b/255.0f, (float)color.a/255.0f }; unsigned char r = (unsigned char)(round(coln.x*31.0f)); unsigned char g = (unsigned char)(round(coln.y*31.0f)); unsigned char b = (unsigned char)(round(coln.z*31.0f)); - unsigned char a = (coln.w > ((float)PIXEL_ALPHA_THRESHOLD/255.0f))? 1 : 0;; + unsigned char a = (coln.w > ((float)R5G5B5A1_ALPHA_THRESHOLD/255.0f))? 1 : 0;; ((unsigned short *)dst->data)[y*dst->width + x] = (unsigned short)r << 11 | (unsigned short)g << 6 | (unsigned short)b << 1 | (unsigned short)a; diff --git a/src/utils.c b/src/utils.c index 74b33b501..9f4b2ded7 100644 --- a/src/utils.c +++ b/src/utils.c @@ -50,9 +50,15 @@ #include // Required for: va_list, va_start(), va_end() #include // Required for: strcpy(), strcat() -#define MAX_TRACELOG_BUFFER_SIZE 128 // Max length of one trace-log message - -#define MAX_UWP_MESSAGES 512 // Max UWP messages to process +//---------------------------------------------------------------------------------- +// Defines and Macros +//---------------------------------------------------------------------------------- +#ifndef MAX_TRACELOG_MSG_LENGTH + #define MAX_TRACELOG_MSG_LENGTH 128 // Max length of one trace-log message +#endif +#ifndef MAX_UWP_MESSAGES + #define MAX_UWP_MESSAGES 512 // Max UWP messages to process +#endif //---------------------------------------------------------------------------------- // Global Variables Definition @@ -132,7 +138,7 @@ void TraceLog(int logType, const char *text, ...) default: break; } #else - char buffer[MAX_TRACELOG_BUFFER_SIZE] = { 0 }; + char buffer[MAX_TRACELOG_MSG_LENGTH] = { 0 }; switch (logType) { From c83477ffcad3f2ff457e74a4cfee9cb6e606d4a1 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Fri, 1 May 2020 17:34:43 +0200 Subject: [PATCH 2/8] WARNING: Big internal redesign! Created RenderBatch type and related functions to allow rlgl users creating custom and separate render batches and not only rely on one internal render batch. This feature has not been exposed on raylib yet because it implies some breaking changes. Right now a custom RenderBatch is just used internally in rlgl. --- src/rlgl.h | 554 +++++++++++++++++++++++++++++------------------------ 1 file changed, 302 insertions(+), 252 deletions(-) diff --git a/src/rlgl.h b/src/rlgl.h index 548709cf4..c2473ee90 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -128,31 +128,45 @@ //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- -#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) - // This is the maximum amount of elements (quads) per batch - // NOTE: Be careful with text, every letter maps to a quad - #define MAX_BATCH_ELEMENTS 8192 -#elif defined(GRAPHICS_API_OPENGL_ES2) - // We reduce memory sizes for embedded systems (RPI and HTML5) - // NOTE: On HTML5 (emscripten) this is allocated on heap, by default it's only 16MB!...just take care... - #define MAX_BATCH_ELEMENTS 2048 +// Default internal render batch limits +#ifndef DEFAULT_BATCH_BUFFER_ELEMENTS + #if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) + // This is the maximum amount of elements (quads) per batch + // NOTE: Be careful with text, every letter maps to a quad + #define DEFAULT_BATCH_BUFFER_ELEMENTS 8192 + #elif defined(GRAPHICS_API_OPENGL_ES2) + // We reduce memory sizes for embedded systems (RPI and HTML5) + // NOTE: On HTML5 (emscripten) this is allocated on heap, + // by default it's only 16MB!...just take care... + #define DEFAULT_BATCH_BUFFER_ELEMENTS 2048 + #endif +#endif +#ifndef DEFAULT_BATCH_BUFFERS + #define DEFAULT_BATCH_BUFFERS 1 // Default number of batch buffers (multi-buffering) +#endif +#ifndef DEFAULT_BATCH_DRAWCALLS + #define DEFAULT_BATCH_DRAWCALLS 256 // Default number of batch draw calls (by state changes: mode, texture) #endif -#ifndef MAX_BATCH_BUFFERING - #define MAX_BATCH_BUFFERING 1 // Max number of buffers for batching (multi-buffering) +// Internal Matrix stack +#ifndef MAX_MATRIX_STACK_SIZE + #define MAX_MATRIX_STACK_SIZE 32 // Maximum size of Matrix stack #endif -#define MAX_MATRIX_STACK_SIZE 32 // Max size of Matrix stack -#define MAX_DRAWCALL_REGISTERED 256 // Max draws by state changes (mode, texture) // Shader and material limits -#define MAX_SHADER_LOCATIONS 32 // Maximum number of predefined locations stored in shader struct -#define MAX_MATERIAL_MAPS 12 // Maximum number of texture maps stored in shader struct - -#ifndef RL_NEAR_CULL_DISTANCE - #define RL_NEAR_CULL_DISTANCE 0.01 // Default near cull distance +#ifndef MAX_SHADER_LOCATIONS + #define MAX_SHADER_LOCATIONS 32 // Maximum number of shader locations supported #endif -#ifndef RL_FAR_CULL_DISTANCE - #define RL_FAR_CULL_DISTANCE 1000.0 // Default far cull distance +#ifndef MAX_MATERIAL_MAPS + #define MAX_MATERIAL_MAPS 12 // Maximum number of shader maps supported +#endif + +// Projection matrix culling +#ifndef RL_CULL_DISTANCE_NEAR + #define RL_CULL_DISTANCE_NEAR 0.01 // Default near cull distance +#endif +#ifndef RL_CULL_DISTANCE_FAR + #define RL_CULL_DISTANCE_FAR 1000.0 // Default far cull distance #endif // Texture parameters (equivalent to OpenGL defines) @@ -263,10 +277,6 @@ typedef unsigned char byte; unsigned int *vboId; // OpenGL Vertex Buffer Objects id (7 types of vertex data) } Mesh; - // Shader and material limits - #define MAX_SHADER_LOCATIONS 32 - #define MAX_MATERIAL_MAPS 12 - // Shader type (generic) typedef struct Shader { unsigned int id; // Shader program id @@ -758,36 +768,52 @@ RLAPI int GetPixelDataSize(int width, int height, int format);// Get pixel data //---------------------------------------------------------------------------------- // Dynamic vertex buffers (position + texcoords + colors + indices arrays) -typedef struct DynamicBuffer { - int vCounter; // vertex position counter to process (and draw) from full buffer - int tcCounter; // vertex texcoord counter to process (and draw) from full buffer - int cCounter; // vertex color counter to process (and draw) from full buffer +typedef struct VertexBuffer { + int elementsCount; // Number of elements in the buffer (QUADS) + + int vCounter; // Vertex position counter to process (and draw) from full buffer + int tcCounter; // Vertex texcoord counter to process (and draw) from full buffer + int cCounter; // Vertex color counter to process (and draw) from full buffer - float *vertices; // vertex position (XYZ - 3 components per vertex) (shader-location = 0) - float *texcoords; // vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1) - unsigned char *colors; // vertex colors (RGBA - 4 components per vertex) (shader-location = 3) + float *vertices; // Vertex position (XYZ - 3 components per vertex) (shader-location = 0) + float *texcoords; // Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1) + unsigned char *colors; // Vertex colors (RGBA - 4 components per vertex) (shader-location = 3) #if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) - unsigned int *indices; // vertex indices (in case vertex data comes indexed) (6 indices per quad) + unsigned int *indices; // Vertex indices (in case vertex data comes indexed) (6 indices per quad) #elif defined(GRAPHICS_API_OPENGL_ES2) - unsigned short *indices; // vertex indices (in case vertex data comes indexed) (6 indices per quad) + unsigned short *indices; // Vertex indices (in case vertex data comes indexed) (6 indices per quad) #endif unsigned int vaoId; // OpenGL Vertex Array Object id unsigned int vboId[4]; // OpenGL Vertex Buffer Objects id (4 types of vertex data) -} DynamicBuffer; +} VertexBuffer; // Draw call type +// NOTE: Only texture changes register a new draw, other state-change-related elements are not +// used at this moment (vaoId, shaderId, matrices), raylib just forces a batch draw call if any +// of those state-change happens (this is done in core module) typedef struct DrawCall { int mode; // Drawing mode: LINES, TRIANGLES, QUADS int vertexCount; // Number of vertex of the draw int vertexAlignment; // Number of vertex required for index alignment (LINES, TRIANGLES) - //unsigned int vaoId; // Vertex array id to be used on the draw - //unsigned int shaderId; // Shader id to be used on the draw + //unsigned int vaoId; // Vertex array id to be used on the draw + //unsigned int shaderId; // Shader id to be used on the draw unsigned int textureId; // Texture id to be used on the draw //Matrix projection; // Projection matrix for this draw //Matrix modelview; // Modelview matrix for this draw } DrawCall; +// RenderBatch type +typedef struct RenderBatch { + int buffersCount; // Number of vertex buffers (multi-buffering support) + int currentBuffer; // Current buffer tracking in case of multi-buffering + VertexBuffer *vertexBuffer; // Dynamic buffer(s) for vertex data + + DrawCall *draws; // Draw calls array + int drawsCounter; // Draw calls counter + float currentDepth; // Current depth value for next draw +} RenderBatch; + #if defined(SUPPORT_VR_SIMULATOR) // VR Stereo rendering configuration for simulator typedef struct VrStereoConfig { @@ -801,21 +827,19 @@ typedef struct VrStereoConfig { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) typedef struct rlglData { + RenderBatch *currentBatch; // Current render batch + RenderBatch defaultBatch; // Default internal render batch + struct { int currentMatrixMode; // Current matrix mode Matrix *currentMatrix; // Current matrix pointer Matrix modelview; // Default modelview matrix Matrix projection; // Default projection matrix Matrix transform; // Transform matrix to be used with rlTranslate, rlRotate, rlScale - bool doTransform; // Use transform matrix against vertex (if required) + bool transformRequired; // Require transform matrix application to current draw-call vertex (if required) Matrix stack[MAX_MATRIX_STACK_SIZE];// Matrix stack for push/pop int stackCounter; // Matrix stack counter - DynamicBuffer vertexData[MAX_BATCH_BUFFERING];// Default dynamic buffer for elements data - int currentBuffer; // Current buffer tracking, multi-buffering system is supported - DrawCall *draws; // Draw calls array - int drawsCounter; // Draw calls counter - Texture2D shapesTexture; // Texture used on shapes drawing (usually a white) Rectangle shapesTextureRec; // Texture source rectangle used on shapes drawing unsigned int defaultTextureId; // Default texture used on shapes/poly drawing (required by shader) @@ -823,7 +847,6 @@ typedef struct rlglData { unsigned int defaultFShaderId; // Default fragment shader Id (used by default shader program) Shader defaultShader; // Basic shader, support vertex color and diffuse texture Shader currentShader; // Shader to be used on rendering (by default, defaultShader) - float currentDepth; // Current depth value int framebufferWidth; // Default framebuffer width int framebufferHeight; // Default framebuffer height @@ -879,14 +902,16 @@ static PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArrays; // Entry point poin static unsigned int CompileShader(const char *shaderStr, int type); // Compile custom shader and return shader id static unsigned int LoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId); // Load custom shader program -static Shader LoadShaderDefault(void); // Load default shader (just vertex positioning and texture coloring) -static void SetShaderDefaultLocations(Shader *shader); // Bind default shader locations (attributes and uniforms) -static void UnloadShaderDefault(void); // Unload default shader +static Shader LoadShaderDefault(void); // Load default shader (just vertex positioning and texture coloring) +static void SetShaderDefaultLocations(Shader *shader); // Bind default shader locations (attributes and uniforms) +static void UnloadShaderDefault(void); // Unload default shader -static void LoadBuffersDefault(void); // Load default internal buffers -static void UpdateBuffersDefault(void); // Update default internal buffers (VAOs/VBOs) with vertex data -static void DrawBuffersDefault(void); // Draw default internal buffers vertex data -static void UnloadBuffersDefault(void); // Unload default internal buffers vertex data from CPU and GPU +static RenderBatch LoadRenderBatch(int numBuffers, int bufferElements); // Load a render batch system +static void UnloadRenderBatch(RenderBatch batch); // Unload render batch system +static void DrawRenderBatch(RenderBatch *batch); // Draw render batch data (Update->Draw->Reset) +static void SetRenderBatchActive(RenderBatch *batch); // Set the active render batch for rlgl +static void SetRenderBatchDefault(void); // Set default render batch for rlgl +//static bool CheckRenderBatchLimit(RenderBatch batch, int vCount); // Check render batch vertex buffer limits static void GenDrawCube(void); // Generate and draw cube static void GenDrawQuad(void); // Generate and draw quad @@ -958,7 +983,7 @@ void rlPushMatrix(void) if (RLGL.State.currentMatrixMode == RL_MODELVIEW) { - RLGL.State.doTransform = true; + RLGL.State.transformRequired = true; RLGL.State.currentMatrix = &RLGL.State.transform; } @@ -979,7 +1004,7 @@ void rlPopMatrix(void) if ((RLGL.State.stackCounter == 0) && (RLGL.State.currentMatrixMode == RL_MODELVIEW)) { RLGL.State.currentMatrix = &RLGL.State.modelview; - RLGL.State.doTransform = false; + RLGL.State.transformRequired = false; } } @@ -1091,36 +1116,36 @@ void rlBegin(int mode) { // Draw mode can be RL_LINES, RL_TRIANGLES and RL_QUADS // NOTE: In all three cases, vertex are accumulated over default internal vertex buffer - if (RLGL.State.draws[RLGL.State.drawsCounter - 1].mode != mode) + if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].mode != mode) { - if (RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount > 0) + if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount > 0) { - // Make sure current RLGL.State.draws[i].vertexCount is aligned a multiple of 4, + // Make sure current RLGL.currentBatch->draws[i].vertexCount is aligned a multiple of 4, // that way, following QUADS drawing will keep aligned with index processing // It implies adding some extra alignment vertex at the end of the draw, // those vertex are not processed but they are considered as an additional offset // for the next set of vertex to be drawn - if (RLGL.State.draws[RLGL.State.drawsCounter - 1].mode == RL_LINES) RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment = ((RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount < 4)? RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount : RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount%4); - else if (RLGL.State.draws[RLGL.State.drawsCounter - 1].mode == RL_TRIANGLES) RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment = ((RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount < 4)? 1 : (4 - (RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount%4))); + if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].mode == RL_LINES) RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount < 4)? RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount : RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount%4); + else if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].mode == RL_TRIANGLES) RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount < 4)? 1 : (4 - (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount%4))); - else RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment = 0; + else RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment = 0; - if (rlCheckBufferLimit(RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment)) rlglDraw(); + if (rlCheckBufferLimit(RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment)) rlglDraw(); else { - RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter += RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment; - RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter += RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment; - RLGL.State.vertexData[RLGL.State.currentBuffer].tcCounter += RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment; - RLGL.State.drawsCounter++; + RLGL.currentBatch->drawsCounter++; } } - if (RLGL.State.drawsCounter >= MAX_DRAWCALL_REGISTERED) rlglDraw(); + if (RLGL.currentBatch->drawsCounter >= DEFAULT_BATCH_DRAWCALLS) rlglDraw(); - RLGL.State.draws[RLGL.State.drawsCounter - 1].mode = mode; - RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount = 0; - RLGL.State.draws[RLGL.State.drawsCounter - 1].textureId = RLGL.State.defaultTextureId; + RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].mode = mode; + RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount = 0; + RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].textureId = RLGL.State.defaultTextureId; } } @@ -1131,30 +1156,30 @@ void rlEnd(void) // NOTE: In OpenGL 1.1, one glColor call can be made for all the subsequent glVertex calls // Make sure colors count match vertex count - if (RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter != RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter) + if (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter != RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter) { - int addColors = RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter - RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter; + int addColors = RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter - RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter; for (int i = 0; i < addColors; i++) { - RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter] = RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter - 4]; - RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter + 1] = RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter - 3]; - RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter + 2] = RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter - 2]; - RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter + 3] = RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter - 1]; - RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter++; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter] = RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter - 4]; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter + 1] = RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter - 3]; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter + 2] = RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter - 2]; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter + 3] = RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter - 1]; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter++; } } // Make sure texcoords count match vertex count - if (RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter != RLGL.State.vertexData[RLGL.State.currentBuffer].tcCounter) + if (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter != RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter) { - int addTexCoords = RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter - RLGL.State.vertexData[RLGL.State.currentBuffer].tcCounter; + int addTexCoords = RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter - RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter; for (int i = 0; i < addTexCoords; i++) { - RLGL.State.vertexData[RLGL.State.currentBuffer].texcoords[2*RLGL.State.vertexData[RLGL.State.currentBuffer].tcCounter] = 0.0f; - RLGL.State.vertexData[RLGL.State.currentBuffer].texcoords[2*RLGL.State.vertexData[RLGL.State.currentBuffer].tcCounter + 1] = 0.0f; - RLGL.State.vertexData[RLGL.State.currentBuffer].tcCounter++; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].texcoords[2*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter] = 0.0f; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].texcoords[2*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter + 1] = 0.0f; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter++; } } @@ -1163,11 +1188,11 @@ void rlEnd(void) // NOTE: Depth increment is dependant on rlOrtho(): z-near and z-far values, // as well as depth buffer bit-depth (16bit or 24bit or 32bit) // Correct increment formula would be: depthInc = (zfar - znear)/pow(2, bits) - RLGL.State.currentDepth += (1.0f/20000.0f); + RLGL.currentBatch->currentDepth += (1.0f/20000.0f); // Verify internal buffers limits // NOTE: This check is combined with usage of rlCheckBufferLimit() - if ((RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter) >= (MAX_BATCH_ELEMENTS*4 - 4)) + if ((RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter) >= (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementsCount*4 - 4)) { // WARNING: If we are between rlPushMatrix() and rlPopMatrix() and we need to force a rlglDraw(), // we need to call rlPopMatrix() before to recover *RLGL.State.currentMatrix (RLGL.State.modelview) for the next forced draw call! @@ -1184,40 +1209,40 @@ void rlVertex3f(float x, float y, float z) Vector3 vec = { x, y, z }; // Transform provided vector if required - if (RLGL.State.doTransform) vec = Vector3Transform(vec, RLGL.State.transform); + if (RLGL.State.transformRequired) vec = Vector3Transform(vec, RLGL.State.transform); - // Verify that MAX_BATCH_ELEMENTS limit not reached - if (RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter < (MAX_BATCH_ELEMENTS*4)) + // Verify that current vertex buffer elements limit has not been reached + if (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter < (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementsCount*4)) { - RLGL.State.vertexData[RLGL.State.currentBuffer].vertices[3*RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter] = vec.x; - RLGL.State.vertexData[RLGL.State.currentBuffer].vertices[3*RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter + 1] = vec.y; - RLGL.State.vertexData[RLGL.State.currentBuffer].vertices[3*RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter + 2] = vec.z; - RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter++; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vertices[3*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter] = vec.x; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vertices[3*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter + 1] = vec.y; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vertices[3*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter + 2] = vec.z; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter++; - RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount++; + RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount++; } - else TRACELOG(LOG_ERROR, "RLGL: Batch elements overflow (MAX_BATCH_ELEMENTS)"); + else TRACELOG(LOG_ERROR, "RLGL: Batch elements overflow"); } // Define one vertex (position) void rlVertex2f(float x, float y) { - rlVertex3f(x, y, RLGL.State.currentDepth); + rlVertex3f(x, y, RLGL.currentBatch->currentDepth); } // Define one vertex (position) void rlVertex2i(int x, int y) { - rlVertex3f((float)x, (float)y, RLGL.State.currentDepth); + rlVertex3f((float)x, (float)y, RLGL.currentBatch->currentDepth); } // Define one vertex (texture coordinate) // NOTE: Texture coordinates are limited to QUADS only void rlTexCoord2f(float x, float y) { - RLGL.State.vertexData[RLGL.State.currentBuffer].texcoords[2*RLGL.State.vertexData[RLGL.State.currentBuffer].tcCounter] = x; - RLGL.State.vertexData[RLGL.State.currentBuffer].texcoords[2*RLGL.State.vertexData[RLGL.State.currentBuffer].tcCounter + 1] = y; - RLGL.State.vertexData[RLGL.State.currentBuffer].tcCounter++; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].texcoords[2*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter] = x; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].texcoords[2*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter + 1] = y; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter++; } // Define one vertex (normal) @@ -1230,11 +1255,11 @@ void rlNormal3f(float x, float y, float z) // Define one vertex (color) void rlColor4ub(byte x, byte y, byte z, byte w) { - RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter] = x; - RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter + 1] = y; - RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter + 2] = z; - RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter + 3] = w; - RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter++; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter] = x; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter + 1] = y; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter + 2] = z; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter + 3] = w; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter++; } // Define one vertex (color) @@ -1264,35 +1289,35 @@ void rlEnableTexture(unsigned int id) #endif #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - if (RLGL.State.draws[RLGL.State.drawsCounter - 1].textureId != id) + if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].textureId != id) { - if (RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount > 0) + if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount > 0) { - // Make sure current RLGL.State.draws[i].vertexCount is aligned a multiple of 4, + // Make sure current RLGL.currentBatch->draws[i].vertexCount is aligned a multiple of 4, // that way, following QUADS drawing will keep aligned with index processing // It implies adding some extra alignment vertex at the end of the draw, // those vertex are not processed but they are considered as an additional offset // for the next set of vertex to be drawn - if (RLGL.State.draws[RLGL.State.drawsCounter - 1].mode == RL_LINES) RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment = ((RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount < 4)? RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount : RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount%4); - else if (RLGL.State.draws[RLGL.State.drawsCounter - 1].mode == RL_TRIANGLES) RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment = ((RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount < 4)? 1 : (4 - (RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount%4))); + if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].mode == RL_LINES) RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount < 4)? RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount : RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount%4); + else if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].mode == RL_TRIANGLES) RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount < 4)? 1 : (4 - (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount%4))); - else RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment = 0; + else RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment = 0; - if (rlCheckBufferLimit(RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment)) rlglDraw(); + if (rlCheckBufferLimit(RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment)) rlglDraw(); else { - RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter += RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment; - RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter += RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment; - RLGL.State.vertexData[RLGL.State.currentBuffer].tcCounter += RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment; - RLGL.State.drawsCounter++; + RLGL.currentBatch->drawsCounter++; } } - if (RLGL.State.drawsCounter >= MAX_DRAWCALL_REGISTERED) rlglDraw(); + if (RLGL.currentBatch->drawsCounter >= DEFAULT_BATCH_DRAWCALLS) rlglDraw(); - RLGL.State.draws[RLGL.State.drawsCounter - 1].textureId = id; - RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount = 0; + RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].textureId = id; + RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount = 0; } #endif } @@ -1306,7 +1331,7 @@ void rlDisableTexture(void) #else // NOTE: If quads batch limit is reached, // we force a draw call and next batch starts - if (RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter >= (MAX_BATCH_ELEMENTS*4)) rlglDraw(); + if (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter >= (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementsCount*4)) rlglDraw(); #endif } @@ -1691,33 +1716,14 @@ void rlglInit(int width, int height) RLGL.State.currentShader = RLGL.State.defaultShader; // Init default vertex arrays buffers - LoadBuffersDefault(); + RLGL.defaultBatch = LoadRenderBatch(DEFAULT_BATCH_BUFFERS, DEFAULT_BATCH_BUFFER_ELEMENTS); + RLGL.currentBatch = &RLGL.defaultBatch; - // Init transformations matrix accumulator - RLGL.State.transform = MatrixIdentity(); - - // Init draw calls tracking system - RLGL.State.draws = (DrawCall *)RL_MALLOC(sizeof(DrawCall)*MAX_DRAWCALL_REGISTERED); - - for (int i = 0; i < MAX_DRAWCALL_REGISTERED; i++) - { - RLGL.State.draws[i].mode = RL_QUADS; - RLGL.State.draws[i].vertexCount = 0; - RLGL.State.draws[i].vertexAlignment = 0; - //RLGL.State.draws[i].vaoId = 0; - //RLGL.State.draws[i].shaderId = 0; - RLGL.State.draws[i].textureId = RLGL.State.defaultTextureId; - //RLGL.State.draws[i].RLGL.State.projection = MatrixIdentity(); - //RLGL.State.draws[i].RLGL.State.modelview = MatrixIdentity(); - } - - RLGL.State.drawsCounter = 1; // Reset draws counter - RLGL.State.currentDepth = -1.0f; // Reset depth value - - // Init RLGL.State.stack matrices (emulating OpenGL 1.1) + // Init stack matrices (emulating OpenGL 1.1) for (int i = 0; i < MAX_MATRIX_STACK_SIZE; i++) RLGL.State.stack[i] = MatrixIdentity(); - // Init RLGL.State.projection and RLGL.State.modelview matrices + // Init internal matrices + RLGL.State.transform = MatrixIdentity(); RLGL.State.projection = MatrixIdentity(); RLGL.State.modelview = MatrixIdentity(); RLGL.State.currentMatrix = &RLGL.State.modelview; @@ -1766,13 +1772,12 @@ void rlglInit(int width, int height) void rlglClose(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - UnloadShaderDefault(); // Unload default shader - UnloadBuffersDefault(); // Unload default buffers + UnloadRenderBatch(RLGL.defaultBatch); + + UnloadShaderDefault(); // Unload default shader glDeleteTextures(1, &RLGL.State.defaultTextureId); // Unload default texture TRACELOG(LOG_INFO, "TEXTURE: [ID %i] Unloaded default texture data from VRAM (GPU)", RLGL.State.defaultTextureId); - - RL_FREE(RLGL.State.draws); #endif } @@ -1780,12 +1785,7 @@ void rlglClose(void) void rlglDraw(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - // Only process data if we have data to process - if (RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter > 0) - { - UpdateBuffersDefault(); - DrawBuffersDefault(); // NOTE: Stereo rendering is checked inside - } + DrawRenderBatch(RLGL.currentBatch); // NOTE: Stereo rendering is checked inside #endif } @@ -1796,7 +1796,7 @@ int rlGetVersion(void) return OPENGL_11; #elif defined(GRAPHICS_API_OPENGL_21) #if defined(__APPLE__) - return OPENGL_33; // NOTE: Force OpenGL 3.3 on OSX + return OPENGL_33; // NOTE: Force OpenGL 3.3 on OSX #else return OPENGL_21; #endif @@ -1812,7 +1812,7 @@ bool rlCheckBufferLimit(int vCount) { bool overflow = false; #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - if ((RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter + vCount) >= (MAX_BATCH_ELEMENTS*4)) overflow = true; + if ((RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter + vCount) >= (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementsCount*4)) overflow = true; #endif return overflow; } @@ -3796,8 +3796,7 @@ void EndVrDrawing(void) rlDisableTexture(); // Update and draw render texture fbo with distortion to backbuffer - UpdateBuffersDefault(); - DrawBuffersDefault(); + DrawRenderBatch(RLGL.currentBatch); // Restore RLGL.State.defaultShader RLGL.State.currentShader = RLGL.State.defaultShader; @@ -3859,7 +3858,6 @@ static unsigned int LoadShaderProgram(unsigned int vShaderId, unsigned int fShad unsigned int program = 0; #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - GLint success = 0; program = glCreateProgram(); @@ -4056,44 +4054,50 @@ static void UnloadShaderDefault(void) glDeleteProgram(RLGL.State.defaultShader.id); } -// Load default internal buffers -static void LoadBuffersDefault(void) +// Load render batch +static RenderBatch LoadRenderBatch(int numBuffers, int bufferElements) { - // Initialize CPU (RAM) arrays (vertex position, texcoord, color data and indexes) + RenderBatch batch = { 0 }; + + // Initialize CPU (RAM) vertex buffers (position, texcoord, color data and indexes) //-------------------------------------------------------------------------------------------- - for (int i = 0; i < MAX_BATCH_BUFFERING; i++) + batch.vertexBuffer = (VertexBuffer *)RL_MALLOC(sizeof(VertexBuffer)*numBuffers); + + for (int i = 0; i < numBuffers; i++) { - RLGL.State.vertexData[i].vertices = (float *)RL_MALLOC(sizeof(float)*3*4*MAX_BATCH_ELEMENTS); // 3 float by vertex, 4 vertex by quad - RLGL.State.vertexData[i].texcoords = (float *)RL_MALLOC(sizeof(float)*2*4*MAX_BATCH_ELEMENTS); // 2 float by texcoord, 4 texcoord by quad - RLGL.State.vertexData[i].colors = (unsigned char *)RL_MALLOC(sizeof(unsigned char)*4*4*MAX_BATCH_ELEMENTS); // 4 float by color, 4 colors by quad + batch.vertexBuffer[i].elementsCount = bufferElements; + + batch.vertexBuffer[i].vertices = (float *)RL_MALLOC(sizeof(float)*3*4*bufferElements); // 3 float by vertex, 4 vertex by quad + batch.vertexBuffer[i].texcoords = (float *)RL_MALLOC(sizeof(float)*2*4*bufferElements); // 2 float by texcoord, 4 texcoord by quad + batch.vertexBuffer[i].colors = (unsigned char *)RL_MALLOC(sizeof(unsigned char)*4*4*bufferElements); // 4 float by color, 4 colors by quad #if defined(GRAPHICS_API_OPENGL_33) - RLGL.State.vertexData[i].indices = (unsigned int *)RL_MALLOC(sizeof(unsigned int)*6*MAX_BATCH_ELEMENTS); // 6 int by quad (indices) + batch.vertexBuffer[i].indices = (unsigned int *)RL_MALLOC(sizeof(unsigned int)*6*bufferElements); // 6 int by quad (indices) #elif defined(GRAPHICS_API_OPENGL_ES2) - RLGL.State.vertexData[i].indices = (unsigned short *)RL_MALLOC(sizeof(unsigned short)*6*MAX_BATCH_ELEMENTS); // 6 int by quad (indices) + batch.vertexBuffer[i].indices = (unsigned short *)RL_MALLOC(sizeof(unsigned short)*6*bufferElements); // 6 int by quad (indices) #endif - for (int j = 0; j < (3*4*MAX_BATCH_ELEMENTS); j++) RLGL.State.vertexData[i].vertices[j] = 0.0f; - for (int j = 0; j < (2*4*MAX_BATCH_ELEMENTS); j++) RLGL.State.vertexData[i].texcoords[j] = 0.0f; - for (int j = 0; j < (4*4*MAX_BATCH_ELEMENTS); j++) RLGL.State.vertexData[i].colors[j] = 0; + for (int j = 0; j < (3*4*bufferElements); j++) batch.vertexBuffer[i].vertices[j] = 0.0f; + for (int j = 0; j < (2*4*bufferElements); j++) batch.vertexBuffer[i].texcoords[j] = 0.0f; + for (int j = 0; j < (4*4*bufferElements); j++) batch.vertexBuffer[i].colors[j] = 0; int k = 0; // Indices can be initialized right now - for (int j = 0; j < (6*MAX_BATCH_ELEMENTS); j += 6) + for (int j = 0; j < (6*bufferElements); j += 6) { - RLGL.State.vertexData[i].indices[j] = 4*k; - RLGL.State.vertexData[i].indices[j + 1] = 4*k + 1; - RLGL.State.vertexData[i].indices[j + 2] = 4*k + 2; - RLGL.State.vertexData[i].indices[j + 3] = 4*k; - RLGL.State.vertexData[i].indices[j + 4] = 4*k + 2; - RLGL.State.vertexData[i].indices[j + 5] = 4*k + 3; + batch.vertexBuffer[i].indices[j] = 4*k; + batch.vertexBuffer[i].indices[j + 1] = 4*k + 1; + batch.vertexBuffer[i].indices[j + 2] = 4*k + 2; + batch.vertexBuffer[i].indices[j + 3] = 4*k; + batch.vertexBuffer[i].indices[j + 4] = 4*k + 2; + batch.vertexBuffer[i].indices[j + 5] = 4*k + 3; k++; } - RLGL.State.vertexData[i].vCounter = 0; - RLGL.State.vertexData[i].tcCounter = 0; - RLGL.State.vertexData[i].cCounter = 0; + batch.vertexBuffer[i].vCounter = 0; + batch.vertexBuffer[i].tcCounter = 0; + batch.vertexBuffer[i].cCounter = 0; } TRACELOG(LOG_INFO, "RLGL: Internal vertex buffers initialized successfully in RAM (CPU)"); @@ -4101,79 +4105,103 @@ static void LoadBuffersDefault(void) // Upload to GPU (VRAM) vertex data and initialize VAOs/VBOs //-------------------------------------------------------------------------------------------- - for (int i = 0; i < MAX_BATCH_BUFFERING; i++) + for (int i = 0; i < numBuffers; i++) { if (RLGL.ExtSupported.vao) { // Initialize Quads VAO - glGenVertexArrays(1, &RLGL.State.vertexData[i].vaoId); - glBindVertexArray(RLGL.State.vertexData[i].vaoId); + glGenVertexArrays(1, &batch.vertexBuffer[i].vaoId); + glBindVertexArray(batch.vertexBuffer[i].vaoId); } // Quads - Vertex buffers binding and attributes enable // Vertex position buffer (shader-location = 0) - glGenBuffers(1, &RLGL.State.vertexData[i].vboId[0]); - glBindBuffer(GL_ARRAY_BUFFER, RLGL.State.vertexData[i].vboId[0]); - glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*MAX_BATCH_ELEMENTS, RLGL.State.vertexData[i].vertices, GL_DYNAMIC_DRAW); + glGenBuffers(1, &batch.vertexBuffer[i].vboId[0]); + glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[0]); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*bufferElements, batch.vertexBuffer[i].vertices, GL_DYNAMIC_DRAW); glEnableVertexAttribArray(RLGL.State.currentShader.locs[LOC_VERTEX_POSITION]); glVertexAttribPointer(RLGL.State.currentShader.locs[LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0); // Vertex texcoord buffer (shader-location = 1) - glGenBuffers(1, &RLGL.State.vertexData[i].vboId[1]); - glBindBuffer(GL_ARRAY_BUFFER, RLGL.State.vertexData[i].vboId[1]); - glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*MAX_BATCH_ELEMENTS, RLGL.State.vertexData[i].texcoords, GL_DYNAMIC_DRAW); + glGenBuffers(1, &batch.vertexBuffer[i].vboId[1]); + glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[1]); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*bufferElements, batch.vertexBuffer[i].texcoords, GL_DYNAMIC_DRAW); glEnableVertexAttribArray(RLGL.State.currentShader.locs[LOC_VERTEX_TEXCOORD01]); glVertexAttribPointer(RLGL.State.currentShader.locs[LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0); // Vertex color buffer (shader-location = 3) - glGenBuffers(1, &RLGL.State.vertexData[i].vboId[2]); - glBindBuffer(GL_ARRAY_BUFFER, RLGL.State.vertexData[i].vboId[2]); - glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*4*MAX_BATCH_ELEMENTS, RLGL.State.vertexData[i].colors, GL_DYNAMIC_DRAW); + glGenBuffers(1, &batch.vertexBuffer[i].vboId[2]); + glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[2]); + glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*4*bufferElements, batch.vertexBuffer[i].colors, GL_DYNAMIC_DRAW); glEnableVertexAttribArray(RLGL.State.currentShader.locs[LOC_VERTEX_COLOR]); glVertexAttribPointer(RLGL.State.currentShader.locs[LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); // Fill index buffer - glGenBuffers(1, &RLGL.State.vertexData[i].vboId[3]); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, RLGL.State.vertexData[i].vboId[3]); + glGenBuffers(1, &batch.vertexBuffer[i].vboId[3]); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[3]); #if defined(GRAPHICS_API_OPENGL_33) - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int)*6*MAX_BATCH_ELEMENTS, RLGL.State.vertexData[i].indices, GL_STATIC_DRAW); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int)*6*bufferElements, batch.vertexBuffer[i].indices, GL_STATIC_DRAW); #elif defined(GRAPHICS_API_OPENGL_ES2) - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(short)*6*MAX_BATCH_ELEMENTS, RLGL.State.vertexData[i].indices, GL_STATIC_DRAW); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(short)*6*bufferElements, batch.vertexBuffer[i].indices, GL_STATIC_DRAW); #endif } - TRACELOG(LOG_INFO, "RLGL: Internal vertex buffers uploaded successfully to VRAM (GPU)"); + TRACELOG(LOG_INFO, "RLGL: Render batch vertex buffers loaded successfully"); // Unbind the current VAO if (RLGL.ExtSupported.vao) glBindVertexArray(0); //-------------------------------------------------------------------------------------------- + + // Init draw calls tracking system + //-------------------------------------------------------------------------------------------- + batch.draws = (DrawCall *)RL_MALLOC(sizeof(DrawCall)*DEFAULT_BATCH_DRAWCALLS); + + for (int i = 0; i < DEFAULT_BATCH_DRAWCALLS; i++) + { + batch.draws[i].mode = RL_QUADS; + batch.draws[i].vertexCount = 0; + batch.draws[i].vertexAlignment = 0; + //batch.draws[i].vaoId = 0; + //batch.draws[i].shaderId = 0; + batch.draws[i].textureId = RLGL.State.defaultTextureId; + //batch.draws[i].RLGL.State.projection = MatrixIdentity(); + //batch.draws[i].RLGL.State.modelview = MatrixIdentity(); + } + + batch.drawsCounter = 1; // Reset draws counter + batch.currentDepth = -1.0f; // Reset depth value + //-------------------------------------------------------------------------------------------- + + return batch; } -// Update default internal buffers (VAOs/VBOs) with vertex array data -// 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) -static void UpdateBuffersDefault(void) +// Draw render batch +// NOTE: We require a pointer to reset batch and increase current buffer (multi-buffer) +static void DrawRenderBatch(RenderBatch *batch) { - // Update vertex buffers data - if (RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter > 0) + // 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) + if (batch->vertexBuffer[batch->currentBuffer].vCounter > 0) { // Activate elements VAO - if (RLGL.ExtSupported.vao) glBindVertexArray(RLGL.State.vertexData[RLGL.State.currentBuffer].vaoId); + if (RLGL.ExtSupported.vao) glBindVertexArray(batch->vertexBuffer[batch->currentBuffer].vaoId); // Vertex positions buffer - glBindBuffer(GL_ARRAY_BUFFER, RLGL.State.vertexData[RLGL.State.currentBuffer].vboId[0]); - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*3*RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter, RLGL.State.vertexData[RLGL.State.currentBuffer].vertices); - //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*MAX_BATCH_ELEMENTS, RLGL.State.vertexData[RLGL.State.currentBuffer].vertices, GL_DYNAMIC_DRAW); // Update all buffer + glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[0]); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*3*batch->vertexBuffer[batch->currentBuffer].vCounter, batch->vertexBuffer[batch->currentBuffer].vertices); + //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*batch->vertexBuffer[batch->currentBuffer].elementsCount, batch->vertexBuffer[batch->currentBuffer].vertices, GL_DYNAMIC_DRAW); // Update all buffer // Texture coordinates buffer - glBindBuffer(GL_ARRAY_BUFFER, RLGL.State.vertexData[RLGL.State.currentBuffer].vboId[1]); - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*2*RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter, RLGL.State.vertexData[RLGL.State.currentBuffer].texcoords); - //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*MAX_BATCH_ELEMENTS, RLGL.State.vertexData[RLGL.State.currentBuffer].texcoords, GL_DYNAMIC_DRAW); // Update all buffer + glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[1]); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*2*batch->vertexBuffer[batch->currentBuffer].vCounter, batch->vertexBuffer[batch->currentBuffer].texcoords); + //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*batch->vertexBuffer[batch->currentBuffer].elementsCount, batch->vertexBuffer[batch->currentBuffer].texcoords, GL_DYNAMIC_DRAW); // Update all buffer // Colors buffer - glBindBuffer(GL_ARRAY_BUFFER, RLGL.State.vertexData[RLGL.State.currentBuffer].vboId[2]); - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(unsigned char)*4*RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter, RLGL.State.vertexData[RLGL.State.currentBuffer].colors); - //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*4*MAX_BATCH_ELEMENTS, RLGL.State.vertexData[RLGL.State.currentBuffer].colors, GL_DYNAMIC_DRAW); // Update all buffer + glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[2]); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(unsigned char)*4*batch->vertexBuffer[batch->currentBuffer].vCounter, batch->vertexBuffer[batch->currentBuffer].colors); + //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*4*batch->vertexBuffer[batch->currentBuffer].elementsCount, batch->vertexBuffer[batch->currentBuffer].colors, GL_DYNAMIC_DRAW); // Update all buffer // NOTE: glMapBuffer() causes sync issue. // If GPU is working with this buffer, glMapBuffer() will wait(stall) until GPU to finish its job. @@ -4183,8 +4211,8 @@ static void UpdateBuffersDefault(void) // Another option: map the buffer object into client's memory // Probably this code could be moved somewhere else... - // RLGL.State.vertexData[RLGL.State.currentBuffer].vertices = (float *)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE); - // if (RLGL.State.vertexData[RLGL.State.currentBuffer].vertices) + // batch->vertexBuffer[batch->currentBuffer].vertices = (float *)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE); + // if (batch->vertexBuffer[batch->currentBuffer].vertices) // { // Update vertex data // } @@ -4193,11 +4221,10 @@ static void UpdateBuffersDefault(void) // Unbind the current VAO if (RLGL.ExtSupported.vao) glBindVertexArray(0); } -} - -// Draw default internal buffers vertex data -static void DrawBuffersDefault(void) -{ + //------------------------------------------------------------------------------------------------------------ + + // Draw batch vertex buffers (considering VR stereo if required) + //------------------------------------------------------------------------------------------------------------ Matrix matProjection = RLGL.State.projection; Matrix matModelView = RLGL.State.modelview; @@ -4213,7 +4240,7 @@ static void DrawBuffersDefault(void) #endif // Draw buffers - if (RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter > 0) + if (batch->vertexBuffer[batch->currentBuffer].vCounter > 0) { // Set current shader and upload current MVP matrix glUseProgram(RLGL.State.currentShader.id); @@ -4233,51 +4260,51 @@ static void DrawBuffersDefault(void) int vertexOffset = 0; - if (RLGL.ExtSupported.vao) glBindVertexArray(RLGL.State.vertexData[RLGL.State.currentBuffer].vaoId); + if (RLGL.ExtSupported.vao) glBindVertexArray(batch->vertexBuffer[batch->currentBuffer].vaoId); else { // Bind vertex attrib: position (shader-location = 0) - glBindBuffer(GL_ARRAY_BUFFER, RLGL.State.vertexData[RLGL.State.currentBuffer].vboId[0]); + glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[0]); glVertexAttribPointer(RLGL.State.currentShader.locs[LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0); glEnableVertexAttribArray(RLGL.State.currentShader.locs[LOC_VERTEX_POSITION]); // Bind vertex attrib: texcoord (shader-location = 1) - glBindBuffer(GL_ARRAY_BUFFER, RLGL.State.vertexData[RLGL.State.currentBuffer].vboId[1]); + glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[1]); glVertexAttribPointer(RLGL.State.currentShader.locs[LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0); glEnableVertexAttribArray(RLGL.State.currentShader.locs[LOC_VERTEX_TEXCOORD01]); // Bind vertex attrib: color (shader-location = 3) - glBindBuffer(GL_ARRAY_BUFFER, RLGL.State.vertexData[RLGL.State.currentBuffer].vboId[2]); + glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[2]); glVertexAttribPointer(RLGL.State.currentShader.locs[LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); glEnableVertexAttribArray(RLGL.State.currentShader.locs[LOC_VERTEX_COLOR]); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, RLGL.State.vertexData[RLGL.State.currentBuffer].vboId[3]); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[3]); } glActiveTexture(GL_TEXTURE0); - for (int i = 0; i < RLGL.State.drawsCounter; i++) + for (int i = 0; i < batch->drawsCounter; i++) { - glBindTexture(GL_TEXTURE_2D, RLGL.State.draws[i].textureId); + glBindTexture(GL_TEXTURE_2D, batch->draws[i].textureId); // TODO: Find some way to bind additional textures --> Use global texture IDs? Register them on draw[i]? //if (RLGL.State.currentShader->locs[LOC_MAP_SPECULAR] > 0) { glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, textureUnit1_id); } //if (RLGL.State.currentShader->locs[LOC_MAP_SPECULAR] > 0) { glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, textureUnit2_id); } - if ((RLGL.State.draws[i].mode == RL_LINES) || (RLGL.State.draws[i].mode == RL_TRIANGLES)) glDrawArrays(RLGL.State.draws[i].mode, vertexOffset, RLGL.State.draws[i].vertexCount); + if ((batch->draws[i].mode == RL_LINES) || (batch->draws[i].mode == RL_TRIANGLES)) glDrawArrays(batch->draws[i].mode, vertexOffset, batch->draws[i].vertexCount); else { #if defined(GRAPHICS_API_OPENGL_33) // We need to define the number of indices to be processed: quadsCount*6 // NOTE: The final parameter tells the GPU the offset in bytes from the // start of the index buffer to the location of the first index to process - glDrawElements(GL_TRIANGLES, RLGL.State.draws[i].vertexCount/4*6, GL_UNSIGNED_INT, (GLvoid *)(sizeof(GLuint)*vertexOffset/4*6)); + glDrawElements(GL_TRIANGLES, batch->draws[i].vertexCount/4*6, GL_UNSIGNED_INT, (GLvoid *)(sizeof(GLuint)*vertexOffset/4*6)); #elif defined(GRAPHICS_API_OPENGL_ES2) - glDrawElements(GL_TRIANGLES, RLGL.State.draws[i].vertexCount/4*6, GL_UNSIGNED_SHORT, (GLvoid *)(sizeof(GLushort)*vertexOffset/4*6)); + glDrawElements(GL_TRIANGLES, batch->draws[i].vertexCount/4*6, GL_UNSIGNED_SHORT, (GLvoid *)(sizeof(GLushort)*vertexOffset/4*6)); #endif } - vertexOffset += (RLGL.State.draws[i].vertexCount + RLGL.State.draws[i].vertexAlignment); + vertexOffset += (batch->draws[i].vertexCount + batch->draws[i].vertexAlignment); } if (!RLGL.ExtSupported.vao) @@ -4293,36 +4320,40 @@ static void DrawBuffersDefault(void) glUseProgram(0); // Unbind shader program } - + //------------------------------------------------------------------------------------------------------------ + + // Reset batch buffers + //------------------------------------------------------------------------------------------------------------ // Reset vertex counters for next frame - RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter = 0; - RLGL.State.vertexData[RLGL.State.currentBuffer].tcCounter = 0; - RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter = 0; + batch->vertexBuffer[batch->currentBuffer].vCounter = 0; + batch->vertexBuffer[batch->currentBuffer].tcCounter = 0; + batch->vertexBuffer[batch->currentBuffer].cCounter = 0; // Reset depth for next draw - RLGL.State.currentDepth = -1.0f; + batch->currentDepth = -1.0f; // Restore projection/modelview matrices RLGL.State.projection = matProjection; RLGL.State.modelview = matModelView; - // Reset RLGL.State.draws array - for (int i = 0; i < MAX_DRAWCALL_REGISTERED; i++) + // Reset RLGL.currentBatch->draws array + for (int i = 0; i < DEFAULT_BATCH_DRAWCALLS; i++) { - RLGL.State.draws[i].mode = RL_QUADS; - RLGL.State.draws[i].vertexCount = 0; - RLGL.State.draws[i].textureId = RLGL.State.defaultTextureId; + batch->draws[i].mode = RL_QUADS; + batch->draws[i].vertexCount = 0; + batch->draws[i].textureId = RLGL.State.defaultTextureId; } - RLGL.State.drawsCounter = 1; + batch->drawsCounter = 1; + //------------------------------------------------------------------------------------------------------------ - // Change to next buffer in the list - RLGL.State.currentBuffer++; - if (RLGL.State.currentBuffer >= MAX_BATCH_BUFFERING) RLGL.State.currentBuffer = 0; + // Change to next buffer in the list (in case of multi-buffering) + batch->currentBuffer++; + if (batch->currentBuffer >= batch->buffersCount) batch->currentBuffer = 0; } // Unload default internal buffers vertex data from CPU and GPU -static void UnloadBuffersDefault(void) +static void UnloadRenderBatch(RenderBatch batch) { // Unbind everything if (RLGL.ExtSupported.vao) glBindVertexArray(0); @@ -4333,23 +4364,42 @@ static void UnloadBuffersDefault(void) glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - for (int i = 0; i < MAX_BATCH_BUFFERING; i++) + // Unload all vertex buffers data + for (int i = 0; i < batch.buffersCount; i++) { // Delete VBOs from GPU (VRAM) - glDeleteBuffers(1, &RLGL.State.vertexData[i].vboId[0]); - glDeleteBuffers(1, &RLGL.State.vertexData[i].vboId[1]); - glDeleteBuffers(1, &RLGL.State.vertexData[i].vboId[2]); - glDeleteBuffers(1, &RLGL.State.vertexData[i].vboId[3]); + glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[0]); + glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[1]); + glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[2]); + glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[3]); // Delete VAOs from GPU (VRAM) - if (RLGL.ExtSupported.vao) glDeleteVertexArrays(1, &RLGL.State.vertexData[i].vaoId); + if (RLGL.ExtSupported.vao) glDeleteVertexArrays(1, &batch.vertexBuffer[i].vaoId); // Free vertex arrays memory from CPU (RAM) - RL_FREE(RLGL.State.vertexData[i].vertices); - RL_FREE(RLGL.State.vertexData[i].texcoords); - RL_FREE(RLGL.State.vertexData[i].colors); - RL_FREE(RLGL.State.vertexData[i].indices); + RL_FREE(batch.vertexBuffer[i].vertices); + RL_FREE(batch.vertexBuffer[i].texcoords); + RL_FREE(batch.vertexBuffer[i].colors); + RL_FREE(batch.vertexBuffer[i].indices); } + + // Unload arrays + RL_FREE(batch.vertexBuffer); + RL_FREE(batch.draws); +} + +// Set the active render batch for rlgl +static void SetRenderBatchActive(RenderBatch *batch) +{ + DrawRenderBatch(RLGL.currentBatch); + RLGL.currentBatch = batch; +} + +// Set default render batch for rlgl +static void SetRenderBatchDefault(void) +{ + DrawRenderBatch(RLGL.currentBatch); + RLGL.currentBatch = &RLGL.defaultBatch; } // Renders a 1x1 XY quad in NDC From 4583987fb937bd3f1ff1409d10e015fa460a37d9 Mon Sep 17 00:00:00 2001 From: Anata Date: Fri, 1 May 2020 17:50:41 +0200 Subject: [PATCH 3/8] Add Vector2MoveTowards function (#1233) --- src/raymath.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/raymath.h b/src/raymath.h index 398aef4ab..acf97fb9c 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -283,6 +283,17 @@ RMDEF Vector2 Vector2Rotate(Vector2 v, float degs) return result; } +// Move towards Target. +RMDEF Vector2 Vector2MoveTowards( Vector2 v, Vector2 target, float maxDistance) +{ + float dx = target.x - v.x; + float dy = target.y - v.y; + float value = ( dx * dx ) + ( dy * dy ); + if ( value == 0 || ( maxDistance >= 0 && value <= maxDistance * maxDistance )) return target; + float result = sqrtf( value ); + return (Vector2){ v.x + dx / result * maxDistance, v.y + dy / result * maxDistance }; +} + //---------------------------------------------------------------------------------- // Module Functions Definition - Vector3 math //---------------------------------------------------------------------------------- From af744b07c31444930dca75b432a650b5519c38a2 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Fri, 1 May 2020 18:04:47 +0200 Subject: [PATCH 4/8] Review latest PR formatting --- src/raymath.h | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/raymath.h b/src/raymath.h index acf97fb9c..e021b9322 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -283,15 +283,22 @@ RMDEF Vector2 Vector2Rotate(Vector2 v, float degs) return result; } -// Move towards Target. -RMDEF Vector2 Vector2MoveTowards( Vector2 v, Vector2 target, float maxDistance) +// Move Vector towards target +RMDEF Vector2 Vector2MoveTowards(Vector2 v, Vector2 target, float maxDistance) { + Vector2 result = { 0 } float dx = target.x - v.x; float dy = target.y - v.y; - float value = ( dx * dx ) + ( dy * dy ); - if ( value == 0 || ( maxDistance >= 0 && value <= maxDistance * maxDistance )) return target; - float result = sqrtf( value ); - return (Vector2){ v.x + dx / result * maxDistance, v.y + dy / result * maxDistance }; + float value = (dx*dx) + (dy*dy); + + if ((value == 0) || ((maxDistance >= 0) && (value <= maxDistance*maxDistance))) result = target; + + float dist = sqrtf(value); + + result.x = v.x + dx/dist*maxDistance; + result.y = v.y + dy/dist*maxDistance; + + return result; } //---------------------------------------------------------------------------------- From 6a8e4795da6d1b485e51cdcc9688d92c9ed890fb Mon Sep 17 00:00:00 2001 From: raysan5 Date: Fri, 1 May 2020 18:16:04 +0200 Subject: [PATCH 5/8] Update core_input_multitouch.c --- examples/core/core_input_multitouch.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/core/core_input_multitouch.c b/examples/core/core_input_multitouch.c index 5fbb086c4..1870b9082 100644 --- a/examples/core/core_input_multitouch.c +++ b/examples/core/core_input_multitouch.c @@ -13,6 +13,8 @@ #include "raylib.h" +#define MAX_TOUCH_POINTS 10 + int main(void) { // Initialization From b8055925bf056b81f92095672552a67dbee2c430 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Fri, 1 May 2020 18:19:54 +0200 Subject: [PATCH 6/8] Update raymath.h --- src/raymath.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/raymath.h b/src/raymath.h index e021b9322..0eb423a01 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -286,7 +286,7 @@ RMDEF Vector2 Vector2Rotate(Vector2 v, float degs) // Move Vector towards target RMDEF Vector2 Vector2MoveTowards(Vector2 v, Vector2 target, float maxDistance) { - Vector2 result = { 0 } + Vector2 result = { 0 }; float dx = target.x - v.x; float dy = target.y - v.y; float value = (dx*dx) + (dy*dy); From 695e93710210325defbbf18737b9032093815dcc Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 2 May 2020 11:48:07 +0200 Subject: [PATCH 7/8] Added binding raylib-Forever --- BINDINGS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/BINDINGS.md b/BINDINGS.md index edc1c0ab1..e498bc550 100644 --- a/BINDINGS.md +++ b/BINDINGS.md @@ -22,6 +22,7 @@ Some people ported raylib to other languages in form of bindings or wrappers to | raylib-nelua | Nelua | https://github.com/Andre-LA/raylib-nelua-mirror | | raylib-Nim | Nim | https://gitlab.com/define-private-public/raylib-Nim | | raylib-nim | Nim | https://github.com/Skrylar/raylib-nim | +| raylib-Forever | Nim | https://github.com/Guevara-chan/Raylib-Forever | | raylib-haskell | Haskell | https://github.com/DevJac/raylib-haskell | | raylib-cr | Crystal | https://github.com/AregevDev/raylib-cr | | cray | Crystal | https://gitlab.com/Zatherz/cray | From 72443f8f25b1f8ded3b05da17857b7eeb1556b35 Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 2 May 2020 11:56:24 +0200 Subject: [PATCH 8/8] Removed RaylibSharp (dead link) --- BINDINGS.md | 1 - 1 file changed, 1 deletion(-) diff --git a/BINDINGS.md b/BINDINGS.md index e498bc550..9c5f4c620 100644 --- a/BINDINGS.md +++ b/BINDINGS.md @@ -7,7 +7,6 @@ Some people ported raylib to other languages in form of bindings or wrappers to | raylib | C | https://github.com/raysan5/raylib | | raylib-cpp | C++ | https://github.com/robloach/raylib-cpp | | Raylib-cs | C# | https://github.com/ChrisDill/Raylib-cs | -| RaylibSharp | C# | https://github.com/TheLumaio/RaylibSharp | | RaylibFS | F# | https://github.com/dallinbeutler/RaylibFS | | raylib_d | D | https://github.com/0xFireball/raylib_d | | raylib-d | D | https://github.com/onroundit/raylib-d |