我为灯光参数定义了一个结构,它包含两个向量。结构在C ++和GLSL中以类似的方式定义(注意:QVector3D
封装3 float
s,而不是double
s):
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
应该表明每个数组元素使用原始浮点数组中的6个GLfloat
,即“元组大小”。
根据Qt文档,不应该使用6的元组大小(仅允许1,2,3,4)。另一方面,QGLShaderProgram允许传入最多4x4个条目的矩阵。 GLSL还允许结构中有超过4个浮点数的制服(according to this example)。
这导致了一个问题:
如何使用Qt将浮点数/向量的结构作为统一数组传递?如果使用Qt不可能,我将调用GL函数来执行此操作,但我对Qt感兴趣能方便地为我做这件事。
当然我还是试过上面的代码。它导致struct中的所有向量都设置为0。
当我在结构中删除第二个参数并使用3的元组大小时,代码仍然不起作用!但是,当在着色器中使用vec3
时(仍然是宿主程序中有一个QVector3D的结构,元组大小= 3),它可以工作。
所以问题似乎是自定义类型在OpenGL主机程序API中的处理方式不同,但Qt似乎不支持它。我目前使用两个统一的阵列(一个用于pos,一个用于强度)作为解决方法。
答案 0 :(得分:11)
Qt与此无关。
你无法传递 structs 的数组,就像它是 values 的数组一样。如果你有一个类型不是a basic type的统一数组,那么每个数组索引和该结构的每个成员都有一个separate uniform location with a separate uniform name。因此,您必须单独传递每个成员。
你必须这样做:
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);
等等。
或者您可以使用proper uniform block并免除所有这些。
答案 1 :(得分: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());
...
}