mirror of
https://github.com/mkxp-z/mkxp-z.git
synced 2025-03-28 14:56:22 +01:00
Merge pull request #21 from Splendide-Imaginarius/mkxp-z-hires
Implement high-resolution Bitmap replacement
This commit is contained in:
commit
d6d1d9699e
36 changed files with 1205 additions and 44 deletions
|
@ -49,6 +49,12 @@ void bitmapInitProps(Bitmap *b, VALUE self) {
|
|||
b->setInitFont(font);
|
||||
|
||||
rb_iv_set(self, "font", fontObj);
|
||||
|
||||
// Leave property as default nil if hasHires() is false.
|
||||
if (b->hasHires()) {
|
||||
b->assumeRubyGC();
|
||||
wrapProperty(self, b->getHires(), "hires", BitmapType);
|
||||
}
|
||||
}
|
||||
|
||||
RB_METHOD(bitmapInitialize) {
|
||||
|
@ -94,6 +100,8 @@ RB_METHOD(bitmapHeight) {
|
|||
return INT2FIX(value);
|
||||
}
|
||||
|
||||
DEF_GFX_PROP_OBJ_REF(Bitmap, Bitmap, Hires, "hires")
|
||||
|
||||
RB_METHOD(bitmapRect) {
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
|
@ -741,6 +749,9 @@ void bitmapBindingInit() {
|
|||
|
||||
_rb_define_method(klass, "width", bitmapWidth);
|
||||
_rb_define_method(klass, "height", bitmapHeight);
|
||||
|
||||
INIT_PROP_BIND(Bitmap, Hires, "hires");
|
||||
|
||||
_rb_define_method(klass, "rect", bitmapRect);
|
||||
_rb_define_method(klass, "blt", bitmapBlt);
|
||||
_rb_define_method(klass, "stretch_blt", bitmapStretchBlt);
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "graphics.h"
|
||||
#include "sharedstate.h"
|
||||
#include "binding-util.h"
|
||||
|
|
29
mkxp.json
29
mkxp.json
|
@ -91,6 +91,35 @@
|
|||
// "lanczos3Scaling": false,
|
||||
|
||||
|
||||
// Replace the game's Bitmap files with external high-res files
|
||||
// provided in the "Hires" directory.
|
||||
// (You'll also need to set the below Scaling Factors.)
|
||||
// (default: disabled)
|
||||
//
|
||||
// "enableHires": false,
|
||||
|
||||
|
||||
// Scaling factor for textures (e.g. Bitmaps)
|
||||
// (higher values will look better if you use high-res textures)
|
||||
// (default: 1.0)
|
||||
//
|
||||
// "textureScalingFactor": 4.0,
|
||||
|
||||
|
||||
// Scaling factor for screen framebuffer
|
||||
// (higher values will look better if you use high-res textures)
|
||||
// (default: 1.0)
|
||||
//
|
||||
// "framebufferScalingFactor": 4.0,
|
||||
|
||||
|
||||
// Scaling factor for tileset atlas
|
||||
// (higher values will look better if you use high-res textures)
|
||||
// (default: 1.0)
|
||||
//
|
||||
// "atlasScalingFactor": 4.0,
|
||||
|
||||
|
||||
// Sync screen redraws to the monitor refresh rate
|
||||
// (default: disabled)
|
||||
//
|
||||
|
|
|
@ -136,6 +136,10 @@ void Config::read(int argc, char *argv[]) {
|
|||
{"fixedAspectRatio", true},
|
||||
{"smoothScaling", false},
|
||||
{"lanczos3Scaling", false},
|
||||
{"enableHires", false},
|
||||
{"textureScalingFactor", 1.},
|
||||
{"framebufferScalingFactor", 1.},
|
||||
{"atlasScalingFactor", 1.},
|
||||
{"vsync", false},
|
||||
{"defScreenW", 0},
|
||||
{"defScreenH", 0},
|
||||
|
@ -261,6 +265,10 @@ try { exp } catch (...) {}
|
|||
SET_OPT(fixedAspectRatio, boolean);
|
||||
SET_OPT(smoothScaling, boolean);
|
||||
SET_OPT(lanczos3Scaling, boolean);
|
||||
SET_OPT(enableHires, boolean);
|
||||
SET_OPT(textureScalingFactor, number);
|
||||
SET_OPT(framebufferScalingFactor, number);
|
||||
SET_OPT(atlasScalingFactor, number);
|
||||
SET_OPT(winResizable, boolean);
|
||||
SET_OPT(vsync, boolean);
|
||||
SET_STRINGOPT(windowTitle, windowTitle);
|
||||
|
|
|
@ -45,6 +45,10 @@ struct Config {
|
|||
bool fixedAspectRatio;
|
||||
bool smoothScaling;
|
||||
bool lanczos3Scaling;
|
||||
bool enableHires;
|
||||
double textureScalingFactor;
|
||||
double framebufferScalingFactor;
|
||||
double atlasScalingFactor;
|
||||
bool vsync;
|
||||
|
||||
int defScreenW;
|
||||
|
|
|
@ -237,11 +237,19 @@ struct BitmapPrivate
|
|||
* in the texture and blit to it directly, saving
|
||||
* ourselves the expensive blending calculation */
|
||||
pixman_region16_t tainted;
|
||||
|
||||
// For high-resolution texture replacement.
|
||||
Bitmap *selfHires;
|
||||
Bitmap *selfLores;
|
||||
bool assumingRubyGC;
|
||||
|
||||
BitmapPrivate(Bitmap *self)
|
||||
: self(self),
|
||||
megaSurface(0),
|
||||
surface(0)
|
||||
selfHires(0),
|
||||
selfLores(0),
|
||||
surface(0),
|
||||
assumingRubyGC(false)
|
||||
{
|
||||
format = SDL_AllocFormat(SDL_PIXELFORMAT_ABGR8888);
|
||||
|
||||
|
@ -326,16 +334,30 @@ struct BitmapPrivate
|
|||
return result != PIXMAN_REGION_OUT;
|
||||
}
|
||||
|
||||
void bindTexture(ShaderBase &shader)
|
||||
void bindTexture(ShaderBase &shader, bool substituteLoresSize = true)
|
||||
{
|
||||
if (selfHires) {
|
||||
selfHires->bindTex(shader);
|
||||
return;
|
||||
}
|
||||
|
||||
if (animation.enabled) {
|
||||
if (selfLores) {
|
||||
Debug() << "BUG: High-res BitmapPrivate bindTexture for animations not implemented";
|
||||
}
|
||||
|
||||
TEXFBO cframe = animation.currentFrame();
|
||||
TEX::bind(cframe.tex);
|
||||
shader.setTexSize(Vec2i(cframe.width, cframe.height));
|
||||
return;
|
||||
}
|
||||
TEX::bind(gl.tex);
|
||||
shader.setTexSize(Vec2i(gl.width, gl.height));
|
||||
if (selfLores && substituteLoresSize) {
|
||||
shader.setTexSize(Vec2i(selfLores->width(), selfLores->height()));
|
||||
}
|
||||
else {
|
||||
shader.setTexSize(Vec2i(gl.width, gl.height));
|
||||
}
|
||||
}
|
||||
|
||||
void bindFBO()
|
||||
|
@ -468,6 +490,24 @@ struct BitmapOpenHandler : FileSystem::OpenHandler
|
|||
|
||||
Bitmap::Bitmap(const char *filename)
|
||||
{
|
||||
std::string hiresPrefix = "Hires/";
|
||||
std::string filenameStd = filename;
|
||||
Bitmap *hiresBitmap = nullptr;
|
||||
// TODO: once C++20 is required, switch to filenameStd.starts_with(hiresPrefix)
|
||||
if (shState->config().enableHires && filenameStd.compare(0, hiresPrefix.size(), hiresPrefix) != 0) {
|
||||
// Look for a high-res version of the file.
|
||||
std::string hiresFilename = hiresPrefix + filenameStd;
|
||||
try {
|
||||
hiresBitmap = new Bitmap(hiresFilename.c_str());
|
||||
hiresBitmap->setLores(this);
|
||||
}
|
||||
catch (const Exception &e)
|
||||
{
|
||||
Debug() << "No high-res Bitmap found at" << hiresFilename;
|
||||
hiresBitmap = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
BitmapOpenHandler handler;
|
||||
shState->fileSystem().openRead(handler, filename);
|
||||
|
||||
|
@ -482,6 +522,8 @@ Bitmap::Bitmap(const char *filename)
|
|||
|
||||
if (handler.gif) {
|
||||
p = new BitmapPrivate(this);
|
||||
|
||||
p->selfHires = hiresBitmap;
|
||||
|
||||
if (handler.gif->width >= (uint32_t)glState.caps.maxTexSize || handler.gif->height > (uint32_t)glState.caps.maxTexSize)
|
||||
{
|
||||
|
@ -510,6 +552,9 @@ Bitmap::Bitmap(const char *filename)
|
|||
delete handler.gif_data;
|
||||
|
||||
p->gl = texfbo;
|
||||
if (p->selfHires != nullptr) {
|
||||
p->gl.selfHires = &p->selfHires->getGLTypes();
|
||||
}
|
||||
p->addTaintedArea(rect());
|
||||
return;
|
||||
}
|
||||
|
@ -583,6 +628,7 @@ Bitmap::Bitmap(const char *filename)
|
|||
{
|
||||
/* Mega surface */
|
||||
p = new BitmapPrivate(this);
|
||||
p->selfHires = hiresBitmap;
|
||||
p->megaSurface = imgSurf;
|
||||
SDL_SetSurfaceBlendMode(p->megaSurface, SDL_BLENDMODE_NONE);
|
||||
}
|
||||
|
@ -602,7 +648,11 @@ Bitmap::Bitmap(const char *filename)
|
|||
}
|
||||
|
||||
p = new BitmapPrivate(this);
|
||||
p->selfHires = hiresBitmap;
|
||||
p->gl = tex;
|
||||
if (p->selfHires != nullptr) {
|
||||
p->gl.selfHires = &p->selfHires->getGLTypes();
|
||||
}
|
||||
|
||||
TEX::bind(p->gl.tex);
|
||||
TEX::uploadImage(p->gl.width, p->gl.height, imgSurf->pixels, GL_RGBA);
|
||||
|
@ -613,15 +663,30 @@ Bitmap::Bitmap(const char *filename)
|
|||
p->addTaintedArea(rect());
|
||||
}
|
||||
|
||||
Bitmap::Bitmap(int width, int height)
|
||||
Bitmap::Bitmap(int width, int height, bool isHires)
|
||||
{
|
||||
if (width <= 0 || height <= 0)
|
||||
throw Exception(Exception::RGSSError, "failed to create bitmap");
|
||||
|
||||
Bitmap *hiresBitmap = nullptr;
|
||||
|
||||
if (shState->config().enableHires && !isHires) {
|
||||
// Create a high-res version as well.
|
||||
double scalingFactor = shState->config().textureScalingFactor;
|
||||
int hiresWidth = (int)lround(scalingFactor * width);
|
||||
int hiresHeight = (int)lround(scalingFactor * height);
|
||||
hiresBitmap = new Bitmap(hiresWidth, hiresHeight, true);
|
||||
hiresBitmap->setLores(this);
|
||||
}
|
||||
|
||||
TEXFBO tex = shState->texPool().request(width, height);
|
||||
|
||||
p = new BitmapPrivate(this);
|
||||
p->gl = tex;
|
||||
if (p->selfHires != nullptr) {
|
||||
p->gl.selfHires = &p->selfHires->getGLTypes();
|
||||
}
|
||||
p->selfHires = hiresBitmap;
|
||||
|
||||
clear();
|
||||
}
|
||||
|
@ -679,6 +744,10 @@ Bitmap::Bitmap(const Bitmap &other, int frame)
|
|||
other.ensureNonMega();
|
||||
if (frame > -2) other.ensureAnimated();
|
||||
|
||||
if (other.hasHires()) {
|
||||
Debug() << "BUG: High-res Bitmap from animation not implemented";
|
||||
}
|
||||
|
||||
p = new BitmapPrivate(this);
|
||||
|
||||
// TODO: Clean me up
|
||||
|
@ -762,6 +831,28 @@ int Bitmap::height() const
|
|||
return p->gl.height;
|
||||
}
|
||||
|
||||
bool Bitmap::hasHires() const{
|
||||
guardDisposed();
|
||||
|
||||
return p->selfHires;
|
||||
}
|
||||
|
||||
DEF_ATTR_RD_SIMPLE(Bitmap, Hires, Bitmap*, p->selfHires)
|
||||
|
||||
void Bitmap::setHires(Bitmap *hires) {
|
||||
guardDisposed();
|
||||
|
||||
Debug() << "BUG: High-res Bitmap setHires not fully implemented, expect bugs";
|
||||
hires->setLores(this);
|
||||
p->selfHires = hires;
|
||||
}
|
||||
|
||||
void Bitmap::setLores(Bitmap *lores) {
|
||||
guardDisposed();
|
||||
|
||||
p->selfLores = lores;
|
||||
}
|
||||
|
||||
bool Bitmap::isMega() const{
|
||||
guardDisposed();
|
||||
|
||||
|
@ -809,13 +900,35 @@ void Bitmap::stretchBlt(const IntRect &destRect,
|
|||
int opacity)
|
||||
{
|
||||
guardDisposed();
|
||||
|
||||
|
||||
// Don't need this, right? This function is fine with megasurfaces it seems
|
||||
//GUARD_MEGA;
|
||||
|
||||
|
||||
if (source.isDisposed())
|
||||
return;
|
||||
|
||||
|
||||
if (hasHires()) {
|
||||
int destX, destY, destWidth, destHeight;
|
||||
destX = destRect.x * p->selfHires->width() / width();
|
||||
destY = destRect.y * p->selfHires->height() / height();
|
||||
destWidth = destRect.w * p->selfHires->width() / width();
|
||||
destHeight = destRect.h * p->selfHires->height() / height();
|
||||
|
||||
p->selfHires->stretchBlt(IntRect(destX, destY, destWidth, destHeight), source, sourceRect, opacity);
|
||||
return;
|
||||
}
|
||||
|
||||
if (source.hasHires()) {
|
||||
int sourceX, sourceY, sourceWidth, sourceHeight;
|
||||
sourceX = sourceRect.x * source.getHires()->width() / source.width();
|
||||
sourceY = sourceRect.y * source.getHires()->height() / source.height();
|
||||
sourceWidth = sourceRect.w * source.getHires()->width() / source.width();
|
||||
sourceHeight = sourceRect.h * source.getHires()->height() / source.height();
|
||||
|
||||
stretchBlt(destRect, *source.getHires(), IntRect(sourceX, sourceY, sourceWidth, sourceHeight), opacity);
|
||||
return;
|
||||
}
|
||||
|
||||
opacity = clamp(opacity, 0, 255);
|
||||
|
||||
if (opacity == 0)
|
||||
|
@ -936,7 +1049,7 @@ void Bitmap::stretchBlt(const IntRect &destRect,
|
|||
quad.setTexPosRect(sourceRect, destRect);
|
||||
quad.setColor(Vec4(1, 1, 1, normOpacity));
|
||||
|
||||
source.p->bindTexture(shader);
|
||||
source.p->bindTexture(shader, false);
|
||||
p->bindFBO();
|
||||
p->pushSetViewport(shader);
|
||||
|
||||
|
@ -963,6 +1076,16 @@ void Bitmap::fillRect(const IntRect &rect, const Vec4 &color)
|
|||
GUARD_MEGA;
|
||||
GUARD_ANIMATED;
|
||||
|
||||
if (hasHires()) {
|
||||
int destX, destY, destWidth, destHeight;
|
||||
destX = rect.x * p->selfHires->width() / width();
|
||||
destY = rect.y * p->selfHires->height() / height();
|
||||
destWidth = rect.w * p->selfHires->width() / width();
|
||||
destHeight = rect.h * p->selfHires->height() / height();
|
||||
|
||||
p->selfHires->fillRect(IntRect(destX, destY, destWidth, destHeight), color);
|
||||
}
|
||||
|
||||
p->fillRect(rect, color);
|
||||
|
||||
if (color.w == 0)
|
||||
|
@ -992,6 +1115,16 @@ void Bitmap::gradientFillRect(const IntRect &rect,
|
|||
GUARD_MEGA;
|
||||
GUARD_ANIMATED;
|
||||
|
||||
if (hasHires()) {
|
||||
int destX, destY, destWidth, destHeight;
|
||||
destX = rect.x * p->selfHires->width() / width();
|
||||
destY = rect.y * p->selfHires->height() / height();
|
||||
destWidth = rect.w * p->selfHires->width() / width();
|
||||
destHeight = rect.h * p->selfHires->height() / height();
|
||||
|
||||
p->selfHires->gradientFillRect(IntRect(destX, destY, destWidth, destHeight), color1, color2, vertical);
|
||||
}
|
||||
|
||||
SimpleColorShader &shader = shState->shaders().simpleColor;
|
||||
shader.bind();
|
||||
shader.setTranslation(Vec2i());
|
||||
|
@ -1039,6 +1172,16 @@ void Bitmap::clearRect(const IntRect &rect)
|
|||
GUARD_MEGA;
|
||||
GUARD_ANIMATED;
|
||||
|
||||
if (hasHires()) {
|
||||
int destX, destY, destWidth, destHeight;
|
||||
destX = rect.x * p->selfHires->width() / width();
|
||||
destY = rect.y * p->selfHires->height() / height();
|
||||
destWidth = rect.w * p->selfHires->width() / width();
|
||||
destHeight = rect.h * p->selfHires->height() / height();
|
||||
|
||||
p->selfHires->clearRect(IntRect(destX, destY, destWidth, destHeight));
|
||||
}
|
||||
|
||||
p->fillRect(rect, Vec4());
|
||||
|
||||
p->onModified();
|
||||
|
@ -1051,6 +1194,12 @@ void Bitmap::blur()
|
|||
GUARD_MEGA;
|
||||
GUARD_ANIMATED;
|
||||
|
||||
if (hasHires()) {
|
||||
p->selfHires->blur();
|
||||
}
|
||||
|
||||
// TODO: Is there some kind of blur radius that we need to handle for high-res mode?
|
||||
|
||||
Quad &quad = shState->gpQuad();
|
||||
FloatRect rect(0, 0, width(), height());
|
||||
quad.setTexPosRect(rect, rect);
|
||||
|
@ -1097,6 +1246,11 @@ void Bitmap::radialBlur(int angle, int divisions)
|
|||
GUARD_MEGA;
|
||||
GUARD_ANIMATED;
|
||||
|
||||
if (hasHires()) {
|
||||
p->selfHires->radialBlur(angle, divisions);
|
||||
return;
|
||||
}
|
||||
|
||||
angle = clamp<int>(angle, 0, 359);
|
||||
divisions = clamp<int>(divisions, 2, 100);
|
||||
|
||||
|
@ -1161,7 +1315,7 @@ void Bitmap::radialBlur(int angle, int divisions)
|
|||
SimpleMatrixShader &shader = shState->shaders().simpleMatrix;
|
||||
shader.bind();
|
||||
|
||||
p->bindTexture(shader);
|
||||
p->bindTexture(shader, false);
|
||||
TEX::setSmooth(true);
|
||||
|
||||
p->pushSetViewport(shader);
|
||||
|
@ -1193,6 +1347,10 @@ void Bitmap::clear()
|
|||
GUARD_MEGA;
|
||||
GUARD_ANIMATED;
|
||||
|
||||
if (hasHires()) {
|
||||
p->selfHires->clear();
|
||||
}
|
||||
|
||||
p->bindFBO();
|
||||
|
||||
glState.clearColor.pushSet(Vec4());
|
||||
|
@ -1221,9 +1379,52 @@ Color Bitmap::getPixel(int x, int y) const
|
|||
GUARD_MEGA;
|
||||
GUARD_ANIMATED;
|
||||
|
||||
if (hasHires()) {
|
||||
Debug() << "GAME BUG: Game is calling getPixel on low-res Bitmap; you may want to patch the game to improve graphics quality.";
|
||||
|
||||
int xHires = x * p->selfHires->width() / width();
|
||||
int yHires = y * p->selfHires->height() / height();
|
||||
|
||||
// We take the average color from the high-res Bitmap.
|
||||
// RGB channels skip fully transparent pixels when averaging.
|
||||
int w = p->selfHires->width() / width();
|
||||
int h = p->selfHires->height() / height();
|
||||
|
||||
if (w >= 1 && h >= 1) {
|
||||
double rSum = 0.;
|
||||
double gSum = 0.;
|
||||
double bSum = 0.;
|
||||
double aSum = 0.;
|
||||
|
||||
long long rgbCount = 0;
|
||||
long long aCount = 0;
|
||||
|
||||
for (int thisX = xHires; thisX < xHires+w && thisX < p->selfHires->width(); thisX++) {
|
||||
for (int thisY = yHires; thisY < yHires+h && thisY < p->selfHires->height(); thisY++) {
|
||||
Color thisColor = p->selfHires->getPixel(thisX, thisY);
|
||||
if (thisColor.getAlpha() >= 1.0) {
|
||||
rSum += thisColor.getRed();
|
||||
gSum += thisColor.getGreen();
|
||||
bSum += thisColor.getBlue();
|
||||
rgbCount++;
|
||||
}
|
||||
aSum += thisColor.getAlpha();
|
||||
aCount++;
|
||||
}
|
||||
}
|
||||
|
||||
double rAvg = rSum / (double)rgbCount;
|
||||
double gAvg = gSum / (double)rgbCount;
|
||||
double bAvg = bSum / (double)rgbCount;
|
||||
double aAvg = aSum / (double)aCount;
|
||||
|
||||
return Color(rAvg, gAvg, bAvg, aAvg);
|
||||
}
|
||||
}
|
||||
|
||||
if (x < 0 || y < 0 || x >= width() || y >= height())
|
||||
return Vec4();
|
||||
|
||||
|
||||
if (!p->surface)
|
||||
{
|
||||
p->allocSurface();
|
||||
|
@ -1252,6 +1453,24 @@ void Bitmap::setPixel(int x, int y, const Color &color)
|
|||
GUARD_MEGA;
|
||||
GUARD_ANIMATED;
|
||||
|
||||
if (hasHires()) {
|
||||
Debug() << "GAME BUG: Game is calling setPixel on low-res Bitmap; you may want to patch the game to improve graphics quality.";
|
||||
|
||||
int xHires = x * p->selfHires->width() / width();
|
||||
int yHires = y * p->selfHires->height() / height();
|
||||
|
||||
int w = p->selfHires->width() / width();
|
||||
int h = p->selfHires->height() / height();
|
||||
|
||||
if (w >= 1 && h >= 1) {
|
||||
for (int thisX = xHires; thisX < xHires+w && thisX < p->selfHires->width(); thisX++) {
|
||||
for (int thisY = yHires; thisY < yHires+h && thisY < p->selfHires->height(); thisY++) {
|
||||
p->selfHires->setPixel(thisX, thisY, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t pixel[] =
|
||||
{
|
||||
(uint8_t) clamp<double>(color.red, 0, 255),
|
||||
|
@ -1283,6 +1502,10 @@ bool Bitmap::getRaw(void *output, int output_size)
|
|||
|
||||
guardDisposed();
|
||||
|
||||
if (hasHires()) {
|
||||
Debug() << "GAME BUG: Game is calling getRaw on low-res Bitmap; you may want to patch the game to improve graphics quality.";
|
||||
}
|
||||
|
||||
if (!p->animation.enabled && (p->surface || p->megaSurface)) {
|
||||
void *src = (p->megaSurface) ? p->megaSurface->pixels : p->surface->pixels;
|
||||
memcpy(output, src, output_size);
|
||||
|
@ -1300,6 +1523,10 @@ void Bitmap::replaceRaw(void *pixel_data, int size)
|
|||
|
||||
GUARD_MEGA;
|
||||
|
||||
if (hasHires()) {
|
||||
Debug() << "GAME BUG: Game is calling replaceRaw on low-res Bitmap; you may want to patch the game to improve graphics quality.";
|
||||
}
|
||||
|
||||
int w = width();
|
||||
int h = height();
|
||||
int requiredsize = w*h*4;
|
||||
|
@ -1318,6 +1545,10 @@ void Bitmap::saveToFile(const char *filename)
|
|||
{
|
||||
guardDisposed();
|
||||
|
||||
if (hasHires()) {
|
||||
Debug() << "GAME BUG: Game is calling saveToFile on low-res Bitmap; you may want to patch the game to improve graphics quality.";
|
||||
}
|
||||
|
||||
SDL_Surface *surf;
|
||||
|
||||
if (p->surface || p->megaSurface) {
|
||||
|
@ -1377,6 +1608,11 @@ void Bitmap::hueChange(int hue)
|
|||
GUARD_MEGA;
|
||||
GUARD_ANIMATED;
|
||||
|
||||
if (hasHires()) {
|
||||
p->selfHires->hueChange(hue);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((hue % 360) == 0)
|
||||
return;
|
||||
|
||||
|
@ -1395,7 +1631,7 @@ void Bitmap::hueChange(int hue)
|
|||
|
||||
FBO::bind(newTex.fbo);
|
||||
p->pushSetViewport(shader);
|
||||
p->bindTexture(shader);
|
||||
p->bindTexture(shader, false);
|
||||
|
||||
p->blitQuad(quad);
|
||||
|
||||
|
@ -1525,6 +1761,26 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align)
|
|||
GUARD_MEGA;
|
||||
GUARD_ANIMATED;
|
||||
|
||||
if (hasHires()) {
|
||||
Font &loresFont = getFont();
|
||||
Font &hiresFont = p->selfHires->getFont();
|
||||
// Disable the illegal font size check when creating a high-res font.
|
||||
hiresFont.setSize(loresFont.getSize() * p->selfHires->width() / width(), false);
|
||||
hiresFont.setBold(loresFont.getBold());
|
||||
hiresFont.setColor(loresFont.getColor());
|
||||
hiresFont.setItalic(loresFont.getItalic());
|
||||
hiresFont.setShadow(loresFont.getShadow());
|
||||
hiresFont.setOutline(loresFont.getOutline());
|
||||
hiresFont.setOutColor(loresFont.getOutColor());
|
||||
|
||||
int rectX = rect.x * p->selfHires->width() / width();
|
||||
int rectY = rect.y * p->selfHires->height() / height();
|
||||
int rectWidth = rect.w * p->selfHires->width() / width();
|
||||
int rectHeight = rect.h * p->selfHires->height() / height();
|
||||
|
||||
p->selfHires->drawText(IntRect(rectX, rectY, rectWidth, rectHeight), str, align);
|
||||
}
|
||||
|
||||
std::string fixed = fixupString(str);
|
||||
str = fixed.c_str();
|
||||
|
||||
|
@ -1564,15 +1820,20 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align)
|
|||
SDL_Color co = outColor.toSDLColor();
|
||||
co.a = 255;
|
||||
SDL_Surface *outline;
|
||||
// Handle high-res for outline.
|
||||
int scaledOutlineSize = OUTLINE_SIZE;
|
||||
if (p->selfLores) {
|
||||
scaledOutlineSize = scaledOutlineSize * width() / p->selfLores->width();
|
||||
}
|
||||
/* set the next font render to render the outline */
|
||||
TTF_SetFontOutline(font, OUTLINE_SIZE);
|
||||
TTF_SetFontOutline(font, scaledOutlineSize);
|
||||
if (p->font->isSolid())
|
||||
outline = TTF_RenderUTF8_Solid(font, str, co);
|
||||
else
|
||||
outline = TTF_RenderUTF8_Blended(font, str, co);
|
||||
|
||||
p->ensureFormat(outline, SDL_PIXELFORMAT_ABGR8888);
|
||||
SDL_Rect outRect = {OUTLINE_SIZE, OUTLINE_SIZE, txtSurf->w, txtSurf->h};
|
||||
SDL_Rect outRect = {scaledOutlineSize, scaledOutlineSize, txtSurf->w, txtSurf->h};
|
||||
|
||||
SDL_SetSurfaceBlendMode(txtSurf, SDL_BLENDMODE_BLEND);
|
||||
SDL_BlitSurface(txtSurf, NULL, outline, &outRect);
|
||||
|
@ -1787,6 +2048,9 @@ IntRect Bitmap::textSize(const char *str)
|
|||
GUARD_MEGA;
|
||||
GUARD_ANIMATED;
|
||||
|
||||
// TODO: High-res Bitmap textSize not implemented, but I think it's the same as low-res?
|
||||
// Need to double-check this.
|
||||
|
||||
TTF_Font *font = p->font->getSdlFont();
|
||||
|
||||
std::string fixed = fixupString(str);
|
||||
|
@ -1811,11 +2075,19 @@ DEF_ATTR_RD_SIMPLE(Bitmap, Font, Font&, *p->font)
|
|||
|
||||
void Bitmap::setFont(Font &value)
|
||||
{
|
||||
// High-res support handled in drawText, not here.
|
||||
*p->font = value;
|
||||
}
|
||||
|
||||
void Bitmap::setInitFont(Font *value)
|
||||
{
|
||||
if (hasHires()) {
|
||||
Font *hiresFont = new Font(*value);
|
||||
// Disable the illegal font size check when creating a high-res font.
|
||||
hiresFont->setSize(hiresFont->getSize() * p->selfHires->width() / width(), false);
|
||||
p->selfHires->setInitFont(hiresFont);
|
||||
}
|
||||
|
||||
p->font = value;
|
||||
}
|
||||
|
||||
|
@ -1826,11 +2098,24 @@ TEXFBO &Bitmap::getGLTypes() const
|
|||
|
||||
SDL_Surface *Bitmap::surface() const
|
||||
{
|
||||
if (hasHires()) {
|
||||
Debug() << "BUG: High-res Bitmap surface not implemented";
|
||||
}
|
||||
|
||||
return p->surface;
|
||||
}
|
||||
|
||||
SDL_Surface *Bitmap::megaSurface() const
|
||||
{
|
||||
if (hasHires()) {
|
||||
if (p->megaSurface) {
|
||||
Debug() << "BUG: High-res Bitmap megaSurface not implemented (low-res has megaSurface)";
|
||||
}
|
||||
if (p->selfHires->megaSurface()) {
|
||||
Debug() << "BUG: High-res Bitmap megaSurface not implemented (high-res has megaSurface)";
|
||||
}
|
||||
}
|
||||
|
||||
return p->megaSurface;
|
||||
}
|
||||
|
||||
|
@ -1865,6 +2150,10 @@ void Bitmap::stop()
|
|||
GUARD_UNANIMATED;
|
||||
if (!p->animation.playing) return;
|
||||
|
||||
if (hasHires()) {
|
||||
Debug() << "BUG: High-res Bitmap stop not implemented";
|
||||
}
|
||||
|
||||
p->animation.stop();
|
||||
}
|
||||
|
||||
|
@ -1874,6 +2163,11 @@ void Bitmap::play()
|
|||
|
||||
GUARD_UNANIMATED;
|
||||
if (p->animation.playing) return;
|
||||
|
||||
if (hasHires()) {
|
||||
Debug() << "BUG: High-res Bitmap play not implemented";
|
||||
}
|
||||
|
||||
p->animation.play();
|
||||
}
|
||||
|
||||
|
@ -1881,6 +2175,10 @@ bool Bitmap::isPlaying() const
|
|||
{
|
||||
guardDisposed();
|
||||
|
||||
if (hasHires()) {
|
||||
Debug() << "BUG: High-res Bitmap isPlaying not implemented";
|
||||
}
|
||||
|
||||
if (!p->animation.playing)
|
||||
return false;
|
||||
|
||||
|
@ -1896,6 +2194,10 @@ void Bitmap::gotoAndStop(int frame)
|
|||
|
||||
GUARD_UNANIMATED;
|
||||
|
||||
if (hasHires()) {
|
||||
Debug() << "BUG: High-res Bitmap gotoAndStop not implemented";
|
||||
}
|
||||
|
||||
p->animation.stop();
|
||||
p->animation.seek(frame);
|
||||
}
|
||||
|
@ -1905,6 +2207,10 @@ void Bitmap::gotoAndPlay(int frame)
|
|||
|
||||
GUARD_UNANIMATED;
|
||||
|
||||
if (hasHires()) {
|
||||
Debug() << "BUG: High-res Bitmap gotoAndPlay not implemented";
|
||||
}
|
||||
|
||||
p->animation.stop();
|
||||
p->animation.seek(frame);
|
||||
p->animation.play();
|
||||
|
@ -1914,6 +2220,10 @@ int Bitmap::numFrames() const
|
|||
{
|
||||
guardDisposed();
|
||||
|
||||
if (hasHires()) {
|
||||
Debug() << "BUG: High-res Bitmap numFrames not implemented";
|
||||
}
|
||||
|
||||
if (!p->animation.enabled) return 1;
|
||||
return (int)p->animation.frames.size();
|
||||
}
|
||||
|
@ -1922,6 +2232,10 @@ int Bitmap::currentFrameI() const
|
|||
{
|
||||
guardDisposed();
|
||||
|
||||
if (hasHires()) {
|
||||
Debug() << "BUG: High-res Bitmap currentFrameI not implemented";
|
||||
}
|
||||
|
||||
if (!p->animation.enabled) return 0;
|
||||
return p->animation.currentFrameI();
|
||||
}
|
||||
|
@ -1932,6 +2246,14 @@ int Bitmap::addFrame(Bitmap &source, int position)
|
|||
|
||||
GUARD_MEGA;
|
||||
|
||||
if (hasHires()) {
|
||||
Debug() << "BUG: High-res Bitmap addFrame dest not implemented";
|
||||
}
|
||||
|
||||
if (source.hasHires()) {
|
||||
Debug() << "BUG: High-res Bitmap addFrame source not implemented";
|
||||
}
|
||||
|
||||
if (source.height() != height() || source.width() != width())
|
||||
throw Exception(Exception::MKXPError, "Animations with varying dimensions are not supported (%ix%i vs %ix%i)",
|
||||
source.width(), source.height(), width(), height());
|
||||
|
@ -1989,6 +2311,10 @@ void Bitmap::removeFrame(int position) {
|
|||
|
||||
GUARD_UNANIMATED;
|
||||
|
||||
if (hasHires()) {
|
||||
Debug() << "BUG: High-res Bitmap removeFrame not implemented";
|
||||
}
|
||||
|
||||
int pos = (position < 0) ? (int)p->animation.frames.size() - 1 : clamp(position, 0, (int)(p->animation.frames.size() - 1));
|
||||
shState->texPool().release(p->animation.frames[pos]);
|
||||
p->animation.frames.erase(p->animation.frames.begin() + pos);
|
||||
|
@ -2016,6 +2342,10 @@ void Bitmap::nextFrame()
|
|||
|
||||
GUARD_UNANIMATED;
|
||||
|
||||
if (hasHires()) {
|
||||
Debug() << "BUG: High-res Bitmap nextFrame not implemented";
|
||||
}
|
||||
|
||||
stop();
|
||||
if ((uint32_t)p->animation.lastFrame >= p->animation.frames.size() - 1) {
|
||||
if (!p->animation.loop) return;
|
||||
|
@ -2032,6 +2362,10 @@ void Bitmap::previousFrame()
|
|||
|
||||
GUARD_UNANIMATED;
|
||||
|
||||
if (hasHires()) {
|
||||
Debug() << "BUG: High-res Bitmap previousFrame not implemented";
|
||||
}
|
||||
|
||||
stop();
|
||||
if (p->animation.lastFrame <= 0) {
|
||||
if (!p->animation.loop) {
|
||||
|
@ -2051,6 +2385,10 @@ void Bitmap::setAnimationFPS(float FPS)
|
|||
|
||||
GUARD_MEGA;
|
||||
|
||||
if (hasHires()) {
|
||||
Debug() << "BUG: High-res Bitmap setAnimationFPS not implemented";
|
||||
}
|
||||
|
||||
bool restart = p->animation.playing;
|
||||
p->animation.stop();
|
||||
p->animation.fps = (FPS < 0) ? 0 : FPS;
|
||||
|
@ -2059,6 +2397,10 @@ void Bitmap::setAnimationFPS(float FPS)
|
|||
|
||||
std::vector<TEXFBO> &Bitmap::getFrames() const
|
||||
{
|
||||
if (hasHires()) {
|
||||
Debug() << "BUG: High-res Bitmap getFrames not implemented";
|
||||
}
|
||||
|
||||
return p->animation.frames;
|
||||
}
|
||||
|
||||
|
@ -2068,6 +2410,10 @@ float Bitmap::getAnimationFPS() const
|
|||
|
||||
GUARD_MEGA;
|
||||
|
||||
if (hasHires()) {
|
||||
Debug() << "BUG: High-res Bitmap getAnimationFPS not implemented";
|
||||
}
|
||||
|
||||
return p->animation.fps;
|
||||
}
|
||||
|
||||
|
@ -2077,6 +2423,10 @@ void Bitmap::setLooping(bool loop)
|
|||
|
||||
GUARD_MEGA;
|
||||
|
||||
if (hasHires()) {
|
||||
Debug() << "BUG: High-res Bitmap setLooping not implemented";
|
||||
}
|
||||
|
||||
p->animation.loop = loop;
|
||||
}
|
||||
|
||||
|
@ -2086,16 +2436,32 @@ bool Bitmap::getLooping() const
|
|||
|
||||
GUARD_MEGA;
|
||||
|
||||
if (hasHires()) {
|
||||
Debug() << "BUG: High-res Bitmap getLooping not implemented";
|
||||
}
|
||||
|
||||
return p->animation.loop;
|
||||
}
|
||||
|
||||
void Bitmap::bindTex(ShaderBase &shader)
|
||||
{
|
||||
// Hires mode is handled by p->bindTexture.
|
||||
|
||||
p->bindTexture(shader);
|
||||
}
|
||||
|
||||
void Bitmap::taintArea(const IntRect &rect)
|
||||
{
|
||||
if (hasHires()) {
|
||||
int destX, destY, destWidth, destHeight;
|
||||
destX = rect.x * p->selfHires->width() / width();
|
||||
destY = rect.y * p->selfHires->height() / height();
|
||||
destWidth = rect.w * p->selfHires->width() / width();
|
||||
destHeight = rect.h * p->selfHires->height() / height();
|
||||
|
||||
p->selfHires->taintArea(IntRect(destX, destY, destWidth, destHeight));
|
||||
}
|
||||
|
||||
p->addTaintedArea(rect);
|
||||
}
|
||||
|
||||
|
@ -2121,8 +2487,17 @@ bool Bitmap::invalid() const {
|
|||
return p == 0;
|
||||
}
|
||||
|
||||
void Bitmap::assumeRubyGC()
|
||||
{
|
||||
p->assumingRubyGC = true;
|
||||
}
|
||||
|
||||
void Bitmap::releaseResources()
|
||||
{
|
||||
if (p->selfHires && !p->assumingRubyGC) {
|
||||
delete p->selfHires;
|
||||
}
|
||||
|
||||
if (p->megaSurface)
|
||||
SDL_FreeSurface(p->megaSurface);
|
||||
else if (p->animation.enabled) {
|
||||
|
|
|
@ -39,7 +39,7 @@ class Bitmap : public Disposable
|
|||
{
|
||||
public:
|
||||
Bitmap(const char *filename);
|
||||
Bitmap(int width, int height);
|
||||
Bitmap(int width, int height, bool isHires = false);
|
||||
Bitmap(void *pixeldata, int width, int height);
|
||||
/* Clone constructor */
|
||||
|
||||
|
@ -49,6 +49,9 @@ public:
|
|||
|
||||
int width() const;
|
||||
int height() const;
|
||||
bool hasHires() const;
|
||||
DECL_ATTR(Hires, Bitmap*)
|
||||
void setLores(Bitmap *lores);
|
||||
bool isMega() const;
|
||||
bool isAnimated() const;
|
||||
|
||||
|
@ -161,6 +164,8 @@ public:
|
|||
|
||||
bool invalid() const;
|
||||
|
||||
void assumeRubyGC();
|
||||
|
||||
private:
|
||||
void releaseResources();
|
||||
const char *klassName() const { return "bitmap"; }
|
||||
|
|
|
@ -399,14 +399,17 @@ void Font::setName(const std::vector<std::string> &names)
|
|||
p->sdlFont = 0;
|
||||
}
|
||||
|
||||
void Font::setSize(int value)
|
||||
void Font::setSize(int value, bool checkIllegal)
|
||||
{
|
||||
if (p->size == value)
|
||||
return;
|
||||
|
||||
/* Catch illegal values (according to RMXP) */
|
||||
if (value < 6 || value > 96)
|
||||
throw Exception(Exception::ArgumentError, "%s", "bad value for size");
|
||||
if (value < 6 || value > 96) {
|
||||
if (checkIllegal) {
|
||||
throw Exception(Exception::ArgumentError, "%s", "bad value for size");
|
||||
}
|
||||
}
|
||||
|
||||
p->size = value;
|
||||
p->sdlFont = 0;
|
||||
|
|
|
@ -76,7 +76,9 @@ public:
|
|||
|
||||
const Font &operator=(const Font &o);
|
||||
|
||||
DECL_ATTR( Size, int )
|
||||
int getSize() const;
|
||||
void setSize(int value, bool checkIllegal=true);
|
||||
|
||||
DECL_ATTR( Bold, bool )
|
||||
DECL_ATTR( Italic, bool )
|
||||
DECL_ATTR( Color, Color& )
|
||||
|
|
|
@ -26,6 +26,11 @@
|
|||
#include "quad.h"
|
||||
#include "config.h"
|
||||
|
||||
namespace FBO
|
||||
{
|
||||
ID boundFramebufferID;
|
||||
}
|
||||
|
||||
namespace GLMeta
|
||||
{
|
||||
|
||||
|
@ -138,6 +143,7 @@ static void _blitBegin(FBO::ID fbo, const Vec2i &size)
|
|||
{
|
||||
if (HAVE_NATIVE_BLIT)
|
||||
{
|
||||
FBO::boundFramebufferID = fbo;
|
||||
gl.BindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo.gl);
|
||||
}
|
||||
else
|
||||
|
@ -164,18 +170,56 @@ static void _blitBegin(FBO::ID fbo, const Vec2i &size)
|
|||
}
|
||||
}
|
||||
|
||||
void blitBegin(TEXFBO &target)
|
||||
int blitDstWidthLores = 1;
|
||||
int blitDstWidthHires = 1;
|
||||
int blitDstHeightLores = 1;
|
||||
int blitDstHeightHires = 1;
|
||||
|
||||
int blitSrcWidthLores = 1;
|
||||
int blitSrcWidthHires = 1;
|
||||
int blitSrcHeightLores = 1;
|
||||
int blitSrcHeightHires = 1;
|
||||
|
||||
void blitBegin(TEXFBO &target, bool preferHires)
|
||||
{
|
||||
_blitBegin(target.fbo, Vec2i(target.width, target.height));
|
||||
blitDstWidthLores = target.width;
|
||||
blitDstHeightLores = target.height;
|
||||
|
||||
if (preferHires && target.selfHires != nullptr) {
|
||||
blitDstWidthHires = target.selfHires->width;
|
||||
blitDstHeightHires = target.selfHires->height;
|
||||
_blitBegin(target.selfHires->fbo, Vec2i(target.selfHires->width, target.selfHires->height));
|
||||
}
|
||||
else {
|
||||
blitDstWidthHires = blitDstWidthLores;
|
||||
blitDstHeightHires = blitDstHeightLores;
|
||||
_blitBegin(target.fbo, Vec2i(target.width, target.height));
|
||||
}
|
||||
}
|
||||
|
||||
void blitBeginScreen(const Vec2i &size)
|
||||
{
|
||||
blitDstWidthLores = 1;
|
||||
blitDstWidthHires = 1;
|
||||
blitDstHeightLores = 1;
|
||||
blitDstHeightHires = 1;
|
||||
|
||||
_blitBegin(FBO::ID(0), size);
|
||||
}
|
||||
|
||||
void blitSource(TEXFBO &source)
|
||||
{
|
||||
blitSrcWidthLores = source.width;
|
||||
blitSrcHeightLores = source.height;
|
||||
if (source.selfHires != nullptr) {
|
||||
blitSrcWidthHires = source.selfHires->width;
|
||||
blitSrcHeightHires = source.selfHires->height;
|
||||
}
|
||||
else {
|
||||
blitSrcWidthHires = blitSrcWidthLores;
|
||||
blitSrcHeightHires = blitSrcHeightLores;
|
||||
}
|
||||
|
||||
if (HAVE_NATIVE_BLIT)
|
||||
{
|
||||
gl.BindFramebuffer(GL_READ_FRAMEBUFFER, source.fbo.gl);
|
||||
|
@ -186,15 +230,20 @@ void blitSource(TEXFBO &source)
|
|||
{
|
||||
Lanczos3Shader &shader = shState->shaders().lanczos3;
|
||||
shader.bind();
|
||||
shader.setTexSize(Vec2i(source.width, source.height));
|
||||
shader.setTexSize(Vec2i(blitSrcWidthHires, blitSrcHeightHires));
|
||||
}
|
||||
else
|
||||
{
|
||||
SimpleShader &shader = shState->shaders().simple;
|
||||
shader.bind();
|
||||
shader.setTexSize(Vec2i(source.width, source.height));
|
||||
shader.setTexSize(Vec2i(blitSrcWidthHires, blitSrcHeightHires));
|
||||
}
|
||||
if (source.selfHires != nullptr) {
|
||||
TEX::bind(source.selfHires->tex);
|
||||
}
|
||||
else {
|
||||
TEX::bind(source.tex);
|
||||
}
|
||||
TEX::bind(source.tex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -205,10 +254,24 @@ void blitRectangle(const IntRect &src, const Vec2i &dstPos)
|
|||
|
||||
void blitRectangle(const IntRect &src, const IntRect &dst, bool smooth)
|
||||
{
|
||||
// Handle high-res dest
|
||||
int scaledDstX = dst.x * blitDstWidthHires / blitDstWidthLores;
|
||||
int scaledDstY = dst.y * blitDstHeightHires / blitDstHeightLores;
|
||||
int scaledDstWidth = dst.w * blitDstWidthHires / blitDstWidthLores;
|
||||
int scaledDstHeight = dst.h * blitDstHeightHires / blitDstHeightLores;
|
||||
IntRect dstScaled(scaledDstX, scaledDstY, scaledDstWidth, scaledDstHeight);
|
||||
|
||||
// Handle high-res source
|
||||
int scaledSrcX = src.x * blitSrcWidthHires / blitSrcWidthLores;
|
||||
int scaledSrcY = src.y * blitSrcHeightHires / blitSrcHeightLores;
|
||||
int scaledSrcWidth = src.w * blitSrcWidthHires / blitSrcWidthLores;
|
||||
int scaledSrcHeight = src.h * blitSrcHeightHires / blitSrcHeightLores;
|
||||
IntRect srcScaled(scaledSrcX, scaledSrcY, scaledSrcWidth, scaledSrcHeight);
|
||||
|
||||
if (HAVE_NATIVE_BLIT)
|
||||
{
|
||||
gl.BlitFramebuffer(src.x, src.y, src.x+src.w, src.y+src.h,
|
||||
dst.x, dst.y, dst.x+dst.w, dst.y+dst.h,
|
||||
gl.BlitFramebuffer(srcScaled.x, srcScaled.y, srcScaled.x+srcScaled.w, srcScaled.y+srcScaled.h,
|
||||
dstScaled.x, dstScaled.y, dstScaled.x+dstScaled.w, dstScaled.y+dstScaled.h,
|
||||
GL_COLOR_BUFFER_BIT, smooth ? GL_LINEAR : GL_NEAREST);
|
||||
}
|
||||
else
|
||||
|
@ -218,7 +281,7 @@ void blitRectangle(const IntRect &src, const IntRect &dst, bool smooth)
|
|||
|
||||
glState.blend.pushSet(false);
|
||||
Quad &quad = shState->gpQuad();
|
||||
quad.setTexPosRect(src, dst);
|
||||
quad.setTexPosRect(srcScaled, dstScaled);
|
||||
quad.draw();
|
||||
glState.blend.pop();
|
||||
|
||||
|
@ -229,8 +292,19 @@ void blitRectangle(const IntRect &src, const IntRect &dst, bool smooth)
|
|||
|
||||
void blitEnd()
|
||||
{
|
||||
if (!HAVE_NATIVE_BLIT)
|
||||
blitDstWidthLores = 1;
|
||||
blitDstWidthHires = 1;
|
||||
blitDstHeightLores = 1;
|
||||
blitDstHeightHires = 1;
|
||||
|
||||
blitSrcWidthLores = 1;
|
||||
blitSrcWidthHires = 1;
|
||||
blitSrcHeightLores = 1;
|
||||
blitSrcHeightHires = 1;
|
||||
|
||||
if (!HAVE_NATIVE_BLIT) {
|
||||
glState.viewport.pop();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ void vaoBind(VAO &vao);
|
|||
void vaoUnbind(VAO &vao);
|
||||
|
||||
/* EXT_framebuffer_blit */
|
||||
void blitBegin(TEXFBO &target);
|
||||
void blitBegin(TEXFBO &target, bool preferHires = false);
|
||||
void blitBeginScreen(const Vec2i &size);
|
||||
void blitSource(TEXFBO &source);
|
||||
void blitRectangle(const IntRect &src, const Vec2i &dstPos);
|
||||
|
|
|
@ -109,6 +109,8 @@ namespace FBO
|
|||
{
|
||||
DEF_GL_ID
|
||||
|
||||
extern ID boundFramebufferID;
|
||||
|
||||
inline ID gen()
|
||||
{
|
||||
ID id;
|
||||
|
@ -124,6 +126,7 @@ namespace FBO
|
|||
|
||||
static inline void bind(ID id)
|
||||
{
|
||||
boundFramebufferID = id;
|
||||
gl.BindFramebuffer(GL_FRAMEBUFFER, id.gl);
|
||||
}
|
||||
|
||||
|
@ -203,8 +206,10 @@ struct TEXFBO
|
|||
FBO::ID fbo;
|
||||
int width, height;
|
||||
|
||||
TEXFBO *selfHires;
|
||||
|
||||
TEXFBO()
|
||||
: tex(0), fbo(0), width(0), height(0)
|
||||
: tex(0), fbo(0), width(0), height(0), selfHires(nullptr)
|
||||
{}
|
||||
|
||||
bool operator==(const TEXFBO &other) const
|
||||
|
|
|
@ -23,7 +23,9 @@
|
|||
#include "config.h"
|
||||
#include "etc.h"
|
||||
#include "gl-fun.h"
|
||||
#include "graphics.h"
|
||||
#include "shader.h"
|
||||
#include "sharedstate.h"
|
||||
|
||||
#include <SDL_rect.h>
|
||||
|
||||
|
@ -36,7 +38,19 @@ void GLClearColor::apply(const Vec4 &value) {
|
|||
}
|
||||
|
||||
void GLScissorBox::apply(const IntRect &value) {
|
||||
gl.Scissor(value.x, value.y, value.w, value.h);
|
||||
// High-res: scale the scissorbox if we're rendering to the PingPong framebuffer.
|
||||
if (shState) {
|
||||
const double framebufferScalingFactor = shState->config().framebufferScalingFactor;
|
||||
if (shState->config().enableHires && shState->graphics().isPingPongFramebufferActive()) {
|
||||
gl.Scissor((int)lround(framebufferScalingFactor * value.x), (int)lround(framebufferScalingFactor * value.y), (int)lround(framebufferScalingFactor * value.w), (int)lround(framebufferScalingFactor * value.h));
|
||||
}
|
||||
else {
|
||||
gl.Scissor(value.x, value.y, value.w, value.h);
|
||||
}
|
||||
}
|
||||
else {
|
||||
gl.Scissor(value.x, value.y, value.w, value.h);
|
||||
}
|
||||
}
|
||||
|
||||
void GLScissorBox::setIntersect(const IntRect &value) {
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#ifndef QUAD_H
|
||||
#define QUAD_H
|
||||
|
||||
#include "config.h"
|
||||
#include "graphics.h"
|
||||
#include "vertex.h"
|
||||
#include "gl-util.h"
|
||||
#include "gl-meta.h"
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
*/
|
||||
|
||||
#include "shader.h"
|
||||
#include "config.h"
|
||||
#include "graphics.h"
|
||||
#include "sharedstate.h"
|
||||
#include "glstate.h"
|
||||
#include "exception.h"
|
||||
|
@ -293,8 +295,19 @@ void ShaderBase::init()
|
|||
|
||||
void ShaderBase::applyViewportProj()
|
||||
{
|
||||
// High-res: scale the matrix if we're rendering to the PingPong framebuffer.
|
||||
const IntRect &vp = glState.viewport.get();
|
||||
projMat.set(Vec2i(vp.w, vp.h));
|
||||
if (shState->config().enableHires && shState->graphics().isPingPongFramebufferActive() && framebufferScalingAllowed()) {
|
||||
projMat.set(Vec2i(shState->graphics().width(), shState->graphics().height()));
|
||||
}
|
||||
else {
|
||||
projMat.set(Vec2i(vp.w, vp.h));
|
||||
}
|
||||
}
|
||||
|
||||
bool ShaderBase::framebufferScalingAllowed()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void ShaderBase::setTexSize(const Vec2i &value)
|
||||
|
@ -593,6 +606,13 @@ GrayShader::GrayShader()
|
|||
GET_U(gray);
|
||||
}
|
||||
|
||||
bool GrayShader::framebufferScalingAllowed()
|
||||
{
|
||||
// This shader is used with input textures that have already had a
|
||||
// framebuffer scale applied. So we don't want to double-apply it.
|
||||
return false;
|
||||
}
|
||||
|
||||
void GrayShader::setGray(float value)
|
||||
{
|
||||
gl.Uniform1f(u_gray, value);
|
||||
|
|
|
@ -91,6 +91,7 @@ public:
|
|||
|
||||
protected:
|
||||
void init();
|
||||
virtual bool framebufferScalingAllowed();
|
||||
|
||||
GLint u_texSizeInv, u_translation;
|
||||
};
|
||||
|
@ -226,6 +227,9 @@ public:
|
|||
|
||||
void setGray(float value);
|
||||
|
||||
protected:
|
||||
virtual bool framebufferScalingAllowed();
|
||||
|
||||
private:
|
||||
GLint u_gray;
|
||||
};
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "tilemap-common.h"
|
||||
#include "bitmap.h"
|
||||
#include "table.h"
|
||||
#include "debugwriter.h"
|
||||
#include "etc-internal.h"
|
||||
#include "gl-util.h"
|
||||
#include "gl-meta.h"
|
||||
|
@ -273,7 +274,7 @@ void build(TEXFBO &tf, Bitmap *bitmaps[BM_COUNT])
|
|||
{
|
||||
assert(tf.width == ATLASVX_W && tf.height == ATLASVX_H);
|
||||
|
||||
GLMeta::blitBegin(tf);
|
||||
GLMeta::blitBegin(tf, true);
|
||||
|
||||
glState.clearColor.pushSet(Vec4());
|
||||
FBO::clear();
|
||||
|
@ -282,13 +283,36 @@ void build(TEXFBO &tf, Bitmap *bitmaps[BM_COUNT])
|
|||
if (rgssVer >= 3)
|
||||
{
|
||||
SDL_Surface *shadow = createShadowSet();
|
||||
TEX::bind(tf.tex);
|
||||
TEX::uploadSubImage(shadowArea.x*32, shadowArea.y*32,
|
||||
shadow->w, shadow->h, shadow->pixels, GL_RGBA);
|
||||
if (tf.selfHires != nullptr) {
|
||||
SDL_Rect srcRect({0, 0, shadow->w, shadow->h});
|
||||
int destX = shadowArea.x*32 * tf.selfHires->width / tf.width;
|
||||
int destY = shadowArea.y*32 * tf.selfHires->height / tf.height;
|
||||
int destWidth = shadow->w * tf.selfHires->width / tf.width;
|
||||
int destHeight = shadow->h * tf.selfHires->height / tf.height;
|
||||
|
||||
int bpp;
|
||||
Uint32 rMask, gMask, bMask, aMask;
|
||||
SDL_PixelFormatEnumToMasks(SDL_PIXELFORMAT_ABGR8888,
|
||||
&bpp, &rMask, &gMask, &bMask, &aMask);
|
||||
SDL_Surface *blitTemp =
|
||||
SDL_CreateRGBSurface(0, destWidth, destHeight, bpp, rMask, gMask, bMask, aMask);
|
||||
|
||||
SDL_BlitScaled(shadow, &srcRect, blitTemp, 0);
|
||||
|
||||
TEX::bind(tf.selfHires->tex);
|
||||
TEX::uploadSubImage(destX, destY,
|
||||
blitTemp->w, blitTemp->h, blitTemp->pixels, GL_RGBA);
|
||||
}
|
||||
else {
|
||||
TEX::bind(tf.tex);
|
||||
TEX::uploadSubImage(shadowArea.x*32, shadowArea.y*32,
|
||||
shadow->w, shadow->h, shadow->pixels, GL_RGBA);
|
||||
}
|
||||
SDL_FreeSurface(shadow);
|
||||
}
|
||||
|
||||
Bitmap *bm;
|
||||
|
||||
#define EXEC_BLITS(part) \
|
||||
if (!nullOrDisposed(bm = bitmaps[BM_##part])) \
|
||||
{ \
|
||||
|
|
|
@ -772,6 +772,7 @@ struct GraphicsPrivate {
|
|||
* RGSS renders at (settable with Graphics.resize_screen).
|
||||
* Can only be changed from within RGSS */
|
||||
Vec2i scRes;
|
||||
Vec2i scResLores;
|
||||
|
||||
/* Screen size, to which the rendered frames are scaled up.
|
||||
* This can be smaller than the window size when fixed aspect
|
||||
|
@ -828,7 +829,7 @@ struct GraphicsPrivate {
|
|||
IntruList<Disposable> dispList;
|
||||
|
||||
GraphicsPrivate(RGSSThreadData *rtData)
|
||||
: scRes(DEF_SCREEN_W, DEF_SCREEN_H), scSize(scRes),
|
||||
: scRes(DEF_SCREEN_W, DEF_SCREEN_H), scResLores(scRes), scSize(scRes),
|
||||
winSize(rtData->config.defScreenW, rtData->config.defScreenH),
|
||||
screen(scRes.x, scRes.y), threadData(rtData),
|
||||
glCtx(SDL_GL_GetCurrentContext()), multithreadedMode(true),
|
||||
|
@ -999,11 +1000,15 @@ struct GraphicsPrivate {
|
|||
}
|
||||
|
||||
void compositeToBuffer(TEXFBO &buffer) {
|
||||
compositeToBufferScaled(buffer, scRes.x, scRes.y);
|
||||
}
|
||||
|
||||
void compositeToBufferScaled(TEXFBO &buffer, int destWidth, int destHeight) {
|
||||
screen.composite();
|
||||
|
||||
GLMeta::blitBegin(buffer);
|
||||
GLMeta::blitSource(screen.getPP().frontBuffer());
|
||||
GLMeta::blitRectangle(IntRect(0, 0, scRes.x, scRes.y), Vec2i());
|
||||
GLMeta::blitRectangle(IntRect(0, 0, scRes.x, scRes.y), IntRect(0, 0, destWidth, destHeight));
|
||||
GLMeta::blitEnd();
|
||||
}
|
||||
|
||||
|
@ -1229,22 +1234,28 @@ void Graphics::transition(int duration, const char *filename, int vague) {
|
|||
TransShader &transShader = shState->shaders().trans;
|
||||
SimpleTransShader &simpleShader = shState->shaders().simpleTrans;
|
||||
|
||||
// Handle high-res.
|
||||
Vec2i transSize(p->scResLores.x, p->scResLores.y);
|
||||
|
||||
if (transMap) {
|
||||
TransShader &shader = transShader;
|
||||
shader.bind();
|
||||
shader.applyViewportProj();
|
||||
shader.setFrozenScene(p->frozenScene.tex);
|
||||
shader.setCurrentScene(currentScene.tex);
|
||||
if (transMap->hasHires()) {
|
||||
Debug() << "BUG: High-res Graphics transMap not implemented";
|
||||
}
|
||||
shader.setTransMap(transMap->getGLTypes().tex);
|
||||
shader.setVague(vague / 256.0f);
|
||||
shader.setTexSize(p->scRes);
|
||||
shader.setTexSize(transSize);
|
||||
} else {
|
||||
SimpleTransShader &shader = simpleShader;
|
||||
shader.bind();
|
||||
shader.applyViewportProj();
|
||||
shader.setFrozenScene(p->frozenScene.tex);
|
||||
shader.setCurrentScene(currentScene.tex);
|
||||
shader.setTexSize(p->scRes);
|
||||
shader.setTexSize(transSize);
|
||||
}
|
||||
|
||||
glState.blend.pushSet(false);
|
||||
|
@ -1391,16 +1402,36 @@ void Graphics::fadein(int duration) {
|
|||
Bitmap *Graphics::snapToBitmap() {
|
||||
Bitmap *bitmap = new Bitmap(width(), height());
|
||||
|
||||
p->compositeToBuffer(bitmap->getGLTypes());
|
||||
if (bitmap->hasHires()) {
|
||||
p->compositeToBufferScaled(bitmap->getHires()->getGLTypes(), bitmap->getHires()->width(), bitmap->getHires()->height());
|
||||
}
|
||||
|
||||
p->compositeToBufferScaled(bitmap->getGLTypes(), bitmap->width(), bitmap->height());
|
||||
|
||||
/* Taint entire bitmap */
|
||||
bitmap->taintArea(IntRect(0, 0, width(), height()));
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
int Graphics::width() const { return p->scRes.x; }
|
||||
int Graphics::width() const { return p->scResLores.x; }
|
||||
|
||||
int Graphics::height() const { return p->scRes.y; }
|
||||
int Graphics::height() const { return p->scResLores.y; }
|
||||
|
||||
int Graphics::widthHires() const { return p->scRes.x; }
|
||||
|
||||
int Graphics::heightHires() const { return p->scRes.y; }
|
||||
|
||||
bool Graphics::isPingPongFramebufferActive() const {
|
||||
return p->screen.getPP().frontBuffer().fbo == FBO::boundFramebufferID || p->screen.getPP().backBuffer().fbo == FBO::boundFramebufferID;
|
||||
}
|
||||
|
||||
int Graphics::displayContentWidth() const {
|
||||
return p->scSize.x;
|
||||
}
|
||||
|
||||
int Graphics::displayContentHeight() const {
|
||||
return p->scSize.y;
|
||||
}
|
||||
|
||||
int Graphics::displayWidth() const {
|
||||
SDL_DisplayMode dm{};
|
||||
|
@ -1418,12 +1449,21 @@ void Graphics::resizeScreen(int width, int height) {
|
|||
p->threadData->rqWindowAdjust.wait();
|
||||
p->checkResize(true);
|
||||
|
||||
Vec2i sizeLores(width, height);
|
||||
|
||||
if (shState->config().enableHires) {
|
||||
double framebufferScalingFactor = shState->config().framebufferScalingFactor;
|
||||
width = (int)lround(framebufferScalingFactor * width);
|
||||
height = (int)lround(framebufferScalingFactor * height);
|
||||
}
|
||||
|
||||
Vec2i size(width, height);
|
||||
|
||||
if (p->scRes == size)
|
||||
return;
|
||||
|
||||
p->scRes = size;
|
||||
p->scResLores = sizeLores;
|
||||
|
||||
p->screen.setResolution(width, height);
|
||||
|
||||
|
@ -1459,6 +1499,10 @@ bool Graphics::updateMovieInput(Movie *movie) {
|
|||
}
|
||||
|
||||
void Graphics::playMovie(const char *filename, int volume_, bool skippable) {
|
||||
if (shState->config().enableHires) {
|
||||
Debug() << "BUG: High-res Graphics playMovie not implemented";
|
||||
}
|
||||
|
||||
Movie *movie = new Movie(skippable);
|
||||
MovieOpenHandler handler(movie->srcOps);
|
||||
shState->fileSystem().openRead(handler, filename);
|
||||
|
|
|
@ -58,6 +58,11 @@ public:
|
|||
|
||||
int width() const;
|
||||
int height() const;
|
||||
int widthHires() const;
|
||||
int heightHires() const;
|
||||
bool isPingPongFramebufferActive() const;
|
||||
int displayContentWidth() const;
|
||||
int displayContentHeight() const;
|
||||
int displayWidth() const;
|
||||
int displayHeight() const;
|
||||
void resizeScreen(int width, int height);
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "sharedstate.h"
|
||||
#include "bitmap.h"
|
||||
#include "debugwriter.h"
|
||||
#include "etc.h"
|
||||
#include "etc-internal.h"
|
||||
#include "util.h"
|
||||
|
@ -605,6 +606,10 @@ void Sprite::draw()
|
|||
shader.setBushOpacity(p->bushOpacity.norm);
|
||||
|
||||
if (p->pattern && p->patternOpacity > 0) {
|
||||
if (p->pattern->hasHires()) {
|
||||
Debug() << "BUG: High-res Sprite pattern not implemented";
|
||||
}
|
||||
|
||||
shader.setPattern(p->pattern->getGLTypes().tex, Vec2(p->pattern->width(), p->pattern->height()));
|
||||
shader.setPatternBlendType(p->patternBlendType);
|
||||
shader.setPatternTile(p->patternTile);
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "sharedstate.h"
|
||||
#include "config.h"
|
||||
#include "debugwriter.h"
|
||||
#include "glstate.h"
|
||||
#include "gl-util.h"
|
||||
#include "gl-meta.h"
|
||||
|
@ -550,6 +551,10 @@ struct TilemapPrivate
|
|||
int blitW = std::min(atW, atAreaW);
|
||||
int blitH = std::min(atH, autotileH);
|
||||
|
||||
if (autotile->hasHires()) {
|
||||
Debug() << "BUG: High-res Tilemap blit autotiles not implemented";
|
||||
}
|
||||
|
||||
GLMeta::blitSource(autotile->getGLTypes());
|
||||
|
||||
if (atW <= autotileW && tiles.animated && !atlas.smallATs[atInd])
|
||||
|
@ -639,6 +644,10 @@ struct TilemapPrivate
|
|||
}
|
||||
else
|
||||
{
|
||||
if (tileset->hasHires()) {
|
||||
Debug() << "BUG: High-res Tilemap regular tileset not implemented";
|
||||
}
|
||||
|
||||
/* Regular tileset */
|
||||
GLMeta::blitBegin(atlas.gl);
|
||||
GLMeta::blitSource(tileset->getGLTypes());
|
||||
|
|
|
@ -72,6 +72,8 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader
|
|||
VBO::ID vbo;
|
||||
GLMeta::VAO vao;
|
||||
|
||||
TEXFBO atlasHires;
|
||||
|
||||
size_t allocQuads;
|
||||
|
||||
size_t groundQuads;
|
||||
|
@ -132,6 +134,14 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader
|
|||
|
||||
shState->requestAtlasTex(ATLASVX_W, ATLASVX_H, atlas);
|
||||
|
||||
if (shState->config().enableHires) {
|
||||
double scalingFactor = shState->config().atlasScalingFactor;
|
||||
int hiresWidth = (int)lround(scalingFactor * ATLASVX_W);
|
||||
int hiresHeight = (int)lround(scalingFactor * ATLASVX_H);
|
||||
shState->requestAtlasTex(hiresWidth, hiresHeight, atlasHires);
|
||||
atlas.selfHires = &atlasHires;
|
||||
}
|
||||
|
||||
vbo = VBO::gen();
|
||||
|
||||
GLMeta::vaoFillInVertexData<SVertex>(vao);
|
||||
|
@ -151,6 +161,9 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader
|
|||
VBO::del(vbo);
|
||||
|
||||
shState->releaseAtlasTex(atlas);
|
||||
if (shState->config().enableHires) {
|
||||
shState->releaseAtlasTex(atlasHires);
|
||||
}
|
||||
|
||||
prepareCon.disconnect();
|
||||
|
||||
|
@ -310,7 +323,12 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader
|
|||
shader->applyViewportProj();
|
||||
shader->setTranslation(dispPos);
|
||||
|
||||
TEX::bind(atlas.tex);
|
||||
if (atlas.selfHires != nullptr) {
|
||||
TEX::bind(atlas.selfHires->tex);
|
||||
}
|
||||
else {
|
||||
TEX::bind(atlas.tex);
|
||||
}
|
||||
GLMeta::vaoBind(vao);
|
||||
|
||||
gl.DrawElements(GL_TRIANGLES, groundQuads*6, _GL_INDEX_TYPE, 0);
|
||||
|
@ -329,7 +347,12 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader
|
|||
shader.applyViewportProj();
|
||||
shader.setTranslation(dispPos);
|
||||
|
||||
TEX::bind(atlas.tex);
|
||||
if (atlas.selfHires != nullptr) {
|
||||
TEX::bind(atlas.selfHires->tex);
|
||||
}
|
||||
else {
|
||||
TEX::bind(atlas.tex);
|
||||
}
|
||||
GLMeta::vaoBind(vao);
|
||||
|
||||
gl.DrawElements(GL_TRIANGLES, aboveQuads*6, _GL_INDEX_TYPE,
|
||||
|
|
BIN
tests/hires-bitmap/Graphics/Pictures/children-alpha-lo.jxl
Normal file
BIN
tests/hires-bitmap/Graphics/Pictures/children-alpha-lo.jxl
Normal file
Binary file not shown.
BIN
tests/hires-bitmap/Graphics/Pictures/children-alpha.jxl
Normal file
BIN
tests/hires-bitmap/Graphics/Pictures/children-alpha.jxl
Normal file
Binary file not shown.
BIN
tests/hires-bitmap/Graphics/Pictures/tree_alpha_16bit-lo.jxl
Normal file
BIN
tests/hires-bitmap/Graphics/Pictures/tree_alpha_16bit-lo.jxl
Normal file
Binary file not shown.
BIN
tests/hires-bitmap/Graphics/Pictures/tree_alpha_16bit.jxl
Normal file
BIN
tests/hires-bitmap/Graphics/Pictures/tree_alpha_16bit.jxl
Normal file
Binary file not shown.
BIN
tests/hires-bitmap/Hires/Graphics/Pictures/children-alpha.jxl
Normal file
BIN
tests/hires-bitmap/Hires/Graphics/Pictures/children-alpha.jxl
Normal file
Binary file not shown.
BIN
tests/hires-bitmap/Hires/Graphics/Pictures/tree_alpha_16bit.jxl
Normal file
BIN
tests/hires-bitmap/Hires/Graphics/Pictures/tree_alpha_16bit.jxl
Normal file
Binary file not shown.
412
tests/hires-bitmap/hires-bitmap-test.rb
Executable file
412
tests/hires-bitmap/hires-bitmap-test.rb
Executable file
|
@ -0,0 +1,412 @@
|
|||
# Test suite for mkxp-z high-res Bitmap replacement.
|
||||
# Bitmap tests.
|
||||
# Copyright 2023 Splendide Imaginarius.
|
||||
# License GPLv2+.
|
||||
# Test images are from https://github.com/xinntao/Real-ESRGAN/
|
||||
#
|
||||
# Run the suite via the "customScript" field in mkxp.json.
|
||||
# Use RGSS v3 for best results.
|
||||
|
||||
def dump(bmp, spr, desc)
|
||||
spr.bitmap = bmp
|
||||
Graphics.wait(1)
|
||||
bmp.to_file("test-results/" + desc + "-lo.png")
|
||||
if !bmp.hires.nil?
|
||||
bmp.hires.to_file("test-results/" + desc + "-hi.png")
|
||||
end
|
||||
System::puts("Finished " + desc)
|
||||
end
|
||||
|
||||
# Setup graphics
|
||||
Graphics.resize_screen(640, 480)
|
||||
|
||||
# Setup font
|
||||
fnt = Font.new("Liberation Sans", 100)
|
||||
|
||||
# Setup splash screen
|
||||
bmp = Bitmap.new(640, 480)
|
||||
bmp.fill_rect(0, 0, 640, 480, Color.new(0, 0, 0))
|
||||
|
||||
bmp.font = fnt
|
||||
bmp.draw_text(0, 0, 640, 240, "High-Res Test Suite", 1)
|
||||
bmp.draw_text(0, 240, 640, 240, "Starting Now", 1)
|
||||
|
||||
spr = Sprite.new()
|
||||
spr.bitmap = bmp
|
||||
|
||||
Graphics.wait(1 * 60)
|
||||
|
||||
# Tests start here
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/children-alpha")
|
||||
dump(bmp, spr, "constructor-filename")
|
||||
|
||||
# TODO: Filename GIF constructor
|
||||
|
||||
bmp = Bitmap.new(640, 480)
|
||||
bmp.clear
|
||||
dump(bmp, spr, "constructor-dimensions")
|
||||
|
||||
# TODO: Animation constructor
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/tree_alpha_16bit")
|
||||
bmp.clear
|
||||
bmp2 = Bitmap.new("Graphics/Pictures/children-alpha-lo")
|
||||
bmp.stretch_blt(bmp.rect, bmp2, bmp2.rect)
|
||||
dump(bmp, spr, "stretch-blt-clear-tree-lo-children-full-opaque")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/tree_alpha_16bit")
|
||||
bmp.clear
|
||||
bmp2 = Bitmap.new("Graphics/Pictures/children-alpha-lo")
|
||||
bmp.stretch_blt(bmp.rect, bmp2, bmp2.rect, 127)
|
||||
dump(bmp, spr, "stretch-blt-clear-tree-lo-children-full-semitransparent")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/tree_alpha_16bit")
|
||||
bmp.clear
|
||||
rect = bmp.rect
|
||||
rect.width /= 2
|
||||
rect.height /= 2
|
||||
rect.x = rect.width
|
||||
rect.y = rect.height
|
||||
bmp2 = Bitmap.new("Graphics/Pictures/children-alpha-lo")
|
||||
rect2 = bmp2.rect
|
||||
rect2.width /= 2
|
||||
rect2.height /= 2
|
||||
rect2.x = rect2.width
|
||||
bmp.stretch_blt(rect, bmp2, rect2, 127)
|
||||
dump(bmp, spr, "stretch-blt-clear-tree-lo-children-quarter-semitransparent")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/tree_alpha_16bit")
|
||||
bmp.clear
|
||||
bmp2 = Bitmap.new("Graphics/Pictures/children-alpha")
|
||||
bmp.stretch_blt(bmp.rect, bmp2, bmp2.rect)
|
||||
dump(bmp, spr, "stretch-blt-clear-tree-hi-children-full-opaque")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/tree_alpha_16bit")
|
||||
bmp.clear
|
||||
bmp2 = Bitmap.new("Graphics/Pictures/children-alpha")
|
||||
bmp.stretch_blt(bmp.rect, bmp2, bmp2.rect, 127)
|
||||
dump(bmp, spr, "stretch-blt-clear-tree-hi-children-full-semitransparent")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/tree_alpha_16bit")
|
||||
bmp.clear
|
||||
rect = bmp.rect
|
||||
rect.width /= 2
|
||||
rect.height /= 2
|
||||
rect.x = rect.width
|
||||
rect.y = rect.height
|
||||
bmp2 = Bitmap.new("Graphics/Pictures/children-alpha")
|
||||
rect2 = bmp2.rect
|
||||
rect2.width /= 2
|
||||
rect2.height /= 2
|
||||
rect2.x = rect2.width
|
||||
bmp.stretch_blt(rect, bmp2, rect2, 127)
|
||||
dump(bmp, spr, "stretch-blt-clear-tree-hi-children-quarter-semitransparent")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/tree_alpha_16bit")
|
||||
bmp.fill_rect(bmp.rect, Color.new(0, 0, 0))
|
||||
bmp2 = Bitmap.new("Graphics/Pictures/children-alpha-lo")
|
||||
bmp.stretch_blt(bmp.rect, bmp2, bmp2.rect)
|
||||
dump(bmp, spr, "stretch-blt-black-tree-lo-children-full-opaque")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/tree_alpha_16bit")
|
||||
bmp.fill_rect(bmp.rect, Color.new(0, 0, 0))
|
||||
bmp2 = Bitmap.new("Graphics/Pictures/children-alpha-lo")
|
||||
bmp.stretch_blt(bmp.rect, bmp2, bmp2.rect, 127)
|
||||
dump(bmp, spr, "stretch-blt-black-tree-lo-children-full-semitransparent")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/tree_alpha_16bit")
|
||||
bmp.fill_rect(bmp.rect, Color.new(0, 0, 0))
|
||||
rect = bmp.rect
|
||||
rect.width /= 2
|
||||
rect.height /= 2
|
||||
rect.x = rect.width
|
||||
rect.y = rect.height
|
||||
bmp2 = Bitmap.new("Graphics/Pictures/children-alpha-lo")
|
||||
rect2 = bmp2.rect
|
||||
rect2.width /= 2
|
||||
rect2.height /= 2
|
||||
rect2.x = rect2.width
|
||||
bmp.stretch_blt(rect, bmp2, rect2, 127)
|
||||
dump(bmp, spr, "stretch-blt-black-tree-lo-children-quarter-semitransparent")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/tree_alpha_16bit")
|
||||
bmp.fill_rect(bmp.rect, Color.new(0, 0, 0))
|
||||
bmp2 = Bitmap.new("Graphics/Pictures/children-alpha")
|
||||
bmp.stretch_blt(bmp.rect, bmp2, bmp2.rect)
|
||||
dump(bmp, spr, "stretch-blt-black-tree-hi-children-full-opaque")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/tree_alpha_16bit")
|
||||
bmp.fill_rect(bmp.rect, Color.new(0, 0, 0))
|
||||
bmp2 = Bitmap.new("Graphics/Pictures/children-alpha")
|
||||
bmp.stretch_blt(bmp.rect, bmp2, bmp2.rect, 127)
|
||||
dump(bmp, spr, "stretch-blt-black-tree-hi-children-full-semitransparent")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/tree_alpha_16bit")
|
||||
bmp.fill_rect(bmp.rect, Color.new(0, 0, 0))
|
||||
rect = bmp.rect
|
||||
rect.width /= 2
|
||||
rect.height /= 2
|
||||
rect.x = rect.width
|
||||
rect.y = rect.height
|
||||
bmp2 = Bitmap.new("Graphics/Pictures/children-alpha")
|
||||
rect2 = bmp2.rect
|
||||
rect2.width /= 2
|
||||
rect2.height /= 2
|
||||
rect2.x = rect2.width
|
||||
bmp.stretch_blt(rect, bmp2, rect2, 127)
|
||||
dump(bmp, spr, "stretch-blt-black-tree-hi-children-quarter-semitransparent")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/tree_alpha_16bit-lo")
|
||||
bmp2 = Bitmap.new("Graphics/Pictures/children-alpha-lo")
|
||||
bmp.stretch_blt(bmp.rect, bmp2, bmp2.rect)
|
||||
dump(bmp, spr, "stretch-blt-lo-tree-lo-children-full-opaque")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/tree_alpha_16bit-lo")
|
||||
bmp2 = Bitmap.new("Graphics/Pictures/children-alpha-lo")
|
||||
bmp.stretch_blt(bmp.rect, bmp2, bmp2.rect, 127)
|
||||
dump(bmp, spr, "stretch-blt-lo-tree-lo-children-full-semitransparent")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/tree_alpha_16bit-lo")
|
||||
rect = bmp.rect
|
||||
rect.width /= 2
|
||||
rect.height /= 2
|
||||
rect.x = rect.width
|
||||
rect.y = rect.height
|
||||
bmp2 = Bitmap.new("Graphics/Pictures/children-alpha-lo")
|
||||
rect2 = bmp2.rect
|
||||
rect2.width /= 2
|
||||
rect2.height /= 2
|
||||
rect2.x = rect2.width
|
||||
bmp.stretch_blt(rect, bmp2, rect2, 127)
|
||||
dump(bmp, spr, "stretch-blt-lo-tree-lo-children-quarter-semitransparent")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/tree_alpha_16bit-lo")
|
||||
bmp2 = Bitmap.new("Graphics/Pictures/children-alpha")
|
||||
bmp.stretch_blt(bmp.rect, bmp2, bmp2.rect)
|
||||
dump(bmp, spr, "stretch-blt-lo-tree-hi-children-full-opaque")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/tree_alpha_16bit-lo")
|
||||
bmp2 = Bitmap.new("Graphics/Pictures/children-alpha")
|
||||
bmp.stretch_blt(bmp.rect, bmp2, bmp2.rect, 127)
|
||||
dump(bmp, spr, "stretch-blt-lo-tree-hi-children-full-semitransparent")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/tree_alpha_16bit-lo")
|
||||
rect = bmp.rect
|
||||
rect.width /= 2
|
||||
rect.height /= 2
|
||||
rect.x = rect.width
|
||||
rect.y = rect.height
|
||||
bmp2 = Bitmap.new("Graphics/Pictures/children-alpha")
|
||||
rect2 = bmp2.rect
|
||||
rect2.width /= 2
|
||||
rect2.height /= 2
|
||||
rect2.x = rect2.width
|
||||
bmp.stretch_blt(rect, bmp2, rect2, 127)
|
||||
dump(bmp, spr, "stretch-blt-lo-tree-hi-children-quarter-semitransparent")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/tree_alpha_16bit")
|
||||
bmp2 = Bitmap.new("Graphics/Pictures/children-alpha-lo")
|
||||
bmp.stretch_blt(bmp.rect, bmp2, bmp2.rect)
|
||||
dump(bmp, spr, "stretch-blt-hi-tree-lo-children-full-opaque")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/tree_alpha_16bit")
|
||||
bmp2 = Bitmap.new("Graphics/Pictures/children-alpha-lo")
|
||||
bmp.stretch_blt(bmp.rect, bmp2, bmp2.rect, 127)
|
||||
dump(bmp, spr, "stretch-blt-hi-tree-lo-children-full-semitransparent")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/tree_alpha_16bit")
|
||||
rect = bmp.rect
|
||||
rect.width /= 2
|
||||
rect.height /= 2
|
||||
rect.x = rect.width
|
||||
rect.y = rect.height
|
||||
bmp2 = Bitmap.new("Graphics/Pictures/children-alpha-lo")
|
||||
rect2 = bmp2.rect
|
||||
rect2.width /= 2
|
||||
rect2.height /= 2
|
||||
rect2.x = rect2.width
|
||||
bmp.stretch_blt(rect, bmp2, rect2, 127)
|
||||
dump(bmp, spr, "stretch-blt-hi-tree-lo-children-quarter-semitransparent")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/tree_alpha_16bit")
|
||||
bmp2 = Bitmap.new("Graphics/Pictures/children-alpha")
|
||||
bmp.stretch_blt(bmp.rect, bmp2, bmp2.rect)
|
||||
dump(bmp, spr, "stretch-blt-hi-tree-hi-children-full-opaque")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/tree_alpha_16bit")
|
||||
bmp2 = Bitmap.new("Graphics/Pictures/children-alpha")
|
||||
bmp.stretch_blt(bmp.rect, bmp2, bmp2.rect, 127)
|
||||
dump(bmp, spr, "stretch-blt-hi-tree-hi-children-full-semitransparent")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/tree_alpha_16bit")
|
||||
rect = bmp.rect
|
||||
rect.width /= 2
|
||||
rect.height /= 2
|
||||
rect.x = rect.width
|
||||
rect.y = rect.height
|
||||
bmp2 = Bitmap.new("Graphics/Pictures/children-alpha")
|
||||
rect2 = bmp2.rect
|
||||
rect2.width /= 2
|
||||
rect2.height /= 2
|
||||
rect2.x = rect2.width
|
||||
bmp.stretch_blt(rect, bmp2, rect2, 127)
|
||||
dump(bmp, spr, "stretch-blt-hi-tree-hi-children-quarter-semitransparent")
|
||||
|
||||
bmp = Bitmap.new(640, 480)
|
||||
bmp.fill_rect(100, 200, 450, 300, Color.new(0, 0, 0))
|
||||
bmp.fill_rect(50, 100, 220, 150, Color.new(255, 0, 0))
|
||||
dump(bmp, spr, "fill-rect")
|
||||
|
||||
bmp = Bitmap.new(640, 480)
|
||||
bmp.gradient_fill_rect(100, 200, 450, 300, Color.new(0, 0, 0), Color.new(0, 0, 255))
|
||||
bmp.gradient_fill_rect(50, 100, 220, 150, Color.new(255, 0, 0), Color.new(255, 255, 0))
|
||||
dump(bmp, spr, "gradient-fill-rect-horizontal")
|
||||
|
||||
bmp = Bitmap.new(640, 480)
|
||||
bmp.gradient_fill_rect(100, 200, 450, 300, Color.new(0, 0, 0), Color.new(0, 0, 255), true)
|
||||
bmp.gradient_fill_rect(50, 100, 220, 150, Color.new(255, 0, 0), Color.new(255, 255, 0), true)
|
||||
dump(bmp, spr, "gradient-fill-rect-vertical")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/children-alpha-lo")
|
||||
bmp.clear_rect(300, 175, 100, 150)
|
||||
dump(bmp, spr, "clear-rect-lo-children")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/children-alpha")
|
||||
bmp.clear_rect(300, 175, 100, 150)
|
||||
dump(bmp, spr, "clear-rect-hi-children")
|
||||
|
||||
# TODO: linear-blur is arguably passing but maybe should have stronger blur?
|
||||
bmp = Bitmap.new("Graphics/Pictures/children-alpha")
|
||||
bmp.blur
|
||||
dump(bmp, spr, "linear-blur")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/children-alpha-lo")
|
||||
bmp.radial_blur(0, 10)
|
||||
dump(bmp, spr, "radial-blur-0-lo-children")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/children-alpha")
|
||||
bmp.radial_blur(0, 10)
|
||||
dump(bmp, spr, "radial-blur-0-hi-children")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/children-alpha-lo")
|
||||
bmp.radial_blur(3, 10)
|
||||
dump(bmp, spr, "radial-blur-3-lo-children")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/children-alpha")
|
||||
bmp.radial_blur(3, 10)
|
||||
dump(bmp, spr, "radial-blur-3-hi-children")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/children-alpha")
|
||||
bmp.clear
|
||||
dump(bmp, spr, "clear-full")
|
||||
|
||||
bmp2 = Bitmap.new("Graphics/Pictures/children-alpha")
|
||||
bmp = Bitmap.new(bmp2.width, bmp2.height)
|
||||
for x in (0...bmp2.width)
|
||||
for y in (0...bmp2.height)
|
||||
bmp.set_pixel(x, y, bmp2.get_pixel(x, y))
|
||||
end
|
||||
end
|
||||
dump(bmp, spr, "get-set-pixel-dimensions")
|
||||
|
||||
bmp2 = Bitmap.new("Graphics/Pictures/children-alpha")
|
||||
bmp = Bitmap.new("Graphics/Pictures/children-alpha")
|
||||
bmp.clear
|
||||
for x in (0...bmp2.width)
|
||||
for y in (0...bmp2.height)
|
||||
bmp.set_pixel(x, y, bmp2.get_pixel(x, y))
|
||||
end
|
||||
end
|
||||
dump(bmp, spr, "get-set-pixel-clear")
|
||||
|
||||
bmp2 = Bitmap.new("Graphics/Pictures/children-alpha")
|
||||
bmp = Bitmap.new("Graphics/Pictures/children-alpha")
|
||||
bmp.hires.clear
|
||||
for x in (0...bmp2.hires.width)
|
||||
for y in (0...bmp2.hires.height)
|
||||
bmp.hires.set_pixel(x, y, bmp2.hires.get_pixel(x, y))
|
||||
end
|
||||
end
|
||||
dump(bmp, spr, "get-set-pixel-direct")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/children-alpha-lo")
|
||||
bmp.hue_change(180)
|
||||
dump(bmp, spr, "hue-change-lo-children")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/children-alpha")
|
||||
bmp.hue_change(180)
|
||||
dump(bmp, spr, "hue-change-hi-children")
|
||||
|
||||
bmp = Bitmap.new(640, 480)
|
||||
fnt = Font.new("Liberation Sans", 100)
|
||||
bmp.font = fnt
|
||||
bmp.draw_text(100, 200, 450, 300, "We <3 Real-ESRGAN", 1)
|
||||
dump(bmp, spr, "draw-text-plain")
|
||||
|
||||
bmp = Bitmap.new(640, 480)
|
||||
fnt = Font.new("Liberation Sans", 15)
|
||||
bmp.font = fnt
|
||||
bmp.draw_text(100, 200, 450, 300, "We <3 Real-ESRGAN", 0)
|
||||
dump(bmp, spr, "draw-text-left")
|
||||
|
||||
bmp = Bitmap.new(640, 480)
|
||||
fnt = Font.new("Liberation Sans", 15)
|
||||
bmp.font = fnt
|
||||
bmp.draw_text(100, 200, 450, 300, "We <3 Real-ESRGAN", 2)
|
||||
dump(bmp, spr, "draw-text-right")
|
||||
|
||||
bmp = Bitmap.new(640, 480)
|
||||
fnt = Font.new("Liberation Sans", 100)
|
||||
fnt.bold = true
|
||||
bmp.font = fnt
|
||||
bmp.draw_text(100, 200, 450, 300, "We <3 Real-ESRGAN", 1)
|
||||
dump(bmp, spr, "draw-text-bold")
|
||||
|
||||
bmp = Bitmap.new(640, 480)
|
||||
fnt = Font.new("Liberation Sans", 100)
|
||||
fnt.italic = true
|
||||
bmp.font = fnt
|
||||
bmp.draw_text(100, 200, 450, 300, "We <3 Real-ESRGAN", 1)
|
||||
dump(bmp, spr, "draw-text-italic")
|
||||
|
||||
bmp = Bitmap.new(640, 480)
|
||||
fnt = Font.new("Liberation Sans", 100)
|
||||
fnt.color = Color.new(255, 0, 0)
|
||||
fnt.outline = false
|
||||
bmp.font = fnt
|
||||
bmp.draw_text(100, 200, 450, 300, "We <3 Real-ESRGAN", 1)
|
||||
dump(bmp, spr, "draw-text-red-no-outline")
|
||||
|
||||
bmp = Bitmap.new(640, 480)
|
||||
fnt = Font.new("Liberation Sans", 100)
|
||||
fnt.color = Color.new(255, 127, 127)
|
||||
fnt.shadow = true
|
||||
bmp.font = fnt
|
||||
bmp.draw_text(100, 200, 450, 300, "We <3 Real-ESRGAN", 1)
|
||||
dump(bmp, spr, "draw-text-pink-shadow")
|
||||
|
||||
bmp = Bitmap.new(640, 480)
|
||||
fnt = Font.new("Liberation Sans", 100)
|
||||
fnt.out_color = Color.new(0, 255, 0)
|
||||
bmp.font = fnt
|
||||
bmp.draw_text(100, 200, 450, 300, "We <3 Real-ESRGAN", 1)
|
||||
dump(bmp, spr, "draw-text-green-outline")
|
||||
|
||||
# TODO: Animation tests, if we can find a good way to test them.
|
||||
|
||||
# Tests are finished, show exit screen
|
||||
|
||||
bmp = Bitmap.new(640, 480)
|
||||
bmp.fill_rect(0, 0, 640, 480, Color.new(0, 0, 0))
|
||||
|
||||
fnt = Font.new("Liberation Sans", 100)
|
||||
|
||||
bmp.font = fnt
|
||||
bmp.draw_text(0, 0, 640, 240, "High-Res Test Suite", 1)
|
||||
bmp.draw_text(0, 240, 640, 240, "Has Finished", 1)
|
||||
spr.bitmap = bmp
|
||||
|
||||
Graphics.wait(1 * 60)
|
||||
|
||||
exit
|
0
tests/hires-bitmap/test-results/.RESULTS WILL GO HERE
Normal file
0
tests/hires-bitmap/test-results/.RESULTS WILL GO HERE
Normal file
BIN
tests/hires-sprite/Graphics/Pictures/OST_009-Big.jxl
Normal file
BIN
tests/hires-sprite/Graphics/Pictures/OST_009-Big.jxl
Normal file
Binary file not shown.
BIN
tests/hires-sprite/Graphics/Pictures/OST_009-Small.jxl
Normal file
BIN
tests/hires-sprite/Graphics/Pictures/OST_009-Small.jxl
Normal file
Binary file not shown.
BIN
tests/hires-sprite/Graphics/Pictures/OST_009.jxl
Normal file
BIN
tests/hires-sprite/Graphics/Pictures/OST_009.jxl
Normal file
Binary file not shown.
BIN
tests/hires-sprite/Hires/Graphics/Pictures/OST_009.jxl
Normal file
BIN
tests/hires-sprite/Hires/Graphics/Pictures/OST_009.jxl
Normal file
Binary file not shown.
82
tests/hires-sprite/hires-sprite-test.rb
Executable file
82
tests/hires-sprite/hires-sprite-test.rb
Executable file
|
@ -0,0 +1,82 @@
|
|||
# Test suite for mkxp-z high-res Bitmap replacement.
|
||||
# Sprite tests.
|
||||
# Copyright 2023 Splendide Imaginarius.
|
||||
# License GPLv2+.
|
||||
# Test images are from https://github.com/xinntao/Real-ESRGAN/
|
||||
#
|
||||
# Run the suite via the "customScript" field in mkxp.json.
|
||||
# Use RGSS v3 for best results.
|
||||
|
||||
def dump2(bmp, spr, desc)
|
||||
spr.bitmap = bmp
|
||||
Graphics.wait(1)
|
||||
#Graphics.wait(5*60)
|
||||
#Graphics.screenshot("test-results/" + desc + ".png")
|
||||
shot = Graphics.snap_to_bitmap
|
||||
shot.to_file("test-results/" + desc + "-lo.png")
|
||||
if !shot.hires.nil?
|
||||
shot.hires.to_file("test-results/" + desc + "-hi.png")
|
||||
end
|
||||
System::puts("Finished " + desc)
|
||||
end
|
||||
|
||||
def dump(bmp, spr, desc)
|
||||
spr.viewport = nil
|
||||
dump2(bmp, spr, desc + "-direct")
|
||||
spr.tone.gray = 128
|
||||
dump2(bmp, spr, desc + "-directtonegray")
|
||||
spr.tone.gray = 0
|
||||
$vp.ox = 0
|
||||
spr.viewport = $vp
|
||||
dump2(bmp, spr, desc + "-viewport")
|
||||
$vp.ox = 250
|
||||
dump2(bmp, spr, desc + "-viewportshift")
|
||||
$vp.ox = 0
|
||||
$vp.rect.width = 320
|
||||
dump2(bmp, spr, desc + "-viewportsquash")
|
||||
$vp.rect.width = 640
|
||||
$vp.tone.green = -128
|
||||
dump2(bmp, spr, desc + "-viewporttonegreen")
|
||||
$vp.tone.green = 0
|
||||
$vp.tone.gray = 128
|
||||
dump2(bmp, spr, desc + "-viewporttonegray")
|
||||
$vp.tone.gray = 0
|
||||
end
|
||||
|
||||
# Setup graphics
|
||||
Graphics.resize_screen(448, 640)
|
||||
|
||||
$vp = Viewport.new()
|
||||
|
||||
spr = Sprite.new()
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/OST_009-Small")
|
||||
spr.zoom_x = 1.0
|
||||
spr.zoom_y = 1.0
|
||||
dump(bmp, spr, "Small")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/OST_009-Big")
|
||||
spr.zoom_x = 448.0 / 1792.0
|
||||
spr.zoom_y = 448.0 / 1792.0
|
||||
dump(bmp, spr, "Big")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/OST_009")
|
||||
spr.zoom_x = 1.0
|
||||
spr.zoom_y = 1.0
|
||||
dump(bmp, spr, "Substituted")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/OST_009")
|
||||
spr.zoom_x = 1.5
|
||||
spr.zoom_y = 1.5
|
||||
dump(bmp, spr, "Substituted-Zoomed")
|
||||
|
||||
bmp = Bitmap.new("Graphics/Pictures/OST_009")
|
||||
spr.zoom_x = 448.0 / 1792.0
|
||||
spr.zoom_y = 448.0 / 1792.0
|
||||
dump(bmp.hires, spr, "Substituted-Explicit")
|
||||
|
||||
# Test for null pointer
|
||||
spr_null = Sprite.new()
|
||||
spr_null.src_rect = Rect.new(0, 0, 448, 640)
|
||||
|
||||
exit
|
0
tests/hires-sprite/test-results/.RESULTS WILL GO HERE
Normal file
0
tests/hires-sprite/test-results/.RESULTS WILL GO HERE
Normal file
Loading…
Add table
Reference in a new issue