使用QGLShaderProgram将自定义类型(struct)制服从Qt传递到GLSL [英] Passing custom type (struct) uniform from Qt to GLSL using QGLShaderProgram

查看:599
本文介绍了使用QGLShaderProgram将自定义类型(struct)制服从Qt传递到GLSL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I defined a struct for light parameters which contains two vectors. The struct is defined in both C++ and GLSL in an analogous way (note: QVector3D encapsulates 3 floats, not doubles):

C ++主机程式

struct LightParameters {
    QVector3D pos;
    QVector3D intensity;
};

碎片着色器

struct LightParameters {
    vec3 pos;
    vec3 intensity;
};

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

In the fragment shader, I also define the following uniforms. The numbers of lights is limited to 8, so the uniform array has a constant size (but only numLights are actually used):

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

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

In the host program, I define the lights and pass them to the shader (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,也就是<元组大小。

The 6 in the last parameter should indicate that each array element uses 6 GLfloats from the raw float array, aka "tuple size".

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

According to the Qt documentation, it should not be possible to use a tuple size of 6 (only 1, 2, 3, 4 are allowed). On the other side, QGLShaderProgram allows to pass in a matrix with up to 4x4 entries. GLSL also allows structs for uniforms which have more than 4 floats in them (according to this example).

这会导致以下问题:

如何传递浮点数/ vector作为一个统一的数组使用Qt?如果不可能使用Qt,我会调用GL函数来做到这一点,但我很感兴趣,如果Qt可以为我方便这样做。

How can I pass structs of floats / vectors as a uniform array using Qt? If it's not possible using Qt, I will call the GL function to do this, but I'm interested if Qt can do this for me conveniently.

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

Of course I tried the code above anyway. It results in all vectors in the struct being set to 0.

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

When I drop the second parameter in the struct and use a tuple size of 3, the code still does not work! However, when just using vec3 in the shader (still the struct with one QVector3D in the host program, tuple size = 3), it works.

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

So the problem seems to be that custom types are handled differently in the OpenGL host program API, but Qt doesn't seem to support it. I currently use two uniform arrays (one for the pos, one for the intensity) as a workaround.

推荐答案

不能传递 structs 数组,因为它是一个值的数组。如果您有一个统一的数组,其类型不是基本类型,则每个数组索引和该结构的每个成员有一个 独立的统一位置,其中包含单独的统一名称。因此,您必须分别传递每个成员

You cannot pass arrays of structs as though it were an array of values. If you have a uniform array who's type is not a basic type, then every array index and every member of that struct has a separate uniform location with a separate uniform name. Therefore, you must pass each member separately.

您必须这样做:

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

等等。

只需使用适当的统一封锁,并免除所有这些。

Or you could just use a proper uniform block and dispense with all of that.

这篇关于使用QGLShaderProgram将自定义类型(struct)制服从Qt传递到GLSL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆