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