[Interest] Apply shader effect from QtGraphicalEffects to QSGGeometryNode?

Sletta Gunnar Gunnar.Sletta at digia.com
Tue Jun 11 09:18:13 CEST 2013

On Jun 10, 2013, at 8:56 PM, Mark <markg85 at gmail.com> wrote:

> Hi Gunnar,
> It seems like i really need to have you in all these questions ;)
> But not possible??
> Well then, lets ignore QtGraphicalEffects then since i'd like to get
> it done one way or the other.
> What is the easiest way to add a shader to a QSGGeometry(Node)?
> 1. I've seen QSGMaterialShader but i don't understand how that works.
> A working example of how to use that class would be very welcome.

If you just want to colorise a mesh, the way to do that is using a QSGMaterial (which includes the use of QSGMaterialShader and QSGMaterialType), but a much more straightforward way is to use the QSGSimpleMaterial which uses templates to autogenerate a lot of the boilerplate code the QSGMaterial API dictates. The "simplematerial" example illustrates how this is done.


There are several options for reaching [0], one option would be:

One way would be to create separate geometry nodes for 
- background gradient, you can create this with either a QSGGeometryNode + QSGVertexColorMaterial or modify the shader in the simple geometry example (which creates a differen type of gradient already)
- background grid using GL_LINES positioned at the correct offsets (details in the other mail)
- one node for the actual line, which is a GL_TRIANGLE_STRIP which you create by walking alone the line and expanding each line segment to a quad. If you want to cheat, there is a private (but exported) class in QtGui called QTriangulatingStroker which does exactly this for OpenGL paint engine. If you want the line to have nicer antialiasing, create a custom simple material and assign a second attribute to each vertex, letting the upper points be 0 and the lower points be 1. Pass this new attribute to the fragment shader as a varying and use it to decide opacity and voila, quick and easy high-quality antialiasing. 
- for the dropshadow, do exactly the same as for the line, except you can use the custom vertex shader to expand it a little bit more and change the opacity to make it a more blurry.
- for the gradient under the line, create a trianglestrip and colorize it according based on the y position in the fragment shader. 

> 2. Another way i see is taking the OpenGL direct approach following
> the "OpenGLunderQML example [1]. I can probably work of that example,
> but i really try to stay away from doing direct opengl interaction..

Raw OpenGL has its benefits, which is why the example and the feature is there, but I've been thinking that the primary usecase for OpenGLUnderQML is when you have a game/cad app running and QML is just the HUD controls. Using raw opengl for UI elements has the downside that you don't get any inherited clipping, transformation, nor opacity so things might be quite a bit more complicated to manage inside your UI.
> 3. A third possible way that i can think of is by throwing everything
> out and starting over in a very abstract manner. Making a bunch of
> small components (in C++) like:
> (note: this is still for the charting stuff [0])
> - 1 component to draw the background with a little more power then a
> Rectangle. However, if i choose this route i might as well use the
> QtGraphicalEffects for the added power (gradients) since that provides
> it.
> - 1 component for drawing a grid on top of the gradient.
> - 1 component for drawing a line where i probably only provide the
> data indicating where the line should be. Again i can use
> QtGraphicalEffects on top of this to add additional shadow. However, i
> find the default OpenGL line drawing stuff (even with multisampling)
> of a very very very poor rendering quality. I'm really thinking of
> using the "vase renderer" for drawing a way sharper line [2] Another
> note, this might also be very interesting for you to draw way sharper
> "scene graph fonts" which at the moment still look quite blurry at
> it's best under desktop environments.

The distancefield fonts are unhinted and this is why they look more blurry than native fonts (at least on windows and potentially linux). You can enable native rendering by sacrificing font scalability:

> - I'm stuck at how to animate the line as more data flows in..
> I hope you can advice me here in picking an option to go for. It's all
> quite a bit of work and all likely has the same end result. Right now
> i'm leaning towards option 3 where i was trying to go for option 1
> till this very moment.
> [0] http://i.stack.imgur.com/Zk2RG.png -- i try to make it look as
> crisp as this one

> [1] https://qt.gitorious.org/qt/qtdeclarative/trees/stable/examples/quick/scenegraph/openglunderqml
> [2] http://www.codeproject.com/Articles/226569/Drawing-polylines-by-tessellation
> On Mon, Jun 10, 2013 at 10:07 AM, Sletta Gunnar <Gunnar.Sletta at digia.com> wrote:
>> On Jun 8, 2013, at 11:33 PM, Mark <markg85 at gmail.com> wrote:
>>> Hi,
>>> Back when the graphical effects where first showcased in a blog i was
>>> already kinda scared that there would be no C++ interface to use them
>>> from the C++ side. Now i find myself in the position where i want to
>>> use the DropShadow element from that very same module in custom QML
>>> Scene Graph module and give a line a shadow.
>>> I kinda - very much - dislike copying the relavant parts of the
>>> DropShadow code and re-create that in C++..
>>> Is there a way that i can use DropShadow from the C++ side?
>> There is no way to do this using pure C++ API. You could construct it from c++ using QQmlComponent and set the source property by passing it the item that creates the geometry node.
>> cheers,
>> Gunnar
>>> Regards,
>>> Mark
>>> _______________________________________________
>>> Interest mailing list
>>> Interest at qt-project.org
>>> http://lists.qt-project.org/mailman/listinfo/interest

More information about the Interest mailing list