summaryrefslogtreecommitdiffhomepage
path: root/src/rlgl.h
diff options
context:
space:
mode:
authorRay <[email protected]>2021-03-22 20:45:04 +0100
committerRay <[email protected]>2021-03-22 20:45:04 +0100
commit2ce28f75addd22a5b56dc68738e6a72af74f125d (patch)
tree922240e1d418688425ff1a4e4775a8bd2a0985aa /src/rlgl.h
parent24dae29a0344823e3a8306f0685664f1580a7751 (diff)
downloadraylib-2ce28f75addd22a5b56dc68738e6a72af74f125d.tar.gz
raylib-2ce28f75addd22a5b56dc68738e6a72af74f125d.zip
WARNING: BREAKING: REDESIGNED: rlgl module
- Many functions renamed to follow rl*() convention - Some internal functions exposed in the API - Some functionality moved to other modules - Reorganized all functions by categories - Make sure it keeps working with OpenGL 1.1 and 2.1
Diffstat (limited to 'src/rlgl.h')
-rw-r--r--src/rlgl.h1847
1 files changed, 920 insertions, 927 deletions
diff --git a/src/rlgl.h b/src/rlgl.h
index 3f3e4fc6..82895d06 100644
--- a/src/rlgl.h
+++ b/src/rlgl.h
@@ -1,6 +1,6 @@
/**********************************************************************************************
*
-* rlgl v3.2 - raylib OpenGL abstraction layer
+* rlgl v3.7 - raylib OpenGL abstraction layer
*
* rlgl is a wrapper for multiple OpenGL versions (1.1, 2.1, 3.3 Core, ES 2.0) to
* pseudo-OpenGL 1.1 style functions (rlVertex, rlTranslate, rlRotate...).
@@ -92,7 +92,7 @@
#define RL_FREE(p) free(p)
#endif
#else
- #include "raylib.h" // Required for: Model, Shader, Texture2D, TRACELOG()
+ #include "raylib.h" // Required for: Model, Mesh, Material, Shader, Texture2D
#endif
#include "raymath.h" // Required for: Vector3, Matrix
@@ -233,7 +233,7 @@ typedef enum {
RL_ATTACHMENT_CUBEMAP_NEGATIVE_Z,
RL_ATTACHMENT_TEXTURE2D = 100,
RL_ATTACHMENT_RENDERBUFFER = 200,
-} FramebufferTexType;
+} FramebufferAttachTextureType;
// Dynamic vertex buffers (position + texcoords + colors + indices arrays)
typedef struct VertexBuffer {
@@ -268,8 +268,8 @@ typedef struct DrawCall {
//unsigned int shaderId; // Shader id to be used on the draw -> Using RLGL.currentShader.id
unsigned int textureId; // Texture id to be used on the draw -> Use to create new draw call if changes
- //Matrix projection; // Projection matrix for this draw -> Using RLGL.projection
- //Matrix modelview; // Modelview matrix for this draw -> Using RLGL.modelview
+ //Matrix projection; // Projection matrix for this draw -> Using RLGL.projection by default
+ //Matrix modelview; // Modelview matrix for this draw -> Using RLGL.modelview by default
} DrawCall;
// RenderBatch type
@@ -364,14 +364,6 @@ typedef struct RenderBatch {
float params[4]; // Material generic parameters (if required)
} Material;
- // Camera type, defines a camera position/orientation in 3d space
- typedef struct Camera {
- Vector3 position; // Camera position
- Vector3 target; // Camera target it looks-at
- Vector3 up; // Camera up vector (rotation over its axis)
- float fovy; // Camera field-of-view apperture in Y (degrees)
- } Camera;
-
// TraceLog message types
typedef enum {
LOG_ALL,
@@ -537,8 +529,9 @@ RLAPI void rlColor3f(float x, float y, float z); // Define one vertex (
RLAPI void rlColor4f(float x, float y, float z, float w); // Define one vertex (color) - 4 float
//------------------------------------------------------------------------------------
-// Functions Declaration - OpenGL equivalent functions (common to 1.1, 3.3+, ES2)
-// NOTE: This functions are used to completely abstract raylib code from OpenGL layer
+// Functions Declaration - OpenGL style functions (common to 1.1, 3.3+, ES2)
+// NOTE: This functions are used to completely abstract raylib code from OpenGL layer,
+// some of them are direct wrappers over OpenGL calls, some others are custom
//------------------------------------------------------------------------------------
RLAPI void rlEnableTexture(unsigned int id); // Enable texture usage
RLAPI void rlDisableTexture(void); // Disable texture usage
@@ -567,19 +560,34 @@ RLAPI void rlDisableStereoRender(void); // Disable stereo renderin
RLAPI void rlClearColor(unsigned char r, unsigned char g, unsigned char b, unsigned char a); // Clear color buffer with color
RLAPI void rlClearScreenBuffers(void); // Clear used screen buffers (color and depth)
+RLAPI void rlCheckErrors(void); // Check and log OpenGL error codes
+RLAPI void rlSetBlendMode(int mode); // Set blending mode
+RLAPI void rlSetBlendFactors(int glSrcFactor, int glDstFactor, int glEquation); // Set blending mode factor and equation (using OpenGL factors)
//------------------------------------------------------------------------------------
// Functions Declaration - rlgl functionality
//------------------------------------------------------------------------------------
+// rlgl initialization functions
RLAPI void rlglInit(int width, int height); // Initialize rlgl (buffers, shaders, textures, states)
RLAPI void rlglClose(void); // De-inititialize rlgl (buffers, shaders, textures)
-
+RLAPI void rlLoadExtensions(void* loader); // Load OpenGL extensions (loader function pointer required)
RLAPI int rlGetVersion(void); // Returns current OpenGL version
-RLAPI void rlCheckErrors(void); // Check and log OpenGL error codes
-RLAPI void rlLoadExtensions(void *loader); // Load OpenGL extensions (loader function pointer required)
-RLAPI void rlSetBlendMode(int mode); // Set blending mode
-RLAPI void rlSetBlendFactors(int glSrcFactor, int glDstFactor, int glEquation); // Set blending mode factor and equation (using OpenGL factors)
+RLAPI Shader rlGetShaderDefault(void); // Get default shader
+RLAPI Texture2D rlGetTextureDefault(void); // Get default texture
+RLAPI Texture2D rlGetShapesTexture(void); // Get texture to draw shapes
+RLAPI Rectangle rlGetShapesTextureRec(void); // Get texture rectangle to draw shapes
+RLAPI void rlSetShapesTexture(Texture2D texture, Rectangle source); // Define default texture used to draw shapes
+
+// Render batch management
+// NOTE: rlgl provides a default render batch to behave like OpenGL 1.1 immediate mode
+// but this render batch API is exposed in case of custom batches are required
+RLAPI RenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements); // Load a render batch system
+RLAPI void rlUnloadRenderBatch(RenderBatch batch); // Unload render batch system
+RLAPI void rlDrawRenderBatch(RenderBatch *batch); // Draw render batch data (Update->Draw->Reset)
+RLAPI void rlSetRenderBatchActive(RenderBatch *batch); // Set the active render batch for rlgl (NULL for default internal)
+RLAPI void rlDrawRenderBatchActive(void); // Update and draw internal render batch
+RLAPI bool rlCheckRenderBatchLimit(int vCount); // Check internal buffer overflow for a given number of vertex
// Textures data management
RLAPI unsigned int rlLoadTexture(void *data, int width, int height, int format, int mipmapCount); // Load texture in GPU
@@ -588,19 +596,10 @@ RLAPI unsigned int rlLoadTextureCubemap(void *data, int size, int format);
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
RLAPI void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned int *glFormat, unsigned int *glType); // Get OpenGL internal formats
RLAPI void rlUnloadTexture(unsigned int id); // Unload texture from GPU memory
-
RLAPI void rlGenerateMipmaps(Texture2D *texture); // Generate mipmap data for selected texture
RLAPI void *rlReadTexturePixels(Texture2D texture); // Read texture pixel data
RLAPI unsigned char *rlReadScreenPixels(int width, int height); // Read screen pixel data (color buffer)
-// OpenGL state management
-RLAPI Matrix rlGetMatrixModelview(void); // Get internal modelview matrix
-RLAPI Matrix rlGetMatrixProjection(void); // Get internal projection matrix
-RLAPI void rlSetMatrixProjection(Matrix proj); // Set a custom projection matrix (replaces internal projection matrix)
-RLAPI void rlSetMatrixModelview(Matrix view); // Set a custom modelview matrix (replaces internal modelview matrix)
-RLAPI void rlSetMatrixProjectionStereo(Matrix right, Matrix left); // Set eyes projection matrices for stereo rendering
-RLAPI void rlSetMatrixViewOffsetStereo(Matrix right, Matrix left); // Set eyes view offsets matrices for stereo rendering
-
// Framebuffer management (fbo)
RLAPI unsigned int rlLoadFramebuffer(int width, int height); // Load an empty framebuffer
RLAPI void rlFramebufferAttach(unsigned int fboId, unsigned int texId, int attachType, int texType); // Attach texture/renderbuffer to a framebuffer
@@ -608,40 +607,38 @@ RLAPI bool rlFramebufferComplete(unsigned int id); // Ver
RLAPI void rlUnloadFramebuffer(unsigned int id); // Delete framebuffer from GPU
// Vertex data management
+// TODO: Avoid dealing with Mesh and Material structs?
RLAPI void rlLoadMesh(Mesh *mesh, bool dynamic); // Upload vertex data into GPU and provided VAO/VBO ids
+RLAPI unsigned int rlLoadVertexBuffer(unsigned int vaoId, int index, void *buffer, int size, bool dynamic); // Load a vertex buffer attribute
RLAPI void rlUpdateMesh(Mesh mesh, int buffer, int count); // Update vertex or index data on GPU (upload new data to one buffer)
RLAPI void rlUpdateMeshAt(Mesh mesh, int buffer, int count, int index); // Update vertex or index data on GPU, at index
+RLAPI void rlUpdateBuffer(int bufferId, void *data, int dataSize); // Update GPU buffer with new data
RLAPI void rlDrawMesh(Mesh mesh, Material material, Matrix transform); // Draw a 3d mesh with material and transform
RLAPI void rlDrawMeshInstanced(Mesh mesh, Material material, Matrix *transforms, int count); // Draw a 3d mesh with material and transform
RLAPI void rlUnloadMesh(Mesh *mesh); // Unload mesh data from CPU and GPU
-RLAPI unsigned int rlLoadVertexBuffer(unsigned int vaoId, int index, void *buffer, int size, bool dynamic); // Load a vertex buffer attribute
-RLAPI void rlUpdateBuffer(int bufferId, void *data, int dataSize); // Update GPU buffer with new data
-
// Shaders management
RLAPI unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode); // Load shader from code strings
+RLAPI unsigned int rlCompileShader(const char *shaderCode, int type); // Compile custom shader and return shader id (type: GL_VERTEX_SHADER, GL_FRAGMENT_SHADER)
+RLAPI unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId); // Load custom shader program
+RLAPI void rlUnloadShaderProgram(unsigned int id); // Unload shader program
RLAPI int rlGetLocationUniform(unsigned int shaderId, const char *uniformName); // Get shader location uniform
RLAPI int rlGetLocationAttrib(unsigned int shaderId, const char *attribName); // Get shader location attribute
RLAPI void rlSetUniform(int locIndex, const void *value, int uniformType, int count); // Set shader value uniform
RLAPI void rlSetUniformMatrix(int locIndex, Matrix mat); // Set shader value matrix
RLAPI void rlSetUniformSampler(int locIndex, Texture2D texture); // Set shader value sampler
+RLAPI void rlSetShaderActive(Shader shader); // Set shader currently active
-// Render batch mangement
-RLAPI bool rlCheckRenderBatchLimit(int vCount); // Check internal buffer overflow for a given number of vertex
-RLAPI RenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements); // Load a render batch system
-RLAPI void rlUnloadRenderBatch(RenderBatch batch); // Unload render batch system
-RLAPI void rlDrawRenderBatch(RenderBatch *batch); // Draw render batch data (Update->Draw->Reset)
-RLAPI void rlSetRenderBatchActive(RenderBatch *batch); // Set the active render batch for rlgl
-RLAPI void rlSetRenderBatchDefault(void); // Set default render batch for rlgl
-
-RLAPI Shader rlGetShaderDefault(void); // Get default shader
-RLAPI Texture2D rlGetTextureDefault(void); // Get default texture
-RLAPI Texture2D rlGetShapesTexture(void); // Get texture to draw shapes
-RLAPI Rectangle rlGetShapesTextureRec(void); // Get texture rectangle to draw shapes
-RLAPI void rlSetShapesTexture(Texture2D texture, Rectangle source); // Define default texture used to draw shapes
+// Matrix state management
+RLAPI Matrix rlGetMatrixModelview(void); // Get internal modelview matrix
+RLAPI Matrix rlGetMatrixProjection(void); // Get internal projection matrix
+RLAPI void rlSetMatrixProjection(Matrix proj); // Set a custom projection matrix (replaces internal projection matrix)
+RLAPI void rlSetMatrixModelview(Matrix view); // Set a custom modelview matrix (replaces internal modelview matrix)
+RLAPI void rlSetMatrixProjectionStereo(Matrix right, Matrix left); // Set eyes projection matrices for stereo rendering
+RLAPI void rlSetMatrixViewOffsetStereo(Matrix right, Matrix left); // Set eyes view offsets matrices for stereo rendering
// Texture maps generation (PBR)
-// NOTE: Required shaders should be provided
+// TODO: Redesign or remove to avoid requiring external shaders
RLAPI TextureCubemap rlGenTextureCubemap(Shader shader, Texture2D panorama, int size, int format); // Generate cubemap (6 faces) from equirectangular (panorama) texture
RLAPI TextureCubemap rlGenTextureIrradiance(Shader shader, TextureCubemap cubemap, int size); // Generate irradiance cubemap using cubemap texture
RLAPI TextureCubemap rlGenTexturePrefilter(Shader shader, TextureCubemap cubemap, int size); // Generate prefilter cubemap using cubemap texture
@@ -891,21 +888,16 @@ static PFNGLVERTEXATTRIBDIVISOREXTPROC glVertexAttribDivisor = NULL;
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-static unsigned int CompileShader(const char *shaderStr, int type); // Compile custom shader and return shader id
-static unsigned int LoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId); // Load custom shader program
+static Shader rlLoadShaderDefault(void); // Load default shader (just vertex positioning and texture coloring)
+static void rlUnloadShaderDefault(void); // Unload default shader
-static Shader LoadShaderDefault(void); // Load default shader (just vertex positioning and texture coloring)
-static void SetShaderDefaultLocations(Shader *shader); // Bind default shader locations (attributes and uniforms)
-static void UnloadShaderDefault(void); // Unload default shader
-
-static void GenDrawCube(void); // Generate and draw cube
-static void GenDrawQuad(void); // Generate and draw quad
+static void rlGenDrawCube(void); // Generate and draw cube
+static void rlGenDrawQuad(void); // Generate and draw quad
#endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
#if defined(GRAPHICS_API_OPENGL_11)
-static int GenerateMipmaps(unsigned char *data, int baseWidth, int baseHeight);
-static Color *GenNextMipmap(Color *srcData, int srcWidth, int srcHeight);
+static int rlGenerateMipmapsData(unsigned char *data, int baseWidth, int baseHeight); // Generate mipmaps data on CPU side
+static Color *rlGenNextMipmapData(Color *srcData, int srcWidth, int srcHeight); // Geenrate next mipmap level on CPU side
#endif
-
static int rlGetPixelDataSize(int width, int height, int format); // Get pixel data size in bytes (image or texture)
//----------------------------------------------------------------------------------
@@ -1253,9 +1245,9 @@ void rlColor3f(float x, float y, float z)
#endif
-//----------------------------------------------------------------------------------
-// Module Functions Definition - OpenGL equivalent functions (common to 1.1, 3.3+, ES2)
-//----------------------------------------------------------------------------------
+//--------------------------------------------------------------------------------------
+// Module Functions Definition - OpenGL style functions (common to 1.1, 3.3+, ES2)
+//--------------------------------------------------------------------------------------
// Enable texture usage
void rlEnableTexture(unsigned int id)
@@ -1459,38 +1451,16 @@ void rlDisableSmoothLines(void)
// Enable stereo rendering
void rlEnableStereoRender(void)
{
+#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2))
RLGL.State.stereoRender = true;
+#endif
}
// Disable stereo rendering
void rlDisableStereoRender(void)
{
+#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2))
RLGL.State.stereoRender = false;
-}
-
-// Unload framebuffer from GPU memory
-// NOTE: All attached textures/cubemaps/renderbuffers are also deleted
-void rlUnloadFramebuffer(unsigned int id)
-{
-#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(SUPPORT_RENDER_TEXTURES_HINT)
-
- // Query depth attachment to automatically delete texture/renderbuffer
- int depthType = 0, depthId = 0;
- glBindFramebuffer(GL_FRAMEBUFFER, id); // Bind framebuffer to query depth texture type
- glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &depthType);
- glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &depthId);
-
- unsigned int depthIdU = (unsigned int)depthId;
- if (depthType == GL_RENDERBUFFER) glDeleteRenderbuffers(1, &depthIdU);
- else if (depthType == GL_RENDERBUFFER) glDeleteTextures(1, &depthIdU);
-
- // NOTE: If a texture object is deleted while its image is attached to the *currently bound* framebuffer,
- // the texture image is automatically detached from the currently bound framebuffer.
-
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- glDeleteFramebuffers(1, &id);
-
- TRACELOG(LOG_INFO, "FBO: [ID %i] Unloaded framebuffer from VRAM (GPU)", id);
#endif
}
@@ -1513,17 +1483,66 @@ void rlClearScreenBuffers(void)
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // Stencil buffer not used...
}
-// Update GPU buffer with new data
-void rlUpdateBuffer(int bufferId, void *data, int dataSize)
+// Check and log OpenGL error codes
+void rlCheckErrors()
+{
+#if defined(GRAPHICS_API_OPENGL_21) || defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+ int check = 1;
+ while (check)
+ {
+ const GLenum err = glGetError();
+ switch (err)
+ {
+ case GL_NO_ERROR: check = 0; break;
+ case 0x0500: TRACELOG(LOG_WARNING, "GL: Error detected: GL_INVALID_ENUM"); break;
+ case 0x0501: TRACELOG(LOG_WARNING, "GL: Error detected: GL_INVALID_VALUE"); break;
+ case 0x0502: TRACELOG(LOG_WARNING, "GL: Error detected: GL_INVALID_OPERATION"); break;
+ case 0x0503: TRACELOG(LOG_WARNING, "GL: Error detected: GL_STACK_OVERFLOW"); break;
+ case 0x0504: TRACELOG(LOG_WARNING, "GL: Error detected: GL_STACK_UNDERFLOW"); break;
+ case 0x0505: TRACELOG(LOG_WARNING, "GL: Error detected: GL_OUT_OF_MEMORY"); break;
+ case 0x0506: TRACELOG(LOG_WARNING, "GL: Error detected: GL_INVALID_FRAMEBUFFER_OPERATION"); break;
+ default: TRACELOG(LOG_WARNING, "GL: Error detected: Unknown error code: %x", err); break;
+ }
+ }
+#endif
+}
+
+// Set blend mode
+void rlSetBlendMode(int mode)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- glBindBuffer(GL_ARRAY_BUFFER, bufferId);
- glBufferSubData(GL_ARRAY_BUFFER, 0, dataSize, data);
+ if (RLGL.State.currentBlendMode != mode)
+ {
+ rlDrawRenderBatch(RLGL.currentBatch);
+
+ switch (mode)
+ {
+ case BLEND_ALPHA: glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendEquation(GL_FUNC_ADD); break;
+ case BLEND_ADDITIVE: glBlendFunc(GL_SRC_ALPHA, GL_ONE); glBlendEquation(GL_FUNC_ADD); break;
+ case BLEND_MULTIPLIED: glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); glBlendEquation(GL_FUNC_ADD); break;
+ case BLEND_ADD_COLORS: glBlendFunc(GL_ONE, GL_ONE); glBlendEquation(GL_FUNC_ADD); break;
+ case BLEND_SUBTRACT_COLORS: glBlendFunc(GL_ONE, GL_ONE); glBlendEquation(GL_FUNC_SUBTRACT); break;
+ case BLEND_CUSTOM: glBlendFunc(RLGL.State.glBlendSrcFactor, RLGL.State.glBlendDstFactor); glBlendEquation(RLGL.State.glBlendEquation); break;
+ default: break;
+ }
+
+ RLGL.State.currentBlendMode = mode;
+ }
+#endif
+}
+
+// Set blending mode factor and equation
+void rlSetBlendFactors(int glSrcFactor, int glDstFactor, int glEquation)
+{
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+ RLGL.State.glBlendSrcFactor = glSrcFactor;
+ RLGL.State.glBlendDstFactor = glDstFactor;
+ RLGL.State.glBlendEquation = glEquation;
#endif
}
//----------------------------------------------------------------------------------
-// Module Functions Definition - rlgl Functions
+// Module Functions Definition - rlgl functionality
//----------------------------------------------------------------------------------
// Initialize rlgl: OpenGL extensions, default buffers/shaders/textures, OpenGL states
@@ -1722,7 +1741,7 @@ void rlglInit(int width, int height)
else TRACELOG(LOG_WARNING, "TEXTURE: Failed to load default texture");
// Init default Shader (customized for GL 3.3 and ES2)
- RLGL.State.defaultShader = LoadShaderDefault();
+ RLGL.State.defaultShader = rlLoadShaderDefault();
RLGL.State.currentShader = RLGL.State.defaultShader;
// Init default vertex arrays buffers
@@ -1791,42 +1810,34 @@ void rlglClose(void)
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
rlUnloadRenderBatch(RLGL.defaultBatch);
- UnloadShaderDefault(); // Unload default shader
+ rlUnloadShaderDefault(); // Unload default shader
glDeleteTextures(1, &RLGL.State.defaultTextureId); // Unload default texture
TRACELOG(LOG_INFO, "TEXTURE: [ID %i] Unloaded default texture data from VRAM (GPU)", RLGL.State.defaultTextureId);
#endif
}
-// Update and draw internal render batch
-void rlDrawRenderBatchActive(void)
+// Load OpenGL extensions
+// NOTE: External loader function could be passed as a pointer
+void rlLoadExtensions(void *loader)
{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- rlDrawRenderBatch(RLGL.currentBatch); // NOTE: Stereo rendering is checked inside
-#endif
-}
+#if defined(GRAPHICS_API_OPENGL_33)
+ // NOTE: glad is generated and contains only required OpenGL 3.3 Core extensions (and lower versions)
+ #if !defined(__APPLE__)
+ if (!gladLoadGLLoader((GLADloadproc)loader)) TRACELOG(LOG_WARNING, "GLAD: Cannot load OpenGL extensions");
+ else TRACELOG(LOG_INFO, "GLAD: OpenGL extensions loaded successfully");
-// Check and log OpenGL error codes
-void rlCheckErrors()
-{
-#if defined(GRAPHICS_API_OPENGL_21) || defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- int check = 1;
- while (check)
- {
- const GLenum err = glGetError();
- switch (err)
- {
- case GL_NO_ERROR: check = 0; break;
- case 0x0500: TRACELOG(LOG_WARNING, "GL: Error detected: GL_INVALID_ENUM"); break;
- case 0x0501: TRACELOG(LOG_WARNING, "GL: Error detected: GL_INVALID_VALUE"); break;
- case 0x0502: TRACELOG(LOG_WARNING, "GL: Error detected: GL_INVALID_OPERATION"); break;
- case 0x0503: TRACELOG(LOG_WARNING, "GL: Error detected: GL_STACK_OVERFLOW"); break;
- case 0x0504: TRACELOG(LOG_WARNING, "GL: Error detected: GL_STACK_UNDERFLOW"); break;
- case 0x0505: TRACELOG(LOG_WARNING, "GL: Error detected: GL_OUT_OF_MEMORY"); break;
- case 0x0506: TRACELOG(LOG_WARNING, "GL: Error detected: GL_INVALID_FRAMEBUFFER_OPERATION"); break;
- default: TRACELOG(LOG_WARNING, "GL: Error detected: Unknown error code: %x", err); break;
- }
- }
+ #if defined(GRAPHICS_API_OPENGL_21)
+ if (GLAD_GL_VERSION_2_1) TRACELOG(LOG_INFO, "GL: OpenGL 2.1 profile supported");
+ #endif
+ #if defined(GRAPHICS_API_OPENGL_33)
+ if (GLAD_GL_VERSION_3_3) TRACELOG(LOG_INFO, "GL: OpenGL 3.3 Core profile supported");
+ else TRACELOG(LOG_ERROR, "GL: OpenGL 3.3 Core profile not supported");
+ #endif
+ #endif
+
+ // With GLAD, we can check if an extension is supported using the GLAD_GL_xxx booleans
+ //if (GLAD_GL_ARB_vertex_array_object) // Use GL_ARB_vertex_array_object
#endif
}
@@ -1851,56 +1862,459 @@ int rlGetVersion(void)
#endif
}
-// Check internal buffer overflow for a given number of vertex
-// and force a RenderBatch draw call if required
-bool rlCheckRenderBatchLimit(int vCount)
+// Get default internal shader (simple texture + tint color)
+Shader rlGetShaderDefault(void)
{
- bool overflow = false;
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- if ((RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter + vCount) >=
- (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementsCount*4))
+ return RLGL.State.defaultShader;
+#else
+ Shader shader = { 0 };
+ return shader;
+#endif
+}
+
+// Get default internal texture (white texture)
+Texture2D rlGetTextureDefault(void)
+{
+ Texture2D texture = { 0 };
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+ texture.id = RLGL.State.defaultTextureId;
+ texture.width = 1;
+ texture.height = 1;
+ texture.mipmaps = 1;
+ texture.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
+#endif
+ return texture;
+}
+
+// Get texture to draw shapes
+Texture2D rlGetShapesTexture(void)
+{
+#if defined(GRAPHICS_API_OPENGL_11)
+ Texture2D texture = { 0 };
+ return texture;
+#else
+ return RLGL.State.shapesTexture;
+#endif
+}
+
+// Get texture rectangle to draw shapes
+Rectangle rlGetShapesTextureRec(void)
+{
+#if defined(GRAPHICS_API_OPENGL_11)
+ Rectangle rec = { 0 };
+ return rec;
+#else
+ return RLGL.State.shapesTextureRec;
+#endif
+}
+
+// Define default texture used to draw shapes
+void rlSetShapesTexture(Texture2D texture, Rectangle source)
+{
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+ RLGL.State.shapesTexture = texture;
+ RLGL.State.shapesTextureRec = source;
+#endif
+}
+
+// Render batch management
+//------------------------------------------------------------------------------------------------
+// Load render batch
+RenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements)
+{
+ RenderBatch batch = { 0 };
+
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+ // Initialize CPU (RAM) vertex buffers (position, texcoord, color data and indexes)
+ //--------------------------------------------------------------------------------------------
+ batch.vertexBuffer = (VertexBuffer *)RL_MALLOC(sizeof(VertexBuffer)*numBuffers);
+
+ for (int i = 0; i < numBuffers; i++)
{
- overflow = true;
- rlDrawRenderBatch(RLGL.currentBatch); // NOTE: Stereo rendering is checked inside
+ batch.vertexBuffer[i].elementsCount = bufferElements;
+
+ batch.vertexBuffer[i].vertices = (float *)RL_MALLOC(bufferElements*3*4*sizeof(float)); // 3 float by vertex, 4 vertex by quad
+ batch.vertexBuffer[i].texcoords = (float *)RL_MALLOC(bufferElements*2*4*sizeof(float)); // 2 float by texcoord, 4 texcoord by quad
+ batch.vertexBuffer[i].colors = (unsigned char *)RL_MALLOC(bufferElements*4*4*sizeof(unsigned char)); // 4 float by color, 4 colors by quad
+#if defined(GRAPHICS_API_OPENGL_33)
+ batch.vertexBuffer[i].indices = (unsigned int *)RL_MALLOC(bufferElements*6*sizeof(unsigned int)); // 6 int by quad (indices)
+#endif
+#if defined(GRAPHICS_API_OPENGL_ES2)
+ batch.vertexBuffer[i].indices = (unsigned short *)RL_MALLOC(bufferElements*6*sizeof(unsigned short)); // 6 int by quad (indices)
+#endif
+
+ for (int j = 0; j < (3*4*bufferElements); j++) batch.vertexBuffer[i].vertices[j] = 0.0f;
+ for (int j = 0; j < (2*4*bufferElements); j++) batch.vertexBuffer[i].texcoords[j] = 0.0f;
+ for (int j = 0; j < (4*4*bufferElements); j++) batch.vertexBuffer[i].colors[j] = 0;
+
+ int k = 0;
+
+ // Indices can be initialized right now
+ for (int j = 0; j < (6*bufferElements); j += 6)
+ {
+ batch.vertexBuffer[i].indices[j] = 4*k;
+ batch.vertexBuffer[i].indices[j + 1] = 4*k + 1;
+ batch.vertexBuffer[i].indices[j + 2] = 4*k + 2;
+ batch.vertexBuffer[i].indices[j + 3] = 4*k;
+ batch.vertexBuffer[i].indices[j + 4] = 4*k + 2;
+ batch.vertexBuffer[i].indices[j + 5] = 4*k + 3;
+
+ k++;
+ }
+
+ batch.vertexBuffer[i].vCounter = 0;
+ batch.vertexBuffer[i].tcCounter = 0;
+ batch.vertexBuffer[i].cCounter = 0;
}
+
+ TRACELOG(LOG_INFO, "RLGL: Internal vertex buffers initialized successfully in RAM (CPU)");
+ //--------------------------------------------------------------------------------------------
+
+ // Upload to GPU (VRAM) vertex data and initialize VAOs/VBOs
+ //--------------------------------------------------------------------------------------------
+ for (int i = 0; i < numBuffers; i++)
+ {
+ if (RLGL.ExtSupported.vao)
+ {
+ // Initialize Quads VAO
+ glGenVertexArrays(1, &batch.vertexBuffer[i].vaoId);
+ glBindVertexArray(batch.vertexBuffer[i].vaoId);
+ }
+
+ // Quads - Vertex buffers binding and attributes enable
+ // Vertex position buffer (shader-location = 0)
+ glGenBuffers(1, &batch.vertexBuffer[i].vboId[0]);
+ glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[0]);
+ glBufferData(GL_ARRAY_BUFFER, bufferElements*3*4*sizeof(float), batch.vertexBuffer[i].vertices, GL_DYNAMIC_DRAW);
+ glEnableVertexAttribArray(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_POSITION]);
+ glVertexAttribPointer(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0);
+
+ // Vertex texcoord buffer (shader-location = 1)
+ glGenBuffers(1, &batch.vertexBuffer[i].vboId[1]);
+ glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[1]);
+ glBufferData(GL_ARRAY_BUFFER, bufferElements*2*4*sizeof(float), batch.vertexBuffer[i].texcoords, GL_DYNAMIC_DRAW);
+ glEnableVertexAttribArray(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_TEXCOORD01]);
+ glVertexAttribPointer(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0);
+
+ // Vertex color buffer (shader-location = 3)
+ glGenBuffers(1, &batch.vertexBuffer[i].vboId[2]);
+ glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[2]);
+ glBufferData(GL_ARRAY_BUFFER, bufferElements*4*4*sizeof(unsigned char), batch.vertexBuffer[i].colors, GL_DYNAMIC_DRAW);
+ glEnableVertexAttribArray(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_COLOR]);
+ glVertexAttribPointer(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
+
+ // Fill index buffer
+ glGenBuffers(1, &batch.vertexBuffer[i].vboId[3]);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[3]);
+#if defined(GRAPHICS_API_OPENGL_33)
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufferElements*6*sizeof(int), batch.vertexBuffer[i].indices, GL_STATIC_DRAW);
#endif
- return overflow;
+#if defined(GRAPHICS_API_OPENGL_ES2)
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufferElements*6*sizeof(short), batch.vertexBuffer[i].indices, GL_STATIC_DRAW);
+#endif
+ }
+
+ TRACELOG(LOG_INFO, "RLGL: Render batch vertex buffers loaded successfully");
+
+ // Unbind the current VAO
+ if (RLGL.ExtSupported.vao) glBindVertexArray(0);
+ //--------------------------------------------------------------------------------------------
+
+ // Init draw calls tracking system
+ //--------------------------------------------------------------------------------------------
+ batch.draws = (DrawCall *)RL_MALLOC(DEFAULT_BATCH_DRAWCALLS*sizeof(DrawCall));
+
+ for (int i = 0; i < DEFAULT_BATCH_DRAWCALLS; i++)
+ {
+ batch.draws[i].mode = RL_QUADS;
+ batch.draws[i].vertexCount = 0;
+ batch.draws[i].vertexAlignment = 0;
+ //batch.draws[i].vaoId = 0;
+ //batch.draws[i].shaderId = 0;
+ batch.draws[i].textureId = RLGL.State.defaultTextureId;
+ //batch.draws[i].RLGL.State.projection = MatrixIdentity();
+ //batch.draws[i].RLGL.State.modelview = MatrixIdentity();
+ }
+
+ batch.buffersCount = numBuffers; // Record buffer count
+ batch.drawsCounter = 1; // Reset draws counter
+ batch.currentDepth = -1.0f; // Reset depth value
+ //--------------------------------------------------------------------------------------------
+#endif
+
+ return batch;
}
-// Set blending mode factor and equation
-void rlSetBlendFactors(int glSrcFactor, int glDstFactor, int glEquation)
+// Unload default internal buffers vertex data from CPU and GPU
+void rlUnloadRenderBatch(RenderBatch batch)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- RLGL.State.glBlendSrcFactor = glSrcFactor;
- RLGL.State.glBlendDstFactor = glDstFactor;
- RLGL.State.glBlendEquation = glEquation;
+ // Unbind everything
+ if (RLGL.ExtSupported.vao) glBindVertexArray(0);
+ glDisableVertexAttribArray(0);
+ glDisableVertexAttribArray(1);
+ glDisableVertexAttribArray(2);
+ glDisableVertexAttribArray(3);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+
+ // Unload all vertex buffers data
+ for (int i = 0; i < batch.buffersCount; i++)
+ {
+ // Delete VBOs from GPU (VRAM)
+ glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[0]);
+ glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[1]);
+ glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[2]);
+ glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[3]);
+
+ // Delete VAOs from GPU (VRAM)
+ if (RLGL.ExtSupported.vao) glDeleteVertexArrays(1, &batch.vertexBuffer[i].vaoId);
+
+ // Free vertex arrays memory from CPU (RAM)
+ RL_FREE(batch.vertexBuffer[i].vertices);
+ RL_FREE(batch.vertexBuffer[i].texcoords);
+ RL_FREE(batch.vertexBuffer[i].colors);
+ RL_FREE(batch.vertexBuffer[i].indices);
+ }
+
+ // Unload arrays
+ RL_FREE(batch.vertexBuffer);
+ RL_FREE(batch.draws);
#endif
}
-// Load OpenGL extensions
-// NOTE: External loader function could be passed as a pointer
-void rlLoadExtensions(void *loader)
+// Draw render batch
+// NOTE: We require a pointer to reset batch and increase current buffer (multi-buffer)
+void rlDrawRenderBatch(RenderBatch *batch)
{
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+ // Update batch vertex buffers
+ //------------------------------------------------------------------------------------------------------------
+ // NOTE: If there is not vertex data, buffers doesn't need to be updated (vertexCount > 0)
+ // TODO: If no data changed on the CPU arrays --> No need to re-update GPU arrays (change flag required)
+ if (batch->vertexBuffer[batch->currentBuffer].vCounter > 0)
+ {
+ // Activate elements VAO
+ if (RLGL.ExtSupported.vao) glBindVertexArray(batch->vertexBuffer[batch->currentBuffer].vaoId);
+
+ // Vertex positions buffer
+ glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[0]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, batch->vertexBuffer[batch->currentBuffer].vCounter*3*sizeof(float), batch->vertexBuffer[batch->currentBuffer].vertices);
+ //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*batch->vertexBuffer[batch->currentBuffer].elementsCount, batch->vertexBuffer[batch->currentBuffer].vertices, GL_DYNAMIC_DRAW); // Update all buffer
+
+ // Texture coordinates buffer
+ glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[1]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, batch->vertexBuffer[batch->currentBuffer].vCounter*2*sizeof(float), batch->vertexBuffer[batch->currentBuffer].texcoords);
+ //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*batch->vertexBuffer[batch->currentBuffer].elementsCount, batch->vertexBuffer[batch->currentBuffer].texcoords, GL_DYNAMIC_DRAW); // Update all buffer
+
+ // Colors buffer
+ glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[2]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, batch->vertexBuffer[batch->currentBuffer].vCounter*4*sizeof(unsigned char), batch->vertexBuffer[batch->currentBuffer].colors);
+ //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*4*batch->vertexBuffer[batch->currentBuffer].elementsCount, batch->vertexBuffer[batch->currentBuffer].colors, GL_DYNAMIC_DRAW); // Update all buffer
+
+ // NOTE: glMapBuffer() causes sync issue.
+ // If GPU is working with this buffer, glMapBuffer() will wait(stall) until GPU to finish its job.
+ // To avoid waiting (idle), you can call first glBufferData() with NULL pointer before glMapBuffer().
+ // If you do that, the previous data in PBO will be discarded and glMapBuffer() returns a new
+ // allocated pointer immediately even if GPU is still working with the previous data.
+
+ // Another option: map the buffer object into client's memory
+ // Probably this code could be moved somewhere else...
+ // batch->vertexBuffer[batch->currentBuffer].vertices = (float *)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);
+ // if (batch->vertexBuffer[batch->currentBuffer].vertices)
+ // {
+ // Update vertex data
+ // }
+ // glUnmapBuffer(GL_ARRAY_BUFFER);
+
+ // Unbind the current VAO
+ if (RLGL.ExtSupported.vao) glBindVertexArray(0);
+ }
+ //------------------------------------------------------------------------------------------------------------
+
+ // Draw batch vertex buffers (considering VR stereo if required)
+ //------------------------------------------------------------------------------------------------------------
+ Matrix matProjection = RLGL.State.projection;
+ Matrix matModelView = RLGL.State.modelview;
+
+ int eyesCount = 1;
+ if (RLGL.State.stereoRender) eyesCount = 2;
+
+ for (int eye = 0; eye < eyesCount; eye++)
+ {
+ if (eyesCount == 2)
+ {
+ // Setup current eye viewport (half screen width)
+ rlViewport(eye*RLGL.State.framebufferWidth/2, 0, RLGL.State.framebufferWidth/2, RLGL.State.framebufferHeight);
+
+ // Set current eye view offset to modelview matrix
+ rlSetMatrixModelview(MatrixMultiply(matModelView, RLGL.State.eyesViewOffset[eye]));
+ // Set current eye projection matrix
+ rlSetMatrixProjection(RLGL.State.eyesProjection[eye]);
+ }
+
+ // Draw buffers
+ if (batch->vertexBuffer[batch->currentBuffer].vCounter > 0)
+ {
+ // Set current shader and upload current MVP matrix
+ glUseProgram(RLGL.State.currentShader.id);
+
+ // Create modelview-projection matrix and upload to shader
+ Matrix matMVP = MatrixMultiply(RLGL.State.modelview, RLGL.State.projection);
+ glUniformMatrix4fv(RLGL.State.currentShader.locs[SHADER_LOC_MATRIX_MVP], 1, false, MatrixToFloat(matMVP));
+
+ if (RLGL.ExtSupported.vao) glBindVertexArray(batch->vertexBuffer[batch->currentBuffer].vaoId);
+ else
+ {
+ // Bind vertex attrib: position (shader-location = 0)
+ glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[0]);
+ glVertexAttribPointer(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0);
+ glEnableVertexAttribArray(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_POSITION]);
+
+ // Bind vertex attrib: texcoord (shader-location = 1)
+ glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[1]);
+ glVertexAttribPointer(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0);
+ glEnableVertexAttribArray(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_TEXCOORD01]);
+
+ // Bind vertex attrib: color (shader-location = 3)
+ glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[2]);
+ glVertexAttribPointer(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
+ glEnableVertexAttribArray(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_COLOR]);
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[3]);
+ }
+
+ // Setup some default shader values
+ glUniform4f(RLGL.State.currentShader.locs[SHADER_LOC_COLOR_DIFFUSE], 1.0f, 1.0f, 1.0f, 1.0f);
+ glUniform1i(RLGL.State.currentShader.locs[SHADER_LOC_MAP_DIFFUSE], 0); // Active default sampler2D: texture0
+
+ // Activate additional sampler textures
+ // Those additional textures will be common for all draw calls of the batch
+ for (int i = 0; i < MAX_BATCH_ACTIVE_TEXTURES; i++)
+ {
+ if (RLGL.State.activeTextureId[i] > 0)
+ {
+ glActiveTexture(GL_TEXTURE0 + 1 + i);
+ glBindTexture(GL_TEXTURE_2D, RLGL.State.activeTextureId[i]);
+ }
+ }
+
+ // Activate default sampler2D texture0 (one texture is always active for default batch shader)
+ // NOTE: Batch system accumulates calls by texture0 changes, additional textures are enabled for all the draw calls
+ glActiveTexture(GL_TEXTURE0);
+
+ for (int i = 0, vertexOffset = 0; i < batch->drawsCounter; i++)
+ {
+ // Bind current draw call texture, activated as GL_TEXTURE0 and binded to sampler2D texture0 by default
+ glBindTexture(GL_TEXTURE_2D, batch->draws[i].textureId);
+
+ if ((batch->draws[i].mode == RL_LINES) || (batch->draws[i].mode == RL_TRIANGLES)) glDrawArrays(batch->draws[i].mode, vertexOffset, batch->draws[i].vertexCount);
+ else
+ {
#if defined(GRAPHICS_API_OPENGL_33)
- // NOTE: glad is generated and contains only required OpenGL 3.3 Core extensions (and lower versions)
- #if !defined(__APPLE__)
- if (!gladLoadGLLoader((GLADloadproc)loader)) TRACELOG(LOG_WARNING, "GLAD: Cannot load OpenGL extensions");
- else TRACELOG(LOG_INFO, "GLAD: OpenGL extensions loaded successfully");
+ // We need to define the number of indices to be processed: quadsCount*6
+ // NOTE: The final parameter tells the GPU the offset in bytes from the
+ // start of the index buffer to the location of the first index to process
+ glDrawElements(GL_TRIANGLES, batch->draws[i].vertexCount/4*6, GL_UNSIGNED_INT, (GLvoid *)(vertexOffset/4*6*sizeof(GLuint)));
+#endif
+#if defined(GRAPHICS_API_OPENGL_ES2)
+ glDrawElements(GL_TRIANGLES, batch->draws[i].vertexCount/4*6, GL_UNSIGNED_SHORT, (GLvoid *)(vertexOffset/4*6*sizeof(GLushort)));
+#endif
+ }
- #if defined(GRAPHICS_API_OPENGL_21)
- if (GLAD_GL_VERSION_2_1) TRACELOG(LOG_INFO, "GL: OpenGL 2.1 profile supported");
- #endif
- #if defined(GRAPHICS_API_OPENGL_33)
- if (GLAD_GL_VERSION_3_3) TRACELOG(LOG_INFO, "GL: OpenGL 3.3 Core profile supported");
- else TRACELOG(LOG_ERROR, "GL: OpenGL 3.3 Core profile not supported");
- #endif
- #endif
+ vertexOffset += (batch->draws[i].vertexCount + batch->draws[i].vertexAlignment);
+ }
- // With GLAD, we can check if an extension is supported using the GLAD_GL_xxx booleans
- //if (GLAD_GL_ARB_vertex_array_object) // Use GL_ARB_vertex_array_object
+ if (!RLGL.ExtSupported.vao)
+ {
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ }
+
+ glBindTexture(GL_TEXTURE_2D, 0); // Unbind textures
+ }
+
+ if (RLGL.ExtSupported.vao) glBindVertexArray(0); // Unbind VAO
+
+ glUseProgram(0); // Unbind shader program
+ }
+ //------------------------------------------------------------------------------------------------------------
+
+ // Reset batch buffers
+ //------------------------------------------------------------------------------------------------------------
+ // Reset vertex counters for next frame
+ batch->vertexBuffer[batch->currentBuffer].vCounter = 0;
+ batch->vertexBuffer[batch->currentBuffer].tcCounter = 0;
+ batch->vertexBuffer[batch->currentBuffer].cCounter = 0;
+
+ // Reset depth for next draw
+ batch->currentDepth = -1.0f;
+
+ // Restore projection/modelview matrices
+ RLGL.State.projection = matProjection;
+ RLGL.State.modelview = matModelView;
+
+ // Reset RLGL.currentBatch->draws array
+ for (int i = 0; i < DEFAULT_BATCH_DRAWCALLS; i++)
+ {
+ batch->draws[i].mode = RL_QUADS;
+ batch->draws[i].vertexCount = 0;
+ batch->draws[i].textureId = RLGL.State.defaultTextureId;
+ }
+
+ // Reset active texture units for next batch
+ for (int i = 0; i < MAX_BATCH_ACTIVE_TEXTURES; i++) RLGL.State.activeTextureId[i] = 0;
+
+ // Reset draws counter to one draw for the batch
+ batch->drawsCounter = 1;
+ //------------------------------------------------------------------------------------------------------------
+
+ // Change to next buffer in the list (in case of multi-buffering)
+ batch->currentBuffer++;
+ if (batch->currentBuffer >= batch->buffersCount) batch->currentBuffer = 0;
+#endif
+}
+
+// Set the active render batch for rlgl
+void rlSetRenderBatchActive(RenderBatch *batch)
+{
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+ rlDrawRenderBatch(RLGL.currentBatch);
+
+ if (batch != NULL) RLGL.currentBatch = batch;
+ else RLGL.currentBatch = &RLGL.defaultBatch;
+#endif
+}
+
+// Update and draw internal render batch
+void rlDrawRenderBatchActive(void)
+{
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+ rlDrawRenderBatch(RLGL.currentBatch); // NOTE: Stereo rendering is checked inside
+#endif
+}
+
+// Check internal buffer overflow for a given number of vertex
+// and force a RenderBatch draw call if required
+bool rlCheckRenderBatchLimit(int vCount)
+{
+ bool overflow = false;
+
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+ if ((RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter + vCount) >=
+ (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementsCount*4))
+ {
+ overflow = true;
+ rlDrawRenderBatch(RLGL.currentBatch); // NOTE: Stereo rendering is checked inside
+ }
#endif
+
+ return overflow;
}
+// Textures data management
+//-----------------------------------------------------------------------------------------
// Convert image data to OpenGL texture (returns OpenGL valid Id)
unsigned int rlLoadTexture(void *data, int width, int height, int format, int mipmapCount)
{
@@ -1990,8 +2404,7 @@ unsigned int rlLoadTexture(void *data, int width, int height, int format, int mi
{
#if defined(GRAPHICS_API_OPENGL_21)
GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_ALPHA };
- #endif
- #if defined(GRAPHICS_API_OPENGL_33)
+ #elif defined(GRAPHICS_API_OPENGL_33)
GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_GREEN };
#endif
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
@@ -2158,8 +2571,7 @@ unsigned int rlLoadTextureCubemap(void *data, int size, int format)
{
#if defined(GRAPHICS_API_OPENGL_21)
GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_ALPHA };
-#endif
-#if defined(GRAPHICS_API_OPENGL_33)
+#elif defined(GRAPHICS_API_OPENGL_33)
GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_GREEN };
#endif
glTexParameteriv(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
@@ -2225,8 +2637,7 @@ void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned
case PIXELFORMAT_UNCOMPRESSED_R32G32B32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
case PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
#endif
- #endif
- #if defined(GRAPHICS_API_OPENGL_33)
+ #elif defined(GRAPHICS_API_OPENGL_33)
case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: *glInternalFormat = GL_R8; *glFormat = GL_RED; *glType = GL_UNSIGNED_BYTE; break;
case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: *glInternalFormat = GL_RG8; *glFormat = GL_RG; *glType = GL_UNSIGNED_BYTE; break;
case PIXELFORMAT_UNCOMPRESSED_R5G6B5: *glInternalFormat = GL_RGB565; *glFormat = GL_RGB; *glType = GL_UNSIGNED_SHORT_5_6_5; break;
@@ -2261,6 +2672,177 @@ void rlUnloadTexture(unsigned int id)
glDeleteTextures(1, &id);
}
+
+// Generate mipmap data for selected texture
+void rlGenerateMipmaps(Texture2D *texture)
+{
+ glBindTexture(GL_TEXTURE_2D, texture->id);
+
+ // Check if texture is power-of-two (POT)
+ bool texIsPOT = false;
+
+ if (((texture->width > 0) && ((texture->width & (texture->width - 1)) == 0)) &&
+ ((texture->height > 0) && ((texture->height & (texture->height - 1)) == 0))) texIsPOT = true;
+
+#if defined(GRAPHICS_API_OPENGL_11)
+ if (texIsPOT)
+ {
+ // WARNING: Manual mipmap generation only works for RGBA 32bit textures!
+ if (texture->format == PIXELFORMAT_UNCOMPRESSED_R8G8B8A8)
+ {
+ // Retrieve texture data from VRAM
+ void *texData = rlReadTexturePixels(*texture);
+
+ // NOTE: Texture data size is reallocated to fit mipmaps data
+ // NOTE: CPU mipmap generation only supports RGBA 32bit data
+ int mipmapCount = rlGenerateMipmapsData(texData, texture->width, texture->height);
+
+ int size = texture->width*texture->height*4;
+ int offset = size;
+
+ int mipWidth = texture->width/2;
+ int mipHeight = texture->height/2;
+
+ // Load the mipmaps
+ for (int level = 1; level < mipmapCount; level++)
+ {
+ glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA8, mipWidth, mipHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)texData + offset);
+
+ size = mipWidth*mipHeight*4;
+ offset += size;
+
+ mipWidth /= 2;
+ mipHeight /= 2;
+ }
+
+ texture->mipmaps = mipmapCount + 1;
+ RL_FREE(texData); // Once mipmaps have been generated and data has been uploaded to GPU VRAM, we can discard RAM data
+
+ TRACELOG(LOG_WARNING, "TEXTURE: [ID %i] Mipmaps generated manually on CPU side, total: %i", texture->id, texture->mipmaps);
+ }
+ else TRACELOG(LOG_WARNING, "TEXTURE: [ID %i] Failed to generate mipmaps for provided texture format", texture->id);
+ }
+#endif
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+ if ((texIsPOT) || (RLGL.ExtSupported.texNPOT))
+ {
+ //glHint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE); // Hint for mipmaps generation algorythm: GL_FASTEST, GL_NICEST, GL_DONT_CARE
+ glGenerateMipmap(GL_TEXTURE_2D); // Generate mipmaps automatically
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // Activate Trilinear filtering for mipmaps
+
+ #define MIN(a,b) (((a)<(b))?(a):(b))
+ #define MAX(a,b) (((a)>(b))?(a):(b))
+
+ texture->mipmaps = 1 + (int)floor(log(MAX(texture->width, texture->height))/log(2));
+ TRACELOG(LOG_INFO, "TEXTURE: [ID %i] Mipmaps generated automatically, total: %i", texture->id, texture->mipmaps);
+ }
+#endif
+ else TRACELOG(LOG_WARNING, "TEXTURE: [ID %i] Failed to generate mipmaps", texture->id);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+}
+
+
+// Read texture pixel data
+void *rlReadTexturePixels(Texture2D texture)
+{
+ void *pixels = NULL;
+
+#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
+ glBindTexture(GL_TEXTURE_2D, texture.id);
+
+ // NOTE: Using texture.id, we can retrieve some texture info (but not on OpenGL ES 2.0)
+ // Possible texture info: GL_TEXTURE_RED_SIZE, GL_TEXTURE_GREEN_SIZE, GL_TEXTURE_BLUE_SIZE, GL_TEXTURE_ALPHA_SIZE
+ //int width, height, format;
+ //glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
+ //glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
+ //glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &format);
+
+ // 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.
+ // Use glPixelStorei to modify padding with the GL_[UN]PACK_ALIGNMENT setting.
+ // GL_PACK_ALIGNMENT affects operations that read from OpenGL memory (glReadPixels, glGetTexImage, etc.)
+ // GL_UNPACK_ALIGNMENT affects operations that write to OpenGL memory (glTexImage, etc.)
+ glPixelStorei(GL_PACK_ALIGNMENT, 1);
+
+ unsigned int glInternalFormat, glFormat, glType;
+ rlGetGlTextureFormats(texture.format, &glInternalFormat, &glFormat, &glType);
+ unsigned int size = rlGetPixelDataSize(texture.width, texture.height, texture.format);
+
+ if ((glInternalFormat != -1) && (texture.format < PIXELFORMAT_COMPRESSED_DXT1_RGB))
+ {
+ pixels = RL_MALLOC(size);
+ glGetTexImage(GL_TEXTURE_2D, 0, glFormat, glType, pixels);
+ }
+ else TRACELOG(LOG_WARNING, "TEXTURE: [ID %i] Data retrieval not suported for pixel format (%i)", texture.id, texture.format);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+#endif
+
+#if defined(GRAPHICS_API_OPENGL_ES2)
+ // glGetTexImage() is not available on OpenGL ES 2.0
+ // Texture2D width and height are required on OpenGL ES 2.0. There is no way to get it from texture id.
+ // Two possible Options:
+ // 1 - Bind texture to color fbo attachment and glReadPixels()
+ // 2 - Create an fbo, activate it, render quad with texture, glReadPixels()
+ // We are using Option 1, just need to care for texture format on retrieval
+ // NOTE: This behaviour could be conditioned by graphic driver...
+ unsigned int fboId = rlLoadFramebuffer(texture.width, texture.height);
+
+ // TODO: Create depth texture/renderbuffer for fbo?
+
+ glBindFramebuffer(GL_FRAMEBUFFER, fboId);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ // Attach our texture to FBO
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.id, 0);
+
+ // We read data as RGBA because FBO texture is configured as RGBA, despite binding another texture format
+ pixels = (unsigned char *)RL_MALLOC(rlGetPixelDataSize(texture.width, texture.height, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8));
+ glReadPixels(0, 0, texture.width, texture.height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ // Clean up temporal fbo
+ rlUnloadFramebuffer(fboId);
+#endif
+
+ return pixels;
+}
+
+
+// Read screen pixel data (color buffer)
+unsigned char *rlReadScreenPixels(int width, int height)
+{
+ unsigned char *screenData = (unsigned char *)RL_CALLOC(width*height*4, sizeof(unsigned char));
+
+ // NOTE 1: glReadPixels returns image flipped vertically -> (0,0) is the bottom left corner of the framebuffer
+ // NOTE 2: We are getting alpha channel! Be careful, it can be transparent if not cleared properly!
+ glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, screenData);
+
+ // Flip image vertically!
+ unsigned char *imgData = (unsigned char *)RL_MALLOC(width*height*4*sizeof(unsigned char));
+
+ for (int y = height - 1; y >= 0; y--)
+ {
+ for (int x = 0; x < (width*4); x++)
+ {
+ imgData[((height - 1) - y)*width*4 + x] = screenData[(y*width*4) + x]; // Flip line
+
+ // Set alpha component value to 255 (no trasparent image retrieval)
+ // NOTE: Alpha value has already been applied to RGB in framebuffer, we don't need it!
+ if (((x + 1)%4) == 0) imgData[((height - 1) - y)*width*4 + x] = 255;
+ }
+ }
+
+ RL_FREE(screenData);
+
+ return imgData; // NOTE: image data should be freed
+}
+
+// Framebuffer management (fbo)
+//-----------------------------------------------------------------------------------------
// Load a framebuffer to be used for rendering
// NOTE: No textures attached
unsigned int rlLoadFramebuffer(int width, int height)
@@ -2349,77 +2931,34 @@ bool rlFramebufferComplete(unsigned int id)
return result;
}
-// Generate mipmap data for selected texture
-void rlGenerateMipmaps(Texture2D *texture)
+// Unload framebuffer from GPU memory
+// NOTE: All attached textures/cubemaps/renderbuffers are also deleted
+void rlUnloadFramebuffer(unsigned int id)
{
- glBindTexture(GL_TEXTURE_2D, texture->id);
-
- // Check if texture is power-of-two (POT)
- bool texIsPOT = false;
-
- if (((texture->width > 0) && ((texture->width & (texture->width - 1)) == 0)) &&
- ((texture->height > 0) && ((texture->height & (texture->height - 1)) == 0))) texIsPOT = true;
-
-#if defined(GRAPHICS_API_OPENGL_11)
- if (texIsPOT)
- {
- // WARNING: Manual mipmap generation only works for RGBA 32bit textures!
- if (texture->format == PIXELFORMAT_UNCOMPRESSED_R8G8B8A8)
- {
- // Retrieve texture data from VRAM
- void *texData = rlReadTexturePixels(*texture);
-
- // NOTE: Texture data size is reallocated to fit mipmaps data
- // NOTE: CPU mipmap generation only supports RGBA 32bit data
- int mipmapCount = GenerateMipmaps(texData, texture->width, texture->height);
-
- int size = texture->width*texture->height*4;
- int offset = size;
-
- int mipWidth = texture->width/2;
- int mipHeight = texture->height/2;
-
- // Load the mipmaps
- for (int level = 1; level < mipmapCount; level++)
- {
- glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA8, mipWidth, mipHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)texData + offset);
-
- size = mipWidth*mipHeight*4;
- offset += size;
-
- mipWidth /= 2;
- mipHeight /= 2;
- }
+#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(SUPPORT_RENDER_TEXTURES_HINT)
- texture->mipmaps = mipmapCount + 1;
- RL_FREE(texData); // Once mipmaps have been generated and data has been uploaded to GPU VRAM, we can discard RAM data
+ // Query depth attachment to automatically delete texture/renderbuffer
+ int depthType = 0, depthId = 0;
+ glBindFramebuffer(GL_FRAMEBUFFER, id); // Bind framebuffer to query depth texture type
+ glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &depthType);
+ glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &depthId);
- TRACELOG(LOG_WARNING, "TEXTURE: [ID %i] Mipmaps generated manually on CPU side, total: %i", texture->id, texture->mipmaps);
- }
- else TRACELOG(LOG_WARNING, "TEXTURE: [ID %i] Failed to generate mipmaps for provided texture format", texture->id);
- }
-#endif
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- if ((texIsPOT) || (RLGL.ExtSupported.texNPOT))
- {
- //glHint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE); // Hint for mipmaps generation algorythm: GL_FASTEST, GL_NICEST, GL_DONT_CARE
- glGenerateMipmap(GL_TEXTURE_2D); // Generate mipmaps automatically
+ unsigned int depthIdU = (unsigned int)depthId;
+ if (depthType == GL_RENDERBUFFER) glDeleteRenderbuffers(1, &depthIdU);
+ else if (depthType == GL_RENDERBUFFER) glDeleteTextures(1, &depthIdU);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // Activate Trilinear filtering for mipmaps
+ // NOTE: If a texture object is deleted while its image is attached to the *currently bound* framebuffer,
+ // the texture image is automatically detached from the currently bound framebuffer.
- #define MIN(a,b) (((a)<(b))?(a):(b))
- #define MAX(a,b) (((a)>(b))?(a):(b))
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glDeleteFramebuffers(1, &id);
- texture->mipmaps = 1 + (int)floor(log(MAX(texture->width, texture->height))/log(2));
- TRACELOG(LOG_INFO, "TEXTURE: [ID %i] Mipmaps generated automatically, total: %i", texture->id, texture->mipmaps);
- }
+ TRACELOG(LOG_INFO, "FBO: [ID %i] Unloaded framebuffer from VRAM (GPU)", id);
#endif
- else TRACELOG(LOG_WARNING, "TEXTURE: [ID %i] Failed to generate mipmaps", texture->id);
-
- glBindTexture(GL_TEXTURE_2D, 0);
}
+// Vertex data management
+//-----------------------------------------------------------------------------------------
// Upload vertex data into a VAO (if supported) and VBO
void rlLoadMesh(Mesh *mesh, bool dynamic)
{
@@ -2663,6 +3202,15 @@ void rlUpdateMeshAt(Mesh mesh, int buffer, int count, int index)
#endif
}
+// Update GPU buffer with new data
+void rlUpdateBuffer(int bufferId, void *data, int dataSize)
+{
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+ glBindBuffer(GL_ARRAY_BUFFER, bufferId);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, dataSize, data);
+#endif
+}
+
// Draw a 3d mesh with material and transform
void rlDrawMesh(Mesh mesh, Material material, Matrix transform)
{
@@ -2977,171 +3525,8 @@ void rlUnloadMesh(Mesh *mesh)
mesh->vboId = NULL;
}
-// Read screen pixel data (color buffer)
-unsigned char *rlReadScreenPixels(int width, int height)
-{
- unsigned char *screenData = (unsigned char *)RL_CALLOC(width*height*4, sizeof(unsigned char));
-
- // NOTE 1: glReadPixels returns image flipped vertically -> (0,0) is the bottom left corner of the framebuffer
- // NOTE 2: We are getting alpha channel! Be careful, it can be transparent if not cleared properly!
- glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, screenData);
-
- // Flip image vertically!
- unsigned char *imgData = (unsigned char *)RL_MALLOC(width*height*4*sizeof(unsigned char));
-
- for (int y = height - 1; y >= 0; y--)
- {
- for (int x = 0; x < (width*4); x++)
- {
- imgData[((height - 1) - y)*width*4 + x] = screenData[(y*width*4) + x]; // Flip line
-
- // Set alpha component value to 255 (no trasparent image retrieval)
- // NOTE: Alpha value has already been applied to RGB in framebuffer, we don't need it!
- if (((x + 1)%4) == 0) imgData[((height - 1) - y)*width*4 + x] = 255;
- }
- }
-
- RL_FREE(screenData);
-
- return imgData; // NOTE: image data should be freed
-}
-
-// Read texture pixel data
-void *rlReadTexturePixels(Texture2D texture)
-{
- void *pixels = NULL;
-
-#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
- glBindTexture(GL_TEXTURE_2D, texture.id);
-
- // NOTE: Using texture.id, we can retrieve some texture info (but not on OpenGL ES 2.0)
- // Possible texture info: GL_TEXTURE_RED_SIZE, GL_TEXTURE_GREEN_SIZE, GL_TEXTURE_BLUE_SIZE, GL_TEXTURE_ALPHA_SIZE
- //int width, height, format;
- //glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
- //glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
- //glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &format);
-
- // 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.
- // Use glPixelStorei to modify padding with the GL_[UN]PACK_ALIGNMENT setting.
- // GL_PACK_ALIGNMENT affects operations that read from OpenGL memory (glReadPixels, glGetTexImage, etc.)
- // GL_UNPACK_ALIGNMENT affects operations that write to OpenGL memory (glTexImage, etc.)
- glPixelStorei(GL_PACK_ALIGNMENT, 1);
-
- unsigned int glInternalFormat, glFormat, glType;
- rlGetGlTextureFormats(texture.format, &glInternalFormat, &glFormat, &glType);
- unsigned int size = rlGetPixelDataSize(texture.width, texture.height, texture.format);
-
- if ((glInternalFormat != -1) && (texture.format < PIXELFORMAT_COMPRESSED_DXT1_RGB))
- {
- pixels = RL_MALLOC(size);
- glGetTexImage(GL_TEXTURE_2D, 0, glFormat, glType, pixels);
- }
- else TRACELOG(LOG_WARNING, "TEXTURE: [ID %i] Data retrieval not suported for pixel format (%i)", texture.id, texture.format);
-
- glBindTexture(GL_TEXTURE_2D, 0);
-#endif
-
-#if defined(GRAPHICS_API_OPENGL_ES2)
- // glGetTexImage() is not available on OpenGL ES 2.0
- // Texture2D width and height are required on OpenGL ES 2.0. There is no way to get it from texture id.
- // Two possible Options:
- // 1 - Bind texture to color fbo attachment and glReadPixels()
- // 2 - Create an fbo, activate it, render quad with texture, glReadPixels()
- // We are using Option 1, just need to care for texture format on retrieval
- // NOTE: This behaviour could be conditioned by graphic driver...
- unsigned int fboId = rlLoadFramebuffer(texture.width, texture.height);
-
- // TODO: Create depth texture/renderbuffer for fbo?
-
- glBindFramebuffer(GL_FRAMEBUFFER, fboId);
- glBindTexture(GL_TEXTURE_2D, 0);
-
- // Attach our texture to FBO
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.id, 0);
-
- // We read data as RGBA because FBO texture is configured as RGBA, despite binding another texture format
- pixels = (unsigned char *)RL_MALLOC(rlGetPixelDataSize(texture.width, texture.height, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8));
- glReadPixels(0, 0, texture.width, texture.height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
-
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
-
- // Clean up temporal fbo
- rlUnloadFramebuffer(fboId);
-#endif
-
- return pixels;
-}
-
-// Set eyes projection matrices for stereo rendering
-void rlSetMatrixProjectionStereo(Matrix right, Matrix left)
-{
- RLGL.State.eyesProjection[0] = right;
- RLGL.State.eyesProjection[1] = left;
-}
-
-// Set eyes view offsets matrices for stereo rendering
-void rlSetMatrixViewOffsetStereo(Matrix right, Matrix left)
-{
- RLGL.State.eyesViewOffset[0] = right;
- RLGL.State.eyesViewOffset[1] = left;
-}
-
-// Get default internal texture (white texture)
-Texture2D rlGetTextureDefault(void)
-{
- Texture2D texture = { 0 };
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- texture.id = RLGL.State.defaultTextureId;
- texture.width = 1;
- texture.height = 1;
- texture.mipmaps = 1;
- texture.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
-#endif
- return texture;
-}
-
-// Get texture to draw shapes (RAII)
-Texture2D rlGetShapesTexture(void)
-{
-#if defined(GRAPHICS_API_OPENGL_11)
- Texture2D texture = { 0 };
- return texture;
-#else
- return RLGL.State.shapesTexture;
-#endif
-}
-
-// Get texture rectangle to draw shapes
-Rectangle rlGetShapesTextureRec(void)
-{
-#if defined(GRAPHICS_API_OPENGL_11)
- Rectangle rec = { 0 };
- return rec;
-#else
- return RLGL.State.shapesTextureRec;
-#endif
-}
-
-// Define default texture used to draw shapes
-void rlSetShapesTexture(Texture2D texture, Rectangle source)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- RLGL.State.shapesTexture = texture;
- RLGL.State.shapesTextureRec = source;
-#endif
-}
-
-// Get default shader
-Shader rlGetShaderDefault(void)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- return RLGL.State.defaultShader;
-#else
- Shader shader = { 0 };
- return shader;
-#endif
-}
-
+// Shaders management
+//-----------------------------------------------------------------------------------------------
// Load shader from code strings
// NOTE: If shader string is NULL, using default vertex/fragment shaders
unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode)
@@ -3152,13 +3537,13 @@ unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode)
unsigned int vertexShaderId = RLGL.State.defaultVShaderId;
unsigned int fragmentShaderId = RLGL.State.defaultFShaderId;
- if (vsCode != NULL) vertexShaderId = CompileShader(vsCode, GL_VERTEX_SHADER);
- if (fsCode != NULL) fragmentShaderId = CompileShader(fsCode, GL_FRAGMENT_SHADER);
+ if (vsCode != NULL) vertexShaderId = rlCompileShader(vsCode, GL_VERTEX_SHADER);
+ if (fsCode != NULL) fragmentShaderId = rlCompileShader(fsCode, GL_FRAGMENT_SHADER);
if ((vertexShaderId == RLGL.State.defaultVShaderId) && (fragmentShaderId == RLGL.State.defaultFShaderId)) id = RLGL.State.defaultShader.id;
else
{
- id = LoadShaderProgram(vertexShaderId, fragmentShaderId);
+ id = rlLoadShaderProgram(vertexShaderId, fragmentShaderId);
if (vertexShaderId != RLGL.State.defaultVShaderId)
{
@@ -3205,47 +3590,101 @@ unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode)
return id;
}
-// Unload shader program
-void rlUnloadShaderProgram(unsigned int id)
+// Compile custom shader and return shader id
+unsigned int rlCompileShader(const char *shaderCode, int type)
{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- glDeleteProgram(id);
-#endif
-}
+ unsigned int shader = 0;
-// Set current shader
-void rlSetShaderCurrent(Shader shader)
-{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- if (RLGL.State.currentShader.id != shader.id)
+ shader = glCreateShader(type);
+ glShaderSource(shader, 1, &shaderCode, NULL);
+
+ GLint success = 0;
+ glCompileShader(shader);
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
+
+ if (success == GL_FALSE)
{
- rlDrawRenderBatch(RLGL.currentBatch);
- RLGL.State.currentShader = shader;
+ TRACELOG(LOG_WARNING, "SHADER: [ID %i] Failed to compile shader code", shader);
+
+ int maxLength = 0;
+ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
+
+ if (maxLength > 0)
+ {
+ int length = 0;
+ char *log = RL_CALLOC(maxLength, sizeof(char));
+ glGetShaderInfoLog(shader, maxLength, &length, log);
+ TRACELOG(LOG_WARNING, "SHADER: [ID %i] Compile error: %s", shader, log);
+ RL_FREE(log);
+ }
}
+ else TRACELOG(LOG_INFO, "SHADER: [ID %i] Compiled successfully", shader);
#endif
+
+ return shader;
}
-// Set blend mode
-void rlSetBlendMode(int mode)
+// Load custom shader strings and return program id
+unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId)
{
+ unsigned int program = 0;
+
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- if (RLGL.State.currentBlendMode != mode)
+ GLint success = 0;
+ program = glCreateProgram();
+
+ glAttachShader(program, vShaderId);
+ glAttachShader(program, fShaderId);
+
+ // NOTE: Default attribute shader locations must be binded before linking
+ glBindAttribLocation(program, 0, DEFAULT_SHADER_ATTRIB_NAME_POSITION);
+ glBindAttribLocation(program, 1, DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD);
+ glBindAttribLocation(program, 2, DEFAULT_SHADER_ATTRIB_NAME_NORMAL);
+ glBindAttribLocation(program, 3, DEFAULT_SHADER_ATTRIB_NAME_COLOR);
+ glBindAttribLocation(program, 4, DEFAULT_SHADER_ATTRIB_NAME_TANGENT);
+ glBindAttribLocation(program, 5, DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2);
+
+ // NOTE: If some attrib name is no found on the shader, it locations becomes -1
+
+ glLinkProgram(program);
+
+ // NOTE: All uniform variables are intitialised to 0 when a program links
+
+ glGetProgramiv(program, GL_LINK_STATUS, &success);
+
+ if (success == GL_FALSE)
{
- rlDrawRenderBatch(RLGL.currentBatch);
+ TRACELOG(LOG_WARNING, "SHADER: [ID %i] Failed to link shader program", program);
- switch (mode)
+ int maxLength = 0;
+ glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
+
+ if (maxLength > 0)
{
- case BLEND_ALPHA: glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendEquation(GL_FUNC_ADD); break;
- case BLEND_ADDITIVE: glBlendFunc(GL_SRC_ALPHA, GL_ONE); glBlendEquation(GL_FUNC_ADD); break;
- case BLEND_MULTIPLIED: glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); glBlendEquation(GL_FUNC_ADD); break;
- case BLEND_ADD_COLORS: glBlendFunc(GL_ONE, GL_ONE); glBlendEquation(GL_FUNC_ADD); break;
- case BLEND_SUBTRACT_COLORS: glBlendFunc(GL_ONE, GL_ONE); glBlendEquation(GL_FUNC_SUBTRACT); break;
- case BLEND_CUSTOM: glBlendFunc(RLGL.State.glBlendSrcFactor, RLGL.State.glBlendDstFactor); glBlendEquation(RLGL.State.glBlendEquation); break;
- default: break;
+ int length = 0;
+ char *log = RL_CALLOC(maxLength, sizeof(char));
+ glGetProgramInfoLog(program, maxLength, &length, log);
+ TRACELOG(LOG_WARNING, "SHADER: [ID %i] Link error: %s", program, log);
+ RL_FREE(log);
}
- RLGL.State.currentBlendMode = mode;
+ glDeleteProgram(program);
+
+ program = 0;
}
+ else TRACELOG(LOG_INFO, "SHADER: [ID %i] Program loaded successfully", program);
+#endif
+ return program;
+}
+
+// Unload shader program
+void rlUnloadShaderProgram(unsigned int id)
+{
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+ glDeleteProgram(id);
+
+ TRACELOG(LOG_INFO, "SHADER: [ID %i] Unloaded shader program data from VRAM (GPU)", id);
#endif
}
@@ -3255,6 +3694,9 @@ int rlGetLocationUniform(unsigned int shaderId, const char *uniformName)
int location = -1;
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
location = glGetUniformLocation(shaderId, uniformName);
+
+ if (location == -1) TRACELOG(LOG_WARNING, "SHADER: [ID %i] Failed to find shader uniform: %s", shaderId, uniformName);
+ else TRACELOG(LOG_INFO, "SHADER: [ID %i] Shader uniform (%s) set at location: %i", shaderId, uniformName, location);
#endif
return location;
}
@@ -3265,6 +3707,9 @@ int rlGetLocationAttrib(unsigned int shaderId, const char *attribName)
int location = -1;
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
location = glGetAttribLocation(shaderId, attribName);
+
+ if (location == -1) TRACELOG(LOG_WARNING, "SHADER: [ID %i] Failed to find shader attribute: %s", shaderId, attribName);
+ else TRACELOG(LOG_INFO, "SHADER: [ID %i] Shader attribute (%s) set at location: %i", shaderId, attribName, location);
#endif
return location;
}
@@ -3318,12 +3763,35 @@ void rlSetUniformSampler(int locIndex, Texture2D texture)
#endif
}
-// Set a custom projection matrix (replaces internal projection matrix)
-void rlSetMatrixProjection(Matrix projection)
+// Set shader currently active
+void rlSetShaderActive(Shader shader)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- RLGL.State.projection = projection;
+ if (RLGL.State.currentShader.id != shader.id)
+ {
+ rlDrawRenderBatch(RLGL.currentBatch);
+ RLGL.State.currentShader = shader;
+ }
+#endif
+}
+
+// Matrix state management
+//-----------------------------------------------------------------------------------------
+// Return internal modelview matrix
+Matrix rlGetMatrixModelview(void)
+{
+ Matrix matrix = MatrixIdentity();
+#if defined(GRAPHICS_API_OPENGL_11)
+ float mat[16];
+ glGetFloatv(GL_MODELVIEW_MATRIX, mat);
+ matrix.m0 = mat[0]; matrix.m1 = mat[1]; matrix.m2 = mat[2]; matrix.m3 = mat[3];
+ matrix.m4 = mat[4]; matrix.m5 = mat[5]; matrix.m6 = mat[6]; matrix.m7 = mat[7];
+ matrix.m8 = mat[8]; matrix.m9 = mat[9]; matrix.m10 = mat[10]; matrix.m11 = mat[11];
+ matrix.m12 = mat[12]; matrix.m13 = mat[13]; matrix.m14 = mat[14]; matrix.m15 = mat[15];
+#else
+ matrix = RLGL.State.modelview;
#endif
+ return matrix;
}
// Return internal projection matrix
@@ -3352,23 +3820,34 @@ void rlSetMatrixModelview(Matrix view)
#endif
}
-// Return internal modelview matrix
-Matrix rlGetMatrixModelview(void)
+// Set a custom projection matrix (replaces internal projection matrix)
+void rlSetMatrixProjection(Matrix projection)
{
- Matrix matrix = MatrixIdentity();
-#if defined(GRAPHICS_API_OPENGL_11)
- float mat[16];
- glGetFloatv(GL_MODELVIEW_MATRIX, mat);
- matrix.m0 = mat[0]; matrix.m1 = mat[1]; matrix.m2 = mat[2]; matrix.m3 = mat[3];
- matrix.m4 = mat[4]; matrix.m5 = mat[5]; matrix.m6 = mat[6]; matrix.m7 = mat[7];
- matrix.m8 = mat[8]; matrix.m9 = mat[9]; matrix.m10 = mat[10]; matrix.m11 = mat[11];
- matrix.m12 = mat[12]; matrix.m13 = mat[13]; matrix.m14 = mat[14]; matrix.m15 = mat[15];
-#else
- matrix = RLGL.State.modelview;
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+ RLGL.State.projection = projection;
+#endif
+}
+
+// Set eyes projection matrices for stereo rendering
+void rlSetMatrixProjectionStereo(Matrix right, Matrix left)
+{
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+ RLGL.State.eyesProjection[0] = right;
+ RLGL.State.eyesProjection[1] = left;
#endif
- return matrix;
}
+// Set eyes view offsets matrices for stereo rendering
+void rlSetMatrixViewOffsetStereo(Matrix right, Matrix left)
+{
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+ RLGL.State.eyesViewOffset[0] = right;
+ RLGL.State.eyesViewOffset[1] = left;
+#endif
+}
+
+// Texture maps generation (PBR)
+//-------------------------------------------------------------------------------------------
// Generate cubemap texture from HDR texture
TextureCubemap rlGenTextureCubemap(Shader shader, Texture2D panorama, int size, int format)
{
@@ -3425,7 +3904,7 @@ TextureCubemap rlGenTextureCubemap(Shader shader, Texture2D panorama, int size,
rlEnableTexture(panorama.id); // WARNING: It must be called after enabling current framebuffer if using internal batch system!
#endif
rlClearScreenBuffers();
- GenDrawCube();
+ rlGenDrawCube();
#if defined(GENTEXTURECUBEMAP_USE_BATCH_SYSTEM)
// Using internal batch system instead of raw OpenGL cube creating+drawing
@@ -3505,7 +3984,7 @@ TextureCubemap rlGenTextureIrradiance(Shader shader, TextureCubemap cubemap, int
rlEnableFramebuffer(fbo);
rlClearScreenBuffers();
- GenDrawCube();
+ rlGenDrawCube();
}
//------------------------------------------------------------------------------------------
@@ -3602,7 +4081,7 @@ TextureCubemap rlGenTexturePrefilter(Shader shader, TextureCubemap cubemap, int
rlEnableFramebuffer(fbo);
rlClearScreenBuffers();
- GenDrawCube();
+ rlGenDrawCube();
}
}
//------------------------------------------------------------------------------------------
@@ -3653,7 +4132,7 @@ Texture2D rlGenTextureBRDF(Shader shader, int size)
rlEnableFramebuffer(fbo);
rlClearScreenBuffers();
- GenDrawQuad();
+ rlGenDrawQuad();
//------------------------------------------------------------------------------------------
// STEP 3: Unload framebuffer and reset state
@@ -3678,96 +4157,10 @@ Texture2D rlGenTextureBRDF(Shader shader, int size)
//----------------------------------------------------------------------------------
// Module specific Functions Definition
//----------------------------------------------------------------------------------
-
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-// Compile custom shader and return shader id
-static unsigned int CompileShader(const char *shaderStr, int type)
-{
- unsigned int shader = glCreateShader(type);
- glShaderSource(shader, 1, &shaderStr, NULL);
-
- GLint success = 0;
- glCompileShader(shader);
- glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
-
- if (success == GL_FALSE)
- {
- TRACELOG(LOG_WARNING, "SHADER: [ID %i] Failed to compile shader code", shader);
-
- int maxLength = 0;
- glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
-
- if (maxLength > 0)
- {
- int length = 0;
- char *log = RL_CALLOC(maxLength, sizeof(char));
- glGetShaderInfoLog(shader, maxLength, &length, log);
- TRACELOG(LOG_WARNING, "SHADER: [ID %i] Compile error: %s", shader, log);
- RL_FREE(log);
- }
- }
- else TRACELOG(LOG_INFO, "SHADER: [ID %i] Compiled successfully", shader);
-
- return shader;
-}
-
-// Load custom shader strings and return program id
-static unsigned int LoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId)
-{
- unsigned int program = 0;
-
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- GLint success = 0;
- program = glCreateProgram();
-
- glAttachShader(program, vShaderId);
- glAttachShader(program, fShaderId);
-
- // NOTE: Default attribute shader locations must be binded before linking
- glBindAttribLocation(program, 0, DEFAULT_SHADER_ATTRIB_NAME_POSITION);
- glBindAttribLocation(program, 1, DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD);
- glBindAttribLocation(program, 2, DEFAULT_SHADER_ATTRIB_NAME_NORMAL);
- glBindAttribLocation(program, 3, DEFAULT_SHADER_ATTRIB_NAME_COLOR);
- glBindAttribLocation(program, 4, DEFAULT_SHADER_ATTRIB_NAME_TANGENT);
- glBindAttribLocation(program, 5, DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2);
-
- // NOTE: If some attrib name is no found on the shader, it locations becomes -1
-
- glLinkProgram(program);
-
- // NOTE: All uniform variables are intitialised to 0 when a program links
-
- glGetProgramiv(program, GL_LINK_STATUS, &success);
-
- if (success == GL_FALSE)
- {
- TRACELOG(LOG_WARNING, "SHADER: [ID %i] Failed to link shader program", program);
-
- int maxLength = 0;
- glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
-
- if (maxLength > 0)
- {
- int length = 0;
- char *log = RL_CALLOC(maxLength, sizeof(char));
- glGetProgramInfoLog(program, maxLength, &length, log);
- TRACELOG(LOG_WARNING, "SHADER: [ID %i] Link error: %s", program, log);
- RL_FREE(log);
- }
-
- glDeleteProgram(program);
-
- program = 0;
- }
- else TRACELOG(LOG_INFO, "SHADER: [ID %i] Program loaded successfully", program);
-#endif
- return program;
-}
-
-
// Load default shader (just vertex positioning and texture coloring)
// NOTE: This shader program is used for internal buffers
-static Shader LoadShaderDefault(void)
+static Shader rlLoadShaderDefault(void)
{
Shader shader = { 0 };
shader.locs = (int *)RL_CALLOC(MAX_SHADER_LOCATIONS, sizeof(int));
@@ -3840,10 +4233,10 @@ static Shader LoadShaderDefault(void)
"} \n";
// NOTE: Compiled vertex/fragment shaders are kept for re-use
- RLGL.State.defaultVShaderId = CompileShader(defaultVShaderStr, GL_VERTEX_SHADER); // Compile default vertex shader
- RLGL.State.defaultFShaderId = CompileShader(defaultFShaderStr, GL_FRAGMENT_SHADER); // Compile default fragment shader
+ RLGL.State.defaultVShaderId = rlCompileShader(defaultVShaderStr, GL_VERTEX_SHADER); // Compile default vertex shader
+ RLGL.State.defaultFShaderId = rlCompileShader(defaultFShaderStr, GL_FRAGMENT_SHADER); // Compile default fragment shader
- shader.id = LoadShaderProgram(RLGL.State.defaultVShaderId, RLGL.State.defaultFShaderId);
+ shader.id = rlLoadShaderProgram(RLGL.State.defaultVShaderId, RLGL.State.defaultFShaderId);
if (shader.id > 0)
{
@@ -3858,50 +4251,14 @@ static Shader LoadShaderDefault(void)
shader.locs[SHADER_LOC_MATRIX_MVP] = glGetUniformLocation(shader.id, "mvp");
shader.locs[SHADER_LOC_COLOR_DIFFUSE] = glGetUniformLocation(shader.id, "colDiffuse");
shader.locs[SHADER_LOC_MAP_DIFFUSE] = glGetUniformLocation(shader.id, "texture0");
-
- // NOTE: We could also use below function but in case DEFAULT_ATTRIB_* points are
- // changed for external custom shaders, we just use direct bindings above
- //SetShaderDefaultLocations(&shader);
}
else TRACELOG(LOG_WARNING, "SHADER: [ID %i] Failed to load default shader", shader.id);
return shader;
}
-// Get location handlers to for shader attributes and uniforms
-// NOTE: If any location is not found, loc point becomes -1
-static void SetShaderDefaultLocations(Shader *shader)
-{
- // NOTE: Default shader attrib locations have been fixed before linking:
- // vertex position location = 0
- // vertex texcoord location = 1
- // vertex normal location = 2
- // vertex color location = 3
- // vertex tangent location = 4
- // vertex texcoord2 location = 5
-
- // Get handles to GLSL input attibute locations
- shader->locs[SHADER_LOC_VERTEX_POSITION] = glGetAttribLocation(shader->id, DEFAULT_SHADER_ATTRIB_NAME_POSITION);
- shader->locs[SHADER_LOC_VERTEX_TEXCOORD01] = glGetAttribLocation(shader->id, DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD);
- shader->locs[SHADER_LOC_VERTEX_TEXCOORD02] = glGetAttribLocation(shader->id, DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2);
- shader->locs[SHADER_LOC_VERTEX_NORMAL] = glGetAttribLocation(shader->id, DEFAULT_SHADER_ATTRIB_NAME_NORMAL);
- shader->locs[SHADER_LOC_VERTEX_TANGENT] = glGetAttribLocation(shader->id, DEFAULT_SHADER_ATTRIB_NAME_TANGENT);
- shader->locs[SHADER_LOC_VERTEX_COLOR] = glGetAttribLocation(shader->id, DEFAULT_SHADER_ATTRIB_NAME_COLOR);
-
- // Get handles to GLSL uniform locations (vertex shader)
- shader->locs[SHADER_LOC_MATRIX_MVP] = glGetUniformLocation(shader->id, "mvp");
- shader->locs[SHADER_LOC_MATRIX_PROJECTION] = glGetUniformLocation(shader->id, "projection");
- shader->locs[SHADER_LOC_MATRIX_VIEW] = glGetUniformLocation(shader->id, "view");
-
- // Get handles to GLSL uniform locations (fragment shader)
- shader->locs[SHADER_LOC_COLOR_DIFFUSE] = glGetUniformLocation(shader->id, "colDiffuse");
- shader->locs[SHADER_LOC_MAP_DIFFUSE] = glGetUniformLocation(shader->id, "texture0");
- shader->locs[SHADER_LOC_MAP_SPECULAR] = glGetUniformLocation(shader->id, "texture1");
- shader->locs[SHADER_LOC_MAP_NORMAL] = glGetUniformLocation(shader->id, "texture2");
-}
-
// Unload default shader
-static void UnloadShaderDefault(void)
+static void rlUnloadShaderDefault(void)
{
glUseProgram(0);
@@ -3915,372 +4272,8 @@ static void UnloadShaderDefault(void)
RL_FREE(RLGL.State.defaultShader.locs);
}
-// Load render batch
-RenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements)
-{
- RenderBatch batch = { 0 };
-
- // Initialize CPU (RAM) vertex buffers (position, texcoord, color data and indexes)
- //--------------------------------------------------------------------------------------------
- batch.vertexBuffer = (VertexBuffer *)RL_MALLOC(sizeof(VertexBuffer)*numBuffers);
-
- for (int i = 0; i < numBuffers; i++)
- {
- batch.vertexBuffer[i].elementsCount = bufferElements;
-
- batch.vertexBuffer[i].vertices = (float *)RL_MALLOC(bufferElements*3*4*sizeof(float)); // 3 float by vertex, 4 vertex by quad
- batch.vertexBuffer[i].texcoords = (float *)RL_MALLOC(bufferElements*2*4*sizeof(float)); // 2 float by texcoord, 4 texcoord by quad
- batch.vertexBuffer[i].colors = (unsigned char *)RL_MALLOC(bufferElements*4*4*sizeof(unsigned char)); // 4 float by color, 4 colors by quad
-#if defined(GRAPHICS_API_OPENGL_33)
- batch.vertexBuffer[i].indices = (unsigned int *)RL_MALLOC(bufferElements*6*sizeof(unsigned int)); // 6 int by quad (indices)
-#endif
-#if defined(GRAPHICS_API_OPENGL_ES2)
- batch.vertexBuffer[i].indices = (unsigned short *)RL_MALLOC(bufferElements*6*sizeof(unsigned short)); // 6 int by quad (indices)
-#endif
-
- for (int j = 0; j < (3*4*bufferElements); j++) batch.vertexBuffer[i].vertices[j] = 0.0f;
- for (int j = 0; j < (2*4*bufferElements); j++) batch.vertexBuffer[i].texcoords[j] = 0.0f;
- for (int j = 0; j < (4*4*bufferElements); j++) batch.vertexBuffer[i].colors[j] = 0;
-
- int k = 0;
-
- // Indices can be initialized right now
- for (int j = 0; j < (6*bufferElements); j += 6)
- {
- batch.vertexBuffer[i].indices[j] = 4*k;
- batch.vertexBuffer[i].indices[j + 1] = 4*k + 1;
- batch.vertexBuffer[i].indices[j + 2] = 4*k + 2;
- batch.vertexBuffer[i].indices[j + 3] = 4*k;
- batch.vertexBuffer[i].indices[j + 4] = 4*k + 2;
- batch.vertexBuffer[i].indices[j + 5] = 4*k + 3;
-
- k++;
- }
-
- batch.vertexBuffer[i].vCounter = 0;
- batch.vertexBuffer[i].tcCounter = 0;
- batch.vertexBuffer[i].cCounter = 0;
- }
-
- TRACELOG(LOG_INFO, "RLGL: Internal vertex buffers initialized successfully in RAM (CPU)");
- //--------------------------------------------------------------------------------------------
-
- // Upload to GPU (VRAM) vertex data and initialize VAOs/VBOs
- //--------------------------------------------------------------------------------------------
- for (int i = 0; i < numBuffers; i++)
- {
- if (RLGL.ExtSupported.vao)
- {
- // Initialize Quads VAO
- glGenVertexArrays(1, &batch.vertexBuffer[i].vaoId);
- glBindVertexArray(batch.vertexBuffer[i].vaoId);
- }
-
- // Quads - Vertex buffers binding and attributes enable
- // Vertex position buffer (shader-location = 0)
- glGenBuffers(1, &batch.vertexBuffer[i].vboId[0]);
- glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[0]);
- glBufferData(GL_ARRAY_BUFFER, bufferElements*3*4*sizeof(float), batch.vertexBuffer[i].vertices, GL_DYNAMIC_DRAW);
- glEnableVertexAttribArray(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_POSITION]);
- glVertexAttribPointer(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0);
-
- // Vertex texcoord buffer (shader-location = 1)
- glGenBuffers(1, &batch.vertexBuffer[i].vboId[1]);
- glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[1]);
- glBufferData(GL_ARRAY_BUFFER, bufferElements*2*4*sizeof(float), batch.vertexBuffer[i].texcoords, GL_DYNAMIC_DRAW);
- glEnableVertexAttribArray(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_TEXCOORD01]);
- glVertexAttribPointer(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0);
-
- // Vertex color buffer (shader-location = 3)
- glGenBuffers(1, &batch.vertexBuffer[i].vboId[2]);
- glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[2]);
- glBufferData(GL_ARRAY_BUFFER, bufferElements*4*4*sizeof(unsigned char), batch.vertexBuffer[i].colors, GL_DYNAMIC_DRAW);
- glEnableVertexAttribArray(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_COLOR]);
- glVertexAttribPointer(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
-
- // Fill index buffer
- glGenBuffers(1, &batch.vertexBuffer[i].vboId[3]);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[3]);
-#if defined(GRAPHICS_API_OPENGL_33)
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufferElements*6*sizeof(int), batch.vertexBuffer[i].indices, GL_STATIC_DRAW);
-#endif
-#if defined(GRAPHICS_API_OPENGL_ES2)
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufferElements*6*sizeof(short), batch.vertexBuffer[i].indices, GL_STATIC_DRAW);
-#endif
- }
-
- TRACELOG(LOG_INFO, "RLGL: Render batch vertex buffers loaded successfully");
-
- // Unbind the current VAO
- if (RLGL.ExtSupported.vao) glBindVertexArray(0);
- //--------------------------------------------------------------------------------------------
-
- // Init draw calls tracking system
- //--------------------------------------------------------------------------------------------
- batch.draws = (DrawCall *)RL_MALLOC(DEFAULT_BATCH_DRAWCALLS*sizeof(DrawCall));
-
- for (int i = 0; i < DEFAULT_BATCH_DRAWCALLS; i++)
- {
- batch.draws[i].mode = RL_QUADS;
- batch.draws[i].vertexCount = 0;
- batch.draws[i].vertexAlignment = 0;
- //batch.draws[i].vaoId = 0;
- //batch.draws[i].shaderId = 0;
- batch.draws[i].textureId = RLGL.State.defaultTextureId;
- //batch.draws[i].RLGL.State.projection = MatrixIdentity();
- //batch.draws[i].RLGL.State.modelview = MatrixIdentity();
- }
-
- batch.buffersCount = numBuffers; // Record buffer count
- batch.drawsCounter = 1; // Reset draws counter
- batch.currentDepth = -1.0f; // Reset depth value
- //--------------------------------------------------------------------------------------------
-
- return batch;
-}
-
-// Draw render batch
-// NOTE: We require a pointer to reset batch and increase current buffer (multi-buffer)
-void rlDrawRenderBatch(RenderBatch *batch)
-{
- // Update batch vertex buffers
- //------------------------------------------------------------------------------------------------------------
- // NOTE: If there is not vertex data, buffers doesn't need to be updated (vertexCount > 0)
- // TODO: If no data changed on the CPU arrays --> No need to re-update GPU arrays (change flag required)
- if (batch->vertexBuffer[batch->currentBuffer].vCounter > 0)
- {
- // Activate elements VAO
- if (RLGL.ExtSupported.vao) glBindVertexArray(batch->vertexBuffer[batch->currentBuffer].vaoId);
-
- // Vertex positions buffer
- glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[0]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, batch->vertexBuffer[batch->currentBuffer].vCounter*3*sizeof(float), batch->vertexBuffer[batch->currentBuffer].vertices);
- //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*batch->vertexBuffer[batch->currentBuffer].elementsCount, batch->vertexBuffer[batch->currentBuffer].vertices, GL_DYNAMIC_DRAW); // Update all buffer
-
- // Texture coordinates buffer
- glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[1]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, batch->vertexBuffer[batch->currentBuffer].vCounter*2*sizeof(float), batch->vertexBuffer[batch->currentBuffer].texcoords);
- //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*batch->vertexBuffer[batch->currentBuffer].elementsCount, batch->vertexBuffer[batch->currentBuffer].texcoords, GL_DYNAMIC_DRAW); // Update all buffer
-
- // Colors buffer
- glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[2]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, batch->vertexBuffer[batch->currentBuffer].vCounter*4*sizeof(unsigned char), batch->vertexBuffer[batch->currentBuffer].colors);
- //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*4*batch->vertexBuffer[batch->currentBuffer].elementsCount, batch->vertexBuffer[batch->currentBuffer].colors, GL_DYNAMIC_DRAW); // Update all buffer
-
- // NOTE: glMapBuffer() causes sync issue.
- // If GPU is working with this buffer, glMapBuffer() will wait(stall) until GPU to finish its job.
- // To avoid waiting (idle), you can call first glBufferData() with NULL pointer before glMapBuffer().
- // If you do that, the previous data in PBO will be discarded and glMapBuffer() returns a new
- // allocated pointer immediately even if GPU is still working with the previous data.
-
- // Another option: map the buffer object into client's memory
- // Probably this code could be moved somewhere else...
- // batch->vertexBuffer[batch->currentBuffer].vertices = (float *)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);
- // if (batch->vertexBuffer[batch->currentBuffer].vertices)
- // {
- // Update vertex data
- // }
- // glUnmapBuffer(GL_ARRAY_BUFFER);
-
- // Unbind the current VAO
- if (RLGL.ExtSupported.vao) glBindVertexArray(0);
- }
- //------------------------------------------------------------------------------------------------------------
-
- // Draw batch vertex buffers (considering VR stereo if required)
- //------------------------------------------------------------------------------------------------------------
- Matrix matProjection = RLGL.State.projection;
- Matrix matModelView = RLGL.State.modelview;
-
- int eyesCount = 1;
- if (RLGL.State.stereoRender) eyesCount = 2;
-
- for (int eye = 0; eye < eyesCount; eye++)
- {
- if (eyesCount == 2)
- {
- // Setup current eye viewport (half screen width)
- rlViewport(eye*RLGL.State.framebufferWidth/2, 0, RLGL.State.framebufferWidth/2, RLGL.State.framebufferHeight);
-
- // Set current eye view offset to modelview matrix
- rlSetMatrixModelview(MatrixMultiply(matModelView, RLGL.State.eyesViewOffset[eye]));
- // Set current eye projection matrix
- rlSetMatrixProjection(RLGL.State.eyesProjection[eye]);
- }
-
- // Draw buffers
- if (batch->vertexBuffer[batch->currentBuffer].vCounter > 0)
- {
- // Set current shader and upload current MVP matrix
- glUseProgram(RLGL.State.currentShader.id);
-
- // Create modelview-projection matrix and upload to shader
- Matrix matMVP = MatrixMultiply(RLGL.State.modelview, RLGL.State.projection);
- glUniformMatrix4fv(RLGL.State.currentShader.locs[SHADER_LOC_MATRIX_MVP], 1, false, MatrixToFloat(matMVP));
-
- if (RLGL.ExtSupported.vao) glBindVertexArray(batch->vertexBuffer[batch->currentBuffer].vaoId);
- else
- {
- // Bind vertex attrib: position (shader-location = 0)
- glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[0]);
- glVertexAttribPointer(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0);
- glEnableVertexAttribArray(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_POSITION]);
-
- // Bind vertex attrib: texcoord (shader-location = 1)
- glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[1]);
- glVertexAttribPointer(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0);
- glEnableVertexAttribArray(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_TEXCOORD01]);
-
- // Bind vertex attrib: color (shader-location = 3)
- glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[2]);
- glVertexAttribPointer(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
- glEnableVertexAttribArray(RLGL.State.currentShader.locs[SHADER_LOC_VERTEX_COLOR]);
-
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[3]);
- }
-
- // Setup some default shader values
- glUniform4f(RLGL.State.currentShader.locs[SHADER_LOC_COLOR_DIFFUSE], 1.0f, 1.0f, 1.0f, 1.0f);
- glUniform1i(RLGL.State.currentShader.locs[SHADER_LOC_MAP_DIFFUSE], 0); // Active default sampler2D: texture0
-
- // Activate additional sampler textures
- // Those additional textures will be common for all draw calls of the batch
- for (int i = 0; i < MAX_BATCH_ACTIVE_TEXTURES; i++)
- {
- if (RLGL.State.activeTextureId[i] > 0)
- {
- glActiveTexture(GL_TEXTURE0 + 1 + i);
- glBindTexture(GL_TEXTURE_2D, RLGL.State.activeTextureId[i]);
- }
- }
-
- // Activate default sampler2D texture0 (one texture is always active for default batch shader)
- // NOTE: Batch system accumulates calls by texture0 changes, additional textures are enabled for all the draw calls
- glActiveTexture(GL_TEXTURE0);
-
- for (int i = 0, vertexOffset = 0; i < batch->drawsCounter; i++)
- {
- // Bind current draw call texture, activated as GL_TEXTURE0 and binded to sampler2D texture0 by default
- glBindTexture(GL_TEXTURE_2D, batch->draws[i].textureId);
-
- if ((batch->draws[i].mode == RL_LINES) || (batch->draws[i].mode == RL_TRIANGLES)) glDrawArrays(batch->draws[i].mode, vertexOffset, batch->draws[i].vertexCount);
- else
- {
-#if defined(GRAPHICS_API_OPENGL_33)
- // We need to define the number of indices to be processed: quadsCount*6
- // NOTE: The final parameter tells the GPU the offset in bytes from the
- // start of the index buffer to the location of the first index to process
- glDrawElements(GL_TRIANGLES, batch->draws[i].vertexCount/4*6, GL_UNSIGNED_INT, (GLvoid *)(vertexOffset/4*6*sizeof(GLuint)));
-#endif
-#if defined(GRAPHICS_API_OPENGL_ES2)
- glDrawElements(GL_TRIANGLES, batch->draws[i].vertexCount/4*6, GL_UNSIGNED_SHORT, (GLvoid *)(vertexOffset/4*6*sizeof(GLushort)));
-#endif
- }
-
- vertexOffset += (batch->draws[i].vertexCount + batch->draws[i].vertexAlignment);
- }
-
- if (!RLGL.ExtSupported.vao)
- {
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- }
-
- glBindTexture(GL_TEXTURE_2D, 0); // Unbind textures
- }
-
- if (RLGL.ExtSupported.vao) glBindVertexArray(0); // Unbind VAO
-
- glUseProgram(0); // Unbind shader program
- }
- //------------------------------------------------------------------------------------------------------------
-
- // Reset batch buffers
- //------------------------------------------------------------------------------------------------------------
- // Reset vertex counters for next frame
- batch->vertexBuffer[batch->currentBuffer].vCounter = 0;
- batch->vertexBuffer[batch->currentBuffer].tcCounter = 0;
- batch->vertexBuffer[batch->currentBuffer].cCounter = 0;
-
- // Reset depth for next draw
- batch->currentDepth = -1.0f;
-
- // Restore projection/modelview matrices
- RLGL.State.projection = matProjection;
- RLGL.State.modelview = matModelView;
-
- // Reset RLGL.currentBatch->draws array
- for (int i = 0; i < DEFAULT_BATCH_DRAWCALLS; i++)
- {
- batch->draws[i].mode = RL_QUADS;
- batch->draws[i].vertexCount = 0;
- batch->draws[i].textureId = RLGL.State.defaultTextureId;
- }
-
- // Reset active texture units for next batch
- for (int i = 0; i < MAX_BATCH_ACTIVE_TEXTURES; i++) RLGL.State.activeTextureId[i] = 0;
-
- // Reset draws counter to one draw for the batch
- batch->drawsCounter = 1;
- //------------------------------------------------------------------------------------------------------------
-
- // Change to next buffer in the list (in case of multi-buffering)
- batch->currentBuffer++;
- if (batch->currentBuffer >= batch->buffersCount) batch->currentBuffer = 0;
-}
-
-// Unload default internal buffers vertex data from CPU and GPU
-void rlUnloadRenderBatch(RenderBatch batch)
-{
- // Unbind everything
- if (RLGL.ExtSupported.vao) glBindVertexArray(0);
- glDisableVertexAttribArray(0);
- glDisableVertexAttribArray(1);
- glDisableVertexAttribArray(2);
- glDisableVertexAttribArray(3);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-
- // Unload all vertex buffers data
- for (int i = 0; i < batch.buffersCount; i++)
- {
- // Delete VBOs from GPU (VRAM)
- glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[0]);
- glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[1]);
- glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[2]);
- glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[3]);
-
- // Delete VAOs from GPU (VRAM)
- if (RLGL.ExtSupported.vao) glDeleteVertexArrays(1, &batch.vertexBuffer[i].vaoId);
-
- // Free vertex arrays memory from CPU (RAM)
- RL_FREE(batch.vertexBuffer[i].vertices);
- RL_FREE(batch.vertexBuffer[i].texcoords);
- RL_FREE(batch.vertexBuffer[i].colors);
- RL_FREE(batch.vertexBuffer[i].indices);
- }
-
- // Unload arrays
- RL_FREE(batch.vertexBuffer);
- RL_FREE(batch.draws);
-}
-
-// Set the active render batch for rlgl
-void rlSetRenderBatchActive(RenderBatch *batch)
-{
- rlDrawRenderBatch(RLGL.currentBatch);
- RLGL.currentBatch = batch;
-}
-
-// Set default render batch for rlgl
-void rlSetRenderBatchDefault(void)
-{
- rlDrawRenderBatch(RLGL.currentBatch);
- RLGL.currentBatch = &RLGL.defaultBatch;
-}
-
// Renders a 1x1 XY quad in NDC
-static void GenDrawQuad(void)
+static void rlGenDrawQuad(void)
{
unsigned int quadVAO = 0;
unsigned int quadVBO = 0;
@@ -4319,7 +4312,7 @@ static void GenDrawQuad(void)
}
// Renders a 1x1 3D cube in NDC
-static void GenDrawCube(void)
+static void rlGenDrawCube(void)
{
unsigned int cubeVAO = 0;
unsigned int cubeVBO = 0;
@@ -4398,7 +4391,7 @@ static void GenDrawCube(void)
#if defined(GRAPHICS_API_OPENGL_11)
// Mipmaps data is generated after image data
// NOTE: Only works with RGBA (4 bytes) data!
-static int GenerateMipmaps(unsigned char *data, int baseWidth, int baseHeight)
+static int rlGenerateMipmapsData(unsigned char *data, int baseWidth, int baseHeight)
{
int mipmapCount = 1; // Required mipmap levels count (including base level)
int width = baseWidth;
@@ -4450,7 +4443,7 @@ static int GenerateMipmaps(unsigned char *data, int baseWidth, int baseHeight)
for (int mip = 1; mip < mipmapCount; mip++)
{
- mipmap = GenNextMipmap(image, width, height);
+ mipmap = rlGenNextMipmapData(image, width, height);
offset += (width*height*4); // Size of last mipmap
j = 0;
@@ -4481,7 +4474,7 @@ static int GenerateMipmaps(unsigned char *data, int baseWidth, int baseHeight)
}
// Manual mipmap generation (basic scaling algorithm)
-static Color *GenNextMipmap(Color *srcData, int srcWidth, int srcHeight)
+static Color *rlGenNextMipmapData(Color *srcData, int srcWidth, int srcHeight)
{
int x2, y2;
Color prow, pcol;