diff options
| author | raysan5 <raysan5@gmail.com> | 2014-04-19 16:36:49 +0200 |
|---|---|---|
| committer | raysan5 <raysan5@gmail.com> | 2014-04-19 16:36:49 +0200 |
| commit | f06a15ac8b3fe92d101ae795225fbf56fa670dba (patch) | |
| tree | cdfba90ee24fd078a15c89d8753ee3e11d8e229b /src/rlgl.c | |
| parent | 650a8f7f159d3ce2addb1b0fdb31c3f460005391 (diff) | |
| download | raylib-f06a15ac8b3fe92d101ae795225fbf56fa670dba.tar.gz raylib-f06a15ac8b3fe92d101ae795225fbf56fa670dba.zip | |
raylib 1.1
View CHANGELOG for a detailed list of changes
Diffstat (limited to 'src/rlgl.c')
| -rw-r--r-- | src/rlgl.c | 473 |
1 files changed, 359 insertions, 114 deletions
@@ -31,10 +31,24 @@ #include <stdio.h> // Standard input / output lib #include <stdlib.h> // Declares malloc() and free() for memory management, rand() -// TODO: Security check in case multiple USE_OPENGL_* defined +// Security check in case no USE_OPENGL_* defined +#if !defined(USE_OPENGL_11) && !defined(USE_OPENGL_33) && !defined(USE_OPENGL_ES2) + #define USE_OPENGL_11 +#endif + +// Security check in case multiple USE_OPENGL_* defined +#ifdef USE_OPENGL_11 + #ifdef USE_OPENGL_33 + #undef USE_OPENGL_33 + #endif + + #ifdef USE_OPENGL_ES2 + #undef USE_OPENGL_ES2 + #endif +#endif #ifdef USE_OPENGL_11 - #include <GL/gl.h> // Extensions loading lib + #include <GL/gl.h> // Basic OpenGL include #endif #ifdef USE_OPENGL_33 @@ -42,7 +56,7 @@ #include <GL/glew.h> // Extensions loading lib #endif -//#include "glad.h" // Extensions loading lib? --> REVIEW +//#include "glad.h" // Other extensions loading lib? --> REVIEW #define USE_VBO_DOUBLE_BUFFERS // Enable VBO double buffers usage --> REVIEW! @@ -56,18 +70,18 @@ //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- -typedef struct { - int numQuads; - int texId; -} QuadsByTexture; +// Vertex buffer (position + color arrays) +// NOTE: Used for lines and triangles VAOs typedef struct { int vCounter; int cCounter; float *vertices; // 3 components per vertex float *colors; // 4 components per vertex } VertexPositionColorBuffer; -/* + +// Vertex buffer (position + texcoords + color arrays) +// NOTE: Not used typedef struct { int vCounter; int tcCounter; @@ -76,8 +90,9 @@ typedef struct { float *texcoords; // 2 components per vertex float *colors; // 4 components per vertex } VertexPositionColorTextureBuffer; -*/ -/* + +// Vertex buffer (position + texcoords + normals arrays) +// NOTE: Not used typedef struct { int vCounter; int tcCounter; @@ -86,7 +101,9 @@ typedef struct { float *texcoords; // 2 components per vertex float *normals; // 3 components per vertex } VertexPositionTextureNormalBuffer; -*/ + +// Vertex buffer (position + texcoords + colors + indices arrays) +// NOTE: Used for quads VAO typedef struct { int vCounter; int tcCounter; @@ -97,12 +114,22 @@ typedef struct { unsigned int *indices; // 6 indices per quad } VertexPositionColorTextureIndexBuffer; +// Draw call type +// NOTE: Used to track required draw-calls, organized by texture typedef struct { - GLuint texId; - int firstVertex; // Actually, when using glDrawElements, this parameter is useless.. - int vCount; + GLuint textureId; + int vertexCount; } DrawCall; +// pixel type (same as Color type) +// NOTE: Used exclusively in mipmap generation functions +typedef struct { + unsigned char r; + unsigned char g; + unsigned char b; + unsigned char a; +} pixel; + //---------------------------------------------------------------------------------- // Global Variables Definition //---------------------------------------------------------------------------------- @@ -140,7 +167,6 @@ static GLuint quadsBuffer[4]; #ifdef USE_VBO_DOUBLE_BUFFERS // Double buffering -// TODO: REVIEW -> Not getting any performance improvement... why? static GLuint vaoQuadsB; static GLuint quadsBufferB[4]; static bool useBufferB = false; @@ -172,6 +198,11 @@ static GLuint LoadShaders(char *vertexFileName, char *fragmentFileName); static char *TextFileRead(char *fn); #endif +#ifdef USE_OPENGL_11 +static int GenerateMipmaps(unsigned char *data, int baseWidth, int baseHeight); +static pixel *GenNextMipmap(pixel *srcData, int srcWidth, int srcHeight); +#endif + //---------------------------------------------------------------------------------- // Module Functions Definition - Matrix operations //---------------------------------------------------------------------------------- @@ -216,7 +247,7 @@ void rlMatrixMode(int mode) { if (mode == RL_PROJECTION) currentMatrix = &projection; else if (mode == RL_MODELVIEW) currentMatrix = &modelview; - //else if (mode == GL_TEXTURE) TODO: NEVER USED! + //else if (mode == RL_TEXTURE) // Not supported currentMatrixMode = mode; } @@ -257,6 +288,7 @@ void rlLoadIdentity() void rlTranslatef(float x, float y, float z) { Matrix mat = MatrixTranslate(x, y, z); + MatrixTranspose(&mat); *currentMatrix = MatrixMultiply(*currentMatrix, mat); } @@ -264,13 +296,15 @@ void rlTranslatef(float x, float y, float z) // Multiply the current matrix by a rotation matrix void rlRotatef(float angleDeg, float x, float y, float z) { - // TODO: Rotation matrix --> REVIEW! + // TODO: Support rotation in multiple axes Matrix rot = MatrixIdentity(); if (x == 1) rot = MatrixRotateX(angleDeg*DEG2RAD); else if (y == 1) rot = MatrixRotateY(angleDeg*DEG2RAD); else if (z == 1) rot = MatrixRotateZ(angleDeg*DEG2RAD); + MatrixTranspose(&rot); + *currentMatrix = MatrixMultiply(*currentMatrix, rot); } @@ -278,6 +312,7 @@ void rlRotatef(float angleDeg, float x, float y, float z) void rlScalef(float x, float y, float z) { Matrix mat = MatrixScale(x, y, z); + MatrixTranspose(&mat); *currentMatrix = MatrixMultiply(*currentMatrix, mat); } @@ -356,12 +391,12 @@ void rlEnd() { if (useTempBuffer) { - // IT WORKS!!! --> Refactor... - Matrix mat = *currentMatrix; - MatrixTranspose(&mat); + // NOTE: In this case, *currentMatrix is already transposed because transposing has been applied + // independently to translation-scale-rotation matrices -> t(M1 x M2) = t(M2) x t(M1) + // This way, rlTranslatef(), rlRotatef()... behaviour is the same than OpenGL 1.1 // Apply transformation matrix to all temp vertices - for (int i = 0; i < tempBufferCount; i++) VectorTransform(&tempBuffer[i], mat); + for (int i = 0; i < tempBufferCount; i++) VectorTransform(&tempBuffer[i], *currentMatrix); // Deactivate tempBuffer usage to allow rlVertex3f do its job useTempBuffer = false; @@ -373,7 +408,7 @@ void rlEnd() tempBufferCount = 0; } - // Make sure vertexCounter is the same for vertices-texcoords-normals-colors + // Make sure vertexCount is the same for vertices-texcoords-normals-colors // NOTE: In OpenGL 1.1, one glColor call can be made for all the subsequent glVertex calls. switch (currentDrawMode) { @@ -490,7 +525,7 @@ void rlVertex3f(float x, float y, float z) quads.vCounter++; - draws[drawsCounter - 1].vCount++; + draws[drawsCounter - 1].vertexCount++; } break; default: break; @@ -596,13 +631,12 @@ void rlEnableTexture(unsigned int id) #endif #if defined(USE_OPENGL_33) || defined(USE_OPENGL_ES2) - if (draws[drawsCounter - 1].texId != id) + if (draws[drawsCounter - 1].textureId != id) { - if (draws[drawsCounter - 1].vCount > 0) drawsCounter++; + if (draws[drawsCounter - 1].vertexCount > 0) drawsCounter++; - draws[drawsCounter - 1].texId = id; - draws[drawsCounter - 1].firstVertex = draws[drawsCounter - 2].vCount; - draws[drawsCounter - 1].vCount = 0; + draws[drawsCounter - 1].textureId = id; + draws[drawsCounter - 1].vertexCount = 0; } #endif } @@ -708,9 +742,7 @@ void rlglInit() projectionMatrixLoc = glGetUniformLocation(shaderProgram, "projectionMatrix"); // Get handles to GLSL uniform vars locations (fragment-shader) - textureLoc = glGetUniformLocation(shaderProgram, "texture0"); - - TraceLog(INFO, "Default shader loaded"); + textureLoc = glGetUniformLocation(shaderProgram, "texture0"); InitializeBuffers(); // Init vertex arrays InitializeVAOs(); // Init VBO and VAO @@ -723,9 +755,9 @@ 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(pixels, 1, 1, false); - if (whiteTexture != 0) TraceLog(INFO, "Base white texture successfully created, id: %i", whiteTexture); + if (whiteTexture != 0) TraceLog(INFO, "[ID %i] Base white texture created successfully", whiteTexture); else TraceLog(WARNING, "Base white texture could not be created"); // Init draw calls tracking system @@ -733,13 +765,12 @@ void rlglInit() for (int i = 0; i < MAX_DRAWS_BY_TEXTURE; i++) { - draws[i].texId = 0; - draws[i].firstVertex = 0; - draws[i].vCount = 0; + draws[i].textureId = 0; + draws[i].vertexCount = 0; } drawsCounter = 1; - draws[drawsCounter - 1].texId = whiteTexture; + draws[drawsCounter - 1].textureId = whiteTexture; } // Vertex Buffer Object deinitialization (memory free) @@ -789,6 +820,8 @@ void rlglClose() // Free GPU texture glDeleteTextures(1, &whiteTexture); + + free(draws); } void rlglDraw() @@ -823,7 +856,7 @@ void rlglDraw() if (quads.vCounter > 0) { - int numQuads = 0; + int quadsCount = 0; int numIndicesToProcess = 0; int indicesOffset = 0; @@ -836,21 +869,21 @@ void rlglDraw() glBindVertexArray(vaoQuads); } - //TraceLog(INFO, "Draws required per frame: %i", drawsCounter); + //TraceLog(DEBUG, "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 + quadsCount = draws[i].vertexCount/4; + numIndicesToProcess = quadsCount*6; // Get number of Quads * 6 index by Quad - //TraceLog(INFO, "Quads to render: %i - Vertex Count: %i", numQuads, draws[i].vCount); + //TraceLog(DEBUG, "Quads to render: %i - Vertex Count: %i", quadsCount, draws[i].vertexCount); - glBindTexture(GL_TEXTURE_2D, draws[i].texId); + glBindTexture(GL_TEXTURE_2D, draws[i].textureId); // 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, numIndicesToProcess, GL_UNSIGNED_INT, (GLvoid*) (sizeof(GLuint) * indicesOffset)); - indicesOffset += draws[i].vCount/4*6; + indicesOffset += draws[i].vertexCount/4*6; } } @@ -859,9 +892,8 @@ void rlglDraw() // Reset draws counter drawsCounter = 1; - draws[0].texId = whiteTexture; - draws[0].firstVertex = 0; - draws[0].vCount = 0; + draws[0].textureId = whiteTexture; + draws[0].vertexCount = 0; // Reset vertex counters for next frame lines.vCounter = 0; @@ -883,52 +915,71 @@ void rlglDraw() #endif // End for OpenGL 3.3+ and ES2 only functions // Draw a 3d model -void rlglDrawModel(Model model, Vector3 position, float scale, bool wires) +void rlglDrawModel(Model model, Vector3 position, Vector3 rotation, Vector3 scale, Color color, bool wires) { if (wires) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); #ifdef USE_OPENGL_11 - // NOTE: For models we use Vertex Arrays (OpenGL 1.1) + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, model.textureId); + + // NOTE: On OpenGL 1.1 we use Vertex Arrays to draw model glEnableClientState(GL_VERTEX_ARRAY); // Enable vertex array glEnableClientState(GL_TEXTURE_COORD_ARRAY); // Enable texture coords array glEnableClientState(GL_NORMAL_ARRAY); // Enable 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 + glVertexPointer(3, GL_FLOAT, 0, model.mesh.vertices); // Pointer to vertex coords array + glTexCoordPointer(2, GL_FLOAT, 0, model.mesh.texcoords); // Pointer to texture coords array + glNormalPointer(GL_FLOAT, 0, model.mesh.normals); // Pointer to normals array //glColorPointer(4, GL_UNSIGNED_BYTE, 0, model.colors); // Pointer to colors array (NOT USED) - + + //TraceLog(DEBUG, "Drawing model.mesh, VertexCount: %i", model.mesh.vertexCount); + rlPushMatrix(); rlTranslatef(position.x, position.y, position.z); - //rlRotatef(rotation * GetFrameTime(), 0, 1, 0); - rlScalef(scale, scale, scale); + rlScalef(scale.x, scale.y, scale.z); + //rlRotatef(rotation, 0, 1, 0); - rlColor4ub(1.0f, 1.0f, 1.0f, 1.0f); + // TODO: If rotate in multiple axis, get rotation matrix and use rlMultMatrix() + + rlColor4ub(color.r, color.g, color.b, color.a); - glDrawArrays(GL_TRIANGLES, 0, model.data.numVertices); + glDrawArrays(GL_TRIANGLES, 0, model.mesh.vertexCount); rlPopMatrix(); glDisableClientState(GL_VERTEX_ARRAY); // Disable vertex array glDisableClientState(GL_TEXTURE_COORD_ARRAY); // Disable texture coords array glDisableClientState(GL_NORMAL_ARRAY); // Disable normals array + + glDisable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, 0); #endif #if defined(USE_OPENGL_33) || defined(USE_OPENGL_ES2) glUseProgram(shaderProgram); // Use our shader - Matrix modelview2 = MatrixMultiply(model.transform, modelview); + // Get transform matrix (rotation -> scale -> translation) + Matrix transform = MatrixTransform(position, rotation, scale); + Matrix modelviewworld = MatrixMultiply(transform, modelview); // NOTE: Drawing in OpenGL 3.3+, transform is passed to shader glUniformMatrix4fv(projectionMatrixLoc, 1, false, GetMatrixVector(projection)); - glUniformMatrix4fv(modelviewMatrixLoc, 1, false, GetMatrixVector(modelview2)); + glUniformMatrix4fv(modelviewMatrixLoc, 1, false, GetMatrixVector(modelviewworld)); glUniform1i(textureLoc, 0); + + //TraceLog(DEBUG, "ShaderProgram: %i, VAO ID: %i, VertexCount: %i", shaderProgram, model.vaoId, model.mesh.vertexCount); glBindVertexArray(model.vaoId); - //glBindTexture(GL_TEXTURE_2D, model.textureId); + + // TODO: Update vertex color + glBindBuffer(GL_ARRAY_BUFFER, linesBuffer[1]); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*4*model.mesh.vertexCount, model.mesh.colors); + + glBindTexture(GL_TEXTURE_2D, model.textureId); - glDrawArrays(GL_TRIANGLES, 0, model.numVertices); + glDrawArrays(GL_TRIANGLES, 0, model.mesh.vertexCount); - //glBindTexture(GL_TEXTURE_2D, 0); // Unbind textures + glBindTexture(GL_TEXTURE_2D, 0); // Unbind textures glBindVertexArray(0); // Unbind VAO #endif @@ -982,8 +1033,7 @@ void rlglInitGraphicsDevice(int fbWidth, int fbHeight) } // 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 *data) +unsigned int rlglLoadTexture(unsigned char *data, int width, int height, bool genMipmaps) { glBindTexture(GL_TEXTURE_2D,0); // Free any old binding @@ -996,27 +1046,82 @@ unsigned int rlglLoadTexture(int width, int height, unsigned char *data) // NOTE: glTexParameteri does NOT affect texture uploading, just the way it's used! glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture to repead on x-axis glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Set texture to repead on y-axis - 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 - -#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) - //glGenerateMipmap(GL_TEXTURE_2D); // OpenGL 3.3! -#endif - // NOTE: Not using mipmappings (texture for 2D drawing) - // At this point we have the image converted to texture and uploaded to GPU + bool texIsPOT = false; + // Check if width and height are power-of-two (POT) + if (((width > 0) && ((width & (width - 1)) == 0)) && ((height > 0) && ((height & (height - 1)) == 0))) texIsPOT = true; + + if (!texIsPOT) + { + TraceLog(WARNING, "[ID %i] Texture is not power-of-two, mipmaps can not be generated", id); + + genMipmaps = false; + } + + // If mipmaps are being used, we configure mag-min filters accordingly + if (genMipmaps) + { + // Trilinear filtering with mipmaps + 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) + } + else + { + // Not using mipmappings + 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_11 + if (genMipmaps) + { + TraceLog(WARNING, "[ID %i] Mipmaps generated manually on CPU side", id); + + // Compute required mipmaps + // NOTE: data size is reallocated to fit mipmaps data + int mipmapCount = GenerateMipmaps(data, width, height); + + int offset = 0; + int size = 0; + + int mipWidth = width; + int mipHeight = height; + + // Load the mipmaps + for (int level = 0; level < mipmapCount; level++) + { + glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA8, mipWidth, mipHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, data + offset); + + size = mipWidth*mipHeight*4; + offset += size; + + mipWidth /= 2; + mipHeight /= 2; + } + } + else glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); +#endif + + +#if defined(USE_OPENGL_33) || defined(USE_OPENGL_ES2) + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + if (genMipmaps) + { + glGenerateMipmap(GL_TEXTURE_2D); // Generate mipmaps automatically + TraceLog(INFO, "[ID %i] Mipmaps generated automatically for new texture", id); + } + +#endif + // At this point we have the image converted to texture and uploaded to GPU // Unbind current texture glBindTexture(GL_TEXTURE_2D, 0); - TraceLog(INFO, "New texture created, id: %i (%i x %i)", id, width, height); + TraceLog(INFO, "[ID %i] New texture created (%i x %i)", id, width, height); return id; } @@ -1024,51 +1129,42 @@ unsigned int rlglLoadTexture(int width, int height, unsigned char *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) +// NOTE: Expected compressed image data and POT image +unsigned int rlglLoadCompressedTexture(unsigned char *data, int width, int height, int mipmapCount, int compFormat) { // Create one OpenGL texture GLuint id; - int compFormat = 0; + + glGenTextures(1, &id); 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(DEBUG, "Compressed texture format: 0x%x", compFormat); + + if (compFormat == 0) { - TraceLog(WARNING, "Texture compressed format not recognized"); + TraceLog(WARNING, "[ID %i] Texture compressed format not recognized", id); 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; + int blockSize = 0; + int offset = 0; + + if (compFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) blockSize = 8; + else blockSize = 16; // Load the mipmaps for (int level = 0; level < mipmapCount && (width || height); level++) { - unsigned int size = ((width+3)/4)*((height+3)/4)*blockSize; + // NOTE: size specifies the number of bytes of image data (S3TC/DXTC) + unsigned int size = ((width + 3)/4)*((height + 3)/4)*blockSize; glCompressedTexImage2D(GL_TEXTURE_2D, level, compFormat, width, height, 0, size, data + offset); @@ -1100,20 +1196,28 @@ unsigned int rlglLoadModel(VertexData mesh) // Enable vertex attributes glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[0]); - glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh.numVertices, mesh.vertices, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh.vertexCount, 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*mesh.numVertices, mesh.texcoords, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*mesh.vertexCount, 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*mesh.numVertices, mesh.normals, GL_STATIC_DRAW); + //glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[2]); + //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh.vertexCount, mesh.normals, GL_STATIC_DRAW); //glEnableVertexAttribArray(normalLoc); //glVertexAttribPointer(normalLoc, 3, GL_FLOAT, 0, 0, 0); + glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[2]); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*mesh.vertexCount, mesh.colors, GL_STATIC_DRAW); + glEnableVertexAttribArray(colorLoc); + glVertexAttribPointer(colorLoc, 4, GL_FLOAT, 0, 0, 0); + + if (vaoModel > 0) TraceLog(INFO, "[ID %i] Model uploaded successfully to VRAM (GPU)", vaoModel); + else TraceLog(WARNING, "Model could not be uploaded to VRAM (GPU)"); + return vaoModel; } #endif @@ -1208,6 +1312,9 @@ static GLuint LoadDefaultShaders() glCompileShader(vertexShader); glCompileShader(fragmentShader); + + TraceLog(INFO, "[ID %i] Default vertex shader compiled succesfully", vertexShader); + TraceLog(INFO, "[ID %i] Default fragment shader compiled succesfully", fragmentShader); program = glCreateProgram(); @@ -1218,6 +1325,8 @@ static GLuint LoadDefaultShaders() glDeleteShader(vertexShader); glDeleteShader(fragmentShader); + + TraceLog(INFO, "[ID %i] Default shader program loaded succesfully", program); return program; } @@ -1245,6 +1354,9 @@ static GLuint LoadShaders(char *vertexFileName, char *fragmentFileName) glCompileShader(vertexShader); glCompileShader(fragmentShader); + + TraceLog(INFO, "[ID %i] Vertex shader compiled succesfully", vertexShader); + TraceLog(INFO, "[ID %i] Fragment shader compiled succesfully", fragmentShader); program = glCreateProgram(); @@ -1255,6 +1367,8 @@ static GLuint LoadShaders(char *vertexFileName, char *fragmentFileName) glDeleteShader(vertexShader); glDeleteShader(fragmentShader); + + TraceLog(INFO, "[ID %i] Shader program loaded succesfully", program); return program; } @@ -1364,7 +1478,8 @@ static void InitializeVAOs() glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*2*MAX_LINES_BATCH, lines.colors, GL_DYNAMIC_DRAW); glEnableVertexAttribArray(colorLoc); glVertexAttribPointer(colorLoc, 4, GL_FLOAT, 0, 0, 0); - + + TraceLog(INFO, "[ID %i] Lines VAO successfully initialized", vaoLines); //-------------------------------------------------------------- // Initialize Triangles VAO @@ -1384,7 +1499,8 @@ static void InitializeVAOs() glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*3*MAX_TRIANGLES_BATCH, triangles.colors, GL_DYNAMIC_DRAW); glEnableVertexAttribArray(colorLoc); glVertexAttribPointer(colorLoc, 4, GL_FLOAT, 0, 0, 0); - + + TraceLog(INFO, "[ID %i] Triangles VAO successfully initialized", vaoTriangles); //-------------------------------------------------------------- // Initialize Quads VAO (Buffer A) @@ -1414,6 +1530,8 @@ static void InitializeVAOs() glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quadsBuffer[3]); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int)*6*MAX_QUADS_BATCH, quads.indices, GL_STATIC_DRAW); + TraceLog(INFO, "[ID %i] Quads VAO successfully initialized", vaoQuads); + #ifdef USE_VBO_DOUBLE_BUFFERS // Initialize Quads VAO (Buffer B) glGenVertexArrays(1, &vaoQuadsB); @@ -1442,11 +1560,9 @@ 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); - TraceLog(INFO, "Using VBO double buffering"); + TraceLog(INFO, "[ID %i] Second Quads VAO successfully initilized (double buffering)", vaoQuadsB); #endif - TraceLog(INFO, "Vertex buffers successfully initialized (lines, triangles, quads)\n"); - // Unbind the current VAO glBindVertexArray(0); } @@ -1540,6 +1656,135 @@ static void UpdateBuffers() glBindVertexArray(0); } +#endif //defined(USE_OPENGL_33) || defined(USE_OPENGL_ES2) + +#ifdef USE_OPENGL_11 + +// Mipmaps data is generated after image data +static int GenerateMipmaps(unsigned char *data, int baseWidth, int baseHeight) +{ + int mipmapCount = 1; // Required mipmap levels count (including base level) + int width = baseWidth; + int height = baseHeight; + int size = baseWidth*baseHeight*4; // Size in bytes (will include mipmaps...) + + // Count mipmap levels required + while ((width != 1) && (height != 1)) + { + if (width != 1) width /= 2; + if (height != 1) height /= 2; + + TraceLog(DEBUG, "Next mipmap size: %i x %i", width, height); + + mipmapCount++; + + size += (width*height*4); // Add mipmap size (in bytes) + } + + TraceLog(DEBUG, "Total mipmaps required: %i", mipmapCount); + TraceLog(DEBUG, "Total size of data required: %i", size); + + unsigned char *temp = realloc(data, size); + + if (temp != NULL) data = temp; + else TraceLog(WARNING, "Mipmaps required memory could not be allocated"); + + width = baseWidth; + height = baseHeight; + size = (width*height*4); + + // Generate mipmaps + // NOTE: Every mipmap data is stored after data + pixel *image = (pixel *)malloc(width*height*sizeof(pixel)); + pixel *mipmap = NULL; + int offset = 0; + int j = 0; + + for (int i = 0; i < size; i += 4) + { + image[j].r = data[i]; + image[j].g = data[i + 1]; + image[j].b = data[i + 2]; + image[j].a = data[i + 3]; + j++; + } + + TraceLog(DEBUG, "Mipmap base (%i, %i)", width, height); + + for (int mip = 1; mip < mipmapCount; mip++) + { + mipmap = GenNextMipmap(image, width, height); + + offset += (width*height*4); // Size of last mipmap + j = 0; + + width /= 2; + height /= 2; + size = (width*height*4); // Mipmap size to store after offset + + // Add mipmap to data + for (int i = 0; i < size; i += 4) + { + data[offset + i] = mipmap[j].r; + data[offset + i + 1] = mipmap[j].g; + data[offset + i + 2] = mipmap[j].b; + data[offset + i + 3] = mipmap[j].a; + j++; + } + + free(image); + + image = mipmap; + mipmap = NULL; + } + + free(mipmap); // free mipmap data + + return mipmapCount; +} + +// Manual mipmap generation (basic scaling algorithm) +static pixel *GenNextMipmap(pixel *srcData, int srcWidth, int srcHeight) +{ + int x2, y2; + pixel prow, pcol; + + int width = srcWidth / 2; + int height = srcHeight / 2; + + pixel *mipmap = (pixel *)malloc(width*height*sizeof(pixel)); + + // Scaling algorithm works perfectly (box-filter) + for (int y = 0; y < height; y++) + { + y2 = 2 * y; + + for (int x = 0; x < width; x++) + { + x2 = 2 * x; + + prow.r = (srcData[y2*srcWidth + x2].r + srcData[y2*srcWidth + x2 + 1].r)/2; + prow.g = (srcData[y2*srcWidth + x2].g + srcData[y2*srcWidth + x2 + 1].g)/2; + prow.b = (srcData[y2*srcWidth + x2].b + srcData[y2*srcWidth + x2 + 1].b)/2; + prow.a = (srcData[y2*srcWidth + x2].a + srcData[y2*srcWidth + x2 + 1].a)/2; + + pcol.r = (srcData[(y2+1)*srcWidth + x2].r + srcData[(y2+1)*srcWidth + x2 + 1].r)/2; + pcol.g = (srcData[(y2+1)*srcWidth + x2].g + srcData[(y2+1)*srcWidth + x2 + 1].g)/2; + pcol.b = (srcData[(y2+1)*srcWidth + x2].b + srcData[(y2+1)*srcWidth + x2 + 1].b)/2; + pcol.a = (srcData[(y2+1)*srcWidth + x2].a + srcData[(y2+1)*srcWidth + x2 + 1].a)/2; + + mipmap[y*width + x].r = (prow.r + pcol.r)/2; + mipmap[y*width + x].g = (prow.g + pcol.g)/2; + mipmap[y*width + x].b = (prow.b + pcol.b)/2; + mipmap[y*width + x].a = (prow.a + pcol.a)/2; + } + } + + TraceLog(DEBUG, "Mipmap generated successfully (%i, %i)", width, height); + + return mipmap; +} + #endif #ifdef RLGL_STANDALONE @@ -1555,10 +1800,10 @@ void TraceLog(int msgType, const char *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; + case INFO: fprintf(stdout, "INFO: "); break; + case ERROR: fprintf(stdout, "ERROR: "); break; + case WARNING: fprintf(stdout, "WARNING: "); break; + case DEBUG: fprintf(stdout, "DEBUG: "); break; default: break; } @@ -1567,6 +1812,6 @@ void TraceLog(int msgType, const char *text, ...) va_end(args); - if (msgType == 1) exit(1); + if (msgType == ERROR) exit(1); } #endif
\ No newline at end of file |
