Gdy renderowany jest tekst oraz jakaś scena do tego np. kostka z oświetleniem w trybie pełnoekranowym albo desktopowym pełnoekranowym to tekst robi dziwne wywijasy. Trudno jest to uchwycić dlatego musiałem nagrać filmik.
W trybie okienkowym takie zjawisko nie występuje. Przestaje ono też występować gdy rozwinę jeden z Collapsing headers
jak na przykład Material
czy Light
, czy Cube
.
Scene jest pokazana dlatego, że bez niej praktycznie niewidoczny (albo w ogóle go nie ma) jest problem. Problem na pewno dotyczy tekstu. Robiłem test, w którym przestałem renderować tekst i od razu problem zniknął.
Tekst renderowany przy pomocy signed distance field
biblioteką freetype-gl
. Okno tworzone za pomocą SDL2
Sposób dodawania wierzchołków i uv wziąłem z przykładowych aplikacji od freetype-gl
, które można sobie zbuildować
void RenderData::DrawString(const std::string& text, const Vector2& position, uint color, float scale, const Font& font)
{
using namespace ftgl;
texture_font_t* ftFont = font.getFTFont();
float textSlot = FindTexture(font.getTexture().get());
Vector2 finalPosition = position;
for (const auto& c : text) {
AddGlyph(finalPosition, c, textSlot, color, scale, ftFont);
}
}
void RenderData::AddGlyph(Vector2& position, const char string, float textureSlot, uint color, float scale, texture_font_t* ftFont)
{
texture_glyph_t* glyph = texture_font_get_glyph(ftFont, &string);
if (glyph) {
if (string) {
position.x += texture_glyph_get_kerning(glyph, &string - 1) * scale;
}
float x0 = position.x + static_cast<float>(glyph->offset_x) * scale,
y0 = position.y + (ftFont->ascender + ftFont->descender - static_cast<float>(glyph->offset_y)) * scale,
x1 = x0 + static_cast<float>(glyph->width) * scale,
y1 = y0 + static_cast<float>(glyph->height) * scale,
u0 = glyph->s0,
v0 = glyph->t0,
u1 = glyph->s1,
v1 = glyph->t1;
//dodaje dane do vektora, który potem będzie przekazany do vbo - glBufferData
AddVertexData(Vector2(x0, y0), Vector2(u0, v0), color, textureSlot);
AddVertexData(Vector2(x0, y1), Vector2(u0, v1), color, textureSlot);
AddVertexData(Vector2(x1, y1), Vector2(u1, v1), color, textureSlot);
AddVertexData(Vector2(x1, y0), Vector2(u1, v0), color, textureSlot);
//Dodaje elementy pod wzór kwadratu
//index + 0; index + 1; index + 2; index + 2; index + 3; index + 0
//do vektora elementów, który potem jest dodawany do ebo - glBufferData
AddRectElements();
position.x += glyph->advance_x * scale;
position.y += glyph->advance_y * scale;
}
}
//Jeden draw call może mieć 32 tekstury, więc sprawdzam czy już są 32 tekstury, jeśli są to dodaje draw call
float RenderData::FindTexture(Texture* t)
{
float result = 0.0f;
bool found = false;
for (uint i = 0; i < texture.size(); ++i) {
if (texture[i] == t) {
result = static_cast<float>(i + 1);
found = true;
break;
}
}
if (!found) {
const int maxTexturePerDrawCall = 32;
if (texture.size() >= maxTexturePerDrawCall ) {
AddDrawCall();
Clear();
}
texture.push_back(t);
result = static_cast<float>(texture.size());
}
return result;
}
Font::Font(const std::string& name, const std::string& filename, float size)
: name(name), filename(filename), size(size)
{
FTAtlas = ftgl::texture_atlas_new(512, 512, 1);
FTFont = ftgl::texture_font_new_from_file(FTAtlas, size, filename.c_str());
FTFont->rendermode = RENDER_SIGNED_DISTANCE_FIELD;
TextureParameters parameters = { RED, TextureFilter::LINEAR, LINEAR, CLAMP_TO_EDGE };
texture = texture->Create(512, 512, parameters);
texture->setData(FTAtlas->data);
}
#version 460 core
layout (location = 0) out vec4 f_color;
layout(location = 1) uniform float width;
layout(location = 2) uniform float edge;
layout(location = 5) uniform sampler2D u_textureSampler[32];
in vec2 te_uv;
in vec4 te_color;
in float te_textID;
void main()
{
float finalAlpha = 1.0f;
if(te_textID > 0) {
int texID = int(te_textID - 0.5);
float distance = 1.0 - texture2D(u_textureSampler[texID], te_uv).r,
alpha = 1.0 - smoothstep(width, width + edge, distance);
finalAlpha = alpha;
}
f_color = vec4(te_color.rgb, te_color.a * finalAlpha);
}
Dlaczego tak się dzieje? W jaki sposób to naprawić?