mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-04-02 13:37:42 -05:00
feat: Added Subpixel Font rendering (#2092)
Proof of concept for implementing subpixel processing in ImGui. This is work in progress, and it is bound to have problems. What it does: 1) Uses freetype own subpixel processing implementation to build a 32-bit color atlas for the default font only (no icons, no unifont) . 2) Avoids pixel perfect font conversion when possible. 3) Self contained, no ImGui source code changes. 4) Results in much improved legibility of fonts rendered on low dpi LCD screens that use horizontal RGB pixel layouts (no BRG or OLED or CRT if they even exist anymore) What it doesn't: 1) Fancy class based interface. The code is barely the minimum needed to show it can work. 2) Dual source color blending. That needs to be implemented in shader code, so it needs to change ImGui source code although minimally. This will result in some characters appearing dimmer than others. Easily fixed with small fragment and vertex shaders. 3) subpixel positioning. If characters are very thin they will look colored, or they can be moved to improve legibility. 4) deal with detection of fringe cases including rare pixel layouts, non LCD screens, Mac-OS not handling subpixel rendering and any other deviation from the standard LCD. 5) tries to be efficient in speed or memory use. Font Atlases will be 4 times the size they were before, but there are no noticeable delays in font loading in the examples I have tried. Any comments and code improvements are welcome. --------- Co-authored-by: Nik <werwolv98@gmail.com>
This commit is contained in:
@@ -40,6 +40,7 @@ set(LIBIMHEX_SOURCES
|
||||
source/helpers/imgui_hooks.cpp
|
||||
source/helpers/semantic_version.cpp
|
||||
source/helpers/keys.cpp
|
||||
source/helpers/freetype.cpp
|
||||
|
||||
source/test/tests.cpp
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <hex.hpp>
|
||||
#include <hex/api/localization_manager.hpp>
|
||||
#include <hex/helpers/semantic_version.hpp>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
#include <hex/helpers/fs.hpp>
|
||||
|
||||
#include <functional>
|
||||
@@ -13,6 +14,7 @@
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <memory>
|
||||
#include "imgui_internal.h"
|
||||
|
||||
#if !defined(HEX_MODULE_EXPORT)
|
||||
using ImGuiID = unsigned int;
|
||||
@@ -752,6 +754,7 @@ EXPORT_MODULE namespace hex {
|
||||
std::vector<GlyphRange> glyphRanges;
|
||||
Offset offset;
|
||||
u32 flags;
|
||||
std::optional<bool> scalable;
|
||||
std::optional<u32> defaultSize;
|
||||
};
|
||||
|
||||
@@ -768,14 +771,18 @@ EXPORT_MODULE namespace hex {
|
||||
GlyphRange range(const char *glyphBegin, const char *glyphEnd);
|
||||
GlyphRange range(u32 codepointBegin, u32 codepointEnd);
|
||||
|
||||
void loadFont(const std::fs::path &path, const std::vector<GlyphRange> &glyphRanges = {}, Offset offset = {}, u32 flags = 0, std::optional<u32> defaultSize = std::nullopt);
|
||||
void loadFont(const std::string &name, const std::span<const u8> &data, const std::vector<GlyphRange> &glyphRanges = {}, Offset offset = {}, u32 flags = 0, std::optional<u32> defaultSize = std::nullopt);
|
||||
void loadFont(const std::fs::path &path, const std::vector<GlyphRange> &glyphRanges = {}, Offset offset = {}, u32 flags = 0, std::optional<bool> scalable = std::nullopt, std::optional<u32> defaultSize = std::nullopt);
|
||||
void loadFont(const std::string &name, const std::span<const u8> &data, const std::vector<GlyphRange> &glyphRanges = {}, Offset offset = {}, u32 flags = 0, std::optional<bool> scalable = std::nullopt, std::optional<u32> defaultSize = std::nullopt);
|
||||
|
||||
constexpr float DefaultFontSize = 13.0;
|
||||
|
||||
void registerFont(const UnlocalizedString &fontName);
|
||||
ImFont* getFont(const UnlocalizedString &fontName);
|
||||
|
||||
float getDpi();
|
||||
float pixelsToPoints(float pixels);
|
||||
float pointsToPixels(float points);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
60
lib/libimhex/include/hex/helpers/freetype.hpp
Normal file
60
lib/libimhex/include/hex/helpers/freetype.hpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
#include "imgui.h"
|
||||
#include <vector>
|
||||
|
||||
namespace hex::ft {
|
||||
|
||||
class Bitmap {
|
||||
ImU32 m_width;
|
||||
ImU32 m_height;
|
||||
ImU32 m_pitch;
|
||||
std::vector <ImU8> m_data;
|
||||
public:
|
||||
Bitmap(ImU32 width, ImU32 height, ImU32 pitch, ImU8 *data) : m_width(width), m_height(height), m_pitch(pitch), m_data(std::vector<ImU8>(data, data + pitch * height)) {}
|
||||
|
||||
Bitmap(ImU32 width, ImU32 height, ImU32 pitch) : m_width(width), m_height(height), m_pitch(pitch) { m_data.resize(pitch * height); }
|
||||
|
||||
void clear() { m_data.clear(); }
|
||||
|
||||
ImU32 getWidth() const { return m_width; }
|
||||
|
||||
ImU32 getHeight() const { return m_height; }
|
||||
|
||||
ImU32 getPitch() const { return m_pitch; }
|
||||
|
||||
const std::vector <ImU8> &getData() const { return m_data; }
|
||||
|
||||
ImU8 *getData() { return m_data.data(); }
|
||||
|
||||
void lcdFilter();
|
||||
};
|
||||
|
||||
class RGBA {
|
||||
public:
|
||||
|
||||
static ImU32 addAlpha(ImU8 r, ImU8 g, ImU8 b) {
|
||||
color.rgbaVec[0] = r;
|
||||
color.rgbaVec[1] = g;
|
||||
color.rgbaVec[2] = b;
|
||||
color.rgbaVec[3] = (r + g + b) / 3;//luminance
|
||||
return color.rgba;
|
||||
}
|
||||
|
||||
RGBA(ImU8 r, ImU8 g, ImU8 b, ImU8 a) {
|
||||
color.rgbaVec[0] = r;
|
||||
color.rgbaVec[1] = b;
|
||||
color.rgbaVec[2] = g;
|
||||
color.rgbaVec[3] = a;
|
||||
}
|
||||
|
||||
explicit RGBA(ImU32 rgba) {
|
||||
color.rgba = rgba;
|
||||
}
|
||||
|
||||
union RGBAU {
|
||||
ImU8 rgbaVec[4];
|
||||
ImU32 rgba;
|
||||
};
|
||||
inline static RGBAU color;
|
||||
};
|
||||
}
|
||||
@@ -1065,7 +1065,7 @@ namespace hex {
|
||||
};
|
||||
}
|
||||
|
||||
void loadFont(const std::fs::path &path, const std::vector<GlyphRange> &glyphRanges, Offset offset, u32 flags, std::optional<u32> defaultSize) {
|
||||
void loadFont(const std::fs::path &path, const std::vector<GlyphRange> &glyphRanges, Offset offset, u32 flags, std::optional<bool> scalable, std::optional<u32> defaultSize) {
|
||||
wolv::io::File fontFile(path, wolv::io::File::Mode::Read);
|
||||
if (!fontFile.isValid()) {
|
||||
log::error("Failed to load font from file '{}'", wolv::util::toUTF8String(path));
|
||||
@@ -1078,17 +1078,19 @@ namespace hex {
|
||||
glyphRanges,
|
||||
offset,
|
||||
flags,
|
||||
scalable,
|
||||
defaultSize
|
||||
});
|
||||
}
|
||||
|
||||
void loadFont(const std::string &name, const std::span<const u8> &data, const std::vector<GlyphRange> &glyphRanges, Offset offset, u32 flags, std::optional<u32> defaultSize) {
|
||||
void loadFont(const std::string &name, const std::span<const u8> &data, const std::vector<GlyphRange> &glyphRanges, Offset offset, u32 flags, std::optional<bool> scalable, std::optional<u32> defaultSize) {
|
||||
impl::s_fonts->emplace_back(Font {
|
||||
name,
|
||||
{ data.begin(), data.end() },
|
||||
glyphRanges,
|
||||
offset,
|
||||
flags,
|
||||
scalable,
|
||||
defaultSize
|
||||
});
|
||||
}
|
||||
@@ -1117,6 +1119,18 @@ namespace hex {
|
||||
return impl::s_italicFont;
|
||||
}
|
||||
|
||||
float getDpi() {
|
||||
auto dpi = ImGui::GetCurrentContext()->CurrentDpiScale * 96.0F;
|
||||
return dpi ? dpi : 96.0F;
|
||||
}
|
||||
|
||||
float pixelsToPoints(float pixels) {
|
||||
return pixels * (72.0 / getDpi());
|
||||
}
|
||||
|
||||
float pointsToPixels(float points) {
|
||||
return points / (72.0 / getDpi());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
60
lib/libimhex/source/helpers/freetype.cpp
Normal file
60
lib/libimhex/source/helpers/freetype.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#include "hex/helpers/freetype.hpp"
|
||||
#include "imgui.h"
|
||||
|
||||
namespace hex::ft {
|
||||
|
||||
void Bitmap::lcdFilter() {
|
||||
if (m_width * m_height == 0)
|
||||
return;
|
||||
std::vector <ImU8> h = {8, 0x4D, 0x55, 0x4D, 8};
|
||||
auto paddedWidth = m_width + 4;
|
||||
auto fWidth = paddedWidth + ((3 - (paddedWidth % 3)) % 3);
|
||||
auto fPitch = (fWidth + 3) & (-4);
|
||||
Bitmap f(fWidth, m_height, fPitch);
|
||||
//std::vector<std::vector<ImU8>> fir(3, std::vector<ImU8>(3, 0));
|
||||
// first output: h[0]*input[0]/255.0f;
|
||||
// 2nd output: (h[1]*input[0] + h[0]*input[1])/255.0f;
|
||||
// 3rd output: (h[2]*input[0] + h[1]*input[1] + h[0]*input[2])/255.0f;
|
||||
// 4th output: (h[1]*input[0] + h[2]*input[1] + h[1]*input[2] + h[0]*input[3])/255.0f;
|
||||
// ith output: (h[0]*input[5+i] + h[1]*input[i+6] + h[2]*input[i+7] + h[1]*input[i+8] + h[0]*input[i+9])/255.0f;
|
||||
// aap output: (h[0]*input[N-4] + h[1]*input[N-3] + h[2]*input[N-2] + h[1]*input[N-1])/255.0f;
|
||||
// ap output: (h[0]*input[N-3] + h[1]*input[N-2] + h[2]*input[N-1])/255.0f;
|
||||
// p output: (h[0]*input[N-2] + h[1]*input[N-1] )/255.0f;
|
||||
// last output: h[0]*input[N-1]/255.0f;
|
||||
for (ImU32 y = 0; y < m_height; y++) {
|
||||
auto fp = y * fPitch;
|
||||
auto yp = y * m_pitch;
|
||||
bool done = false;
|
||||
for (ImU32 x = 0; x < 4; x++) {
|
||||
ImU32 head = 0;
|
||||
ImU32 tail = 0;
|
||||
if (m_width >= x + 1) {
|
||||
for (ImU32 i = 0; i < x + 1; i++) {
|
||||
head += h[x - i] * m_data[yp + i];
|
||||
tail += h[i] * m_data[yp + m_width - 1 - x + i];
|
||||
}
|
||||
f.m_data[fp + x] = head >> 8;
|
||||
f.m_data[fp + paddedWidth - 1 - x] = tail >> 8;
|
||||
} else {
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (done)
|
||||
continue;
|
||||
for (ImU32 x = 4; x < paddedWidth - 4; x++) {
|
||||
ImU32 head = 0;
|
||||
for (ImS32 i = 0; i < 5; i++) {
|
||||
head += h[i] * m_data[yp + i + x - 4];
|
||||
}
|
||||
f.m_data[fp + x] = head >> 8;
|
||||
}
|
||||
}
|
||||
clear();
|
||||
m_width = f.m_width;
|
||||
m_height = f.m_height;
|
||||
m_pitch = f.m_pitch;
|
||||
m_data = std::move(f.m_data);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -419,6 +419,20 @@ void ImGui_ImplOpenGL3_NewFrame()
|
||||
ImGui_ImplOpenGL3_CreateDeviceObjects();
|
||||
}
|
||||
|
||||
// IMHEX PATCH BEGIN
|
||||
bool useFontShaders = false;
|
||||
|
||||
void FontShadersOn(const ImDrawList *parent_list, const ImDrawCmd *cmd) {
|
||||
useFontShaders = !useFontShaders;
|
||||
}
|
||||
void FontShadersOff(const ImDrawList *parent_list, const ImDrawCmd *cmd) {
|
||||
useFontShaders = !useFontShaders;
|
||||
}
|
||||
ImDrawCallback ImGui_ImplOpenGL3_TurnFontShadersOn = &FontShadersOn;
|
||||
ImDrawCallback ImGui_ImplOpenGL3_TurnFontShadersOff = &FontShadersOff;
|
||||
|
||||
// IMHEX PATCH END
|
||||
|
||||
static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height, GLuint vertex_array_object)
|
||||
{
|
||||
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
||||
@@ -426,7 +440,19 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
|
||||
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill
|
||||
glEnable(GL_BLEND);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
// IMHEX PATCH BEGIN
|
||||
#if !defined(__EMSCRIPTEN__)
|
||||
if (useFontShaders) {
|
||||
glBlendFuncSeparate(GL_SRC1_COLOR, GL_ONE_MINUS_SRC1_COLOR,GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
} else {
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
#else
|
||||
// IMHEX PATCH END
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
// IMHEX PATCH BEGIN
|
||||
#endif
|
||||
// IMHEX PATCH END
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
@@ -461,9 +487,19 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
|
||||
#if defined(GL_CLIP_ORIGIN)
|
||||
if (!clip_origin_lower_left) { float tmp = T; T = B; B = tmp; } // Swap top and bottom if origin is upper left
|
||||
#endif
|
||||
// IMHEX PATCH BEGIN
|
||||
float Gamma;
|
||||
if (useFontShaders)
|
||||
Gamma = 1.0f;
|
||||
else
|
||||
Gamma = 0.0f;
|
||||
// IMHEX PATCH END
|
||||
const float ortho_projection[4][4] =
|
||||
{
|
||||
{ 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
|
||||
// IMHEX PATCH BEGIN
|
||||
{ 2.0f/(R-L), 0.0f, Gamma, 0.0f },
|
||||
// { 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
|
||||
// IMHEX PATCH END
|
||||
{ 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, -1.0f, 0.0f },
|
||||
{ (R+L)/(L-R), (T+B)/(B-T), 0.0f, 1.0f },
|
||||
@@ -603,6 +639,14 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
||||
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
|
||||
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
|
||||
ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object);
|
||||
// IMHEX PATCH BEGIN
|
||||
else if (pcmd->UserCallback == ImGui_ImplOpenGL3_TurnFontShadersOn) {
|
||||
ImGui_ImplOpenGL3_TurnFontShadersOn(cmd_list, pcmd);
|
||||
ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object);
|
||||
} else if (pcmd->UserCallback == ImGui_ImplOpenGL3_TurnFontShadersOff) {
|
||||
ImGui_ImplOpenGL3_TurnFontShadersOff(cmd_list, pcmd);
|
||||
ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object);
|
||||
} // IMHEX PATCH END
|
||||
else
|
||||
pcmd->UserCallback(cmd_list, pcmd);
|
||||
}
|
||||
@@ -827,11 +871,21 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects()
|
||||
"uniform mat4 ProjMtx;\n"
|
||||
"out vec2 Frag_UV;\n"
|
||||
"out vec4 Frag_Color;\n"
|
||||
// IMHEX PATCH BEGIN
|
||||
"out mat4 Frag_mat;\n"
|
||||
// IMHEX PATCH END
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" Frag_UV = UV;\n"
|
||||
// IMHEX PATCH BEGIN
|
||||
" mat4 projMtx = ProjMtx;\n"
|
||||
" projMtx[0][2] = 0.0;\n"
|
||||
" Frag_mat = ProjMtx;\n"
|
||||
" Frag_Color = Color;\n"
|
||||
" gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
|
||||
" gl_Position = projMtx * vec4(Position.xy,0,1);\n"
|
||||
//" Frag_Color = Color;\n"
|
||||
// " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
|
||||
// IMHEX PATCH END
|
||||
"}\n";
|
||||
|
||||
const GLchar* fragment_shader_glsl_120 =
|
||||
@@ -870,11 +924,27 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects()
|
||||
const GLchar* fragment_shader_glsl_410_core =
|
||||
"in vec2 Frag_UV;\n"
|
||||
"in vec4 Frag_Color;\n"
|
||||
// IMHEX PATCH BEGIN
|
||||
"in mat4 Frag_mat;\n"
|
||||
// IMHEX PATCH END
|
||||
"uniform sampler2D Texture;\n"
|
||||
"layout (location = 0) out vec4 Out_Color;\n"
|
||||
// IMHEX PATCH BEGIN
|
||||
"layout (location = 0, index = 1) out vec4 SRC1_Color;\n"
|
||||
// IMHEX PATCH END
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
|
||||
// IMHEX PATCH BEGIN
|
||||
" float Gamma = Frag_mat[0][2];\n"
|
||||
" if (Gamma == 0.0)\n"
|
||||
// IMHEX PATCH END
|
||||
" Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
|
||||
// IMHEX PATCH BEGIN
|
||||
" else {\n"
|
||||
" Out_Color = Frag_Color;\n"
|
||||
" SRC1_Color = vec4(texture(Texture, Frag_UV.st).rgb * Frag_Color.aaa,1.0);\n"
|
||||
" }\n"
|
||||
// IMHEX PATCH END
|
||||
"}\n";
|
||||
|
||||
// Select shaders matching our GLSL versions
|
||||
|
||||
@@ -34,7 +34,8 @@ enum ImGuiFreeTypeBuilderFlags
|
||||
ImGuiFreeTypeBuilderFlags_Oblique = 1 << 6, // Styling: Should we slant the font, emulating italic style?
|
||||
ImGuiFreeTypeBuilderFlags_Monochrome = 1 << 7, // Disable anti-aliasing. Combine this with MonoHinting for best results!
|
||||
ImGuiFreeTypeBuilderFlags_LoadColor = 1 << 8, // Enable FreeType color-layered glyphs
|
||||
ImGuiFreeTypeBuilderFlags_Bitmap = 1 << 9 // Enable FreeType bitmap glyphs
|
||||
ImGuiFreeTypeBuilderFlags_Bitmap = 1 << 9, // Enable FreeType bitmap glyphs
|
||||
ImGuiFreeTypeBuilderFlags_SubPixel = 1 << 10 // Atlas was generated with sub-pixel rendering enabled
|
||||
};
|
||||
|
||||
namespace ImGuiFreeType
|
||||
|
||||
@@ -1695,7 +1695,10 @@ void ImDrawList::AddBezierQuadratic(const ImVec2& p1, const ImVec2& p2, const Im
|
||||
PathBezierQuadraticCurveTo(p2, p3, num_segments);
|
||||
PathStroke(col, 0, thickness);
|
||||
}
|
||||
|
||||
// IMHEX PATCH BEGIN
|
||||
extern ImDrawCallback ImGui_ImplOpenGL3_TurnFontShadersOn;
|
||||
extern ImDrawCallback ImGui_ImplOpenGL3_TurnFontShadersOff;
|
||||
// IMHEX PATCH END
|
||||
void ImDrawList::AddText(ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end, float wrap_width, const ImVec4* cpu_fine_clip_rect)
|
||||
{
|
||||
if ((col & IM_COL32_A_MASK) == 0)
|
||||
@@ -1713,7 +1716,16 @@ void ImDrawList::AddText(ImFont* font, float font_size, const ImVec2& pos, ImU32
|
||||
font_size = _Data->FontSize;
|
||||
|
||||
IM_ASSERT(font->ContainerAtlas->TexID == _CmdHeader.TextureId); // Use high-level ImGui::PushFont() or low-level ImDrawList::PushTextureId() to change font.
|
||||
|
||||
// IMHEX PATCH BEGIN
|
||||
int flags;
|
||||
bool is_subpixel = false;
|
||||
if (font != nullptr && font->ContainerAtlas != nullptr) {
|
||||
flags = font->ContainerAtlas->FontBuilderFlags;
|
||||
is_subpixel = (flags & ImGuiFreeTypeBuilderFlags_SubPixel) != 0;
|
||||
}
|
||||
if (is_subpixel)
|
||||
AddCallback(ImGui_ImplOpenGL3_TurnFontShadersOn, NULL);
|
||||
// IMHEX PATCH END
|
||||
ImVec4 clip_rect = _CmdHeader.ClipRect;
|
||||
if (cpu_fine_clip_rect)
|
||||
{
|
||||
@@ -1723,6 +1735,10 @@ void ImDrawList::AddText(ImFont* font, float font_size, const ImVec2& pos, ImU32
|
||||
clip_rect.w = ImMin(clip_rect.w, cpu_fine_clip_rect->w);
|
||||
}
|
||||
font->RenderText(this, font_size, pos, col, clip_rect, text_begin, text_end, wrap_width, cpu_fine_clip_rect != NULL);
|
||||
// IMHEX PATCH BEGIN
|
||||
if (is_subpixel)
|
||||
AddCallback(ImGui_ImplOpenGL3_TurnFontShadersOff, NULL);
|
||||
// IMHEX PATCH END
|
||||
}
|
||||
|
||||
void ImDrawList::AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end)
|
||||
@@ -3313,8 +3329,12 @@ void ImFontAtlas::GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_wid
|
||||
TexPixelsRGBA32 = (unsigned int*)IM_ALLOC((size_t)TexWidth * (size_t)TexHeight * 4);
|
||||
const unsigned char* src = pixels;
|
||||
unsigned int* dst = TexPixelsRGBA32;
|
||||
for (int n = TexWidth * TexHeight; n > 0; n--)
|
||||
*dst++ = IM_COL32(255, 255, 255, (unsigned int)(*src++));
|
||||
// IMHEX PATCH BEGIN
|
||||
//for (int n = TexWidth * TexHeight; n > 0; n--)
|
||||
// *dst++ = IM_COL32(255, 255, 255, (unsigned int)(*src++));
|
||||
for (int n = TexWidth * TexHeight; n > 0; n--,src++)
|
||||
*dst++ = IM_COL32(*src, *src, *src, *src);
|
||||
// IMHEX PATCH END
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user