[Interest] Using QSGMaterial & QSGMaterialShader with multiple shaders

Nuno Santos nuno.santos at imaginando.pt
Mon Feb 15 15:36:28 CET 2021


Hi,

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.

Thanks!

Nuno

VSMaterial::VSMaterial(QString source) :
    _source(source)
{
    setFlag(RequiresFullMatrixExceptTranslate, true);
    setFlag(Blending, true);
}

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

    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)
{
    Q_UNUSED(newEffect)

    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[] = {
        "vertex",
        "vertexColor",
        "vertexOffset",
        0
    };

    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/20210215/1ee499f1/attachment.html>


More information about the Interest mailing list