使用OpenGL / GLSL的输入/输出块数据的奇怪行为

时间:2014-12-10 09:21:46

标签: opengl glsl shader fragment-shader vertex-shader

我在OpenGL / GLSL应用程序中实现了普通的映射着色器。为了计算片段着色器中的凹凸和阴影因子,我需要从顶点着色器发送一些数据,例如切线空间中的光方向和光场中的顶点位置,用于场景的每个光。所以要做的工作我需要声明2输出变量,如下面(顶点着色器):

#define MAX_LIGHT_COUNT 5

[...]

out vec4 ShadowCoords[MAX_LIGHT_COUNT]; //Vertex position in light space
out vec3 lightDir_TS[MAX_LIGHT_COUNT]; //light direction in tangent space

uniform int LightCount;

[...]

for (int idx = 0; idx < LightCount; idx++)
{
     [...]

     lightDir_TS[idx] = TBN * lightDir_CS;
     ShadowCoords[idx] = ShadowInfos[idx].ShadowMatrix * VertexPosition;

     [...]
}

在片段着色器中,由于以下输入声明,我恢复了这些变量:

in vec3 lightDir_TS[MAX_LIGHT_COUNT];
in vec4 ShadowCoords[MAX_LIGHT_COUNT];

其余代码对解释我的问题并不重要。

所以现在这里的结果是图像:

enter image description here

你可以看到,直到这里一切都好!

但是现在,为了简单起见,我想使用单个输出声明而不是2!因此,逻辑上的选择是使用如下的输入/输出数据块:

#define MAX_LIGHT_COUNT 5

[...]

out LightData_VS
{
    vec3 lightDir_TS;
    vec4 ShadowCoords;

} LightData_OUT[MAX_LIGHT_COUNT];

uniform int LightCount;

[...]

for (int idx = 0; idx < LightCount; idx++)
{
     [...]

     LightData_OUT[idx].lightDir_TS = TBN * lightDir_CS;
     LightData_OUT[idx].ShadowCoords = ShadowInfos[idx].ShadowMatrix * VertexPosition;

     [...]
}

在片段着色器中输入数据块:

in LightData_VS
{
    vec3 lightDir_TS;
    vec4 ShadowCoords;

} LightData_IN[MAX_LIGHT_COUNT];

但是这次当我执行我的程序时,我有以下显示:

enter image description here

正如您所看到的,镜面反射光与上面第一种情况不同!

但是我注意到我是否更换了这条线:

for (int idx = 0; idx < LightCount; idx++) //Use 'LightCount' uniform variable

通过以下方式:

for (int idx = 0; idx < 1; idx++) //'1' value hard coded

int count = 1;

for (int idx = 0; idx < count; idx++)

着色结果是正确的!

问题似乎来自于我在&#39;中使用统一变量的事实。条件。但是,当我在第一种情况下使用单独的输出变量时,这是有效的!

I checked: the uniform variable 'LightCount' is correct and equal to '1'; (I tried unsigned int data type without success and it's the same thing using a 'while' loop)

你怎么解释这样的结果?

我用:

OpenGL: 4.4.0 NVIDIA driver 344.75
GLSL: 4.40 NVIDIA via Cg compiler

我已经使用了输入/输出数据块而没有问题,但它不是数组,只是简单的块,如下所示:

[in/out] VertexData_VS
{
    vec3 viewDir_TS;
    vec4 Position_CS;
    vec3 Normal_CS;
    vec2 TexCoords;

} VertexData_[IN/OUT];

您是否认为在for条件中使用统一变量在循环中使用输入/输出数据块作为数组是不可能的?

更新

我尝试使用2 vec4(为了数据对齐,比如统一块(对于这种情况,数据需要在vec4上对齐))到数据结构中,如下所示:

[in/out] LightData_VS
{
    vec4 lightDir_TS; //vec4((TBN * lightDir_CS), 0.0f);
    vec4 ShadowCoords;

} LightData_[IN/OUT][MAX_LIGHT_COUNT];

没有成功......

更新2

这是关于着色器编译日志的代码:

core::FileSystem file(filename);
std::ifstream ifs(file.GetFullName());

if (ifs)
{
    GLint compilationError = 0;
    std::string fileContent, line;
    char const *sourceCode;

    while (std::getline(ifs, line, '\n'))
        fileContent.append(line + '\n');
    sourceCode = fileContent.c_str();
    ifs.close();

    this->m_Handle = glCreateShader(this->m_Type);

    glShaderSource(this->m_Handle, 1, &sourceCode, 0);
    glCompileShader(this->m_Handle);
    glGetShaderiv(this->m_Handle, GL_COMPILE_STATUS, &compilationError);

    if (compilationError != GL_TRUE)
    {
        GLint errorSize = 0;
        glGetShaderiv(this->m_Handle, GL_INFO_LOG_LENGTH, &errorSize);
        char *errorStr = new char[errorSize + 1];
        glGetShaderInfoLog(this->m_Handle, errorSize, &errorSize, errorStr);
        errorStr[errorSize] = '\0';
        std::cout << errorStr << std::endl;
        delete[] errorStr;
        glDeleteShader(this->m_Handle);
    }
}

关于程序日志的代码:

GLint errorLink = 0;

glGetProgramiv(this->m_Handle, GL_LINK_STATUS, &errorLink);

if (errorLink != GL_TRUE)
{
    GLint sizeError = 0;

    glGetProgramiv(this->m_Handle, GL_INFO_LOG_LENGTH, &sizeError);
    char *error = new char[sizeError + 1];
    glGetShaderInfoLog(this->m_Handle, sizeError, &sizeError, error);
    error[sizeError] = '\0';
    std::cerr << error << std::endl;
    glDeleteProgram(this->m_Handle);
    delete[] error;
}

不幸的是,我没有任何错误记录!

0 个答案:

没有答案