PBOとかそういうレベルでは・・・
そっかPBOを使おうが使わなかろうが、pngからの読み込みルーチンで時間がかかってるのか。
PBOでの高速化なんて全然効かないわけです。わざわビデオメモリー使ってPBOを使う意味ないですね。
ということで読み込みルーチンはシンプルにしておこう。ということでシンプルになったpng読み込みコード。
簡単なBMPの読み込みが800行超えそうなことを考えると、ライブラリがあるということはなんとも楽チンですね。
class LoadPNG { private: png_structp png_; png_infop info_; png_infop endinfo_; png_uint_32 width_; // 幅 png_uint_32 width_align_; // 幅 png_uint_32 height_; // 高さ png_uint_32 height_align_; // 高さ int bpp_; // 1pixelのbit数 int colortype_; // ピクセルの表すデータの種類 png_colorp palette_; // パレット情報 int palette_number_; // パレットの数 GLuint id_; // テクスチャID public: bool load(Reader& reader) { if (loadInit() == false) { return false; } // 読み込み関数のセット png_set_read_fn(png_, &reader, readPNGData); if (loadHeader() == false) { return false; } if (loadImage() == false) { return false; } png_read_end(png_, info_); png_destroy_read_struct(&png_, &info_, &endinfo_); return true; } public: TextureInfo textureInfo() const { return TextureInfo(id_, 0, 0, (float)width_ / width_align_, (float)height_ / height_align_); } protected: //-------------------------------------------------------------------------------- bool loadInit() { png_ = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); info_ = png_create_info_struct(png_); if (info_ == NULL) { png_destroy_read_struct(&png_, NULL, NULL); return false; } endinfo_ = png_create_info_struct(png_); if (endinfo_ == NULL) { png_destroy_read_struct(&png_, &info_, NULL); return false; } if (setjmp(png_jmpbuf(png_))) { png_destroy_read_struct(&png_, &info_, &endinfo_); return false; } return true; } //-------------------------------------------------------------------------------- bool loadHeader() { // ヘッダ情報を読み込む png_read_info(png_, info_); png_get_IHDR(png_, info_, &width_, &height_, &bpp_, &colortype_, NULL, NULL, NULL); // 2のべき乗に合わせる width_align_ = power_of_two(width_); height_align_ = power_of_two(height_); // 入力データの変換ルール設定 switch (colortype_) { case PNG_COLOR_TYPE_PALETTE: png_set_palette_to_rgb(png_); // 以後RGBと同じように扱う colortype_ = PNG_COLOR_TYPE_RGB; case PNG_COLOR_TYPE_RGB: case PNG_COLOR_TYPE_RGB_ALPHA: png_set_bgr(png_); break; case PNG_COLOR_TYPE_GRAY: if (bpp_ < 8) { png_set_gray_1_2_4_to_8(png_); } break; default: ; } // 透明色がある場合にはALPHAレイヤを追加する if (png_get_valid(png_, info_, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png_); colortype_ |= PNG_COLOR_MASK_ALPHA; } // 16bitは8bitに縮小 if (bpp_ == 16) { png_set_strip_16(png_); } return true; } //-------------------------------------------------------------------------------- /** イメージの読み取り */ bool loadImage() { // テクスチャを作成 glGenTextures(1, &id_); glBindTexture(GL_TEXTURE_2D, id_); // テクスチャへイメージの読み込み switch(colortype_) { case PNG_COLOR_TYPE_GRAY: loadBit(GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, 1); break; case PNG_COLOR_TYPE_RGB: case PNG_COLOR_TYPE_PALETTE: loadBit(GL_RGB, GL_BGR, GL_UNSIGNED_BYTE, 3); break; case PNG_COLOR_TYPE_GRAY_ALPHA: loadBit(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 2); break; case PNG_COLOR_TYPE_RGB_ALPHA: loadBit(GL_RGBA, GL_BGRA, GL_UNSIGNED_BYTE, 4); break; default: return false; } // テクスチャの設定 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); return true; } //-------------------------------------------------------------------------------- /** イメージの読み取り */ void loadBit(GLenum internal, GLenum upload, GLenum type, int bpp) { glTexImage2D(GL_TEXTURE_2D, 0, internal, width_align_, height_align_, 0, upload, type, NULL); unsigned char* buffer = new unsigned char[width_ * bpp]; for (int y = 0; y < height_; ++y) { png_read_row(png_, buffer, NULL); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, y, width_, 1, upload, type, (const GLvoid*)buffer); } delete [] buffer; } }