speedup sprite loading
This commit is contained in:
parent
4584ce5b86
commit
edeee80631
|
@ -118,22 +118,27 @@ void Texture::setSmooth(bool smooth)
|
||||||
|
|
||||||
std::vector<uint8> Texture::getPixels()
|
std::vector<uint8> Texture::getPixels()
|
||||||
{
|
{
|
||||||
// hack to copy pixels from opengl memory
|
|
||||||
FrameBufferPtr fb(new FrameBuffer(m_size));
|
|
||||||
std::vector<uint8> pixels(m_size.area()*4, 0);
|
std::vector<uint8> pixels(m_size.area()*4, 0);
|
||||||
|
#ifdef OPENGL_ES
|
||||||
|
// hack to copy pixels from opengl memory in opengl es
|
||||||
|
// NOTE: this can be slow, but its the only way to get pixels from a texture in OpenGL ES
|
||||||
|
FrameBufferPtr fb(new FrameBuffer(m_size));
|
||||||
fb->bind();
|
fb->bind();
|
||||||
g_painter.saveAndResetState();
|
g_painter.saveAndResetState();
|
||||||
g_painter.drawTexturedRect(Rect(0,0,m_size), shared_from_this());
|
g_painter.drawTexturedRect(Rect(0,0,m_size), shared_from_this());
|
||||||
glReadPixels(0, 0, m_size.width(), m_size.height(), GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]);
|
glReadPixels(0, 0, m_size.width(), m_size.height(), GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]);
|
||||||
g_painter.restoreSavedState();
|
g_painter.restoreSavedState();
|
||||||
fb->release();
|
fb->release();
|
||||||
|
#else
|
||||||
|
// copy pixels from opengl memory
|
||||||
|
glBindTexture(GL_TEXTURE_2D, m_textureId);
|
||||||
|
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]);
|
||||||
|
#endif
|
||||||
return pixels;
|
return pixels;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture::generateBilinearMipmaps()
|
void Texture::generateBilinearMipmaps(std::vector<uint8> inPixels)
|
||||||
{
|
{
|
||||||
std::vector<uint8> inPixels = getPixels();
|
|
||||||
|
|
||||||
bind();
|
bind();
|
||||||
|
|
||||||
if(!m_useMipmaps) {
|
if(!m_useMipmaps) {
|
||||||
|
@ -188,7 +193,7 @@ void Texture::generateBilinearMipmaps()
|
||||||
if(inSize.width() == 1 || inSize.height() == 1)
|
if(inSize.width() == 1 || inSize.height() == 1)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
inPixels = outPixels;
|
inPixels = std::move(outPixels);
|
||||||
inSize /= 2;
|
inSize /= 2;
|
||||||
outSize /= 2;
|
outSize /= 2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,10 @@ public:
|
||||||
void bind() { glBindTexture(GL_TEXTURE_2D, m_textureId); }
|
void bind() { glBindTexture(GL_TEXTURE_2D, m_textureId); }
|
||||||
|
|
||||||
void generateMipmaps();
|
void generateMipmaps();
|
||||||
void generateBilinearMipmaps();
|
|
||||||
|
// generate bilinear mipmaps optimized for alpha textures
|
||||||
|
void generateBilinearMipmaps(std::vector<uint8> inPixels);
|
||||||
|
|
||||||
void setSmooth(bool smooth);
|
void setSmooth(bool smooth);
|
||||||
GLuint getId() { return m_textureId; }
|
GLuint getId() { return m_textureId; }
|
||||||
|
|
||||||
|
|
|
@ -77,8 +77,10 @@ void Item::setPosition(const Position& position)
|
||||||
Thing::setPosition(position);
|
Thing::setPosition(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Item::setCount(uint8 count)
|
void Item::setCount(int count)
|
||||||
{
|
{
|
||||||
|
count = std::max(std::min(count, 255), 0);
|
||||||
|
|
||||||
if(isStackable() && getNumPatternsX() == 4 && getNumPatternsY() == 2) {
|
if(isStackable() && getNumPatternsX() == 4 && getNumPatternsY() == 2) {
|
||||||
if(count < 5) {
|
if(count < 5) {
|
||||||
m_xPattern = count-1;
|
m_xPattern = count-1;
|
||||||
|
|
|
@ -36,9 +36,9 @@ public:
|
||||||
void draw(const Point& dest, float scaleFactor);
|
void draw(const Point& dest, float scaleFactor);
|
||||||
|
|
||||||
void setPosition(const Position &position);
|
void setPosition(const Position &position);
|
||||||
void setCount(uint8 data);
|
void setCount(int count);
|
||||||
|
|
||||||
uint8 getCount() { return m_count; }
|
int getCount() { return m_count; }
|
||||||
|
|
||||||
ItemPtr asItem() { return std::static_pointer_cast<Item>(shared_from_this()); }
|
ItemPtr asItem() { return std::static_pointer_cast<Item>(shared_from_this()); }
|
||||||
|
|
||||||
|
|
|
@ -153,9 +153,14 @@ void MapView::draw(const Rect& rect)
|
||||||
animatedText->draw(p, rect);
|
animatedText->draw(p, rect);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// draw a arrow for position the center in non near views
|
// draw a cross in the center instead of our creature
|
||||||
g_painter.setColor(Fw::red);
|
Rect vRect(0, 0, 2, 10);
|
||||||
g_painter.drawFilledRect(Rect(rect.center(), 4, 4));
|
Rect hRect(0, 0, 10, 2);
|
||||||
|
vRect.moveCenter(rect.center());
|
||||||
|
hRect.moveCenter(rect.center());
|
||||||
|
g_painter.setColor(Fw::white);
|
||||||
|
g_painter.drawFilledRect(vRect);
|
||||||
|
g_painter.drawFilledRect(hRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -405,18 +410,11 @@ void MapView::setVisibleDimension(const Size& visibleDimension)
|
||||||
viewRange = NEAR_VIEW;
|
viewRange = NEAR_VIEW;
|
||||||
else if(tileSize >= 16 && visibleDimension.area() <= MID_VIEW_AREA)
|
else if(tileSize >= 16 && visibleDimension.area() <= MID_VIEW_AREA)
|
||||||
viewRange = MID_VIEW;
|
viewRange = MID_VIEW;
|
||||||
else if(tileSize >= 8)
|
else if(tileSize >= 8 && visibleDimension.area() <= FAR_VIEW_AREA)
|
||||||
viewRange = FAR_VIEW;
|
viewRange = FAR_VIEW;
|
||||||
else
|
else
|
||||||
viewRange = HUGE_VIEW;
|
viewRange = HUGE_VIEW;
|
||||||
|
|
||||||
if(m_viewRange != viewRange) {
|
|
||||||
if(viewRange == NEAR_VIEW) dump << "near view";
|
|
||||||
else if(viewRange == MID_VIEW) dump << "mid view";
|
|
||||||
else if(viewRange == FAR_VIEW) dump << "far view";
|
|
||||||
else if(viewRange == HUGE_VIEW) dump << "huge view";
|
|
||||||
}
|
|
||||||
|
|
||||||
// draw actually more than what is needed to avoid massive recalculations on far views
|
// draw actually more than what is needed to avoid massive recalculations on far views
|
||||||
if(viewRange >= FAR_VIEW) {
|
if(viewRange >= FAR_VIEW) {
|
||||||
Size oldDimension = drawDimension;
|
Size oldDimension = drawDimension;
|
||||||
|
|
|
@ -38,7 +38,8 @@ class MapView : public LuaObject
|
||||||
DEFAULT_FRAMBUFFER_HEIGHT = 1440,
|
DEFAULT_FRAMBUFFER_HEIGHT = 1440,
|
||||||
|
|
||||||
NEAR_VIEW_AREA = 32*32,
|
NEAR_VIEW_AREA = 32*32,
|
||||||
MID_VIEW_AREA = 96*96,
|
MID_VIEW_AREA = 64*64,
|
||||||
|
FAR_VIEW_AREA = 128*128,
|
||||||
MAX_TILE_UPDATES = NEAR_VIEW_AREA*7
|
MAX_TILE_UPDATES = NEAR_VIEW_AREA*7
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
#include "spritemanager.h"
|
#include "spritemanager.h"
|
||||||
#include <framework/core/resourcemanager.h>
|
#include <framework/core/resourcemanager.h>
|
||||||
|
#include <framework/core/eventdispatcher.h>
|
||||||
#include <framework/graphics/graphics.h>
|
#include <framework/graphics/graphics.h>
|
||||||
|
|
||||||
SpriteManager g_sprites;
|
SpriteManager g_sprites;
|
||||||
|
@ -38,6 +39,7 @@ bool SpriteManager::load(const std::string& file)
|
||||||
g_resources.loadFile(file, m_fin);
|
g_resources.loadFile(file, m_fin);
|
||||||
m_signature = Fw::getU32(m_fin);
|
m_signature = Fw::getU32(m_fin);
|
||||||
m_spritesCount = Fw::getU16(m_fin);
|
m_spritesCount = Fw::getU16(m_fin);
|
||||||
|
dump << m_spritesCount;
|
||||||
m_sprites.resize(m_spritesCount);
|
m_sprites.resize(m_spritesCount);
|
||||||
m_loaded = true;
|
m_loaded = true;
|
||||||
return true;
|
return true;
|
||||||
|
@ -54,6 +56,21 @@ void SpriteManager::unload()
|
||||||
m_signature = 0;
|
m_signature = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SpriteManager::preloadSprites()
|
||||||
|
{
|
||||||
|
// preload every 100 sprites, periodically
|
||||||
|
const int burst = 50;
|
||||||
|
const int interval = 10;
|
||||||
|
auto preload = [this](int start) {
|
||||||
|
for(int i=start;i<start+burst && i<=m_spritesCount;++i) {
|
||||||
|
loadSpriteTexture(i);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for(int i=1;i<=m_spritesCount;i+=burst)
|
||||||
|
g_dispatcher.scheduleEvent(std::bind(preload, i), (i/burst) * interval);
|
||||||
|
}
|
||||||
|
|
||||||
TexturePtr SpriteManager::loadSpriteTexture(int id)
|
TexturePtr SpriteManager::loadSpriteTexture(int id)
|
||||||
{
|
{
|
||||||
m_fin.seekg(((id-1) * 4) + 6, std::ios_base::beg);
|
m_fin.seekg(((id-1) * 4) + 6, std::ios_base::beg);
|
||||||
|
@ -74,7 +91,7 @@ TexturePtr SpriteManager::loadSpriteTexture(int id)
|
||||||
|
|
||||||
uint16 pixelDataSize = Fw::getU16(m_fin);
|
uint16 pixelDataSize = Fw::getU16(m_fin);
|
||||||
|
|
||||||
uchar pixels[4096];
|
static std::vector<uint8> pixels(4096);
|
||||||
int writePos = 0;
|
int writePos = 0;
|
||||||
int read = 0;
|
int read = 0;
|
||||||
|
|
||||||
|
@ -116,9 +133,9 @@ TexturePtr SpriteManager::loadSpriteTexture(int id)
|
||||||
writePos += 4;
|
writePos += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
TexturePtr spriteTex(new Texture(32, 32, 4, pixels));
|
TexturePtr spriteTex(new Texture(32, 32, 4, &pixels[0]));
|
||||||
spriteTex->setSmooth(true);
|
spriteTex->setSmooth(true);
|
||||||
spriteTex->generateBilinearMipmaps();
|
spriteTex->generateBilinearMipmaps(pixels);
|
||||||
return spriteTex;
|
return spriteTex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ public:
|
||||||
|
|
||||||
bool load(const std::string& file);
|
bool load(const std::string& file);
|
||||||
void unload();
|
void unload();
|
||||||
|
void preloadSprites();
|
||||||
|
|
||||||
uint32 getSignature() { return m_signature; }
|
uint32 getSignature() { return m_signature; }
|
||||||
int getSpritesCount() { return m_spritesCount; }
|
int getSpritesCount() { return m_spritesCount; }
|
||||||
|
@ -45,7 +46,7 @@ private:
|
||||||
|
|
||||||
Boolean<false> m_loaded;
|
Boolean<false> m_loaded;
|
||||||
uint32 m_signature;
|
uint32 m_signature;
|
||||||
uint16 m_spritesCount;
|
int m_spritesCount;
|
||||||
std::stringstream m_fin;
|
std::stringstream m_fin;
|
||||||
std::vector<TexturePtr> m_sprites;
|
std::vector<TexturePtr> m_sprites;
|
||||||
TexturePtr m_transparentSprite;
|
TexturePtr m_transparentSprite;
|
||||||
|
|
|
@ -58,6 +58,7 @@ void OTClient::registerLuaFunctions()
|
||||||
g_lua.bindClassStaticFunction("g_sprites", "load", std::bind(&SpriteManager::load, &g_sprites, _1));
|
g_lua.bindClassStaticFunction("g_sprites", "load", std::bind(&SpriteManager::load, &g_sprites, _1));
|
||||||
g_lua.bindClassStaticFunction("g_sprites", "isLoaded", std::bind(&SpriteManager::isLoaded, &g_sprites));
|
g_lua.bindClassStaticFunction("g_sprites", "isLoaded", std::bind(&SpriteManager::isLoaded, &g_sprites));
|
||||||
g_lua.bindClassStaticFunction("g_sprites", "getSignature", std::bind(&SpriteManager::getSignature, &g_sprites));
|
g_lua.bindClassStaticFunction("g_sprites", "getSignature", std::bind(&SpriteManager::getSignature, &g_sprites));
|
||||||
|
g_lua.bindClassStaticFunction("g_sprites", "preloadSprites", std::bind(&SpriteManager::preloadSprites, &g_sprites));
|
||||||
|
|
||||||
g_lua.registerStaticClass("g_map");
|
g_lua.registerStaticClass("g_map");
|
||||||
g_lua.bindClassStaticFunction("g_map", "isLookPossible", std::bind(&Map::isLookPossible, &g_map, _1));
|
g_lua.bindClassStaticFunction("g_map", "isLookPossible", std::bind(&Map::isLookPossible, &g_map, _1));
|
||||||
|
|
Loading…
Reference in New Issue