Browse Source

[models] Move vboId ALLOC/FREE to rlgl module #1603

Actually, it seems more logical that rlgl takes care of OpenGL data than the models module...

Also, models module loaded vertex data is unloaded by models module.
pull/1608/head
Ray 4 years ago
parent
commit
ef8318f5e3
3 changed files with 48 additions and 79 deletions
  1. +1
    -0
      src/config.h
  2. +30
    -58
      src/models.c
  3. +17
    -21
      src/rlgl.h

+ 1
- 0
src/config.h View File

@ -92,6 +92,7 @@
#define DEFAULT_BATCH_DRAWCALLS 256 // Default number of batch draw calls (by state changes: mode, texture) #define DEFAULT_BATCH_DRAWCALLS 256 // Default number of batch draw calls (by state changes: mode, texture)
#define MAX_MATRIX_STACK_SIZE 32 // Maximum size of internal Matrix stack #define MAX_MATRIX_STACK_SIZE 32 // Maximum size of internal Matrix stack
#define MAX_MESH_VERTEX_BUFFERS 7 // Maximum vertex buffers (VBO) per mesh
#define MAX_SHADER_LOCATIONS 32 // Maximum number of shader locations supported #define MAX_SHADER_LOCATIONS 32 // Maximum number of shader locations supported
#define MAX_MATERIAL_MAPS 12 // Maximum number of shader maps supported #define MAX_MATERIAL_MAPS 12 // Maximum number of shader maps supported

+ 30
- 58
src/models.c View File

@ -92,9 +92,7 @@
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Defines and Macros // Defines and Macros
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
#ifndef DEFAULT_MESH_VERTEX_BUFFERS
#define DEFAULT_MESH_VERTEX_BUFFERS 7 // Number of vertex buffers (VBO) per mesh
#endif
// ...
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Types and Structures Definition // Types and Structures Definition
@ -860,8 +858,21 @@ void UploadMesh(Mesh *mesh)
// Unload mesh from memory (RAM and/or VRAM) // Unload mesh from memory (RAM and/or VRAM)
void UnloadMesh(Mesh mesh) void UnloadMesh(Mesh mesh)
{ {
// Unload rlgl mesh vboId data
rlUnloadMesh(mesh); rlUnloadMesh(mesh);
RL_FREE(mesh.vboId);
RL_FREE(mesh.vertices);
RL_FREE(mesh.texcoords);
RL_FREE(mesh.normals);
RL_FREE(mesh.colors);
RL_FREE(mesh.tangents);
RL_FREE(mesh.texcoords2);
RL_FREE(mesh.indices);
RL_FREE(mesh.animVertices);
RL_FREE(mesh.animNormals);
RL_FREE(mesh.boneWeights);
RL_FREE(mesh.boneIds);
} }
// Export mesh data to file // Export mesh data to file
@ -1128,8 +1139,6 @@ Mesh GenMeshPoly(int sides, float radius)
if (sides < 3) return mesh; if (sides < 3) return mesh;
mesh.vboId = (unsigned int *)RL_CALLOC(DEFAULT_MESH_VERTEX_BUFFERS, sizeof(unsigned int));
int vertexCount = sides*3; int vertexCount = sides*3;
// Vertices definition // Vertices definition
@ -1186,6 +1195,7 @@ Mesh GenMeshPoly(int sides, float radius)
RL_FREE(texcoords); RL_FREE(texcoords);
// Upload vertex data to GPU (static mesh) // Upload vertex data to GPU (static mesh)
// NOTE: mesh.vboId array is allocated inside rlLoadMesh()
rlLoadMesh(&mesh, false); rlLoadMesh(&mesh, false);
return mesh; return mesh;
@ -1195,7 +1205,6 @@ Mesh GenMeshPoly(int sides, float radius)
Mesh GenMeshPlane(float width, float length, int resX, int resZ) Mesh GenMeshPlane(float width, float length, int resX, int resZ)
{ {
Mesh mesh = { 0 }; Mesh mesh = { 0 };
mesh.vboId = (unsigned int *)RL_CALLOC(DEFAULT_MESH_VERTEX_BUFFERS, sizeof(unsigned int));
#define CUSTOM_MESH_GEN_PLANE #define CUSTOM_MESH_GEN_PLANE
#if defined(CUSTOM_MESH_GEN_PLANE) #if defined(CUSTOM_MESH_GEN_PLANE)
@ -1329,7 +1338,6 @@ Mesh GenMeshPlane(float width, float length, int resX, int resZ)
Mesh GenMeshCube(float width, float height, float length) Mesh GenMeshCube(float width, float height, float length)
{ {
Mesh mesh = { 0 }; Mesh mesh = { 0 };
mesh.vboId = (unsigned int *)RL_CALLOC(DEFAULT_MESH_VERTEX_BUFFERS, sizeof(unsigned int));
#define CUSTOM_MESH_GEN_CUBE #define CUSTOM_MESH_GEN_CUBE
#if defined(CUSTOM_MESH_GEN_CUBE) #if defined(CUSTOM_MESH_GEN_CUBE)
@ -1498,8 +1506,6 @@ RLAPI Mesh GenMeshSphere(float radius, int rings, int slices)
if ((rings >= 3) && (slices >= 3)) if ((rings >= 3) && (slices >= 3))
{ {
mesh.vboId = (unsigned int *)RL_CALLOC(DEFAULT_MESH_VERTEX_BUFFERS, sizeof(unsigned int));
par_shapes_mesh *sphere = par_shapes_create_parametric_sphere(slices, rings); par_shapes_mesh *sphere = par_shapes_create_parametric_sphere(slices, rings);
par_shapes_scale(sphere, radius, radius, radius); par_shapes_scale(sphere, radius, radius, radius);
// NOTE: Soft normals are computed internally // NOTE: Soft normals are computed internally
@ -1544,8 +1550,6 @@ RLAPI Mesh GenMeshHemiSphere(float radius, int rings, int slices)
{ {
if (radius < 0.0f) radius = 0.0f; if (radius < 0.0f) radius = 0.0f;
mesh.vboId = (unsigned int *)RL_CALLOC(DEFAULT_MESH_VERTEX_BUFFERS, sizeof(unsigned int));
par_shapes_mesh *sphere = par_shapes_create_hemisphere(slices, rings); par_shapes_mesh *sphere = par_shapes_create_hemisphere(slices, rings);
par_shapes_scale(sphere, radius, radius, radius); par_shapes_scale(sphere, radius, radius, radius);
// NOTE: Soft normals are computed internally // NOTE: Soft normals are computed internally
@ -1588,8 +1592,6 @@ Mesh GenMeshCylinder(float radius, float height, int slices)
if (slices >= 3) if (slices >= 3)
{ {
mesh.vboId = (unsigned int *)RL_CALLOC(DEFAULT_MESH_VERTEX_BUFFERS, sizeof(unsigned int));
// Instance a cylinder that sits on the Z=0 plane using the given tessellation // Instance a cylinder that sits on the Z=0 plane using the given tessellation
// levels across the UV domain. Think of "slices" like a number of pizza // levels across the UV domain. Think of "slices" like a number of pizza
// slices, and "stacks" like a number of stacked rings. // slices, and "stacks" like a number of stacked rings.
@ -1653,8 +1655,6 @@ Mesh GenMeshTorus(float radius, float size, int radSeg, int sides)
if ((sides >= 3) && (radSeg >= 3)) if ((sides >= 3) && (radSeg >= 3))
{ {
mesh.vboId = (unsigned int *)RL_CALLOC(DEFAULT_MESH_VERTEX_BUFFERS, sizeof(unsigned int));
if (radius > 1.0f) radius = 1.0f; if (radius > 1.0f) radius = 1.0f;
else if (radius < 0.1f) radius = 0.1f; else if (radius < 0.1f) radius = 0.1f;
@ -1701,8 +1701,6 @@ Mesh GenMeshKnot(float radius, float size, int radSeg, int sides)
if ((sides >= 3) && (radSeg >= 3)) if ((sides >= 3) && (radSeg >= 3))
{ {
mesh.vboId = (unsigned int *)RL_CALLOC(DEFAULT_MESH_VERTEX_BUFFERS, sizeof(unsigned int));
if (radius > 3.0f) radius = 3.0f; if (radius > 3.0f) radius = 3.0f;
else if (radius < 0.5f) radius = 0.5f; else if (radius < 0.5f) radius = 0.5f;
@ -1747,7 +1745,6 @@ Mesh GenMeshHeightmap(Image heightmap, Vector3 size)
#define GRAY_VALUE(c) ((c.r+c.g+c.b)/3) #define GRAY_VALUE(c) ((c.r+c.g+c.b)/3)
Mesh mesh = { 0 }; Mesh mesh = { 0 };
mesh.vboId = (unsigned int *)RL_CALLOC(DEFAULT_MESH_VERTEX_BUFFERS, sizeof(unsigned int));
int mapX = heightmap.width; int mapX = heightmap.width;
int mapZ = heightmap.height; int mapZ = heightmap.height;
@ -1883,7 +1880,6 @@ Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize)
#define COLOR_EQUAL(col1, col2) ((col1.r == col2.r)&&(col1.g == col2.g)&&(col1.b == col2.b)&&(col1.a == col2.a)) #define COLOR_EQUAL(col1, col2) ((col1.r == col2.r)&&(col1.g == col2.g)&&(col1.b == col2.b)&&(col1.a == col2.a))
Mesh mesh = { 0 }; Mesh mesh = { 0 };
mesh.vboId = (unsigned int *)RL_CALLOC(DEFAULT_MESH_VERTEX_BUFFERS, sizeof(unsigned int));
Color *pixels = LoadImageColors(cubicmap); Color *pixels = LoadImageColors(cubicmap);
@ -2842,7 +2838,6 @@ static Model LoadOBJ(const char *fileName)
model.meshes[mi].vertices = (float *)RL_CALLOC(model.meshes[mi].vertexCount*3, sizeof(float)); model.meshes[mi].vertices = (float *)RL_CALLOC(model.meshes[mi].vertexCount*3, sizeof(float));
model.meshes[mi].texcoords = (float *)RL_CALLOC(model.meshes[mi].vertexCount*2, sizeof(float)); model.meshes[mi].texcoords = (float *)RL_CALLOC(model.meshes[mi].vertexCount*2, sizeof(float));
model.meshes[mi].normals = (float *)RL_CALLOC(model.meshes[mi].vertexCount*3, sizeof(float)); model.meshes[mi].normals = (float *)RL_CALLOC(model.meshes[mi].vertexCount*3, sizeof(float));
model.meshes[mi].vboId = (unsigned int *)RL_CALLOC(DEFAULT_MESH_VERTEX_BUFFERS, sizeof(unsigned int));
model.meshMaterial[mi] = mi; model.meshMaterial[mi] = mi;
} }
@ -3108,8 +3103,6 @@ static Model LoadIQM(const char *fileName)
// NOTE: Animated vertex should be re-uploaded to GPU (if not using GPU skinning) // NOTE: Animated vertex should be re-uploaded to GPU (if not using GPU skinning)
model.meshes[i].animVertices = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float)); model.meshes[i].animVertices = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));
model.meshes[i].animNormals = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float)); model.meshes[i].animNormals = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));
model.meshes[i].vboId = (unsigned int *)RL_CALLOC(DEFAULT_MESH_VERTEX_BUFFERS, sizeof(unsigned int));
} }
// Triangles data processing // Triangles data processing
@ -3726,10 +3719,7 @@ static Model LoadGLTF(const char *fileName)
model.boneCount = (int)data->nodes_count; model.boneCount = (int)data->nodes_count;
model.bones = RL_CALLOC(model.boneCount, sizeof(BoneInfo)); model.bones = RL_CALLOC(model.boneCount, sizeof(BoneInfo));
model.bindPose = RL_CALLOC(model.boneCount, sizeof(Transform)); model.bindPose = RL_CALLOC(model.boneCount, sizeof(Transform));
for (int i = 0; i < model.meshCount; i++)
model.meshes[i].vboId = (unsigned int *)RL_CALLOC(DEFAULT_MESH_VERTEX_BUFFERS, sizeof(unsigned int));
for (unsigned int j = 0; j < data->nodes_count; j++) for (unsigned int j = 0; j < data->nodes_count; j++)
{ {
strcpy(model.bones[j].name, data->nodes[j].name == 0 ? "ANIMJOINT" : data->nodes[j].name); strcpy(model.bones[j].name, data->nodes[j].name == 0 ? "ANIMJOINT" : data->nodes[j].name);
@ -3738,43 +3728,25 @@ static Model LoadGLTF(const char *fileName)
for (unsigned int i = 0; i < data->nodes_count; i++) for (unsigned int i = 0; i < data->nodes_count; i++)
{ {
if (data->nodes[i].has_translation)
{
memcpy(&model.bindPose[i].translation, data->nodes[i].translation, 3 * sizeof(float));
}
else
{
model.bindPose[i].translation = Vector3Zero();
}
if (data->nodes[i].has_rotation)
{
memcpy(&model.bindPose[i].rotation, data->nodes[i].rotation, 4 * sizeof(float));
}
else
{
model.bindPose[i].rotation = QuaternionIdentity();
}
if (data->nodes[i].has_translation) memcpy(&model.bindPose[i].translation, data->nodes[i].translation, 3 * sizeof(float));
else model.bindPose[i].translation = Vector3Zero();
if (data->nodes[i].has_rotation) memcpy(&model.bindPose[i].rotation, data->nodes[i].rotation, 4 * sizeof(float));
else model.bindPose[i].rotation = QuaternionIdentity();
model.bindPose[i].rotation = QuaternionNormalize(model.bindPose[i].rotation); model.bindPose[i].rotation = QuaternionNormalize(model.bindPose[i].rotation);
if (data->nodes[i].has_scale)
{
memcpy(&model.bindPose[i].scale, data->nodes[i].scale, 3 * sizeof(float));
}
else
{
model.bindPose[i].scale = Vector3One();
}
if (data->nodes[i].has_scale) memcpy(&model.bindPose[i].scale, data->nodes[i].scale, 3 * sizeof(float));
else model.bindPose[i].scale = Vector3One();
} }
for (int i = 0; i < model.boneCount; i++) for (int i = 0; i < model.boneCount; i++)
{ {
Transform* currentTransform = model.bindPose + i;
BoneInfo* currentBone = model.bones + i;
Transform *currentTransform = model.bindPose + i;
BoneInfo *currentBone = model.bones + i;
int root = currentBone->parent; int root = currentBone->parent;
if (root >= model.boneCount)
root = 0;
Transform* parentTransform = model.bindPose + root;
if (root >= model.boneCount) root = 0;
Transform *parentTransform = model.bindPose + root;
if (currentBone->parent >= 0) if (currentBone->parent >= 0)
{ {
@ -3791,7 +3763,7 @@ static Model LoadGLTF(const char *fileName)
Color tint = (Color){ 255, 255, 255, 255 }; Color tint = (Color){ 255, 255, 255, 255 };
const char *texPath = GetDirectoryPath(fileName); const char *texPath = GetDirectoryPath(fileName);
//Ensure material follows raylib support for PBR (metallic/roughness flow)
// Ensure material follows raylib support for PBR (metallic/roughness flow)
if (data->materials[i].has_pbr_metallic_roughness) if (data->materials[i].has_pbr_metallic_roughness)
{ {
tint.r = (unsigned char)(data->materials[i].pbr_metallic_roughness.base_color_factor[0] * 255); tint.r = (unsigned char)(data->materials[i].pbr_metallic_roughness.base_color_factor[0] * 255);

+ 17
- 21
src/rlgl.h View File

@ -158,6 +158,11 @@
#define MAX_MATRIX_STACK_SIZE 32 // Maximum size of Matrix stack #define MAX_MATRIX_STACK_SIZE 32 // Maximum size of Matrix stack
#endif #endif
// Vertex buffers id limit
#ifndef MAX_MESH_VERTEX_BUFFERS
#define MAX_MESH_VERTEX_BUFFERS 7 // Maximum vertex buffers (VBO) per mesh
#endif
// Shader and material limits // Shader and material limits
#ifndef MAX_SHADER_LOCATIONS #ifndef MAX_SHADER_LOCATIONS
#define MAX_SHADER_LOCATIONS 32 // Maximum number of shader locations supported #define MAX_SHADER_LOCATIONS 32 // Maximum number of shader locations supported
@ -2420,9 +2425,9 @@ void rlGenerateMipmaps(Texture2D *texture)
if (texture->format == UNCOMPRESSED_R8G8B8A8) if (texture->format == UNCOMPRESSED_R8G8B8A8)
{ {
// Retrieve texture data from VRAM // Retrieve texture data from VRAM
void *data = rlReadTexturePixels(*texture);
void *texData = rlReadTexturePixels(*texture);
// NOTE: data size is reallocated to fit mipmaps data
// NOTE: Texture data size is reallocated to fit mipmaps data
// NOTE: CPU mipmap generation only supports RGBA 32bit data // NOTE: CPU mipmap generation only supports RGBA 32bit data
int mipmapCount = GenerateMipmaps(data, texture->width, texture->height); int mipmapCount = GenerateMipmaps(data, texture->width, texture->height);
@ -2435,7 +2440,7 @@ void rlGenerateMipmaps(Texture2D *texture)
// Load the mipmaps // Load the mipmaps
for (int level = 1; level < mipmapCount; level++) for (int level = 1; level < mipmapCount; level++)
{ {
glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA8, mipWidth, mipHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data + offset);
glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA8, mipWidth, mipHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)texData + offset);
size = mipWidth*mipHeight*4; size = mipWidth*mipHeight*4;
offset += size; offset += size;
@ -2445,7 +2450,7 @@ void rlGenerateMipmaps(Texture2D *texture)
} }
texture->mipmaps = mipmapCount + 1; texture->mipmaps = mipmapCount + 1;
RL_FREE(data); // Once mipmaps have been generated and data has been uploaded to GPU VRAM, we can discard RAM data
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); TRACELOG(LOG_WARNING, "TEXTURE: [ID %i] Mipmaps generated manually on CPU side, total: %i", texture->id, texture->mipmaps);
} }
@ -2481,6 +2486,8 @@ void rlLoadMesh(Mesh *mesh, bool dynamic)
TRACELOG(LOG_WARNING, "VAO: [ID %i] Trying to re-load an already loaded mesh", mesh->vaoId); TRACELOG(LOG_WARNING, "VAO: [ID %i] Trying to re-load an already loaded mesh", mesh->vaoId);
return; return;
} }
mesh->vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VERTEX_BUFFERS, sizeof(unsigned int));
mesh->vaoId = 0; // Vertex Array Object mesh->vaoId = 0; // Vertex Array Object
mesh->vboId[0] = 0; // Vertex positions VBO mesh->vboId[0] = 0; // Vertex positions VBO
@ -2952,9 +2959,9 @@ void rlDrawMeshInstanced(Mesh mesh, Material material, Matrix *transforms, int c
glUniformMatrix4fv(material.shader.locs[LOC_MATRIX_MVP], 1, false, glUniformMatrix4fv(material.shader.locs[LOC_MATRIX_MVP], 1, false,
MatrixToFloat(MatrixMultiply(MatrixMultiply(RLGL.State.transform, RLGL.State.modelview), RLGL.State.projection))); MatrixToFloat(MatrixMultiply(MatrixMultiply(RLGL.State.transform, RLGL.State.modelview), RLGL.State.projection)));
float16* instances = RL_MALLOC(count*sizeof(float16));
float16* instanceTransforms = RL_MALLOC(count*sizeof(float16));
for (int i = 0; i < count; i++) instances[i] = MatrixToFloatV(transforms[i]);
for (int i = 0; i < count; i++) instanceTransforms[i] = MatrixToFloatV(transforms[i]);
// This could alternatively use a static VBO and either glMapBuffer or glBufferSubData. // This could alternatively use a static VBO and either glMapBuffer or glBufferSubData.
// It isn't clear which would be reliably faster in all cases and on all platforms, and // It isn't clear which would be reliably faster in all cases and on all platforms, and
@ -2963,7 +2970,7 @@ void rlDrawMeshInstanced(Mesh mesh, Material material, Matrix *transforms, int c
unsigned int instancesB = 0; unsigned int instancesB = 0;
glGenBuffers(1, &instancesB); glGenBuffers(1, &instancesB);
glBindBuffer(GL_ARRAY_BUFFER, instancesB); glBindBuffer(GL_ARRAY_BUFFER, instancesB);
glBufferData(GL_ARRAY_BUFFER, count*sizeof(float16), instances, GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, count*sizeof(float16), instanceTransforms, GL_STATIC_DRAW);
// Instances are put in LOC_MATRIX_MODEL attribute location with space for 4x Vector4, eg: // Instances are put in LOC_MATRIX_MODEL attribute location with space for 4x Vector4, eg:
// layout (location = 12) in mat4 instance; // layout (location = 12) in mat4 instance;
@ -2983,7 +2990,7 @@ void rlDrawMeshInstanced(Mesh mesh, Material material, Matrix *transforms, int c
else glDrawArraysInstanced(GL_TRIANGLES, 0, mesh.vertexCount, count); else glDrawArraysInstanced(GL_TRIANGLES, 0, mesh.vertexCount, count);
glDeleteBuffers(1, &instancesB); glDeleteBuffers(1, &instancesB);
RL_FREE(instances);
RL_FREE(instanceTransforms);
// Unbind all binded texture maps // Unbind all binded texture maps
for (int i = 0; i < MAX_MATERIAL_MAPS; i++) for (int i = 0; i < MAX_MATERIAL_MAPS; i++)
@ -3007,19 +3014,6 @@ void rlDrawMeshInstanced(Mesh mesh, Material material, Matrix *transforms, int c
// Unload mesh data from CPU and GPU // Unload mesh data from CPU and GPU
void rlUnloadMesh(Mesh mesh) void rlUnloadMesh(Mesh mesh)
{ {
RL_FREE(mesh.vertices);
RL_FREE(mesh.texcoords);
RL_FREE(mesh.normals);
RL_FREE(mesh.colors);
RL_FREE(mesh.tangents);
RL_FREE(mesh.texcoords2);
RL_FREE(mesh.indices);
RL_FREE(mesh.animVertices);
RL_FREE(mesh.animNormals);
RL_FREE(mesh.boneWeights);
RL_FREE(mesh.boneIds);
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
for (int i = 0; i < 7; i++) glDeleteBuffers(1, &mesh.vboId[i]); // DEFAULT_MESH_VERTEX_BUFFERS (model.c) for (int i = 0; i < 7; i++) glDeleteBuffers(1, &mesh.vboId[i]); // DEFAULT_MESH_VERTEX_BUFFERS (model.c)
if (RLGL.ExtSupported.vao) if (RLGL.ExtSupported.vao)
@ -3030,6 +3024,8 @@ void rlUnloadMesh(Mesh mesh)
} }
else TRACELOG(LOG_INFO, "VBO: Unloaded vertex data from VRAM (GPU)"); else TRACELOG(LOG_INFO, "VBO: Unloaded vertex data from VRAM (GPU)");
#endif #endif
RL_FREE(mesh.vboId);
} }
// Read screen pixel data (color buffer) // Read screen pixel data (color buffer)

Loading…
Cancel
Save