I'm a Spannish student. Now, I'm studying OpenGL in C++.
I'm learning about it but i found a problem: the function glGetShaderiv gives me GL_FALSE (but after it the shader is used by the program without problems...)
My C++ code is:
glShaderSource(vertID, 1, &vertCode, NULL);
glGetShaderiv(vertID, GL_COMPILE_STATUS, &status);
if(!status) {
std::cout << "Error compiling vertex shader source at file '" << vertPath << "'!" << std::endl;
}
The file is found well. Data is copied well (I know it because the shader is used without problems by the OpenGL program)
My GLSL Vertex Shader Source:
#version 330 core
layout(location = 0) out vec4 color;
void main() {
color = vec4(1.0, 0.0, 0.0, 1.0);
}
Please help me! Thank you very much!
Related
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.
I am trying to find the locations of my attributes in my vertex shader. When I print the locations I get 0, -1, and -1. The "0" corresponds to the aPos variable. Even if I move the aPos variable down it still prints 0. I read that -1 means that the variable can't be found.
Here is my code:
// build and compile shaders
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, &vertex_shader, NULL);
glCompileShader(vs);
GLint status = GL_TRUE;
glGetShaderiv( vs, GL_COMPILE_STATUS, &status );
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, &fragment_shader, NULL);
glCompileShader(fs);
GLuint shader_program = glCreateProgram(); //creating joint shader program
glAttachShader(shader_program, fs);
glAttachShader(shader_program, vs);
glLinkProgram(shader_program);
GLint loc_pos = glGetAttribLocation( shader_program, "aPos" );
std::cout << "apos position: " << loc_pos << " ";
loc_pos = glGetAttribLocation( shader_program, "aNormal" );
std::cout << "normal position: " << loc_pos << " ";
loc_pos = glGetAttribLocation( shader_program, "TexCoords" );
std::cout << "texCoords position: " << loc_pos << " ";
Here is my vertex shader:
#version 150 core
in vec3 aPos;
in vec3 aNormal;
in vec2 aTexCoords;
out vec2 TexCoords;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
TexCoords = aTexCoords;
gl_Position = projection * view * model * vec4(aPos, 1.0);
}
Fragment shader:
#version 150 core
out vec4 FragColor;
in vec2 TexCoords;
uniform sampler2D texture_diffuse1;
void main()
{
FragColor = texture(texture_diffuse1, TexCoords);
//FragColor = vec4(1.0);
}
Any help would be greatly appreciated!!
You won't get a location for aNormal, because aNormal is not an active program resource, because it is not "used" in the vertex shader. So the driver optimize away the attribute aNormal and it gets no attribute index.
If you don't use TexCoords in the fragment shader, then the same is the case for aTexCoords, if TexCoords is not "used", then aTexCoords is not "used", too.
See OpenGL 4.6 Core Profile Specification - 7.3.1 Program Interfaces, page 102:
7.3.1 Program Interfaces
When a program object is made part of the current rendering state, its executable code may communicate with other GL pipeline stages or application code through a variety of interfaces. When a program is linked, the GL builds a list of active resources for each interface. Examples of active resources include variables, interface blocks, and subroutines used by shader code. Resources referenced in shader code are considered active unless the compiler and linker can conclusively determine that they have no observable effect on the results produced by the executable code of the program.
The code
loc_pos = glGetAttribLocation( shader_program, "TexCoords" );
returns -1, because "TexCoords" is not th name of an attribute. The name of the attribute is "aTexCoords" rather than "TexCoords".
I'm building a game using OpenGL and C++. I'm using GLFW and GLAD. I'm currently in the process of setting up simple shaders, but I'm completely roadblocked by a compilation problem. In a nutshell, shader compilation fails with no error message.
Here's my vertex shader (it's meant to draw 2D images and text):
#version 330 core
layout (location = 0) in vec2 vPosition;
layout (location = 1) in vec2 vTexCoords;
layout (location = 2) in vec4 vColor;
out vec4 fColor;
out vec2 fTexCoords;
uniform mat4 mvp;
void main()
{
vec4 position = mvp * vec4(vPosition, 0, 1);
position.y *= -1;
gl_Position = position;
fColor = vColor;
fTexCoords = vTexCoords;
}
And here's the relevant code to create the shader, load the shader source, compile the shader, and check for errors.
GLuint shaderId = glCreateShader(GL_VERTEX_SHADER);
std::string source = FileUtilities::ReadAllText(Paths::Shaders + filename);
GLchar const* file = source.c_str();
GLint length = static_cast<GLint>(source.size());
glShaderSource(shaderId, 0, &file, &length);
glCompileShader(shaderId);
GLint status;
glGetShaderiv(shaderId, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE)
{
GLint logSize = 0;
glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &logSize);
std::vector<GLchar> message = std::vector<GLchar>(logSize);
glGetShaderInfoLog(shaderId, logSize, nullptr, &message[0]);
glDeleteShader(shaderId);
std::cout << std::string(message.begin(), message.end());
}
Using that code, logSize is returned as 1, meaning that I'm unable to access the error message provided by GL. From what I can tell, the message doesn't exist at all. I've already seen the question posted here, in which the issue was a missing call to glCompileShader. As you can see, my code does call that function.
In attempting to solve this problem, I've already confirmed a few things.
My shader source (a string) is being read correctly. The source is a single string that, as far as I can tell, exactly matches the actual shader file.
There are no casting issues from the string source to GLchar const* or GLint (the variables file and length). Both look correct.
If I artificially inflate the value of logSize (to, say, 1000), the resulting message is nothing but zeroes. No error message exists.
I am calling glfwInit() and related functions before reaching this point in the code. Querying glGetString(GL_VERSION) does correctly return the target version (3.3.0).
Does anyone know how to fix this? As I said, my progress is completely blocked since I can't render anything (2D or 3D) without working shaders.
Thank you!
The problem is that you never upload any shader source to the shader.
The second parameter in this line:
glShaderSource(shaderId, 0, &file, &length);
tells OpenGL to load 0 code strings to the shader (nothing). Change this to 1, and it should work.
I'm trying to create a little shader for brightness and contrast of the window (that I've seen here).
I can load the file, and compile the shader successfully. But I fail to link it. My problem is that the log has no output, so I can't see what's wrong with it. How can I check the linking problem? Where can I find informations about linking failing, and check why linking can fail (I'm new to shaders).
I'm using Ubuntu 12.04.
This is the initialization code
if (GLEW_ARB_fragment_shader) {
// I enter here so I suppose that shader is enabled for
// my graphics card
std::cout << "arb shader enabled" << std::endl;
}
// Loading shader
string fragmentShaderSource;
GLint len;
std::ifstream in("/path/to/file.glsl");
fragmentShaderSource = std::string((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
len = fragmentShaderSource->size();
// I've checked the string and file seems to be loaded properly.
// Creating shader
GLint flength;
GLuint fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
GLcharARB** text = new (GLcharARB*);
text[0] = (char*)fragmentShaderSource.c_str();
glShaderSourceARB(fragmentShader, 1, (const GLcharARB**) text, &flength);
// Compile shader
glCompileShaderARB(fragmentShader);
GLint compiled;
glGetObjectParameteriv(ShaderObject, GL_COMPILE_STATUS, &compiled);
if (compiled)
{
// I enter here so I suppose that compilation is ok.
std::cout << "shader compiled" << std::endl;
}
// Attaching to program
GLuint program;
program = glCreateProgram();
glAttachShader(program, fragmentShader);
// Linking
glLinkProgram(program);
// Link check
GLint linked;
glGetProgramivARB(program, GL_LINK_STATUS, &linked);
if (linked) {
std::cout << "linked" << std::endl;
} else {
// I enter here so linking is failed
std::cout << "not linked" << std::endl;
GLint blen = 0;
GLsizei slen = 0;
glGetShaderiv(program, GL_INFO_LOG_LENGTH, &blen);
// blen is equal to zero so I cannot print the log message
// because it's absent
if (blen > 1) {
GLchar* linking_log = (GLchar*) malloc(blen);
glGetProgramInfoLog(program, blen, &slen, linking_log);
glGetInfoLogARB(program, blen, &slen, linking_log);
std::cout << "compiler_log:\n" << linking_log << std::endl;
free(linking_log);
}
}
And this is the glsl code that I load
uniform float Brightness : register(C0);
uniform float Contrast : register(C1);
sampler2D Texture1Sampler : register(S0);
float4 main(float2 uv : TEXCOORD) : COLOR
{
float4 pixelColor = tex2D(Texture1Sampler, uv);
pixelColor.rgb /= pixelColor.a;
// Apply contrast.
pixelColor.rgb = ((pixelColor.rgb - 0.5f) * max(Contrast, 0)) + 0.5f;
// Apply brightness.
pixelColor.rgb += Brightness;
// Return final pixel color.
pixelColor.rgb *= pixelColor.a;
return pixelColor;
}
EDIT:
I fixed log, when linking fails, I obtain following output:
Fragment info
-------------
0(1) : warning C7557: OpenGL does not allow Cg-style semantics
0(2) : warning C7557: OpenGL does not allow Cg-style semantics
0(4) : warning C7557: OpenGL does not allow Cg-style semantics
0(4) : warning C7554: OpenGL requires sampler variables to be explicitly declared as uniform
0(6) : warning C7506: OpenGL does not define the global type float4
0(6) : warning C7506: OpenGL does not define the global type float2
0(6) : warning C7557: OpenGL does not allow Cg-style semantics
0(6) : warning C7557: OpenGL does not allow Cg-style semantics
0(6) : warning C7527: OpenGL requires main to take no parameters
0(6) : warning C7530: OpenGL requires main to return void
0(9) : warning C7506: OpenGL does not define the global function tex2D
0(13) : warning C7502: OpenGL does not allow type suffix 'f' on constant literals in versions below 120
0(13) : warning C7011: implicit cast from "int" to "float"
0(13) : warning C7502: OpenGL does not allow type suffix 'f' on constant literals in versions below 120
EDIT2:
I've fixed fragment shader
uniform float Brightness;
uniform float Contrast;
uniform vec2 vTextureCoord;
uniform sampler2D Texture1Sampler;
void main() {
vec4 textureColor = texture2D(Texture1Sampler, vTextureCoord);
vec3 fragRGB = textureColor.rgb / textureColor.a;
fragRGB.rgb = ((fragRGB.rgb - 0.5) * max(Contrast, 0.0)) + 0.5;
fragRGB.rgb += Brightness;
fragRGB.rgb *= textureColor.a;
gl_FragColor = vec4(fragRGB, textureColor.a);
}
And I've added a basic vertex shader
attribute vec4 gl_Vertex;
void main(){
gl_Position = gl_Vertex;
}
I've added them to program. Now all compilation warning disappeared, but linking fails again.
program = glCreateProgram();
glAttachShader(program, fragmentShader); // fragment shader compiled. No warnings
glAttachShader(program, vertexShader); // vertex shader compiled. No warnings
glLinkProgram(program);
GLint linked;
glGetProgramivARB(program, GL_LINK_STATUS, &linked); // linked != GL_TRUE. Linking failed.
What I'm yet doing wrong?
You are only attaching a fragment shader and not a vertex shader. In fully programmable openGL both are required. Your code should be:
glAttachShader(program, fragmentShader);
glAttachShader(program, vertexShader);
Linking happens after shaders are attached to a program, and since both vertex and fragment shaders are required linking failed.
Moreover you are basically writing Cg in GLSL.
float4 main(float2 uv : TEXCOORD) : COLOR // These Cg semantics are not accepted in GLSL
The point is that GLSL doen't use Cg like semantics and you need to use GLSL special out variables. Check the following psudo-GLSL code.
in vec3 vertex;
//vertex shader.
void main() // write a main and output should be done using special variables
{
// output using special variables.
gl_Position = vertex;
}
//fragment shader.
uniform vec4 color;
void main() // write a main and output should be done using special variables
{
// output using special variables.
gl_FragColor = color;
}
I actually recommend that you pick a GLSL language tutorial like this one.
I'm using xcode to make a game with OpenGL. I have used GLUT to initialise a window. I have shaders that I wish to implement but when I try to compile them, I get two compile errors in the info log. My shaders look like this:
//FirstShader.vsh
#version 150 core
in vec3 position;
void main()
{
gl_Position = vec4(position, 1.0);
}
//FirstShader.fsh
#version 150 core
out vec4 fragData;
void main()
{
fragData = vec4(0.0, 0.0, 1.0, 1.0);
}
I'm reading the file and compiling it with this code:
GLuint createShaderFromFile(const GLchar *path, GLenum shaderType){
GLuint shaderID = glCreateShader(shaderType);
std::ifstream fin;
fin.open(path);
if(!fin.is_open()){
fin.close();
std::cout << "Shader Not Found" << std:: endl;
return 0;
}
std::string source((std::istreambuf_iterator<GLchar>(fin)),std::istreambuf_iterator<GLchar> ());
fin.close();
const GLchar* shaderSource = source.c_str();
glShaderSource(shaderID, 1, &shaderSource, NULL);
glCompileShader(shaderID);
GLint compileStatus;
glGetShaderiv(shaderID, GL_COMPILE_STATUS, &compileStatus);
if (compileStatus != GL_TRUE) {
std::cout << "Shader failed to compile" << std::endl;
GLint infoLoglength;
glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &infoLoglength);
GLchar* infoLog = new GLchar[infoLoglength + 1];
glGetShaderInfoLog(shaderID, infoLoglength, NULL, infoLog);
std::cout << infoLog << std::endl;
delete infoLog;
return 0;
}
return shaderID;
}
Im getting these errors:
ERROR: 0:1: '' : version '150' is not supported
ERROR: 0:1: '' : syntax error #version
My OpenGL version is 2.1 and my glsl version is 1.20. Does anybody know how I can fix this?
You can tell OSX to use a newer version of OpenGL by setting it in your pixel format when you create the context. Here is an example of how to set it up.
Or if you're using glut, I think you want glutInitContextVersion(x, y); where x and y are the major and minor version numbers. GLSL 1.5 is supported in OpenGL 3.2, I think. (And you might also want glutInitContextProfile(GLUT_CORE_PROFILE);, I think.)
I re-wrote your shaders in a way that they will actually work in GLSL 1.20.
in must be replaced with attribute in a GLSL 1.20 vertex shader
out for fragment shader output is invalid, use gl_FragColor or gl_FragData [n] instead
Declaring a vertex attribute as vec3 and then doing something like vec4 (vtx, 1.0) is completely redundant
If you declare the attribute as vec4 and give it data using fewer than 4 components GLSL will automatically fill-in the attribute's missing components this way: vec4 (0.0, 0.0, 0.0, 1.0).
Fragment Shader:
#version 120
attribute vec4 position;
void main()
{
gl_Position = position;
}
Vertex Shader:
#version 120
void main()
{
gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
}
Of course this does not really solve your problem, because if you have a version of OS X 10.7 or newer, it supports OpenGL 3.2 and therefore GLSL 1.50 core. You need to request a core profile context for this to work, however - otherwise you will get OpenGL 2.1 and GLSL 1.20.