mirror of https://github.com/OpenRCT2/OpenRCT2.git
Added OpenGL TTF hinting
This commit is contained in:
parent
f64706e1d9
commit
8c7d1d149a
|
@ -5,6 +5,7 @@ uniform sampler2D uOpaqueDepth;
|
|||
uniform usampler2D uTransparentTex;
|
||||
uniform sampler2D uTransparentDepth;
|
||||
uniform usampler2D uPaletteTex;
|
||||
uniform usampler2D uBlendPaletteTex;
|
||||
|
||||
in vec2 fTextureCoordinate;
|
||||
|
||||
|
@ -22,5 +23,20 @@ void main()
|
|||
transparent = 0u;
|
||||
}
|
||||
|
||||
uint blendColour = (transparent & 0xff00u) >> 8;
|
||||
if(blendColour > 0u)
|
||||
{
|
||||
if((transparent & 0x00ffu) != 0u)
|
||||
{
|
||||
oColour = blendColour;
|
||||
}
|
||||
else
|
||||
{
|
||||
oColour = texture(uBlendPaletteTex, vec2(opaque, blendColour) / 256.f).r;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
oColour = texture(uPaletteTex, vec2(opaque, transparent) / 256.f).r;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,10 +47,24 @@ void main()
|
|||
texel += fColour;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint hint_thresh = uint(fFlags & 0xff00) >> 8;
|
||||
if(hint_thresh > 0u)
|
||||
{
|
||||
bool solidColor = texel > 180u;
|
||||
texel = (texel > hint_thresh) ? fColour : 0u;
|
||||
texel = texel << 8;
|
||||
if(solidColor)
|
||||
{
|
||||
texel += 1u;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
texel = fColour;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
texel = fColour;
|
||||
|
|
|
@ -8,19 +8,21 @@
|
|||
- Feature: [#20825] Made setting the game speed a game action.
|
||||
- Feature: [#20853] [Plugin] Add “BaseTileElement.owner” which is saved in the park file.
|
||||
- Change: [#20790] Default ride price set to free if park charges for entry.
|
||||
- Fix: [#15293] TTF fonts don’t format correctly with OpenGL.
|
||||
- Fix: [#16453] Tile inspector invisibility shortcut does not use a game action.
|
||||
- Fix: [#17774] Misplaced/missing land and construction rights tiles in RCT1 & RCT2 scenarios.
|
||||
- Fix: [#18199] Dots in the game save's name no longer get truncated.
|
||||
- Fix: [#19722] “Forbid tree removal” restriction doesn't forbid removal of large scenery tree items.
|
||||
- Fix: [#20253] Crash when displaying a Lay-Down RC’s half loop.
|
||||
- Fix: [#20356] Cannot set tertiary colour on small scenery.
|
||||
- Fix: [#20624] Scrolling text glitches after language is changed.
|
||||
- Fix: [#20679] Android: game crashes at launch.
|
||||
- Fix: [#20737] Spent money in player window underflows when getting refunds.
|
||||
- Fix: [#20747] Staff speed cheat not applying to newly hired staff, UI not showing the current applied speed.
|
||||
- Fix: [#20778] [Plugin] Incorrect target api when executing custom actions.
|
||||
- Fix: [#20807] Tertiary colour not copied with small scenery.
|
||||
- Fix: [#20964] Crash when player connects to server with a group assigned that no longer exists.
|
||||
- Fix: [#20624] Scrolling text glitches after language is changed.
|
||||
- Fix: [#20995] TTF fonts don’t support hinting, outlines, or insets with OpenGL.
|
||||
|
||||
0.4.6 (2023-09-03)
|
||||
------------------------------------------------------------------------
|
||||
|
|
|
@ -54,6 +54,7 @@ ApplyTransparencyShader::ApplyTransparencyShader()
|
|||
glUniform1i(uTransparentTex, 2);
|
||||
glUniform1i(uTransparentDepth, 3);
|
||||
glUniform1i(uPaletteTex, 4);
|
||||
glUniform1i(uBlendPaletteTex, 5);
|
||||
}
|
||||
|
||||
ApplyTransparencyShader::~ApplyTransparencyShader()
|
||||
|
@ -69,19 +70,22 @@ void ApplyTransparencyShader::GetLocations()
|
|||
uTransparentTex = GetUniformLocation("uTransparentTex");
|
||||
uTransparentDepth = GetUniformLocation("uTransparentDepth");
|
||||
uPaletteTex = GetUniformLocation("uPaletteTex");
|
||||
uBlendPaletteTex = GetUniformLocation("uBlendPaletteTex");
|
||||
|
||||
vPosition = GetAttributeLocation("vPosition");
|
||||
vTextureCoordinate = GetAttributeLocation("vTextureCoordinate");
|
||||
}
|
||||
|
||||
void ApplyTransparencyShader::SetTextures(
|
||||
GLuint opaqueTex, GLuint opaqueDepth, GLuint transparentTex, GLuint transparentDepth, GLuint paletteTex)
|
||||
GLuint opaqueTex, GLuint opaqueDepth, GLuint transparentTex, GLuint transparentDepth, GLuint paletteTex,
|
||||
GLuint blendPaletteTex)
|
||||
{
|
||||
OpenGLAPI::SetTexture(0, GL_TEXTURE_2D, opaqueTex);
|
||||
OpenGLAPI::SetTexture(1, GL_TEXTURE_2D, opaqueDepth);
|
||||
OpenGLAPI::SetTexture(2, GL_TEXTURE_2D, transparentTex);
|
||||
OpenGLAPI::SetTexture(3, GL_TEXTURE_2D, transparentDepth);
|
||||
OpenGLAPI::SetTexture(4, GL_TEXTURE_2D, paletteTex);
|
||||
OpenGLAPI::SetTexture(5, GL_TEXTURE_2D, blendPaletteTex);
|
||||
}
|
||||
|
||||
void ApplyTransparencyShader::Draw()
|
||||
|
|
|
@ -20,6 +20,7 @@ private:
|
|||
GLuint uTransparentTex;
|
||||
GLuint uTransparentDepth;
|
||||
GLuint uPaletteTex;
|
||||
GLuint uBlendPaletteTex;
|
||||
|
||||
GLuint vPosition;
|
||||
GLuint vTextureCoordinate;
|
||||
|
@ -32,7 +33,8 @@ public:
|
|||
~ApplyTransparencyShader() override;
|
||||
|
||||
static void SetTextures(
|
||||
GLuint opaqueTex, GLuint opaqueDepth, GLuint transparentTex, GLuint transparentDepth, GLuint paletteTex);
|
||||
GLuint opaqueTex, GLuint opaqueDepth, GLuint transparentTex, GLuint transparentDepth, GLuint paletteTex,
|
||||
GLuint blendPaletteTex);
|
||||
void Draw();
|
||||
|
||||
private:
|
||||
|
|
|
@ -119,6 +119,8 @@ struct DrawRectCommand
|
|||
FLAG_MASK = (1u << 3u),
|
||||
FLAG_CROSS_HATCH = (1u << 4u),
|
||||
FLAG_TTF_TEXT = (1u << 5u),
|
||||
// bits 8 to 16 used to store hinting threshold.
|
||||
FLAG_TTF_HINTING_THRESHOLD_MASK = 0xff00
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
|
||||
# include <SDL.h>
|
||||
# include <algorithm>
|
||||
# include <array>
|
||||
# include <cmath>
|
||||
# include <openrct2-ui/interface/Window.h>
|
||||
# include <openrct2/Intro.h>
|
||||
|
@ -112,7 +111,7 @@ public:
|
|||
void DrawGlyph(DrawPixelInfo* dpi, const ImageId image, int32_t x, int32_t y, const PaletteMap& palette) override;
|
||||
void DrawTTFBitmap(
|
||||
DrawPixelInfo* dpi, TextDrawInfo* info, ImageIndex image, const void* pixels, int32_t width, int32_t height, int32_t x,
|
||||
int32_t y) override;
|
||||
int32_t y, uint8_t hinting_threshold) override;
|
||||
|
||||
void FlushCommandBuffers();
|
||||
|
||||
|
@ -910,7 +909,7 @@ void OpenGLDrawingContext::DrawGlyph(DrawPixelInfo* dpi, const ImageId image, in
|
|||
|
||||
void OpenGLDrawingContext::DrawTTFBitmap(
|
||||
DrawPixelInfo* dpi, TextDrawInfo* info, ImageIndex image, const void* pixels, int32_t width, int32_t height, int32_t x,
|
||||
int32_t y)
|
||||
int32_t y, uint8_t hinting_threshold)
|
||||
{
|
||||
CalculcateClipping(dpi);
|
||||
|
||||
|
@ -977,15 +976,15 @@ void OpenGLDrawingContext::DrawTTFBitmap(
|
|||
command.bounds = { left + 1, top + 1, right + 1, bottom + 1 };
|
||||
command.depth = _drawCount++;
|
||||
}
|
||||
|
||||
DrawRectCommand& command = _commandBuffers.rects.allocate();
|
||||
auto& cmdBuf = hinting_threshold > 0 ? _commandBuffers.transparent : _commandBuffers.rects;
|
||||
DrawRectCommand& command = cmdBuf.allocate();
|
||||
command.clip = { _clipLeft, _clipTop, _clipRight, _clipBottom };
|
||||
command.texColourAtlas = texture.index;
|
||||
command.texColourBounds = texture.normalizedBounds;
|
||||
command.texMaskAtlas = 0;
|
||||
command.texMaskBounds = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
command.palettes = { 0, 0, 0 };
|
||||
command.flags = DrawRectCommand::FLAG_TTF_TEXT;
|
||||
command.flags = DrawRectCommand::FLAG_TTF_TEXT | (hinting_threshold << 8);
|
||||
command.colour = info->palette[1];
|
||||
command.bounds = { left, top, right, bottom };
|
||||
command.depth = _drawCount++;
|
||||
|
@ -1061,7 +1060,8 @@ void OpenGLDrawingContext::HandleTransparency()
|
|||
|
||||
_drawRectShader->Use();
|
||||
_drawRectShader->DrawInstances();
|
||||
_swapFramebuffer->ApplyTransparency(*_applyTransparencyShader, _textureCache->GetPaletteTexture());
|
||||
_swapFramebuffer->ApplyTransparency(
|
||||
*_applyTransparencyShader, _textureCache->GetPaletteTexture(), _textureCache->GetBlendPaletteTexture());
|
||||
}
|
||||
|
||||
_commandBuffers.transparent.clear();
|
||||
|
|
|
@ -26,7 +26,7 @@ OpenGLFramebuffer::OpenGLFramebuffer(SDL_Window* window)
|
|||
SDL_GL_GetDrawableSize(window, &_width, &_height);
|
||||
}
|
||||
|
||||
OpenGLFramebuffer::OpenGLFramebuffer(int32_t width, int32_t height, bool depth, bool integer)
|
||||
OpenGLFramebuffer::OpenGLFramebuffer(int32_t width, int32_t height, bool depth, bool integer, bool word)
|
||||
{
|
||||
_width = width;
|
||||
_height = height;
|
||||
|
@ -35,7 +35,9 @@ OpenGLFramebuffer::OpenGLFramebuffer(int32_t width, int32_t height, bool depth,
|
|||
glBindTexture(GL_TEXTURE_2D, _texture);
|
||||
if (integer)
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8UI, width, height, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, nullptr);
|
||||
int internalFormat = word ? GL_R16UI : GL_R8UI;
|
||||
int type = word ? GL_UNSIGNED_SHORT : GL_UNSIGNED_BYTE;
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, GL_RED_INTEGER, type, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -28,7 +28,7 @@ private:
|
|||
|
||||
public:
|
||||
explicit OpenGLFramebuffer(SDL_Window* window);
|
||||
OpenGLFramebuffer(int32_t width, int32_t height, bool depth = true, bool integer = true);
|
||||
OpenGLFramebuffer(int32_t width, int32_t height, bool depth = true, bool integer = true, bool word = false);
|
||||
~OpenGLFramebuffer();
|
||||
|
||||
OpenGLFramebuffer(const OpenGLFramebuffer&) = delete;
|
||||
|
|
|
@ -19,7 +19,7 @@ constexpr GLuint indexValue[4] = { 0, 0, 0, 0 };
|
|||
|
||||
SwapFramebuffer::SwapFramebuffer(int32_t width, int32_t height)
|
||||
: _opaqueFramebuffer(width, height)
|
||||
, _transparentFramebuffer(width, height)
|
||||
, _transparentFramebuffer(width, height, true, true, true)
|
||||
, _mixFramebuffer(width, height, false)
|
||||
, _backDepth(OpenGLFramebuffer::CreateDepthTexture(width, height))
|
||||
{
|
||||
|
@ -32,14 +32,14 @@ SwapFramebuffer::~SwapFramebuffer()
|
|||
glDeleteTextures(1, &_backDepth);
|
||||
}
|
||||
|
||||
void SwapFramebuffer::ApplyTransparency(ApplyTransparencyShader& shader, GLuint paletteTex)
|
||||
void SwapFramebuffer::ApplyTransparency(ApplyTransparencyShader& shader, GLuint paletteTex, GLuint blendPaletteTex)
|
||||
{
|
||||
_mixFramebuffer.Bind();
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
shader.Use();
|
||||
shader.SetTextures(
|
||||
_opaqueFramebuffer.GetTexture(), _opaqueFramebuffer.GetDepthTexture(), _transparentFramebuffer.GetTexture(),
|
||||
_transparentFramebuffer.GetDepthTexture(), paletteTex);
|
||||
_transparentFramebuffer.GetDepthTexture(), paletteTex, blendPaletteTex);
|
||||
shader.Draw();
|
||||
|
||||
_backDepth = _transparentFramebuffer.SwapDepthTexture(_backDepth);
|
||||
|
|
|
@ -52,6 +52,6 @@ public:
|
|||
_transparentFramebuffer.Bind();
|
||||
}
|
||||
|
||||
void ApplyTransparency(ApplyTransparencyShader& shader, GLuint paletteTex);
|
||||
void ApplyTransparency(ApplyTransparencyShader& shader, GLuint paletteTex, GLuint blendPaletteTex);
|
||||
void Clear();
|
||||
};
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
# include <algorithm>
|
||||
# include <openrct2/drawing/Drawing.h>
|
||||
# include <openrct2/interface/Colour.h>
|
||||
# include <openrct2/util/Util.h>
|
||||
# include <openrct2/world/Location.hpp>
|
||||
# include <stdexcept>
|
||||
|
@ -193,6 +194,18 @@ void TextureCache::CreateTextures()
|
|||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
GeneratePaletteTexture();
|
||||
|
||||
auto blendArray = GetBlendColourMap();
|
||||
if (blendArray != nullptr)
|
||||
{
|
||||
glGenTextures(1, &_blendPaletteTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, _blendPaletteTexture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_2D, 0, GL_R8UI, PALETTE_SIZE, PALETTE_SIZE, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, blendArray);
|
||||
}
|
||||
|
||||
_initialized = true;
|
||||
_atlasesTextureIndices = 0;
|
||||
_atlasesTextureCapacity = 0;
|
||||
|
@ -414,6 +427,11 @@ GLuint TextureCache::GetPaletteTexture()
|
|||
return _paletteTexture;
|
||||
}
|
||||
|
||||
GLuint TextureCache::GetBlendPaletteTexture()
|
||||
{
|
||||
return _blendPaletteTexture;
|
||||
}
|
||||
|
||||
GLint TextureCache::PaletteToY(FilterPaletteID palette)
|
||||
{
|
||||
return palette > FilterPaletteID::PaletteWater ? EnumValue(palette) + 5 : EnumValue(palette) + 1;
|
||||
|
|
|
@ -206,6 +206,7 @@ private:
|
|||
std::array<uint32_t, SPR_IMAGE_LIST_END> _indexMap;
|
||||
|
||||
GLuint _paletteTexture = 0;
|
||||
GLuint _blendPaletteTexture = 0;
|
||||
|
||||
#ifndef __MACOSX__
|
||||
std::shared_mutex _mutex;
|
||||
|
@ -227,6 +228,7 @@ public:
|
|||
|
||||
GLuint GetAtlasesTexture();
|
||||
GLuint GetPaletteTexture();
|
||||
GLuint GetBlendPaletteTexture();
|
||||
static GLint PaletteToY(FilterPaletteID palette);
|
||||
|
||||
private:
|
||||
|
|
|
@ -541,19 +541,21 @@ static void TTFDrawStringRawTTF(DrawPixelInfo& dpi, std::string_view text, TextD
|
|||
|
||||
if (OpenRCT2::GetContext()->GetDrawingEngineType() == DrawingEngine::OpenGL)
|
||||
{
|
||||
// if(use_hinting) return; // Not implemented yet.
|
||||
auto baseId = uint32_t(0x7FFFF) - 1024;
|
||||
auto imageId = baseId + _ttfGlId;
|
||||
auto drawingEngine = dpi.DrawingEngine;
|
||||
auto drawingContext = drawingEngine->GetDrawingContext();
|
||||
uint8_t hint_thresh = use_hinting ? fontDesc->hinting_threshold : 0;
|
||||
drawingEngine->InvalidateImage(imageId);
|
||||
drawingContext->DrawTTFBitmap(&dpi, info, imageId, surface->pixels, surface->pitch, surface->h, drawX, drawY);
|
||||
drawingContext->DrawTTFBitmap(
|
||||
&dpi, info, imageId, surface->pixels, surface->pitch, surface->h, drawX, drawY, hint_thresh);
|
||||
|
||||
_ttfGlId++;
|
||||
if (_ttfGlId >= 1023)
|
||||
{
|
||||
_ttfGlId = 0;
|
||||
}
|
||||
info->x += width;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace OpenRCT2::Drawing
|
|||
DrawPixelInfo* dpi, const ImageId image, int32_t x, int32_t y, const PaletteMap& palette) abstract;
|
||||
virtual void DrawTTFBitmap(
|
||||
DrawPixelInfo* dpi, TextDrawInfo* info, ImageIndex image, const void* pixels, int32_t width, int32_t height,
|
||||
int32_t x, int32_t y) abstract;
|
||||
int32_t x, int32_t y, uint8_t hinting_threshold) abstract;
|
||||
};
|
||||
|
||||
} // namespace OpenRCT2::Drawing
|
||||
|
|
|
@ -149,7 +149,7 @@ namespace OpenRCT2
|
|||
DrawPixelInfo* dpi, const ImageId image, int32_t x, int32_t y, const PaletteMap& paletteMap) override;
|
||||
void DrawTTFBitmap(
|
||||
DrawPixelInfo* dpi, TextDrawInfo* info, uint32_t image, const void* pixels, int32_t width, int32_t height,
|
||||
int32_t x, int32_t y) override
|
||||
int32_t x, int32_t y, uint8_t hinting_threshold) override
|
||||
{
|
||||
}
|
||||
};
|
||||
|
|
|
@ -130,7 +130,9 @@ namespace Colour
|
|||
} // namespace Colour
|
||||
|
||||
#ifndef NO_TTF
|
||||
static uint8_t BlendColourMap[PALETTE_COUNT][PALETTE_COUNT] = { 0 };
|
||||
static BlendColourMapType BlendColourMap = { 0 };
|
||||
|
||||
static bool BlendColourMapInitialised = false;
|
||||
|
||||
static uint8_t FindClosestPaletteIndex(uint8_t red, uint8_t green, uint8_t blue)
|
||||
{
|
||||
|
@ -152,21 +154,44 @@ static uint8_t FindClosestPaletteIndex(uint8_t red, uint8_t green, uint8_t blue)
|
|||
return closest;
|
||||
}
|
||||
|
||||
static void InitBlendColourMap()
|
||||
{
|
||||
for (int i = 0; i < PALETTE_SIZE; i++)
|
||||
{
|
||||
for (int j = i; j < PALETTE_SIZE; j++)
|
||||
{
|
||||
uint8_t red = (gPalette[i].Red + gPalette[j].Red) / 2;
|
||||
uint8_t green = (gPalette[i].Green + gPalette[j].Green) / 2;
|
||||
uint8_t blue = (gPalette[i].Blue + gPalette[j].Blue) / 2;
|
||||
|
||||
auto colour = FindClosestPaletteIndex(red, green, blue);
|
||||
BlendColourMap[i][j] = colour;
|
||||
BlendColourMap[j][i] = colour;
|
||||
}
|
||||
}
|
||||
BlendColourMapInitialised = true;
|
||||
}
|
||||
|
||||
BlendColourMapType* GetBlendColourMap()
|
||||
{
|
||||
if (!BlendColourMapInitialised)
|
||||
{
|
||||
InitBlendColourMap();
|
||||
}
|
||||
return &BlendColourMap;
|
||||
}
|
||||
|
||||
uint8_t BlendColours(const uint8_t paletteIndex1, const uint8_t paletteIndex2)
|
||||
{
|
||||
const uint8_t cMin = std::min(paletteIndex1, paletteIndex2);
|
||||
const uint8_t cMax = std::max(paletteIndex1, paletteIndex2);
|
||||
|
||||
if (BlendColourMap[cMin][cMax] != 0)
|
||||
if (!BlendColourMapInitialised)
|
||||
{
|
||||
return BlendColourMap[cMin][cMax];
|
||||
InitBlendColourMap();
|
||||
}
|
||||
|
||||
uint8_t red = (gPalette[cMin].Red + gPalette[cMax].Red) / 2;
|
||||
uint8_t green = (gPalette[cMin].Green + gPalette[cMax].Green) / 2;
|
||||
uint8_t blue = (gPalette[cMin].Blue + gPalette[cMax].Blue) / 2;
|
||||
|
||||
BlendColourMap[cMin][cMax] = FindClosestPaletteIndex(red, green, blue);
|
||||
return BlendColourMap[cMin][cMax];
|
||||
return BlendColourMap[paletteIndex1][paletteIndex2];
|
||||
}
|
||||
#else
|
||||
BlendColourMapType* GetBlendColourMap()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -252,3 +252,6 @@ namespace Colour
|
|||
#ifndef NO_TTF
|
||||
uint8_t BlendColours(const uint8_t paletteIndex1, const uint8_t paletteIndex2);
|
||||
#endif
|
||||
|
||||
typedef uint8_t BlendColourMapType[PALETTE_COUNT][PALETTE_COUNT];
|
||||
BlendColourMapType* GetBlendColourMap();
|
Loading…
Reference in New Issue