main
parent
f75cbbb10c
commit
1afe267163
|
@ -1,7 +1,7 @@
|
|||
cmake_minimum_required(VERSION 3.25)
|
||||
include(FetchContent)
|
||||
|
||||
set(BLT_GRAPHICS_VERSION 1.0.11)
|
||||
set(BLT_GRAPHICS_VERSION 1.0.12)
|
||||
set(BLT_GRAPHICS_TEST_VERSION 0.0.1)
|
||||
|
||||
project(BLT_WITH_GRAPHICS VERSION ${BLT_GRAPHICS_VERSION})
|
||||
|
|
|
@ -8,8 +8,13 @@
|
|||
|
||||
namespace ImGui
|
||||
{
|
||||
namespace Spectrum
|
||||
{
|
||||
extern const unsigned int SourceSansProRegular_compressed_size;
|
||||
extern const unsigned int SourceSansProRegular_compressed_data[]; // defined later in the file
|
||||
}
|
||||
|
||||
inline void SetupImGuiStyle( bool bStyleDark_, float alpha_ )
|
||||
inline void SetupImGuiStyle(bool bStyleDark_, float alpha_)
|
||||
{
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
|
||||
|
@ -60,31 +65,30 @@ namespace ImGui
|
|||
style.Colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
|
||||
//style.Colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f);
|
||||
|
||||
if( bStyleDark_ )
|
||||
if (bStyleDark_)
|
||||
{
|
||||
for (int i = 0; i < ImGuiCol_COUNT; i++)
|
||||
{
|
||||
ImVec4& col = style.Colors[i];
|
||||
float H, S, V;
|
||||
ImGui::ColorConvertRGBtoHSV( col.x, col.y, col.z, H, S, V );
|
||||
ImGui::ColorConvertRGBtoHSV(col.x, col.y, col.z, H, S, V);
|
||||
|
||||
if( S < 0.1f )
|
||||
if (S < 0.1f)
|
||||
{
|
||||
V = 1.0f - V;
|
||||
}
|
||||
ImGui::ColorConvertHSVtoRGB( H, S, V, col.x, col.y, col.z );
|
||||
if( col.w < 1.00f )
|
||||
ImGui::ColorConvertHSVtoRGB(H, S, V, col.x, col.y, col.z);
|
||||
if (col.w < 1.00f)
|
||||
{
|
||||
col.w *= alpha_;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
} else
|
||||
{
|
||||
for (int i = 0; i < ImGuiCol_COUNT; i++)
|
||||
{
|
||||
ImVec4& col = style.Colors[i];
|
||||
if( col.w < 1.00f )
|
||||
if (col.w < 1.00f)
|
||||
{
|
||||
col.x *= alpha_;
|
||||
col.y *= alpha_;
|
||||
|
@ -95,49 +99,47 @@ namespace ImGui
|
|||
}
|
||||
}
|
||||
|
||||
inline bool CheckBoxFont( const char* name_, bool* pB_, const char* pOn_ = "[X]", const char* pOff_="[ ]" )
|
||||
inline bool CheckBoxFont(const char* name_, bool* pB_, const char* pOn_ = "[X]", const char* pOff_ = "[ ]")
|
||||
{
|
||||
if( *pB_ )
|
||||
if (*pB_)
|
||||
{
|
||||
ImGui::Text("%s", pOn_);
|
||||
}
|
||||
else
|
||||
} else
|
||||
{
|
||||
ImGui::Text("%s", pOff_);
|
||||
}
|
||||
bool bHover = false;
|
||||
bHover = bHover || ImGui::IsItemHovered();
|
||||
ImGui::SameLine();
|
||||
ImGui::Text( "%s", name_ );
|
||||
ImGui::Text("%s", name_);
|
||||
bHover = bHover || ImGui::IsItemHovered();
|
||||
if( bHover && ImGui::IsMouseClicked(0) )
|
||||
if (bHover && ImGui::IsMouseClicked(0))
|
||||
{
|
||||
*pB_ = ! *pB_;
|
||||
*pB_ = !*pB_;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool CheckBoxTick( const char* name_, bool* pB_ )
|
||||
inline bool CheckBoxTick(const char* name_, bool* pB_)
|
||||
{
|
||||
return CheckBoxFont( name_, pB_, ICON_FA_CHECK_SQUARE, ICON_FA_SQUARE );
|
||||
return CheckBoxFont(name_, pB_, ICON_FA_CHECK_SQUARE, ICON_FA_SQUARE);
|
||||
}
|
||||
|
||||
inline bool MenuItemCheckbox( const char* name_, bool* pB_ )
|
||||
inline bool MenuItemCheckbox(const char* name_, bool* pB_)
|
||||
{
|
||||
bool retval = ImGui::MenuItem( name_ );
|
||||
bool retval = ImGui::MenuItem(name_);
|
||||
ImGui::SameLine();
|
||||
if( *pB_ )
|
||||
if (*pB_)
|
||||
{
|
||||
ImGui::Text(ICON_FA_CHECK_SQUARE);
|
||||
}
|
||||
else
|
||||
} else
|
||||
{
|
||||
ImGui::Text(ICON_FA_SQUARE);
|
||||
}
|
||||
if( retval )
|
||||
if (retval)
|
||||
{
|
||||
*pB_ = ! *pB_;
|
||||
*pB_ = !*pB_;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
@ -148,19 +150,19 @@ namespace ImGui
|
|||
static const int NUM = 101; //last value is from T-1 to inf.
|
||||
|
||||
float dT = 0.001f; // in seconds, default 1ms
|
||||
float refresh = 1.0f/60.0f;// set this to your target refresh rate
|
||||
float refresh = 1.0f / 60.0f;// set this to your target refresh rate
|
||||
|
||||
static const int NUM_MARKERS = 2;
|
||||
float markers[NUM_MARKERS] = { 0.99f, 0.999f };
|
||||
float markers[NUM_MARKERS] = {0.99f, 0.999f};
|
||||
|
||||
// data
|
||||
ImVec2 size = ImVec2( 3.0f * NUM, 40.0f );
|
||||
ImVec2 size = ImVec2(3.0f * NUM, 40.0f);
|
||||
float lastdT = 0.0f;
|
||||
float timesTotal;
|
||||
float countsTotal;
|
||||
float times[ NUM];
|
||||
float times[NUM];
|
||||
float counts[NUM];
|
||||
float hitchTimes[ NUM];
|
||||
float hitchTimes[NUM];
|
||||
float hitchCounts[NUM];
|
||||
|
||||
FrameTimeHistogram()
|
||||
|
@ -172,43 +174,43 @@ namespace ImGui
|
|||
{
|
||||
timesTotal = 0.0f;
|
||||
countsTotal = 0.0f;
|
||||
memset(times, 0, sizeof(times) );
|
||||
memset(counts, 0, sizeof(counts) );
|
||||
memset(hitchTimes, 0, sizeof(hitchTimes) );
|
||||
memset(hitchCounts, 0, sizeof(hitchCounts) );
|
||||
memset(times, 0, sizeof(times));
|
||||
memset(counts, 0, sizeof(counts));
|
||||
memset(hitchTimes, 0, sizeof(hitchTimes));
|
||||
memset(hitchCounts, 0, sizeof(hitchCounts));
|
||||
}
|
||||
|
||||
int GetBin( float time_ )
|
||||
int GetBin(float time_)
|
||||
{
|
||||
int bin = (int)std::floor( time_ / dT );
|
||||
if( bin >= NUM )
|
||||
int bin = (int) std::floor(time_ / dT);
|
||||
if (bin >= NUM)
|
||||
{
|
||||
bin = NUM - 1;
|
||||
}
|
||||
return bin;
|
||||
}
|
||||
|
||||
void Update( float deltaT_ )
|
||||
void Update(float deltaT_)
|
||||
{
|
||||
if( deltaT_ < 0.0f )
|
||||
if (deltaT_ < 0.0f)
|
||||
{
|
||||
assert(false);
|
||||
return;
|
||||
}
|
||||
int bin = GetBin( deltaT_ );
|
||||
times[ bin] += deltaT_;
|
||||
int bin = GetBin(deltaT_);
|
||||
times[bin] += deltaT_;
|
||||
timesTotal += deltaT_;
|
||||
counts[bin] += 1.0f;
|
||||
countsTotal += 1.0f;
|
||||
|
||||
float hitch = abs( lastdT - deltaT_ );
|
||||
int deltaBin = GetBin( hitch );
|
||||
hitchTimes[ deltaBin] += hitch;
|
||||
float hitch = abs(lastdT - deltaT_);
|
||||
int deltaBin = GetBin(hitch);
|
||||
hitchTimes[deltaBin] += hitch;
|
||||
hitchCounts[deltaBin] += 1.0f;
|
||||
lastdT = deltaT_;
|
||||
}
|
||||
|
||||
void PlotRefreshLines( float total_ = 0.0f, float* pValues_ = NULL)
|
||||
void PlotRefreshLines(float total_ = 0.0f, float* pValues_ = NULL)
|
||||
{
|
||||
ImDrawList* draw = ImGui::GetWindowDrawList();
|
||||
const ImGuiStyle& style = ImGui::GetStyle();
|
||||
|
@ -218,35 +220,36 @@ namespace ImGui
|
|||
ImVec2 max = ImGui::GetItemRectMax();
|
||||
max.x -= pad.x;
|
||||
|
||||
float xRefresh = (max.x - min.x) * refresh / ( dT * NUM );
|
||||
float xRefresh = (max.x - min.x) * refresh / (dT * NUM);
|
||||
|
||||
float xCurr = xRefresh + min.x;
|
||||
while( xCurr < max.x )
|
||||
while (xCurr < max.x)
|
||||
{
|
||||
float xP = ceil( xCurr ); // use ceil to get integer coords or else lines look odd
|
||||
draw->AddLine( ImVec2( xP, min.y ), ImVec2( xP, max.y ), 0x50FFFFFF );
|
||||
float xP = ceil(xCurr); // use ceil to get integer coords or else lines look odd
|
||||
draw->AddLine(ImVec2(xP, min.y), ImVec2(xP, max.y), 0x50FFFFFF);
|
||||
xCurr += xRefresh;
|
||||
}
|
||||
|
||||
if( pValues_ )
|
||||
if (pValues_)
|
||||
{
|
||||
// calc markers
|
||||
float currTotal = 0.0f;
|
||||
int mark = 0;
|
||||
for( int i = 0; i < NUM && mark < NUM_MARKERS; ++i )
|
||||
for (int i = 0; i < NUM && mark < NUM_MARKERS; ++i)
|
||||
{
|
||||
currTotal += pValues_[i];
|
||||
if( total_ * markers[mark] < currTotal )
|
||||
if (total_ * markers[mark] < currTotal)
|
||||
{
|
||||
float xP = ceil( (float)(i+1)/(float)NUM * ( max.x - min.x ) + min.x ); // use ceil to get integer coords or else lines look odd
|
||||
draw->AddLine( ImVec2( xP, min.y ), ImVec2( xP, max.y ), 0xFFFF0000 );
|
||||
float xP = ceil(
|
||||
(float) (i + 1) / (float) NUM * (max.x - min.x) + min.x); // use ceil to get integer coords or else lines look odd
|
||||
draw->AddLine(ImVec2(xP, min.y), ImVec2(xP, max.y), 0xFFFF0000);
|
||||
++mark;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CalcHistogramSize( int numShown_ )
|
||||
void CalcHistogramSize(int numShown_)
|
||||
{
|
||||
ImVec2 wRegion = ImGui::GetContentRegionMax();
|
||||
float heightGone = 7.0f * ImGui::GetTextLineHeightWithSpacing();
|
||||
|
@ -259,40 +262,40 @@ namespace ImGui
|
|||
}
|
||||
|
||||
|
||||
void Draw(const char* name_, bool* pOpen_ = NULL )
|
||||
void Draw(const char* name_, bool* pOpen_ = NULL)
|
||||
{
|
||||
if (ImGui::Begin( name_, pOpen_ ))
|
||||
if (ImGui::Begin(name_, pOpen_))
|
||||
{
|
||||
int numShown = 0;
|
||||
if(ImGui::CollapsingHeader("Time Histogram"))
|
||||
if (ImGui::CollapsingHeader("Time Histogram"))
|
||||
{
|
||||
++numShown;
|
||||
ImGui::PlotHistogram("", times, NUM, 0, NULL, FLT_MAX, FLT_MAX, size );
|
||||
PlotRefreshLines( timesTotal, times );
|
||||
ImGui::PlotHistogram("", times, NUM, 0, NULL, FLT_MAX, FLT_MAX, size);
|
||||
PlotRefreshLines(timesTotal, times);
|
||||
}
|
||||
if(ImGui::CollapsingHeader("Count Histogram"))
|
||||
if (ImGui::CollapsingHeader("Count Histogram"))
|
||||
{
|
||||
++numShown;
|
||||
ImGui::PlotHistogram("", counts, NUM, 0, NULL, FLT_MAX, FLT_MAX, size );
|
||||
PlotRefreshLines( countsTotal, counts );
|
||||
ImGui::PlotHistogram("", counts, NUM, 0, NULL, FLT_MAX, FLT_MAX, size);
|
||||
PlotRefreshLines(countsTotal, counts);
|
||||
}
|
||||
if(ImGui::CollapsingHeader("Hitch Time Histogram"))
|
||||
if (ImGui::CollapsingHeader("Hitch Time Histogram"))
|
||||
{
|
||||
++numShown;
|
||||
ImGui::PlotHistogram("", hitchTimes, NUM, 0, NULL, FLT_MAX, FLT_MAX, size );
|
||||
ImGui::PlotHistogram("", hitchTimes, NUM, 0, NULL, FLT_MAX, FLT_MAX, size);
|
||||
PlotRefreshLines();
|
||||
}
|
||||
if(ImGui::CollapsingHeader("Hitch Count Histogram"))
|
||||
if (ImGui::CollapsingHeader("Hitch Count Histogram"))
|
||||
{
|
||||
++numShown;
|
||||
ImGui::PlotHistogram("", hitchCounts, NUM, 0, NULL, FLT_MAX, FLT_MAX, size );
|
||||
ImGui::PlotHistogram("", hitchCounts, NUM, 0, NULL, FLT_MAX, FLT_MAX, size);
|
||||
PlotRefreshLines();
|
||||
}
|
||||
if( ImGui::Button("Clear") )
|
||||
if (ImGui::Button("Clear"))
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
CalcHistogramSize( numShown );
|
||||
CalcHistogramSize(numShown);
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
|
|
@ -87,7 +87,8 @@ namespace blt::gfx
|
|||
explicit point2d_t(const vec2f pos): pos(pos)
|
||||
{}
|
||||
|
||||
point2d_t apply_scale(float s) const {
|
||||
point2d_t apply_scale(float s) const
|
||||
{
|
||||
return {pos, scale * s};
|
||||
}
|
||||
};
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <blt/gfx/texture.h>
|
||||
#include <blt/gfx/shader.h>
|
||||
#include <blt/gfx/model.h>
|
||||
#include <blt/gfx/framebuffer.h>
|
||||
#include <blt/std/hashmap.h>
|
||||
#include <blt/std/binary_tree.h>
|
||||
|
||||
|
@ -118,6 +119,24 @@ namespace blt::gfx
|
|||
class font_renderer_t
|
||||
{
|
||||
public:
|
||||
struct render_context
|
||||
{
|
||||
blt::vec2f position, bounds;
|
||||
blt::vec2f scale;
|
||||
blt::vec4 color;
|
||||
};
|
||||
|
||||
struct text_index_t
|
||||
{
|
||||
std::string text;
|
||||
float size;
|
||||
std::string font;
|
||||
|
||||
bool operator==(const text_index_t& rhs) const;
|
||||
|
||||
bool operator!=(const text_index_t& rhs) const;
|
||||
};
|
||||
|
||||
struct compiled_text_t
|
||||
{
|
||||
friend font_renderer_t;
|
||||
|
@ -135,22 +154,21 @@ namespace blt::gfx
|
|||
compiled_text_t& setBounds(const blt::vec2f& limit)
|
||||
{
|
||||
bounds = limit;
|
||||
recompile();
|
||||
return *this;
|
||||
}
|
||||
|
||||
compiled_text_t& setBounds(float width, float height)
|
||||
{
|
||||
return setBounds({width, height});
|
||||
}
|
||||
|
||||
compiled_text_t& setUnrestrictedBounds()
|
||||
{
|
||||
bounds = {};
|
||||
return *this;
|
||||
}
|
||||
|
||||
compiled_text_t& setSize(float size)
|
||||
{
|
||||
current_size = size;
|
||||
scale = {size / generator.get_generated_size(), size / generator.get_generated_size()};
|
||||
return *this;
|
||||
}
|
||||
|
||||
compiled_text_t& setColor(const blt::vec4f& c)
|
||||
{
|
||||
color = c;
|
||||
|
@ -169,6 +187,14 @@ namespace blt::gfx
|
|||
return *this;
|
||||
}
|
||||
|
||||
compiled_text_t& setSize(float size)
|
||||
{
|
||||
current_size = size;
|
||||
scale = {size / generator.get_generated_size(), size / generator.get_generated_size()};
|
||||
recompile();
|
||||
return *this;
|
||||
}
|
||||
|
||||
compiled_text_t& setZIndex(float s)
|
||||
{
|
||||
z_index = s;
|
||||
|
@ -212,7 +238,7 @@ namespace blt::gfx
|
|||
std::vector<text_render_info_t> renders;
|
||||
blt::vec2f position, bounds;
|
||||
blt::vec2f scale = {1, 1};
|
||||
blt::vec4 color = blt::make_color(1, 1, 1);
|
||||
blt::vec4 color = blt::make_color(0.8, 0.8, 0.8);
|
||||
float z_index = 0;
|
||||
float current_size = 0;
|
||||
};
|
||||
|
@ -237,19 +263,52 @@ namespace blt::gfx
|
|||
|
||||
compiled_text_t* create_text(std::string_view str, float size, std::string_view font = "__default");
|
||||
|
||||
compiled_text_t* render_text(std::string_view str, float size, std::string_view font = "__default");
|
||||
|
||||
void destroy_text(compiled_text_t* text);
|
||||
|
||||
void render();
|
||||
|
||||
private:
|
||||
std::unique_ptr<compiled_text_t> allocate_text();
|
||||
|
||||
std::unique_ptr<font_generator_t> generator;
|
||||
std::unique_ptr<shader_t> font_shader;
|
||||
|
||||
blt::hashmap_t<text_index_t, compiled_text_t*> rendered_strings;
|
||||
blt::hashmap_t<compiled_text_t*, text_index_t> text_ptr_to_text_index;
|
||||
|
||||
blt::hashset_t<compiled_text_t*> last_rendered_strings;
|
||||
blt::hashset_t<compiled_text_t*> currently_rendered_strings;
|
||||
|
||||
blt::hashmap_t<compiled_text_t*, blt::size_t> text_ptr_to_index;
|
||||
std::vector<std::unique_ptr<compiled_text_t>> added_texts;
|
||||
std::vector<std::unique_ptr<compiled_text_t>> cached_text_objects;
|
||||
std::vector<std::unique_ptr<compiled_text_t>> cached_deallocated_text_objects;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace blt::gfx::detail
|
||||
{
|
||||
inline void hash_combine(std::size_t& seed, const std::size_t& value)
|
||||
{
|
||||
seed ^= value + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
}
|
||||
}
|
||||
|
||||
// Specialization of std::hash for text_index_t
|
||||
template<>
|
||||
struct std::hash<blt::gfx::font_renderer_t::text_index_t>
|
||||
{
|
||||
std::size_t operator()(const blt::gfx::font_renderer_t::text_index_t& key) const
|
||||
{
|
||||
blt::size_t hash = 0;
|
||||
blt::gfx::detail::hash_combine(hash, std::hash<std::string>{}(key.text));
|
||||
blt::gfx::detail::hash_combine(hash, std::hash<float>{}(key.size));
|
||||
blt::gfx::detail::hash_combine(hash, std::hash<std::string>{}(key.font));
|
||||
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //BLT_WITH_GRAPHICS_FONT_RENDERER_H
|
||||
|
|
|
@ -11,9 +11,14 @@ const std::string shader_2d_font_frag = R"("
|
|||
uniform vec4 color;
|
||||
|
||||
void main() {
|
||||
FragColor = texture(tex, uv).r * color;
|
||||
if (FragColor.a < 0.2)
|
||||
if (texture(tex, uv).r > 0.2)
|
||||
FragColor = color;
|
||||
else
|
||||
discard;
|
||||
// if (FragColor.a < 0.2)
|
||||
// discard;
|
||||
// else
|
||||
// FragColor.a = 1.0;
|
||||
}
|
||||
|
||||
")";
|
||||
|
|
|
@ -18,7 +18,10 @@
|
|||
#include <blt/gfx/renderer/font_renderer.h>
|
||||
#include <blt/gfx/renderer/shaders/2d_font.vert>
|
||||
#include <blt/gfx/renderer/shaders/2d_font.frag>
|
||||
#include "blt/gfx/window.h"
|
||||
|
||||
#include <blt/gfx/shader.h>
|
||||
#include <blt/gfx/imgui/ImGuiUtils.h>
|
||||
#include <cctype>
|
||||
|
||||
// TODO: signed distance fonts
|
||||
|
@ -148,17 +151,19 @@ namespace blt::gfx
|
|||
{
|
||||
create(gen_size, dimensions);
|
||||
|
||||
add_default_font(reinterpret_cast<const blt::u8*>(font::default_font_compressed_data), font::default_font_compressed_size, true);
|
||||
// add_default_font(reinterpret_cast<const blt::u8*>(font::default_font_compressed_data), font::default_font_compressed_size, true);
|
||||
add_default_font(reinterpret_cast<const blt::u8*>(ImGui::Spectrum::SourceSansProRegular_compressed_data),
|
||||
ImGui::Spectrum::SourceSansProRegular_compressed_size, true);
|
||||
}
|
||||
|
||||
void font_renderer_t::cleanup()
|
||||
{
|
||||
for (auto& n : added_texts)
|
||||
n = nullptr;
|
||||
for (auto& c : cached_text_objects)
|
||||
for (auto& c : cached_deallocated_text_objects)
|
||||
c = nullptr;
|
||||
added_texts.clear();
|
||||
cached_text_objects.clear();
|
||||
cached_deallocated_text_objects.clear();
|
||||
text_ptr_to_index.clear();
|
||||
font_shader = nullptr;
|
||||
generator = nullptr;
|
||||
|
@ -167,15 +172,7 @@ namespace blt::gfx
|
|||
|
||||
font_renderer_t::compiled_text_t* font_renderer_t::create_text(std::string_view str, float size, std::string_view font)
|
||||
{
|
||||
std::unique_ptr<font_renderer_t::compiled_text_t> ptr;
|
||||
if (!cached_text_objects.empty())
|
||||
{
|
||||
ptr = std::move(*cached_text_objects.begin());
|
||||
cached_text_objects.erase(cached_text_objects.begin());
|
||||
} else
|
||||
{
|
||||
ptr = std::unique_ptr<compiled_text_t>(new compiled_text_t{*generator});
|
||||
}
|
||||
std::unique_ptr<font_renderer_t::compiled_text_t> ptr = allocate_text();
|
||||
ptr->setText(str, size, font);
|
||||
auto index = added_texts.size();
|
||||
added_texts.push_back(std::move(ptr));
|
||||
|
@ -187,18 +184,22 @@ namespace blt::gfx
|
|||
{
|
||||
auto index = text_ptr_to_index[text];
|
||||
text_ptr_to_index.erase(text);
|
||||
cached_text_objects.push_back(std::move(added_texts[index]));
|
||||
cached_deallocated_text_objects.push_back(std::move(added_texts[index]));
|
||||
added_texts[index] = nullptr;
|
||||
added_texts.erase(added_texts.begin() + static_cast<blt::ptrdiff_t>(index));
|
||||
}
|
||||
|
||||
void font_renderer_t::render()
|
||||
{
|
||||
#ifndef __EMSCRIPTEN__
|
||||
glDisable(GL_MULTISAMPLE);
|
||||
#endif
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
font_shader->bind();
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
for (auto& text : added_texts)
|
||||
for (auto [text, index] : text_ptr_to_index)
|
||||
{
|
||||
blt::mat4x4 transform;
|
||||
transform.translate(text->position);
|
||||
|
@ -208,22 +209,87 @@ namespace blt::gfx
|
|||
font_shader->setVec4("color", text->color);
|
||||
text->draw();
|
||||
}
|
||||
|
||||
for (auto& text : currently_rendered_strings)
|
||||
{
|
||||
blt::mat4x4 transform;
|
||||
transform.translate(text->position);
|
||||
transform.scale(text->scale);
|
||||
font_shader->setMatrix("transform", transform);
|
||||
font_shader->setFloat("z_index", text->z_index);
|
||||
font_shader->setVec4("color", text->color);
|
||||
text->draw();
|
||||
|
||||
if (last_rendered_strings.find(text) != last_rendered_strings.end())
|
||||
last_rendered_strings.erase(text);
|
||||
}
|
||||
|
||||
for (auto& text : last_rendered_strings)
|
||||
{
|
||||
rendered_strings.erase(text_ptr_to_text_index[text]);
|
||||
text_ptr_to_text_index.erase(text);
|
||||
cached_deallocated_text_objects.emplace_back(std::move(added_texts[text_ptr_to_index[text]]));
|
||||
text_ptr_to_index.erase(text);
|
||||
}
|
||||
|
||||
for (auto& text : currently_rendered_strings)
|
||||
last_rendered_strings.insert(text);
|
||||
currently_rendered_strings.clear();
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void font_renderer_t::add_default_font(std::string_view path, std::string_view name)
|
||||
{
|
||||
font::font_face_t default_font_face{path, name};
|
||||
font::font_file_t default_font{default_font_face, 0, 128};
|
||||
font::font_file_t default_font{default_font_face, 0, 256};
|
||||
add_font(default_font);
|
||||
}
|
||||
|
||||
void font_renderer_t::add_default_font(const blt::u8* data, blt::size_t size, bool compressed, std::string_view name)
|
||||
{
|
||||
font::font_face_t default_font_face{name, data, size, compressed};
|
||||
font::font_file_t default_font{default_font_face, 0, 128};
|
||||
font::font_file_t default_font{default_font_face, 0, 256};
|
||||
add_font(default_font);
|
||||
}
|
||||
|
||||
std::unique_ptr<font_renderer_t::compiled_text_t> font_renderer_t::allocate_text()
|
||||
{
|
||||
std::unique_ptr<font_renderer_t::compiled_text_t> ptr;
|
||||
if (!cached_deallocated_text_objects.empty())
|
||||
{
|
||||
ptr = std::move(*cached_deallocated_text_objects.begin());
|
||||
cached_deallocated_text_objects.erase(cached_deallocated_text_objects.begin());
|
||||
} else
|
||||
{
|
||||
ptr = std::unique_ptr<compiled_text_t>(new compiled_text_t{*generator});
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
font_renderer_t::compiled_text_t* font_renderer_t::render_text(std::string_view str, float size, std::string_view font)
|
||||
{
|
||||
auto str_iter = rendered_strings.find(text_index_t{std::string(str), size, std::string(font)});
|
||||
if (str_iter != rendered_strings.end())
|
||||
{
|
||||
currently_rendered_strings.insert(str_iter->second);
|
||||
return str_iter->second;
|
||||
}
|
||||
auto index = added_texts.size();
|
||||
added_texts.emplace_back(allocate_text());
|
||||
auto ptr = added_texts.back().get();
|
||||
ptr->setText(str, size);
|
||||
|
||||
text_ptr_to_text_index[ptr] = text_index_t{std::string(str), size, std::string(font)};
|
||||
rendered_strings[text_index_t{std::string(str), size, std::string(font)}] = ptr;
|
||||
text_ptr_to_index[ptr] = index;
|
||||
|
||||
currently_rendered_strings.insert(ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
font_renderer_t::compiled_text_t& font_renderer_t::compiled_text_t::setText(std::string_view str, float size, std::string_view f)
|
||||
{
|
||||
if (str == contents)
|
||||
|
@ -262,40 +328,9 @@ namespace blt::gfx
|
|||
}
|
||||
}
|
||||
|
||||
struct word_t
|
||||
{
|
||||
std::vector<float> vertices;
|
||||
float x = 0;
|
||||
|
||||
void apply(std::vector<float>& out)
|
||||
{
|
||||
for (float v : vertices)
|
||||
out.push_back(v + x);
|
||||
vertices.clear();
|
||||
x = 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct position_tracker_t
|
||||
{
|
||||
float global_x = 0, global_y = 0;
|
||||
|
||||
void newline(float line_size)
|
||||
{
|
||||
global_y -= line_size;
|
||||
global_x = 0;
|
||||
}
|
||||
|
||||
void advance(blt::u64 size)
|
||||
{
|
||||
global_x += static_cast<float>(size >> 6);
|
||||
}
|
||||
};
|
||||
|
||||
font_renderer_t::compiled_text_t& font_renderer_t::compiled_text_t::recompile()
|
||||
{
|
||||
static std::vector<float> vertices;
|
||||
static word_t current_word;
|
||||
vertices.clear();
|
||||
renders.clear();
|
||||
|
||||
|
@ -303,27 +338,33 @@ namespace blt::gfx
|
|||
blt::size_t draw_start = 0;
|
||||
blt::size_t draw_count = 0;
|
||||
|
||||
position_tracker_t current_pos;
|
||||
const float sc = generator.get_generated_size() / current_size;
|
||||
|
||||
float global_x = 0;
|
||||
float global_y = 0;
|
||||
// TODO: parker UTF8
|
||||
for (const auto& c : contents)
|
||||
{
|
||||
// std::cout << "C: " << c << " || " << static_cast<int>(c) << std::endl;
|
||||
if (bounds.y() > 0 && std::abs(global_y) >= bounds.y() * sc)
|
||||
continue;
|
||||
if (c == '\n')
|
||||
{
|
||||
current_pos.newline(generator.get_generated_size());
|
||||
global_x = 0;
|
||||
global_y -= generator.get_generated_size();
|
||||
continue;
|
||||
}
|
||||
auto& texture = generator.get_texture(std::string(font), c);
|
||||
auto& ch = texture.get_glyph(c, font);
|
||||
|
||||
// if (std::isblank(c))
|
||||
// {
|
||||
// if (bounds.x() > 0 && current_pos.global_x + current_word.x > bounds.x())
|
||||
// current_pos.newline(generator.get_generated_size());
|
||||
//
|
||||
// }
|
||||
if (std::isspace(c))
|
||||
current_word.apply(vertices);
|
||||
if (std::isblank(c))
|
||||
{
|
||||
if (bounds.x() > 0 && global_x > bounds.x() * sc)
|
||||
{
|
||||
global_x = 0;
|
||||
global_y -= generator.get_generated_size();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (last_texture == nullptr)
|
||||
last_texture = &texture;
|
||||
|
@ -336,8 +377,8 @@ namespace blt::gfx
|
|||
|
||||
auto dims = static_cast<float>(generator.get_dimensions());
|
||||
|
||||
float x_pos = current_pos.global_x + static_cast<float>(ch.glyph.bearing.x());
|
||||
float y_pos = current_pos.global_y - static_cast<float>(ch.glyph.size.y() - ch.glyph.bearing.y());
|
||||
float x_pos = global_x + static_cast<float>(ch.glyph.bearing.x());
|
||||
float y_pos = global_y - static_cast<float>(ch.glyph.size.y() - ch.glyph.bearing.y());
|
||||
|
||||
auto w = static_cast<float>(ch.glyph.size.x());
|
||||
auto h = static_cast<float>(ch.glyph.size.y());
|
||||
|
@ -358,12 +399,11 @@ namespace blt::gfx
|
|||
x_pos + w, y_pos, texture_max_x, texture_max_y,
|
||||
x_pos + w, y_pos + h, texture_max_x, texture_min_y
|
||||
};
|
||||
current_word.vertices.insert(current_word.vertices.end(), local_vert.begin(), local_vert.end());
|
||||
vertices.insert(vertices.end(), local_vert.begin(), local_vert.end());
|
||||
|
||||
draw_count += 6;
|
||||
current_pos.advance(ch.glyph.advance);
|
||||
global_x += static_cast<float>(ch.glyph.advance >> 6);
|
||||
}
|
||||
current_word.apply(vertices);
|
||||
|
||||
// BLT_TRACE("size: %ld %ld %ld", draw_count, vertices.size(), vertices.size() / 4);
|
||||
|
||||
|
@ -373,4 +413,13 @@ namespace blt::gfx
|
|||
}
|
||||
|
||||
|
||||
bool font_renderer_t::text_index_t::operator==(const font_renderer_t::text_index_t& rhs) const
|
||||
{
|
||||
return text == rhs.text && blt::f_equal(size, rhs.size) && font == rhs.font;
|
||||
}
|
||||
|
||||
bool font_renderer_t::text_index_t::operator!=(const font_renderer_t::text_index_t& rhs) const
|
||||
{
|
||||
return !(rhs == *this);
|
||||
}
|
||||
}
|
|
@ -76,10 +76,13 @@ namespace blt::gfx
|
|||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
} while (true);
|
||||
#else
|
||||
for (const auto& texture : textures_to_load)
|
||||
for (const auto& [destination, texture] : textures_to_load)
|
||||
{
|
||||
BLT_DEBUG("Loading texture file %s", texture.path.c_str());
|
||||
loaded_textures.push_back(new texture_file(texture.path, texture.name));
|
||||
auto path = resource_prefix + texture.get_path();
|
||||
auto* file = new texture_file(path, texture.get_name(), texture.get_desired_channels());
|
||||
file->resize(texture.get_desired_width(), texture.get_desired_height());
|
||||
BLT_DEBUG("Loading texture file %s", path.c_str());
|
||||
destination.add(file);
|
||||
}
|
||||
textures_to_load.clear();
|
||||
#endif
|
||||
|
|
|
@ -136,7 +136,7 @@ namespace blt::gfx
|
|||
|
||||
// Setup Dear ImGui style
|
||||
ImGui::StyleColorsDark();
|
||||
//ImGui::Spectrum::StyleColorsSpectrum();
|
||||
// ImGui::Spectrum::StyleColorsSpectrum();
|
||||
ImGui::Spectrum::LoadFont();
|
||||
ImGui::SetupImGuiStyle(true, 1.0);
|
||||
|
||||
|
@ -157,7 +157,7 @@ namespace blt::gfx
|
|||
// Setup Platform/Renderer backends
|
||||
ImGui_ImplGlfw_InitForOpenGL(window_state.window, true);
|
||||
#ifdef __EMSCRIPTEN__
|
||||
ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback("#canvas");
|
||||
// ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback("#canvas");
|
||||
#endif
|
||||
ImGui_ImplOpenGL3_Init(glsl_version);
|
||||
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
|
||||
namespace ImGui::Spectrum
|
||||
{
|
||||
extern const unsigned int SourceSansProRegular_compressed_size = 149392;
|
||||
extern const unsigned int SourceSansProRegular_compressed_data[]; // defined later in the file
|
||||
// extern const unsigned int SourceSansProRegular_compressed_size;
|
||||
// extern const unsigned int SourceSansProRegular_compressed_data[]; // defined later in the file
|
||||
|
||||
void StyleColorsSpectrum()
|
||||
{
|
||||
|
@ -81,6 +81,7 @@ namespace ImGui::Spectrum
|
|||
io.FontDefault = font;
|
||||
}
|
||||
|
||||
const unsigned int SourceSansProRegular_compressed_size = 149392;
|
||||
const unsigned int SourceSansProRegular_compressed_data[149392 / 4] =
|
||||
{
|
||||
0x0000bc57, 0x00000000, 0x7ce00300, 0x00000400, 0x00010037, 0x000f0000, 0x00030080, 0x53414270, 0x5d1e6545, 0x2d0200bd,
|
||||
|
|
Loading…
Reference in New Issue