00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <GLEXT/GLTexture.h>
00022 #include <GLEXT/GLStateExtension.h>
00023 #include <common/Defines.h>
00024 #include <set>
00025
00026
00027 unsigned int GLTexture::textureSpace_ = 0;
00028 unsigned int GLTexture::textureSets_ = 0;
00029
00030 GLTexture::GLTexture() :
00031 texNum_(0), texType_(GL_TEXTURE_2D),
00032 usedSpace_(0),
00033 width_(0), height_(0)
00034 {
00035
00036 }
00037
00038 GLTexture::~GLTexture()
00039 {
00040 textureSpace_ -= usedSpace_;
00041 if (texNum_)
00042 {
00043 glDeleteTextures(1, &texNum_);
00044
00045 texNum_ = 0;
00046 }
00047 }
00048
00049 void GLTexture::draw(bool force)
00050 {
00051 if ((this != lastBind_) || force)
00052 {
00053 glBindTexture(texType_, texNum_);
00054 lastBind_ = this;
00055 textureSets_++;
00056 }
00057 }
00058
00059 bool GLTexture::replace(Image &bitmap, bool mipMap)
00060 {
00061 GLenum format =
00062 (bitmap.getComponents()==1)?GL_LUMINANCE:
00063 ((bitmap.getComponents() == 3)?GL_RGB:GL_RGBA);
00064
00065 if (textureValid())
00066 {
00067 if(GLStateExtension::getNoTexSubImage() ||
00068 (bitmap.getWidth() != width_) ||
00069 (bitmap.getHeight() != height_))
00070 {
00071 glDeleteTextures(1, &texNum_);
00072
00073 texNum_ = 0;
00074 }
00075 }
00076
00077 if (textureValid())
00078 {
00079 draw();
00080 {
00081 glPixelStorei(GL_UNPACK_ROW_LENGTH, bitmap.getWidth());
00082 glTexSubImage2D(texType_, 0,
00083 0, 0,
00084 bitmap.getWidth(), bitmap.getHeight(),
00085 format, GL_UNSIGNED_BYTE,
00086 bitmap.getBits());
00087 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
00088 }
00089 }
00090 else
00091 {
00092 return create(bitmap, mipMap);
00093 }
00094 return true;
00095 }
00096
00097 bool GLTexture::create(Image &bitmap, bool mipMap)
00098 {
00099 GLenum format =
00100 (bitmap.getComponents()==1)?GL_LUMINANCE:
00101 ((bitmap.getComponents() == 3)?GL_RGB:GL_RGBA);
00102
00103 bool success = create(bitmap.getBits(),
00104 bitmap.getWidth(),
00105 bitmap.getHeight(),
00106 bitmap.getComponents(),
00107 bitmap.getAlignment(),
00108 format,
00109 mipMap);
00110
00111 return success;
00112 }
00113
00114 bool GLTexture::createObject()
00115 {
00116 if (!textureValid())
00117 {
00118 GLfloat priority = 1.0f;
00119 glGenTextures(1, &texNum_);
00120
00121
00122
00123
00124
00125
00126 glPrioritizeTextures(1, &texNum_, &priority);
00127 }
00128
00129 return true;
00130 }
00131
00132 bool GLTexture::create(const void * data,
00133 GLint width,
00134 GLint height,
00135 GLint components,
00136 GLint alignment,
00137 GLenum format,
00138 bool mipMap)
00139 {
00140 bool success = false;
00141 if (data)
00142 {
00143 if (height == 1 || width == 1) texType_ = GL_TEXTURE_1D;
00144 else texType_ = GL_TEXTURE_2D;
00145
00146 if (!validateSize(width) || !validateSize(height))
00147 {
00148 S3D::dialogExit("Scorched3D",
00149 S3D::formatStringBuffer("Invalid OpenGL texture size %ix%i specified",
00150 width, height));
00151 }
00152
00153 if (!createObject()) return false;
00154 glBindTexture(texType_, texNum_);
00155
00156 success = createTexture(data, width, height, components, alignment, format, mipMap);
00157 }
00158
00159 return success;
00160 }
00161
00162 bool GLTexture::createTexture(const void * data,
00163 GLint width,
00164 GLint height,
00165 GLint components,
00166 GLint alignment,
00167 GLenum format,
00168 bool mipMap)
00169 {
00170 textureSpace_ -= usedSpace_;
00171 usedSpace_ = width * height * components;
00172 textureSpace_ += usedSpace_;
00173 width_ = width;
00174 height_ = height;
00175
00176 texFormat_ = format;
00177 glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
00178 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
00179 glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
00180 glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
00181
00182 if (height == 1)
00183 {
00184 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00185 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
00186
00187 gluBuild1DMipmaps(GL_TEXTURE_1D, components, width,
00188 format, GL_UNSIGNED_BYTE, data);
00189 }
00190 else if (width == 1)
00191 {
00192 if (mipMap)
00193 {
00194 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00195 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
00196
00197 gluBuild1DMipmaps(GL_TEXTURE_1D, components, height,
00198 format, GL_UNSIGNED_BYTE, data);
00199 }
00200 else
00201 {
00202 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00203 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00204
00205 glTexImage1D(GL_TEXTURE_1D, 0, components, height,
00206 0, format, GL_UNSIGNED_BYTE, data);
00207 }
00208 }
00209 else
00210 {
00211 if (mipMap)
00212 {
00213 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00214 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
00215
00216 if (GLStateExtension::hasHardwareMipmaps())
00217 {
00218 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
00219
00220 glTexImage2D(GL_TEXTURE_2D, 0, components, width,
00221 height, 0, format, GL_UNSIGNED_BYTE, data);
00222 }
00223 else
00224 {
00225 gluBuild2DMipmaps(GL_TEXTURE_2D, components, width,
00226 height, format, GL_UNSIGNED_BYTE, data);
00227 }
00228 }
00229 else
00230 {
00231 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
00232 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
00233
00234 glTexImage2D(GL_TEXTURE_2D, 0, components, width,
00235 height, 0, format, GL_UNSIGNED_BYTE, data);
00236 }
00237 };
00238
00239 return true;
00240 }
00241
00242 bool GLTexture::create(GLint width, GLint height, GLenum format)
00243 {
00244
00245 texType_ = GL_TEXTURE_2D;
00246 width_ = width;
00247 height_ = height;
00248 texFormat_ = format;
00249
00250
00251 if (!createObject()) return false;
00252
00253 glBindTexture(texType_, texNum_);
00254
00255 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00256 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00257 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00258 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00259
00260 glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0,
00261 GL_RGBA, GL_UNSIGNED_BYTE,NULL);
00262
00263 return true;
00264 }
00265
00266 bool GLTexture::createBufferTexture(GLint width, GLint height, bool depthTex)
00267 {
00268
00269 texType_ = GL_TEXTURE_2D;
00270 width_ = width;
00271 height_ = height;
00272
00273
00274 if (!createObject()) return false;
00275
00276 glBindTexture(texType_, texNum_);
00277
00278 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00279 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00280 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00281 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00282
00283 if (!depthTex)
00284 {
00285 texFormat_ = GL_RGB;
00286
00287 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,
00288 GL_RGB, GL_UNSIGNED_BYTE, NULL);
00289 }
00290 else
00291 {
00292 texFormat_ = GL_DEPTH_COMPONENT;
00293
00294 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
00295 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
00296
00297
00298 GLint depth_bits;
00299 glGetIntegerv(GL_DEPTH_BITS, &depth_bits);
00300 GLenum depth_format;
00301 if(depth_bits == 16) depth_format = GL_DEPTH_COMPONENT16_ARB;
00302 else depth_format = GL_DEPTH_COMPONENT24_ARB;
00303
00304 glTexImage2D(GL_TEXTURE_2D, 0, depth_format, width, height, 0,
00305 GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0);
00306 }
00307
00308 return true;
00309 }
00310
00311 bool GLTexture::textureValid()
00312 {
00313 return (glIsTexture(texNum_) == GL_TRUE);
00314 }
00315
00316 bool GLTexture::validateSize(int size)
00317 {
00318 return (!(size != 1 &&
00319 size != 2 &&
00320 size != 4 &&
00321 size != 8 &&
00322 size != 16 &&
00323 size != 32 &&
00324 size != 64 &&
00325 size != 128 &&
00326 size != 256 &&
00327 size != 512 &&
00328 size != 1024 &&
00329 size != 2048));
00330 }