DrawList: extend the detailed stroke textures up stroke thickness 4.

This commit is contained in:
Mikko Mononen
2026-05-26 17:37:50 +03:00
committed by ocornut
parent e6097985be
commit 7fa09cf7f6
2 changed files with 26 additions and 20 deletions

12
imgui.h
View File

@@ -3333,10 +3333,16 @@ struct ImGuiSelectionExternalStorage
#define IM_DRAWLIST_TEX_LINES_WIDTH_MAX (32)
#endif
#ifndef IM_DRAWLIST_TEX_LINES_SUPERSAMPLE_MAX
#define IM_DRAWLIST_TEX_LINES_SUPERSAMPLE_MAX (2) // How many samples for lines between [1..2) thickness.
#ifndef IM_DRAWLIST_TEX_LINES_DETAILED_WIDTH
#define IM_DRAWLIST_TEX_LINES_DETAILED_WIDTH (4) // Calculate detailed textures for width [1..IM_DRAWLIST_TEX_LINES_DETAILED_WIDTH]
#endif
#ifndef IM_DRAWLIST_TEX_LINES_SAMPLE_COUNT
#define IM_DRAWLIST_TEX_LINES_SAMPLE_COUNT (2) // How many samples per integer thickness level.
#endif
#define IM_DRAWLIST_TEX_LINES_DETAILED_WIDTH_MAX (IM_DRAWLIST_TEX_LINES_DETAILED_WIDTH * IM_DRAWLIST_TEX_LINES_SAMPLE_COUNT)
#ifndef IM_DRAWLIST_TEX_CORNERS_ROUNDING_MAX
#define IM_DRAWLIST_TEX_CORNERS_ROUNDING_MAX (16)
#endif
@@ -4029,7 +4035,7 @@ struct ImFontAtlas
ImVec2 TexUvWhitePixel; // Texture coordinates to a white pixel. May change as new texture gets created.
ImVector<ImFont*> Fonts; // Hold all the fonts returned by AddFont*. Fonts[0] is the default font upon calling ImGui::NewFrame(), use ImGui::PushFont()/PopFont() to change the current font.
ImVector<ImFontConfig> Sources; // Source/configuration data
ImVec4 TexUvLines[IM_DRAWLIST_TEX_LINES_WIDTH_MAX + 1 + IM_DRAWLIST_TEX_LINES_SUPERSAMPLE_MAX + 1]; // UVs for baked anti-aliased lines
ImVec4 TexUvLines[IM_DRAWLIST_TEX_LINES_WIDTH_MAX + 1 + IM_DRAWLIST_TEX_LINES_DETAILED_WIDTH_MAX + 1]; // UVs for baked anti-aliased lines
ImVec4 TexUvCorners[IM_DRAWLIST_TEX_CORNERS_ROUNDING_MAX * IM_DRAWLIST_TEX_CORNERS_THICKNESS_MAX]; // UVs for baked anti-aliased corners (0= fill, 1> stroke thickness)
int TexNextUniqueID; // Next value to be stored in TexData->UniqueID
int FontNextUniqueID; // Next value to be stored in ImFont->FontID

View File

@@ -1191,18 +1191,18 @@ void ImDrawList::_SelectFringeTexture(float screen_thickness, ImVec4& tex_uvs, f
{
if (screen_thickness <= 2.f)
{
// Handle the thickness between [1..2]. The texture scaling in this range will cause visual pop near 1, so we generate super sampled textures in this range.
// There IM_DRAWLIST_TEX_LINES_SUPERSAMPLE_MAX+1 textures, where 0 maps to 1.0 and IM_DRAWLIST_TEX_LINES_SUPERSAMPLE_MAX maps 2.0.
// Handle the thickness between [1..IM_DRAWLIST_TEX_LINES_DETAILED_WIDTH]. The texture scaling in this range will cause slight visual pops, so we generate super sampled textures in this range.
// There are IM_DRAWLIST_TEX_LINES_DETAILED_WIDTH_MAX+1 textures, where 0 maps to 1.0 and IM_DRAWLIST_TEX_LINES_DETAILED_WIDTH_MAX maps to IM_DRAWLIST_TEX_LINES_DETAILED_WIDTH.
constexpr float base_width = 1.f;
const int texture_idx = ImClamp((int)((screen_thickness - base_width) * IM_DRAWLIST_TEX_LINES_SUPERSAMPLE_MAX + 0.5f), 0, IM_DRAWLIST_TEX_LINES_SUPERSAMPLE_MAX);
const float tex_width = base_width + (float)texture_idx / IM_DRAWLIST_TEX_LINES_SUPERSAMPLE_MAX;
const int texture_idx = ImClamp((int)((screen_thickness - base_width) * IM_DRAWLIST_TEX_LINES_SAMPLE_COUNT + 0.995f), 0, IM_DRAWLIST_TEX_LINES_DETAILED_WIDTH_MAX);
const float tex_width = base_width + (float)texture_idx / IM_DRAWLIST_TEX_LINES_SAMPLE_COUNT;
fringe = _FringeScale * (screen_thickness / tex_width); // Scale the fringe to cover the discrepancy between the texture and requested size.
tex_uvs = _Data->TexUvLines[IM_DRAWLIST_TEX_LINES_WIDTH_MAX + 1 + texture_idx];
}
else
{
// Bias the texture selection towards higher resolution to avoid visual pops when the texture change.
const int texture_idx = ImClamp((int)(screen_thickness + 0.95f), 1, IM_DRAWLIST_TEX_LINES_WIDTH_MAX - 1);
const int texture_idx = ImClamp((int)(screen_thickness + 0.995f), 2, IM_DRAWLIST_TEX_LINES_WIDTH_MAX - 1);
fringe = _FringeScale * (screen_thickness / (float)texture_idx); // Scale the fringe to cover the discrepancy between the texture and requested size.
tex_uvs = _Data->TexUvLines[texture_idx];
}
@@ -5122,7 +5122,7 @@ static void ImFontAtlasBuildUpdateTexDataLines(ImFontAtlas* atlas)
bool add_and_draw = atlas->GetCustomRect(builder->PackIdLinesTexData, &r) == false;
if (add_and_draw)
{
ImVec2i pack_size = ImVec2i(IM_DRAWLIST_TEX_LINES_WIDTH_MAX + 2, IM_DRAWLIST_TEX_LINES_WIDTH_MAX + 1 + IM_DRAWLIST_TEX_LINES_SUPERSAMPLE_MAX + 1);
ImVec2i pack_size = ImVec2i(IM_DRAWLIST_TEX_LINES_WIDTH_MAX + 2, IM_DRAWLIST_TEX_LINES_WIDTH_MAX + 1 + IM_DRAWLIST_TEX_LINES_DETAILED_WIDTH_MAX + 1);
builder->PackIdLinesTexData = atlas->AddCustomRect(pack_size.x, pack_size.y, &r);
IM_ASSERT(builder->PackIdLinesTexData != ImFontAtlasRectId_Invalid);
}
@@ -5176,16 +5176,16 @@ static void ImFontAtlasBuildUpdateTexDataLines(ImFontAtlas* atlas)
{
ImU8 ramp[IM_DRAWLIST_TEX_LINES_SUPERSAMPLE_MAX];
for (int n = 0; n < IM_DRAWLIST_TEX_LINES_SUPERSAMPLE_MAX; n++)
ramp[n] = (ImU8)(((float)n / IM_DRAWLIST_TEX_LINES_SUPERSAMPLE_MAX) * 255.f);
ImU8 ramp[IM_DRAWLIST_TEX_LINES_SAMPLE_COUNT];
for (int n = 0; n < IM_DRAWLIST_TEX_LINES_SAMPLE_COUNT; n++)
ramp[n] = (ImU8)(((float)n / IM_DRAWLIST_TEX_LINES_SAMPLE_COUNT) * 255.f);
for (int n = 0; n < IM_DRAWLIST_TEX_LINES_SUPERSAMPLE_MAX + 1; n++)
for (int n = 0; n < IM_DRAWLIST_TEX_LINES_DETAILED_WIDTH_MAX + 1; n++)
{
// Each line consists of at least two empty pixels at the ends, with a line of solid pixels in the middle
const int y = IM_DRAWLIST_TEX_LINES_WIDTH_MAX + 1 + n;
const int line_width = IM_DRAWLIST_TEX_LINES_SUPERSAMPLE_MAX + n;
IM_ASSERT(IM_DRAWLIST_TEX_LINES_SUPERSAMPLE_MAX + line_width + IM_DRAWLIST_TEX_LINES_SUPERSAMPLE_MAX <= r.w && y < r.h); // Make sure we're inside the texture bounds before we start writing pixels
const int line_width = IM_DRAWLIST_TEX_LINES_SAMPLE_COUNT + n;
IM_ASSERT(IM_DRAWLIST_TEX_LINES_SAMPLE_COUNT + line_width + IM_DRAWLIST_TEX_LINES_SAMPLE_COUNT <= r.w && y < r.h); // Make sure we're inside the texture bounds before we start writing pixels
// Write each slice
if (add_and_draw && tex->Format == ImTextureFormat_Alpha8)
@@ -5193,13 +5193,13 @@ static void ImFontAtlasBuildUpdateTexDataLines(ImFontAtlas* atlas)
ImU8* write_ptr = (ImU8*)tex->GetPixelsAt(r.x, r.y + y);
int idx = 0;
for (int i = 0; i < IM_DRAWLIST_TEX_LINES_SUPERSAMPLE_MAX; i++)
for (int i = 0; i < IM_DRAWLIST_TEX_LINES_SAMPLE_COUNT; i++)
write_ptr[idx++] = ramp[i];
for (int i = 0; i < line_width; i++)
write_ptr[idx++] = 0xFF;
for (int i = IM_DRAWLIST_TEX_LINES_SUPERSAMPLE_MAX-1; i >= 0; i--)
for (int i = IM_DRAWLIST_TEX_LINES_SAMPLE_COUNT - 1; i >= 0; i--)
write_ptr[idx++] = ramp[i];
while (idx < r.w)
@@ -5211,13 +5211,13 @@ static void ImFontAtlasBuildUpdateTexDataLines(ImFontAtlas* atlas)
int idx = 0;
for (int i = 0; i < IM_DRAWLIST_TEX_LINES_SUPERSAMPLE_MAX; i++)
for (int i = 0; i < IM_DRAWLIST_TEX_LINES_SAMPLE_COUNT; i++)
write_ptr[idx++] = IM_COL32(255, 255, 255, ramp[i]);
for (int i = 0; i < line_width; i++)
write_ptr[idx++] = IM_COL32(255, 255, 255, 255);
for (int i = IM_DRAWLIST_TEX_LINES_SUPERSAMPLE_MAX - 1; i >= 0; i--)
for (int i = IM_DRAWLIST_TEX_LINES_SAMPLE_COUNT - 1; i >= 0; i--)
write_ptr[idx++] = IM_COL32(255, 255, 255, ramp[i]);
while (idx < r.w)
@@ -5226,7 +5226,7 @@ static void ImFontAtlasBuildUpdateTexDataLines(ImFontAtlas* atlas)
// Refresh UV coordinates
ImVec2 uv0 = ImVec2((float)(r.x), (float)(r.y + y)) * atlas->TexUvScale;
ImVec2 uv1 = ImVec2((float)(r.x + IM_DRAWLIST_TEX_LINES_SUPERSAMPLE_MAX * 2 + line_width), (float)(r.y + y + 1)) * atlas->TexUvScale;
ImVec2 uv1 = ImVec2((float)(r.x + IM_DRAWLIST_TEX_LINES_SAMPLE_COUNT * 2 + line_width), (float)(r.y + y + 1)) * atlas->TexUvScale;
float half_v = (uv0.y + uv1.y) * 0.5f; // Calculate a constant V in the middle of the row to avoid sampling artifacts
atlas->TexUvLines[IM_DRAWLIST_TEX_LINES_WIDTH_MAX + 1 + n] = ImVec4(uv0.x, half_v, uv1.x, half_v);
}