mirror of
https://github.com/raysan5/raylib.git
synced 2025-09-11 22:08:15 +00:00
raylib basic folders structure and some files... ;)
This commit is contained in:
275
src/textures.c
Normal file
275
src/textures.c
Normal file
@@ -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
|
||||
}
|
Reference in New Issue
Block a user