-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
OpenGL Labels #72
OpenGL Labels #72
Conversation
- added quads on future label positions that stay the same size regardless of camera position and always face the camera
- Labels are now fully done in the shader
- added quads on future label positions that stay the same size regardless of camera position and always face the camera
- Labels are now fully done in the shader
- separated code into nucleus / gl_engine - only one draw call for all labels and implemented instancing
- svg icon below the label
- unicode char in string to integer list (correct unicode decoding) - only render characters that are needed (until now we rendered chars 32-223 on the ascii table, now we can specify each char individually) - characters now contain an outline
- occlusion culling - distance fadeout - code structure refactoring
- improved label fadeout
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
very nice changes. i'm super happy that we have much improved labels now.
in general i like the code, there are some minor code style issues detailed in the comments.
I'll push some changes to radix very soon, because currently address sanitizer is broken. they'll also enable warnings (just fix your own).
Workflow:
update your labels branch, the changes will be automatically forwarded to this pull request. this also means, that you should not mix in the changes from the vector labels (create an extra branch). then click on request review in this pull request.
In addition, AddressSanitizer shows me the following issue (i don't think it's the possible leak i mentioned below):
=================================================================
==64331==ERROR: AddressSanitizer: heap-use-after-free on address 0x7f15601c4278 at pc 0x55fa84a63e2e bp 0x7f1553d012b0 sp 0x7f1553d012a0
READ of size 1 at 0x7f15601c4278 thread T4 (QSGRenderThread)
#0 0x55fa84a63e2d in ttSHORT /home/madam/Documents/work/tuw/alpinemaps/renderer_labels/extern/stb_slim/src/stb_slim/stb_truetype.h:1287
#1 0x55fa84a63e2d in stbtt_ScaleForPixelHeight /home/madam/Documents/work/tuw/alpinemaps/renderer_labels/extern/stb_slim/src/stb_slim/stb_truetype.h:2662
#2 0x55fa84a4dec6 in nucleus::MapLabel::create_text_meta(std::unordered_map<int, nucleus::MapLabel::CharData const, std::hash<int>, std::equal_to<int>, std::allocator<std::pair<int const, nucleus::MapLabel::CharData const> > > const&, stbtt_fontinfo const*, std::vector<int, std::allocator<int> >&, float&) /home/madam/Documents/work/tuw/alpinemaps/renderer_labels/nucleus/map_label/MapLabel.cpp:75
#3 0x55fa84a4dec6 in nucleus::MapLabel::init(std::unordered_map<int, nucleus::MapLabel::CharData const, std::hash<int>, std::equal_to<int>, std::allocator<std::pair<int const, nucleus::MapLabel::CharData const> > > const&, stbtt_fontinfo const*) /home/madam/Documents/work/tuw/alpinemaps/renderer_labels/nucleus/map_label/MapLabel.cpp:45
#4 0x55fa84a7ea8a in nucleus::MapLabelManager::init() /home/madam/Documents/work/tuw/alpinemaps/renderer_labels/nucleus/map_label/MapLabelManager.cpp:94
#5 0x55fa84a412db in gl_engine::MapLabelManager::init() /home/madam/Documents/work/tuw/alpinemaps/renderer_labels/gl_engine/MapLabelManager.cpp:32
#6 0x55fa849f4015 in gl_engine::Window::initialise_gpu() /home/madam/Documents/work/tuw/alpinemaps/renderer_labels/gl_engine/Window.cpp:147
#7 0x55fa847f3872 in TerrainRenderer::TerrainRenderer() /home/madam/Documents/work/tuw/alpinemaps/renderer_labels/app/TerrainRenderer.cpp:37
#8 0x55fa847dfbd5 in TerrainRendererItem::createRenderer() const /home/madam/Documents/work/tuw/alpinemaps/renderer_labels/app/TerrainRendererItem.cpp:101
#9 0x7f1573d6f7d0 in QQuickFramebufferObject::updatePaintNode(QSGNode*, QQuickItem::UpdatePaintNodeData*) (/home/madam/bin/Qt/6.6.1/gcc_64/lib/libQt6Quick.so.6+0x4337d0)
#10 0x7f1573bba81f in QQuickWindowPrivate::updateDirtyNode(QQuickItem*) (/home/madam/bin/Qt/6.6.1/gcc_64/lib/libQt6Quick.so.6+0x27e81f)
#11 0x7f1573bbb13b in QQuickWindowPrivate::updateDirtyNodes() (/home/madam/bin/Qt/6.6.1/gcc_64/lib/libQt6Quick.so.6+0x27f13b)
#12 0x7f1573bbeab3 in QQuickWindowPrivate::syncSceneGraph() (/home/madam/bin/Qt/6.6.1/gcc_64/lib/libQt6Quick.so.6+0x282ab3)
#13 0x7f1573d7723f (/home/madam/bin/Qt/6.6.1/gcc_64/lib/libQt6Quick.so.6+0x43b23f)
#14 0x7f1573d78663 (/home/madam/bin/Qt/6.6.1/gcc_64/lib/libQt6Quick.so.6+0x43c663)
#15 0x7f1573d795c6 (/home/madam/bin/Qt/6.6.1/gcc_64/lib/libQt6Quick.so.6+0x43d5c6)
#16 0x7f15718619dc (/home/madam/bin/Qt/6.6.1/gcc_64/lib/libQt6Core.so.6+0x2f29dc)
#17 0x7f15710a8ac2 in start_thread nptl/pthread_create.c:442
#18 0x7f157113a65f (/lib/x86_64-linux-gnu/libc.so.6+0x12665f)
0x7f15601c4278 is located 367224 bytes inside of 524288-byte region [0x7f156016a800,0x7f15601ea800)
freed by thread T4 (QSGRenderThread) here:
#0 0x7f1574105537 in __interceptor_free ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:127
#1 0x55fa84a7df46 in QArrayDataPointer<char>::~QArrayDataPointer() /home/madam/bin/Qt/6.6.1/gcc_64/include/QtCore/qarraydatapointer.h:104
#2 0x55fa84a7df46 in QByteArray::~QByteArray() /home/madam/bin/Qt/6.6.1/gcc_64/include/QtCore/qbytearray.h:521
#3 0x55fa84a7df46 in nucleus::MapLabelManager::create_font() /home/madam/Documents/work/tuw/alpinemaps/renderer_labels/nucleus/map_label/MapLabelManager.cpp:202
#4 0x55fa84a7e964 in nucleus::MapLabelManager::init() /home/madam/Documents/work/tuw/alpinemaps/renderer_labels/nucleus/map_label/MapLabelManager.cpp:91
#5 0x55fa84a412db in gl_engine::MapLabelManager::init() /home/madam/Documents/work/tuw/alpinemaps/renderer_labels/gl_engine/MapLabelManager.cpp:32
#6 0x55fa849f4015 in gl_engine::Window::initialise_gpu() /home/madam/Documents/work/tuw/alpinemaps/renderer_labels/gl_engine/Window.cpp:147
#7 0x55fa847f3872 in TerrainRenderer::TerrainRenderer() /home/madam/Documents/work/tuw/alpinemaps/renderer_labels/app/TerrainRenderer.cpp:37
#8 0x55fa847dfbd5 in TerrainRendererItem::createRenderer() const /home/madam/Documents/work/tuw/alpinemaps/renderer_labels/app/TerrainRendererItem.cpp:101
#9 0x7f1573d6f7d0 in QQuickFramebufferObject::updatePaintNode(QSGNode*, QQuickItem::UpdatePaintNodeData*) (/home/madam/bin/Qt/6.6.1/gcc_64/lib/libQt6Quick.so.6+0x4337d0)
previously allocated by thread T4 (QSGRenderThread) here:
#0 0x7f1574105887 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
#1 0x7f15717e1d34 in QArrayData::allocate(QArrayData**, long long, long long, long long, QArrayData::AllocationOption) (/home/madam/bin/Qt/6.6.1/gcc_64/lib/libQt6Core.so.6+0x272d34)
Thread T4 (QSGRenderThread) created by T0 here:
#0 0x7f15740a9685 in __interceptor_pthread_create ../../../../src/libsanitizer/asan/asan_interceptors.cpp:216
#1 0x7f157186144c in QThread::start(QThread::Priority) (/home/madam/bin/Qt/6.6.1/gcc_64/lib/libQt6Core.so.6+0x2f244c)
SUMMARY: AddressSanitizer: heap-use-after-free /home/madam/Documents/work/tuw/alpinemaps/renderer_labels/extern/stb_slim/src/stb_slim/stb_truetype.h:1287 in ttSHORT
Shadow bytes around the buggy address:
0x0fe32c0307f0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0fe32c030800: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0fe32c030810: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0fe32c030820: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0fe32c030830: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
=>0x0fe32c030840: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd[fd]
0x0fe32c030850: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0fe32c030860: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0fe32c030870: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0fe32c030880: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0fe32c030890: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==64331==ABORTING
nucleus/map_label/MapLabel.h
Outdated
|
||
namespace nucleus::map_label { | ||
#include "stb_slim/stb_truetype.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
replace with struct stbtt_fontinfo; and move the import to the cpp file
{ | ||
// create the final font bitmap (3 channels -> 1 for font; 1 for outline; the last channel is empty) | ||
const int channels = 3; | ||
m_font_bitmap = new uint8_t[m_font_atlas_size.width() * m_font_atlas_size.height() * channels]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please no raw new and delete. these are very C like. use RAII, which is how you should do things in C++ :)
a good replacement would be std::vector<uint8_t> + resize()
or, in this case, a nucleus::Raster<uint8_t> (you would have to add a resize and fill method)
const int channels = 3; | ||
m_font_bitmap = new uint8_t[m_font_atlas_size.width() * m_font_atlas_size.height() * channels]; | ||
// set everything to 0 | ||
memset(m_font_bitmap, 0, m_font_atlas_size.width() * m_font_atlas_size.height() * channels); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
memset is very c-like. please use c++. use e.g. std::fill
memset(m_font_bitmap, 0, m_font_atlas_size.width() * m_font_atlas_size.height() * channels); | ||
|
||
const int outline_bit_count = 4 * (m_font_outline.x - 1) * (m_font_outline.y - 1) + 2 * (m_font_outline.x - 1) + 2 * (m_font_outline.y - 1) + 1; | ||
int* outline_mask = new int[outline_bit_count]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here. please use std::vector
const auto font_init = stbtt_InitFont(&m_fontinfo, reinterpret_cast<const uint8_t*>(data.constData()), stbtt_GetFontOffsetForIndex(reinterpret_cast<const uint8_t*>(data.constData()), 0)); | ||
assert(font_init); | ||
|
||
uint8_t* temp_bitmap = new uint8_t[m_font_atlas_size.width() * m_font_atlas_size.height()]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here (no raw new and delete)
nucleus/map_label/MapLabel.cpp
Outdated
void MapLabel::init(const std::unordered_map<int, const MapLabel::CharData>& character_data, const stbtt_fontinfo* fontinfo) | ||
{ | ||
float offset_x = 0; | ||
float offset_y = -font_size / 2.0f + 75.0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this also converts float -> double -> float
nucleus/map_label/MapLabel.cpp
Outdated
float offset_x = 0; | ||
float offset_y = -font_size / 2.0f + 75.0; | ||
|
||
float uv_width_norm = 1.0f / 512.0f; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
constexpr
nucleus/map_label/MapLabelManager.h
Outdated
|
||
private: | ||
// list of all characters that will be available (will be rendered to the font_atlas) | ||
const std::string all_char_list = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789()[]{},;.:-_!\"§$%&/\\=+-*/#'~°^<>|@€´`öÖüÜäÄß"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this could be a static constexpr auto all_char_list
nucleus/map_label/MapLabelManager.h
Outdated
std::unordered_map<int, const MapLabel::CharData> m_char_data; | ||
|
||
stbtt_fontinfo m_fontinfo; | ||
uint8_t* m_font_bitmap; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no naked new and delete. i believe this one we are even leaking :)
you can use the address sanitizer to detect such issues (enable the cmake variable ALP_ENABLE_ADDRESS_SANITIZER, but you have to pull first)
// we are interpolating the far label according to importance | ||
float interpolatedFarLabelDistance = mix(farLabel0, farLabel1, importance); | ||
|
||
// apply "soft" distance scaling depending on near/far label values (if option is set as uniform) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the following gives me nicer results:
` // apply "soft" distance scaling depending on near/far label values (if option is set as uniform)
if(label_dist_scaling)
{
float dist_scale = 1.0 - ((dist - nearLabel) / (farLabel1 - nearLabel)) * 0.4f;
scale *= (dist_scale * dist_scale);
}
// importance based scaling
scale *= (importance + 1.5) / 2.5;
`
and with label_dist_scaling set to true
latest commit should address all the requested changes. |
closing pull request and reopening from main (as discussed in discord) |
No description provided.