mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-22 22:25:38 +00:00
Added support for upscaling bitmap images using linear filtering.
This commit is contained in:
parent
8e25609d4f
commit
6e882dd564
|
@ -138,7 +138,7 @@ void ImageComponent::resize()
|
||||||
onSizeChanged();
|
onSizeChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageComponent::setImage(std::string path, bool tile)
|
void ImageComponent::setImage(std::string path, bool tile, bool linearMagnify)
|
||||||
{
|
{
|
||||||
// Always load bundled graphic resources statically, unless mForceLoad has been set.
|
// Always load bundled graphic resources statically, unless mForceLoad has been set.
|
||||||
// This eliminates annoying texture pop-in problems that would otherwise occur.
|
// This eliminates annoying texture pop-in problems that would otherwise occur.
|
||||||
|
@ -150,10 +150,11 @@ void ImageComponent::setImage(std::string path, bool tile)
|
||||||
if (mDefaultPath.empty() || !ResourceManager::getInstance()->fileExists(mDefaultPath))
|
if (mDefaultPath.empty() || !ResourceManager::getInstance()->fileExists(mDefaultPath))
|
||||||
mTexture.reset();
|
mTexture.reset();
|
||||||
else
|
else
|
||||||
mTexture = TextureResource::get(mDefaultPath, tile, mForceLoad, mDynamic);
|
mTexture =
|
||||||
|
TextureResource::get(mDefaultPath, tile, mForceLoad, mDynamic, linearMagnify);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mTexture = TextureResource::get(path, tile, mForceLoad, mDynamic);
|
mTexture = TextureResource::get(path, tile, mForceLoad, mDynamic, linearMagnify);
|
||||||
}
|
}
|
||||||
|
|
||||||
resize();
|
resize();
|
||||||
|
|
|
@ -24,7 +24,7 @@ public:
|
||||||
|
|
||||||
// Loads the image at the given filepath. Will tile if tile is true (retrieves texture
|
// Loads the image at the given filepath. Will tile if tile is true (retrieves texture
|
||||||
// as tiling, creates vertices accordingly).
|
// as tiling, creates vertices accordingly).
|
||||||
void setImage(std::string path, bool tile = false);
|
void setImage(std::string path, bool tile = false, bool linearMagnify = false);
|
||||||
// Loads an image from memory.
|
// Loads an image from memory.
|
||||||
void setImage(const char* data, size_t length, bool tile = false);
|
void setImage(const char* data, size_t length, bool tile = false);
|
||||||
// Use an already existing texture.
|
// Use an already existing texture.
|
||||||
|
|
|
@ -59,7 +59,7 @@ void NinePatchComponent::buildVertices()
|
||||||
else
|
else
|
||||||
scaleFactor = glm::clamp(Renderer::getScreenWidthModifier(), 0.4f, 3.0f);
|
scaleFactor = glm::clamp(Renderer::getScreenWidthModifier(), 0.4f, 3.0f);
|
||||||
|
|
||||||
mTexture = TextureResource::get(mPath, false, false, true, scaleFactor);
|
mTexture = TextureResource::get(mPath, false, false, true, true, scaleFactor);
|
||||||
|
|
||||||
if (mTexture->getSize() == glm::ivec2{}) {
|
if (mTexture->getSize() == glm::ivec2{}) {
|
||||||
mVertices = nullptr;
|
mVertices = nullptr;
|
||||||
|
|
|
@ -167,12 +167,13 @@ namespace Renderer
|
||||||
void setupWindow();
|
void setupWindow();
|
||||||
bool createContext();
|
bool createContext();
|
||||||
void destroyContext();
|
void destroyContext();
|
||||||
unsigned int createTexture(const Texture::Type _type,
|
unsigned int createTexture(const Texture::Type type,
|
||||||
const bool _linear,
|
const bool linearMinify,
|
||||||
const bool _repeat,
|
const bool linearMagnify,
|
||||||
const unsigned int _width,
|
const bool repeat,
|
||||||
const unsigned int _height,
|
const unsigned int width,
|
||||||
void* _data);
|
const unsigned int height,
|
||||||
|
void* data);
|
||||||
void destroyTexture(const unsigned int _texture);
|
void destroyTexture(const unsigned int _texture);
|
||||||
void updateTexture(const unsigned int _texture,
|
void updateTexture(const unsigned int _texture,
|
||||||
const Texture::Type _type,
|
const Texture::Type _type,
|
||||||
|
|
|
@ -138,7 +138,7 @@ namespace Renderer
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t data[4] = {255, 255, 255, 255};
|
uint8_t data[4] = {255, 255, 255, 255};
|
||||||
whiteTexture = createTexture(Texture::RGBA, false, true, 1, 1, data);
|
whiteTexture = createTexture(Texture::RGBA, false, false, true, 1, 1, data);
|
||||||
|
|
||||||
GL_CHECK_ERROR(glClearColor(0.0f, 0.0f, 0.0f, 1.0f));
|
GL_CHECK_ERROR(glClearColor(0.0f, 0.0f, 0.0f, 1.0f));
|
||||||
GL_CHECK_ERROR(glEnable(GL_TEXTURE_2D));
|
GL_CHECK_ERROR(glEnable(GL_TEXTURE_2D));
|
||||||
|
@ -162,32 +162,35 @@ namespace Renderer
|
||||||
sdlContext = nullptr;
|
sdlContext = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int createTexture(const Texture::Type _type,
|
unsigned int createTexture(const Texture::Type type,
|
||||||
const bool _linear,
|
const bool linearMinify,
|
||||||
const bool _repeat,
|
const bool linearMagnify,
|
||||||
const unsigned int _width,
|
const bool repeat,
|
||||||
const unsigned int _height,
|
const unsigned int width,
|
||||||
void* _data)
|
const unsigned int height,
|
||||||
|
void* data)
|
||||||
{
|
{
|
||||||
const GLenum type = convertTextureType(_type);
|
const GLenum textureType = convertTextureType(type);
|
||||||
unsigned int texture;
|
unsigned int texture;
|
||||||
|
|
||||||
GL_CHECK_ERROR(glGenTextures(1, &texture));
|
GL_CHECK_ERROR(glGenTextures(1, &texture));
|
||||||
GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture));
|
GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture));
|
||||||
|
|
||||||
GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
|
GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
|
||||||
_repeat ? static_cast<GLfloat>(GL_REPEAT) :
|
repeat ? static_cast<GLfloat>(GL_REPEAT) :
|
||||||
static_cast<GLfloat>(GL_CLAMP_TO_EDGE)));
|
static_cast<GLfloat>(GL_CLAMP_TO_EDGE)));
|
||||||
GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
|
GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
|
||||||
_repeat ? static_cast<GLfloat>(GL_REPEAT) :
|
repeat ? static_cast<GLfloat>(GL_REPEAT) :
|
||||||
static_cast<GLfloat>(GL_CLAMP_TO_EDGE)));
|
static_cast<GLfloat>(GL_CLAMP_TO_EDGE)));
|
||||||
GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
||||||
_linear ? static_cast<GLfloat>(GL_LINEAR) :
|
linearMinify ? static_cast<GLfloat>(GL_LINEAR) :
|
||||||
|
static_cast<GLfloat>(GL_NEAREST)));
|
||||||
|
GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
|
||||||
|
linearMagnify ? static_cast<GLfloat>(GL_LINEAR) :
|
||||||
static_cast<GLfloat>(GL_NEAREST)));
|
static_cast<GLfloat>(GL_NEAREST)));
|
||||||
GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
|
|
||||||
|
|
||||||
GL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, 0, type, _width, _height, 0, type,
|
GL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, 0, textureType, width, height, 0, textureType,
|
||||||
GL_UNSIGNED_BYTE, _data));
|
GL_UNSIGNED_BYTE, data));
|
||||||
|
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
@ -448,7 +451,8 @@ namespace Renderer
|
||||||
vertices[0].saturation = parameters.fragmentSaturation;
|
vertices[0].saturation = parameters.fragmentSaturation;
|
||||||
|
|
||||||
setMatrix(getIdentity());
|
setMatrix(getIdentity());
|
||||||
GLuint screenTexture = createTexture(Texture::RGBA, false, false, width, height, nullptr);
|
GLuint screenTexture =
|
||||||
|
createTexture(Texture::RGBA, false, false, false, width, height, nullptr);
|
||||||
|
|
||||||
GL_CHECK_ERROR(glBindFramebuffer(GL_READ_FRAMEBUFFER, 0));
|
GL_CHECK_ERROR(glBindFramebuffer(GL_READ_FRAMEBUFFER, 0));
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,7 @@ namespace Renderer
|
||||||
"MISSING");
|
"MISSING");
|
||||||
|
|
||||||
uint8_t data[4] = {255, 255, 255, 255};
|
uint8_t data[4] = {255, 255, 255, 255};
|
||||||
whiteTexture = createTexture(Texture::RGBA, false, true, 1, 1, data);
|
whiteTexture = createTexture(Texture::RGBA, false, false, true, 1, 1, data);
|
||||||
|
|
||||||
GL_CHECK_ERROR(glClearColor(0.0f, 0.0f, 0.0f, 1.0f));
|
GL_CHECK_ERROR(glClearColor(0.0f, 0.0f, 0.0f, 1.0f));
|
||||||
GL_CHECK_ERROR(glEnable(GL_TEXTURE_2D));
|
GL_CHECK_ERROR(glEnable(GL_TEXTURE_2D));
|
||||||
|
@ -111,29 +111,31 @@ namespace Renderer
|
||||||
sdlContext = nullptr;
|
sdlContext = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int createTexture(const Texture::Type _type,
|
unsigned int createTexture(const Texture::Type type,
|
||||||
const bool _linear,
|
const bool linearMinify,
|
||||||
const bool _repeat,
|
const bool linearMagnify,
|
||||||
const unsigned int _width,
|
const bool repeat,
|
||||||
const unsigned int _height,
|
const unsigned int width,
|
||||||
void* _data)
|
const unsigned int height,
|
||||||
|
void* data)
|
||||||
{
|
{
|
||||||
const GLenum type = convertTextureType(_type);
|
const GLenum textureType = convertTextureType(type);
|
||||||
unsigned int texture;
|
unsigned int texture;
|
||||||
|
|
||||||
GL_CHECK_ERROR(glGenTextures(1, &texture));
|
GL_CHECK_ERROR(glGenTextures(1, &texture));
|
||||||
GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture));
|
GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture));
|
||||||
|
|
||||||
GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
|
GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
|
||||||
_repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE));
|
repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE));
|
||||||
GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
|
GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
|
||||||
_repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE));
|
repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE));
|
||||||
GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
||||||
_linear ? GL_LINEAR : GL_NEAREST));
|
linearMinify ? GL_LINEAR : GL_NEAREST));
|
||||||
GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
|
GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
|
||||||
|
linearMagnify ? GL_LINEAR : GL_NEAREST));
|
||||||
|
|
||||||
GL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, 0, type, _width, _height, 0, type,
|
GL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, 0, textureType, width, height, 0, textureType,
|
||||||
GL_UNSIGNED_BYTE, _data));
|
GL_UNSIGNED_BYTE, data));
|
||||||
|
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
|
@ -179,8 +179,8 @@ bool Font::FontTexture::findEmpty(const glm::ivec2& size, glm::ivec2& cursor_out
|
||||||
void Font::FontTexture::initTexture()
|
void Font::FontTexture::initTexture()
|
||||||
{
|
{
|
||||||
assert(textureId == 0);
|
assert(textureId == 0);
|
||||||
textureId = Renderer::createTexture(Renderer::Texture::ALPHA, false, false, textureSize.x,
|
textureId = Renderer::createTexture(Renderer::Texture::ALPHA, false, false, false,
|
||||||
textureSize.y, nullptr);
|
textureSize.x, textureSize.y, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Font::FontTexture::deinitTexture()
|
void Font::FontTexture::deinitTexture()
|
||||||
|
|
|
@ -28,6 +28,7 @@ TextureData::TextureData(bool tile)
|
||||||
, mDataRGBA({})
|
, mDataRGBA({})
|
||||||
, mScaleDuringLoad(1.0f)
|
, mScaleDuringLoad(1.0f)
|
||||||
, mScalable(false)
|
, mScalable(false)
|
||||||
|
, mLinearMagnify(false)
|
||||||
, mWidth(0)
|
, mWidth(0)
|
||||||
, mHeight(0)
|
, mHeight(0)
|
||||||
, mSourceWidth(0.0f)
|
, mSourceWidth(0.0f)
|
||||||
|
@ -196,8 +197,9 @@ bool TextureData::uploadAndBind()
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Upload texture.
|
// Upload texture.
|
||||||
mTextureID = Renderer::createTexture(
|
mTextureID =
|
||||||
Renderer::Texture::RGBA, true, mTile, static_cast<const unsigned int>(mWidth),
|
Renderer::createTexture(Renderer::Texture::RGBA, true, mLinearMagnify, mTile,
|
||||||
|
static_cast<const unsigned int>(mWidth),
|
||||||
static_cast<const unsigned int>(mHeight), mDataRGBA.data());
|
static_cast<const unsigned int>(mHeight), mDataRGBA.data());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -56,6 +56,8 @@ public:
|
||||||
|
|
||||||
// Define a factor for scaling the file when loading it (1.0f = no scaling).
|
// Define a factor for scaling the file when loading it (1.0f = no scaling).
|
||||||
void setScaleDuringLoad(float scale) { mScaleDuringLoad = scale; }
|
void setScaleDuringLoad(float scale) { mScaleDuringLoad = scale; }
|
||||||
|
// Whether to use linear filtering when magnifying the texture.
|
||||||
|
void setLinearMagnify(bool setting) { mLinearMagnify = setting; }
|
||||||
|
|
||||||
std::vector<unsigned char> getRawRGBAData() { return mDataRGBA; }
|
std::vector<unsigned char> getRawRGBAData() { return mDataRGBA; }
|
||||||
std::string getTextureFilePath() { return mPath; }
|
std::string getTextureFilePath() { return mPath; }
|
||||||
|
@ -73,6 +75,7 @@ private:
|
||||||
float mSourceHeight;
|
float mSourceHeight;
|
||||||
float mScaleDuringLoad;
|
float mScaleDuringLoad;
|
||||||
bool mScalable;
|
bool mScalable;
|
||||||
|
bool mLinearMagnify;
|
||||||
bool mReloadable;
|
bool mReloadable;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -16,10 +16,8 @@ std::map<TextureResource::TextureKeyType, std::weak_ptr<TextureResource>>
|
||||||
TextureResource::sTextureMap;
|
TextureResource::sTextureMap;
|
||||||
std::set<TextureResource*> TextureResource::sAllTextures;
|
std::set<TextureResource*> TextureResource::sAllTextures;
|
||||||
|
|
||||||
TextureResource::TextureResource(const std::string& path,
|
TextureResource::TextureResource(
|
||||||
bool tile,
|
const std::string& path, bool tile, bool dynamic, bool linearMagnify, float scaleDuringLoad)
|
||||||
bool dynamic,
|
|
||||||
float scaleDuringLoad)
|
|
||||||
: mTextureData(nullptr)
|
: mTextureData(nullptr)
|
||||||
, mForceLoad(false)
|
, mForceLoad(false)
|
||||||
{
|
{
|
||||||
|
@ -33,6 +31,7 @@ TextureResource::TextureResource(const std::string& path,
|
||||||
data->initFromPath(path);
|
data->initFromPath(path);
|
||||||
if (scaleDuringLoad != 1.0f)
|
if (scaleDuringLoad != 1.0f)
|
||||||
data->setScaleDuringLoad(scaleDuringLoad);
|
data->setScaleDuringLoad(scaleDuringLoad);
|
||||||
|
data->setLinearMagnify(linearMagnify);
|
||||||
// Force the texture manager to load it using a blocking load.
|
// Force the texture manager to load it using a blocking load.
|
||||||
sTextureDataManager.load(data, true);
|
sTextureDataManager.load(data, true);
|
||||||
}
|
}
|
||||||
|
@ -42,6 +41,7 @@ TextureResource::TextureResource(const std::string& path,
|
||||||
data->initFromPath(path);
|
data->initFromPath(path);
|
||||||
if (scaleDuringLoad != 1.0f)
|
if (scaleDuringLoad != 1.0f)
|
||||||
data->setScaleDuringLoad(scaleDuringLoad);
|
data->setScaleDuringLoad(scaleDuringLoad);
|
||||||
|
data->setLinearMagnify(linearMagnify);
|
||||||
// Load it so we can read the width/height.
|
// Load it so we can read the width/height.
|
||||||
data->load();
|
data->load();
|
||||||
}
|
}
|
||||||
|
@ -143,14 +143,19 @@ bool TextureResource::bind()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<TextureResource> TextureResource::get(
|
std::shared_ptr<TextureResource> TextureResource::get(const std::string& path,
|
||||||
const std::string& path, bool tile, bool forceLoad, bool dynamic, float scaleDuringLoad)
|
bool tile,
|
||||||
|
bool forceLoad,
|
||||||
|
bool dynamic,
|
||||||
|
bool linearMagnify,
|
||||||
|
float scaleDuringLoad)
|
||||||
{
|
{
|
||||||
std::shared_ptr<ResourceManager>& rm = ResourceManager::getInstance();
|
std::shared_ptr<ResourceManager>& rm = ResourceManager::getInstance();
|
||||||
|
|
||||||
const std::string canonicalPath = Utils::FileSystem::getCanonicalPath(path);
|
const std::string canonicalPath = Utils::FileSystem::getCanonicalPath(path);
|
||||||
if (canonicalPath.empty()) {
|
if (canonicalPath.empty()) {
|
||||||
std::shared_ptr<TextureResource> tex(new TextureResource("", tile, false, scaleDuringLoad));
|
std::shared_ptr<TextureResource> tex(
|
||||||
|
new TextureResource("", tile, false, linearMagnify, scaleDuringLoad));
|
||||||
// Make sure we get properly deinitialized even though we do nothing on reinitialization.
|
// Make sure we get properly deinitialized even though we do nothing on reinitialization.
|
||||||
rm->addReloadable(tex);
|
rm->addReloadable(tex);
|
||||||
return tex;
|
return tex;
|
||||||
|
@ -167,7 +172,7 @@ std::shared_ptr<TextureResource> TextureResource::get(
|
||||||
// Need to create it.
|
// Need to create it.
|
||||||
std::shared_ptr<TextureResource> tex;
|
std::shared_ptr<TextureResource> tex;
|
||||||
tex = std::shared_ptr<TextureResource>(
|
tex = std::shared_ptr<TextureResource>(
|
||||||
new TextureResource(key.first, tile, dynamic, scaleDuringLoad));
|
new TextureResource(key.first, tile, dynamic, linearMagnify, scaleDuringLoad));
|
||||||
std::shared_ptr<TextureData> data = sTextureDataManager.get(tex.get());
|
std::shared_ptr<TextureData> data = sTextureDataManager.get(tex.get());
|
||||||
|
|
||||||
// Is it an SVG?
|
// Is it an SVG?
|
||||||
|
|
|
@ -29,6 +29,7 @@ public:
|
||||||
bool tile = false,
|
bool tile = false,
|
||||||
bool forceLoad = false,
|
bool forceLoad = false,
|
||||||
bool dynamic = true,
|
bool dynamic = true,
|
||||||
|
bool linearMagnify = false,
|
||||||
float scaleDuringLoad = 1.0f);
|
float scaleDuringLoad = 1.0f);
|
||||||
void initFromPixels(const unsigned char* dataRGBA, size_t width, size_t height);
|
void initFromPixels(const unsigned char* dataRGBA, size_t width, size_t height);
|
||||||
virtual void initFromMemory(const char* data, size_t length);
|
virtual void initFromMemory(const char* data, size_t length);
|
||||||
|
@ -60,7 +61,11 @@ public:
|
||||||
static size_t getTotalTextureSize();
|
static size_t getTotalTextureSize();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TextureResource(const std::string& path, bool tile, bool dynamic, float scaleDuringLoad);
|
TextureResource(const std::string& path,
|
||||||
|
bool tile,
|
||||||
|
bool dynamic,
|
||||||
|
bool linearMagnify,
|
||||||
|
float scaleDuringLoad);
|
||||||
virtual void unload(std::shared_ptr<ResourceManager>& rm);
|
virtual void unload(std::shared_ptr<ResourceManager>& rm);
|
||||||
virtual void reload(std::shared_ptr<ResourceManager>& rm);
|
virtual void reload(std::shared_ptr<ResourceManager>& rm);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue