[Interest] How to use QSGSimpleTextureNode?

Gunnar Sletta gunnar at sletta.org
Wed Nov 5 18:39:21 CET 2014


On 04 Nov 2014, at 23:20, Nuno Santos <nunosantos at imaginando.pt> wrote:

> Gunnar,
> 
> I have implemented a really basic node for text rendering on scene graph based on my previous approach but adapter to Qt API. The setup code is below. I can already draw a string on OpenGL but the characters are not smooth at small sizes with a pixel font. With a non pixel font, even at big sizes the size is not appearing really good. I was wondering if the method i’m performing and/or setup is the most appropriated. 

Is the contents of the QImage correct? If so, then your geometry data is probably using the wrong texture or vertex coordinates. If you want to dig through Qt's sources, the equivalent bits for drawing pixel-by-pixel (aka Text.NativeRendering) fonts in Qt are in the qtdeclarative/src/quick/scenegraph/qsgdefaultglyphnode* files.

cheers,
Gunnar

PS, always use QImage::Format_ARGB32_Premultiplied or QImage::Format_RGBA32_Premultiplied when working alpha images with QPainter. It is faster than ARGB32.



> 
> Below is the code that draws the glyphs in a texture and then transfers it to a texture. I haven’t included the texture mapping into the vertices but I don’t think that’s the origin of the problem. I would love to have your feedback on this. 
> 
> Regards,
> 
> Nuno
> 
> // setup
> 
> QFont font("OpenSans");
> font.setPixelSize(32);
> QFontMetrics fm(font);
> QPainter painter;
> 
> _gs = qMax(fm.maxWidth(), fm.height());
> _ts = nextPowerOfTwo(_gs)*16;
> 
> for (int i=0; i<256; i++)
> {
>     _glyphs[i].character = (char) i;
>     _glyphs[i].pos.setX((i % 16) * _gs);
>     _glyphs[i].pos.setY((i / 16) * _gs);
>     _glyphs[i].rect = fm.boundingRect(QChar((char) i));
> }
> 
> QImage image(_ts, _ts, QImage::Format_ARGB32);
> 
> painter.begin(&image);
> //painter.setRenderHint(QPainter::TextAntialiasing, false);
> //painter.setRenderHint(QPainter::SmoothPixmapTransform, false);
> painter.setFont(font);
> painter.setBrush(QBrush(Qt::white));
> painter.setPen(QPen(Qt::black));
> 
> for (int i=0; i<256; i++)
> {
>     painter.drawText(_glyphs[i].pos,QString(_glyphs[i].character));
> }
> 
> painter.end();
> 
> _geometry.setDrawingMode(GL_TRIANGLES);
> setGeometry(&_geometry);
> 
> QSGTexture *t = window->createTextureFromImage(image);
> 
> //t->setMipmapFiltering(QSGTexture::Nearest);
> //t->setFiltering(QSGTexture::Linear);
> 
> _material.setTexture(t);
> setMaterial(&_material);
> 
> On 03 Nov 2014, at 21:11, Gunnar Sletta <gunnar at sletta.org> wrote:
> 
>> 
>> On 03 Nov 2014, at 17:15, Nuno Santos <nunosantos at imaginando.pt> wrote:
>> 
>>> Hi,
>>> 
>>> I’m trying to render text on scene graph. My strategy consists in creating a texture with all the glyphs and then draw a specific subset of the texture for each glyph. I have already done this for iOS and Android native API’s but now, i’m porting my app to Qt/Qml and need to do it on scene graph.
>> 
>> If you already have working GL code, then maybe QQuickWindow::beforeRendering() is a more straightforward way to get this working? You only need to go through scene graph API if you want this to interact with a QML UI.
>> 
>>> 
>>> My new node is extending QSGSimpleTextureNode. The code below is just for the most basic test purpose. 
>> 
>> QSGSimpleTextureNode only supports drawing a textured quad. If you want to draw a bunch of glyphs on one node (like a word or a sentence), you probably want to use a QSGGeomtryNode with TexturedPoint2D as attribute set combined with a QSGTextureMaterial.
>> 
>>> 
>>> unsigned char *data = (unsigned char*) malloc(ts*ts*4);
>>> uint8_t * p = data;
>>> 
>>> for(int i=0; i<ts*ts; ++i)
>>> {
>>>   *p = 0; ++p;
>>>   *p = 255; ++p;
>>>   *p = 255; ++p;
>>>   *p = 0; ++p;
>>> }
>>> 
>>> glGenTextures(1, &_texture);
>>> 
>>> glBindTexture(GL_TEXTURE_2D, _texture);
>>> 
>>> glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
>>> glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
>>> glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ts, ts, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
>> 
>> You create QSGTexture instances from a GL texture id with QQuickWindow::createTextureFromId(). If your texture has special needs, you can also subclass QSGTexture and reimplement the pure virtuals.
>> 
>>> 
>>> // how do I set data to the texture?
>>> setTexture()
>>> 
>>> free(data);
>>> 
>>> The essential question right now is how do I set my custom texture data to a texture? 
>>> 
>>> I have a Googled a lot about QSGSimpleTextureNode and QSGTexture but couldn’t find any clear example on how to do this.
>>> 
>>> Any thoughts?
>> 
>> There are several examples that show how the scene graph APIs work in the qtdeclarative/examples/quick/scenegraph folder. That is the place to start.
>> 
>> cheers,
>> Gunnar
>> 
>>> 
>>> Thanks,
>>> 
>>> Nuno Santos
>>> _______________________________________________
>>> Interest mailing list
>>> Interest at qt-project.org
>>> http://lists.qt-project.org/mailman/listinfo/interest
> 




More information about the Interest mailing list