Fixed artifacts on toolbar and gizmobar icons showing up when changing screen or toolbar scale factors

This commit is contained in:
Enrico Turri 2020-01-07 12:40:03 +01:00
parent bea82a4501
commit 5b2e2fe7b3
5 changed files with 123 additions and 5 deletions

View File

@ -68,4 +68,8 @@
// Enable using Y axis of 3Dconnexion devices as zoom
#define ENABLE_3DCONNEXION_Y_AS_ZOOM (1 && ENABLE_2_2_0_BETA1)
// Enable a modified version of the toolbar textures where all the icons are separated by 1 pixel
#define ENABLE_MODIFIED_TOOLBAR_TEXTURES (1 && ENABLE_2_2_0_BETA1)
#endif // _technologies_h_

View File

@ -168,12 +168,26 @@ bool GLTexture::load_from_svg_files_as_sprites_array(const std::vector<std::stri
if (filenames.empty() || states.empty() || (sprite_size_px == 0))
return false;
#if ENABLE_MODIFIED_TOOLBAR_TEXTURES
// every tile needs to have a 1px border around it to avoid artifacts when linear sampling on its edges
unsigned int sprite_size_px_ex = sprite_size_px + 1;
m_width = 1 + (int)(sprite_size_px_ex * states.size());
m_height = 1 + (int)(sprite_size_px_ex * filenames.size());
#else
m_width = (int)(sprite_size_px * states.size());
m_height = (int)(sprite_size_px * filenames.size());
#endif // ENABLE_MODIFIED_TOOLBAR_TEXTURES
int n_pixels = m_width * m_height;
#if ENABLE_MODIFIED_TOOLBAR_TEXTURES
int sprite_n_pixels = sprite_size_px_ex * sprite_size_px_ex;
int sprite_stride = sprite_size_px_ex * 4;
#else
int sprite_n_pixels = sprite_size_px * sprite_size_px;
int sprite_bytes = sprite_n_pixels * 4;
int sprite_stride = sprite_size_px * 4;
#endif // ENABLE_MODIFIED_TOOLBAR_TEXTURES
int sprite_bytes = sprite_n_pixels * 4;
if (n_pixels <= 0)
{
@ -211,7 +225,12 @@ bool GLTexture::load_from_svg_files_as_sprites_array(const std::vector<std::stri
float scale = (float)sprite_size_px / std::max(image->width, image->height);
#if ENABLE_MODIFIED_TOOLBAR_TEXTURES
// offset by 1 to leave the first pixel empty (both in x and y)
nsvgRasterize(rast, image, 1, 1, scale, sprite_data.data(), sprite_size_px, sprite_size_px, sprite_stride);
#else
nsvgRasterize(rast, image, 0, 0, scale, sprite_data.data(), sprite_size_px, sprite_size_px, sprite_stride);
#endif // ENABLE_MODIFIED_TOOLBAR_TEXTURES
// makes white only copy of the sprite
::memcpy((void*)sprite_white_only_data.data(), (const void*)sprite_data.data(), sprite_bytes);
@ -231,7 +250,11 @@ bool GLTexture::load_from_svg_files_as_sprites_array(const std::vector<std::stri
::memset((void*)&sprite_gray_only_data.data()[offset], 128, 3);
}
#if ENABLE_MODIFIED_TOOLBAR_TEXTURES
int sprite_offset_px = sprite_id * (int)sprite_size_px_ex * m_width;
#else
int sprite_offset_px = sprite_id * sprite_size_px * m_width;
#endif // ENABLE_MODIFIED_TOOLBAR_TEXTURES
int state_id = -1;
for (const std::pair<int, bool>& state : states)
{
@ -250,6 +273,23 @@ bool GLTexture::load_from_svg_files_as_sprites_array(const std::vector<std::stri
// applies background, if needed
if (state.second)
{
#if ENABLE_MODIFIED_TOOLBAR_TEXTURES
float inv_255 = 1.0f / 255.0f;
// offset by 1 to leave the first pixel empty (both in x and y)
for (int r = 1; r <= sprite_size_px; ++r)
{
int offset_r = r * sprite_size_px_ex;
for (int c = 1; c <= sprite_size_px; ++c)
{
int offset = (offset_r + c) * 4;
float alpha = (float)output_data.data()[offset + 3] * inv_255;
output_data.data()[offset + 0] = (unsigned char)(output_data.data()[offset + 0] * alpha);
output_data.data()[offset + 1] = (unsigned char)(output_data.data()[offset + 1] * alpha);
output_data.data()[offset + 2] = (unsigned char)(output_data.data()[offset + 2] * alpha);
output_data.data()[offset + 3] = (unsigned char)(128 * (1.0f - alpha) + output_data.data()[offset + 3] * alpha);
}
}
#else
for (int i = 0; i < sprite_n_pixels; ++i)
{
int offset = i * 4;
@ -259,13 +299,22 @@ bool GLTexture::load_from_svg_files_as_sprites_array(const std::vector<std::stri
output_data.data()[offset + 2] = (unsigned char)(output_data.data()[offset + 2] * alpha);
output_data.data()[offset + 3] = (unsigned char)(128 * (1.0f - alpha) + output_data.data()[offset + 3] * alpha);
}
#endif // ENABLE_MODIFIED_TOOLBAR_TEXTURES
}
#if ENABLE_MODIFIED_TOOLBAR_TEXTURES
int state_offset_px = sprite_offset_px + state_id * sprite_size_px_ex;
for (int j = 0; j < (int)sprite_size_px_ex; ++j)
{
::memcpy((void*)&data.data()[(state_offset_px + j * m_width) * 4], (const void*)&output_data.data()[j * sprite_stride], sprite_stride);
}
#else
int state_offset_px = sprite_offset_px + state_id * sprite_size_px;
for (int j = 0; j < (int)sprite_size_px; ++j)
{
::memcpy((void*)&data.data()[(state_offset_px + j * m_width) * 4], (const void*)&output_data.data()[j * sprite_stride], sprite_stride);
}
#endif // ENABLE_MODIFIED_TOOLBAR_TEXTURES
}
nsvgDelete(image);

View File

@ -86,7 +86,35 @@ bool GLToolbarItem::update_enabled_state()
void GLToolbarItem::render(unsigned int tex_id, float left, float right, float bottom, float top, unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const
{
#if ENABLE_MODIFIED_TOOLBAR_TEXTURES
auto uvs = [this](unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) ->GLTexture::Quad_UVs
{
assert((tex_width != 0) && (tex_height != 0));
GLTexture::Quad_UVs ret;
// tiles in the texture are spaced by 1 pixel
float icon_size_px = (float)(tex_width - 1) / (float)Num_States;
float inv_tex_width = 1.0f / (float)tex_width;
float inv_tex_height = 1.0f / (float)tex_height;
// tiles in the texture are spaced by 1 pixel
float u_offset = 1.0f * inv_tex_width;
float v_offset = 1.0f * inv_tex_height;
float du = icon_size_px * inv_tex_width;
float dv = icon_size_px * inv_tex_height;
float left = u_offset + (float)m_state * du;
float right = left + du - u_offset;
float top = v_offset + (float)m_data.sprite_id * dv;
float bottom = top + dv - v_offset;
ret.left_top = { left, top };
ret.left_bottom = { left, bottom };
ret.right_bottom = { right, bottom };
ret.right_top = { right, top };
return ret;
};
GLTexture::render_sub_texture(tex_id, left, right, bottom, top, uvs(tex_width, tex_height, icon_size));
#else
GLTexture::render_sub_texture(tex_id, left, right, bottom, top, get_uvs(tex_width, tex_height, icon_size));
#endif // ENABLE_MODIFIED_TOOLBAR_TEXTURES
if (is_pressed())
{
@ -97,6 +125,7 @@ void GLToolbarItem::render(unsigned int tex_id, float left, float right, float b
}
}
#if !ENABLE_MODIFIED_TOOLBAR_TEXTURES
GLTexture::Quad_UVs GLToolbarItem::get_uvs(unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const
{
GLTexture::Quad_UVs uvs;
@ -110,14 +139,14 @@ GLTexture::Quad_UVs GLToolbarItem::get_uvs(unsigned int tex_width, unsigned int
float right = left + scaled_icon_width;
float top = (float)m_data.sprite_id * scaled_icon_height;
float bottom = top + scaled_icon_height;
uvs.left_top = { left, top };
uvs.left_bottom = { left, bottom };
uvs.right_bottom = { right, bottom };
uvs.right_top = { right, top };
return uvs;
}
#endif // !ENABLE_MODIFIED_TOOLBAR_TEXTURES
BackgroundTexture::Metadata::Metadata()
: filename("")

View File

@ -143,7 +143,9 @@ public:
void render(unsigned int tex_id, float left, float right, float bottom, float top, unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const;
private:
#if !ENABLE_MODIFIED_TOOLBAR_TEXTURES
GLTexture::Quad_UVs get_uvs(unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const;
#endif // !ENABLE_MODIFIED_TOOLBAR_TEXTURES
void set_visible(bool visible) { m_data.visible = visible; }
friend class GLToolbar;

View File

@ -838,8 +838,14 @@ void GLGizmosManager::render_background(float left, float top, float right, floa
void GLGizmosManager::do_render_overlay() const
{
#if ENABLE_MODIFIED_TOOLBAR_TEXTURES
std::vector<size_t> selectable_idxs = get_selectable_idxs();
if (selectable_idxs.empty())
return;
#else
if (m_gizmos.empty())
return;
#endif // ENABLE_MODIFIED_TOOLBAR_TEXTURES
float cnv_w = (float)m_parent.get_canvas_size().get_width();
float cnv_h = (float)m_parent.get_canvas_size().get_height();
@ -870,13 +876,34 @@ void GLGizmosManager::do_render_overlay() const
unsigned int icons_texture_id = m_icons_texture.get_id();
int tex_width = m_icons_texture.get_width();
int tex_height = m_icons_texture.get_height();
float inv_tex_width = (tex_width != 0) ? 1.0f / tex_width : 0.0f;
float inv_tex_height = (tex_height != 0) ? 1.0f / tex_height : 0.0f;
#if ENABLE_MODIFIED_TOOLBAR_TEXTURES
if ((icons_texture_id == 0) || (tex_width <= 1) || (tex_height <= 1))
return;
#if ENABLE_GIZMO_ICONS_NON_ACTIVABLE_STATE
float du = (float)(tex_width - 1) / (4.0f * (float)tex_width); // 4 is the number of possible states if the icons
#else
float du = (float)(tex_width - 1) / (3.0f * (float)tex_width); // 3 is the number of possible states if the icons
#endif // ENABLE_GIZMO_ICONS_NON_ACTIVABLE_STATE
float dv = (float)(tex_height - 1) / (float)(selectable_idxs.size() * tex_height);
// tiles in the texture are spaced by 1 pixel
float u_offset = 1.0f / (float)tex_width;
float v_offset = 1.0f / (float)tex_height;
#else
if ((icons_texture_id == 0) || (tex_width <= 0) || (tex_height <= 0))
return;
float inv_tex_width = (tex_width != 0) ? 1.0f / tex_width : 0.0f;
float inv_tex_height = (tex_height != 0) ? 1.0f / tex_height : 0.0f;
#endif // ENABLE_MODIFIED_TOOLBAR_TEXTURES
#if ENABLE_MODIFIED_TOOLBAR_TEXTURES
for (size_t idx : selectable_idxs)
#else
for (size_t idx : get_selectable_idxs())
#endif // ENABLE_MODIFIED_TOOLBAR_TEXTURES
{
GLGizmoBase* gizmo = m_gizmos[idx].get();
@ -887,6 +914,12 @@ void GLGizmosManager::do_render_overlay() const
int icon_idx = m_current == idx ? 2 : (m_hover == idx ? 1 : 0);
#endif // ENABLE_GIZMO_ICONS_NON_ACTIVABLE_STATE
#if ENABLE_MODIFIED_TOOLBAR_TEXTURES
float v_top = v_offset + sprite_id * dv;
float u_left = u_offset + icon_idx * du;
float v_bottom = v_top + dv - v_offset;
float u_right = u_left + du - u_offset;
#else
float u_icon_size = icons_size * inv_tex_width;
float v_icon_size = icons_size * inv_tex_height;
@ -894,6 +927,7 @@ void GLGizmosManager::do_render_overlay() const
float u_left = icon_idx * u_icon_size;
float v_bottom = v_top + v_icon_size;
float u_right = u_left + u_icon_size;
#endif // ENABLE_MODIFIED_TOOLBAR_TEXTURES
GLTexture::render_sub_texture(icons_texture_id, zoomed_top_x, zoomed_top_x + zoomed_icons_size, zoomed_top_y - zoomed_icons_size, zoomed_top_y, { { u_left, v_bottom }, { u_right, v_bottom }, { u_right, v_top }, { u_left, v_top } });
if (idx == m_current) {