00001 #include "gui_gl_material.hpp" 00002 #include "gui_gl_manager.hpp" 00003 #include "gui_out.hpp" 00004 00005 #include <utils_string.hpp> 00006 #include <GL/gl.h> 00007 #include <cmath> 00008 00009 namespace gui { 00010 namespace gl 00011 { 00012 bool material::ONLY_POWER_OF_TWO = true; 00013 uint material::MAXIMUM_SIZE = 128; 00014 00015 material::material(uint uiWidth, uint uiHeight, wrap mWrap, filter mFilter, bool bGPUOnly) : 00016 mType_(TYPE_TEXTURE) 00017 { 00018 pTexData_ = utils::refptr<texture_data>(new texture_data()); 00019 pTexData_->uiWidth_ = uiWidth; 00020 pTexData_->uiHeight_ = uiHeight; 00021 pTexData_->mWrap_ = mWrap; 00022 pTexData_->mFilter_ = mFilter; 00023 00024 if (ONLY_POWER_OF_TWO) 00025 { 00026 pTexData_->uiRealWidth_ = pow(2.0f, ceil(log2(uiWidth))); 00027 pTexData_->uiRealHeight_ = pow(2.0f, ceil(log2(uiHeight))); 00028 } 00029 else 00030 { 00031 pTexData_->uiRealWidth_ = uiWidth; 00032 pTexData_->uiRealHeight_ = uiHeight; 00033 } 00034 00035 if (pTexData_->uiRealWidth_ > MAXIMUM_SIZE || pTexData_->uiRealHeight_ > MAXIMUM_SIZE) 00036 { 00037 throw gui::exception("gui::gl::material", "Texture dimensions not supported by graphics card : ("+ 00038 utils::to_string(pTexData_->uiRealWidth_)+" x "+ 00039 utils::to_string(pTexData_->uiRealHeight_)+")." 00040 ); 00041 } 00042 00043 GLint iPreviousID; 00044 glGetIntegerv(GL_TEXTURE_BINDING_2D, &iPreviousID); 00045 00046 glGenTextures(1, &pTexData_->uiTextureHandle_); 00047 00048 glBindTexture(GL_TEXTURE_2D, pTexData_->uiTextureHandle_); 00049 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 00050 pTexData_->uiRealWidth_, pTexData_->uiRealHeight_, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr 00051 ); 00052 00053 switch (mWrap) 00054 { 00055 case CLAMP : 00056 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); 00057 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); 00058 break; 00059 case REPEAT : 00060 default : 00061 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 00062 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 00063 break; 00064 } 00065 switch (mFilter) 00066 { 00067 case LINEAR : 00068 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 00069 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 00070 break; 00071 case NONE : 00072 default : 00073 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 00074 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 00075 break; 00076 } 00077 00078 glBindTexture(GL_TEXTURE_2D, iPreviousID); 00079 00080 if (!bGPUOnly) 00081 pTexData_->pData_.resize(uiWidth*uiHeight); 00082 } 00083 00084 material::material(const color& mColor) : mType_(TYPE_COLOR) 00085 { 00086 pColData_ = utils::refptr<color_data>(new color_data()); 00087 pColData_->mColor_ = mColor; 00088 } 00089 00090 material::~material() 00091 { 00092 switch (mType_) 00093 { 00094 case TYPE_TEXTURE : 00095 glDeleteTextures(1, &pTexData_->uiTextureHandle_); break; 00096 case TYPE_COLOR : 00097 break; 00098 } 00099 } 00100 00101 material::type material::get_type() const 00102 { 00103 return mType_; 00104 } 00105 00106 color material::get_color() const 00107 { 00108 return pColData_->mColor_; 00109 } 00110 00111 void material::set_wrap(wrap mWrap) 00112 { 00113 GLint iPreviousID; 00114 glGetIntegerv(GL_TEXTURE_BINDING_2D, &iPreviousID); 00115 glBindTexture(GL_TEXTURE_2D, pTexData_->uiTextureHandle_); 00116 00117 switch (mWrap) 00118 { 00119 case CLAMP : 00120 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); 00121 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); 00122 break; 00123 case REPEAT : 00124 default : 00125 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 00126 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 00127 break; 00128 } 00129 00130 glBindTexture(GL_TEXTURE_2D, iPreviousID); 00131 } 00132 00133 void material::set_filter(filter mFilter) 00134 { 00135 GLint iPreviousID; 00136 glGetIntegerv(GL_TEXTURE_BINDING_2D, &iPreviousID); 00137 glBindTexture(GL_TEXTURE_2D, pTexData_->uiTextureHandle_); 00138 00139 switch (mFilter) 00140 { 00141 case LINEAR : 00142 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 00143 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 00144 break; 00145 case NONE : 00146 default : 00147 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 00148 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 00149 break; 00150 } 00151 00152 glBindTexture(GL_TEXTURE_2D, iPreviousID); 00153 } 00154 00155 void material::bind() const 00156 { 00157 glBindTexture(GL_TEXTURE_2D, pTexData_->uiTextureHandle_); 00158 } 00159 00160 const std::vector<ub32color>& material::get_data() const 00161 { 00162 return pTexData_->pData_; 00163 } 00164 00165 std::vector<ub32color>& material::get_data() 00166 { 00167 return pTexData_->pData_; 00168 } 00169 00170 void material::set_pixel(uint x, uint y, const ub32color& mColor) 00171 { 00172 pTexData_->pData_[x + y*pTexData_->uiWidth_] = mColor; 00173 } 00174 00175 const ub32color& material::get_pixel(uint x, uint y) const 00176 { 00177 return pTexData_->pData_[x + y*pTexData_->uiWidth_]; 00178 } 00179 00180 ub32color& material::get_pixel(uint x, uint y) 00181 { 00182 return pTexData_->pData_[x + y*pTexData_->uiWidth_]; 00183 } 00184 00185 void material::premultiply_alpha() 00186 { 00187 uint imax = pTexData_->uiWidth_*pTexData_->uiHeight_; 00188 for (uint i = 0; i < imax; ++i) 00189 { 00190 ub32color& c = pTexData_->pData_[i]; 00191 float a = c.a/255.0f; 00192 c.r *= a; 00193 c.g *= a; 00194 c.b *= a; 00195 } 00196 } 00197 00198 float material::get_width() const 00199 { 00200 switch (mType_) 00201 { 00202 case TYPE_TEXTURE : 00203 return pTexData_->uiWidth_; 00204 case TYPE_COLOR : 00205 return 1.0f; 00206 } 00207 00208 return 1.0f; 00209 } 00210 00211 float material::get_height() const 00212 { 00213 switch (mType_) 00214 { 00215 case TYPE_TEXTURE : 00216 return pTexData_->uiHeight_; 00217 case TYPE_COLOR : 00218 return 1.0f; 00219 } 00220 00221 return 1.0f; 00222 } 00223 00224 float material::get_real_width() const 00225 { 00226 switch (mType_) 00227 { 00228 case TYPE_TEXTURE : 00229 return pTexData_->uiRealWidth_; 00230 case TYPE_COLOR : 00231 return 1.0f; 00232 } 00233 00234 return 1.0f; 00235 } 00236 00237 float material::get_real_height() const 00238 { 00239 switch (mType_) 00240 { 00241 case TYPE_TEXTURE : 00242 return pTexData_->uiRealHeight_; 00243 case TYPE_COLOR : 00244 return 1.0f; 00245 } 00246 00247 return 1.0f; 00248 } 00249 00250 bool material::set_dimensions(uint uiWidth, uint uiHeight) 00251 { 00252 if (uiWidth > pTexData_->uiRealWidth_ || uiHeight > pTexData_->uiRealHeight_) 00253 { 00254 00255 utils::refptr<texture_data> pOldData = pTexData_; 00256 pTexData_ = utils::refptr<texture_data>(new texture_data()); 00257 pTexData_->uiWidth_ = uiWidth; 00258 pTexData_->uiHeight_ = uiHeight; 00259 pTexData_->mWrap_ = pOldData->mWrap_; 00260 pTexData_->mFilter_ = pOldData->mFilter_; 00261 00262 if (ONLY_POWER_OF_TWO) 00263 { 00264 pTexData_->uiRealWidth_ = pow(2.0f, ceil(log2(uiWidth))); 00265 pTexData_->uiRealHeight_ = pow(2.0f, ceil(log2(uiHeight))); 00266 } 00267 else 00268 { 00269 pTexData_->uiRealWidth_ = uiWidth; 00270 pTexData_->uiRealHeight_ = uiHeight; 00271 } 00272 00273 if (pTexData_->uiRealWidth_ > MAXIMUM_SIZE || pTexData_->uiRealHeight_ > MAXIMUM_SIZE) 00274 { 00275 pTexData_ = pOldData; 00276 return false; 00277 } 00278 00279 glDeleteTextures(1, &pTexData_->uiTextureHandle_); 00280 00281 GLint iPreviousID; 00282 glGetIntegerv(GL_TEXTURE_BINDING_2D, &iPreviousID); 00283 00284 glGenTextures(1, &pTexData_->uiTextureHandle_); 00285 00286 glBindTexture(GL_TEXTURE_2D, pTexData_->uiTextureHandle_); 00287 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 00288 pTexData_->uiRealWidth_, pTexData_->uiRealHeight_, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr 00289 ); 00290 00291 switch (pTexData_->mWrap_) 00292 { 00293 case CLAMP : 00294 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); 00295 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); 00296 break; 00297 case REPEAT : 00298 default : 00299 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 00300 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 00301 break; 00302 } 00303 switch (pTexData_->mFilter_) 00304 { 00305 case LINEAR : 00306 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 00307 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 00308 break; 00309 case NONE : 00310 default : 00311 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 00312 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 00313 break; 00314 } 00315 00316 glBindTexture(GL_TEXTURE_2D, iPreviousID); 00317 return true; 00318 } 00319 else 00320 { 00321 pTexData_->uiWidth_ = uiWidth; 00322 pTexData_->uiHeight_ = uiHeight; 00323 return false; 00324 } 00325 } 00326 00327 void material::update_texture() 00328 { 00329 GLint iPreviousID; 00330 glGetIntegerv(GL_TEXTURE_BINDING_2D, &iPreviousID); 00331 00332 glBindTexture(GL_TEXTURE_2D, pTexData_->uiTextureHandle_); 00333 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, pTexData_->uiWidth_, pTexData_->uiHeight_, 00334 GL_RGBA, GL_UNSIGNED_BYTE, pTexData_->pData_.data() 00335 ); 00336 00337 glBindTexture(GL_TEXTURE_2D, iPreviousID); 00338 } 00339 00340 void material::clear_cache_data_() 00341 { 00342 pTexData_->pData_.clear(); 00343 } 00344 00345 uint material::get_handle_() 00346 { 00347 return pTexData_->uiTextureHandle_; 00348 } 00349 00350 void material::check_availability() 00351 { 00352 ONLY_POWER_OF_TWO = !manager::is_gl_extension_supported("GL_ARB_texture_non_power_of_two"); 00353 gui::out << "Note : non power of two textures are " << (ONLY_POWER_OF_TWO ? "not " : "") << "supported." << std::endl; 00354 int max; 00355 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max); 00356 MAXIMUM_SIZE = max; 00357 gui::out << "Note : maximum texture size is " << MAXIMUM_SIZE << "." << std::endl; 00358 } 00359 } 00360 }