aboutsummaryrefslogtreecommitdiff
path: root/src/textures.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/textures.c')
-rw-r--r--src/textures.c275
1 files changed, 275 insertions, 0 deletions
diff --git a/src/textures.c b/src/textures.c
new file mode 100644
index 00000000..1a7e23a7
--- /dev/null
+++ b/src/textures.c
@@ -0,0 +1,275 @@
+/*********************************************************************************************
+*
+* raylib.textures
+*
+* Basic functions to load and draw Textures (2d)
+*
+* Uses external lib:
+* stb_image - Multiple formats image loading (JPEG, PNG, BMP, TGA, PSD, GIF, PIC)
+*
+* Copyright (c) 2013 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+*
+* This software is provided "as-is", without any express or implied warranty. In no event
+* will the authors be held liable for any damages arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose, including commercial
+* applications, and to alter it and redistribute it freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not claim that you
+* wrote the original software. If you use this software in a product, an acknowledgment
+* in the product documentation would be appreciated but is not required.
+*
+* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
+* as being the original software.
+*
+* 3. This notice may not be removed or altered from any source distribution.
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+
+#include <GL/gl.h> // OpenGL functions
+#include <stdlib.h> // Declares malloc() and free() for memory management
+#include "stb_image.h" // Used to read image data (multiple formats support)
+
+//----------------------------------------------------------------------------------
+// Defines and Macros
+//----------------------------------------------------------------------------------
+// Nop...
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+typedef unsigned char byte;
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition
+//----------------------------------------------------------------------------------
+// It's lonely here...
+
+//----------------------------------------------------------------------------------
+// Module specific Functions Declaration
+//----------------------------------------------------------------------------------
+// No private (static) functions in this module (.c file)
+
+//----------------------------------------------------------------------------------
+// Module Functions Definition
+//----------------------------------------------------------------------------------
+
+// Load an image into CPU memory (RAM)
+Image LoadImage(const char *fileName)
+{
+ Image image;
+
+ int imgWidth;
+ int imgHeight;
+ int imgBpp;
+
+ // NOTE: Using stb_image to load images (Supports: BMP, TGA, PNG, JPG, ...)
+ byte *imgData = stbi_load(fileName, &imgWidth, &imgHeight, &imgBpp, 4); // Force loading to 4 components (RGBA)
+
+ // Convert array to pixel array for working convenience
+ image.pixels = (Color *)malloc(imgWidth * imgHeight * sizeof(Color));
+
+ int pix = 0;
+
+ for (int i = 0; i < (imgWidth * imgHeight * 4); i += 4)
+ {
+ image.pixels[pix].r = imgData[i];
+ image.pixels[pix].g = imgData[i+1];
+ image.pixels[pix].b = imgData[i+2];
+ image.pixels[pix].a = imgData[i+3];
+ pix++;
+ }
+
+ stbi_image_free(imgData);
+
+ image.width = imgWidth;
+ image.height = imgHeight;
+
+ // ALTERNATIVE: We can load pixel data directly into Color struct pixels array,
+ // to do that struct data alignment should be the right one (4 byte); it is.
+ //image.pixels = stbi_load(fileName, &imgWidth, &imgHeight, &imgBpp, 4);
+
+ return image;
+}
+
+// Unload image from CPU memory (RAM)
+void UnloadImage(Image image)
+{
+ free(image.pixels);
+}
+
+// Load an image as texture into GPU memory
+Texture2D LoadTexture(const char *fileName)
+{
+ Texture2D texture;
+
+ int imgWidth;
+ int imgHeight;
+ int imgBpp;
+
+ // NOTE: Using stb_image to load images (Supports: BMP, TGA, PNG, JPG, ...)
+ byte *imgData = stbi_load(fileName, &imgWidth, &imgHeight, &imgBpp, 4); // Force loading to 4 components (RGBA)
+
+ // Convert loaded data to OpenGL texture
+ //----------------------------------------
+ GLuint id;
+ glGenTextures(1, &id); // Generate Pointer to the Texture
+
+ glBindTexture(GL_TEXTURE_2D, id);
+
+ 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_MIN_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, imgWidth, imgHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, imgData);
+
+ // NOTE: Not using mipmappings (texture for 2D drawing)
+ // At this point we have the image converted to texture and uploaded to GPU
+
+ stbi_image_free(imgData); // Now we can free loaded data from RAM memory
+
+ texture.glId = id;
+ texture.width = imgWidth;
+ texture.height = imgHeight;
+
+ return texture;
+}
+
+// Load an image as texture (and convert to POT with mipmaps)
+Texture2D LoadTextureEx(const char *fileName, bool createPOT, bool mipmaps)
+{
+ Texture2D texture;
+
+ // TODO: Load and image and convert to Power-Of-Two
+ // NOTE: Conversion could be done just adding extra space to image or by scaling image
+ // NOTE: If scaling image, be careful with scaling algorithm (aproximation, bilinear, bicubic...)
+
+ // TODO: Generate all required mipmap levels from image and convert to testure (not that easy)
+ // NOTE: If using OpenGL 1.1, the only option is doing mipmap generation on CPU side (i.e. gluBuild2DMipmaps)
+ // NOTE: raylib tries to minimize external dependencies so, we are not using GLU
+ // NOTE: Re-implement some function similar to gluBuild2DMipmaps (not that easy...)
+
+ return texture;
+}
+
+// Unload texture from GPU memory
+void UnloadTexture(Texture2D texture)
+{
+ glDeleteTextures(1, &texture.glId);
+}
+
+// Draw a Texture2D
+void DrawTexture(Texture2D texture, int posX, int posY, Color tint)
+{
+ DrawTextureEx(texture, (Vector2){ (float)posX, (float)posY}, 0, 1.0f, tint);
+}
+
+// Draw a Texture2D with extended parameters
+void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint)
+{
+ glEnable(GL_TEXTURE_2D); // Enable textures usage
+
+ glBindTexture(GL_TEXTURE_2D, texture.glId);
+
+ glPushMatrix();
+ // NOTE: Rotation is applied before translation and scaling, even being called in inverse order...
+ // NOTE: Rotation point is upper-left corner
+ glTranslatef(position.x, position.y, 0);
+ glScalef(scale, scale, 1.0f);
+ glRotatef(rotation, 0, 0, 1);
+
+ glBegin(GL_QUADS);
+ glColor4ub(tint.r, tint.g, tint.b, tint.a);
+ glNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
+ glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f); // Bottom-left corner for texture and quad
+ glTexCoord2f(1.0f, 0.0f); glVertex2f(texture.width, 0.0f); // Bottom-right corner for texture and quad
+ glTexCoord2f(1.0f, 1.0f); glVertex2f(texture.width, texture.height); // Top-right corner for texture and quad
+ glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, texture.height); // Top-left corner for texture and quad
+ glEnd();
+ glPopMatrix();
+
+ glDisable(GL_TEXTURE_2D); // Disable textures usage
+}
+
+// Draw a part of a texture (defined by a rectangle)
+void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, float scale, Color tint)
+{
+ glEnable(GL_TEXTURE_2D); // Enable textures usage
+
+ glBindTexture(GL_TEXTURE_2D, texture.glId);
+
+ glPushMatrix();
+ glTranslatef(position.x, position.y, 0);
+ glScalef(scale, scale, 1.0f);
+ //glRotatef(rotation, 0, 0, 1);
+
+ glBegin(GL_QUADS);
+ glColor4ub(tint.r, tint.g, tint.b, tint.a);
+ glNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
+
+ // Bottom-left corner for texture and quad
+ glTexCoord2f((float)sourceRec.x / texture.width, (float)sourceRec.y / texture.height);
+ glVertex2f(0.0f, 0.0f);
+
+ // Bottom-right corner for texture and quad
+ glTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)sourceRec.y / texture.height);
+ glVertex2f(sourceRec.width, 0.0f);
+
+ // Top-right corner for texture and quad
+ glTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
+ glVertex2f(sourceRec.width, sourceRec.height);
+
+ // Top-left corner for texture and quad
+ glTexCoord2f((float)sourceRec.x / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
+ glVertex2f(0.0f, sourceRec.height);
+ glEnd();
+ glPopMatrix();
+
+ glDisable(GL_TEXTURE_2D); // Disable textures usage
+}
+
+// Creates a bitmap (BMP) file from an array of pixel data
+// NOTE: This function is only used by module [core], not explicitly available to raylib users
+extern void WriteBitmap(const char *fileName, const Color *imgDataPixel, int width, int height)
+{
+ int filesize = 54 + 3*width*height;
+
+ unsigned char bmpFileHeader[14] = {'B','M', 0,0,0,0, 0,0, 0,0, 54,0,0,0}; // Standard BMP file header
+ unsigned char bmpInfoHeader[40] = {40,0,0,0, 0,0,0,0, 0,0,0,0, 1,0, 24,0}; // Standard BMP info header
+
+ bmpFileHeader[2] = (unsigned char)(filesize);
+ bmpFileHeader[3] = (unsigned char)(filesize>>8);
+ bmpFileHeader[4] = (unsigned char)(filesize>>16);
+ bmpFileHeader[5] = (unsigned char)(filesize>>24);
+
+ bmpInfoHeader[4] = (unsigned char)(width);
+ bmpInfoHeader[5] = (unsigned char)(width>>8);
+ bmpInfoHeader[6] = (unsigned char)(width>>16);
+ bmpInfoHeader[7] = (unsigned char)(width>>24);
+ bmpInfoHeader[8] = (unsigned char)(height);
+ bmpInfoHeader[9] = (unsigned char)(height>>8);
+ bmpInfoHeader[10] = (unsigned char)(height>>16);
+ bmpInfoHeader[11] = (unsigned char)(height>>24);
+
+ FILE *bmpFile = fopen(fileName, "wb"); // Define a pointer to bitmap file and open it in write-binary mode
+
+ // NOTE: fwrite parameters are: data pointer, size in bytes of each element to be written, number of elements, file-to-write pointer
+ fwrite(bmpFileHeader, sizeof(unsigned char), 14, bmpFile); // Write BMP file header data
+ fwrite(bmpInfoHeader, sizeof(unsigned char), 40, bmpFile); // Write BMP info header data
+
+ // Write pixel data to file
+ for (int y = 0; y < height ; y++)
+ {
+ for (int x = 0; x < width; x++)
+ {
+ fputc(imgDataPixel[x + y*width].b, bmpFile);
+ fputc(imgDataPixel[x + y*width].g, bmpFile);
+ fputc(imgDataPixel[x + y*width].r, bmpFile);
+ }
+ }
+
+ fclose(bmpFile); // Close bitmap file
+} \ No newline at end of file