mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2026-04-27 04:41:39 +00:00
Fix untextured draws, implement custom rectangles.
This commit is contained in:
parent
26fa3cea58
commit
bdebd6408f
10 changed files with 232 additions and 49 deletions
|
|
@ -2,12 +2,165 @@
|
|||
|
||||
#include <msdf-atlas-gen/msdf-atlas-gen.h>
|
||||
|
||||
// Taken directly from msdf-atlas-gen, modified to support custom rectangles.
|
||||
struct TightAtlasPacker {
|
||||
|
||||
TightAtlasPacker() :
|
||||
width(-1), height(-1),
|
||||
spacing(0),
|
||||
dimensionsConstraint(msdf_atlas::DimensionsConstraint::POWER_OF_TWO_SQUARE),
|
||||
scale(-1),
|
||||
minScale(1),
|
||||
unitRange(0),
|
||||
pxRange(0),
|
||||
miterLimit(0),
|
||||
pxAlignOriginX(false), pxAlignOriginY(false),
|
||||
scaleMaximizationTolerance(.001)
|
||||
{
|
||||
}
|
||||
|
||||
int pack(msdf_atlas::GlyphGeometry* glyphs, int count, msdf_atlas::Rectangle* customRects, int customRectCount) {
|
||||
double initialScale = scale > 0 ? scale : minScale;
|
||||
if (initialScale > 0) {
|
||||
if (int remaining = tryPack(glyphs, count, customRects, customRectCount, dimensionsConstraint, width, height, initialScale))
|
||||
return remaining;
|
||||
}
|
||||
else if (width < 0 || height < 0)
|
||||
return -1;
|
||||
if (scale <= 0)
|
||||
scale = packAndScale(glyphs, count, customRects, customRectCount);
|
||||
if (scale <= 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int width, height;
|
||||
int spacing;
|
||||
msdf_atlas::DimensionsConstraint dimensionsConstraint;
|
||||
double scale;
|
||||
double minScale;
|
||||
msdfgen::Range unitRange;
|
||||
msdfgen::Range pxRange;
|
||||
double miterLimit;
|
||||
bool pxAlignOriginX, pxAlignOriginY;
|
||||
msdf_atlas::Padding innerUnitPadding, outerUnitPadding;
|
||||
msdf_atlas::Padding innerPxPadding, outerPxPadding;
|
||||
double scaleMaximizationTolerance;
|
||||
|
||||
int tryPack(msdf_atlas::GlyphGeometry* glyphs, int count, msdf_atlas::Rectangle* customRects, int customRectCount, msdf_atlas::DimensionsConstraint dimensionsConstraint, int& width, int& height, double scale) const {
|
||||
// Wrap glyphs into boxes
|
||||
std::vector<msdf_atlas::Rectangle> rectangles;
|
||||
std::vector<msdf_atlas::GlyphGeometry*> rectangleGlyphs;
|
||||
rectangles.reserve(count + customRectCount);
|
||||
rectangleGlyphs.reserve(count);
|
||||
msdf_atlas::GlyphGeometry::GlyphAttributes attribs = { };
|
||||
attribs.scale = scale;
|
||||
attribs.range = { unitRange.lower + pxRange.lower / scale, unitRange.upper + pxRange.upper / scale };
|
||||
attribs.innerPadding = innerUnitPadding + innerPxPadding / scale;
|
||||
attribs.outerPadding = outerUnitPadding + outerPxPadding / scale;
|
||||
attribs.miterLimit = miterLimit;
|
||||
attribs.pxAlignOriginX = pxAlignOriginX;
|
||||
attribs.pxAlignOriginY = pxAlignOriginY;
|
||||
for (msdf_atlas::GlyphGeometry* glyph = glyphs, *end = glyphs + count; glyph < end; ++glyph) {
|
||||
if (!glyph->isWhitespace()) {
|
||||
msdf_atlas::Rectangle rect = { };
|
||||
glyph->wrapBox(attribs);
|
||||
glyph->getBoxSize(rect.w, rect.h);
|
||||
if (rect.w > 0 && rect.h > 0) {
|
||||
rectangles.push_back(rect);
|
||||
rectangleGlyphs.push_back(glyph);
|
||||
}
|
||||
}
|
||||
}
|
||||
rectangles.insert(rectangles.end(), customRects, customRects + customRectCount);
|
||||
// No non-zero size boxes?
|
||||
if (rectangles.empty()) {
|
||||
if (width < 0 || height < 0)
|
||||
width = 0, height = 0;
|
||||
return 0;
|
||||
}
|
||||
// Box rectangle packing
|
||||
if (width < 0 || height < 0) {
|
||||
std::pair<int, int> dimensions = std::make_pair(width, height);
|
||||
switch (dimensionsConstraint) {
|
||||
case msdf_atlas::DimensionsConstraint::POWER_OF_TWO_SQUARE:
|
||||
dimensions = msdf_atlas::packRectangles<msdf_atlas::SquarePowerOfTwoSizeSelector>(rectangles.data(), rectangles.size(), spacing);
|
||||
break;
|
||||
case msdf_atlas::DimensionsConstraint::POWER_OF_TWO_RECTANGLE:
|
||||
dimensions = msdf_atlas::packRectangles<msdf_atlas::PowerOfTwoSizeSelector>(rectangles.data(), rectangles.size(), spacing);
|
||||
break;
|
||||
case msdf_atlas::DimensionsConstraint::MULTIPLE_OF_FOUR_SQUARE:
|
||||
dimensions = msdf_atlas::packRectangles<msdf_atlas::SquareSizeSelector<4> >(rectangles.data(), rectangles.size(), spacing);
|
||||
break;
|
||||
case msdf_atlas::DimensionsConstraint::EVEN_SQUARE:
|
||||
dimensions = msdf_atlas::packRectangles<msdf_atlas::SquareSizeSelector<2> >(rectangles.data(), rectangles.size(), spacing);
|
||||
break;
|
||||
case msdf_atlas::DimensionsConstraint::SQUARE:
|
||||
default:
|
||||
dimensions = msdf_atlas::packRectangles<msdf_atlas::SquareSizeSelector<> >(rectangles.data(), rectangles.size(), spacing);
|
||||
break;
|
||||
}
|
||||
if (!(dimensions.first > 0 && dimensions.second > 0))
|
||||
return -1;
|
||||
width = dimensions.first, height = dimensions.second;
|
||||
}
|
||||
else {
|
||||
if (int result = packRectangles(rectangles.data(), rectangles.size(), width, height, spacing))
|
||||
return result;
|
||||
}
|
||||
|
||||
// Set glyph box placement
|
||||
for (size_t i = 0; i < rectangleGlyphs.size(); ++i)
|
||||
rectangleGlyphs[i]->placeBox(rectangles[i].x, height - (rectangles[i].y + rectangles[i].h));
|
||||
|
||||
for (int i = 0; i < customRectCount; ++i) {
|
||||
customRects[i].x = rectangles[rectangleGlyphs.size() + i].x;
|
||||
customRects[i].y = height - (rectangles[rectangleGlyphs.size() + i].y + rectangles[rectangleGlyphs.size() + i].h);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
double packAndScale(msdf_atlas::GlyphGeometry* glyphs, int count, msdf_atlas::Rectangle* customRects, int customRectCount) const {
|
||||
bool lastResult = false;
|
||||
int w = width, h = height;
|
||||
#define TRY_PACK(scale) (lastResult = !tryPack(glyphs, count, customRects, customRectCount, msdf_atlas::DimensionsConstraint(), w, h, (scale)))
|
||||
double minScale = 1, maxScale = 1;
|
||||
if (TRY_PACK(1)) {
|
||||
while (maxScale < 1e+32 && ((maxScale = 2 * minScale), TRY_PACK(maxScale)))
|
||||
minScale = maxScale;
|
||||
}
|
||||
else {
|
||||
while (minScale > 1e-32 && ((minScale = .5 * maxScale), !TRY_PACK(minScale)))
|
||||
maxScale = minScale;
|
||||
}
|
||||
if (minScale == maxScale)
|
||||
return 0;
|
||||
while (minScale / maxScale < 1 - scaleMaximizationTolerance) {
|
||||
double midScale = .5 * (minScale + maxScale);
|
||||
if (TRY_PACK(midScale))
|
||||
minScale = midScale;
|
||||
else
|
||||
maxScale = midScale;
|
||||
}
|
||||
if (!lastResult)
|
||||
TRY_PACK(minScale);
|
||||
return minScale;
|
||||
}
|
||||
};
|
||||
|
||||
extern void ImFontAtlasBuildInit(ImFontAtlas* atlas);
|
||||
extern void ImFontAtlasBuildFinish(ImFontAtlas* atlas);
|
||||
|
||||
static bool FontBuilder_Build(ImFontAtlas* atlas)
|
||||
{
|
||||
ImFontAtlasBuildInit(atlas);
|
||||
|
||||
auto freeType = msdfgen::initializeFreetype();
|
||||
|
||||
std::vector<msdf_atlas::GlyphGeometry> glyphs;
|
||||
std::vector<std::pair<size_t, size_t>> ranges;
|
||||
std::vector<msdf_atlas::Rectangle> customRects;
|
||||
|
||||
for (auto& config : atlas->ConfigData)
|
||||
{
|
||||
|
|
@ -44,16 +197,25 @@ static bool FontBuilder_Build(ImFontAtlas* atlas)
|
|||
for (auto& glyph : glyphs)
|
||||
glyph.edgeColoring(&msdfgen::edgeColoringInkTrap, 3.0, 0);
|
||||
|
||||
msdf_atlas::TightAtlasPacker packer;
|
||||
packer.setMinimumScale(32.0);
|
||||
packer.setMiterLimit(1.0);
|
||||
packer.setPixelRange(2.0);
|
||||
packer.pack(glyphs.data(), glyphs.size());
|
||||
for (auto& customRect : atlas->CustomRects)
|
||||
customRects.emplace_back(0, 0, int(customRect.Width), int(customRect.Height));
|
||||
|
||||
int width = 0, height = 0;
|
||||
packer.getDimensions(width, height);
|
||||
TightAtlasPacker packer;
|
||||
packer.spacing = 1;
|
||||
packer.minScale = 16.0;
|
||||
packer.miterLimit = 1.0;
|
||||
packer.pxRange = 4.0;
|
||||
packer.pack(glyphs.data(), glyphs.size(), customRects.data(), customRects.size());
|
||||
|
||||
msdf_atlas::ImmediateAtlasGenerator<float, 4, &msdf_atlas::mtsdfGenerator, msdf_atlas::BitmapAtlasStorage<uint8_t, 4>> generator(width, height);
|
||||
for (size_t i = 0; i < customRects.size(); i++)
|
||||
{
|
||||
auto& srcRect = customRects[i];
|
||||
auto& dstRect = atlas->CustomRects[i];
|
||||
dstRect.X = srcRect.x;
|
||||
dstRect.Y = srcRect.y;
|
||||
}
|
||||
|
||||
msdf_atlas::ImmediateAtlasGenerator<float, 3, &msdf_atlas::msdfGenerator, msdf_atlas::BitmapAtlasStorage<uint8_t, 3>> generator(packer.width, packer.height);
|
||||
generator.generate(glyphs.data(), glyphs.size());
|
||||
|
||||
for (size_t i = 0; i < atlas->ConfigData.size(); i++)
|
||||
|
|
@ -73,28 +235,39 @@ static bool FontBuilder_Build(ImFontAtlas* atlas)
|
|||
-y1 + config.DstFont->Ascent,
|
||||
x1,
|
||||
-y0 + config.DstFont->Ascent,
|
||||
u0 / width,
|
||||
v1 / height,
|
||||
u1 / width,
|
||||
v0 / height,
|
||||
u0 / packer.width,
|
||||
v1 / packer.height,
|
||||
u1 / packer.width,
|
||||
v0 / packer.height,
|
||||
glyph.getAdvance());
|
||||
}
|
||||
|
||||
config.DstFont->BuildLookupTable();
|
||||
}
|
||||
|
||||
atlas->TexReady = true;
|
||||
atlas->TexPixelsUseColors = true;
|
||||
atlas->TexPixelsRGBA32 = (unsigned int*)IM_ALLOC(width * height * 4);
|
||||
atlas->TexWidth = width;
|
||||
atlas->TexHeight = height;
|
||||
atlas->TexUvScale = { 1.0f / width, 1.0f / height };
|
||||
atlas->TexPixelsRGBA32 = (unsigned int*)IM_ALLOC(packer.width * packer.height * 4);
|
||||
atlas->TexWidth = packer.width;
|
||||
atlas->TexHeight = packer.height;
|
||||
atlas->TexUvScale = { 1.0f / packer.width, 1.0f / packer.height };
|
||||
|
||||
auto bitmapRef = (msdfgen::BitmapConstRef<uint8_t, 4>)generator.atlasStorage();
|
||||
memcpy(atlas->TexPixelsRGBA32, bitmapRef.pixels, width * height * 4);
|
||||
auto bitmapRef = (msdfgen::BitmapConstRef<uint8_t, 3>)generator.atlasStorage();
|
||||
for (int y = 0; y < packer.height; y++)
|
||||
{
|
||||
for (int x = 0; x < packer.width; x++)
|
||||
{
|
||||
auto* srcPixels = bitmapRef(x, y);
|
||||
auto* dstPixels = (uint8_t*)&atlas->TexPixelsRGBA32[y * packer.width + x];
|
||||
dstPixels[0] = srcPixels[0];
|
||||
dstPixels[1] = srcPixels[1];
|
||||
dstPixels[2] = srcPixels[2];
|
||||
dstPixels[3] = 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
msdfgen::deinitializeFreetype(freeType);
|
||||
|
||||
ImFontAtlasBuildFinish(atlas);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -252,12 +252,12 @@ void ImFontAtlasSnapshot::GenerateGlyphRanges()
|
|||
g_glyphRanges.push_back(0);
|
||||
}
|
||||
|
||||
ImFont* ImFontAtlasSnapshot::GetFont(const char* name, float size)
|
||||
ImFont* ImFontAtlasSnapshot::GetFont(const char* name)
|
||||
{
|
||||
auto fontAtlas = ImGui::GetIO().Fonts;
|
||||
for (auto& configData : fontAtlas->ConfigData)
|
||||
{
|
||||
if (strstr(configData.Name, name) != nullptr && abs(configData.SizePixels - size) < 0.001f)
|
||||
if (strstr(configData.Name, name) != nullptr)
|
||||
{
|
||||
assert(configData.DstFont != nullptr);
|
||||
return configData.DstFont;
|
||||
|
|
@ -268,5 +268,5 @@ ImFont* ImFontAtlasSnapshot::GetFont(const char* name, float size)
|
|||
assert(false && "Unable to locate equivalent font in the atlas file.");
|
||||
#endif
|
||||
|
||||
return fontAtlas->AddFontFromFileTTF(name, size, nullptr, g_glyphRanges.data());
|
||||
return fontAtlas->AddFontFromFileTTF(name, 1.0f, nullptr, g_glyphRanges.data());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,5 +58,5 @@ struct ImFontAtlasSnapshot
|
|||
static void GenerateGlyphRanges();
|
||||
|
||||
// When ENABLE_IM_FONT_ATLAS_SNAPSHOT is undefined, this creates the font runtime instead.
|
||||
static ImFont* GetFont(const char* name, float size);
|
||||
static ImFont* GetFont(const char* name);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -73,13 +73,34 @@ float4 PixelAntialiasing(float2 uvTexspace)
|
|||
return SampleLinear(uvTexspace);
|
||||
}
|
||||
|
||||
float ComputeScreenPixelRange(float2 texCoord)
|
||||
{
|
||||
uint width, height;
|
||||
g_Texture2DDescriptorHeap[g_PushConstants.Texture2DDescriptorIndex].GetDimensions(width, height);
|
||||
|
||||
float2 unitRange = 4.0 / float2(width, height);
|
||||
float2 screenTextureSize = 1.0 / fwidth(texCoord);
|
||||
return max(0.5 * dot(unitRange, screenTextureSize), 1.0);
|
||||
}
|
||||
|
||||
float median(float r, float g, float b)
|
||||
{
|
||||
return max(min(r, g), min(max(r, g), b));
|
||||
}
|
||||
|
||||
float4 main(in Interpolators interpolators) : SV_Target
|
||||
{
|
||||
float4 color = interpolators.Color;
|
||||
color *= PixelAntialiasing(interpolators.Position.xy - 0.5);
|
||||
|
||||
if (g_PushConstants.Texture2DDescriptorIndex != 0)
|
||||
color *= g_Texture2DDescriptorHeap[g_PushConstants.Texture2DDescriptorIndex].Sample(g_SamplerDescriptorHeap[0], interpolators.UV);
|
||||
{
|
||||
float4 msd = g_Texture2DDescriptorHeap[g_PushConstants.Texture2DDescriptorIndex].Sample(g_SamplerDescriptorHeap[0], interpolators.UV);
|
||||
float sd = median(msd.r, msd.g, msd.b) - 0.5;
|
||||
float screenPixelDistance = ComputeScreenPixelRange(interpolators.UV) * sd;
|
||||
color.a *= saturate(screenPixelDistance + 0.5);
|
||||
color.a *= msd.a;
|
||||
}
|
||||
|
||||
if (g_PushConstants.ShaderModifier == IMGUI_SHADER_MODIFIER_MARQUEE_FADE)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -765,11 +765,9 @@ void AchievementMenu::Init()
|
|||
{
|
||||
auto& io = ImGui::GetIO();
|
||||
|
||||
constexpr float FONT_SCALE = 2.0f;
|
||||
|
||||
g_fntSeurat = ImFontAtlasSnapshot::GetFont("FOT-SeuratPro-M.otf", 24.0f * FONT_SCALE);
|
||||
g_fntNewRodinDB = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-DB.otf", 20.0f * FONT_SCALE);
|
||||
g_fntNewRodinUB = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-UB.otf", 20.0f * FONT_SCALE);
|
||||
g_fntSeurat = ImFontAtlasSnapshot::GetFont("FOT-SeuratPro-M.otf");
|
||||
g_fntNewRodinDB = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-DB.otf");
|
||||
g_fntNewRodinUB = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-UB.otf");
|
||||
|
||||
g_upTrophyIcon = LOAD_ZSTD_TEXTURE(g_trophy);
|
||||
g_upSelectionCursor = LOAD_ZSTD_TEXTURE(g_select_fill);
|
||||
|
|
|
|||
|
|
@ -76,9 +76,7 @@ void AchievementOverlay::Init()
|
|||
{
|
||||
auto& io = ImGui::GetIO();
|
||||
|
||||
constexpr float FONT_SCALE = 2.0f;
|
||||
|
||||
g_fntSeurat = ImFontAtlasSnapshot::GetFont("FOT-SeuratPro-M.otf", 24.0f * FONT_SCALE);
|
||||
g_fntSeurat = ImFontAtlasSnapshot::GetFont("FOT-SeuratPro-M.otf");
|
||||
|
||||
g_upWindow = LOAD_ZSTD_TEXTURE(g_general_window);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -214,10 +214,8 @@ void ButtonGuide::Init()
|
|||
{
|
||||
auto& io = ImGui::GetIO();
|
||||
|
||||
constexpr float FONT_SCALE = 2.0f;
|
||||
|
||||
g_fntNewRodin = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-M.otf", 24.0f * FONT_SCALE);
|
||||
g_fntNewRodinLQ = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-M.otf", 19.0f);
|
||||
g_fntNewRodin = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-M.otf");
|
||||
g_fntNewRodinLQ = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-M.otf");
|
||||
|
||||
g_upControllerIcons = LOAD_ZSTD_TEXTURE(g_controller);
|
||||
g_upKBMIcons = LOAD_ZSTD_TEXTURE(g_kbm);
|
||||
|
|
|
|||
|
|
@ -1334,10 +1334,9 @@ static void DrawMessagePrompt()
|
|||
void InstallerWizard::Init()
|
||||
{
|
||||
auto &io = ImGui::GetIO();
|
||||
constexpr float FONT_SCALE = 2.0f;
|
||||
g_seuratFont = ImFontAtlasSnapshot::GetFont("FOT-SeuratPro-M.otf", 24.0f * FONT_SCALE);
|
||||
g_dfsogeistdFont = ImFontAtlasSnapshot::GetFont("DFSoGeiStd-W7.otf", 48.0f * FONT_SCALE);
|
||||
g_newRodinFont = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-DB.otf", 20.0f * FONT_SCALE);
|
||||
g_seuratFont = ImFontAtlasSnapshot::GetFont("FOT-SeuratPro-M.otf");
|
||||
g_dfsogeistdFont = ImFontAtlasSnapshot::GetFont("DFSoGeiStd-W7.otf");
|
||||
g_newRodinFont = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-DB.otf");
|
||||
g_installTextures[0] = LOAD_ZSTD_TEXTURE(g_install_001);
|
||||
g_installTextures[1] = LOAD_ZSTD_TEXTURE(g_install_002);
|
||||
g_installTextures[2] = LOAD_ZSTD_TEXTURE(g_install_003);
|
||||
|
|
|
|||
|
|
@ -256,9 +256,7 @@ void MessageWindow::Init()
|
|||
{
|
||||
auto& io = ImGui::GetIO();
|
||||
|
||||
constexpr float FONT_SCALE = 2.0f;
|
||||
|
||||
g_fntSeurat = ImFontAtlasSnapshot::GetFont("FOT-SeuratPro-M.otf", 24.0f * FONT_SCALE);
|
||||
g_fntSeurat = ImFontAtlasSnapshot::GetFont("FOT-SeuratPro-M.otf");
|
||||
|
||||
g_upSelectionCursor = LOAD_ZSTD_TEXTURE(g_select_fade);
|
||||
g_upWindow = LOAD_ZSTD_TEXTURE(g_general_window);
|
||||
|
|
|
|||
|
|
@ -990,11 +990,9 @@ void OptionsMenu::Init()
|
|||
{
|
||||
auto& io = ImGui::GetIO();
|
||||
|
||||
constexpr float FONT_SCALE = 2.0f;
|
||||
|
||||
g_seuratFont = ImFontAtlasSnapshot::GetFont("FOT-SeuratPro-M.otf", 24.0f * FONT_SCALE);
|
||||
g_dfsogeistdFont = ImFontAtlasSnapshot::GetFont("DFSoGeiStd-W7.otf", 48.0f * FONT_SCALE);
|
||||
g_newRodinFont = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-DB.otf", 20.0f * FONT_SCALE);
|
||||
g_seuratFont = ImFontAtlasSnapshot::GetFont("FOT-SeuratPro-M.otf");
|
||||
g_dfsogeistdFont = ImFontAtlasSnapshot::GetFont("DFSoGeiStd-W7.otf");
|
||||
g_newRodinFont = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-DB.otf");
|
||||
|
||||
LoadThumbnails();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue