Samuel

Widgets enter the third dimension: WolfenQt

Published Tuesday December 2nd, 2008 | by

Some people have been asking how to embed Qt painted content (and especially Qt widgets) in a 3d scene. As I’ve been wanting to do this ever since we added QTransform supporting fully projective transformations, I sat down and wrote a small example demonstrating these capabilities. With no further delay, I present WolfenQt:

Here’s a screenshot as well for the Youtube-challenged:

WolfenQt screenshot

A Wolfenstein like maze theme was chosen because of ease of implementation, you could of course embed a widget onto any 3d surface. The trick is to create a 3d transform mapping from a 2d plane (where the widget or other Qt drawn graphics resides) onto any quad in 3d space, and then do a perspective projection, before converting the 3d transform to a QTransform. Now, by making all the widgets and wall segments graphics items, you only need to use QGraphicsItem::setTransform() with the custom created transform and QGraphicsView will handle all event translation for you. The way the camera movement works is by recomputing and resetting every item’s transform on each frame. To avoid having to continuously redraw all the widgets if they’re not being updated, QGraphicsItem::setCacheMode(QGraphicsItem::ItemCoordinateCache) is the way to go.

I’ve embedded Qt’s media player demo to show the ability to embed videos in a QGraphicsView as tbastian blogged about just recently: Videos get pimped

I’ve also embedded the 3d .obj model viewer I blogged about earlier (Accelerate your widgets with OpenGL) to show how to mix in OpenGL content by setting up the correct projection and modelview matrices. Note that except from this 3d model everything else is drawn using QPainter with QTransform, both the walls, sprites, and widgets.

Now, this example might not be the most useful thing in the world, but it’s meant as a demonstration of how you can stretch the Qt API in new directions.

Want to play with the source? It’s available through our gitweb at http://labs.trolltech.com/gitweb?p=WolfenQt;a=summary

Note that the performance against Qt 4.5 is better than against Qt 4.4, so if you try it out you might want to use the 4.5 snapshots at the moment. For the very best performance run with the “-graphicssystem raster” option (So long and thanks for the blit!). Also, there seems to be some bugs regarding certain widgets not being shown on Windows/Mac. Left-clicking links in embedded QWebViews is also broken at the moment.

40 Comments


Posted in Graphics Dojo, Graphics Items, Graphics View, KDE, Labs, Qt, Qt Concurrent, Qt Script, WebKit

Translucent widgets on X11

Published Tuesday September 23rd, 2008 | by

When running an X11 compositing manager it’s possible to have translucent widgets by using 32 bit visuals, also known as ARGB visuals. We don’t use these visuals by default in Qt because we’ve seen some driver issues which cause buggy rendering and widgets containing garbage pixels when first being shown, as well as generic slow-downs in some cases. However, we’re now adding conditional ARGB visuals to top-level widgets that are non-opaque, i.e. either have the Qt::WA_NoSystemBackground attribute set or have a transparent or semi-transparent background color specified in the palette. This means that the ARGB visuals will be opt-in instead of being forced onto every Qt application.

What this all means that in 4.5 you’ll be able to have nice translucent Qt widgets on your Linux desktop without any hassle, as long as you have a compositing manager running (which should be easy to enable on newer distributions). Of course, this wouldn’t be a proper graphics dojo post without a nice and shiny example, so I’ve cooked up an example which puts some nice chrome buttons inside a graphics view, and does a fancy animation when you click on the buttons. Here’s a screenshot:

Translucent widget example

Translucent widget video capture

To play with the source and try the example out for yourself, do “svn checkout svn://labs.trolltech.com/svn/graphics/dojo/glossygradients”. You’ll have to wait for the snapshots to be back online to get the translucency effect though :)

9 Comments


Posted in Graphics Dojo, KDE

Subpixel antialiasing on X11

Published Monday September 1st, 2008 | by

The last week I looked at some issues regarding Qt’s font rendering on X11, triggered by some bug reports comparing Qt 4′s font rendering to Qt 3′s and GTK’s font rendering, specifically when subpixel antialiasing is enabled. When rendering fonts with subpixel antialiasing Qt asks Freetype to render into an alpha mask that is three times wider than the desired glyph size (or taller in the case of a vertical LCD display). We then convert this alpha mask into an ARGB mask based on subpixel ordering and a smoothing filter. The smoothing filter is necessary to avoid color fringes; without it the glyphs would look like this:

Text without smoothing filter

With the default Qt 4 smoothing filter the fonts instead look like this (slight improvement, don’t you think?):

Text with smoothing filter

After doing some digging I found out that we changed the smoothing filter in the transition from Qt 3 to Qt 4 to use an interpixel as opposed to intrapixel filter. Interpixel means we do the smoothing on the subpixels directly, ignoring pixel boundaries, which is arguably more correct from a technical perspective. However, since Qt 4 was released, Freetype has added support for doing subpixel rendering and filtering itself, along with several settings for which filter to use. In Qt 4.5 we will use Freetype’s filtering if available, and thus honor the lcdfilter setting in font config. Note that the filtering we use in Qt 4.4 and earlier is pretty much the same as Freetype’s default filtering, but unlike before we now also support the other filtering settings. For Qt 4.5 we’ve also fixed an issue where we’d ignore the “slight” and “medium” hinting options in font config, leaving only “full” or “none” as the real options.

One of our goals was to make Qt 4 applications with QGtkStyle have the same font rendering as native GNOME applications, but apparently there’s a known issue in GNOME/Cairo/GTK that makes Cairo use the legacy filter as soon as medium or full hinting is enabled in the GNOME font settings dialog: https://bugs.launchpad.net/ubuntu/+source/fontconfig/+bug/200707

Gnome font settings dialog - hinting

As the legacy smoothing filter looks really ugly with certain fonts and/or slight hinting there is no way we want to use it by default in Qt, but if you really want Qt 4′s fonts to be rendered as in Qt 3, you can enable the legacy subpixel filtering as described on http://johan.kiviniemi.name/blag/2008/01/12/ubuntu-hardy-fonts/ (note it seems you might have to use the value “legacy” or “lcdlegacy” instead of “lcdfilterlegacy” depending on your system). Note that this can cause severe color fringes with certain fonts, while making other fonts crisper. This is how the font above looks with the legacy filter and full hinting:

Text with legacy smoothing filter

With the “slight” hinting option however it turns quite ugly (note the color fringes):

Text with legacy smoothing filter and slight hinting

To sum up, in Qt 4.5 we should honor more of the font config settings, including lcd filter and hinting style. However, unless you explicitly change the LCD filter or hinting style things should look basically the same as in Qt 4.4. By tweaking the LCD filter and hinting settings it should be possible to get Qt applications with QGtkStyle to look even closer to native on GNOME, though hopefully the configuration issues on GNOME will be fixed eventually and you won’t have to change anything to achieve this. We could of course try to mimic GNOME’s behavior in Qt, but as long as there are open issues regarding this in Gtk/Cairo it doesn’t make sense to change Qt’s behavior.

Note: all the screenshots in this article were taken on an LCD monitor with horizontal RGB subpixel ordering, and will probably look quite ugly on other display types.

3 Comments


Posted in KDE, Qt

Old school effect: the radial blur

Published Friday August 1st, 2008 | by

For this episode of the graphics dojo I’ve implemented the classic radial blur effect. The core radial blur effect is implemented with per-pixel manipulation, which Qt lets us do quite elegantly using the QImage class. The final dojo example uses the radial blur effect in combination with scrolling text drawn using QPainter to create a nice visual impression. Below is a screenshot of the effect as well as a recording:

Radial blur screenshot

Radial blur movie capture

As usual, the source code is available from the SVN repository: svn checkout svn://labs.trolltech.com/svn/graphics/dojo/radialblur

2 Comments


Posted in Graphics Dojo, Qt

Accelerate your widgets with OpenGL

Published Friday June 27th, 2008 | by

To breathe some new life into the graphics dojo, here’s an example of how to put widgets on top of an OpenGL scene using QGraphicsView. By leveraging the synergy (tounge in cheek) of the OpenGL module and graphics view’s in 4.4 new widget capabilities, the long lacking feature of putting widgets in OpenGL becomes possible. All that’s needed is to set a QGLWidget as viewport on the graphics view, override QGraphicsScene::drawBackground() to do the OpenGL rendering, and add widgets and other graphics items to the graphics scene as usual. The result can be seen in the screenshot below, which shows a simple obj-model viewer application written in just a couple of hundred lines of code:

Widgets on top of an OpenGL scene

The source code is available by “svn checkout svn://labs.trolltech.com/svn/graphics/dojo/modelviewer”. Have fun!

Update (8 Feb 2010): Latest version of source code with some new patches is available at http://qt.gitorious.org/qt-labs/modelviewer

11 Comments


Posted in Graphics Dojo, Graphics Items, Graphics View, Qt

Rasterizing dragons

Published Friday August 31st, 2007 | by

I’ve been working on a new rasterizer to replace the Freetype rasterizer for aliased painting in the raster paint engine, which is used on Windows and when rendering to a QImage. The new rasterizer is scheduled to be part of Qt 4.4, and is already available in the snapshots.

The performance of rasterizing various paths with QRasterizer compared to the Freetype rasterizer can bee seen in the following figure:

Freetype rasterizer vs QRasterizer

And the same results in table form:

Freetype QRasterizer Improvement
A – Plain rectangle 25773.2 37174.72 1.44
B – Rotated rectangle 1 23201.86 27247.96 1.17
C – Rotated rectangle 2 23041.47 28735.63 1.25
D – Rect dash stroke 276.24 1754.39 6.35
E – Rect dot stroke 87.95 826.45 9.4
F – Ellipse 3558.72 6944.44 1.95
G – Ellipse dash stroke 141.64 1282.05 9.05
H – Ellipse dot stroke 83.54 800 9.58
I – Short text path 14285.71 17241.38 1.21
J – Long text path 1683.5 1930.5 1.15
K – Random path size 5 24523.81 30294.12 1.24
L – Random path size 50 778.15 1098.13 1.41
M – Random rects (5) 25750 39615.38 1.54
N – Random rects (50) 324.81 753.21 2.32

Note: the numbers are for generating spans only, not filling. The benchmark used to measure these results can be downloaded from here: rasterizerbench.tar.gz

These numbers are already quite impressive, but where the new rasterizer really shines is for rasterizing complex paths with a lot of elements and potentially many self intersections. I’ve created an example which generates a path representing the Dragon Curve fractal. A screenshot from the application is shown below:

Dragon Curve (fractal) rendered using QRasterizer

At the highest detail setting the path (which is a round-cap/round-join stroke of the dragon curve) contains 507913 path elements. In this specific case the frame rate is approximately 36 times higher with the new rasterizer (filling included) :)

The example is available for download from here: dragoncurve.tar.gz

Note: the new rasterizer only affects primitive rendering (polygons, paths, ellipses, strokes, etc), and does not replace the Freetype rasterizer for plain font rendering.

7 Comments


Posted in Qt