github.com/Konstantin8105/c4go@v0.0.0-20240505174241-768bb1c65a51/tests/raylib/rlgl.h (about)

     1  /**********************************************************************************************
     2  *
     3  *   rlgl v4.2 - A multi-OpenGL abstraction layer with an immediate-mode style API
     4  *
     5  *   An abstraction layer for multiple OpenGL versions (1.1, 2.1, 3.3 Core, 4.3 Core, ES 2.0)
     6  *   that provides a pseudo-OpenGL 1.1 immediate-mode style API (rlVertex, rlTranslate, rlRotate...)
     7  *
     8  *   When chosing an OpenGL backend different than OpenGL 1.1, some internal buffer are
     9  *   initialized on rlglInit() to accumulate vertex data.
    10  *
    11  *   When an internal state change is required all the stored vertex data is renderer in batch,
    12  *   additioanlly, rlDrawRenderBatchActive() could be called to force flushing of the batch.
    13  *
    14  *   Some additional resources are also loaded for convenience, here the complete list:
    15  *      - Default batch (RLGL.defaultBatch): RenderBatch system to accumulate vertex data
    16  *      - Default texture (RLGL.defaultTextureId): 1x1 white pixel R8G8B8A8
    17  *      - Default shader (RLGL.State.defaultShaderId, RLGL.State.defaultShaderLocs)
    18  *
    19  *   Internal buffer (and additional resources) must be manually unloaded calling rlglClose().
    20  *
    21  *
    22  *   CONFIGURATION:
    23  *
    24  *   #define GRAPHICS_API_OPENGL_11
    25  *   #define GRAPHICS_API_OPENGL_21
    26  *   #define GRAPHICS_API_OPENGL_33
    27  *   #define GRAPHICS_API_OPENGL_43
    28  *   #define GRAPHICS_API_OPENGL_ES2
    29  *       Use selected OpenGL graphics backend, should be supported by platform
    30  *       Those preprocessor defines are only used on rlgl module, if OpenGL version is
    31  *       required by any other module, use rlGetVersion() to check it
    32  *
    33  *   #define RLGL_IMPLEMENTATION
    34  *       Generates the implementation of the library into the included file.
    35  *       If not defined, the library is in header only mode and can be included in other headers
    36  *       or source files without problems. But only ONE file should hold the implementation.
    37  *
    38  *   #define RLGL_RENDER_TEXTURES_HINT
    39  *       Enable framebuffer objects (fbo) support (enabled by default)
    40  *       Some GPUs could not support them despite the OpenGL version
    41  *
    42  *   #define RLGL_SHOW_GL_DETAILS_INFO
    43  *       Show OpenGL extensions and capabilities detailed logs on init
    44  *
    45  *   #define RLGL_ENABLE_OPENGL_DEBUG_CONTEXT
    46  *       Enable debug context (only available on OpenGL 4.3)
    47  *
    48  *   rlgl capabilities could be customized just defining some internal
    49  *   values before library inclusion (default values listed):
    50  *
    51  *   #define RL_DEFAULT_BATCH_BUFFER_ELEMENTS   8192    // Default internal render batch elements limits
    52  *   #define RL_DEFAULT_BATCH_BUFFERS              1    // Default number of batch buffers (multi-buffering)
    53  *   #define RL_DEFAULT_BATCH_DRAWCALLS          256    // Default number of batch draw calls (by state changes: mode, texture)
    54  *   #define RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS    4    // Maximum number of textures units that can be activated on batch drawing (SetShaderValueTexture())
    55  *
    56  *   #define RL_MAX_MATRIX_STACK_SIZE             32    // Maximum size of internal Matrix stack
    57  *   #define RL_MAX_SHADER_LOCATIONS              32    // Maximum number of shader locations supported
    58  *   #define RL_CULL_DISTANCE_NEAR              0.01    // Default projection matrix near cull distance
    59  *   #define RL_CULL_DISTANCE_FAR             1000.0    // Default projection matrix far cull distance
    60  *
    61  *   When loading a shader, the following vertex attribute and uniform
    62  *   location names are tried to be set automatically:
    63  *
    64  *   #define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION     "vertexPosition"    // Binded by default to shader location: 0
    65  *   #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD     "vertexTexCoord"    // Binded by default to shader location: 1
    66  *   #define RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL       "vertexNormal"      // Binded by default to shader location: 2
    67  *   #define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR        "vertexColor"       // Binded by default to shader location: 3
    68  *   #define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT      "vertexTangent"     // Binded by default to shader location: 4
    69  *   #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2    "vertexTexCoord2"   // Binded by default to shader location: 5
    70  *   #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP         "mvp"               // model-view-projection matrix
    71  *   #define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW        "matView"           // view matrix
    72  *   #define RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION  "matProjection"     // projection matrix
    73  *   #define RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL       "matModel"          // model matrix
    74  *   #define RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL      "matNormal"         // normal matrix (transpose(inverse(matModelView))
    75  *   #define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR       "colDiffuse"        // color diffuse (base tint color, multiplied by texture color)
    76  *   #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0  "texture0"          // texture0 (texture slot active 0)
    77  *   #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1  "texture1"          // texture1 (texture slot active 1)
    78  *   #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2  "texture2"          // texture2 (texture slot active 2)
    79  *
    80  *   DEPENDENCIES:
    81  *
    82  *      - OpenGL libraries (depending on platform and OpenGL version selected)
    83  *      - GLAD OpenGL extensions loading library (only for OpenGL 3.3 Core, 4.3 Core)
    84  *
    85  *
    86  *   LICENSE: zlib/libpng
    87  *
    88  *   Copyright (c) 2014-2022 Ramon Santamaria (@raysan5)
    89  *
    90  *   This software is provided "as-is", without any express or implied warranty. In no event
    91  *   will the authors be held liable for any damages arising from the use of this software.
    92  *
    93  *   Permission is granted to anyone to use this software for any purpose, including commercial
    94  *   applications, and to alter it and redistribute it freely, subject to the following restrictions:
    95  *
    96  *     1. The origin of this software must not be misrepresented; you must not claim that you
    97  *     wrote the original software. If you use this software in a product, an acknowledgment
    98  *     in the product documentation would be appreciated but is not required.
    99  *
   100  *     2. Altered source versions must be plainly marked as such, and must not be misrepresented
   101  *     as being the original software.
   102  *
   103  *     3. This notice may not be removed or altered from any source distribution.
   104  *
   105  **********************************************************************************************/
   106  
   107  #ifndef RLGL_H
   108  #define RLGL_H
   109  
   110  #define RLGL_VERSION  "4.2"
   111  
   112  // Function specifiers in case library is build/used as a shared library (Windows)
   113  // NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll
   114  #if defined(_WIN32)
   115      #if defined(BUILD_LIBTYPE_SHARED)
   116          #define RLAPI __declspec(dllexport)     // We are building the library as a Win32 shared library (.dll)
   117      #elif defined(USE_LIBTYPE_SHARED)
   118          #define RLAPI __declspec(dllimport)     // We are using the library as a Win32 shared library (.dll)
   119      #endif
   120  #endif
   121  
   122  // Function specifiers definition
   123  #ifndef RLAPI
   124      #define RLAPI       // Functions defined as 'extern' by default (implicit specifiers)
   125  #endif
   126  
   127  // Support TRACELOG macros
   128  #ifndef TRACELOG
   129      #define TRACELOG(level, ...) (void)0
   130      #define TRACELOGD(...) (void)0
   131  #endif
   132  
   133  // Allow custom memory allocators
   134  #ifndef RL_MALLOC
   135      #define RL_MALLOC(sz)     malloc(sz)
   136  #endif
   137  #ifndef RL_CALLOC
   138      #define RL_CALLOC(n,sz)   calloc(n,sz)
   139  #endif
   140  #ifndef RL_REALLOC
   141      #define RL_REALLOC(n,sz)  realloc(n,sz)
   142  #endif
   143  #ifndef RL_FREE
   144      #define RL_FREE(p)        free(p)
   145  #endif
   146  
   147  // Security check in case no GRAPHICS_API_OPENGL_* defined
   148  #if !defined(GRAPHICS_API_OPENGL_11) && \
   149      !defined(GRAPHICS_API_OPENGL_21) && \
   150      !defined(GRAPHICS_API_OPENGL_33) && \
   151      !defined(GRAPHICS_API_OPENGL_43) && \
   152      !defined(GRAPHICS_API_OPENGL_ES2)
   153          #define GRAPHICS_API_OPENGL_33
   154  #endif
   155  
   156  // Security check in case multiple GRAPHICS_API_OPENGL_* defined
   157  #if defined(GRAPHICS_API_OPENGL_11)
   158      #if defined(GRAPHICS_API_OPENGL_21)
   159          #undef GRAPHICS_API_OPENGL_21
   160      #endif
   161      #if defined(GRAPHICS_API_OPENGL_33)
   162          #undef GRAPHICS_API_OPENGL_33
   163      #endif
   164      #if defined(GRAPHICS_API_OPENGL_43)
   165          #undef GRAPHICS_API_OPENGL_43
   166      #endif
   167      #if defined(GRAPHICS_API_OPENGL_ES2)
   168          #undef GRAPHICS_API_OPENGL_ES2
   169      #endif
   170  #endif
   171  
   172  // OpenGL 2.1 uses most of OpenGL 3.3 Core functionality
   173  // WARNING: Specific parts are checked with #if defines
   174  #if defined(GRAPHICS_API_OPENGL_21)
   175      #define GRAPHICS_API_OPENGL_33
   176  #endif
   177  
   178  // OpenGL 4.3 uses OpenGL 3.3 Core functionality
   179  #if defined(GRAPHICS_API_OPENGL_43)
   180      #define GRAPHICS_API_OPENGL_33
   181  #endif
   182  
   183  // Support framebuffer objects by default
   184  // NOTE: Some driver implementation do not support it, despite they should
   185  #define RLGL_RENDER_TEXTURES_HINT
   186  
   187  //----------------------------------------------------------------------------------
   188  // Defines and Macros
   189  //----------------------------------------------------------------------------------
   190  
   191  // Default internal render batch elements limits
   192  #ifndef RL_DEFAULT_BATCH_BUFFER_ELEMENTS
   193      #if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
   194          // This is the maximum amount of elements (quads) per batch
   195          // NOTE: Be careful with text, every letter maps to a quad
   196          #define RL_DEFAULT_BATCH_BUFFER_ELEMENTS  8192
   197      #endif
   198      #if defined(GRAPHICS_API_OPENGL_ES2)
   199          // We reduce memory sizes for embedded systems (RPI and HTML5)
   200          // NOTE: On HTML5 (emscripten) this is allocated on heap,
   201          // by default it's only 16MB!...just take care...
   202          #define RL_DEFAULT_BATCH_BUFFER_ELEMENTS  2048
   203      #endif
   204  #endif
   205  #ifndef RL_DEFAULT_BATCH_BUFFERS
   206      #define RL_DEFAULT_BATCH_BUFFERS                 1      // Default number of batch buffers (multi-buffering)
   207  #endif
   208  #ifndef RL_DEFAULT_BATCH_DRAWCALLS
   209      #define RL_DEFAULT_BATCH_DRAWCALLS             256      // Default number of batch draw calls (by state changes: mode, texture)
   210  #endif
   211  #ifndef RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS
   212      #define RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS       4      // Maximum number of textures units that can be activated on batch drawing (SetShaderValueTexture())
   213  #endif
   214  
   215  // Internal Matrix stack
   216  #ifndef RL_MAX_MATRIX_STACK_SIZE
   217      #define RL_MAX_MATRIX_STACK_SIZE                32      // Maximum size of Matrix stack
   218  #endif
   219  
   220  // Shader limits
   221  #ifndef RL_MAX_SHADER_LOCATIONS
   222      #define RL_MAX_SHADER_LOCATIONS                 32      // Maximum number of shader locations supported
   223  #endif
   224  
   225  // Projection matrix culling
   226  #ifndef RL_CULL_DISTANCE_NEAR
   227      #define RL_CULL_DISTANCE_NEAR                 0.01      // Default near cull distance
   228  #endif
   229  #ifndef RL_CULL_DISTANCE_FAR
   230      #define RL_CULL_DISTANCE_FAR                1000.0      // Default far cull distance
   231  #endif
   232  
   233  // Texture parameters (equivalent to OpenGL defines)
   234  #define RL_TEXTURE_WRAP_S                       0x2802      // GL_TEXTURE_WRAP_S
   235  #define RL_TEXTURE_WRAP_T                       0x2803      // GL_TEXTURE_WRAP_T
   236  #define RL_TEXTURE_MAG_FILTER                   0x2800      // GL_TEXTURE_MAG_FILTER
   237  #define RL_TEXTURE_MIN_FILTER                   0x2801      // GL_TEXTURE_MIN_FILTER
   238  
   239  #define RL_TEXTURE_FILTER_NEAREST               0x2600      // GL_NEAREST
   240  #define RL_TEXTURE_FILTER_LINEAR                0x2601      // GL_LINEAR
   241  #define RL_TEXTURE_FILTER_MIP_NEAREST           0x2700      // GL_NEAREST_MIPMAP_NEAREST
   242  #define RL_TEXTURE_FILTER_NEAREST_MIP_LINEAR    0x2702      // GL_NEAREST_MIPMAP_LINEAR
   243  #define RL_TEXTURE_FILTER_LINEAR_MIP_NEAREST    0x2701      // GL_LINEAR_MIPMAP_NEAREST
   244  #define RL_TEXTURE_FILTER_MIP_LINEAR            0x2703      // GL_LINEAR_MIPMAP_LINEAR
   245  #define RL_TEXTURE_FILTER_ANISOTROPIC           0x3000      // Anisotropic filter (custom identifier)
   246  #define RL_TEXTURE_MIPMAP_BIAS_RATIO            0x4000      // Texture mipmap bias, percentage ratio (custom identifier)
   247  
   248  #define RL_TEXTURE_WRAP_REPEAT                  0x2901      // GL_REPEAT
   249  #define RL_TEXTURE_WRAP_CLAMP                   0x812F      // GL_CLAMP_TO_EDGE
   250  #define RL_TEXTURE_WRAP_MIRROR_REPEAT           0x8370      // GL_MIRRORED_REPEAT
   251  #define RL_TEXTURE_WRAP_MIRROR_CLAMP            0x8742      // GL_MIRROR_CLAMP_EXT
   252  
   253  // Matrix modes (equivalent to OpenGL)
   254  #define RL_MODELVIEW                            0x1700      // GL_MODELVIEW
   255  #define RL_PROJECTION                           0x1701      // GL_PROJECTION
   256  #define RL_TEXTURE                              0x1702      // GL_TEXTURE
   257  
   258  // Primitive assembly draw modes
   259  #define RL_LINES                                0x0001      // GL_LINES
   260  #define RL_TRIANGLES                            0x0004      // GL_TRIANGLES
   261  #define RL_QUADS                                0x0007      // GL_QUADS
   262  
   263  // GL equivalent data types
   264  #define RL_UNSIGNED_BYTE                        0x1401      // GL_UNSIGNED_BYTE
   265  #define RL_FLOAT                                0x1406      // GL_FLOAT
   266  
   267  // Buffer usage hint
   268  #define RL_STREAM_DRAW                          0x88E0      // GL_STREAM_DRAW
   269  #define RL_STREAM_READ                          0x88E1      // GL_STREAM_READ
   270  #define RL_STREAM_COPY                          0x88E2      // GL_STREAM_COPY
   271  #define RL_STATIC_DRAW                          0x88E4      // GL_STATIC_DRAW
   272  #define RL_STATIC_READ                          0x88E5      // GL_STATIC_READ
   273  #define RL_STATIC_COPY                          0x88E6      // GL_STATIC_COPY
   274  #define RL_DYNAMIC_DRAW                         0x88E8      // GL_DYNAMIC_DRAW
   275  #define RL_DYNAMIC_READ                         0x88E9      // GL_DYNAMIC_READ
   276  #define RL_DYNAMIC_COPY                         0x88EA      // GL_DYNAMIC_COPY
   277  
   278  // GL Shader type
   279  #define RL_FRAGMENT_SHADER                      0x8B30      // GL_FRAGMENT_SHADER
   280  #define RL_VERTEX_SHADER                        0x8B31      // GL_VERTEX_SHADER
   281  #define RL_COMPUTE_SHADER                       0x91B9      // GL_COMPUTE_SHADER
   282  
   283  //----------------------------------------------------------------------------------
   284  // Types and Structures Definition
   285  //----------------------------------------------------------------------------------
   286  #if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
   287      #include <stdbool.h>
   288  #elif !defined(__cplusplus) && !defined(bool) && !defined(RL_BOOL_TYPE)
   289      // Boolean type
   290  typedef enum bool { false = 0, true = !false } bool;
   291  #endif
   292  
   293  #if !defined(RL_MATRIX_TYPE)
   294  // Matrix, 4x4 components, column major, OpenGL style, right handed
   295  typedef struct Matrix {
   296      float m0, m4, m8, m12;      // Matrix first row (4 components)
   297      float m1, m5, m9, m13;      // Matrix second row (4 components)
   298      float m2, m6, m10, m14;     // Matrix third row (4 components)
   299      float m3, m7, m11, m15;     // Matrix fourth row (4 components)
   300  } Matrix;
   301  #define RL_MATRIX_TYPE
   302  #endif
   303  
   304  // Dynamic vertex buffers (position + texcoords + colors + indices arrays)
   305  typedef struct rlVertexBuffer {
   306      int elementCount;           // Number of elements in the buffer (QUADS)
   307  
   308      float *vertices;            // Vertex position (XYZ - 3 components per vertex) (shader-location = 0)
   309      float *texcoords;           // Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1)
   310      unsigned char *colors;      // Vertex colors (RGBA - 4 components per vertex) (shader-location = 3)
   311  #if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
   312      unsigned int *indices;      // Vertex indices (in case vertex data comes indexed) (6 indices per quad)
   313  #endif
   314  #if defined(GRAPHICS_API_OPENGL_ES2)
   315      unsigned short *indices;    // Vertex indices (in case vertex data comes indexed) (6 indices per quad)
   316  #endif
   317      unsigned int vaoId;         // OpenGL Vertex Array Object id
   318      unsigned int vboId[4];      // OpenGL Vertex Buffer Objects id (4 types of vertex data)
   319  } rlVertexBuffer;
   320  
   321  // Draw call type
   322  // NOTE: Only texture changes register a new draw, other state-change-related elements are not
   323  // used at this moment (vaoId, shaderId, matrices), raylib just forces a batch draw call if any
   324  // of those state-change happens (this is done in core module)
   325  typedef struct rlDrawCall {
   326      int mode;                   // Drawing mode: LINES, TRIANGLES, QUADS
   327      int vertexCount;            // Number of vertex of the draw
   328      int vertexAlignment;        // Number of vertex required for index alignment (LINES, TRIANGLES)
   329      //unsigned int vaoId;       // Vertex array id to be used on the draw -> Using RLGL.currentBatch->vertexBuffer.vaoId
   330      //unsigned int shaderId;    // Shader id to be used on the draw -> Using RLGL.currentShaderId
   331      unsigned int textureId;     // Texture id to be used on the draw -> Use to create new draw call if changes
   332  
   333      //Matrix projection;        // Projection matrix for this draw -> Using RLGL.projection by default
   334      //Matrix modelview;         // Modelview matrix for this draw -> Using RLGL.modelview by default
   335  } rlDrawCall;
   336  
   337  // rlRenderBatch type
   338  typedef struct rlRenderBatch {
   339      int bufferCount;            // Number of vertex buffers (multi-buffering support)
   340      int currentBuffer;          // Current buffer tracking in case of multi-buffering
   341      rlVertexBuffer *vertexBuffer; // Dynamic buffer(s) for vertex data
   342  
   343      rlDrawCall *draws;          // Draw calls array, depends on textureId
   344      int drawCounter;            // Draw calls counter
   345      float currentDepth;         // Current depth value for next draw
   346  } rlRenderBatch;
   347  
   348  // OpenGL version
   349  typedef enum {
   350      RL_OPENGL_11 = 1,           // OpenGL 1.1
   351      RL_OPENGL_21,               // OpenGL 2.1 (GLSL 120)
   352      RL_OPENGL_33,               // OpenGL 3.3 (GLSL 330)
   353      RL_OPENGL_43,               // OpenGL 4.3 (using GLSL 330)
   354      RL_OPENGL_ES_20             // OpenGL ES 2.0 (GLSL 100)
   355  } rlGlVersion;
   356  
   357  // Trace log level
   358  // NOTE: Organized by priority level
   359  typedef enum {
   360      RL_LOG_ALL = 0,             // Display all logs
   361      RL_LOG_TRACE,               // Trace logging, intended for internal use only
   362      RL_LOG_DEBUG,               // Debug logging, used for internal debugging, it should be disabled on release builds
   363      RL_LOG_INFO,                // Info logging, used for program execution info
   364      RL_LOG_WARNING,             // Warning logging, used on recoverable failures
   365      RL_LOG_ERROR,               // Error logging, used on unrecoverable failures
   366      RL_LOG_FATAL,               // Fatal logging, used to abort program: exit(EXIT_FAILURE)
   367      RL_LOG_NONE                 // Disable logging
   368  } rlTraceLogLevel;
   369  
   370  // Texture pixel formats
   371  // NOTE: Support depends on OpenGL version
   372  typedef enum {
   373      RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE = 1,     // 8 bit per pixel (no alpha)
   374      RL_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA,        // 8*2 bpp (2 channels)
   375      RL_PIXELFORMAT_UNCOMPRESSED_R5G6B5,            // 16 bpp
   376      RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8,            // 24 bpp
   377      RL_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1,          // 16 bpp (1 bit alpha)
   378      RL_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4,          // 16 bpp (4 bit alpha)
   379      RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8,          // 32 bpp
   380      RL_PIXELFORMAT_UNCOMPRESSED_R32,               // 32 bpp (1 channel - float)
   381      RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32,         // 32*3 bpp (3 channels - float)
   382      RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32,      // 32*4 bpp (4 channels - float)
   383      RL_PIXELFORMAT_COMPRESSED_DXT1_RGB,            // 4 bpp (no alpha)
   384      RL_PIXELFORMAT_COMPRESSED_DXT1_RGBA,           // 4 bpp (1 bit alpha)
   385      RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA,           // 8 bpp
   386      RL_PIXELFORMAT_COMPRESSED_DXT5_RGBA,           // 8 bpp
   387      RL_PIXELFORMAT_COMPRESSED_ETC1_RGB,            // 4 bpp
   388      RL_PIXELFORMAT_COMPRESSED_ETC2_RGB,            // 4 bpp
   389      RL_PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA,       // 8 bpp
   390      RL_PIXELFORMAT_COMPRESSED_PVRT_RGB,            // 4 bpp
   391      RL_PIXELFORMAT_COMPRESSED_PVRT_RGBA,           // 4 bpp
   392      RL_PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA,       // 8 bpp
   393      RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA        // 2 bpp
   394  } rlPixelFormat;
   395  
   396  // Texture parameters: filter mode
   397  // NOTE 1: Filtering considers mipmaps if available in the texture
   398  // NOTE 2: Filter is accordingly set for minification and magnification
   399  typedef enum {
   400      RL_TEXTURE_FILTER_POINT = 0,        // No filter, just pixel approximation
   401      RL_TEXTURE_FILTER_BILINEAR,         // Linear filtering
   402      RL_TEXTURE_FILTER_TRILINEAR,        // Trilinear filtering (linear with mipmaps)
   403      RL_TEXTURE_FILTER_ANISOTROPIC_4X,   // Anisotropic filtering 4x
   404      RL_TEXTURE_FILTER_ANISOTROPIC_8X,   // Anisotropic filtering 8x
   405      RL_TEXTURE_FILTER_ANISOTROPIC_16X,  // Anisotropic filtering 16x
   406  } rlTextureFilter;
   407  
   408  // Color blending modes (pre-defined)
   409  typedef enum {
   410      RL_BLEND_ALPHA = 0,                 // Blend textures considering alpha (default)
   411      RL_BLEND_ADDITIVE,                  // Blend textures adding colors
   412      RL_BLEND_MULTIPLIED,                // Blend textures multiplying colors
   413      RL_BLEND_ADD_COLORS,                // Blend textures adding colors (alternative)
   414      RL_BLEND_SUBTRACT_COLORS,           // Blend textures subtracting colors (alternative)
   415      RL_BLEND_ALPHA_PREMULTIPLY,         // Blend premultiplied textures considering alpha
   416      RL_BLEND_CUSTOM,                    // Blend textures using custom src/dst factors (use rlSetBlendFactors())
   417      RL_BLEND_CUSTOM_SEPARATE            // Blend textures using custom src/dst factors (use rlSetBlendFactorsSeparate())
   418  } rlBlendMode;
   419  
   420  // Shader location point type
   421  typedef enum {
   422      RL_SHADER_LOC_VERTEX_POSITION = 0,  // Shader location: vertex attribute: position
   423      RL_SHADER_LOC_VERTEX_TEXCOORD01,    // Shader location: vertex attribute: texcoord01
   424      RL_SHADER_LOC_VERTEX_TEXCOORD02,    // Shader location: vertex attribute: texcoord02
   425      RL_SHADER_LOC_VERTEX_NORMAL,        // Shader location: vertex attribute: normal
   426      RL_SHADER_LOC_VERTEX_TANGENT,       // Shader location: vertex attribute: tangent
   427      RL_SHADER_LOC_VERTEX_COLOR,         // Shader location: vertex attribute: color
   428      RL_SHADER_LOC_MATRIX_MVP,           // Shader location: matrix uniform: model-view-projection
   429      RL_SHADER_LOC_MATRIX_VIEW,          // Shader location: matrix uniform: view (camera transform)
   430      RL_SHADER_LOC_MATRIX_PROJECTION,    // Shader location: matrix uniform: projection
   431      RL_SHADER_LOC_MATRIX_MODEL,         // Shader location: matrix uniform: model (transform)
   432      RL_SHADER_LOC_MATRIX_NORMAL,        // Shader location: matrix uniform: normal
   433      RL_SHADER_LOC_VECTOR_VIEW,          // Shader location: vector uniform: view
   434      RL_SHADER_LOC_COLOR_DIFFUSE,        // Shader location: vector uniform: diffuse color
   435      RL_SHADER_LOC_COLOR_SPECULAR,       // Shader location: vector uniform: specular color
   436      RL_SHADER_LOC_COLOR_AMBIENT,        // Shader location: vector uniform: ambient color
   437      RL_SHADER_LOC_MAP_ALBEDO,           // Shader location: sampler2d texture: albedo (same as: RL_SHADER_LOC_MAP_DIFFUSE)
   438      RL_SHADER_LOC_MAP_METALNESS,        // Shader location: sampler2d texture: metalness (same as: RL_SHADER_LOC_MAP_SPECULAR)
   439      RL_SHADER_LOC_MAP_NORMAL,           // Shader location: sampler2d texture: normal
   440      RL_SHADER_LOC_MAP_ROUGHNESS,        // Shader location: sampler2d texture: roughness
   441      RL_SHADER_LOC_MAP_OCCLUSION,        // Shader location: sampler2d texture: occlusion
   442      RL_SHADER_LOC_MAP_EMISSION,         // Shader location: sampler2d texture: emission
   443      RL_SHADER_LOC_MAP_HEIGHT,           // Shader location: sampler2d texture: height
   444      RL_SHADER_LOC_MAP_CUBEMAP,          // Shader location: samplerCube texture: cubemap
   445      RL_SHADER_LOC_MAP_IRRADIANCE,       // Shader location: samplerCube texture: irradiance
   446      RL_SHADER_LOC_MAP_PREFILTER,        // Shader location: samplerCube texture: prefilter
   447      RL_SHADER_LOC_MAP_BRDF              // Shader location: sampler2d texture: brdf
   448  } rlShaderLocationIndex;
   449  
   450  #define RL_SHADER_LOC_MAP_DIFFUSE       RL_SHADER_LOC_MAP_ALBEDO
   451  #define RL_SHADER_LOC_MAP_SPECULAR      RL_SHADER_LOC_MAP_METALNESS
   452  
   453  // Shader uniform data type
   454  typedef enum {
   455      RL_SHADER_UNIFORM_FLOAT = 0,        // Shader uniform type: float
   456      RL_SHADER_UNIFORM_VEC2,             // Shader uniform type: vec2 (2 float)
   457      RL_SHADER_UNIFORM_VEC3,             // Shader uniform type: vec3 (3 float)
   458      RL_SHADER_UNIFORM_VEC4,             // Shader uniform type: vec4 (4 float)
   459      RL_SHADER_UNIFORM_INT,              // Shader uniform type: int
   460      RL_SHADER_UNIFORM_IVEC2,            // Shader uniform type: ivec2 (2 int)
   461      RL_SHADER_UNIFORM_IVEC3,            // Shader uniform type: ivec3 (3 int)
   462      RL_SHADER_UNIFORM_IVEC4,            // Shader uniform type: ivec4 (4 int)
   463      RL_SHADER_UNIFORM_SAMPLER2D         // Shader uniform type: sampler2d
   464  } rlShaderUniformDataType;
   465  
   466  // Shader attribute data types
   467  typedef enum {
   468      RL_SHADER_ATTRIB_FLOAT = 0,         // Shader attribute type: float
   469      RL_SHADER_ATTRIB_VEC2,              // Shader attribute type: vec2 (2 float)
   470      RL_SHADER_ATTRIB_VEC3,              // Shader attribute type: vec3 (3 float)
   471      RL_SHADER_ATTRIB_VEC4               // Shader attribute type: vec4 (4 float)
   472  } rlShaderAttributeDataType;
   473  
   474  // Framebuffer attachment type
   475  // NOTE: By default up to 8 color channels defined but it can be more
   476  typedef enum {
   477      RL_ATTACHMENT_COLOR_CHANNEL0 = 0,   // Framebuffer attachmment type: color 0
   478      RL_ATTACHMENT_COLOR_CHANNEL1,       // Framebuffer attachmment type: color 1
   479      RL_ATTACHMENT_COLOR_CHANNEL2,       // Framebuffer attachmment type: color 2
   480      RL_ATTACHMENT_COLOR_CHANNEL3,       // Framebuffer attachmment type: color 3
   481      RL_ATTACHMENT_COLOR_CHANNEL4,       // Framebuffer attachmment type: color 4
   482      RL_ATTACHMENT_COLOR_CHANNEL5,       // Framebuffer attachmment type: color 5
   483      RL_ATTACHMENT_COLOR_CHANNEL6,       // Framebuffer attachmment type: color 6
   484      RL_ATTACHMENT_COLOR_CHANNEL7,       // Framebuffer attachmment type: color 7
   485      RL_ATTACHMENT_DEPTH = 100,          // Framebuffer attachmment type: depth
   486      RL_ATTACHMENT_STENCIL = 200,        // Framebuffer attachmment type: stencil
   487  } rlFramebufferAttachType;
   488  
   489  // Framebuffer texture attachment type
   490  typedef enum {
   491      RL_ATTACHMENT_CUBEMAP_POSITIVE_X = 0, // Framebuffer texture attachment type: cubemap, +X side
   492      RL_ATTACHMENT_CUBEMAP_NEGATIVE_X,   // Framebuffer texture attachment type: cubemap, -X side
   493      RL_ATTACHMENT_CUBEMAP_POSITIVE_Y,   // Framebuffer texture attachment type: cubemap, +Y side
   494      RL_ATTACHMENT_CUBEMAP_NEGATIVE_Y,   // Framebuffer texture attachment type: cubemap, -Y side
   495      RL_ATTACHMENT_CUBEMAP_POSITIVE_Z,   // Framebuffer texture attachment type: cubemap, +Z side
   496      RL_ATTACHMENT_CUBEMAP_NEGATIVE_Z,   // Framebuffer texture attachment type: cubemap, -Z side
   497      RL_ATTACHMENT_TEXTURE2D = 100,      // Framebuffer texture attachment type: texture2d
   498      RL_ATTACHMENT_RENDERBUFFER = 200,   // Framebuffer texture attachment type: renderbuffer
   499  } rlFramebufferAttachTextureType;
   500  
   501  // Face culling mode
   502  typedef enum {
   503      RL_CULL_FACE_FRONT = 0,
   504      RL_CULL_FACE_BACK
   505  } rlCullMode;
   506  
   507  //------------------------------------------------------------------------------------
   508  // Functions Declaration - Matrix operations
   509  //------------------------------------------------------------------------------------
   510  
   511  #if defined(__cplusplus)
   512  extern "C" {            // Prevents name mangling of functions
   513  #endif
   514  
   515  RLAPI void rlMatrixMode(int mode);                    // Choose the current matrix to be transformed
   516  RLAPI void rlPushMatrix(void);                        // Push the current matrix to stack
   517  RLAPI void rlPopMatrix(void);                         // Pop lattest inserted matrix from stack
   518  RLAPI void rlLoadIdentity(void);                      // Reset current matrix to identity matrix
   519  RLAPI void rlTranslatef(float x, float y, float z);   // Multiply the current matrix by a translation matrix
   520  RLAPI void rlRotatef(float angle, float x, float y, float z);  // Multiply the current matrix by a rotation matrix
   521  RLAPI void rlScalef(float x, float y, float z);       // Multiply the current matrix by a scaling matrix
   522  RLAPI void rlMultMatrixf(float *matf);                // Multiply the current matrix by another matrix
   523  RLAPI void rlFrustum(double left, double right, double bottom, double top, double znear, double zfar);
   524  RLAPI void rlOrtho(double left, double right, double bottom, double top, double znear, double zfar);
   525  RLAPI void rlViewport(int x, int y, int width, int height); // Set the viewport area
   526  
   527  //------------------------------------------------------------------------------------
   528  // Functions Declaration - Vertex level operations
   529  //------------------------------------------------------------------------------------
   530  RLAPI void rlBegin(int mode);                         // Initialize drawing mode (how to organize vertex)
   531  RLAPI void rlEnd(void);                               // Finish vertex providing
   532  RLAPI void rlVertex2i(int x, int y);                  // Define one vertex (position) - 2 int
   533  RLAPI void rlVertex2f(float x, float y);              // Define one vertex (position) - 2 float
   534  RLAPI void rlVertex3f(float x, float y, float z);     // Define one vertex (position) - 3 float
   535  RLAPI void rlTexCoord2f(float x, float y);            // Define one vertex (texture coordinate) - 2 float
   536  RLAPI void rlNormal3f(float x, float y, float z);     // Define one vertex (normal) - 3 float
   537  RLAPI void rlColor4ub(unsigned char r, unsigned char g, unsigned char b, unsigned char a);  // Define one vertex (color) - 4 byte
   538  RLAPI void rlColor3f(float x, float y, float z);          // Define one vertex (color) - 3 float
   539  RLAPI void rlColor4f(float x, float y, float z, float w); // Define one vertex (color) - 4 float
   540  
   541  //------------------------------------------------------------------------------------
   542  // Functions Declaration - OpenGL style functions (common to 1.1, 3.3+, ES2)
   543  // NOTE: This functions are used to completely abstract raylib code from OpenGL layer,
   544  // some of them are direct wrappers over OpenGL calls, some others are custom
   545  //------------------------------------------------------------------------------------
   546  
   547  // Vertex buffers state
   548  RLAPI bool rlEnableVertexArray(unsigned int vaoId);     // Enable vertex array (VAO, if supported)
   549  RLAPI void rlDisableVertexArray(void);                  // Disable vertex array (VAO, if supported)
   550  RLAPI void rlEnableVertexBuffer(unsigned int id);       // Enable vertex buffer (VBO)
   551  RLAPI void rlDisableVertexBuffer(void);                 // Disable vertex buffer (VBO)
   552  RLAPI void rlEnableVertexBufferElement(unsigned int id);// Enable vertex buffer element (VBO element)
   553  RLAPI void rlDisableVertexBufferElement(void);          // Disable vertex buffer element (VBO element)
   554  RLAPI void rlEnableVertexAttribute(unsigned int index); // Enable vertex attribute index
   555  RLAPI void rlDisableVertexAttribute(unsigned int index);// Disable vertex attribute index
   556  #if defined(GRAPHICS_API_OPENGL_11)
   557  RLAPI void rlEnableStatePointer(int vertexAttribType, void *buffer);    // Enable attribute state pointer
   558  RLAPI void rlDisableStatePointer(int vertexAttribType);                 // Disable attribute state pointer
   559  #endif
   560  
   561  // Textures state
   562  RLAPI void rlActiveTextureSlot(int slot);               // Select and active a texture slot
   563  RLAPI void rlEnableTexture(unsigned int id);            // Enable texture
   564  RLAPI void rlDisableTexture(void);                      // Disable texture
   565  RLAPI void rlEnableTextureCubemap(unsigned int id);     // Enable texture cubemap
   566  RLAPI void rlDisableTextureCubemap(void);               // Disable texture cubemap
   567  RLAPI void rlTextureParameters(unsigned int id, int param, int value); // Set texture parameters (filter, wrap)
   568  
   569  // Shader state
   570  RLAPI void rlEnableShader(unsigned int id);             // Enable shader program
   571  RLAPI void rlDisableShader(void);                       // Disable shader program
   572  
   573  // Framebuffer state
   574  RLAPI void rlEnableFramebuffer(unsigned int id);        // Enable render texture (fbo)
   575  RLAPI void rlDisableFramebuffer(void);                  // Disable render texture (fbo), return to default framebuffer
   576  RLAPI void rlActiveDrawBuffers(int count);              // Activate multiple draw color buffers
   577  
   578  // General render state
   579  RLAPI void rlEnableColorBlend(void);                     // Enable color blending
   580  RLAPI void rlDisableColorBlend(void);                   // Disable color blending
   581  RLAPI void rlEnableDepthTest(void);                     // Enable depth test
   582  RLAPI void rlDisableDepthTest(void);                    // Disable depth test
   583  RLAPI void rlEnableDepthMask(void);                     // Enable depth write
   584  RLAPI void rlDisableDepthMask(void);                    // Disable depth write
   585  RLAPI void rlEnableBackfaceCulling(void);               // Enable backface culling
   586  RLAPI void rlDisableBackfaceCulling(void);              // Disable backface culling
   587  RLAPI void rlSetCullFace(int mode);                     // Set face culling mode
   588  RLAPI void rlEnableScissorTest(void);                   // Enable scissor test
   589  RLAPI void rlDisableScissorTest(void);                  // Disable scissor test
   590  RLAPI void rlScissor(int x, int y, int width, int height); // Scissor test
   591  RLAPI void rlEnableWireMode(void);                      // Enable wire mode
   592  RLAPI void rlDisableWireMode(void);                     // Disable wire mode
   593  RLAPI void rlSetLineWidth(float width);                 // Set the line drawing width
   594  RLAPI float rlGetLineWidth(void);                       // Get the line drawing width
   595  RLAPI void rlEnableSmoothLines(void);                   // Enable line aliasing
   596  RLAPI void rlDisableSmoothLines(void);                  // Disable line aliasing
   597  RLAPI void rlEnableStereoRender(void);                  // Enable stereo rendering
   598  RLAPI void rlDisableStereoRender(void);                 // Disable stereo rendering
   599  RLAPI bool rlIsStereoRenderEnabled(void);               // Check if stereo render is enabled
   600  
   601  RLAPI void rlClearColor(unsigned char r, unsigned char g, unsigned char b, unsigned char a); // Clear color buffer with color
   602  RLAPI void rlClearScreenBuffers(void);                  // Clear used screen buffers (color and depth)
   603  RLAPI void rlCheckErrors(void);                         // Check and log OpenGL error codes
   604  RLAPI void rlSetBlendMode(int mode);                    // Set blending mode
   605  RLAPI void rlSetBlendFactors(int glSrcFactor, int glDstFactor, int glEquation); // Set blending mode factor and equation (using OpenGL factors)
   606  RLAPI void rlSetBlendFactorsSeparate(int glSrcRGB, int glDstRGB, int glSrcAlpha, int glDstAlpha, int glEqRGB, int glEqAlpha); // Set blending mode factors and equations separately (using OpenGL factors)
   607  
   608  //------------------------------------------------------------------------------------
   609  // Functions Declaration - rlgl functionality
   610  //------------------------------------------------------------------------------------
   611  // rlgl initialization functions
   612  RLAPI void rlglInit(int width, int height);             // Initialize rlgl (buffers, shaders, textures, states)
   613  RLAPI void rlglClose(void);                             // De-inititialize rlgl (buffers, shaders, textures)
   614  RLAPI void rlLoadExtensions(void *loader);              // Load OpenGL extensions (loader function required)
   615  RLAPI int rlGetVersion(void);                           // Get current OpenGL version
   616  RLAPI void rlSetFramebufferWidth(int width);            // Set current framebuffer width
   617  RLAPI int rlGetFramebufferWidth(void);                  // Get default framebuffer width
   618  RLAPI void rlSetFramebufferHeight(int height);          // Set current framebuffer height
   619  RLAPI int rlGetFramebufferHeight(void);                 // Get default framebuffer height
   620  
   621  RLAPI unsigned int rlGetTextureIdDefault(void);         // Get default texture id
   622  RLAPI unsigned int rlGetShaderIdDefault(void);          // Get default shader id
   623  RLAPI int *rlGetShaderLocsDefault(void);                // Get default shader locations
   624  
   625  // Render batch management
   626  // NOTE: rlgl provides a default render batch to behave like OpenGL 1.1 immediate mode
   627  // but this render batch API is exposed in case of custom batches are required
   628  RLAPI rlRenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements);  // Load a render batch system
   629  RLAPI void rlUnloadRenderBatch(rlRenderBatch batch);                        // Unload render batch system
   630  RLAPI void rlDrawRenderBatch(rlRenderBatch *batch);                         // Draw render batch data (Update->Draw->Reset)
   631  RLAPI void rlSetRenderBatchActive(rlRenderBatch *batch);                    // Set the active render batch for rlgl (NULL for default internal)
   632  RLAPI void rlDrawRenderBatchActive(void);                                   // Update and draw internal render batch
   633  RLAPI bool rlCheckRenderBatchLimit(int vCount);                             // Check internal buffer overflow for a given number of vertex
   634  
   635  RLAPI void rlSetTexture(unsigned int id);               // Set current texture for render batch and check buffers limits
   636  
   637  //------------------------------------------------------------------------------------------------------------------------
   638  
   639  // Vertex buffers management
   640  RLAPI unsigned int rlLoadVertexArray(void);                               // Load vertex array (vao) if supported
   641  RLAPI unsigned int rlLoadVertexBuffer(const void *buffer, int size, bool dynamic);            // Load a vertex buffer attribute
   642  RLAPI unsigned int rlLoadVertexBufferElement(const void *buffer, int size, bool dynamic);     // Load a new attributes element buffer
   643  RLAPI void rlUpdateVertexBuffer(unsigned int bufferId, const void *data, int dataSize, int offset);     // Update GPU buffer with new data
   644  RLAPI void rlUpdateVertexBufferElements(unsigned int id, const void *data, int dataSize, int offset);   // Update vertex buffer elements with new data
   645  RLAPI void rlUnloadVertexArray(unsigned int vaoId);
   646  RLAPI void rlUnloadVertexBuffer(unsigned int vboId);
   647  RLAPI void rlSetVertexAttribute(unsigned int index, int compSize, int type, bool normalized, int stride, const void *pointer);
   648  RLAPI void rlSetVertexAttributeDivisor(unsigned int index, int divisor);
   649  RLAPI void rlSetVertexAttributeDefault(int locIndex, const void *value, int attribType, int count); // Set vertex attribute default value
   650  RLAPI void rlDrawVertexArray(int offset, int count);
   651  RLAPI void rlDrawVertexArrayElements(int offset, int count, const void *buffer);
   652  RLAPI void rlDrawVertexArrayInstanced(int offset, int count, int instances);
   653  RLAPI void rlDrawVertexArrayElementsInstanced(int offset, int count, const void *buffer, int instances);
   654  
   655  // Textures management
   656  RLAPI unsigned int rlLoadTexture(const void *data, int width, int height, int format, int mipmapCount); // Load texture in GPU
   657  RLAPI unsigned int rlLoadTextureDepth(int width, int height, bool useRenderBuffer);               // Load depth texture/renderbuffer (to be attached to fbo)
   658  RLAPI unsigned int rlLoadTextureCubemap(const void *data, int size, int format);                        // Load texture cubemap
   659  RLAPI void rlUpdateTexture(unsigned int id, int offsetX, int offsetY, int width, int height, int format, const void *data);  // Update GPU texture with new data
   660  RLAPI void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned int *glFormat, unsigned int *glType);  // Get OpenGL internal formats
   661  RLAPI const char *rlGetPixelFormatName(unsigned int format);              // Get name string for pixel format
   662  RLAPI void rlUnloadTexture(unsigned int id);                              // Unload texture from GPU memory
   663  RLAPI void rlGenTextureMipmaps(unsigned int id, int width, int height, int format, int *mipmaps); // Generate mipmap data for selected texture
   664  RLAPI void *rlReadTexturePixels(unsigned int id, int width, int height, int format);              // Read texture pixel data
   665  RLAPI unsigned char *rlReadScreenPixels(int width, int height);           // Read screen pixel data (color buffer)
   666  
   667  // Framebuffer management (fbo)
   668  RLAPI unsigned int rlLoadFramebuffer(int width, int height);              // Load an empty framebuffer
   669  RLAPI void rlFramebufferAttach(unsigned int fboId, unsigned int texId, int attachType, int texType, int mipLevel);  // Attach texture/renderbuffer to a framebuffer
   670  RLAPI bool rlFramebufferComplete(unsigned int id);                        // Verify framebuffer is complete
   671  RLAPI void rlUnloadFramebuffer(unsigned int id);                          // Delete framebuffer from GPU
   672  
   673  // Shaders management
   674  RLAPI unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode);    // Load shader from code strings
   675  RLAPI unsigned int rlCompileShader(const char *shaderCode, int type);           // Compile custom shader and return shader id (type: RL_VERTEX_SHADER, RL_FRAGMENT_SHADER, RL_COMPUTE_SHADER)
   676  RLAPI unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId); // Load custom shader program
   677  RLAPI void rlUnloadShaderProgram(unsigned int id);                              // Unload shader program
   678  RLAPI int rlGetLocationUniform(unsigned int shaderId, const char *uniformName); // Get shader location uniform
   679  RLAPI int rlGetLocationAttrib(unsigned int shaderId, const char *attribName);   // Get shader location attribute
   680  RLAPI void rlSetUniform(int locIndex, const void *value, int uniformType, int count);   // Set shader value uniform
   681  RLAPI void rlSetUniformMatrix(int locIndex, Matrix mat);                        // Set shader value matrix
   682  RLAPI void rlSetUniformSampler(int locIndex, unsigned int textureId);           // Set shader value sampler
   683  RLAPI void rlSetShader(unsigned int id, int *locs);                             // Set shader currently active (id and locations)
   684  
   685  // Compute shader management
   686  RLAPI unsigned int rlLoadComputeShaderProgram(unsigned int shaderId);           // Load compute shader program
   687  RLAPI void rlComputeShaderDispatch(unsigned int groupX, unsigned int groupY, unsigned int groupZ);  // Dispatch compute shader (equivalent to *draw* for graphics pilepine)
   688  
   689  // Shader buffer storage object management (ssbo)
   690  RLAPI unsigned int rlLoadShaderBuffer(unsigned int size, const void *data, int usageHint); // Load shader storage buffer object (SSBO)
   691  RLAPI void rlUnloadShaderBuffer(unsigned int ssboId);                           // Unload shader storage buffer object (SSBO)
   692  RLAPI void rlUpdateShaderBuffer(unsigned int id, const void *data, unsigned int dataSize, unsigned int offset); // Update SSBO buffer data
   693  RLAPI void rlBindShaderBuffer(unsigned int id, unsigned int index);             // Bind SSBO buffer
   694  RLAPI void rlReadShaderBuffer(unsigned int id, void *dest, unsigned int count, unsigned int offset); // Read SSBO buffer data (GPU->CPU)
   695  RLAPI void rlCopyShaderBuffer(unsigned int destId, unsigned int srcId, unsigned int destOffset, unsigned int srcOffset, unsigned int count); // Copy SSBO data between buffers
   696  RLAPI unsigned int rlGetShaderBufferSize(unsigned int id);                      // Get SSBO buffer size
   697  
   698  // Buffer management
   699  RLAPI void rlBindImageTexture(unsigned int id, unsigned int index, unsigned int format, int readonly);  // Bind image texture
   700  
   701  // Matrix state management
   702  RLAPI Matrix rlGetMatrixModelview(void);                                  // Get internal modelview matrix
   703  RLAPI Matrix rlGetMatrixProjection(void);                                 // Get internal projection matrix
   704  RLAPI Matrix rlGetMatrixTransform(void);                                  // Get internal accumulated transform matrix
   705  RLAPI Matrix rlGetMatrixProjectionStereo(int eye);                        // Get internal projection matrix for stereo render (selected eye)
   706  RLAPI Matrix rlGetMatrixViewOffsetStereo(int eye);                        // Get internal view offset matrix for stereo render (selected eye)
   707  RLAPI void rlSetMatrixProjection(Matrix proj);                            // Set a custom projection matrix (replaces internal projection matrix)
   708  RLAPI void rlSetMatrixModelview(Matrix view);                             // Set a custom modelview matrix (replaces internal modelview matrix)
   709  RLAPI void rlSetMatrixProjectionStereo(Matrix right, Matrix left);        // Set eyes projection matrices for stereo rendering
   710  RLAPI void rlSetMatrixViewOffsetStereo(Matrix right, Matrix left);        // Set eyes view offsets matrices for stereo rendering
   711  
   712  // Quick and dirty cube/quad buffers load->draw->unload
   713  RLAPI void rlLoadDrawCube(void);     // Load and draw a cube
   714  RLAPI void rlLoadDrawQuad(void);     // Load and draw a quad
   715  
   716  #if defined(__cplusplus)
   717  }
   718  #endif
   719  
   720  #endif // RLGL_H
   721  
   722  /***********************************************************************************
   723  *
   724  *   RLGL IMPLEMENTATION
   725  *
   726  ************************************************************************************/
   727  
   728  #if defined(RLGL_IMPLEMENTATION)
   729  
   730  #if defined(GRAPHICS_API_OPENGL_11)
   731      #if defined(__APPLE__)
   732          #include <OpenGL/gl.h>          // OpenGL 1.1 library for OSX
   733          #include <OpenGL/glext.h>       // OpenGL extensions library
   734      #else
   735          // APIENTRY for OpenGL function pointer declarations is required
   736          #if !defined(APIENTRY)
   737              #if defined(_WIN32)
   738                  #define APIENTRY __stdcall
   739              #else
   740                  #define APIENTRY
   741              #endif
   742          #endif
   743          // WINGDIAPI definition. Some Windows OpenGL headers need it
   744          #if !defined(WINGDIAPI) && defined(_WIN32)
   745              #define WINGDIAPI __declspec(dllimport)
   746          #endif
   747  
   748          #include <GL/gl.h>              // OpenGL 1.1 library
   749      #endif
   750  #endif
   751  
   752  #if defined(GRAPHICS_API_OPENGL_33)
   753      #define GLAD_MALLOC RL_MALLOC
   754      #define GLAD_FREE RL_FREE
   755  
   756      #define GLAD_GL_IMPLEMENTATION
   757      #include "external/glad.h"      // GLAD extensions loading library, includes OpenGL headers
   758  #endif
   759  
   760  #if defined(GRAPHICS_API_OPENGL_ES2)
   761      #define GL_GLEXT_PROTOTYPES
   762      //#include <EGL/egl.h>              // EGL library -> not required, platform layer
   763      #include <GLES2/gl2.h>              // OpenGL ES 2.0 library
   764      #include <GLES2/gl2ext.h>           // OpenGL ES 2.0 extensions library
   765  
   766      // It seems OpenGL ES 2.0 instancing entry points are not defined on Raspberry Pi
   767      // provided headers (despite being defined in official Khronos GLES2 headers)
   768      #if defined(PLATFORM_RPI) || defined(PLATFORM_DRM)
   769      typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount);
   770      typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
   771      typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISOREXTPROC) (GLuint index, GLuint divisor);
   772      #endif
   773  #endif
   774  
   775  #include <stdlib.h>                     // Required for: malloc(), free()
   776  #include <string.h>                     // Required for: strcmp(), strlen() [Used in rlglInit(), on extensions loading]
   777  #include <math.h>                       // Required for: sqrtf(), sinf(), cosf(), floor(), log()
   778  
   779  //----------------------------------------------------------------------------------
   780  // Defines and Macros
   781  //----------------------------------------------------------------------------------
   782  #ifndef PI
   783      #define PI 3.14159265358979323846f
   784  #endif
   785  #ifndef DEG2RAD
   786      #define DEG2RAD (PI/180.0f)
   787  #endif
   788  #ifndef RAD2DEG
   789      #define RAD2DEG (180.0f/PI)
   790  #endif
   791  
   792  #ifndef GL_SHADING_LANGUAGE_VERSION
   793      #define GL_SHADING_LANGUAGE_VERSION         0x8B8C
   794  #endif
   795  
   796  #ifndef GL_COMPRESSED_RGB_S3TC_DXT1_EXT
   797      #define GL_COMPRESSED_RGB_S3TC_DXT1_EXT     0x83F0
   798  #endif
   799  #ifndef GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
   800      #define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT    0x83F1
   801  #endif
   802  #ifndef GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
   803      #define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT    0x83F2
   804  #endif
   805  #ifndef GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
   806      #define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT    0x83F3
   807  #endif
   808  #ifndef GL_ETC1_RGB8_OES
   809      #define GL_ETC1_RGB8_OES                    0x8D64
   810  #endif
   811  #ifndef GL_COMPRESSED_RGB8_ETC2
   812      #define GL_COMPRESSED_RGB8_ETC2             0x9274
   813  #endif
   814  #ifndef GL_COMPRESSED_RGBA8_ETC2_EAC
   815      #define GL_COMPRESSED_RGBA8_ETC2_EAC        0x9278
   816  #endif
   817  #ifndef GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
   818      #define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG  0x8C00
   819  #endif
   820  #ifndef GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
   821      #define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02
   822  #endif
   823  #ifndef GL_COMPRESSED_RGBA_ASTC_4x4_KHR
   824      #define GL_COMPRESSED_RGBA_ASTC_4x4_KHR     0x93b0
   825  #endif
   826  #ifndef GL_COMPRESSED_RGBA_ASTC_8x8_KHR
   827      #define GL_COMPRESSED_RGBA_ASTC_8x8_KHR     0x93b7
   828  #endif
   829  
   830  #ifndef GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT
   831      #define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT   0x84FF
   832  #endif
   833  #ifndef GL_TEXTURE_MAX_ANISOTROPY_EXT
   834      #define GL_TEXTURE_MAX_ANISOTROPY_EXT       0x84FE
   835  #endif
   836  
   837  #if defined(GRAPHICS_API_OPENGL_11)
   838      #define GL_UNSIGNED_SHORT_5_6_5             0x8363
   839      #define GL_UNSIGNED_SHORT_5_5_5_1           0x8034
   840      #define GL_UNSIGNED_SHORT_4_4_4_4           0x8033
   841  #endif
   842  
   843  #if defined(GRAPHICS_API_OPENGL_21)
   844      #define GL_LUMINANCE                        0x1909
   845      #define GL_LUMINANCE_ALPHA                  0x190A
   846  #endif
   847  
   848  #if defined(GRAPHICS_API_OPENGL_ES2)
   849      #define glClearDepth                 glClearDepthf
   850      #define GL_READ_FRAMEBUFFER         GL_FRAMEBUFFER
   851      #define GL_DRAW_FRAMEBUFFER         GL_FRAMEBUFFER
   852  #endif
   853  
   854  // Default shader vertex attribute names to set location points
   855  #ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION
   856      #define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION     "vertexPosition"    // Binded by default to shader location: 0
   857  #endif
   858  #ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD
   859      #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD     "vertexTexCoord"    // Binded by default to shader location: 1
   860  #endif
   861  #ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL
   862      #define RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL       "vertexNormal"      // Binded by default to shader location: 2
   863  #endif
   864  #ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR
   865      #define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR        "vertexColor"       // Binded by default to shader location: 3
   866  #endif
   867  #ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT
   868      #define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT      "vertexTangent"     // Binded by default to shader location: 4
   869  #endif
   870  #ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2
   871      #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2    "vertexTexCoord2"   // Binded by default to shader location: 5
   872  #endif
   873  
   874  #ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_MVP
   875      #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP         "mvp"               // model-view-projection matrix
   876  #endif
   877  #ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW
   878      #define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW        "matView"           // view matrix
   879  #endif
   880  #ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION
   881      #define RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION  "matProjection"     // projection matrix
   882  #endif
   883  #ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL
   884      #define RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL       "matModel"          // model matrix
   885  #endif
   886  #ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL
   887      #define RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL      "matNormal"         // normal matrix (transpose(inverse(matModelView))
   888  #endif
   889  #ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR
   890      #define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR       "colDiffuse"        // color diffuse (base tint color, multiplied by texture color)
   891  #endif
   892  #ifndef RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0
   893      #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0  "texture0"          // texture0 (texture slot active 0)
   894  #endif
   895  #ifndef RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1
   896      #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1  "texture1"          // texture1 (texture slot active 1)
   897  #endif
   898  #ifndef RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2
   899      #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2  "texture2"          // texture2 (texture slot active 2)
   900  #endif
   901  
   902  //----------------------------------------------------------------------------------
   903  // Types and Structures Definition
   904  //----------------------------------------------------------------------------------
   905  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
   906  typedef struct rlglData {
   907      rlRenderBatch *currentBatch;            // Current render batch
   908      rlRenderBatch defaultBatch;             // Default internal render batch
   909  
   910      struct {
   911          int vertexCounter;                  // Current active render batch vertex counter (generic, used for all batches)
   912          float texcoordx, texcoordy;         // Current active texture coordinate (added on glVertex*())
   913          float normalx, normaly, normalz;    // Current active normal (added on glVertex*())
   914          unsigned char colorr, colorg, colorb, colora;   // Current active color (added on glVertex*())
   915  
   916          int currentMatrixMode;              // Current matrix mode
   917          Matrix *currentMatrix;              // Current matrix pointer
   918          Matrix modelview;                   // Default modelview matrix
   919          Matrix projection;                  // Default projection matrix
   920          Matrix transform;                   // Transform matrix to be used with rlTranslate, rlRotate, rlScale
   921          bool transformRequired;             // Require transform matrix application to current draw-call vertex (if required)
   922          Matrix stack[RL_MAX_MATRIX_STACK_SIZE];// Matrix stack for push/pop
   923          int stackCounter;                   // Matrix stack counter
   924  
   925          unsigned int defaultTextureId;      // Default texture used on shapes/poly drawing (required by shader)
   926          unsigned int activeTextureId[RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS];    // Active texture ids to be enabled on batch drawing (0 active by default)
   927          unsigned int defaultVShaderId;      // Default vertex shader id (used by default shader program)
   928          unsigned int defaultFShaderId;      // Default fragment shader id (used by default shader program)
   929          unsigned int defaultShaderId;       // Default shader program id, supports vertex color and diffuse texture
   930          int *defaultShaderLocs;             // Default shader locations pointer to be used on rendering
   931          unsigned int currentShaderId;       // Current shader id to be used on rendering (by default, defaultShaderId)
   932          int *currentShaderLocs;             // Current shader locations pointer to be used on rendering (by default, defaultShaderLocs)
   933  
   934          bool stereoRender;                  // Stereo rendering flag
   935          Matrix projectionStereo[2];         // VR stereo rendering eyes projection matrices
   936          Matrix viewOffsetStereo[2];         // VR stereo rendering eyes view offset matrices
   937  
   938          // Blending variables
   939          int currentBlendMode;               // Blending mode active
   940          int glBlendSrcFactor;               // Blending source factor
   941          int glBlendDstFactor;               // Blending destination factor
   942          int glBlendEquation;                // Blending equation
   943          int glBlendSrcFactorRGB;            // Blending source RGB factor
   944          int glBlendDestFactorRGB;           // Blending destination RGB factor
   945          int glBlendSrcFactorAlpha;          // Blending source alpha factor
   946          int glBlendDestFactorAlpha;         // Blending destination alpha factor
   947          int glBlendEquationRGB;             // Blending equation for RGB
   948          int glBlendEquationAlpha;           // Blending equation for alpha
   949          bool glCustomBlendModeModified;     // Custom blending factor and equation modification status
   950  
   951          int framebufferWidth;               // Current framebuffer width
   952          int framebufferHeight;              // Current framebuffer height
   953  
   954      } State;            // Renderer state
   955      struct {
   956          bool vao;                           // VAO support (OpenGL ES2 could not support VAO extension) (GL_ARB_vertex_array_object)
   957          bool instancing;                    // Instancing supported (GL_ANGLE_instanced_arrays, GL_EXT_draw_instanced + GL_EXT_instanced_arrays)
   958          bool texNPOT;                       // NPOT textures full support (GL_ARB_texture_non_power_of_two, GL_OES_texture_npot)
   959          bool texDepth;                      // Depth textures supported (GL_ARB_depth_texture, GL_WEBGL_depth_texture, GL_OES_depth_texture)
   960          bool texFloat32;                    // float textures support (32 bit per channel) (GL_OES_texture_float)
   961          bool texCompDXT;                    // DDS texture compression support (GL_EXT_texture_compression_s3tc, GL_WEBGL_compressed_texture_s3tc, GL_WEBKIT_WEBGL_compressed_texture_s3tc)
   962          bool texCompETC1;                   // ETC1 texture compression support (GL_OES_compressed_ETC1_RGB8_texture, GL_WEBGL_compressed_texture_etc1)
   963          bool texCompETC2;                   // ETC2/EAC texture compression support (GL_ARB_ES3_compatibility)
   964          bool texCompPVRT;                   // PVR texture compression support (GL_IMG_texture_compression_pvrtc)
   965          bool texCompASTC;                   // ASTC texture compression support (GL_KHR_texture_compression_astc_hdr, GL_KHR_texture_compression_astc_ldr)
   966          bool texMirrorClamp;                // Clamp mirror wrap mode supported (GL_EXT_texture_mirror_clamp)
   967          bool texAnisoFilter;                // Anisotropic texture filtering support (GL_EXT_texture_filter_anisotropic)
   968          bool computeShader;                 // Compute shaders support (GL_ARB_compute_shader)
   969          bool ssbo;                          // Shader storage buffer object support (GL_ARB_shader_storage_buffer_object)
   970  
   971          float maxAnisotropyLevel;           // Maximum anisotropy level supported (minimum is 2.0f)
   972          int maxDepthBits;                   // Maximum bits for depth component
   973  
   974      } ExtSupported;     // Extensions supported flags
   975  } rlglData;
   976  
   977  typedef void *(*rlglLoadProc)(const char *name);   // OpenGL extension functions loader signature (same as GLADloadproc)
   978  
   979  #endif  // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
   980  
   981  //----------------------------------------------------------------------------------
   982  // Global Variables Definition
   983  //----------------------------------------------------------------------------------
   984  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
   985  static rlglData RLGL = { 0 };
   986  #endif  // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
   987  
   988  #if defined(GRAPHICS_API_OPENGL_ES2)
   989  // NOTE: VAO functionality is exposed through extensions (OES)
   990  static PFNGLGENVERTEXARRAYSOESPROC glGenVertexArrays = NULL;
   991  static PFNGLBINDVERTEXARRAYOESPROC glBindVertexArray = NULL;
   992  static PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArrays = NULL;
   993  
   994  // NOTE: Instancing functionality could also be available through extension
   995  static PFNGLDRAWARRAYSINSTANCEDEXTPROC glDrawArraysInstanced = NULL;
   996  static PFNGLDRAWELEMENTSINSTANCEDEXTPROC glDrawElementsInstanced = NULL;
   997  static PFNGLVERTEXATTRIBDIVISOREXTPROC glVertexAttribDivisor = NULL;
   998  #endif
   999  
  1000  //----------------------------------------------------------------------------------
  1001  // Module specific Functions Declaration
  1002  //----------------------------------------------------------------------------------
  1003  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  1004  static void rlLoadShaderDefault(void);      // Load default shader
  1005  static void rlUnloadShaderDefault(void);    // Unload default shader
  1006  #if defined(RLGL_SHOW_GL_DETAILS_INFO)
  1007  static char *rlGetCompressedFormatName(int format); // Get compressed format official GL identifier name
  1008  #endif  // RLGL_SHOW_GL_DETAILS_INFO
  1009  #endif  // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
  1010  
  1011  static int rlGetPixelDataSize(int width, int height, int format);   // Get pixel data size in bytes (image or texture)
  1012  
  1013  // Auxiliar matrix math functions
  1014  static Matrix rlMatrixIdentity(void);                       // Get identity matrix
  1015  static Matrix rlMatrixMultiply(Matrix left, Matrix right);  // Multiply two matrices
  1016  
  1017  //----------------------------------------------------------------------------------
  1018  // Module Functions Definition - Matrix operations
  1019  //----------------------------------------------------------------------------------
  1020  
  1021  #if defined(GRAPHICS_API_OPENGL_11)
  1022  // Fallback to OpenGL 1.1 function calls
  1023  //---------------------------------------
  1024  void rlMatrixMode(int mode)
  1025  {
  1026      switch (mode)
  1027      {
  1028          case RL_PROJECTION: glMatrixMode(GL_PROJECTION); break;
  1029          case RL_MODELVIEW: glMatrixMode(GL_MODELVIEW); break;
  1030          case RL_TEXTURE: glMatrixMode(GL_TEXTURE); break;
  1031          default: break;
  1032      }
  1033  }
  1034  
  1035  void rlFrustum(double left, double right, double bottom, double top, double znear, double zfar)
  1036  {
  1037      glFrustum(left, right, bottom, top, znear, zfar);
  1038  }
  1039  
  1040  void rlOrtho(double left, double right, double bottom, double top, double znear, double zfar)
  1041  {
  1042      glOrtho(left, right, bottom, top, znear, zfar);
  1043  }
  1044  
  1045  void rlPushMatrix(void) { glPushMatrix(); }
  1046  void rlPopMatrix(void) { glPopMatrix(); }
  1047  void rlLoadIdentity(void) { glLoadIdentity(); }
  1048  void rlTranslatef(float x, float y, float z) { glTranslatef(x, y, z); }
  1049  void rlRotatef(float angle, float x, float y, float z) { glRotatef(angle, x, y, z); }
  1050  void rlScalef(float x, float y, float z) { glScalef(x, y, z); }
  1051  void rlMultMatrixf(float *matf) { glMultMatrixf(matf); }
  1052  #endif
  1053  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  1054  // Choose the current matrix to be transformed
  1055  void rlMatrixMode(int mode)
  1056  {
  1057      if (mode == RL_PROJECTION) RLGL.State.currentMatrix = &RLGL.State.projection;
  1058      else if (mode == RL_MODELVIEW) RLGL.State.currentMatrix = &RLGL.State.modelview;
  1059      //else if (mode == RL_TEXTURE) // Not supported
  1060  
  1061      RLGL.State.currentMatrixMode = mode;
  1062  }
  1063  
  1064  // Push the current matrix into RLGL.State.stack
  1065  void rlPushMatrix(void)
  1066  {
  1067      if (RLGL.State.stackCounter >= RL_MAX_MATRIX_STACK_SIZE) TRACELOG(RL_LOG_ERROR, "RLGL: Matrix stack overflow (RL_MAX_MATRIX_STACK_SIZE)");
  1068  
  1069      if (RLGL.State.currentMatrixMode == RL_MODELVIEW)
  1070      {
  1071          RLGL.State.transformRequired = true;
  1072          RLGL.State.currentMatrix = &RLGL.State.transform;
  1073      }
  1074  
  1075      RLGL.State.stack[RLGL.State.stackCounter] = *RLGL.State.currentMatrix;
  1076      RLGL.State.stackCounter++;
  1077  }
  1078  
  1079  // Pop lattest inserted matrix from RLGL.State.stack
  1080  void rlPopMatrix(void)
  1081  {
  1082      if (RLGL.State.stackCounter > 0)
  1083      {
  1084          Matrix mat = RLGL.State.stack[RLGL.State.stackCounter - 1];
  1085          *RLGL.State.currentMatrix = mat;
  1086          RLGL.State.stackCounter--;
  1087      }
  1088  
  1089      if ((RLGL.State.stackCounter == 0) && (RLGL.State.currentMatrixMode == RL_MODELVIEW))
  1090      {
  1091          RLGL.State.currentMatrix = &RLGL.State.modelview;
  1092          RLGL.State.transformRequired = false;
  1093      }
  1094  }
  1095  
  1096  // Reset current matrix to identity matrix
  1097  void rlLoadIdentity(void)
  1098  {
  1099      *RLGL.State.currentMatrix = rlMatrixIdentity();
  1100  }
  1101  
  1102  // Multiply the current matrix by a translation matrix
  1103  void rlTranslatef(float x, float y, float z)
  1104  {
  1105      Matrix matTranslation = {
  1106          1.0f, 0.0f, 0.0f, x,
  1107          0.0f, 1.0f, 0.0f, y,
  1108          0.0f, 0.0f, 1.0f, z,
  1109          0.0f, 0.0f, 0.0f, 1.0f
  1110      };
  1111  
  1112      // NOTE: We transpose matrix with multiplication order
  1113      *RLGL.State.currentMatrix = rlMatrixMultiply(matTranslation, *RLGL.State.currentMatrix);
  1114  }
  1115  
  1116  // Multiply the current matrix by a rotation matrix
  1117  // NOTE: The provided angle must be in degrees
  1118  void rlRotatef(float angle, float x, float y, float z)
  1119  {
  1120      Matrix matRotation = rlMatrixIdentity();
  1121  
  1122      // Axis vector (x, y, z) normalization
  1123      float lengthSquared = x*x + y*y + z*z;
  1124      if ((lengthSquared != 1.0f) && (lengthSquared != 0.0f))
  1125      {
  1126          float inverseLength = 1.0f/sqrtf(lengthSquared);
  1127          x *= inverseLength;
  1128          y *= inverseLength;
  1129          z *= inverseLength;
  1130      }
  1131  
  1132      // Rotation matrix generation
  1133      float sinres = sinf(DEG2RAD*angle);
  1134      float cosres = cosf(DEG2RAD*angle);
  1135      float t = 1.0f - cosres;
  1136  
  1137      matRotation.m0 = x*x*t + cosres;
  1138      matRotation.m1 = y*x*t + z*sinres;
  1139      matRotation.m2 = z*x*t - y*sinres;
  1140      matRotation.m3 = 0.0f;
  1141  
  1142      matRotation.m4 = x*y*t - z*sinres;
  1143      matRotation.m5 = y*y*t + cosres;
  1144      matRotation.m6 = z*y*t + x*sinres;
  1145      matRotation.m7 = 0.0f;
  1146  
  1147      matRotation.m8 = x*z*t + y*sinres;
  1148      matRotation.m9 = y*z*t - x*sinres;
  1149      matRotation.m10 = z*z*t + cosres;
  1150      matRotation.m11 = 0.0f;
  1151  
  1152      matRotation.m12 = 0.0f;
  1153      matRotation.m13 = 0.0f;
  1154      matRotation.m14 = 0.0f;
  1155      matRotation.m15 = 1.0f;
  1156  
  1157      // NOTE: We transpose matrix with multiplication order
  1158      *RLGL.State.currentMatrix = rlMatrixMultiply(matRotation, *RLGL.State.currentMatrix);
  1159  }
  1160  
  1161  // Multiply the current matrix by a scaling matrix
  1162  void rlScalef(float x, float y, float z)
  1163  {
  1164      Matrix matScale = {
  1165          x, 0.0f, 0.0f, 0.0f,
  1166          0.0f, y, 0.0f, 0.0f,
  1167          0.0f, 0.0f, z, 0.0f,
  1168          0.0f, 0.0f, 0.0f, 1.0f
  1169      };
  1170  
  1171      // NOTE: We transpose matrix with multiplication order
  1172      *RLGL.State.currentMatrix = rlMatrixMultiply(matScale, *RLGL.State.currentMatrix);
  1173  }
  1174  
  1175  // Multiply the current matrix by another matrix
  1176  void rlMultMatrixf(float *matf)
  1177  {
  1178      // Matrix creation from array
  1179      Matrix mat = { matf[0], matf[4], matf[8], matf[12],
  1180                     matf[1], matf[5], matf[9], matf[13],
  1181                     matf[2], matf[6], matf[10], matf[14],
  1182                     matf[3], matf[7], matf[11], matf[15] };
  1183  
  1184      *RLGL.State.currentMatrix = rlMatrixMultiply(*RLGL.State.currentMatrix, mat);
  1185  }
  1186  
  1187  // Multiply the current matrix by a perspective matrix generated by parameters
  1188  void rlFrustum(double left, double right, double bottom, double top, double znear, double zfar)
  1189  {
  1190      Matrix matFrustum = { 0 };
  1191  
  1192      float rl = (float)(right - left);
  1193      float tb = (float)(top - bottom);
  1194      float fn = (float)(zfar - znear);
  1195  
  1196      matFrustum.m0 = ((float) znear*2.0f)/rl;
  1197      matFrustum.m1 = 0.0f;
  1198      matFrustum.m2 = 0.0f;
  1199      matFrustum.m3 = 0.0f;
  1200  
  1201      matFrustum.m4 = 0.0f;
  1202      matFrustum.m5 = ((float) znear*2.0f)/tb;
  1203      matFrustum.m6 = 0.0f;
  1204      matFrustum.m7 = 0.0f;
  1205  
  1206      matFrustum.m8 = ((float)right + (float)left)/rl;
  1207      matFrustum.m9 = ((float)top + (float)bottom)/tb;
  1208      matFrustum.m10 = -((float)zfar + (float)znear)/fn;
  1209      matFrustum.m11 = -1.0f;
  1210  
  1211      matFrustum.m12 = 0.0f;
  1212      matFrustum.m13 = 0.0f;
  1213      matFrustum.m14 = -((float)zfar*(float)znear*2.0f)/fn;
  1214      matFrustum.m15 = 0.0f;
  1215  
  1216      *RLGL.State.currentMatrix = rlMatrixMultiply(*RLGL.State.currentMatrix, matFrustum);
  1217  }
  1218  
  1219  // Multiply the current matrix by an orthographic matrix generated by parameters
  1220  void rlOrtho(double left, double right, double bottom, double top, double znear, double zfar)
  1221  {
  1222      // NOTE: If left-right and top-botton values are equal it could create a division by zero,
  1223      // response to it is platform/compiler dependant
  1224      Matrix matOrtho = { 0 };
  1225  
  1226      float rl = (float)(right - left);
  1227      float tb = (float)(top - bottom);
  1228      float fn = (float)(zfar - znear);
  1229  
  1230      matOrtho.m0 = 2.0f/rl;
  1231      matOrtho.m1 = 0.0f;
  1232      matOrtho.m2 = 0.0f;
  1233      matOrtho.m3 = 0.0f;
  1234      matOrtho.m4 = 0.0f;
  1235      matOrtho.m5 = 2.0f/tb;
  1236      matOrtho.m6 = 0.0f;
  1237      matOrtho.m7 = 0.0f;
  1238      matOrtho.m8 = 0.0f;
  1239      matOrtho.m9 = 0.0f;
  1240      matOrtho.m10 = -2.0f/fn;
  1241      matOrtho.m11 = 0.0f;
  1242      matOrtho.m12 = -((float)left + (float)right)/rl;
  1243      matOrtho.m13 = -((float)top + (float)bottom)/tb;
  1244      matOrtho.m14 = -((float)zfar + (float)znear)/fn;
  1245      matOrtho.m15 = 1.0f;
  1246  
  1247      *RLGL.State.currentMatrix = rlMatrixMultiply(*RLGL.State.currentMatrix, matOrtho);
  1248  }
  1249  #endif
  1250  
  1251  // Set the viewport area (transformation from normalized device coordinates to window coordinates)
  1252  // NOTE: We store current viewport dimensions
  1253  void rlViewport(int x, int y, int width, int height)
  1254  {
  1255      glViewport(x, y, width, height);
  1256  }
  1257  
  1258  //----------------------------------------------------------------------------------
  1259  // Module Functions Definition - Vertex level operations
  1260  //----------------------------------------------------------------------------------
  1261  #if defined(GRAPHICS_API_OPENGL_11)
  1262  // Fallback to OpenGL 1.1 function calls
  1263  //---------------------------------------
  1264  void rlBegin(int mode)
  1265  {
  1266      switch (mode)
  1267      {
  1268          case RL_LINES: glBegin(GL_LINES); break;
  1269          case RL_TRIANGLES: glBegin(GL_TRIANGLES); break;
  1270          case RL_QUADS: glBegin(GL_QUADS); break;
  1271          default: break;
  1272      }
  1273  }
  1274  
  1275  void rlEnd() { glEnd(); }
  1276  void rlVertex2i(int x, int y) { glVertex2i(x, y); }
  1277  void rlVertex2f(float x, float y) { glVertex2f(x, y); }
  1278  void rlVertex3f(float x, float y, float z) { glVertex3f(x, y, z); }
  1279  void rlTexCoord2f(float x, float y) { glTexCoord2f(x, y); }
  1280  void rlNormal3f(float x, float y, float z) { glNormal3f(x, y, z); }
  1281  void rlColor4ub(unsigned char r, unsigned char g, unsigned char b, unsigned char a) { glColor4ub(r, g, b, a); }
  1282  void rlColor3f(float x, float y, float z) { glColor3f(x, y, z); }
  1283  void rlColor4f(float x, float y, float z, float w) { glColor4f(x, y, z, w); }
  1284  #endif
  1285  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  1286  // Initialize drawing mode (how to organize vertex)
  1287  void rlBegin(int mode)
  1288  {
  1289      // Draw mode can be RL_LINES, RL_TRIANGLES and RL_QUADS
  1290      // NOTE: In all three cases, vertex are accumulated over default internal vertex buffer
  1291      if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode != mode)
  1292      {
  1293          if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount > 0)
  1294          {
  1295              // Make sure current RLGL.currentBatch->draws[i].vertexCount is aligned a multiple of 4,
  1296              // that way, following QUADS drawing will keep aligned with index processing
  1297              // It implies adding some extra alignment vertex at the end of the draw,
  1298              // those vertex are not processed but they are considered as an additional offset
  1299              // for the next set of vertex to be drawn
  1300              if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode == RL_LINES) RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount < 4)? RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount : RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount%4);
  1301              else if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode == RL_TRIANGLES) RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount < 4)? 1 : (4 - (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount%4)));
  1302              else RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment = 0;
  1303  
  1304              if (!rlCheckRenderBatchLimit(RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment))
  1305              {
  1306                  RLGL.State.vertexCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment;
  1307                  RLGL.currentBatch->drawCounter++;
  1308              }
  1309          }
  1310  
  1311          if (RLGL.currentBatch->drawCounter >= RL_DEFAULT_BATCH_DRAWCALLS) rlDrawRenderBatch(RLGL.currentBatch);
  1312  
  1313          RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode = mode;
  1314          RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount = 0;
  1315          RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].textureId = RLGL.State.defaultTextureId;
  1316      }
  1317  }
  1318  
  1319  // Finish vertex providing
  1320  void rlEnd(void)
  1321  {
  1322      // NOTE: Depth increment is dependant on rlOrtho(): z-near and z-far values,
  1323      // as well as depth buffer bit-depth (16bit or 24bit or 32bit)
  1324      // Correct increment formula would be: depthInc = (zfar - znear)/pow(2, bits)
  1325      RLGL.currentBatch->currentDepth += (1.0f/20000.0f);
  1326  }
  1327  
  1328  // Define one vertex (position)
  1329  // NOTE: Vertex position data is the basic information required for drawing
  1330  void rlVertex3f(float x, float y, float z)
  1331  {
  1332      float tx = x;
  1333      float ty = y;
  1334      float tz = z;
  1335  
  1336      // Transform provided vector if required
  1337      if (RLGL.State.transformRequired)
  1338      {
  1339          tx = RLGL.State.transform.m0*x + RLGL.State.transform.m4*y + RLGL.State.transform.m8*z + RLGL.State.transform.m12;
  1340          ty = RLGL.State.transform.m1*x + RLGL.State.transform.m5*y + RLGL.State.transform.m9*z + RLGL.State.transform.m13;
  1341          tz = RLGL.State.transform.m2*x + RLGL.State.transform.m6*y + RLGL.State.transform.m10*z + RLGL.State.transform.m14;
  1342      }
  1343  
  1344      // WARNING: We can't break primitives when launching a new batch.
  1345      // RL_LINES comes in pairs, RL_TRIANGLES come in groups of 3 vertices and RL_QUADS come in groups of 4 vertices.
  1346      // We must check current draw.mode when a new vertex is required and finish the batch only if the draw.mode draw.vertexCount is %2, %3 or %4
  1347      if (RLGL.State.vertexCounter > (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementCount*4 - 4))
  1348      {
  1349          if ((RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode == RL_LINES) &&
  1350              (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount%2 == 0))
  1351          {
  1352              // Reached the maximum number of vertices for RL_LINES drawing
  1353              // Launch a draw call but keep current state for next vertices comming
  1354              // NOTE: We add +1 vertex to the check for security
  1355              rlCheckRenderBatchLimit(2 + 1);
  1356          }
  1357          else if ((RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode == RL_TRIANGLES) &&
  1358              (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount%3 == 0))
  1359          {
  1360              rlCheckRenderBatchLimit(3 + 1);
  1361          }
  1362          else if ((RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode == RL_QUADS) &&
  1363              (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount%4 == 0))
  1364          {
  1365              rlCheckRenderBatchLimit(4 + 1);
  1366          }
  1367      }
  1368  
  1369      // Add vertices
  1370      RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vertices[3*RLGL.State.vertexCounter] = tx;
  1371      RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vertices[3*RLGL.State.vertexCounter + 1] = ty;
  1372      RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vertices[3*RLGL.State.vertexCounter + 2] = tz;
  1373  
  1374      // Add current texcoord
  1375      RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].texcoords[2*RLGL.State.vertexCounter] = RLGL.State.texcoordx;
  1376      RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].texcoords[2*RLGL.State.vertexCounter + 1] = RLGL.State.texcoordy;
  1377  
  1378      // TODO: Add current normal
  1379      // By default rlVertexBuffer type does not store normals
  1380  
  1381      // Add current color
  1382      RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.State.vertexCounter] = RLGL.State.colorr;
  1383      RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.State.vertexCounter + 1] = RLGL.State.colorg;
  1384      RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.State.vertexCounter + 2] = RLGL.State.colorb;
  1385      RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.State.vertexCounter + 3] = RLGL.State.colora;
  1386  
  1387      RLGL.State.vertexCounter++;
  1388      RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount++;
  1389  }
  1390  
  1391  // Define one vertex (position)
  1392  void rlVertex2f(float x, float y)
  1393  {
  1394      rlVertex3f(x, y, RLGL.currentBatch->currentDepth);
  1395  }
  1396  
  1397  // Define one vertex (position)
  1398  void rlVertex2i(int x, int y)
  1399  {
  1400      rlVertex3f((float)x, (float)y, RLGL.currentBatch->currentDepth);
  1401  }
  1402  
  1403  // Define one vertex (texture coordinate)
  1404  // NOTE: Texture coordinates are limited to QUADS only
  1405  void rlTexCoord2f(float x, float y)
  1406  {
  1407      RLGL.State.texcoordx = x;
  1408      RLGL.State.texcoordy = y;
  1409  }
  1410  
  1411  // Define one vertex (normal)
  1412  // NOTE: Normals limited to TRIANGLES only?
  1413  void rlNormal3f(float x, float y, float z)
  1414  {
  1415      RLGL.State.normalx = x;
  1416      RLGL.State.normaly = y;
  1417      RLGL.State.normalz = z;
  1418  }
  1419  
  1420  // Define one vertex (color)
  1421  void rlColor4ub(unsigned char x, unsigned char y, unsigned char z, unsigned char w)
  1422  {
  1423      RLGL.State.colorr = x;
  1424      RLGL.State.colorg = y;
  1425      RLGL.State.colorb = z;
  1426      RLGL.State.colora = w;
  1427  }
  1428  
  1429  // Define one vertex (color)
  1430  void rlColor4f(float r, float g, float b, float a)
  1431  {
  1432      rlColor4ub((unsigned char)(r*255), (unsigned char)(g*255), (unsigned char)(b*255), (unsigned char)(a*255));
  1433  }
  1434  
  1435  // Define one vertex (color)
  1436  void rlColor3f(float x, float y, float z)
  1437  {
  1438      rlColor4ub((unsigned char)(x*255), (unsigned char)(y*255), (unsigned char)(z*255), 255);
  1439  }
  1440  
  1441  #endif
  1442  
  1443  //--------------------------------------------------------------------------------------
  1444  // Module Functions Definition - OpenGL style functions (common to 1.1, 3.3+, ES2)
  1445  //--------------------------------------------------------------------------------------
  1446  
  1447  // Set current texture to use
  1448  void rlSetTexture(unsigned int id)
  1449  {
  1450      if (id == 0)
  1451      {
  1452  #if defined(GRAPHICS_API_OPENGL_11)
  1453          rlDisableTexture();
  1454  #else
  1455          // NOTE: If quads batch limit is reached, we force a draw call and next batch starts
  1456          if (RLGL.State.vertexCounter >=
  1457              RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementCount*4)
  1458          {
  1459              rlDrawRenderBatch(RLGL.currentBatch);
  1460          }
  1461  #endif
  1462      }
  1463      else
  1464      {
  1465  #if defined(GRAPHICS_API_OPENGL_11)
  1466          rlEnableTexture(id);
  1467  #else
  1468          if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].textureId != id)
  1469          {
  1470              if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount > 0)
  1471              {
  1472                  // Make sure current RLGL.currentBatch->draws[i].vertexCount is aligned a multiple of 4,
  1473                  // that way, following QUADS drawing will keep aligned with index processing
  1474                  // It implies adding some extra alignment vertex at the end of the draw,
  1475                  // those vertex are not processed but they are considered as an additional offset
  1476                  // for the next set of vertex to be drawn
  1477                  if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode == RL_LINES) RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount < 4)? RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount : RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount%4);
  1478                  else if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode == RL_TRIANGLES) RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount < 4)? 1 : (4 - (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount%4)));
  1479                  else RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment = 0;
  1480  
  1481                  if (!rlCheckRenderBatchLimit(RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment))
  1482                  {
  1483                      RLGL.State.vertexCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment;
  1484  
  1485                      RLGL.currentBatch->drawCounter++;
  1486                  }
  1487              }
  1488  
  1489              if (RLGL.currentBatch->drawCounter >= RL_DEFAULT_BATCH_DRAWCALLS) rlDrawRenderBatch(RLGL.currentBatch);
  1490  
  1491              RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].textureId = id;
  1492              RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount = 0;
  1493          }
  1494  #endif
  1495      }
  1496  }
  1497  
  1498  // Select and active a texture slot
  1499  void rlActiveTextureSlot(int slot)
  1500  {
  1501  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  1502      glActiveTexture(GL_TEXTURE0 + slot);
  1503  #endif
  1504  }
  1505  
  1506  // Enable texture
  1507  void rlEnableTexture(unsigned int id)
  1508  {
  1509  #if defined(GRAPHICS_API_OPENGL_11)
  1510      glEnable(GL_TEXTURE_2D);
  1511  #endif
  1512      glBindTexture(GL_TEXTURE_2D, id);
  1513  }
  1514  
  1515  // Disable texture
  1516  void rlDisableTexture(void)
  1517  {
  1518  #if defined(GRAPHICS_API_OPENGL_11)
  1519      glDisable(GL_TEXTURE_2D);
  1520  #endif
  1521      glBindTexture(GL_TEXTURE_2D, 0);
  1522  }
  1523  
  1524  // Enable texture cubemap
  1525  void rlEnableTextureCubemap(unsigned int id)
  1526  {
  1527  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  1528      glBindTexture(GL_TEXTURE_CUBE_MAP, id);
  1529  #endif
  1530  }
  1531  
  1532  // Disable texture cubemap
  1533  void rlDisableTextureCubemap(void)
  1534  {
  1535  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  1536      glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
  1537  #endif
  1538  }
  1539  
  1540  // Set texture parameters (wrap mode/filter mode)
  1541  void rlTextureParameters(unsigned int id, int param, int value)
  1542  {
  1543      glBindTexture(GL_TEXTURE_2D, id);
  1544  
  1545  #if !defined(GRAPHICS_API_OPENGL_11)
  1546      // Reset anisotropy filter, in case it was set
  1547      glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
  1548  #endif
  1549  
  1550      switch (param)
  1551      {
  1552          case RL_TEXTURE_WRAP_S:
  1553          case RL_TEXTURE_WRAP_T:
  1554          {
  1555              if (value == RL_TEXTURE_WRAP_MIRROR_CLAMP)
  1556              {
  1557  #if !defined(GRAPHICS_API_OPENGL_11)
  1558                  if (RLGL.ExtSupported.texMirrorClamp) glTexParameteri(GL_TEXTURE_2D, param, value);
  1559                  else TRACELOG(RL_LOG_WARNING, "GL: Clamp mirror wrap mode not supported (GL_MIRROR_CLAMP_EXT)");
  1560  #endif
  1561              }
  1562              else glTexParameteri(GL_TEXTURE_2D, param, value);
  1563  
  1564          } break;
  1565          case RL_TEXTURE_MAG_FILTER:
  1566          case RL_TEXTURE_MIN_FILTER: glTexParameteri(GL_TEXTURE_2D, param, value); break;
  1567          case RL_TEXTURE_FILTER_ANISOTROPIC:
  1568          {
  1569  #if !defined(GRAPHICS_API_OPENGL_11)
  1570              if (value <= RLGL.ExtSupported.maxAnisotropyLevel) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value);
  1571              else if (RLGL.ExtSupported.maxAnisotropyLevel > 0.0f)
  1572              {
  1573                  TRACELOG(RL_LOG_WARNING, "GL: Maximum anisotropic filter level supported is %iX", id, (int)RLGL.ExtSupported.maxAnisotropyLevel);
  1574                  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value);
  1575              }
  1576              else TRACELOG(RL_LOG_WARNING, "GL: Anisotropic filtering not supported");
  1577  #endif
  1578          } break;
  1579  #if defined(GRAPHICS_API_OPENGL_33)
  1580          case RL_TEXTURE_MIPMAP_BIAS_RATIO: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, value/100.0f);
  1581  #endif
  1582          default: break;
  1583      }
  1584  
  1585      glBindTexture(GL_TEXTURE_2D, 0);
  1586  }
  1587  
  1588  // Enable shader program
  1589  void rlEnableShader(unsigned int id)
  1590  {
  1591  #if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2))
  1592      glUseProgram(id);
  1593  #endif
  1594  }
  1595  
  1596  // Disable shader program
  1597  void rlDisableShader(void)
  1598  {
  1599  #if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2))
  1600      glUseProgram(0);
  1601  #endif
  1602  }
  1603  
  1604  // Enable rendering to texture (fbo)
  1605  void rlEnableFramebuffer(unsigned int id)
  1606  {
  1607  #if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(RLGL_RENDER_TEXTURES_HINT)
  1608      glBindFramebuffer(GL_FRAMEBUFFER, id);
  1609  #endif
  1610  }
  1611  
  1612  // Disable rendering to texture
  1613  void rlDisableFramebuffer(void)
  1614  {
  1615  #if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(RLGL_RENDER_TEXTURES_HINT)
  1616      glBindFramebuffer(GL_FRAMEBUFFER, 0);
  1617  #endif
  1618  }
  1619  
  1620  // Activate multiple draw color buffers
  1621  // NOTE: One color buffer is always active by default
  1622  void rlActiveDrawBuffers(int count)
  1623  {
  1624  #if (defined(GRAPHICS_API_OPENGL_33) && defined(RLGL_RENDER_TEXTURES_HINT))
  1625      // NOTE: Maximum number of draw buffers supported is implementation dependant,
  1626      // it can be queried with glGet*() but it must be at least 8
  1627      //GLint maxDrawBuffers = 0;
  1628      //glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
  1629  
  1630      if (count > 0)
  1631      {
  1632          if (count > 8) TRACELOG(LOG_WARNING, "GL: Max color buffers limited to 8");
  1633          else
  1634          {
  1635              unsigned int buffers[8] = {
  1636                  GL_COLOR_ATTACHMENT0,
  1637                  GL_COLOR_ATTACHMENT1,
  1638                  GL_COLOR_ATTACHMENT2,
  1639                  GL_COLOR_ATTACHMENT3,
  1640                  GL_COLOR_ATTACHMENT4,
  1641                  GL_COLOR_ATTACHMENT5,
  1642                  GL_COLOR_ATTACHMENT6,
  1643                  GL_COLOR_ATTACHMENT7,
  1644              };
  1645  
  1646              glDrawBuffers(count, buffers);
  1647          }
  1648      }
  1649      else TRACELOG(LOG_WARNING, "GL: One color buffer active by default");
  1650  #endif
  1651  }
  1652  
  1653  //----------------------------------------------------------------------------------
  1654  // General render state configuration
  1655  //----------------------------------------------------------------------------------
  1656  
  1657  // Enable color blending
  1658  void rlEnableColorBlend(void) { glEnable(GL_BLEND); }
  1659  
  1660  // Disable color blending
  1661  void rlDisableColorBlend(void) { glDisable(GL_BLEND); }
  1662  
  1663  // Enable depth test
  1664  void rlEnableDepthTest(void) { glEnable(GL_DEPTH_TEST); }
  1665  
  1666  // Disable depth test
  1667  void rlDisableDepthTest(void) { glDisable(GL_DEPTH_TEST); }
  1668  
  1669  // Enable depth write
  1670  void rlEnableDepthMask(void) { glDepthMask(GL_TRUE); }
  1671  
  1672  // Disable depth write
  1673  void rlDisableDepthMask(void) { glDepthMask(GL_FALSE); }
  1674  
  1675  // Enable backface culling
  1676  void rlEnableBackfaceCulling(void) { glEnable(GL_CULL_FACE); }
  1677  
  1678  // Disable backface culling
  1679  void rlDisableBackfaceCulling(void) { glDisable(GL_CULL_FACE); }
  1680  
  1681  // Set face culling mode
  1682  void rlSetCullFace(int mode)
  1683  {
  1684      switch (mode)
  1685      {
  1686          case RL_CULL_FACE_BACK: glCullFace(GL_BACK); break;
  1687          case RL_CULL_FACE_FRONT: glCullFace(GL_FRONT); break;
  1688          default: break;
  1689      }
  1690  }
  1691  
  1692  // Enable scissor test
  1693  void rlEnableScissorTest(void) { glEnable(GL_SCISSOR_TEST); }
  1694  
  1695  // Disable scissor test
  1696  void rlDisableScissorTest(void) { glDisable(GL_SCISSOR_TEST); }
  1697  
  1698  // Scissor test
  1699  void rlScissor(int x, int y, int width, int height) { glScissor(x, y, width, height); }
  1700  
  1701  // Enable wire mode
  1702  void rlEnableWireMode(void)
  1703  {
  1704  #if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
  1705      // NOTE: glPolygonMode() not available on OpenGL ES
  1706      glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  1707  #endif
  1708  }
  1709  
  1710  // Disable wire mode
  1711  void rlDisableWireMode(void)
  1712  {
  1713  #if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
  1714      // NOTE: glPolygonMode() not available on OpenGL ES
  1715      glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  1716  #endif
  1717  }
  1718  
  1719  // Set the line drawing width
  1720  void rlSetLineWidth(float width) { glLineWidth(width); }
  1721  
  1722  // Get the line drawing width
  1723  float rlGetLineWidth(void)
  1724  {
  1725      float width = 0;
  1726      glGetFloatv(GL_LINE_WIDTH, &width);
  1727      return width;
  1728  }
  1729  
  1730  // Enable line aliasing
  1731  void rlEnableSmoothLines(void)
  1732  {
  1733  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_11)
  1734      glEnable(GL_LINE_SMOOTH);
  1735  #endif
  1736  }
  1737  
  1738  // Disable line aliasing
  1739  void rlDisableSmoothLines(void)
  1740  {
  1741  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_11)
  1742      glDisable(GL_LINE_SMOOTH);
  1743  #endif
  1744  }
  1745  
  1746  // Enable stereo rendering
  1747  void rlEnableStereoRender(void)
  1748  {
  1749  #if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2))
  1750      RLGL.State.stereoRender = true;
  1751  #endif
  1752  }
  1753  
  1754  // Disable stereo rendering
  1755  void rlDisableStereoRender(void)
  1756  {
  1757  #if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2))
  1758      RLGL.State.stereoRender = false;
  1759  #endif
  1760  }
  1761  
  1762  // Check if stereo render is enabled
  1763  bool rlIsStereoRenderEnabled(void)
  1764  {
  1765  #if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2))
  1766      return RLGL.State.stereoRender;
  1767  #else
  1768      return false;
  1769  #endif
  1770  }
  1771  
  1772  // Clear color buffer with color
  1773  void rlClearColor(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
  1774  {
  1775      // Color values clamp to 0.0f(0) and 1.0f(255)
  1776      float cr = (float)r/255;
  1777      float cg = (float)g/255;
  1778      float cb = (float)b/255;
  1779      float ca = (float)a/255;
  1780  
  1781      glClearColor(cr, cg, cb, ca);
  1782  }
  1783  
  1784  // Clear used screen buffers (color and depth)
  1785  void rlClearScreenBuffers(void)
  1786  {
  1787      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);     // Clear used buffers: Color and Depth (Depth is used for 3D)
  1788      //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);     // Stencil buffer not used...
  1789  }
  1790  
  1791  // Check and log OpenGL error codes
  1792  void rlCheckErrors()
  1793  {
  1794  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  1795      int check = 1;
  1796      while (check)
  1797      {
  1798          const GLenum err = glGetError();
  1799          switch (err)
  1800          {
  1801              case GL_NO_ERROR: check = 0; break;
  1802              case 0x0500: TRACELOG(RL_LOG_WARNING, "GL: Error detected: GL_INVALID_ENUM"); break;
  1803              case 0x0501: TRACELOG(RL_LOG_WARNING, "GL: Error detected: GL_INVALID_VALUE"); break;
  1804              case 0x0502: TRACELOG(RL_LOG_WARNING, "GL: Error detected: GL_INVALID_OPERATION"); break;
  1805              case 0x0503: TRACELOG(RL_LOG_WARNING, "GL: Error detected: GL_STACK_OVERFLOW"); break;
  1806              case 0x0504: TRACELOG(RL_LOG_WARNING, "GL: Error detected: GL_STACK_UNDERFLOW"); break;
  1807              case 0x0505: TRACELOG(RL_LOG_WARNING, "GL: Error detected: GL_OUT_OF_MEMORY"); break;
  1808              case 0x0506: TRACELOG(RL_LOG_WARNING, "GL: Error detected: GL_INVALID_FRAMEBUFFER_OPERATION"); break;
  1809              default: TRACELOG(RL_LOG_WARNING, "GL: Error detected: Unknown error code: %x", err); break;
  1810          }
  1811      }
  1812  #endif
  1813  }
  1814  
  1815  // Set blend mode
  1816  void rlSetBlendMode(int mode)
  1817  {
  1818  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  1819      if (RLGL.State.currentBlendMode != mode || ((mode == RL_BLEND_CUSTOM || mode == RL_BLEND_CUSTOM_SEPARATE) && RLGL.State.glCustomBlendModeModified))
  1820      {
  1821          rlDrawRenderBatch(RLGL.currentBatch);
  1822  
  1823          switch (mode)
  1824          {
  1825              case RL_BLEND_ALPHA: glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendEquation(GL_FUNC_ADD); break;
  1826              case RL_BLEND_ADDITIVE: glBlendFunc(GL_SRC_ALPHA, GL_ONE); glBlendEquation(GL_FUNC_ADD); break;
  1827              case RL_BLEND_MULTIPLIED: glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); glBlendEquation(GL_FUNC_ADD); break;
  1828              case RL_BLEND_ADD_COLORS: glBlendFunc(GL_ONE, GL_ONE); glBlendEquation(GL_FUNC_ADD); break;
  1829              case RL_BLEND_SUBTRACT_COLORS: glBlendFunc(GL_ONE, GL_ONE); glBlendEquation(GL_FUNC_SUBTRACT); break;
  1830              case RL_BLEND_ALPHA_PREMULTIPLY: glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glBlendEquation(GL_FUNC_ADD); break;
  1831              case RL_BLEND_CUSTOM:
  1832              {
  1833                  // NOTE: Using GL blend src/dst factors and GL equation configured with rlSetBlendFactors()
  1834                  glBlendFunc(RLGL.State.glBlendSrcFactor, RLGL.State.glBlendDstFactor); glBlendEquation(RLGL.State.glBlendEquation);
  1835  
  1836              } break;
  1837              case RL_BLEND_CUSTOM_SEPARATE:
  1838              {
  1839                  // NOTE: Using GL blend src/dst factors and GL equation configured with rlSetBlendFactorsSeparate()
  1840                  glBlendFuncSeparate(RLGL.State.glBlendSrcFactorRGB, RLGL.State.glBlendDestFactorRGB, RLGL.State.glBlendSrcFactorAlpha, RLGL.State.glBlendDestFactorAlpha);
  1841                  glBlendEquationSeparate(RLGL.State.glBlendEquationRGB, RLGL.State.glBlendEquationAlpha);
  1842  
  1843              } break;
  1844              default: break;
  1845          }
  1846  
  1847          RLGL.State.currentBlendMode = mode;
  1848          RLGL.State.glCustomBlendModeModified = false;
  1849      }
  1850  #endif
  1851  }
  1852  
  1853  // Set blending mode factor and equation
  1854  void rlSetBlendFactors(int glSrcFactor, int glDstFactor, int glEquation)
  1855  {
  1856  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  1857      if ((RLGL.State.glBlendSrcFactor != glSrcFactor) ||
  1858          (RLGL.State.glBlendDstFactor != glDstFactor) ||
  1859          (RLGL.State.glBlendEquation != glEquation))
  1860      {
  1861          RLGL.State.glBlendSrcFactor = glSrcFactor;
  1862          RLGL.State.glBlendDstFactor = glDstFactor;
  1863          RLGL.State.glBlendEquation = glEquation;
  1864  
  1865          RLGL.State.glCustomBlendModeModified = true;
  1866      }
  1867  #endif
  1868  }
  1869  
  1870  // Set blending mode factor and equation separately for RGB and alpha
  1871  void rlSetBlendFactorsSeparate(int glSrcRGB, int glDstRGB, int glSrcAlpha, int glDstAlpha, int glEqRGB, int glEqAlpha)
  1872  {
  1873  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  1874      if ((RLGL.State.glBlendSrcFactorRGB != glSrcRGB) ||
  1875          (RLGL.State.glBlendDestFactorRGB != glDstRGB) ||
  1876          (RLGL.State.glBlendSrcFactorAlpha != glSrcAlpha) ||
  1877          (RLGL.State.glBlendDestFactorAlpha != glDstAlpha) ||
  1878          (RLGL.State.glBlendEquationRGB != glEqRGB) ||
  1879          (RLGL.State.glBlendEquationAlpha != glEqAlpha))
  1880      {
  1881          RLGL.State.glBlendSrcFactorRGB = glSrcRGB;
  1882          RLGL.State.glBlendDestFactorRGB = glDstRGB;
  1883          RLGL.State.glBlendSrcFactorAlpha = glSrcAlpha;
  1884          RLGL.State.glBlendDestFactorAlpha = glDstAlpha;
  1885          RLGL.State.glBlendEquationRGB = glEqRGB;
  1886          RLGL.State.glBlendEquationAlpha = glEqAlpha;
  1887  
  1888          RLGL.State.glCustomBlendModeModified = true;
  1889      }
  1890  #endif
  1891  }
  1892  
  1893  //----------------------------------------------------------------------------------
  1894  // Module Functions Definition - OpenGL Debug
  1895  //----------------------------------------------------------------------------------
  1896  #if defined(RLGL_ENABLE_OPENGL_DEBUG_CONTEXT) && defined(GRAPHICS_API_OPENGL_43)
  1897  static void GLAPIENTRY rlDebugMessageCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam)
  1898  {
  1899      // Ignore non-significant error/warning codes (NVidia drivers)
  1900      // NOTE: Here there are the details with a sample output:
  1901      // - #131169 - Framebuffer detailed info: The driver allocated storage for renderbuffer 2. (severity: low)
  1902      // - #131185 - Buffer detailed info: Buffer object 1 (bound to GL_ELEMENT_ARRAY_BUFFER_ARB, usage hint is GL_ENUM_88e4)
  1903      //             will use VIDEO memory as the source for buffer object operations. (severity: low)
  1904      // - #131218 - Program/shader state performance warning: Vertex shader in program 7 is being recompiled based on GL state. (severity: medium)
  1905      // - #131204 - Texture state usage warning: The texture object (0) bound to texture image unit 0 does not have
  1906      //             a defined base level and cannot be used for texture mapping. (severity: low)
  1907      if ((id == 131169) || (id == 131185) || (id == 131218) || (id == 131204)) return;
  1908  
  1909      const char *msgSource = NULL;
  1910      switch (source)
  1911      {
  1912          case GL_DEBUG_SOURCE_API: msgSource = "API"; break;
  1913          case GL_DEBUG_SOURCE_WINDOW_SYSTEM: msgSource = "WINDOW_SYSTEM"; break;
  1914          case GL_DEBUG_SOURCE_SHADER_COMPILER: msgSource = "SHADER_COMPILER"; break;
  1915          case GL_DEBUG_SOURCE_THIRD_PARTY: msgSource = "THIRD_PARTY"; break;
  1916          case GL_DEBUG_SOURCE_APPLICATION: msgSource = "APPLICATION"; break;
  1917          case GL_DEBUG_SOURCE_OTHER: msgSource = "OTHER"; break;
  1918          default: break;
  1919      }
  1920  
  1921      const char *msgType = NULL;
  1922      switch (type)
  1923      {
  1924          case GL_DEBUG_TYPE_ERROR: msgType = "ERROR"; break;
  1925          case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: msgType = "DEPRECATED_BEHAVIOR"; break;
  1926          case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: msgType = "UNDEFINED_BEHAVIOR"; break;
  1927          case GL_DEBUG_TYPE_PORTABILITY: msgType = "PORTABILITY"; break;
  1928          case GL_DEBUG_TYPE_PERFORMANCE: msgType = "PERFORMANCE"; break;
  1929          case GL_DEBUG_TYPE_MARKER: msgType = "MARKER"; break;
  1930          case GL_DEBUG_TYPE_PUSH_GROUP: msgType = "PUSH_GROUP"; break;
  1931          case GL_DEBUG_TYPE_POP_GROUP: msgType = "POP_GROUP"; break;
  1932          case GL_DEBUG_TYPE_OTHER: msgType = "OTHER"; break;
  1933          default: break;
  1934      }
  1935  
  1936      const char *msgSeverity = "DEFAULT";
  1937      switch (severity)
  1938      {
  1939          case GL_DEBUG_SEVERITY_LOW: msgSeverity = "LOW"; break;
  1940          case GL_DEBUG_SEVERITY_MEDIUM: msgSeverity = "MEDIUM"; break;
  1941          case GL_DEBUG_SEVERITY_HIGH: msgSeverity = "HIGH"; break;
  1942          case GL_DEBUG_SEVERITY_NOTIFICATION: msgSeverity = "NOTIFICATION"; break;
  1943          default: break;
  1944      }
  1945  
  1946      TRACELOG(LOG_WARNING, "GL: OpenGL debug message: %s", message);
  1947      TRACELOG(LOG_WARNING, "    > Type: %s", msgType);
  1948      TRACELOG(LOG_WARNING, "    > Source = %s", msgSource);
  1949      TRACELOG(LOG_WARNING, "    > Severity = %s", msgSeverity);
  1950  }
  1951  #endif
  1952  
  1953  //----------------------------------------------------------------------------------
  1954  // Module Functions Definition - rlgl functionality
  1955  //----------------------------------------------------------------------------------
  1956  
  1957  // Initialize rlgl: OpenGL extensions, default buffers/shaders/textures, OpenGL states
  1958  void rlglInit(int width, int height)
  1959  {
  1960      // Enable OpenGL debug context if required
  1961  #if defined(RLGL_ENABLE_OPENGL_DEBUG_CONTEXT) && defined(GRAPHICS_API_OPENGL_43)
  1962      if ((glDebugMessageCallback != NULL) && (glDebugMessageControl != NULL))
  1963      {
  1964          glDebugMessageCallback(rlDebugMessageCallback, 0);
  1965          // glDebugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DEBUG_SEVERITY_HIGH, 0, 0, GL_TRUE); // TODO: Filter message
  1966  
  1967          // Debug context options:
  1968          //  - GL_DEBUG_OUTPUT - Faster version but not useful for breakpoints
  1969          //  - GL_DEBUG_OUTPUT_SYNCHRONUS - Callback is in sync with errors, so a breakpoint can be placed on the callback in order to get a stacktrace for the GL error
  1970          glEnable(GL_DEBUG_OUTPUT);
  1971          glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
  1972      }
  1973  #endif
  1974  
  1975  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  1976      // Init default white texture
  1977      unsigned char pixels[4] = { 255, 255, 255, 255 };   // 1 pixel RGBA (4 bytes)
  1978      RLGL.State.defaultTextureId = rlLoadTexture(pixels, 1, 1, RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, 1);
  1979  
  1980      if (RLGL.State.defaultTextureId != 0) TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Default texture loaded successfully", RLGL.State.defaultTextureId);
  1981      else TRACELOG(RL_LOG_WARNING, "TEXTURE: Failed to load default texture");
  1982  
  1983      // Init default Shader (customized for GL 3.3 and ES2)
  1984      // Loaded: RLGL.State.defaultShaderId + RLGL.State.defaultShaderLocs
  1985      rlLoadShaderDefault();
  1986      RLGL.State.currentShaderId = RLGL.State.defaultShaderId;
  1987      RLGL.State.currentShaderLocs = RLGL.State.defaultShaderLocs;
  1988  
  1989      // Init default vertex arrays buffers
  1990      RLGL.defaultBatch = rlLoadRenderBatch(RL_DEFAULT_BATCH_BUFFERS, RL_DEFAULT_BATCH_BUFFER_ELEMENTS);
  1991      RLGL.currentBatch = &RLGL.defaultBatch;
  1992  
  1993      // Init stack matrices (emulating OpenGL 1.1)
  1994      for (int i = 0; i < RL_MAX_MATRIX_STACK_SIZE; i++) RLGL.State.stack[i] = rlMatrixIdentity();
  1995  
  1996      // Init internal matrices
  1997      RLGL.State.transform = rlMatrixIdentity();
  1998      RLGL.State.projection = rlMatrixIdentity();
  1999      RLGL.State.modelview = rlMatrixIdentity();
  2000      RLGL.State.currentMatrix = &RLGL.State.modelview;
  2001  #endif  // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
  2002  
  2003      // Initialize OpenGL default states
  2004      //----------------------------------------------------------
  2005      // Init state: Depth test
  2006      glDepthFunc(GL_LEQUAL);                                 // Type of depth testing to apply
  2007      glDisable(GL_DEPTH_TEST);                               // Disable depth testing for 2D (only used for 3D)
  2008  
  2009      // Init state: Blending mode
  2010      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);      // Color blending function (how colors are mixed)
  2011      glEnable(GL_BLEND);                                     // Enable color blending (required to work with transparencies)
  2012  
  2013      // Init state: Culling
  2014      // NOTE: All shapes/models triangles are drawn CCW
  2015      glCullFace(GL_BACK);                                    // Cull the back face (default)
  2016      glFrontFace(GL_CCW);                                    // Front face are defined counter clockwise (default)
  2017      glEnable(GL_CULL_FACE);                                 // Enable backface culling
  2018  
  2019      // Init state: Cubemap seamless
  2020  #if defined(GRAPHICS_API_OPENGL_33)
  2021      glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);                 // Seamless cubemaps (not supported on OpenGL ES 2.0)
  2022  #endif
  2023  
  2024  #if defined(GRAPHICS_API_OPENGL_11)
  2025      // Init state: Color hints (deprecated in OpenGL 3.0+)
  2026      glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);      // Improve quality of color and texture coordinate interpolation
  2027      glShadeModel(GL_SMOOTH);                                // Smooth shading between vertex (vertex colors interpolation)
  2028  #endif
  2029  
  2030  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  2031      // Store screen size into global variables
  2032      RLGL.State.framebufferWidth = width;
  2033      RLGL.State.framebufferHeight = height;
  2034  
  2035      TRACELOG(RL_LOG_INFO, "RLGL: Default OpenGL state initialized successfully");
  2036      //----------------------------------------------------------
  2037  #endif
  2038  
  2039      // Init state: Color/Depth buffers clear
  2040      glClearColor(0.0f, 0.0f, 0.0f, 1.0f);                   // Set clear color (black)
  2041      glClearDepth(1.0f);                                     // Set clear depth value (default)
  2042      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);     // Clear color and depth buffers (depth buffer required for 3D)
  2043  }
  2044  
  2045  // Vertex Buffer Object deinitialization (memory free)
  2046  void rlglClose(void)
  2047  {
  2048  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  2049      rlUnloadRenderBatch(RLGL.defaultBatch);
  2050  
  2051      rlUnloadShaderDefault();          // Unload default shader
  2052  
  2053      glDeleteTextures(1, &RLGL.State.defaultTextureId); // Unload default texture
  2054      TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Default texture unloaded successfully", RLGL.State.defaultTextureId);
  2055  #endif
  2056  }
  2057  
  2058  // Load OpenGL extensions
  2059  // NOTE: External loader function must be provided
  2060  void rlLoadExtensions(void *loader)
  2061  {
  2062  #if defined(GRAPHICS_API_OPENGL_33)     // Also defined for GRAPHICS_API_OPENGL_21
  2063      // NOTE: glad is generated and contains only required OpenGL 3.3 Core extensions (and lower versions)
  2064      if (gladLoadGL((GLADloadfunc)loader) == 0) TRACELOG(RL_LOG_WARNING, "GLAD: Cannot load OpenGL extensions");
  2065      else TRACELOG(RL_LOG_INFO, "GLAD: OpenGL extensions loaded successfully");
  2066  
  2067      // Get number of supported extensions
  2068      GLint numExt = 0;
  2069      glGetIntegerv(GL_NUM_EXTENSIONS, &numExt);
  2070      TRACELOG(RL_LOG_INFO, "GL: Supported extensions count: %i", numExt);
  2071  
  2072  #if defined(RLGL_SHOW_GL_DETAILS_INFO)
  2073      // Get supported extensions list
  2074      // WARNING: glGetStringi() not available on OpenGL 2.1
  2075      TRACELOG(RL_LOG_INFO, "GL: OpenGL extensions:");
  2076      for (int i = 0; i < numExt; i++) TRACELOG(RL_LOG_INFO, "    %s", glGetStringi(GL_EXTENSIONS, i));
  2077  #endif
  2078  
  2079  #if defined(GRAPHICS_API_OPENGL_21)
  2080      // Register supported extensions flags
  2081      // Optional OpenGL 2.1 extensions
  2082      RLGL.ExtSupported.vao = GLAD_GL_ARB_vertex_array_object;
  2083      RLGL.ExtSupported.instancing = (GLAD_GL_EXT_draw_instanced && GLAD_GL_ARB_instanced_arrays);
  2084      RLGL.ExtSupported.texNPOT = GLAD_GL_ARB_texture_non_power_of_two;
  2085      RLGL.ExtSupported.texFloat32 = GLAD_GL_ARB_texture_float;
  2086      RLGL.ExtSupported.texDepth = GLAD_GL_ARB_depth_texture;
  2087      RLGL.ExtSupported.maxDepthBits = 32;
  2088      RLGL.ExtSupported.texAnisoFilter = GLAD_GL_EXT_texture_filter_anisotropic;
  2089      RLGL.ExtSupported.texMirrorClamp = GLAD_GL_EXT_texture_mirror_clamp;
  2090  #else
  2091      // Register supported extensions flags
  2092      // OpenGL 3.3 extensions supported by default (core)
  2093      RLGL.ExtSupported.vao = true;
  2094      RLGL.ExtSupported.instancing = true;
  2095      RLGL.ExtSupported.texNPOT = true;
  2096      RLGL.ExtSupported.texFloat32 = true;
  2097      RLGL.ExtSupported.texDepth = true;
  2098      RLGL.ExtSupported.maxDepthBits = 32;
  2099      RLGL.ExtSupported.texAnisoFilter = true;
  2100      RLGL.ExtSupported.texMirrorClamp = true;
  2101  #endif
  2102  
  2103      // Optional OpenGL 3.3 extensions
  2104      RLGL.ExtSupported.texCompASTC = GLAD_GL_KHR_texture_compression_astc_hdr && GLAD_GL_KHR_texture_compression_astc_ldr;
  2105      RLGL.ExtSupported.texCompDXT = GLAD_GL_EXT_texture_compression_s3tc;  // Texture compression: DXT
  2106      RLGL.ExtSupported.texCompETC2 = GLAD_GL_ARB_ES3_compatibility;        // Texture compression: ETC2/EAC
  2107      #if defined(GRAPHICS_API_OPENGL_43)
  2108      RLGL.ExtSupported.computeShader = GLAD_GL_ARB_compute_shader;
  2109      RLGL.ExtSupported.ssbo = GLAD_GL_ARB_shader_storage_buffer_object;
  2110      #endif
  2111  
  2112  #endif  // GRAPHICS_API_OPENGL_33
  2113  
  2114  #if defined(GRAPHICS_API_OPENGL_ES2)
  2115      // Get supported extensions list
  2116      GLint numExt = 0;
  2117      const char **extList = RL_MALLOC(512*sizeof(const char *)); // Allocate 512 strings pointers (2 KB)
  2118      const char *extensions = (const char *)glGetString(GL_EXTENSIONS);  // One big const string
  2119  
  2120      // NOTE: We have to duplicate string because glGetString() returns a const string
  2121      int size = strlen(extensions) + 1;      // Get extensions string size in bytes
  2122      char *extensionsDup = (char *)RL_CALLOC(size, sizeof(char));
  2123      strcpy(extensionsDup, extensions);
  2124      extList[numExt] = extensionsDup;
  2125  
  2126      for (int i = 0; i < size; i++)
  2127      {
  2128          if (extensionsDup[i] == ' ')
  2129          {
  2130              extensionsDup[i] = '\0';
  2131              numExt++;
  2132              extList[numExt] = &extensionsDup[i + 1];
  2133          }
  2134      }
  2135  
  2136      TRACELOG(RL_LOG_INFO, "GL: Supported extensions count: %i", numExt);
  2137  
  2138  #if defined(RLGL_SHOW_GL_DETAILS_INFO)
  2139      TRACELOG(RL_LOG_INFO, "GL: OpenGL extensions:");
  2140      for (int i = 0; i < numExt; i++) TRACELOG(RL_LOG_INFO, "    %s", extList[i]);
  2141  #endif
  2142  
  2143      // Check required extensions
  2144      for (int i = 0; i < numExt; i++)
  2145      {
  2146          // Check VAO support
  2147          // NOTE: Only check on OpenGL ES, OpenGL 3.3 has VAO support as core feature
  2148          if (strcmp(extList[i], (const char *)"GL_OES_vertex_array_object") == 0)
  2149          {
  2150              // The extension is supported by our hardware and driver, try to get related functions pointers
  2151              // NOTE: emscripten does not support VAOs natively, it uses emulation and it reduces overall performance...
  2152              glGenVertexArrays = (PFNGLGENVERTEXARRAYSOESPROC)((rlglLoadProc)loader)("glGenVertexArraysOES");
  2153              glBindVertexArray = (PFNGLBINDVERTEXARRAYOESPROC)((rlglLoadProc)loader)("glBindVertexArrayOES");
  2154              glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSOESPROC)((rlglLoadProc)loader)("glDeleteVertexArraysOES");
  2155              //glIsVertexArray = (PFNGLISVERTEXARRAYOESPROC)loader("glIsVertexArrayOES");     // NOTE: Fails in WebGL, omitted
  2156  
  2157              if ((glGenVertexArrays != NULL) && (glBindVertexArray != NULL) && (glDeleteVertexArrays != NULL)) RLGL.ExtSupported.vao = true;
  2158          }
  2159  
  2160          // Check instanced rendering support
  2161          if (strcmp(extList[i], (const char *)"GL_ANGLE_instanced_arrays") == 0)         // Web ANGLE
  2162          {
  2163              glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedANGLE");
  2164              glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedANGLE");
  2165              glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorANGLE");
  2166  
  2167              if ((glDrawArraysInstanced != NULL) && (glDrawElementsInstanced != NULL) && (glVertexAttribDivisor != NULL)) RLGL.ExtSupported.instancing = true;
  2168          }
  2169          else
  2170          {
  2171              if ((strcmp(extList[i], (const char *)"GL_EXT_draw_instanced") == 0) &&     // Standard EXT
  2172                  (strcmp(extList[i], (const char *)"GL_EXT_instanced_arrays") == 0))
  2173              {
  2174                  glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawArraysInstancedEXT");
  2175                  glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)((rlglLoadProc)loader)("glDrawElementsInstancedEXT");
  2176                  glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOREXTPROC)((rlglLoadProc)loader)("glVertexAttribDivisorEXT");
  2177  
  2178                  if ((glDrawArraysInstanced != NULL) && (glDrawElementsInstanced != NULL) && (glVertexAttribDivisor != NULL)) RLGL.ExtSupported.instancing = true;
  2179              }
  2180          }
  2181  
  2182          // Check NPOT textures support
  2183          // NOTE: Only check on OpenGL ES, OpenGL 3.3 has NPOT textures full support as core feature
  2184          if (strcmp(extList[i], (const char *)"GL_OES_texture_npot") == 0) RLGL.ExtSupported.texNPOT = true;
  2185  
  2186          // Check texture float support
  2187          if (strcmp(extList[i], (const char *)"GL_OES_texture_float") == 0) RLGL.ExtSupported.texFloat32 = true;
  2188  
  2189          // Check depth texture support
  2190          if ((strcmp(extList[i], (const char *)"GL_OES_depth_texture") == 0) ||
  2191              (strcmp(extList[i], (const char *)"GL_WEBGL_depth_texture") == 0)) RLGL.ExtSupported.texDepth = true;
  2192  
  2193          if (strcmp(extList[i], (const char *)"GL_OES_depth24") == 0) RLGL.ExtSupported.maxDepthBits = 24;
  2194          if (strcmp(extList[i], (const char *)"GL_OES_depth32") == 0) RLGL.ExtSupported.maxDepthBits = 32;
  2195  
  2196          // Check texture compression support: DXT
  2197          if ((strcmp(extList[i], (const char *)"GL_EXT_texture_compression_s3tc") == 0) ||
  2198              (strcmp(extList[i], (const char *)"GL_WEBGL_compressed_texture_s3tc") == 0) ||
  2199              (strcmp(extList[i], (const char *)"GL_WEBKIT_WEBGL_compressed_texture_s3tc") == 0)) RLGL.ExtSupported.texCompDXT = true;
  2200  
  2201          // Check texture compression support: ETC1
  2202          if ((strcmp(extList[i], (const char *)"GL_OES_compressed_ETC1_RGB8_texture") == 0) ||
  2203              (strcmp(extList[i], (const char *)"GL_WEBGL_compressed_texture_etc1") == 0)) RLGL.ExtSupported.texCompETC1 = true;
  2204  
  2205          // Check texture compression support: ETC2/EAC
  2206          if (strcmp(extList[i], (const char *)"GL_ARB_ES3_compatibility") == 0) RLGL.ExtSupported.texCompETC2 = true;
  2207  
  2208          // Check texture compression support: PVR
  2209          if (strcmp(extList[i], (const char *)"GL_IMG_texture_compression_pvrtc") == 0) RLGL.ExtSupported.texCompPVRT = true;
  2210  
  2211          // Check texture compression support: ASTC
  2212          if (strcmp(extList[i], (const char *)"GL_KHR_texture_compression_astc_hdr") == 0) RLGL.ExtSupported.texCompASTC = true;
  2213  
  2214          // Check anisotropic texture filter support
  2215          if (strcmp(extList[i], (const char *)"GL_EXT_texture_filter_anisotropic") == 0) RLGL.ExtSupported.texAnisoFilter = true;
  2216  
  2217          // Check clamp mirror wrap mode support
  2218          if (strcmp(extList[i], (const char *)"GL_EXT_texture_mirror_clamp") == 0) RLGL.ExtSupported.texMirrorClamp = true;
  2219      }
  2220  
  2221      // Free extensions pointers
  2222      RL_FREE(extList);
  2223      RL_FREE(extensionsDup);    // Duplicated string must be deallocated
  2224  #endif  // GRAPHICS_API_OPENGL_ES2
  2225  
  2226      // Check OpenGL information and capabilities
  2227      //------------------------------------------------------------------------------
  2228      // Show current OpenGL and GLSL version
  2229      TRACELOG(RL_LOG_INFO, "GL: OpenGL device information:");
  2230      TRACELOG(RL_LOG_INFO, "    > Vendor:   %s", glGetString(GL_VENDOR));
  2231      TRACELOG(RL_LOG_INFO, "    > Renderer: %s", glGetString(GL_RENDERER));
  2232      TRACELOG(RL_LOG_INFO, "    > Version:  %s", glGetString(GL_VERSION));
  2233      TRACELOG(RL_LOG_INFO, "    > GLSL:     %s", glGetString(GL_SHADING_LANGUAGE_VERSION));
  2234  
  2235  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  2236      // NOTE: Anisotropy levels capability is an extension
  2237      #ifndef GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT
  2238          #define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
  2239      #endif
  2240      glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &RLGL.ExtSupported.maxAnisotropyLevel);
  2241  
  2242  #if defined(RLGL_SHOW_GL_DETAILS_INFO)
  2243      // Show some OpenGL GPU capabilities
  2244      TRACELOG(RL_LOG_INFO, "GL: OpenGL capabilities:");
  2245      GLint capability = 0;
  2246      glGetIntegerv(GL_MAX_TEXTURE_SIZE, &capability);
  2247      TRACELOG(RL_LOG_INFO, "    GL_MAX_TEXTURE_SIZE: %i", capability);
  2248      glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &capability);
  2249      TRACELOG(RL_LOG_INFO, "    GL_MAX_CUBE_MAP_TEXTURE_SIZE: %i", capability);
  2250      glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &capability);
  2251      TRACELOG(RL_LOG_INFO, "    GL_MAX_TEXTURE_IMAGE_UNITS: %i", capability);
  2252      glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &capability);
  2253      TRACELOG(RL_LOG_INFO, "    GL_MAX_VERTEX_ATTRIBS: %i", capability);
  2254      #if !defined(GRAPHICS_API_OPENGL_ES2)
  2255      glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &capability);
  2256      TRACELOG(RL_LOG_INFO, "    GL_MAX_UNIFORM_BLOCK_SIZE: %i", capability);
  2257      glGetIntegerv(GL_MAX_DRAW_BUFFERS, &capability);
  2258      TRACELOG(RL_LOG_INFO, "    GL_MAX_DRAW_BUFFERS: %i", capability);
  2259      if (RLGL.ExtSupported.texAnisoFilter) TRACELOG(RL_LOG_INFO, "    GL_MAX_TEXTURE_MAX_ANISOTROPY: %.0f", RLGL.ExtSupported.maxAnisotropyLevel);
  2260      #endif
  2261      glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &capability);
  2262      TRACELOG(RL_LOG_INFO, "    GL_NUM_COMPRESSED_TEXTURE_FORMATS: %i", capability);
  2263      GLint *compFormats = (GLint *)RL_CALLOC(capability, sizeof(GLint));
  2264      glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, compFormats);
  2265      for (int i = 0; i < capability; i++) TRACELOG(RL_LOG_INFO, "        %s", rlGetCompressedFormatName(compFormats[i]));
  2266      RL_FREE(compFormats);
  2267  
  2268  #if defined(GRAPHICS_API_OPENGL_43)
  2269      glGetIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &capability);
  2270      TRACELOG(RL_LOG_INFO, "    GL_MAX_VERTEX_ATTRIB_BINDINGS: %i", capability);
  2271      glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, &capability);
  2272      TRACELOG(RL_LOG_INFO, "    GL_MAX_UNIFORM_LOCATIONS: %i", capability);
  2273  #endif  // GRAPHICS_API_OPENGL_43
  2274  #else   // RLGL_SHOW_GL_DETAILS_INFO
  2275  
  2276      // Show some basic info about GL supported features
  2277      if (RLGL.ExtSupported.vao) TRACELOG(RL_LOG_INFO, "GL: VAO extension detected, VAO functions loaded successfully");
  2278      else TRACELOG(RL_LOG_WARNING, "GL: VAO extension not found, VAO not supported");
  2279      if (RLGL.ExtSupported.texNPOT) TRACELOG(RL_LOG_INFO, "GL: NPOT textures extension detected, full NPOT textures supported");
  2280      else TRACELOG(RL_LOG_WARNING, "GL: NPOT textures extension not found, limited NPOT support (no-mipmaps, no-repeat)");
  2281      if (RLGL.ExtSupported.texCompDXT) TRACELOG(RL_LOG_INFO, "GL: DXT compressed textures supported");
  2282      if (RLGL.ExtSupported.texCompETC1) TRACELOG(RL_LOG_INFO, "GL: ETC1 compressed textures supported");
  2283      if (RLGL.ExtSupported.texCompETC2) TRACELOG(RL_LOG_INFO, "GL: ETC2/EAC compressed textures supported");
  2284      if (RLGL.ExtSupported.texCompPVRT) TRACELOG(RL_LOG_INFO, "GL: PVRT compressed textures supported");
  2285      if (RLGL.ExtSupported.texCompASTC) TRACELOG(RL_LOG_INFO, "GL: ASTC compressed textures supported");
  2286      if (RLGL.ExtSupported.computeShader) TRACELOG(RL_LOG_INFO, "GL: Compute shaders supported");
  2287      if (RLGL.ExtSupported.ssbo) TRACELOG(RL_LOG_INFO, "GL: Shader storage buffer objects supported");
  2288  #endif  // RLGL_SHOW_GL_DETAILS_INFO
  2289  
  2290  #endif  // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
  2291  }
  2292  
  2293  // Get current OpenGL version
  2294  int rlGetVersion(void)
  2295  {
  2296      int glVersion = 0;
  2297  #if defined(GRAPHICS_API_OPENGL_11)
  2298      glVersion = RL_OPENGL_11;
  2299  #endif
  2300  #if defined(GRAPHICS_API_OPENGL_21)
  2301      glVersion = RL_OPENGL_21;
  2302  #elif defined(GRAPHICS_API_OPENGL_33)
  2303      glVersion = RL_OPENGL_33;
  2304  #endif
  2305  #if defined(GRAPHICS_API_OPENGL_43)
  2306      glVersion = RL_OPENGL_43;
  2307  #endif
  2308  #if defined(GRAPHICS_API_OPENGL_ES2)
  2309      glVersion = RL_OPENGL_ES_20;
  2310  #endif
  2311      return glVersion;
  2312  }
  2313  
  2314  // Set current framebuffer width
  2315  void rlSetFramebufferWidth(int width)
  2316  {
  2317  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  2318      RLGL.State.framebufferWidth = width;
  2319  #endif
  2320  }
  2321  
  2322  // Set current framebuffer height
  2323  void rlSetFramebufferHeight(int height)
  2324  {
  2325  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  2326      RLGL.State.framebufferHeight = height;
  2327  #endif
  2328  }
  2329  
  2330  // Get default framebuffer width
  2331  int rlGetFramebufferWidth(void)
  2332  {
  2333      int width = 0;
  2334  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  2335      width = RLGL.State.framebufferWidth;
  2336  #endif
  2337      return width;
  2338  }
  2339  
  2340  // Get default framebuffer height
  2341  int rlGetFramebufferHeight(void)
  2342  {
  2343      int height = 0;
  2344  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  2345      height = RLGL.State.framebufferHeight;
  2346  #endif
  2347      return height;
  2348  }
  2349  
  2350  // Get default internal texture (white texture)
  2351  // NOTE: Default texture is a 1x1 pixel UNCOMPRESSED_R8G8B8A8
  2352  unsigned int rlGetTextureIdDefault(void)
  2353  {
  2354      unsigned int id = 0;
  2355  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  2356      id = RLGL.State.defaultTextureId;
  2357  #endif
  2358      return id;
  2359  }
  2360  
  2361  // Get default shader id
  2362  unsigned int rlGetShaderIdDefault(void)
  2363  {
  2364      unsigned int id = 0;
  2365  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  2366      id = RLGL.State.defaultShaderId;
  2367  #endif
  2368      return id;
  2369  }
  2370  
  2371  // Get default shader locs
  2372  int *rlGetShaderLocsDefault(void)
  2373  {
  2374      int *locs = NULL;
  2375  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  2376      locs = RLGL.State.defaultShaderLocs;
  2377  #endif
  2378      return locs;
  2379  }
  2380  
  2381  // Render batch management
  2382  //------------------------------------------------------------------------------------------------
  2383  // Load render batch
  2384  rlRenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements)
  2385  {
  2386      rlRenderBatch batch = { 0 };
  2387  
  2388  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  2389      // Initialize CPU (RAM) vertex buffers (position, texcoord, color data and indexes)
  2390      //--------------------------------------------------------------------------------------------
  2391      batch.vertexBuffer = (rlVertexBuffer *)RL_MALLOC(numBuffers*sizeof(rlVertexBuffer));
  2392  
  2393      for (int i = 0; i < numBuffers; i++)
  2394      {
  2395          batch.vertexBuffer[i].elementCount = bufferElements;
  2396  
  2397          batch.vertexBuffer[i].vertices = (float *)RL_MALLOC(bufferElements*3*4*sizeof(float));        // 3 float by vertex, 4 vertex by quad
  2398          batch.vertexBuffer[i].texcoords = (float *)RL_MALLOC(bufferElements*2*4*sizeof(float));       // 2 float by texcoord, 4 texcoord by quad
  2399          batch.vertexBuffer[i].colors = (unsigned char *)RL_MALLOC(bufferElements*4*4*sizeof(unsigned char));   // 4 float by color, 4 colors by quad
  2400  #if defined(GRAPHICS_API_OPENGL_33)
  2401          batch.vertexBuffer[i].indices = (unsigned int *)RL_MALLOC(bufferElements*6*sizeof(unsigned int));      // 6 int by quad (indices)
  2402  #endif
  2403  #if defined(GRAPHICS_API_OPENGL_ES2)
  2404          batch.vertexBuffer[i].indices = (unsigned short *)RL_MALLOC(bufferElements*6*sizeof(unsigned short));  // 6 int by quad (indices)
  2405  #endif
  2406  
  2407          for (int j = 0; j < (3*4*bufferElements); j++) batch.vertexBuffer[i].vertices[j] = 0.0f;
  2408          for (int j = 0; j < (2*4*bufferElements); j++) batch.vertexBuffer[i].texcoords[j] = 0.0f;
  2409          for (int j = 0; j < (4*4*bufferElements); j++) batch.vertexBuffer[i].colors[j] = 0;
  2410  
  2411          int k = 0;
  2412  
  2413          // Indices can be initialized right now
  2414          for (int j = 0; j < (6*bufferElements); j += 6)
  2415          {
  2416              batch.vertexBuffer[i].indices[j] = 4*k;
  2417              batch.vertexBuffer[i].indices[j + 1] = 4*k + 1;
  2418              batch.vertexBuffer[i].indices[j + 2] = 4*k + 2;
  2419              batch.vertexBuffer[i].indices[j + 3] = 4*k;
  2420              batch.vertexBuffer[i].indices[j + 4] = 4*k + 2;
  2421              batch.vertexBuffer[i].indices[j + 5] = 4*k + 3;
  2422  
  2423              k++;
  2424          }
  2425  
  2426          RLGL.State.vertexCounter = 0;
  2427      }
  2428  
  2429      TRACELOG(RL_LOG_INFO, "RLGL: Render batch vertex buffers loaded successfully in RAM (CPU)");
  2430      //--------------------------------------------------------------------------------------------
  2431  
  2432      // Upload to GPU (VRAM) vertex data and initialize VAOs/VBOs
  2433      //--------------------------------------------------------------------------------------------
  2434      for (int i = 0; i < numBuffers; i++)
  2435      {
  2436          if (RLGL.ExtSupported.vao)
  2437          {
  2438              // Initialize Quads VAO
  2439              glGenVertexArrays(1, &batch.vertexBuffer[i].vaoId);
  2440              glBindVertexArray(batch.vertexBuffer[i].vaoId);
  2441          }
  2442  
  2443          // Quads - Vertex buffers binding and attributes enable
  2444          // Vertex position buffer (shader-location = 0)
  2445          glGenBuffers(1, &batch.vertexBuffer[i].vboId[0]);
  2446          glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[0]);
  2447          glBufferData(GL_ARRAY_BUFFER, bufferElements*3*4*sizeof(float), batch.vertexBuffer[i].vertices, GL_DYNAMIC_DRAW);
  2448          glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_POSITION]);
  2449          glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0);
  2450  
  2451          // Vertex texcoord buffer (shader-location = 1)
  2452          glGenBuffers(1, &batch.vertexBuffer[i].vboId[1]);
  2453          glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[1]);
  2454          glBufferData(GL_ARRAY_BUFFER, bufferElements*2*4*sizeof(float), batch.vertexBuffer[i].texcoords, GL_DYNAMIC_DRAW);
  2455          glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_TEXCOORD01]);
  2456          glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0);
  2457  
  2458          // Vertex color buffer (shader-location = 3)
  2459          glGenBuffers(1, &batch.vertexBuffer[i].vboId[2]);
  2460          glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[2]);
  2461          glBufferData(GL_ARRAY_BUFFER, bufferElements*4*4*sizeof(unsigned char), batch.vertexBuffer[i].colors, GL_DYNAMIC_DRAW);
  2462          glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_COLOR]);
  2463          glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
  2464  
  2465          // Fill index buffer
  2466          glGenBuffers(1, &batch.vertexBuffer[i].vboId[3]);
  2467          glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[3]);
  2468  #if defined(GRAPHICS_API_OPENGL_33)
  2469          glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufferElements*6*sizeof(int), batch.vertexBuffer[i].indices, GL_STATIC_DRAW);
  2470  #endif
  2471  #if defined(GRAPHICS_API_OPENGL_ES2)
  2472          glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufferElements*6*sizeof(short), batch.vertexBuffer[i].indices, GL_STATIC_DRAW);
  2473  #endif
  2474      }
  2475  
  2476      TRACELOG(RL_LOG_INFO, "RLGL: Render batch vertex buffers loaded successfully in VRAM (GPU)");
  2477  
  2478      // Unbind the current VAO
  2479      if (RLGL.ExtSupported.vao) glBindVertexArray(0);
  2480      //--------------------------------------------------------------------------------------------
  2481  
  2482      // Init draw calls tracking system
  2483      //--------------------------------------------------------------------------------------------
  2484      batch.draws = (rlDrawCall *)RL_MALLOC(RL_DEFAULT_BATCH_DRAWCALLS*sizeof(rlDrawCall));
  2485  
  2486      for (int i = 0; i < RL_DEFAULT_BATCH_DRAWCALLS; i++)
  2487      {
  2488          batch.draws[i].mode = RL_QUADS;
  2489          batch.draws[i].vertexCount = 0;
  2490          batch.draws[i].vertexAlignment = 0;
  2491          //batch.draws[i].vaoId = 0;
  2492          //batch.draws[i].shaderId = 0;
  2493          batch.draws[i].textureId = RLGL.State.defaultTextureId;
  2494          //batch.draws[i].RLGL.State.projection = rlMatrixIdentity();
  2495          //batch.draws[i].RLGL.State.modelview = rlMatrixIdentity();
  2496      }
  2497  
  2498      batch.bufferCount = numBuffers;    // Record buffer count
  2499      batch.drawCounter = 1;             // Reset draws counter
  2500      batch.currentDepth = -1.0f;         // Reset depth value
  2501      //--------------------------------------------------------------------------------------------
  2502  #endif
  2503  
  2504      return batch;
  2505  }
  2506  
  2507  // Unload default internal buffers vertex data from CPU and GPU
  2508  void rlUnloadRenderBatch(rlRenderBatch batch)
  2509  {
  2510  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  2511      // Unbind everything
  2512      glBindBuffer(GL_ARRAY_BUFFER, 0);
  2513      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  2514  
  2515      // Unload all vertex buffers data
  2516      for (int i = 0; i < batch.bufferCount; i++)
  2517      {
  2518          // Unbind VAO attribs data
  2519          if (RLGL.ExtSupported.vao)
  2520          {
  2521              glBindVertexArray(batch.vertexBuffer[i].vaoId);
  2522              glDisableVertexAttribArray(0);
  2523              glDisableVertexAttribArray(1);
  2524              glDisableVertexAttribArray(2);
  2525              glDisableVertexAttribArray(3);
  2526              glBindVertexArray(0);
  2527          }
  2528  
  2529          // Delete VBOs from GPU (VRAM)
  2530          glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[0]);
  2531          glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[1]);
  2532          glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[2]);
  2533          glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[3]);
  2534  
  2535          // Delete VAOs from GPU (VRAM)
  2536          if (RLGL.ExtSupported.vao) glDeleteVertexArrays(1, &batch.vertexBuffer[i].vaoId);
  2537  
  2538          // Free vertex arrays memory from CPU (RAM)
  2539          RL_FREE(batch.vertexBuffer[i].vertices);
  2540          RL_FREE(batch.vertexBuffer[i].texcoords);
  2541          RL_FREE(batch.vertexBuffer[i].colors);
  2542          RL_FREE(batch.vertexBuffer[i].indices);
  2543      }
  2544  
  2545      // Unload arrays
  2546      RL_FREE(batch.vertexBuffer);
  2547      RL_FREE(batch.draws);
  2548  #endif
  2549  }
  2550  
  2551  // Draw render batch
  2552  // NOTE: We require a pointer to reset batch and increase current buffer (multi-buffer)
  2553  void rlDrawRenderBatch(rlRenderBatch *batch)
  2554  {
  2555  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  2556      // Update batch vertex buffers
  2557      //------------------------------------------------------------------------------------------------------------
  2558      // NOTE: If there is not vertex data, buffers doesn't need to be updated (vertexCount > 0)
  2559      // TODO: If no data changed on the CPU arrays --> No need to re-update GPU arrays (change flag required)
  2560      if (RLGL.State.vertexCounter > 0)
  2561      {
  2562          // Activate elements VAO
  2563          if (RLGL.ExtSupported.vao) glBindVertexArray(batch->vertexBuffer[batch->currentBuffer].vaoId);
  2564  
  2565          // Vertex positions buffer
  2566          glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[0]);
  2567          glBufferSubData(GL_ARRAY_BUFFER, 0, RLGL.State.vertexCounter*3*sizeof(float), batch->vertexBuffer[batch->currentBuffer].vertices);
  2568          //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*batch->vertexBuffer[batch->currentBuffer].elementCount, batch->vertexBuffer[batch->currentBuffer].vertices, GL_DYNAMIC_DRAW);  // Update all buffer
  2569  
  2570          // Texture coordinates buffer
  2571          glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[1]);
  2572          glBufferSubData(GL_ARRAY_BUFFER, 0, RLGL.State.vertexCounter*2*sizeof(float), batch->vertexBuffer[batch->currentBuffer].texcoords);
  2573          //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*batch->vertexBuffer[batch->currentBuffer].elementCount, batch->vertexBuffer[batch->currentBuffer].texcoords, GL_DYNAMIC_DRAW); // Update all buffer
  2574  
  2575          // Colors buffer
  2576          glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[2]);
  2577          glBufferSubData(GL_ARRAY_BUFFER, 0, RLGL.State.vertexCounter*4*sizeof(unsigned char), batch->vertexBuffer[batch->currentBuffer].colors);
  2578          //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*4*batch->vertexBuffer[batch->currentBuffer].elementCount, batch->vertexBuffer[batch->currentBuffer].colors, GL_DYNAMIC_DRAW);    // Update all buffer
  2579  
  2580          // NOTE: glMapBuffer() causes sync issue.
  2581          // If GPU is working with this buffer, glMapBuffer() will wait(stall) until GPU to finish its job.
  2582          // To avoid waiting (idle), you can call first glBufferData() with NULL pointer before glMapBuffer().
  2583          // If you do that, the previous data in PBO will be discarded and glMapBuffer() returns a new
  2584          // allocated pointer immediately even if GPU is still working with the previous data.
  2585  
  2586          // Another option: map the buffer object into client's memory
  2587          // Probably this code could be moved somewhere else...
  2588          // batch->vertexBuffer[batch->currentBuffer].vertices = (float *)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);
  2589          // if (batch->vertexBuffer[batch->currentBuffer].vertices)
  2590          // {
  2591              // Update vertex data
  2592          // }
  2593          // glUnmapBuffer(GL_ARRAY_BUFFER);
  2594  
  2595          // Unbind the current VAO
  2596          if (RLGL.ExtSupported.vao) glBindVertexArray(0);
  2597      }
  2598      //------------------------------------------------------------------------------------------------------------
  2599  
  2600      // Draw batch vertex buffers (considering VR stereo if required)
  2601      //------------------------------------------------------------------------------------------------------------
  2602      Matrix matProjection = RLGL.State.projection;
  2603      Matrix matModelView = RLGL.State.modelview;
  2604  
  2605      int eyeCount = 1;
  2606      if (RLGL.State.stereoRender) eyeCount = 2;
  2607  
  2608      for (int eye = 0; eye < eyeCount; eye++)
  2609      {
  2610          if (eyeCount == 2)
  2611          {
  2612              // Setup current eye viewport (half screen width)
  2613              rlViewport(eye*RLGL.State.framebufferWidth/2, 0, RLGL.State.framebufferWidth/2, RLGL.State.framebufferHeight);
  2614  
  2615              // Set current eye view offset to modelview matrix
  2616              rlSetMatrixModelview(rlMatrixMultiply(matModelView, RLGL.State.viewOffsetStereo[eye]));
  2617              // Set current eye projection matrix
  2618              rlSetMatrixProjection(RLGL.State.projectionStereo[eye]);
  2619          }
  2620  
  2621          // Draw buffers
  2622          if (RLGL.State.vertexCounter > 0)
  2623          {
  2624              // Set current shader and upload current MVP matrix
  2625              glUseProgram(RLGL.State.currentShaderId);
  2626  
  2627              // Create modelview-projection matrix and upload to shader
  2628              Matrix matMVP = rlMatrixMultiply(RLGL.State.modelview, RLGL.State.projection);
  2629              float matMVPfloat[16] = {
  2630                  matMVP.m0, matMVP.m1, matMVP.m2, matMVP.m3,
  2631                  matMVP.m4, matMVP.m5, matMVP.m6, matMVP.m7,
  2632                  matMVP.m8, matMVP.m9, matMVP.m10, matMVP.m11,
  2633                  matMVP.m12, matMVP.m13, matMVP.m14, matMVP.m15
  2634              };
  2635              glUniformMatrix4fv(RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_MVP], 1, false, matMVPfloat);
  2636  
  2637              if (RLGL.ExtSupported.vao) glBindVertexArray(batch->vertexBuffer[batch->currentBuffer].vaoId);
  2638              else
  2639              {
  2640                  // Bind vertex attrib: position (shader-location = 0)
  2641                  glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[0]);
  2642                  glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0);
  2643                  glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_POSITION]);
  2644  
  2645                  // Bind vertex attrib: texcoord (shader-location = 1)
  2646                  glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[1]);
  2647                  glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0);
  2648                  glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_TEXCOORD01]);
  2649  
  2650                  // Bind vertex attrib: color (shader-location = 3)
  2651                  glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[2]);
  2652                  glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
  2653                  glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_COLOR]);
  2654  
  2655                  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[3]);
  2656              }
  2657  
  2658              // Setup some default shader values
  2659              glUniform4f(RLGL.State.currentShaderLocs[RL_SHADER_LOC_COLOR_DIFFUSE], 1.0f, 1.0f, 1.0f, 1.0f);
  2660              glUniform1i(RLGL.State.currentShaderLocs[RL_SHADER_LOC_MAP_DIFFUSE], 0);  // Active default sampler2D: texture0
  2661  
  2662              // Activate additional sampler textures
  2663              // Those additional textures will be common for all draw calls of the batch
  2664              for (int i = 0; i < RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS; i++)
  2665              {
  2666                  if (RLGL.State.activeTextureId[i] > 0)
  2667                  {
  2668                      glActiveTexture(GL_TEXTURE0 + 1 + i);
  2669                      glBindTexture(GL_TEXTURE_2D, RLGL.State.activeTextureId[i]);
  2670                  }
  2671              }
  2672  
  2673              // Activate default sampler2D texture0 (one texture is always active for default batch shader)
  2674              // NOTE: Batch system accumulates calls by texture0 changes, additional textures are enabled for all the draw calls
  2675              glActiveTexture(GL_TEXTURE0);
  2676  
  2677              for (int i = 0, vertexOffset = 0; i < batch->drawCounter; i++)
  2678              {
  2679                  // Bind current draw call texture, activated as GL_TEXTURE0 and binded to sampler2D texture0 by default
  2680                  glBindTexture(GL_TEXTURE_2D, batch->draws[i].textureId);
  2681  
  2682                  if ((batch->draws[i].mode == RL_LINES) || (batch->draws[i].mode == RL_TRIANGLES)) glDrawArrays(batch->draws[i].mode, vertexOffset, batch->draws[i].vertexCount);
  2683                  else
  2684                  {
  2685  #if defined(GRAPHICS_API_OPENGL_33)
  2686                      // We need to define the number of indices to be processed: elementCount*6
  2687                      // NOTE: The final parameter tells the GPU the offset in bytes from the
  2688                      // start of the index buffer to the location of the first index to process
  2689                      glDrawElements(GL_TRIANGLES, batch->draws[i].vertexCount/4*6, GL_UNSIGNED_INT, (GLvoid *)(vertexOffset/4*6*sizeof(GLuint)));
  2690  #endif
  2691  #if defined(GRAPHICS_API_OPENGL_ES2)
  2692                      glDrawElements(GL_TRIANGLES, batch->draws[i].vertexCount/4*6, GL_UNSIGNED_SHORT, (GLvoid *)(vertexOffset/4*6*sizeof(GLushort)));
  2693  #endif
  2694                  }
  2695  
  2696                  vertexOffset += (batch->draws[i].vertexCount + batch->draws[i].vertexAlignment);
  2697              }
  2698  
  2699              if (!RLGL.ExtSupported.vao)
  2700              {
  2701                  glBindBuffer(GL_ARRAY_BUFFER, 0);
  2702                  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  2703              }
  2704  
  2705              glBindTexture(GL_TEXTURE_2D, 0);    // Unbind textures
  2706          }
  2707  
  2708          if (RLGL.ExtSupported.vao) glBindVertexArray(0); // Unbind VAO
  2709  
  2710          glUseProgram(0);    // Unbind shader program
  2711      }
  2712  
  2713      // Restore viewport to default measures
  2714      if (eyeCount == 2) rlViewport(0, 0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight);
  2715      //------------------------------------------------------------------------------------------------------------
  2716  
  2717      // Reset batch buffers
  2718      //------------------------------------------------------------------------------------------------------------
  2719      // Reset vertex counter for next frame
  2720      RLGL.State.vertexCounter = 0;
  2721  
  2722      // Reset depth for next draw
  2723      batch->currentDepth = -1.0f;
  2724  
  2725      // Restore projection/modelview matrices
  2726      RLGL.State.projection = matProjection;
  2727      RLGL.State.modelview = matModelView;
  2728  
  2729      // Reset RLGL.currentBatch->draws array
  2730      for (int i = 0; i < RL_DEFAULT_BATCH_DRAWCALLS; i++)
  2731      {
  2732          batch->draws[i].mode = RL_QUADS;
  2733          batch->draws[i].vertexCount = 0;
  2734          batch->draws[i].textureId = RLGL.State.defaultTextureId;
  2735      }
  2736  
  2737      // Reset active texture units for next batch
  2738      for (int i = 0; i < RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS; i++) RLGL.State.activeTextureId[i] = 0;
  2739  
  2740      // Reset draws counter to one draw for the batch
  2741      batch->drawCounter = 1;
  2742      //------------------------------------------------------------------------------------------------------------
  2743  
  2744      // Change to next buffer in the list (in case of multi-buffering)
  2745      batch->currentBuffer++;
  2746      if (batch->currentBuffer >= batch->bufferCount) batch->currentBuffer = 0;
  2747  #endif
  2748  }
  2749  
  2750  // Set the active render batch for rlgl
  2751  void rlSetRenderBatchActive(rlRenderBatch *batch)
  2752  {
  2753  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  2754      rlDrawRenderBatch(RLGL.currentBatch);
  2755  
  2756      if (batch != NULL) RLGL.currentBatch = batch;
  2757      else RLGL.currentBatch = &RLGL.defaultBatch;
  2758  #endif
  2759  }
  2760  
  2761  // Update and draw internal render batch
  2762  void rlDrawRenderBatchActive(void)
  2763  {
  2764  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  2765      rlDrawRenderBatch(RLGL.currentBatch);    // NOTE: Stereo rendering is checked inside
  2766  #endif
  2767  }
  2768  
  2769  // Check internal buffer overflow for a given number of vertex
  2770  // and force a rlRenderBatch draw call if required
  2771  bool rlCheckRenderBatchLimit(int vCount)
  2772  {
  2773      bool overflow = false;
  2774  
  2775  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  2776      if ((RLGL.State.vertexCounter + vCount) >=
  2777          (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementCount*4))
  2778      {
  2779          overflow = true;
  2780  
  2781          // Store current primitive drawing mode and texture id
  2782          int currentMode = RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode;
  2783          int currentTexture = RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].textureId;
  2784  
  2785          rlDrawRenderBatch(RLGL.currentBatch);    // NOTE: Stereo rendering is checked inside
  2786  
  2787          // Restore state of last batch so we can continue adding vertices
  2788          RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode = currentMode;
  2789          RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].textureId = currentTexture;
  2790      }
  2791  #endif
  2792  
  2793      return overflow;
  2794  }
  2795  
  2796  // Textures data management
  2797  //-----------------------------------------------------------------------------------------
  2798  // Convert image data to OpenGL texture (returns OpenGL valid Id)
  2799  unsigned int rlLoadTexture(const void *data, int width, int height, int format, int mipmapCount)
  2800  {
  2801      unsigned int id = 0;
  2802  
  2803      glBindTexture(GL_TEXTURE_2D, 0);    // Free any old binding
  2804  
  2805      // Check texture format support by OpenGL 1.1 (compressed textures not supported)
  2806  #if defined(GRAPHICS_API_OPENGL_11)
  2807      if (format >= RL_PIXELFORMAT_COMPRESSED_DXT1_RGB)
  2808      {
  2809          TRACELOG(RL_LOG_WARNING, "GL: OpenGL 1.1 does not support GPU compressed texture formats");
  2810          return id;
  2811      }
  2812  #else
  2813      if ((!RLGL.ExtSupported.texCompDXT) && ((format == RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) || (format == RL_PIXELFORMAT_COMPRESSED_DXT1_RGBA) ||
  2814          (format == RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA) || (format == RL_PIXELFORMAT_COMPRESSED_DXT5_RGBA)))
  2815      {
  2816          TRACELOG(RL_LOG_WARNING, "GL: DXT compressed texture format not supported");
  2817          return id;
  2818      }
  2819  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  2820      if ((!RLGL.ExtSupported.texCompETC1) && (format == RL_PIXELFORMAT_COMPRESSED_ETC1_RGB))
  2821      {
  2822          TRACELOG(RL_LOG_WARNING, "GL: ETC1 compressed texture format not supported");
  2823          return id;
  2824      }
  2825  
  2826      if ((!RLGL.ExtSupported.texCompETC2) && ((format == RL_PIXELFORMAT_COMPRESSED_ETC2_RGB) || (format == RL_PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA)))
  2827      {
  2828          TRACELOG(RL_LOG_WARNING, "GL: ETC2 compressed texture format not supported");
  2829          return id;
  2830      }
  2831  
  2832      if ((!RLGL.ExtSupported.texCompPVRT) && ((format == RL_PIXELFORMAT_COMPRESSED_PVRT_RGB) || (format == RL_PIXELFORMAT_COMPRESSED_PVRT_RGBA)))
  2833      {
  2834          TRACELOG(RL_LOG_WARNING, "GL: PVRT compressed texture format not supported");
  2835          return id;
  2836      }
  2837  
  2838      if ((!RLGL.ExtSupported.texCompASTC) && ((format == RL_PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA) || (format == RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA)))
  2839      {
  2840          TRACELOG(RL_LOG_WARNING, "GL: ASTC compressed texture format not supported");
  2841          return id;
  2842      }
  2843  #endif
  2844  #endif  // GRAPHICS_API_OPENGL_11
  2845  
  2846      glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  2847  
  2848      glGenTextures(1, &id);              // Generate texture id
  2849  
  2850      glBindTexture(GL_TEXTURE_2D, id);
  2851  
  2852      int mipWidth = width;
  2853      int mipHeight = height;
  2854      int mipOffset = 0;          // Mipmap data offset
  2855  
  2856      // Load the different mipmap levels
  2857      for (int i = 0; i < mipmapCount; i++)
  2858      {
  2859          unsigned int mipSize = rlGetPixelDataSize(mipWidth, mipHeight, format);
  2860  
  2861          unsigned int glInternalFormat, glFormat, glType;
  2862          rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType);
  2863  
  2864          TRACELOGD("TEXTURE: Load mipmap level %i (%i x %i), size: %i, offset: %i", i, mipWidth, mipHeight, mipSize, mipOffset);
  2865  
  2866          if (glInternalFormat != -1)
  2867          {
  2868              if (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) glTexImage2D(GL_TEXTURE_2D, i, glInternalFormat, mipWidth, mipHeight, 0, glFormat, glType, (unsigned char *)data + mipOffset);
  2869  #if !defined(GRAPHICS_API_OPENGL_11)
  2870              else glCompressedTexImage2D(GL_TEXTURE_2D, i, glInternalFormat, mipWidth, mipHeight, 0, mipSize, (unsigned char *)data + mipOffset);
  2871  #endif
  2872  
  2873  #if defined(GRAPHICS_API_OPENGL_33)
  2874              if (format == RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE)
  2875              {
  2876                  GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_ONE };
  2877                  glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
  2878              }
  2879              else if (format == RL_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA)
  2880              {
  2881  #if defined(GRAPHICS_API_OPENGL_21)
  2882                  GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_ALPHA };
  2883  #elif defined(GRAPHICS_API_OPENGL_33)
  2884                  GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_GREEN };
  2885  #endif
  2886                  glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
  2887              }
  2888  #endif
  2889          }
  2890  
  2891          mipWidth /= 2;
  2892          mipHeight /= 2;
  2893          mipOffset += mipSize;
  2894  
  2895          // Security check for NPOT textures
  2896          if (mipWidth < 1) mipWidth = 1;
  2897          if (mipHeight < 1) mipHeight = 1;
  2898      }
  2899  
  2900      // Texture parameters configuration
  2901      // NOTE: glTexParameteri does NOT affect texture uploading, just the way it's used
  2902  #if defined(GRAPHICS_API_OPENGL_ES2)
  2903      // NOTE: OpenGL ES 2.0 with no GL_OES_texture_npot support (i.e. WebGL) has limited NPOT support, so CLAMP_TO_EDGE must be used
  2904      if (RLGL.ExtSupported.texNPOT)
  2905      {
  2906          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);       // Set texture to repeat on x-axis
  2907          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);       // Set texture to repeat on y-axis
  2908      }
  2909      else
  2910      {
  2911          // NOTE: If using negative texture coordinates (LoadOBJ()), it does not work!
  2912          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);       // Set texture to clamp on x-axis
  2913          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);       // Set texture to clamp on y-axis
  2914      }
  2915  #else
  2916      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);       // Set texture to repeat on x-axis
  2917      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);       // Set texture to repeat on y-axis
  2918  #endif
  2919  
  2920      // Magnification and minification filters
  2921      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);  // Alternative: GL_LINEAR
  2922      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);  // Alternative: GL_LINEAR
  2923  
  2924  #if defined(GRAPHICS_API_OPENGL_33)
  2925      if (mipmapCount > 1)
  2926      {
  2927          // Activate Trilinear filtering if mipmaps are available
  2928          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  2929          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
  2930      }
  2931  #endif
  2932  
  2933      // At this point we have the texture loaded in GPU and texture parameters configured
  2934  
  2935      // NOTE: If mipmaps were not in data, they are not generated automatically
  2936  
  2937      // Unbind current texture
  2938      glBindTexture(GL_TEXTURE_2D, 0);
  2939  
  2940      if (id > 0) TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Texture loaded successfully (%ix%i | %s | %i mipmaps)", id, width, height, rlGetPixelFormatName(format), mipmapCount);
  2941      else TRACELOG(RL_LOG_WARNING, "TEXTURE: Failed to load texture");
  2942  
  2943      return id;
  2944  }
  2945  
  2946  // Load depth texture/renderbuffer (to be attached to fbo)
  2947  // WARNING: OpenGL ES 2.0 requires GL_OES_depth_texture/WEBGL_depth_texture extensions
  2948  unsigned int rlLoadTextureDepth(int width, int height, bool useRenderBuffer)
  2949  {
  2950      unsigned int id = 0;
  2951  
  2952  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  2953      // In case depth textures not supported, we force renderbuffer usage
  2954      if (!RLGL.ExtSupported.texDepth) useRenderBuffer = true;
  2955  
  2956      // NOTE: We let the implementation to choose the best bit-depth
  2957      // Possible formats: GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT32 and GL_DEPTH_COMPONENT32F
  2958      unsigned int glInternalFormat = GL_DEPTH_COMPONENT;
  2959  
  2960  #if defined(GRAPHICS_API_OPENGL_ES2)
  2961      if (RLGL.ExtSupported.maxDepthBits == 32) glInternalFormat = GL_DEPTH_COMPONENT32_OES;
  2962      else if (RLGL.ExtSupported.maxDepthBits == 24) glInternalFormat = GL_DEPTH_COMPONENT24_OES;
  2963      else glInternalFormat = GL_DEPTH_COMPONENT16;
  2964  #endif
  2965  
  2966      if (!useRenderBuffer && RLGL.ExtSupported.texDepth)
  2967      {
  2968          glGenTextures(1, &id);
  2969          glBindTexture(GL_TEXTURE_2D, id);
  2970          glTexImage2D(GL_TEXTURE_2D, 0, glInternalFormat, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
  2971  
  2972          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  2973          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  2974          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  2975          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  2976  
  2977          glBindTexture(GL_TEXTURE_2D, 0);
  2978  
  2979          TRACELOG(RL_LOG_INFO, "TEXTURE: Depth texture loaded successfully");
  2980      }
  2981      else
  2982      {
  2983          // Create the renderbuffer that will serve as the depth attachment for the framebuffer
  2984          // NOTE: A renderbuffer is simpler than a texture and could offer better performance on embedded devices
  2985          glGenRenderbuffers(1, &id);
  2986          glBindRenderbuffer(GL_RENDERBUFFER, id);
  2987          glRenderbufferStorage(GL_RENDERBUFFER, glInternalFormat, width, height);
  2988  
  2989          glBindRenderbuffer(GL_RENDERBUFFER, 0);
  2990  
  2991          TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Depth renderbuffer loaded successfully (%i bits)", id, (RLGL.ExtSupported.maxDepthBits >= 24)? RLGL.ExtSupported.maxDepthBits : 16);
  2992      }
  2993  #endif
  2994  
  2995      return id;
  2996  }
  2997  
  2998  // Load texture cubemap
  2999  // NOTE: Cubemap data is expected to be 6 images in a single data array (one after the other),
  3000  // expected the following convention: +X, -X, +Y, -Y, +Z, -Z
  3001  unsigned int rlLoadTextureCubemap(const void *data, int size, int format)
  3002  {
  3003      unsigned int id = 0;
  3004  
  3005  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3006      unsigned int dataSize = rlGetPixelDataSize(size, size, format);
  3007  
  3008      glGenTextures(1, &id);
  3009      glBindTexture(GL_TEXTURE_CUBE_MAP, id);
  3010  
  3011      unsigned int glInternalFormat, glFormat, glType;
  3012      rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType);
  3013  
  3014      if (glInternalFormat != -1)
  3015      {
  3016          // Load cubemap faces
  3017          for (unsigned int i = 0; i < 6; i++)
  3018          {
  3019              if (data == NULL)
  3020              {
  3021                  if (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB)
  3022                  {
  3023                      if (format == RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32)
  3024                      {
  3025                          // 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)
  3026                          if (RLGL.ExtSupported.texFloat32) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, size, size, 0, GL_RGB, GL_FLOAT, NULL);
  3027                          else TRACELOG(RL_LOG_WARNING, "TEXTURES: Cubemap requested format not supported");
  3028                      }
  3029                      else if ((format == RL_PIXELFORMAT_UNCOMPRESSED_R32) || (format == RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32)) TRACELOG(RL_LOG_WARNING, "TEXTURES: Cubemap requested format not supported");
  3030                      else glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, size, size, 0, glFormat, glType, NULL);
  3031                  }
  3032                  else TRACELOG(RL_LOG_WARNING, "TEXTURES: Empty cubemap creation does not support compressed format");
  3033              }
  3034              else
  3035              {
  3036                  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);
  3037                  else glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, size, size, 0, dataSize, (unsigned char *)data + i*dataSize);
  3038              }
  3039  
  3040  #if defined(GRAPHICS_API_OPENGL_33)
  3041              if (format == RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE)
  3042              {
  3043                  GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_ONE };
  3044                  glTexParameteriv(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
  3045              }
  3046              else if (format == RL_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA)
  3047              {
  3048  #if defined(GRAPHICS_API_OPENGL_21)
  3049                  GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_ALPHA };
  3050  #elif defined(GRAPHICS_API_OPENGL_33)
  3051                  GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_GREEN };
  3052  #endif
  3053                  glTexParameteriv(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
  3054              }
  3055  #endif
  3056          }
  3057      }
  3058  
  3059      // Set cubemap texture sampling parameters
  3060      glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  3061      glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  3062      glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  3063      glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  3064  #if defined(GRAPHICS_API_OPENGL_33)
  3065      glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);  // Flag not supported on OpenGL ES 2.0
  3066  #endif
  3067  
  3068      glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
  3069  #endif
  3070  
  3071      if (id > 0) TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Cubemap texture loaded successfully (%ix%i)", id, size, size);
  3072      else TRACELOG(RL_LOG_WARNING, "TEXTURE: Failed to load cubemap texture");
  3073  
  3074      return id;
  3075  }
  3076  
  3077  // Update already loaded texture in GPU with new data
  3078  // NOTE: We don't know safely if internal texture format is the expected one...
  3079  void rlUpdateTexture(unsigned int id, int offsetX, int offsetY, int width, int height, int format, const void *data)
  3080  {
  3081      glBindTexture(GL_TEXTURE_2D, id);
  3082  
  3083      unsigned int glInternalFormat, glFormat, glType;
  3084      rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType);
  3085  
  3086      if ((glInternalFormat != -1) && (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB))
  3087      {
  3088          glTexSubImage2D(GL_TEXTURE_2D, 0, offsetX, offsetY, width, height, glFormat, glType, data);
  3089      }
  3090      else TRACELOG(RL_LOG_WARNING, "TEXTURE: [ID %i] Failed to update for current texture format (%i)", id, format);
  3091  }
  3092  
  3093  // Get OpenGL internal formats and data type from raylib PixelFormat
  3094  void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned int *glFormat, unsigned int *glType)
  3095  {
  3096      *glInternalFormat = 0;
  3097      *glFormat = 0;
  3098      *glType = 0;
  3099  
  3100      switch (format)
  3101      {
  3102      #if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_21) || defined(GRAPHICS_API_OPENGL_ES2)
  3103          // NOTE: on OpenGL ES 2.0 (WebGL), internalFormat must match format and options allowed are: GL_LUMINANCE, GL_RGB, GL_RGBA
  3104          case RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_UNSIGNED_BYTE; break;
  3105          case RL_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: *glInternalFormat = GL_LUMINANCE_ALPHA; *glFormat = GL_LUMINANCE_ALPHA; *glType = GL_UNSIGNED_BYTE; break;
  3106          case RL_PIXELFORMAT_UNCOMPRESSED_R5G6B5: *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_UNSIGNED_SHORT_5_6_5; break;
  3107          case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8: *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_UNSIGNED_BYTE; break;
  3108          case RL_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_SHORT_5_5_5_1; break;
  3109          case RL_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_SHORT_4_4_4_4; break;
  3110          case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_BYTE; break;
  3111          #if !defined(GRAPHICS_API_OPENGL_11)
  3112          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
  3113          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
  3114          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
  3115          #endif
  3116      #elif defined(GRAPHICS_API_OPENGL_33)
  3117          case RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: *glInternalFormat = GL_R8; *glFormat = GL_RED; *glType = GL_UNSIGNED_BYTE; break;
  3118          case RL_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: *glInternalFormat = GL_RG8; *glFormat = GL_RG; *glType = GL_UNSIGNED_BYTE; break;
  3119          case RL_PIXELFORMAT_UNCOMPRESSED_R5G6B5: *glInternalFormat = GL_RGB565; *glFormat = GL_RGB; *glType = GL_UNSIGNED_SHORT_5_6_5; break;
  3120          case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8: *glInternalFormat = GL_RGB8; *glFormat = GL_RGB; *glType = GL_UNSIGNED_BYTE; break;
  3121          case RL_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: *glInternalFormat = GL_RGB5_A1; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_SHORT_5_5_5_1; break;
  3122          case RL_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: *glInternalFormat = GL_RGBA4; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_SHORT_4_4_4_4; break;
  3123          case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: *glInternalFormat = GL_RGBA8; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_BYTE; break;
  3124          case RL_PIXELFORMAT_UNCOMPRESSED_R32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_R32F; *glFormat = GL_RED; *glType = GL_FLOAT; break;
  3125          case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGB32F; *glFormat = GL_RGB; *glType = GL_FLOAT; break;
  3126          case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGBA32F; *glFormat = GL_RGBA; *glType = GL_FLOAT; break;
  3127      #endif
  3128      #if !defined(GRAPHICS_API_OPENGL_11)
  3129          case RL_PIXELFORMAT_COMPRESSED_DXT1_RGB: if (RLGL.ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; break;
  3130          case RL_PIXELFORMAT_COMPRESSED_DXT1_RGBA: if (RLGL.ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; break;
  3131          case RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA: if (RLGL.ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break;
  3132          case RL_PIXELFORMAT_COMPRESSED_DXT5_RGBA: if (RLGL.ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break;
  3133          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
  3134          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
  3135          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
  3136          case RL_PIXELFORMAT_COMPRESSED_PVRT_RGB: if (RLGL.ExtSupported.texCompPVRT) *glInternalFormat = GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG; break;    // NOTE: Requires PowerVR GPU
  3137          case RL_PIXELFORMAT_COMPRESSED_PVRT_RGBA: if (RLGL.ExtSupported.texCompPVRT) *glInternalFormat = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; break;  // NOTE: Requires PowerVR GPU
  3138          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
  3139          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
  3140      #endif
  3141          default: TRACELOG(RL_LOG_WARNING, "TEXTURE: Current format not supported (%i)", format); break;
  3142      }
  3143  }
  3144  
  3145  // Unload texture from GPU memory
  3146  void rlUnloadTexture(unsigned int id)
  3147  {
  3148      glDeleteTextures(1, &id);
  3149  }
  3150  
  3151  // Generate mipmap data for selected texture
  3152  // NOTE: Only supports GPU mipmap generation
  3153  void rlGenTextureMipmaps(unsigned int id, int width, int height, int format, int *mipmaps)
  3154  {
  3155      glBindTexture(GL_TEXTURE_2D, id);
  3156  
  3157      // Check if texture is power-of-two (POT)
  3158      bool texIsPOT = false;
  3159  
  3160      if (((width > 0) && ((width & (width - 1)) == 0)) &&
  3161          ((height > 0) && ((height & (height - 1)) == 0))) texIsPOT = true;
  3162  
  3163  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3164      if ((texIsPOT) || (RLGL.ExtSupported.texNPOT))
  3165      {
  3166          //glHint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE);   // Hint for mipmaps generation algorithm: GL_FASTEST, GL_NICEST, GL_DONT_CARE
  3167          glGenerateMipmap(GL_TEXTURE_2D);    // Generate mipmaps automatically
  3168  
  3169          #define MIN(a,b) (((a)<(b))? (a):(b))
  3170          #define MAX(a,b) (((a)>(b))? (a):(b))
  3171  
  3172          *mipmaps = 1 + (int)floor(log(MAX(width, height))/log(2));
  3173          TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Mipmaps generated automatically, total: %i", id, *mipmaps);
  3174      }
  3175  #endif
  3176      else TRACELOG(RL_LOG_WARNING, "TEXTURE: [ID %i] Failed to generate mipmaps", id);
  3177  
  3178      glBindTexture(GL_TEXTURE_2D, 0);
  3179  }
  3180  
  3181  
  3182  // Read texture pixel data
  3183  void *rlReadTexturePixels(unsigned int id, int width, int height, int format)
  3184  {
  3185      void *pixels = NULL;
  3186  
  3187  #if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
  3188      glBindTexture(GL_TEXTURE_2D, id);
  3189  
  3190      // NOTE: Using texture id, we can retrieve some texture info (but not on OpenGL ES 2.0)
  3191      // Possible texture info: GL_TEXTURE_RED_SIZE, GL_TEXTURE_GREEN_SIZE, GL_TEXTURE_BLUE_SIZE, GL_TEXTURE_ALPHA_SIZE
  3192      //int width, height, format;
  3193      //glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
  3194      //glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
  3195      //glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &format);
  3196  
  3197      // NOTE: Each row written to or read from by OpenGL pixel operations like glGetTexImage are aligned to a 4 byte boundary by default, which may add some padding.
  3198      // Use glPixelStorei to modify padding with the GL_[UN]PACK_ALIGNMENT setting.
  3199      // GL_PACK_ALIGNMENT affects operations that read from OpenGL memory (glReadPixels, glGetTexImage, etc.)
  3200      // GL_UNPACK_ALIGNMENT affects operations that write to OpenGL memory (glTexImage, etc.)
  3201      glPixelStorei(GL_PACK_ALIGNMENT, 1);
  3202  
  3203      unsigned int glInternalFormat, glFormat, glType;
  3204      rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType);
  3205      unsigned int size = rlGetPixelDataSize(width, height, format);
  3206  
  3207      if ((glInternalFormat != -1) && (format < RL_PIXELFORMAT_COMPRESSED_DXT1_RGB))
  3208      {
  3209          pixels = RL_MALLOC(size);
  3210          glGetTexImage(GL_TEXTURE_2D, 0, glFormat, glType, pixels);
  3211      }
  3212      else TRACELOG(RL_LOG_WARNING, "TEXTURE: [ID %i] Data retrieval not suported for pixel format (%i)", id, format);
  3213  
  3214      glBindTexture(GL_TEXTURE_2D, 0);
  3215  #endif
  3216  
  3217  #if defined(GRAPHICS_API_OPENGL_ES2)
  3218      // glGetTexImage() is not available on OpenGL ES 2.0
  3219      // Texture width and height are required on OpenGL ES 2.0. There is no way to get it from texture id.
  3220      // Two possible Options:
  3221      // 1 - Bind texture to color fbo attachment and glReadPixels()
  3222      // 2 - Create an fbo, activate it, render quad with texture, glReadPixels()
  3223      // We are using Option 1, just need to care for texture format on retrieval
  3224      // NOTE: This behaviour could be conditioned by graphic driver...
  3225      unsigned int fboId = rlLoadFramebuffer(width, height);
  3226  
  3227      glBindFramebuffer(GL_FRAMEBUFFER, fboId);
  3228      glBindTexture(GL_TEXTURE_2D, 0);
  3229  
  3230      // Attach our texture to FBO
  3231      glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, id, 0);
  3232  
  3233      // We read data as RGBA because FBO texture is configured as RGBA, despite binding another texture format
  3234      pixels = (unsigned char *)RL_MALLOC(rlGetPixelDataSize(width, height, RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8));
  3235      glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
  3236  
  3237      glBindFramebuffer(GL_FRAMEBUFFER, 0);
  3238  
  3239      // Clean up temporal fbo
  3240      rlUnloadFramebuffer(fboId);
  3241  #endif
  3242  
  3243      return pixels;
  3244  }
  3245  
  3246  // Read screen pixel data (color buffer)
  3247  unsigned char *rlReadScreenPixels(int width, int height)
  3248  {
  3249      unsigned char *screenData = (unsigned char *)RL_CALLOC(width*height*4, sizeof(unsigned char));
  3250  
  3251      // NOTE 1: glReadPixels returns image flipped vertically -> (0,0) is the bottom left corner of the framebuffer
  3252      // NOTE 2: We are getting alpha channel! Be careful, it can be transparent if not cleared properly!
  3253      glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, screenData);
  3254  
  3255      // Flip image vertically!
  3256      unsigned char *imgData = (unsigned char *)RL_MALLOC(width*height*4*sizeof(unsigned char));
  3257  
  3258      for (int y = height - 1; y >= 0; y--)
  3259      {
  3260          for (int x = 0; x < (width*4); x++)
  3261          {
  3262              imgData[((height - 1) - y)*width*4 + x] = screenData[(y*width*4) + x];  // Flip line
  3263  
  3264              // Set alpha component value to 255 (no trasparent image retrieval)
  3265              // NOTE: Alpha value has already been applied to RGB in framebuffer, we don't need it!
  3266              if (((x + 1)%4) == 0) imgData[((height - 1) - y)*width*4 + x] = 255;
  3267          }
  3268      }
  3269  
  3270      RL_FREE(screenData);
  3271  
  3272      return imgData;     // NOTE: image data should be freed
  3273  }
  3274  
  3275  // Framebuffer management (fbo)
  3276  //-----------------------------------------------------------------------------------------
  3277  // Load a framebuffer to be used for rendering
  3278  // NOTE: No textures attached
  3279  unsigned int rlLoadFramebuffer(int width, int height)
  3280  {
  3281      unsigned int fboId = 0;
  3282  
  3283  #if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(RLGL_RENDER_TEXTURES_HINT)
  3284      glGenFramebuffers(1, &fboId);       // Create the framebuffer object
  3285      glBindFramebuffer(GL_FRAMEBUFFER, 0);   // Unbind any framebuffer
  3286  #endif
  3287  
  3288      return fboId;
  3289  }
  3290  
  3291  // Attach color buffer texture to an fbo (unloads previous attachment)
  3292  // NOTE: Attach type: 0-Color, 1-Depth renderbuffer, 2-Depth texture
  3293  void rlFramebufferAttach(unsigned int fboId, unsigned int texId, int attachType, int texType, int mipLevel)
  3294  {
  3295  #if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(RLGL_RENDER_TEXTURES_HINT)
  3296      glBindFramebuffer(GL_FRAMEBUFFER, fboId);
  3297  
  3298      switch (attachType)
  3299      {
  3300          case RL_ATTACHMENT_COLOR_CHANNEL0:
  3301          case RL_ATTACHMENT_COLOR_CHANNEL1:
  3302          case RL_ATTACHMENT_COLOR_CHANNEL2:
  3303          case RL_ATTACHMENT_COLOR_CHANNEL3:
  3304          case RL_ATTACHMENT_COLOR_CHANNEL4:
  3305          case RL_ATTACHMENT_COLOR_CHANNEL5:
  3306          case RL_ATTACHMENT_COLOR_CHANNEL6:
  3307          case RL_ATTACHMENT_COLOR_CHANNEL7:
  3308          {
  3309              if (texType == RL_ATTACHMENT_TEXTURE2D) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + attachType, GL_TEXTURE_2D, texId, mipLevel);
  3310              else if (texType == RL_ATTACHMENT_RENDERBUFFER) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + attachType, GL_RENDERBUFFER, texId);
  3311              else if (texType >= RL_ATTACHMENT_CUBEMAP_POSITIVE_X) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + attachType, GL_TEXTURE_CUBE_MAP_POSITIVE_X + texType, texId, mipLevel);
  3312  
  3313          } break;
  3314          case RL_ATTACHMENT_DEPTH:
  3315          {
  3316              if (texType == RL_ATTACHMENT_TEXTURE2D) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, texId, mipLevel);
  3317              else if (texType == RL_ATTACHMENT_RENDERBUFFER)  glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, texId);
  3318  
  3319          } break;
  3320          case RL_ATTACHMENT_STENCIL:
  3321          {
  3322              if (texType == RL_ATTACHMENT_TEXTURE2D) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, texId, mipLevel);
  3323              else if (texType == RL_ATTACHMENT_RENDERBUFFER)  glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, texId);
  3324  
  3325          } break;
  3326          default: break;
  3327      }
  3328  
  3329      glBindFramebuffer(GL_FRAMEBUFFER, 0);
  3330  #endif
  3331  }
  3332  
  3333  // Verify render texture is complete
  3334  bool rlFramebufferComplete(unsigned int id)
  3335  {
  3336      bool result = false;
  3337  
  3338  #if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(RLGL_RENDER_TEXTURES_HINT)
  3339      glBindFramebuffer(GL_FRAMEBUFFER, id);
  3340  
  3341      GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
  3342  
  3343      if (status != GL_FRAMEBUFFER_COMPLETE)
  3344      {
  3345          switch (status)
  3346          {
  3347              case GL_FRAMEBUFFER_UNSUPPORTED: TRACELOG(RL_LOG_WARNING, "FBO: [ID %i] Framebuffer is unsupported", id); break;
  3348              case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: TRACELOG(RL_LOG_WARNING, "FBO: [ID %i] Framebuffer has incomplete attachment", id); break;
  3349  #if defined(GRAPHICS_API_OPENGL_ES2)
  3350              case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: TRACELOG(RL_LOG_WARNING, "FBO: [ID %i] Framebuffer has incomplete dimensions", id); break;
  3351  #endif
  3352              case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: TRACELOG(RL_LOG_WARNING, "FBO: [ID %i] Framebuffer has a missing attachment", id); break;
  3353              default: break;
  3354          }
  3355      }
  3356  
  3357      glBindFramebuffer(GL_FRAMEBUFFER, 0);
  3358  
  3359      result = (status == GL_FRAMEBUFFER_COMPLETE);
  3360  #endif
  3361  
  3362      return result;
  3363  }
  3364  
  3365  // Unload framebuffer from GPU memory
  3366  // NOTE: All attached textures/cubemaps/renderbuffers are also deleted
  3367  void rlUnloadFramebuffer(unsigned int id)
  3368  {
  3369  #if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(RLGL_RENDER_TEXTURES_HINT)
  3370  
  3371      // Query depth attachment to automatically delete texture/renderbuffer
  3372      int depthType = 0, depthId = 0;
  3373      glBindFramebuffer(GL_FRAMEBUFFER, id);   // Bind framebuffer to query depth texture type
  3374      glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &depthType);
  3375      glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &depthId);
  3376  
  3377      unsigned int depthIdU = (unsigned int)depthId;
  3378      if (depthType == GL_RENDERBUFFER) glDeleteRenderbuffers(1, &depthIdU);
  3379      else if (depthType == GL_RENDERBUFFER) glDeleteTextures(1, &depthIdU);
  3380  
  3381      // NOTE: If a texture object is deleted while its image is attached to the *currently bound* framebuffer,
  3382      // the texture image is automatically detached from the currently bound framebuffer.
  3383  
  3384      glBindFramebuffer(GL_FRAMEBUFFER, 0);
  3385      glDeleteFramebuffers(1, &id);
  3386  
  3387      TRACELOG(RL_LOG_INFO, "FBO: [ID %i] Unloaded framebuffer from VRAM (GPU)", id);
  3388  #endif
  3389  }
  3390  
  3391  // Vertex data management
  3392  //-----------------------------------------------------------------------------------------
  3393  // Load a new attributes buffer
  3394  unsigned int rlLoadVertexBuffer(const void *buffer, int size, bool dynamic)
  3395  {
  3396      unsigned int id = 0;
  3397  
  3398  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3399      glGenBuffers(1, &id);
  3400      glBindBuffer(GL_ARRAY_BUFFER, id);
  3401      glBufferData(GL_ARRAY_BUFFER, size, buffer, dynamic? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
  3402  #endif
  3403  
  3404      return id;
  3405  }
  3406  
  3407  // Load a new attributes element buffer
  3408  unsigned int rlLoadVertexBufferElement(const void *buffer, int size, bool dynamic)
  3409  {
  3410      unsigned int id = 0;
  3411  
  3412  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3413      glGenBuffers(1, &id);
  3414      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, id);
  3415      glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, buffer, dynamic? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
  3416  #endif
  3417  
  3418      return id;
  3419  }
  3420  
  3421  // Enable vertex buffer (VBO)
  3422  void rlEnableVertexBuffer(unsigned int id)
  3423  {
  3424  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3425      glBindBuffer(GL_ARRAY_BUFFER, id);
  3426  #endif
  3427  }
  3428  
  3429  // Disable vertex buffer (VBO)
  3430  void rlDisableVertexBuffer(void)
  3431  {
  3432  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3433      glBindBuffer(GL_ARRAY_BUFFER, 0);
  3434  #endif
  3435  }
  3436  
  3437  // Enable vertex buffer element (VBO element)
  3438  void rlEnableVertexBufferElement(unsigned int id)
  3439  {
  3440  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3441      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, id);
  3442  #endif
  3443  }
  3444  
  3445  // Disable vertex buffer element (VBO element)
  3446  void rlDisableVertexBufferElement(void)
  3447  {
  3448  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3449      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  3450  #endif
  3451  }
  3452  
  3453  // Update vertex buffer with new data
  3454  // NOTE: dataSize and offset must be provided in bytes
  3455  void rlUpdateVertexBuffer(unsigned int id, const void *data, int dataSize, int offset)
  3456  {
  3457  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3458      glBindBuffer(GL_ARRAY_BUFFER, id);
  3459      glBufferSubData(GL_ARRAY_BUFFER, offset, dataSize, data);
  3460  #endif
  3461  }
  3462  
  3463  // Update vertex buffer elements with new data
  3464  // NOTE: dataSize and offset must be provided in bytes
  3465  void rlUpdateVertexBufferElements(unsigned int id, const void *data, int dataSize, int offset)
  3466  {
  3467  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3468      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, id);
  3469      glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset, dataSize, data);
  3470  #endif
  3471  }
  3472  
  3473  // Enable vertex array object (VAO)
  3474  bool rlEnableVertexArray(unsigned int vaoId)
  3475  {
  3476      bool result = false;
  3477  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3478      if (RLGL.ExtSupported.vao)
  3479      {
  3480          glBindVertexArray(vaoId);
  3481          result = true;
  3482      }
  3483  #endif
  3484      return result;
  3485  }
  3486  
  3487  // Disable vertex array object (VAO)
  3488  void rlDisableVertexArray(void)
  3489  {
  3490  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3491      if (RLGL.ExtSupported.vao) glBindVertexArray(0);
  3492  #endif
  3493  }
  3494  
  3495  // Enable vertex attribute index
  3496  void rlEnableVertexAttribute(unsigned int index)
  3497  {
  3498  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3499      glEnableVertexAttribArray(index);
  3500  #endif
  3501  }
  3502  
  3503  // Disable vertex attribute index
  3504  void rlDisableVertexAttribute(unsigned int index)
  3505  {
  3506  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3507      glDisableVertexAttribArray(index);
  3508  #endif
  3509  }
  3510  
  3511  // Draw vertex array
  3512  void rlDrawVertexArray(int offset, int count)
  3513  {
  3514      glDrawArrays(GL_TRIANGLES, offset, count);
  3515  }
  3516  
  3517  // Draw vertex array elements
  3518  void rlDrawVertexArrayElements(int offset, int count, const void *buffer)
  3519  {
  3520      glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, (const unsigned short *)buffer + offset);
  3521  }
  3522  
  3523  // Draw vertex array instanced
  3524  void rlDrawVertexArrayInstanced(int offset, int count, int instances)
  3525  {
  3526  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3527      glDrawArraysInstanced(GL_TRIANGLES, 0, count, instances);
  3528  #endif
  3529  }
  3530  
  3531  // Draw vertex array elements instanced
  3532  void rlDrawVertexArrayElementsInstanced(int offset, int count, const void *buffer, int instances)
  3533  {
  3534  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3535      glDrawElementsInstanced(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, (const unsigned short *)buffer + offset, instances);
  3536  #endif
  3537  }
  3538  
  3539  #if defined(GRAPHICS_API_OPENGL_11)
  3540  // Enable vertex state pointer
  3541  void rlEnableStatePointer(int vertexAttribType, void *buffer)
  3542  {
  3543      if (buffer != NULL) glEnableClientState(vertexAttribType);
  3544      switch (vertexAttribType)
  3545      {
  3546          case GL_VERTEX_ARRAY: glVertexPointer(3, GL_FLOAT, 0, buffer); break;
  3547          case GL_TEXTURE_COORD_ARRAY: glTexCoordPointer(2, GL_FLOAT, 0, buffer); break;
  3548          case GL_NORMAL_ARRAY: if (buffer != NULL) glNormalPointer(GL_FLOAT, 0, buffer); break;
  3549          case GL_COLOR_ARRAY: if (buffer != NULL) glColorPointer(4, GL_UNSIGNED_BYTE, 0, buffer); break;
  3550          //case GL_INDEX_ARRAY: if (buffer != NULL) glIndexPointer(GL_SHORT, 0, buffer); break; // Indexed colors
  3551          default: break;
  3552      }
  3553  }
  3554  
  3555  // Disable vertex state pointer
  3556  void rlDisableStatePointer(int vertexAttribType)
  3557  {
  3558      glDisableClientState(vertexAttribType);
  3559  }
  3560  #endif
  3561  
  3562  // Load vertex array object (VAO)
  3563  unsigned int rlLoadVertexArray(void)
  3564  {
  3565      unsigned int vaoId = 0;
  3566  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3567      if (RLGL.ExtSupported.vao)
  3568      {
  3569          glGenVertexArrays(1, &vaoId);
  3570      }
  3571  #endif
  3572      return vaoId;
  3573  }
  3574  
  3575  // Set vertex attribute
  3576  void rlSetVertexAttribute(unsigned int index, int compSize, int type, bool normalized, int stride, const void *pointer)
  3577  {
  3578  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3579      glVertexAttribPointer(index, compSize, type, normalized, stride, pointer);
  3580  #endif
  3581  }
  3582  
  3583  // Set vertex attribute divisor
  3584  void rlSetVertexAttributeDivisor(unsigned int index, int divisor)
  3585  {
  3586  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3587      glVertexAttribDivisor(index, divisor);
  3588  #endif
  3589  }
  3590  
  3591  // Unload vertex array object (VAO)
  3592  void rlUnloadVertexArray(unsigned int vaoId)
  3593  {
  3594  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3595      if (RLGL.ExtSupported.vao)
  3596      {
  3597          glBindVertexArray(0);
  3598          glDeleteVertexArrays(1, &vaoId);
  3599          TRACELOG(RL_LOG_INFO, "VAO: [ID %i] Unloaded vertex array data from VRAM (GPU)", vaoId);
  3600      }
  3601  #endif
  3602  }
  3603  
  3604  // Unload vertex buffer (VBO)
  3605  void rlUnloadVertexBuffer(unsigned int vboId)
  3606  {
  3607  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3608      glDeleteBuffers(1, &vboId);
  3609      //TRACELOG(RL_LOG_INFO, "VBO: Unloaded vertex data from VRAM (GPU)");
  3610  #endif
  3611  }
  3612  
  3613  // Shaders management
  3614  //-----------------------------------------------------------------------------------------------
  3615  // Load shader from code strings
  3616  // NOTE: If shader string is NULL, using default vertex/fragment shaders
  3617  unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode)
  3618  {
  3619      unsigned int id = 0;
  3620  
  3621  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3622      unsigned int vertexShaderId = 0;
  3623      unsigned int fragmentShaderId = 0;
  3624  
  3625      // Compile vertex shader (if provided)
  3626      if (vsCode != NULL) vertexShaderId = rlCompileShader(vsCode, GL_VERTEX_SHADER);
  3627      // In case no vertex shader was provided or compilation failed, we use default vertex shader
  3628      if (vertexShaderId == 0) vertexShaderId = RLGL.State.defaultVShaderId;
  3629  
  3630      // Compile fragment shader (if provided)
  3631      if (fsCode != NULL) fragmentShaderId = rlCompileShader(fsCode, GL_FRAGMENT_SHADER);
  3632      // In case no fragment shader was provided or compilation failed, we use default fragment shader
  3633      if (fragmentShaderId == 0) fragmentShaderId = RLGL.State.defaultFShaderId;
  3634  
  3635      // In case vertex and fragment shader are the default ones, no need to recompile, we can just assign the default shader program id
  3636      if ((vertexShaderId == RLGL.State.defaultVShaderId) && (fragmentShaderId == RLGL.State.defaultFShaderId)) id = RLGL.State.defaultShaderId;
  3637      else
  3638      {
  3639          // One of or both shader are new, we need to compile a new shader program
  3640          id = rlLoadShaderProgram(vertexShaderId, fragmentShaderId);
  3641  
  3642          // We can detach and delete vertex/fragment shaders (if not default ones)
  3643          // NOTE: We detach shader before deletion to make sure memory is freed
  3644          if (vertexShaderId != RLGL.State.defaultVShaderId)
  3645          {
  3646              glDetachShader(id, vertexShaderId);
  3647              glDeleteShader(vertexShaderId);
  3648          }
  3649          if (fragmentShaderId != RLGL.State.defaultFShaderId)
  3650          {
  3651              glDetachShader(id, fragmentShaderId);
  3652              glDeleteShader(fragmentShaderId);
  3653          }
  3654  
  3655          // In case shader program loading failed, we assign default shader
  3656          if (id == 0)
  3657          {
  3658              // In case shader loading fails, we return the default shader
  3659              TRACELOG(RL_LOG_WARNING, "SHADER: Failed to load custom shader code, using default shader");
  3660              id = RLGL.State.defaultShaderId;
  3661          }
  3662          /*
  3663          else
  3664          {
  3665              // Get available shader uniforms
  3666              // NOTE: This information is useful for debug...
  3667              int uniformCount = -1;
  3668              glGetProgramiv(id, GL_ACTIVE_UNIFORMS, &uniformCount);
  3669  
  3670              for (int i = 0; i < uniformCount; i++)
  3671              {
  3672                  int namelen = -1;
  3673                  int num = -1;
  3674                  char name[256] = { 0 };     // Assume no variable names longer than 256
  3675                  GLenum type = GL_ZERO;
  3676  
  3677                  // Get the name of the uniforms
  3678                  glGetActiveUniform(id, i, sizeof(name) - 1, &namelen, &num, &type, name);
  3679  
  3680                  name[namelen] = 0;
  3681                  TRACELOGD("SHADER: [ID %i] Active uniform (%s) set at location: %i", id, name, glGetUniformLocation(id, name));
  3682              }
  3683          }
  3684          */
  3685      }
  3686  #endif
  3687  
  3688      return id;
  3689  }
  3690  
  3691  // Compile custom shader and return shader id
  3692  unsigned int rlCompileShader(const char *shaderCode, int type)
  3693  {
  3694      unsigned int shader = 0;
  3695  
  3696  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3697      shader = glCreateShader(type);
  3698      glShaderSource(shader, 1, &shaderCode, NULL);
  3699  
  3700      GLint success = 0;
  3701      glCompileShader(shader);
  3702      glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
  3703  
  3704      if (success == GL_FALSE)
  3705      {
  3706          switch (type)
  3707          {
  3708              case GL_VERTEX_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to compile vertex shader code", shader); break;
  3709              case GL_FRAGMENT_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to compile fragment shader code", shader); break;
  3710              //case GL_GEOMETRY_SHADER:
  3711          #if defined(GRAPHICS_API_OPENGL_43)
  3712              case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to compile compute shader code", shader); break;
  3713          #endif
  3714              default: break;
  3715          }
  3716  
  3717          int maxLength = 0;
  3718          glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
  3719  
  3720          if (maxLength > 0)
  3721          {
  3722              int length = 0;
  3723              char *log = (char *)RL_CALLOC(maxLength, sizeof(char));
  3724              glGetShaderInfoLog(shader, maxLength, &length, log);
  3725              TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Compile error: %s", shader, log);
  3726              RL_FREE(log);
  3727          }
  3728      }
  3729      else
  3730      {
  3731          switch (type)
  3732          {
  3733              case GL_VERTEX_SHADER: TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Vertex shader compiled successfully", shader); break;
  3734              case GL_FRAGMENT_SHADER: TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Fragment shader compiled successfully", shader); break;
  3735              //case GL_GEOMETRY_SHADER:
  3736          #if defined(GRAPHICS_API_OPENGL_43)
  3737              case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Compute shader compiled successfully", shader); break;
  3738          #endif
  3739              default: break;
  3740          }
  3741      }
  3742  #endif
  3743  
  3744      return shader;
  3745  }
  3746  
  3747  // Load custom shader strings and return program id
  3748  unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId)
  3749  {
  3750      unsigned int program = 0;
  3751  
  3752  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3753      GLint success = 0;
  3754      program = glCreateProgram();
  3755  
  3756      glAttachShader(program, vShaderId);
  3757      glAttachShader(program, fShaderId);
  3758  
  3759      // NOTE: Default attribute shader locations must be binded before linking
  3760      glBindAttribLocation(program, 0, RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION);
  3761      glBindAttribLocation(program, 1, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD);
  3762      glBindAttribLocation(program, 2, RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL);
  3763      glBindAttribLocation(program, 3, RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR);
  3764      glBindAttribLocation(program, 4, RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT);
  3765      glBindAttribLocation(program, 5, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2);
  3766  
  3767      // NOTE: If some attrib name is no found on the shader, it locations becomes -1
  3768  
  3769      glLinkProgram(program);
  3770  
  3771      // NOTE: All uniform variables are intitialised to 0 when a program links
  3772  
  3773      glGetProgramiv(program, GL_LINK_STATUS, &success);
  3774  
  3775      if (success == GL_FALSE)
  3776      {
  3777          TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to link shader program", program);
  3778  
  3779          int maxLength = 0;
  3780          glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
  3781  
  3782          if (maxLength > 0)
  3783          {
  3784              int length = 0;
  3785              char *log = (char *)RL_CALLOC(maxLength, sizeof(char));
  3786              glGetProgramInfoLog(program, maxLength, &length, log);
  3787              TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Link error: %s", program, log);
  3788              RL_FREE(log);
  3789          }
  3790  
  3791          glDeleteProgram(program);
  3792  
  3793          program = 0;
  3794      }
  3795      else
  3796      {
  3797          // Get the size of compiled shader program (not available on OpenGL ES 2.0)
  3798          // NOTE: If GL_LINK_STATUS is GL_FALSE, program binary length is zero.
  3799          //GLint binarySize = 0;
  3800          //glGetProgramiv(id, GL_PROGRAM_BINARY_LENGTH, &binarySize);
  3801  
  3802          TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Program shader loaded successfully", program);
  3803      }
  3804  #endif
  3805      return program;
  3806  }
  3807  
  3808  // Unload shader program
  3809  void rlUnloadShaderProgram(unsigned int id)
  3810  {
  3811  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3812      glDeleteProgram(id);
  3813  
  3814      TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Unloaded shader program data from VRAM (GPU)", id);
  3815  #endif
  3816  }
  3817  
  3818  // Get shader location uniform
  3819  int rlGetLocationUniform(unsigned int shaderId, const char *uniformName)
  3820  {
  3821      int location = -1;
  3822  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3823      location = glGetUniformLocation(shaderId, uniformName);
  3824  
  3825      if (location == -1) TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to find shader uniform: %s", shaderId, uniformName);
  3826      else TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Shader uniform (%s) set at location: %i", shaderId, uniformName, location);
  3827  #endif
  3828      return location;
  3829  }
  3830  
  3831  // Get shader location attribute
  3832  int rlGetLocationAttrib(unsigned int shaderId, const char *attribName)
  3833  {
  3834      int location = -1;
  3835  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3836      location = glGetAttribLocation(shaderId, attribName);
  3837  
  3838      if (location == -1) TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to find shader attribute: %s", shaderId, attribName);
  3839      else TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Shader attribute (%s) set at location: %i", shaderId, attribName, location);
  3840  #endif
  3841      return location;
  3842  }
  3843  
  3844  // Set shader value uniform
  3845  void rlSetUniform(int locIndex, const void *value, int uniformType, int count)
  3846  {
  3847  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3848      switch (uniformType)
  3849      {
  3850          case RL_SHADER_UNIFORM_FLOAT: glUniform1fv(locIndex, count, (float *)value); break;
  3851          case RL_SHADER_UNIFORM_VEC2: glUniform2fv(locIndex, count, (float *)value); break;
  3852          case RL_SHADER_UNIFORM_VEC3: glUniform3fv(locIndex, count, (float *)value); break;
  3853          case RL_SHADER_UNIFORM_VEC4: glUniform4fv(locIndex, count, (float *)value); break;
  3854          case RL_SHADER_UNIFORM_INT: glUniform1iv(locIndex, count, (int *)value); break;
  3855          case RL_SHADER_UNIFORM_IVEC2: glUniform2iv(locIndex, count, (int *)value); break;
  3856          case RL_SHADER_UNIFORM_IVEC3: glUniform3iv(locIndex, count, (int *)value); break;
  3857          case RL_SHADER_UNIFORM_IVEC4: glUniform4iv(locIndex, count, (int *)value); break;
  3858          case RL_SHADER_UNIFORM_SAMPLER2D: glUniform1iv(locIndex, count, (int *)value); break;
  3859          default: TRACELOG(RL_LOG_WARNING, "SHADER: Failed to set uniform value, data type not recognized");
  3860      }
  3861  #endif
  3862  }
  3863  
  3864  // Set shader value attribute
  3865  void rlSetVertexAttributeDefault(int locIndex, const void *value, int attribType, int count)
  3866  {
  3867  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3868      switch (attribType)
  3869      {
  3870          case RL_SHADER_ATTRIB_FLOAT: if (count == 1) glVertexAttrib1fv(locIndex, (float *)value); break;
  3871          case RL_SHADER_ATTRIB_VEC2: if (count == 2) glVertexAttrib2fv(locIndex, (float *)value); break;
  3872          case RL_SHADER_ATTRIB_VEC3: if (count == 3) glVertexAttrib3fv(locIndex, (float *)value); break;
  3873          case RL_SHADER_ATTRIB_VEC4: if (count == 4) glVertexAttrib4fv(locIndex, (float *)value); break;
  3874          default: TRACELOG(RL_LOG_WARNING, "SHADER: Failed to set attrib default value, data type not recognized");
  3875      }
  3876  #endif
  3877  }
  3878  
  3879  // Set shader value uniform matrix
  3880  void rlSetUniformMatrix(int locIndex, Matrix mat)
  3881  {
  3882  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3883      float matfloat[16] = {
  3884          mat.m0, mat.m1, mat.m2, mat.m3,
  3885          mat.m4, mat.m5, mat.m6, mat.m7,
  3886          mat.m8, mat.m9, mat.m10, mat.m11,
  3887          mat.m12, mat.m13, mat.m14, mat.m15
  3888      };
  3889      glUniformMatrix4fv(locIndex, 1, false, matfloat);
  3890  #endif
  3891  }
  3892  
  3893  // Set shader value uniform sampler
  3894  void rlSetUniformSampler(int locIndex, unsigned int textureId)
  3895  {
  3896  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3897      // Check if texture is already active
  3898      for (int i = 0; i < RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS; i++) if (RLGL.State.activeTextureId[i] == textureId) return;
  3899  
  3900      // Register a new active texture for the internal batch system
  3901      // NOTE: Default texture is always activated as GL_TEXTURE0
  3902      for (int i = 0; i < RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS; i++)
  3903      {
  3904          if (RLGL.State.activeTextureId[i] == 0)
  3905          {
  3906              glUniform1i(locIndex, 1 + i);              // Activate new texture unit
  3907              RLGL.State.activeTextureId[i] = textureId; // Save texture id for binding on drawing
  3908              break;
  3909          }
  3910      }
  3911  #endif
  3912  }
  3913  
  3914  // Set shader currently active (id and locations)
  3915  void rlSetShader(unsigned int id, int *locs)
  3916  {
  3917  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  3918      if (RLGL.State.currentShaderId != id)
  3919      {
  3920          rlDrawRenderBatch(RLGL.currentBatch);
  3921          RLGL.State.currentShaderId = id;
  3922          RLGL.State.currentShaderLocs = locs;
  3923      }
  3924  #endif
  3925  }
  3926  
  3927  // Load compute shader program
  3928  unsigned int rlLoadComputeShaderProgram(unsigned int shaderId)
  3929  {
  3930      unsigned int program = 0;
  3931  
  3932  #if defined(GRAPHICS_API_OPENGL_43)
  3933      GLint success = 0;
  3934      program = glCreateProgram();
  3935      glAttachShader(program, shaderId);
  3936      glLinkProgram(program);
  3937  
  3938      // NOTE: All uniform variables are intitialised to 0 when a program links
  3939  
  3940      glGetProgramiv(program, GL_LINK_STATUS, &success);
  3941  
  3942      if (success == GL_FALSE)
  3943      {
  3944          TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to link compute shader program", program);
  3945  
  3946          int maxLength = 0;
  3947          glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
  3948  
  3949          if (maxLength > 0)
  3950          {
  3951              int length = 0;
  3952              char *log = (char *)RL_CALLOC(maxLength, sizeof(char));
  3953              glGetProgramInfoLog(program, maxLength, &length, log);
  3954              TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Link error: %s", program, log);
  3955              RL_FREE(log);
  3956          }
  3957  
  3958          glDeleteProgram(program);
  3959  
  3960          program = 0;
  3961      }
  3962      else
  3963      {
  3964          // Get the size of compiled shader program (not available on OpenGL ES 2.0)
  3965          // NOTE: If GL_LINK_STATUS is GL_FALSE, program binary length is zero.
  3966          //GLint binarySize = 0;
  3967          //glGetProgramiv(id, GL_PROGRAM_BINARY_LENGTH, &binarySize);
  3968  
  3969          TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Compute shader program loaded successfully", program);
  3970      }
  3971  #endif
  3972  
  3973      return program;
  3974  }
  3975  
  3976  // Dispatch compute shader (equivalent to *draw* for graphics pilepine)
  3977  void rlComputeShaderDispatch(unsigned int groupX, unsigned int groupY, unsigned int groupZ)
  3978  {
  3979  #if defined(GRAPHICS_API_OPENGL_43)
  3980      glDispatchCompute(groupX, groupY, groupZ);
  3981  #endif
  3982  }
  3983  
  3984  // Load shader storage buffer object (SSBO)
  3985  unsigned int rlLoadShaderBuffer(unsigned int size, const void *data, int usageHint)
  3986  {
  3987      unsigned int ssbo = 0;
  3988  
  3989  #if defined(GRAPHICS_API_OPENGL_43)
  3990      glGenBuffers(1, &ssbo);
  3991      glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
  3992      glBufferData(GL_SHADER_STORAGE_BUFFER, size, data, usageHint? usageHint : RL_STREAM_COPY);
  3993      glClearBufferData(GL_SHADER_STORAGE_BUFFER, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, 0);
  3994      glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
  3995  #endif
  3996  
  3997      return ssbo;
  3998  }
  3999  
  4000  // Unload shader storage buffer object (SSBO)
  4001  void rlUnloadShaderBuffer(unsigned int ssboId)
  4002  {
  4003  #if defined(GRAPHICS_API_OPENGL_43)
  4004      glDeleteBuffers(1, &ssboId);
  4005  #endif
  4006  }
  4007  
  4008  // Update SSBO buffer data
  4009  void rlUpdateShaderBuffer(unsigned int id, const void *data, unsigned int dataSize, unsigned int offset)
  4010  {
  4011  #if defined(GRAPHICS_API_OPENGL_43)
  4012      glBindBuffer(GL_SHADER_STORAGE_BUFFER, id);
  4013      glBufferSubData(GL_SHADER_STORAGE_BUFFER, offset, dataSize, data);
  4014  #endif
  4015  }
  4016  
  4017  // Get SSBO buffer size
  4018  unsigned int rlGetShaderBufferSize(unsigned int id)
  4019  {
  4020      long long size = 0;
  4021  
  4022  #if defined(GRAPHICS_API_OPENGL_43)
  4023      glBindBuffer(GL_SHADER_STORAGE_BUFFER, id);
  4024      glGetInteger64v(GL_SHADER_STORAGE_BUFFER_SIZE, &size);
  4025  #endif
  4026  
  4027      return (size > 0)? (unsigned int)size : 0;
  4028  }
  4029  
  4030  // Read SSBO buffer data (GPU->CPU)
  4031  void rlReadShaderBuffer(unsigned int id, void *dest, unsigned int count, unsigned int offset)
  4032  {
  4033  #if defined(GRAPHICS_API_OPENGL_43)
  4034      glBindBuffer(GL_SHADER_STORAGE_BUFFER, id);
  4035      glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, offset, count, dest);
  4036  #endif
  4037  }
  4038  
  4039  // Bind SSBO buffer
  4040  void rlBindShaderBuffer(unsigned int id, unsigned int index)
  4041  {
  4042  #if defined(GRAPHICS_API_OPENGL_43)
  4043      glBindBufferBase(GL_SHADER_STORAGE_BUFFER, index, id);
  4044  #endif
  4045  }
  4046  
  4047  // Copy SSBO buffer data
  4048  void rlCopyShaderBuffer(unsigned int destId, unsigned int srcId, unsigned int destOffset, unsigned int srcOffset, unsigned int count)
  4049  {
  4050  #if defined(GRAPHICS_API_OPENGL_43)
  4051      glBindBuffer(GL_COPY_READ_BUFFER, srcId);
  4052      glBindBuffer(GL_COPY_WRITE_BUFFER, destId);
  4053      glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, srcOffset, destOffset, count);
  4054  #endif
  4055  }
  4056  
  4057  // Bind image texture
  4058  void rlBindImageTexture(unsigned int id, unsigned int index, unsigned int format, int readonly)
  4059  {
  4060  #if defined(GRAPHICS_API_OPENGL_43)
  4061      unsigned int glInternalFormat = 0, glFormat = 0, glType = 0;
  4062  
  4063      rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType);
  4064      glBindImageTexture(index, id, 0, 0, 0, readonly ? GL_READ_ONLY : GL_READ_WRITE, glInternalFormat);
  4065  #endif
  4066  }
  4067  
  4068  // Matrix state management
  4069  //-----------------------------------------------------------------------------------------
  4070  // Get internal modelview matrix
  4071  Matrix rlGetMatrixModelview(void)
  4072  {
  4073      Matrix matrix = rlMatrixIdentity();
  4074  #if defined(GRAPHICS_API_OPENGL_11)
  4075      float mat[16];
  4076      glGetFloatv(GL_MODELVIEW_MATRIX, mat);
  4077      matrix.m0 = mat[0];
  4078      matrix.m1 = mat[1];
  4079      matrix.m2 = mat[2];
  4080      matrix.m3 = mat[3];
  4081      matrix.m4 = mat[4];
  4082      matrix.m5 = mat[5];
  4083      matrix.m6 = mat[6];
  4084      matrix.m7 = mat[7];
  4085      matrix.m8 = mat[8];
  4086      matrix.m9 = mat[9];
  4087      matrix.m10 = mat[10];
  4088      matrix.m11 = mat[11];
  4089      matrix.m12 = mat[12];
  4090      matrix.m13 = mat[13];
  4091      matrix.m14 = mat[14];
  4092      matrix.m15 = mat[15];
  4093  #else
  4094      matrix = RLGL.State.modelview;
  4095  #endif
  4096      return matrix;
  4097  }
  4098  
  4099  // Get internal projection matrix
  4100  Matrix rlGetMatrixProjection(void)
  4101  {
  4102  #if defined(GRAPHICS_API_OPENGL_11)
  4103      float mat[16];
  4104      glGetFloatv(GL_PROJECTION_MATRIX,mat);
  4105      Matrix m;
  4106      m.m0 = mat[0];
  4107      m.m1 = mat[1];
  4108      m.m2 = mat[2];
  4109      m.m3 = mat[3];
  4110      m.m4 = mat[4];
  4111      m.m5 = mat[5];
  4112      m.m6 = mat[6];
  4113      m.m7 = mat[7];
  4114      m.m8 = mat[8];
  4115      m.m9 = mat[9];
  4116      m.m10 = mat[10];
  4117      m.m11 = mat[11];
  4118      m.m12 = mat[12];
  4119      m.m13 = mat[13];
  4120      m.m14 = mat[14];
  4121      m.m15 = mat[15];
  4122      return m;
  4123  #else
  4124      return RLGL.State.projection;
  4125  #endif
  4126  }
  4127  
  4128  // Get internal accumulated transform matrix
  4129  Matrix rlGetMatrixTransform(void)
  4130  {
  4131      Matrix mat = rlMatrixIdentity();
  4132  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  4133      // TODO: Consider possible transform matrices in the RLGL.State.stack
  4134      // Is this the right order? or should we start with the first stored matrix instead of the last one?
  4135      //Matrix matStackTransform = rlMatrixIdentity();
  4136      //for (int i = RLGL.State.stackCounter; i > 0; i--) matStackTransform = rlMatrixMultiply(RLGL.State.stack[i], matStackTransform);
  4137      mat = RLGL.State.transform;
  4138  #endif
  4139      return mat;
  4140  }
  4141  
  4142  // Get internal projection matrix for stereo render (selected eye)
  4143  RLAPI Matrix rlGetMatrixProjectionStereo(int eye)
  4144  {
  4145      Matrix mat = rlMatrixIdentity();
  4146  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  4147      mat = RLGL.State.projectionStereo[eye];
  4148  #endif
  4149      return mat;
  4150  }
  4151  
  4152  // Get internal view offset matrix for stereo render (selected eye)
  4153  RLAPI Matrix rlGetMatrixViewOffsetStereo(int eye)
  4154  {
  4155      Matrix mat = rlMatrixIdentity();
  4156  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  4157      mat = RLGL.State.viewOffsetStereo[eye];
  4158  #endif
  4159      return mat;
  4160  }
  4161  
  4162  // Set a custom modelview matrix (replaces internal modelview matrix)
  4163  void rlSetMatrixModelview(Matrix view)
  4164  {
  4165  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  4166      RLGL.State.modelview = view;
  4167  #endif
  4168  }
  4169  
  4170  // Set a custom projection matrix (replaces internal projection matrix)
  4171  void rlSetMatrixProjection(Matrix projection)
  4172  {
  4173  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  4174      RLGL.State.projection = projection;
  4175  #endif
  4176  }
  4177  
  4178  // Set eyes projection matrices for stereo rendering
  4179  void rlSetMatrixProjectionStereo(Matrix right, Matrix left)
  4180  {
  4181  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  4182      RLGL.State.projectionStereo[0] = right;
  4183      RLGL.State.projectionStereo[1] = left;
  4184  #endif
  4185  }
  4186  
  4187  // Set eyes view offsets matrices for stereo rendering
  4188  void rlSetMatrixViewOffsetStereo(Matrix right, Matrix left)
  4189  {
  4190  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  4191      RLGL.State.viewOffsetStereo[0] = right;
  4192      RLGL.State.viewOffsetStereo[1] = left;
  4193  #endif
  4194  }
  4195  
  4196  // Load and draw a quad in NDC
  4197  void rlLoadDrawQuad(void)
  4198  {
  4199  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  4200      unsigned int quadVAO = 0;
  4201      unsigned int quadVBO = 0;
  4202  
  4203      float vertices[] = {
  4204           // Positions         Texcoords
  4205          -1.0f,  1.0f, 0.0f,   0.0f, 1.0f,
  4206          -1.0f, -1.0f, 0.0f,   0.0f, 0.0f,
  4207           1.0f,  1.0f, 0.0f,   1.0f, 1.0f,
  4208           1.0f, -1.0f, 0.0f,   1.0f, 0.0f,
  4209      };
  4210  
  4211      // Gen VAO to contain VBO
  4212      glGenVertexArrays(1, &quadVAO);
  4213      glBindVertexArray(quadVAO);
  4214  
  4215      // Gen and fill vertex buffer (VBO)
  4216      glGenBuffers(1, &quadVBO);
  4217      glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
  4218      glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices, GL_STATIC_DRAW);
  4219  
  4220      // Bind vertex attributes (position, texcoords)
  4221      glEnableVertexAttribArray(0);
  4222      glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void *)0); // Positions
  4223      glEnableVertexAttribArray(1);
  4224      glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void *)(3*sizeof(float))); // Texcoords
  4225  
  4226      // Draw quad
  4227      glBindVertexArray(quadVAO);
  4228      glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  4229      glBindVertexArray(0);
  4230  
  4231      // Delete buffers (VBO and VAO)
  4232      glDeleteBuffers(1, &quadVBO);
  4233      glDeleteVertexArrays(1, &quadVAO);
  4234  #endif
  4235  }
  4236  
  4237  // Load and draw a cube in NDC
  4238  void rlLoadDrawCube(void)
  4239  {
  4240  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  4241      unsigned int cubeVAO = 0;
  4242      unsigned int cubeVBO = 0;
  4243  
  4244      float vertices[] = {
  4245           // Positions          Normals               Texcoords
  4246          -1.0f, -1.0f, -1.0f,   0.0f,  0.0f, -1.0f,   0.0f, 0.0f,
  4247           1.0f,  1.0f, -1.0f,   0.0f,  0.0f, -1.0f,   1.0f, 1.0f,
  4248           1.0f, -1.0f, -1.0f,   0.0f,  0.0f, -1.0f,   1.0f, 0.0f,
  4249           1.0f,  1.0f, -1.0f,   0.0f,  0.0f, -1.0f,   1.0f, 1.0f,
  4250          -1.0f, -1.0f, -1.0f,   0.0f,  0.0f, -1.0f,   0.0f, 0.0f,
  4251          -1.0f,  1.0f, -1.0f,   0.0f,  0.0f, -1.0f,   0.0f, 1.0f,
  4252          -1.0f, -1.0f,  1.0f,   0.0f,  0.0f,  1.0f,   0.0f, 0.0f,
  4253           1.0f, -1.0f,  1.0f,   0.0f,  0.0f,  1.0f,   1.0f, 0.0f,
  4254           1.0f,  1.0f,  1.0f,   0.0f,  0.0f,  1.0f,   1.0f, 1.0f,
  4255           1.0f,  1.0f,  1.0f,   0.0f,  0.0f,  1.0f,   1.0f, 1.0f,
  4256          -1.0f,  1.0f,  1.0f,   0.0f,  0.0f,  1.0f,   0.0f, 1.0f,
  4257          -1.0f, -1.0f,  1.0f,   0.0f,  0.0f,  1.0f,   0.0f, 0.0f,
  4258          -1.0f,  1.0f,  1.0f,  -1.0f,  0.0f,  0.0f,   1.0f, 0.0f,
  4259          -1.0f,  1.0f, -1.0f,  -1.0f,  0.0f,  0.0f,   1.0f, 1.0f,
  4260          -1.0f, -1.0f, -1.0f,  -1.0f,  0.0f,  0.0f,   0.0f, 1.0f,
  4261          -1.0f, -1.0f, -1.0f,  -1.0f,  0.0f,  0.0f,   0.0f, 1.0f,
  4262          -1.0f, -1.0f,  1.0f,  -1.0f,  0.0f,  0.0f,   0.0f, 0.0f,
  4263          -1.0f,  1.0f,  1.0f,  -1.0f,  0.0f,  0.0f,   1.0f, 0.0f,
  4264           1.0f,  1.0f,  1.0f,   1.0f,  0.0f,  0.0f,   1.0f, 0.0f,
  4265           1.0f, -1.0f, -1.0f,   1.0f,  0.0f,  0.0f,   0.0f, 1.0f,
  4266           1.0f,  1.0f, -1.0f,   1.0f,  0.0f,  0.0f,   1.0f, 1.0f,
  4267           1.0f, -1.0f, -1.0f,   1.0f,  0.0f,  0.0f,   0.0f, 1.0f,
  4268           1.0f,  1.0f,  1.0f,   1.0f,  0.0f,  0.0f,   1.0f, 0.0f,
  4269           1.0f, -1.0f,  1.0f,   1.0f,  0.0f,  0.0f,   0.0f, 0.0f,
  4270          -1.0f, -1.0f, -1.0f,   0.0f, -1.0f,  0.0f,   0.0f, 1.0f,
  4271           1.0f, -1.0f, -1.0f,   0.0f, -1.0f,  0.0f,   1.0f, 1.0f,
  4272           1.0f, -1.0f,  1.0f,   0.0f, -1.0f,  0.0f,   1.0f, 0.0f,
  4273           1.0f, -1.0f,  1.0f,   0.0f, -1.0f,  0.0f,   1.0f, 0.0f,
  4274          -1.0f, -1.0f,  1.0f,   0.0f, -1.0f,  0.0f,   0.0f, 0.0f,
  4275          -1.0f, -1.0f, -1.0f,   0.0f, -1.0f,  0.0f,   0.0f, 1.0f,
  4276          -1.0f,  1.0f, -1.0f,   0.0f,  1.0f,  0.0f,   0.0f, 1.0f,
  4277           1.0f,  1.0f,  1.0f,   0.0f,  1.0f,  0.0f,   1.0f, 0.0f,
  4278           1.0f,  1.0f, -1.0f,   0.0f,  1.0f,  0.0f,   1.0f, 1.0f,
  4279           1.0f,  1.0f,  1.0f,   0.0f,  1.0f,  0.0f,   1.0f, 0.0f,
  4280          -1.0f,  1.0f, -1.0f,   0.0f,  1.0f,  0.0f,   0.0f, 1.0f,
  4281          -1.0f,  1.0f,  1.0f,   0.0f,  1.0f,  0.0f,   0.0f, 0.0f
  4282      };
  4283  
  4284      // Gen VAO to contain VBO
  4285      glGenVertexArrays(1, &cubeVAO);
  4286      glBindVertexArray(cubeVAO);
  4287  
  4288      // Gen and fill vertex buffer (VBO)
  4289      glGenBuffers(1, &cubeVBO);
  4290      glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
  4291      glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
  4292  
  4293      // Bind vertex attributes (position, normals, texcoords)
  4294      glBindVertexArray(cubeVAO);
  4295      glEnableVertexAttribArray(0);
  4296      glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)0); // Positions
  4297      glEnableVertexAttribArray(1);
  4298      glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)(3*sizeof(float))); // Normals
  4299      glEnableVertexAttribArray(2);
  4300      glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)(6*sizeof(float))); // Texcoords
  4301      glBindBuffer(GL_ARRAY_BUFFER, 0);
  4302      glBindVertexArray(0);
  4303  
  4304      // Draw cube
  4305      glBindVertexArray(cubeVAO);
  4306      glDrawArrays(GL_TRIANGLES, 0, 36);
  4307      glBindVertexArray(0);
  4308  
  4309      // Delete VBO and VAO
  4310      glDeleteBuffers(1, &cubeVBO);
  4311      glDeleteVertexArrays(1, &cubeVAO);
  4312  #endif
  4313  }
  4314  
  4315  // Get name string for pixel format
  4316  const char *rlGetPixelFormatName(unsigned int format)
  4317  {
  4318      switch (format)
  4319      {
  4320          case RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: return "GRAYSCALE"; break;         // 8 bit per pixel (no alpha)
  4321          case RL_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: return "GRAY_ALPHA"; break;       // 8*2 bpp (2 channels)
  4322          case RL_PIXELFORMAT_UNCOMPRESSED_R5G6B5: return "R5G6B5"; break;               // 16 bpp
  4323          case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8: return "R8G8B8"; break;               // 24 bpp
  4324          case RL_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: return "R5G5B5A1"; break;           // 16 bpp (1 bit alpha)
  4325          case RL_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: return "R4G4B4A4"; break;           // 16 bpp (4 bit alpha)
  4326          case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: return "R8G8B8A8"; break;           // 32 bpp
  4327          case RL_PIXELFORMAT_UNCOMPRESSED_R32: return "R32"; break;                     // 32 bpp (1 channel - float)
  4328          case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32: return "R32G32B32"; break;         // 32*3 bpp (3 channels - float)
  4329          case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: return "R32G32B32A32"; break;   // 32*4 bpp (4 channels - float)
  4330          case RL_PIXELFORMAT_COMPRESSED_DXT1_RGB: return "DXT1_RGB"; break;             // 4 bpp (no alpha)
  4331          case RL_PIXELFORMAT_COMPRESSED_DXT1_RGBA: return "DXT1_RGBA"; break;           // 4 bpp (1 bit alpha)
  4332          case RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA: return "DXT3_RGBA"; break;           // 8 bpp
  4333          case RL_PIXELFORMAT_COMPRESSED_DXT5_RGBA: return "DXT5_RGBA"; break;           // 8 bpp
  4334          case RL_PIXELFORMAT_COMPRESSED_ETC1_RGB: return "ETC1_RGB"; break;             // 4 bpp
  4335          case RL_PIXELFORMAT_COMPRESSED_ETC2_RGB: return "ETC2_RGB"; break;             // 4 bpp
  4336          case RL_PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA: return "ETC2_RGBA"; break;       // 8 bpp
  4337          case RL_PIXELFORMAT_COMPRESSED_PVRT_RGB: return "PVRT_RGB"; break;             // 4 bpp
  4338          case RL_PIXELFORMAT_COMPRESSED_PVRT_RGBA: return "PVRT_RGBA"; break;           // 4 bpp
  4339          case RL_PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA: return "ASTC_4x4_RGBA"; break;   // 8 bpp
  4340          case RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: return "ASTC_8x8_RGBA"; break;   // 2 bpp
  4341          default: return "UNKNOWN"; break;
  4342      }
  4343  }
  4344  
  4345  //----------------------------------------------------------------------------------
  4346  // Module specific Functions Definition
  4347  //----------------------------------------------------------------------------------
  4348  #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  4349  // Load default shader (just vertex positioning and texture coloring)
  4350  // NOTE: This shader program is used for internal buffers
  4351  // NOTE: Loaded: RLGL.State.defaultShaderId, RLGL.State.defaultShaderLocs
  4352  static void rlLoadShaderDefault(void)
  4353  {
  4354      RLGL.State.defaultShaderLocs = (int *)RL_CALLOC(RL_MAX_SHADER_LOCATIONS, sizeof(int));
  4355  
  4356      // NOTE: All locations must be reseted to -1 (no location)
  4357      for (int i = 0; i < RL_MAX_SHADER_LOCATIONS; i++) RLGL.State.defaultShaderLocs[i] = -1;
  4358  
  4359      // Vertex shader directly defined, no external file required
  4360      const char *defaultVShaderCode =
  4361  #if defined(GRAPHICS_API_OPENGL_21)
  4362      "#version 120                       \n"
  4363      "attribute vec3 vertexPosition;     \n"
  4364      "attribute vec2 vertexTexCoord;     \n"
  4365      "attribute vec4 vertexColor;        \n"
  4366      "varying vec2 fragTexCoord;         \n"
  4367      "varying vec4 fragColor;            \n"
  4368  #elif defined(GRAPHICS_API_OPENGL_33)
  4369      "#version 330                       \n"
  4370      "in vec3 vertexPosition;            \n"
  4371      "in vec2 vertexTexCoord;            \n"
  4372      "in vec4 vertexColor;               \n"
  4373      "out vec2 fragTexCoord;             \n"
  4374      "out vec4 fragColor;                \n"
  4375  #endif
  4376  #if defined(GRAPHICS_API_OPENGL_ES2)
  4377      "#version 100                       \n"
  4378      "attribute vec3 vertexPosition;     \n"
  4379      "attribute vec2 vertexTexCoord;     \n"
  4380      "attribute vec4 vertexColor;        \n"
  4381      "varying vec2 fragTexCoord;         \n"
  4382      "varying vec4 fragColor;            \n"
  4383  #endif
  4384      "uniform mat4 mvp;                  \n"
  4385      "void main()                        \n"
  4386      "{                                  \n"
  4387      "    fragTexCoord = vertexTexCoord; \n"
  4388      "    fragColor = vertexColor;       \n"
  4389      "    gl_Position = mvp*vec4(vertexPosition, 1.0); \n"
  4390      "}                                  \n";
  4391  
  4392      // Fragment shader directly defined, no external file required
  4393      const char *defaultFShaderCode =
  4394  #if defined(GRAPHICS_API_OPENGL_21)
  4395      "#version 120                       \n"
  4396      "varying vec2 fragTexCoord;         \n"
  4397      "varying vec4 fragColor;            \n"
  4398      "uniform sampler2D texture0;        \n"
  4399      "uniform vec4 colDiffuse;           \n"
  4400      "void main()                        \n"
  4401      "{                                  \n"
  4402      "    vec4 texelColor = texture2D(texture0, fragTexCoord); \n"
  4403      "    gl_FragColor = texelColor*colDiffuse*fragColor;      \n"
  4404      "}                                  \n";
  4405  #elif defined(GRAPHICS_API_OPENGL_33)
  4406      "#version 330       \n"
  4407      "in vec2 fragTexCoord;              \n"
  4408      "in vec4 fragColor;                 \n"
  4409      "out vec4 finalColor;               \n"
  4410      "uniform sampler2D texture0;        \n"
  4411      "uniform vec4 colDiffuse;           \n"
  4412      "void main()                        \n"
  4413      "{                                  \n"
  4414      "    vec4 texelColor = texture(texture0, fragTexCoord);   \n"
  4415      "    finalColor = texelColor*colDiffuse*fragColor;        \n"
  4416      "}                                  \n";
  4417  #endif
  4418  #if defined(GRAPHICS_API_OPENGL_ES2)
  4419      "#version 100                       \n"
  4420      "precision mediump float;           \n"     // Precision required for OpenGL ES2 (WebGL)
  4421      "varying vec2 fragTexCoord;         \n"
  4422      "varying vec4 fragColor;            \n"
  4423      "uniform sampler2D texture0;        \n"
  4424      "uniform vec4 colDiffuse;           \n"
  4425      "void main()                        \n"
  4426      "{                                  \n"
  4427      "    vec4 texelColor = texture2D(texture0, fragTexCoord); \n"
  4428      "    gl_FragColor = texelColor*colDiffuse*fragColor;      \n"
  4429      "}                                  \n";
  4430  #endif
  4431  
  4432      // NOTE: Compiled vertex/fragment shaders are not deleted,
  4433      // they are kept for re-use as default shaders in case some shader loading fails
  4434      RLGL.State.defaultVShaderId = rlCompileShader(defaultVShaderCode, GL_VERTEX_SHADER);     // Compile default vertex shader
  4435      RLGL.State.defaultFShaderId = rlCompileShader(defaultFShaderCode, GL_FRAGMENT_SHADER);   // Compile default fragment shader
  4436  
  4437      RLGL.State.defaultShaderId = rlLoadShaderProgram(RLGL.State.defaultVShaderId, RLGL.State.defaultFShaderId);
  4438  
  4439      if (RLGL.State.defaultShaderId > 0)
  4440      {
  4441          TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Default shader loaded successfully", RLGL.State.defaultShaderId);
  4442  
  4443          // Set default shader locations: attributes locations
  4444          RLGL.State.defaultShaderLocs[RL_SHADER_LOC_VERTEX_POSITION] = glGetAttribLocation(RLGL.State.defaultShaderId, "vertexPosition");
  4445          RLGL.State.defaultShaderLocs[RL_SHADER_LOC_VERTEX_TEXCOORD01] = glGetAttribLocation(RLGL.State.defaultShaderId, "vertexTexCoord");
  4446          RLGL.State.defaultShaderLocs[RL_SHADER_LOC_VERTEX_COLOR] = glGetAttribLocation(RLGL.State.defaultShaderId, "vertexColor");
  4447  
  4448          // Set default shader locations: uniform locations
  4449          RLGL.State.defaultShaderLocs[RL_SHADER_LOC_MATRIX_MVP]  = glGetUniformLocation(RLGL.State.defaultShaderId, "mvp");
  4450          RLGL.State.defaultShaderLocs[RL_SHADER_LOC_COLOR_DIFFUSE] = glGetUniformLocation(RLGL.State.defaultShaderId, "colDiffuse");
  4451          RLGL.State.defaultShaderLocs[RL_SHADER_LOC_MAP_DIFFUSE] = glGetUniformLocation(RLGL.State.defaultShaderId, "texture0");
  4452      }
  4453      else TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to load default shader", RLGL.State.defaultShaderId);
  4454  }
  4455  
  4456  // Unload default shader
  4457  // NOTE: Unloads: RLGL.State.defaultShaderId, RLGL.State.defaultShaderLocs
  4458  static void rlUnloadShaderDefault(void)
  4459  {
  4460      glUseProgram(0);
  4461  
  4462      glDetachShader(RLGL.State.defaultShaderId, RLGL.State.defaultVShaderId);
  4463      glDetachShader(RLGL.State.defaultShaderId, RLGL.State.defaultFShaderId);
  4464      glDeleteShader(RLGL.State.defaultVShaderId);
  4465      glDeleteShader(RLGL.State.defaultFShaderId);
  4466  
  4467      glDeleteProgram(RLGL.State.defaultShaderId);
  4468  
  4469      RL_FREE(RLGL.State.defaultShaderLocs);
  4470  
  4471      TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Default shader unloaded successfully", RLGL.State.defaultShaderId);
  4472  }
  4473  
  4474  #if defined(RLGL_SHOW_GL_DETAILS_INFO)
  4475  // Get compressed format official GL identifier name
  4476  static char *rlGetCompressedFormatName(int format)
  4477  {
  4478      switch (format)
  4479      {
  4480          // GL_EXT_texture_compression_s3tc
  4481          case 0x83F0: return "GL_COMPRESSED_RGB_S3TC_DXT1_EXT"; break;
  4482          case 0x83F1: return "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT"; break;
  4483          case 0x83F2: return "GL_COMPRESSED_RGBA_S3TC_DXT3_EXT"; break;
  4484          case 0x83F3: return "GL_COMPRESSED_RGBA_S3TC_DXT5_EXT"; break;
  4485          // GL_3DFX_texture_compression_FXT1
  4486          case 0x86B0: return "GL_COMPRESSED_RGB_FXT1_3DFX"; break;
  4487          case 0x86B1: return "GL_COMPRESSED_RGBA_FXT1_3DFX"; break;
  4488          // GL_IMG_texture_compression_pvrtc
  4489          case 0x8C00: return "GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG"; break;
  4490          case 0x8C01: return "GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG"; break;
  4491          case 0x8C02: return "GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG"; break;
  4492          case 0x8C03: return "GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG"; break;
  4493          // GL_OES_compressed_ETC1_RGB8_texture
  4494          case 0x8D64: return "GL_ETC1_RGB8_OES"; break;
  4495          // GL_ARB_texture_compression_rgtc
  4496          case 0x8DBB: return "GL_COMPRESSED_RED_RGTC1"; break;
  4497          case 0x8DBC: return "GL_COMPRESSED_SIGNED_RED_RGTC1"; break;
  4498          case 0x8DBD: return "GL_COMPRESSED_RG_RGTC2"; break;
  4499          case 0x8DBE: return "GL_COMPRESSED_SIGNED_RG_RGTC2"; break;
  4500          // GL_ARB_texture_compression_bptc
  4501          case 0x8E8C: return "GL_COMPRESSED_RGBA_BPTC_UNORM_ARB"; break;
  4502          case 0x8E8D: return "GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB"; break;
  4503          case 0x8E8E: return "GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB"; break;
  4504          case 0x8E8F: return "GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB"; break;
  4505          // GL_ARB_ES3_compatibility
  4506          case 0x9274: return "GL_COMPRESSED_RGB8_ETC2"; break;
  4507          case 0x9275: return "GL_COMPRESSED_SRGB8_ETC2"; break;
  4508          case 0x9276: return "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2"; break;
  4509          case 0x9277: return "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2"; break;
  4510          case 0x9278: return "GL_COMPRESSED_RGBA8_ETC2_EAC"; break;
  4511          case 0x9279: return "GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC"; break;
  4512          case 0x9270: return "GL_COMPRESSED_R11_EAC"; break;
  4513          case 0x9271: return "GL_COMPRESSED_SIGNED_R11_EAC"; break;
  4514          case 0x9272: return "GL_COMPRESSED_RG11_EAC"; break;
  4515          case 0x9273: return "GL_COMPRESSED_SIGNED_RG11_EAC"; break;
  4516          // GL_KHR_texture_compression_astc_hdr
  4517          case 0x93B0: return "GL_COMPRESSED_RGBA_ASTC_4x4_KHR"; break;
  4518          case 0x93B1: return "GL_COMPRESSED_RGBA_ASTC_5x4_KHR"; break;
  4519          case 0x93B2: return "GL_COMPRESSED_RGBA_ASTC_5x5_KHR"; break;
  4520          case 0x93B3: return "GL_COMPRESSED_RGBA_ASTC_6x5_KHR"; break;
  4521          case 0x93B4: return "GL_COMPRESSED_RGBA_ASTC_6x6_KHR"; break;
  4522          case 0x93B5: return "GL_COMPRESSED_RGBA_ASTC_8x5_KHR"; break;
  4523          case 0x93B6: return "GL_COMPRESSED_RGBA_ASTC_8x6_KHR"; break;
  4524          case 0x93B7: return "GL_COMPRESSED_RGBA_ASTC_8x8_KHR"; break;
  4525          case 0x93B8: return "GL_COMPRESSED_RGBA_ASTC_10x5_KHR"; break;
  4526          case 0x93B9: return "GL_COMPRESSED_RGBA_ASTC_10x6_KHR"; break;
  4527          case 0x93BA: return "GL_COMPRESSED_RGBA_ASTC_10x8_KHR"; break;
  4528          case 0x93BB: return "GL_COMPRESSED_RGBA_ASTC_10x10_KHR"; break;
  4529          case 0x93BC: return "GL_COMPRESSED_RGBA_ASTC_12x10_KHR"; break;
  4530          case 0x93BD: return "GL_COMPRESSED_RGBA_ASTC_12x12_KHR"; break;
  4531          case 0x93D0: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR"; break;
  4532          case 0x93D1: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR"; break;
  4533          case 0x93D2: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR"; break;
  4534          case 0x93D3: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR"; break;
  4535          case 0x93D4: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR"; break;
  4536          case 0x93D5: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR"; break;
  4537          case 0x93D6: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR"; break;
  4538          case 0x93D7: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR"; break;
  4539          case 0x93D8: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR"; break;
  4540          case 0x93D9: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR"; break;
  4541          case 0x93DA: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR"; break;
  4542          case 0x93DB: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR"; break;
  4543          case 0x93DC: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR"; break;
  4544          case 0x93DD: return "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR"; break;
  4545          default: return "GL_COMPRESSED_UNKNOWN"; break;
  4546      }
  4547  }
  4548  #endif  // RLGL_SHOW_GL_DETAILS_INFO
  4549  
  4550  #endif  // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
  4551  
  4552  // Get pixel data size in bytes (image or texture)
  4553  // NOTE: Size depends on pixel format
  4554  static int rlGetPixelDataSize(int width, int height, int format)
  4555  {
  4556      int dataSize = 0;       // Size in bytes
  4557      int bpp = 0;            // Bits per pixel
  4558  
  4559      switch (format)
  4560      {
  4561          case RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: bpp = 8; break;
  4562          case RL_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA:
  4563          case RL_PIXELFORMAT_UNCOMPRESSED_R5G6B5:
  4564          case RL_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1:
  4565          case RL_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: bpp = 16; break;
  4566          case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: bpp = 32; break;
  4567          case RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8: bpp = 24; break;
  4568          case RL_PIXELFORMAT_UNCOMPRESSED_R32: bpp = 32; break;
  4569          case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32: bpp = 32*3; break;
  4570          case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: bpp = 32*4; break;
  4571          case RL_PIXELFORMAT_COMPRESSED_DXT1_RGB:
  4572          case RL_PIXELFORMAT_COMPRESSED_DXT1_RGBA:
  4573          case RL_PIXELFORMAT_COMPRESSED_ETC1_RGB:
  4574          case RL_PIXELFORMAT_COMPRESSED_ETC2_RGB:
  4575          case RL_PIXELFORMAT_COMPRESSED_PVRT_RGB:
  4576          case RL_PIXELFORMAT_COMPRESSED_PVRT_RGBA: bpp = 4; break;
  4577          case RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA:
  4578          case RL_PIXELFORMAT_COMPRESSED_DXT5_RGBA:
  4579          case RL_PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA:
  4580          case RL_PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA: bpp = 8; break;
  4581          case RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: bpp = 2; break;
  4582          default: break;
  4583      }
  4584  
  4585      dataSize = width*height*bpp/8;  // Total data size in bytes
  4586  
  4587      // Most compressed formats works on 4x4 blocks,
  4588      // if texture is smaller, minimum dataSize is 8 or 16
  4589      if ((width < 4) && (height < 4))
  4590      {
  4591          if ((format >= RL_PIXELFORMAT_COMPRESSED_DXT1_RGB) && (format < RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA)) dataSize = 8;
  4592          else if ((format >= RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA) && (format < RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA)) dataSize = 16;
  4593      }
  4594  
  4595      return dataSize;
  4596  }
  4597  
  4598  // Auxiliar math functions
  4599  
  4600  // Get identity matrix
  4601  static Matrix rlMatrixIdentity(void)
  4602  {
  4603      Matrix result = {
  4604          1.0f, 0.0f, 0.0f, 0.0f,
  4605          0.0f, 1.0f, 0.0f, 0.0f,
  4606          0.0f, 0.0f, 1.0f, 0.0f,
  4607          0.0f, 0.0f, 0.0f, 1.0f
  4608      };
  4609  
  4610      return result;
  4611  }
  4612  
  4613  // Get two matrix multiplication
  4614  // NOTE: When multiplying matrices... the order matters!
  4615  static Matrix rlMatrixMultiply(Matrix left, Matrix right)
  4616  {
  4617      Matrix result = { 0 };
  4618  
  4619      result.m0 = left.m0*right.m0 + left.m1*right.m4 + left.m2*right.m8 + left.m3*right.m12;
  4620      result.m1 = left.m0*right.m1 + left.m1*right.m5 + left.m2*right.m9 + left.m3*right.m13;
  4621      result.m2 = left.m0*right.m2 + left.m1*right.m6 + left.m2*right.m10 + left.m3*right.m14;
  4622      result.m3 = left.m0*right.m3 + left.m1*right.m7 + left.m2*right.m11 + left.m3*right.m15;
  4623      result.m4 = left.m4*right.m0 + left.m5*right.m4 + left.m6*right.m8 + left.m7*right.m12;
  4624      result.m5 = left.m4*right.m1 + left.m5*right.m5 + left.m6*right.m9 + left.m7*right.m13;
  4625      result.m6 = left.m4*right.m2 + left.m5*right.m6 + left.m6*right.m10 + left.m7*right.m14;
  4626      result.m7 = left.m4*right.m3 + left.m5*right.m7 + left.m6*right.m11 + left.m7*right.m15;
  4627      result.m8 = left.m8*right.m0 + left.m9*right.m4 + left.m10*right.m8 + left.m11*right.m12;
  4628      result.m9 = left.m8*right.m1 + left.m9*right.m5 + left.m10*right.m9 + left.m11*right.m13;
  4629      result.m10 = left.m8*right.m2 + left.m9*right.m6 + left.m10*right.m10 + left.m11*right.m14;
  4630      result.m11 = left.m8*right.m3 + left.m9*right.m7 + left.m10*right.m11 + left.m11*right.m15;
  4631      result.m12 = left.m12*right.m0 + left.m13*right.m4 + left.m14*right.m8 + left.m15*right.m12;
  4632      result.m13 = left.m12*right.m1 + left.m13*right.m5 + left.m14*right.m9 + left.m15*right.m13;
  4633      result.m14 = left.m12*right.m2 + left.m13*right.m6 + left.m14*right.m10 + left.m15*right.m14;
  4634      result.m15 = left.m12*right.m3 + left.m13*right.m7 + left.m14*right.m11 + left.m15*right.m15;
  4635  
  4636      return result;
  4637  }
  4638  
  4639  #endif  // RLGL_IMPLEMENTATION