簡體   English   中英

使用QGLShaderProgram將自定義類型(結構)從Qt傳遞到GLSL

[英]Passing custom type (struct) uniform from Qt to GLSL using QGLShaderProgram

我為包含兩個向量的光照參數定義了一個結構。 在C ++和GLSL中都以類似的方式定義了該結構(注意: QVector3D封裝了3個float而不是double ):

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應該指示每個數組元素使用原始float數組中的6個GLfloat ,也就是“ 元組大小 ”。

根據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());
    ...
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM