Closed paindoll closed 2 days ago
Not that I know of. But there are a few ways to accomplish this:
AddRectFilledMultiColor()
.ImDrawList::Prim...()
methods.I needed efficient lines interpolating between two colors for something. I didn't want to reimplement the vertex construction with taking anti aliasing into account, so I used approach 2 for my lines. Here is the code:
void DrawTwoColorLine( ImDrawList* drawList,
const ImVec2& p1,
const ImVec2& p2,
ImU32 color1,
ImU32 color2,
float thickness )
{
if ( color1 == color2 )
{
drawList->AddLine( p1, p2, color1, thickness );
return;
}
if ( ( ( color1 | color2 ) & IM_COL32_A_MASK ) == 0 )
return;
const int vtxStart = drawList->VtxBuffer.size();
drawList->AddLine( p1, p2, 0xFFFFFFFF, thickness );
const int vtxEnd = drawList->VtxBuffer.size();
ImDrawVert* vtxData = drawList->VtxBuffer.begin();
const ImVec4 col1 = ImColor( color1 );
const ImVec4 col2 = ImColor( color2 );
const float amul = 1.0f / (float)IM_COL32_A_MASK;
const float dx = p2.x - p1.x;
const float dy = p2.y - p1.y;
for ( int i = vtxStart; i < vtxEnd; ++i )
{
ImDrawVert& v = vtxData[ i ];
const float dp = ( ( v.pos.x - p1.x ) * dx + ( v.pos.y - p1.y ) * dy ) / ( dx * dx + dy * dy );
const float u = ( dp < 0.0f ) ? 0.0f : ( ( dp < 1.0f ) ? dp : 1.0f );
const float ui = 1.0f - u;
const float a = (float)( v.col & IM_COL32_A_MASK ) * amul;
v.col = ImColor( col1.x * ui + col2.x * u, col1.y * ui + col2.y * u, col1.z * ui + col2.z * u, ( col1.w * ui + col2.w * u ) * a );
}
}
You can use this as a reference. It should be relatively easy to adapt this to rectangles.
Also see #4722 but it is essentially the same as answered above: draw the shape you want as white and then "shade" them, which is the call to ShadeVertsLinearColorGradientKeepAlpha()
in #4722. I am also pretty sure the loop Daniel posted is equivalent to be calling ShadeVertsLinearColorGradientKeepAlpha()
. So technically you could add well call AddRect()
+ ShadeVertsLinearColorGradientKeepAlpha()
.
However, I strongly feel that answer (1) is probably the right answer. It's very probably not a problem to call e.g. AddRectFilledMultiColor()
multiple times if you need it. If you are not drawing 10000+ shapes every frame the difference will likely not matter.
Closing as answered. Thanks Daniel!
Version/Branch of Dear ImGui:
Current version
Back-ends:
imgui_impl_win32.cpp + imgui_impl_dx11.cpp
Compiler, OS:
Windows 11 + MSVC 2022
Full config/build information:
v1.91.5 WIP
Details:
Is there any kind method to render a non-filled gradient rect without creating four rects of AddRectFilledMultiColor?
Screenshots/Video:
No response
Minimal, Complete and Verifiable Example code:
No response