GCC Code Coverage Report


Directory: ./
File: submodules/raylib/src/rlgl.h
Date: 2023-09-29 04:53:15
Exec Total Coverage
Lines: 0 1097 0.0%
Branches: 0 533 0.0%

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