From 127a6d336aa180614fa2864aab5b29d58b753d3f Mon Sep 17 00:00:00 2001 From: Marc Date: Sun, 4 Jul 2021 16:19:01 +0200 Subject: [PATCH] Implement heatmap rendering in a single function (#263) --- backends/implot_backend.h | 7 +++- backends/implot_impl_opengl3.cpp | 69 ++++++++++++++++---------------- implot_items.cpp | 12 ++---- 3 files changed, 44 insertions(+), 44 deletions(-) diff --git a/backends/implot_backend.h b/backends/implot_backend.h index 65b022c..54b8cd5 100644 --- a/backends/implot_backend.h +++ b/backends/implot_backend.h @@ -66,8 +66,11 @@ namespace Backend { void SetHeatmapData(int itemID, const double* values, int rows, int cols); void SetHeatmapData(int itemID, const float* values, int rows, int cols); void RenderHeatmap( - int itemID, ImDrawList& DrawList, const ImVec2& bounds_min, const ImVec2& bounds_max, - float scale_min, float scale_max, ImPlotColormap colormap, bool reverse_y); + int itemID, const void* data, ImGuiDataType data_type, int rows, int cols, + float scale_min, float scale_max, const ImVec2& coords_min, + const ImVec2& coords_max, const ImPlotPoint& bounds_min, + const ImPlotPoint& bounds_max, /*ImPlotScale*/int scale, bool reverse_y, + ImPlotColormap cmap, ImDrawList& DrawList); void SetAxisLog(int itemID, bool x_is_log, bool y_is_log, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max); #endif diff --git a/backends/implot_impl_opengl3.cpp b/backends/implot_impl_opengl3.cpp index f117c24..31606e6 100644 --- a/backends/implot_impl_opengl3.cpp +++ b/backends/implot_impl_opengl3.cpp @@ -246,14 +246,9 @@ static void ResetState(const ImDrawList*, const ImDrawCmd*) glUseProgram(Context.ImGuiShader); } -static void SetTextureData(int itemID, const void* data, GLsizei rows, GLsizei cols, GLint internalFormat, GLenum format, GLenum type) +static void SetTextureData(GLuint textureID, const void* data, GLsizei rows, GLsizei cols, GLint internalFormat, GLenum format, GLenum type) { - ContextData& Context = *((ContextData*)GImPlot->backendCtx); - - HeatmapData& hm = *Context.Heatmaps.GetByKey(itemID); - hm.ShaderProgram = (type == GL_FLOAT ? &Context.ShaderFloat : &Context.ShaderInt); - - glBindTexture(GL_TEXTURE_2D, hm.HeatmapTexID); + glBindTexture(GL_TEXTURE_2D, textureID); glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, cols, rows, 0, format, type, data); } @@ -273,15 +268,7 @@ void AddColormap(const ImU32* keys, int count, bool qual) Context.ColormapIDs.push_back(textureID); } -void SetHeatmapData(int itemID, const ImS8* values, int rows, int cols) { SetTextureData(itemID, values, rows, cols, GL_R8I, GL_RED_INTEGER, GL_BYTE); } -void SetHeatmapData(int itemID, const ImU8* values, int rows, int cols) { SetTextureData(itemID, values, rows, cols, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE); } -void SetHeatmapData(int itemID, const ImS16* values, int rows, int cols) { SetTextureData(itemID, values, rows, cols, GL_R16I, GL_RED_INTEGER, GL_SHORT); } -void SetHeatmapData(int itemID, const ImU16* values, int rows, int cols) { SetTextureData(itemID, values, rows, cols, GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT); } -void SetHeatmapData(int itemID, const ImS32* values, int rows, int cols) { SetTextureData(itemID, values, rows, cols, GL_R32I, GL_RED_INTEGER, GL_INT); } -void SetHeatmapData(int itemID, const ImU32* values, int rows, int cols) { SetTextureData(itemID, values, rows, cols, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT); } -void SetHeatmapData(int itemID, const float* values, int rows, int cols) { SetTextureData(itemID, values, rows, cols, GL_R32F, GL_RED, GL_FLOAT); } - -void SetHeatmapData(int itemID, const double* values, int rows, int cols) +void SetHeatmapData(GLuint textureID, const double* values, int rows, int cols) { ContextData& Context = *((ContextData*)GImPlot->backendCtx); @@ -291,10 +278,10 @@ void SetHeatmapData(int itemID, const double* values, int rows, int cols) for(int i = 0; i < rows*cols; i++) Context.temp1[i] = (float)values[i]; - SetTextureData(itemID, Context.temp1.Data, rows, cols, GL_R32F, GL_RED, GL_FLOAT); + SetTextureData(textureID, Context.temp1.Data, rows, cols, GL_R32F, GL_RED, GL_FLOAT); } -void SetHeatmapData(int itemID, const ImS64* values, int rows, int cols) +void SetHeatmapData(GLuint textureID, const ImS64* values, int rows, int cols) { ContextData& Context = *((ContextData*)GImPlot->backendCtx); @@ -304,10 +291,10 @@ void SetHeatmapData(int itemID, const ImS64* values, int rows, int cols) for(int i = 0; i < rows*cols; i++) Context.temp2[i] = (ImS32)values[i]; - SetTextureData(itemID, Context.temp2.Data, rows, cols, GL_R32I, GL_RED_INTEGER, GL_INT); + SetTextureData(textureID, Context.temp2.Data, rows, cols, GL_R32I, GL_RED_INTEGER, GL_INT); } -void SetHeatmapData(int itemID, const ImU64* values, int rows, int cols) +void SetHeatmapData(GLuint textureID, const ImU64* values, int rows, int cols) { ContextData& Context = *((ContextData*)GImPlot->backendCtx); @@ -317,32 +304,46 @@ void SetHeatmapData(int itemID, const ImU64* values, int rows, int cols) for(int i = 0; i < rows*cols; i++) Context.temp3[i] = (ImU32)values[i]; - SetTextureData(itemID, Context.temp3.Data, rows, cols, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT); + SetTextureData(textureID, Context.temp3.Data, rows, cols, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT); } -void SetAxisLog(int itemID, bool x_is_log, bool y_is_log, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max) -{ - ContextData& Context = *((ContextData*)GImPlot->backendCtx); - HeatmapData& data = *Context.Heatmaps.GetByKey(itemID); - data.AxisLogX = x_is_log; - data.AxisLogY = y_is_log; - data.MinBounds = bounds_min; - data.MaxBounds = bounds_max; -} - -void RenderHeatmap(int itemID, ImDrawList& DrawList, const ImVec2& bounds_min, const ImVec2& bounds_max, float scale_min, float scale_max, ImPlotColormap colormap, bool reverse_y) +void RenderHeatmap( + int itemID, const void* values, ImGuiDataType data_type, int rows, int cols, float scale_min, float scale_max, + const ImVec2& coords_min, const ImVec2& coords_max, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max, + ImPlotScale scale, bool reverse_y, ImPlotColormap cmap, ImDrawList& DrawList) { ContextData& Context = *((ContextData*)GImPlot->backendCtx); HeatmapData& data = *Context.Heatmaps.GetOrAddByKey(itemID); data.ID = itemID; - data.ColormapTexID = Context.ColormapIDs[colormap]; + data.ColormapTexID = Context.ColormapIDs[cmap]; data.MinValue = scale_min; data.MaxValue = scale_max; + data.AxisLogX = scale == ImPlotScale_LogLin || scale == ImPlotScale_LogLog; + data.AxisLogY = scale == ImPlotScale_LinLog || scale == ImPlotScale_LogLog; + data.MinBounds = bounds_min; + data.MaxBounds = bounds_max; + data.ShaderProgram = (data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double ? &Context.ShaderFloat : &Context.ShaderInt); + + switch(data_type) + { + case ImGuiDataType_S8: SetTextureData(data.HeatmapTexID, (const ImS8*) values, rows, cols, GL_R8I, GL_RED_INTEGER, GL_BYTE ); break; + case ImGuiDataType_U8: SetTextureData(data.HeatmapTexID, (const ImU8*) values, rows, cols, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE ); break; + case ImGuiDataType_S16: SetTextureData(data.HeatmapTexID, (const ImS16*)values, rows, cols, GL_R16I, GL_RED_INTEGER, GL_SHORT ); break; + case ImGuiDataType_U16: SetTextureData(data.HeatmapTexID, (const ImU16*)values, rows, cols, GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT); break; + case ImGuiDataType_S32: SetTextureData(data.HeatmapTexID, (const ImS32*)values, rows, cols, GL_R32I, GL_RED_INTEGER, GL_INT ); break; + case ImGuiDataType_U32: SetTextureData(data.HeatmapTexID, (const ImU32*)values, rows, cols, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT ); break; + case ImGuiDataType_S64: SetHeatmapData(data.HeatmapTexID, (const ImS64*)values, rows, cols); break; + case ImGuiDataType_U64: SetHeatmapData(data.HeatmapTexID, (const ImU64*)values, rows, cols); break; + case ImGuiDataType_Float: SetTextureData(data.HeatmapTexID, (const float*)values, rows, cols, GL_R32F, GL_RED, GL_FLOAT); break; + case ImGuiDataType_Double: SetHeatmapData(data.HeatmapTexID, (double*)values, rows, cols); break; + }; + if(Context.ShaderInt.ID == 0 || Context.ShaderFloat.ID == 0) DrawList.AddCallback(CreateHeatmapShader, nullptr); + DrawList.AddCallback(RenderCallback, (void*)(intptr_t)itemID); DrawList.PrimReserve(6, 4); - DrawList.PrimRectUV(bounds_min, bounds_max, ImVec2(0.0f, reverse_y ? 1.0f : 0.0f), ImVec2(1.0f, reverse_y ? 0.0f : 1.0f), 0); + DrawList.PrimRectUV(coords_min, coords_max, ImVec2(0.0f, reverse_y ? 1.0f : 0.0f), ImVec2(1.0f, reverse_y ? 0.0f : 1.0f), 0); DrawList.AddCallback(ResetState, nullptr); } diff --git a/implot_items.cpp b/implot_items.cpp index 25c3de3..6b6842a 100644 --- a/implot_items.cpp +++ b/implot_items.cpp @@ -1910,15 +1910,11 @@ void RenderHeatmap(Transformer transformer, ImDrawList& DrawList, const T* value if (GImPlot->Style.UseGpuAacceleration) { ImVec2 bmin = transformer(bounds_min); ImVec2 bmax = transformer(bounds_max); - ImPlotScale scale = GetCurrentScale(); - // NOTE: Order is important! - Backend::RenderHeatmap(gp.CurrentItem->ID, DrawList, bmin, bmax, (float)scale_min, (float)scale_max, gp.Style.Colormap, reverse_y); - Backend::SetAxisLog(gp.CurrentItem->ID, - scale == ImPlotScale_LogLin || scale == ImPlotScale_LogLog, - scale == ImPlotScale_LinLog || scale == ImPlotScale_LogLog, - bounds_min, bounds_max); - Backend::SetHeatmapData(gp.CurrentItem->ID, values, rows, cols); + Backend::RenderHeatmap( + gp.CurrentItem->ID, values, ImGuiDataTypeGetter::Value, rows, cols, + (float)scale_min, (float)scale_max, bmin, bmax, bounds_min, bounds_max, + GetCurrentScale(), reverse_y, gp.Style.Colormap, DrawList); } else #endif