使用QGLShaderProgram从Qt传递自定义类型(结构体)统一到GLSL
Passing custom type (struct) uniform from Qt to GLSL using QGLShaderProgram
我为光参数定义了一个结构体,它包含两个向量。该结构体在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
s,即"元组大小"。
根据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());
...
}
- 根据用户回答声明"Players"。用户选择玩家数量。播放器是结构体
- 结构体 S { int align; } 之间的区别;(struct 关键字后的名称)和 struct { int al
- C++ - 如何在结构向量中找到结构体一个成员的最大值?
- 包含 std::list 的结构体的 C++ 初始化
- 结构体和类的不同大小(),彼此具有相同的字段类型
- 如何使用结构体的向量数组?
- 如何使用结构体在C++中更改这些代码?
- 无法在 Mosquitto MQTT Broker 插件上访问结构体 mosquitto 的元素
- 我应该如何在C++中使用结构体解决输入失败的问题?
- Qsort() 比较结构体整数的总和
- 如何使用迭代器指向结构体c++的向量
- 在C++中使用链表的堆栈实现中,访问结构体headNode成员count和top会导致运行时错误
- 如何获取结构体成员的地址
- 创建结构体向量,表达式:向量下标超出范围
- boost::任何带有结构体和无符号整数
- 如何在构造函数中初始化结构体的动态数组?
- 只写结构体的某些字段
- C++ push_back() 一个结构体到一个向量中
- C++14 结构体上的统一初始化
- 使用QGLShaderProgram从Qt传递自定义类型(结构体)统一到GLSL