Improved mipmaps support and image loading

This commit is contained in:
raysan5 2015-07-05 18:21:01 +02:00
parent 84befaea24
commit c944d62374
5 changed files with 413 additions and 227 deletions

View file

@ -358,18 +358,19 @@ typedef enum {
} TextureFormat; } TextureFormat;
// Gestures type // Gestures type
// NOTE: It could be used as flags to enable only some gestures
typedef enum { typedef enum {
GESTURE_NONE = 0, GESTURE_NONE = 1,
GESTURE_TAP, GESTURE_TAP = 2,
GESTURE_DOUBLETAP, GESTURE_DOUBLETAP = 4,
GESTURE_HOLD, GESTURE_HOLD = 8,
GESTURE_DRAG, GESTURE_DRAG = 16,
GESTURE_SWIPE_RIGHT, GESTURE_SWIPE_RIGHT = 32,
GESTURE_SWIPE_LEFT, GESTURE_SWIPE_LEFT = 64,
GESTURE_SWIPE_UP, GESTURE_SWIPE_UP = 128,
GESTURE_SWIPE_DOWN, GESTURE_SWIPE_DOWN = 256,
GESTURE_PINCH_IN, GESTURE_PINCH_IN = 512,
GESTURE_PINCH_OUT GESTURE_PINCH_OUT = 1024
} Gestures; } Gestures;
#ifdef __cplusplus #ifdef __cplusplus
@ -431,14 +432,15 @@ void SetCameraMode(int mode); // Select camera mod
Camera UpdateCamera(Vector3 *position); // Update camera with position Camera UpdateCamera(Vector3 *position); // Update camera with position
void SetCameraControls(int front, int left, int back, int right, int up, int down); void SetCameraControls(int front, int left, int back, int right, int up, int down);
void SetMouseSensitivity(float sensitivity); void SetCameraMouseSensitivity(float sensitivity);
void SetResetPosition(Vector3 resetPosition); void SetCameraResetPosition(Vector3 resetPosition);
void SetResetControl(int resetKey); void SetCameraResetControl(int resetKey);
void SetPawnControl(int pawnControlKey); void SetCameraPawnControl(int pawnControlKey);
void SetFnControl(int fnControlKey); void SetCameraFnControl(int fnControlKey);
void SetSmoothZoomControl(int smoothZoomControlKey); void SetCameraSmoothZoomControl(int smoothZoomControlKey);
void SetOrbitalTarget(Vector3 target); void SetCameraOrbitalTarget(Vector3 target);
// Shaders control functions
int GetShaderLocation(Shader shader, const char *uniformName); int GetShaderLocation(Shader shader, const char *uniformName);
void SetShaderValue(Shader shader, int uniformLoc, float *value, int size); void SetShaderValue(Shader shader, int uniformLoc, float *value, int size);
@ -488,12 +490,14 @@ Vector2 GetTouchPosition(void); // Returns touch positio
// Gestures System (module: gestures) // Gestures System (module: gestures)
bool IsGestureDetected(void); bool IsGestureDetected(void);
int GetGestureType(void); int GetGestureType(void);
float GetDragIntensity(void); void SetGesturesEnabled(unsigned int gestureFlags);
float GetDragAngle(void);
Vector2 GetDragVector(void); float GetGestureDragIntensity(void);
int GetHoldDuration(void); // Hold time in frames float GetGestureDragAngle(void);
float GetPinchDelta(void); Vector2 GetGestureDragVector(void);
float GetPinchAngle(void); int GetGestureHoldDuration(void); // Hold time in frames
float GetGesturePinchDelta(void);
float GetGesturePinchAngle(void);
#endif #endif
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
@ -530,16 +534,19 @@ bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2
// Texture Loading and Drawing Functions (Module: textures) // Texture Loading and Drawing Functions (Module: textures)
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
Image LoadImage(const char *fileName); // Load an image into CPU memory (RAM) Image LoadImage(const char *fileName); // Load an image into CPU memory (RAM)
Image LoadImageEx(Color *pixels, int width, int height); // Load image data from Color array data (RGBA - 32bit)
Image LoadImageFromRES(const char *rresName, int resId); // Load an image from rRES file (raylib Resource) Image LoadImageFromRES(const char *rresName, int resId); // Load an image from rRES file (raylib Resource)
Image LoadImageFromData(Color *pixels, int width, int height, int format); // Load image from Color array data
Texture2D LoadTexture(const char *fileName); // Load an image as texture into GPU memory Texture2D LoadTexture(const char *fileName); // Load an image as texture into GPU memory
Texture2D LoadTextureEx(void *data, int width, int height, int textureFormat, int mipmapCount, bool genMipmaps); // Load a texture from raw data into GPU memory Texture2D LoadTextureEx(void *data, int width, int height, int textureFormat, int mipmapCount); // Load a texture from raw data into GPU memory
Texture2D LoadTextureFromRES(const char *rresName, int resId); // Load an image as texture from rRES file (raylib Resource) Texture2D LoadTextureFromRES(const char *rresName, int resId); // Load an image as texture from rRES file (raylib Resource)
Texture2D LoadTextureFromImage(Image image, bool genMipmaps); // Load a texture from image data (and generate mipmaps) Texture2D LoadTextureFromImage(Image image); // Load a texture from image data (and generate mipmaps)
void UnloadImage(Image image); // Unload image from CPU memory (RAM) void UnloadImage(Image image); // Unload image from CPU memory (RAM)
void UnloadTexture(Texture2D texture); // Unload texture from GPU memory void UnloadTexture(Texture2D texture); // Unload texture from GPU memory
void ConvertToPOT(Image *image, Color fillColor); // Convert image to POT (power-of-two) void ImageConvertToPOT(Image *image, Color fillColor); // Convert image to POT (power-of-two)
void ImageConvertFormat(Image *image, int newFormat); // Convert image data to desired format
Color *GetPixelData(Image image); // Get pixel data from image as a Color struct array Color *GetPixelData(Image image); // Get pixel data from image as a Color struct array
Image GetTextureData(Texture2D texture); // Get pixel data from GPU texture and return an Image
void GenTextureMipmaps(Texture2D texture); // Generate GPU mipmaps for a texture
void DrawTexture(Texture2D texture, int posX, int posY, Color tint); // Draw a Texture2D void DrawTexture(Texture2D texture, int posX, int posY, Color tint); // Draw a Texture2D
void DrawTextureV(Texture2D texture, Vector2 position, Color tint); // Draw a Texture2D with position defined as Vector2 void DrawTextureV(Texture2D texture, Vector2 position, Color tint); // Draw a Texture2D with position defined as Vector2

View file

@ -221,7 +221,7 @@ static bool vaoSupported = false; // VAO support (OpenGL ES2 could not support
static bool npotSupported = false; // NPOT textures full support static bool npotSupported = false; // NPOT textures full support
// Compressed textures support flags // Compressed textures support flags
static bool texCompDXTSupported = false; // DDS texture compression support //static bool texCompDXTSupported = false; // DDS texture compression support
static bool texCompETC1Supported = false; // ETC1 texture compression support static bool texCompETC1Supported = false; // ETC1 texture compression support
static bool texCompETC2Supported = false; // ETC2/EAC texture compression support static bool texCompETC2Supported = false; // ETC2/EAC texture compression support
static bool texCompPVRTSupported = false; // PVR texture compression support static bool texCompPVRTSupported = false; // PVR texture compression support
@ -232,6 +232,9 @@ static GLuint fbo, fboColorTexture, fboDepthTexture;
static Model postproQuad; static Model postproQuad;
#endif #endif
// Compressed textures support flags
static bool texCompDXTSupported = false; // DDS texture compression support
#if defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_ES2)
// NOTE: VAO functionality is exposed through extensions (OES) // NOTE: VAO functionality is exposed through extensions (OES)
static PFNGLGENVERTEXARRAYSOESPROC glGenVertexArrays; static PFNGLGENVERTEXARRAYSOESPROC glGenVertexArrays;
@ -263,7 +266,9 @@ static int GenerateMipmaps(unsigned char *data, int baseWidth, int baseHeight);
static pixel *GenNextMipmap(pixel *srcData, int srcWidth, int srcHeight); static pixel *GenNextMipmap(pixel *srcData, int srcWidth, int srcHeight);
#endif #endif
#if defined(GRAPHICS_API_OPENGL_ES2)
static char** StringSplit(char *baseString, const char delimiter, int *numExt); static char** StringSplit(char *baseString, const char delimiter, int *numExt);
#endif
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Functions Definition - Matrix operations // Module Functions Definition - Matrix operations
@ -967,7 +972,7 @@ void rlglInit(void)
// Create default white texture for plain colors (required by shader) // Create default white texture for plain colors (required by shader)
unsigned char pixels[4] = { 255, 255, 255, 255 }; // 1 pixel RGBA (4 bytes) unsigned char pixels[4] = { 255, 255, 255, 255 }; // 1 pixel RGBA (4 bytes)
whiteTexture = rlglLoadTexture(pixels, 1, 1, UNCOMPRESSED_R8G8B8A8, 1, false); whiteTexture = rlglLoadTexture(pixels, 1, 1, UNCOMPRESSED_R8G8B8A8, 1);
if (whiteTexture != 0) TraceLog(INFO, "[TEX ID %i] Base white texture loaded successfully", whiteTexture); if (whiteTexture != 0) TraceLog(INFO, "[TEX ID %i] Base white texture loaded successfully", whiteTexture);
else TraceLog(WARNING, "Base white texture could not be loaded"); else TraceLog(WARNING, "Base white texture could not be loaded");
@ -1623,7 +1628,7 @@ Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view)
} }
// Convert image data to OpenGL texture (returns OpenGL valid Id) // Convert image data to OpenGL texture (returns OpenGL valid Id)
unsigned int rlglLoadTexture(void *data, int width, int height, int textureFormat, int mipmapCount, bool genMipmaps) unsigned int rlglLoadTexture(void *data, int width, int height, int textureFormat, int mipmapCount)
{ {
glBindTexture(GL_TEXTURE_2D, 0); // Free any old binding glBindTexture(GL_TEXTURE_2D, 0); // Free any old binding
@ -1642,7 +1647,7 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int textureForma
TraceLog(WARNING, "DXT compressed texture format not supported"); TraceLog(WARNING, "DXT compressed texture format not supported");
return id; return id;
} }
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
if ((!texCompETC1Supported) && (textureFormat == COMPRESSED_ETC1_RGB)) if ((!texCompETC1Supported) && (textureFormat == COMPRESSED_ETC1_RGB))
{ {
TraceLog(WARNING, "ETC1 compressed texture format not supported"); TraceLog(WARNING, "ETC1 compressed texture format not supported");
@ -1666,7 +1671,8 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int textureForma
TraceLog(WARNING, "ASTC compressed texture format not supported"); TraceLog(WARNING, "ASTC compressed texture format not supported");
return id; return id;
} }
#endif
glGenTextures(1, &id); // Generate Pointer to the texture glGenTextures(1, &id); // Generate Pointer to the texture
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
@ -1755,23 +1761,63 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int textureForma
} }
#endif #endif
// Texture parameters configuration
// NOTE: glTexParameteri does NOT affect texture uploading, just the way it's used
#if defined(GRAPHICS_API_OPENGL_ES2)
// NOTE: OpenGL ES 2.0 with no GL_OES_texture_npot support (i.e. WebGL) has limited NPOT support, so CLAMP_TO_EDGE must be used
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // Set texture to clamp on x-axis
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // Set texture to clamp on y-axis
#else
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture to repeat on x-axis
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Set texture to repeat on y-axis
#endif
// Magnification and minification filters
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(GRAPHICS_API_OPENGL_33)
if (mipmapCount > 1)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // Activate Trilinear filtering for mipmaps (must be available)
}
#endif
// At this point we have the texture loaded in GPU and texture parameters configured
// NOTE: If mipmaps were not in data, they are not generated automatically
// Unbind current texture
glBindTexture(GL_TEXTURE_2D, 0);
if (id > 0) TraceLog(INFO, "[TEX ID %i] Texture created successfully (%ix%i)", id, width, height);
else TraceLog(WARNING, "Texture could not be created");
return id;
}
// Generate mipmap data for selected texture
void rlglGenerateMipmaps(unsigned int textureId)
{
glBindTexture(GL_TEXTURE_2D, textureId);
int width, height;
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
// Check if texture is power-of-two (POT) to enable mipmap generation // Check if texture is power-of-two (POT) to enable mipmap generation
bool texIsPOT = false; bool texIsPOT = false;
if (((width > 0) && ((width & (width - 1)) == 0)) && ((height > 0) && ((height & (height - 1)) == 0))) texIsPOT = true; if (((width > 0) && ((width & (width - 1)) == 0)) && ((height > 0) && ((height & (height - 1)) == 0))) texIsPOT = true;
if (genMipmaps && !texIsPOT) if (texIsPOT)
{ {
TraceLog(WARNING, "[TEX ID %i] Texture is not power-of-two, mipmaps can not be generated", id);
genMipmaps = false;
}
// Generate mipmaps if required
// TODO: Improve mipmaps support
#if defined(GRAPHICS_API_OPENGL_11) #if defined(GRAPHICS_API_OPENGL_11)
if (genMipmaps)
{
// Compute required mipmaps // Compute required mipmaps
void *data = rlglReadTexturePixels(textureId, UNCOMPRESSED_R8G8B8A8); // TODO: Detect internal format
// NOTE: data size is reallocated to fit mipmaps data // NOTE: data size is reallocated to fit mipmaps data
int mipmapCount = GenerateMipmaps(data, width, height); int mipmapCount = GenerateMipmaps(data, width, height);
@ -1794,48 +1840,21 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int textureForma
mipHeight /= 2; mipHeight /= 2;
} }
TraceLog(WARNING, "[TEX ID %i] Mipmaps generated manually on CPU side", id); TraceLog(WARNING, "[TEX ID %i] Mipmaps generated manually on CPU side", textureId);
}
#elif defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #elif defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
if ((mipmapCount == 1) && (genMipmaps)) glGenerateMipmap(GL_TEXTURE_2D); // Generate mipmaps automatically
{ TraceLog(INFO, "[TEX ID %i] Mipmaps generated automatically", textureId);
glGenerateMipmap(GL_TEXTURE_2D); // Generate mipmaps automatically
TraceLog(INFO, "[TEX ID %i] Mipmaps generated automatically for new texture", id);
}
#endif #endif
// Texture parameters configuration
// NOTE: glTexParameteri does NOT affect texture uploading, just the way it's used
#if defined(GRAPHICS_API_OPENGL_ES2)
// NOTE: OpenGL ES 2.0 with no GL_OES_texture_npot support (i.e. WebGL) has limited NPOT support, so CLAMP_TO_EDGE must be used
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // Set texture to clamp on x-axis
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // Set texture to clamp on y-axis
#else
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture to repeat on x-axis
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Set texture to repeat on y-axis
#endif
// Magnification and minification filters
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(GRAPHICS_API_OPENGL_33) #if defined(GRAPHICS_API_OPENGL_33)
if ((mipmapCount > 1) || (genMipmaps))
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // Activate Trilinear filtering for mipmaps (must be available) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // Activate Trilinear filtering for mipmaps (must be available)
}
#endif #endif
}
// At this point we have the texture loaded in GPU, with mipmaps generated (if desired) and texture parameters configured else TraceLog(WARNING, "[TEX ID %i] Texture is not power-of-two, mipmaps can not be generated", textureId);
// Unbind current texture
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
if (id > 0) TraceLog(INFO, "[TEX ID %i] Texture created successfully (%ix%i)", id, width, height);
else TraceLog(WARNING, "Texture could not be created");
return id;
} }
// Load vertex data into a VAO (if supported) and VBO // Load vertex data into a VAO (if supported) and VBO
@ -2039,6 +2058,47 @@ unsigned char *rlglReadScreenPixels(int width, int height)
return imgData; // NOTE: image data should be freed return imgData; // NOTE: image data should be freed
} }
// Read texture pixel data
void *rlglReadTexturePixels(unsigned int textureId, unsigned int format)
{
int width, height;
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
//glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &format);
//GL_TEXTURE_RED_SIZE, GL_TEXTURE_GREEN_SIZE, GL_TEXTURE_BLUE_SIZE, GL_TEXTURE_ALPHA_SIZE
int glFormat, glType;
void *pixels = NULL;
unsigned int size = width*height;
switch (format)
{
case UNCOMPRESSED_GRAYSCALE: pixels = (unsigned char *)malloc(size); glFormat = GL_LUMINANCE; glType = GL_UNSIGNED_BYTE; // 8 bit per pixel (no alpha)
case UNCOMPRESSED_GRAY_ALPHA: pixels = (unsigned char *)malloc(size*2); glFormat = GL_LUMINANCE_ALPHA; glType = GL_UNSIGNED_BYTE; // 16 bpp (2 channels)
case UNCOMPRESSED_R5G6B5: pixels = (unsigned short *)malloc(size); glFormat = GL_RGB; glType = GL_UNSIGNED_SHORT_5_6_5; // 16 bpp
case UNCOMPRESSED_R8G8B8: pixels = (unsigned char *)malloc(size*3); glFormat = GL_RGB; glType = GL_UNSIGNED_BYTE; // 24 bpp
case UNCOMPRESSED_R5G5B5A1: pixels = (unsigned short *)malloc(size); glFormat = GL_RGBA; glType = GL_UNSIGNED_SHORT_5_5_5_1; // 16 bpp (1 bit alpha)
case UNCOMPRESSED_R4G4B4A4: pixels = (unsigned short *)malloc(size); glFormat = GL_RGBA; glType = GL_UNSIGNED_SHORT_4_4_4_4; // 16 bpp (4 bit alpha)
case UNCOMPRESSED_R8G8B8A8: pixels = (unsigned char *)malloc(size*4); glFormat = GL_RGBA; glType = GL_UNSIGNED_BYTE; // 32 bpp
default: TraceLog(WARNING, "Texture format not suported"); break;
}
glBindTexture(GL_TEXTURE_2D, textureId);
// NOTE: Each row written to or read from by OpenGL pixel operations like glGetTexImage are aligned to a 4 byte boundary by default, which may add some padding.
// Use glPixelStorei to modify padding with the GL_[UN]PACK_ALIGNMENT setting.
// GL_PACK_ALIGNMENT affects operations that read from OpenGL memory (glReadPixels, glGetTexImage, etc.)
// GL_UNPACK_ALIGNMENT affects operations that write to OpenGL memory (glTexImage, etc.)
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glGetTexImage(GL_TEXTURE_2D, 0, glFormat, glType, pixels);
glBindTexture(GL_TEXTURE_2D, 0);
return pixels;
}
// Load a shader (vertex shader + fragment shader) from files // Load a shader (vertex shader + fragment shader) from files
Shader rlglLoadShader(char *vsFileName, char *fsFileName) Shader rlglLoadShader(char *vsFileName, char *fsFileName)
{ {
@ -2159,15 +2219,18 @@ void rlglSetDefaultShader(void)
int GetShaderLocation(Shader shader, const char *uniformName) int GetShaderLocation(Shader shader, const char *uniformName)
{ {
int location = glGetUniformLocation(shader.id, uniformName); int location = -1;
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
location = glGetUniformLocation(shader.id, uniformName);
if (location == -1) TraceLog(WARNING, "[SHDR ID %i] Shader location for %s could not be found", shader.id, uniformName); if (location == -1) TraceLog(WARNING, "[SHDR ID %i] Shader location for %s could not be found", shader.id, uniformName);
#endif
return location; return location;
} }
void SetShaderValue(Shader shader, int uniformLoc, float *value, int size) void SetShaderValue(Shader shader, int uniformLoc, float *value, int size)
{ {
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
glUseProgram(shader.id); glUseProgram(shader.id);
if (size == 1) glUniform1fv(uniformLoc, 1, value); // Shader uniform type: float if (size == 1) glUniform1fv(uniformLoc, 1, value); // Shader uniform type: float
@ -2177,10 +2240,12 @@ void SetShaderValue(Shader shader, int uniformLoc, float *value, int size)
else TraceLog(WARNING, "Shader value float array size not recognized"); else TraceLog(WARNING, "Shader value float array size not recognized");
glUseProgram(0); glUseProgram(0);
#endif
} }
void SetShaderMapDiffuse(Shader *shader, Texture2D texture) void SetShaderMapDiffuse(Shader *shader, Texture2D texture)
{ {
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
shader->texDiffuseId = texture.id; shader->texDiffuseId = texture.id;
glUseProgram(shader->id); glUseProgram(shader->id);
@ -2193,10 +2258,12 @@ void SetShaderMapDiffuse(Shader *shader, Texture2D texture)
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glUseProgram(0); glUseProgram(0);
#endif
} }
void SetShaderMapNormal(Shader *shader, const char *uniformName, Texture2D texture) void SetShaderMapNormal(Shader *shader, const char *uniformName, Texture2D texture)
{ {
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
shader->mapNormalLoc = glGetUniformLocation(shader->id, uniformName); shader->mapNormalLoc = glGetUniformLocation(shader->id, uniformName);
if (shader->mapNormalLoc == -1) TraceLog(WARNING, "[SHDR ID %i] Shader location for %s could not be found", shader->id, uniformName); if (shader->mapNormalLoc == -1) TraceLog(WARNING, "[SHDR ID %i] Shader location for %s could not be found", shader->id, uniformName);
@ -2215,10 +2282,12 @@ void SetShaderMapNormal(Shader *shader, const char *uniformName, Texture2D textu
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glUseProgram(0); glUseProgram(0);
} }
#endif
} }
void SetShaderMapSpecular(Shader *shader, const char *uniformName, Texture2D texture) void SetShaderMapSpecular(Shader *shader, const char *uniformName, Texture2D texture)
{ {
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
shader->mapSpecularLoc = glGetUniformLocation(shader->id, uniformName); shader->mapSpecularLoc = glGetUniformLocation(shader->id, uniformName);
if (shader->mapSpecularLoc == -1) TraceLog(WARNING, "[SHDR ID %i] Shader location for %s could not be found", shader->id, uniformName); if (shader->mapSpecularLoc == -1) TraceLog(WARNING, "[SHDR ID %i] Shader location for %s could not be found", shader->id, uniformName);
@ -2237,6 +2306,7 @@ void SetShaderMapSpecular(Shader *shader, const char *uniformName, Texture2D tex
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glUseProgram(0); glUseProgram(0);
} }
#endif
} }
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
@ -2865,6 +2935,7 @@ void TraceLog(int msgType, const char *text, ...)
} }
#endif #endif
#if defined(GRAPHICS_API_OPENGL_ES2)
static char **StringSplit(char *baseString, const char delimiter, int *numExt) static char **StringSplit(char *baseString, const char delimiter, int *numExt)
{ {
char **result = 0; char **result = 0;
@ -2913,4 +2984,5 @@ static char **StringSplit(char *baseString, const char delimiter, int *numExt)
*numExt = (count - 1); *numExt = (count - 1);
return result; return result;
} }
#endif

View file

@ -209,7 +209,9 @@ void rlglClose(void); // De-init rlgl
void rlglDraw(void); // Draw VAO/VBO void rlglDraw(void); // Draw VAO/VBO
void rlglInitGraphics(int offsetX, int offsetY, int width, int height); // Initialize Graphics (OpenGL stuff) void rlglInitGraphics(int offsetX, int offsetY, int width, int height); // Initialize Graphics (OpenGL stuff)
unsigned int rlglLoadTexture(void *data, int width, int height, int textureFormat, int mipmapCount, bool genMipmaps); // Load in GPU OpenGL texture unsigned int rlglLoadTexture(void *data, int width, int height, int textureFormat, int mipmapCount); // Load in GPU OpenGL texture
void rlglGenerateMipmaps(unsigned int textureId); // Generate mipmap data for selected texture
Shader rlglLoadShader(char *vsFileName, char *fsFileName); // Load a shader (vertex shader + fragment shader) from files Shader rlglLoadShader(char *vsFileName, char *fsFileName); // Load a shader (vertex shader + fragment shader) from files
unsigned int rlglLoadShaderFromText(char *vShaderStr, char *fShaderStr); // Load a shader from text data unsigned int rlglLoadShaderFromText(char *vShaderStr, char *fShaderStr); // Load a shader from text data
void rlglInitPostpro(void); // Initialize postprocessing system void rlglInitPostpro(void); // Initialize postprocessing system
@ -222,9 +224,10 @@ void rlglSetDefaultShader(void); // Set default shader to be used
Model rlglLoadModel(VertexData mesh); // Upload vertex data into GPU and provided VAO/VBO ids Model rlglLoadModel(VertexData mesh); // Upload vertex data into GPU and provided VAO/VBO ids
void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 rotationAxis, Vector3 scale, Color color, bool wires); void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 rotationAxis, Vector3 scale, Color color, bool wires);
Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view); // Get world coordinates from screen coordinates Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view); // Get world coordinates from screen coordinates
byte *rlglReadScreenPixels(int width, int height); // Read screen pixel data (color buffer) unsigned char *rlglReadScreenPixels(int width, int height); // Read screen pixel data (color buffer)
void *rlglReadTexturePixels(unsigned int textureId, unsigned int format); // Read texture pixel data
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
void PrintProjectionMatrix(void); // DEBUG: Print projection matrix void PrintProjectionMatrix(void); // DEBUG: Print projection matrix

View file

@ -171,11 +171,12 @@ extern void LoadDefaultFont(void)
//fwrite(image.pixels, 1, 128*128*4, myimage); //fwrite(image.pixels, 1, 128*128*4, myimage);
//fclose(myimage); //fclose(myimage);
Image image = LoadImageFromData(imagePixels, imWidth, imHeight, UNCOMPRESSED_GRAY_ALPHA); Image image = LoadImageEx(imagePixels, imWidth, imHeight);
ImageConvertFormat(&image, UNCOMPRESSED_GRAY_ALPHA);
free(imagePixels); free(imagePixels);
defaultFont.texture = LoadTextureFromImage(image, false); // Convert loaded image to OpenGL texture defaultFont.texture = LoadTextureFromImage(image);
UnloadImage(image); UnloadImage(image);
// Reconstruct charSet using charsWidth[], charsHeight, charsDivisor, numChars // Reconstruct charSet using charsWidth[], charsHeight, charsDivisor, numChars
@ -240,7 +241,7 @@ SpriteFont LoadSpriteFont(const char *fileName)
Color *imagePixels = GetPixelData(image); Color *imagePixels = GetPixelData(image);
#if defined(PLATFORM_RPI) || defined(PLATFORM_WEB) #if defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
ConvertToPOT(&image, MAGENTA); ImageConvertToPOT(&image, MAGENTA);
#endif #endif
// Process bitmap Font pixel data to get measures (Character array) // Process bitmap Font pixel data to get measures (Character array)
// spriteFont.charSet data is filled inside the function and memory is allocated! // spriteFont.charSet data is filled inside the function and memory is allocated!
@ -251,7 +252,7 @@ SpriteFont LoadSpriteFont(const char *fileName)
spriteFont.numChars = numChars; spriteFont.numChars = numChars;
spriteFont.texture = LoadTextureFromImage(image, false); // Convert loaded image to OpenGL texture spriteFont.texture = LoadTextureFromImage(image); // Convert loaded image to OpenGL texture
free(imagePixels); free(imagePixels);
UnloadImage(image); UnloadImage(image);
@ -556,13 +557,14 @@ static SpriteFont LoadRBMF(const char *fileName)
counter++; counter++;
} }
Image image = LoadImageFromData(imagePixels, rbmfHeader.imgWidth, rbmfHeader.imgHeight, UNCOMPRESSED_GRAY_ALPHA); Image image = LoadImageEx(imagePixels, rbmfHeader.imgWidth, rbmfHeader.imgHeight);
ImageConvertFormat(&image, UNCOMPRESSED_GRAY_ALPHA);
free(imagePixels); free(imagePixels);
TraceLog(INFO, "[%s] Image reconstructed correctly, now converting it to texture", fileName); TraceLog(INFO, "[%s] Image reconstructed correctly, now converting it to texture", fileName);
spriteFont.texture = LoadTextureFromImage(image, false); spriteFont.texture = LoadTextureFromImage(image);
UnloadImage(image); // Unload image data UnloadImage(image); // Unload image data
//TraceLog(INFO, "[%s] Starting charSet reconstruction", fileName); //TraceLog(INFO, "[%s] Starting charSet reconstruction", fileName);
@ -689,7 +691,7 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize)
*/ */
font.numChars = 95; font.numChars = 95;
font.charSet = (Character *)malloc(font.numChars*sizeof(Character)); font.charSet = (Character *)malloc(font.numChars*sizeof(Character));
font.texture = LoadTextureFromImage(image, false); font.texture = LoadTextureFromImage(image);
//stbtt_aligned_quad letter; //stbtt_aligned_quad letter;
//int x = 0, y = 0; //int x = 0, y = 0;

View file

@ -123,6 +123,32 @@ Image LoadImage(const char *fileName)
return image; return image;
} }
// Load image data from Color array data (RGBA - 32bit)
Image LoadImageEx(Color *pixels, int width, int height)
{
Image image;
image.data = NULL;
image.width = width;
image.height = height;
image.mipmaps = 1;
image.format = UNCOMPRESSED_R8G8B8A8;
int k = 0;
image.data = (unsigned char *)malloc(image.width*image.height*4*sizeof(unsigned char));
for (int i = 0; i < image.width*image.height*4; i += 4)
{
((unsigned char *)image.data)[i] = pixels[k].r;
((unsigned char *)image.data)[i + 1] = pixels[k].g;
((unsigned char *)image.data)[i + 2] = pixels[k].b;
((unsigned char *)image.data)[i + 3] = pixels[k].a;
k++;
}
return image;
}
// Load an image from rRES file (raylib Resource) // Load an image from rRES file (raylib Resource)
// TODO: Review function to support multiple color modes // TODO: Review function to support multiple color modes
Image LoadImageFromRES(const char *rresName, int resId) Image LoadImageFromRES(const char *rresName, int resId)
@ -243,12 +269,12 @@ Texture2D LoadTexture(const char *fileName)
Image image = LoadImage(fileName); Image image = LoadImage(fileName);
#if defined(PLATFORM_RPI) || defined(PLATFORM_WEB) #if defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
ConvertToPOT(&image, BLANK); ImageConvertToPOT(&image, BLANK);
#endif #endif
if (image.data != NULL) if (image.data != NULL)
{ {
texture = LoadTextureFromImage(image, false); texture = LoadTextureFromImage(image);
UnloadImage(image); UnloadImage(image);
} }
else else
@ -261,7 +287,7 @@ Texture2D LoadTexture(const char *fileName)
return texture; return texture;
} }
Texture2D LoadTextureEx(void *data, int width, int height, int textureFormat, int mipmapCount, bool genMipmaps) Texture2D LoadTextureEx(void *data, int width, int height, int textureFormat, int mipmapCount)
{ {
Texture2D texture; Texture2D texture;
@ -270,14 +296,14 @@ Texture2D LoadTextureEx(void *data, int width, int height, int textureFormat, in
texture.mipmaps = mipmapCount; texture.mipmaps = mipmapCount;
texture.format = textureFormat; texture.format = textureFormat;
texture.id = rlglLoadTexture(data, width, height, textureFormat, mipmapCount, genMipmaps); texture.id = rlglLoadTexture(data, width, height, textureFormat, mipmapCount);
return texture; return texture;
} }
// Load a texture from image data // Load a texture from image data
// NOTE: image is not unloaded, it must be done manually // NOTE: image is not unloaded, it must be done manually
Texture2D LoadTextureFromImage(Image image, bool genMipmaps) Texture2D LoadTextureFromImage(Image image)
{ {
Texture2D texture; Texture2D texture;
@ -288,7 +314,7 @@ Texture2D LoadTextureFromImage(Image image, bool genMipmaps)
texture.mipmaps = 0; texture.mipmaps = 0;
texture.format = 0; texture.format = 0;
texture.id = rlglLoadTexture(image.data, image.width, image.height, image.format, image.mipmaps, false); texture.id = rlglLoadTexture(image.data, image.width, image.height, image.format, image.mipmaps);
texture.width = image.width; texture.width = image.width;
texture.height = image.height; texture.height = image.height;
@ -304,7 +330,7 @@ Texture2D LoadTextureFromRES(const char *rresName, int resId)
Texture2D texture; Texture2D texture;
Image image = LoadImageFromRES(rresName, resId); Image image = LoadImageFromRES(rresName, resId);
texture = LoadTextureFromImage(image, false); texture = LoadTextureFromImage(image);
UnloadImage(image); UnloadImage(image);
return texture; return texture;
@ -324,7 +350,7 @@ void UnloadTexture(Texture2D texture)
// Convert image to POT (power-of-two) // Convert image to POT (power-of-two)
// NOTE: Requirement on OpenGL ES 2.0 (RPI, HTML5) // NOTE: Requirement on OpenGL ES 2.0 (RPI, HTML5)
void ConvertToPOT(Image *image, Color fillColor) void ImageConvertToPOT(Image *image, Color fillColor)
{ {
// TODO: Review for new image struct // TODO: Review for new image struct
/* /*
@ -447,144 +473,174 @@ Color *GetPixelData(Image image)
return pixels; return pixels;
} }
// Fill image data with pixels Color data (RGBA - 32bit) // Get pixel data from GPU texture and return an Image
// NOTE: Data is transformed to desired format Image GetTextureData(Texture2D texture)
Image LoadImageFromData(Color *pixels, int width, int height, int format)
{ {
Image image; Image image;
image.data = NULL;
image.width = width;
image.height = height;
image.mipmaps = 1;
image.format = format;
int k = 0;
switch (format) image.data = rlglReadTexturePixels(texture.id, texture.format);
if (image.data != NULL)
{ {
case UNCOMPRESSED_GRAYSCALE: image.width = texture.width;
{ image.height = texture.height;
image.data = (unsigned char *)malloc(image.width*image.height*sizeof(unsigned char)); image.format = texture.format;
image.mipmaps = 1;
for (int i = 0; i < image.width*image.height; i++)
{
((unsigned char *)image.data)[i] = (unsigned char)((float)pixels[k].r*0.299f + (float)pixels[k].g*0.587f + (float)pixels[k].b*0.114f);
k++;
}
} break;
case UNCOMPRESSED_GRAY_ALPHA:
{
image.data = (unsigned char *)malloc(image.width*image.height*2*sizeof(unsigned char));
for (int i = 0; i < image.width*image.height*2; i += 2)
{
((unsigned char *)image.data)[i] = (unsigned char)((float)pixels[k].r*0.299f + (float)pixels[k].g*0.587f + (float)pixels[k].b*0.114f);
((unsigned char *)image.data)[i + 1] = pixels[k].a;
k++;
}
} break;
case UNCOMPRESSED_R5G6B5:
{
image.data = (unsigned short *)malloc(image.width*image.height*sizeof(unsigned short));
unsigned char r;
unsigned char g;
unsigned char b;
for (int i = 0; i < image.width*image.height; i++)
{
r = (unsigned char)(round((float)pixels[k].r*31/255));
g = (unsigned char)(round((float)pixels[k].g*63/255));
b = (unsigned char)(round((float)pixels[k].b*31/255));
((unsigned short *)image.data)[i] = (unsigned short)r << 11 | (unsigned short)g << 5 | (unsigned short)b;
k++;
}
} break;
case UNCOMPRESSED_R8G8B8:
{
image.data = (unsigned char *)malloc(image.width*image.height*3*sizeof(unsigned char));
for (int i = 0; i < image.width*image.height*3; i += 3)
{
((unsigned char *)image.data)[i] = pixels[k].r;
((unsigned char *)image.data)[i + 1] = pixels[k].g;
((unsigned char *)image.data)[i + 2] = pixels[k].b;
k++;
}
} break;
case UNCOMPRESSED_R5G5B5A1:
{
image.data = (unsigned short *)malloc(image.width*image.height*sizeof(unsigned short));
unsigned char r;
unsigned char g;
unsigned char b;
unsigned char a = 1;
for (int i = 0; i < image.width*image.height; i++)
{
r = (unsigned char)(round((float)pixels[k].r*31/255));
g = (unsigned char)(round((float)pixels[k].g*31/255));
b = (unsigned char)(round((float)pixels[k].b*31/255));
a = (pixels[k].a > 50) ? 1 : 0;
((unsigned short *)image.data)[i] = (unsigned short)r << 11 | (unsigned short)g << 6 | (unsigned short)b << 1| (unsigned short)a;
k++;
}
} break;
case UNCOMPRESSED_R4G4B4A4:
{
image.data = (unsigned short *)malloc(image.width*image.height*sizeof(unsigned short));
unsigned char r;
unsigned char g;
unsigned char b;
unsigned char a;
for (int i = 0; i < image.width*image.height; i++)
{
r = (unsigned char)(round((float)pixels[k].r*15/255));
g = (unsigned char)(round((float)pixels[k].g*15/255));
b = (unsigned char)(round((float)pixels[k].b*15/255));
a = (unsigned char)(round((float)pixels[k].a*15/255));
((unsigned short *)image.data)[i] = (unsigned short)r << 12 | (unsigned short)g << 8| (unsigned short)b << 4| (unsigned short)a;
k++;
}
} break;
case UNCOMPRESSED_R8G8B8A8:
{
image.data = (unsigned char *)malloc(image.width*image.height*4*sizeof(unsigned char));
for (int i = 0; i < image.width*image.height*4; i += 4)
{
((unsigned char *)image.data)[i] = pixels[k].r;
((unsigned char *)image.data)[i + 1] = pixels[k].g;
((unsigned char *)image.data)[i + 2] = pixels[k].b;
((unsigned char *)image.data)[i + 3] = pixels[k].a;
k++;
}
} break;
default:
{
TraceLog(WARNING, "Format not recognized, image could not be loaded");
return image;
} break;
} }
else TraceLog(WARNING, "Texture pixel data could not be obtained");
return image; return image;
} }
// Convert image data to desired format
void ImageConvertFormat(Image *image, int newFormat)
{
if ((image->format != newFormat) && (image->format < 8) && (newFormat < 8))
{
Color *pixels = GetPixelData(*image);
free(image->data);
image->format = newFormat;
int k = 0;
switch (image->format)
{
case UNCOMPRESSED_GRAYSCALE:
{
image->data = (unsigned char *)malloc(image->width*image->height*sizeof(unsigned char));
for (int i = 0; i < image->width*image->height; i++)
{
((unsigned char *)image->data)[i] = (unsigned char)((float)pixels[k].r*0.299f + (float)pixels[k].g*0.587f + (float)pixels[k].b*0.114f);
k++;
}
} break;
case UNCOMPRESSED_GRAY_ALPHA:
{
image->data = (unsigned char *)malloc(image->width*image->height*2*sizeof(unsigned char));
for (int i = 0; i < image->width*image->height*2; i += 2)
{
((unsigned char *)image->data)[i] = (unsigned char)((float)pixels[k].r*0.299f + (float)pixels[k].g*0.587f + (float)pixels[k].b*0.114f);
((unsigned char *)image->data)[i + 1] = pixels[k].a;
k++;
}
} break;
case UNCOMPRESSED_R5G6B5:
{
image->data = (unsigned short *)malloc(image->width*image->height*sizeof(unsigned short));
unsigned char r;
unsigned char g;
unsigned char b;
for (int i = 0; i < image->width*image->height; i++)
{
r = (unsigned char)(round((float)pixels[k].r*31/255));
g = (unsigned char)(round((float)pixels[k].g*63/255));
b = (unsigned char)(round((float)pixels[k].b*31/255));
((unsigned short *)image->data)[i] = (unsigned short)r << 11 | (unsigned short)g << 5 | (unsigned short)b;
k++;
}
} break;
case UNCOMPRESSED_R8G8B8:
{
image->data = (unsigned char *)malloc(image->width*image->height*3*sizeof(unsigned char));
for (int i = 0; i < image->width*image->height*3; i += 3)
{
((unsigned char *)image->data)[i] = pixels[k].r;
((unsigned char *)image->data)[i + 1] = pixels[k].g;
((unsigned char *)image->data)[i + 2] = pixels[k].b;
k++;
}
} break;
case UNCOMPRESSED_R5G5B5A1:
{
image->data = (unsigned short *)malloc(image->width*image->height*sizeof(unsigned short));
unsigned char r;
unsigned char g;
unsigned char b;
unsigned char a = 1;
for (int i = 0; i < image->width*image->height; i++)
{
r = (unsigned char)(round((float)pixels[k].r*31/255));
g = (unsigned char)(round((float)pixels[k].g*31/255));
b = (unsigned char)(round((float)pixels[k].b*31/255));
a = (pixels[k].a > 50) ? 1 : 0;
((unsigned short *)image->data)[i] = (unsigned short)r << 11 | (unsigned short)g << 6 | (unsigned short)b << 1| (unsigned short)a;
k++;
}
} break;
case UNCOMPRESSED_R4G4B4A4:
{
image->data = (unsigned short *)malloc(image->width*image->height*sizeof(unsigned short));
unsigned char r;
unsigned char g;
unsigned char b;
unsigned char a;
for (int i = 0; i < image->width*image->height; i++)
{
r = (unsigned char)(round((float)pixels[k].r*15/255));
g = (unsigned char)(round((float)pixels[k].g*15/255));
b = (unsigned char)(round((float)pixels[k].b*15/255));
a = (unsigned char)(round((float)pixels[k].a*15/255));
((unsigned short *)image->data)[i] = (unsigned short)r << 12 | (unsigned short)g << 8| (unsigned short)b << 4| (unsigned short)a;
k++;
}
} break;
case UNCOMPRESSED_R8G8B8A8:
{
image->data = (unsigned char *)malloc(image->width*image->height*4*sizeof(unsigned char));
for (int i = 0; i < image->width*image->height*4; i += 4)
{
((unsigned char *)image->data)[i] = pixels[k].r;
((unsigned char *)image->data)[i + 1] = pixels[k].g;
((unsigned char *)image->data)[i + 2] = pixels[k].b;
((unsigned char *)image->data)[i + 3] = pixels[k].a;
k++;
}
} break;
default: break;
}
free(pixels);
}
else TraceLog(WARNING, "Image data format is compressed, can not be converted");
}
/*
Image ImageCopy(Image image);
void ImageCrop(Image *image, Rectangle crop);
void ImageResize(Image *image, int newWidth, int newHeight);
void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec);
void ImageDrawText(Image *dst, const char *text, Vector2 position, int size, Color color);
*/
// Generate GPU mipmaps for a texture
void GenTextureMipmaps(Texture2D texture)
{
rlglGenerateMipmaps(texture.id);
}
// Draw a Texture2D // Draw a Texture2D
void DrawTexture(Texture2D texture, int posX, int posY, Color tint) void DrawTexture(Texture2D texture, int posX, int posY, Color tint)
{ {
@ -1224,6 +1280,8 @@ static Image LoadASTC(const char *fileName)
// NOTE: Assuming Little Endian (could it be wrong?) // NOTE: Assuming Little Endian (could it be wrong?)
image.width = 0x00000000 | ((int)header.width[2] << 16) | ((int)header.width[1] << 8) | ((int)header.width[0]); image.width = 0x00000000 | ((int)header.width[2] << 16) | ((int)header.width[1] << 8) | ((int)header.width[0]);
image.height = 0x00000000 | ((int)header.height[2] << 16) | ((int)header.height[1] << 8) | ((int)header.height[0]); image.height = 0x00000000 | ((int)header.height[2] << 16) | ((int)header.height[1] << 8) | ((int)header.height[0]);
// NOTE: ASTC format only contains one mipmap level
image.mipmaps = 1; image.mipmaps = 1;
TraceLog(DEBUG, "ASTC image width: %i", image.width); TraceLog(DEBUG, "ASTC image width: %i", image.width);
@ -1250,5 +1308,49 @@ static Image LoadASTC(const char *fileName)
fclose(astcFile); fclose(astcFile);
} }
return image;
}
// Load RAW image file
static Image LoadRAW(const char *fileName, int width, int height, int format, int headerSize)
{
Image image;
image.data = NULL;
image.width = 0;
image.height = 0;
image.mipmaps = 0;
image.format = 0;
FILE *rawFile = fopen(fileName, "rb");
if (rawFile == NULL)
{
TraceLog(WARNING, "[%s] RAW image file could not be opened", fileName);
}
else
{
if (headerSize > 0) fseek(rawFile, headerSize, SEEK_SET);
int dataSize = 0;
// TODO: Calculate data size and allocate memory
switch (format)
{
}
fread(image.data, dataSize, 1, rawFile);
// TODO: Check if data have been read
image.width = width;
image.height = height;
image.mipmaps = 0;
image.format = format;
fclose(rawFile);
}
return image; return image;
} }