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