kovacsmarcell / freetype-gl

Automatically exported from code.google.com/p/freetype-gl
Other
0 stars 0 forks source link

Subpixel not working #48

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
I checked out the source, compiled and looked at the subpixel demo. This demo 
did not show any color differences at all. (only greytone antialiasing). I then 
looked at the fragment shader and found several issues.

1: The resulting subpixel color is multiplied by the font color, in this case 
black, removing any color anyway.
2: The mixing of rgb code does not contain any usage of next, only previous and 
current
3: The vertex structure for the glyph | is only one pixel wide, which does not 
allow the fragment shader to do anything with the neighboring pixel.

Is there a newer version that rendered the screenshot on the mainpage? which 
correctly has subpixel AA.

Original issue reported on code.google.com by ove.la...@gmail.com on 25 Feb 2013 at 2:31

GoogleCodeExporter commented 9 years ago
1. You have to make sure Freetype has been compiled with subpixel rendering 
support (check for freetype2/freetype/config/ftoption.h and 
FT_CONFIG_OPTION_SUBPIXEL_RENDERING).

2. Yes, glyph is shifted in one direction only such that next is not used.

3. Not sure I get you point here.

Did you chek the gl-3.0 branch or main trunk ?

Nicolas

Original comment by Nicolas.Rougier@gmail.com on 25 Feb 2013 at 2:52

GoogleCodeExporter commented 9 years ago
Super response time :)
This issue is created on the basis of the trunk, but now I have also tried the 
gl3 branch, where I get an error when I run the demo "this demo requires 
freetype to be compiled with subpixel rendering." So you might be on to 
something.

1: I used the freetype which was placed in trunk/windows/freetype  .. which 
indeed did not have subpixel enabled.
2: Ok.. makes sorta sense.. 
3: When I changed the fragment shader the | character was only one pixel wide, 
which makes it impossible to draw something in the neighboring pixel.. But this 
is possibly mitigated by enabling the subpixel support in freetype.

Original comment by ove.la...@gmail.com on 25 Feb 2013 at 3:03

GoogleCodeExporter commented 9 years ago
I seem to have the same issue; see attached PNG of demo-subpixel compared to 
the one on the main page (zoom in and note the lack of any color).

I replaced the bundeled FreeType with the newest (2.4.11) compiled with 
FT_CONFIG_OPTION_SUBPIXEL_RENDERING enabeled.

I'm using MSVC2012 together with the newest commit (6a41a4f, Mar 08) from 
GitHub, and aside from choosing to compile demo-subpixel as C++ I had to change 
the definition of "makup_t markup" so it doesn't use the C99-only designated 
initializer.

(Oh, and as an aside, the "IF (ANT_TWEAK_BAR_FOUND)"-section in CMakeLists.txt 
doesn't work with MSVC12 (complains of a DLL not found). Seems to be because of 
the "EXECUTE_PROCESS" test-compilation. I simply removed it since it seemingly 
only effects demo-atb-agg.)

Original comment by cforf...@gmail.com on 18 Mar 2013 at 11:08

Attachments:

GoogleCodeExporter commented 9 years ago
It seems your output is correct. Text is shifted smoothly by .1 pixel, no ?

Original comment by Nicolas.Rougier@gmail.com on 29 Mar 2013 at 7:27

GoogleCodeExporter commented 9 years ago
Sure, but I believe (I'm not completely up on neither the terminology nor have 
any complete understanding of subpixel rendering, so I might be off base here) 
that is more an example of "gray-level anti-aliased glyphs", like referenced in 
the FreeType comment to enabling subpixel rendering, than actual subpixel 
rendering.

As I understand it -- and please correct me if I'm wrong -- subpixel rendering 
works as follows. Say you have two pixels surrounded by black. Physically on 
screen this could look like this:

   RGB|RGB

I.e., you have the subpixel RGB-components laid out sequentially. If we wanted 
a sharp white (necessarily) pixel-sized area, we could align it to the 
pixel-grid so it looks like this:

  111|000

Three fully lit RGB-components in a row = white to our eyes. Now, say we wanted 
to shift this area a bit to the right. Without subpixel rendering (so we're 
working at the pixel level only), we have two choices: either snap it to the 
physical pixels (it would remain sharp, but the spacing between other pixels 
would be wrong), or average the area between the two pixels it now covers, 
giving us two gray pixels (blurring the area we wanted to be white). Something 
like the latter is what it (visually) seems to me freetype-gl is doing at the 
moment.

However, with subpixel rendering we're aware of the pixel-components. 
Leveraging this, we can instead lay the pixels out like this:

   001|110

Physically this gives us a BRG-sequence of fully-lit components -- i.e. just as 
white and sharp as the 111|000 RGB-sequence to us, just shifted a bit. However, 
at the pixel level this would appear as a blue pixel followed by a yellow pixel 
-- this is why zooming in on the reference image shows these coloured pixels 
because, while it looks strange at the pixel level, at the physical screen 
subpixel-level it looks completely fine.

Now, as I've just realized, doing this using a texture atlas for the glyphs (as 
I assume freetype-gl is currently doing) might not be very straightforward at 
all, since I assume it only stores each glyph once -- while for correct 
subpixel rendering they could be subtly different depending on their position 
on screen (actually depending on their position relative to the pixel-grid). I 
can see the text.frag shader doing some fixup depending on the next and 
following pixel, and maybe something like this is enough for correct subpixel 
rendering but I have not idea.

Another option for seemingly guaranteed correct rendering is support for 
putting the actual text-string in a texture as rendered (with subpixels) by 
freetype. Of course, moving this texture (on screen) by by less than a full 
pixel, or resizing it, would destroy the effect but that would be the 
responsibility of the user. Seems like a good option for users valuing quality 
over performance, assuming it's not possible to get 100% correct subpixel 
rendering from the texture-atlas (while only storing each glyph once per 
font+size).

Original comment by cforf...@gmail.com on 29 Mar 2013 at 9:54

Attachments:

GoogleCodeExporter commented 9 years ago
Youre' right in your explanation of the subpixel rendering.

For freetype-gl however, there are two different things: subpixel rendering and 
subpixel positioning. Rendering is done by freetype and positioning is done by 
the fragment shader and hence we only need to store one glyph.

For the color fringes on the reference, it is actually wrong because I've been 
using some weird LCD transformation to limit the fringe and I just get the 
opposite effect it seems. Your result should be the reference since there are 
limited color fringes (but they are still present) while the shifting is here.

I'll change the screenshot on the webpage.

Hope that answer your questions.

Original comment by Nicolas.Rougier@gmail.com on 29 Mar 2013 at 10:14

GoogleCodeExporter commented 9 years ago
Looks like a confirmation of a subpixel rendering bug from issue 45.
With the most recent versions of both freetype-gl and FreeType, I receive 
exactly the same result as in the pixture `subpixel.png`.
Indeed, subpixel positioning is working, but subpixel rendering is not (text is 
antialiased instead). Subpixel rendering is not working in demo-lcd demo as 
well.

Also, have you changed this screenshot already? 

Original comment by wmam...@gmail.com on 2 Apr 2013 at 2:32

GoogleCodeExporter commented 9 years ago
What do you mean by test is antialiased ? (This is expected indeed).
Also, if you look closely at subpixel.png, you should see the text is not 
aligned to the vertical bar but shifts smoothly to the right. This is the 
expected output.

I just replace the screenshot with my own output.

Also, did you check  for freetype2/freetype/config/ftoption.h and 
FT_CONFIG_OPTION_SUBPIXEL_RENDERING ?

Original comment by vente.ma...@gmail.com on 2 Apr 2013 at 3:38

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
there are 3 render modes available in FT: FT_RENDER_MODE_MONO, 
FT_RENDER_MODE_NORMAL and FT_RENDER_MODE_LCD. Second one corresponds to 8-bit 
anti-aliased bitmaps.

> What do you mean by test is antialiased ? (This is expected indeed).

demo-lcd and demo-subpixel should both result in text being rendered with 
subpixel accuracy, i.e. using FT_RENDER_MODE_LCD. Screenshots from yesterday 
were compatible with that. The new screenshots use antialiased render mode 
instead. This is consistent with what I received back when I composed  issue 45 
, but is totally illogical with demo's names. Why would you name the demo 
program demo-lcd, if it used anti-aliased render mode? Also, subpixel 
positioning (demo-subpixel) is senseless when subpixel rendering is off - 
resulting text is very blurry.

> Also, if you look closely at subpixel.png, you should see the text is not 
aligned to the vertical bar but shifts smoothly to the right. This is the 
expected output.

Didn't I say "Indeed, subpixel positioning is working"?

> Also, did you check  for freetype2/freetype/config/ftoption.h and 
FT_CONFIG_OPTION_SUBPIXEL_RENDERING ?

And you? Did you check for it? Your screenshots are NOT using lcd/subpixel 
render mode!

Original comment by wmam...@gmail.com on 3 Apr 2013 at 11:27

GoogleCodeExporter commented 9 years ago
Sorry I got your point now. 

The "problem" is that freetype renders glyph (in LCD mode) as white over black 
background (255 = full lite pixel). So what do we do if the user wants to draw 
the glyph in another color, let's say red. What it the transformation that goes 
from the white subpixel RGB white version to the red ?

First screenshot came from the previous version (1.0, 
http://code.google.com/p/freetype-gl/source/browse/tags/1.0/demo-subpixel.c). 
I've been using OpenGL blending func (but I think it was only working for 
black).

  float alpha = 1;
  glBlendFunc( GL_CONSTANT_COLOR_EXT, GL_ONE_MINUS_SRC_COLOR );
  glEnable( GL_BLEND );
  glColor3f( alpha, alpha, alpha );
  glBlendColor( 1-alpha, 1-alpha, 1-alpha, 1 );

Now, the blending is done within the shader and I think this is the problem 
that needs to be fixed:

    vec3 color = pow( vec3(r,g,b), vec3(1.0/vgamma));
    gl_FragColor.rgb = color*gl_Color.rgb;
    gl_FragColor.a = (color.r+color.g+color.b)/3.0 * gl_Color.a;

In demo-subpixel, if you change the clear color to black and rewrite the three 
lines above as:

    vec3 color = vec3(r,g,b); 
    gl_FragColor.rgb = color;
    gl_FragColor.a = (color.r+color.g+color.b)/3.0 * gl_Color.a;

Then it works. I need to find the proper color transformation now.

Any idea ?

Original comment by Nicolas.Rougier@gmail.com on 3 Apr 2013 at 12:20

Attachments:

GoogleCodeExporter commented 9 years ago
I replaced the screenshot with the right one but I did not commit changes yet.

I can colorize the output with:

  glBlendFunc( GL_CONSTANT_COLOR_EXT,  GL_ONE_MINUS_SRC_COLOR );
  glBlendColor(r,g,b,1);

but this is for the whole vertex buffer. I would need to modify the blend color 
on a per-vertex basis and I do not know if this can be done since blending is 
made after fragment stage.

Original comment by Nicolas.Rougier@gmail.com on 3 Apr 2013 at 5:38

GoogleCodeExporter commented 9 years ago
I fixed the rendering bug.

Original comment by Nicolas.Rougier@gmail.com on 4 Apr 2013 at 9:59