首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用QGLShaderProgram将自定义类型(struct)从Qt传递到GLSL

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

Stack Overflow用户
提问于 2013-05-24 16:54:21
回答 2查看 14.3K关注 0票数 5

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

C++主机程序:

代码语言:javascript
运行
复制
struct LightParameters {
    QVector3D pos;
    QVector3D intensity;
};

片段着色器:

代码语言:javascript
运行
复制
struct LightParameters {
    vec3 pos;
    vec3 intensity;
};

在片段着色器中,我还定义了以下制服。光的数目限制在8,所以均匀阵列的大小是恒定的(但实际上只使用numLights ):

代码语言:javascript
运行
复制
const int maxLights = 8;
uniform int numLights;
uniform LightParameters lights[maxLights];

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

代码语言:javascript
运行
复制
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个GLfloats,也就是“元组大小”。

根据Qt文档,不应该使用6的元组大小(只允许1、2、3、4)。另一方面,QGLShaderProgram允许传递具有最多4x4项的矩阵。GLSL还允许有超过4个浮动的制服(根据这个例子)的结构。

这就引出了一个问题:

如何将浮点数/向量的结构作为一个统一数组传递给Qt?,如果不能使用Qt,我将调用GL函数来完成这个任务,但是如果Qt可以方便地为我做到这一点,我很感兴趣。

我当然试过上面的代码了。它将导致结构中的所有向量都被设置为0。

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

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-05-24 17:48:20

Qt和这件事无关。

不能像传递值数组一样传递结构数组。如果有一个类型不是基本类型的统一数组,那么每个数组索引和该结构的每个成员都有一个统一名称。因此,您必须分别传递每个成员。

你必须这样做:

代码语言:javascript
运行
复制
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);

以此类推。

或者,您可以使用一个适当均匀块并免除所有这些。

票数 13
EN

Stack Overflow用户

发布于 2015-06-09 14:49:03

我使用一个模板函数:

代码语言:javascript
运行
复制
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);
}

在该方案中:

代码语言:javascript
运行
复制
for (int i = 0; i < m_lights.size(); i++) {
    setUniformArrayValue<QColor>(program, "lights", "ambient", i, m_lights[i].ambient());
    ...
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16739993

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档