Lots of changes, most of them under testing-review

Added a Tracing/Log system
Added OGG stream music support (DOESN'T WORK)
Added Compressed textures support
* This update is probably very buggy...
This commit is contained in:
raysan5
2014-04-09 20:25:26 +02:00
parent c04f37d0f5
commit e6b82cb111
12 changed files with 1149 additions and 531 deletions

View File

@@ -31,7 +31,7 @@
#include <stdio.h> // Standard input / output lib
#include <stdlib.h> // Declares malloc() and free() for memory management, rand()
#include "raymath.h" // Required for data type Matrix and Matrix functions
// TODO: Security check in case multiple USE_OPENGL_* defined
#ifdef USE_OPENGL_11
#include <GL/gl.h> // Extensions loading lib
@@ -51,7 +51,7 @@
//----------------------------------------------------------------------------------
#define MATRIX_STACK_SIZE 16 // Matrix stack max size
#define MAX_DRAWS_BY_TEXTURE 256 // Draws are organized by texture changes
#define TEMP_VERTEX_BUFFER_SIZE 1024 // Temporal Vertex Buffer (required for vertex-transformations)
#define TEMP_VERTEX_BUFFER_SIZE 4096 // Temporal Vertex Buffer (required for vertex-transformations)
//----------------------------------------------------------------------------------
// Types and Structures Definition
@@ -226,9 +226,7 @@ void rlPushMatrix()
{
if (stackCounter == MATRIX_STACK_SIZE - 1)
{
printf("ERROR: Stack Buffer Overflow! (MAX 16 MATRIX)");
exit(1);
TraceLog(ERROR, "Stack Buffer Overflow (MAX %i Matrix)", MATRIX_STACK_SIZE);
}
stack[stackCounter] = *currentMatrix;
@@ -667,17 +665,22 @@ void rlglInit()
if (error != GLEW_OK)
{
fprintf(stderr, "Failed to initialize GLEW - Error: %s\n", glewGetErrorString(error));
exit(1);
TraceLog(ERROR, "Failed to initialize GLEW - Error Code: %s\n", glewGetErrorString(error));
}
if (glewIsSupported("GL_VERSION_3_3")) printf("OpenGL 3.3 initialized\n");
if (glewIsSupported("GL_VERSION_3_3")) TraceLog(INFO, "OpenGL 3.3 initialized\n");
// Print OpenGL and GLSL version
TraceLog(INFO, "Vendor: %s", glGetString(GL_VENDOR));
TraceLog(INFO, "Renderer: %s", glGetString(GL_RENDERER));
TraceLog(INFO, "Version: %s", glGetString(GL_VERSION));
TraceLog(INFO, "GLSL: %s\n", glGetString(0x8B8C)); //GL_SHADING_LANGUAGE_VERSION
/*
// TODO: GLEW is a big library that loads ALL extensions, maybe using glad we can only load required ones...
if (!gladLoadGL())
{
fprintf(stderr, printf("Failed to initialize glad.\n");
exit(1);
TraceLog("ERROR: Failed to initialize glad\n");
}
*/
// Set default draw mode
@@ -707,13 +710,7 @@ void rlglInit()
// Get handles to GLSL uniform vars locations (fragment-shader)
textureLoc = glGetUniformLocation(shaderProgram, "texture0");
printf("Default shaders loaded\n\n");
// Print OpenGL and GLSL version
printf("Vendor: %s\n", glGetString(GL_VENDOR));
printf("Renderer: %s\n", glGetString(GL_RENDERER));
printf("Version: %s\n", glGetString(GL_VERSION));
printf("GLSL: %s\n\n", glGetString(0x8B8C)); //GL_SHADING_LANGUAGE_VERSION
TraceLog(INFO, "Default shader loaded");
InitializeBuffers(); // Init vertex arrays
InitializeVAOs(); // Init VBO and VAO
@@ -726,7 +723,10 @@ void rlglInit()
// Create default white texture for plain colors (required by shader)
unsigned char pixels[4] = { 255, 255, 255, 255 }; // 1 pixel RGBA (4 bytes)
whiteTexture = rlglLoadTexture(1, 1, pixels);
whiteTexture = rlglLoadTexture(1, 1, pixels);
if (whiteTexture != 0) TraceLog(INFO, "Base white texture successfully created, id: %i", whiteTexture);
else TraceLog(WARNING, "Base white texture could not be created");
// Init draw calls tracking system
draws = (DrawCall *)malloc(sizeof(DrawCall)*MAX_DRAWS_BY_TEXTURE);
@@ -836,16 +836,14 @@ void rlglDraw()
glBindVertexArray(vaoQuads);
}
//printf("\nRequired Draws: %i\n", drawsCounter);
//TraceLog(INFO, "Draws required per frame: %i", drawsCounter);
for (int i = 0; i < drawsCounter; i++)
{
numQuads = draws[i].vCount/4;
numIndicesToProcess = numQuads*6; // Get number of Quads * 6 index by Quad
//printf("Quads to render: %i - ", numQuads);
//printf("Vertex Count: %i - ", draws[i].vCount);
//printf("Binding texture: %i\n", draws[i].texId);
//TraceLog(INFO, "Quads to render: %i - Vertex Count: %i", numQuads, draws[i].vCount);
glBindTexture(GL_TEXTURE_2D, draws[i].texId);
@@ -882,7 +880,10 @@ void rlglDraw()
#endif
}
void rlglDrawModel(Model model, bool wires)
#endif // End for OpenGL 3.3+ and ES2 only functions
// Draw a 3d model
void rlglDrawModel(Model model, Vector3 position, float scale, bool wires)
{
if (wires) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
@@ -892,19 +893,19 @@ void rlglDrawModel(Model model, bool wires)
glEnableClientState(GL_TEXTURE_COORD_ARRAY); // Enable texture coords array
glEnableClientState(GL_NORMAL_ARRAY); // Enable normals array
glVertexPointer(3, GL_FLOAT, 0, model.vertices); // Pointer to vertex coords array
glTexCoordPointer(2, GL_FLOAT, 0, model.texcoords); // Pointer to texture coords array
glNormalPointer(GL_FLOAT, 0, model.normals); // Pointer to normals array
glVertexPointer(3, GL_FLOAT, 0, model.data.vertices); // Pointer to vertex coords array
glTexCoordPointer(2, GL_FLOAT, 0, model.data.texcoords); // Pointer to texture coords array
glNormalPointer(GL_FLOAT, 0, model.data.normals); // Pointer to normals array
//glColorPointer(4, GL_UNSIGNED_BYTE, 0, model.colors); // Pointer to colors array (NOT USED)
rlPushMatrix();
rlTranslatef(position.x, position.y, position.z);
//glRotatef(rotation * GetFrameTime(), 0, 1, 0);
//rlRotatef(rotation * GetFrameTime(), 0, 1, 0);
rlScalef(scale, scale, scale);
rlColor4ub(color.r, color.g, color.b, color.a);
rlColor4ub(1.0f, 1.0f, 1.0f, 1.0f);
glDrawArrays(GL_TRIANGLES, 0, model.numVertices);
glDrawArrays(GL_TRIANGLES, 0, model.data.numVertices);
rlPopMatrix();
glDisableClientState(GL_VERTEX_ARRAY); // Disable vertex array
@@ -912,7 +913,7 @@ void rlglDrawModel(Model model, bool wires)
glDisableClientState(GL_NORMAL_ARRAY); // Disable normals array
#endif
#ifdef USE_OPENGL_33
#if defined(USE_OPENGL_33) || defined(USE_OPENGL_ES2)
glUseProgram(shaderProgram); // Use our shader
Matrix modelview2 = MatrixMultiply(model.transform, modelview);
@@ -934,8 +935,6 @@ void rlglDrawModel(Model model, bool wires)
if (wires) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
#endif
// Initialize Graphics Device (OpenGL stuff)
void rlglInitGraphicsDevice(int fbWidth, int fbHeight)
{
@@ -968,7 +967,7 @@ void rlglInitGraphicsDevice(int fbWidth, int fbHeight)
rlMatrixMode(RL_MODELVIEW); // Switch back to MODELVIEW matrix
rlLoadIdentity(); // Reset current matrix (MODELVIEW)
// TODO: Review all shapes/models are drawn CCW and enable backface culling
// NOTE: All shapes/models triangles are drawn CCW
glEnable(GL_CULL_FACE); // Enable backface culling (Disabled by default)
//glCullFace(GL_BACK); // Cull the Back face (default)
@@ -978,11 +977,13 @@ void rlglInitGraphicsDevice(int fbWidth, int fbHeight)
glShadeModel(GL_SMOOTH); // Smooth shading between vertex (vertex colors interpolation) (Deprecated on OpenGL 3.3+)
// Possible options: GL_SMOOTH (Color interpolation) or GL_FLAT (no interpolation)
#endif
TraceLog(INFO, "OpenGL graphics device initialized");
}
// Convert image data to OpenGL texture (returns OpenGL valid Id)
// NOTE: Image is not unloaded, it should be done manually...
unsigned int rlglLoadTexture(int width, int height, unsigned char *pixels)
unsigned int rlglLoadTexture(int width, int height, unsigned char *data)
{
glBindTexture(GL_TEXTURE_2D,0); // Free any old binding
@@ -998,7 +999,7 @@ unsigned int rlglLoadTexture(int width, int height, unsigned char *pixels)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR
#ifdef USE_OPENGL_33
#if defined(USE_OPENGL_33) || defined(USE_OPENGL_ES2)
// Trilinear filtering
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // Activate use of mipmaps (must be available)
@@ -1008,20 +1009,84 @@ unsigned int rlglLoadTexture(int width, int height, unsigned char *pixels)
// NOTE: Not using mipmappings (texture for 2D drawing)
// At this point we have the image converted to texture and uploaded to GPU
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
// At this point we have the image converted to texture and uploaded to GPU
// Unbind current texture
glBindTexture(GL_TEXTURE_2D, 0);
printf("New texture created, id: %i (%i x %i)\n", id, width, height);
TraceLog(INFO, "New texture created, id: %i (%i x %i)", id, width, height);
return id;
}
#ifdef USE_OPENGL_33
unsigned int rlglLoadModel(VertexData data)
#ifdef USE_OPENGL_33
#define FOURCC_DXT1 0x31545844 // Equivalent to "DXT1" in ASCII
#define FOURCC_DXT3 0x33545844 // Equivalent to "DXT3" in ASCII
#define FOURCC_DXT5 0x35545844 // Equivalent to "DXT5" in ASCII
// Convert image data to OpenGL texture (returns OpenGL valid Id)
// NOTE: Expected compressed data from DDS file
unsigned int rlglLoadCompressedTexture(unsigned char *data, int width, int height, int mipmapCount, int format)
{
// Create one OpenGL texture
GLuint id;
int compFormat = 0;
TraceLog(DEBUG, "Compressed texture width: %i", width);
TraceLog(DEBUG, "Compressed texture height: %i", height);
TraceLog(DEBUG, "Compressed texture mipmap levels: %i", mipmapCount);
TraceLog(DEBUG, "Compressed texture format: 0x%x", format);
switch(format)
{
case FOURCC_DXT1: compFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; break;
case FOURCC_DXT3: compFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break;
case FOURCC_DXT5: compFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break;
default: compFormat = -1; break;
}
if (compFormat == -1)
{
TraceLog(WARNING, "Texture compressed format not recognized");
id = 0;
}
else
{
glGenTextures(1, &id);
// Bind the texture
glBindTexture(GL_TEXTURE_2D, id);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
unsigned int blockSize = (compFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ? 8 : 16;
unsigned int offset = 0;
// Load the mipmaps
for (int level = 0; level < mipmapCount && (width || height); level++)
{
unsigned int size = ((width+3)/4)*((height+3)/4)*blockSize;
glCompressedTexImage2D(GL_TEXTURE_2D, level, compFormat, width, height, 0, size, data + offset);
offset += size;
width /= 2;
height /= 2;
// Security check for NPOT textures
if (width < 1) width = 1;
if (height < 1) height = 1;
}
}
return id;
}
// Load vertex data into a VAO
unsigned int rlglLoadModel(VertexData mesh)
{
GLuint vaoModel; // Vertex Array Objects (VAO)
GLuint vertexBuffer[3]; // Vertex Buffer Objects (VBO)
@@ -1035,17 +1100,17 @@ unsigned int rlglLoadModel(VertexData data)
// Enable vertex attributes
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*data.numVertices, data.vertices, GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh.numVertices, mesh.vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(vertexLoc);
glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, 0, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*data.numVertices, data.texcoords, GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*mesh.numVertices, mesh.texcoords, GL_STATIC_DRAW);
glEnableVertexAttribArray(texcoordLoc);
glVertexAttribPointer(texcoordLoc, 2, GL_FLOAT, 0, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[2]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*data.numVertices, data.normals, GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh.numVertices, mesh.normals, GL_STATIC_DRAW);
//glEnableVertexAttribArray(normalLoc);
//glVertexAttribPointer(normalLoc, 3, GL_FLOAT, 0, 0, 0);
@@ -1077,7 +1142,7 @@ unsigned char *rlglReadScreenPixels(int width, int height)
return imgData; // NOTE: image data should be freed
}
#ifdef USE_OPENGL_33
#if defined(USE_OPENGL_33) || defined(USE_OPENGL_ES2)
void PrintProjectionMatrix()
{
@@ -1154,7 +1219,7 @@ static GLuint LoadDefaultShaders()
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
return(program);
return program;
}
@@ -1191,14 +1256,14 @@ static GLuint LoadShaders(char *vertexFileName, char *fragmentFileName)
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
return(program);
return program;
}
// Read shader text file
static char *TextFileRead(char *fn)
{
FILE *fp;
char *content = NULL;
char *text = NULL;
int count=0;
@@ -1214,15 +1279,15 @@ static char *TextFileRead(char *fn)
if (count > 0)
{
content = (char *)malloc(sizeof(char) * (count+1));
count = fread(content, sizeof(char), count, fp);
content[count] = '\0';
text = (char *)malloc(sizeof(char) * (count+1));
count = fread(text, sizeof(char), count, fp);
text[count] = '\0';
}
fclose(fp);
}
}
return content;
return text;
}
// Allocate and initialize float array buffers to store vertex data (lines, triangles, quads)
@@ -1377,10 +1442,10 @@ static void InitializeVAOs()
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quadsBufferB[3]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int)*6*MAX_QUADS_BATCH, quads.indices, GL_STATIC_DRAW);
printf("Using VBO double buffering\n");
TraceLog(INFO, "Using VBO double buffering");
#endif
printf("Vertex buffers initialized (lines, triangles, quads)\n\n");
TraceLog(INFO, "Vertex buffers successfully initialized (lines, triangles, quads)\n");
// Unbind the current VAO
glBindVertexArray(0);
@@ -1475,4 +1540,33 @@ static void UpdateBuffers()
glBindVertexArray(0);
}
#endif
#ifdef RLGL_STANDALONE
typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType;
// Output a trace log message
// NOTE: Expected msgType: (0)Info, (1)Error, (2)Warning
void TraceLog(int msgType, const char *text, ...)
{
va_list args;
va_start(args, text);
switch(msgType)
{
case 0: fprintf(stdout, "INFO: "); break;
case 1: fprintf(stdout, "ERROR: "); break;
case 2: fprintf(stdout, "WARNING: "); break;
case 3: fprintf(logstream, "DEBUG: "); break;
default: break;
}
vfprintf(stdout, text, args);
fprintf(stdout, "\n");
va_end(args);
if (msgType == 1) exit(1);
}
#endif