Comments (7)
A sufficient border for this exact purpose is already included. When used correctly, there is absolutely no possibility of this happening. I can help you figure out what you're doing wrong but there is no reason to add the feature you requested.
from msdf-atlas-gen.
interesting- thanks for the response!
I don't quite understand, though. in the extreme example, lets say you're rendering the font at approximately the texture resolution (lets say 80px/glyph). if you want a 100px border (using the alpha channel of mtsdf texture), how can that be accomplished?
NOTE: don't worry about scouring this huge information dump- I just figured it's better to include more info than less. :)
This is what the issue looks like in my case. See the right side of the 'k's, you can see a sliver of white from the adjacent glyph ('l').
I noticed when I bring the mesh very close to the camera, the artifact actually goes away. So this is it from a bit of distance (zoom in to see the artifact). In my case, the artifact is very visible when viewed through a Valve Index HMD.
Each glyph is 5 quads, one which minimally fits the character, and 4 extending the quad to the height of the row and the width of its spacing (so I can have black text with a thin white outline on a red background).
Here's my code that constructs the mesh (per character):
The vertexs are a vec2 for position, and a vec2 for UV. The "FontGlyph" struct just has "pl,pb,pr,pt" which are "place {left,bottom,right,top}", and correspond to where the glyph quad should be placed relative to the cursor and baseline, and "access {left,bottom,right,top}", aka its UVs. (and size(height) just multiplies the "place" values).
void DoRendererMenu::setChar(FontGlyph *charLut, char c, glm::vec2 key_p, float cursor, float key_h, float *mesh_x, float *cursor_x, CharVertexBufferObject *vertexs)
{
FontGlyph lut = charLut[c];
FontGlyph elut = charLut[' '];
float char_s = key_h*0.8;
lut.size(char_s);
float gw = lut.pr-lut.pl;
float gh = lut.pt-lut.pb;
float gl = cursor;
float gr = cursor+gw;
float gb = key_p.y-key_h*0.9+lut.pb;
if(gb < key_p.y-key_h) gb = key_p.y-key_h;
float gt = gb+gh;
*cursor_x = cursor+lut.advance;
float new_meshx = gr+(*cursor_x-gr)/2.0;
*mesh_x = new_meshx;
//top
vertexs[0] = {glm::vec2(key_p.x, key_p.y), glm::vec2(elut.al,elut.at)};
vertexs[1] = {glm::vec2(new_meshx,key_p.y), glm::vec2(elut.ar,elut.at)};
vertexs[2] = {glm::vec2(gl ,gt), glm::vec2(elut.al,elut.ab)};
vertexs[3] = {glm::vec2(gr ,gt), glm::vec2(elut.ar,elut.ab)};
//left
vertexs[4] = {glm::vec2(key_p.x ,key_p.y), glm::vec2(elut.al,elut.at)};
vertexs[5] = {glm::vec2(gl ,gt), glm::vec2(elut.ar,elut.at)};
vertexs[6] = {glm::vec2(key_p.x ,key_p.y-key_h), glm::vec2(elut.al,elut.ab)};
vertexs[7] = {glm::vec2(gl ,gb), glm::vec2(elut.ar,elut.ab)};
//glyph
vertexs[8] = {glm::vec2(gl,gt), glm::vec2(lut.al,lut.at)};
vertexs[9] = {glm::vec2(gr,gt), glm::vec2(lut.ar,lut.at)};
vertexs[10] = {glm::vec2(gl,gb), glm::vec2(lut.al,lut.ab)};
vertexs[11] = {glm::vec2(gr,gb), glm::vec2(lut.ar,lut.ab)};
//right
vertexs[12] = {glm::vec2(gr ,gt ), glm::vec2(elut.al,elut.at)};
vertexs[13] = {glm::vec2(new_meshx,key_p.y), glm::vec2(elut.ar,elut.at)};
vertexs[14] = {glm::vec2(gr ,gb ), glm::vec2(elut.al,elut.ab)};
vertexs[15] = {glm::vec2(new_meshx,key_p.y-key_h), glm::vec2(elut.ar,elut.ab)};
//bottom
vertexs[16] = {glm::vec2(gl ,gb ), glm::vec2(elut.al,elut.at)};
vertexs[17] = {glm::vec2(gr ,gb ), glm::vec2(elut.ar,elut.at)};
vertexs[18] = {glm::vec2(key_p.x ,key_p.y-key_h), glm::vec2(elut.al,elut.ab)};
vertexs[19] = {glm::vec2(new_meshx,key_p.y-key_h), glm::vec2(elut.ar,elut.ab)};
}
and here's the shader I use:
#version 450
#extension GL_KHR_vulkan_glsl : enable
#extension GL_ARB_separate_shader_objects : enable
#extension GL_EXT_multiview : enable
layout(set = 0, binding = 2) uniform sampler2D colorSampler;
layout(location = 0) in vec2 fragUV;
layout(location = 1) in vec3 fragNormal;
layout(location = 0) out vec4 outColor;
void main()
{
vec4 s = texture(colorSampler,fragUV);
float bsd = max(min(s.r,s.g), min(max(s.r,s.g), s.b));
float wsd = s.a;
float omega = 5.0;
float black = clamp(omega*(bsd-0.5)+0.5, 0.0, 1.0);
omega = 1.0;
float white = clamp(omega*(wsd-0.5)+0.5, 0.0, 1.0);
float omblack = 1.0-black;
float a = max(white,black);
outColor = vec4(mix(vec3(0.8,0.1,0.1),vec3(omblack,omblack,omblack),a),0.8+(a*0.2));
}
If there's anything weird about how I'm approaching this, I'd love to be pointed in a more sensible direction! Thanks for your help, and for your work on this library :)
from msdf-atlas-gen.
oh wow I'm just realizing that this might be a mipmapping issue. let me test that real quick
from msdf-atlas-gen.
That's quite likely if the artifact disappears when the camera is closer. Mipmapping should never be used with distance field textures as it doesn't help. However you need to increase the distance range significantly to be able to achieve anti-aliasing for minification. Also, looking at your texture, it is generated incorrectly due to overlapping parts in the font, so I would strongly recommend the latest version with Skia geometry preprocessing.
from msdf-atlas-gen.
Would you mind expanding on what you mean by "you need to increase the distance range significantly to be able to achieve anti-aliasing for minification"? Also, I've updated to the latest (1.1), and will try with that, but where do you see "overlapping parts in the font"?
Thanks for your help!
from msdf-atlas-gen.
To be able to achieve anti-aliasing using the signed distance retrieved from the distance field, you need to have a range of distances covering at least two screen-space pixels. Assuming the texture you posted is the one you're using, it is very much insufficient for this purpose at the minification level in your screenshots. You can increase the distance range coverage with the -pxrange
and -emrange
arguments. Specifically, pxrange
should be at least 2/s
where s
is the lowest display scale (on-screen size / texture size). I'd say the texture is also about 4 times bigger than it needs to be but that's beside the point (although it can become a problem as a larger texture size requires a greater pxrange
and at pxrange around 128 the smooth gradient starts breaking down in a typical 8-bit color encoding).
As for the overlapping parts, I mean self-intersecting paths. You can see that there are certain strange indentations near some corners in the generated atlas, which are due to the geometry of the glyphs being composed of overlapping segments, which is something that requires additional preprocessing. That was added in the latest version with the help of the Skia library. Before that, fonts like these were simply not supported (the preprocessing can be performed in a font editor software instead). Proper fonts have these self-intersections resolved and do not cause this issue. Sometimes it happens with certain accents or extended character sets like CJK, but this is the first time I've seen this with the base ASCII character set. A good example is the ampersand character in your image. Normally, it would be composed of three contours, seen below as red, green, and blue, but in your font, it is presumably realized as a single self-intersecting contour (bottom right).
from msdf-atlas-gen.
ah that's so helpful! thank you so much. issue closed
from msdf-atlas-gen.
Related Issues (20)
- Question: How do i make it output the atlas in a grid layout? HOT 8
- Pixel-perfect positioning of hardmask & softmask atlas HOT 5
- set inverseYAxis of Shape HOT 2
- json export does not respect charset HOT 3
- Feature request: add font name into json in metrics section HOT 2
- Border /Edge bleeding issue HOT 1
- Generated SDF looks too sharp? HOT 3
- The program crashes immediately HOT 1
- Export all glyphs instead of user-defined subset HOT 2
- Padding HOT 5
- Bottom-alligned text for a top-left aligned display
- Question:The padding parameter.
- New Release for Dynamic Atlas? HOT 3
- where is the width and height information at?
- does this build for linux? HOT 2
- How do I output all glyphs, but with the "unicode" field included in the JSON where appropriate? HOT 1
- Regression/difference between output from latest version and 1.2 HOT 1
- Why this all dlls are needed? HOT 2
- How can I solve these problem? HOT 11
- Font file not recognised HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from msdf-atlas-gen.