Browse Source

WARNING: Big internal redesign!

Created RenderBatch type and related functions to allow rlgl users creating custom and separate render batches and not only rely on one internal render batch.

This feature has not been exposed on raylib yet because it implies some breaking changes. Right now a custom RenderBatch is just used internally in rlgl.
pull/1233/head
raysan5 4 years ago
parent
commit
c83477ffca
1 changed files with 302 additions and 252 deletions
  1. +302
    -252
      src/rlgl.h

+ 302
- 252
src/rlgl.h View File

@ -128,31 +128,45 @@
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
// This is the maximum amount of elements (quads) per batch
// NOTE: Be careful with text, every letter maps to a quad
#define MAX_BATCH_ELEMENTS 8192
#elif defined(GRAPHICS_API_OPENGL_ES2)
// We reduce memory sizes for embedded systems (RPI and HTML5)
// NOTE: On HTML5 (emscripten) this is allocated on heap, by default it's only 16MB!...just take care...
#define MAX_BATCH_ELEMENTS 2048
// Default internal render batch limits
#ifndef DEFAULT_BATCH_BUFFER_ELEMENTS
#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
// This is the maximum amount of elements (quads) per batch
// NOTE: Be careful with text, every letter maps to a quad
#define DEFAULT_BATCH_BUFFER_ELEMENTS 8192
#elif defined(GRAPHICS_API_OPENGL_ES2)
// We reduce memory sizes for embedded systems (RPI and HTML5)
// NOTE: On HTML5 (emscripten) this is allocated on heap,
// by default it's only 16MB!...just take care...
#define DEFAULT_BATCH_BUFFER_ELEMENTS 2048
#endif
#endif
#ifndef DEFAULT_BATCH_BUFFERS
#define DEFAULT_BATCH_BUFFERS 1 // Default number of batch buffers (multi-buffering)
#endif
#ifndef DEFAULT_BATCH_DRAWCALLS
#define DEFAULT_BATCH_DRAWCALLS 256 // Default number of batch draw calls (by state changes: mode, texture)
#endif
#ifndef MAX_BATCH_BUFFERING
#define MAX_BATCH_BUFFERING 1 // Max number of buffers for batching (multi-buffering)
// Internal Matrix stack
#ifndef MAX_MATRIX_STACK_SIZE
#define MAX_MATRIX_STACK_SIZE 32 // Maximum size of Matrix stack
#endif
#define MAX_MATRIX_STACK_SIZE 32 // Max size of Matrix stack
#define MAX_DRAWCALL_REGISTERED 256 // Max draws by state changes (mode, texture)
// Shader and material limits
#define MAX_SHADER_LOCATIONS 32 // Maximum number of predefined locations stored in shader struct
#define MAX_MATERIAL_MAPS 12 // Maximum number of texture maps stored in shader struct
#ifndef MAX_SHADER_LOCATIONS
#define MAX_SHADER_LOCATIONS 32 // Maximum number of shader locations supported
#endif
#ifndef MAX_MATERIAL_MAPS
#define MAX_MATERIAL_MAPS 12 // Maximum number of shader maps supported
#endif
#ifndef RL_NEAR_CULL_DISTANCE
#define RL_NEAR_CULL_DISTANCE 0.01 // Default near cull distance
// Projection matrix culling
#ifndef RL_CULL_DISTANCE_NEAR
#define RL_CULL_DISTANCE_NEAR 0.01 // Default near cull distance
#endif
#ifndef RL_FAR_CULL_DISTANCE
#define RL_FAR_CULL_DISTANCE 1000.0 // Default far cull distance
#ifndef RL_CULL_DISTANCE_FAR
#define RL_CULL_DISTANCE_FAR 1000.0 // Default far cull distance
#endif
// Texture parameters (equivalent to OpenGL defines)
@ -263,10 +277,6 @@ typedef unsigned char byte;
unsigned int *vboId; // OpenGL Vertex Buffer Objects id (7 types of vertex data)
} Mesh;
// Shader and material limits
#define MAX_SHADER_LOCATIONS 32
#define MAX_MATERIAL_MAPS 12
// Shader type (generic)
typedef struct Shader {
unsigned int id; // Shader program id
@ -758,36 +768,52 @@ RLAPI int GetPixelDataSize(int width, int height, int format);// Get pixel data
//----------------------------------------------------------------------------------
// Dynamic vertex buffers (position + texcoords + colors + indices arrays)
typedef struct DynamicBuffer {
int vCounter; // vertex position counter to process (and draw) from full buffer
int tcCounter; // vertex texcoord counter to process (and draw) from full buffer
int cCounter; // vertex color counter to process (and draw) from full buffer
float *vertices; // vertex position (XYZ - 3 components per vertex) (shader-location = 0)
float *texcoords; // vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1)
unsigned char *colors; // vertex colors (RGBA - 4 components per vertex) (shader-location = 3)
typedef struct VertexBuffer {
int elementsCount; // Number of elements in the buffer (QUADS)
int vCounter; // Vertex position counter to process (and draw) from full buffer
int tcCounter; // Vertex texcoord counter to process (and draw) from full buffer
int cCounter; // Vertex color counter to process (and draw) from full buffer
float *vertices; // Vertex position (XYZ - 3 components per vertex) (shader-location = 0)
float *texcoords; // Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1)
unsigned char *colors; // Vertex colors (RGBA - 4 components per vertex) (shader-location = 3)
#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
unsigned int *indices; // vertex indices (in case vertex data comes indexed) (6 indices per quad)
unsigned int *indices; // Vertex indices (in case vertex data comes indexed) (6 indices per quad)
#elif defined(GRAPHICS_API_OPENGL_ES2)
unsigned short *indices; // vertex indices (in case vertex data comes indexed) (6 indices per quad)
unsigned short *indices; // Vertex indices (in case vertex data comes indexed) (6 indices per quad)
#endif
unsigned int vaoId; // OpenGL Vertex Array Object id
unsigned int vboId[4]; // OpenGL Vertex Buffer Objects id (4 types of vertex data)
} DynamicBuffer;
} VertexBuffer;
// Draw call type
// NOTE: Only texture changes register a new draw, other state-change-related elements are not
// used at this moment (vaoId, shaderId, matrices), raylib just forces a batch draw call if any
// of those state-change happens (this is done in core module)
typedef struct DrawCall {
int mode; // Drawing mode: LINES, TRIANGLES, QUADS
int vertexCount; // Number of vertex of the draw
int vertexAlignment; // Number of vertex required for index alignment (LINES, TRIANGLES)
//unsigned int vaoId; // Vertex array id to be used on the draw
//unsigned int shaderId; // Shader id to be used on the draw
//unsigned int vaoId; // Vertex array id to be used on the draw
//unsigned int shaderId; // Shader id to be used on the draw
unsigned int textureId; // Texture id to be used on the draw
//Matrix projection; // Projection matrix for this draw
//Matrix modelview; // Modelview matrix for this draw
} DrawCall;
// RenderBatch type
typedef struct RenderBatch {
int buffersCount; // Number of vertex buffers (multi-buffering support)
int currentBuffer; // Current buffer tracking in case of multi-buffering
VertexBuffer *vertexBuffer; // Dynamic buffer(s) for vertex data
DrawCall *draws; // Draw calls array
int drawsCounter; // Draw calls counter
float currentDepth; // Current depth value for next draw
} RenderBatch;
#if defined(SUPPORT_VR_SIMULATOR)
// VR Stereo rendering configuration for simulator
typedef struct VrStereoConfig {
@ -801,21 +827,19 @@ typedef struct VrStereoConfig {
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
typedef struct rlglData {
RenderBatch *currentBatch; // Current render batch
RenderBatch defaultBatch; // Default internal render batch
struct {
int currentMatrixMode; // Current matrix mode
Matrix *currentMatrix; // Current matrix pointer
Matrix modelview; // Default modelview matrix
Matrix projection; // Default projection matrix
Matrix transform; // Transform matrix to be used with rlTranslate, rlRotate, rlScale
bool doTransform; // Use transform matrix against vertex (if required)
bool transformRequired; // Require transform matrix application to current draw-call vertex (if required)
Matrix stack[MAX_MATRIX_STACK_SIZE];// Matrix stack for push/pop
int stackCounter; // Matrix stack counter
DynamicBuffer vertexData[MAX_BATCH_BUFFERING];// Default dynamic buffer for elements data
int currentBuffer; // Current buffer tracking, multi-buffering system is supported
DrawCall *draws; // Draw calls array
int drawsCounter; // Draw calls counter
Texture2D shapesTexture; // Texture used on shapes drawing (usually a white)
Rectangle shapesTextureRec; // Texture source rectangle used on shapes drawing
unsigned int defaultTextureId; // Default texture used on shapes/poly drawing (required by shader)
@ -823,7 +847,6 @@ typedef struct rlglData {
unsigned int defaultFShaderId; // Default fragment shader Id (used by default shader program)
Shader defaultShader; // Basic shader, support vertex color and diffuse texture
Shader currentShader; // Shader to be used on rendering (by default, defaultShader)
float currentDepth; // Current depth value
int framebufferWidth; // Default framebuffer width
int framebufferHeight; // Default framebuffer height
@ -879,14 +902,16 @@ static PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArrays; // Entry point poin
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 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 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 LoadBuffersDefault(void); // Load default internal buffers
static void UpdateBuffersDefault(void); // Update default internal buffers (VAOs/VBOs) with vertex data
static void DrawBuffersDefault(void); // Draw default internal buffers vertex data
static void UnloadBuffersDefault(void); // Unload default internal buffers vertex data from CPU and GPU
static RenderBatch LoadRenderBatch(int numBuffers, int bufferElements); // Load a render batch system
static void UnloadRenderBatch(RenderBatch batch); // Unload render batch system
static void DrawRenderBatch(RenderBatch *batch); // Draw render batch data (Update->Draw->Reset)
static void SetRenderBatchActive(RenderBatch *batch); // Set the active render batch for rlgl
static void SetRenderBatchDefault(void); // Set default render batch for rlgl
//static bool CheckRenderBatchLimit(RenderBatch batch, int vCount); // Check render batch vertex buffer limits
static void GenDrawCube(void); // Generate and draw cube
static void GenDrawQuad(void); // Generate and draw quad
@ -958,7 +983,7 @@ void rlPushMatrix(void)
if (RLGL.State.currentMatrixMode == RL_MODELVIEW)
{
RLGL.State.doTransform = true;
RLGL.State.transformRequired = true;
RLGL.State.currentMatrix = &RLGL.State.transform;
}
@ -979,7 +1004,7 @@ void rlPopMatrix(void)
if ((RLGL.State.stackCounter == 0) && (RLGL.State.currentMatrixMode == RL_MODELVIEW))
{
RLGL.State.currentMatrix = &RLGL.State.modelview;
RLGL.State.doTransform = false;
RLGL.State.transformRequired = false;
}
}
@ -1091,36 +1116,36 @@ void rlBegin(int mode)
{
// Draw mode can be RL_LINES, RL_TRIANGLES and RL_QUADS
// NOTE: In all three cases, vertex are accumulated over default internal vertex buffer
if (RLGL.State.draws[RLGL.State.drawsCounter - 1].mode != mode)
if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].mode != mode)
{
if (RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount > 0)
if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount > 0)
{
// Make sure current RLGL.State.draws[i].vertexCount is aligned a multiple of 4,
// Make sure current RLGL.currentBatch->draws[i].vertexCount is aligned a multiple of 4,
// that way, following QUADS drawing will keep aligned with index processing
// It implies adding some extra alignment vertex at the end of the draw,
// those vertex are not processed but they are considered as an additional offset
// for the next set of vertex to be drawn
if (RLGL.State.draws[RLGL.State.drawsCounter - 1].mode == RL_LINES) RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment = ((RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount < 4)? RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount : RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount%4);
else if (RLGL.State.draws[RLGL.State.drawsCounter - 1].mode == RL_TRIANGLES) RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment = ((RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount < 4)? 1 : (4 - (RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount%4)));
if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].mode == RL_LINES) RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount < 4)? RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount : RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount%4);
else if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].mode == RL_TRIANGLES) RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount < 4)? 1 : (4 - (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount%4)));
else RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment = 0;
else RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment = 0;
if (rlCheckBufferLimit(RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment)) rlglDraw();
if (rlCheckBufferLimit(RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment)) rlglDraw();
else
{
RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter += RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment;
RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter += RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment;
RLGL.State.vertexData[RLGL.State.currentBuffer].tcCounter += RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment;
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment;
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment;
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment;
RLGL.State.drawsCounter++;
RLGL.currentBatch->drawsCounter++;
}
}
if (RLGL.State.drawsCounter >= MAX_DRAWCALL_REGISTERED) rlglDraw();
if (RLGL.currentBatch->drawsCounter >= DEFAULT_BATCH_DRAWCALLS) rlglDraw();
RLGL.State.draws[RLGL.State.drawsCounter - 1].mode = mode;
RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount = 0;
RLGL.State.draws[RLGL.State.drawsCounter - 1].textureId = RLGL.State.defaultTextureId;
RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].mode = mode;
RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount = 0;
RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].textureId = RLGL.State.defaultTextureId;
}
}
@ -1131,30 +1156,30 @@ void rlEnd(void)
// NOTE: In OpenGL 1.1, one glColor call can be made for all the subsequent glVertex calls
// Make sure colors count match vertex count
if (RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter != RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter)
if (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter != RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter)
{
int addColors = RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter - RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter;
int addColors = RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter - RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter;
for (int i = 0; i < addColors; i++)
{
RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter] = RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter - 4];
RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter + 1] = RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter - 3];
RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter + 2] = RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter - 2];
RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter + 3] = RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter - 1];
RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter++;
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter] = RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter - 4];
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter + 1] = RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter - 3];
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter + 2] = RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter - 2];
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter + 3] = RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter - 1];
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter++;
}
}
// Make sure texcoords count match vertex count
if (RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter != RLGL.State.vertexData[RLGL.State.currentBuffer].tcCounter)
if (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter != RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter)
{
int addTexCoords = RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter - RLGL.State.vertexData[RLGL.State.currentBuffer].tcCounter;
int addTexCoords = RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter - RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter;
for (int i = 0; i < addTexCoords; i++)
{
RLGL.State.vertexData[RLGL.State.currentBuffer].texcoords[2*RLGL.State.vertexData[RLGL.State.currentBuffer].tcCounter] = 0.0f;
RLGL.State.vertexData[RLGL.State.currentBuffer].texcoords[2*RLGL.State.vertexData[RLGL.State.currentBuffer].tcCounter + 1] = 0.0f;
RLGL.State.vertexData[RLGL.State.currentBuffer].tcCounter++;
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].texcoords[2*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter] = 0.0f;
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].texcoords[2*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter + 1] = 0.0f;
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter++;
}
}
@ -1163,11 +1188,11 @@ void rlEnd(void)
// NOTE: Depth increment is dependant on rlOrtho(): z-near and z-far values,
// as well as depth buffer bit-depth (16bit or 24bit or 32bit)
// Correct increment formula would be: depthInc = (zfar - znear)/pow(2, bits)
RLGL.State.currentDepth += (1.0f/20000.0f);
RLGL.currentBatch->currentDepth += (1.0f/20000.0f);
// Verify internal buffers limits
// NOTE: This check is combined with usage of rlCheckBufferLimit()
if ((RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter) >= (MAX_BATCH_ELEMENTS*4 - 4))
if ((RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter) >= (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementsCount*4 - 4))
{
// WARNING: If we are between rlPushMatrix() and rlPopMatrix() and we need to force a rlglDraw(),
// we need to call rlPopMatrix() before to recover *RLGL.State.currentMatrix (RLGL.State.modelview) for the next forced draw call!
@ -1184,40 +1209,40 @@ void rlVertex3f(float x, float y, float z)
Vector3 vec = { x, y, z };
// Transform provided vector if required
if (RLGL.State.doTransform) vec = Vector3Transform(vec, RLGL.State.transform);
if (RLGL.State.transformRequired) vec = Vector3Transform(vec, RLGL.State.transform);
// Verify that MAX_BATCH_ELEMENTS limit not reached
if (RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter < (MAX_BATCH_ELEMENTS*4))
// Verify that current vertex buffer elements limit has not been reached
if (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter < (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementsCount*4))
{
RLGL.State.vertexData[RLGL.State.currentBuffer].vertices[3*RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter] = vec.x;
RLGL.State.vertexData[RLGL.State.currentBuffer].vertices[3*RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter + 1] = vec.y;
RLGL.State.vertexData[RLGL.State.currentBuffer].vertices[3*RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter + 2] = vec.z;
RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter++;
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vertices[3*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter] = vec.x;
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vertices[3*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter + 1] = vec.y;
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vertices[3*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter + 2] = vec.z;
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter++;
RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount++;
RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount++;
}
else TRACELOG(LOG_ERROR, "RLGL: Batch elements overflow (MAX_BATCH_ELEMENTS)");
else TRACELOG(LOG_ERROR, "RLGL: Batch elements overflow");
}
// Define one vertex (position)
void rlVertex2f(float x, float y)
{
rlVertex3f(x, y, RLGL.State.currentDepth);
rlVertex3f(x, y, RLGL.currentBatch->currentDepth);
}
// Define one vertex (position)
void rlVertex2i(int x, int y)
{
rlVertex3f((float)x, (float)y, RLGL.State.currentDepth);
rlVertex3f((float)x, (float)y, RLGL.currentBatch->currentDepth);
}
// Define one vertex (texture coordinate)
// NOTE: Texture coordinates are limited to QUADS only
void rlTexCoord2f(float x, float y)
{
RLGL.State.vertexData[RLGL.State.currentBuffer].texcoords[2*RLGL.State.vertexData[RLGL.State.currentBuffer].tcCounter] = x;
RLGL.State.vertexData[RLGL.State.currentBuffer].texcoords[2*RLGL.State.vertexData[RLGL.State.currentBuffer].tcCounter + 1] = y;
RLGL.State.vertexData[RLGL.State.currentBuffer].tcCounter++;
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].texcoords[2*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter] = x;
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].texcoords[2*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter + 1] = y;
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter++;
}
// Define one vertex (normal)
@ -1230,11 +1255,11 @@ void rlNormal3f(float x, float y, float z)
// Define one vertex (color)
void rlColor4ub(byte x, byte y, byte z, byte w)
{
RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter] = x;
RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter + 1] = y;
RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter + 2] = z;
RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter + 3] = w;
RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter++;
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter] = x;
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter + 1] = y;
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter + 2] = z;
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter + 3] = w;
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter++;
}
// Define one vertex (color)
@ -1264,35 +1289,35 @@ void rlEnableTexture(unsigned int id)
#endif
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
if (RLGL.State.draws[RLGL.State.drawsCounter - 1].textureId != id)
if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].textureId != id)
{
if (RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount > 0)
if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount > 0)
{
// Make sure current RLGL.State.draws[i].vertexCount is aligned a multiple of 4,
// Make sure current RLGL.currentBatch->draws[i].vertexCount is aligned a multiple of 4,
// that way, following QUADS drawing will keep aligned with index processing
// It implies adding some extra alignment vertex at the end of the draw,
// those vertex are not processed but they are considered as an additional offset
// for the next set of vertex to be drawn
if (RLGL.State.draws[RLGL.State.drawsCounter - 1].mode == RL_LINES) RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment = ((RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount < 4)? RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount : RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount%4);
else if (RLGL.State.draws[RLGL.State.drawsCounter - 1].mode == RL_TRIANGLES) RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment = ((RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount < 4)? 1 : (4 - (RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount%4)));
if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].mode == RL_LINES) RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount < 4)? RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount : RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount%4);
else if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].mode == RL_TRIANGLES) RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount < 4)? 1 : (4 - (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount%4)));
else RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment = 0;
else RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment = 0;
if (rlCheckBufferLimit(RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment)) rlglDraw();
if (rlCheckBufferLimit(RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment)) rlglDraw();
else
{
RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter += RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment;
RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter += RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment;
RLGL.State.vertexData[RLGL.State.currentBuffer].tcCounter += RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment;
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment;
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment;
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment;
RLGL.State.drawsCounter++;
RLGL.currentBatch->drawsCounter++;
}
}
if (RLGL.State.drawsCounter >= MAX_DRAWCALL_REGISTERED) rlglDraw();
if (RLGL.currentBatch->drawsCounter >= DEFAULT_BATCH_DRAWCALLS) rlglDraw();
RLGL.State.draws[RLGL.State.drawsCounter - 1].textureId = id;
RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount = 0;
RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].textureId = id;
RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount = 0;
}
#endif
}
@ -1306,7 +1331,7 @@ void rlDisableTexture(void)
#else
// NOTE: If quads batch limit is reached,
// we force a draw call and next batch starts
if (RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter >= (MAX_BATCH_ELEMENTS*4)) rlglDraw();
if (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter >= (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementsCount*4)) rlglDraw();
#endif
}
@ -1691,33 +1716,14 @@ void rlglInit(int width, int height)
RLGL.State.currentShader = RLGL.State.defaultShader;
// Init default vertex arrays buffers
LoadBuffersDefault();
// Init transformations matrix accumulator
RLGL.State.transform = MatrixIdentity();
RLGL.defaultBatch = LoadRenderBatch(DEFAULT_BATCH_BUFFERS, DEFAULT_BATCH_BUFFER_ELEMENTS);
RLGL.currentBatch = &RLGL.defaultBatch;
// Init draw calls tracking system
RLGL.State.draws = (DrawCall *)RL_MALLOC(sizeof(DrawCall)*MAX_DRAWCALL_REGISTERED);
for (int i = 0; i < MAX_DRAWCALL_REGISTERED; i++)
{
RLGL.State.draws[i].mode = RL_QUADS;
RLGL.State.draws[i].vertexCount = 0;
RLGL.State.draws[i].vertexAlignment = 0;
//RLGL.State.draws[i].vaoId = 0;
//RLGL.State.draws[i].shaderId = 0;
RLGL.State.draws[i].textureId = RLGL.State.defaultTextureId;
//RLGL.State.draws[i].RLGL.State.projection = MatrixIdentity();
//RLGL.State.draws[i].RLGL.State.modelview = MatrixIdentity();
}
RLGL.State.drawsCounter = 1; // Reset draws counter
RLGL.State.currentDepth = -1.0f; // Reset depth value
// Init RLGL.State.stack matrices (emulating OpenGL 1.1)
// Init stack matrices (emulating OpenGL 1.1)
for (int i = 0; i < MAX_MATRIX_STACK_SIZE; i++) RLGL.State.stack[i] = MatrixIdentity();
// Init RLGL.State.projection and RLGL.State.modelview matrices
// Init internal matrices
RLGL.State.transform = MatrixIdentity();
RLGL.State.projection = MatrixIdentity();
RLGL.State.modelview = MatrixIdentity();
RLGL.State.currentMatrix = &RLGL.State.modelview;
@ -1766,13 +1772,12 @@ void rlglInit(int width, int height)
void rlglClose(void)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
UnloadShaderDefault(); // Unload default shader
UnloadBuffersDefault(); // Unload default buffers
UnloadRenderBatch(RLGL.defaultBatch);
UnloadShaderDefault(); // 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);
RL_FREE(RLGL.State.draws);
#endif
}
@ -1780,12 +1785,7 @@ void rlglClose(void)
void rlglDraw(void)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
// Only process data if we have data to process
if (RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter > 0)
{
UpdateBuffersDefault();
DrawBuffersDefault(); // NOTE: Stereo rendering is checked inside
}
DrawRenderBatch(RLGL.currentBatch); // NOTE: Stereo rendering is checked inside
#endif
}
@ -1796,7 +1796,7 @@ int rlGetVersion(void)
return OPENGL_11;
#elif defined(GRAPHICS_API_OPENGL_21)
#if defined(__APPLE__)
return OPENGL_33; // NOTE: Force OpenGL 3.3 on OSX
return OPENGL_33; // NOTE: Force OpenGL 3.3 on OSX
#else
return OPENGL_21;
#endif
@ -1812,7 +1812,7 @@ bool rlCheckBufferLimit(int vCount)
{
bool overflow = false;
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
if ((RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter + vCount) >= (MAX_BATCH_ELEMENTS*4)) overflow = true;
if ((RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter + vCount) >= (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementsCount*4)) overflow = true;
#endif
return overflow;
}
@ -3796,8 +3796,7 @@ void EndVrDrawing(void)
rlDisableTexture();
// Update and draw render texture fbo with distortion to backbuffer
UpdateBuffersDefault();
DrawBuffersDefault();
DrawRenderBatch(RLGL.currentBatch);
// Restore RLGL.State.defaultShader
RLGL.State.currentShader = RLGL.State.defaultShader;
@ -3859,7 +3858,6 @@ static unsigned int LoadShaderProgram(unsigned int vShaderId, unsigned int fShad
unsigned int program = 0;
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
GLint success = 0;
program = glCreateProgram();
@ -4056,44 +4054,50 @@ static void UnloadShaderDefault(void)
glDeleteProgram(RLGL.State.defaultShader.id);
}
// Load k">default internal buffers
static kt">void LoadBuffersDefault(void)
// Load n">render batch
static n">RenderBatch LoadRenderBatch(int numBuffers, int bufferElements)
{
// Initialize CPU (RAM) arrays (vertex position, texcoord, color data and indexes)
RenderBatch batch = { 0 };
// Initialize CPU (RAM) vertex buffers (position, texcoord, color data and indexes)
//--------------------------------------------------------------------------------------------
for (int i = 0; i < MAX_BATCH_BUFFERING; i++)
batch.vertexBuffer = (VertexBuffer *)RL_MALLOC(sizeof(VertexBuffer)*numBuffers);
for (int i = 0; i < numBuffers; i++)
{
RLGL.State.vertexData[i].vertices = (float *)RL_MALLOC(sizeof(float)*3*4*MAX_BATCH_ELEMENTS); // 3 float by vertex, 4 vertex by quad
RLGL.State.vertexData[i].texcoords = (float *)RL_MALLOC(sizeof(float)*2*4*MAX_BATCH_ELEMENTS); // 2 float by texcoord, 4 texcoord by quad
RLGL.State.vertexData[i].colors = (unsigned char *)RL_MALLOC(sizeof(unsigned char)*4*4*MAX_BATCH_ELEMENTS); // 4 float by color, 4 colors by quad
batch.vertexBuffer[i].elementsCount = bufferElements;
batch.vertexBuffer[i].vertices = (float *)RL_MALLOC(sizeof(float)*3*4*bufferElements); // 3 float by vertex, 4 vertex by quad
batch.vertexBuffer[i].texcoords = (float *)RL_MALLOC(sizeof(float)*2*4*bufferElements); // 2 float by texcoord, 4 texcoord by quad
batch.vertexBuffer[i].colors = (unsigned char *)RL_MALLOC(sizeof(unsigned char)*4*4*bufferElements); // 4 float by color, 4 colors by quad
#if defined(GRAPHICS_API_OPENGL_33)
RLGL.State.vertexData[i].indices = (unsigned int *)RL_MALLOC(sizeof(unsigned int)*6*MAX_BATCH_ELEMENTS); // 6 int by quad (indices)
batch.vertexBuffer[i].indices = (unsigned int *)RL_MALLOC(sizeof(unsigned int)*6*bufferElements); // 6 int by quad (indices)
#elif defined(GRAPHICS_API_OPENGL_ES2)
RLGL.State.vertexData[i].indices = (unsigned short *)RL_MALLOC(sizeof(unsigned short)*6*MAX_BATCH_ELEMENTS); // 6 int by quad (indices)
batch.vertexBuffer[i].indices = (unsigned short *)RL_MALLOC(sizeof(unsigned short)*6*bufferElements); // 6 int by quad (indices)
#endif
for (int j = 0; j < (3*4*MAX_BATCH_ELEMENTS); j++) RLGL.State.vertexData[i].vertices[j] = 0.0f;
for (int j = 0; j < (2*4*MAX_BATCH_ELEMENTS); j++) RLGL.State.vertexData[i].texcoords[j] = 0.0f;
for (int j = 0; j < (4*4*MAX_BATCH_ELEMENTS); j++) RLGL.State.vertexData[i].colors[j] = 0;
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*MAX_BATCH_ELEMENTS); j += 6)
for (int j = 0; j < (6*bufferElements); j += 6)
{
RLGL.State.vertexData[i].indices[j] = 4*k;
RLGL.State.vertexData[i].indices[j + 1] = 4*k + 1;
RLGL.State.vertexData[i].indices[j + 2] = 4*k + 2;
RLGL.State.vertexData[i].indices[j + 3] = 4*k;
RLGL.State.vertexData[i].indices[j + 4] = 4*k + 2;
RLGL.State.vertexData[i].indices[j + 5] = 4*k + 3;
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++;
}
RLGL.State.vertexData[i].vCounter = 0;
RLGL.State.vertexData[i].tcCounter = 0;
RLGL.State.vertexData[i].cCounter = 0;
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)");
@ -4101,79 +4105,103 @@ static void LoadBuffersDefault(void)
// Upload to GPU (VRAM) vertex data and initialize VAOs/VBOs
//--------------------------------------------------------------------------------------------
for (int i = 0; i < MAX_BATCH_BUFFERING; i++)
for (int i = 0; i < numBuffers; i++)
{
if (RLGL.ExtSupported.vao)
{
// Initialize Quads VAO
glGenVertexArrays(1, &RLGL.State.vertexData[i].vaoId);
glBindVertexArray(RLGL.State.vertexData[i].vaoId);
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, &RLGL.State.vertexData[i].vboId[0]);
glBindBuffer(GL_ARRAY_BUFFER, RLGL.State.vertexData[i].vboId[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*MAX_BATCH_ELEMENTS, RLGL.State.vertexData[i].vertices, GL_DYNAMIC_DRAW);
glGenBuffers(1, &batch.vertexBuffer[i].vboId[0]);
glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*bufferElements, batch.vertexBuffer[i].vertices, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(RLGL.State.currentShader.locs[LOC_VERTEX_POSITION]);
glVertexAttribPointer(RLGL.State.currentShader.locs[LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0);
// Vertex texcoord buffer (shader-location = 1)
glGenBuffers(1, &RLGL.State.vertexData[i].vboId[1]);
glBindBuffer(GL_ARRAY_BUFFER, RLGL.State.vertexData[i].vboId[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*MAX_BATCH_ELEMENTS, RLGL.State.vertexData[i].texcoords, GL_DYNAMIC_DRAW);
glGenBuffers(1, &batch.vertexBuffer[i].vboId[1]);
glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*bufferElements, batch.vertexBuffer[i].texcoords, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(RLGL.State.currentShader.locs[LOC_VERTEX_TEXCOORD01]);
glVertexAttribPointer(RLGL.State.currentShader.locs[LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0);
// Vertex color buffer (shader-location = 3)
glGenBuffers(1, &RLGL.State.vertexData[i].vboId[2]);
glBindBuffer(GL_ARRAY_BUFFER, RLGL.State.vertexData[i].vboId[2]);
glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*4*MAX_BATCH_ELEMENTS, RLGL.State.vertexData[i].colors, GL_DYNAMIC_DRAW);
glGenBuffers(1, &batch.vertexBuffer[i].vboId[2]);
glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[2]);
glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*4*bufferElements, batch.vertexBuffer[i].colors, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(RLGL.State.currentShader.locs[LOC_VERTEX_COLOR]);
glVertexAttribPointer(RLGL.State.currentShader.locs[LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
// Fill index buffer
glGenBuffers(1, &RLGL.State.vertexData[i].vboId[3]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, RLGL.State.vertexData[i].vboId[3]);
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, sizeof(int)*6*MAX_BATCH_ELEMENTS, RLGL.State.vertexData[i].indices, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int)*6*bufferElements, batch.vertexBuffer[i].indices, GL_STATIC_DRAW);
#elif defined(GRAPHICS_API_OPENGL_ES2)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(short)*6*MAX_BATCH_ELEMENTS, RLGL.State.vertexData[i].indices, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(short)*6*bufferElements, batch.vertexBuffer[i].indices, GL_STATIC_DRAW);
#endif
}
TRACELOG(LOG_INFO, "RLGL: Internal vertex buffers uploaded successfully to VRAM (GPU)");
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(sizeof(DrawCall)*DEFAULT_BATCH_DRAWCALLS);
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.drawsCounter = 1; // Reset draws counter
batch.currentDepth = -1.0f; // Reset depth value
//--------------------------------------------------------------------------------------------
return batch;
}
// Update default internal buffers (VAOs/VBOs) with vertex array data
// 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)
static void UpdateBuffersDefault(void)
// Draw render batch
// NOTE: We require a pointer to reset batch and increase current buffer (multi-buffer)
static void DrawRenderBatch(RenderBatch *batch)
{
// Update vertex buffers data
if (RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter > 0)
// 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(RLGL.State.vertexData[RLGL.State.currentBuffer].vaoId);
if (RLGL.ExtSupported.vao) glBindVertexArray(batch->vertexBuffer[batch->currentBuffer].vaoId);
// Vertex positions buffer
glBindBuffer(GL_ARRAY_BUFFER, RLGL.State.vertexData[RLGL.State.currentBuffer].vboId[0]);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*3*RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter, RLGL.State.vertexData[RLGL.State.currentBuffer].vertices);
//glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*MAX_BATCH_ELEMENTS, RLGL.State.vertexData[RLGL.State.currentBuffer].vertices, GL_DYNAMIC_DRAW); // Update all buffer
glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[0]);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*3*batch->vertexBuffer[batch->currentBuffer].vCounter, 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, RLGL.State.vertexData[RLGL.State.currentBuffer].vboId[1]);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*2*RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter, RLGL.State.vertexData[RLGL.State.currentBuffer].texcoords);
//glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*MAX_BATCH_ELEMENTS, RLGL.State.vertexData[RLGL.State.currentBuffer].texcoords, GL_DYNAMIC_DRAW); // Update all buffer
glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[1]);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*2*batch->vertexBuffer[batch->currentBuffer].vCounter, 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, RLGL.State.vertexData[RLGL.State.currentBuffer].vboId[2]);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(unsigned char)*4*RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter, RLGL.State.vertexData[RLGL.State.currentBuffer].colors);
//glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*4*MAX_BATCH_ELEMENTS, RLGL.State.vertexData[RLGL.State.currentBuffer].colors, GL_DYNAMIC_DRAW); // Update all buffer
glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[2]);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(unsigned char)*4*batch->vertexBuffer[batch->currentBuffer].vCounter, 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.
@ -4183,8 +4211,8 @@ static void UpdateBuffersDefault(void)
// Another option: map the buffer object into client's memory
// Probably this code could be moved somewhere else...
// RLGL.State.vertexData[RLGL.State.currentBuffer].vertices = (float *)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);
// if (RLGL.State.vertexData[RLGL.State.currentBuffer].vertices)
// batch->vertexBuffer[batch->currentBuffer].vertices = (float *)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);
// if (batch->vertexBuffer[batch->currentBuffer].vertices)
// {
// Update vertex data
// }
@ -4193,11 +4221,10 @@ static void UpdateBuffersDefault(void)
// Unbind the current VAO
if (RLGL.ExtSupported.vao) glBindVertexArray(0);
}
}
// Draw default internal buffers vertex data
static void DrawBuffersDefault(void)
{
//------------------------------------------------------------------------------------------------------------
// Draw batch vertex buffers (considering VR stereo if required)
//------------------------------------------------------------------------------------------------------------
Matrix matProjection = RLGL.State.projection;
Matrix matModelView = RLGL.State.modelview;
@ -4213,7 +4240,7 @@ static void DrawBuffersDefault(void)
#endif
// Draw buffers
if (RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter > 0)
if (batch->vertexBuffer[batch->currentBuffer].vCounter > 0)
{
// Set current shader and upload current MVP matrix
glUseProgram(RLGL.State.currentShader.id);
@ -4233,51 +4260,51 @@ static void DrawBuffersDefault(void)
int vertexOffset = 0;
if (RLGL.ExtSupported.vao) glBindVertexArray(RLGL.State.vertexData[RLGL.State.currentBuffer].vaoId);
if (RLGL.ExtSupported.vao) glBindVertexArray(batch->vertexBuffer[batch->currentBuffer].vaoId);
else
{
// Bind vertex attrib: position (shader-location = 0)
glBindBuffer(GL_ARRAY_BUFFER, RLGL.State.vertexData[RLGL.State.currentBuffer].vboId[0]);
glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[0]);
glVertexAttribPointer(RLGL.State.currentShader.locs[LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0);
glEnableVertexAttribArray(RLGL.State.currentShader.locs[LOC_VERTEX_POSITION]);
// Bind vertex attrib: texcoord (shader-location = 1)
glBindBuffer(GL_ARRAY_BUFFER, RLGL.State.vertexData[RLGL.State.currentBuffer].vboId[1]);
glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[1]);
glVertexAttribPointer(RLGL.State.currentShader.locs[LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0);
glEnableVertexAttribArray(RLGL.State.currentShader.locs[LOC_VERTEX_TEXCOORD01]);
// Bind vertex attrib: color (shader-location = 3)
glBindBuffer(GL_ARRAY_BUFFER, RLGL.State.vertexData[RLGL.State.currentBuffer].vboId[2]);
glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[2]);
glVertexAttribPointer(RLGL.State.currentShader.locs[LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
glEnableVertexAttribArray(RLGL.State.currentShader.locs[LOC_VERTEX_COLOR]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, RLGL.State.vertexData[RLGL.State.currentBuffer].vboId[3]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[3]);
}
glActiveTexture(GL_TEXTURE0);
for (int i = 0; i < RLGL.State.drawsCounter; i++)
for (int i = 0; i < batch->drawsCounter; i++)
{
glBindTexture(GL_TEXTURE_2D, RLGL.State.draws[i].textureId);
glBindTexture(GL_TEXTURE_2D, batch->draws[i].textureId);
// TODO: Find some way to bind additional textures --> Use global texture IDs? Register them on draw[i]?
//if (RLGL.State.currentShader->locs[LOC_MAP_SPECULAR] > 0) { glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, textureUnit1_id); }
//if (RLGL.State.currentShader->locs[LOC_MAP_SPECULAR] > 0) { glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, textureUnit2_id); }
if ((RLGL.State.draws[i].mode == RL_LINES) || (RLGL.State.draws[i].mode == RL_TRIANGLES)) glDrawArrays(RLGL.State.draws[i].mode, vertexOffset, RLGL.State.draws[i].vertexCount);
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, RLGL.State.draws[i].vertexCount/4*6, GL_UNSIGNED_INT, (GLvoid *)(sizeof(GLuint)*vertexOffset/4*6));
glDrawElements(GL_TRIANGLES, batch->draws[i].vertexCount/4*6, GL_UNSIGNED_INT, (GLvoid *)(sizeof(GLuint)*vertexOffset/4*6));
#elif defined(GRAPHICS_API_OPENGL_ES2)
glDrawElements(GL_TRIANGLES, RLGL.State.draws[i].vertexCount/4*6, GL_UNSIGNED_SHORT, (GLvoid *)(sizeof(GLushort)*vertexOffset/4*6));
glDrawElements(GL_TRIANGLES, batch->draws[i].vertexCount/4*6, GL_UNSIGNED_SHORT, (GLvoid *)(sizeof(GLushort)*vertexOffset/4*6));
#endif
}
vertexOffset += (RLGL.State.draws[i].vertexCount + RLGL.State.draws[i].vertexAlignment);
vertexOffset += (batch->draws[i].vertexCount + batch->draws[i].vertexAlignment);
}
if (!RLGL.ExtSupported.vao)
@ -4293,36 +4320,40 @@ static void DrawBuffersDefault(void)
glUseProgram(0); // Unbind shader program
}
//------------------------------------------------------------------------------------------------------------
// Reset batch buffers
//------------------------------------------------------------------------------------------------------------
// Reset vertex counters for next frame
RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter = 0;
RLGL.State.vertexData[RLGL.State.currentBuffer].tcCounter = 0;
RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter = 0;
batch->vertexBuffer[batch->currentBuffer].vCounter = 0;
batch->vertexBuffer[batch->currentBuffer].tcCounter = 0;
batch->vertexBuffer[batch->currentBuffer].cCounter = 0;
// Reset depth for next draw
RLGL.State.currentDepth = -1.0f;
batch->currentDepth = -1.0f;
// Restore projection/modelview matrices
RLGL.State.projection = matProjection;
RLGL.State.modelview = matModelView;
// Reset RLGL.State.draws array
for (int i = 0; i < MAX_DRAWCALL_REGISTERED; i++)
// Reset RLGL.currentBatch->draws array
for (int i = 0; i < DEFAULT_BATCH_DRAWCALLS; i++)
{
RLGL.State.draws[i].mode = RL_QUADS;
RLGL.State.draws[i].vertexCount = 0;
RLGL.State.draws[i].textureId = RLGL.State.defaultTextureId;
batch->draws[i].mode = RL_QUADS;
batch->draws[i].vertexCount = 0;
batch->draws[i].textureId = RLGL.State.defaultTextureId;
}
RLGL.State.drawsCounter = 1;
batch->drawsCounter = 1;
//------------------------------------------------------------------------------------------------------------
// Change to next buffer in the list
RLGL.State.currentBuffer++;
if (RLGL.State.currentBuffer >= MAX_BATCH_BUFFERING) RLGL.State.currentBuffer = 0;
// 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
static void UnloadBuffersDefault(void)
static void UnloadRenderBatch(RenderBatch batch)
{
// Unbind everything
if (RLGL.ExtSupported.vao) glBindVertexArray(0);
@ -4333,23 +4364,42 @@ static void UnloadBuffersDefault(void)
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
for (int i = 0; i < MAX_BATCH_BUFFERING; i++)
// Unload all vertex buffers data
for (int i = 0; i < batch.buffersCount; i++)
{
// Delete VBOs from GPU (VRAM)
glDeleteBuffers(1, &RLGL.State.vertexData[i].vboId[0]);
glDeleteBuffers(1, &RLGL.State.vertexData[i].vboId[1]);
glDeleteBuffers(1, &RLGL.State.vertexData[i].vboId[2]);
glDeleteBuffers(1, &RLGL.State.vertexData[i].vboId[3]);
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, &RLGL.State.vertexData[i].vaoId);
if (RLGL.ExtSupported.vao) glDeleteVertexArrays(1, &batch.vertexBuffer[i].vaoId);
// Free vertex arrays memory from CPU (RAM)
RL_FREE(RLGL.State.vertexData[i].vertices);
RL_FREE(RLGL.State.vertexData[i].texcoords);
RL_FREE(RLGL.State.vertexData[i].colors);
RL_FREE(RLGL.State.vertexData[i].indices);
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
static void SetRenderBatchActive(RenderBatch *batch)
{
DrawRenderBatch(RLGL.currentBatch);
RLGL.currentBatch = batch;
}
// Set default render batch for rlgl
static void SetRenderBatchDefault(void)
{
DrawRenderBatch(RLGL.currentBatch);
RLGL.currentBatch = &RLGL.defaultBatch;
}
// Renders a 1x1 XY quad in NDC

Loading…
Cancel
Save