Пишу приложение для android на c++ с использование OpenGL. Все время тестировал на трубке и все работало. Тут реши попробовать на эмуляторе и вдруг перестали отображаться текстуры.
Такие функции у меня в инициализации:
glEnable(GL_BLEND); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable( GL_DEPTH_TEST);
а так создаются текстуры:
glBindTexture(GL_TEXTURE_2D, _textures[ch]); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D( GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, invertedPixmap);
Решил попробовать включить на эмуляторе поддержку GPU и о чудо, все заработало. Подскажите, получиться ли выводить текстуры с альфаканалами на устройствах без GPU?
glGenTextures() где?
На эмуле могут быть проблемы с доступом к ресурсам. Возможно просто файл найти неможет. И проследи чтобы текстуры была POT. NPOT андройд очень нелюбит.
На эмуляторе не работает половина собственных примеров из SDK, так что я бы не парился.
glGenTextures() есть, вот весь код для загрузки текстур:
void GLFont::init(const string& fileName, int size) { // Инициализация библиотеки FreeType. FT_Library library; if ( FT_Init_FreeType( &library) != 0) { throw runtime_error( "Could not initialize FreeType2 library."); } // Объект для хранения шрифта. FT_Face face; // Загрузим шрифт из файла. if ( FT_New_Face( library, fileName.c_str( ), 0, &face) != 0) { throw runtime_error( "Could not load font file."); } FT_Set_Char_Size( face, size << 6, size << 6, 96, 96); // Выделяем память для всех текстур //deleteTextures(); size_t nChars = _fontCodes.back( ) + 1; _textures.resize( nChars); glGenTextures( nChars, &_textures[0]); GLint params[4]; glGetIntegerv( GL_VIEWPORT, params); GLfloat screenSize = max( params[2], params[3]) / 2.0f; _entries.resize( nChars); vector<unsigned>::const_iterator charsIt; for ( charsIt = _fontCodes.begin( ); charsIt < _fontCodes.end( ); charsIt += 2) { for ( unsigned ch = *charsIt; ch <= *( charsIt + 1); ++ch) { // Look up the character in the font file. size_t charIndex = FT_Get_Char_Index( face, ch); // Render the current glyph. FT_Load_Glyph( face, charIndex, FT_LOAD_DEFAULT); FT_Render_Glyph( face->glyph, FT_RENDER_MODE_NORMAL); int width, height; GLubyte* invertedPixmap = invertPixmap( face->glyph->bitmap, width, height); glBindTexture( GL_TEXTURE_2D, _textures[ch]); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D( GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, invertedPixmap); GlyphEntry entry; entry.leftBearing = ( GLfloat)face->glyph->bitmap_left / screenSize; entry.bottomBearing = ( GLfloat)( face->glyph->bitmap_top - face->glyph->bitmap.rows) / screenSize; entry.width = ( GLfloat)face->glyph->bitmap.width / screenSize; entry.height = ( GLfloat)face->glyph->bitmap.rows / screenSize; entry.x = ( GLfloat)face->glyph->bitmap.width / width; entry.y = ( GLfloat)face->glyph->bitmap.rows / height; entry.advanceX = ( GLfloat)( face->glyph->advance.x >> 6) / screenSize; entry.advanceY = ( GLfloat)( face->glyph->advance.y >> 6) / screenSize; _entries[ch] = entry; delete [] invertedPixmap; } } // Уничтожим шрифт. FT_Done_Face( face); // Не нужна и библиотека. FT_Done_FreeType( library); }
Я использую POT, вот функции для конвертации:
inline int GLFont::nearestPowerCeil(int a) { int rVal = 1; while ( rVal < a) rVal <<= 1; return rVal; } GLubyte* GLFont::invertPixmap( const FT_Bitmap& bitmap, int& width, int& height) { width = nearestPowerCeil( bitmap.width); height = nearestPowerCeil( bitmap.rows); GLubyte* inverse = new GLubyte[2 * width * height]; memset( inverse, 0, width * height * 2); GLubyte* inverse_ptr = inverse; for ( int r = 0; r < bitmap.rows; r++) { GLubyte* bitmap_ptr = &bitmap.buffer[bitmap.pitch * ( bitmap.rows - r - 1)]; for ( int p = 0; p < bitmap.width; p++) { *inverse_ptr++ = 0xff; *inverse_ptr++ = *bitmap_ptr++; } inverse_ptr += 2 * ( width - bitmap.pitch); } return inverse; }
Из файла текстуры загружаются, я проверял отладчиком. Сегодня взял старую трубку с андроидом 2.1, на которой не должно быть GPU. На ней тоже не отображаются. На дорогой трубке с андроид 2.3 и наличием GPU это же приложение работает корректно. Теоретически это должно зависеть от наличия графического процессора?
После нескольких дней проб и ошибок, оказалось что разница работы была в функции glGetIntegerv(GL_VIEWPORT, params); В одном случае она возвращала корректные значения, а в другом мусор. Будем надеется, что другие функции будут работать корректно и не зависеть от платформы.
Тема в архиве.