繁体   English   中英

使用QGLShaderProgram将自定义类型(结构)从Qt传递到GLSL

[英]Passing custom type (struct) uniform from Qt to GLSL using QGLShaderProgram

我为包含两个向量的光照参数定义了一个结构。 在C ++和GLSL中都以类似的方式定义了该结构(注意: QVector3D封装了3个float而不是double ):

C ++主机程序:

struct LightParameters {
    QVector3D pos;
    QVector3D intensity;
};

片段着色器:

struct LightParameters {
    vec3 pos;
    vec3 intensity;
};

在片段着色器中,我还定义了以下制服。 灯光的数量限制为8,因此统一数组的大小是恒定的(但实际上仅使用numLights ):

const int maxLights = 8;
uniform int numLights;
uniform LightParameters lights[maxLights];

在主机程序中,我定义了灯光并将它们传递给着色器( QGLShaderProgram ):

static const int maxLights = 8;
LightParameters lights[maxLights];

int numLights = 1;
lights[0].pos = {0, 1, 0};
lights[0].intensity = {1, 1, 1};

shaderProgram->bind();
shaderProgram->setUniformValue("numLights", numLights);
shaderProgram->setUniformValueArray("lights", reinterpret_cast<GLfloat*>(lights), maxLights, 6);
shaderProgram->release();

最后一个参数中的6应该指示每个数组元素使用原始float数组中的6个GLfloat ,也就是“ 元组大小 ”。

根据Qt文档,应该不可能使用6的元组大小(仅允许使用1、2、3、4)。 另一方面,QGLShaderProgram允许传入具有最多4x4条目的矩阵。 GLSL还允许其中包含超过4个浮点的制服结构( 根据此示例 )。

这导致了一个问题:

如何使用Qt将浮点数/向量的结构作为统一数组传递? 如果无法使用Qt,我将调用GL函数来执行此操作,但是我对Qt能否为我方便地执行此操作感兴趣。

当然我还是尝试了上面的代码。 结果将结构中的所有向量都设置为0。

当我将第二个参数放在结构中并使用元组大小3时,代码仍然无法正常工作! 但是,仅在着色器中使用vec3时(仍在主机程序中使用一个QVector3D的结构,元组大小= 3),它就可以工作。

因此,问题似乎在于自定义类型在OpenGL主机程序API中的处理方式有所不同,但Qt似乎不支持它。 我目前使用两个统一的数组(一个用于pos,一个用于强度)作为解决方法。

Qt与此无关。

就像它是的数组,你不能传递结构的阵列。 如果您有一个类型不是基本类型的统一数组,则每个数组索引和该结构的每个成员都具有一个单独的统一位置,并具有一个单独的统一名称 因此,你必须分别通过每一个成员。

您必须这样做:

shaderProgram->setUniformValue("lights[0].pos", lights[0].pos);
shaderProgram->setUniformValue("lights[0].intensity", lights[0].intensity);
shaderProgram->setUniformValue("lights[1].pos", lights[1].pos);
shaderProgram->setUniformValue("lights[1].intensity", lights[1].intensity);
shaderProgram->setUniformValue("lights[2].pos", lights[2].pos);
shaderProgram->setUniformValue("lights[2].intensity", lights[2].intensity);

依此类推。

或者,您可以使用适当的统一块并省去所有这些。

我使用模板功能:

template<class T> void setUniformArrayValue(QOpenGLShaderProgram *program,
                                       const QString& arrayName,
                                       const QString& varName,
                                       int index,
                                       const T& value)
{
    const char* name = QString("%1[%2].%3")
            .arg(arrayName)
            .arg(index)
            .arg(varName)
            .toStdString().c_str();
    program->setUniformValue(name, value);
}

并在程序中:

for (int i = 0; i < m_lights.size(); i++) {
    setUniformArrayValue<QColor>(program, "lights", "ambient", i, m_lights[i].ambient());
    ...
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM