[Interest] Using QSGMaterial & QSGMaterialShader with multiple shaders

Laszlo Agocs laszlo.agocs at qt.io
Wed Feb 17 12:19:49 CET 2021

Hi Nuno,

Check your implementation of type(). It should return something unique for all the different 'source' values (i.e. for every different vertex+fragment shader combinations). Right now, with the same static type object is returns, VSMaterial::createShader() is only ever called once, so all instances of VSMaterial will use the same VSMaterialShader regardless of the different fragment shader code in 'source', which explains the effect you are seeing.

An example of a dynamic implementation of type() you are looking for can be found in ShaderEffect:

Best regards,

From: Interest <interest-bounces at qt-project.org> on behalf of Nuno Santos <nuno.santos at imaginando.pt>
Sent: Monday, February 15, 2021 3:36 PM
To: interestqt-project.org <interest at qt-project.org>
Subject: [Interest] Using QSGMaterial & QSGMaterialShader with multiple shaders


I’m trying to make a shader gallery using a GridView where the model is an array of shaders path.

Then, a custom QQuickView, instantiates a custom QSGGeometryNode with a material that extends QSGMaterial. The QSGMaterial creates the shader:

I’m having a problem though. All the items draw the first shader in the list. Shader A draws everything red, shader B draws everything blue.

If model = [A, B], the two items show as red, if I swap the model order to [B, A], the two items show blue.

I’ve added debug and there are classes being instantiated correctly for each item, and the right shader source is being used for each one, but it seems that only the first shader that is passed to the model seems to be loaded or active.

Is there any gotcha in the way QSGMateria and QSGMaterialShader are used?

Code for material and material shader are included below.



VSMaterial::VSMaterial(QString source) :



    setFlag(RequiresFullMatrixExceptTranslate, true);

    setFlag(Blending, true);


int VSMaterial::compare(const QSGMaterial *other) const



    return 0;


QSGMaterialType *VSMaterial::type() const


    static QSGMaterialType type;

    return &type;


QSGMaterialShader *VSMaterial::createShader() const


    return new VSMaterialShader(_source);


VSMaterialShader::VSMaterialShader(QString source)

    : QSGMaterialShader()


    setShaderSourceFile(QOpenGLShader::Vertex, QString(":/shaders/rectangle.vert"));

    setShaderSourceFile(QOpenGLShader::Fragment, source);


void VSMaterialShader::updateState(const QSGMaterialShader::RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)



    if (state.isOpacityDirty())

        program()->setUniformValue(m_opacityLoc, state.opacity());

    if (state.isMatrixDirty())

        program()->setUniformValue(m_matrixLoc, state.combinedMatrix());

    if (oldEffect == 0)


        // The viewport is constant, so set the pixel size uniform only once.

        QRect r = state.viewportRect();

        program()->setUniformValue(m_pixelSizeLoc, 2.0f / r.width(), 2.0f / r.height());


    VSMaterial *material = static_cast<VSMaterial*>(newEffect);

    program()->setUniformValue(_idPositionX, material->positionX);

    program()->setUniformValue(_idPositionY, material->positionY);


const char * const *VSMaterialShader::attributeNames() const


    static char const *const attributes[] = {






    return attributes;


void VSMaterialShader::initialize()


    m_matrixLoc = program()->uniformLocation("matrix");

    m_opacityLoc = program()->uniformLocation("opacity");

    m_pixelSizeLoc = program()->uniformLocation("pixelSize");

    _idPositionX = program()->uniformLocation("positionX");

    _idPositionY = program()->uniformLocation("positionY");


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20210217/6cf8c98d/attachment.html>

More information about the Interest mailing list