OpenGL着色器与着色器程序不链接

3

我正在尝试使用GLFW / GLEW添加着色器。

我遇到了一个错误,即这些着色器已经被加载但它们没有有效的对象代码。

这是我用于加载着色器的代码:

class SHADER {
public:

void LoadShaders(const char *vertexFile, const char *fragmentFile);

char *vertexShader;
char *fragmentShader;

private:

int Load(const char *filename, char*&shaderSource);
fstream file;
};

int SHADER::Load(const char *filename, char *&shaderSource) {
file.open(filename, ios::in);
if(file.is_open()) {
    file.tellg();
    file.seekg(0,ios::end);
    unsigned long len = file.tellg();
    file.seekg(ios::beg);

    if(len == 0 ) {
        return -2;
    } else {
        shaderSource = new char[len + 1];
        file.read(shaderSource,len);
        file.close();
        printf("%s\n",shaderSource);
    }
} else {
    return -1;
}
return 0;
}

void SHADER::LoadShaders(const char *vertexFile, const char *fragmentFile) {
int resultVertex = this->Load(vertexFile, vertexShader);
int resultFragment = this->Load(fragmentFile, fragmentShader);
if(resultVertex ==0 && resultFragment ==0) {
    printf("Shaders loaded succesfully.\n");
}
if(resultVertex == -2) {
    printf("VertexShader is empty!\n");
}
if(resultFragment == -2) {
    printf("FragmentShader is empty!\n");
}
if(resultVertex == -1) {
    printf("Unable to load VertexShader!\n");
}
if(resultFragment == -1) {
    printf("Unable to load FragmentShader!\n");
}
}

这是初始化着色器的代码:
SHADER Shaders;
GLhandleARB vertexShader, fragmentShader, shaderProgram;

Shaders.LoadShaders("vertexShader.vert","fragmentShader.frag");

const char* vertTemp = Shaders.vertexShader;
vertexShader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
glShaderSourceARB(vertexShader, 1, &vertTemp, NULL);
glCompileShaderARB(vertexShader);
traceShaderInfoLog(vertexShader);

const char* fragTemp = Shaders.fragmentShader;
fragmentShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
glShaderSourceARB(fragmentShader, 1, &fragTemp, NULL);
glCompileShaderARB(fragmentShader);
traceShaderInfoLog(fragmentShader);

delete[] Shaders.vertexShader;
delete[] Shaders.fragmentShader;

shaderProgram = glCreateProgramObjectARB();
glAttachObjectARB(shaderProgram,vertexShader);
glAttachObjectARB(shaderProgram,fragmentShader);
glLinkProgramARB(shaderProgram);
traceProgramInfoLog(shaderProgram);

glUseProgramObjectARB(shaderProgram);

这是vertexShader.vert和fragmentShader.frag文件:
void main(){
gl_Position = ftransform();
}
void main(){
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

当我打印日志时,遇到了错误。每次重新编译后,脚本末尾会出现一个非常奇怪的符号:

void main(){
    //gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
    gl_Position = ftransform();
}┘
void main(){
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}♣
Shaders loaded succesfully.
Vertex shader was successfully compiled to run on hardware.

Fragment shader failed to compile with the following errors:
ERROR: 0:3: error(#132) Syntax error: '<' parse error
ERROR: error(#273) 1 compilation errors.  No code generated

Fragment shader(s) were not successfully compiled before glLinkProgram() was called.
Link failed.

奇怪的字符来自于未能附加NUL(您留出了空间,但从未写入最后一个字符)。在Shader :: LOAD中,设置shaderSource [len] = 0; - Ben Voigt
当我设置shaderSource[len] = 0;时,我仍然会得到奇怪的字符。 - tversteeg
2个回答

4
您的Load函数很可能是问题所在:签名应该如下所示。
int SHADER::Load(const char *filename, char *&shaderSource) // Note the &

为了快速修复,您正在该函数中分配内存并重新分配指针 - 您只将源加载到该地址 - 但它永远不会离开该函数。

编译器很可能由于内存被零初始化(您是否在调试中运行此代码?)而获得空字符串,并且不会失败,因为有时这是可以的。但链接器注意到实际上没有任何要链接的代码!


此外,您不应该释放您使用new[]分配的内存 - 您应该使用delete[]。而您的SHADER类的析构函数就是释放内存的地方 - 同时,在构造函数中将这些指针初始化为零。或者更好的方法是:使用std::string或任何优秀的字符串类。 - ltjax
谢谢,但现在我遇到了这个错误:`着色器已成功加载。 顶点着色器已成功编译以在硬件上运行。 片段着色器无法编译,出现以下错误: 错误:0:3:错误(#132)语法错误:'<'解析错误 错误:错误(#273)1个编译错误。没有生成代码在调用glLinkProgram()之前,片段着色器未能成功编译。 链接失败。` - tversteeg
2
你是否按照Ben Voigt的建议添加了零终止字符?在打印源代码时,你是否仍然有那些奇怪的字符?当像这样读取文件时,你应该在open()中添加std::ios::binary标志,以便tellg按预期工作。 - ltjax

0

当连接失败时,检索链接错误日志,其中可能有其他线索。

请参见{{link1:glGetProgramInfoLog}}。


我使用了glGetProgramInfoLog,结果出现了ERROR: error(#280) Not all shaders have valid object code ERROR: error(#280) Not all shaders have valid object code - tversteeg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接