C++ GLSL Linking error - c++

I'm developing a 3d Engine and I got some trouble with the GLSL shader in C++.
Vertex shader:
layout(location = 0) in vec3 vertexUP;
layout(location = 1) in vec3 vertexUV;
out vec3 UP;
out vec3 UV;
void main(){
UP = vertexUP;//Without this line, everything works fine
UV = vertexUV;
gl_Position = ftransform();
}
Fragment shader:
in vec3 UP;
in vec3 UV;
out vec3 color;
uniform sampler2D rs0;
uniform sampler2D rs1;
uniform sampler2D rs2;
void main(){
if(UV[2]==0){//Selects between different textures
color = texture( rs0, vec2(UV[0], UV[1]) ).rgb;
}else if(UV[2]==1){
color = texture( rs1, vec2(UV[0], UV[1]) ).rgb;
}else{
color = texture( rs2, vec2(UV[0], UV[1]) ).rgb;
}
if(UP[0]<2){//Test thing
color[0] = 1.0;
}
}
I want to parse the position array (Location 0) to the fragement shader so I can use it for lighting. It Compiles but linking the vertex shader gives a error:
Vertex shader(s) failed to link, Fragment shader(s) linked.
What am I doing wrong?
EDIT:
The code to load the shaders:
GLuint LoadShaders(const char * vertex_file_path,const char * fragment_file_path){
// Create the shaders
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
// Read the Vertex Shader code from the file
std::string VertexShaderCode;
std::ifstream VertexShaderStream(vertex_file_path, std::ios::in);
if(VertexShaderStream.is_open())
{
std::string Line = "";
while(getline(VertexShaderStream, Line))
VertexShaderCode += "\n" + Line;
VertexShaderStream.close();
}
// Read the Fragment Shader code from the file
std::string FragmentShaderCode;
std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
if(FragmentShaderStream.is_open()){
std::string Line = "";
while(getline(FragmentShaderStream, Line))
FragmentShaderCode += "\n" + Line;
FragmentShaderStream.close();
}
GLint Result = GL_FALSE;
int InfoLogLength;
// Compile Vertex Shader
printf("Compiling shader : %s\n", vertex_file_path);
char const * VertexSourcePointer = VertexShaderCode.c_str();
glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
glCompileShader(VertexShaderID);
// Check Vertex Shader
glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
std::vector<char> VertexShaderErrorMessage(InfoLogLength);
glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
fprintf(stdout, "%s\n", &VertexShaderErrorMessage[0]);
// Compile Fragment Shader
printf("Compiling shader : %s\n", fragment_file_path);
char const * FragmentSourcePointer = FragmentShaderCode.c_str();
glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
glCompileShader(FragmentShaderID);
// Check Fragment Shader
glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
std::vector<char> FragmentShaderErrorMessage(InfoLogLength);
glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
fprintf(stdout, "%s\n", &FragmentShaderErrorMessage[0]);
// Link the program
fprintf(stdout, "Linking program\n");
GLuint ProgramID = glCreateProgram();
glAttachShader(ProgramID, VertexShaderID);
glAttachShader(ProgramID, FragmentShaderID);
glLinkProgram(ProgramID);
// Check the program
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
std::vector<char> ProgramErrorMessage(InfoLogLength);
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
fprintf(stdout, "%s\n", &ProgramErrorMessage[0]);
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
return ProgramID;
}

You can't do that:
layout(location = 0) in vec3 vertexUP;
layout(location = 1) in vec3 vertexUV;
...
gl_Position = ftransform();
ftransform() uses the builtin gl_Vertex, and the GL spec requires that to alias attribute index 0, so the GL cannot assign the attribute indices without collision.
You really shouldn't mix the old, deprecated builtins with generic attributes. And if you do, you should led the GL assign the attribute locations.

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.

GLSL Error: (0) : error C5145: must write to gl_Position

When I go to link my compiled vertex and fragment shaders, I get this error:
(0) : error C5145: must write to gl_Position
Here is the basic section of my code where the error occurs:
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(GL_VERTEX_SHADER, 1, &vertexShaderCode, nullptr);
glCompileShader(GL_VERTEX_SHADER);
GLint okay;
glGetShaderiv(GL_VERTEX_SHADER, GL_COMPILE_STATUS, &okay);
if (okay == GL_FALSE) {
char infoLog[512];
glGetShaderInfoLog(GL_VERTEX_SHADER, 512, nullptr, infoLog);
error("Failed to compile vertex shader.", infoLog);
}
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(GL_FRAGMENT_SHADER, 1, &fragmentShaderCode, nullptr);
glCompileShader(GL_FRAGMENT_SHADER);
glGetShaderiv(GL_FRAGMENT_SHADER, GL_COMPILE_STATUS, &okay);
if (okay == GL_FALSE) {
char infoLog[512];
glGetShaderInfoLog(GL_FRAGMENT_SHADER, 512, nullptr, infoLog);
error("Failed to compile fragment shader.", infoLog);
}
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &okay);
if (okay == GL_FALSE) {
char infoLog[512];
glGetProgramInfoLog(shaderProgram, 512, nullptr, infoLog);
error("Failed to link the shader program.", infoLog);
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
Here is the vertex shader:
#version 330 core
layout (location = 0) in vec3 vertexData;
layout (location = 1) in vec2 textureCoord;
out vec2 textCoord;
uniform mat4 projectionMat;
uniform mat4 viewMat;
uniform mat4 modelMat;
void main() {
gl_Position = projectionMat * viewMat * modelMat * vec4(vertexData, 1.0f);
vertColor = vertexColor;
textCoord = textureCoord;
}
Here is the fragment shader (in case it matters):
#version 330 core
in vec2 textCoord;
out vec4 color;
uniform sampler2D text;
uniform vec4 textColor;
void main() {
color = texture(text, textCoord) * textColor;
}
I did some investigating and toyed around with it and found that (unlike other people) the source I was sending to OpenGL was not empty and was the full, correct source (I found this by printing vertexShaderCode).
How do I fix it?
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
This creates a shader object for a vertex shader. And this means that vertexShader now contains that shader object. Given that:
glShaderSource(GL_VERTEX_SHADER, 1, &vertexShaderCode, nullptr);
What does this do? It's supposed to put the given code into a shader object. But none of the parameters are a shader object. The first parameter is an OpenGL enumerator, which is not a shader object.
Shader and program objects are not like most OpenGL objects. You don't bind them just to set data into them (except for uniforms and programs, but we don't even need to bind them for that since GL 4.1). If you want to manipulate a shader, you have to actually pass the shader to the function that manipulates it.
glShaderSource(vertexShader, 1, &vertexShaderCode, nullptr);

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

GLSL Attribute Location Returning -1

I am clearly misunderstanding something pretty simple here to do with GLSL and all Google results point to the obvious answer that I'm not using the variable I'm trying to find and it has been optimised out - However I am using the variable in question. Consider the following very basic shaders:
Vertex shader
attribute vec2 TexCoord;
varying vec2 TexCoordA;
void main(){
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
TexCoordA = TexCoord;
}
Fragment shader
varying vec2 TexCoordA;
void main(){
gl_FragColor = vec3(TexCoordA.x, TexCoordA.y, 0);
}
They compile and link fine- no errors. However using "glGetAttribLocation" returns -1 when I try and find the location of "TexCoord". If I use TexCoordA for another purpose (such as a call to "texture2D()") then I am able to find the location of TexCoord correctly.
Why does this matter you're probably asking (because why else would you use UV coords for anything other than a texture call)? I am trying to render one pixel into a frame buffer for all the UV coordinates and then read them back again on a second pass - this is the only way I can guarantee the results I'm looking for.
TL;DR
Why does "glGetAttribLocation" return -1 for the above shaders given they compile and link without a problem?
Requested information about code surrounding the problem area as follows (I am loading about 20-25 other shaders the same way so I'm confident the problem isn't here):
Problem lines:
mPassOneProgram = LoadShader("PCT_UV_CORRECTION_PASS_1.vert", "PCT_UV_CORRECTION_PASS_1.frag");
mPassOneUVLocation = glGetAttribLocation(mPassOneProgram, "TexCoord");
Shader loader code:
GLuint LoadShader(const char *vertex_path, const char *fragment_path) {
GLuint vertShader = glCreateShader(GL_VERTEX_SHADER);
GLuint fragShader = glCreateShader(GL_FRAGMENT_SHADER);
// Read shaders
std::string vertShaderStr = readFile(vertex_path);
std::string fragShaderStr = readFile(fragment_path);
const char *vertShaderSrc = vertShaderStr.c_str();
const char *fragShaderSrc = fragShaderStr.c_str();
GLint result = GL_FALSE;
int logLength;
// Compile vertex shader
std::cout << "Compiling vertex shader." << std::endl;
glShaderSource(vertShader, 1, &vertShaderSrc, NULL);
glCompileShader(vertShader);
// Check vertex shader
glGetShaderiv(vertShader, GL_COMPILE_STATUS, &result);
glGetShaderiv(vertShader, GL_INFO_LOG_LENGTH, &logLength);
std::vector<char> vertShaderError(logLength);
glGetShaderInfoLog(vertShader, logLength, NULL, &vertShaderError[0]);
std::cout << &vertShaderError[0] << std::endl;
OutputDebugString(&vertShaderError[0]);
// Compile fragment shader
std::cout << "Compiling fragment shader." << std::endl;
glShaderSource(fragShader, 1, &fragShaderSrc, NULL);
glCompileShader(fragShader);
// Check fragment shader
glGetShaderiv(fragShader, GL_COMPILE_STATUS, &result);
glGetShaderiv(fragShader, GL_INFO_LOG_LENGTH, &logLength);
std::vector<char> fragShaderError(logLength);
glGetShaderInfoLog(fragShader, logLength, NULL, &fragShaderError[0]);
std::cout << &fragShaderError[0] << std::endl;
OutputDebugString(&vertShaderError[0]);
std::cout << "Linking program" << std::endl;
GLuint program = glCreateProgram();
glAttachShader(program, vertShader);
glAttachShader(program, fragShader);
glLinkProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &result);
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
std::vector<char> programError( (logLength > 1) ? logLength : 1 );
glGetProgramInfoLog(program, logLength, NULL, &programError[0]);
std::cout << &programError[0] << std::endl;
OutputDebugString(&vertShaderError[0]);
glDeleteShader(vertShader);
glDeleteShader(fragShader);
return program;
}
Managed to solve this by doing
gl_FrontColor = vec3(TexCoord.x, TexCoord.y, 0)
in the Vertex shader and
gl_FragColor = gl_Color;
in the Fragment shader.
Which is essentially the same thing and I still don't understand why it wasn't working before. I'm gonna put this one down to a bug in the compiler as nobody else seems to be able to find a problem.
glGetShaderiv(vertShader, GL_COMPILE_STATUS, &result);
...
glGetShaderiv(fragShader, GL_COMPILE_STATUS, &result);
...
glGetProgramiv(program, GL_LINK_STATUS, &result);
Each of these should be followed by a check to ensure that result is equal to GL_TRUE, otherwise the shader hasn't properly compiled. See here for a complete shader / program set of classes.