ソースを参照

Improved pixel formats support

- Renamed enum TextureFormat to PixelFormat for consistency
- Added support for pixel format UNCOMPRESSED_R32
- Using GetPixelDataSize() where required
raysan5 7 年 前
コミット
7caa3201d5
4 ファイル変更33 行追加56 行削除
  1. 8 7
      src/raylib.h
  2. 2 0
      src/rlgl.c
  3. 5 4
      src/rlgl.h
  4. 18 45
      src/textures.c

+ 8 - 7
src/raylib.h

@@ -341,7 +341,7 @@ typedef struct Image {
     int width;              // Image base width
     int height;             // Image base height
     int mipmaps;            // Mipmap levels, 1 by default
-    int format;             // Data format (TextureFormat type)
+    int format;             // Data format (PixelFormat type)
 } Image;
 
 // Texture2D type
@@ -351,7 +351,7 @@ typedef struct Texture2D {
     int width;              // Texture base width
     int height;             // Texture base height
     int mipmaps;            // Mipmap levels, 1 by default
-    int format;             // Data format (TextureFormat type)
+    int format;             // Data format (PixelFormat type)
 } Texture2D;
 
 // RenderTexture2D type, for texture rendering
@@ -571,18 +571,19 @@ typedef enum {
 #define MAP_DIFFUSE      MAP_ALBEDO
 #define MAP_SPECULAR     MAP_METALNESS
 
-// Texture formats
+// Pixel formats
 // NOTE: Support depends on OpenGL version and platform
 typedef enum {
     UNCOMPRESSED_GRAYSCALE = 1,     // 8 bit per pixel (no alpha)
-    UNCOMPRESSED_GRAY_ALPHA,        // 16 bpp (2 channels)
+    UNCOMPRESSED_GRAY_ALPHA,        // 8*2 bpp (2 channels)
     UNCOMPRESSED_R5G6B5,            // 16 bpp
     UNCOMPRESSED_R8G8B8,            // 24 bpp
     UNCOMPRESSED_R5G5B5A1,          // 16 bpp (1 bit alpha)
     UNCOMPRESSED_R4G4B4A4,          // 16 bpp (4 bit alpha)
     UNCOMPRESSED_R8G8B8A8,          // 32 bpp
-    UNCOMPRESSED_R32G32B32,         // 32 bit per channel (float) - HDR
-    UNCOMPRESSED_R32G32B32A32,      // 32 bit per channel (float) - HDR
+    UNCOMPRESSED_R32,               // 32 bpp (1 channel - float)
+    UNCOMPRESSED_R32G32B32,         // 32*3 bpp (3 channels - float)
+    UNCOMPRESSED_R32G32B32A32,      // 32*4 bpp (4 channels - float)
     COMPRESSED_DXT1_RGB,            // 4 bpp (no alpha)
     COMPRESSED_DXT1_RGBA,           // 4 bpp (1 bit alpha)
     COMPRESSED_DXT3_RGBA,           // 8 bpp
@@ -594,7 +595,7 @@ typedef enum {
     COMPRESSED_PVRT_RGBA,           // 4 bpp
     COMPRESSED_ASTC_4x4_RGBA,       // 8 bpp
     COMPRESSED_ASTC_8x8_RGBA        // 2 bpp
-} TextureFormat;
+} PixelFormat;
 
 // Texture parameters: filter mode
 // NOTE 1: Filtering considers mipmaps if available in the texture

+ 2 - 0
src/rlgl.c

@@ -1420,6 +1420,7 @@ unsigned int rlLoadTexture(void *data, int width, int height, int format, int mi
         case COMPRESSED_DXT5_RGBA: if (texCompDXTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, mipmapCount); break;
     #endif
     #if defined(GRAPHICS_API_OPENGL_ES2)
+        case UNCOMPRESSED_R32: if (texFloatSupported) glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, GL_RGB, GL_FLOAT, (float *)data); break;  // NOTE: Requires extension OES_texture_float
         case UNCOMPRESSED_R32G32B32: if (texFloatSupported) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_FLOAT, (float *)data); break;  // NOTE: Requires extension OES_texture_float
         case UNCOMPRESSED_R32G32B32A32: if (texFloatSupported) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGB, GL_FLOAT, (float *)data); break;  // NOTE: Requires extension OES_texture_float
         case COMPRESSED_DXT1_RGB: if (texCompDXTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, mipmapCount); break;
@@ -1475,6 +1476,7 @@ unsigned int rlLoadTexture(void *data, int width, int height, int format, int mi
         case UNCOMPRESSED_R5G5B5A1: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5_A1, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, (unsigned short *)data); break;
         case UNCOMPRESSED_R4G4B4A4: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA4, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, (unsigned short *)data); break;
         case UNCOMPRESSED_R8G8B8A8: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data); break;
+        case UNCOMPRESSED_R32: if (texFloatSupported) glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, width, height, 0, GL_RGB, GL_FLOAT, (float *)data); break;
         case UNCOMPRESSED_R32G32B32: if (texFloatSupported) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, width, height, 0, GL_RGB, GL_FLOAT, (float *)data); break;
         case UNCOMPRESSED_R32G32B32A32: if (texFloatSupported) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGB, GL_FLOAT, (float *)data); break;
         case COMPRESSED_DXT1_RGB: if (texCompDXTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, mipmapCount); break;

+ 5 - 4
src/rlgl.h

@@ -169,7 +169,7 @@ typedef unsigned char byte;
         int width;              // Texture base width
         int height;             // Texture base height
         int mipmaps;            // Mipmap levels, 1 by default
-        int format;             // Data format (TextureFormat)
+        int format;             // Data format (PixelFormat)
     } Texture2D;
 
     // RenderTexture2D type, for texture rendering
@@ -259,8 +259,9 @@ typedef unsigned char byte;
         UNCOMPRESSED_R5G5B5A1,          // 16 bpp (1 bit alpha)
         UNCOMPRESSED_R4G4B4A4,          // 16 bpp (4 bit alpha)
         UNCOMPRESSED_R8G8B8A8,          // 32 bpp
-        UNCOMPRESSED_R32G32B32,         // 32 bit per channel (float) - HDR
-        UNCOMPRESSED_R32G32B32A32,      // 32 bit per channel (float) - HDR
+        UNCOMPRESSED_R32,               // 32 bpp (1 channel - float)
+        UNCOMPRESSED_R32G32B32,         // 32*3 bpp (3 channels - float)
+        UNCOMPRESSED_R32G32B32A32,      // 32*4 bpp (4 channels - float)
         COMPRESSED_DXT1_RGB,            // 4 bpp (no alpha)
         COMPRESSED_DXT1_RGBA,           // 4 bpp (1 bit alpha)
         COMPRESSED_DXT3_RGBA,           // 8 bpp
@@ -272,7 +273,7 @@ typedef unsigned char byte;
         COMPRESSED_PVRT_RGBA,           // 4 bpp
         COMPRESSED_ASTC_4x4_RGBA,       // 8 bpp
         COMPRESSED_ASTC_8x8_RGBA        // 2 bpp
-    } TextureFormat;
+    } PixelFormat;
 
     // Texture parameters: filter mode
     // NOTE 1: Filtering considers mipmaps if available in the texture

+ 18 - 45
src/textures.c

@@ -226,11 +226,11 @@ Image LoadImage(const char *fileName)
         
         image.mipmaps = 1;
         
-        if (imgBpp == 3) image.format = UNCOMPRESSED_R32G32B32;
+        if (imgBpp == 1) image.format = UNCOMPRESSED_R32;
+        else if (imgBpp == 3) image.format = UNCOMPRESSED_R32G32B32;
         else if (imgBpp == 4) image.format = UNCOMPRESSED_R32G32B32A32;
         else 
         {
-            // TODO: Support different number of channels at 32 bit float
             TraceLog(LOG_WARNING, "[%s] Image fileformat not supported", fileName);
             UnloadImage(image);
         }
@@ -318,21 +318,9 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int
     {
         if (headerSize > 0) fseek(rawFile, headerSize, SEEK_SET);
 
-        unsigned int size = width*height;
-
-        switch (format)
-        {
-            case UNCOMPRESSED_GRAYSCALE: image.data = (unsigned char *)malloc(size); break;               // 8 bit per pixel (no alpha)
-            case UNCOMPRESSED_GRAY_ALPHA: image.data = (unsigned char *)malloc(size*2); size *= 2; break; // 16 bpp (2 channels)
-            case UNCOMPRESSED_R5G6B5: image.data = (unsigned short *)malloc(size); break;                 // 16 bpp
-            case UNCOMPRESSED_R8G8B8: image.data = (unsigned char *)malloc(size*3); size *= 3; break;     // 24 bpp
-            case UNCOMPRESSED_R5G5B5A1: image.data = (unsigned short *)malloc(size); break;               // 16 bpp (1 bit alpha)
-            case UNCOMPRESSED_R4G4B4A4: image.data = (unsigned short *)malloc(size); break;               // 16 bpp (4 bit alpha)
-            case UNCOMPRESSED_R8G8B8A8: image.data = (unsigned char *)malloc(size*4); size *= 4; break;   // 32 bpp
-            case UNCOMPRESSED_R32G32B32: image.data = (float *)malloc(size*12); size *= 12; break;        // 4 byte per channel (12 byte)
-            case UNCOMPRESSED_R32G32B32A32: image.data = (float *)malloc(size*16); size *= 16; break;     // 4 byte per channel (16 byte)
-            default: TraceLog(LOG_WARNING, "Image format not suported"); break;
-        }
+        unsigned int size = GetPixelDataSize(width, height, format);
+        
+        image.data = malloc(size);      // Allocate required memory in bytes
 
         // NOTE: fread() returns num read elements instead of bytes, 
         // to get bytes we need to read (1 byte size, elements) instead of (x byte size, 1 element)
@@ -531,6 +519,7 @@ int GetPixelDataSize(int width, int height, int format)
         case UNCOMPRESSED_R4G4B4A4: bpp = 16; break;
         case UNCOMPRESSED_R8G8B8A8: bpp = 32; break;
         case UNCOMPRESSED_R8G8B8: bpp = 24; break;
+        case UNCOMPRESSED_R32: bpp = 32; break;
         case UNCOMPRESSED_R32G32B32: bpp = 32*3; break;
         case UNCOMPRESSED_R32G32B32A32: bpp = 32*4; break;
         case COMPRESSED_DXT1_RGB:
@@ -727,6 +716,15 @@ void ImageFormat(Image *image, int newFormat)
                         k++;
                     }
                 } break;
+                case UNCOMPRESSED_R32:
+                {
+                    image->data = (float *)malloc(image->width*image->height*sizeof(float));
+
+                    for (int i = 0; i < image->width*image->height; i++)
+                    {
+                        ((float *)image->data)[i] = (float)((float)pixels[i].r*0.299f/255.0f + (float)pixels[i].g*0.587f/255.0f + (float)pixels[i].b*0.114f/255.0f);
+                    }
+                } break;
                 case UNCOMPRESSED_R32G32B32:
                 {
                     image->data = (float *)malloc(image->width*image->height*3*sizeof(float));
@@ -858,39 +856,14 @@ Image ImageCopy(Image image)
 {
     Image newImage = { 0 };
 
-    int byteSize = image.width*image.height;
-
-    switch (image.format)
-    {
-        case UNCOMPRESSED_GRAYSCALE: break;                 // 8 bpp (1 byte)
-        case UNCOMPRESSED_GRAY_ALPHA:                       // 16 bpp
-        case UNCOMPRESSED_R5G6B5:                           // 16 bpp
-        case UNCOMPRESSED_R5G5B5A1:                         // 16 bpp
-        case UNCOMPRESSED_R4G4B4A4: byteSize *= 2; break;   // 16 bpp (2 bytes)
-        case UNCOMPRESSED_R8G8B8: byteSize *= 3; break;     // 24 bpp (3 bytes)
-        case UNCOMPRESSED_R8G8B8A8: byteSize *= 4; break;   // 32 bpp (4 bytes)
-        case UNCOMPRESSED_R32G32B32: byteSize *= 12; break; // 4 byte per channel (12 bytes)
-        case UNCOMPRESSED_R32G32B32A32: byteSize *= 16; break; // 4 byte per channel (16 bytes)
-        case COMPRESSED_DXT3_RGBA:
-        case COMPRESSED_DXT5_RGBA:
-        case COMPRESSED_ETC2_EAC_RGBA:
-        case COMPRESSED_ASTC_4x4_RGBA: break;               // 8 bpp (1 byte)
-        case COMPRESSED_DXT1_RGB:
-        case COMPRESSED_DXT1_RGBA:
-        case COMPRESSED_ETC1_RGB:
-        case COMPRESSED_ETC2_RGB:
-        case COMPRESSED_PVRT_RGB:
-        case COMPRESSED_PVRT_RGBA: byteSize /= 2; break;    // 4 bpp
-        case COMPRESSED_ASTC_8x8_RGBA: byteSize /= 4; break;// 2 bpp
-        default: TraceLog(LOG_WARNING, "Image format not recognized"); break;
-    }
+    int size = GetPixelDataSize(image.width, image.height, image.format);
 
-    newImage.data = malloc(byteSize);
+    newImage.data = malloc(size);
 
     if (newImage.data != NULL)
     {
         // NOTE: Size must be provided in bytes
-        memcpy(newImage.data, image.data, byteSize);
+        memcpy(newImage.data, image.data, size);
 
         newImage.width = image.width;
         newImage.height = image.height;