Shaders not attaching properly when linking.

I’m coding my first shaders program thanks to a tutorial, the problem i am getting it’s that when using glGetProgramInfoLog for error checking, it pops an error saying “Link called without any attached shader objects” the problem is that i used glAttachShader both for vertex and fragment shaders, so it should not throw me that error, if i remove error checking program runs perfectly, but the “sprite” i created has no color (with shaders loaded it should be red), here’s the important parts of the code: GLSL_Program.cpp:


void GLSL_Program::compileShaders(const std::string& vertexShaderFilePath, const std::string& fragmentShaderFilePath) {
	_programID = glCreateProgram();
	
	GLuint _vertexShader, _fragmentShader;

	_vertexShader = glCreateShader(GL_VERTEX_SHADER);
	_fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

	compileShader(vertexShaderFilePath, _vertexShaderID);
	compileShader(fragmentShaderFilePath, _fragmentShaderID);
}

void GLSL_Program::linkShaders() {
	glAttachShader(_programID, _vertexShaderID);
	glAttachShader(_programID, _fragmentShaderID);

	glLinkProgram(_programID);

	glDetachShader(_programID, _vertexShaderID);
	glDetachShader(_programID, _fragmentShaderID);

	glDeleteShader(_vertexShaderID);
	glDeleteShader(_fragmentShaderID);
}

void GLSL_Program::compileShader(const std::string& filePath, GLuint shaderID) {
	std::ifstream vertexFile(filePath);

	std::string fileContents = "";
	std::string line;

	while (std::getline(vertexFile, line)) {
		std::getline(vertexFile, line);
		fileContents = fileContents + line + "/n";
	}
	vertexFile.close();

	const char* contentsPtr = fileContents.c_str();
	glShaderSource(shaderID, 1, &contentsPtr, nullptr);

	glCompileShader(shaderID);
}

MainGame.cpp (another class):


void MainGame::initSystems() {
(...)
initShaders();
}

void MainGame::initShaders() {
	_colorProgram.compileShaders("Shaders/colorShading.vert", "Shaders/colorShading.frag");
	_colorProgram.addAttribute("vertexPosition");
	_colorProgram.linkShaders();
}

And here are the shader files code: colorShading.vert:


#version 130

in vec2 vertexPosition;

void main() {
	gl_Position.xy = vertexPosition;
	gl_Position.z = 0.0;
	gl_Position.w = 1.0;
}

colorShading.frag:


#version 130

out vec3 color;

void main() {
	color = vec3(1.0, 0.0, 0.0);
}

In case any more code is requiered, just tell me and i will add it.

I tryied this page solution but it didn’t seemed to work.


	_vertexShader = glCreateShader(GL_VERTEX_SHADER);
	_fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
 
	compileShader(vertexShaderFilePath, _vertexShaderID);
	compileShader(fragmentShaderFilePath, _fragmentShaderID);

_vertexShader and _vertexShaderID are not the same variable. I assume the later is a member subobject of this class, but you never assigned a valid shader object to it. So the rest of the linking code doesn’t use the shader you created. And since _vertexShader is a local variable, it falls off the stack once the function returns.

Also:


	while (std::getline(vertexFile, line)) {
		std::getline(vertexFile, line);
		fileContents = fileContents + line + "/n";
	}

This is wrong in two ways. #1, you’re trying to read an entire file line by line. Please don’t do this.

#2: you’re doing it wrong. The while condition is executed each time through the loop, so it reads a line. The first line of the loop then reads another line, thus overwriting the previously read line.

So instead, read the entire file. Any of these methods will work.

Also, be advised: prefixing variables with _ in C++ is… not advised. The standard reserves identifiers that begin with an _ followed by a capital letter to the implementation; it is undefined behavior to create an identifier like _Foo. So while _vertexShader is itself fine because the first letter after _ is a lower-case letter, your naming convention is getting very close to that rule. If you want to identify member or local variables differently from parameters, it’s better to use a trailing _ or something than a prefix.

Thanks, i got it to work now.