00001
00010 #include "texture.h"
00011
00016 Texture::Texture()
00017 {
00018 texname = "null";
00019 textype = BASE;
00020 imageData = NULL;
00021 texID = width = height = bpp = 0;
00022 texmode = MODULATE;
00023 tileX = tileY = 1.0;
00024 texLoc = tileXLoc = tileYLoc;
00025 }
00026
00032 Texture::~Texture()
00033 {
00034 glDeleteTextures(1,&texID);
00035 }
00036
00052 GLint Texture::Load(const char *_texname, int _textype, const char *filename, int _texmode,
00053 GLfloat _intensity, GLfloat _tileX, GLfloat _tileY, bool mipmap, bool aniso, GLint cache)
00054 {
00056 if(cache != -1)
00057 {
00058 texID = cache;
00059 }
00060 else
00061 {
00062 if(!LoadTGA(filename))
00063 return ERR;
00064
00065
00066 glGenTextures(1, &texID);
00067 glBindTexture(GL_TEXTURE_2D, texID);
00068
00069
00070 if(aniso)
00071 {
00072
00073 if(!GLEW_EXT_texture_filter_anisotropic)
00074 {
00075 cout<<"Anisotropic filtering not supported. Using linear instead.\n";
00076 }
00077 else
00078 {
00079 float maxAnisotropy;
00080
00081 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropy);
00082 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAnisotropy);
00083 }
00084 }
00085 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
00086
00087 if(mipmap)
00088 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
00089 else
00090 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
00091
00092 if(_textype == BUMP)
00093 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, imageData);
00094 else
00095 glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, imageData);
00096
00097 if(mipmap)
00098 #ifdef GL3
00099 glGenerateMipmap(GL_TEXTURE_2D);
00100 #else
00101 gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width,height, GL_RGB, GL_UNSIGNED_BYTE,imageData);
00102 #endif
00103
00104 delete [] imageData;
00105 }
00106
00107
00108 texname = _texname;
00109 textype = _textype;
00110 texmode = _texmode;
00111 tileX = _tileX;
00112 tileY = _tileY;
00113 intensity = _intensity;
00114
00115
00116
00117 return texID;
00118 }
00119
00120
00137 GLint Texture::Load(const char *_texname, int _textype,
00138 const char **cube_files, int _texmode, GLfloat _intensity, GLfloat _tileX, GLfloat _tileY, bool aniso, GLint cache)
00139 {
00141 if(cache != -1)
00142 {
00143 texID = cache;
00144 }
00145 else
00146 {
00147
00148 glGenTextures(1, &texID);
00149 glBindTexture(GL_TEXTURE_CUBE_MAP, texID);
00150
00151
00152 for(int i = 0; i < 6; i++)
00153 {
00154 if(!LoadTGA(cube_files[i]))
00155 return ERR;
00156
00157
00158 if(aniso)
00159 {
00160
00161 if(!GLEW_EXT_texture_filter_anisotropic)
00162 {
00163 cout<<"Anisotropic filtering not supported. Using linear instead.\n";
00164 }
00165 else
00166 {
00167 float maxAnisotropy;
00168
00169 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropy);
00170 glTexParameterf(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAnisotropy);
00171 }
00172 }
00173
00174
00175 glTexParameteri(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, GL_TEXTURE_MAG_FILTER,GL_LINEAR);
00176 glTexParameteri(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
00177 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_COMPRESSED_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, imageData);
00178 #ifdef GL3
00179 glGenerateMipmap(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i);
00180 #else
00181 gluBuild2DMipmaps(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 3, width,height, GL_RGB, GL_UNSIGNED_BYTE,imageData);
00182 #endif
00183
00184 delete [] imageData;
00185 }
00186 }
00187
00188
00189 texname = _texname;
00190 textype = _textype;
00191 texmode = _texmode;
00192 tileX = _tileX;
00193 tileY = _tileY;
00194 intensity = _intensity;
00195
00196
00197
00198 return texID;
00199 }
00200
00201
00202
00209 bool Texture::LoadTGA(const char* filename)
00210 {
00211 FILE* fTGA;
00212 int type;
00213
00214 GLubyte tgaheader[12];
00215
00216
00217 GLubyte uTGAcompare[12] = { 0,0, 2,0,0,0,0,0,0,0,0,0 };
00218 GLubyte cTGAcompare[12] = { 0,0,10,0,0,0,0,0,0,0,0,0 };
00219
00220
00221 fTGA = fopen(filename, "rb");
00222 if(fTGA == NULL)
00223 {
00224 string err = "Can't open texture file ";
00225 err += filename;
00226 err += " !";
00227 ShowMessage(err.c_str(), false);
00228 return false;
00229 }
00230
00231 cout<<"Loading image "<<filename<<"...";
00232
00234 if(fread(&tgaheader, 12, 1, fTGA) == 0)
00235 {
00236 ShowMessage("Can't read image header!");
00237 if(fTGA != NULL) fclose(fTGA);
00238 return false;
00239 }
00240
00242 if(memcmp(uTGAcompare, &tgaheader, sizeof(tgaheader)) == 0)
00243 type = UNCOMPRESSED;
00244 else if(memcmp(cTGAcompare, &tgaheader, sizeof(tgaheader)) == 0)
00245 type = COMPRESSED;
00246
00247 else
00248 {
00249 ShowMessage("Unknown TGA image type!");
00250 fclose(fTGA);
00251 return false;
00252 }
00253
00254
00255 if(fread(tgaheader, 6, 1, fTGA) == 0)
00256 {
00257 ShowMessage("Can't read image header!");
00258 if(fTGA != NULL) fclose(fTGA);
00259 return false;
00260 }
00261
00263 width = tgaheader[1] * 256 + tgaheader[0];
00264 height = tgaheader[3] * 256 + tgaheader[2];
00265 bpp = tgaheader[4];
00266
00267 cout<<width<<"x"<<height<<"x"<<bpp<<"...";
00268
00269
00270 if((width <= 0) || (height <= 0) || ((bpp != 24) && (bpp != 32)) )
00271 {
00272 ShowMessage("Unknown TGA image type!");
00273 if(fTGA != NULL) fclose(fTGA);
00274 return false;
00275 }
00276
00277
00278
00279
00280
00281
00282
00283
00285 unsigned bytesPerPixel = (bpp / 8);
00286 unsigned imageSize = (bytesPerPixel * width * height);
00287 imageData = new GLubyte[imageSize];
00288 if(imageData == NULL)
00289 {
00290 ShowMessage("Can't allocate image data!");
00291 fclose(fTGA);
00292 return false;
00293 }
00294
00296 if(type == UNCOMPRESSED)
00297 {
00299 if(fread(imageData, 1, imageSize, fTGA) != imageSize)
00300 {
00301 ShowMessage("Can't read image data!");
00302 if(imageData != NULL) delete [] imageData;
00303 fclose(fTGA);
00304 return false;
00305 }
00306
00307 for(unsigned cswap = 0; cswap < imageSize; cswap += bytesPerPixel)
00308 imageData[cswap] ^= imageData[cswap+2] ^= imageData[cswap] ^= imageData[cswap+2];
00309 }
00310
00312 else if(type == COMPRESSED)
00313 {
00314 GLuint pixelcount = height * width;
00315 GLuint currentpixel = 0;
00316 GLuint currentbyte = 0;
00317
00318
00319 GLubyte* colorbuffer = new GLubyte[bytesPerPixel];
00320 if(colorbuffer == NULL)
00321 {
00322 ShowMessage("Can't allocate color buffer data!");
00323 fclose(fTGA);
00324 return false;
00325 }
00326
00327 do
00328 {
00329
00330 GLubyte chunkheader = 0;
00331 if(fread(&chunkheader, sizeof(GLubyte), 1, fTGA) == 0)
00332 {
00333 ShowMessage("Can't read RLE header!");
00334 if(fTGA != NULL) fclose(fTGA);
00335 if(imageData != NULL) delete [] imageData;
00336 if(colorbuffer != NULL) delete [] colorbuffer;
00337 return false;
00338 }
00339
00340
00341 if(chunkheader < 128)
00342 {
00343 chunkheader++;
00344
00345 for(short counter = 0; counter < chunkheader; counter++)
00346 {
00347 if(fread(colorbuffer, 1, bytesPerPixel, fTGA) != bytesPerPixel)
00348 {
00349 ShowMessage("Can't read image data!");
00350 if(fTGA != NULL) fclose(fTGA);
00351 if(colorbuffer != NULL) delete [] colorbuffer;
00352 if(imageData != NULL) delete [] imageData;
00353 return false;
00354 }
00355
00356 imageData[currentbyte] = colorbuffer[2];
00357 imageData[currentbyte + 1] = colorbuffer[1];
00358 imageData[currentbyte + 2] = colorbuffer[0];
00360
00361
00362 currentbyte += bytesPerPixel;
00363 currentpixel++;
00364
00365
00366 if(currentpixel > pixelcount)
00367 {
00368 ShowMessage("Wrong image format - too many pixels.");
00369 if(fTGA != NULL) fclose(fTGA);
00370 if(colorbuffer != NULL) delete [] colorbuffer;
00371 if(imageData != NULL) delete [] imageData;
00372 return false;
00373 }
00374 }
00375 }
00376
00377 else
00378 {
00379 chunkheader -= 127;
00380
00381 if(fread(colorbuffer, 1, bytesPerPixel, fTGA) != bytesPerPixel)
00382 {
00383 ShowMessage("Can't read image data!");
00384 if(fTGA != NULL) fclose(fTGA);
00385 if(colorbuffer != NULL) delete [] colorbuffer;
00386 if(imageData != NULL) delete [] imageData;
00387 return false;
00388 }
00389
00390 for(short counter = 0; counter < chunkheader; counter++)
00391 {
00392
00393 imageData[currentbyte] = colorbuffer[2];
00394 imageData[currentbyte + 1] = colorbuffer[1];
00395 imageData[currentbyte + 2] = colorbuffer[0];
00396
00397
00398
00399 currentbyte += bytesPerPixel;
00400 currentpixel++;
00401
00402
00403 if(currentpixel > pixelcount)
00404 {
00405 ShowMessage("Wrong image format - too many pixels.");
00406 if(fTGA != NULL) fclose(fTGA);
00407 if(colorbuffer != NULL) delete [] colorbuffer;
00408 if(imageData != NULL) delete [] imageData;
00409 return false;
00410 }
00411 }
00412 }
00413 }while(currentpixel < pixelcount);
00414
00415
00416 if(colorbuffer != NULL) delete [] colorbuffer;
00417 }
00418
00419
00420 fclose(fTGA);
00421 cout<<"OK\n";
00422 return true;
00423 }
00424
00425
00431 void Texture::ActivateTexture(GLint tex_unit, bool set_uniforms)
00432 {
00434 if(set_uniforms)
00435 {
00436 glUniform1f(tileXLoc, tileX);
00437 glUniform1f(tileYLoc, tileY);
00438 glUniform1f(intensityLoc, intensity);
00439 }
00440
00441 glUniform1i(texLoc, tex_unit);
00442 if(texMatrixloc != -1)
00443 glUniformMatrix4fv(texMatrixloc, 1, GL_FALSE, texMatrix);
00444
00446 glActiveTexture(GL_TEXTURE0 + tex_unit);
00447
00448 if(textype == CUBEMAP || textype == CUBEMAP_ENV)
00449 glBindTexture(GL_TEXTURE_CUBE_MAP, texID);
00450 else
00451 glBindTexture(GL_TEXTURE_2D, texID);
00452 }
00453
00459 void Texture::GetUniforms(GLuint shader)
00460 {
00461 if(HasTiles())
00462 {
00463 string tileX_str = texname + "_tileX";
00464 string tileY_str = texname + "_tileY";
00465 tileXLoc = glGetUniformLocation(shader,tileX_str.c_str() );
00466 tileYLoc = glGetUniformLocation(shader,tileY_str.c_str() );
00467 }
00468
00470 string texMatrix_str = texname + "_texMatrix";
00471 string intensity_str = texname + "_intensity";
00472
00474 texLoc = glGetUniformLocation(shader,texname.c_str());
00475 texMatrixloc = glGetUniformLocation(shader,texMatrix_str.c_str() );
00476 intensityLoc = glGetUniformLocation(shader,intensity_str.c_str() );
00477 }
00478