1
0
Fork 0
mirror of https://github.com/ocornut/imgui.git synced 2026-01-11 00:04:24 +00:00

Shadows: Added experimental texture-based shadows (stripped of dynamic tex config and back-end code)

(merged 10 commits, removing dynamic tex config, moved tex config to internal structs, removed back-end changes)
(squashed 2025-06-11, fixed conflict, doesn't build as-is)
Shadows: Added IMGUI_HAS_SHADOWS
Shadows: Demo code in Custom Rendering section. Added AddShadowRectFilled() variant. BeginMainMenuBar() disable shadows.
Shadows: Added initial version of convex shape shadow code.
(+stripped out of original polygon generation demo, moved to imgui_dev)
Shadows: Tweak demo to use AddShadowCircle() functions + fix warnings.
 (+ stripped old polygon generation code from commits)
Shadows: Convex shape shadow improvement/fixes
- Fixed pixel cracking on convex shadow edges
- Added convex shadow offset support
- Fixed some convex shadow fringing issues
- Added convex shadow demo code
Shadows: Added ImDrawShadowFlags, simplified API surface, reordered parameters
+ fix minor warnings
+ removed NGon variant for now.
Shadows: Re-added AddShadowNGon().
Shadows: Shallow styling tweaks and renaming for consistency.
Shadows: Fixes + two fixes for PVS Studio static analyzer.
Shadows: Fix for latest, reuse ImDrawList, remove ImDrawShadowFlags.
Shadows: Fix to support for colored-only font atlas. (4202)
Shadows: Fix broken shadows due to zero-clear added in 9417acc2.
Shadows: remove use of GetWindowContentRegionMax().
Shadows: WIP fixes for latest. (broken UV caching)
Shadows: WIP for latest (refreshing UV coordinates).
This commit is contained in:
Ben Carter 2020-04-24 18:16:48 +02:00 committed by ocornut
parent 6d910d5487
commit aea4f38726
6 changed files with 1270 additions and 0 deletions

View file

@ -8626,6 +8626,22 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
EndTabItem();
}
if (BeginTabItem("Shadows"))
{
Text("Window shadows:");
ColorEdit4("Color", (float*)&style.Colors[ImGuiCol_WindowShadow], ImGuiColorEditFlags_AlphaBar);
SameLine();
HelpMarker("Same as 'WindowShadow' in Colors tab.");
SliderFloat("Size", &style.WindowShadowSize, 0.0f, 128.0f, "%.1f");
SameLine();
HelpMarker("Set shadow size to zero to disable shadows.");
SliderFloat("Offset distance", &style.WindowShadowOffsetDist, 0.0f, 64.0f, "%.0f");
SliderAngle("Offset angle", &style.WindowShadowOffsetAngle);
EndTabItem();
}
EndTabBar();
}
PopItemWidth();
@ -10096,6 +10112,168 @@ static void ShowExampleAppCustomRendering(bool* p_open)
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Shadows"))
{
static float shadow_thickness = 40.0f;
static ImVec4 shadow_color = ImVec4(0.0f, 0.0f, 0.0f, 1.0f);
static bool shadow_filled = false;
static ImVec4 shape_color = ImVec4(0.9f, 0.6f, 0.3f, 1.0f);
static float shape_rounding = 0.0f;
static ImVec2 shadow_offset(0.0f, 0.0f);
static ImVec4 background_color = ImVec4(0.5f, 0.5f, 0.7f, 1.0f);
static bool wireframe = false;
static bool aa = true;
static int poly_shape_index = 0;
ImGui::Checkbox("Shadow filled", &shadow_filled);
ImGui::SameLine();
HelpMarker("This will fill the section behind the shape to shadow. It's often unnecessary and wasteful but provided for consistency.");
ImGui::Checkbox("Wireframe shapes", &wireframe);
ImGui::SameLine();
HelpMarker("This draws the shapes in wireframe so you can see the shadow underneath.");
ImGui::Checkbox("Anti-aliasing", &aa);
ImGui::DragFloat("Shadow Thickness", &shadow_thickness, 1.0f, 0.0f, 100.0f, "%.02f");
ImGui::SliderFloat2("Offset", (float*)&shadow_offset, -32.0f, 32.0f);
ImGui::SameLine();
HelpMarker("Note that currently circles/convex shapes do not support non-zero offsets for unfilled shadows.");
ImGui::ColorEdit4("Background Color", &background_color.x);
ImGui::ColorEdit4("Shadow Color", &shadow_color.x);
ImGui::ColorEdit4("Shape Color", &shape_color.x);
ImGui::DragFloat("Shape Rounding", &shape_rounding, 1.0f, 0.0f, 20.0f, "%.02f");
ImGui::Combo("Convex shape", &poly_shape_index, "Shape 1\0Shape 2\0Shape 3\0Shape 4\0Shape 4 (winding reversed)");
ImDrawList* draw_list = ImGui::GetWindowDrawList();
ImDrawListFlags old_flags = draw_list->Flags;
if (aa)
draw_list->Flags |= ~ImDrawListFlags_AntiAliasedFill;
else
draw_list->Flags &= ~ImDrawListFlags_AntiAliasedFill;
// Fill a strip of background
{
ImVec2 p = ImGui::GetCursorScreenPos();
draw_list->AddRectFilled(p, ImVec2(p.x + ImGui::GetContentRegionAvail().x, p.y + 200.0f), ImGui::GetColorU32(background_color));
}
// Rectangle
{
ImVec2 p = ImGui::GetCursorScreenPos();
ImGui::Dummy(ImVec2(200.0f, 200.0f));
ImVec2 r1(p.x + 50.0f, p.y + 50.0f);
ImVec2 r2(p.x + 150.0f, p.y + 150.0f);
ImDrawFlags draw_flags = shadow_filled ? ImDrawFlags_None : ImDrawFlags_ShadowCutOutShapeBackground;
draw_list->AddShadowRect(r1, r2, ImGui::GetColorU32(shadow_color), shadow_thickness, shadow_offset, draw_flags, shape_rounding);
if (wireframe)
draw_list->AddRect(r1, r2, ImGui::GetColorU32(shape_color), shape_rounding);
else
draw_list->AddRectFilled(r1, r2, ImGui::GetColorU32(shape_color), shape_rounding);
}
ImGui::SameLine();
// Circle
{
ImVec2 p = ImGui::GetCursorScreenPos();
ImGui::Dummy(ImVec2(200.0f, 200.0f));
// FIXME-SHADOWS: Offset forced to zero when shadow is not filled because it isn't supported
float off = 10.0f;
ImVec2 r1(p.x + 50.0f + off, p.y + 50.0f + off);
ImVec2 r2(p.x + 150.0f - off, p.y + 150.0f - off);
ImVec2 center(p.x + 100.0f, p.y + 100.0f);
ImDrawFlags draw_flags = shadow_filled ? ImDrawFlags_None : ImDrawFlags_ShadowCutOutShapeBackground;
draw_list->AddShadowCircle(center, 50.0f, ImGui::GetColorU32(shadow_color), shadow_thickness, shadow_filled ? shadow_offset : ImVec2(0.0f, 0.0f), draw_flags, 0);
if (wireframe)
draw_list->AddCircle(center, 50.0f, ImGui::GetColorU32(shape_color), 0);
else
draw_list->AddCircleFilled(center, 50.0f, ImGui::GetColorU32(shape_color), 0);
}
ImGui::SameLine();
// Convex shape
{
ImVec2 pos = ImGui::GetCursorScreenPos();
ImGui::Dummy(ImVec2(200.0f, 200.0f));
const ImVec2 poly_centre(pos.x + 50.0f, pos.y + 100.0f);
ImVec2 poly_points[8];
int poly_points_count = 0;
switch (poly_shape_index)
{
default:
case 0:
{
poly_points[0] = ImVec2(poly_centre.x - 32.0f, poly_centre.y);
poly_points[1] = ImVec2(poly_centre.x - 24.0f, poly_centre.y + 24.0f);
poly_points[2] = ImVec2(poly_centre.x, poly_centre.y + 32.0f);
poly_points[3] = ImVec2(poly_centre.x + 24.0f, poly_centre.y + 24.0f);
poly_points[4] = ImVec2(poly_centre.x + 32.0f, poly_centre.y);
poly_points[5] = ImVec2(poly_centre.x + 24.0f, poly_centre.y - 24.0f);
poly_points[6] = ImVec2(poly_centre.x, poly_centre.y - 32.0f);
poly_points[7] = ImVec2(poly_centre.x - 32.0f, poly_centre.y - 32.0f);
poly_points_count = 8;
break;
}
case 1:
{
poly_points[0] = ImVec2(poly_centre.x + 40.0f, poly_centre.y - 20.0f);
poly_points[1] = ImVec2(poly_centre.x, poly_centre.y + 32.0f);
poly_points[2] = ImVec2(poly_centre.x - 24.0f, poly_centre.y - 32.0f);
poly_points_count = 3;
break;
}
case 2:
{
poly_points[0] = ImVec2(poly_centre.x - 32.0f, poly_centre.y);
poly_points[1] = ImVec2(poly_centre.x, poly_centre.y + 32.0f);
poly_points[2] = ImVec2(poly_centre.x + 32.0f, poly_centre.y);
poly_points[3] = ImVec2(poly_centre.x, poly_centre.y - 32.0f);
poly_points_count = 4;
break;
}
case 3:
{
poly_points[0] = ImVec2(poly_centre.x - 4.0f, poly_centre.y - 20.0f);
poly_points[1] = ImVec2(poly_centre.x + 12.0f, poly_centre.y + 2.0f);
poly_points[2] = ImVec2(poly_centre.x + 8.0f, poly_centre.y + 16.0f);
poly_points[3] = ImVec2(poly_centre.x, poly_centre.y + 32.0f);
poly_points[4] = ImVec2(poly_centre.x - 16.0f, poly_centre.y - 32.0f);
poly_points_count = 5;
break;
}
case 4: // Same as test case 3 but with reversed winding
{
poly_points[0] = ImVec2(poly_centre.x - 16.0f, poly_centre.y - 32.0f);
poly_points[1] = ImVec2(poly_centre.x, poly_centre.y + 32.0f);
poly_points[2] = ImVec2(poly_centre.x + 8.0f, poly_centre.y + 16.0f);
poly_points[3] = ImVec2(poly_centre.x + 12.0f, poly_centre.y + 2.0f);
poly_points[4] = ImVec2(poly_centre.x - 4.0f, poly_centre.y - 20.0f);
poly_points_count = 5;
break;
}
}
// FIXME-SHADOWS: Offset forced to zero when shadow is not filled because it isn't supported
ImDrawFlags draw_flags = shadow_filled ? ImDrawFlags_None : ImDrawFlags_ShadowCutOutShapeBackground;
draw_list->AddShadowConvexPoly(poly_points, poly_points_count, ImGui::GetColorU32(shadow_color), shadow_thickness, shadow_filled ? shadow_offset : ImVec2(0.0f, 0.0f), draw_flags);
if (wireframe)
draw_list->AddPolyline(poly_points, poly_points_count, ImGui::GetColorU32(shape_color), true, 1.0f);
else
draw_list->AddConvexPolyFilled(poly_points, poly_points_count, ImGui::GetColorU32(shape_color));
}
draw_list->Flags = old_flags;
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("BG/FG draw lists"))
{
static bool draw_bg = true;