5

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

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一个参数中的 应该指示每个数组元素使用GLfloat原始浮点数组中的 6 秒,即“元组大小”。

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

这就引出了一个问题:

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

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

当我在结构中删除第二个参数并使用 3 的元组大小时,代码仍然不起作用!但是,当仅vec3在着色器中使用时(仍然是主机程序中具有一个 QVector3D 的结构,元组大小 = 3),它可以工作。

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

4

2 回答 2

12

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);

等等。

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

于 2013-05-24T17:48:20.203 回答
0

我使用模板函数:

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());
    ...
}
于 2015-06-09T14:49:03.457 回答