glGetProgramIv 声称着色器链接失败,但 glGetProgramInfoLog 为空
glGetProgramIv claims that shader linking failed, but glGetProgramInfoLog is empty
我目前正在尝试用 OpenGl 和 C++ 编写一个基本的图形引擎。这样做时,OpenGl 的行为非常奇怪,没有明显的解释。它声称着色器编译失败,但随后拒绝给出任何类型的错误来解释原因。具体来说,当我调用 glGetProgramiv
时,returned 值为 0,但 glGetProgramInfoLog
给出一个空字符串¹。
这是一个最小的完整可验证示例:
#include <SDL2/SDL.h>
#include <GL/glew.h>
#include <sstream>
#include <stdexcept>
#include <fstream>
GLuint loadShader(const std::string &path, GLenum type);
int main(int argc, char *argv[]){
//show window & other housekeeping
SDL_Init(SDL_INIT_EVERYTHING);
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_Window *window = SDL_CreateWindow("test window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
SDL_GLContext glContext = SDL_GL_CreateContext(window);
SDL_GL_MakeCurrent(window, glContext);
GLenum c = glewInit();
if(c != GLEW_OK){
std::ostringstream sout;
sout << "Failed to initialize OpenGl: " << glewGetErrorString(c);
throw std::runtime_error(sout.str());
}
//**** -- BEGIN IMPORTANT BIT -- ****//
//This is where the shaders are loaded
//load shaders
GLuint vertexShader = loadShader("shader.vert", GL_VERTEX_SHADER);
GLuint fragmentShader = loadShader("shader.frag", GL_FRAGMENT_SHADER);
//create & link program
GLuint program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glLinkProgram(program);
//check for errors
GLint success;
glGetProgramiv(program, GL_LINK_STATUS, &success);
if(!success){
GLchar infoLog[512];
GLint size; //gives 0 when checked in debugger
glGetProgramInfoLog(program, 512, &size, infoLog);
throw std::runtime_error(std::string("Failed to link shader program: ") + infoLog);
}
//cleanup
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
//**** -- END IMPORTANT BIT -- ****//
//update loop
bool isClosed = false;
while(!isClosed){
SDL_GL_SwapWindow(window);
SDL_Event e;
while(SDL_PollEvent(&e)){
switch(e.type){
case SDL_QUIT:
isClosed = true;
break;
}
}
}
}
GLuint loadShader(const std::string &path, GLenum type){
//load file
std::ifstream fin(path);
std::string line, total = "";
while(std::getline(fin, line)){
total += (line + "\n");
}
//reformat source into OpenGl's ridiculous format
const char *cArray = total.c_str();
const char **pointerToCArray = &cArray;
//create shader
GLuint shader = glCreateShader(type);
glShaderSource(shader, 1, pointerToCArray, nullptr);
glCompileShader(shader);
//check for erros
GLint success;
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if(!success){
GLchar infoLog[512];
glGetShaderInfoLog(shader, 512, nullptr, infoLog);
throw std::runtime_error(std::string("Failed to compile shader: ") + infoLog);
}
}
MCVE testshader.vert:
#version 330 core
layout (location = 0) in vec3 position;
void main()
{
gl_Position = vec4(position.x, position.y, position.z, 1.0);
}
MCVE testshader.frag:
#version 330 core
out vec4 color;
void main()
{
color = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}
当我 运行 这除了 window 的短暂闪光外,我得到以下输出:
terminate called after throwing an instance of 'std::runtime_error'
what(): Failed to link shader program:
Aborted (core dumped)
补充说明:
- 我正在使用 Ubuntu 16.10 x64
- 我使用的是驱动程序版本为 375.39 的 Nvidia GTX 1070
- SDL 和 glew 版本分别是从
libsdl2-dev
和 libglew-dev
软件包安装的。我正在使用 pkg-config 来 link.
在解决此错误的研究过程中,我主要发现了各种论坛和 Whosebug 帖子,这些帖子在其他人的代码中发现了特定错误。 None 这些适用于我的代码,在发现此错误后,我将我的代码与 this 应该工作的示例进行了比较。此示例还在我的计算机上正确编译和 运行s,这排除了任何类型的配置错误。
¹:glGetProgramInfoLog
不可能对外部后果无所作为,并且 infoLog
数组碰巧在其第一个地址分配了一个空终止符,因为大小 return of glGetProgramInfoLog
returns 0 即使在调用 glGetProgramInfoLog
之前设置为不同的值。
我发现了问题:loadShader() 方法中缺少 return 语句。然而,正如我在尝试解决此问题时所经历的那样,这并没有帮助。因此,我建议任何未来阅读本文的人找到一个工作示例(即 this 一个),它做的事情与您正在尝试做的事情相似,并且其代码的 copy/paste 逐渐变小进入你的(或反之亦然)做一种二进制搜索来找到你的错误。
我目前正在尝试用 OpenGl 和 C++ 编写一个基本的图形引擎。这样做时,OpenGl 的行为非常奇怪,没有明显的解释。它声称着色器编译失败,但随后拒绝给出任何类型的错误来解释原因。具体来说,当我调用 glGetProgramiv
时,returned 值为 0,但 glGetProgramInfoLog
给出一个空字符串¹。
这是一个最小的完整可验证示例:
#include <SDL2/SDL.h>
#include <GL/glew.h>
#include <sstream>
#include <stdexcept>
#include <fstream>
GLuint loadShader(const std::string &path, GLenum type);
int main(int argc, char *argv[]){
//show window & other housekeeping
SDL_Init(SDL_INIT_EVERYTHING);
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_Window *window = SDL_CreateWindow("test window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
SDL_GLContext glContext = SDL_GL_CreateContext(window);
SDL_GL_MakeCurrent(window, glContext);
GLenum c = glewInit();
if(c != GLEW_OK){
std::ostringstream sout;
sout << "Failed to initialize OpenGl: " << glewGetErrorString(c);
throw std::runtime_error(sout.str());
}
//**** -- BEGIN IMPORTANT BIT -- ****//
//This is where the shaders are loaded
//load shaders
GLuint vertexShader = loadShader("shader.vert", GL_VERTEX_SHADER);
GLuint fragmentShader = loadShader("shader.frag", GL_FRAGMENT_SHADER);
//create & link program
GLuint program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glLinkProgram(program);
//check for errors
GLint success;
glGetProgramiv(program, GL_LINK_STATUS, &success);
if(!success){
GLchar infoLog[512];
GLint size; //gives 0 when checked in debugger
glGetProgramInfoLog(program, 512, &size, infoLog);
throw std::runtime_error(std::string("Failed to link shader program: ") + infoLog);
}
//cleanup
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
//**** -- END IMPORTANT BIT -- ****//
//update loop
bool isClosed = false;
while(!isClosed){
SDL_GL_SwapWindow(window);
SDL_Event e;
while(SDL_PollEvent(&e)){
switch(e.type){
case SDL_QUIT:
isClosed = true;
break;
}
}
}
}
GLuint loadShader(const std::string &path, GLenum type){
//load file
std::ifstream fin(path);
std::string line, total = "";
while(std::getline(fin, line)){
total += (line + "\n");
}
//reformat source into OpenGl's ridiculous format
const char *cArray = total.c_str();
const char **pointerToCArray = &cArray;
//create shader
GLuint shader = glCreateShader(type);
glShaderSource(shader, 1, pointerToCArray, nullptr);
glCompileShader(shader);
//check for erros
GLint success;
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if(!success){
GLchar infoLog[512];
glGetShaderInfoLog(shader, 512, nullptr, infoLog);
throw std::runtime_error(std::string("Failed to compile shader: ") + infoLog);
}
}
MCVE testshader.vert:
#version 330 core
layout (location = 0) in vec3 position;
void main()
{
gl_Position = vec4(position.x, position.y, position.z, 1.0);
}
MCVE testshader.frag:
#version 330 core
out vec4 color;
void main()
{
color = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}
当我 运行 这除了 window 的短暂闪光外,我得到以下输出:
terminate called after throwing an instance of 'std::runtime_error'
what(): Failed to link shader program:
Aborted (core dumped)
补充说明:
- 我正在使用 Ubuntu 16.10 x64
- 我使用的是驱动程序版本为 375.39 的 Nvidia GTX 1070
- SDL 和 glew 版本分别是从
libsdl2-dev
和libglew-dev
软件包安装的。我正在使用 pkg-config 来 link.
在解决此错误的研究过程中,我主要发现了各种论坛和 Whosebug 帖子,这些帖子在其他人的代码中发现了特定错误。 None 这些适用于我的代码,在发现此错误后,我将我的代码与 this 应该工作的示例进行了比较。此示例还在我的计算机上正确编译和 运行s,这排除了任何类型的配置错误。
¹:glGetProgramInfoLog
不可能对外部后果无所作为,并且 infoLog
数组碰巧在其第一个地址分配了一个空终止符,因为大小 return of glGetProgramInfoLog
returns 0 即使在调用 glGetProgramInfoLog
之前设置为不同的值。
我发现了问题:loadShader() 方法中缺少 return 语句。然而,正如我在尝试解决此问题时所经历的那样,这并没有帮助。因此,我建议任何未来阅读本文的人找到一个工作示例(即 this 一个),它做的事情与您正在尝试做的事情相似,并且其代码的 copy/paste 逐渐变小进入你的(或反之亦然)做一种二进制搜索来找到你的错误。