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