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".
Related
I have been trying to pass a mat4 into VS.
I am activating the shader program before passing the data:
renderProg.use(); // glUseProgram( m_programHandle );
glm::mat4 mv = view * model;
renderProg.setUniform("u_ModelViewMatrix", mv);
renderProg.setUniform("u_MVP", projection * mv);
But for some reason the uniform variable(u_ModelViewMatrix) is not being activated and returning -1 in the "Location" of glGetUniformLocation. Here is the VS code:
#version 460
layout (location = 0 ) in vec3 VertexPosition;
uniform mat4 u_MVP;
uniform mat4 u_ModelViewMatrix;
out vec3 Position;
void main()
{
vec4 vp = vec4(VertexPosition, 1.0);
Position = (u_ModelViewMatrix * vp).xyz;
gl_Position = u_MVP * vp;
}
FS Code:
#version 460
in vec3 Position;
uniform vec4 Color;
layout( location = 0 ) out vec4 FragColor;
void main() {
FragColor = Color;
}
Only one uniform is not being able to set "u_ModelViewMatrix", the other is being successfully accessed "u_MVP". Both uniforms use the same call for receiving data:
glUniformMatrix4fv(loc, 1, GL_FALSE, &m[0][0]);
Right after successful linking and compiling of the Vertex and the Fragment shader , if I am querying the active uniforms , its returning two location of uniforms , one is from FS "Color" the other is from VS "u_MVP"
for( int i = 0; i < nUniforms; ++i ) {
glGetActiveUniform( m_programHandle, i, maxLen, &written, &size, &type, name );
location = glGetUniformLocation(m_programHandle, name);
qDebug() << "Location: " << location << " Name: " << name;
}
Output:
Location: 0 Name: Color
Location: 1 Name: u_MVP
What am I doing wrong here?
The interface variabel Position is not used in the fragment shader. So the uniform variable u_ModelViewMatrix is not required. This uniform is "optimized out" by the linker and does not become an active program resource. Therefor you'll not get a uniform location for "u_ModelViewMatrix".
I have a very basic engine based on OpenGL that can render polygons in any color to a resizeable window. I'm now trying to implement matrices for my shaders by giving the model, perspective and view matrices as uniforms via my shader. Before adding the uniforms everything worked as it should, I could even pass in a uniform vec2 to simulate a light source at my mouse position. The uniform mat4s doesn't work as well as the vec2s.
For debugging purposes I'm only rendering one yellow square centered on the screen. When using no uniforms the square shows as expected. i now try passing in one mat4, set as an identity matrix. In the vertex shader I'm multiplying gl_Position by the identity matrix I uniformed. When I run the program it only shows a black window.
I've tried manually creating an identity matrix in the vertex shader and multiplying gl_Position by that matrix instead of the uniform one. When I do that my yellow square shows as normal. This leads me to believe that the uniform mat4 doesn't get the correct values, however, I don't know how to check the values of the matrix when it's being used in the shader.
This is how my vertex shader looks:
#version 430 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec4 color;
out vec4 Color;
uniform mat4 model;
uniform mat4 view;
uniform mat4 project;
void main()
{
mat4 id;
id[0] = vec4(1.0, 0.0, 0.0, 0.0);
id[1] = vec4(0.0, 1.0, 0.0, 0.0);
id[2] = vec4(0.0, 0.0, 1.0, 0.0);
id[3] = vec4(0.0, 0.0, 0.0, 1.0);
Color = color;
gl_Position = id * vec4(position, 1.0);
}
The mat4 id is the manually created identity matrix, when changing id * to model * I get the black window.
This is how my fragment shader looks:
#version 430 core
in vec4 Color;
out vec4 outColor;
void main()
{
outColor = Color;
}
The shader is initialized by this code:
m_shaderID = glCreateProgram();
const char* vertexSource = ReadFile::readFile(vertpath);
const char* fragmentSource = ReadFile::readFile(fragpath);
GLint status;
// Vertex Shader
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSource, NULL);
glCompileShader(vertexShader);
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status);
if (status != GL_TRUE)
{
std::cout << "Failed to compile vertex shader!\nInfo log: " << std::endl;
char buffer[512];
glGetShaderInfoLog(vertexShader, 512, NULL, buffer);
std::cout << buffer << std::endl;
glDeleteShader(vertexShader);
}
// Fragment Shader
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &status);
if (status != GL_TRUE)
{
std::cout << "Failed to compile fragment shader!\nInfo log: " << std::endl;
char buffer[512];
glGetShaderInfoLog(fragmentShader, 512, NULL, buffer);
std::cout << buffer << std::endl;
glDeleteShader(fragmentShader);
}
// Shader program
glAttachShader(m_shaderID, vertexShader);
glAttachShader(m_shaderID, fragmentShader);
glLinkProgram(m_shaderID);
glValidateProgram(m_shaderID);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
The matrix is created as a uniform by this code:
void Shader::setUniformmat4(const GLchar* name, glm::mat4 matrix)
{
for (int i = 0; i <= 3; i++)
printf("%f, %f, %f, %f\n", matrix[i].x, matrix[i].y, matrix[i].z, matrix[i].w);
glUniformMatrix4fv(glGetUniformLocation(m_shaderID, name), 1, GL_FALSE, glm::value_ptr(matrix));
}
The printf is for checking the values of the matrix as they are used to create the uniform, and they have the values of an identity matrix at that point.
The function setUniformmat4 is called by this code:
glm::mat4 model = glm::mat4(1.0);
shader.setUniformmat4("model", model);
When creating a lighting effect I create the uniform by calling this function:
void Shader::setUniformvec2(const GLchar* name, glm::vec2 vector)
{
glUniform2f(glGetUniformLocation(m_shaderID, name), vector.x, vector.y);
}
via this piece of code:
shader.setUniformvec2("light_pos", glm::vec2((x / window.getWidth()) * 2.0 - 1.0, 1.0 - 2.0 * (y / window.getHeight())));
Where x and y are the mouses coordinates. I then add the line
uniform vec2 light_pos;
To the fragment shader. This works no problem, and it traces the mouse perfectly. The function used for setting the uniform mat4 looks the same as the function for setting the uniform vec2, only difference is the 4fv for the mat4 and 2f for the vec2.
As you can see, I'm using glm for the matrices and vectors.
My main function looks like this:
Window window(720, 720, "Window");
Shader shader("shader.vert", "shader.frag");
glm::mat4 model = glm::mat4(1.0);
shader.setUniformmat4("model", model);
Renderer* renderer = new Renderer();
std::vector<StaticSprite*> sprites;
sprites.push_back(new StaticSprite(-0.5, -0.5, 0.0, 1.0, 1.0, glm::vec4(1.0, 1.0, 0.0, 1.0), &shader));
while (!window.closed())
{
window.clear();
shader.enable();
double x, y;
window.getMousePosition(x, y);
shader.setUniformvec2("light_pos", glm::vec2((x / window.getWidth()) * 2.0 - 1.0, 1.0 - 2.0 * (y / window.getHeight())));
for (StaticSprite* sprite : sprites)
renderer->submit(sprite);
renderer->flush();
shader.disable();
window.update();
}
return 0;
My question summarized is basically why are the values of the uniform mat4 not correct, is there any way to find out what those values are, and what should I change in the code to make the uniform mat4s work?
Please ask for any additional information needed to give an answer, I will happily provide anything I forgot to include.
glUniform* specify the value of a uniform variable for the current program object. This means the program has to be installed by glUseProgram before:
Shader shader("shader.vert", "shader.frag");
shader.enable(); // <--- this is missing
glm::mat4 model = glm::mat4(1.0);
shader.setUniformmat4("model", model);
Active program resources can be get from a program object which is not the "current" program (e.g. glGetUniformLocation). Note, the program object is a parameter of glGetUniformLocation.
But to set the value of a uniform by glUniform*, the program has to be the currently installed program.
Im having trouble with getting a proper location of my uniform in my opengl shaders. I always but always get -1 returned from the glGetUniformLocation Function.
maybe I didnt load it well?
I read online that uniforms can get optimized out for not-using them, but I do use my uniforms in a way that can affect my shaders(or do I,I think I do).
also, everytime I encounter an answer that is related to this problem on stackoverflow or on some other site,they do talk about this fact, but NO ONE EXPLAINS about an alternative solution for this, and that realy got me struggling. is it something new just for new opengl iterations?
here is my vertex shader code:
#version 410 core
in vec4 position;
uniform mat4 mvmatrix;
uniform mat4 projmatrix;
void main(void)
{
gl_Position = projmatrix * mvmatrix * position;
}
here is my fragment shader code:
#version 410 core
out vec4 color;
void main(void)
{
color = vec4(1.0,1.0,1.0,1.0)
}
and here is the whole source code for the whole program..for now I didnt implement the whole code itself,only the part that compliles the program and shaders, but yet, Im struggling to get the location for the uniforms, Ive been struggling with this for several days...hoping someone could save me here:
codeHere
also if you need only the specific part that Im talking about:
//creating program and shaders, compiling shaders, compiling program
GLchar * v_Shader[] = {
"#version 410 core \n"
" \n"
"in vec4 position; \n"
" \n"
" \n"
"uniform mat4 mvmatrix; \n"
"uniform mat4 projmatrix; \n"
" \n"
"void main(void) \n"
"{ \n"
" gl_Position = proj_matrix * mv_matrix * position; \n"
"} \n"
};
GLchar * f_Shader[] = {
"#version 410 core \n"
" \n"
"out vec4 color; \n"
" \n"
"in VS_OUT \n"
"{ \n"
" vec4 color; \n"
"} fs_in; \n"
" \n"
"void main(void) \n"
"{ \n"
" color = vec4(1.0,1.0,1.0,1.0) \n"
"} \n"
};
//creating a opengl program
program = glCreateProgram();
//creating the vertex shader and compiling it
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, v_Shader, NULL);
glCompileShader(vertexShader);
//creating the fragment shader and compiling it
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, f_Shader, NULL);
glCompileShader(fragmentShader);
//attaching the shaders to the program and linking the program
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glLinkProgram(program);
glUseProgram(program);
//getting the program's uniform locations
modelViewMatrixLocation = glGetUniformLocation(program, "mvmatrix");
projectionMatrixLocation = glGetUniformLocation(program, "projmatrix");
And nope, I dont like using glfw/sdl/glew/freeglut or any other library. they just confuse me all around.
You are misspelling the uniform names in the vertex shader:
uniform mat4 mvmatrix;
uniform mat4 projmatrix;
...
gl_Position = proj_matrix * mv_matrix * position;
To fix, replace gl_Position line with
gl_Position = projmatrix * mvmatrix * position;
To catch errors like this in the future, check the shader compile status:
GLint wasCompiled;
glGetShaderiv( shader, GL_COMPILE_STATUS, &wasCompiled );
GLint logLength;
glGetShaderiv( shader, GL_INFO_LOG_LENGTH, &logLength );
if (logLength > 0)
{
GLchar* log = new GLchar[ (std::size_t)logLength + 1 ];
GLsizei charsWritten = 0;
glGetShaderInfoLog( shader, logLength, &charsWritten, log );
std::cout << std::string( log );
}
You also have a syntax error in your fragment shader:
color = vec4(1.0,1.0,1.0,1.0)
It's missing ; at the end. You should check for shader compile errors.
Your fragment shader takes color as input from vertex shader, but vertex shader doesn't output it and you don't use color input in the fragment shader. To fix, remove these lines:
"in VS_OUT \n"
"{ \n"
" vec4 color; \n"
"} fs_in; \n"
In the latest version in the comments you have a line:
color = vec4(1.0,0.0,0.0.1.0)
There are 2 errors. You are missing ; and the character before 1.0 should be ,, not .
i'm a beginner in OpenGL, and i write a vertex shader and do other things like compiling shader.
Vertex shader:
in vec4 vPosition;
in vec4 vColor;
out vec4 Color;
void main(void){
gl_Position = vPosition;
Color = vColor;
}
After i write this code in C++:
GLuint PositionID = glGetAttribLocation(SProgram, "vPosition");
GLuint ColorID = glGetAttribLocation(SProgram, "vColor");
cout << "vPosition location: " << PositionID << endl << "vColor location: " << ColorID << endl;
And result was pretty interesting, two same locations:
vPosition location: 4294967295
vColor location: 4294967295
What is why of that?
Actually the return type of glGetAttribLocation is not GLuint but GLint (which is signed).
So 4294967295 it's indeed -1 which means that a problem occurred somewhere. Causes could be many:
program is invalid or incorrectly linked
attribute is not used
attribute name is invalid
It's hard to tell the cause since we can't guess your code but the problem is somewhere else.
This is my shader 'triangles.vert':
#version 430 core
layout(location = 0) in vec4 vPosition;
layout(location = 1) in vec4 vColor;
uniform mat4 vRota;
out vec4 color;
void main()
{
color = vColor;
gl_Position = vRota * vPosition;
}
and this is the snippet of the C++ source:
ShaderInfo shaders[] =
{
{ GL_VERTEX_SHADER, "triangles.vert" },
{ GL_FRAGMENT_SHADER, "triangles.frag" },
{ GL_NONE, NULL }
};
GLuint program = LoadShaders(shaders);
glUseProgram(program);
//...
int vRota_loc = glGetAttribLocation(program, "vRota");
if (vRota_loc == -1)
{
cout << "No uniform match for 'vRota'" << endl;
}
It returns -1, but I don't know why.
Am I doing something wrong in the shader?
ps LoadShaders() is function for compiling and linking the shader programm. it is given as sourcefile by a book I'm practicing with. So I supose there won't be the error.
glGetAttribLocation is for vertex attributes, i.e. in variables in the vertex shader (such as vPosition). You want glGetUniformLocation.
A uniform is not an attribute. You need to use glGetUniformLocation
A uniform is consistent for each vertex while an attribute is per vertex.