【问题标题】:OpenGL - Problems getting shaders to compileOpenGL - 让着色器编译的问题
【发布时间】:2012-07-21 07:37:32
【问题描述】:

终于解决了我的shader不适应编译失败的问题。

这是我的着色器加载例程。第一部分在着色器中读取:

void GLSLShader::LoadFromFile(GLenum whichShader, const string filename)
{   
    ifstream fp;

    // Attempt to open the shader
    fp.open(filename.c_str(), ios_base::in);

    // If the file exists, load it
    if(fp) 
    {
        // Copy the shader into the buffer
        string buffer(std::istreambuf_iterator<char>(fp), (std::istreambuf_iterator<char>()));

        // Debug output to show full text of shader
        errorLog.writeSuccess("Shader debug: %s", buffer.c_str());

        LoadFromString(whichShader, buffer);
    } 
    else 
    {
        errorLog.writeError("Could not load the shader %s", filename.c_str());
    }
}

将其加载到字符串中后,将其发送以进行加载:

void GLSLShader::LoadFromString(GLenum type, const string source) 
{
    // Create the shader
    GLuint shader = glCreateShader(type);

    // Convert the string
    const char * ptmp = source.c_str();
    glShaderSource(shader, 1, &ptmp, NULL);

    // Compile the shader
    glCompileShader(shader);

    // Check to see if the shader has loaded
    GLint status;
    glGetShaderiv (shader, GL_COMPILE_STATUS, &status);
    if (status == GL_FALSE) {
        GLint infoLogLength;
        glGetShaderiv (shader, GL_INFO_LOG_LENGTH, &infoLogLength);
        GLchar *infoLog= new GLchar[infoLogLength];
        glGetShaderInfoLog (shader, infoLogLength, NULL, infoLog);
        errorLog.writeError("could not compile: %s", infoLog);
        delete [] infoLog;
    }
    _shaders[_totalShaders++]=shader;
}

我得到调试输出“无法编译:”,错误缓冲区似乎是空的。在过去的 3 天里,这一直让我发疯。有人看到我的错误吗?

以下是非常简单的着色器:

#version 330

layout (location = 0) in vec4 position;
layout (location = 1) in vec4 color;

smooth out vec4 theColor;

void main()
{
    gl_Position = position;
    theColor = color;
}



#version 330

smooth in vec4 theColor;

out vec4 outputColor;

void main()
{
    outputColor = theColor;
}

更新

看起来由于某种原因,内存中的着色器末尾添加了垃圾。我不确定为什么。我已经尝试将它读入一个 char* 和一个字符串。这是输出:

<-!-> Shader: #version 330

layout (location = 0) in vec4 position;
layout (location = 1) in vec4 color;

smooth out vec4 theColor;

void main()
{
    gl_Position = position;
    theColor = color;
}
n
<-!-> Shader: #version 330

smooth in vec4 theColor;

out vec4 outputColor;

void main()
{
    outputColor = theColor;
}
nts/Resources

注意第一个着色器末尾的“n”和第二个着色器末尾的“nts/Resources”。知道为什么吗?

另一个更新

结尾的废话是由结尾的额外行引起的。我删除了它,它又恢复了输出正确的着色器文本。编译仍然没有运气。

我在这里不知所措。 Superbible 有大量未优化的库,我不需要。 Mac 似乎没有一个该死的像样的着色器编译器。我真的不介意它有多简单。它只需要与着色器一起工作。有人举个例子吗?

【问题讨论】:

  • 您是否尝试过使用 malloc 分配错误字符串?
  • 读得很快,我愿意打赌你的 OpenGL 实现错误地为 GL_INFO_LOG_LENGTH 返回零。尝试将其限制在合理的最小值(例如 256 字节)并使用它,只是为了好玩。从广义上讲,我的经验是,更模糊的 glGet*() 枚举器往往在实现之间以大约 50% 的可靠性工作。
  • 此外,当您在调试器中单步执行时,您是否正在验证从磁盘读取是否正确发生?
  • @user1118321 是的,着色器文本输出正确。可能它有额外的空间或其他东西。只是猜测。
  • @AndyRoss 我将缓冲区强制设置为 256,但仍然没有输出...

标签: c++ opengl shader


【解决方案1】:

您调用glShaderSource 时未提供源数组中每个字符串的长度。因此,假定提供的字符串以空字节 ('\0') 终止。您将文件读入内存的方式不会以额外的空字节终止着色器源。因此,GLSL 编译器会将着色器源代码末尾之外的内容读取到随机内存中,并在其中找到……垃圾。

解决方案:添加终止空字节,或提供着色器文本长度参数。

【讨论】:

  • 虽然你的回答听起来很合理,但考虑到他的着色器末尾的垃圾,我看不出他在哪里可以阅读垃圾。他将其读入std::string(不需要附加任何显式的NUL),然后使用c_str() 从中获取C 字符串,从而保证NUL 终止。
  • @ChristianRau:可能是有缺陷的 STL 实现。无论如何,无论是否存在空终止符,简单的解决方案都只是提供提供给 glShaderSource 的字符串的长度。无论如何都应该这样做。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多