How to pass QML array to OpenGL shader



  • Hello everyone,
    I am implementing an application using QML 3D, there is 3D scene in this application and you can move around in the scene.
    I am trying to pass an array of vectors from QML into fragment shader, but it doesn't work for me.

    I am using Scene3D QML type as the viewport into OpenGL scene.
    My project is implemented in really similar way as this example https://doc.qt.io/qt-5/qt3d-shadow-map-qml-example.html.
    I have scene with shadows and I need to have more than just one light in the scene.

    The important part is :
    My implementation of Effect in QML

    Effect {
    
        parameters: [
            Parameter { name: "lightViewProjection"; value: root.light.lightViewProjection },
            Parameter { name: "lightPosition"; value: 
    [Qt.vector3d(30.0, 100.0, 0.0), Qt.vector3d(-30.0, 100.0, 0.0)] },
            Parameter { name: "lightIntensity"; value: 
    [Qt.vector3d(0.5, 0.5, 0.5), Qt.vector3d(0.5, 0.5, 0.5)] },
            Parameter { name: "shadowMapTexture"; value: root.shadowTexture },
        ]
    
        techniques: [
            Technique {
                graphicsApiFilter {
                    api: GraphicsApiFilter.OpenGL
                    profile: GraphicsApiFilter.CoreProfile
                    majorVersion: 3
                    minorVersion: 2
                }
    
                renderPasses: [
    
                    RenderPass {
                        filterKeys: [ FilterKey { name: "pass"; value: "shadowmap" } ]
                        shaderProgram: ShaderProgram {
                            id: shader1
                            vertexShaderCode:   loadSource("qrc:/shaders/shaders/shadowmap.vert")
                            fragmentShaderCode: loadSource("qrc:/shaders/shaders/shadowmap.frag")
                        }
                        renderStates: [
                            PolygonOffset { scaleFactor: 4; depthSteps: 4 },
                            DepthTest { depthFunction: DepthTest.Less }
                        ]
                    },
    
                    RenderPass {
                        filterKeys: [ FilterKey { name: "pass"; value: "forward" } ]
                        shaderProgram: ShaderProgram {
                            vertexShaderCode:   loadSource("qrc:/shaders/shaders/myshader.vert")
                            fragmentShaderCode: loadSource("qrc:/shaders/shaders/myshader.frag")
                        }
                    }
                ]
            }
        ]
    }
    

    just important part of my fragment shader:

    uniform vec3 lightPosition [2];     // set from QML Effect
    uniform vec3 lightIntensity [2];    // set from QML Effect
    uniform sampler2DShadow shadowMapTexture;   // set from QML Effect
    

    The problem is the data are not loaded from QML to the shader when there is array.
    If I declare static values in the shader like this LightPosition[0] = vec3(10, 0, 20) and so on everything works.
    If I pass only one vector3d from QML and don't use array neither in shader, it works as well.

    Can someone help me how to pass array of vector3d from qml to shader?



  • Hi! Looking at quick3dparameter.cpp...

    void Quick3DParameterPrivate::setValue(const QVariant &value)
    {
        if (value.userType() == qjsValueTypeId) {
            QJSValue v = value.value<QJSValue>();
            if (v.isArray())
                QParameterPrivate::setValue(value.value<QVariantList>());
        } else {
            QParameterPrivate::setValue(value);
        }
    }
    

    ...to me, at least it looks as if the JS-to-Parameter-Item-part should work. So, before we start further investigations, one stupid question: what's your Qt version?



  • I am using Qt 5.7.1
    To store the value is called this function:

    void Quick3DParameterPrivate::setValue(const QVariant &value)
    

    or this one:

    void QParameterPrivate::setValue(const QVariant &v)
    {
        Qt3DCore::QNode *nodeValue = v.value<Qt3DCore::QNode *>();
        if (nodeValue != nullptr)
            m_backendValue = QVariant::fromValue(nodeValue->id());
        else
            m_backendValue = v;
        m_value = v;
    }
    

    As in the documentation is said that Parameter QML Type Instantiates QParameter.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.