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