Implement cropped and rescaling texture hack
This commit is contained in:
parent
f7a3e3c5d2
commit
9506c05ba6
125
src/bitmap.cpp
125
src/bitmap.cpp
|
@ -43,6 +43,7 @@
|
||||||
#include "filesystem.h"
|
#include "filesystem.h"
|
||||||
#include "font.h"
|
#include "font.h"
|
||||||
#include "eventthread.h"
|
#include "eventthread.h"
|
||||||
|
#include "debugwriter.h"
|
||||||
|
|
||||||
#define GUARD_MEGA \
|
#define GUARD_MEGA \
|
||||||
{ \
|
{ \
|
||||||
|
@ -100,10 +101,20 @@ struct BitmapPrivate
|
||||||
* ourselves the expensive blending calculation */
|
* ourselves the expensive blending calculation */
|
||||||
pixman_region16_t tainted;
|
pixman_region16_t tainted;
|
||||||
|
|
||||||
|
bool isCrop;
|
||||||
|
CropTexture cropTex;
|
||||||
|
TEX::ID cropTexTex;
|
||||||
|
|
||||||
|
bool isResized;
|
||||||
|
Vec2i resizedSize;
|
||||||
|
TEX::ID resTex;
|
||||||
|
|
||||||
BitmapPrivate(Bitmap *self)
|
BitmapPrivate(Bitmap *self)
|
||||||
: self(self),
|
: self(self),
|
||||||
megaSurface(0),
|
megaSurface(0),
|
||||||
surface(0)
|
surface(0),
|
||||||
|
isCrop(false),
|
||||||
|
isResized(false)
|
||||||
{
|
{
|
||||||
format = SDL_AllocFormat(SDL_PIXELFORMAT_ABGR8888);
|
format = SDL_AllocFormat(SDL_PIXELFORMAT_ABGR8888);
|
||||||
|
|
||||||
|
@ -167,7 +178,10 @@ struct BitmapPrivate
|
||||||
void bindTexture(ShaderBase &shader)
|
void bindTexture(ShaderBase &shader)
|
||||||
{
|
{
|
||||||
TEX::bind(gl.tex);
|
TEX::bind(gl.tex);
|
||||||
shader.setTexSize(Vec2i(gl.width, gl.height));
|
if (isCrop)
|
||||||
|
shader.setTexSize(Vec2i(cropTex.w, cropTex.h));
|
||||||
|
else
|
||||||
|
shader.setTexSize(Vec2i(gl.width, gl.height));
|
||||||
}
|
}
|
||||||
|
|
||||||
void bindFBO()
|
void bindFBO()
|
||||||
|
@ -242,14 +256,114 @@ Bitmap::Bitmap(const char *filename)
|
||||||
throw Exception(Exception::SDLError, "Error loading image '%s': %s",
|
throw Exception(Exception::SDLError, "Error loading image '%s': %s",
|
||||||
filename, SDL_GetError());
|
filename, SDL_GetError());
|
||||||
|
|
||||||
|
bool isCrop = false;
|
||||||
|
CropTexture cropTex;
|
||||||
|
const std::vector<CropTexture> &crops = shState->config().cropTexs;
|
||||||
|
for (size_t i = 0; i < crops.size(); ++i)
|
||||||
|
{
|
||||||
|
if (crops[i].filename != filename)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Debug() << "Loading cropped texture:" << filename << crops[i].w << crops[i].h;
|
||||||
|
isCrop = true;
|
||||||
|
cropTex = crops[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
p->ensureFormat(imgSurf, SDL_PIXELFORMAT_ABGR8888);
|
p->ensureFormat(imgSurf, SDL_PIXELFORMAT_ABGR8888);
|
||||||
|
|
||||||
if (imgSurf->w > glState.caps.maxTexSize || imgSurf->h > glState.caps.maxTexSize)
|
SDL_SetSurfaceBlendMode(imgSurf, SDL_BLENDMODE_NONE);
|
||||||
|
|
||||||
|
// Try catching too large images, while trying NOT to catch giant tilesets
|
||||||
|
if ((imgSurf->w > glState.caps.maxTexSize || imgSurf->h > glState.caps.maxTexSize) && imgSurf->w != 256 && !isCrop)
|
||||||
|
{
|
||||||
|
Vec2i resSize(imgSurf->w/2, imgSurf->h/2);
|
||||||
|
while (resSize.x > glState.caps.maxTexSize || resSize.y > glState.caps.maxTexSize)
|
||||||
|
{
|
||||||
|
resSize.x = resSize.x/2;
|
||||||
|
resSize.y = resSize.y/2;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug() << "Loading image" << filename << "at resolution"
|
||||||
|
<< resSize.x << resSize.y << "down from" << imgSurf->w << imgSurf->h;
|
||||||
|
|
||||||
|
// Use texture with halved dimensions instead
|
||||||
|
p = new BitmapPrivate(this);
|
||||||
|
p->isResized = true;
|
||||||
|
p->resizedSize = resSize;
|
||||||
|
|
||||||
|
int bpp; Uint32 rm, gm, bm, am;
|
||||||
|
SDL_PixelFormatEnumToMasks(SDL_PIXELFORMAT_ABGR8888, &bpp, &rm, &gm, &bm, &am);
|
||||||
|
SDL_Surface *resImg = SDL_CreateRGBSurface(0, resSize.x, resSize.y, bpp, rm, gm, bm, am);
|
||||||
|
|
||||||
|
SDL_BlitScaled(imgSurf, 0, resImg, 0);
|
||||||
|
|
||||||
|
TEX::ID tex = TEX::gen();
|
||||||
|
TEX::bind(tex);
|
||||||
|
TEX::uploadImage(resImg->w, resImg->h, resImg->pixels, GL_RGBA);
|
||||||
|
TEX::setRepeat(false);
|
||||||
|
TEX::setSmooth(true);
|
||||||
|
|
||||||
|
p->resTex = tex;
|
||||||
|
p->gl.tex = tex;
|
||||||
|
p->gl.width = imgSurf->w;
|
||||||
|
p->gl.height = imgSurf->h;
|
||||||
|
|
||||||
|
SDL_FreeSurface(imgSurf);
|
||||||
|
SDL_FreeSurface(resImg);
|
||||||
|
}
|
||||||
|
else if ((imgSurf->h > glState.caps.maxTexSize) && !isCrop) // Too large tilesets go here
|
||||||
{
|
{
|
||||||
/* Mega surface */
|
/* Mega surface */
|
||||||
p = new BitmapPrivate(this);
|
p = new BitmapPrivate(this);
|
||||||
p->megaSurface = imgSurf;
|
p->megaSurface = imgSurf;
|
||||||
}
|
}
|
||||||
|
else if (isCrop)
|
||||||
|
{
|
||||||
|
p = new BitmapPrivate(this);
|
||||||
|
p->cropTex = cropTex;
|
||||||
|
|
||||||
|
Vec2i resSize(cropTex.w, cropTex.h);
|
||||||
|
while (resSize.x > glState.caps.maxTexSize || resSize.y > glState.caps.maxTexSize)
|
||||||
|
{
|
||||||
|
resSize.x = resSize.x/2;
|
||||||
|
resSize.y = resSize.y/2;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEX::ID tex = TEX::gen();
|
||||||
|
TEX::bind(tex);
|
||||||
|
TEX::setRepeat(false);
|
||||||
|
TEX::setSmooth(false);
|
||||||
|
|
||||||
|
if (resSize == Vec2i(cropTex.w, cropTex.h))
|
||||||
|
{
|
||||||
|
TEX::allocEmpty(cropTex.w, cropTex.h);
|
||||||
|
GLMeta::subRectImageUpload(imgSurf->w, 0, 0, 0, 0, cropTex.w, cropTex.h, imgSurf, GL_RGBA);
|
||||||
|
GLMeta::subRectImageEnd();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int bpp; Uint32 rm, gm, bm, am;
|
||||||
|
SDL_PixelFormatEnumToMasks(SDL_PIXELFORMAT_ABGR8888, &bpp, &rm, &gm, &bm, &am);
|
||||||
|
SDL_Surface *resImg = SDL_CreateRGBSurface(0, resSize.x, resSize.y, bpp, rm, gm, bm, am);
|
||||||
|
|
||||||
|
IntRect src(0, 0, cropTex.w, cropTex.h);
|
||||||
|
SDL_BlitScaled(imgSurf, &src, resImg, 0);
|
||||||
|
TEX::uploadImage(resSize.x, resSize.y, resImg->pixels, GL_RGBA);
|
||||||
|
|
||||||
|
SDL_FreeSurface(resImg);
|
||||||
|
|
||||||
|
Debug() << "Loading cropped image" << filename << "at resolution"
|
||||||
|
<< resSize.x << resSize.y << "down from" << cropTex.w << cropTex.h;
|
||||||
|
}
|
||||||
|
|
||||||
|
p->cropTexTex = tex;
|
||||||
|
|
||||||
|
p->gl.tex = tex;
|
||||||
|
p->gl.width = imgSurf->w;
|
||||||
|
p->gl.height = imgSurf->h;
|
||||||
|
SDL_FreeSurface(imgSurf);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Regular surface */
|
/* Regular surface */
|
||||||
|
@ -274,6 +388,7 @@ Bitmap::Bitmap(const char *filename)
|
||||||
SDL_FreeSurface(imgSurf);
|
SDL_FreeSurface(imgSurf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p->isCrop = isCrop;
|
||||||
p->addTaintedArea(rect());
|
p->addTaintedArea(rect());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1230,6 +1345,10 @@ void Bitmap::releaseResources()
|
||||||
{
|
{
|
||||||
if (p->megaSurface)
|
if (p->megaSurface)
|
||||||
SDL_FreeSurface(p->megaSurface);
|
SDL_FreeSurface(p->megaSurface);
|
||||||
|
else if (p->isCrop)
|
||||||
|
TEX::del(p->cropTexTex);
|
||||||
|
else if (p->isResized)
|
||||||
|
TEX::del(p->resTex);
|
||||||
else
|
else
|
||||||
shState->texPool().release(p->gl);
|
shState->texPool().release(p->gl);
|
||||||
|
|
||||||
|
|
|
@ -261,6 +261,53 @@ void Config::read(int argc, char *argv[])
|
||||||
customDataPath = prefPath(dataPathOrg.c_str(), dataPathApp.c_str());
|
customDataPath = prefPath(dataPathOrg.c_str(), dataPathApp.c_str());
|
||||||
|
|
||||||
commonDataPath = prefPath(".", "mkxp");
|
commonDataPath = prefPath(".", "mkxp");
|
||||||
|
|
||||||
|
/* parse cropped textures config */
|
||||||
|
std::string cropTexFile;
|
||||||
|
if (!readFile("croptextures", cropTexFile))
|
||||||
|
{
|
||||||
|
Debug() << "Couldn't read croptextures config file";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t lineStart = 0;
|
||||||
|
bool atEnd = false;
|
||||||
|
|
||||||
|
while (!atEnd)
|
||||||
|
{
|
||||||
|
CropTexture tex;
|
||||||
|
|
||||||
|
size_t fnEnd = cropTexFile.find('"', lineStart+1);
|
||||||
|
size_t numSep = cropTexFile.find(' ', fnEnd+2);
|
||||||
|
size_t lineEnd = cropTexFile.find('\n', numSep);
|
||||||
|
|
||||||
|
if (fnEnd == std::string::npos || numSep == std::string::npos)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (lineEnd == std::string::npos)
|
||||||
|
{
|
||||||
|
lineEnd = cropTexFile.size();
|
||||||
|
atEnd = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
tex.filename = cropTexFile.substr(lineStart+1, fnEnd-(lineStart+1));
|
||||||
|
tex.w = atoi(cropTexFile.substr(fnEnd+2, numSep-(fnEnd+2)).c_str());
|
||||||
|
tex.h = atoi(cropTexFile.substr(numSep+1, lineEnd-(numSep+1)).c_str());
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
Debug() << "Couldn't parse croptextures config file";
|
||||||
|
cropTexs.clear();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cropTexs.push_back(tex);
|
||||||
|
Debug() << "Parsed:" << tex.filename << tex.w << tex.h;
|
||||||
|
|
||||||
|
lineStart = lineEnd+1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string baseName(const std::string &path)
|
static std::string baseName(const std::string &path)
|
||||||
|
|
|
@ -25,6 +25,12 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
struct CropTexture
|
||||||
|
{
|
||||||
|
std::string filename;
|
||||||
|
int w, h;
|
||||||
|
};
|
||||||
|
|
||||||
struct Config
|
struct Config
|
||||||
{
|
{
|
||||||
int rgssVersion;
|
int rgssVersion;
|
||||||
|
@ -89,6 +95,8 @@ struct Config
|
||||||
std::string customDataPath;
|
std::string customDataPath;
|
||||||
std::string commonDataPath;
|
std::string commonDataPath;
|
||||||
|
|
||||||
|
std::vector<CropTexture> cropTexs;
|
||||||
|
|
||||||
Config();
|
Config();
|
||||||
|
|
||||||
void read(int argc, char *argv[]);
|
void read(int argc, char *argv[]);
|
||||||
|
|
Loading…
Reference in New Issue