diff --git a/.gitignore b/.gitignore index a1ca6c009..dcfa5bce2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,11 @@ # Ignore generated files # ... +# Ignore all without extensions +* +!*.* +!*/ + # Ignore VIM's backup generated files *.swp *.swo @@ -52,6 +57,13 @@ packages/ *.a *.bc *.so +*.so.* + +# Ignore wasm data in examples/ +examples/**/*.wasm +examples/**/*.data +examples/**/*.js +examples/**/*.html # Ignore files build by xcode *.mode*v* diff --git a/BINDINGS.md b/BINDINGS.md index 1c43d1871..b154dc7b2 100644 --- a/BINDINGS.md +++ b/BINDINGS.md @@ -1,13 +1,12 @@ -## raylib bindings +# raylib bindings and wrappers -Some people ported raylib to other languages in form of bindings or wrappers to the library. +Some people ported raylib to other languages in form of bindings or wrappers to the library. Here it is alist with all the ports available. Feel free to send a PR if you know of any binding/wrapper not in this list. -Here it is a list with the ones I'm aware of: +### Language Bindings | name | raylib version | language | repo | |:------------------:|:-------------: | :--------:|----------------------------------------------------------------------| -| raylib | **3.7** | [C](https://en.wikipedia.org/wiki/C_(programming_language)) | https://github.com/raysan5/raylib | -| raylib-cpp | 3.7 | [C++](https://en.wikipedia.org/wiki/C%2B%2B) | https://github.com/robloach/raylib-cpp | +| raylib | **3.7** | [C/C++](https://en.wikipedia.org/wiki/C_(programming_language)) | https://github.com/raysan5/raylib | | Raylib-cs | 3.7 | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | https://github.com/ChrisDill/Raylib-cs | | raylib-cppsharp | 2.5 | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | https://github.com/phxvyper/raylib-cppsharp | | raylib-boo | 3.7 | [Boo](http://boo-language.github.io/) | https://github.com/Rabios/raylib-boo | @@ -28,6 +27,7 @@ Here it is a list with the ones I'm aware of: | raylib-luamore | 3.0 | [Lua](http://www.lua.org/) | https://github.com/HDPLocust/raylib-luamore | | raylua | 3.7 | [Lua](http://www.lua.org/) | https://github.com/Rabios/raylua | | LuaJIT-Raylib | 2.6 | [Lua](http://www.lua.org/) | https://github.com/Bambofy/LuaJIT-Raylib | +| raylib-nelua | 3.7 | [nelua](https://nelua.io/) | https://github.com/edubart/nelua-decl/tree/main/libs/raylib | | raylib-nelua | 3.0 | [Nelua](https://nelua.io/) | https://github.com/Andre-LA/raylib-nelua | | raylib-Nim | 1.7 | [Nim](https://nim-lang.org/) | https://gitlab.com/define-private-public/raylib-Nim | | raylib-nim | 2.0 | [Nim](https://nim-lang.org/) | https://github.com/Skrylar/raylib-nim | @@ -96,10 +96,16 @@ Here it is a list with the ones I'm aware of: | raylib-never | 3.0 | [Never](https://github.com/never-lang/never) | https://github.com/never-lang/raylib-never | | hb-raylib | 3.5 | [Harbour](https://harbour.github.io) | https://github.com/MarcosLeonardoMendezGerencir/hb-raylib | | Relib | 3.5 | [ReCT](https://github.com/RedCubeDev-ByteSpace/ReCT) | https://github.com/RedCubeDev-ByteSpace/Relib | +| rayex | 3.7 | [elixir](https://elixir-lang.org/) | https://github.com/shiryel/rayex | | raylib.cbl | 2.0 | [COBOL](https://en.wikipedia.org/wiki/COBOL) | *[code examples](https://github.com/Martinfx/Cobol/tree/master/OpenCobol/Games/raylib)* | +### Utility Wrapers + +| name | raylib version | language | repo | +|:------------------:|:-------------: | :--------:|----------------------------------------------------------------------| +| raylib-cpp | 3.7 | [C++](https://en.wikipedia.org/wiki/C%2B%2B) | https://github.com/robloach/raylib-cpp | -Missing some language? Feel free to create a new binding! :) +Missing some language or wrapper? Feel free to create a new one! :) Usually, raylib bindings follow the convention: `raylib-{language}` diff --git a/CHANGELOG b/CHANGELOG index c37aa3162..54bf0db61 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,6 +3,17 @@ changelog Current Release: raylib 3.7.0 (26 April 2021) +------------------------------------------------------------------------- +Release: raylib 4.0 (November? 2021) +------------------------------------------------------------------------- +KEY CHANGES: + - + - + - + +Detailed changes: + + ------------------------------------------------------------------------- Release: raylib 3.7 (26 April 2021) ------------------------------------------------------------------------- diff --git a/CONVENTIONS.md b/CONVENTIONS.md index f963f1e05..e47a1e841 100644 --- a/CONVENTIONS.md +++ b/CONVENTIONS.md @@ -8,7 +8,7 @@ Defines | ALL_CAPS | `#define PLATFORM_DESKTOP` Macros | ALL_CAPS | `#define MIN(a,b) (((a)<(b))?(a):(b))` Variables | lowerCase | `int screenWidth = 0;`, `float targetFrameTime = 0.016f;` Local variables | lowerCase | `Vector2 playerPosition = { 0 };` -Global variables | lowerCase | `bool fullscreen = false;` +Global variables | lowerCase | `bool windowReady = false;` Constants | lowerCase | `const int maxValue = 8;` Pointers | MyType *pointer | `Texture2D *array = NULL;` float values | always x.xf | `float gravity = 10.0f` diff --git a/SPONSORS.md b/SPONSORS.md index c4822d0e0..c308a513c 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -27,6 +27,7 @@ Note that Sponsors donations vary between sponsors, I just decided not to make a - Merlyn Morgan-Graham ([@kavika13](https://github.com/kavika13)) - Toby4213 ([@Toby4213](https://github.com/Toby4213)) - linus ([@hochbaum](https://github.com/hochbaum)) + - Nawarian ([@nawarian](https://github.com/nawarian) - [thephp.website](https://thephp.website/)) ### Past raylib GitHub Sponsors diff --git a/examples/Makefile b/examples/Makefile index aa183fd17..5abf0c708 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -195,7 +195,7 @@ endif # -std=gnu99 defines C language mode (GNU C from 1999 revision) # -Wno-missing-braces ignore invalid warning (GCC bug 53119) # -D_DEFAULT_SOURCE use with -std=c99 on Linux and PLATFORM_WEB, required for timespec -CFLAGS += -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces +CFLAGS += -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces -Wunused-result ifeq ($(BUILD_MODE),DEBUG) CFLAGS += -g @@ -244,7 +244,7 @@ ifeq ($(PLATFORM),PLATFORM_WEB) # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) # --preload-file resources # specify a resources folder for data compilation # --source-map-base # allow debugging in browser with source map - CFLAGS += -s USE_GLFW=3 -s ASYNCIFY -s TOTAL_MEMORY=67108864 -s FORCE_FILESYSTEM=1 $(dir $<)resources@resources + CFLAGS += -s USE_GLFW=3 -s ASYNCIFY -s TOTAL_MEMORY=67108864 -s FORCE_FILESYSTEM=1 --preload-file $(dir $<)resources@resources # NOTE: Simple raylib examples are compiled to be interpreter with asyncify, that way, # we can compile same code for ALL platforms with no change required, but, working on bigger diff --git a/examples/models/models_rlgl_solar_system.c b/examples/models/models_rlgl_solar_system.c index 97d692453..24394bec2 100644 --- a/examples/models/models_rlgl_solar_system.c +++ b/examples/models/models_rlgl_solar_system.c @@ -14,6 +14,8 @@ #include "raylib.h" #include "rlgl.h" +#include // Required for: cosf(), sinf() + //------------------------------------------------------------------------------------ // Module Functions Declaration //------------------------------------------------------------------------------------ diff --git a/examples/models/models_skybox.c b/examples/models/models_skybox.c index 2b98435ac..168d61f61 100644 --- a/examples/models/models_skybox.c +++ b/examples/models/models_skybox.c @@ -11,6 +11,7 @@ #include "raylib.h" #include "rlgl.h" +#include "raymath.h" #if defined(PLATFORM_DESKTOP) #define GLSL_VERSION 330 diff --git a/examples/network/network_ping_pong.c b/examples/network/network_ping_pong.c index ec45f6445..7b5dd2dd6 100644 --- a/examples/network/network_ping_pong.c +++ b/examples/network/network_ping_pong.c @@ -12,7 +12,7 @@ #include "raylib.h" #define RNET_IMPLEMENTATION -#include "rnet.h" +#include "extras/rnet.h" float elapsed = 0.0f; float delay = 1.0f; diff --git a/examples/network/network_resolve_host.c b/examples/network/network_resolve_host.c index a6e9ecdf4..a00ccb2d2 100644 --- a/examples/network/network_resolve_host.c +++ b/examples/network/network_resolve_host.c @@ -12,7 +12,7 @@ #include "raylib.h" #define RNET_IMPLEMENTATION -#include "rnet.h" +#include "extras/rnet.h" int main(void) { diff --git a/examples/network/network_tcp_client.c b/examples/network/network_tcp_client.c index 1779a3a4a..ad78c691e 100644 --- a/examples/network/network_tcp_client.c +++ b/examples/network/network_tcp_client.c @@ -12,7 +12,7 @@ #include "raylib.h" #define RNET_IMPLEMENTATION -#include "rnet.h" +#include "extras/rnet.h" int main(void) { diff --git a/examples/network/network_tcp_server.c b/examples/network/network_tcp_server.c index 5cbbe54bd..bffe03fa5 100644 --- a/examples/network/network_tcp_server.c +++ b/examples/network/network_tcp_server.c @@ -12,7 +12,7 @@ #include "raylib.h" #define RNET_IMPLEMENTATION -#include "rnet.h" +#include "extras/rnet.h" int main(void) { diff --git a/examples/network/network_test.c b/examples/network/network_test.c index 957ed8ba0..70349e79c 100644 --- a/examples/network/network_test.c +++ b/examples/network/network_test.c @@ -12,7 +12,7 @@ #include "raylib.h" #define RNET_IMPLEMENTATION -#include "rnet.h" +#include "extras/rnet.h" #include diff --git a/examples/network/network_udp_client.c b/examples/network/network_udp_client.c index d351372b5..bcf9fc076 100644 --- a/examples/network/network_udp_client.c +++ b/examples/network/network_udp_client.c @@ -12,7 +12,7 @@ #include "raylib.h" #define RNET_IMPLEMENTATION -#include "rnet.h" +#include "extras/rnet.h" int main(void) { diff --git a/examples/network/network_udp_server.c b/examples/network/network_udp_server.c index 29fffbe7b..eae1c6b33 100644 --- a/examples/network/network_udp_server.c +++ b/examples/network/network_udp_server.c @@ -12,7 +12,7 @@ #include "raylib.h" #define RNET_IMPLEMENTATION -#include "rnet.h" +#include "extras/rnet.h" int main(void) { diff --git a/examples/others/opengl_interop.c b/examples/others/raylib_opengl_interop.c similarity index 68% rename from examples/others/opengl_interop.c rename to examples/others/raylib_opengl_interop.c index 5d435f2a8..2ecc637d5 100644 --- a/examples/others/opengl_interop.c +++ b/examples/others/raylib_opengl_interop.c @@ -2,7 +2,7 @@ * * raylib [shaders] example - OpenGL point particle system * -* This example has been created using raylib 2ad3eb1 (www.raylib.com) +* This example has been created using raylib 3.8 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Example contributed by Stephan Soller (@arkanis - http://arkanis.de/) @@ -24,8 +24,9 @@ ********************************************************************************************/ #include "raylib.h" -#include "rlgl.h" -#include "glad.h" +#include "rlgl.h" // Required for: rlDrawRenderBatchActive(), rlGetMatrixModelview(), rlGetMatrixProjection() +#include "glad.h" // Required for: OpenGL functionality +#include "raymath.h" // Required for: MatrixMultiply(), MatrixToFloat() #if defined(PLATFORM_DESKTOP) #define GLSL_VERSION 330 @@ -33,6 +34,15 @@ #define GLSL_VERSION 100 #endif +#define MAX_PARTICLES 1000 + +// Particle type +typedef struct Particle { + float x; + float y; + float period; +} Particle; + int main() { // Initialization @@ -42,32 +52,34 @@ int main() InitWindow(screenWidth, screenHeight, "raylib - point particles"); - Shader shader = LoadShader( - TextFormat("resources/shaders/glsl%i/point_particle.vs", GLSL_VERSION), - TextFormat("resources/shaders/glsl%i/point_particle.fs", GLSL_VERSION)); + Shader shader = LoadShader(TextFormat("resources/shaders/glsl%i/point_particle.vs", GLSL_VERSION), + TextFormat("resources/shaders/glsl%i/point_particle.fs", GLSL_VERSION)); + int currentTimeLoc = GetShaderLocation(shader, "currentTime"); int colorLoc = GetShaderLocation(shader, "color"); // Initialize the vertex buffer for the particles and assign each particle random values - struct { float x, y, period; } particles[10000]; - const size_t particleCount = sizeof(particles) / sizeof(particles[0]); - for (size_t i = 0; i < particleCount; i++) + Particle particles[MAX_PARTICLES] = { 0 }; + + for (int i = 0; i < MAX_PARTICLES; i++) { - particles[i].x = GetRandomValue(20, screenWidth - 20); - particles[i].y = GetRandomValue(50, screenHeight - 20); - // Give each particle a slightly different period. But don't spread it to much. This way the particles line up - // every so often and you get a glimps of what is going on. - particles[i].period = GetRandomValue(10, 30) / 10.0f; + particles[i].x = (float)GetRandomValue(20, screenWidth - 20); + particles[i].y = (float)GetRandomValue(50, screenHeight - 20); + + // Give each particle a slightly different period. But don't spread it to much. + // This way the particles line up every so often and you get a glimps of what is going on. + particles[i].period = (float)GetRandomValue(10, 30)/10.0f; } - // Create a plain OpenGL vertex buffer with the data and an vertex array object that feeds the data from the buffer - // into the vertexPosition shader attribute. - GLuint vao = 0, vbo = 0; + // Create a plain OpenGL vertex buffer with the data and an vertex array object + // that feeds the data from the buffer into the vertexPosition shader attribute. + GLuint vao = 0; + GLuint vbo = 0; glGenVertexArrays(1, &vao); glBindVertexArray(vao); glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); - glBufferData(GL_ARRAY_BUFFER, sizeof(particles), particles, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, MAX_PARTICLES*sizeof(Particle), particles, GL_STATIC_DRAW); // Note: LoadShader() automatically fetches the attribute index of "vertexPosition" and saves it in shader.locs[SHADER_LOC_VERTEX_POSITION] glVertexAttribPointer(shader.locs[SHADER_LOC_VERTEX_POSITION], 3, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(0); @@ -89,32 +101,33 @@ int main() ClearBackground(WHITE); DrawRectangle(10, 10, 210, 30, MAROON); - DrawText(TextFormat("%zu particles in one vertex buffer", particleCount), 20, 20, 10, RAYWHITE); + DrawText(TextFormat("%zu particles in one vertex buffer", MAX_PARTICLES), 20, 20, 10, RAYWHITE); + + rlDrawRenderBatchActive(); // Draw iternal buffers data (previous draw calls) // Switch to plain OpenGL //------------------------------------------------------------------------------ - // rlglDraw() in raylib 3.5 - rlDrawRenderBatchActive(); glUseProgram(shader.id); + glUniform1f(currentTimeLoc, GetTime()); Vector4 color = ColorNormalize((Color){ 255, 0, 0, 128 }); - glUniform4fv(colorLoc, 1, (float*)&color); + glUniform4fv(colorLoc, 1, (float *)&color); - // The the current model view projection matrix so the particle system is displayed and transformed - // (e.g. by cameras) just like everything else. - // GetMatrixModelview() and GetMatrixProjection() in raylib 3.5 + // Get the current modelview and projection matrix so the particle system is displayed and transformed Matrix modelViewProjection = MatrixMultiply(rlGetMatrixModelview(), rlGetMatrixProjection()); + glUniformMatrix4fv(shader.locs[SHADER_LOC_MATRIX_MVP], 1, false, MatrixToFloat(modelViewProjection)); glBindVertexArray(vao); - glDrawArrays(GL_POINTS, 0, particleCount); + glDrawArrays(GL_POINTS, 0, MAX_PARTICLES); glBindVertexArray(0); + glUseProgram(0); - - // And back to raylib again //------------------------------------------------------------------------------ + DrawFPS(screenWidth - 100, 10); + EndDrawing(); //---------------------------------------------------------------------------------- } @@ -124,8 +137,9 @@ int main() glDeleteBuffers(1, &vbo); glDeleteVertexArrays(1, &vao); - UnloadShader(shader); - CloseWindow(); // Close window and OpenGL context + UnloadShader(shader); // Unload shader + + CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; diff --git a/examples/others/opengl_interop.png b/examples/others/raylib_opengl_interop.png similarity index 100% rename from examples/others/opengl_interop.png rename to examples/others/raylib_opengl_interop.png diff --git a/examples/others/rlgl_standalone.c b/examples/others/rlgl_standalone.c index 0a5cb5096..cc0eda2db 100644 --- a/examples/others/rlgl_standalone.c +++ b/examples/others/rlgl_standalone.c @@ -2,18 +2,17 @@ * * raylib [rlgl] example - Using rlgl module as standalone module * -* NOTE: This example requires OpenGL 3.3 or ES2 versions for shaders support, +* rlgl library is an abstraction layer for multiple OpenGL versions (1.1, 2.1, 3.3 Core, ES 2.0) +* that provides a pseudo-OpenGL 1.1 immediate-mode style API (rlVertex, rlTranslate, rlRotate...) +* +* NOTE: This example requires OpenGL 3.3 or OpenGL ES 2.0 for shaders support, * OpenGL 1.1 does not support shaders but it can also be used. * * DEPENDENCIES: -* rlgl.h - OpenGL 1.1 immediate-mode style coding translation layer -* glad.h - OpenGL extensions initialization library (required by rlgl) -* raymath.h - 3D math library (required by rlgl) * glfw3 - Windows and context initialization library -* -* rlgl library is provided as a single-file header-only library, this library -* allows coding in a pseudo-OpenGL 1.1 style while translating calls to multiple -* OpenGL versions backends (1.1, 2.1, 3.3, ES 2.0). +* rlgl.h - OpenGL abstraction layer to OpenGL 1.1, 3.3 or ES2 +* glad.h - OpenGL extensions initialization library (required by rlgl) +* raymath.h - 3D math library * * WINDOWS COMPILATION: * gcc -o rlgl_standalone.exe rlgl_standalone.c -s -Iexternal\include -I..\..\src \ @@ -21,15 +20,16 @@ * * APPLE COMPILATION: * gcc -o rlgl_standalone rlgl_standalone.c -I../../src -Iexternal/include -Lexternal/lib \ -* -lglfw3 -std=c99 -framework CoreVideo -framework OpenGL -framework OpenAL \ -* -framework IOKit -framework Cocoa -Wno-deprecated-declarations +* -lglfw3 -framework CoreVideo -framework OpenGL -framework IOKit -framework Cocoa +* -Wno-deprecated-declarations -std=c99 -DGRAPHICS_API_OPENGL_33 +* * * LICENSE: zlib/libpng * * This example is licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software: * -* Copyright (c) 2014-2019 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2021 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. @@ -48,15 +48,25 @@ * ********************************************************************************************/ +// NOTE: rlgl can be configured just re-defining the following values: +//#define RL_DEFAULT_BATCH_BUFFER_ELEMENTS 8192 // Default internal render batch elements limits +//#define RL_DEFAULT_BATCH_BUFFERS 1 // Default number of batch buffers (multi-buffering) +//#define RL_DEFAULT_BATCH_DRAWCALLS 256 // Default number of batch draw calls (by state changes: mode, texture) +//#define RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS 4 // Maximum number of textures units that can be activated on batch drawing (SetShaderValueTexture()) +//#define RL_MAX_MATRIX_STACK_SIZE 32 // Maximum size of internal Matrix stack +//#define RL_MAX_SHADER_LOCATIONS 32 // Maximum number of shader locations supported +//#define RL_CULL_DISTANCE_NEAR 0.01 // Default projection matrix near cull distance +//#define RL_CULL_DISTANCE_FAR 1000.0 // Default projection matrix far cull distance + #define RLGL_IMPLEMENTATION -#define RLGL_STANDALONE -#define RLGL_SUPPORT_TRACELOG -#include "rlgl.h" // OpenGL 1.1 immediate-mode style coding +#include "rlgl.h" // OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2 + +#define RAYMATH_STATIC_INLINE +#include "raymath.h" // Vector2, Vector3, Quaternion and Matrix functionality #if defined(__EMSCRIPTEN__) #define GLFW_INCLUDE_ES2 #endif - #include "GLFW/glfw3.h" // Windows/Context and inputs management #include // Required for: printf() @@ -65,6 +75,9 @@ #define RAYWHITE (Color){ 245, 245, 245, 255 } // My own White (raylib logo) #define DARKGRAY (Color){ 80, 80, 80, 255 } // Dark Gray +//---------------------------------------------------------------------------------- +// Structures Definition +//---------------------------------------------------------------------------------- // Color, 4 components, R8G8B8A8 (32bit) typedef struct Color { unsigned char r; // Color red value @@ -94,6 +107,12 @@ static void DrawCube(Vector3 position, float width, float height, float length, static void DrawCubeWires(Vector3 position, float width, float height, float length, Color color); static void DrawRectangleV(Vector2 position, Vector2 size, Color color); +// NOTE: We use raymath to get this functionality but it could be implemented in this module +//static Matrix MatrixIdentity(void); +//static Matrix MatrixOrtho(double left, double right, double bottom, double top, double near, double far); +//static Matrix MatrixPerspective(double fovy, double aspect, double near, double far); +//static Matrix MatrixLookAt(Vector3 eye, Vector3 target, Vector3 up); + //---------------------------------------------------------------------------------- // Main Entry point //---------------------------------------------------------------------------------- @@ -125,7 +144,6 @@ int main(void) glfwWindowHint( GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE ); #endif - GLFWwindow *window = glfwCreateWindow(screenWidth, screenHeight, "rlgl standalone", NULL, NULL); if (!window) @@ -200,8 +218,8 @@ int main(void) // Draw '2D' elements in the scene (GUI) //----------------------------------------------- -#define RLGL_CREATE_MATRIX_MANUALLY -#if defined(RLGL_CREATE_MATRIX_MANUALLY) +#define RLGL_SET_MATRIX_MANUALLY +#if defined(RLGL_SET_MATRIX_MANUALLY) matProj = MatrixOrtho(0.0, screenWidth, screenHeight, 0.0, 0.0, 1.0); matView = MatrixIdentity(); @@ -218,7 +236,7 @@ int main(void) #endif DrawRectangleV((Vector2){ 10.0f, 10.0f }, (Vector2){ 780.0f, 20.0f }, DARKGRAY); - // Draw internal render batch buffers (3D data) + // Draw internal render batch buffers (2D data) rlDrawRenderBatchActive(); //----------------------------------------------- diff --git a/examples/physics/physics_demo.c b/examples/physics/physics_demo.c index fd4c1d25c..382a4ab37 100644 --- a/examples/physics/physics_demo.c +++ b/examples/physics/physics_demo.c @@ -14,7 +14,7 @@ #include "raylib.h" #define PHYSAC_IMPLEMENTATION -#include "physac.h" +#include "extras/physac.h" int main(void) { diff --git a/examples/physics/physics_friction.c b/examples/physics/physics_friction.c index d1ade9796..f50eb67f2 100644 --- a/examples/physics/physics_friction.c +++ b/examples/physics/physics_friction.c @@ -14,7 +14,7 @@ #include "raylib.h" #define PHYSAC_IMPLEMENTATION -#include "physac.h" +#include "extras/physac.h" int main(void) { diff --git a/examples/physics/physics_movement.c b/examples/physics/physics_movement.c index d6155da15..e13caec75 100644 --- a/examples/physics/physics_movement.c +++ b/examples/physics/physics_movement.c @@ -14,7 +14,7 @@ #include "raylib.h" #define PHYSAC_IMPLEMENTATION -#include "physac.h" +#include "extras/physac.h" #define VELOCITY 0.5f diff --git a/examples/physics/physics_restitution.c b/examples/physics/physics_restitution.c index 917ab8d09..91de5589f 100644 --- a/examples/physics/physics_restitution.c +++ b/examples/physics/physics_restitution.c @@ -14,7 +14,7 @@ #include "raylib.h" #define PHYSAC_IMPLEMENTATION -#include "physac.h" +#include "extras/physac.h" int main(void) { diff --git a/examples/physics/physics_shatter.c b/examples/physics/physics_shatter.c index 6c5bebfda..493443863 100644 --- a/examples/physics/physics_shatter.c +++ b/examples/physics/physics_shatter.c @@ -14,7 +14,7 @@ #include "raylib.h" #define PHYSAC_IMPLEMENTATION -#include "physac.h" +#include "extras/physac.h" int main(void) { diff --git a/examples/shaders/resources/LICENSE.md b/examples/shaders/resources/LICENSE.md index 96458eca5..b08a555ab 100644 --- a/examples/shaders/resources/LICENSE.md +++ b/examples/shaders/resources/LICENSE.md @@ -9,3 +9,5 @@ | raysan.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - | | space.png | ❔ | ❔ | - | | texel_checker.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | Made with [UV Checker Map Maker](http://uvchecker.byvalle.com/) | +| egg.png | [@GoldenThumbs](https://github.com/GoldenThumbs) | +| torus.png | [@GoldenThumbs](https://github.com/GoldenThumbs) | diff --git a/examples/shaders/resources/egg.png b/examples/shaders/resources/egg.png new file mode 100644 index 000000000..c85249523 Binary files /dev/null and b/examples/shaders/resources/egg.png differ diff --git a/examples/shaders/resources/shaders/glsl100/outline.fs b/examples/shaders/resources/shaders/glsl100/outline.fs new file mode 100644 index 000000000..67410b3a7 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl100/outline.fs @@ -0,0 +1,35 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; +uniform vec2 texScale; + +// Function for drawing outlines on alpha-blended textures +vec4 DrawOutline(sampler2D tex, vec2 uv, vec2 lineScale, vec3 lineCol) +{ + vec2 texelScale = 1.0 / lineScale; + vec4 center = texture2D(tex, uv); // We sample the center texel, (with all color data) + // Next we sample four corner texels, but only for the alpha channel (this is for the outline) + vec4 corners; + corners.x = texture2D(tex, uv+vec2( texelScale.x, texelScale.y)).a; + corners.y = texture2D(tex, uv+vec2( texelScale.x,-texelScale.y)).a; + corners.z = texture2D(tex, uv+vec2(-texelScale.x, texelScale.y)).a; + corners.w = texture2D(tex, uv+vec2(-texelScale.x,-texelScale.y)).a; + + float outline = min(dot(corners, vec4(1.0)), 1.0); + vec4 col = mix(vec4(0.0), vec4(lineCol, 1.0), outline); + col = mix(col, center, center.a); + return col; +} + +void main() +{ + gl_FragColor = DrawOutline(texture0, fragTexCoord, texScale, vec3(0.0)); +} \ No newline at end of file diff --git a/examples/shaders/resources/shaders/glsl330/outline.fs b/examples/shaders/resources/shaders/glsl330/outline.fs new file mode 100644 index 000000000..c1be1b5de --- /dev/null +++ b/examples/shaders/resources/shaders/glsl330/outline.fs @@ -0,0 +1,36 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; +uniform vec2 texScale; + +// Output fragment color +out vec4 finalColor; + +// Function for drawing outlines on alpha-blended textures +vec4 DrawOutline(sampler2D tex, vec2 uv, vec2 lineScale, vec3 lineCol) +{ + vec2 texelScale = 1.0 / lineScale; + vec4 center = texture(tex, uv); // We sample the center texel, (with all color data) + // Next we sample four corner texels, but only for the alpha channel (this is for the outline) + vec4 corners; + corners.x = texture(tex, uv+vec2( texelScale.x, texelScale.y)).a; + corners.y = texture(tex, uv+vec2( texelScale.x,-texelScale.y)).a; + corners.z = texture(tex, uv+vec2(-texelScale.x, texelScale.y)).a; + corners.w = texture(tex, uv+vec2(-texelScale.x,-texelScale.y)).a; + + float outline = min(dot(corners, vec4(1.0)), 1.0); + vec4 col = mix(vec4(0.0), vec4(lineCol, 1.0), outline); + col = mix(col, center, center.a); + return col; +} + +void main() +{ + finalColor = DrawOutline(texture0, fragTexCoord, texScale, vec3(0.0)); +} \ No newline at end of file diff --git a/examples/shaders/resources/torus.png b/examples/shaders/resources/torus.png new file mode 100644 index 000000000..399d78257 Binary files /dev/null and b/examples/shaders/resources/torus.png differ diff --git a/examples/shaders/shaders_hot_reloading.c b/examples/shaders/shaders_hot_reloading.c index 05da7b7ab..6f66f3613 100644 --- a/examples/shaders/shaders_hot_reloading.c +++ b/examples/shaders/shaders_hot_reloading.c @@ -77,7 +77,7 @@ int main(void) // Try reloading updated shader Shader updatedShader = LoadShader(0, TextFormat(fragShaderFileName, GLSL_VERSION)); - if (updatedShader.id != rlGetShaderDefault().id) // It was correctly loaded + if (updatedShader.id != rlGetShaderIdDefault()) // It was correctly loaded { UnloadShader(shader); shader = updatedShader; diff --git a/examples/shaders/shaders_shapes_outline.c b/examples/shaders/shaders_shapes_outline.c new file mode 100644 index 000000000..d70f7645d --- /dev/null +++ b/examples/shaders/shaders_shapes_outline.c @@ -0,0 +1,84 @@ +/******************************************************************************************* +* +* raylib [shaders] example - Apply an shdrOutline to a texture +* +* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, +* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. +* +* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3). +* +* This example has been created using raylib 3.8 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Example contributed by Samuel Skiff (@GoldenThumbs) +* +* Copyright (c) 2021 Samuel SKiff (@GoldenThumbs) and Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#if defined(PLATFORM_DESKTOP) + #define GLSL_VERSION 330 +#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB + #define GLSL_VERSION 100 +#endif + +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [shaders] example - Apply an shdrOutline to a texture"); + + Texture2D egg = LoadTexture("resources/egg.png"); + Texture2D torus = LoadTexture("resources/torus.png"); + Shader shdrOutline = LoadShader(0, TextFormat("resources/shaders/glsl%i/shdrOutline.fs", GLSL_VERSION)); + + float outlineScale = 16.0f; + float textureScale[2] = { 16.0f*4, 16.0f*4 }; + SetShaderValue(shdrOutline, GetShaderLocation(shdrOutline, "texScale"), textureScale, SHADER_UNIFORM_VEC2); + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + // TODO: Update your variables here + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + BeginShaderMode(shdrOutline); + DrawTextureEx(egg, (Vector2){ 0, 230 }, 0.0, outlineScale, WHITE); + DrawTextureEx(torus, (Vector2){ 544, 230 }, 0.0, outlineScale, WHITE); + EndShaderMode(); + + DrawText("Shader-based shdrOutlines for textures", 190, 200, 20, LIGHTGRAY); + + DrawFPS(710, 10); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadTexture(egg); + UnloadTexture(torus); + UnloadShader(shdrOutline); + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} \ No newline at end of file diff --git a/examples/shapes/easings.h b/examples/shapes/easings.h deleted file mode 100644 index 892ce3525..000000000 --- a/examples/shapes/easings.h +++ /dev/null @@ -1,263 +0,0 @@ -/******************************************************************************************* -* -* raylib easings (header only file) -* -* Useful easing functions for values animation -* -* This header uses: -* #define EASINGS_STATIC_INLINE // Inlines all functions code, so it runs faster. -* // This requires lots of memory on system. -* How to use: -* The four inputs t,b,c,d are defined as follows: -* t = current time (in any unit measure, but same unit as duration) -* b = starting value to interpolate -* c = the total change in value of b that needs to occur -* d = total time it should take to complete (duration) -* -* Example: -* -* int currentTime = 0; -* int duration = 100; -* float startPositionX = 0.0f; -* float finalPositionX = 30.0f; -* float currentPositionX = startPositionX; -* -* while (currentPositionX < finalPositionX) -* { -* currentPositionX = EaseSineIn(currentTime, startPositionX, finalPositionX - startPositionX, duration); -* currentTime++; -* } -* -* A port of Robert Penner's easing equations to C (http://robertpenner.com/easing/) -* -* Robert Penner License -* --------------------------------------------------------------------------------- -* Open source under the BSD License. -* -* Copyright (c) 2001 Robert Penner. All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, -* are permitted provided that the following conditions are met: -* -* - Redistributions of source code must retain the above copyright notice, -* this list of conditions and the following disclaimer. -* - Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* - Neither the name of the author nor the names of contributors may be used -* to endorse or promote products derived from this software without specific -* prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -* IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED -* OF THE POSSIBILITY OF SUCH DAMAGE. -* --------------------------------------------------------------------------------- -* -* Copyright (c) 2015 Ramon Santamaria -* -* This software is provided "as-is", without any express or implied warranty. In no event -* will the authors be held liable for any damages arising from the use of this software. -* -* Permission is granted to anyone to use this software for any purpose, including commercial -* applications, and to alter it and redistribute it freely, subject to the following restrictions: -* -* 1. The origin of this software must not be misrepresented; you must not claim that you -* wrote the original software. If you use this software in a product, an acknowledgment -* in the product documentation would be appreciated but is not required. -* -* 2. Altered source versions must be plainly marked as such, and must not be misrepresented -* as being the original software. -* -* 3. This notice may not be removed or altered from any source distribution. -* -**********************************************************************************************/ - -#ifndef EASINGS_H -#define EASINGS_H - -#define EASINGS_STATIC_INLINE // NOTE: By default, compile functions as static inline - -#if defined(EASINGS_STATIC_INLINE) - #define EASEDEF static inline -#else - #define EASEDEF extern -#endif - -#include // Required for: sin(), cos(), sqrt(), pow() - -#ifndef PI - #define PI 3.14159265358979323846f //Required as PI is not always defined in math.h -#endif - -#ifdef __cplusplus -extern "C" { // Prevents name mangling of functions -#endif - -// Linear Easing functions -EASEDEF float EaseLinearNone(float t, float b, float c, float d) { return (c*t/d + b); } -EASEDEF float EaseLinearIn(float t, float b, float c, float d) { return (c*t/d + b); } -EASEDEF float EaseLinearOut(float t, float b, float c, float d) { return (c*t/d + b); } -EASEDEF float EaseLinearInOut(float t,float b, float c, float d) { return (c*t/d + b); } - -// Sine Easing functions -EASEDEF float EaseSineIn(float t, float b, float c, float d) { return (-c*cos(t/d*(PI/2)) + c + b); } -EASEDEF float EaseSineOut(float t, float b, float c, float d) { return (c*sin(t/d*(PI/2)) + b); } -EASEDEF float EaseSineInOut(float t, float b, float c, float d) { return (-c/2*(cos(PI*t/d) - 1) + b); } - -// Circular Easing functions -EASEDEF float EaseCircIn(float t, float b, float c, float d) { t /= d; return (-c*(sqrt(1 - t*t) - 1) + b); } -EASEDEF float EaseCircOut(float t, float b, float c, float d) { t = t/d - 1; return (c*sqrt(1 - t*t) + b); } -EASEDEF float EaseCircInOut(float t, float b, float c, float d) -{ - if ((t/=d/2) < 1) return (-c/2*(sqrt(1 - t*t) - 1) + b); - t -= 2; return (c/2*(sqrt(1 - t*t) + 1) + b); -} - -// Cubic Easing functions -EASEDEF float EaseCubicIn(float t, float b, float c, float d) { t /= d; return (c*t*t*t + b); } -EASEDEF float EaseCubicOut(float t, float b, float c, float d) { t = t/d-1; return (c*(t*t*t + 1) + b); } -EASEDEF float EaseCubicInOut(float t, float b, float c, float d) -{ - if ((t/=d/2) < 1) return (c/2*t*t*t + b); - t -= 2; return (c/2*(t*t*t + 2) + b); -} - -// Quadratic Easing functions -EASEDEF float EaseQuadIn(float t, float b, float c, float d) { t /= d; return (c*t*t + b); } -EASEDEF float EaseQuadOut(float t, float b, float c, float d) { t /= d; return (-c*t*(t - 2) + b); } -EASEDEF float EaseQuadInOut(float t, float b, float c, float d) -{ - if ((t/=d/2) < 1) return (((c/2)*(t*t)) + b); - t--; return (-c/2*(((t - 2)*t) - 1) + b); -} - -// Exponential Easing functions -EASEDEF float EaseExpoIn(float t, float b, float c, float d) { return (t == 0) ? b : (c*pow(2, 10*(t/d - 1)) + b); } -EASEDEF float EaseExpoOut(float t, float b, float c, float d) { return (t == d) ? (b + c) : (c*(-pow(2, -10*t/d) + 1) + b); } -EASEDEF float EaseExpoInOut(float t, float b, float c, float d) -{ - if (t == 0) return b; - if (t == d) return (b + c); - if ((t/=d/2) < 1) return (c/2*pow(2, 10*(t - 1)) + b); - - return (c/2*(-pow(2, -10*--t) + 2) + b); -} - -// Back Easing functions -EASEDEF float EaseBackIn(float t, float b, float c, float d) -{ - float s = 1.70158f; - float postFix = t/=d; - return (c*(postFix)*t*((s + 1)*t - s) + b); -} - -EASEDEF float EaseBackOut(float t, float b, float c, float d) -{ - float s = 1.70158f; - t = t/d - 1; - return (c*(t*t*((s + 1)*t + s) + 1) + b); -} - -EASEDEF float EaseBackInOut(float t, float b, float c, float d) -{ - float s = 1.70158f; - if ((t/=d/2) < 1) - { - s *= 1.525f; - return (c/2*(t*t*((s + 1)*t - s)) + b); - } - - float postFix = t-=2; - s *= 1.525f; - return (c/2*((postFix)*t*((s + 1)*t + s) + 2) + b); -} - -// Bounce Easing functions -EASEDEF float EaseBounceOut(float t, float b, float c, float d) -{ - if ((t/=d) < (1/2.75f)) - { - return (c*(7.5625f*t*t) + b); - } - else if (t < (2/2.75f)) - { - float postFix = t-=(1.5f/2.75f); - return (c*(7.5625f*(postFix)*t + 0.75f) + b); - } - else if (t < (2.5/2.75)) - { - float postFix = t-=(2.25f/2.75f); - return (c*(7.5625f*(postFix)*t + 0.9375f) + b); - } - else - { - float postFix = t-=(2.625f/2.75f); - return (c*(7.5625f*(postFix)*t + 0.984375f) + b); - } -} - -EASEDEF float EaseBounceIn(float t, float b, float c, float d) { return (c - EaseBounceOut(d-t, 0, c, d) + b); } -EASEDEF float EaseBounceInOut(float t, float b, float c, float d) -{ - if (t < d/2) return (EaseBounceIn(t*2, 0, c, d)*0.5f + b); - else return (EaseBounceOut(t*2-d, 0, c, d)*0.5f + c*0.5f + b); -} - -// Elastic Easing functions -EASEDEF float EaseElasticIn(float t, float b, float c, float d) -{ - if (t == 0) return b; - if ((t/=d) == 1) return (b + c); - - float p = d*0.3f; - float a = c; - float s = p/4; - float postFix = a*pow(2, 10*(t-=1)); - - return (-(postFix*sin((t*d-s)*(2*PI)/p )) + b); -} - -EASEDEF float EaseElasticOut(float t, float b, float c, float d) -{ - if (t == 0) return b; - if ((t/=d) == 1) return (b + c); - - float p = d*0.3f; - float a = c; - float s = p/4; - - return (a*pow(2,-10*t)*sin((t*d-s)*(2*PI)/p) + c + b); -} - -EASEDEF float EaseElasticInOut(float t, float b, float c, float d) -{ - if (t == 0) return b; - if ((t/=d/2) == 2) return (b + c); - - float p = d*(0.3f*1.5f); - float a = c; - float s = p/4; - - if (t < 1) - { - float postFix = a*pow(2, 10*(t-=1)); - return -0.5f*(postFix*sin((t*d-s)*(2*PI)/p)) + b; - } - - float postFix = a*pow(2, -10*(t-=1)); - - return (postFix*sin((t*d-s)*(2*PI)/p)*0.5f + c + b); -} - -#ifdef __cplusplus -} -#endif - -#endif // EASINGS_H diff --git a/examples/shapes/shapes_draw_circle_sector.c b/examples/shapes/shapes_draw_circle_sector.c index 009288df6..787b1d4a6 100644 --- a/examples/shapes/shapes_draw_circle_sector.c +++ b/examples/shapes/shapes_draw_circle_sector.c @@ -14,7 +14,7 @@ #include #define RAYGUI_IMPLEMENTATION -#include "raygui.h" // Required for GUI controls +#include "extras/raygui.h" // Required for GUI controls int main(void) { diff --git a/examples/shapes/shapes_draw_rectangle_rounded.c b/examples/shapes/shapes_draw_rectangle_rounded.c index b76e1264d..cc3649806 100644 --- a/examples/shapes/shapes_draw_rectangle_rounded.c +++ b/examples/shapes/shapes_draw_rectangle_rounded.c @@ -14,7 +14,7 @@ #include #define RAYGUI_IMPLEMENTATION -#include "raygui.h" // Required for GUI controls +#include "extras/raygui.h" // Required for GUI controls int main(void) { diff --git a/examples/shapes/shapes_draw_ring.c b/examples/shapes/shapes_draw_ring.c index b60ed2b7e..cd4c1f090 100644 --- a/examples/shapes/shapes_draw_ring.c +++ b/examples/shapes/shapes_draw_ring.c @@ -14,7 +14,7 @@ #include #define RAYGUI_IMPLEMENTATION -#include "raygui.h" // Required for GUI controls +#include "extras/raygui.h" // Required for GUI controls int main(void) { diff --git a/examples/shapes/shapes_easings_ball_anim.c b/examples/shapes/shapes_easings_ball_anim.c index 5bb2b4c66..579d04dd6 100644 --- a/examples/shapes/shapes_easings_ball_anim.c +++ b/examples/shapes/shapes_easings_ball_anim.c @@ -11,7 +11,7 @@ #include "raylib.h" -#include "easings.h" // Required for easing functions +#include "extras/easings.h" // Required for easing functions int main(void) { diff --git a/examples/shapes/shapes_easings_box_anim.c b/examples/shapes/shapes_easings_box_anim.c index 6805d5310..7812bd535 100644 --- a/examples/shapes/shapes_easings_box_anim.c +++ b/examples/shapes/shapes_easings_box_anim.c @@ -11,7 +11,7 @@ #include "raylib.h" -#include "easings.h" // Required for easing functions +#include "extras/easings.h" // Required for easing functions int main(void) { diff --git a/examples/shapes/shapes_easings_rectangle_array.c b/examples/shapes/shapes_easings_rectangle_array.c index 07de98a05..eb782cd1b 100644 --- a/examples/shapes/shapes_easings_rectangle_array.c +++ b/examples/shapes/shapes_easings_rectangle_array.c @@ -14,7 +14,7 @@ #include "raylib.h" -#include "easings.h" // Required for easing functions +#include "extras/easings.h" // Required for easing functions #define RECS_WIDTH 50 #define RECS_HEIGHT 50 diff --git a/examples/shapes/shapes_logo_raylib_anim.c b/examples/shapes/shapes_logo_raylib_anim.c index fe5eeffb4..f91b6c7d3 100644 --- a/examples/shapes/shapes_logo_raylib_anim.c +++ b/examples/shapes/shapes_logo_raylib_anim.c @@ -138,9 +138,9 @@ int main(void) DrawRectangle(logoPositionX + 240, logoPositionY + 16, 16, rightSideRecHeight - 32, Fade(BLACK, alpha)); DrawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, Fade(BLACK, alpha)); - DrawRectangle(screenWidth/2 - 112, screenHeight/2 - 112, 224, 224, Fade(RAYWHITE, alpha)); + DrawRectangle(GetScreenWidth()/2 - 112, GetScreenHeight()/2 - 112, 224, 224, Fade(RAYWHITE, alpha)); - DrawText(TextSubtext("raylib", 0, lettersCount), screenWidth/2 - 44, screenHeight/2 + 48, 50, Fade(BLACK, alpha)); + DrawText(TextSubtext("raylib", 0, lettersCount), GetScreenWidth()/2 - 44, GetScreenHeight()/2 + 48, 50, Fade(BLACK, alpha)); } else if (state == 4) { diff --git a/examples/text/text_draw_3d.c b/examples/text/text_draw_3d.c index 8ce576b6b..04b6e18ca 100644 --- a/examples/text/text_draw_3d.c +++ b/examples/text/text_draw_3d.c @@ -5,14 +5,14 @@ * Draw a 2D text in 3D space, each letter is drawn in a quad (or 2 quads if backface is set) * where the texture coodinates of each quad map to the texture coordinates of the glyphs * inside the font texture. -* A more efficient approach, i believe, would be to render the text in a render texture and -* map that texture to a plane and render that, or maybe a shader but my method allows more -* flexibility...for example to change position of each letter individually to make somethink -* like a wavy text effect. -* -* Special thanks to: -* @Nighten for the DrawTextStyle() code https://github.com/NightenDushi/Raylib_DrawTextStyle -* Chris Camacho (codifies - http://bedroomcoders.co.uk/) for the alpha discard shader +* A more efficient approach, i believe, would be to render the text in a render texture and +* map that texture to a plane and render that, or maybe a shader but my method allows more +* flexibility...for example to change position of each letter individually to make somethink +* like a wavy text effect. +* +* Special thanks to: +* @Nighten for the DrawTextStyle() code https://github.com/NightenDushi/Raylib_DrawTextStyle +* Chris Camacho (codifies - http://bedroomcoders.co.uk/) for the alpha discard shader * * This example has been created using raylib 3.5 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) @@ -196,7 +196,7 @@ int main(void) (Vector3){ cubePosition.x + cubeSize.x/2, cubePosition.y + cubeSize.y/2, cubePosition.z + cubeSize.z/2 }}); if (collision.hit) { - // Generate new random colors + // Generate new random colors light = GenerateRandomColor(0.5f, 0.78f); dark = GenerateRandomColor(0.4f, 0.58f); } diff --git a/examples/text/text_rectangle_bounds.c b/examples/text/text_rectangle_bounds.c index 9754cd456..c763fb2ec 100644 --- a/examples/text/text_rectangle_bounds.c +++ b/examples/text/text_rectangle_bounds.c @@ -13,6 +13,10 @@ #include "raylib.h" +static void DrawTextRec(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint); // Draw text using font inside rectangle limits +static void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint, int selectStart, int selectLength, Color selectTint, Color selectBackTint); // Draw text using font inside rectangle limits with support for text selection + +// Main entry point int main(void) { // Initialization @@ -119,4 +123,144 @@ tempor incididunt ut labore et dolore magna aliqua. Nec ullamcorper sit amet ris //-------------------------------------------------------------------------------------- return 0; +} + +//-------------------------------------------------------------------------------------- +// Module functions definition +//-------------------------------------------------------------------------------------- + +// Draw text using font inside rectangle limits +static void DrawTextRec(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint) +{ + DrawTextRecEx(font, text, rec, fontSize, spacing, wordWrap, tint, 0, 0, WHITE, WHITE); +} + +// Draw text using font inside rectangle limits with support for text selection +static void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint, int selectStart, int selectLength, Color selectTint, Color selectBackTint) +{ + int length = TextLength(text); // Total length in bytes of the text, scanned by codepoints in loop + + float textOffsetY = 0; // Offset between lines (on line break '\n') + float textOffsetX = 0.0f; // Offset X to next character to draw + + float scaleFactor = fontSize/(float)font.baseSize; // Character rectangle scaling factor + + // Word/character wrapping mechanism variables + enum { MEASURE_STATE = 0, DRAW_STATE = 1 }; + int state = wordWrap? MEASURE_STATE : DRAW_STATE; + + int startLine = -1; // Index where to begin drawing (where a line begins) + int endLine = -1; // Index where to stop drawing (where a line ends) + int lastk = -1; // Holds last value of the character position + + for (int i = 0, k = 0; i < length; i++, k++) + { + // Get next codepoint from byte string and glyph index in font + int codepointByteCount = 0; + int codepoint = GetCodepoint(&text[i], &codepointByteCount); + int index = GetGlyphIndex(font, codepoint); + + // NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f) + // but we need to draw all of the bad bytes using the '?' symbol moving one byte + if (codepoint == 0x3f) codepointByteCount = 1; + i += (codepointByteCount - 1); + + float glyphWidth = 0; + if (codepoint != '\n') + { + glyphWidth = (font.chars[index].advanceX == 0) ? font.recs[index].width*scaleFactor : font.chars[index].advanceX*scaleFactor; + + if (i + 1 < length) glyphWidth = glyphWidth + spacing; + } + + // NOTE: When wordWrap is ON we first measure how much of the text we can draw before going outside of the rec container + // We store this info in startLine and endLine, then we change states, draw the text between those two variables + // and change states again and again recursively until the end of the text (or until we get outside of the container). + // When wordWrap is OFF we don't need the measure state so we go to the drawing state immediately + // and begin drawing on the next line before we can get outside the container. + if (state == MEASURE_STATE) + { + // TODO: There are multiple types of spaces in UNICODE, maybe it's a good idea to add support for more + // Ref: http://jkorpela.fi/chars/spaces.html + if ((codepoint == ' ') || (codepoint == '\t') || (codepoint == '\n')) endLine = i; + + if ((textOffsetX + glyphWidth) > rec.width) + { + endLine = (endLine < 1)? i : endLine; + if (i == endLine) endLine -= codepointByteCount; + if ((startLine + codepointByteCount) == endLine) endLine = (i - codepointByteCount); + + state = !state; + } + else if ((i + 1) == length) + { + endLine = i; + state = !state; + } + else if (codepoint == '\n') state = !state; + + if (state == DRAW_STATE) + { + textOffsetX = 0; + i = startLine; + glyphWidth = 0; + + // Save character position when we switch states + int tmp = lastk; + lastk = k - 1; + k = tmp; + } + } + else + { + if (codepoint == '\n') + { + if (!wordWrap) + { + textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor; + textOffsetX = 0; + } + } + else + { + if (!wordWrap && ((textOffsetX + glyphWidth) > rec.width)) + { + textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor; + textOffsetX = 0; + } + + // When text overflows rectangle height limit, just stop drawing + if ((textOffsetY + font.baseSize*scaleFactor) > rec.height) break; + + // Draw selection background + bool isGlyphSelected = false; + if ((selectStart >= 0) && (k >= selectStart) && (k < (selectStart + selectLength))) + { + DrawRectangleRec((Rectangle){ rec.x + textOffsetX - 1, rec.y + textOffsetY, glyphWidth, (float)font.baseSize*scaleFactor }, selectBackTint); + isGlyphSelected = true; + } + + // Draw current character glyph + if ((codepoint != ' ') && (codepoint != '\t')) + { + DrawTextCodepoint(font, codepoint, (Vector2){ rec.x + textOffsetX, rec.y + textOffsetY }, fontSize, isGlyphSelected? selectTint : tint); + } + } + + if (wordWrap && (i == endLine)) + { + textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor; + textOffsetX = 0; + startLine = endLine; + endLine = -1; + glyphWidth = 0; + selectStart += lastk - k; + k = lastk; + + state = !state; + } + } + + textOffsetX += glyphWidth; + } } \ No newline at end of file diff --git a/examples/text/text_unicode.c b/examples/text/text_unicode.c index fa336de7f..2954a28e1 100644 --- a/examples/text/text_unicode.c +++ b/examples/text/text_unicode.c @@ -133,6 +133,9 @@ struct { //-------------------------------------------------------------------------------------- static void RandomizeEmoji(void); // Fills the emoji array with random emojis +static void DrawTextRec(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint); // Draw text using font inside rectangle limits +static void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint, int selectStart, int selectLength, Color selectTint, Color selectBackTint); // Draw text using font inside rectangle limits with support for text selection + //-------------------------------------------------------------------------------------- // Global variables //-------------------------------------------------------------------------------------- @@ -145,6 +148,9 @@ struct { static int hovered = -1, selected = -1; +//-------------------------------------------------------------------------------------- +// Main entry point +//-------------------------------------------------------------------------------------- int main(int argc, char **argv) { // Initialization @@ -317,3 +323,143 @@ static void RandomizeEmoji(void) emoji[i].message = GetRandomValue(0, SIZEOF(messages) - 1); } } + +//-------------------------------------------------------------------------------------- +// Module functions definition +//-------------------------------------------------------------------------------------- + +// Draw text using font inside rectangle limits +static void DrawTextRec(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint) +{ + DrawTextRecEx(font, text, rec, fontSize, spacing, wordWrap, tint, 0, 0, WHITE, WHITE); +} + +// Draw text using font inside rectangle limits with support for text selection +static void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint, int selectStart, int selectLength, Color selectTint, Color selectBackTint) +{ + int length = TextLength(text); // Total length in bytes of the text, scanned by codepoints in loop + + float textOffsetY = 0; // Offset between lines (on line break '\n') + float textOffsetX = 0.0f; // Offset X to next character to draw + + float scaleFactor = fontSize/(float)font.baseSize; // Character rectangle scaling factor + + // Word/character wrapping mechanism variables + enum { MEASURE_STATE = 0, DRAW_STATE = 1 }; + int state = wordWrap? MEASURE_STATE : DRAW_STATE; + + int startLine = -1; // Index where to begin drawing (where a line begins) + int endLine = -1; // Index where to stop drawing (where a line ends) + int lastk = -1; // Holds last value of the character position + + for (int i = 0, k = 0; i < length; i++, k++) + { + // Get next codepoint from byte string and glyph index in font + int codepointByteCount = 0; + int codepoint = GetCodepoint(&text[i], &codepointByteCount); + int index = GetGlyphIndex(font, codepoint); + + // NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f) + // but we need to draw all of the bad bytes using the '?' symbol moving one byte + if (codepoint == 0x3f) codepointByteCount = 1; + i += (codepointByteCount - 1); + + float glyphWidth = 0; + if (codepoint != '\n') + { + glyphWidth = (font.chars[index].advanceX == 0) ? font.recs[index].width*scaleFactor : font.chars[index].advanceX*scaleFactor; + + if (i + 1 < length) glyphWidth = glyphWidth + spacing; + } + + // NOTE: When wordWrap is ON we first measure how much of the text we can draw before going outside of the rec container + // We store this info in startLine and endLine, then we change states, draw the text between those two variables + // and change states again and again recursively until the end of the text (or until we get outside of the container). + // When wordWrap is OFF we don't need the measure state so we go to the drawing state immediately + // and begin drawing on the next line before we can get outside the container. + if (state == MEASURE_STATE) + { + // TODO: There are multiple types of spaces in UNICODE, maybe it's a good idea to add support for more + // Ref: http://jkorpela.fi/chars/spaces.html + if ((codepoint == ' ') || (codepoint == '\t') || (codepoint == '\n')) endLine = i; + + if ((textOffsetX + glyphWidth) > rec.width) + { + endLine = (endLine < 1)? i : endLine; + if (i == endLine) endLine -= codepointByteCount; + if ((startLine + codepointByteCount) == endLine) endLine = (i - codepointByteCount); + + state = !state; + } + else if ((i + 1) == length) + { + endLine = i; + state = !state; + } + else if (codepoint == '\n') state = !state; + + if (state == DRAW_STATE) + { + textOffsetX = 0; + i = startLine; + glyphWidth = 0; + + // Save character position when we switch states + int tmp = lastk; + lastk = k - 1; + k = tmp; + } + } + else + { + if (codepoint == '\n') + { + if (!wordWrap) + { + textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor; + textOffsetX = 0; + } + } + else + { + if (!wordWrap && ((textOffsetX + glyphWidth) > rec.width)) + { + textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor; + textOffsetX = 0; + } + + // When text overflows rectangle height limit, just stop drawing + if ((textOffsetY + font.baseSize*scaleFactor) > rec.height) break; + + // Draw selection background + bool isGlyphSelected = false; + if ((selectStart >= 0) && (k >= selectStart) && (k < (selectStart + selectLength))) + { + DrawRectangleRec((Rectangle){ rec.x + textOffsetX - 1, rec.y + textOffsetY, glyphWidth, (float)font.baseSize*scaleFactor }, selectBackTint); + isGlyphSelected = true; + } + + // Draw current character glyph + if ((codepoint != ' ') && (codepoint != '\t')) + { + DrawTextCodepoint(font, codepoint, (Vector2){ rec.x + textOffsetX, rec.y + textOffsetY }, fontSize, isGlyphSelected? selectTint : tint); + } + } + + if (wordWrap && (i == endLine)) + { + textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor; + textOffsetX = 0; + startLine = endLine; + endLine = -1; + glyphWidth = 0; + selectStart += lastk - k; + k = lastk; + + state = !state; + } + } + + textOffsetX += glyphWidth; + } +} \ No newline at end of file diff --git a/parser/raylib_parser.c b/parser/raylib_parser.c index 4720af912..3e5db1ae2 100644 --- a/parser/raylib_parser.c +++ b/parser/raylib_parser.c @@ -70,6 +70,10 @@ #define MAX_LINE_LENGTH 512 // Maximum length of one line (including comments) #define MAX_STRUCT_LINE_LENGTH 2048 // Maximum length of one struct (multiple lines) +#define MAX_FUNCTION_PARAMETERS 12 // Maximum number of function parameters +#define MAX_STRUCT_FIELDS 32 // Maximum number of struct fields +#define MAX_ENUM_VALUES 512 // Maximum number of enum values + //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- @@ -79,9 +83,9 @@ typedef struct FunctionInfo { char desc[128]; // Function description (comment at the end) char retType[32]; // Return value type int paramCount; // Number of function parameters - char paramType[12][32]; // Parameters type (max: 12 parameters) - char paramName[12][32]; // Parameters name (max: 12 parameters) - char paramDesc[12][8]; // Parameters description (max: 12 parameters) + char paramType[MAX_FUNCTION_PARAMETERS][32]; // Parameters type + char paramName[MAX_FUNCTION_PARAMETERS][32]; // Parameters name + char paramDesc[MAX_FUNCTION_PARAMETERS][8]; // Parameters description } FunctionInfo; // Struct info data @@ -89,9 +93,9 @@ typedef struct StructInfo { char name[64]; // Struct name char desc[64]; // Struct type description int fieldCount; // Number of fields in the struct - char fieldType[16][32]; // Field type (max: 16 fields) - char fieldName[16][32]; // Field name (max: 16 fields) - char fieldDesc[16][128]; // Field description (max: 16 fields) + char fieldType[MAX_STRUCT_FIELDS][64]; // Field type + char fieldName[MAX_STRUCT_FIELDS][64]; // Field name + char fieldDesc[MAX_STRUCT_FIELDS][128]; // Field description } StructInfo; // Enum info data @@ -99,9 +103,9 @@ typedef struct EnumInfo { char name[64]; // Enum name char desc[64]; // Enum description int valueCount; // Number of values in enumerator - char valueName[128][64]; // Value name definition (max: 128 values) - int valueInteger[128]; // Value integer (max: 128 values) - char valueDesc[128][64]; // Value description (max: 128 values) + char valueName[MAX_ENUM_VALUES][64]; // Value name definition + int valueInteger[MAX_ENUM_VALUES]; // Value integer + char valueDesc[MAX_ENUM_VALUES][64]; // Value description } EnumInfo; // Output format for parsed data @@ -116,6 +120,7 @@ static int enumCount = 0; static FunctionInfo *funcs = NULL; static StructInfo *structs = NULL; static EnumInfo *enums = NULL; +static char apiDefine[32] = "RLAPI\0"; // Command line variables static char inFileName[512] = { 0 }; // Input file name (required in case of provided through CLI) @@ -171,8 +176,8 @@ int main(int argc, char* argv[]) // Read function lines for (int i = 0; i < linesCount; i++) { - // Read function line (starting with "RLAPI") - if (IsTextEqual(lines[i], "RLAPI", 5)) + // Read function line (starting with `define`, i.e. for raylib.h "RLAPI") + if (IsTextEqual(lines[i], apiDefine, TextLength(apiDefine))) { // Keep a pointer to the function line funcLines[funcCount] = lines[i]; @@ -217,12 +222,6 @@ int main(int argc, char* argv[]) j++; } - while (buffer[i + j] != '}') - { - structLines[structCount][j] = buffer[i + j]; - j++; - } - while (buffer[i + j] != '\n') { structLines[structCount][j] = buffer[i + j]; @@ -238,7 +237,7 @@ int main(int argc, char* argv[]) // Read enum lines for (int i = 0; i < linesCount; i++) { - // Read function line (starting with "RLAPI") + // Read enum line if (IsTextEqual(lines[i], "typedef enum {", 14)) { // Keep the line position in the array of lines, @@ -335,7 +334,7 @@ int main(int argc, char* argv[]) { // TODO: Get enum description from lines[enumLines[i] - 1] - for (int j = 1; j < 256; j++) // Maximum number of lines following enum first line + for (int j = 1; j < MAX_ENUM_VALUES*2; j++) // Maximum number of lines following enum first line { char *linePtr = lines[enumLines[i] + j]; @@ -428,8 +427,9 @@ int main(int argc, char* argv[]) // At this point we have function return type and function name char funcRetTypeName[128] = { 0 }; - int funcRetTypeNameLen = c - 6; // Substract "RLAPI " - MemoryCopy(funcRetTypeName, &funcLines[i][6], funcRetTypeNameLen); + int dc = TextLength(apiDefine) + 1; + int funcRetTypeNameLen = c - dc; // Substract `define` ("RLAPI " for raylib.h) + MemoryCopy(funcRetTypeName, &funcLines[i][dc], funcRetTypeNameLen); GetDataTypeAndName(funcRetTypeName, funcRetTypeNameLen, funcs[i].retType, funcs[i].name); break; @@ -525,7 +525,7 @@ static void ShowCommandLineInfo(void) printf("//////////////////////////////////////////////////////////////////////////////////\n\n"); printf("USAGE:\n\n"); - printf(" > raylib_parser [--help] [--input ] [--output ] [--format ]\n"); + printf(" > raylib_parser [--help] [--input ] [--output ] [--format ] [--define ]\n"); printf("\nOPTIONS:\n\n"); printf(" -h, --help : Show tool version and command line usage help\n\n"); @@ -536,12 +536,16 @@ static void ShowCommandLineInfo(void) printf(" NOTE: If not specified, defaults to: raylib_api.txt\n\n"); printf(" -f, --format : Define output format for parser data.\n"); printf(" Supported types: DEFAULT, JSON, XML\n\n"); + printf(" -d, --define : Define functions define (i.e. RLAPI for raylib.h, RMDEF for raymath.h, etc\n"); + printf(" NOTE: If not specified, defaults to: RLAPI\n\n"); printf("\nEXAMPLES:\n\n"); printf(" > raylib_parser --input raylib.h --output api.json\n"); printf(" Process to generate \n\n"); printf(" > raylib_parser --output raylib_data.info --format XML\n"); printf(" Process to generate as XML text data\n\n"); + printf(" > raylib_parser --input raymath.h --output raymath_data.info --format XML\n"); + printf(" Process to generate as XML text data\n\n"); } // Process command line arguments @@ -583,6 +587,16 @@ static void ProcessCommandLine(int argc, char *argv[]) } else printf("WARNING: No format parameters provided\n"); } + else if (IsTextEqual(argv[i], "-d", 2) || IsTextEqual(argv[i], "--define", 8)) + { + if (((i + 1) < argc) && (argv[i + 1][0] != '-')) + { + MemoryCopy(apiDefine, argv[i + 1], TextLength(argv[i + 1])); // Read functions define + apiDefine[TextLength(argv[i + 1])] = '\0'; + i++; + } + else printf("WARNING: No define key provided\n"); + } } } diff --git a/projects/VS2019/raylib/raylib.vcxproj b/projects/VS2019/raylib/raylib.vcxproj index d31d48022..7e3e99d65 100644 --- a/projects/VS2019/raylib/raylib.vcxproj +++ b/projects/VS2019/raylib/raylib.vcxproj @@ -313,6 +313,7 @@ + diff --git a/src/config.h b/src/config.h index 4a74655ce..b7358d7e7 100644 --- a/src/config.h +++ b/src/config.h @@ -87,41 +87,36 @@ // Show OpenGL extensions and capabilities detailed logs on init //#define SUPPORT_GL_DETAILS_INFO 1 -#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) - #define DEFAULT_BATCH_BUFFER_ELEMENTS 8192 // Default internal render batch limits -#elif defined(GRAPHICS_API_OPENGL_ES2) - #define DEFAULT_BATCH_BUFFER_ELEMENTS 2048 // Default internal render batch limits -#endif +//#define RL_DEFAULT_BATCH_BUFFER_ELEMENTS 4096 // Default internal render batch elements limits +#define RL_DEFAULT_BATCH_BUFFERS 1 // Default number of batch buffers (multi-buffering) +#define RL_DEFAULT_BATCH_DRAWCALLS 256 // Default number of batch draw calls (by state changes: mode, texture) +#define RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS 4 // Maximum number of textures units that can be activated on batch drawing (SetShaderValueTexture()) -#define DEFAULT_BATCH_BUFFERS 1 // Default number of batch buffers (multi-buffering) -#define DEFAULT_BATCH_DRAWCALLS 256 // Default number of batch draw calls (by state changes: mode, texture) +#define RL_MAX_MATRIX_STACK_SIZE 32 // Maximum size of internal Matrix stack -#define MAX_MATRIX_STACK_SIZE 32 // Maximum size of internal Matrix stack -#define MAX_MESH_VERTEX_BUFFERS 7 // Maximum vertex buffers (VBO) per mesh -#define MAX_SHADER_LOCATIONS 32 // Maximum number of shader locations supported -#define MAX_MATERIAL_MAPS 12 // Maximum number of shader maps supported +#define RL_MAX_SHADER_LOCATIONS 32 // Maximum number of shader locations supported -#define RL_CULL_DISTANCE_NEAR 0.01 // Default projection matrix near cull distance -#define RL_CULL_DISTANCE_FAR 1000.0 // Default projection matrix far cull distance +#define RL_CULL_DISTANCE_NEAR 0.01 // Default projection matrix near cull distance +#define RL_CULL_DISTANCE_FAR 1000.0 // Default projection matrix far cull distance // Default shader vertex attribute names to set location points // NOTE: When a new shader is loaded, the following locations are tried to be set for convenience -#define DEFAULT_SHADER_ATTRIB_NAME_POSITION "vertexPosition" // Binded by default to shader location: 0 -#define DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD "vertexTexCoord" // Binded by default to shader location: 1 -#define DEFAULT_SHADER_ATTRIB_NAME_NORMAL "vertexNormal" // Binded by default to shader location: 2 -#define DEFAULT_SHADER_ATTRIB_NAME_COLOR "vertexColor" // Binded by default to shader location: 3 -#define DEFAULT_SHADER_ATTRIB_NAME_TANGENT "vertexTangent" // Binded by default to shader location: 4 -#define DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Binded by default to shader location: 5 +#define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION "vertexPosition" // Binded by default to shader location: 0 +#define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD "vertexTexCoord" // Binded by default to shader location: 1 +#define RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL "vertexNormal" // Binded by default to shader location: 2 +#define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR "vertexColor" // Binded by default to shader location: 3 +#define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT "vertexTangent" // Binded by default to shader location: 4 +#define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Binded by default to shader location: 5 -#define DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix -#define DEFAULT_SHADER_UNIFORM_NAME_VIEW "matView" // view matrix -#define DEFAULT_SHADER_UNIFORM_NAME_PROJECTION "matProjection" // projection matrix -#define DEFAULT_SHADER_UNIFORM_NAME_MODEL "matModel" // model matrix -#define DEFAULT_SHADER_UNIFORM_NAME_NORMAL "matNormal" // normal matrix (transpose(inverse(matModelView)) -#define DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color) -#define DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0) -#define DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1 "texture1" // texture1 (texture slot active 1) -#define DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 "texture2" // texture2 (texture slot active 2) +#define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix +#define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW "matView" // view matrix +#define RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION "matProjection" // projection matrix +#define RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL "matModel" // model matrix +#define RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL "matNormal" // normal matrix (transpose(inverse(matModelView)) +#define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color) +#define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0) +#define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1 "texture1" // texture1 (texture slot active 1) +#define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 "texture2" // texture2 (texture slot active 2) //------------------------------------------------------------------------------------ @@ -191,6 +186,10 @@ // NOTE: Some generated meshes DO NOT include generated texture coordinates #define SUPPORT_MESH_GENERATION 1 +// models: Configuration values +//------------------------------------------------------------------------------------ +#define MAX_MATERIAL_MAPS 12 // Maximum number of shader maps supported +#define MAX_MESH_VERTEX_BUFFERS 7 // Maximum vertex buffers (VBO) per mesh //------------------------------------------------------------------------------------ // Module: audio - Configuration Flags @@ -224,4 +223,3 @@ // utils: Configuration values //------------------------------------------------------------------------------------ #define MAX_TRACELOG_MSG_LENGTH 128 // Max length of one trace-log message -#define MAX_UWP_MESSAGES 512 // Max UWP messages to process diff --git a/src/core.c b/src/core.c index 03f60c6d3..b03216cc2 100644 --- a/src/core.c +++ b/src/core.c @@ -119,19 +119,14 @@ #include "config.h" // Defines module configuration flags #endif -#include "utils.h" // 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 RLGL_IMPLEMENTATION +#include "rlgl.h" // OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2 #define RAYMATH_IMPLEMENTATION // Define external out-of-line implementation #include "raymath.h" // Vector3, Quaternion and Matrix functionality -#define RLGL_IMPLEMENTATION -#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 @@ -159,6 +154,11 @@ #include "external/sdefl.h" // Deflate (RFC 1951) compressor #endif +#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 + #include // Required for: srand(), rand(), atexit() #include // Required for: sprintf() [Used in OpenURL()] #include // Required for: strrchr(), strcmp(), strlen() @@ -622,6 +622,7 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event) #endif #if defined(PLATFORM_WEB) +static EM_BOOL EmscriptenMouseCallback(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData); static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData); static EM_BOOL EmscriptenGamepadCallback(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData); static EM_BOOL EmscriptenResizeCallback(int eventType, const EmscriptenUiEvent *e, void *userData); @@ -794,8 +795,10 @@ void InitWindow(int width, int height, const char *title) // NOTE: We setup a 1px padding on char rectangle to avoid pixel bleeding on MSAA filtering SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 1, rec.y + 1, rec.width - 2, rec.height - 2 }); #else - // Set default internal texture (1px white) and rectangle to be used for shapes drawing - SetShapesTexture(rlGetTextureDefault(), (Rectangle){ 0.0f, 0.0f, 1.0f, 1.0f }); + // Set default texture and rectangle to be used for shapes drawing + // NOTE: rlgl default texture is a 1x1 pixel UNCOMPRESSED_R8G8B8A8 + Texture2D texture = { rlGetTextureIdDefault(), 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 }; + SetShapesTexture(texture, (Rectangle){ 0.0f, 0.0f, 1.0f, 1.0f }); #endif #if defined(PLATFORM_DESKTOP) if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0) @@ -823,6 +826,9 @@ void InitWindow(int width, int height, const char *title) //emscripten_set_keypress_callback("#canvas", NULL, 1, EmscriptenKeyboardCallback); //emscripten_set_keydown_callback("#canvas", NULL, 1, EmscriptenKeyboardCallback); + // Support mouse events + emscripten_set_click_callback("#canvas", NULL, 1, EmscriptenMouseCallback); + // Support touch events emscripten_set_touchstart_callback("#canvas", NULL, 1, EmscriptenTouchCallback); emscripten_set_touchend_callback("#canvas", NULL, 1, EmscriptenTouchCallback); @@ -2134,13 +2140,13 @@ void EndTextureMode(void) // Begin custom shader mode void BeginShaderMode(Shader shader) { - rlSetShader(shader); + rlSetShader(shader.id, shader.locs); } // End custom shader mode (returns to default shader) void EndShaderMode(void) { - rlSetShader(rlGetShaderDefault()); + rlSetShader(rlGetShaderIdDefault(), rlGetShaderLocsDefault()); } // Begin blending mode (alpha, additive, multiplied, subtract, custom) @@ -2290,10 +2296,10 @@ Shader LoadShader(const char *vsFileName, const char *fsFileName) RLAPI Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode) { Shader shader = { 0 }; - shader.locs = (int *)RL_CALLOC(MAX_SHADER_LOCATIONS, sizeof(int)); + shader.locs = (int *)RL_CALLOC(RL_MAX_SHADER_LOCATIONS, sizeof(int)); // NOTE: All locations must be reseted to -1 (no location) - for (int i = 0; i < MAX_SHADER_LOCATIONS; i++) shader.locs[i] = -1; + for (int i = 0; i < RL_MAX_SHADER_LOCATIONS; i++) shader.locs[i] = -1; shader.id = rlLoadShaderCode(vsCode, fsCode); @@ -2311,25 +2317,25 @@ RLAPI Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode) // NOTE: If any location is not found, loc point becomes -1 // Get handles to GLSL input attibute locations - shader.locs[SHADER_LOC_VERTEX_POSITION] = rlGetLocationAttrib(shader.id, DEFAULT_SHADER_ATTRIB_NAME_POSITION); - shader.locs[SHADER_LOC_VERTEX_TEXCOORD01] = rlGetLocationAttrib(shader.id, DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD); - shader.locs[SHADER_LOC_VERTEX_TEXCOORD02] = rlGetLocationAttrib(shader.id, DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2); - shader.locs[SHADER_LOC_VERTEX_NORMAL] = rlGetLocationAttrib(shader.id, DEFAULT_SHADER_ATTRIB_NAME_NORMAL); - shader.locs[SHADER_LOC_VERTEX_TANGENT] = rlGetLocationAttrib(shader.id, DEFAULT_SHADER_ATTRIB_NAME_TANGENT); - shader.locs[SHADER_LOC_VERTEX_COLOR] = rlGetLocationAttrib(shader.id, DEFAULT_SHADER_ATTRIB_NAME_COLOR); + shader.locs[SHADER_LOC_VERTEX_POSITION] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION); + shader.locs[SHADER_LOC_VERTEX_TEXCOORD01] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD); + shader.locs[SHADER_LOC_VERTEX_TEXCOORD02] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2); + shader.locs[SHADER_LOC_VERTEX_NORMAL] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL); + shader.locs[SHADER_LOC_VERTEX_TANGENT] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT); + shader.locs[SHADER_LOC_VERTEX_COLOR] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR); // Get handles to GLSL uniform locations (vertex shader) - shader.locs[SHADER_LOC_MATRIX_MVP] = rlGetLocationUniform(shader.id, DEFAULT_SHADER_UNIFORM_NAME_MVP); - shader.locs[SHADER_LOC_MATRIX_VIEW] = rlGetLocationUniform(shader.id, DEFAULT_SHADER_UNIFORM_NAME_VIEW); - shader.locs[SHADER_LOC_MATRIX_PROJECTION] = rlGetLocationUniform(shader.id, DEFAULT_SHADER_UNIFORM_NAME_PROJECTION); - shader.locs[SHADER_LOC_MATRIX_MODEL] = rlGetLocationUniform(shader.id, DEFAULT_SHADER_UNIFORM_NAME_MODEL); - shader.locs[SHADER_LOC_MATRIX_NORMAL] = rlGetLocationUniform(shader.id, DEFAULT_SHADER_UNIFORM_NAME_NORMAL); + shader.locs[SHADER_LOC_MATRIX_MVP] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_MVP); + shader.locs[SHADER_LOC_MATRIX_VIEW] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW); + shader.locs[SHADER_LOC_MATRIX_PROJECTION] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION); + shader.locs[SHADER_LOC_MATRIX_MODEL] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL); + shader.locs[SHADER_LOC_MATRIX_NORMAL] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL); // Get handles to GLSL uniform locations (fragment shader) - shader.locs[SHADER_LOC_COLOR_DIFFUSE] = rlGetLocationUniform(shader.id, DEFAULT_SHADER_UNIFORM_NAME_COLOR); - shader.locs[SHADER_LOC_MAP_DIFFUSE] = rlGetLocationUniform(shader.id, DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0); // SHADER_LOC_MAP_ALBEDO - shader.locs[SHADER_LOC_MAP_SPECULAR] = rlGetLocationUniform(shader.id, DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1); // SHADER_LOC_MAP_METALNESS - shader.locs[SHADER_LOC_MAP_NORMAL] = rlGetLocationUniform(shader.id, DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2); + shader.locs[SHADER_LOC_COLOR_DIFFUSE] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR); + shader.locs[SHADER_LOC_MAP_DIFFUSE] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0); // SHADER_LOC_MAP_ALBEDO + shader.locs[SHADER_LOC_MAP_SPECULAR] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1); // SHADER_LOC_MAP_METALNESS + shader.locs[SHADER_LOC_MAP_NORMAL] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2); } return shader; @@ -2338,7 +2344,7 @@ RLAPI Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode) // Unload shader from GPU memory (VRAM) void UnloadShader(Shader shader) { - if (shader.id != rlGetShaderDefault().id) + if (shader.id != rlGetShaderIdDefault()) { rlUnloadShaderProgram(shader.id); RL_FREE(shader.locs); @@ -5315,6 +5321,13 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event) #endif #if defined(PLATFORM_WEB) +// Register mouse input events +static EM_BOOL EmscriptenMouseCallback(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData) +{ + // This is only for registering mouse click events with emscripten and doesn't need to do anything + return 0; +} + // Register touch input events static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData) { diff --git a/src/external/par_shapes.h b/src/external/par_shapes.h index 8b65e384a..994a605a9 100644 --- a/src/external/par_shapes.h +++ b/src/external/par_shapes.h @@ -21,8 +21,7 @@ // coordinates (one per vertex). That's it! If you need something fancier, // look elsewhere. // -// The MIT License -// Copyright (c) 2015 Philip Rideout +// Distributed under the MIT License, see bottom of file. #ifndef PAR_SHAPES_H #define PAR_SHAPES_H @@ -32,8 +31,7 @@ extern "C" { #endif #include - -// Ray: commented to avoid conflict with raylib bool +// Ray (@raysan5): Commented to avoid conflict with raylib bool /* #if !defined(_MSC_VER) # include @@ -41,9 +39,9 @@ extern "C" { # if _MSC_VER >= 1800 # include # else // stdbool.h missing prior to MSVC++ 12.0 (VS2013) -//# define bool int -//# define true 1 -//# define false 0 +# define bool int +# define true 1 +# define false 0 # endif #endif */ @@ -71,6 +69,14 @@ void par_shapes_free_mesh(par_shapes_mesh*); // both 1.0, but they can easily be changed with par_shapes_scale. par_shapes_mesh* par_shapes_create_cylinder(int slices, int stacks); +// Cone is similar to cylinder but the radius diminishes to zero as Z increases. +// Again, height and radius are 1.0, but can be changed with par_shapes_scale. +par_shapes_mesh* par_shapes_create_cone(int slices, int stacks); + +// Create a disk of radius 1.0 with texture coordinates and normals by squashing +// a cone flat on the Z=0 plane. +par_shapes_mesh* par_shapes_create_parametric_disk(int slices, int stacks); + // Create a donut that sits on the Z=0 plane with the specified inner radius. // The outer radius can be controlled with par_shapes_scale. par_shapes_mesh* par_shapes_create_torus(int slices, int stacks, float radius); @@ -172,6 +178,17 @@ par_shapes_mesh* par_shapes_weld(par_shapes_mesh const*, float epsilon, // Compute smooth normals by averaging adjacent facet normals. void par_shapes_compute_normals(par_shapes_mesh* m); +// Global Config --------------------------------------------------------------- + +void par_shapes_set_epsilon_welded_normals(float epsilon); +void par_shapes_set_epsilon_degenerate_sphere(float epsilon); + +// Advanced -------------------------------------------------------------------- + +void par_shapes__compute_welded_normals(par_shapes_mesh* m); +void par_shapes__connect(par_shapes_mesh* scene, par_shapes_mesh* cylinder, + int slices); + #ifndef PAR_PI #define PAR_PI (3.14159265359) #define PAR_MIN(a, b) (a > b ? b : a) @@ -205,11 +222,15 @@ void par_shapes_compute_normals(par_shapes_mesh* m); #include #include +static float par_shapes__epsilon_welded_normals = 0.001; +static float par_shapes__epsilon_degenerate_sphere = 0.0001; + static void par_shapes__sphere(float const* uv, float* xyz, void*); static void par_shapes__hemisphere(float const* uv, float* xyz, void*); static void par_shapes__plane(float const* uv, float* xyz, void*); static void par_shapes__klein(float const* uv, float* xyz, void*); static void par_shapes__cylinder(float const* uv, float* xyz, void*); +static void par_shapes__cone(float const* uv, float* xyz, void*); static void par_shapes__torus(float const* uv, float* xyz, void*); static void par_shapes__trefoil(float const* uv, float* xyz, void*); @@ -298,11 +319,12 @@ static float par_shapes__sqrdist3(float const* a, float const* b) return dx * dx + dy * dy + dz * dz; } -static void par_shapes__compute_welded_normals(par_shapes_mesh* m) +void par_shapes__compute_welded_normals(par_shapes_mesh* m) { + const float epsilon = par_shapes__epsilon_welded_normals; m->normals = PAR_MALLOC(float, m->npoints * 3); PAR_SHAPES_T* weldmap = PAR_MALLOC(PAR_SHAPES_T, m->npoints); - par_shapes_mesh* welded = par_shapes_weld(m, 0.01, weldmap); + par_shapes_mesh* welded = par_shapes_weld(m, epsilon, weldmap); par_shapes_compute_normals(welded); float* pdst = m->normals; for (int i = 0; i < m->npoints; i++, pdst += 3) { @@ -325,6 +347,24 @@ par_shapes_mesh* par_shapes_create_cylinder(int slices, int stacks) stacks, 0); } +par_shapes_mesh* par_shapes_create_cone(int slices, int stacks) +{ + if (slices < 3 || stacks < 1) { + return 0; + } + return par_shapes_create_parametric(par_shapes__cone, slices, + stacks, 0); +} + +par_shapes_mesh* par_shapes_create_parametric_disk(int slices, int stacks) +{ + par_shapes_mesh* m = par_shapes_create_cone(slices, stacks); + if (m) { + par_shapes_scale(m, 1.0f, 1.0f, 0.0f); + } + return m; +} + par_shapes_mesh* par_shapes_create_parametric_sphere(int slices, int stacks) { if (slices < 3 || stacks < 3) { @@ -332,7 +372,7 @@ par_shapes_mesh* par_shapes_create_parametric_sphere(int slices, int stacks) } par_shapes_mesh* m = par_shapes_create_parametric(par_shapes__sphere, slices, stacks, 0); - par_shapes_remove_degenerate(m, 0.0001); + par_shapes_remove_degenerate(m, par_shapes__epsilon_degenerate_sphere); return m; } @@ -343,7 +383,7 @@ par_shapes_mesh* par_shapes_create_hemisphere(int slices, int stacks) } par_shapes_mesh* m = par_shapes_create_parametric(par_shapes__hemisphere, slices, stacks, 0); - par_shapes_remove_degenerate(m, 0.0001); + par_shapes_remove_degenerate(m, par_shapes__epsilon_degenerate_sphere); return m; } @@ -579,6 +619,15 @@ static void par_shapes__cylinder(float const* uv, float* xyz, void* userdata) xyz[2] = uv[0]; } +static void par_shapes__cone(float const* uv, float* xyz, void* userdata) +{ + float r = 1.0f - uv[0]; + float theta = uv[1] * 2 * PAR_PI; + xyz[0] = r * sinf(theta); + xyz[1] = r * cosf(theta); + xyz[2] = uv[0]; +} + static void par_shapes__torus(float const* uv, float* xyz, void* userdata) { float major = 1; @@ -620,6 +669,14 @@ static void par_shapes__trefoil(float const* uv, float* xyz, void* userdata) xyz[2] = z + d * ww[2] * sin(v); } +void par_shapes_set_epsilon_welded_normals(float epsilon) { + par_shapes__epsilon_welded_normals = epsilon; +} + +void par_shapes_set_epsilon_degenerate_sphere(float epsilon) { + par_shapes__epsilon_degenerate_sphere = epsilon; +} + void par_shapes_merge(par_shapes_mesh* dst, par_shapes_mesh const* src) { PAR_SHAPES_T offset = dst->npoints; @@ -744,15 +801,15 @@ void par_shapes_rotate(par_shapes_mesh* mesh, float radians, float const* axis) p[1] = y; p[2] = z; } - p = mesh->normals; - if (p) { - for (int i = 0; i < mesh->npoints; i++, p += 3) { - float x = col0[0] * p[0] + col1[0] * p[1] + col2[0] * p[2]; - float y = col0[1] * p[0] + col1[1] * p[1] + col2[1] * p[2]; - float z = col0[2] * p[0] + col1[2] * p[1] + col2[2] * p[2]; - p[0] = x; - p[1] = y; - p[2] = z; + float* n = mesh->normals; + if (n) { + for (int i = 0; i < mesh->npoints; i++, n += 3) { + float x = col0[0] * n[0] + col1[0] * n[1] + col2[0] * n[2]; + float y = col0[1] * n[0] + col1[1] * n[1] + col2[1] * n[2]; + float z = col0[2] * n[0] + col1[2] * n[1] + col2[2] * n[2]; + n[0] = x; + n[1] = y; + n[2] = z; } } } @@ -765,6 +822,27 @@ void par_shapes_scale(par_shapes_mesh* m, float x, float y, float z) *points++ *= y; *points++ *= z; } + float* n = m->normals; + if (n && !(x == y && y == z)) { + bool x_zero = x == 0; + bool y_zero = y == 0; + bool z_zero = z == 0; + if (!x_zero && !y_zero && !z_zero) { + x = 1.0f / x; + y = 1.0f / y; + z = 1.0f / z; + } else { + x = x_zero && !y_zero && !z_zero; + y = y_zero && !x_zero && !z_zero; + z = z_zero && !x_zero && !y_zero; + } + for (int i = 0; i < m->npoints; i++, n += 3) { + n[0] *= x; + n[1] *= y; + n[2] *= z; + par_shapes__normalize3(n); + } + } } void par_shapes_merge_and_free(par_shapes_mesh* dst, par_shapes_mesh* src) @@ -1098,8 +1176,8 @@ static par_shapes_mesh* par_shapes__apply_turtle(par_shapes_mesh* mesh, return m; } -static void par_shapes__connect(par_shapes_mesh* scene, - par_shapes_mesh* cylinder, int slices) +void par_shapes__connect(par_shapes_mesh* scene, par_shapes_mesh* cylinder, + int slices) { int stacks = 1; int npoints = (slices + 1) * (stacks + 1); @@ -1118,7 +1196,8 @@ static void par_shapes__connect(par_shapes_mesh* scene, // Create the new triangle list. int ntriangles = scene->ntriangles + 2 * slices * stacks; PAR_SHAPES_T* triangles = PAR_MALLOC(PAR_SHAPES_T, ntriangles * 3); - memcpy(triangles, scene->triangles, 2 * scene->ntriangles * 3); + memcpy(triangles, scene->triangles, + sizeof(PAR_SHAPES_T) * scene->ntriangles * 3); int v = scene->npoints - (slices + 1); PAR_SHAPES_T* face = triangles + scene->ntriangles * 3; for (int stack = 0; stack < stacks; stack++) { @@ -1154,7 +1233,7 @@ par_shapes_mesh* par_shapes_create_lsystem(char const* text, int slices, while (cmd) { char *arg = strtok(0, " "); if (!arg) { - //puts("lsystem error: unexpected end of program."); + puts("lsystem error: unexpected end of program."); break; } if (!strcmp(cmd, "rule")) { @@ -1208,7 +1287,6 @@ par_shapes_mesh* par_shapes_create_lsystem(char const* text, int slices, // For testing purposes, dump out the parsed program. #ifdef TEST_PARSE - /* for (int i = 0; i < nrules; i++) { par_shapes__rule rule = rules[i]; printf("rule %s.%d\n", rule.name, rule.weight); @@ -1217,7 +1295,6 @@ par_shapes_mesh* par_shapes_create_lsystem(char const* text, int slices, printf("\t%s %s\n", cmd.cmd, cmd.arg); } } - */ #endif // Instantiate the aggregated shape and the template shapes. @@ -1258,7 +1335,8 @@ par_shapes_mesh* par_shapes_create_lsystem(char const* text, int slices, par_shapes__command* cmd = rule->commands + (frame->pc++); #ifdef DUMP_TRACE - //printf("%5s %5s %5s:%d %03d\n", cmd->cmd, cmd->arg, rule->name, frame->pc - 1, stackptr); + printf("%5s %5s %5s:%d %03d\n", cmd->cmd, cmd->arg, rule->name, + frame->pc - 1, stackptr); #endif float value; @@ -1620,7 +1698,7 @@ static void par_shapes__weld_points(par_shapes_mesh* mesh, int gridsize, PAR_SHAPES_T binvalue = *(bins + binindex); if (binvalue > 0) { if (nbins == 8) { - //printf("Epsilon value is too large.\n"); + printf("Epsilon value is too large.\n"); break; } nearby[nbins++] = binindex; @@ -1632,8 +1710,9 @@ static void par_shapes__weld_points(par_shapes_mesh* mesh, int gridsize, // Check for colocated points in each nearby bin. for (int b = 0; b < nbins; b++) { int binindex = nearby[b]; - PAR_SHAPES_T binvalue = *(bins + binindex); + PAR_SHAPES_T binvalue = bins[binindex]; PAR_SHAPES_T nindex = binvalue - 1; + assert(nindex < mesh->npoints); while (true) { // If this isn't "self" and it's colocated, then weld it! @@ -1699,6 +1778,9 @@ static void par_shapes__weld_points(par_shapes_mesh* mesh, int gridsize, PAR_SHAPES_T b = weldmap[tsrc[1]]; PAR_SHAPES_T c = weldmap[tsrc[2]]; if (a != b && a != c && b != c) { + assert(a < mesh->npoints); + assert(b < mesh->npoints); + assert(c < mesh->npoints); *tdst++ = a; *tdst++ = b; *tdst++ = c; @@ -2049,3 +2131,25 @@ void par_shapes_remove_degenerate(par_shapes_mesh* mesh, float mintriarea) #endif // PAR_SHAPES_IMPLEMENTATION #endif // PAR_SHAPES_H + +// par_shapes is distributed under the MIT license: +// +// Copyright (c) 2019 Philip Rideout +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. diff --git a/examples/shapes/raygui.h b/src/extras/raygui.h similarity index 99% rename from examples/shapes/raygui.h rename to src/extras/raygui.h index 4629e04fe..fdc8feeb1 100644 --- a/examples/shapes/raygui.h +++ b/src/extras/raygui.h @@ -516,8 +516,8 @@ RAYGUIDEF bool GuiCheckIconPixel(int iconId, int x, int y); // Check icon pi #endif #include // Required for: FILE, fopen(), fclose(), fprintf(), feof(), fscanf(), vsprintf() -#include // Required for: strlen() on GuiTextBox() -#include // Required for: roundf() on GuiColorPicker() +#include // Required for: strlen() [GuiTextBox()] +#include // Required for: roundf() [GuiColorPicker()] #if defined(RAYGUI_STANDALONE) #include // Required for: va_list, va_start(), vfprintf(), va_end() @@ -1373,7 +1373,7 @@ bool GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMo // NOTE 2: Returns if KEY_ENTER pressed (useful for data validation) bool GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode) { - static int framesCounter = 0; // Required for blinking cursor + static int framesCounter = 0; // Blinking cursor counter GuiControlState state = guiState; bool pressed = false; @@ -1561,7 +1561,7 @@ bool GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, i #define VALUEBOX_MAX_CHARS 32 #endif - static int framesCounter = 0; // Required for blinking cursor + static int framesCounter = 0; // Blinking cursor counter GuiControlState state = guiState; bool pressed = false; @@ -1678,7 +1678,7 @@ bool GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, i // Text Box control with multiple lines bool GuiTextBoxMulti(Rectangle bounds, char *text, int textSize, bool editMode) { - static int framesCounter = 0; // Required for blinking cursor + static int framesCounter = 0; // Blinking cursor counter GuiControlState state = guiState; bool pressed = false; @@ -3083,9 +3083,10 @@ char **GuiLoadIcons(const char *fileName, bool loadIconsName) for (int i = 0; i < iconsCount; i++) { guiIconsName[i] = (char *)RAYGUI_MALLOC(RICON_MAX_NAME_LENGTH); - fread(guiIconsName[i], 32, 1, rgiFile); + fread(guiIconsName[i], RICON_MAX_NAME_LENGTH, 1, rgiFile); } } + else fseek(rgiFile, iconsCount*RICON_MAX_NAME_LENGTH, SEEK_CUR); // Read icons data directly over guiIcons data array fread(guiIcons, iconsCount*(iconsSize*iconsSize/32), sizeof(unsigned int), rgiFile); diff --git a/examples/shapes/ricons.h b/src/extras/ricons.h similarity index 99% rename from examples/shapes/ricons.h rename to src/extras/ricons.h index 6befa36ba..121cf5432 100644 --- a/examples/shapes/ricons.h +++ b/src/extras/ricons.h @@ -22,7 +22,7 @@ // Icons data is defined by bit array (every bit represents one pixel) // Those arrays are stored as unsigned int data arrays, so every array // element defines 32 pixels (bits) of information -// Number of elemens depend on RICON_SIZE (by default 16x16 pixels) +// Number of elemens depend on RICON_SIZE (by default 16x16 pixels) #define RICON_DATA_ELEMENTS (RICON_SIZE*RICON_SIZE/32) //---------------------------------------------------------------------------------- diff --git a/src/models.c b/src/models.c index da9219bff..329d8d4a8 100644 --- a/src/models.c +++ b/src/models.c @@ -40,26 +40,18 @@ // 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 "utils.h" // Required for: LoadFileData(), LoadFileText(), SaveFileText() +#include "utils.h" // Required for: TRACELOG(), LoadFileData(), LoadFileText(), SaveFileText() +#include "rlgl.h" // OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2 +#include "raymath.h" // Required for: Vector3, Quaternion and Matrix functionality #include // Required for: sprintf() #include // Required for: malloc(), free() #include // Required for: memcmp(), strlen() #include // Required for: sinf(), cosf(), sqrtf(), fabsf() -#if defined(_WIN32) - #include // Required for: _chdir() [Used in LoadOBJ()] - #define CHDIR _chdir -#else - #include // Required for: chdir() (POSIX) [Used in LoadOBJ()] - #define CHDIR chdir -#endif - -#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2 - #if defined(SUPPORT_FILEFORMAT_OBJ) || defined(SUPPORT_FILEFORMAT_MTL) #define TINYOBJ_MALLOC RL_MALLOC #define TINYOBJ_CALLOC RL_CALLOC @@ -89,10 +81,23 @@ #include "external/par_shapes.h" // Shapes 3d parametric generation #endif +#if defined(_WIN32) + #include // Required for: _chdir() [Used in LoadOBJ()] + #define CHDIR _chdir +#else + #include // Required for: chdir() (POSIX) [Used in LoadOBJ()] + #define CHDIR chdir +#endif + //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- -// ... +#ifndef MAX_MATERIAL_MAPS + #define MAX_MATERIAL_MAPS 12 // Maximum number of maps supported +#endif +#ifndef MAX_MESH_VERTEX_BUFFERS + #define MAX_MESH_VERTEX_BUFFERS 7 // Maximum vertex buffers (VBO) per mesh +#endif //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -819,6 +824,35 @@ void UnloadModelKeepMeshes(Model model) TRACELOG(LOG_INFO, "MODEL: Unloaded model (but not meshes) from RAM and VRAM"); } +// Compute model bounding box limits (considers all meshes) +BoundingBox GetModelBoundingBox(Model model) +{ + BoundingBox bounds = { 0 }; + + if (model.meshCount > 0) + { + Vector3 temp = { 0 }; + bounds = GetMeshBoundingBox(model.meshes[0]); + + for (int i = 1; i < model.meshCount; i++) + { + BoundingBox tempBounds = GetMeshBoundingBox(model.meshes[i]); + + temp.x = (bounds.min.x < tempBounds.min.x)? bounds.min.x : tempBounds.min.x; + temp.y = (bounds.min.y < tempBounds.min.y)? bounds.min.y : tempBounds.min.y; + temp.z = (bounds.min.z < tempBounds.min.z)? bounds.min.z : tempBounds.min.z; + bounds.min = temp; + + temp.x = (bounds.max.x > tempBounds.max.x)? bounds.max.x : tempBounds.max.x; + temp.y = (bounds.max.y > tempBounds.max.y)? bounds.max.y : tempBounds.max.y; + temp.z = (bounds.max.z > tempBounds.max.z)? bounds.max.z : tempBounds.max.z; + bounds.max = temp; + } + } + + return bounds; +} + // Upload vertex data into a VAO (if supported) and VBO void UploadMesh(Mesh *mesh, bool dynamic) { @@ -1342,7 +1376,11 @@ Material *LoadMaterials(const char *fileName, int *materialCount) // Set materials shader to default (DIFFUSE, SPECULAR, NORMAL) if (materials != NULL) { - for (unsigned int i = 0; i < count; i++) materials[i].shader = rlGetShaderDefault(); + for (unsigned int i = 0; i < count; i++) + { + materials[i].shader.id = rlGetShaderIdDefault(); + materials[i].shader.locs = rlGetShaderLocsDefault(); + } } *materialCount = count; @@ -1355,8 +1393,12 @@ Material LoadMaterialDefault(void) Material material = { 0 }; material.maps = (MaterialMap *)RL_CALLOC(MAX_MATERIAL_MAPS, sizeof(MaterialMap)); - material.shader = rlGetShaderDefault(); - material.maps[MATERIAL_MAP_DIFFUSE].texture = rlGetTextureDefault(); // White texture (1x1 pixel) + // Using rlgl default shader + material.shader.id = rlGetShaderIdDefault(); + material.shader.locs = rlGetShaderLocsDefault(); + + // Using rlgl default texture (1x1 pixel, UNCOMPRESSED_R8G8B8A8, 1 mipmap) + material.maps[MATERIAL_MAP_DIFFUSE].texture = (Texture2D){ rlGetTextureIdDefault(), 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 }; //material.maps[MATERIAL_MAP_NORMAL].texture; // NOTE: By default, not set //material.maps[MATERIAL_MAP_SPECULAR].texture; // NOTE: By default, not set @@ -1370,12 +1412,12 @@ Material LoadMaterialDefault(void) void UnloadMaterial(Material material) { // Unload material shader (avoid unloading default shader, managed by raylib) - if (material.shader.id != rlGetShaderDefault().id) UnloadShader(material.shader); + if (material.shader.id != rlGetShaderIdDefault()) UnloadShader(material.shader); // Unload loaded texture maps (avoid unloading default texture, managed by raylib) for (int i = 0; i < MAX_MATERIAL_MAPS; i++) { - if (material.maps[i].texture.id != rlGetTextureDefault().id) rlUnloadTexture(material.maps[i].texture.id); + if (material.maps[i].texture.id != rlGetTextureIdDefault()) rlUnloadTexture(material.maps[i].texture.id); } RL_FREE(material.maps); @@ -2042,6 +2084,61 @@ Mesh GenMeshCylinder(float radius, float height, int slices) return mesh; } +// Generate cone/pyramid mesh +Mesh GenMeshCone(float radius, float height, int slices) +{ + Mesh mesh = { 0 }; + + if (slices >= 3) + { + // Instance a cone that sits on the Z=0 plane using the given tessellation + // levels across the UV domain. Think of "slices" like a number of pizza + // slices, and "stacks" like a number of stacked rings. + // Height and radius are both 1.0, but they can easily be changed with par_shapes_scale + par_shapes_mesh *cone = par_shapes_create_cone(slices, 8); + par_shapes_scale(cone, radius, radius, height); + par_shapes_rotate(cone, -PI/2.0f, (float[]){ 1, 0, 0 }); + par_shapes_rotate(cone, PI/2.0f, (float[]){ 0, 1, 0 }); + + // Generate an orientable disk shape (bottom cap) + par_shapes_mesh *capBottom = par_shapes_create_disk(radius, slices, (float[]){ 0, 0, 0 }, (float[]){ 0, 0, -1 }); + capBottom->tcoords = PAR_MALLOC(float, 2*capBottom->npoints); + for (int i = 0; i < 2*capBottom->npoints; i++) capBottom->tcoords[i] = 0.95f; + par_shapes_rotate(capBottom, PI/2.0f, (float[]){ 1, 0, 0 }); + + par_shapes_merge_and_free(cone, capBottom); + + mesh.vertices = (float *)RL_MALLOC(cone->ntriangles*3*3*sizeof(float)); + mesh.texcoords = (float *)RL_MALLOC(cone->ntriangles*3*2*sizeof(float)); + mesh.normals = (float *)RL_MALLOC(cone->ntriangles*3*3*sizeof(float)); + + mesh.vertexCount = cone->ntriangles*3; + mesh.triangleCount = cone->ntriangles; + + for (int k = 0; k < mesh.vertexCount; k++) + { + mesh.vertices[k*3] = cone->points[cone->triangles[k]*3]; + mesh.vertices[k*3 + 1] = cone->points[cone->triangles[k]*3 + 1]; + mesh.vertices[k*3 + 2] = cone->points[cone->triangles[k]*3 + 2]; + + mesh.normals[k*3] = cone->normals[cone->triangles[k]*3]; + mesh.normals[k*3 + 1] = cone->normals[cone->triangles[k]*3 + 1]; + mesh.normals[k*3 + 2] = cone->normals[cone->triangles[k]*3 + 2]; + + mesh.texcoords[k*2] = cone->tcoords[cone->triangles[k]*2]; + mesh.texcoords[k*2 + 1] = cone->tcoords[cone->triangles[k]*2 + 1]; + } + + par_shapes_free_mesh(cone); + + // Upload vertex data to GPU (static mesh) + UploadMesh(&mesh, false); + } + else TRACELOG(LOG_WARNING, "MESH: Failed to generate mesh: cone"); + + return mesh; +} + // Generate torus mesh Mesh GenMeshTorus(float radius, float size, int radSeg, int sides) { @@ -2652,19 +2749,15 @@ BoundingBox GetMeshBoundingBox(Mesh mesh) // Implementation base don: https://answers.unity.com/questions/7789/calculating-tangents-vector4.html void GenMeshTangents(Mesh *mesh) { - - if (mesh->tangents == NULL) + if (mesh->tangents == NULL) mesh->tangents = (float *)RL_MALLOC(mesh->vertexCount*4*sizeof(float)); + else { - mesh->tangents = (float*)RL_MALLOC(mesh->vertexCount*4*sizeof(float)); - } - else - { RL_FREE(mesh->tangents); - mesh->tangents = (float*)RL_MALLOC(mesh->vertexCount*4*sizeof(float)); + mesh->tangents = (float *)RL_MALLOC(mesh->vertexCount*4*sizeof(float)); } - Vector3* tan1 = (Vector3*)RL_MALLOC(mesh->vertexCount*sizeof(Vector3)); - Vector3* tan2 = (Vector3*)RL_MALLOC(mesh->vertexCount*sizeof(Vector3)); + Vector3 *tan1 = (Vector3 *)RL_MALLOC(mesh->vertexCount*sizeof(Vector3)); + Vector3 *tan2 = (Vector3 *)RL_MALLOC(mesh->vertexCount*sizeof(Vector3)); for (int i = 0; i < mesh->vertexCount; i += 3) { @@ -2691,7 +2784,7 @@ void GenMeshTangents(Mesh *mesh) float t2 = uv3.y - uv1.y; float div = s1*t2 - s2*t1; - float r = (div == 0.0f) ? 0.0f : 1.0f/div; + float r = (div == 0.0f)? 0.0f : 1.0f/div; Vector3 sdir = { (t2*x1 - t1*x2)*r, (t2*y1 - t1*y2)*r, (t2*z1 - t1*z2)*r }; Vector3 tdir = { (s1*x2 - s2*x1)*r, (s1*y2 - s2*y1)*r, (s1*z2 - s2*z1)*r }; @@ -2706,53 +2799,51 @@ void GenMeshTangents(Mesh *mesh) } // Compute tangents considering normals - for (int i = 0; i < mesh->vertexCount; ++i) + for (int i = 0; i < mesh->vertexCount; i++) { Vector3 normal = { mesh->normals[i*3 + 0], mesh->normals[i*3 + 1], mesh->normals[i*3 + 2] }; Vector3 tangent = tan1[i]; // TODO: Review, not sure if tangent computation is right, just used reference proposed maths... - #if defined(COMPUTE_TANGENTS_METHOD_01) +#if defined(COMPUTE_TANGENTS_METHOD_01) Vector3 tmp = Vector3Subtract(tangent, Vector3Scale(normal, Vector3DotProduct(normal, tangent))); tmp = Vector3Normalize(tmp); mesh->tangents[i*4 + 0] = tmp.x; mesh->tangents[i*4 + 1] = tmp.y; mesh->tangents[i*4 + 2] = tmp.z; mesh->tangents[i*4 + 3] = 1.0f; - #else +#else Vector3OrthoNormalize(&normal, &tangent); mesh->tangents[i*4 + 0] = tangent.x; mesh->tangents[i*4 + 1] = tangent.y; mesh->tangents[i*4 + 2] = tangent.z; - mesh->tangents[i*4 + 3] = (Vector3DotProduct(Vector3CrossProduct(normal, tangent), tan2[i]) < 0.0f) ? -1.0f : 1.0f; - #endif + mesh->tangents[i*4 + 3] = (Vector3DotProduct(Vector3CrossProduct(normal, tangent), tan2[i]) < 0.0f)? -1.0f : 1.0f; +#endif } RL_FREE(tan1); RL_FREE(tan2); - - if (mesh->vboId != NULL) - { - - if (mesh->vboId[SHADER_LOC_VERTEX_TANGENT] != 0) - { - // Upate existing vertex buffer - rlUpdateVertexBuffer(mesh->vboId[SHADER_LOC_VERTEX_TANGENT], mesh->tangents, mesh->vertexCount*4*sizeof(float), 0); - } - else - { - // Load a new tangent attributes buffer - mesh->vboId[SHADER_LOC_VERTEX_TANGENT] = rlLoadVertexBuffer(mesh->tangents, mesh->vertexCount*4*sizeof(float), false); - } - - rlEnableVertexArray(mesh->vaoId); - rlSetVertexAttribute(4, 4, RL_FLOAT, 0, 0, 0); - rlEnableVertexAttribute(4); - rlDisableVertexArray(); - } + if (mesh->vboId != NULL) + { + if (mesh->vboId[SHADER_LOC_VERTEX_TANGENT] != 0) + { + // Upate existing vertex buffer + rlUpdateVertexBuffer(mesh->vboId[SHADER_LOC_VERTEX_TANGENT], mesh->tangents, mesh->vertexCount*4*sizeof(float), 0); + } + else + { + // Load a new tangent attributes buffer + mesh->vboId[SHADER_LOC_VERTEX_TANGENT] = rlLoadVertexBuffer(mesh->tangents, mesh->vertexCount*4*sizeof(float), false); + } + + rlEnableVertexArray(mesh->vaoId); + rlSetVertexAttribute(4, 4, RL_FLOAT, 0, 0, 0); + rlEnableVertexAttribute(4); + rlDisableVertexArray(); + } - TRACELOG(LOG_INFO, "MESH: Tangents data computed for provided mesh"); + TRACELOG(LOG_INFO, "MESH: Tangents data computed and uploaded for provided mesh"); } // Compute mesh binormals (aka bitangent) @@ -3087,11 +3178,10 @@ RayCollision GetRayCollisionBox(Ray ray, BoundingBox box) collision.normal = Vector3Scale(collision.normal, 2.01f); collision.normal = Vector3Divide(collision.normal, Vector3Subtract(box.max, box.min)); // The relevant elemets of the vector are now slightly larger than 1.0f (or smaller than -1.0f) - // and the others are somewhere between -1.0 and 1.0 - // casting to int is exactly our wanted normal! - collision.normal.x = (int)collision.normal.x; - collision.normal.y = (int)collision.normal.y; - collision.normal.z = (int)collision.normal.z; + // and the others are somewhere between -1.0 and 1.0 casting to int is exactly our wanted normal! + collision.normal.x = (float)((int)collision.normal.x); + collision.normal.y = (float)((int)collision.normal.y); + collision.normal.z = (float)((int)collision.normal.z); collision.normal = Vector3Normalize(collision.normal); @@ -3377,10 +3467,11 @@ static Model LoadOBJ(const char *fileName) // NOTE: Uses default shader, which only supports MATERIAL_MAP_DIFFUSE model.materials[m] = LoadMaterialDefault(); - model.materials[m].maps[MATERIAL_MAP_DIFFUSE].texture = rlGetTextureDefault(); // Get default texture, in case no texture is defined + // Get default texture, in case no texture is defined + // NOTE: rlgl default texture is a 1x1 pixel UNCOMPRESSED_R8G8B8A8 + model.materials[m].maps[MATERIAL_MAP_DIFFUSE].texture = (Texture2D){ rlGetTextureIdDefault(), 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 }; if (materials[m].diffuse_texname != NULL) model.materials[m].maps[MATERIAL_MAP_DIFFUSE].texture = LoadTexture(materials[m].diffuse_texname); //char *diffuse_texname; // map_Kd - else model.materials[m].maps[MATERIAL_MAP_DIFFUSE].texture = rlGetTextureDefault(); model.materials[m].maps[MATERIAL_MAP_DIFFUSE].color = (Color){ (unsigned char)(materials[m].diffuse[0]*255.0f), (unsigned char)(materials[m].diffuse[1]*255.0f), (unsigned char)(materials[m].diffuse[2]*255.0f), 255 }; //float diffuse[3]; model.materials[m].maps[MATERIAL_MAP_DIFFUSE].value = 0.0f; @@ -4403,12 +4494,12 @@ static void *ReadGLTFValuesAs(cgltf_accessor* acc, cgltf_component_type type, bo } break; case cgltf_component_type_r_32f: { - float* typedArray = (float*) array; + float *typedArray = (float *)array; for (unsigned int i = 0; i < count*typeElements; i++) typedArray[i] = (float)typedAdditionalArray[i]; } break; case cgltf_component_type_r_32u: { - unsigned int* typedArray = (unsigned int*) array; + unsigned int *typedArray = (unsigned int *)array; for (unsigned int i = 0; i < count*typeElements; i++) typedArray[i] = (unsigned int)typedAdditionalArray[i]; } break; default: @@ -4900,7 +4991,7 @@ static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCo { output->framePoses[frame] = RL_MALLOC(output->boneCount*sizeof(Transform)); - for (unsigned int i = 0; i < output->boneCount; i++) + for (int i = 0; i < output->boneCount; i++) { if (data->nodes[i].has_translation) memcpy(&output->framePoses[frame][i].translation, data->nodes[i].translation, 3*sizeof(float)); else output->framePoses[frame][i].translation = Vector3Zero(); @@ -5093,7 +5184,7 @@ void LoadGLTFMesh(cgltf_data* data, cgltf_mesh* mesh, Model* outModel, Matrix cu outModel->meshes[(*primitiveIndex)].vertices = ReadGLTFValuesAs(acc, cgltf_component_type_r_32f, false); // Transform using the nodes matrix attributes - for (unsigned int v = 0; v < outModel->meshes[(*primitiveIndex)].vertexCount; v++) + for (int v = 0; v < outModel->meshes[(*primitiveIndex)].vertexCount; v++) { Vector3 vertex = { outModel->meshes[(*primitiveIndex)].vertices[(v*3 + 0)], @@ -5119,7 +5210,7 @@ void LoadGLTFMesh(cgltf_data* data, cgltf_mesh* mesh, Model* outModel, Matrix cu outModel->meshes[(*primitiveIndex)].normals = ReadGLTFValuesAs(acc, cgltf_component_type_r_32f, false); // Transform using the nodes matrix attributes - for (unsigned int v = 0; v < outModel->meshes[(*primitiveIndex)].vertexCount; v++) + for (int v = 0; v < outModel->meshes[(*primitiveIndex)].vertexCount; v++) { Vector3 normal = { outModel->meshes[(*primitiveIndex)].normals[(v*3 + 0)], diff --git a/src/raudio.c b/src/raudio.c index 8f6d32e0a..9a4a6c944 100644 --- a/src/raudio.c +++ b/src/raudio.c @@ -70,11 +70,10 @@ #include // Required for: va_list, va_start(), vfprintf(), va_end() #else #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 -#endif + // Check if config flags have been externally provided on compilation line + #if !defined(EXTERNAL_CONFIG_FLAGS) + #include "config.h" // Defines module configuration flags + #endif #include "utils.h" // Required for: fopen() Android mapping #endif @@ -173,7 +172,7 @@ typedef struct tagBITMAPINFOHEADER { #if defined(RAUDIO_STANDALONE) #include // Required for: strcmp() [Used in IsFileExtension()] - #if !defined(TRACELOG) + #ifndef TRACELOG #define TRACELOG(level, ...) (void)0 #endif @@ -1724,9 +1723,9 @@ void UpdateMusicStream(Music music) case MUSIC_MODULE_XM: { // NOTE: Internally we consider 2 channels generation, so samplesCount/2 - if (AUDIO_DEVICE_FORMAT == ma_format_f32) jar_xm_generate_samples((jar_xm_context_t*)music.ctxData, (float *)pcm, samplesCount/2); - else if (AUDIO_DEVICE_FORMAT == ma_format_s16) jar_xm_generate_samples_16bit((jar_xm_context_t*)music.ctxData, (short *)pcm, samplesCount/2); - else if (AUDIO_DEVICE_FORMAT == ma_format_u8) jar_xm_generate_samples_8bit((jar_xm_context_t*)music.ctxData, (char *)pcm, samplesCount/2); + if (AUDIO_DEVICE_FORMAT == ma_format_f32) jar_xm_generate_samples((jar_xm_context_t *)music.ctxData, (float *)pcm, samplesCount/2); + else if (AUDIO_DEVICE_FORMAT == ma_format_s16) jar_xm_generate_samples_16bit((jar_xm_context_t *)music.ctxData, (short *)pcm, samplesCount/2); + else if (AUDIO_DEVICE_FORMAT == ma_format_u8) jar_xm_generate_samples_8bit((jar_xm_context_t *)music.ctxData, (char *)pcm, samplesCount/2); } break; #endif diff --git a/src/raylib.h b/src/raylib.h index 38af9f0eb..7f8728137 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -22,7 +22,7 @@ * * NOTES: * One default Font is loaded on InitWindow()->LoadFontDefault() [core, text] -* One default Texture2D is loaded on rlglInit() [rlgl] (OpenGL 3.3 or ES2) +* One default Texture2D is loaded on rlglInit(), 1x1 white pixel R8G8B8A8 [rlgl] (OpenGL 3.3 or ES2) * One default Shader is loaded on rlglInit()->rlLoadShaderDefault() [rlgl] (OpenGL 3.3 or ES2) * One default RenderBatch is loaded on rlglInit()->rlLoadRenderBatch() [rlgl] (OpenGL 3.3 or ES2) * @@ -102,9 +102,12 @@ #ifndef PI #define PI 3.14159265358979323846f #endif - -#define DEG2RAD (PI/180.0f) -#define RAD2DEG (180.0f/PI) +#ifndef DEG2RAD + #define DEG2RAD (PI/180.0f) +#endif +#ifndef RAD2DEG + #define RAD2DEG (180.0f/PI) +#endif // Allow custom memory allocators #ifndef RL_MALLOC @@ -128,6 +131,16 @@ #define CLITERAL(type) (type) #endif +// NOTE: We set some defines with some data types declared by raylib +// Other modules (raymath, rlgl) also require some of those types, so, +// to be able to use those other modules as standalone (not depending on raylib) +// this defines are very useful for internal check and avoid type (re)definitions +#define RL_VECTOR2_TYPE +#define RL_VECTOR3_TYPE +#define RL_VECTOR4_TYPE +#define RL_QUATERNION_TYPE +#define RL_MATRIX_TYPE + // Some Basic Colors // NOTE: Custom raylib color palette for amazing visuals on WHITE background #define LIGHTGRAY CLITERAL(Color){ 200, 200, 200, 255 } // Light Gray @@ -174,6 +187,7 @@ #include #elif !defined(__cplusplus) && !defined(bool) typedef enum bool { false, true } bool; + #define RL_BOOL_TYPE #endif // Vector2, 2 components @@ -268,23 +282,23 @@ typedef struct NPatchInfo { int layout; // Layout of the n-patch: 3x3, 1x3 or 3x1 } NPatchInfo; -// CharInfo, font character info -typedef struct CharInfo { +// GlyphInfo, font characters glyphs info +typedef struct GlyphInfo { int value; // Character value (Unicode) int offsetX; // Character offset X when drawing int offsetY; // Character offset Y when drawing int advanceX; // Character advance position X Image image; // Character image data -} CharInfo; +} GlyphInfo; -// Font, font texture and CharInfo array data +// Font, font texture and GlyphInfo array data typedef struct Font { int baseSize; // Base size (default chars height) int charsCount; // Number of characters int charsPadding; // Padding around the chars Texture2D texture; // Characters texture atlas Rectangle *recs; // Characters rectangles in texture - CharInfo *chars; // Characters info data + GlyphInfo *chars; // Characters glyphs info data } Font; // Camera, defines position/orientation in 3d space @@ -334,7 +348,7 @@ typedef struct Mesh { // Shader typedef struct Shader { unsigned int id; // Shader program id - int *locs; // Shader locations array (MAX_SHADER_LOCATIONS) + int *locs; // Shader locations array (RL_MAX_SHADER_LOCATIONS) } Shader; // MaterialMap @@ -1063,8 +1077,8 @@ RLAPI bool IsKeyDown(int key); // Check if a key RLAPI bool IsKeyReleased(int key); // Check if a key has been released once RLAPI bool IsKeyUp(int key); // Check if a key is NOT being pressed RLAPI void SetExitKey(int key); // Set a custom key to exit program (default is ESC) -RLAPI int GetKeyPressed(void); // Get key pressed (keycode), call it multiple times for keys queued -RLAPI int GetCharPressed(void); // Get char pressed (unicode), call it multiple times for chars queued +RLAPI int GetKeyPressed(void); // Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty +RLAPI int GetCharPressed(void); // Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty // Input-related functions: gamepads RLAPI bool IsGamepadAvailable(int gamepad); // Check if a gamepad is available @@ -1203,7 +1217,7 @@ RLAPI Image GenImageGradientRadial(int width, int height, float density, Color i RLAPI Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2); // Generate image: checked RLAPI Image GenImageWhiteNoise(int width, int height, float factor); // Generate image: white noise RLAPI Image GenImagePerlinNoise(int width, int height, int offsetX, int offsetY, float scale); // Generate image: perlin noise -RLAPI Image GenImageCellular(int width, int height, int tileSize); // Generate image: cellular algorithm. Bigger tileSize means bigger cells +RLAPI Image GenImageCellular(int width, int height, int tileSize); // Generate image: cellular algorithm, bigger tileSize means bigger cells // Image manipulation functions RLAPI Image ImageCopy(Image image); // Create an image duplicate (useful for transformations) @@ -1306,33 +1320,42 @@ RLAPI Font LoadFont(const char *fileName); RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int charsCount); // Load font from file with extended parameters RLAPI Font LoadFontFromImage(Image image, Color key, int firstChar); // Load font from Image (XNA style) RLAPI Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int charsCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf' -RLAPI CharInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int charsCount, int type); // Load font data for further use -RLAPI Image GenImageFontAtlas(const CharInfo *chars, Rectangle **recs, int charsCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info -RLAPI void UnloadFontData(CharInfo *chars, int charsCount); // Unload font chars info data (RAM) +RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int charsCount, int type); // Load font data for further use +RLAPI Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **recs, int charsCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info +RLAPI void UnloadFontData(GlyphInfo *chars, int charsCount); // Unload font chars info data (RAM) RLAPI void UnloadFont(Font font); // Unload Font from GPU memory (VRAM) // Text drawing functions RLAPI void DrawFPS(int posX, int posY); // Draw current FPS RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font) -RLAPI void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using font and additional parameters -RLAPI void DrawTextRec(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint); // Draw text using font inside rectangle limits -RLAPI void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint, int selectStart, int selectLength, Color selectTint, Color selectBackTint); // Draw text using font inside rectangle limits with support for text selection +RLAPI void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using font and additional parameters +RLAPI void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint); // Draw text using Font and pro parameters (rotation) RLAPI void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSize, Color tint); // Draw one character (codepoint) -// Text misc. functions +// Text font info functions RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font RLAPI Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing); // Measure string size for Font -RLAPI int GetGlyphIndex(Font font, int codepoint); // Get index position for a unicode character on font +RLAPI int GetGlyphIndex(Font font, int codepoint); // Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found +RLAPI GlyphInfo GetGlyphInfo(Font font, int codepoint); // Get glyph font info data for a codepoint (unicode character), fallback to '?' if not found +RLAPI Rectangle GetGlyphAtlasRec(Font font, int codepoint); // Get glyph rectangle in font atlas for a codepoint (unicode character), fallback to '?' if not found -// Text strings management functions (no utf8 strings, only byte chars) +// Text codepoints management functions (unicode characters) +RLAPI int *LoadCodepoints(const char *text, int *count); // Load all codepoints from a UTF-8 text string, codepoints count returned by parameter +RLAPI void UnloadCodepoints(int *codepoints); // Unload codepoints data from memory +RLAPI int GetCodepointsCount(const char *text); // Get total number of codepoints in a UTF-8 encoded string +RLAPI int GetCodepoint(const char *text, int *bytesProcessed); // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure +RLAPI const char *CodepointToUTF8(int codepoint, int *byteLength); // Encode one codepoint into UTF-8 byte array (array length returned as parameter) +RLAPI char *TextCodepointsToUTF8(int *codepoints, int length); // Encode text as codepoints array into UTF-8 text string (WARNING: memory must be freed!) + +// Text strings management functions (no UTF-8 strings, only byte chars) // NOTE: Some strings allocate memory internally for returned strings, just be careful! RLAPI int TextCopy(char *dst, const char *src); // Copy one string to another, returns bytes copied RLAPI bool TextIsEqual(const char *text1, const char *text2); // Check if two text string are equal RLAPI unsigned int TextLength(const char *text); // Get text length, checks for '\0' ending -RLAPI const char *TextFormat(const char *text, ...); // Text formatting with variables (sprintf style) +RLAPI const char *TextFormat(const char *text, ...); // Text formatting with variables (sprintf() style) RLAPI const char *TextSubtext(const char *text, int position, int length); // Get a piece of a text string -RLAPI char *TextReplace(char *text, const char *replace, const char *by); // Replace text string (memory must be freed!) -RLAPI char *TextInsert(const char *text, const char *insert, int position); // Insert text in a position (memory must be freed!) +RLAPI char *TextReplace(char *text, const char *replace, const char *by); // Replace text string (WARNING: memory must be freed!) +RLAPI char *TextInsert(const char *text, const char *insert, int position); // Insert text in a position (WARNING: memory must be freed!) RLAPI const char *TextJoin(const char **textList, int count, const char *delimiter); // Join text strings with delimiter RLAPI const char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings RLAPI void TextAppend(char *text, const char *append, int *position); // Append text at specific position and move cursor! @@ -1341,14 +1364,6 @@ RLAPI const char *TextToUpper(const char *text); // Get upp RLAPI const char *TextToLower(const char *text); // Get lower case version of provided string RLAPI const char *TextToPascal(const char *text); // Get Pascal case notation version of provided string RLAPI int TextToInteger(const char *text); // Get integer value from text (negative values not supported) -RLAPI char *TextToUtf8(int *codepoints, int length); // Encode text codepoint into utf8 text (memory must be freed!) - -// UTF8 text strings management functions -RLAPI int *LoadCodepoints(const char *text, int *count); // Load all codepoints from a UTF8 text string, codepoints count returned by parameter -RLAPI void UnloadCodepoints(int *codepoints); // Unload codepoints data from memory -RLAPI int GetCodepointsCount(const char *text); // Get total number of characters (codepoints) in a UTF8 encoded string -RLAPI int GetCodepoint(const char *text, int *bytesProcessed); // Get next codepoint in a UTF8 encoded string, 0x3f('?') is returned on failure -RLAPI const char *CodepointToUtf8(int codepoint, int *byteLength); // Encode codepoint into utf8 text (char array length returned as parameter) //------------------------------------------------------------------------------------ // Basic 3d Shapes Drawing Functions (Module: models) @@ -1378,19 +1393,46 @@ RLAPI void DrawGrid(int slices, float spacing); // Model 3d Loading and Drawing Functions (Module: models) //------------------------------------------------------------------------------------ -// Model loading/unloading functions +// Model management functions RLAPI Model LoadModel(const char *fileName); // Load model from files (meshes and materials) RLAPI Model LoadModelFromMesh(Mesh mesh); // Load model from generated mesh (default material) RLAPI void UnloadModel(Model model); // Unload model (including meshes) from memory (RAM and/or VRAM) RLAPI void UnloadModelKeepMeshes(Model model); // Unload model (but not meshes) from memory (RAM and/or VRAM) +RLAPI BoundingBox GetModelBoundingBox(Model model); // Compute model bounding box limits (considers all meshes) -// Mesh loading/unloading functions +// Model drawing functions +RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set) +RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters +RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set) +RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters +RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires) +RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float size, Color tint); // Draw a billboard texture +RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by source +RLAPI void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Vector2 origin, float rotation, Color tint); // Draw a billboard texture defined by source and rotation + +// Mesh management functions RLAPI void UploadMesh(Mesh *mesh, bool dynamic); // Upload mesh vertex data in GPU and provide VAO/VBO ids RLAPI void UpdateMeshBuffer(Mesh mesh, int index, void *data, int dataSize, int offset); // Update mesh vertex data in GPU for a specific buffer index +RLAPI void UnloadMesh(Mesh mesh); // Unload mesh data from CPU and GPU RLAPI void DrawMesh(Mesh mesh, Material material, Matrix transform); // Draw a 3d mesh with material and transform RLAPI void DrawMeshInstanced(Mesh mesh, Material material, Matrix *transforms, int instances); // Draw multiple mesh instances with material and different transforms -RLAPI void UnloadMesh(Mesh mesh); // Unload mesh data from CPU and GPU RLAPI bool ExportMesh(Mesh mesh, const char *fileName); // Export mesh data to file, returns true on success +RLAPI BoundingBox GetMeshBoundingBox(Mesh mesh); // Compute mesh bounding box limits +RLAPI void GenMeshTangents(Mesh *mesh); // Compute mesh tangents +RLAPI void GenMeshBinormals(Mesh *mesh); // Compute mesh binormals + +// Mesh generation functions +RLAPI Mesh GenMeshPoly(int sides, float radius); // Generate polygonal mesh +RLAPI Mesh GenMeshPlane(float width, float length, int resX, int resZ); // Generate plane mesh (with subdivisions) +RLAPI Mesh GenMeshCube(float width, float height, float length); // Generate cuboid mesh +RLAPI Mesh GenMeshSphere(float radius, int rings, int slices); // Generate sphere mesh (standard sphere) +RLAPI Mesh GenMeshHemiSphere(float radius, int rings, int slices); // Generate half-sphere mesh (no bottom cap) +RLAPI Mesh GenMeshCylinder(float radius, float height, int slices); // Generate cylinder mesh +RLAPI Mesh GenMeshCone(float radius, float height, int slices); // Generate cone/pyramid mesh +RLAPI Mesh GenMeshTorus(float radius, float size, int radSeg, int sides); // Generate torus mesh +RLAPI Mesh GenMeshKnot(float radius, float size, int radSeg, int sides); // Generate trefoil knot mesh +RLAPI Mesh GenMeshHeightmap(Image heightmap, Vector3 size); // Generate heightmap mesh from image data +RLAPI Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize); // Generate cubes-based map mesh from image data // Material loading/unloading functions RLAPI Material *LoadMaterials(const char *fileName, int *materialCount); // Load materials from model file @@ -1406,33 +1448,6 @@ RLAPI void UnloadModelAnimation(ModelAnimation anim); RLAPI void UnloadModelAnimations(ModelAnimation* animations, unsigned int count); // Unload animation array data RLAPI bool IsModelAnimationValid(Model model, ModelAnimation anim); // Check model animation skeleton match -// Mesh generation functions -RLAPI Mesh GenMeshPoly(int sides, float radius); // Generate polygonal mesh -RLAPI Mesh GenMeshPlane(float width, float length, int resX, int resZ); // Generate plane mesh (with subdivisions) -RLAPI Mesh GenMeshCube(float width, float height, float length); // Generate cuboid mesh -RLAPI Mesh GenMeshSphere(float radius, int rings, int slices); // Generate sphere mesh (standard sphere) -RLAPI Mesh GenMeshHemiSphere(float radius, int rings, int slices); // Generate half-sphere mesh (no bottom cap) -RLAPI Mesh GenMeshCylinder(float radius, float height, int slices); // Generate cylinder mesh -RLAPI Mesh GenMeshTorus(float radius, float size, int radSeg, int sides); // Generate torus mesh -RLAPI Mesh GenMeshKnot(float radius, float size, int radSeg, int sides); // Generate trefoil knot mesh -RLAPI Mesh GenMeshHeightmap(Image heightmap, Vector3 size); // Generate heightmap mesh from image data -RLAPI Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize); // Generate cubes-based map mesh from image data - -// Mesh manipulation functions -RLAPI BoundingBox GetMeshBoundingBox(Mesh mesh); // Compute mesh bounding box limits -RLAPI void GenMeshTangents(Mesh *mesh); // Compute mesh tangents -RLAPI void GenMeshBinormals(Mesh *mesh); // Compute mesh binormals - -// Model drawing functions -RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set) -RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters -RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set) -RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters -RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires) -RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float size, Color tint); // Draw a billboard texture -RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by source -RLAPI void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Vector2 origin, float rotation, Color tint); // Draw a billboard texture defined by source and rotation - // Collision detection functions RLAPI bool CheckCollisionSpheres(Vector3 center1, float radius1, Vector3 center2, float radius2); // Check collision between two spheres RLAPI bool CheckCollisionBoxes(BoundingBox box1, BoundingBox box2); // Check collision between two bounding boxes diff --git a/src/raymath.h b/src/raymath.h index ea888cf01..0909eb7e5 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -1,6 +1,6 @@ /********************************************************************************************** * -* raymath v1.2 - Math functions to work with Vector3, Matrix and Quaternions +* raymath v1.3 - Math functions to work with Vector3, Matrix and Quaternions * * CONFIGURATION: * @@ -9,14 +9,10 @@ * If not defined, the library is in header only mode and can be included in other headers * or source files without problems. But only ONE file should hold the implementation. * -* #define RAYMATH_HEADER_ONLY +* #define RAYMATH_STATIC_INLINE * Define static inline functions code, so #include header suffices for use. * This may use up lots of memory. * -* #define RAYMATH_STANDALONE -* Avoid raylib.h header inclusion in this file. -* Vector3 and Matrix data types are defined internally in raymath module. -* * * LICENSE: zlib/libpng * @@ -42,15 +38,8 @@ #ifndef RAYMATH_H #define RAYMATH_H -//#define RAYMATH_STANDALONE // NOTE: To use raymath as standalone lib, just uncomment this line -//#define RAYMATH_HEADER_ONLY // NOTE: To compile functions as static inline, uncomment this line - -#ifndef RAYMATH_STANDALONE - #include "raylib.h" // Required for: Vector3, Matrix structs definition -#endif - -#if defined(RAYMATH_IMPLEMENTATION) && defined(RAYMATH_HEADER_ONLY) - #error "Specifying both RAYMATH_IMPLEMENTATION and RAYMATH_HEADER_ONLY is contradictory" +#if defined(RAYMATH_IMPLEMENTATION) && defined(RAYMATH_STATIC_INLINE) + #error "Specifying both RAYMATH_IMPLEMENTATION and RAYMATH_STATIC_INLINE is contradictory" #endif #if defined(RAYMATH_IMPLEMENTATION) @@ -61,7 +50,7 @@ #else #define RMDEF extern inline // Provide external definition #endif -#elif defined(RAYMATH_HEADER_ONLY) +#elif defined(RAYMATH_STATIC_INLINE) #define RMDEF static inline // Functions may be inlined, no external out-of-line definition #else #if defined(__TINYC__) @@ -100,43 +89,61 @@ // Types and Structures Definition //---------------------------------------------------------------------------------- -#if defined(RAYMATH_STANDALONE) - // Vector2 type - typedef struct Vector2 { - float x; - float y; - } Vector2; +#if !defined(RL_VECTOR2_TYPE) +// Vector2 type +typedef struct Vector2 { + float x; + float y; +} Vector2; +#define RL_VECTOR2_TYPE +#endif - // Vector3 type - typedef struct Vector3 { - float x; - float y; - float z; - } Vector3; +#if !defined(RL_VECTOR3_TYPE) +// Vector3 type +typedef struct Vector3 { + float x; + float y; + float z; +} Vector3; +#define RL_VECTOR3_TYPE +#endif - // Vector4 type - typedef struct Vector4 { - float x; - float y; - float z; - float w; - } Vector4; +#if !defined(RL_VECTOR4_TYPE) +// Vector4 type +typedef struct Vector4 { + float x; + float y; + float z; + float w; +} Vector4; +#define RL_VECTOR4_TYPE +#endif - // Quaternion type - typedef Vector4 Quaternion; +#if !defined(RL_QUATERNION_TYPE) +// Quaternion type +typedef Vector4 Quaternion; +#define RL_QUATERNION_TYPE +#endif - // Matrix type (OpenGL style 4x4 - right handed, column major) - typedef struct Matrix { - float m0, m4, m8, m12; - float m1, m5, m9, m13; - float m2, m6, m10, m14; - float m3, m7, m11, m15; - } Matrix; +#if !defined(RL_MATRIX_TYPE) +// Matrix type (OpenGL style 4x4 - right handed, column major) +typedef struct Matrix { + float m0, m4, m8, m12; // Matrix first row (4 components) + float m1, m5, m9, m13; // Matrix second row (4 components) + float m2, m6, m10, m14; // Matrix third row (4 components) + float m3, m7, m11, m15; // Matrix fourth row (4 components) +} Matrix; +#define RL_MATRIX_TYPE #endif // NOTE: Helper types to be used instead of array return types for *ToFloat functions -typedef struct float3 { float v[3]; } float3; -typedef struct float16 { float v[16]; } float16; +typedef struct float3 { + float v[3]; +} float3; + +typedef struct float16 { + float v[16]; +} float16; #include // Required for: sinf(), cosf(), tan(), atan2f(), sqrtf(), fminf(), fmaxf(), fabs() @@ -282,7 +289,11 @@ RMDEF Vector2 Vector2Divide(Vector2 v1, Vector2 v2) // Normalize provided vector RMDEF Vector2 Vector2Normalize(Vector2 v) { - Vector2 result = Vector2Scale(v, 1/Vector2Length(v)); + float length = Vector2Length(v); + if (length <= 0) + return v; + + Vector2 result = Vector2Scale(v, 1/length); return result; } @@ -479,14 +490,14 @@ RMDEF Vector3 Vector3Normalize(Vector3 v) { Vector3 result = v; - float length, ilength; - length = Vector3Length(v); + float length, inverseLength; + length = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z); if (length == 0.0f) length = 1.0f; - ilength = 1.0f/length; + inverseLength = 1.0f/length; - result.x *= ilength; - result.y *= ilength; - result.z *= ilength; + result.x *= inverseLength; + result.y *= inverseLength; + result.z *= inverseLength; return result; } @@ -1420,22 +1431,24 @@ RMDEF Matrix QuaternionToMatrix(Quaternion q) RMDEF Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle) { Quaternion result = { 0.0f, 0.0f, 0.0f, 1.0f }; + float axisLength = sqrtf(axis.x*axis.x + axis.y*axis.y + axis.z*axis.z); + + if (axisLength != 0.0f) + { + angle *= 0.5f; - if (Vector3Length(axis) != 0.0f) + axis = Vector3Normalize(axis); - angle *= 0.5f; + float sinres = sinf(angle); + float cosres = cosf(angle); - axis = Vector3Normalize(axis); + result.x = axis.x*sinres; + result.y = axis.y*sinres; + result.z = axis.z*sinres; + result.w = cosres; - float sinres = sinf(angle); - float cosres = cosf(angle); - - result.x = axis.x*sinres; - result.y = axis.y*sinres; - result.z = axis.z*sinres; - result.w = cosres; - - result = QuaternionNormalize(result); + result = QuaternionNormalize(result); + } return result; } diff --git a/src/rlgl.h b/src/rlgl.h index a2d890e60..76b5114af 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -1,14 +1,23 @@ /********************************************************************************************** * -* rlgl v3.7 - raylib OpenGL abstraction layer +* rlgl v4.0 * -* rlgl is a wrapper for multiple OpenGL versions (1.1, 2.1, 3.3 Core, ES 2.0) to -* pseudo-OpenGL 1.1 style functions (rlVertex, rlTranslate, rlRotate...). +* An abstraction layer for multiple OpenGL versions (1.1, 2.1, 3.3 Core, ES 2.0) +* that provides a pseudo-OpenGL 1.1 immediate-mode style API (rlVertex, rlTranslate, rlRotate...) +* +* When chosing an OpenGL backend different than OpenGL 1.1, some internal buffer are +* initialized on rlglInit() to accumulate vertex data. +* +* When an internal state change is required all the stored vertex data is renderer in batch, +* additioanlly, rlDrawRenderBatchActive() could be called to force flushing of the batch. +* +* Some additional resources are also loaded for convenience, here the complete list: +* - Default batch (RLGL.defaultBatch): RenderBatch system to accumulate vertex data +* - Default texture (RLGL.defaultTextureId): 1x1 white pixel R8G8B8A8 +* - Default shader (RLGL.State.defaultShaderId, RLGL.State.defaultShaderLocs) +* +* Internal buffer (and additional resources) must be manually unloaded calling rlglClose(). * -* When chosing an OpenGL version greater than OpenGL 1.1, rlgl stores vertex data on internal -* VBO buffers (and VAOs if available). It requires calling 3 functions: -* rlglInit() - Initialize internal buffers and auxiliary resources -* rlglClose() - De-initialize internal buffers data and other auxiliar resources * * CONFIGURATION: * @@ -25,15 +34,49 @@ * If not defined, the library is in header only mode and can be included in other headers * or source files without problems. But only ONE file should hold the implementation. * -* #define RLGL_STANDALONE -* Use rlgl as standalone library (no raylib dependency) +* #define SUPPORT_RENDER_TEXTURES_HINT +* Enable framebuffer objects (fbo) support (enabled by default) +* Some GPUs could not support them despite the OpenGL version * * #define SUPPORT_GL_DETAILS_INFO * Show OpenGL extensions and capabilities detailed logs on init * +* rlgl capabilities could be customized just defining some internal +* values before library inclusion (default values listed): +* +* #define RL_DEFAULT_BATCH_BUFFER_ELEMENTS 8192 // Default internal render batch elements limits +* #define RL_DEFAULT_BATCH_BUFFERS 1 // Default number of batch buffers (multi-buffering) +* #define RL_DEFAULT_BATCH_DRAWCALLS 256 // Default number of batch draw calls (by state changes: mode, texture) +* #define RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS 4 // Maximum number of textures units that can be activated on batch drawing (SetShaderValueTexture()) +* +* #define RL_MAX_MATRIX_STACK_SIZE 32 // Maximum size of internal Matrix stack +* #define RL_MAX_SHADER_LOCATIONS 32 // Maximum number of shader locations supported +* #define RL_CULL_DISTANCE_NEAR 0.01 // Default projection matrix near cull distance +* #define RL_CULL_DISTANCE_FAR 1000.0 // Default projection matrix far cull distance +* +* When loading a shader, the following vertex attribute and uniform +* location names are tried to be set automatically: +* +* #define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION "vertexPosition" // Binded by default to shader location: 0 +* #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD "vertexTexCoord" // Binded by default to shader location: 1 +* #define RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL "vertexNormal" // Binded by default to shader location: 2 +* #define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR "vertexColor" // Binded by default to shader location: 3 +* #define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT "vertexTangent" // Binded by default to shader location: 4 +* #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Binded by default to shader location: 5 +* #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix +* #define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW "matView" // view matrix +* #define RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION "matProjection" // projection matrix +* #define RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL "matModel" // model matrix +* #define RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL "matNormal" // normal matrix (transpose(inverse(matModelView)) +* #define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color) +* #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0) +* #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1 "texture1" // texture1 (texture slot active 1) +* #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 "texture2" // texture2 (texture slot active 2) +* * DEPENDENCIES: -* raymath - 3D math functionality (Vector3, Matrix, Quaternion) -* GLAD - OpenGL extensions loading (OpenGL 3.3 Core only) +* +* - OpenGL libraries (depending on platform and OpenGL version selected) +* - GLAD OpenGL extensions loading library (only for OpenGL 3.3 Core) * * * LICENSE: zlib/libpng @@ -60,44 +103,39 @@ #ifndef RLGL_H #define RLGL_H -#if defined(RLGL_STANDALONE) - #define RAYMATH_STANDALONE - #define RAYMATH_HEADER_ONLY +#define SUPPORT_RENDER_TEXTURES_HINT +#ifndef RLAPI #define RLAPI // We are building or using rlgl as a static library (or Linux shared library) - - #if defined(_WIN32) - #if defined(BUILD_LIBTYPE_SHARED) - #define RLAPI __declspec(dllexport) // We are building raylib as a Win32 shared library (.dll) - #elif defined(USE_LIBTYPE_SHARED) - #define RLAPI __declspec(dllimport) // We are using raylib as a Win32 shared library (.dll) - #endif - #endif - - // Support TRACELOG macros - #if !defined(TRACELOG) - #define TRACELOG(level, ...) (void)0 - #define TRACELOGD(...) (void)0 - #endif - - // Allow custom memory allocators - #ifndef RL_MALLOC - #define RL_MALLOC(sz) malloc(sz) - #endif - #ifndef RL_CALLOC - #define RL_CALLOC(n,sz) calloc(n,sz) - #endif - #ifndef RL_REALLOC - #define RL_REALLOC(n,sz) realloc(n,sz) - #endif - #ifndef RL_FREE - #define RL_FREE(p) free(p) - #endif -#else - #include "raylib.h" // Required for: Shader, Texture2D #endif -#include "raymath.h" // Required for: Vector3, Matrix +#if defined(_WIN32) + #if defined(BUILD_LIBTYPE_SHARED) + #define RLAPI __declspec(dllexport) // We are building raylib as a Win32 shared library (.dll) + #elif defined(USE_LIBTYPE_SHARED) + #define RLAPI __declspec(dllimport) // We are using raylib as a Win32 shared library (.dll) + #endif +#endif + +// Support TRACELOG macros +#ifndef TRACELOG + #define TRACELOG(level, ...) (void)0 + #define TRACELOGD(...) (void)0 +#endif + +// Allow custom memory allocators +#ifndef RL_MALLOC + #define RL_MALLOC(sz) malloc(sz) +#endif +#ifndef RL_CALLOC + #define RL_CALLOC(n,sz) calloc(n,sz) +#endif +#ifndef RL_REALLOC + #define RL_REALLOC(n,sz) realloc(n,sz) +#endif +#ifndef RL_FREE + #define RL_FREE(p) free(p) +#endif // Security check in case no GRAPHICS_API_OPENGL_* defined #if !defined(GRAPHICS_API_OPENGL_11) && \ @@ -126,59 +164,50 @@ #define GRAPHICS_API_OPENGL_33 #endif -#define SUPPORT_RENDER_TEXTURES_HINT - //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- -// Default internal render batch limits -#ifndef DEFAULT_BATCH_BUFFER_ELEMENTS + +// Default internal render batch elements limits +#ifndef RL_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 + #define RL_DEFAULT_BATCH_BUFFER_ELEMENTS 8192 #endif #if 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 + #define RL_DEFAULT_BATCH_BUFFER_ELEMENTS 2048 #endif #endif -#ifndef DEFAULT_BATCH_BUFFERS - #define DEFAULT_BATCH_BUFFERS 1 // Default number of batch buffers (multi-buffering) +#ifndef RL_DEFAULT_BATCH_BUFFERS + #define RL_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) +#ifndef RL_DEFAULT_BATCH_DRAWCALLS + #define RL_DEFAULT_BATCH_DRAWCALLS 256 // Default number of batch draw calls (by state changes: mode, texture) #endif -#ifndef MAX_BATCH_ACTIVE_TEXTURES - #define MAX_BATCH_ACTIVE_TEXTURES 4 // Maximum number of additional textures that can be activated on batch drawing (SetShaderValueTexture()) +#ifndef RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS + #define RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS 4 // Maximum number of textures units that can be activated on batch drawing (SetShaderValueTexture()) #endif // Internal Matrix stack -#ifndef MAX_MATRIX_STACK_SIZE - #define MAX_MATRIX_STACK_SIZE 32 // Maximum size of Matrix stack +#ifndef RL_MAX_MATRIX_STACK_SIZE + #define RL_MAX_MATRIX_STACK_SIZE 32 // Maximum size of Matrix stack #endif -// Vertex buffers id limit -#ifndef MAX_MESH_VERTEX_BUFFERS - #define MAX_MESH_VERTEX_BUFFERS 7 // Maximum vertex buffers (VBO) per mesh -#endif - -// Shader and material limits -#ifndef MAX_SHADER_LOCATIONS - #define MAX_SHADER_LOCATIONS 32 // Maximum number of shader locations supported -#endif -#ifndef MAX_MATERIAL_MAPS - #define MAX_MATERIAL_MAPS 12 // Maximum number of shader maps supported +// Shader limits +#ifndef RL_MAX_SHADER_LOCATIONS + #define RL_MAX_SHADER_LOCATIONS 32 // Maximum number of shader locations supported #endif // Projection matrix culling #ifndef RL_CULL_DISTANCE_NEAR - #define RL_CULL_DISTANCE_NEAR 0.01 // Default near cull distance + #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 + #define RL_CULL_DISTANCE_FAR 1000.0 // Default far cull distance #endif // Texture parameters (equivalent to OpenGL defines) @@ -217,7 +246,12 @@ //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- -typedef enum { OPENGL_11 = 1, OPENGL_21, OPENGL_33, OPENGL_ES_20 } GlVersion; +typedef enum { + OPENGL_11 = 1, + OPENGL_21, + OPENGL_33, + OPENGL_ES_20 +} rlGlVersion; typedef enum { RL_ATTACHMENT_COLOR_CHANNEL0 = 0, @@ -230,7 +264,7 @@ typedef enum { RL_ATTACHMENT_COLOR_CHANNEL7, RL_ATTACHMENT_DEPTH = 100, RL_ATTACHMENT_STENCIL = 200, -} FramebufferAttachType; +} rlFramebufferAttachType; typedef enum { RL_ATTACHMENT_CUBEMAP_POSITIVE_X = 0, @@ -241,10 +275,10 @@ typedef enum { RL_ATTACHMENT_CUBEMAP_NEGATIVE_Z, RL_ATTACHMENT_TEXTURE2D = 100, RL_ATTACHMENT_RENDERBUFFER = 200, -} FramebufferAttachTextureType; +} rlFramebufferAttachTextureType; // Dynamic vertex buffers (position + texcoords + colors + indices arrays) -typedef struct VertexBuffer { +typedef struct rlVertexBuffer { int elementsCount; // Number of elements in the buffer (QUADS) int vCounter; // Vertex position counter to process (and draw) from full buffer @@ -262,180 +296,167 @@ typedef struct VertexBuffer { #endif unsigned int vaoId; // OpenGL Vertex Array Object id unsigned int vboId[4]; // OpenGL Vertex Buffer Objects id (4 types of vertex data) -} VertexBuffer; +} rlVertexBuffer; // 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 { +typedef struct rlDrawCall { 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 -> Using RLGL.currentBatch->vertexBuffer.vaoId - //unsigned int shaderId; // Shader id to be used on the draw -> Using RLGL.currentShader.id + //unsigned int shaderId; // Shader id to be used on the draw -> Using RLGL.currentShaderId unsigned int textureId; // Texture id to be used on the draw -> Use to create new draw call if changes - //Matrix projection; // Projection matrix for this draw -> Using RLGL.projection by default - //Matrix modelview; // Modelview matrix for this draw -> Using RLGL.modelview by default -} DrawCall; + //Matrix projection; // Projection matrix for this draw -> Using RLGL.projection by default + //Matrix modelview; // Modelview matrix for this draw -> Using RLGL.modelview by default +} rlDrawCall; -// RenderBatch type -typedef struct RenderBatch { +// rlRenderBatch type +typedef struct rlRenderBatch { 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 + rlVertexBuffer *vertexBuffer; // Dynamic buffer(s) for vertex data - DrawCall *draws; // Draw calls array, depends on textureId + rlDrawCall *draws; // Draw calls array, depends on textureId int drawsCounter; // Draw calls counter float currentDepth; // Current depth value for next draw -} RenderBatch; +} rlRenderBatch; -#if defined(RLGL_STANDALONE) - #ifndef __cplusplus +#if defined(__STDC__) && __STDC_VERSION__ >= 199901L + #include +#elif !defined(__cplusplus) && !defined(bool) && !defined(RL_BOOL_TYPE) // Boolean type - typedef enum { false, true } bool; - #endif - - // Texture type - // NOTE: Data stored in GPU memory - typedef struct Texture2D { - unsigned int id; // OpenGL texture id - int width; // Texture base width - int height; // Texture base height - int mipmaps; // Mipmap levels, 1 by default - int format; // Data format (PixelFormat) - } Texture2D; - - // Shader type (generic) - typedef struct Shader { - unsigned int id; // Shader program id - int *locs; // Shader locations array (MAX_SHADER_LOCATIONS) - } Shader; - - // Trace log level - // NOTE: Organized by priority level - typedef enum { - LOG_ALL = 0, // Display all logs - LOG_TRACE, // Trace logging, intended for internal use only - LOG_DEBUG, // Debug logging, used for internal debugging, it should be disabled on release builds - LOG_INFO, // Info logging, used for program execution info - LOG_WARNING, // Warning logging, used on recoverable failures - LOG_ERROR, // Error logging, used on unrecoverable failures - LOG_FATAL, // Fatal logging, used to abort program: exit(EXIT_FAILURE) - LOG_NONE // Disable logging - } TraceLogLevel; - - // Texture formats (support depends on OpenGL version) - typedef enum { - PIXELFORMAT_UNCOMPRESSED_GRAYSCALE = 1, // 8 bit per pixel (no alpha) - PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA, // 8*2 bpp (2 channels) - PIXELFORMAT_UNCOMPRESSED_R5G6B5, // 16 bpp - PIXELFORMAT_UNCOMPRESSED_R8G8B8, // 24 bpp - PIXELFORMAT_UNCOMPRESSED_R5G5B5A1, // 16 bpp (1 bit alpha) - PIXELFORMAT_UNCOMPRESSED_R4G4B4A4, // 16 bpp (4 bit alpha) - PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, // 32 bpp - PIXELFORMAT_UNCOMPRESSED_R32, // 32 bpp (1 channel - float) - PIXELFORMAT_UNCOMPRESSED_R32G32B32, // 32*3 bpp (3 channels - float) - PIXELFORMAT_UNCOMPRESSED_R32G32B32A32, // 32*4 bpp (4 channels - float) - PIXELFORMAT_COMPRESSED_DXT1_RGB, // 4 bpp (no alpha) - PIXELFORMAT_COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha) - PIXELFORMAT_COMPRESSED_DXT3_RGBA, // 8 bpp - PIXELFORMAT_COMPRESSED_DXT5_RGBA, // 8 bpp - PIXELFORMAT_COMPRESSED_ETC1_RGB, // 4 bpp - PIXELFORMAT_COMPRESSED_ETC2_RGB, // 4 bpp - PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA, // 8 bpp - PIXELFORMAT_COMPRESSED_PVRT_RGB, // 4 bpp - PIXELFORMAT_COMPRESSED_PVRT_RGBA, // 4 bpp - PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA, // 8 bpp - PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA // 2 bpp - } PixelFormat; - - // Texture parameters: filter mode - // NOTE 1: Filtering considers mipmaps if available in the texture - // NOTE 2: Filter is accordingly set for minification and magnification - typedef enum { - TEXTURE_FILTER_POINT = 0, // No filter, just pixel aproximation - TEXTURE_FILTER_BILINEAR, // Linear filtering - TEXTURE_FILTER_TRILINEAR, // Trilinear filtering (linear with mipmaps) - TEXTURE_FILTER_ANISOTROPIC_4X, // Anisotropic filtering 4x - TEXTURE_FILTER_ANISOTROPIC_8X, // Anisotropic filtering 8x - TEXTURE_FILTER_ANISOTROPIC_16X, // Anisotropic filtering 16x - } TextureFilter; - - // Texture parameters: wrap mode - typedef enum { - TEXTURE_WRAP_REPEAT = 0, // Repeats texture in tiled mode - TEXTURE_WRAP_CLAMP, // Clamps texture to edge pixel in tiled mode - TEXTURE_WRAP_MIRROR_REPEAT, // Mirrors and repeats the texture in tiled mode - TEXTURE_WRAP_MIRROR_CLAMP // Mirrors and clamps to border the texture in tiled mode - } TextureWrap; - - // Color blending modes (pre-defined) - typedef enum { - BLEND_ALPHA = 0, // Blend textures considering alpha (default) - BLEND_ADDITIVE, // Blend textures adding colors - BLEND_MULTIPLIED, // Blend textures multiplying colors - BLEND_ADD_COLORS, // Blend textures adding colors (alternative) - BLEND_SUBTRACT_COLORS, // Blend textures subtracting colors (alternative) - BLEND_CUSTOM // Belnd textures using custom src/dst factors (use SetBlendModeCustom()) - } BlendMode; - - // Shader location point type - typedef enum { - SHADER_LOC_VERTEX_POSITION = 0, // Shader location: vertex attribute: position - SHADER_LOC_VERTEX_TEXCOORD01, // Shader location: vertex attribute: texcoord01 - SHADER_LOC_VERTEX_TEXCOORD02, // Shader location: vertex attribute: texcoord02 - SHADER_LOC_VERTEX_NORMAL, // Shader location: vertex attribute: normal - SHADER_LOC_VERTEX_TANGENT, // Shader location: vertex attribute: tangent - SHADER_LOC_VERTEX_COLOR, // Shader location: vertex attribute: color - SHADER_LOC_MATRIX_MVP, // Shader location: matrix uniform: model-view-projection - SHADER_LOC_MATRIX_VIEW, // Shader location: matrix uniform: view (camera transform) - SHADER_LOC_MATRIX_PROJECTION, // Shader location: matrix uniform: projection - SHADER_LOC_MATRIX_MODEL, // Shader location: matrix uniform: model (transform) - SHADER_LOC_MATRIX_NORMAL, // Shader location: matrix uniform: normal - SHADER_LOC_VECTOR_VIEW, // Shader location: vector uniform: view - SHADER_LOC_COLOR_DIFFUSE, // Shader location: vector uniform: diffuse color - SHADER_LOC_COLOR_SPECULAR, // Shader location: vector uniform: specular color - SHADER_LOC_COLOR_AMBIENT, // Shader location: vector uniform: ambient color - SHADER_LOC_MAP_ALBEDO, // Shader location: sampler2d texture: albedo (same as: SHADER_LOC_MAP_DIFFUSE) - SHADER_LOC_MAP_METALNESS, // Shader location: sampler2d texture: metalness (same as: SHADER_LOC_MAP_SPECULAR) - SHADER_LOC_MAP_NORMAL, // Shader location: sampler2d texture: normal - SHADER_LOC_MAP_ROUGHNESS, // Shader location: sampler2d texture: roughness - SHADER_LOC_MAP_OCCLUSION, // Shader location: sampler2d texture: occlusion - SHADER_LOC_MAP_EMISSION, // Shader location: sampler2d texture: emission - SHADER_LOC_MAP_HEIGHT, // Shader location: sampler2d texture: height - SHADER_LOC_MAP_CUBEMAP, // Shader location: samplerCube texture: cubemap - SHADER_LOC_MAP_IRRADIANCE, // Shader location: samplerCube texture: irradiance - SHADER_LOC_MAP_PREFILTER, // Shader location: samplerCube texture: prefilter - SHADER_LOC_MAP_BRDF // Shader location: sampler2d texture: brdf - } ShaderLocationIndex; - - #define SHADER_LOC_MAP_DIFFUSE SHADER_LOC_MAP_ALBEDO - #define SHADER_LOC_MAP_SPECULAR SHADER_LOC_MAP_METALNESS - - // Shader uniform data type - typedef enum { - SHADER_UNIFORM_FLOAT = 0, // Shader uniform type: float - SHADER_UNIFORM_VEC2, // Shader uniform type: vec2 (2 float) - SHADER_UNIFORM_VEC3, // Shader uniform type: vec3 (3 float) - SHADER_UNIFORM_VEC4, // Shader uniform type: vec4 (4 float) - SHADER_UNIFORM_INT, // Shader uniform type: int - SHADER_UNIFORM_IVEC2, // Shader uniform type: ivec2 (2 int) - SHADER_UNIFORM_IVEC3, // Shader uniform type: ivec3 (3 int) - SHADER_UNIFORM_IVEC4, // Shader uniform type: ivec4 (4 int) - SHADER_UNIFORM_SAMPLER2D // Shader uniform type: sampler2d - } ShaderUniformDataType; - - // Shader attribute data types - typedef enum { - SHADER_ATTRIB_FLOAT = 0, // Shader attribute type: float - SHADER_ATTRIB_VEC2, // Shader attribute type: vec2 (2 float) - SHADER_ATTRIB_VEC3, // Shader attribute type: vec3 (3 float) - SHADER_ATTRIB_VEC4 // Shader attribute type: vec4 (4 float) - } ShaderAttributeDataType; + typedef enum bool { false, true } bool; #endif +#if !defined(RL_MATRIX_TYPE) +// Matrix, 4x4 components, column major, OpenGL style, right handed +typedef struct Matrix { + float m0, m4, m8, m12; // Matrix first row (4 components) + float m1, m5, m9, m13; // Matrix second row (4 components) + float m2, m6, m10, m14; // Matrix third row (4 components) + float m3, m7, m11, m15; // Matrix fourth row (4 components) +} Matrix; +#define RL_MATRIX_TYPE +#endif + +// Trace log level +// NOTE: Organized by priority level +typedef enum { + RL_LOG_ALL = 0, // Display all logs + RL_LOG_TRACE, // Trace logging, intended for internal use only + RL_LOG_DEBUG, // Debug logging, used for internal debugging, it should be disabled on release builds + RL_LOG_INFO, // Info logging, used for program execution info + RL_LOG_WARNING, // Warning logging, used on recoverable failures + RL_LOG_ERROR, // Error logging, used on unrecoverable failures + RL_LOG_FATAL, // Fatal logging, used to abort program: exit(EXIT_FAILURE) + RL_LOG_NONE // Disable logging +} rlTraceLogLevel; + +// Texture formats (support depends on OpenGL version) +typedef enum { + RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE = 1, // 8 bit per pixel (no alpha) + RL_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA, // 8*2 bpp (2 channels) + RL_PIXELFORMAT_UNCOMPRESSED_R5G6B5, // 16 bpp + RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8, // 24 bpp + RL_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1, // 16 bpp (1 bit alpha) + RL_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4, // 16 bpp (4 bit alpha) + RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, // 32 bpp + RL_PIXELFORMAT_UNCOMPRESSED_R32, // 32 bpp (1 channel - float) + RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32, // 32*3 bpp (3 channels - float) + RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32, // 32*4 bpp (4 channels - float) + RL_PIXELFORMAT_COMPRESSED_DXT1_RGB, // 4 bpp (no alpha) + RL_PIXELFORMAT_COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha) + RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA, // 8 bpp + RL_PIXELFORMAT_COMPRESSED_DXT5_RGBA, // 8 bpp + RL_PIXELFORMAT_COMPRESSED_ETC1_RGB, // 4 bpp + RL_PIXELFORMAT_COMPRESSED_ETC2_RGB, // 4 bpp + RL_PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA, // 8 bpp + RL_PIXELFORMAT_COMPRESSED_PVRT_RGB, // 4 bpp + RL_PIXELFORMAT_COMPRESSED_PVRT_RGBA, // 4 bpp + RL_PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA, // 8 bpp + RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA // 2 bpp +} rlPixelFormat; + +// Texture parameters: filter mode +// NOTE 1: Filtering considers mipmaps if available in the texture +// NOTE 2: Filter is accordingly set for minification and magnification +typedef enum { + RL_TEXTURE_FILTER_POINT = 0, // No filter, just pixel aproximation + RL_TEXTURE_FILTER_BILINEAR, // Linear filtering + RL_TEXTURE_FILTER_TRILINEAR, // Trilinear filtering (linear with mipmaps) + RL_TEXTURE_FILTER_ANISOTROPIC_4X, // Anisotropic filtering 4x + RL_TEXTURE_FILTER_ANISOTROPIC_8X, // Anisotropic filtering 8x + RL_TEXTURE_FILTER_ANISOTROPIC_16X, // Anisotropic filtering 16x +} rlTextureFilter; + +// Color blending modes (pre-defined) +typedef enum { + RL_BLEND_ALPHA = 0, // Blend textures considering alpha (default) + RL_BLEND_ADDITIVE, // Blend textures adding colors + RL_BLEND_MULTIPLIED, // Blend textures multiplying colors + RL_BLEND_ADD_COLORS, // Blend textures adding colors (alternative) + RL_BLEND_SUBTRACT_COLORS, // Blend textures subtracting colors (alternative) + RL_BLEND_CUSTOM // Belnd textures using custom src/dst factors (use SetBlendModeCustom()) +} rlBlendMode; + +// Shader location point type +typedef enum { + RL_SHADER_LOC_VERTEX_POSITION = 0, // Shader location: vertex attribute: position + RL_SHADER_LOC_VERTEX_TEXCOORD01, // Shader location: vertex attribute: texcoord01 + RL_SHADER_LOC_VERTEX_TEXCOORD02, // Shader location: vertex attribute: texcoord02 + RL_SHADER_LOC_VERTEX_NORMAL, // Shader location: vertex attribute: normal + RL_SHADER_LOC_VERTEX_TANGENT, // Shader location: vertex attribute: tangent + RL_SHADER_LOC_VERTEX_COLOR, // Shader location: vertex attribute: color + RL_SHADER_LOC_MATRIX_MVP, // Shader location: matrix uniform: model-view-projection + RL_SHADER_LOC_MATRIX_VIEW, // Shader location: matrix uniform: view (camera transform) + RL_SHADER_LOC_MATRIX_PROJECTION, // Shader location: matrix uniform: projection + RL_SHADER_LOC_MATRIX_MODEL, // Shader location: matrix uniform: model (transform) + RL_SHADER_LOC_MATRIX_NORMAL, // Shader location: matrix uniform: normal + RL_SHADER_LOC_VECTOR_VIEW, // Shader location: vector uniform: view + RL_SHADER_LOC_COLOR_DIFFUSE, // Shader location: vector uniform: diffuse color + RL_SHADER_LOC_COLOR_SPECULAR, // Shader location: vector uniform: specular color + RL_SHADER_LOC_COLOR_AMBIENT, // Shader location: vector uniform: ambient color + RL_SHADER_LOC_MAP_ALBEDO, // Shader location: sampler2d texture: albedo (same as: RL_SHADER_LOC_MAP_DIFFUSE) + RL_SHADER_LOC_MAP_METALNESS, // Shader location: sampler2d texture: metalness (same as: RL_SHADER_LOC_MAP_SPECULAR) + RL_SHADER_LOC_MAP_NORMAL, // Shader location: sampler2d texture: normal + RL_SHADER_LOC_MAP_ROUGHNESS, // Shader location: sampler2d texture: roughness + RL_SHADER_LOC_MAP_OCCLUSION, // Shader location: sampler2d texture: occlusion + RL_SHADER_LOC_MAP_EMISSION, // Shader location: sampler2d texture: emission + RL_SHADER_LOC_MAP_HEIGHT, // Shader location: sampler2d texture: height + RL_SHADER_LOC_MAP_CUBEMAP, // Shader location: samplerCube texture: cubemap + RL_SHADER_LOC_MAP_IRRADIANCE, // Shader location: samplerCube texture: irradiance + RL_SHADER_LOC_MAP_PREFILTER, // Shader location: samplerCube texture: prefilter + RL_SHADER_LOC_MAP_BRDF // Shader location: sampler2d texture: brdf +} rlShaderLocationIndex; + +#define RL_SHADER_LOC_MAP_DIFFUSE RL_SHADER_LOC_MAP_ALBEDO +#define RL_SHADER_LOC_MAP_SPECULAR RL_SHADER_LOC_MAP_METALNESS + +// Shader uniform data type +typedef enum { + RL_SHADER_UNIFORM_FLOAT = 0, // Shader uniform type: float + RL_SHADER_UNIFORM_VEC2, // Shader uniform type: vec2 (2 float) + RL_SHADER_UNIFORM_VEC3, // Shader uniform type: vec3 (3 float) + RL_SHADER_UNIFORM_VEC4, // Shader uniform type: vec4 (4 float) + RL_SHADER_UNIFORM_INT, // Shader uniform type: int + RL_SHADER_UNIFORM_IVEC2, // Shader uniform type: ivec2 (2 int) + RL_SHADER_UNIFORM_IVEC3, // Shader uniform type: ivec3 (3 int) + RL_SHADER_UNIFORM_IVEC4, // Shader uniform type: ivec4 (4 int) + RL_SHADER_UNIFORM_SAMPLER2D // Shader uniform type: sampler2d +} rlShaderUniformDataType; + +// Shader attribute data types +typedef enum { + RL_SHADER_ATTRIB_FLOAT = 0, // Shader attribute type: float + RL_SHADER_ATTRIB_VEC2, // Shader attribute type: vec2 (2 float) + RL_SHADER_ATTRIB_VEC3, // Shader attribute type: vec3 (3 float) + RL_SHADER_ATTRIB_VEC4 // Shader attribute type: vec4 (4 float) +} rlShaderAttributeDataType; + #if defined(__cplusplus) extern "C" { // Prevents name mangling of functions #endif @@ -448,7 +469,7 @@ RLAPI void rlPushMatrix(void); // Push the current matrix RLAPI void rlPopMatrix(void); // Pop lattest inserted matrix from stack RLAPI void rlLoadIdentity(void); // Reset current matrix to identity matrix RLAPI void rlTranslatef(float x, float y, float z); // Multiply the current matrix by a translation matrix -RLAPI void rlRotatef(float angleDeg, float x, float y, float z); // Multiply the current matrix by a rotation matrix +RLAPI void rlRotatef(float angle, float x, float y, float z); // Multiply the current matrix by a rotation matrix RLAPI void rlScalef(float x, float y, float z); // Multiply the current matrix by a scaling matrix RLAPI void rlMultMatrixf(float *matf); // Multiply the current matrix by another matrix RLAPI void rlFrustum(double left, double right, double bottom, double top, double znear, double zfar); @@ -542,18 +563,19 @@ RLAPI int rlGetVersion(void); // Get current OpenGL vers RLAPI int rlGetFramebufferWidth(void); // Get default framebuffer width RLAPI int rlGetFramebufferHeight(void); // Get default framebuffer height -RLAPI Shader rlGetShaderDefault(void); // Get default shader -RLAPI Texture2D rlGetTextureDefault(void); // Get default texture +RLAPI unsigned int rlGetTextureIdDefault(void); // Get default texture id +RLAPI unsigned int rlGetShaderIdDefault(void); // Get default shader id +RLAPI int *rlGetShaderLocsDefault(void); // Get default shader locations // Render batch management // NOTE: rlgl provides a default render batch to behave like OpenGL 1.1 immediate mode // but this render batch API is exposed in case of custom batches are required -RLAPI RenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements); // Load a render batch system -RLAPI void rlUnloadRenderBatch(RenderBatch batch); // Unload render batch system -RLAPI void rlDrawRenderBatch(RenderBatch *batch); // Draw render batch data (Update->Draw->Reset) -RLAPI void rlSetRenderBatchActive(RenderBatch *batch); // Set the active render batch for rlgl (NULL for default internal) -RLAPI void rlDrawRenderBatchActive(void); // Update and draw internal render batch -RLAPI bool rlCheckRenderBatchLimit(int vCount); // Check internal buffer overflow for a given number of vertex +RLAPI rlRenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements); // Load a render batch system +RLAPI void rlUnloadRenderBatch(rlRenderBatch batch); // Unload render batch system +RLAPI void rlDrawRenderBatch(rlRenderBatch *batch); // Draw render batch data (Update->Draw->Reset) +RLAPI void rlSetRenderBatchActive(rlRenderBatch *batch); // Set the active render batch for rlgl (NULL for default internal) +RLAPI void rlDrawRenderBatchActive(void); // Update and draw internal render batch +RLAPI bool rlCheckRenderBatchLimit(int vCount); // Check internal buffer overflow for a given number of vertex RLAPI void rlSetTexture(unsigned int id); // Set current texture for render batch and check buffers limits //------------------------------------------------------------------------------------------------------------------------ @@ -581,8 +603,8 @@ RLAPI void rlUpdateTexture(unsigned int id, int offsetX, int offsetY, int width, RLAPI void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned int *glFormat, unsigned int *glType); // Get OpenGL internal formats RLAPI const char *rlGetPixelFormatName(unsigned int format); // Get name string for pixel format RLAPI void rlUnloadTexture(unsigned int id); // Unload texture from GPU memory -RLAPI void rlGenerateMipmaps(Texture2D *texture); // Generate mipmap data for selected texture -RLAPI void *rlReadTexturePixels(Texture2D texture); // Read texture pixel data +RLAPI void rlGenTextureMipmaps(unsigned int id, int width, int height, int format, int *mipmaps); // Generate mipmap data for selected texture +RLAPI void *rlReadTexturePixels(unsigned int id, int width, int height, int format); // Read texture pixel data RLAPI unsigned char *rlReadScreenPixels(int width, int height); // Read screen pixel data (color buffer) // Framebuffer management (fbo) @@ -599,9 +621,9 @@ RLAPI void rlUnloadShaderProgram(unsigned int id); RLAPI int rlGetLocationUniform(unsigned int shaderId, const char *uniformName); // Get shader location uniform RLAPI int rlGetLocationAttrib(unsigned int shaderId, const char *attribName); // Get shader location attribute RLAPI void rlSetUniform(int locIndex, const void *value, int uniformType, int count); // Set shader value uniform -RLAPI void rlSetUniformMatrix(int locIndex, Matrix mat); // Set shader value matrix +RLAPI void rlSetUniformMatrix(int locIndex, Matrix mat); // Set shader value matrix RLAPI void rlSetUniformSampler(int locIndex, unsigned int textureId); // Set shader value sampler -RLAPI void rlSetShader(Shader shader); // Set shader currently active +RLAPI void rlSetShader(unsigned int id, int *locs); // Set shader currently active (id and locations) // Matrix state management RLAPI Matrix rlGetMatrixModelview(void); // Get internal modelview matrix @@ -611,8 +633,8 @@ RLAPI Matrix rlGetMatrixProjectionStereo(int eye); // Get RLAPI Matrix rlGetMatrixViewOffsetStereo(int eye); // Get internal view offset matrix for stereo render (selected eye) RLAPI void rlSetMatrixProjection(Matrix proj); // Set a custom projection matrix (replaces internal projection matrix) RLAPI void rlSetMatrixModelview(Matrix view); // Set a custom modelview matrix (replaces internal modelview matrix) -RLAPI void rlSetMatrixProjectionStereo(Matrix right, Matrix left); // Set eyes projection matrices for stereo rendering -RLAPI void rlSetMatrixViewOffsetStereo(Matrix right, Matrix left); // Set eyes view offsets matrices for stereo rendering +RLAPI void rlSetMatrixProjectionStereo(Matrix right, Matrix left); // Set eyes projection matrices for stereo rendering +RLAPI void rlSetMatrixViewOffsetStereo(Matrix right, Matrix left); // Set eyes view offsets matrices for stereo rendering // Quick and dirty cube/quad buffers load->draw->unload RLAPI void rlLoadDrawCube(void); // Load and draw a cube @@ -631,17 +653,6 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad #if defined(RLGL_IMPLEMENTATION) -#if !defined(RLGL_STANDALONE) - // Check if config flags have been externally provided on compilation line - #if !defined(EXTERNAL_CONFIG_FLAGS) - #include "config.h" // Defines module configuration flags - #endif - #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] - #if defined(GRAPHICS_API_OPENGL_11) #if defined(__APPLE__) #include // OpenGL 1.1 library for OSX @@ -673,11 +684,7 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad #define GLAD_FREE RL_FREE #define GLAD_IMPLEMENTATION - #if defined(RLGL_STANDALONE) - #include "glad.h" // GLAD extensions loading library, includes OpenGL headers - #else - #include "external/glad.h" // GLAD extensions loading library, includes OpenGL headers - #endif + #include "external/glad.h" // GLAD extensions loading library, includes OpenGL headers #endif #endif @@ -696,9 +703,23 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad #endif #endif +#include // Required for: malloc(), free() +#include // Required for: strcmp(), strlen() [Used in rlglInit(), on extensions loading] +#include // Required for: sqrtf(), sinf(), cosf(), floor(), log() + //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- +#ifndef PI + #define PI 3.14159265358979323846f +#endif +#ifndef DEG2RAD + #define DEG2RAD (PI/180.0f) +#endif +#ifndef RAD2DEG + #define RAD2DEG (180.0f/PI) +#endif + #ifndef GL_SHADING_LANGUAGE_VERSION #define GL_SHADING_LANGUAGE_VERSION 0x8B8C #endif @@ -762,51 +783,51 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad #endif // 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 +#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION + #define RL_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 +#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD + #define RL_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 +#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL + #define RL_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 +#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR + #define RL_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 +#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT + #define RL_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 +#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 + #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Binded by default to shader location: 5 #endif -#ifndef DEFAULT_SHADER_UNIFORM_NAME_MVP - #define DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix +#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_MVP + #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix #endif -#ifndef DEFAULT_SHADER_UNIFORM_NAME_VIEW - #define DEFAULT_SHADER_UNIFORM_NAME_VIEW "matView" // view matrix +#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW + #define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW "matView" // view matrix #endif -#ifndef DEFAULT_SHADER_UNIFORM_NAME_PROJECTION - #define DEFAULT_SHADER_UNIFORM_NAME_PROJECTION "matProjection" // projection matrix +#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION + #define RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION "matProjection" // projection matrix #endif -#ifndef DEFAULT_SHADER_UNIFORM_NAME_MODEL - #define DEFAULT_SHADER_UNIFORM_NAME_MODEL "matModel" // model matrix +#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL + #define RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL "matModel" // model matrix #endif -#ifndef DEFAULT_SHADER_UNIFORM_NAME_NORMAL - #define DEFAULT_SHADER_UNIFORM_NAME_NORMAL "matNormal" // normal matrix (transpose(inverse(matModelView)) +#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL + #define RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL "matNormal" // normal matrix (transpose(inverse(matModelView)) #endif -#ifndef DEFAULT_SHADER_UNIFORM_NAME_COLOR - #define DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color) +#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR + #define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color) #endif -#ifndef DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 - #define DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0) +#ifndef RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 + #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0) #endif -#ifndef DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1 - #define DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1 "texture1" // texture1 (texture slot active 1) +#ifndef RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1 + #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1 "texture1" // texture1 (texture slot active 1) #endif -#ifndef DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 - #define DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 "texture2" // texture2 (texture slot active 2) +#ifndef RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 + #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 "texture2" // texture2 (texture slot active 2) #endif //---------------------------------------------------------------------------------- @@ -814,29 +835,31 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad //---------------------------------------------------------------------------------- #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 + rlRenderBatch *currentBatch; // Current render batch + rlRenderBatch 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 + 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 transformRequired; // Require transform matrix application to current draw-call vertex (if required) - Matrix stack[MAX_MATRIX_STACK_SIZE];// Matrix stack for push/pop + Matrix stack[RL_MAX_MATRIX_STACK_SIZE];// Matrix stack for push/pop int stackCounter; // Matrix stack counter unsigned int defaultTextureId; // Default texture used on shapes/poly drawing (required by shader) - unsigned int activeTextureId[MAX_BATCH_ACTIVE_TEXTURES]; // Active texture ids to be enabled on batch drawing (0 active by default) + unsigned int activeTextureId[RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS]; // Active texture ids to be enabled on batch drawing (0 active by default) unsigned int defaultVShaderId; // Default vertex shader id (used by default shader program) - 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) + unsigned int defaultFShaderId; // Default fragment shader id (used by default shader program) + unsigned int defaultShaderId; // Default shader program id, supports vertex color and diffuse texture + int *defaultShaderLocs; // Default shader locations pointer to be used on rendering + unsigned int currentShaderId; // Current shader id to be used on rendering (by default, defaultShaderId) + int *currentShaderLocs; // Current shader locations pointer to be used on rendering (by default, defaultShaderLocs) bool stereoRender; // Stereo rendering flag - Matrix projectionStereo[2]; // VR stereo rendering eyes projection matrices - Matrix viewOffsetStereo[2]; // VR stereo rendering eyes view offset matrices + Matrix projectionStereo[2]; // VR stereo rendering eyes projection matrices + Matrix viewOffsetStereo[2]; // VR stereo rendering eyes view offset matrices int currentBlendMode; // Blending mode active int glBlendSrcFactor; // Blending source factor @@ -894,17 +917,20 @@ static PFNGLVERTEXATTRIBDIVISOREXTPROC glVertexAttribDivisor = NULL; // Module specific Functions Declaration //---------------------------------------------------------------------------------- #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) -static void rlLoadShaderDefault(void); // Load default shader (RLGL.State.defaultShader) -static void rlUnloadShaderDefault(void); // Unload default shader (RLGL.State.defaultShader) +static void rlLoadShaderDefault(void); // Load default shader +static void rlUnloadShaderDefault(void); // Unload default shader #if defined(SUPPORT_GL_DETAILS_INFO) static char *rlGetCompressedFormatName(int format); // Get compressed format official GL identifier name #endif // SUPPORT_GL_DETAILS_INFO #endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2 #if defined(GRAPHICS_API_OPENGL_11) -static int rlGenerateMipmapsData(unsigned char *data, int baseWidth, int baseHeight); // Generate mipmaps data on CPU side +static int rlGenTextureMipmapsData(unsigned char *data, int baseWidth, int baseHeight); // Generate mipmaps data on CPU side static unsigned char *rlGenNextMipmapData(unsigned char *srcData, int srcWidth, int srcHeight); // Generate next mipmap level on CPU side #endif static int rlGetPixelDataSize(int width, int height, int format); // Get pixel data size in bytes (image or texture) +// Auxiliar matrix math functions +static Matrix rlMatrixIdentity(void); // Get identity matrix +static Matrix rlMatrixMultiply(Matrix left, Matrix right); // Multiply two matrices //---------------------------------------------------------------------------------- // Module Functions Definition - Matrix operations @@ -938,7 +964,7 @@ void rlPushMatrix(void) { glPushMatrix(); } void rlPopMatrix(void) { glPopMatrix(); } void rlLoadIdentity(void) { glLoadIdentity(); } void rlTranslatef(float x, float y, float z) { glTranslatef(x, y, z); } -void rlRotatef(float angleDeg, float x, float y, float z) { glRotatef(angleDeg, x, y, z); } +void rlRotatef(float angle, float x, float y, float z) { glRotatef(angle, x, y, z); } void rlScalef(float x, float y, float z) { glScalef(x, y, z); } void rlMultMatrixf(float *matf) { glMultMatrixf(matf); } #endif @@ -956,7 +982,7 @@ void rlMatrixMode(int mode) // Push the current matrix into RLGL.State.stack void rlPushMatrix(void) { - if (RLGL.State.stackCounter >= MAX_MATRIX_STACK_SIZE) TRACELOG(LOG_ERROR, "RLGL: Matrix stack overflow (MAX_MATRIX_STACK_SIZE)"); + if (RLGL.State.stackCounter >= RL_MAX_MATRIX_STACK_SIZE) TRACELOG(RL_LOG_ERROR, "RLGL: Matrix stack overflow (RL_MAX_MATRIX_STACK_SIZE)"); if (RLGL.State.currentMatrixMode == RL_MODELVIEW) { @@ -988,37 +1014,80 @@ void rlPopMatrix(void) // Reset current matrix to identity matrix void rlLoadIdentity(void) { - *RLGL.State.currentMatrix = MatrixIdentity(); + *RLGL.State.currentMatrix = rlMatrixIdentity(); } // Multiply the current matrix by a translation matrix void rlTranslatef(float x, float y, float z) { - Matrix matTranslation = MatrixTranslate(x, y, z); + Matrix matTranslation = { + 1.0f, 0.0f, 0.0f, x, + 0.0f, 1.0f, 0.0f, y, + 0.0f, 0.0f, 1.0f, z, + 0.0f, 0.0f, 0.0f, 1.0f + }; // NOTE: We transpose matrix with multiplication order - *RLGL.State.currentMatrix = MatrixMultiply(matTranslation, *RLGL.State.currentMatrix); + *RLGL.State.currentMatrix = rlMatrixMultiply(matTranslation, *RLGL.State.currentMatrix); } // Multiply the current matrix by a rotation matrix -void rlRotatef(float angleDeg, float x, float y, float z) +// NOTE: The provided angle must be in degrees +void rlRotatef(float angle, float x, float y, float z) { - Matrix matRotation = MatrixIdentity(); + Matrix matRotation = rlMatrixIdentity(); + + // Axis vector (x, y, z) normalization + float lengthSquared = x*x + y*y + z*z; + if ((lengthSquared != 1.0f) && (lengthSquared != 0.0f)) + { + float inverseLength = 1.0f/sqrtf(lengthSquared); + x *= inverseLength; + y *= inverseLength; + z *= inverseLength; + } + + // Rotation matrix generation + float sinres = sinf(DEG2RAD*angle); + float cosres = cosf(DEG2RAD*angle); + float t = 1.0f - cosres; - Vector3 axis = (Vector3){ x, y, z }; - matRotation = MatrixRotate(Vector3Normalize(axis), angleDeg*DEG2RAD); + matRotation.m0 = x*x*t + cosres; + matRotation.m1 = y*x*t + z*sinres; + matRotation.m2 = z*x*t - y*sinres; + matRotation.m3 = 0.0f; + + matRotation.m4 = x*y*t - z*sinres; + matRotation.m5 = y*y*t + cosres; + matRotation.m6 = z*y*t + x*sinres; + matRotation.m7 = 0.0f; + + matRotation.m8 = x*z*t + y*sinres; + matRotation.m9 = y*z*t - x*sinres; + matRotation.m10 = z*z*t + cosres; + matRotation.m11 = 0.0f; + + matRotation.m12 = 0.0f; + matRotation.m13 = 0.0f; + matRotation.m14 = 0.0f; + matRotation.m15 = 1.0f; // NOTE: We transpose matrix with multiplication order - *RLGL.State.currentMatrix = MatrixMultiply(matRotation, *RLGL.State.currentMatrix); + *RLGL.State.currentMatrix = rlMatrixMultiply(matRotation, *RLGL.State.currentMatrix); } // Multiply the current matrix by a scaling matrix void rlScalef(float x, float y, float z) { - Matrix matScale = MatrixScale(x, y, z); + Matrix matScale = { + x, 0.0f, 0.0f, 0.0f, + 0.0f, y, 0.0f, 0.0f, + 0.0f, 0.0f, z, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; // NOTE: We transpose matrix with multiplication order - *RLGL.State.currentMatrix = MatrixMultiply(matScale, *RLGL.State.currentMatrix); + *RLGL.State.currentMatrix = rlMatrixMultiply(matScale, *RLGL.State.currentMatrix); } // Multiply the current matrix by another matrix @@ -1030,25 +1099,70 @@ void rlMultMatrixf(float *matf) matf[2], matf[6], matf[10], matf[14], matf[3], matf[7], matf[11], matf[15] }; - *RLGL.State.currentMatrix = MatrixMultiply(*RLGL.State.currentMatrix, mat); + *RLGL.State.currentMatrix = rlMatrixMultiply(*RLGL.State.currentMatrix, mat); } // Multiply the current matrix by a perspective matrix generated by parameters void rlFrustum(double left, double right, double bottom, double top, double znear, double zfar) { - Matrix matPerps = MatrixFrustum(left, right, bottom, top, znear, zfar); + Matrix matFrustum = { 0 }; - *RLGL.State.currentMatrix = MatrixMultiply(*RLGL.State.currentMatrix, matPerps); + float rl = (float)(right - left); + float tb = (float)(top - bottom); + float fn = (float)(zfar - znear); + + matFrustum.m0 = ((float) znear*2.0f)/rl; + matFrustum.m1 = 0.0f; + matFrustum.m2 = 0.0f; + matFrustum.m3 = 0.0f; + + matFrustum.m4 = 0.0f; + matFrustum.m5 = ((float) znear*2.0f)/tb; + matFrustum.m6 = 0.0f; + matFrustum.m7 = 0.0f; + + matFrustum.m8 = ((float)right + (float)left)/rl; + matFrustum.m9 = ((float)top + (float)bottom)/tb; + matFrustum.m10 = -((float)zfar + (float)znear)/fn; + matFrustum.m11 = -1.0f; + + matFrustum.m12 = 0.0f; + matFrustum.m13 = 0.0f; + matFrustum.m14 = -((float)zfar*(float)znear*2.0f)/fn; + matFrustum.m15 = 0.0f; + + *RLGL.State.currentMatrix = rlMatrixMultiply(*RLGL.State.currentMatrix, matFrustum); } // Multiply the current matrix by an orthographic matrix generated by parameters void rlOrtho(double left, double right, double bottom, double top, double znear, double zfar) { - // NOTE: If left-right and top-botton values are equal it could create - // a division by zero on MatrixOrtho(), response to it is platform/compiler dependant - Matrix matOrtho = MatrixOrtho(left, right, bottom, top, znear, zfar); + // NOTE: If left-right and top-botton values are equal it could create a division by zero, + // response to it is platform/compiler dependant + Matrix matOrtho = { 0 }; + + float rl = (float)(right - left); + float tb = (float)(top - bottom); + float fn = (float)(zfar - znear); - *RLGL.State.currentMatrix = MatrixMultiply(*RLGL.State.currentMatrix, matOrtho); + matOrtho.m0 = 2.0f/rl; + matOrtho.m1 = 0.0f; + matOrtho.m2 = 0.0f; + matOrtho.m3 = 0.0f; + matOrtho.m4 = 0.0f; + matOrtho.m5 = 2.0f/tb; + matOrtho.m6 = 0.0f; + matOrtho.m7 = 0.0f; + matOrtho.m8 = 0.0f; + matOrtho.m9 = 0.0f; + matOrtho.m10 = -2.0f/fn; + matOrtho.m11 = 0.0f; + matOrtho.m12 = -((float)left + (float)right)/rl; + matOrtho.m13 = -((float)top + (float)bottom)/tb; + matOrtho.m14 = -((float)zfar + (float)znear)/fn; + matOrtho.m15 = 1.0f; + + *RLGL.State.currentMatrix = rlMatrixMultiply(*RLGL.State.currentMatrix, matOrtho); } #endif @@ -1114,7 +1228,7 @@ void rlBegin(int mode) } } - if (RLGL.currentBatch->drawsCounter >= DEFAULT_BATCH_DRAWCALLS) rlDrawRenderBatch(RLGL.currentBatch); + if (RLGL.currentBatch->drawsCounter >= RL_DEFAULT_BATCH_DRAWCALLS) rlDrawRenderBatch(RLGL.currentBatch); RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].mode = mode; RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount = 0; @@ -1180,22 +1294,29 @@ void rlEnd(void) // NOTE: Vertex position data is the basic information required for drawing void rlVertex3f(float x, float y, float z) { - Vector3 vec = { x, y, z }; + float tx = x; + float ty = y; + float tz = z; // Transform provided vector if required - if (RLGL.State.transformRequired) vec = Vector3Transform(vec, RLGL.State.transform); + if (RLGL.State.transformRequired) + { + tx = RLGL.State.transform.m0*x + RLGL.State.transform.m4*y + RLGL.State.transform.m8*z + RLGL.State.transform.m12; + ty = RLGL.State.transform.m1*x + RLGL.State.transform.m5*y + RLGL.State.transform.m9*z + RLGL.State.transform.m13; + tz = RLGL.State.transform.m2*x + RLGL.State.transform.m6*y + RLGL.State.transform.m10*z + RLGL.State.transform.m14; + } // 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.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].vertices[3*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter] = tx; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vertices[3*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter + 1] = ty; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vertices[3*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter + 2] = tz; RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter++; RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount++; } - else TRACELOG(LOG_ERROR, "RLGL: Batch elements overflow"); + else TRACELOG(RL_LOG_ERROR, "RLGL: Batch elements overflow"); } // Define one vertex (position) @@ -1298,7 +1419,7 @@ void rlSetTexture(unsigned int id) } } - if (RLGL.currentBatch->drawsCounter >= DEFAULT_BATCH_DRAWCALLS) rlDrawRenderBatch(RLGL.currentBatch); + if (RLGL.currentBatch->drawsCounter >= RL_DEFAULT_BATCH_DRAWCALLS) rlDrawRenderBatch(RLGL.currentBatch); RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].textureId = id; RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount = 0; @@ -1365,7 +1486,7 @@ void rlTextureParameters(unsigned int id, int param, int value) { #if !defined(GRAPHICS_API_OPENGL_11) if (RLGL.ExtSupported.texMirrorClamp) glTexParameteri(GL_TEXTURE_2D, param, value); - else TRACELOG(LOG_WARNING, "GL: Clamp mirror wrap mode not supported (GL_MIRROR_CLAMP_EXT)"); + else TRACELOG(RL_LOG_WARNING, "GL: Clamp mirror wrap mode not supported (GL_MIRROR_CLAMP_EXT)"); #endif } else glTexParameteri(GL_TEXTURE_2D, param, value); @@ -1379,10 +1500,10 @@ void rlTextureParameters(unsigned int id, int param, int value) if (value <= RLGL.ExtSupported.maxAnisotropyLevel) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value); else if (RLGL.ExtSupported.maxAnisotropyLevel > 0.0f) { - TRACELOG(LOG_WARNING, "GL: Maximum anisotropic filter level supported is %iX", id, RLGL.ExtSupported.maxAnisotropyLevel); + TRACELOG(RL_LOG_WARNING, "GL: Maximum anisotropic filter level supported is %iX", id, RLGL.ExtSupported.maxAnisotropyLevel); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value); } - else TRACELOG(LOG_WARNING, "GL: Anisotropic filtering not supported"); + else TRACELOG(RL_LOG_WARNING, "GL: Anisotropic filtering not supported"); #endif } break; default: break; @@ -1553,14 +1674,14 @@ void rlCheckErrors() switch (err) { case GL_NO_ERROR: check = 0; break; - case 0x0500: TRACELOG(LOG_WARNING, "GL: Error detected: GL_INVALID_ENUM"); break; - case 0x0501: TRACELOG(LOG_WARNING, "GL: Error detected: GL_INVALID_VALUE"); break; - case 0x0502: TRACELOG(LOG_WARNING, "GL: Error detected: GL_INVALID_OPERATION"); break; - case 0x0503: TRACELOG(LOG_WARNING, "GL: Error detected: GL_STACK_OVERFLOW"); break; - case 0x0504: TRACELOG(LOG_WARNING, "GL: Error detected: GL_STACK_UNDERFLOW"); break; - case 0x0505: TRACELOG(LOG_WARNING, "GL: Error detected: GL_OUT_OF_MEMORY"); break; - case 0x0506: TRACELOG(LOG_WARNING, "GL: Error detected: GL_INVALID_FRAMEBUFFER_OPERATION"); break; - default: TRACELOG(LOG_WARNING, "GL: Error detected: Unknown error code: %x", err); break; + case 0x0500: TRACELOG(RL_LOG_WARNING, "GL: Error detected: GL_INVALID_ENUM"); break; + case 0x0501: TRACELOG(RL_LOG_WARNING, "GL: Error detected: GL_INVALID_VALUE"); break; + case 0x0502: TRACELOG(RL_LOG_WARNING, "GL: Error detected: GL_INVALID_OPERATION"); break; + case 0x0503: TRACELOG(RL_LOG_WARNING, "GL: Error detected: GL_STACK_OVERFLOW"); break; + case 0x0504: TRACELOG(RL_LOG_WARNING, "GL: Error detected: GL_STACK_UNDERFLOW"); break; + case 0x0505: TRACELOG(RL_LOG_WARNING, "GL: Error detected: GL_OUT_OF_MEMORY"); break; + case 0x0506: TRACELOG(RL_LOG_WARNING, "GL: Error detected: GL_INVALID_FRAMEBUFFER_OPERATION"); break; + default: TRACELOG(RL_LOG_WARNING, "GL: Error detected: Unknown error code: %x", err); break; } } #endif @@ -1576,12 +1697,12 @@ void rlSetBlendMode(int mode) switch (mode) { - case BLEND_ALPHA: glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendEquation(GL_FUNC_ADD); break; - case BLEND_ADDITIVE: glBlendFunc(GL_SRC_ALPHA, GL_ONE); glBlendEquation(GL_FUNC_ADD); break; - case BLEND_MULTIPLIED: glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); glBlendEquation(GL_FUNC_ADD); break; - case BLEND_ADD_COLORS: glBlendFunc(GL_ONE, GL_ONE); glBlendEquation(GL_FUNC_ADD); break; - case BLEND_SUBTRACT_COLORS: glBlendFunc(GL_ONE, GL_ONE); glBlendEquation(GL_FUNC_SUBTRACT); break; - case BLEND_CUSTOM: glBlendFunc(RLGL.State.glBlendSrcFactor, RLGL.State.glBlendDstFactor); glBlendEquation(RLGL.State.glBlendEquation); break; + case RL_BLEND_ALPHA: glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendEquation(GL_FUNC_ADD); break; + case RL_BLEND_ADDITIVE: glBlendFunc(GL_SRC_ALPHA, GL_ONE); glBlendEquation(GL_FUNC_ADD); break; + case RL_BLEND_MULTIPLIED: glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); glBlendEquation(GL_FUNC_ADD); break; + case RL_BLEND_ADD_COLORS: glBlendFunc(GL_ONE, GL_ONE); glBlendEquation(GL_FUNC_ADD); break; + case RL_BLEND_SUBTRACT_COLORS: glBlendFunc(GL_ONE, GL_ONE); glBlendEquation(GL_FUNC_SUBTRACT); break; + case RL_BLEND_CUSTOM: glBlendFunc(RLGL.State.glBlendSrcFactor, RLGL.State.glBlendDstFactor); glBlendEquation(RLGL.State.glBlendEquation); break; default: break; } @@ -1610,26 +1731,28 @@ void rlglInit(int width, int height) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // Init default white texture unsigned char pixels[4] = { 255, 255, 255, 255 }; // 1 pixel RGBA (4 bytes) - RLGL.State.defaultTextureId = rlLoadTexture(pixels, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, 1); + RLGL.State.defaultTextureId = rlLoadTexture(pixels, 1, 1, RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, 1); - if (RLGL.State.defaultTextureId != 0) TRACELOG(LOG_INFO, "TEXTURE: [ID %i] Default texture loaded successfully", RLGL.State.defaultTextureId); - else TRACELOG(LOG_WARNING, "TEXTURE: Failed to load default texture"); + if (RLGL.State.defaultTextureId != 0) TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Default texture loaded successfully", RLGL.State.defaultTextureId); + else TRACELOG(RL_LOG_WARNING, "TEXTURE: Failed to load default texture"); // Init default Shader (customized for GL 3.3 and ES2) - rlLoadShaderDefault(); // RLGL.State.defaultShader - RLGL.State.currentShader = RLGL.State.defaultShader; + // Loaded: RLGL.State.defaultShaderId + RLGL.State.defaultShaderLocs + rlLoadShaderDefault(); + RLGL.State.currentShaderId = RLGL.State.defaultShaderId; + RLGL.State.currentShaderLocs = RLGL.State.defaultShaderLocs; // Init default vertex arrays buffers - RLGL.defaultBatch = rlLoadRenderBatch(DEFAULT_BATCH_BUFFERS, DEFAULT_BATCH_BUFFER_ELEMENTS); + RLGL.defaultBatch = rlLoadRenderBatch(RL_DEFAULT_BATCH_BUFFERS, RL_DEFAULT_BATCH_BUFFER_ELEMENTS); RLGL.currentBatch = &RLGL.defaultBatch; // Init stack matrices (emulating OpenGL 1.1) - for (int i = 0; i < MAX_MATRIX_STACK_SIZE; i++) RLGL.State.stack[i] = MatrixIdentity(); + for (int i = 0; i < RL_MAX_MATRIX_STACK_SIZE; i++) RLGL.State.stack[i] = rlMatrixIdentity(); // Init internal matrices - RLGL.State.transform = MatrixIdentity(); - RLGL.State.projection = MatrixIdentity(); - RLGL.State.modelview = MatrixIdentity(); + RLGL.State.transform = rlMatrixIdentity(); + RLGL.State.projection = rlMatrixIdentity(); + RLGL.State.modelview = rlMatrixIdentity(); RLGL.State.currentMatrix = &RLGL.State.modelview; #endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2 @@ -1665,7 +1788,7 @@ void rlglInit(int width, int height) RLGL.State.framebufferWidth = width; RLGL.State.framebufferHeight = height; - TRACELOG(LOG_INFO, "RLGL: Default OpenGL state initialized successfully"); + TRACELOG(RL_LOG_INFO, "RLGL: Default OpenGL state initialized successfully"); //---------------------------------------------------------- #endif @@ -1684,7 +1807,7 @@ void rlglClose(void) rlUnloadShaderDefault(); // Unload default shader glDeleteTextures(1, &RLGL.State.defaultTextureId); // Unload default texture - TRACELOG(LOG_INFO, "TEXTURE: [ID %i] Default texture unloaded successfully", RLGL.State.defaultTextureId); + TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Default texture unloaded successfully", RLGL.State.defaultTextureId); #endif } @@ -1695,24 +1818,24 @@ void rlLoadExtensions(void *loader) #if defined(GRAPHICS_API_OPENGL_33) // Also defined for GRAPHICS_API_OPENGL_21 // NOTE: glad is generated and contains only required OpenGL 3.3 Core extensions (and lower versions) #if !defined(__APPLE__) - if (!gladLoadGLLoader((GLADloadproc)loader)) TRACELOG(LOG_WARNING, "GLAD: Cannot load OpenGL extensions"); - else TRACELOG(LOG_INFO, "GLAD: OpenGL extensions loaded successfully"); + if (!gladLoadGLLoader((GLADloadproc)loader)) TRACELOG(RL_LOG_WARNING, "GLAD: Cannot load OpenGL extensions"); + else TRACELOG(RL_LOG_INFO, "GLAD: OpenGL extensions loaded successfully"); #endif // Get number of supported extensions GLint numExt = 0; glGetIntegerv(GL_NUM_EXTENSIONS, &numExt); - TRACELOG(LOG_INFO, "GL: Supported extensions count: %i", numExt); + TRACELOG(RL_LOG_INFO, "GL: Supported extensions count: %i", numExt); #if defined(SUPPORT_GL_DETAILS_INFO) // Get supported extensions list // WARNING: glGetStringi() not available on OpenGL 2.1 char **extList = RL_MALLOC(numExt*sizeof(char *)); - TRACELOG(LOG_INFO, "GL: OpenGL extensions:"); + TRACELOG(RL_LOG_INFO, "GL: OpenGL extensions:"); for (int i = 0; i < numExt; i++) { extList[i] = (char *)glGetStringi(GL_EXTENSIONS, i); - TRACELOG(LOG_INFO, " %s", extList[i]); + TRACELOG(RL_LOG_INFO, " %s", extList[i]); } RL_FREE(extList); // Free extensions pointers #endif @@ -1756,11 +1879,11 @@ void rlLoadExtensions(void *loader) } } - TRACELOG(LOG_INFO, "GL: Supported extensions count: %i", numExt); + TRACELOG(RL_LOG_INFO, "GL: Supported extensions count: %i", numExt); #if defined(SUPPORT_GL_DETAILS_INFO) - TRACELOG(LOG_INFO, "GL: OpenGL extensions:"); - for (int i = 0; i < numExt; i++) TRACELOG(LOG_INFO, " %s", extList[i]); + TRACELOG(RL_LOG_INFO, "GL: OpenGL extensions:"); + for (int i = 0; i < numExt; i++) TRACELOG(RL_LOG_INFO, " %s", extList[i]); #endif // Check required extensions @@ -1849,11 +1972,11 @@ void rlLoadExtensions(void *loader) // Check OpenGL information and capabilities //------------------------------------------------------------------------------ // Show current OpenGL and GLSL version - TRACELOG(LOG_INFO, "GL: OpenGL device information:"); - TRACELOG(LOG_INFO, " > Vendor: %s", glGetString(GL_VENDOR)); - TRACELOG(LOG_INFO, " > Renderer: %s", glGetString(GL_RENDERER)); - TRACELOG(LOG_INFO, " > Version: %s", glGetString(GL_VERSION)); - TRACELOG(LOG_INFO, " > GLSL: %s", glGetString(GL_SHADING_LANGUAGE_VERSION)); + TRACELOG(RL_LOG_INFO, "GL: OpenGL device information:"); + TRACELOG(RL_LOG_INFO, " > Vendor: %s", glGetString(GL_VENDOR)); + TRACELOG(RL_LOG_INFO, " > Renderer: %s", glGetString(GL_RENDERER)); + TRACELOG(RL_LOG_INFO, " > Version: %s", glGetString(GL_VERSION)); + TRACELOG(RL_LOG_INFO, " > GLSL: %s", glGetString(GL_SHADING_LANGUAGE_VERSION)); #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // NOTE: Anisotropy levels capability is an extension @@ -1864,50 +1987,50 @@ void rlLoadExtensions(void *loader) #if defined(SUPPORT_GL_DETAILS_INFO) // Show some OpenGL GPU capabilities - TRACELOG(LOG_INFO, "GL: OpenGL capabilities:"); + TRACELOG(RL_LOG_INFO, "GL: OpenGL capabilities:"); GLint capability = 0; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &capability); - TRACELOG(LOG_INFO, " GL_MAX_TEXTURE_SIZE: %i", capability); + TRACELOG(RL_LOG_INFO, " GL_MAX_TEXTURE_SIZE: %i", capability); glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &capability); - TRACELOG(LOG_INFO, " GL_MAX_CUBE_MAP_TEXTURE_SIZE: %i", capability); + TRACELOG(RL_LOG_INFO, " GL_MAX_CUBE_MAP_TEXTURE_SIZE: %i", capability); glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &capability); - TRACELOG(LOG_INFO, " GL_MAX_TEXTURE_IMAGE_UNITS: %i", capability); + TRACELOG(RL_LOG_INFO, " GL_MAX_TEXTURE_IMAGE_UNITS: %i", capability); glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &capability); - TRACELOG(LOG_INFO, " GL_MAX_VERTEX_ATTRIBS: %i", capability); + TRACELOG(RL_LOG_INFO, " GL_MAX_VERTEX_ATTRIBS: %i", capability); #if !defined(GRAPHICS_API_OPENGL_ES2) glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &capability); - TRACELOG(LOG_INFO, " GL_MAX_UNIFORM_BLOCK_SIZE: %i", capability); + TRACELOG(RL_LOG_INFO, " GL_MAX_UNIFORM_BLOCK_SIZE: %i", capability); glGetIntegerv(GL_MAX_DRAW_BUFFERS, &capability); - TRACELOG(LOG_INFO, " GL_MAX_DRAW_BUFFERS: %i", capability); - if (RLGL.ExtSupported.texAnisoFilter) TRACELOG(LOG_INFO, " GL_MAX_TEXTURE_MAX_ANISOTROPY: %.0f", RLGL.ExtSupported.maxAnisotropyLevel); + TRACELOG(RL_LOG_INFO, " GL_MAX_DRAW_BUFFERS: %i", capability); + if (RLGL.ExtSupported.texAnisoFilter) TRACELOG(RL_LOG_INFO, " GL_MAX_TEXTURE_MAX_ANISOTROPY: %.0f", RLGL.ExtSupported.maxAnisotropyLevel); #endif glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &capability); - TRACELOG(LOG_INFO, " GL_NUM_COMPRESSED_TEXTURE_FORMATS: %i", capability); + TRACELOG(RL_LOG_INFO, " GL_NUM_COMPRESSED_TEXTURE_FORMATS: %i", capability); GLint format[32] = { 0 }; glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, format); - for (int i = 0; i < capability; i++) TRACELOG(LOG_INFO, " %s", rlGetCompressedFormatName(format[i])); + for (int i = 0; i < capability; i++) TRACELOG(RL_LOG_INFO, " %s", rlGetCompressedFormatName(format[i])); /* // Following capabilities are only supported by OpenGL 4.3 or greater glGetIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &capability); - TRACELOG(LOG_INFO, " GL_MAX_VERTEX_ATTRIB_BINDINGS: %i", capability); + TRACELOG(RL_LOG_INFO, " GL_MAX_VERTEX_ATTRIB_BINDINGS: %i", capability); glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, &capability); - TRACELOG(LOG_INFO, " GL_MAX_UNIFORM_LOCATIONS: %i", capability); + TRACELOG(RL_LOG_INFO, " GL_MAX_UNIFORM_LOCATIONS: %i", capability); */ #else // SUPPORT_GL_DETAILS_INFO // Show some basic info about GL supported features #if defined(GRAPHICS_API_OPENGL_ES2) - if (RLGL.ExtSupported.vao) TRACELOG(LOG_INFO, "GL: VAO extension detected, VAO functions loaded successfully"); - else TRACELOG(LOG_WARNING, "GL: VAO extension not found, VAO not supported"); - if (RLGL.ExtSupported.texNPOT) TRACELOG(LOG_INFO, "GL: NPOT textures extension detected, full NPOT textures supported"); - else TRACELOG(LOG_WARNING, "GL: NPOT textures extension not found, limited NPOT support (no-mipmaps, no-repeat)"); + if (RLGL.ExtSupported.vao) TRACELOG(RL_LOG_INFO, "GL: VAO extension detected, VAO functions loaded successfully"); + else TRACELOG(RL_LOG_WARNING, "GL: VAO extension not found, VAO not supported"); + if (RLGL.ExtSupported.texNPOT) TRACELOG(RL_LOG_INFO, "GL: NPOT textures extension detected, full NPOT textures supported"); + else TRACELOG(RL_LOG_WARNING, "GL: NPOT textures extension not found, limited NPOT support (no-mipmaps, no-repeat)"); #endif - if (RLGL.ExtSupported.texCompDXT) TRACELOG(LOG_INFO, "GL: DXT compressed textures supported"); - if (RLGL.ExtSupported.texCompETC1) TRACELOG(LOG_INFO, "GL: ETC1 compressed textures supported"); - if (RLGL.ExtSupported.texCompETC2) TRACELOG(LOG_INFO, "GL: ETC2/EAC compressed textures supported"); - if (RLGL.ExtSupported.texCompPVRT) TRACELOG(LOG_INFO, "GL: PVRT compressed textures supported"); - if (RLGL.ExtSupported.texCompASTC) TRACELOG(LOG_INFO, "GL: ASTC compressed textures supported"); + if (RLGL.ExtSupported.texCompDXT) TRACELOG(RL_LOG_INFO, "GL: DXT compressed textures supported"); + if (RLGL.ExtSupported.texCompETC1) TRACELOG(RL_LOG_INFO, "GL: ETC1 compressed textures supported"); + if (RLGL.ExtSupported.texCompETC2) TRACELOG(RL_LOG_INFO, "GL: ETC2/EAC compressed textures supported"); + if (RLGL.ExtSupported.texCompPVRT) TRACELOG(RL_LOG_INFO, "GL: PVRT compressed textures supported"); + if (RLGL.ExtSupported.texCompASTC) TRACELOG(RL_LOG_INFO, "GL: ASTC compressed textures supported"); #endif // SUPPORT_GL_DETAILS_INFO #endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2 @@ -1916,79 +2039,87 @@ void rlLoadExtensions(void *loader) // Get current OpenGL version int rlGetVersion(void) { + int glVersion = 0; #if defined(GRAPHICS_API_OPENGL_11) - return OPENGL_11; + glVersion = OPENGL_11; #endif #if defined(GRAPHICS_API_OPENGL_21) #if defined(__APPLE__) - return OPENGL_33; // NOTE: Force OpenGL 3.3 on OSX + glVersion = OPENGL_33; // NOTE: Force OpenGL 3.3 on OSX #else - return OPENGL_21; + glVersion = OPENGL_21; #endif #elif defined(GRAPHICS_API_OPENGL_33) - return OPENGL_33; + glVersion = OPENGL_33; #endif #if defined(GRAPHICS_API_OPENGL_ES2) - return OPENGL_ES_20; + glVersion = OPENGL_ES_20; #endif + return glVersion; } // Get default framebuffer width int rlGetFramebufferWidth(void) { + int width = 0; #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - return RLGL.State.framebufferWidth; -#else - return 0; + width = RLGL.State.framebufferWidth; #endif + return width; } // Get default framebuffer height int rlGetFramebufferHeight(void) { + int height = 0; #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - return RLGL.State.framebufferHeight; -#else - return 0; -#endif -} - -// Get default internal shader (simple texture + tint color) -Shader rlGetShaderDefault(void) -{ -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - return RLGL.State.defaultShader; -#else - Shader shader = { 0 }; - return shader; + height = RLGL.State.framebufferHeight; #endif + return height; } // Get default internal texture (white texture) -Texture2D rlGetTextureDefault(void) +// NOTE: Default texture is a 1x1 pixel UNCOMPRESSED_R8G8B8A8 +unsigned int rlGetTextureIdDefault(void) { - Texture2D texture = { 0 }; + unsigned int id = 0; #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - texture.id = RLGL.State.defaultTextureId; - texture.width = 1; - texture.height = 1; - texture.mipmaps = 1; - texture.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8; + id = RLGL.State.defaultTextureId; #endif - return texture; + return id; +} + +// Get default shader id +unsigned int rlGetShaderIdDefault(void) +{ + unsigned int id = 0; +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + id = RLGL.State.defaultShaderId; +#endif + return id; +} + +// Get default shader locs +int *rlGetShaderLocsDefault(void) +{ + int *locs = NULL; +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + locs = RLGL.State.defaultShaderLocs; +#endif + return locs; } // Render batch management //------------------------------------------------------------------------------------------------ // Load render batch -RenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements) +rlRenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements) { - RenderBatch batch = { 0 }; + rlRenderBatch batch = { 0 }; #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // Initialize CPU (RAM) vertex buffers (position, texcoord, color data and indexes) //-------------------------------------------------------------------------------------------- - batch.vertexBuffer = (VertexBuffer *)RL_MALLOC(numBuffers*sizeof(VertexBuffer)); + batch.vertexBuffer = (rlVertexBuffer *)RL_MALLOC(numBuffers*sizeof(rlVertexBuffer)); for (int i = 0; i < numBuffers; i++) { @@ -2028,7 +2159,7 @@ RenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements) batch.vertexBuffer[i].cCounter = 0; } - TRACELOG(LOG_INFO, "RLGL: Render batch vertex buffers loaded successfully in RAM (CPU)"); + TRACELOG(RL_LOG_INFO, "RLGL: Render batch vertex buffers loaded successfully in RAM (CPU)"); //-------------------------------------------------------------------------------------------- // Upload to GPU (VRAM) vertex data and initialize VAOs/VBOs @@ -2047,22 +2178,22 @@ RenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements) glGenBuffers(1, &batch.vertexBuffer[i].vboId[0]); glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[0]); glBufferData(GL_ARRAY_BUFFER, bufferElements*3*4*sizeof(float), batch.vertexBuffer[i].vertices, GL_DYNAMIC_DRAW); - glEnableVertexAttribArray(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_POSITION]); - glVertexAttribPointer(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_POSITION]); + glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0); // Vertex texcoord buffer (shader-location = 1) glGenBuffers(1, &batch.vertexBuffer[i].vboId[1]); glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[1]); glBufferData(GL_ARRAY_BUFFER, bufferElements*2*4*sizeof(float), batch.vertexBuffer[i].texcoords, GL_DYNAMIC_DRAW); - glEnableVertexAttribArray(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_TEXCOORD01]); - glVertexAttribPointer(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_TEXCOORD01]); + glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0); // Vertex color buffer (shader-location = 3) glGenBuffers(1, &batch.vertexBuffer[i].vboId[2]); glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[2]); glBufferData(GL_ARRAY_BUFFER, bufferElements*4*4*sizeof(unsigned char), batch.vertexBuffer[i].colors, GL_DYNAMIC_DRAW); - glEnableVertexAttribArray(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_COLOR]); - glVertexAttribPointer(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); + glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_COLOR]); + glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); // Fill index buffer glGenBuffers(1, &batch.vertexBuffer[i].vboId[3]); @@ -2075,7 +2206,7 @@ RenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements) #endif } - TRACELOG(LOG_INFO, "RLGL: Render batch vertex buffers loaded successfully in VRAM (GPU)"); + TRACELOG(RL_LOG_INFO, "RLGL: Render batch vertex buffers loaded successfully in VRAM (GPU)"); // Unbind the current VAO if (RLGL.ExtSupported.vao) glBindVertexArray(0); @@ -2083,9 +2214,9 @@ RenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements) // Init draw calls tracking system //-------------------------------------------------------------------------------------------- - batch.draws = (DrawCall *)RL_MALLOC(DEFAULT_BATCH_DRAWCALLS*sizeof(DrawCall)); + batch.draws = (rlDrawCall *)RL_MALLOC(RL_DEFAULT_BATCH_DRAWCALLS*sizeof(rlDrawCall)); - for (int i = 0; i < DEFAULT_BATCH_DRAWCALLS; i++) + for (int i = 0; i < RL_DEFAULT_BATCH_DRAWCALLS; i++) { batch.draws[i].mode = RL_QUADS; batch.draws[i].vertexCount = 0; @@ -2093,8 +2224,8 @@ RenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements) //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.draws[i].RLGL.State.projection = rlMatrixIdentity(); + //batch.draws[i].RLGL.State.modelview = rlMatrixIdentity(); } batch.buffersCount = numBuffers; // Record buffer count @@ -2107,7 +2238,7 @@ RenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements) } // Unload default internal buffers vertex data from CPU and GPU -void rlUnloadRenderBatch(RenderBatch batch) +void rlUnloadRenderBatch(rlRenderBatch batch) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // Unbind everything @@ -2146,7 +2277,7 @@ void rlUnloadRenderBatch(RenderBatch batch) // Draw render batch // NOTE: We require a pointer to reset batch and increase current buffer (multi-buffer) -void rlDrawRenderBatch(RenderBatch *batch) +void rlDrawRenderBatch(rlRenderBatch *batch) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // Update batch vertex buffers @@ -2209,7 +2340,7 @@ void rlDrawRenderBatch(RenderBatch *batch) rlViewport(eye*RLGL.State.framebufferWidth/2, 0, RLGL.State.framebufferWidth/2, RLGL.State.framebufferHeight); // Set current eye view offset to modelview matrix - rlSetMatrixModelview(MatrixMultiply(matModelView, RLGL.State.viewOffsetStereo[eye])); + rlSetMatrixModelview(rlMatrixMultiply(matModelView, RLGL.State.viewOffsetStereo[eye])); // Set current eye projection matrix rlSetMatrixProjection(RLGL.State.projectionStereo[eye]); } @@ -2218,40 +2349,46 @@ void rlDrawRenderBatch(RenderBatch *batch) if (batch->vertexBuffer[batch->currentBuffer].vCounter > 0) { // Set current shader and upload current MVP matrix - glUseProgram(RLGL.State.currentShader.id); + glUseProgram(RLGL.State.currentShaderId); // Create modelview-projection matrix and upload to shader - Matrix matMVP = MatrixMultiply(RLGL.State.modelview, RLGL.State.projection); - glUniformMatrix4fv(RLGL.State.currentShader.locs[SHADER_LOC_MATRIX_MVP], 1, false, MatrixToFloat(matMVP)); + Matrix matMVP = rlMatrixMultiply(RLGL.State.modelview, RLGL.State.projection); + float matMVPfloat[16] = { + matMVP.m0, matMVP.m1, matMVP.m2, matMVP.m3, + matMVP.m4, matMVP.m5, matMVP.m6, matMVP.m7, + matMVP.m8, matMVP.m9, matMVP.m10, matMVP.m11, + matMVP.m12, matMVP.m13, matMVP.m14, matMVP.m15 + }; + glUniformMatrix4fv(RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_MVP], 1, false, matMVPfloat); if (RLGL.ExtSupported.vao) glBindVertexArray(batch->vertexBuffer[batch->currentBuffer].vaoId); else { // Bind vertex attrib: position (shader-location = 0) glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[0]); - glVertexAttribPointer(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_POSITION]); + glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_POSITION]); // Bind vertex attrib: texcoord (shader-location = 1) glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[1]); - glVertexAttribPointer(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_TEXCOORD01]); + glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_TEXCOORD01]); // Bind vertex attrib: color (shader-location = 3) glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[2]); - glVertexAttribPointer(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); - glEnableVertexAttribArray(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_COLOR]); + glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); + glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_COLOR]); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[3]); } // Setup some default shader values - glUniform4f(RLGL.State.currentShader.locs[SHADER_LOC_COLOR_DIFFUSE], 1.0f, 1.0f, 1.0f, 1.0f); - glUniform1i(RLGL.State.currentShader.locs[SHADER_LOC_MAP_DIFFUSE], 0); // Active default sampler2D: texture0 + glUniform4f(RLGL.State.currentShaderLocs[RL_SHADER_LOC_COLOR_DIFFUSE], 1.0f, 1.0f, 1.0f, 1.0f); + glUniform1i(RLGL.State.currentShaderLocs[RL_SHADER_LOC_MAP_DIFFUSE], 0); // Active default sampler2D: texture0 // Activate additional sampler textures // Those additional textures will be common for all draw calls of the batch - for (int i = 0; i < MAX_BATCH_ACTIVE_TEXTURES; i++) + for (int i = 0; i < RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS; i++) { if (RLGL.State.activeTextureId[i] > 0) { @@ -2316,7 +2453,7 @@ void rlDrawRenderBatch(RenderBatch *batch) RLGL.State.modelview = matModelView; // Reset RLGL.currentBatch->draws array - for (int i = 0; i < DEFAULT_BATCH_DRAWCALLS; i++) + for (int i = 0; i < RL_DEFAULT_BATCH_DRAWCALLS; i++) { batch->draws[i].mode = RL_QUADS; batch->draws[i].vertexCount = 0; @@ -2324,7 +2461,7 @@ void rlDrawRenderBatch(RenderBatch *batch) } // Reset active texture units for next batch - for (int i = 0; i < MAX_BATCH_ACTIVE_TEXTURES; i++) RLGL.State.activeTextureId[i] = 0; + for (int i = 0; i < RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS; i++) RLGL.State.activeTextureId[i] = 0; // Reset draws counter to one draw for the batch batch->drawsCounter = 1; @@ -2337,7 +2474,7 @@ void rlDrawRenderBatch(RenderBatch *batch) } // Set the active render batch for rlgl -void rlSetRenderBatchActive(RenderBatch *batch) +void rlSetRenderBatchActive(rlRenderBatch *batch) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) rlDrawRenderBatch(RLGL.currentBatch); @@ -2356,7 +2493,7 @@ void rlDrawRenderBatchActive(void) } // Check internal buffer overflow for a given number of vertex -// and force a RenderBatch draw call if required +// and force a rlRenderBatch draw call if required bool rlCheckRenderBatchLimit(int vCount) { bool overflow = false; @@ -2384,40 +2521,40 @@ unsigned int rlLoadTexture(void *data, int width, int height, int format, int mi // Check texture format support by OpenGL 1.1 (compressed textures not supported) #if defined(GRAPHICS_API_OPENGL_11) - if (format >= PIXELFORMAT_COMPRESSED_DXT1_RGB) + if (format >= RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) { - TRACELOG(LOG_WARNING, "GL: OpenGL 1.1 does not support GPU compressed texture formats"); + TRACELOG(RL_LOG_WARNING, "GL: OpenGL 1.1 does not support GPU compressed texture formats"); return id; } #else - if ((!RLGL.ExtSupported.texCompDXT) && ((format == PIXELFORMAT_COMPRESSED_DXT1_RGB) || (format == PIXELFORMAT_COMPRESSED_DXT1_RGBA) || - (format == PIXELFORMAT_COMPRESSED_DXT3_RGBA) || (format == PIXELFORMAT_COMPRESSED_DXT5_RGBA))) + if ((!RLGL.ExtSupported.texCompDXT) && ((format == RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) || (format == RL_PIXELFORMAT_COMPRESSED_DXT1_RGBA) || + (format == RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA) || (format == RL_PIXELFORMAT_COMPRESSED_DXT5_RGBA))) { - TRACELOG(LOG_WARNING, "GL: DXT compressed texture format not supported"); + TRACELOG(RL_LOG_WARNING, "GL: DXT compressed texture format not supported"); return id; } #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - if ((!RLGL.ExtSupported.texCompETC1) && (format == PIXELFORMAT_COMPRESSED_ETC1_RGB)) + if ((!RLGL.ExtSupported.texCompETC1) && (format == RL_PIXELFORMAT_COMPRESSED_ETC1_RGB)) { - TRACELOG(LOG_WARNING, "GL: ETC1 compressed texture format not supported"); + TRACELOG(RL_LOG_WARNING, "GL: ETC1 compressed texture format not supported"); return id; } - if ((!RLGL.ExtSupported.texCompETC2) && ((format == PIXELFORMAT_COMPRESSED_ETC2_RGB) || (format == PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA))) + if ((!RLGL.ExtSupported.texCompETC2) && ((format == RL_PIXELFORMAT_COMPRESSED_ETC2_RGB) || (format == RL_PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA))) { - TRACELOG(LOG_WARNING, "GL: ETC2 compressed texture format not supported"); + TRACELOG(RL_LOG_WARNING, "GL: ETC2 compressed texture format not supported"); return id; } - if ((!RLGL.ExtSupported.texCompPVRT) && ((format == PIXELFORMAT_COMPRESSED_PVRT_RGB) || (format == PIXELFORMAT_COMPRESSED_PVRT_RGBA))) + if ((!RLGL.ExtSupported.texCompPVRT) && ((format == RL_PIXELFORMAT_COMPRESSED_PVRT_RGB) || (format == RL_PIXELFORMAT_COMPRESSED_PVRT_RGBA))) { - TRACELOG(LOG_WARNING, "GL: PVRT compressed texture format not supported"); + TRACELOG(RL_LOG_WARNING, "GL: PVRT compressed texture format not supported"); return id; } - if ((!RLGL.ExtSupported.texCompASTC) && ((format == PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA) || (format == PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA))) + if ((!RLGL.ExtSupported.texCompASTC) && ((format == RL_PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA) || (format == RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA))) { - TRACELOG(LOG_WARNING, "GL: ASTC compressed texture format not supported"); + TRACELOG(RL_LOG_WARNING, "GL: ASTC compressed texture format not supported"); return id; } #endif @@ -2445,18 +2582,18 @@ unsigned int rlLoadTexture(void *data, int width, int height, int format, int mi if (glInternalFormat != -1) { - if (format < PIXELFORMAT_COMPRESSED_DXT1_RGB) glTexImage2D(GL_TEXTURE_2D, i, glInternalFormat, mipWidth, mipHeight, 0, glFormat, glType, (unsigned char *)data + mipOffset); + if (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) glTexImage2D(GL_TEXTURE_2D, i, glInternalFormat, mipWidth, mipHeight, 0, glFormat, glType, (unsigned char *)data + mipOffset); #if !defined(GRAPHICS_API_OPENGL_11) else glCompressedTexImage2D(GL_TEXTURE_2D, i, glInternalFormat, mipWidth, mipHeight, 0, mipSize, (unsigned char *)data + mipOffset); #endif #if defined(GRAPHICS_API_OPENGL_33) - if (format == PIXELFORMAT_UNCOMPRESSED_GRAYSCALE) + if (format == RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE) { GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_ONE }; glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); } - else if (format == PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA) + else if (format == RL_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA) { #if defined(GRAPHICS_API_OPENGL_21) GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_ALPHA }; @@ -2517,8 +2654,8 @@ unsigned int rlLoadTexture(void *data, int width, int height, int format, int mi // Unbind current texture glBindTexture(GL_TEXTURE_2D, 0); - if (id > 0) TRACELOG(LOG_INFO, "TEXTURE: [ID %i] Texture loaded successfully (%ix%i | %s | %i mipmaps)", id, width, height, rlGetPixelFormatName(format), mipmapCount); - else TRACELOG(LOG_WARNING, "TEXTURE: Failed to load texture"); + if (id > 0) TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Texture loaded successfully (%ix%i | %s | %i mipmaps)", id, width, height, rlGetPixelFormatName(format), mipmapCount); + else TRACELOG(RL_LOG_WARNING, "TEXTURE: Failed to load texture"); return id; } @@ -2556,7 +2693,7 @@ unsigned int rlLoadTextureDepth(int width, int height, bool useRenderBuffer) glBindTexture(GL_TEXTURE_2D, 0); - TRACELOG(LOG_INFO, "TEXTURE: Depth texture loaded successfully"); + TRACELOG(RL_LOG_INFO, "TEXTURE: Depth texture loaded successfully"); } else { @@ -2568,7 +2705,7 @@ unsigned int rlLoadTextureDepth(int width, int height, bool useRenderBuffer) glBindRenderbuffer(GL_RENDERBUFFER, 0); - TRACELOG(LOG_INFO, "TEXTURE: [ID %i] Depth renderbuffer loaded successfully (%i bits)", id, (RLGL.ExtSupported.maxDepthBits >= 24)? RLGL.ExtSupported.maxDepthBits : 16); + TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Depth renderbuffer loaded successfully (%i bits)", id, (RLGL.ExtSupported.maxDepthBits >= 24)? RLGL.ExtSupported.maxDepthBits : 16); } #endif @@ -2598,32 +2735,32 @@ unsigned int rlLoadTextureCubemap(void *data, int size, int format) { if (data == NULL) { - if (format < PIXELFORMAT_COMPRESSED_DXT1_RGB) + if (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) { - if (format == PIXELFORMAT_UNCOMPRESSED_R32G32B32) + if (format == RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32) { // Instead of using a sized internal texture format (GL_RGB16F, GL_RGB32F), we let the driver to choose the better format for us (GL_RGB) if (RLGL.ExtSupported.texFloat32) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, size, size, 0, GL_RGB, GL_FLOAT, NULL); - else TRACELOG(LOG_WARNING, "TEXTURES: Cubemap requested format not supported"); + else TRACELOG(RL_LOG_WARNING, "TEXTURES: Cubemap requested format not supported"); } - else if ((format == PIXELFORMAT_UNCOMPRESSED_R32) || (format == PIXELFORMAT_UNCOMPRESSED_R32G32B32A32)) TRACELOG(LOG_WARNING, "TEXTURES: Cubemap requested format not supported"); + else if ((format == RL_PIXELFORMAT_UNCOMPRESSED_R32) || (format == RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32)) TRACELOG(RL_LOG_WARNING, "TEXTURES: Cubemap requested format not supported"); else glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, size, size, 0, glFormat, glType, NULL); } - else TRACELOG(LOG_WARNING, "TEXTURES: Empty cubemap creation does not support compressed format"); + else TRACELOG(RL_LOG_WARNING, "TEXTURES: Empty cubemap creation does not support compressed format"); } else { - if (format < PIXELFORMAT_COMPRESSED_DXT1_RGB) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, size, size, 0, glFormat, glType, (unsigned char *)data + i*dataSize); + if (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, size, size, 0, glFormat, glType, (unsigned char *)data + i*dataSize); else glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, size, size, 0, dataSize, (unsigned char *)data + i*dataSize); } #if defined(GRAPHICS_API_OPENGL_33) - if (format == PIXELFORMAT_UNCOMPRESSED_GRAYSCALE) + if (format == RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE) { GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_ONE }; glTexParameteriv(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); } - else if (format == PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA) + else if (format == RL_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA) { #if defined(GRAPHICS_API_OPENGL_21) GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_ALPHA }; @@ -2648,8 +2785,8 @@ unsigned int rlLoadTextureCubemap(void *data, int size, int format) glBindTexture(GL_TEXTURE_CUBE_MAP, 0); #endif - if (id > 0) TRACELOG(LOG_INFO, "TEXTURE: [ID %i] Cubemap texture loaded successfully (%ix%i)", id, size, size); - else TRACELOG(LOG_WARNING, "TEXTURE: Failed to load cubemap texture"); + if (id > 0) TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Cubemap texture loaded successfully (%ix%i)", id, size, size); + else TRACELOG(RL_LOG_WARNING, "TEXTURE: Failed to load cubemap texture"); return id; } @@ -2663,11 +2800,11 @@ void rlUpdateTexture(unsigned int id, int offsetX, int offsetY, int width, int h unsigned int glInternalFormat, glFormat, glType; rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType); - if ((glInternalFormat != -1) && (format < PIXELFORMAT_COMPRESSED_DXT1_RGB)) + if ((glInternalFormat != -1) && (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB)) { glTexSubImage2D(GL_TEXTURE_2D, 0, offsetX, offsetY, width, height, glFormat, glType, (unsigned char *)data); } - else TRACELOG(LOG_WARNING, "TEXTURE: [ID %i] Failed to update for current texture format (%i)", id, format); + else TRACELOG(RL_LOG_WARNING, "TEXTURE: [ID %i] Failed to update for current texture format (%i)", id, format); } // Get OpenGL internal formats and data type from raylib PixelFormat @@ -2681,44 +2818,44 @@ void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned { #if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_21) || defined(GRAPHICS_API_OPENGL_ES2) // NOTE: on OpenGL ES 2.0 (WebGL), internalFormat must match format and options allowed are: GL_LUMINANCE, GL_RGB, GL_RGBA - case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_UNSIGNED_BYTE; break; - case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: *glInternalFormat = GL_LUMINANCE_ALPHA; *glFormat = GL_LUMINANCE_ALPHA; *glType = GL_UNSIGNED_BYTE; break; - case PIXELFORMAT_UNCOMPRESSED_R5G6B5: *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_UNSIGNED_SHORT_5_6_5; break; - case PIXELFORMAT_UNCOMPRESSED_R8G8B8: *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_UNSIGNED_BYTE; break; - case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_SHORT_5_5_5_1; break; - case PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_SHORT_4_4_4_4; break; - case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_BYTE; break; + case RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_UNSIGNED_BYTE; break; + case RL_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: *glInternalFormat = GL_LUMINANCE_ALPHA; *glFormat = GL_LUMINANCE_ALPHA; *glType = GL_UNSIGNED_BYTE; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R5G6B5: *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_UNSIGNED_SHORT_5_6_5; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8: *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_UNSIGNED_BYTE; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_SHORT_5_5_5_1; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_SHORT_4_4_4_4; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_BYTE; break; #if !defined(GRAPHICS_API_OPENGL_11) - case PIXELFORMAT_UNCOMPRESSED_R32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float - case PIXELFORMAT_UNCOMPRESSED_R32G32B32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float - case PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float + case RL_PIXELFORMAT_UNCOMPRESSED_R32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float + case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float + case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float #endif #elif defined(GRAPHICS_API_OPENGL_33) - case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: *glInternalFormat = GL_R8; *glFormat = GL_RED; *glType = GL_UNSIGNED_BYTE; break; - case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: *glInternalFormat = GL_RG8; *glFormat = GL_RG; *glType = GL_UNSIGNED_BYTE; break; - case PIXELFORMAT_UNCOMPRESSED_R5G6B5: *glInternalFormat = GL_RGB565; *glFormat = GL_RGB; *glType = GL_UNSIGNED_SHORT_5_6_5; break; - case PIXELFORMAT_UNCOMPRESSED_R8G8B8: *glInternalFormat = GL_RGB8; *glFormat = GL_RGB; *glType = GL_UNSIGNED_BYTE; break; - case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: *glInternalFormat = GL_RGB5_A1; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_SHORT_5_5_5_1; break; - case PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: *glInternalFormat = GL_RGBA4; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_SHORT_4_4_4_4; break; - case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: *glInternalFormat = GL_RGBA8; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_BYTE; break; - case PIXELFORMAT_UNCOMPRESSED_R32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_R32F; *glFormat = GL_RED; *glType = GL_FLOAT; break; - case PIXELFORMAT_UNCOMPRESSED_R32G32B32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGB32F; *glFormat = GL_RGB; *glType = GL_FLOAT; break; - case PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGBA32F; *glFormat = GL_RGBA; *glType = GL_FLOAT; break; + case RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: *glInternalFormat = GL_R8; *glFormat = GL_RED; *glType = GL_UNSIGNED_BYTE; break; + case RL_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: *glInternalFormat = GL_RG8; *glFormat = GL_RG; *glType = GL_UNSIGNED_BYTE; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R5G6B5: *glInternalFormat = GL_RGB565; *glFormat = GL_RGB; *glType = GL_UNSIGNED_SHORT_5_6_5; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8: *glInternalFormat = GL_RGB8; *glFormat = GL_RGB; *glType = GL_UNSIGNED_BYTE; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: *glInternalFormat = GL_RGB5_A1; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_SHORT_5_5_5_1; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: *glInternalFormat = GL_RGBA4; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_SHORT_4_4_4_4; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: *glInternalFormat = GL_RGBA8; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_BYTE; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_R32F; *glFormat = GL_RED; *glType = GL_FLOAT; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGB32F; *glFormat = GL_RGB; *glType = GL_FLOAT; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGBA32F; *glFormat = GL_RGBA; *glType = GL_FLOAT; break; #endif #if !defined(GRAPHICS_API_OPENGL_11) - case PIXELFORMAT_COMPRESSED_DXT1_RGB: if (RLGL.ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; break; - case PIXELFORMAT_COMPRESSED_DXT1_RGBA: if (RLGL.ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; break; - case PIXELFORMAT_COMPRESSED_DXT3_RGBA: if (RLGL.ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break; - case PIXELFORMAT_COMPRESSED_DXT5_RGBA: if (RLGL.ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break; - case PIXELFORMAT_COMPRESSED_ETC1_RGB: if (RLGL.ExtSupported.texCompETC1) *glInternalFormat = GL_ETC1_RGB8_OES; break; // NOTE: Requires OpenGL ES 2.0 or OpenGL 4.3 - case PIXELFORMAT_COMPRESSED_ETC2_RGB: if (RLGL.ExtSupported.texCompETC2) *glInternalFormat = GL_COMPRESSED_RGB8_ETC2; break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3 - case PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA: if (RLGL.ExtSupported.texCompETC2) *glInternalFormat = GL_COMPRESSED_RGBA8_ETC2_EAC; break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3 - case PIXELFORMAT_COMPRESSED_PVRT_RGB: if (RLGL.ExtSupported.texCompPVRT) *glInternalFormat = GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG; break; // NOTE: Requires PowerVR GPU - case PIXELFORMAT_COMPRESSED_PVRT_RGBA: if (RLGL.ExtSupported.texCompPVRT) *glInternalFormat = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; break; // NOTE: Requires PowerVR GPU - case PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA: if (RLGL.ExtSupported.texCompASTC) *glInternalFormat = GL_COMPRESSED_RGBA_ASTC_4x4_KHR; break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 - case PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: if (RLGL.ExtSupported.texCompASTC) *glInternalFormat = GL_COMPRESSED_RGBA_ASTC_8x8_KHR; break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 + case RL_PIXELFORMAT_COMPRESSED_DXT1_RGB: if (RLGL.ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; break; + case RL_PIXELFORMAT_COMPRESSED_DXT1_RGBA: if (RLGL.ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; break; + case RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA: if (RLGL.ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break; + case RL_PIXELFORMAT_COMPRESSED_DXT5_RGBA: if (RLGL.ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break; + case RL_PIXELFORMAT_COMPRESSED_ETC1_RGB: if (RLGL.ExtSupported.texCompETC1) *glInternalFormat = GL_ETC1_RGB8_OES; break; // NOTE: Requires OpenGL ES 2.0 or OpenGL 4.3 + case RL_PIXELFORMAT_COMPRESSED_ETC2_RGB: if (RLGL.ExtSupported.texCompETC2) *glInternalFormat = GL_COMPRESSED_RGB8_ETC2; break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3 + case RL_PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA: if (RLGL.ExtSupported.texCompETC2) *glInternalFormat = GL_COMPRESSED_RGBA8_ETC2_EAC; break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3 + case RL_PIXELFORMAT_COMPRESSED_PVRT_RGB: if (RLGL.ExtSupported.texCompPVRT) *glInternalFormat = GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG; break; // NOTE: Requires PowerVR GPU + case RL_PIXELFORMAT_COMPRESSED_PVRT_RGBA: if (RLGL.ExtSupported.texCompPVRT) *glInternalFormat = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; break; // NOTE: Requires PowerVR GPU + case RL_PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA: if (RLGL.ExtSupported.texCompASTC) *glInternalFormat = GL_COMPRESSED_RGBA_ASTC_4x4_KHR; break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 + case RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: if (RLGL.ExtSupported.texCompASTC) *glInternalFormat = GL_COMPRESSED_RGBA_ASTC_8x8_KHR; break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 #endif - default: TRACELOG(LOG_WARNING, "TEXTURE: Current format not supported (%i)", format); break; + default: TRACELOG(RL_LOG_WARNING, "TEXTURE: Current format not supported (%i)", format); break; } } @@ -2729,34 +2866,34 @@ void rlUnloadTexture(unsigned int id) } // Generate mipmap data for selected texture -void rlGenerateMipmaps(Texture2D *texture) +void rlGenTextureMipmaps(unsigned int id, int width, int height, int format, int *mipmaps) { - glBindTexture(GL_TEXTURE_2D, texture->id); + glBindTexture(GL_TEXTURE_2D, id); // Check if texture is power-of-two (POT) bool texIsPOT = false; - if (((texture->width > 0) && ((texture->width & (texture->width - 1)) == 0)) && - ((texture->height > 0) && ((texture->height & (texture->height - 1)) == 0))) texIsPOT = true; + if (((width > 0) && ((width & (width - 1)) == 0)) && + ((height > 0) && ((height & (height - 1)) == 0))) texIsPOT = true; #if defined(GRAPHICS_API_OPENGL_11) if (texIsPOT) { // WARNING: Manual mipmap generation only works for RGBA 32bit textures! - if (texture->format == PIXELFORMAT_UNCOMPRESSED_R8G8B8A8) + if (format == RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8) { // Retrieve texture data from VRAM - void *texData = rlReadTexturePixels(*texture); + void *texData = rlReadTexturePixels(id, width, height, format); // NOTE: Texture data size is reallocated to fit mipmaps data // NOTE: CPU mipmap generation only supports RGBA 32bit data - int mipmapCount = rlGenerateMipmapsData(texData, texture->width, texture->height); + int mipmapCount = rlGenTextureMipmapsData(texData, width, height); - int size = texture->width*texture->height*4; + int size = width*height*4; int offset = size; - int mipWidth = texture->width/2; - int mipHeight = texture->height/2; + int mipWidth = width/2; + int mipHeight = height/2; // Load the mipmaps for (int level = 1; level < mipmapCount; level++) @@ -2770,12 +2907,12 @@ void rlGenerateMipmaps(Texture2D *texture) mipHeight /= 2; } - texture->mipmaps = mipmapCount + 1; + *mipmaps = mipmapCount + 1; RL_FREE(texData); // Once mipmaps have been generated and data has been uploaded to GPU VRAM, we can discard RAM data - TRACELOG(LOG_WARNING, "TEXTURE: [ID %i] Mipmaps generated manually on CPU side, total: %i", texture->id, texture->mipmaps); + TRACELOG(RL_LOG_WARNING, "TEXTURE: [ID %i] Mipmaps generated manually on CPU side, total: %i", texture->id, texture->mipmaps); } - else TRACELOG(LOG_WARNING, "TEXTURE: [ID %i] Failed to generate mipmaps for provided texture format", texture->id); + else TRACELOG(RL_LOG_WARNING, "TEXTURE: [ID %i] Failed to generate mipmaps for provided texture format", texture->id); } #endif #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) @@ -2790,25 +2927,25 @@ void rlGenerateMipmaps(Texture2D *texture) #define MIN(a,b) (((a)<(b))?(a):(b)) #define MAX(a,b) (((a)>(b))?(a):(b)) - texture->mipmaps = 1 + (int)floor(log(MAX(texture->width, texture->height))/log(2)); - TRACELOG(LOG_INFO, "TEXTURE: [ID %i] Mipmaps generated automatically, total: %i", texture->id, texture->mipmaps); + *mipmaps = 1 + (int)floor(log(MAX(width, height))/log(2)); + TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Mipmaps generated automatically, total: %i", id, *mipmaps); } #endif - else TRACELOG(LOG_WARNING, "TEXTURE: [ID %i] Failed to generate mipmaps", texture->id); + else TRACELOG(RL_LOG_WARNING, "TEXTURE: [ID %i] Failed to generate mipmaps", id); glBindTexture(GL_TEXTURE_2D, 0); } // Read texture pixel data -void *rlReadTexturePixels(Texture2D texture) +void *rlReadTexturePixels(unsigned int id, int width, int height, int format) { void *pixels = NULL; #if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) - glBindTexture(GL_TEXTURE_2D, texture.id); + glBindTexture(GL_TEXTURE_2D, id); - // NOTE: Using texture.id, we can retrieve some texture info (but not on OpenGL ES 2.0) + // NOTE: Using texture id, we can retrieve some texture info (but not on OpenGL ES 2.0) // Possible texture info: GL_TEXTURE_RED_SIZE, GL_TEXTURE_GREEN_SIZE, GL_TEXTURE_BLUE_SIZE, GL_TEXTURE_ALPHA_SIZE //int width, height, format; //glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width); @@ -2822,15 +2959,15 @@ void *rlReadTexturePixels(Texture2D texture) glPixelStorei(GL_PACK_ALIGNMENT, 1); unsigned int glInternalFormat, glFormat, glType; - rlGetGlTextureFormats(texture.format, &glInternalFormat, &glFormat, &glType); - unsigned int size = rlGetPixelDataSize(texture.width, texture.height, texture.format); + rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType); + unsigned int size = rlGetPixelDataSize(width, height, format); - if ((glInternalFormat != -1) && (texture.format < PIXELFORMAT_COMPRESSED_DXT1_RGB)) + if ((glInternalFormat != -1) && (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB)) { pixels = RL_MALLOC(size); glGetTexImage(GL_TEXTURE_2D, 0, glFormat, glType, pixels); } - else TRACELOG(LOG_WARNING, "TEXTURE: [ID %i] Data retrieval not suported for pixel format (%i)", texture.id, texture.format); + else TRACELOG(RL_LOG_WARNING, "TEXTURE: [ID %i] Data retrieval not suported for pixel format (%i)", id, format); glBindTexture(GL_TEXTURE_2D, 0); #endif @@ -2843,7 +2980,7 @@ void *rlReadTexturePixels(Texture2D texture) // 2 - Create an fbo, activate it, render quad with texture, glReadPixels() // We are using Option 1, just need to care for texture format on retrieval // NOTE: This behaviour could be conditioned by graphic driver... - unsigned int fboId = rlLoadFramebuffer(texture.width, texture.height); + unsigned int fboId = rlLoadFramebuffer(width, height); // TODO: Create depth texture/renderbuffer for fbo? @@ -2851,11 +2988,11 @@ void *rlReadTexturePixels(Texture2D texture) glBindTexture(GL_TEXTURE_2D, 0); // Attach our texture to FBO - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.id, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, id, 0); // We read data as RGBA because FBO texture is configured as RGBA, despite binding another texture format - pixels = (unsigned char *)RL_MALLOC(rlGetPixelDataSize(texture.width, texture.height, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8)); - glReadPixels(0, 0, texture.width, texture.height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + pixels = (unsigned char *)RL_MALLOC(rlGetPixelDataSize(width, height, RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8)); + glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); glBindFramebuffer(GL_FRAMEBUFFER, 0); @@ -2968,12 +3105,12 @@ bool rlFramebufferComplete(unsigned int id) { switch (status) { - case GL_FRAMEBUFFER_UNSUPPORTED: TRACELOG(LOG_WARNING, "FBO: [ID %i] Framebuffer is unsupported", id); break; - case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: TRACELOG(LOG_WARNING, "FBO: [ID %i] Framebuffer has incomplete attachment", id); break; + case GL_FRAMEBUFFER_UNSUPPORTED: TRACELOG(RL_LOG_WARNING, "FBO: [ID %i] Framebuffer is unsupported", id); break; + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: TRACELOG(RL_LOG_WARNING, "FBO: [ID %i] Framebuffer has incomplete attachment", id); break; #if defined(GRAPHICS_API_OPENGL_ES2) - case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: TRACELOG(LOG_WARNING, "FBO: [ID %i] Framebuffer has incomplete dimensions", id); break; + case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: TRACELOG(RL_LOG_WARNING, "FBO: [ID %i] Framebuffer has incomplete dimensions", id); break; #endif - case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: TRACELOG(LOG_WARNING, "FBO: [ID %i] Framebuffer has a missing attachment", id); break; + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: TRACELOG(RL_LOG_WARNING, "FBO: [ID %i] Framebuffer has a missing attachment", id); break; default: break; } } @@ -3008,7 +3145,7 @@ void rlUnloadFramebuffer(unsigned int id) glBindFramebuffer(GL_FRAMEBUFFER, 0); glDeleteFramebuffers(1, &id); - TRACELOG(LOG_INFO, "FBO: [ID %i] Unloaded framebuffer from VRAM (GPU)", id); + TRACELOG(RL_LOG_INFO, "FBO: [ID %i] Unloaded framebuffer from VRAM (GPU)", id); #endif } @@ -3121,7 +3258,7 @@ void rlDrawVertexArray(int offset, int count) void rlDrawVertexArrayElements(int offset, int count, void *buffer) { - glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, (unsigned short*)buffer + offset); + glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, (unsigned short *)buffer + offset); } void rlDrawVertexArrayInstanced(int offset, int count, int instances) @@ -3134,7 +3271,7 @@ void rlDrawVertexArrayInstanced(int offset, int count, int instances) void rlDrawVertexArrayElementsInstanced(int offset, int count, void *buffer, int instances) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - glDrawElementsInstanced(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, (unsigned short*)buffer + offset, instances); + glDrawElementsInstanced(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, (unsigned short *)buffer + offset, instances); #endif } @@ -3192,7 +3329,7 @@ void rlUnloadVertexArray(unsigned int vaoId) { glBindVertexArray(0); glDeleteVertexArrays(1, &vaoId); - TRACELOG(LOG_INFO, "VAO: [ID %i] Unloaded vertex array data from VRAM (GPU)", vaoId); + TRACELOG(RL_LOG_INFO, "VAO: [ID %i] Unloaded vertex array data from VRAM (GPU)", vaoId); } #endif } @@ -3201,7 +3338,7 @@ void rlUnloadVertexBuffer(unsigned int vboId) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) glDeleteBuffers(1, &vboId); - //TRACELOG(LOG_INFO, "VBO: Unloaded vertex data from VRAM (GPU)"); + //TRACELOG(RL_LOG_INFO, "VBO: Unloaded vertex data from VRAM (GPU)"); #endif } @@ -3220,7 +3357,7 @@ unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode) if (vsCode != NULL) vertexShaderId = rlCompileShader(vsCode, GL_VERTEX_SHADER); if (fsCode != NULL) fragmentShaderId = rlCompileShader(fsCode, GL_FRAGMENT_SHADER); - if ((vertexShaderId == RLGL.State.defaultVShaderId) && (fragmentShaderId == RLGL.State.defaultFShaderId)) id = RLGL.State.defaultShader.id; + if ((vertexShaderId == RLGL.State.defaultVShaderId) && (fragmentShaderId == RLGL.State.defaultFShaderId)) id = RLGL.State.defaultShaderId; else { id = rlLoadShaderProgram(vertexShaderId, fragmentShaderId); @@ -3240,8 +3377,8 @@ unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode) if (id == 0) { - TRACELOG(LOG_WARNING, "SHADER: Failed to load custom shader code"); - id = RLGL.State.defaultShader.id; + TRACELOG(RL_LOG_WARNING, "SHADER: Failed to load custom shader code"); + id = RLGL.State.defaultShaderId; } } @@ -3287,8 +3424,8 @@ unsigned int rlCompileShader(const char *shaderCode, int type) { switch (type) { - case GL_VERTEX_SHADER: TRACELOG(LOG_WARNING, "SHADER: [ID %i] Failed to compile vertex shader code", shader); break; - case GL_FRAGMENT_SHADER: TRACELOG(LOG_WARNING, "SHADER: [ID %i] Failed to compile fragment shader code", shader); break; + case GL_VERTEX_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to compile vertex shader code", shader); break; + case GL_FRAGMENT_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to compile fragment shader code", shader); break; //case GL_GEOMETRY_SHADER: //case GL_COMPUTE_SHADER: default: break; @@ -3302,7 +3439,7 @@ unsigned int rlCompileShader(const char *shaderCode, int type) int length = 0; char *log = RL_CALLOC(maxLength, sizeof(char)); glGetShaderInfoLog(shader, maxLength, &length, log); - TRACELOG(LOG_WARNING, "SHADER: [ID %i] Compile error: %s", shader, log); + TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Compile error: %s", shader, log); RL_FREE(log); } } @@ -3310,8 +3447,8 @@ unsigned int rlCompileShader(const char *shaderCode, int type) { switch (type) { - case GL_VERTEX_SHADER: TRACELOG(LOG_INFO, "SHADER: [ID %i] Vertex shader compiled successfully", shader); break; - case GL_FRAGMENT_SHADER: TRACELOG(LOG_INFO, "SHADER: [ID %i] Fragment shader compiled successfully", shader); break; + case GL_VERTEX_SHADER: TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Vertex shader compiled successfully", shader); break; + case GL_FRAGMENT_SHADER: TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Fragment shader compiled successfully", shader); break; //case GL_GEOMETRY_SHADER: //case GL_COMPUTE_SHADER: default: break; @@ -3335,12 +3472,12 @@ unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId) glAttachShader(program, fShaderId); // NOTE: Default attribute shader locations must be binded before linking - 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); + glBindAttribLocation(program, 0, RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION); + glBindAttribLocation(program, 1, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD); + glBindAttribLocation(program, 2, RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL); + glBindAttribLocation(program, 3, RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR); + glBindAttribLocation(program, 4, RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT); + glBindAttribLocation(program, 5, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2); // NOTE: If some attrib name is no found on the shader, it locations becomes -1 @@ -3352,7 +3489,7 @@ unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId) if (success == GL_FALSE) { - TRACELOG(LOG_WARNING, "SHADER: [ID %i] Failed to link shader program", program); + TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to link shader program", program); int maxLength = 0; glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength); @@ -3362,7 +3499,7 @@ unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId) int length = 0; char *log = RL_CALLOC(maxLength, sizeof(char)); glGetProgramInfoLog(program, maxLength, &length, log); - TRACELOG(LOG_WARNING, "SHADER: [ID %i] Link error: %s", program, log); + TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Link error: %s", program, log); RL_FREE(log); } @@ -3370,7 +3507,7 @@ unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId) program = 0; } - else TRACELOG(LOG_INFO, "SHADER: [ID %i] Program shader loaded successfully", program); + else TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Program shader loaded successfully", program); #endif return program; } @@ -3381,7 +3518,7 @@ void rlUnloadShaderProgram(unsigned int id) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) glDeleteProgram(id); - TRACELOG(LOG_INFO, "SHADER: [ID %i] Unloaded shader program data from VRAM (GPU)", id); + TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Unloaded shader program data from VRAM (GPU)", id); #endif } @@ -3392,8 +3529,8 @@ int rlGetLocationUniform(unsigned int shaderId, const char *uniformName) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) location = glGetUniformLocation(shaderId, uniformName); - if (location == -1) TRACELOG(LOG_WARNING, "SHADER: [ID %i] Failed to find shader uniform: %s", shaderId, uniformName); - else TRACELOG(LOG_INFO, "SHADER: [ID %i] Shader uniform (%s) set at location: %i", shaderId, uniformName, location); + if (location == -1) TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to find shader uniform: %s", shaderId, uniformName); + else TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Shader uniform (%s) set at location: %i", shaderId, uniformName, location); #endif return location; } @@ -3405,8 +3542,8 @@ int rlGetLocationAttrib(unsigned int shaderId, const char *attribName) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) location = glGetAttribLocation(shaderId, attribName); - if (location == -1) TRACELOG(LOG_WARNING, "SHADER: [ID %i] Failed to find shader attribute: %s", shaderId, attribName); - else TRACELOG(LOG_INFO, "SHADER: [ID %i] Shader attribute (%s) set at location: %i", shaderId, attribName, location); + if (location == -1) TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to find shader attribute: %s", shaderId, attribName); + else TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Shader attribute (%s) set at location: %i", shaderId, attribName, location); #endif return location; } @@ -3417,16 +3554,16 @@ void rlSetUniform(int locIndex, const void *value, int uniformType, int count) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) switch (uniformType) { - case SHADER_UNIFORM_FLOAT: glUniform1fv(locIndex, count, (float *)value); break; - case SHADER_UNIFORM_VEC2: glUniform2fv(locIndex, count, (float *)value); break; - case SHADER_UNIFORM_VEC3: glUniform3fv(locIndex, count, (float *)value); break; - case SHADER_UNIFORM_VEC4: glUniform4fv(locIndex, count, (float *)value); break; - case SHADER_UNIFORM_INT: glUniform1iv(locIndex, count, (int *)value); break; - case SHADER_UNIFORM_IVEC2: glUniform2iv(locIndex, count, (int *)value); break; - case SHADER_UNIFORM_IVEC3: glUniform3iv(locIndex, count, (int *)value); break; - case SHADER_UNIFORM_IVEC4: glUniform4iv(locIndex, count, (int *)value); break; - case SHADER_UNIFORM_SAMPLER2D: glUniform1iv(locIndex, count, (int *)value); break; - default: TRACELOG(LOG_WARNING, "SHADER: Failed to set uniform value, data type not recognized"); + case RL_SHADER_UNIFORM_FLOAT: glUniform1fv(locIndex, count, (float *)value); break; + case RL_SHADER_UNIFORM_VEC2: glUniform2fv(locIndex, count, (float *)value); break; + case RL_SHADER_UNIFORM_VEC3: glUniform3fv(locIndex, count, (float *)value); break; + case RL_SHADER_UNIFORM_VEC4: glUniform4fv(locIndex, count, (float *)value); break; + case RL_SHADER_UNIFORM_INT: glUniform1iv(locIndex, count, (int *)value); break; + case RL_SHADER_UNIFORM_IVEC2: glUniform2iv(locIndex, count, (int *)value); break; + case RL_SHADER_UNIFORM_IVEC3: glUniform3iv(locIndex, count, (int *)value); break; + case RL_SHADER_UNIFORM_IVEC4: glUniform4iv(locIndex, count, (int *)value); break; + case RL_SHADER_UNIFORM_SAMPLER2D: glUniform1iv(locIndex, count, (int *)value); break; + default: TRACELOG(RL_LOG_WARNING, "SHADER: Failed to set uniform value, data type not recognized"); } #endif } @@ -3437,11 +3574,11 @@ void rlSetVertexAttributeDefault(int locIndex, const void *value, int attribType #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) switch (attribType) { - case SHADER_ATTRIB_FLOAT: if (count == 1) glVertexAttrib1fv(locIndex, (float *)value); break; - case SHADER_ATTRIB_VEC2: if (count == 2) glVertexAttrib2fv(locIndex, (float *)value); break; - case SHADER_ATTRIB_VEC3: if (count == 3) glVertexAttrib3fv(locIndex, (float *)value); break; - case SHADER_ATTRIB_VEC4: if (count == 4) glVertexAttrib4fv(locIndex, (float *)value); break; - default: TRACELOG(LOG_WARNING, "SHADER: Failed to set attrib default value, data type not recognized"); + case RL_SHADER_ATTRIB_FLOAT: if (count == 1) glVertexAttrib1fv(locIndex, (float *)value); break; + case RL_SHADER_ATTRIB_VEC2: if (count == 2) glVertexAttrib2fv(locIndex, (float *)value); break; + case RL_SHADER_ATTRIB_VEC3: if (count == 3) glVertexAttrib3fv(locIndex, (float *)value); break; + case RL_SHADER_ATTRIB_VEC4: if (count == 4) glVertexAttrib4fv(locIndex, (float *)value); break; + default: TRACELOG(RL_LOG_WARNING, "SHADER: Failed to set attrib default value, data type not recognized"); } #endif } @@ -3450,7 +3587,13 @@ void rlSetVertexAttributeDefault(int locIndex, const void *value, int attribType void rlSetUniformMatrix(int locIndex, Matrix mat) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - glUniformMatrix4fv(locIndex, 1, false, MatrixToFloat(mat)); + float matfloat[16] = { + mat.m0, mat.m1, mat.m2, mat.m3, + mat.m4, mat.m5, mat.m6, mat.m7, + mat.m8, mat.m9, mat.m10, mat.m11, + mat.m12, mat.m13, mat.m14, mat.m15 + }; + glUniformMatrix4fv(locIndex, 1, false, matfloat); #endif } @@ -3459,11 +3602,11 @@ void rlSetUniformSampler(int locIndex, unsigned int textureId) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // Check if texture is already active - for (int i = 0; i < MAX_BATCH_ACTIVE_TEXTURES; i++) if (RLGL.State.activeTextureId[i] == textureId) return; + for (int i = 0; i < RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS; i++) if (RLGL.State.activeTextureId[i] == textureId) return; // Register a new active texture for the internal batch system // NOTE: Default texture is always activated as GL_TEXTURE0 - for (int i = 0; i < MAX_BATCH_ACTIVE_TEXTURES; i++) + for (int i = 0; i < RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS; i++) { if (RLGL.State.activeTextureId[i] == 0) { @@ -3475,14 +3618,15 @@ void rlSetUniformSampler(int locIndex, unsigned int textureId) #endif } -// Set shader currently active -void rlSetShader(Shader shader) +// Set shader currently active (id and locations) +void rlSetShader(unsigned int id, int *locs) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - if (RLGL.State.currentShader.id != shader.id) + if (RLGL.State.currentShaderId != id) { rlDrawRenderBatch(RLGL.currentBatch); - RLGL.State.currentShader = shader; + RLGL.State.currentShaderId = id; + RLGL.State.currentShaderLocs = locs; } #endif } @@ -3492,7 +3636,7 @@ void rlSetShader(Shader shader) // Get internal modelview matrix Matrix rlGetMatrixModelview(void) { - Matrix matrix = MatrixIdentity(); + Matrix matrix = rlMatrixIdentity(); #if defined(GRAPHICS_API_OPENGL_11) float mat[16]; glGetFloatv(GL_MODELVIEW_MATRIX, mat); @@ -3550,12 +3694,12 @@ Matrix rlGetMatrixProjection(void) // Get internal accumulated transform matrix Matrix rlGetMatrixTransform(void) { - Matrix mat = MatrixIdentity(); + Matrix mat = rlMatrixIdentity(); #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // TODO: Consider possible transform matrices in the RLGL.State.stack // Is this the right order? or should we start with the first stored matrix instead of the last one? - //Matrix matStackTransform = MatrixIdentity(); - //for (int i = RLGL.State.stackCounter; i > 0; i--) matStackTransform = MatrixMultiply(RLGL.State.stack[i], matStackTransform); + //Matrix matStackTransform = rlMatrixIdentity(); + //for (int i = RLGL.State.stackCounter; i > 0; i--) matStackTransform = rlMatrixMultiply(RLGL.State.stack[i], matStackTransform); mat = RLGL.State.transform; #endif return mat; @@ -3564,7 +3708,7 @@ Matrix rlGetMatrixTransform(void) // Get internal projection matrix for stereo render (selected eye) RLAPI Matrix rlGetMatrixProjectionStereo(int eye) { - Matrix mat = MatrixIdentity(); + Matrix mat = rlMatrixIdentity(); #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) mat = RLGL.State.projectionStereo[eye]; #endif @@ -3574,7 +3718,7 @@ RLAPI Matrix rlGetMatrixProjectionStereo(int eye) // Get internal view offset matrix for stereo render (selected eye) RLAPI Matrix rlGetMatrixViewOffsetStereo(int eye) { - Matrix mat = MatrixIdentity(); + Matrix mat = rlMatrixIdentity(); #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) mat = RLGL.State.viewOffsetStereo[eye]; #endif @@ -3739,28 +3883,28 @@ const char *rlGetPixelFormatName(unsigned int format) { switch (format) { - case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: return "GRAYSCALE"; break; // 8 bit per pixel (no alpha) - case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: return "GRAY_ALPHA"; break; // 8*2 bpp (2 channels) - case PIXELFORMAT_UNCOMPRESSED_R5G6B5: return "R5G6B5"; break; // 16 bpp - case PIXELFORMAT_UNCOMPRESSED_R8G8B8: return "R8G8B8"; break; // 24 bpp - case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: return "R5G5B5A1"; break; // 16 bpp (1 bit alpha) - case PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: return "R4G4B4A4"; break; // 16 bpp (4 bit alpha) - case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: return "R8G8B8A8"; break; // 32 bpp - case PIXELFORMAT_UNCOMPRESSED_R32: return "R32"; break; // 32 bpp (1 channel - float) - case PIXELFORMAT_UNCOMPRESSED_R32G32B32: return "R32G32B32"; break; // 32*3 bpp (3 channels - float) - case PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: return "R32G32B32A32"; break; // 32*4 bpp (4 channels - float) - case PIXELFORMAT_COMPRESSED_DXT1_RGB: return "DXT1_RGB"; break; // 4 bpp (no alpha) - case PIXELFORMAT_COMPRESSED_DXT1_RGBA: return "DXT1_RGBA"; break; // 4 bpp (1 bit alpha) - case PIXELFORMAT_COMPRESSED_DXT3_RGBA: return "DXT3_RGBA"; break; // 8 bpp - case PIXELFORMAT_COMPRESSED_DXT5_RGBA: return "DXT5_RGBA"; break; // 8 bpp - case PIXELFORMAT_COMPRESSED_ETC1_RGB: return "ETC1_RGB"; break; // 4 bpp - case PIXELFORMAT_COMPRESSED_ETC2_RGB: return "ETC2_RGB"; break; // 4 bpp - case PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA: return "ETC2_RGBA"; break; // 8 bpp - case PIXELFORMAT_COMPRESSED_PVRT_RGB: return "PVRT_RGB"; break; // 4 bpp - case PIXELFORMAT_COMPRESSED_PVRT_RGBA: return "PVRT_RGBA"; break; // 4 bpp - case PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA: return "ASTC_4x4_RGBA"; break; // 8 bpp - case PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: return "ASTC_8x8_RGBA"; break; // 2 bpp - default: return "\0"; break; + case RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: return "GRAYSCALE"; break; // 8 bit per pixel (no alpha) + case RL_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: return "GRAY_ALPHA"; break; // 8*2 bpp (2 channels) + case RL_PIXELFORMAT_UNCOMPRESSED_R5G6B5: return "R5G6B5"; break; // 16 bpp + case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8: return "R8G8B8"; break; // 24 bpp + case RL_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: return "R5G5B5A1"; break; // 16 bpp (1 bit alpha) + case RL_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: return "R4G4B4A4"; break; // 16 bpp (4 bit alpha) + case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: return "R8G8B8A8"; break; // 32 bpp + case RL_PIXELFORMAT_UNCOMPRESSED_R32: return "R32"; break; // 32 bpp (1 channel - float) + case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32: return "R32G32B32"; break; // 32*3 bpp (3 channels - float) + case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: return "R32G32B32A32"; break; // 32*4 bpp (4 channels - float) + case RL_PIXELFORMAT_COMPRESSED_DXT1_RGB: return "DXT1_RGB"; break; // 4 bpp (no alpha) + case RL_PIXELFORMAT_COMPRESSED_DXT1_RGBA: return "DXT1_RGBA"; break; // 4 bpp (1 bit alpha) + case RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA: return "DXT3_RGBA"; break; // 8 bpp + case RL_PIXELFORMAT_COMPRESSED_DXT5_RGBA: return "DXT5_RGBA"; break; // 8 bpp + case RL_PIXELFORMAT_COMPRESSED_ETC1_RGB: return "ETC1_RGB"; break; // 4 bpp + case RL_PIXELFORMAT_COMPRESSED_ETC2_RGB: return "ETC2_RGB"; break; // 4 bpp + case RL_PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA: return "ETC2_RGBA"; break; // 8 bpp + case RL_PIXELFORMAT_COMPRESSED_PVRT_RGB: return "PVRT_RGB"; break; // 4 bpp + case RL_PIXELFORMAT_COMPRESSED_PVRT_RGBA: return "PVRT_RGBA"; break; // 4 bpp + case RL_PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA: return "ASTC_4x4_RGBA"; break; // 8 bpp + case RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: return "ASTC_8x8_RGBA"; break; // 2 bpp + default: return "UNKNOWN"; break; } } @@ -3770,16 +3914,16 @@ const char *rlGetPixelFormatName(unsigned int format) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // Load default shader (just vertex positioning and texture coloring) // NOTE: This shader program is used for internal buffers -// NOTE: It uses global variable: RLGL.State.defaultShader +// NOTE: Loaded: RLGL.State.defaultShaderId, RLGL.State.defaultShaderLocs static void rlLoadShaderDefault(void) { - RLGL.State.defaultShader.locs = (int *)RL_CALLOC(MAX_SHADER_LOCATIONS, sizeof(int)); + RLGL.State.defaultShaderLocs = (int *)RL_CALLOC(RL_MAX_SHADER_LOCATIONS, sizeof(int)); // NOTE: All locations must be reseted to -1 (no location) - for (int i = 0; i < MAX_SHADER_LOCATIONS; i++) RLGL.State.defaultShader.locs[i] = -1; + for (int i = 0; i < RL_MAX_SHADER_LOCATIONS; i++) RLGL.State.defaultShaderLocs[i] = -1; // Vertex shader directly defined, no external file required - const char *vShaderDefault = + const char *defaultVShaderCode = #if defined(GRAPHICS_API_OPENGL_21) "#version 120 \n" "attribute vec3 vertexPosition; \n" @@ -3812,7 +3956,7 @@ static void rlLoadShaderDefault(void) "} \n"; // Fragment shader directly defined, no external file required - const char *fShaderDefault = + const char *defaultFShaderCode = #if defined(GRAPHICS_API_OPENGL_21) "#version 120 \n" "varying vec2 fragTexCoord; \n" @@ -3852,44 +3996,44 @@ static void rlLoadShaderDefault(void) #endif // NOTE: Compiled vertex/fragment shaders are kept for re-use - RLGL.State.defaultVShaderId = rlCompileShader(vShaderDefault, GL_VERTEX_SHADER); // Compile default vertex shader - RLGL.State.defaultFShaderId = rlCompileShader(fShaderDefault, GL_FRAGMENT_SHADER); // Compile default fragment shader + RLGL.State.defaultVShaderId = rlCompileShader(defaultVShaderCode, GL_VERTEX_SHADER); // Compile default vertex shader + RLGL.State.defaultFShaderId = rlCompileShader(defaultFShaderCode, GL_FRAGMENT_SHADER); // Compile default fragment shader - RLGL.State.defaultShader.id = rlLoadShaderProgram(RLGL.State.defaultVShaderId, RLGL.State.defaultFShaderId); + RLGL.State.defaultShaderId = rlLoadShaderProgram(RLGL.State.defaultVShaderId, RLGL.State.defaultFShaderId); - if (RLGL.State.defaultShader.id > 0) + if (RLGL.State.defaultShaderId > 0) { - TRACELOG(LOG_INFO, "SHADER: [ID %i] Default shader loaded successfully", RLGL.State.defaultShader.id); + TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Default shader loaded successfully", RLGL.State.defaultShaderId); // Set default shader locations: attributes locations - RLGL.State.defaultShader.locs[SHADER_LOC_VERTEX_POSITION] = glGetAttribLocation(RLGL.State.defaultShader.id, "vertexPosition"); - RLGL.State.defaultShader.locs[SHADER_LOC_VERTEX_TEXCOORD01] = glGetAttribLocation(RLGL.State.defaultShader.id, "vertexTexCoord"); - RLGL.State.defaultShader.locs[SHADER_LOC_VERTEX_COLOR] = glGetAttribLocation(RLGL.State.defaultShader.id, "vertexColor"); + RLGL.State.defaultShaderLocs[RL_SHADER_LOC_VERTEX_POSITION] = glGetAttribLocation(RLGL.State.defaultShaderId, "vertexPosition"); + RLGL.State.defaultShaderLocs[RL_SHADER_LOC_VERTEX_TEXCOORD01] = glGetAttribLocation(RLGL.State.defaultShaderId, "vertexTexCoord"); + RLGL.State.defaultShaderLocs[RL_SHADER_LOC_VERTEX_COLOR] = glGetAttribLocation(RLGL.State.defaultShaderId, "vertexColor"); // Set default shader locations: uniform locations - RLGL.State.defaultShader.locs[SHADER_LOC_MATRIX_MVP] = glGetUniformLocation(RLGL.State.defaultShader.id, "mvp"); - RLGL.State.defaultShader.locs[SHADER_LOC_COLOR_DIFFUSE] = glGetUniformLocation(RLGL.State.defaultShader.id, "colDiffuse"); - RLGL.State.defaultShader.locs[SHADER_LOC_MAP_DIFFUSE] = glGetUniformLocation(RLGL.State.defaultShader.id, "texture0"); + RLGL.State.defaultShaderLocs[RL_SHADER_LOC_MATRIX_MVP] = glGetUniformLocation(RLGL.State.defaultShaderId, "mvp"); + RLGL.State.defaultShaderLocs[RL_SHADER_LOC_COLOR_DIFFUSE] = glGetUniformLocation(RLGL.State.defaultShaderId, "colDiffuse"); + RLGL.State.defaultShaderLocs[RL_SHADER_LOC_MAP_DIFFUSE] = glGetUniformLocation(RLGL.State.defaultShaderId, "texture0"); } - else TRACELOG(LOG_WARNING, "SHADER: [ID %i] Failed to load default shader", RLGL.State.defaultShader.id); + else TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to load default shader", RLGL.State.defaultShaderId); } // Unload default shader -// NOTE: It uses global variable: RLGL.State.defaultShader +// NOTE: Unloads: RLGL.State.defaultShaderId, RLGL.State.defaultShaderLocs static void rlUnloadShaderDefault(void) { glUseProgram(0); - glDetachShader(RLGL.State.defaultShader.id, RLGL.State.defaultVShaderId); - glDetachShader(RLGL.State.defaultShader.id, RLGL.State.defaultFShaderId); + glDetachShader(RLGL.State.defaultShaderId, RLGL.State.defaultVShaderId); + glDetachShader(RLGL.State.defaultShaderId, RLGL.State.defaultFShaderId); glDeleteShader(RLGL.State.defaultVShaderId); glDeleteShader(RLGL.State.defaultFShaderId); - glDeleteProgram(RLGL.State.defaultShader.id); + glDeleteProgram(RLGL.State.defaultShaderId); - RL_FREE(RLGL.State.defaultShader.locs); + RL_FREE(RLGL.State.defaultShaderLocs); - TRACELOG(LOG_INFO, "SHADER: [ID %i] Default shader unloaded successfully", RLGL.State.defaultShader.id); + TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Default shader unloaded successfully", RLGL.State.defaultShaderId); } #if defined(SUPPORT_GL_DETAILS_INFO) @@ -3978,7 +4122,7 @@ static char *rlGetCompressedFormatName(int format) #if defined(GRAPHICS_API_OPENGL_11) // Mipmaps data is generated after image data // NOTE: Only works with RGBA (4 bytes) data! -static int rlGenerateMipmapsData(unsigned char *data, int baseWidth, int baseHeight) +static int rlGenTextureMipmapsData(unsigned char *data, int baseWidth, int baseHeight) { int mipmapCount = 1; // Required mipmap levels count (including base level) int width = baseWidth; @@ -4004,7 +4148,7 @@ static int rlGenerateMipmapsData(unsigned char *data, int baseWidth, int baseHei unsigned char *temp = RL_REALLOC(data, size); if (temp != NULL) data = temp; - else TRACELOG(LOG_WARNING, "TEXTURE: Failed to re-allocate required mipmaps memory"); + else TRACELOG(RL_LOG_WARNING, "TEXTURE: Failed to re-allocate required mipmaps memory"); width = baseWidth; height = baseHeight; @@ -4110,27 +4254,27 @@ static int rlGetPixelDataSize(int width, int height, int format) switch (format) { - case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: bpp = 8; break; - case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: - case PIXELFORMAT_UNCOMPRESSED_R5G6B5: - case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: - case PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: bpp = 16; break; - case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: bpp = 32; break; - case PIXELFORMAT_UNCOMPRESSED_R8G8B8: bpp = 24; break; - case PIXELFORMAT_UNCOMPRESSED_R32: bpp = 32; break; - case PIXELFORMAT_UNCOMPRESSED_R32G32B32: bpp = 32*3; break; - case PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: bpp = 32*4; break; - case PIXELFORMAT_COMPRESSED_DXT1_RGB: - case PIXELFORMAT_COMPRESSED_DXT1_RGBA: - case PIXELFORMAT_COMPRESSED_ETC1_RGB: - case PIXELFORMAT_COMPRESSED_ETC2_RGB: - case PIXELFORMAT_COMPRESSED_PVRT_RGB: - case PIXELFORMAT_COMPRESSED_PVRT_RGBA: bpp = 4; break; - case PIXELFORMAT_COMPRESSED_DXT3_RGBA: - case PIXELFORMAT_COMPRESSED_DXT5_RGBA: - case PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA: - case PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA: bpp = 8; break; - case PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: bpp = 2; break; + case RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: bpp = 8; break; + case RL_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: + case RL_PIXELFORMAT_UNCOMPRESSED_R5G6B5: + case RL_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: + case RL_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: bpp = 16; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: bpp = 32; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8: bpp = 24; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R32: bpp = 32; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32: bpp = 32*3; break; + case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: bpp = 32*4; break; + case RL_PIXELFORMAT_COMPRESSED_DXT1_RGB: + case RL_PIXELFORMAT_COMPRESSED_DXT1_RGBA: + case RL_PIXELFORMAT_COMPRESSED_ETC1_RGB: + case RL_PIXELFORMAT_COMPRESSED_ETC2_RGB: + case RL_PIXELFORMAT_COMPRESSED_PVRT_RGB: + case RL_PIXELFORMAT_COMPRESSED_PVRT_RGBA: bpp = 4; break; + case RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA: + case RL_PIXELFORMAT_COMPRESSED_DXT5_RGBA: + case RL_PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA: + case RL_PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA: bpp = 8; break; + case RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: bpp = 2; break; default: break; } @@ -4140,10 +4284,52 @@ static int rlGetPixelDataSize(int width, int height, int format) // if texture is smaller, minimum dataSize is 8 or 16 if ((width < 4) && (height < 4)) { - if ((format >= PIXELFORMAT_COMPRESSED_DXT1_RGB) && (format < PIXELFORMAT_COMPRESSED_DXT3_RGBA)) dataSize = 8; - else if ((format >= PIXELFORMAT_COMPRESSED_DXT3_RGBA) && (format < PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA)) dataSize = 16; + if ((format >= RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) && (format < RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA)) dataSize = 8; + else if ((format >= RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA) && (format < RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA)) dataSize = 16; } return dataSize; } + +// Auxiliar math functions + +// Get identity matrix +static Matrix rlMatrixIdentity(void) +{ + Matrix result = { + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + + return result; +} + +// Get two matrix multiplication +// NOTE: When multiplying matrices... the order matters! +static Matrix rlMatrixMultiply(Matrix left, Matrix right) +{ + Matrix result = { 0 }; + + result.m0 = left.m0*right.m0 + left.m1*right.m4 + left.m2*right.m8 + left.m3*right.m12; + result.m1 = left.m0*right.m1 + left.m1*right.m5 + left.m2*right.m9 + left.m3*right.m13; + result.m2 = left.m0*right.m2 + left.m1*right.m6 + left.m2*right.m10 + left.m3*right.m14; + result.m3 = left.m0*right.m3 + left.m1*right.m7 + left.m2*right.m11 + left.m3*right.m15; + result.m4 = left.m4*right.m0 + left.m5*right.m4 + left.m6*right.m8 + left.m7*right.m12; + result.m5 = left.m4*right.m1 + left.m5*right.m5 + left.m6*right.m9 + left.m7*right.m13; + result.m6 = left.m4*right.m2 + left.m5*right.m6 + left.m6*right.m10 + left.m7*right.m14; + result.m7 = left.m4*right.m3 + left.m5*right.m7 + left.m6*right.m11 + left.m7*right.m15; + result.m8 = left.m8*right.m0 + left.m9*right.m4 + left.m10*right.m8 + left.m11*right.m12; + result.m9 = left.m8*right.m1 + left.m9*right.m5 + left.m10*right.m9 + left.m11*right.m13; + result.m10 = left.m8*right.m2 + left.m9*right.m6 + left.m10*right.m10 + left.m11*right.m14; + result.m11 = left.m8*right.m3 + left.m9*right.m7 + left.m10*right.m11 + left.m11*right.m15; + result.m12 = left.m12*right.m0 + left.m13*right.m4 + left.m14*right.m8 + left.m15*right.m12; + result.m13 = left.m12*right.m1 + left.m13*right.m5 + left.m14*right.m9 + left.m15*right.m13; + result.m14 = left.m12*right.m2 + left.m13*right.m6 + left.m14*right.m10 + left.m15*right.m14; + result.m15 = left.m12*right.m3 + left.m13*right.m7 + left.m14*right.m11 + left.m15*right.m15; + + return result; +} + #endif // RLGL_IMPLEMENTATION diff --git a/src/shapes.c b/src/shapes.c index 6f8ae6490..104aef0a7 100644 --- a/src/shapes.c +++ b/src/shapes.c @@ -36,7 +36,7 @@ #include "config.h" // Defines module configuration flags #endif -#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2 +#include "rlgl.h" // OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2 #include // Required for: sinf(), asinf(), cosf(), acosf(), sqrtf(), fabsf() diff --git a/src/text.c b/src/text.c index e16547f38..9d336f218 100644 --- a/src/text.c +++ b/src/text.c @@ -53,14 +53,15 @@ #include "config.h" // Defines module configuration flags #endif +#include "utils.h" // Required for: LoadFileText() +#include "rlgl.h" // OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2 -> Only DrawTextPro() + #include // Required for: malloc(), free() #include // Required for: vsprintf() #include // Required for: strcmp(), strstr(), strcpy(), strncpy() [Used in TextReplace()], sscanf() [Used in LoadBMFont()] #include // Required for: va_list, va_start(), vsprintf(), va_end() [Used in TextFormat()] #include // Requried for: toupper(), tolower() [Used in TextToUpper(), TextToLower()] -#include "utils.h" // Required for: LoadFileText() - #if defined(SUPPORT_FILEFORMAT_TTF) #define STB_RECT_PACK_IMPLEMENTATION #include "external/stb_rect_pack.h" // Required for: ttf font rectangles packaging @@ -125,7 +126,7 @@ extern void LoadFontDefault(void) { #define BIT_CHECK(a,b) ((a) & (1u << (b))) - // NOTE: Using UTF8 encoding table for Unicode U+0000..U+00FF Basic Latin + Latin-1 Supplement + // NOTE: Using UTF-8 encoding table for Unicode U+0000..U+00FF Basic Latin + Latin-1 Supplement // Ref: http://www.utf8-chartable.de/unicode-utf8-table.pl defaultFont.charsCount = 224; // Number of chars included in our default font @@ -224,7 +225,7 @@ extern void LoadFontDefault(void) // Allocate space for our characters info data // NOTE: This memory should be freed at end! --> CloseWindow() - defaultFont.chars = (CharInfo *)RL_MALLOC(defaultFont.charsCount*sizeof(CharInfo)); + defaultFont.chars = (GlyphInfo *)RL_MALLOC(defaultFont.charsCount*sizeof(GlyphInfo)); defaultFont.recs = (Rectangle *)RL_MALLOC(defaultFont.charsCount*sizeof(Rectangle)); int currentLine = 0; @@ -266,7 +267,7 @@ extern void LoadFontDefault(void) defaultFont.baseSize = (int)defaultFont.recs[0].height; - TRACELOG(LOG_INFO, "FONT: Default font loaded successfully"); + TRACELOG(LOG_INFO, "FONT: [ID %i] Default font texture loaded successfully", defaultFont.texture.id); } // Unload raylib default font @@ -453,7 +454,7 @@ Font LoadFontFromImage(Image image, Color key, int firstChar) // We got tempCharValues and tempCharsRecs populated with chars data // Now we move temp data to sized charValues and charRecs arrays - font.chars = (CharInfo *)RL_MALLOC(font.charsCount*sizeof(CharInfo)); + font.chars = (GlyphInfo *)RL_MALLOC(font.charsCount*sizeof(GlyphInfo)); font.recs = (Rectangle *)RL_MALLOC(font.charsCount*sizeof(Rectangle)); for (int i = 0; i < font.charsCount; i++) @@ -523,7 +524,7 @@ Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int // Load font data for further use // NOTE: Requires TTF font memory data and can generate SDF data -CharInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int charsCount, int type) +GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int charsCount, int type) { // NOTE: Using some SDF generation default values, // trades off precision with ability to handle *smaller* sizes @@ -540,7 +541,7 @@ CharInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize #define FONT_BITMAP_ALPHA_THRESHOLD 80 // Bitmap (B&W) font generation alpha threshold #endif - CharInfo *chars = NULL; + GlyphInfo *chars = NULL; #if defined(SUPPORT_FILEFORMAT_TTF) // Load font data (including pixel data) from TTF memory file @@ -573,7 +574,7 @@ CharInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize genFontChars = true; } - chars = (CharInfo *)RL_MALLOC(charsCount*sizeof(CharInfo)); + chars = (GlyphInfo *)RL_MALLOC(charsCount*sizeof(GlyphInfo)); // NOTE: Using simple packaging, one char after another for (int i = 0; i < charsCount; i++) @@ -649,7 +650,7 @@ CharInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize // Generate image font atlas using chars info // NOTE: Packing method: 0-Default, 1-Skyline #if defined(SUPPORT_FILEFORMAT_TTF) -Image GenImageFontAtlas(const CharInfo *chars, Rectangle **charRecs, int charsCount, int fontSize, int padding, int packMethod) +Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int charsCount, int fontSize, int padding, int packMethod) { Image atlas = { 0 }; @@ -792,7 +793,7 @@ Image GenImageFontAtlas(const CharInfo *chars, Rectangle **charRecs, int charsCo #endif // Unload font chars info data (RAM) -void UnloadFontData(CharInfo *chars, int charsCount) +void UnloadFontData(GlyphInfo *chars, int charsCount) { for (int i = 0; i < charsCount; i++) UnloadImage(chars[i].image); @@ -890,140 +891,18 @@ void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, f } } -// Draw text using font inside rectangle limits -void DrawTextRec(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint) +// Draw text using Font and pro parameters (rotation) +void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint) { - DrawTextRecEx(font, text, rec, fontSize, spacing, wordWrap, tint, 0, 0, WHITE, WHITE); -} + rlPushMatrix(); -// Draw text using font inside rectangle limits with support for text selection -void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint, int selectStart, int selectLength, Color selectTint, Color selectBackTint) -{ - int length = TextLength(text); // Total length in bytes of the text, scanned by codepoints in loop - - float textOffsetY = 0; // Offset between lines (on line break '\n') - float textOffsetX = 0.0f; // Offset X to next character to draw - - float scaleFactor = fontSize/(float)font.baseSize; // Character quad scaling factor - - // Word/character wrapping mechanism variables - enum { MEASURE_STATE = 0, DRAW_STATE = 1 }; - int state = wordWrap? MEASURE_STATE : DRAW_STATE; - - int startLine = -1; // Index where to begin drawing (where a line begins) - int endLine = -1; // Index where to stop drawing (where a line ends) - int lastk = -1; // Holds last value of the character position - - for (int i = 0, k = 0; i < length; i++, k++) - { - // Get next codepoint from byte string and glyph index in font - int codepointByteCount = 0; - int codepoint = GetCodepoint(&text[i], &codepointByteCount); - int index = GetGlyphIndex(font, codepoint); - - // NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f) - // but we need to draw all of the bad bytes using the '?' symbol moving one byte - if (codepoint == 0x3f) codepointByteCount = 1; - i += (codepointByteCount - 1); - - float glyphWidth = 0; - if (codepoint != '\n') - { - glyphWidth = (font.chars[index].advanceX == 0) ? font.recs[index].width*scaleFactor : font.chars[index].advanceX*scaleFactor; - - if (i + 1 < length) glyphWidth = glyphWidth + spacing; - } - - // NOTE: When wordWrap is ON we first measure how much of the text we can draw before going outside of the rec container - // We store this info in startLine and endLine, then we change states, draw the text between those two variables - // and change states again and again recursively until the end of the text (or until we get outside of the container). - // When wordWrap is OFF we don't need the measure state so we go to the drawing state immediately - // and begin drawing on the next line before we can get outside the container. - if (state == MEASURE_STATE) - { - // TODO: There are multiple types of spaces in UNICODE, maybe it's a good idea to add support for more - // Ref: http://jkorpela.fi/chars/spaces.html - if ((codepoint == ' ') || (codepoint == '\t') || (codepoint == '\n')) endLine = i; - - if ((textOffsetX + glyphWidth) > rec.width) - { - endLine = (endLine < 1)? i : endLine; - if (i == endLine) endLine -= codepointByteCount; - if ((startLine + codepointByteCount) == endLine) endLine = (i - codepointByteCount); - - state = !state; - } - else if ((i + 1) == length) - { - endLine = i; - state = !state; - } - else if (codepoint == '\n') state = !state; - - if (state == DRAW_STATE) - { - textOffsetX = 0; - i = startLine; - glyphWidth = 0; - - // Save character position when we switch states - int tmp = lastk; - lastk = k - 1; - k = tmp; - } - } - else - { - if (codepoint == '\n') - { - if (!wordWrap) - { - textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor; - textOffsetX = 0; - } - } - else - { - if (!wordWrap && ((textOffsetX + glyphWidth) > rec.width)) - { - textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor; - textOffsetX = 0; - } - - // When text overflows rectangle height limit, just stop drawing - if ((textOffsetY + font.baseSize*scaleFactor) > rec.height) break; - - // Draw selection background - bool isGlyphSelected = false; - if ((selectStart >= 0) && (k >= selectStart) && (k < (selectStart + selectLength))) - { - DrawRectangleRec((Rectangle){ rec.x + textOffsetX - 1, rec.y + textOffsetY, glyphWidth, (float)font.baseSize*scaleFactor }, selectBackTint); - isGlyphSelected = true; - } - - // Draw current character glyph - if ((codepoint != ' ') && (codepoint != '\t')) - { - DrawTextCodepoint(font, codepoint, (Vector2){ rec.x + textOffsetX, rec.y + textOffsetY }, fontSize, isGlyphSelected? selectTint : tint); - } - } - - if (wordWrap && (i == endLine)) - { - textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor; - textOffsetX = 0; - startLine = endLine; - endLine = -1; - glyphWidth = 0; - selectStart += lastk - k; - k = lastk; - - state = !state; - } - } - - textOffsetX += glyphWidth; - } + rlTranslatef(position.x, position.y, 0.0f); + rlRotatef(rotation, 0.0f, 0.0f, 1.0f); + rlTranslatef(-origin.x, -origin.y, 0.0f); + + DrawTextEx(font, text, (Vector2){ 0.0f, 0.0f }, fontSize, spacing, tint); + + rlPopMatrix(); } // Draw one character (codepoint) @@ -1123,6 +1002,7 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing } // Get index position for a unicode character on font +// NOTE: If codepoint is not found in the font it fallbacks to '?' int GetGlyphIndex(Font font, int codepoint) { #ifndef GLYPH_NOTFOUND_CHAR_FALLBACK @@ -1149,6 +1029,28 @@ int GetGlyphIndex(Font font, int codepoint) #endif } +// Get glyph font info data for a codepoint (unicode character) +// NOTE: If codepoint is not found in the font it fallbacks to '?' +GlyphInfo GetGlyphInfo(Font font, int codepoint) +{ + GlyphInfo info = { 0 }; + + info = font.chars[GetGlyphIndex(font, codepoint)]; + + return info; +} + +// Get glyph rectangle in font atlas for a codepoint (unicode character) +// NOTE: If codepoint is not found in the font it fallbacks to '?' +Rectangle GetGlyphAtlasRec(Font font, int codepoint) +{ + Rectangle rec = { 0 }; + + rec = font.recs[GetGlyphIndex(font, codepoint)]; + + return rec; +} + //---------------------------------------------------------------------------------- // Text strings management functions //---------------------------------------------------------------------------------- @@ -1446,7 +1348,7 @@ const char *TextToUpper(const char *text) buffer[i] = (char)toupper(text[i]); //if ((text[i] >= 'a') && (text[i] <= 'z')) buffer[i] = text[i] - 32; - // TODO: Support Utf8 diacritics! + // TODO: Support UTF-8 diacritics! //if ((text[i] >= 'à') && (text[i] <= 'ý')) buffer[i] = text[i] - 32; } else { buffer[i] = '\0'; break; } @@ -1499,10 +1401,10 @@ const char *TextToPascal(const char *text) return buffer; } -// Encode text codepoint into utf8 text +// Encode text codepoint into UTF-8 text // REQUIRES: memcpy() // WARNING: Allocated memory should be manually freed -char *TextToUtf8(int *codepoints, int length) +char *TextCodepointsToUTF8(int *codepoints, int length) { // We allocate enough memory fo fit all possible codepoints // NOTE: 5 bytes for every codepoint should be enough @@ -1512,7 +1414,7 @@ char *TextToUtf8(int *codepoints, int length) for (int i = 0, bytes = 0; i < length; i++) { - utf8 = CodepointToUtf8(codepoints[i], &bytes); + utf8 = CodepointToUTF8(codepoints[i], &bytes); memcpy(text + size, utf8, bytes); size += bytes; } @@ -1526,7 +1428,8 @@ char *TextToUtf8(int *codepoints, int length) } // Encode codepoint into utf8 text (char array length returned as parameter) -RLAPI const char *CodepointToUtf8(int codepoint, int *byteLength) +// NOTE: It uses a static array to store UTF-8 bytes +RLAPI const char *CodepointToUTF8(int codepoint, int *byteLength) { static char utf8[6] = { 0 }; int length = 0; @@ -1563,7 +1466,7 @@ RLAPI const char *CodepointToUtf8(int codepoint, int *byteLength) return utf8; } -// Load all codepoints from a UTF8 text string, codepoints count returned by parameter +// Load all codepoints from a UTF-8 text string, codepoints count returned by parameter int *LoadCodepoints(const char *text, int *count) { int textLength = TextLength(text); @@ -1595,8 +1498,8 @@ void UnloadCodepoints(int *codepoints) RL_FREE(codepoints); } -// Get total number of characters(codepoints) in a UTF8 encoded text, until '\0' is found -// NOTE: If an invalid UTF8 sequence is encountered a '?'(0x3f) codepoint is counted instead +// Get total number of characters(codepoints) in a UTF-8 encoded text, until '\0' is found +// NOTE: If an invalid UTF-8 sequence is encountered a '?'(0x3f) codepoint is counted instead int GetCodepointsCount(const char *text) { unsigned int len = 0; @@ -1617,8 +1520,8 @@ int GetCodepointsCount(const char *text) } #endif // SUPPORT_TEXT_MANIPULATION -// Get next codepoint in a UTF8 encoded text, scanning until '\0' is found -// When a invalid UTF8 byte is encountered we exit as soon as possible and a '?'(0x3f) codepoint is returned +// Get next codepoint in a UTF-8 encoded text, scanning until '\0' is found +// When a invalid UTF-8 byte is encountered we exit as soon as possible and a '?'(0x3f) codepoint is returned // Total number of bytes processed are returned as a parameter // NOTE: the standard says U+FFFD should be returned in case of errors // but that character is not supported by the default font in raylib @@ -1626,7 +1529,7 @@ int GetCodepointsCount(const char *text) int GetCodepoint(const char *text, int *bytesProcessed) { /* - UTF8 specs from https://www.ietf.org/rfc/rfc3629.txt + UTF-8 specs from https://www.ietf.org/rfc/rfc3629.txt Char. number range | UTF-8 octet sequence (hexadecimal) | (binary) @@ -1845,7 +1748,7 @@ static Font LoadBMFont(const char *fileName) font.baseSize = fontSize; font.charsCount = charsCount; font.charsPadding = 0; - font.chars = (CharInfo *)RL_MALLOC(charsCount*sizeof(CharInfo)); + font.chars = (GlyphInfo *)RL_MALLOC(charsCount*sizeof(GlyphInfo)); font.recs = (Rectangle *)RL_MALLOC(charsCount*sizeof(Rectangle)); int charId, charX, charY, charWidth, charHeight, charOffsetX, charOffsetY, charAdvanceX; diff --git a/src/textures.c b/src/textures.c index 9bef90c4c..2480bcfcc 100644 --- a/src/textures.c +++ b/src/textures.c @@ -64,17 +64,14 @@ #include "config.h" // Defines module configuration flags #endif +#include "utils.h" // Required for: TRACELOG() and fopen() Android mapping +#include "rlgl.h" // OpenGL abstraction layer to OpenGL 1.1, 3.3 or ES2 + #include // Required for: malloc(), free() #include // Required for: strlen() [Used in ImageTextEx()] #include // Required for: fabsf() #include // Required for: sprintf() [Used in ExportImageAsCode()] -#include "utils.h" // Required for: fopen() Android mapping - -#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3 or ES2 - // Required for: rlLoadTexture() rlUnloadTexture(), - // rlGenerateMipmaps(), some funcs for DrawTexturePro() - // Support only desired texture formats on stb_image #if !defined(SUPPORT_FILEFORMAT_BMP) #define STBI_NO_BMP @@ -331,12 +328,15 @@ Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, i int comp = 0; image.data = stbi_load_from_memory(fileData, dataSize, &image.width, &image.height, &comp, 0); - image.mipmaps = 1; + if (image.data != NULL) + { + image.mipmaps = 1; - if (comp == 1) image.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE; - else if (comp == 2) image.format = PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA; - else if (comp == 3) image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8; - else if (comp == 4) image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8; + if (comp == 1) image.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE; + else if (comp == 2) image.format = PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA; + else if (comp == 3) image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8; + else if (comp == 4) image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8; + } } #endif } @@ -380,8 +380,9 @@ Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, i #endif else TRACELOG(LOG_WARNING, "IMAGE: Data format not supported"); - TRACELOG(LOG_INFO, "IMAGE: Data loaded successfully (%ix%i | %s | %i mipmaps)", image.width, image.height, rlGetPixelFormatName(image.format), image.mipmaps); - + if (image.data != NULL) TRACELOG(LOG_INFO, "IMAGE: Data loaded successfully (%ix%i | %s | %i mipmaps)", image.width, image.height, rlGetPixelFormatName(image.format), image.mipmaps); + else TRACELOG(LOG_WARNING, "IMAGE: Failed to load image data"); + return image; } @@ -393,7 +394,7 @@ Image LoadImageFromTexture(Texture2D texture) if (texture.format < PIXELFORMAT_COMPRESSED_DXT1_RGB) { - image.data = rlReadTexturePixels(texture); + image.data = rlReadTexturePixels(texture.id, texture.width, texture.height, texture.format); if (image.data != NULL) { @@ -2344,7 +2345,7 @@ void ImageDrawPixel(Image *dst, int x, int y, Color color) 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)PIXELFORMAT_UNCOMPRESSED_R5G5B5A1_ALPHA_THRESHOLD/255.0f))? 1 : 0;; + unsigned char a = (coln.w > ((float)PIXELFORMAT_UNCOMPRESSED_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; @@ -2418,19 +2419,91 @@ void ImageDrawPixelV(Image *dst, Vector2 position, Color color) // Draw line within an image void ImageDrawLine(Image *dst, int startPosX, int startPosY, int endPosX, int endPosY, Color color) { - int m = 2*(endPosY - startPosY); - int slopeError = m - (endPosX - startPosX); - - for (int x = startPosX, y = startPosY; x <= endPosX; x++) + // Using Bresenham's algorithm as described in + // Drawing Lines with Pixels - Joshua Scott - March 2012 + // https://classic.csunplugged.org/wp-content/uploads/2014/12/Lines.pdf + + int changeInX = (endPosX - startPosX); + int absChangeInX = (changeInX < 0)? -changeInX : changeInX; + int changeInY = (endPosY - startPosY); + int absChangeInY = (changeInY < 0)? -changeInY : changeInY; + + int startU, startV, endU, stepV; // Substitutions, either U = X, V = Y or vice versa. See loop at end of function + //int endV; // Not needed but left for better understanding, check code below + int A, B, P; // See linked paper above, explained down in the main loop + int reversedXY = (absChangeInY < absChangeInX); + + if (reversedXY) { - ImageDrawPixel(dst, x, y, color); - slopeError += m; + A = 2*absChangeInY; + B = A - 2*absChangeInX; + P = A - absChangeInX; - if (slopeError >= 0) - { - y++; - slopeError -= 2*(endPosX - startPosX); + if (changeInX > 0) + { + startU = startPosX; + startV = startPosY; + endU = endPosX; + //endV = endPosY; } + else + { + startU = endPosX; + startV = endPosY; + endU = startPosX; + //endV = startPosY; + + // Since start and end are reversed + changeInX = -changeInX; + changeInY = -changeInY; + } + + stepV = (changeInY < 0)? -1 : 1; + + ImageDrawPixel(dst, startU, startV, color); // At this point they are correctly ordered... + } + else + { + A = 2*absChangeInX; + B = A - 2*absChangeInY; + P = A - absChangeInY; + + if (changeInY > 0) + { + startU = startPosY; + startV = startPosX; + endU = endPosY; + //endV = endPosX; + } + else + { + startU = endPosY; + startV = endPosX; + endU = startPosY; + //endV = startPosX; + + // Since start and end are reversed + changeInX = -changeInX; + changeInY = -changeInY; + } + + stepV = (changeInX < 0)? -1 : 1; + + ImageDrawPixel(dst, startV, startU, color); // ... but need to be reversed here. Repeated in the main loop below + } + + // We already drew the start point. If we started at startU + 0, the line would be crooked and too short + for (int u = startU + 1, v = startV; u <= endU; u++) + { + if (P >= 0) + { + v += stepV; // Adjusts whenever we stray too far from the direct line. Details in the linked paper above + P += B; // Remembers that we corrected our path + } + else P += A; // Remembers how far we are from the direct line + + if (reversedXY) ImageDrawPixel(dst, u, v, color); + else ImageDrawPixel(dst, v, u, color); } } @@ -2858,7 +2931,7 @@ void GenTextureMipmaps(Texture2D *texture) { // NOTE: NPOT textures support check inside function // On WebGL (OpenGL ES 2.0) NPOT textures support is limited - rlGenerateMipmaps(texture); + rlGenTextureMipmaps(texture->id, texture->width, texture->height, texture->format, &texture->mipmaps); } // Set texture scaling filter mode @@ -3734,7 +3807,7 @@ void SetPixelColor(void *dstPtr, Color color, int format) 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)PIXELFORMAT_UNCOMPRESSED_R5G5B5A1_ALPHA_THRESHOLD/255.0f))? 1 : 0;; + unsigned char a = (coln.w > ((float)PIXELFORMAT_UNCOMPRESSED_R5G5B5A1_ALPHA_THRESHOLD/255.0f))? 1 : 0; ((unsigned short *)dstPtr)[0] = (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 2e3e4fd31..dbf4b3bbb 100644 --- a/src/utils.c +++ b/src/utils.c @@ -56,9 +56,6 @@ #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