GLSL program fails to link depending on their files' size - c++

I've a weird problem with GLSL shaders. My program seems to not launch or launch successfully depending on the size of my shader files. If I only write a few lines of code in shader files, the program works fine. For example, the program launches successfully with this much code:
vertex.vs:
#version 460 core
layout (location = 0) in vec2 coords;
uniform float u_time;
out vec3 result_color;
void main()
{
vec3 colorA = vec3(0.514f, 0.179f, 0.900f);
vec3 colorB = vec3(0.895f, 0.359f, 0.488f);
gl_Position = vec4(coords, 0.0f, 1.0f);
result_color = colorA;
}
fragment.fs:
#version 460 core
in vec3 result_color;
out vec4 color;
void main()
{
color = vec4(result_color, 1.0f);
}
If I add more code to any of my shader files it only launches about 50% of the time:
vertex.vs:
#version 460 core
layout (location = 0) in vec2 coords;
uniform float u_time;
out vec3 result_color;
// float wave(float x)
// {
// return min(2.0f - 2.0f * fract(x / 2.0f),
// 2.0f * fract(x / 2.0f));
// }
void main()
{
vec3 colorA = vec3(0.514f, 0.179f, 0.900f);
vec3 colorB = vec3(0.895f, 0.359f, 0.488f);
// float frequency = 15.0f;
// float y = wave(coords.x * frequency + cos(u_time) * 5.0f);
// float fr_y = fract(coords.y * frequency + u_time);
gl_Position = vec4(coords, 0.0f, 1.0f);
result_color = colorA;
}
Note that the code I added is commented out but still the error occurs. And the more code I add the less is the chance it works.
Here's the class I use to read shaders from files and create a shader program:
#include <iostream>
#include <fstream>
#include <sstream>
#include <glad/glad.h>
#include "shader_program.h"
ShaderProgram::ShaderProgram(std::string vertexShaderPath, std::string fragmentShaderPath)
{
std::ifstream vShaderFile;
std::ifstream fShaderFile;
std::stringstream vShaderStream;
std::stringstream fShaderStream;
vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
try
{
vShaderFile.open(vertexShaderPath);
vShaderStream << vShaderFile.rdbuf();
}
catch(std::ifstream::failure e)
{
std::cout << "ERROR: FAILED TO READ SHADER FILE: VERTEX SHADER" << std::endl;
}
try
{
fShaderFile.open(fragmentShaderPath);
fShaderStream << fShaderFile.rdbuf();
}
catch(std::ifstream::failure e)
{
std::cout << "ERROR: FAILED TO READ SHADER FILE: FRAGMENT SHADER" << std::endl;
}
const char* vertexShaderSource = vShaderStream.str().c_str();
const char* fragmentShaderSource = fShaderStream.str().c_str();
CreateShaderProgram(vertexShaderSource, fragmentShaderSource);
}
unsigned int ShaderProgram::GetProgram()
{
return program;
}
void ShaderProgram::CreateShaderProgram(const char* vertexShaderSource, const char* fragmentShaderSource)
{
program = glCreateProgram();
unsigned int vertexShader = CompileShader(GL_VERTEX_SHADER, vertexShaderSource);
unsigned int fragmentShader = CompileShader(GL_FRAGMENT_SHADER, fragmentShaderSource);
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glLinkProgram(program);
int linkingResult;
glGetProgramiv(program, GL_LINK_STATUS, &linkingResult);
if (linkingResult == GL_FALSE)
{
char infoLog[512];
glGetProgramInfoLog(program, 512, NULL, infoLog);
std::cout << "ERROR: FAILED TO LINK PROGRAM\n" << infoLog << std::endl;
}
}
unsigned int ShaderProgram::CompileShader(GLuint type, const char* source)
{
unsigned int shader = glCreateShader(type);
glShaderSource(shader, 1, &source, NULL);
glCompileShader(shader);
int compilationResult;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compilationResult);
if (compilationResult == GL_FALSE)
{
char infoLog[512];
glGetShaderInfoLog(shader, 512, NULL, infoLog);
std::cout << "ERROR: FAILED TO COMPILE SHADER: "
<< (type == GL_VERTEX_SHADER ? "VERTEX" : "FRAGMENT")
<< " SHADER\n" << infoLog << std::endl;
}
return shader;
}
The error message I get sometimes seems random. Most of the time it's this:
ERROR: FAILED TO LINK PROGRAM
Vertex shader(s) failed to link, fragment shader(s) failed to link.
Vertex link error: INVALID_OPERATION.
ERROR: error(#97) No program main found
fragment link error: INVALID_OPERATION.
ERROR: error(#97) No program main found
But sometimes it's about a syntax error which is nowhere to be found really:
ERROR: FAILED TO COMPILE SHADER: VERTEX SHADER
Vertex shader failed to compile with the following errors:
ERROR: 0:1: error(#132) Syntax error: "0" parse error
ERROR: error(#273) 1 compilation errors. No code generated
ERROR: FAILED TO LINK PROGRAM
Vertex shader(s) were not successfully compiled before glLinkProgram() was called. Link failed.
I use GLFW 3.3.8 and Glad. I started with OpenGL version 3.3 and tried switching to 4.6 which had no effect. Also tried to update my GPU drivers to no success either. I really have no idea where this behaviour may be coming from.

You have undefined behaviour.
vShaderStream.str().c_str();
str() returns string by value. So this temporary string object is destroyed at the end of full expression, and the pointer obtained by c_str() is dangling. As a solution you could do:
CreateShaderProgram(vShaderStream.str().c_str(), fShaderStream.str().c_str());
in case above, string temporaries are still alive when CreateShaderProgram is called.

Related

OpenGL shader does not compile but gives no error message

I am trying to write a function for loading and compiling a shader using OpenGl, but the shader refuses to compile while giving me an empty (or random) error log.
The following is my minimal example:
vertexShader = glCreateShader( GL_VERTEX_SHADER );
std::string vertexSource = ShaderLoader::load("vertexShader.vert");
const char * vertexAdress = vertexSource.c_str();
glShaderSource( vertexShader, 1, &vertexAdress, NULL );
int shaderCompiled = GL_FALSE;
char errorLog[512];
glCompileShader(vertexShader);
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &shaderCompiled );
glGetShaderInfoLog(vertexShader, 512, nullptr, &errorLog[0]);
glDeleteShader(vertexShader);
Outputting shaderCompiled gives 0 and errorLog gives either an empty string or a few random characters.
The function ShaderLoader::load contains the following code:
std::string ShaderLoader::load(std::string source) {
std::string shader;
std::fstream readFile(source, std::ios::in);
if (readFile.is_open()){
std::stringstream buffer;
buffer << readFile.rdbuf();
shader = buffer.str() + "\0";
} else {
throw std::runtime_error( "Couldn't load shader file: " + source);
}
return shader;
}
It seems to be working as expected. The shader source code is
#version 330 core
layout (location = 0) in vec3 inVertex;
layout (location = 1) in vec3 inNormal;
out vec3 FragmentPosition;
out vec3 Normal;
uniform mat4 transform;
void main()
{
FragmentPosition = vec3(inVertex);
Normal = mat3(transpose(inverse(transform))) * inNormal;
gl_Position = transform * vec4( inVertex, 1 );
}
How can I populate errorLog with an actual error message, or even better, get the shader to compile.
First only use error logging if shaderCompiled is false so you don't get random strings,
glGetShaderiv(VS, GL_COMPILE_STATUS, &shaderCompiled);
if (!shaderCompiled)
{
//error
GLchar InfoLog[256];
glGetShaderInfoLog(vertexShader, sizeof(InfoLog), NULL, InfoLog);
Second, are you actually linking and using the shaders, the problem might not be with the compilation:
// after compilation
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glLinkProgram(shaderProgram);
glDetachShader(shaderProgram, vertexShader);
glDeleteShader(vertexShader);
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);

When trying to link my Shader I get the Error Code "error c5145 must write to gl_position" [duplicate]

This question already has answers here:
OpenGL shaders don't compile
(2 answers)
Closed 3 years ago.
I'm using vs2019 as my IDE, GLEW(ver2.1.0), glm and GLfw(3.3.2) as libraries. When trying to link the Vertex Shader I get the afor mentioned error code.
ERROR::SHADER::Programm::LINK_ERROR
Vertex info
-----------
(0) : error C5145: must write to gl_Position
Below you can find the Code to compile and link the shader. Compiling seems to get done without any problems but the link wont work for the vertex shader, fragment shader seems to be fine.
#ifndef SHADER_H
#define SHADER_H
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <GL/glew.h>
class Shader
{
public:
GLuint Program;
// Erstellen des Shaders
Shader(const GLchar* vertexPath, const GLchar* fragmentPath)
{
// Speicher und Laden der Shader
std::string vertexCode;
std::string fragmentCode;
std::ifstream verShaderFile;
std::ifstream fragShaderFile;
//sicherstellen das ifstreams ausnahmen werfen können
verShaderFile.exceptions(std::ifstream::badbit);
fragShaderFile.exceptions(std::ifstream::badbit);
try
{
//öffnen der Datein
verShaderFile.open(vertexPath);
fragShaderFile.open(fragmentPath);
std::stringstream verShaderStream, fragShaderStream;
//Inhalte der Datei-Buffer in den Streams speichern
verShaderStream << verShaderFile.rdbuf();
fragShaderStream << fragShaderFile.rdbuf();
//Datein schließen
verShaderFile.close();
fragShaderFile.close();
//Stream in String umwandeln
vertexCode = verShaderStream.str();
fragmentCode = fragShaderStream.str();
}
catch (std::ifstream::failure e)
{
std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl;
}
const GLchar *verShaderCode = vertexCode.c_str();
const GLchar *fragShaderCode = fragmentCode.c_str();
//Compilen der Shader
//leere Shader erstellen
GLuint vertex;
GLuint fragment;
GLint success;
GLchar infoLog[512];
//Vertex Shader
vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &verShaderCode, NULL);
glCompileShader(vertex);
//Compile Fehler ausgeben
glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertex, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
//Fragment Shader
fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fragShaderCode, NULL);
glCompileShader(fragment);
//Output of compiling errors
glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragment, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION FAILED\n" << infoLog << std::endl;
}
//Shader Program erstellen
this->Program = glCreateProgram();
glAttachShader(this->Program, vertex);
glAttachShader(this->Program, fragment);
glLinkProgram(this->Program);
// Linking Errors ausgeben
glGetProgramiv(this->Program, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(this->Program, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::Programm::LINK_ERROR\n" << infoLog << std::endl;
}
//Löschen der Shader nach Linken mit dem Programm
glDeleteShader(vertex);
glDeleteShader(fragment);
}
//nutzen des Shaders
void ShaderStarten()
{
glUseProgram(this->Program);
}
};
#endif // !SHADER_H
This is the vertex shader itself:
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
layout (location = 2) in vec2 texCoord;
out vec3 ourColor;
out vec2 TexCoord;
void main()
{
gl_Position = vec4( position, 1.0f );
ourColor = color;
TexCoord = vec2( texCoord.x, 1.0 - texCoord.y);
}
Would really appreciate the help.
edit. here is the fragment shader someone requested
#version 330 core
in vec3 ourColor;
in vec2 TexCoord;
out vec4 color;
uniform sampler2D ourTexture1;
void main()
{
color = texture (ourTexture1, TexCoord);
}
edit2. added the semicolon to color = texture (ourTexture1, TexCoord); and added the TexCoord back to the vertex shader. Issue is still present.
So I found out what's wrong, I don't quite understand why though. I was keeping the vertex and fragment programm files in a subfolder as seperate files. When calling for the Shader I gave the file name and subfolder as input Shader myShader("Shader/core.vs", "Shader/core.frag") like this. This lead to problems for the vertex shader not for the fragment shader though. Which I don't really get if I'm honest.
I'm sorry that this trivial mistake cost you so much time. Thank you for all of your input though I learned some new things.
edit. So you should probably check out the thread Rabbid76 mentioned in a comment under the question.

GLEW Vertex Shader compile error

I recently started working on Vertex and Fragment shaders in GLEW. For some reason I am getting a failed to compile shader error.
The error I am getting is as follow:
Failed to compile vertex shader: Vertex shader failed to compile with the following errors:
ERROR: 0:3 error (#12) Unexpected qualifier.
ERROR: 0:3 error(#132) Syntax error: "position" parse error
ERROR: error(#273) 2 compilation errors. No code generated.
The text document that contain the code for the shader is:
#version 330 core
layout (location = 0) in Vector4 position;
uniform Matrix pr_matrix;
uniform Matrix vw_matrix = Matrix(1, 0);
uniform Matrix ml_matrix = Matrix(1, 0);
void main()
{
gl_Position = /*pr_matrix **/ position;
}
And the code that compile the shader is:
GLuint Shader::load() {
GLuint program = glCreateProgram();
GLuint vertex = glCreateShader(GL_VERTEX_SHADER);
GLuint fragment = glCreateShader(GL_FRAGMENT_SHADER);
std::string vertexSourceString = File::read_file(mVertex);
std::string fragmentSourceString = File::read_file(mFragment);
const char* vertexSource = vertexSourceString.c_str();
const char* fragmentSource = fragmentSourceString.c_str();
glShaderSource(vertex, 1, &vertexSource, NULL);
glCompileShader(vertex);
GLint result;
glGetShaderiv(vertex, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE) {
GLint length;
glGetShaderiv(vertex, GL_INFO_LOG_LENGTH, &length);
std::vector<char> error(length);
glGetShaderInfoLog(vertex, length, &length, &error[0]);
std::cout << "Failed to compile vertex shader: " << &error[0] << std::endl;
glDeleteShader(vertex);
return 0;
}
glShaderSource(fragment, 1, &fragmentSource, NULL);
glCompileShader(fragment);
glGetShaderiv(fragment, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE) {
GLint length;
glGetShaderiv(fragment, GL_INFO_LOG_LENGTH, &length);
std::vector<char> error(length);
glGetShaderInfoLog(fragment, length, &length, &error[0]);
std::cout << "Failed to compile fragment shader: " << &error[0] << std::endl;
glDeleteShader(fragment);
return 0;
}
glAttachShader(program, vertex);
glAttachShader(program, fragment);
glLinkProgram(program);
glValidateProgram(program);
glDeleteShader(vertex);
glDeleteShader(fragment);
return program;
}
I think something is wrong with the vertex, if anyone can help I will appreciate it. Thanks.
The strings Vertex4 and Matrix have no meaning for GLSL. Types in GLSL are things like vec4 and mat4

OpenGL Compiled Shader was corrupt

I'm trying to compile a shader program in OpenGL 3.2, but I'm getting a strange linking error.
After creating the vertex and fragment shaders compiling and attaching them, I try to link them into a program but I get the following infolog error:
ERROR: Compiled vertex shader was corrupt.
ERROR: Compiled fragment shader was corrupt.
I have absolutely no idea what it means and the only thing I could find on google was to ignore it. However, when I glUseProgram() it I get an invalid operation, so I can't just ignore this error.
Moreover, I just updated to XCode 5 and the very same code/shader source was working. Don't know how it can be related though..
Edit: shader source
Vertex:
#version 150
in vec3 position;
uniform mat4 worldMatrix;
uniform float time;
out vec3 outPos;
void main(){
gl_Position = worldMatrix*vec4(position, 1.0);
outPos = position;
}
Fragment:
#version 150
out vec4 outColor;
uniform float time;
uniform float red;
uniform float green;
uniform float blue;
void main(){
outColor=vec4(red, green, blue,1.0);
}
Got it to work.
At first I rewrote the shaders with another editor (text mate) and then it worked sometimes. Then I made sure that it was properly null terminated and it worked every time.
Maybe somehow there were non-printing characters like Andon M. Coleman suggested.
I had the same issue, and discovered that if you use the ' std::stringstream buffer' to read the file, as many code examples on the web use, the method .str().c_str() to get a *ptr needed for glShaderSource, the pointer gets deleted, meaning, you get random linker errors. Here is the work around I created...
int shaderFromFile(const std::string& filePath, GLenum shaderType) {
//open file
std::ifstream f;
f.open(filePath.c_str(), std::ios::in);
if(!f.is_open()){
throw std::runtime_error(std::string("Failed to open file: ") + filePath);
}
//read whole file into stringstream buffer
std::stringstream buffer;
buffer << f.rdbuf();
buffer << "\0";
f.close();
// need to copy, as pointer is deleted when call is finished
std::string shaderCode = buffer.str().c_str();
//create new shader
int ShaderID = glCreateShader(shaderType);
//set the source code
const GLchar* code = (const GLchar *) shaderCode.c_str();
glShaderSource(ShaderID, 1, &code, NULL);
//compile
glCompileShader(ShaderID);
//throw exception if compile error occurred
GLint status;
glGetShaderiv(ShaderID, GL_COMPILE_STATUS, &status);
std::cout << "Status from compile:" << status << "\r\n";
if (status == GL_FALSE) {
std::string msg("Compile failure in shader:\n");
GLint infoLogLength;
glGetShaderiv(ShaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
char* strInfoLog = new char[infoLogLength + 1];
glGetShaderInfoLog(ShaderID, infoLogLength, NULL, strInfoLog);
msg += strInfoLog;
delete[] strInfoLog;
glDeleteShader(ShaderID); ShaderID = 0;
throw std::runtime_error(msg);
}
return ShaderID;
}

c++ OpenGL glGetUniformLocation for Sampler2D returns -1 on Raspberry PI but works on Windows

I'm making a crossplatform OpenGL program. However, I've encountered a problem, where glGetUniformLocation, which should return the location of a uniform variable in my shader program, returns -1, and it only occurs on Linux (Raspbian distro, ran on Raspberry PI), and on Windows the same code works perfectly! Here's my code:
Load Shader program function:
int shader, status;
programID = glCreateProgram();
// Load vertex shader
shader = LoadShaderFromString(GL_VERTEX_SHADER, Tools::GetFileAsString("VertexShader.glsl"), "Unable to compile vertex shader.\n");
glAttachShader(programID, shader);
// Load pixel shader
shader = LoadShaderFromString(GL_FRAGMENT_SHADER, Tools::GetFileAsString("FilterPixelShader.glsl"), "Unable to compile pixel shader.\n");
glAttachShader(programID, shader);
// Link the program
glLinkProgram(programID);
glGetProgramiv(programID, GL_LINK_STATUS, &status);
if (status == 0)
{
Log("Unable to link filter shader program.\n");
PrintProgramLog(programID);
Fail(); // Quits program
}
// returns -1 here!
frameTextureLocation = glGetUniformLocation(programID, "FrameTextureUnit");
if (frameTextureLocation == -1)
{
int errorCode = glGetError();
Log(string("Error retrieving variable frameTextureLocation from shader program: "));
Log((const char*)glewGetErrorString(errorCode))
Log("!\n");
Fail();
}
LoadShaderFromString:
int Shader::LoadShaderFromString(int type, const string& shaderSource, const string& errorMessage)
{
int shader, status;
const char* programSource;
shader = glCreateShader(type);
programSource = shaderSource.c_str();
glShaderSource(shader, 1, &programSource, nullptr);
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if (status == 0)
{
Log(errorMessage);
PrintShaderLog(shader);
Fail();
}
return shader;
}
Lastly, the shader itself:
uniform sampler2D FrameTextureUnit;
uniform sampler2D BackgroundTextureUnit;
#if __VERSION__ >= 130
// Texture coordinate
in vec2 texCoord;
// Final color
out vec4 gl_FragColor;
#else
// Texture coordinate
varying vec2 texCoord;
#endif
uniform float Tolerance; // Tolerance for color difference
uniform vec4 FilterColor; // Color of the filter
void main()
{
vec4 pixel = texture2D(FrameTextureUnit, texCoord);
vec4 background = texture2D(BackgroundTextureUnit, texCoord);
float difference = abs(background.x - pixel.x)
+ abs(background.y - pixel.y)
+ abs(background.z - pixel.z);
if (difference > Tolerance)
{
gl_FragColor = FilterColor;
}
else
{
// Y = 0.2126 R + 0.7152 G + 0.0722 B
float gray = pixel.x * 0.2126 + pixel.y * 0.7152 + pixel.z * 0.0722;
gl_FragColor = vec4(gray, gray, gray, 1);
}
}
Does anyone know why this might be happening? :( It's worth adding that the error handling code:
int errorCode = glGetError();
Log(string("Error retrieving variable frameTextureLocation from shader program: "));
Log((const char*)glewGetErrorString(errorCode));
Prints "Error retrieving variable frameTextureLocation from shader program: No error".
Always specify GLSL version at the top of your shaders, otherwise it defaults to a very old version. It must be the first line. It will also eliminate the need for version checking inline.
#version 150
// rest of shader here