ПрограммированиеФорумГрафика

Не отображаются текстуры без GPU в OpenGL

#0
2:31, 4 июня 2012

Пишу приложение для 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?

#1
8:09, 4 июня 2012

glGenTextures() где?

#2
8:54, 4 июня 2012

На эмуле могут быть проблемы с доступом к ресурсам. Возможно просто файл найти неможет. И проследи чтобы текстуры была POT. NPOT андройд очень нелюбит.

#3
9:06, 4 июня 2012

На эмуляторе не работает половина собственных примеров из SDK, так что я бы не парился.

#4
17:22, 4 июня 2012

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 это же приложение работает корректно. Теоретически это должно зависеть от наличия графического процессора?

#5
15:31, 5 июня 2012

После нескольких дней проб и ошибок, оказалось что разница работы была в функции glGetIntegerv(GL_VIEWPORT, params); В одном случае она возвращала корректные значения, а в другом мусор. Будем надеется, что другие функции будут работать корректно и не зависеть от платформы.

ПрограммированиеФорумГрафика

Тема в архиве.