Logo

index : raylib-jai

---

  • summary
  • about
  • tree
  • log
  • branches
<< path: root/public/raylib-jai.git/html/Raylib/raylib/src/rlgl.h blob: cda64896c51ed2adc1b10c746ab5d8dff270a8f6 [raw] [clear marker]

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