OpenGL can't send variables from vertex shader to fragment shader - c++

I'm pretty new to OpenGL and just started with a basic program that has a vertex shader and a fragment shader. Everything worked until I tried to send data from the vertex shader to the fragment shader. I use out in the vertex shader and in in the fragment shader.
Here are the shaders.
The Vertex:
#version 120
varying vec4 ourColor;
attribute vec3 position;
void main()
{
gl_Position = vec4(position, 1.0);
ourColor = vec4(1.0,0.1,0.2,0.5);
}
And the Fragment:
#version 120
varying vec4 ourColor;
void main()
{
gl_FragColor = ourColor;
}
The error is:
Fragment Shader contains a user varying but is linked without a vertex shader.
I tried using the flat keyword, and the varying keyword, same result. Also I've tried changing the version and then using in and out, same error.
Here is the Shader code (it's in a shader class, this is Shader.cpp):
Shader::Shader(const std::string & fileName)
{
m_program = glCreateProgram();
//vertex shader
m_shaders[0] = CreateShader(LoadShader(fileName + ".vs"), GL_VERTEX_SHADER);
m_shaders[0] = CreateShader(LoadShader(fileName + ".fs"),
GL_FRAGMENT_SHADER);
for(unsigned int i = 0; i < NUM_SHADERS; i++)
glAttachShader(m_program, m_shaders[i]);
glBindAttribLocation(m_program, 0, "position");
glLinkProgram(m_program);
CheckShaderError(m_program, GL_LINK_STATUS, true, "Error: Program linking failed. ");
glValidateProgram(m_program);
CheckShaderError(m_program, GL_VALIDATE_STATUS, true, "Error: Program is invalid. ");
}
//-----------
Shader::~Shader(void)
{
for(unsigned int i = 0; i < NUM_SHADERS; i++)
{
glDetachShader(m_program, m_shaders[i]);
glDeleteShader(m_shaders[i]);
}
glDeleteProgram(m_program);
}
//----------
void Shader::Bind()
{
glUseProgram(m_program);
}
static GLuint CreateShader(const std::string & text, GLenum shaderType)
{
GLuint shader = glCreateShader(shaderType);
if(shader == 0)
{
std::cerr << "Error: Shader creation failed! " << std::endl;
}
const GLchar* ShaderSourceStrings[1];
GLint ShaderSourceStringsLengths[1];
ShaderSourceStrings[0] = text.c_str();
ShaderSourceStringsLengths[0] = text.length();
glShaderSource(shader, 1, ShaderSourceStrings, ShaderSourceStringsLengths);
glCompileShader(shader);
CheckShaderError(shader, GL_COMPILE_STATUS, false, "Error: Shader compilation failed");
return shader;
}
//-----------
static std::string LoadShader(const std::string & fileName)
{
std::ifstream file;
file.open((fileName).c_str());
std::string output;
std::string line;
if(file.is_open())
{
while(file.good())
{
getline(file, line);
output.append(line + "\n");
}
}
else
{
std::cerr << "unable to load shader file: " << fileName << std::endl;
}
return output;
}
//-----------
static void CheckShaderError(GLuint shader, GLuint flag, bool isProgram, const std::string & errorMessage)
{
GLint success = 0;
GLchar error[1024] = {0};
if(isProgram)
glGetProgramiv(shader, flag, &success);
else
glGetShaderiv(shader, flag, &success);
if(success == GL_FALSE)
{
if(isProgram){
glGetProgramInfoLog(shader, sizeof(error), NULL, error);
std::cout << "error from program" << std::endl;
}
else{
glGetShaderInfoLog(shader, sizeof(error), NULL, error);
std::cout << "error from shader" << std::endl;
}
std::cerr << errorMessage << ": '" << error << "'" << std::endl;
}
}

Here's the error.
m_shaders[0] =
m_shaders[0] =
Fragment Shader contains a user varying but is linked without a vertex shader.
Linked without a vertex shader? That would definitely cause problems. The code should look something vaguely like this:
GLuint load_shader(GLenum shader_type, ...) {
GLuint shader = glCreateShader(shader_type);
... load shader source code ...
glCompileShader(shader);
GLint success;
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if (!success) {
// boom
}
... glGetShaderInfoLog ...
return shader;
}
GLuint load_program(...) {
GLuint prog = glCreateProgram();
// Attach both fragment and vertex shader
glAttachShader(prog, load_shader(GL_VERTEX_SHADER, ...));
glAttachShader(prog, load_shader(GL_FRAGMENT_SHADER, ...));
// Then link them together
glLinkProgram(prog);
GLint success;
glGetProgramiv(program, GL_LINK_STATUS, &success);
if (!success) {
// boom
}
... glGetProgramInfoLog ...
}
It's a fair bit of boilerplate code, and there are a lot of opportunities for the code to contain errors, so it's common for something to be wrong, especially since practically everything in OpenGL is just typedef int GLxxx; or something like that.
In GLSL 120, in and out are not storage qualifiers. Use varying instead.
// Same in vertex and fragment shader.
varying vec4 ourColor;
Alternatively, use a newer GLSL version.
#version 330
out vec4 ourColor;
in vec3 position;
#version 330
in vec4 ourColor;
out vec4 fragColor;

Related

OpenGL Shader does not compile [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 20 hours ago.
Improve this question
This shader doesn't seem to compile i am using c++ and glew, openGL. The glew version is 2.2.0 and the openGL version is 4.6. the glGetShaderInfoLog() function just returns nonsense. The compiled shaders id's just return as 0. The glGetShaderiv() return GLEW_ERROR_NO_GL_VERSION. here are the shaders and the c++ code for compiling and linking the shaders.
INIT
glfwSetErrorCallback(GlfwErrorCallback);
if(!glfwInit()) ERROR("failed to initialize glfw\n");
LOG("glfw version: " << glfwGetVersionString() << "\n");
m_Window = glfwCreateWindow(800, 800, "Cotton Game Engine", NULL, NULL);
if(!m_Window) ERROR("failed to create window\n");
glfwMakeContextCurrent(m_Window);
if(glewInit() != GLEW_OK) ERROR("failed to initialize glew\n");
LOG("glew version: " << glewGetString(GLEW_VERSION) << "\n");
LOG("opengl version: " << glGetString(GL_VERSION) << "\n");
glEnable(GL_DEBUG_OUTPUT);
glDebugMessageCallback(GlErrorCallback, 0);
VERTEX SHADER
#version 460 core
layout(location = 0) in vec3 a_Position;
layout(location = 1) in vec4 a_Color;
layout(location = 2) in vec2 a_TexCoord;
layout(location = 3) in float a_TexIndex;
uniform mat4 u_MVP;
out vec4 v_Color;
out vec2 v_TexCoord;
out float v_TexIndex;
void main()
{
v_TexCoord = a_TexCoord;
v_Color = a_Color;
v_TexIndex = a_TexIndex;
gl_Position = u_MVP * vec4(a_Position, 1.0);
}
FRAGMENT SHADER
#version 460 core
layout(location = 0) out vec4 o_Color;
in vec4 v_Color;
in vec2 v_TexCoord;
in float v_TexIndex;
uniform sampler2D u_Textures[10];
void main()
{
o_Color = texture(u_Textures[int(v_TexIndex)], v_TexCoord) * v_Color;
}
C++ Side
Shader::Shader(const std::string &vertexFilepath, const std::string &fragmentFilepath)
{
std::string vertexSource = ReadFileIntoString(vertexFilepath);
std::string fragmentSource = ReadFileIntoString(fragmentFilepath);
m_ID = CreateShader(vertexSource, fragmentSource);
}
unsigned int Shader::CreateShader(const std::string& vertexSource, const std::string& fragmentSource)
{
unsigned int program = glCreateProgram();
unsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexSource);
unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentSource);
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
glValidateProgram(program);
glDeleteShader(vs);
glDeleteShader(fs);
return program;
}
unsigned int Shader::CompileShader(unsigned int type, const std::string& source)
{
unsigned int id = glCreateShader(type);
const char* src = source.c_str();
glShaderSource(id, 1, &src, nullptr);
glCompileShader(id);
int result;
glGetShaderiv(id, GL_COMPILE_STATUS, &result);
if(result != GLEW_OK) {
char message[128];
glGetShaderInfoLog(id, sizeof(message), NULL, message);
ERROR("could not compile " << (type == GL_VERTEX_SHADER ? "vertex" : "fragment") << " shader: " << message << "\n");
glDeleteShader(id);
return 0;
}
return id;
}

Linking a Shader results in an error of file not being read

My issue begins with my shader, specifically the Vertex Shader not being linked, I am currently following the LearnOpenGL guide for the code.
ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ
ERROR::PROGRAM_LINKING_ERROR of type: PROGRAM
Vertex info
-----------
(0) : error C5145: must write to gl_Position
So this is my shader.vert file-
#version 330 core
layout (location = 0) in vec3 aPos;
void main()
{
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
}
A very simple, vert file I was able to achieve this working with the strings method, but when reading from file is where the issues begin.
Here is the shader.frag file -
#version 330 core
out vec4 FragColor;
in vec4 vertexColor; // the input variable from the vertex shader (same
name and same type)
void main()
{
FragColor = vertexColor;
}
This is the .h file which reads the files from LearnOpenGL, and to my knowledge this file isn't the problem.
#include <GL/glew.h>
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
class Shader
{
public:
unsigned int ID;
// constructor generates the shader on the fly
// ------------------------------------------------------------------------
Shader(const char* vertexPath, const char* fragmentPath)
{
// 1. retrieve the vertex/fragment source code from filePath
std::string vertexCode;
std::string fragmentCode;
std::ifstream vShaderFile;
std::ifstream fShaderFile;
// ensure ifstream objects can throw exceptions:
vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
try
{
// open files
vShaderFile.open(vertexPath);
fShaderFile.open(fragmentPath);
std::stringstream vShaderStream, fShaderStream;
// read file's buffer contents into streams
vShaderStream << vShaderFile.rdbuf();
fShaderStream << fShaderFile.rdbuf();
// close file handlers
vShaderFile.close();
fShaderFile.close();
// convert stream into string
vertexCode = vShaderStream.str();
fragmentCode = fShaderStream.str();
}
catch (std::ifstream::failure& e)
{
std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl;
}
const char* vShaderCode = vertexCode.c_str();
const char* fShaderCode = fragmentCode.c_str();
// 2. compile shaders
unsigned int vertex, fragment;
// vertex shader
vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vShaderCode, NULL);
glCompileShader(vertex);
checkCompileErrors(vertex, "VERTEX");
// fragment Shader
fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fShaderCode, NULL);
glCompileShader(fragment);
checkCompileErrors(fragment, "FRAGMENT");
// shader Program
ID = glCreateProgram();
glAttachShader(ID, vertex);
glAttachShader(ID, fragment);
glLinkProgram(ID);
checkCompileErrors(ID, "PROGRAM");
// delete the shaders as they're linked into our program now and no longer necessary
glDeleteShader(vertex);
glDeleteShader(fragment);
}
// activate the shader
// ------------------------------------------------------------------------
void use()
{
glUseProgram(ID);
}
// utility uniform functions
// ------------------------------------------------------------------------
void setBool(const std::string& name, bool value) const
{
glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value);
}
// ------------------------------------------------------------------------
void setInt(const std::string& name, int value) const
{
glUniform1i(glGetUniformLocation(ID, name.c_str()), value);
}
// ------------------------------------------------------------------------
void setFloat(const std::string& name, float value) const
{
glUniform1f(glGetUniformLocation(ID, name.c_str()), value);
}
private:
// utility function for checking shader compilation/linking errors.
// ------------------------------------------------------------------------
void checkCompileErrors(unsigned int shader, std::string type)
{
int success;
char infoLog[1024];
if (type != "PROGRAM")
{
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(shader, 1024, NULL, infoLog);
std::cout << "ERROR::SHADER_COMPILATION_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
}
}
else
{
glGetProgramiv(shader, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(shader, 1024, NULL, infoLog);
std::cout << "ERROR::PROGRAM_LINKING_ERROR of type: " << type << "\n" << infoLog << "\n -
- --------------------------------------------------- -- " << std::endl;
}
}
}
};
I am unsure how many different ways I tried linking the files, renaming them with different names, using Full Paths, and relative Paths, and still wasn't able to find the solution.
Shader ourShader("Shaders/shader.vert","Shaders/shader.frag");
Alright, so after testing so many things I have found the solution:
So for linking files always have the right folder path,
Shader ourShader("Source/Shaders/Shader.vert", "Source/Shaders/Shader.frag");
Also I found that my GLEW wasn't initialized before I used this function which also led to errors, hope my solution will help to those who has the same problem.

Why do I get a linking error when there should be nothing wrong

I'm a Java developer and I recently switched to C++. I've been trying to make a little OpenGL program and I ran into a problem. Whenever I try compiling my shader program it gives a linking error. Here it is:
ERROR::SHADER::PROGRAML::LINKING_ERROR
Link info
---------
error: "TexCoord" not declared as an output from the previous stage
Here are the shader files:
Vertex:
#version 440 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;
out vec3 ourColor;
out vec2 TexCoord;
void main()
{
gl_Position = vec4(aPos, 1.0);
ourColor = aColor;
TexCoord = vec2(aTexCoord.x, aTexCoord.y);
}
Fragment
#version 440 core
out vec4 FragColor;
in vec3 ourColor;
in vec2 TexCoord;
// texture sampler
uniform sampler2D texture1;
void main()
{
FragColor = texture(texture1, TexCoord);
}
And here is the shader creation:
int success;
char infoLog[512];
const char* vertexSource;
const char* fragmentSource;
// Load in shader source
std::ifstream inFile;
inFile.open(vertexPath);
std::string temp = "";
std::string source = "";
if (inFile.is_open())
{
while (std::getline(inFile, temp))
source += temp + "\n";
}
else
{
std::cout << "ERROR::SHADER::VERTEX::COULD_NOT_OPEN_SOURCE_FILE" << std::endl;
}
inFile.close();
vertexSource = source.c_str();
temp = "";
source = "";
inFile.open(fragmentPath);
if (inFile.is_open())
{
while (std::getline(inFile, temp))
source += temp + "\n";
}
else
{
std::cout << "ERROR::SHADER::FRAGMENT::COULD_NOT_OPEN_SOURCE_FILE" << std::endl;
}
inFile.close();
fragmentSource = source.c_str();
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSource, nullptr);
glCompileShader(vertexShader);
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, nullptr, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COULD_NOT_COMPILE\n" << infoLog << std::endl;
}
unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentSource, nullptr);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShader, 512, nullptr, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COULD_NOT_COMPILE\n" << infoLog << std::endl;
}
// Program
ID = glCreateProgram();
glAttachShader(ID, vertexShader);
glAttachShader(ID, fragmentShader);
glLinkProgram(ID);
glGetProgramiv(ID, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(ID, 512, nullptr, infoLog);
std::cout << "ERROR::SHADER::PROGRAML::LINKING_ERROR\n" << infoLog << std::endl;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glUseProgram(0);
To my understanding, I should only be getting this error if the two variables that I'm trying to link aren't the same name or type, but they are. I just don't understand.
Thanks.
You essentially have...
std::string source;
const char *vertexSource;
const char *fragmentSource;
...read into source...
vertexSource = source.c_str();
...read into source...
fragmentSource = source.c_str();
The pointer stored in vertexSource will be invalidated by the second read into source. From the documentation
The pointer obtained from c_str() may be invalidated by:
Passing a non-const reference to the string to any standard library function, or
Calling non-const member functions on the string, excluding operator[], at(), front(), back(), begin(), rbegin(), end() and
rend().

OpenGL shader linking error with no error message

I've been trying to figure this one out for a long time, but can't manage to get things to work. I want simply to compile/run my OpenGL program, but my shaders does not link correctly and I get no helpful error message. In one case the error is purely empty, and in the other case it is ??y? for some reason.
To create my program and compile my shaders, I have the following code:
GLuint buildProgram(const char* vertexShaderFile, const char* fragmentShaderFile)
{
std::string vs = fileContents(vertexShaderFile);
std::string fs = fileContents(fragmentShaderFile);
return createProgram(vs.c_str(), fs.c_str());
}
The shaders look like
#version 330
out vec4 out_color;
void main()
{
out_color = vec4(0.5, 0.5, 0.5, 0.5);
}
#version 330
in vec4 in_Position;
void main()
{
gl_Position = in_Position;
}
With
GLuint createProgram(const char* vertexSource, const char* fragmentSource)
{
GLuint vertexshader = createShader(vertexSource, GL_VERTEX_SHADER);
GLuint fragmentshader = createShader(fragmentSource, GL_FRAGMENT_SHADER);
GLuint program = glCreateProgram();
glAttachShader(program, vertexshader);
glAttachShader(program, fragmentshader);
glLinkProgram(program);
GLint ret;
checkShader(vertexshader, GL_LINK_STATUS, &ret, "unable to link vertex shader");
checkShader(fragmentshader, GL_LINK_STATUS, &ret, "unable to link fragment shader");
glUseProgram(program);
return program;
}
GLuint createShader(const char* source, GLenum shaderType)
{
GLuint shader = glCreateShader(shaderType);
glShaderSource(shader, 1, &source, NULL);
glCompileShader(shader);
GLint isCompiled = 0;
checkShader(shader, GL_COMPILE_STATUS, &isCompiled, "shader failed to compile");
if (isCompiled == GL_FALSE)
{
glDeleteShader(shader);
return 0;
}
return shader;
}
I try to generate error messages from the shaders by
void checkShader(GLuint shader, GLuint type, GLint* ret, const char* onfail)
{
switch(type) {
case(GL_COMPILE_STATUS):
glGetShaderiv(shader, type, ret);
if(*ret == false) {
int infologLength = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infologLength);
GLchar buffer[infologLength];
GLsizei charsWritten = 0;
std::cout << onfail << std::endl;
glGetShaderInfoLog(shader, infologLength, &charsWritten, buffer);
std::cout << buffer << std::endl;
}
break;
case(GL_LINK_STATUS):
glGetProgramiv(shader, type, ret);
if(*ret == false) {
int infologLength = 0;
glGetProgramiv(shader, GL_INFO_LOG_LENGTH, &infologLength);
GLchar buffer[infologLength];
GLsizei charsWritten = 0;
std::cout << onfail << std::endl;
glGetProgramInfoLog(shader, infologLength, &charsWritten, buffer);
std::cout << buffer << std::endl;
}
break;
default:
break;
};
}
Running GLuint program = buildProgram("shaders/test.vert", "shaders/test.frag"); gives me the following output:
unable to link vertex shader
unable to link fragment shader
??y?
error build program
error 502 : GL_INVALID_OPERATION
Does anyone have a guess why my shaders compile just fine but does not link?
You are calling getProgramiv(...,GL_LINK_STATUS,...) on shader objects. It doesn't make the slightest sense to even call that checkShader function twice - once for each shader object - when you try to get information about the program (of which there is only one). And it also doesn't make sense to name the function that way, for the GL_LINK_STATUS case.

Unable to use separate shader programs "<program> object is not successfully linked."

const char *vs_source =
"#version 440\n\
layout(location = 0) in vec2 position;\n\
layout(location = 1) in float offset;\n\
void main() {\n\
vec2 new_pos = vec2(position.x + offset,position.y);\n\
gl_Position = vec4(new_pos,0,1);\n\
}";
const char *fs_source =
"#version 440\n\
out vec4 out_color;\n\
void main() {\n\
out_color = vec4(1,0,0,1);\n\
}";
auto vsp = createShaderProgram(GL_VERTEX_SHADER,1,&vs_source);
auto fsp = createShaderProgram(GL_FRAGMENT_SHADER,1,&fs_source);
GLuint pipeline;
glGenProgramPipelines(1,&pipeline);
glUseProgramStages(pipeline, GL_VERTEX_SHADER_BIT , vsp.handle);
glUseProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, fsp.handle);
glBindProgramPipeline(pipeline);
with
struct Program{
GLuint handle;
};
Program createShaderProgram(GLenum type,
GLsizei count,
const char **strings){
const GLuint shader = glCreateShader(type);
if (shader) {
glShaderSource(shader, count, strings, NULL);
glCompileShader(shader);
const GLuint program = glCreateProgram();
if (program) {
GLint compiled = GL_FALSE;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
glProgramParameteri(program, GL_PROGRAM_SEPARABLE, GL_TRUE);
if (compiled) {
glAttachShader(program, shader);
glLinkProgram(program);
glDetachShader(program, shader);
}
else{
/* append-shader-info-log-to-program-info-log */
GLint infoLogLength;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar* infoLog = new GLchar[infoLogLength + 1];
glGetShaderInfoLog(shader, infoLogLength, NULL, infoLog);
std::cout << "ERROR: Unable to compile shader" << std::endl << infoLog << std::endl;
delete[] infoLog;
}
}
glDeleteShader(shader);
return Program{program};
} else {
return Program{0};
}
}
OpenGL tells me that
message: GL_INVALID_OPERATION error generated. <program> object is not successfully linked.
type: ERROR
HIGH
and I am not sure why. If I link it the old way and only create one program it works perfectly.
I am guessing I have misused the the new pipeline system?
I should also mention that the error only appears when I start to call
glUseProgramStages(pipeline, GL_VERTEX_SHADER_BIT , vsp.handle);
glUseProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, fsp.handle);
Could this be a driver bug?
Solved it. The vertex shader didn't link. I had to redeclare gl_Position.
const char *vs_source =
"#version 440\n\
layout(location = 0) in vec2 position;\n\
layout(location = 1) in float offset;\n\
out gl_PerVertex\n\
{\n\
vec4 gl_Position;\n\
float gl_PointSize;\n\
float gl_ClipDistance[];\n\
};\n\
void main() {\n\
vec2 new_pos = vec2(position.x + offset,position.y);\n\
gl_Position = vec4(new_pos,0,1);\n\
}";