[af116c0] | 1 | #include <stdio.h>
|
---|
| 2 | #include <stdlib.h>
|
---|
| 3 | #include <string.h>
|
---|
| 4 |
|
---|
| 5 | #include <GL/glew.h>
|
---|
| 6 |
|
---|
| 7 | #include <GLFW/glfw3.h>
|
---|
| 8 |
|
---|
| 9 |
|
---|
| 10 | GLuint loadBMP_custom(const char * imagepath){
|
---|
| 11 |
|
---|
| 12 | printf("Reading image %s\n", imagepath);
|
---|
| 13 |
|
---|
| 14 | // Data read from the header of the BMP file
|
---|
| 15 | unsigned char header[54];
|
---|
| 16 | unsigned int dataPos;
|
---|
| 17 | unsigned int imageSize;
|
---|
| 18 | unsigned int width, height;
|
---|
| 19 | // Actual RGB data
|
---|
| 20 | unsigned char * data;
|
---|
| 21 |
|
---|
| 22 | // Open the file
|
---|
| 23 | FILE * file = fopen(imagepath,"rb");
|
---|
| 24 | if (!file) {printf("%s could not be opened. Are you in the right directory ? Don't forget to read the FAQ !\n", imagepath); getchar(); return 0;}
|
---|
| 25 |
|
---|
| 26 | // Read the header, i.e. the 54 first bytes
|
---|
| 27 |
|
---|
| 28 | // If less than 54 bytes are read, problem
|
---|
| 29 | if ( fread(header, 1, 54, file)!=54 ){
|
---|
| 30 | printf("Not a correct BMP file\n");
|
---|
| 31 | return 0;
|
---|
| 32 | }
|
---|
| 33 | // A BMP files always begins with "BM"
|
---|
| 34 | if ( header[0]!='B' || header[1]!='M' ){
|
---|
| 35 | printf("Not a correct BMP file\n");
|
---|
| 36 | return 0;
|
---|
| 37 | }
|
---|
| 38 | // Make sure this is a 24bpp file
|
---|
| 39 | if ( *(int*)&(header[0x1E])!=0 ) {printf("Not a correct BMP file\n"); return 0;}
|
---|
| 40 | if ( *(int*)&(header[0x1C])!=24 ) {printf("Not a correct BMP file\n"); return 0;}
|
---|
| 41 |
|
---|
| 42 | // Read the information about the image
|
---|
| 43 | dataPos = *(int*)&(header[0x0A]);
|
---|
| 44 | imageSize = *(int*)&(header[0x22]);
|
---|
| 45 | width = *(int*)&(header[0x12]);
|
---|
| 46 | height = *(int*)&(header[0x16]);
|
---|
| 47 |
|
---|
| 48 | // Some BMP files are misformatted, guess missing information
|
---|
| 49 | if (imageSize==0) imageSize=width*height*3; // 3 : one byte for each Red, Green and Blue component
|
---|
| 50 | if (dataPos==0) dataPos=54; // The BMP header is done that way
|
---|
| 51 |
|
---|
| 52 | // Create a buffer
|
---|
| 53 | data = new unsigned char [imageSize];
|
---|
| 54 |
|
---|
| 55 | // Read the actual data from the file into the buffer
|
---|
| 56 | fread(data,1,imageSize,file);
|
---|
| 57 |
|
---|
| 58 | // Everything is in memory now, the file wan be closed
|
---|
| 59 | fclose (file);
|
---|
| 60 |
|
---|
| 61 | // Create one OpenGL texture
|
---|
| 62 | GLuint textureID;
|
---|
| 63 | glGenTextures(1, &textureID);
|
---|
| 64 |
|
---|
| 65 | // "Bind" the newly created texture : all future texture functions will modify this texture
|
---|
| 66 | glBindTexture(GL_TEXTURE_2D, textureID);
|
---|
| 67 |
|
---|
| 68 | // Give the image to OpenGL
|
---|
| 69 | glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data);
|
---|
| 70 |
|
---|
| 71 | // OpenGL has now copied the data. Free our own version
|
---|
| 72 | delete [] data;
|
---|
| 73 |
|
---|
| 74 | // Poor filtering, or ...
|
---|
| 75 | //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
---|
| 76 | //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
---|
| 77 |
|
---|
| 78 | // ... nice trilinear filtering.
|
---|
| 79 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
---|
| 80 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
---|
| 81 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
---|
| 82 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
---|
| 83 | glGenerateMipmap(GL_TEXTURE_2D);
|
---|
| 84 |
|
---|
| 85 | // Return the ID of the texture we just created
|
---|
| 86 | return textureID;
|
---|
| 87 | }
|
---|
| 88 |
|
---|
| 89 | // Since GLFW 3, glfwLoadTexture2D() has been removed. You have to use another texture loading library,
|
---|
| 90 | // or do it yourself (just like loadBMP_custom and loadDDS)
|
---|
| 91 | //GLuint loadTGA_glfw(const char * imagepath){
|
---|
| 92 | //
|
---|
| 93 | // // Create one OpenGL texture
|
---|
| 94 | // GLuint textureID;
|
---|
| 95 | // glGenTextures(1, &textureID);
|
---|
| 96 | //
|
---|
| 97 | // // "Bind" the newly created texture : all future texture functions will modify this texture
|
---|
| 98 | // glBindTexture(GL_TEXTURE_2D, textureID);
|
---|
| 99 | //
|
---|
| 100 | // // Read the file, call glTexImage2D with the right parameters
|
---|
| 101 | // glfwLoadTexture2D(imagepath, 0);
|
---|
| 102 | //
|
---|
| 103 | // // Nice trilinear filtering.
|
---|
| 104 | // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
---|
| 105 | // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
---|
| 106 | // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
---|
| 107 | // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
---|
| 108 | // glGenerateMipmap(GL_TEXTURE_2D);
|
---|
| 109 | //
|
---|
| 110 | // // Return the ID of the texture we just created
|
---|
| 111 | // return textureID;
|
---|
| 112 | //}
|
---|
| 113 |
|
---|
| 114 |
|
---|
| 115 |
|
---|
| 116 | #define FOURCC_DXT1 0x31545844 // Equivalent to "DXT1" in ASCII
|
---|
| 117 | #define FOURCC_DXT3 0x33545844 // Equivalent to "DXT3" in ASCII
|
---|
| 118 | #define FOURCC_DXT5 0x35545844 // Equivalent to "DXT5" in ASCII
|
---|
| 119 |
|
---|
| 120 | GLuint loadDDS(const char * imagepath){
|
---|
| 121 |
|
---|
| 122 | unsigned char header[124];
|
---|
| 123 |
|
---|
| 124 | FILE *fp;
|
---|
| 125 |
|
---|
| 126 | /* try to open the file */
|
---|
| 127 | fp = fopen(imagepath, "rb");
|
---|
| 128 | if (fp == NULL){
|
---|
| 129 | printf("%s could not be opened. Are you in the right directory ? Don't forget to read the FAQ !\n", imagepath); getchar();
|
---|
| 130 | return 0;
|
---|
| 131 | }
|
---|
| 132 |
|
---|
| 133 | /* verify the type of file */
|
---|
| 134 | char filecode[4];
|
---|
| 135 | fread(filecode, 1, 4, fp);
|
---|
| 136 | if (strncmp(filecode, "DDS ", 4) != 0) {
|
---|
| 137 | fclose(fp);
|
---|
| 138 | return 0;
|
---|
| 139 | }
|
---|
| 140 |
|
---|
| 141 | /* get the surface desc */
|
---|
| 142 | fread(&header, 124, 1, fp);
|
---|
| 143 |
|
---|
| 144 | unsigned int height = *(unsigned int*)&(header[8 ]);
|
---|
| 145 | unsigned int width = *(unsigned int*)&(header[12]);
|
---|
| 146 | unsigned int linearSize = *(unsigned int*)&(header[16]);
|
---|
| 147 | unsigned int mipMapCount = *(unsigned int*)&(header[24]);
|
---|
| 148 | unsigned int fourCC = *(unsigned int*)&(header[80]);
|
---|
| 149 |
|
---|
| 150 |
|
---|
| 151 | unsigned char * buffer;
|
---|
| 152 | unsigned int bufsize;
|
---|
| 153 | /* how big is it going to be including all mipmaps? */
|
---|
| 154 | bufsize = mipMapCount > 1 ? linearSize * 2 : linearSize;
|
---|
| 155 | buffer = (unsigned char*)malloc(bufsize * sizeof(unsigned char));
|
---|
| 156 | fread(buffer, 1, bufsize, fp);
|
---|
| 157 | /* close the file pointer */
|
---|
| 158 | fclose(fp);
|
---|
| 159 |
|
---|
| 160 | unsigned int components = (fourCC == FOURCC_DXT1) ? 3 : 4;
|
---|
| 161 | unsigned int format;
|
---|
| 162 | switch(fourCC)
|
---|
| 163 | {
|
---|
| 164 | case FOURCC_DXT1:
|
---|
| 165 | format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
---|
| 166 | break;
|
---|
| 167 | case FOURCC_DXT3:
|
---|
| 168 | format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
---|
| 169 | break;
|
---|
| 170 | case FOURCC_DXT5:
|
---|
| 171 | format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
---|
| 172 | break;
|
---|
| 173 | default:
|
---|
| 174 | free(buffer);
|
---|
| 175 | return 0;
|
---|
| 176 | }
|
---|
| 177 |
|
---|
| 178 | // Create one OpenGL texture
|
---|
| 179 | GLuint textureID;
|
---|
| 180 | glGenTextures(1, &textureID);
|
---|
| 181 |
|
---|
| 182 | // "Bind" the newly created texture : all future texture functions will modify this texture
|
---|
| 183 | glBindTexture(GL_TEXTURE_2D, textureID);
|
---|
| 184 | glPixelStorei(GL_UNPACK_ALIGNMENT,1);
|
---|
| 185 |
|
---|
| 186 | unsigned int blockSize = (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ? 8 : 16;
|
---|
| 187 | unsigned int offset = 0;
|
---|
| 188 |
|
---|
| 189 | /* load the mipmaps */
|
---|
| 190 | for (unsigned int level = 0; level < mipMapCount && (width || height); ++level)
|
---|
| 191 | {
|
---|
| 192 | unsigned int size = ((width+3)/4)*((height+3)/4)*blockSize;
|
---|
| 193 | glCompressedTexImage2D(GL_TEXTURE_2D, level, format, width, height,
|
---|
| 194 | 0, size, buffer + offset);
|
---|
| 195 |
|
---|
| 196 | offset += size;
|
---|
| 197 | width /= 2;
|
---|
| 198 | height /= 2;
|
---|
| 199 |
|
---|
| 200 | // Deal with Non-Power-Of-Two textures. This code is not included in the webpage to reduce clutter.
|
---|
| 201 | if(width < 1) width = 1;
|
---|
| 202 | if(height < 1) height = 1;
|
---|
| 203 |
|
---|
| 204 | }
|
---|
| 205 |
|
---|
| 206 | free(buffer);
|
---|
| 207 |
|
---|
| 208 | return textureID;
|
---|
| 209 |
|
---|
| 210 |
|
---|
| 211 | }
|
---|