mirror of
				https://github.com/Drezil/imgui.git
				synced 2025-10-31 21:21:06 +01:00 
			
		
		
		
	Texture-based thick lines: Remove unnecessary indirection in fetching UV data, removed lerp call, renames, tweaks.
This commit is contained in:
		| @@ -668,7 +668,6 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 | ||||
|  | ||||
|     const ImVec2 opaque_uv = _Data->TexUvWhitePixel; | ||||
|     const int count = closed ? points_count : points_count - 1; // The number of line segments we need to draw | ||||
|  | ||||
|     const bool thick_line = (thickness > 1.0f); | ||||
|  | ||||
|     if (Flags & ImDrawListFlags_AntiAliasedLines) | ||||
| @@ -679,12 +678,11 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 | ||||
|  | ||||
|         // Thicknesses <1.0 should behave like thickness 1.0 | ||||
|         thickness = ImMax(thickness, 1.0f); | ||||
|  | ||||
|         const int integer_thickness = (int)thickness ; | ||||
|         const float fractional_thickness = (thickness) - integer_thickness; | ||||
|         const int integer_thickness = (int)thickness; | ||||
|         const float fractional_thickness = thickness - integer_thickness; | ||||
|  | ||||
|         // Do we want to draw this line using a texture? | ||||
|         const bool use_texture = (Flags & ImDrawListFlags_AntiAliasedLinesUseTexData) && (integer_thickness < IM_DRAWLIST_TEX_AA_LINES_WIDTH_MAX); | ||||
|         const bool use_texture = (Flags & ImDrawListFlags_AntiAliasedLinesUseTex) && (integer_thickness < IM_DRAWLIST_TEX_AA_LINES_WIDTH_MAX); | ||||
|  | ||||
|         // We should never hit this, because NewFrame() doesn't set ImDrawListFlags_AntiAliasedLinesUseTexData unless ImFontAtlasFlags_NoAALines is off | ||||
|         IM_ASSERT_PARANOID((!use_texture) || (!(_Data->Font->ContainerAtlas->Flags & ImFontAtlasFlags_NoAALines))); | ||||
| @@ -712,8 +710,11 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 | ||||
|             temp_normals[points_count - 1] = temp_normals[points_count - 2]; | ||||
|  | ||||
|         // If we are drawing a one-pixel-wide line without a texture, or a textured line of any width, we only need 2 or 3 vertices per point | ||||
|         if (!thick_line || use_texture) | ||||
|         if (use_texture || !thick_line) | ||||
|         { | ||||
|             // [PATH 1] Texture-based lines (thick or non-thick) | ||||
|             // [PATH 2] Non texture-based lines (non-thick) | ||||
|  | ||||
|             // The width of the geometry we need to draw - this is essentially <thickness> pixels for the line itself, plus one pixel for AA | ||||
|             // We don't use AA_SIZE here because the +1 is tied to the generated texture and so alternate values won't work without changes to that code | ||||
|             const float half_draw_size = use_texture ? ((thickness * 0.5f) + 1) : 1.0f; | ||||
| @@ -734,7 +735,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 | ||||
|             for (int i1 = 0; i1 < count; i1++) // i1 is the first point of the line segment | ||||
|             { | ||||
|                 const int i2 = (i1 + 1) == points_count ? 0 : i1 + 1; // i2 is the second point of the line segment | ||||
|                 unsigned int idx2 = ((i1 + 1) == points_count) ? _VtxCurrentIdx : (idx1 + (use_texture ? 2 : 3)); // Vertex index for end of segment | ||||
|                 const unsigned int idx2 = ((i1 + 1) == points_count) ? _VtxCurrentIdx : (idx1 + (use_texture ? 2 : 3)); // Vertex index for end of segment | ||||
|  | ||||
|                 // Average normals | ||||
|                 float dm_x = (temp_normals[i1].x + temp_normals[i2].x) * 0.5f; | ||||
| @@ -774,32 +775,30 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 | ||||
|             if (use_texture) | ||||
|             { | ||||
|                 // If we're using textures we only need to emit the left/right edge vertices | ||||
|  | ||||
|                 ImVec4 tex_uvs; | ||||
|  | ||||
|                 if (fractional_thickness == 0.0f) // Fast path for pure integer widths | ||||
|                     tex_uvs = (*_Data->TexUvAALines)[integer_thickness]; | ||||
|                 else | ||||
|                 ImVec4 tex_uvs = _Data->TexUvAALines[integer_thickness]; | ||||
|                 if (fractional_thickness != 0.0f) | ||||
|                 { | ||||
|                     // Calculate UV by interpolating between the two nearest integer line widths | ||||
|                     const ImVec4 tex_uvs_0 = (*_Data->TexUvAALines)[integer_thickness]; | ||||
|                     const ImVec4 tex_uvs_1 = (*_Data->TexUvAALines)[integer_thickness + 1]; | ||||
|                     tex_uvs = ImLerp(tex_uvs_0, tex_uvs_1, fractional_thickness); | ||||
|                     const ImVec4 tex_uvs_1 = _Data->TexUvAALines[integer_thickness + 1]; | ||||
|                     tex_uvs.x = tex_uvs.x + (tex_uvs_1.x - tex_uvs.x) * fractional_thickness; // inlined ImLerp() | ||||
|                     tex_uvs.y = tex_uvs.y + (tex_uvs_1.y - tex_uvs.y) * fractional_thickness; | ||||
|                     tex_uvs.z = tex_uvs.z + (tex_uvs_1.z - tex_uvs.z) * fractional_thickness; | ||||
|                     tex_uvs.w = tex_uvs.w + (tex_uvs_1.w - tex_uvs.w) * fractional_thickness; | ||||
|                 } | ||||
|  | ||||
|                 ImVec2 tex_uv0(tex_uvs.x, tex_uvs.y); | ||||
|                 ImVec2 tex_uv1(tex_uvs.z, tex_uvs.w); | ||||
|                 for (int i = 0; i < points_count; i++) | ||||
|                 { | ||||
|                     _VtxWritePtr[0].pos = temp_points[i * 2 + 0]; _VtxWritePtr[0].uv = ImVec2(tex_uvs.x, tex_uvs.y); _VtxWritePtr[0].col = col; // Left-side outer edge | ||||
|                     _VtxWritePtr[1].pos = temp_points[i * 2 + 1]; _VtxWritePtr[1].uv = ImVec2(tex_uvs.z, tex_uvs.y); _VtxWritePtr[1].col = col; // Right-side outer edge | ||||
|                     _VtxWritePtr[0].pos = temp_points[i * 2 + 0]; _VtxWritePtr[0].uv = tex_uv0; _VtxWritePtr[0].col = col; // Left-side outer edge | ||||
|                     _VtxWritePtr[1].pos = temp_points[i * 2 + 1]; _VtxWritePtr[1].uv = tex_uv1; _VtxWritePtr[1].col = col; // Right-side outer edge | ||||
|                     _VtxWritePtr += 2; | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 // If we're not using a texture, we need the centre vertex as well | ||||
|                 // If we're not using a texture, we need the center vertex as well | ||||
|                 for (int i = 0; i < points_count; i++) | ||||
|                 { | ||||
|                     _VtxWritePtr[0].pos = points[i];              _VtxWritePtr[0].uv = opaque_uv; _VtxWritePtr[0].col = col; // Centre of line | ||||
|                     _VtxWritePtr[0].pos = points[i];              _VtxWritePtr[0].uv = opaque_uv; _VtxWritePtr[0].col = col;       // Center of line | ||||
|                     _VtxWritePtr[1].pos = temp_points[i * 2 + 0]; _VtxWritePtr[1].uv = opaque_uv; _VtxWritePtr[1].col = col_trans; // Left-side outer edge | ||||
|                     _VtxWritePtr[2].pos = temp_points[i * 2 + 1]; _VtxWritePtr[2].uv = opaque_uv; _VtxWritePtr[2].col = col_trans; // Right-side outer edge | ||||
|                     _VtxWritePtr += 3; | ||||
| @@ -808,7 +807,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             // For untextured lines that are greater than a pixel in width, we need to draw the solid line core and thus require four vertices per point | ||||
|             // [PATH 2] Non texture-based lines (thick): we need to draw the solid line core and thus require four vertices per point | ||||
|             const float half_inner_thickness = (thickness - AA_SIZE) * 0.5f; | ||||
|  | ||||
|             // If line is not closed, the first and last points need to be generated differently as there are no normals to blend | ||||
| @@ -880,7 +879,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         // Non texture-based, Non anti-aliased lines | ||||
|         // [PATH 4] Non texture-based, Non anti-aliased lines | ||||
|         const int idx_count = count * 6; | ||||
|         const int vtx_count = count * 4;    // FIXME-OPT: Not sharing edges | ||||
|         PrimReserve(idx_count, vtx_count); | ||||
| @@ -1720,7 +1719,7 @@ ImFontAtlas::ImFontAtlas() | ||||
|     TexWidth = TexHeight = 0; | ||||
|     TexUvScale = ImVec2(0.0f, 0.0f); | ||||
|     TexUvWhitePixel = ImVec2(0.0f, 0.0f); | ||||
|     PackIdMouseCursors = -1; | ||||
|     PackIdMouseCursors = PackIdAALines = -1; | ||||
| } | ||||
|  | ||||
| ImFontAtlas::~ImFontAtlas() | ||||
| @@ -1748,7 +1747,7 @@ void    ImFontAtlas::ClearInputData() | ||||
|         } | ||||
|     ConfigData.clear(); | ||||
|     CustomRects.clear(); | ||||
|     PackIdMouseCursors = -1; | ||||
|     PackIdMouseCursors = PackIdAALines = -1; | ||||
| } | ||||
|  | ||||
| void    ImFontAtlas::ClearTexData() | ||||
| @@ -2390,41 +2389,38 @@ static void ImFontAtlasBuildRenderDefaultTexData(ImFontAtlas* atlas) | ||||
|  | ||||
| static void ImFontAtlasBuildRegisterAALineCustomRects(ImFontAtlas* atlas) | ||||
| { | ||||
|     if ((atlas->Flags & ImFontAtlasFlags_NoAALines)) | ||||
|     if (atlas->Flags & ImFontAtlasFlags_NoAntiAliasedLines) | ||||
|         return; | ||||
|  | ||||
|     // The "max_width + 2" here is to give space for the end caps, whilst height (IM_DRAWLIST_TEX_AA_LINES_WIDTH_MAX+1) is to accommodate the fact we have a zero-width row | ||||
|     const int max_width = IM_DRAWLIST_TEX_AA_LINES_WIDTH_MAX; // The maximum line width we want to generate | ||||
|     atlas->AALineRectId = atlas->AddCustomRectRegular(max_width + 2, IM_DRAWLIST_TEX_AA_LINES_WIDTH_MAX + 1); | ||||
|     // The +2 here is to give space for the end caps, whilst height +1 is to accommodate the fact we have a zero-width row | ||||
|     atlas->PackIdAALines = atlas->AddCustomRectRegular(IM_DRAWLIST_TEX_AA_LINES_WIDTH_MAX + 2, IM_DRAWLIST_TEX_AA_LINES_WIDTH_MAX + 1); | ||||
| } | ||||
|  | ||||
| static void ImFontAtlasBuildRenderAALinesTexData(ImFontAtlas* atlas) | ||||
| { | ||||
|     IM_ASSERT(atlas->TexPixelsAlpha8 != NULL); | ||||
|     IM_ASSERT(atlas->TexUvAALines.Size == 0); | ||||
|  | ||||
|     if (atlas->Flags & ImFontAtlasFlags_NoAALines) | ||||
|     if (atlas->Flags & ImFontAtlasFlags_NoAntiAliasedLines) | ||||
|         return; | ||||
|  | ||||
|     ImFontAtlasCustomRect& r = atlas->CustomRects[atlas->AALineRectId]; | ||||
|     IM_ASSERT(r.IsPacked()); | ||||
|     ImFontAtlasCustomRect* r = atlas->GetCustomRectByIndex(atlas->PackIdAALines); | ||||
|     IM_ASSERT(r->IsPacked()); | ||||
|  | ||||
|     // This generates a triangular shape in the texture, with the various line widths stacked on top of each other to allow interpolation between them | ||||
|     const int w = atlas->TexWidth; | ||||
|     for (unsigned int n = 0; n < (IM_DRAWLIST_TEX_AA_LINES_WIDTH_MAX + 1); n++) // +1 because of the zero-width row | ||||
|     for (unsigned int n = 0; n < IM_DRAWLIST_TEX_AA_LINES_WIDTH_MAX + 1; n++) // +1 because of the zero-width row | ||||
|     { | ||||
|         // Each line consists of at least two empty pixels at the ends, with a line of solid pixels in the middle | ||||
|         unsigned int y = n; | ||||
|         unsigned int line_width = n; | ||||
|         // Each line consists of at least two empty pixels at the ends, with a line of solid pixels in the middle | ||||
|         unsigned int pad_left = (r.Width - line_width) / 2; | ||||
|         unsigned int pad_right = r.Width - (pad_left + line_width); | ||||
|         unsigned int pad_left = (r->Width - line_width) / 2; | ||||
|         unsigned int pad_right = r->Width - (pad_left + line_width); | ||||
|  | ||||
|         // Make sure we're inside the texture bounds before we start writing pixels | ||||
|         IM_ASSERT_PARANOID(pad_left + line_width + pad_right == r.Width); | ||||
|         IM_ASSERT_PARANOID(y < r.Height); | ||||
|  | ||||
|         // Write each slice | ||||
|         unsigned char* write_ptr = &atlas->TexPixelsAlpha8[r.X + ((r.Y + y) * w)]; | ||||
|         unsigned char* write_ptr = &atlas->TexPixelsAlpha8[r->X + ((r->Y + y) * w)]; | ||||
|         for (unsigned int x = 0; x < pad_left; x++) | ||||
|             *(write_ptr++) = 0; | ||||
|         for (unsigned int x = 0; x < line_width; x++) | ||||
| @@ -2433,16 +2429,16 @@ static void ImFontAtlasBuildRenderAALinesTexData(ImFontAtlas* atlas) | ||||
|             *(write_ptr++) = 0; | ||||
|  | ||||
|         // Calculate UVs for this line | ||||
|         ImFontAtlasCustomRect line_rect = r; | ||||
|         ImFontAtlasCustomRect line_rect = *r; | ||||
|         line_rect.X += (unsigned short)(pad_left - 1); | ||||
|         line_rect.Width = (unsigned short)(line_width + 2); | ||||
|         line_rect.Y += (unsigned short)y; | ||||
|         line_rect.Width = (unsigned short)(line_width + 2); | ||||
|         line_rect.Height = 1; | ||||
|  | ||||
|         ImVec2 uv0, uv1; | ||||
|         atlas->CalcCustomRectUV(&line_rect, &uv0, &uv1); | ||||
|         float halfV = (uv0.y + uv1.y) * 0.5f; // Calculate a constant V in the middle of the row to avoid sampling artifacts | ||||
|         atlas->TexUvAALines.push_back(ImVec4(uv0.x, halfV, uv1.x, halfV)); | ||||
|         float half_v = (uv0.y + uv1.y) * 0.5f; // Calculate a constant V in the middle of the row to avoid sampling artifacts | ||||
|         atlas->TexUvAALines[n] = ImVec4(uv0.x, half_v, uv1.x, half_v); | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user