STARK: Optionally use linear filtering when rendering backgrounds
This commit is contained in:
parent
45c5cf0c80
commit
b9a1b8eefd
17 changed files with 87 additions and 9 deletions
|
@ -298,6 +298,7 @@ static const ADFileBasedFallback fileBasedFallback[] = {
|
||||||
};*/
|
};*/
|
||||||
|
|
||||||
#define GAMEOPTION_ASSETS_MOD GUIO_GAMEOPTIONS1
|
#define GAMEOPTION_ASSETS_MOD GUIO_GAMEOPTIONS1
|
||||||
|
#define GAMEOPTION_LINEAR_FILTERING GUIO_GAMEOPTIONS2
|
||||||
|
|
||||||
static const ADExtraGuiOptionsMap optionsList[] = {
|
static const ADExtraGuiOptionsMap optionsList[] = {
|
||||||
{
|
{
|
||||||
|
@ -309,6 +310,15 @@ static const ADExtraGuiOptionsMap optionsList[] = {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
GAMEOPTION_LINEAR_FILTERING,
|
||||||
|
{
|
||||||
|
_s("Enable linear filtering of the backgrounds images"),
|
||||||
|
_s("When linear filtering is enabled the background graphics are smoother in full screen mode, at the cost of some details."),
|
||||||
|
"use_linear_filtering",
|
||||||
|
true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
AD_EXTRA_GUI_OPTIONS_TERMINATOR
|
AD_EXTRA_GUI_OPTIONS_TERMINATOR
|
||||||
};
|
};
|
||||||
|
@ -317,7 +327,7 @@ class StarkMetaEngine : public AdvancedMetaEngine {
|
||||||
public:
|
public:
|
||||||
StarkMetaEngine() : AdvancedMetaEngine(gameDescriptions, sizeof(ADGameDescription), starkGames, optionsList) {
|
StarkMetaEngine() : AdvancedMetaEngine(gameDescriptions, sizeof(ADGameDescription), starkGames, optionsList) {
|
||||||
_singleId = "stark";
|
_singleId = "stark";
|
||||||
_guiOptions = GUIO2(GUIO_NOMIDI, GAMEOPTION_ASSETS_MOD);
|
_guiOptions = GUIO3(GUIO_NOMIDI, GAMEOPTION_ASSETS_MOD, GAMEOPTION_LINEAR_FILTERING);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *getName() const override {
|
const char *getName() const override {
|
||||||
|
|
|
@ -198,10 +198,10 @@ XMGDecoder::Block XMGDecoder::processYCrCb() {
|
||||||
XMGDecoder::Block XMGDecoder::processTrans() {
|
XMGDecoder::Block XMGDecoder::processTrans() {
|
||||||
Block block;
|
Block block;
|
||||||
|
|
||||||
block.a1 = _transColor;
|
block.a1 = 0;
|
||||||
block.a2 = _transColor;
|
block.a2 = 0;
|
||||||
block.b1 = _transColor;
|
block.b1 = 0;
|
||||||
block.b2 = _transColor;
|
block.b2 = 0;
|
||||||
|
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
@ -214,24 +214,32 @@ XMGDecoder::Block XMGDecoder::processRGB() {
|
||||||
color += _stream->readByte() << 16;
|
color += _stream->readByte() << 16;
|
||||||
if (color != _transColor)
|
if (color != _transColor)
|
||||||
color += 255 << 24;
|
color += 255 << 24;
|
||||||
|
else
|
||||||
|
color = 0;
|
||||||
block.a1 = color;
|
block.a1 = color;
|
||||||
|
|
||||||
color = _stream->readUint16LE();
|
color = _stream->readUint16LE();
|
||||||
color += _stream->readByte() << 16;
|
color += _stream->readByte() << 16;
|
||||||
if (color != _transColor)
|
if (color != _transColor)
|
||||||
color += 255 << 24;
|
color += 255 << 24;
|
||||||
|
else
|
||||||
|
color = 0;
|
||||||
block.a2 = color;
|
block.a2 = color;
|
||||||
|
|
||||||
color = _stream->readUint16LE();
|
color = _stream->readUint16LE();
|
||||||
color += _stream->readByte() << 16;
|
color += _stream->readByte() << 16;
|
||||||
if (color != _transColor)
|
if (color != _transColor)
|
||||||
color += 255 << 24;
|
color += 255 << 24;
|
||||||
|
else
|
||||||
|
color = 0;
|
||||||
block.b1 = color;
|
block.b1 = color;
|
||||||
|
|
||||||
color = _stream->readUint16LE();
|
color = _stream->readUint16LE();
|
||||||
color += _stream->readByte() << 16;
|
color += _stream->readByte() << 16;
|
||||||
if (color != _transColor)
|
if (color != _transColor)
|
||||||
color += 255 << 24;
|
color += 255 << 24;
|
||||||
|
else
|
||||||
|
color = 0;
|
||||||
block.b2 = color;
|
block.b2 = color;
|
||||||
|
|
||||||
return block;
|
return block;
|
||||||
|
|
|
@ -65,6 +65,11 @@ private:
|
||||||
|
|
||||||
Common::ReadStream *_stream;
|
Common::ReadStream *_stream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The transparency color in the RGB and transparency blocks.
|
||||||
|
* In the output surface, the transparent color is black with zero
|
||||||
|
* alpha. So the images are effectively pre-multiplied alpha.
|
||||||
|
*/
|
||||||
uint32 _transColor;
|
uint32 _transColor;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -162,7 +162,11 @@ void OpenGLSDriver::start2DMode() {
|
||||||
// Enable alpha blending
|
// Enable alpha blending
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
//glBlendEquation(GL_FUNC_ADD); // It's the default
|
//glBlendEquation(GL_FUNC_ADD); // It's the default
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
|
// This blend mode prevents color fringes due to filtering.
|
||||||
|
// It requires the textures to have their color values pre-multiplied
|
||||||
|
// with their alpha value. This is the "Premultiplied Alpha" technique.
|
||||||
|
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
glDepthMask(GL_FALSE);
|
glDepthMask(GL_FALSE);
|
||||||
|
|
|
@ -78,6 +78,23 @@ void OpenGlTexture::update(const Graphics::Surface *surface, const byte *palette
|
||||||
updateLevel(0, surface, palette);
|
updateLevel(0, surface, palette);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OpenGlTexture::setSamplingFilter(Texture::SamplingFilter filter) {
|
||||||
|
assert(_levelCount == 0);
|
||||||
|
|
||||||
|
switch (filter) {
|
||||||
|
case kNearest:
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
break;
|
||||||
|
case kLinear:
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
warning("Unhandled sampling filter %d", filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void OpenGlTexture::setLevelCount(uint32 count) {
|
void OpenGlTexture::setLevelCount(uint32 count) {
|
||||||
_levelCount = count;
|
_levelCount = count;
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@ public:
|
||||||
// Texture API
|
// Texture API
|
||||||
void bind() const override;
|
void bind() const override;
|
||||||
void update(const Graphics::Surface *surface, const byte *palette = nullptr) override;
|
void update(const Graphics::Surface *surface, const byte *palette = nullptr) override;
|
||||||
|
void setSamplingFilter(SamplingFilter filter) override;
|
||||||
void setLevelCount(uint32 count) override;
|
void setLevelCount(uint32 count) override;
|
||||||
void addLevel(uint32 level, const Graphics::Surface *surface, const byte *palette = nullptr) override;
|
void addLevel(uint32 level, const Graphics::Surface *surface, const byte *palette = nullptr) override;
|
||||||
|
|
||||||
|
|
|
@ -40,12 +40,20 @@ public:
|
||||||
Texture();
|
Texture();
|
||||||
virtual ~Texture();
|
virtual ~Texture();
|
||||||
|
|
||||||
|
enum SamplingFilter {
|
||||||
|
kNearest,
|
||||||
|
kLinear
|
||||||
|
};
|
||||||
|
|
||||||
/** Make the texture active */
|
/** Make the texture active */
|
||||||
virtual void bind() const = 0;
|
virtual void bind() const = 0;
|
||||||
|
|
||||||
/** Define or update the texture pixel data */
|
/** Define or update the texture pixel data */
|
||||||
virtual void update(const Graphics::Surface *surface, const byte *palette = nullptr) = 0;
|
virtual void update(const Graphics::Surface *surface, const byte *palette = nullptr) = 0;
|
||||||
|
|
||||||
|
/** Set the filter used when sampling the texture */
|
||||||
|
virtual void setSamplingFilter(SamplingFilter filter) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define the total number of levels of details
|
* Define the total number of levels of details
|
||||||
*
|
*
|
||||||
|
|
|
@ -88,4 +88,8 @@ bool Settings::isAssetsModEnabled() const {
|
||||||
return ConfMan.getBool("enable_assets_mod");
|
return ConfMan.getBool("enable_assets_mod");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Gfx::Texture::SamplingFilter Settings::getImageSamplingFilter() const {
|
||||||
|
return ConfMan.getBool("use_linear_filtering") ? Gfx::Texture::kLinear : Gfx::Texture::kNearest;
|
||||||
|
}
|
||||||
|
|
||||||
} // End of namespace Stark
|
} // End of namespace Stark
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
#include "common/config-manager.h"
|
#include "common/config-manager.h"
|
||||||
|
|
||||||
|
#include "engines/stark/gfx/texture.h"
|
||||||
#include "engines/stark/services/services.h"
|
#include "engines/stark/services/services.h"
|
||||||
|
|
||||||
struct ADGameDescription;
|
struct ADGameDescription;
|
||||||
|
@ -97,6 +98,9 @@ public:
|
||||||
/** Should the game try to load external replacement assets? */
|
/** Should the game try to load external replacement assets? */
|
||||||
bool isAssetsModEnabled() const;
|
bool isAssetsModEnabled() const;
|
||||||
|
|
||||||
|
/** Should linear filtering be used when sampling the background image textures? */
|
||||||
|
Gfx::Texture::SamplingFilter getImageSamplingFilter() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Audio::Mixer *_mixer;
|
Audio::Mixer *_mixer;
|
||||||
bool _hasLowRes;
|
bool _hasLowRes;
|
||||||
|
|
|
@ -255,7 +255,7 @@ Screen *UserInterface::getScreenByName(Screen::Name screenName) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UserInterface::isInGameScreen() const {
|
bool UserInterface::isInGameScreen() const {
|
||||||
return _currentScreen->getName() == Screen::kScreenGame;
|
return _currentScreen && (_currentScreen->getName() == Screen::kScreenGame);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UserInterface::isInSaveLoadMenuScreen() const {
|
bool UserInterface::isInSaveLoadMenuScreen() const {
|
||||||
|
|
|
@ -45,6 +45,8 @@ FMVScreen::FMVScreen(Gfx::Driver *gfx, Cursor *cursor) :
|
||||||
_decoder->setSoundType(Audio::Mixer::kSFXSoundType);
|
_decoder->setSoundType(Audio::Mixer::kSFXSoundType);
|
||||||
|
|
||||||
_texture = _gfx->createTexture();
|
_texture = _gfx->createTexture();
|
||||||
|
_texture->setSamplingFilter(StarkSettings->getImageSamplingFilter());
|
||||||
|
|
||||||
_surfaceRenderer = _gfx->createSurfaceRenderer();
|
_surfaceRenderer = _gfx->createSurfaceRenderer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
#include "engines/stark/gfx/driver.h"
|
#include "engines/stark/gfx/driver.h"
|
||||||
#include "engines/stark/gfx/surfacerenderer.h"
|
#include "engines/stark/gfx/surfacerenderer.h"
|
||||||
#include "engines/stark/gfx/texture.h"
|
#include "engines/stark/gfx/texture.h"
|
||||||
|
#include "engines/stark/services/services.h"
|
||||||
|
#include "engines/stark/services/settings.h"
|
||||||
|
|
||||||
namespace Stark {
|
namespace Stark {
|
||||||
|
|
||||||
|
@ -40,6 +42,7 @@ VisualEffect::VisualEffect(VisualType type, const Common::Point &size, Gfx::Driv
|
||||||
_surface->create(size.x, size.y, Gfx::Driver::getRGBAPixelFormat());
|
_surface->create(size.x, size.y, Gfx::Driver::getRGBAPixelFormat());
|
||||||
|
|
||||||
_texture = _gfx->createTexture(_surface);
|
_texture = _gfx->createTexture(_surface);
|
||||||
|
_texture->setSamplingFilter(StarkSettings->getImageSamplingFilter());
|
||||||
|
|
||||||
_surfaceRenderer = _gfx->createSurfaceRenderer();
|
_surfaceRenderer = _gfx->createSurfaceRenderer();
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
|
|
||||||
#include "engines/stark/services/global.h"
|
#include "engines/stark/services/global.h"
|
||||||
#include "engines/stark/services/services.h"
|
#include "engines/stark/services/services.h"
|
||||||
|
#include "engines/stark/services/settings.h"
|
||||||
|
|
||||||
namespace Stark {
|
namespace Stark {
|
||||||
|
|
||||||
|
@ -57,7 +58,9 @@ void VisualExplodingImage::initFromSurface(const Graphics::Surface *surface) {
|
||||||
// Decode the XMG
|
// Decode the XMG
|
||||||
_surface = new Graphics::Surface();
|
_surface = new Graphics::Surface();
|
||||||
_surface->copyFrom(*surface);
|
_surface->copyFrom(*surface);
|
||||||
|
|
||||||
_texture = _gfx->createTexture(_surface);
|
_texture = _gfx->createTexture(_surface);
|
||||||
|
_texture->setSamplingFilter(StarkSettings->getImageSamplingFilter());
|
||||||
|
|
||||||
// Create an explosion unit for each pixel in the surface
|
// Create an explosion unit for each pixel in the surface
|
||||||
_units.resize(_surface->w * _surface->h);
|
_units.resize(_surface->w * _surface->h);
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
|
|
||||||
#include "engines/stark/services/global.h"
|
#include "engines/stark/services/global.h"
|
||||||
#include "engines/stark/services/services.h"
|
#include "engines/stark/services/services.h"
|
||||||
|
#include "engines/stark/services/settings.h"
|
||||||
|
|
||||||
namespace Stark {
|
namespace Stark {
|
||||||
|
|
||||||
|
@ -55,6 +56,7 @@ void VisualFlashingImage::initFromSurface(const Graphics::Surface *surface) {
|
||||||
assert(!_texture);
|
assert(!_texture);
|
||||||
|
|
||||||
_texture = _gfx->createTexture(surface);
|
_texture = _gfx->createTexture(surface);
|
||||||
|
_texture->setSamplingFilter(StarkSettings->getImageSamplingFilter());
|
||||||
}
|
}
|
||||||
|
|
||||||
void VisualFlashingImage::updateFadeLevel() {
|
void VisualFlashingImage::updateFadeLevel() {
|
||||||
|
|
|
@ -29,6 +29,8 @@
|
||||||
#include "engines/stark/gfx/driver.h"
|
#include "engines/stark/gfx/driver.h"
|
||||||
#include "engines/stark/gfx/surfacerenderer.h"
|
#include "engines/stark/gfx/surfacerenderer.h"
|
||||||
#include "engines/stark/gfx/texture.h"
|
#include "engines/stark/gfx/texture.h"
|
||||||
|
#include "engines/stark/services/services.h"
|
||||||
|
#include "engines/stark/services/settings.h"
|
||||||
|
|
||||||
namespace Stark {
|
namespace Stark {
|
||||||
|
|
||||||
|
@ -61,6 +63,7 @@ void VisualImageXMG::load(Common::ReadStream *stream) {
|
||||||
// Decode the XMG
|
// Decode the XMG
|
||||||
_surface = Formats::XMGDecoder::decode(stream);
|
_surface = Formats::XMGDecoder::decode(stream);
|
||||||
_texture = _gfx->createTexture(_surface);
|
_texture = _gfx->createTexture(_surface);
|
||||||
|
_texture->setSamplingFilter(StarkSettings->getImageSamplingFilter());
|
||||||
|
|
||||||
_originalWidth = _surface->w;
|
_originalWidth = _surface->w;
|
||||||
_originalHeight = _surface->h;
|
_originalHeight = _surface->h;
|
||||||
|
@ -81,7 +84,7 @@ bool VisualImageXMG::loadPNG(Common::SeekableReadStream *stream) {
|
||||||
|
|
||||||
_surface = pngDecoder.getSurface()->convertTo(Gfx::Driver::getRGBAPixelFormat());
|
_surface = pngDecoder.getSurface()->convertTo(Gfx::Driver::getRGBAPixelFormat());
|
||||||
_texture = _gfx->createTexture(_surface);
|
_texture = _gfx->createTexture(_surface);
|
||||||
_texture->setSamplingFilter(Gfx::Texture::kLinear);
|
_texture->setSamplingFilter(StarkSettings->getImageSamplingFilter());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "engines/stark/gfx/texture.h"
|
#include "engines/stark/gfx/texture.h"
|
||||||
#include "engines/stark/scene.h"
|
#include "engines/stark/scene.h"
|
||||||
#include "engines/stark/services/services.h"
|
#include "engines/stark/services/services.h"
|
||||||
|
#include "engines/stark/services/settings.h"
|
||||||
|
|
||||||
#include "common/str.h"
|
#include "common/str.h"
|
||||||
#include "common/archive.h"
|
#include "common/archive.h"
|
||||||
|
@ -63,6 +64,7 @@ void VisualSmacker::load(Common::SeekableReadStream *stream) {
|
||||||
rewind();
|
rewind();
|
||||||
|
|
||||||
_texture = _gfx->createTexture();
|
_texture = _gfx->createTexture();
|
||||||
|
_texture->setSamplingFilter(StarkSettings->getImageSamplingFilter());
|
||||||
|
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,6 +140,8 @@ void VisualText::createTexture() {
|
||||||
|
|
||||||
// Create a texture from the surface
|
// Create a texture from the surface
|
||||||
_texture = _gfx->createTexture(&surface);
|
_texture = _gfx->createTexture(&surface);
|
||||||
|
_texture->setSamplingFilter(Gfx::Texture::kNearest);
|
||||||
|
|
||||||
surface.free();
|
surface.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue