00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <texture.h>
00019
00020 #include <renderer.h>
00021
00022 #include <qpixmap.h>
00023 #include <qimage.h>
00024 #include <qrect.h>
00025 #include <qstring.h>
00026 #include <QtDebug>
00027
00028
00029 namespace
00030 {
00031
00032 GLint determineFormat(GLint internalformat)
00033 {
00034 switch (internalformat) {
00035
00036 case GL_ALPHA:
00037 case GL_ALPHA4:
00038 case GL_ALPHA8:
00039 case GL_ALPHA12:
00040 case GL_ALPHA16:
00041 return GL_ALPHA;
00042 case GL_DEPTH_COMPONENT16:
00043 case GL_DEPTH_COMPONENT24:
00044 case GL_DEPTH_COMPONENT32:
00045 return GL_DEPTH_COMPONENT;
00046 case GL_LUMINANCE:
00047 case GL_LUMINANCE4:
00048 case GL_LUMINANCE8:
00049 case GL_LUMINANCE12:
00050 case GL_LUMINANCE16:
00051 return GL_LUMINANCE;
00052 case GL_LUMINANCE_ALPHA:
00053 case GL_LUMINANCE4_ALPHA4:
00054 case GL_LUMINANCE6_ALPHA2:
00055 case GL_LUMINANCE8_ALPHA8:
00056 case GL_LUMINANCE12_ALPHA4:
00057 case GL_LUMINANCE12_ALPHA12:
00058 case GL_LUMINANCE16_ALPHA16:
00059 return GL_LUMINANCE_ALPHA;
00060 case GL_INTENSITY:
00061 case GL_INTENSITY4:
00062 case GL_INTENSITY8:
00063 case GL_INTENSITY12:
00064 case GL_INTENSITY16:
00065 return GL_INTENSITY;
00066 case GL_R3_G3_B2:
00067 case GL_RGB:
00068 case GL_RGB4:
00069 case GL_RGB5:
00070 case GL_RGB8:
00071 case GL_RGB10:
00072 case GL_RGB12:
00073 case GL_RGB16:
00074 return GL_RGB;
00075 case GL_RGBA:
00076 case GL_RGBA2:
00077 case GL_RGBA4:
00078 case GL_RGB5_A1:
00079 case GL_RGBA8:
00080 case GL_RGB10_A2:
00081 case GL_RGBA12:
00082 case GL_RGBA16:
00083 return GL_RGBA;
00084
00085 case GL_SRGB8: return GL_RGB;
00086 case GL_SRGB8_ALPHA8: return GL_RGBA;
00087 case GL_SLUMINANCE: return GL_LUMINANCE;
00088 case GL_SLUMINANCE8_ALPHA8: return GL_LUMINANCE_ALPHA;
00089
00090 case GL_COMPRESSED_ALPHA: return GL_ALPHA;
00091 case GL_COMPRESSED_LUMINANCE: return GL_LUMINANCE;
00092 case GL_COMPRESSED_LUMINANCE_ALPHA: return GL_LUMINANCE_ALPHA;
00093 case GL_COMPRESSED_INTENSITY: return GL_INTENSITY;
00094 case GL_COMPRESSED_RGB: return GL_RGB;
00095 case GL_COMPRESSED_RGBA: return GL_RGBA;
00096 case GL_COMPRESSED_SRGB: return GL_RGB;
00097 case GL_COMPRESSED_SRGB_ALPHA: return GL_RGBA;
00098 case GL_COMPRESSED_SLUMINANCE: return GL_LUMINANCE;
00099 case GL_COMPRESSED_SLUMINANCE_ALPHA: return GL_LUMINANCE_ALPHA;
00100
00101 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
00102 return GL_RGB;
00103 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
00104 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
00105 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
00106 return GL_RGBA;
00107
00108 case GL_RGBA32F_ARB: return GL_RGBA;
00109 case GL_RGB32F_ARB: return GL_RGB;
00110 case GL_ALPHA32F_ARB: return GL_ALPHA;
00111 case GL_INTENSITY32F_ARB: return GL_INTENSITY;
00112 case GL_LUMINANCE32F_ARB: return GL_LUMINANCE;
00113 case GL_LUMINANCE_ALPHA32F_ARB: return GL_LUMINANCE_ALPHA;
00114 case GL_RGBA16F_ARB: return GL_RGBA;
00115 case GL_RGB16F_ARB: return GL_RGB;
00116 case GL_ALPHA16F_ARB: return GL_ALPHA;
00117 case GL_INTENSITY16F_ARB: return GL_INTENSITY;
00118 case GL_LUMINANCE16F_ARB: return GL_LUMINANCE;
00119 case GL_LUMINANCE_ALPHA16F_ARB: return GL_LUMINANCE_ALPHA;
00120
00121 default:
00122 return 0;
00123 }
00124 }
00125
00126 GLint determineDataType(GLint internalformat)
00127 {
00128 switch (internalformat) {
00129 case GL_RGBA32F_ARB:
00130 case GL_RGB32F_ARB:
00131 case GL_ALPHA32F_ARB:
00132 case GL_INTENSITY32F_ARB:
00133 case GL_LUMINANCE32F_ARB:
00134 case GL_LUMINANCE_ALPHA32F_ARB:
00135 return GL_FLOAT;
00136 case GL_RGBA16F_ARB:
00137 case GL_RGB16F_ARB:
00138 case GL_ALPHA16F_ARB:
00139 case GL_INTENSITY16F_ARB:
00140 case GL_LUMINANCE16F_ARB:
00141 case GL_LUMINANCE_ALPHA16F_ARB:
00142 return GL_HALF_FLOAT_ARB;
00143
00144 default:
00145 return GL_UNSIGNED_BYTE;
00146 }
00147 }
00148
00149 }
00150
00151 namespace KGLLib
00152 {
00153
00154
00155 TextureBase::TextureBase()
00156 {
00157 mValid = false;
00158 mGLId = 0;
00159 }
00160
00161 TextureBase::TextureBase(const QString& name)
00162 {
00163 mValid = false;
00164 mGLId = 0;
00165 setName(name);
00166 }
00167
00168 TextureBase::~TextureBase()
00169 {
00170 if (mGLId) {
00171 glDeleteTextures(1, &mGLId);
00172 }
00173 }
00174
00175 void TextureBase::bind() const
00176 {
00177 renderer->bindTexture(this);
00178 }
00179
00180 void TextureBase::unbind() const
00181 {
00182 renderer->unbindTexture(this);
00183 }
00184
00185 void TextureBase::enable(bool _bind) const
00186 {
00187 renderer->enableTexture(this);
00188 if (_bind) {
00189 bind();
00190 }
00191 }
00192
00193 void TextureBase::disable(bool _unbind) const
00194 {
00195 renderer->disableTexture(this);
00196 if (_unbind) {
00197 unbind();
00198 }
00199 }
00200
00201 void TextureBase::setFilter(GLenum filter)
00202 {
00203 GLenum magfilter = (filter == GL_NEAREST) ? GL_NEAREST : GL_LINEAR;
00204 glTexParameteri(glTarget(), GL_TEXTURE_MAG_FILTER, magfilter);
00205 glTexParameteri(glTarget(), GL_TEXTURE_MIN_FILTER, filter);
00206 }
00207
00208 void TextureBase::setWrapMode(GLenum coordinate, GLenum mode)
00209 {
00210 glTexParameteri(glTarget(), coordinate, mode);
00211 }
00212
00213 void TextureBase::setName(const QString& name)
00214 {
00215 mName = name;
00216 }
00217
00218 QString TextureBase::debugString() const
00219 {
00220 if (name().isEmpty()) {
00221 return QString("<Texture id %1>").arg(glId());
00222 } else {
00223 return QString("<Texture name %1>").arg(name());
00224 }
00225 }
00226
00227
00228
00229 Texture::Texture(int width, int height, GLint internalformat, GLint format)
00230 {
00231 mValid = init(width, height, internalformat, format);
00232 }
00233
00234 Texture::Texture(const QImage& img, GLenum filter)
00235 {
00236 mValid = init(img, filter);
00237 }
00238
00239 Texture::Texture(const QPixmap& pix, GLenum filter)
00240 {
00241 mValid = init(pix.toImage(), filter);
00242 }
00243
00244 Texture::Texture(const QString& filename, GLenum filter) : TextureBase(filename)
00245 {
00246 mValid = init(filename, filter);
00247 }
00248
00249 Texture::~Texture()
00250 {
00251 }
00252
00253 bool Texture::init(int width, int height, GLint internalformat, GLint format)
00254 {
00255 mWidth = width;
00256 mHeight = height;
00257
00258 glGenTextures(1, &mGLId);
00259 bind();
00260 setFilter(GL_LINEAR);
00261
00262 if (!format) {
00263 format = determineFormat(internalformat);
00264 if (!format) {
00265 qCritical() << "Texture::init(): Couldn't determine matching format for internalformat" << internalformat;
00266 return false;
00267 }
00268 }
00269 mInternalFormat = internalformat;
00270 mFormat = format;
00271 glTexImage2D( glTarget(), 0, mInternalFormat, mWidth, mHeight, 0,
00272 mFormat, determineDataType(mInternalFormat), 0);
00273
00274 checkGLError(QString("Texture::init(%1, %2)").arg(mWidth).arg(mHeight));
00275
00276 return true;
00277 }
00278
00279 bool Texture::init(const QImage& img, GLenum filter)
00280 {
00281 if (img.isNull()) {
00282 qWarning() << "Texture::init(): NULL QImage!";
00283 return false;
00284 }
00285 if (!init(img.width(), img.height())) {
00286 return false;
00287 }
00288
00289 setFilter(filter);
00290 QImage glimg = convertToGLFormat( img );
00291
00292
00293 glTexParameteri(glTarget(), GL_GENERATE_MIPMAP, GL_TRUE);
00294 glTexImage2D( glTarget(), 0, mInternalFormat, glimg.width(), glimg.height(), 0,
00295 mFormat, GL_UNSIGNED_BYTE, glimg.bits());
00296 checkGLError("Texture::init(Qimage)");
00297
00298 return true;
00299 }
00300
00301 bool Texture::init(const QString& filename, GLenum filter)
00302 {
00303 QImage img(filename);
00304 if (img.isNull()) {
00305 qWarning() << "Texture::init(): failed to load from file" << filename;
00306 return false;
00307 }
00308 return init(img, filter);
00309 }
00310
00311 void Texture::setWrapMode(GLenum mode)
00312 {
00313 TextureBase::setWrapMode(GL_TEXTURE_WRAP_S, mode);
00314 TextureBase::setWrapMode(GL_TEXTURE_WRAP_T, mode);
00315 }
00316
00317 QImage Texture::convertToGLFormat(const QImage& img) const
00318 {
00319
00320 QImage res = img.convertToFormat(QImage::Format_ARGB32);
00321 res = res.mirrored();
00322
00323 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
00324
00325 for (int i=0; i < res.height(); i++) {
00326 uint *p = (uint*)res.scanLine(i);
00327 uint *end = p + res.width();
00328 while (p < end) {
00329 *p = (*p << 8) | ((*p >> 24) & 0xFF);
00330 p++;
00331 }
00332 }
00333 } else {
00334
00335 res = res.rgbSwapped();
00336 }
00337 return res;
00338 }
00339
00340
00341
00342
00343 Texture3D::~Texture3D()
00344 {
00345 }
00346
00347 void Texture3D::setWrapMode(GLenum mode)
00348 {
00349 TextureBase::setWrapMode(GL_TEXTURE_WRAP_S, mode);
00350 TextureBase::setWrapMode(GL_TEXTURE_WRAP_T, mode);
00351 TextureBase::setWrapMode(GL_TEXTURE_WRAP_R, mode);
00352 }
00353
00354 }
00355