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 .
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 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 am writing an OpenGL / C++ plugin using VBO and GLSL shaders. However, while I can compile the shaders successfully, and link them to the program, its status link check with glGetProgramiv(...,GL_LINK_STATUS,...) returns a "No definition of main in vertex shader" error.
The vertex shader is sending a color to the fragment shader. If I remove this color-passing, the link is successfully validated.
What's wrong in my code if I want to pass color to fragment shader ?
const GLchar *vert_src =
"#version 410\n"
"layout (location = 0) in vec3 Pos;\n"
"layout (location = 1) in vec3 vColor;\n"
"uniform mat4 projectionMatrix;\n"
"uniform mat4 modelViewMatrix;\n"
"out vec3 color;\n"; // -> REMOVING THIS LINE MAKES THE VALIDATION WORK
"void main() {\n"
" color=vColor;\n" // -> AND THIS LINE TOO
" gl_Position = projectionMatrix*modelViewMatrix*vec4(Pos.x, Pos.y, Pos.z, 1.0);"
"}\n";
const GLchar *frag_src =
"#version 410\n"
"in vec3 color;\n";
"out vec4 fragColor;\n"
"void main() {\n"
" fragColor = vec4(color, 1.0);"
"}\n";
GLuint program = glCreateProgram();
GLuint v_shader = glCreateShader(GL_VERTEX_SHADER);
GLuint f_shader = glCreateShader(GL_FRAGMENT_SHADER);
int len=(GLint)strlen(vert_src);
glShaderSource(v_shader, 1, &vert_src, &len);
glCompileShader(v_shader);
glGetShaderiv(v_shader, GL_COMPILE_STATUS, &success); --> SUCCESS
len=(GLint)strlen(frag_src);
glShaderSource(f_shader, 1, &frag_src, &len);
glCompileShader(f_shader);
glGetShaderiv(f_shader, GL_COMPILE_STATUS, &success); --> SUCCESS
glAttachShader(program, v_shader); --> SUCCESS
glAttachShader(program, f_shader); --> SUCCESS
glLinkProgram(program); --> SUCCESS
glValidateProgram(program); --> SUCCESS
glGetProgramiv(program, GL_LINK_STATUS, &success); --> ERROR: Program is not successfully linked
[...] rest of code
You have semicolons outside the strings that should not be there:
const GLchar *vert_src =
"#version 410\n"
"layout (location = 0) in vec3 Pos;\n"
"layout (location = 1) in vec3 vColor;\n"
"uniform mat4 projectionMatrix;\n"
"uniform mat4 modelViewMatrix;\n"
"out vec3 color;\n"; // <- HERE YOU HAVE A SEMICOLON
"void main() {\n"
" color=vColor;\n"
" gl_Position = projectionMatrix*modelViewMatrix*vec4(Pos.x, Pos.y, Pos.z, 1.0);"
"}\n";
const GLchar *frag_src =
"#version 410\n"
"in vec3 color;\n"; // <- HERE YOU HAVE ANOTHER SEMICOLON
"out vec4 fragColor;\n"
"void main() {\n"
" fragColor = vec4(color, 1.0);"
"}\n";
I am writing a simple video player using opengl. I used Qt and followed its basic texture examples.
The vertex and fragment shaders are here:
QOpenGLShader *vshader = new QOpenGLShader(QOpenGLShader::Vertex, this);
const char *vsrc =
"attribute highp vec4 vertex;\n"
"attribute mediump vec4 texCoord;\n"
"varying mediump vec4 texc;\n"
"uniform mediump mat4 matrix;\n"
"void main(void)\n"
"{\n"
" gl_Position = matrix * vertex;\n"
" texc = texCoord;\n"
"}\n";
vshader->compileSourceCode(vsrc);
QOpenGLShader *fshader = new QOpenGLShader(QOpenGLShader::Fragment, this);
const char *fsrc =
"uniform sampler2D texture;\n"
"varying mediump vec4 texc;\n"
"void main(void)\n"
"{\n"
" gl_FragColor = texture2D(texture, texc.st);\n"
"}\n";
fshader->compileSourceCode(fsrc);
And I did this to display a image:
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture_cv.cols, texture_cv.rows, GL_RGB, GL_UNSIGNED_BYTE, texture_cv.data);
//then draw a quad
...
Then after this how could I draw several red lines on the screen, since I am using the fragment shader (I am very new to shader), I cannot turn off the texture.
By far the easiest solution is to use a different shader program for drawing your red lines. Since it just draws a solid color, it will be very easy. The fragment shader could be something like:
void main()
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
The vertex shader will be very similar to what you have, except that it does not need to produce texture coordinates. You might even be able to use the existing vertex shader.
It is very common to use multiple shader programs for rendering. You have a shader program for each different type of rendering, and switch between them with glUseProgram().
I'm a bit confused about how the shader pipeline works with regards to passing data through each stage.
What I'm trying to do is pass color data that is loaded in the vertex stage using glVertexAttrib4fv() through the tessellation control shader, and then the tessellation evaluation shader, so that it can be used in the fragment shader. I'm not sure if I've made some sort of conceptual mistake (quite possible, since I'm still trying to get my head around this over fixed functions), but either way, as soon as I try and pass anything through the tessellation shaders, my primitives refuse to render at all. Before that, my primitive renders, but it only renders in black. My shaders are as follows:
Vertex Shader:
static const GLchar* vss[] =
{
"#version 430 core \n"
" \n"
"layout (location = 0) in vec4 offset; \n"
"layout (location = 1) in vec4 color; \n"
" \n"
"out vec4 vs_color; \n"
" \n"
"void main(void) \n"
"{ \n"
" const vec4 vertices[] = vec4[](vec4( 0.25, -0.25, -0.5, 1.0), \n"
" vec4(-0.25, -0.25, -0.5, 1.0), \n"
" vec4( 0.25, 0.25, -0.5, 1.0)); \n"
" \n"
" gl_Position = vertices[gl_VertexID] + offset; \n"
" vs_color = color; \n"
"} \n"
};
Tessellation control shader:
static const GLchar* tc_ss[] =
{
"#version 430 core \n"
"layout (vertices = 3) out; \n"
"in vec4 vs_color; \n"
"out vec4 tcs_color; \n"
"void main(void) \n"
"{ \n"
" if (gl_InvocationID == 0) \n"
" { \n"
" gl_TessLevelInner[0] = 10.0; \n"
" gl_TessLevelOuter[0] = 10.0; \n"
" gl_TessLevelOuter[1] = 10.0; \n"
" gl_TessLevelOuter[2] = 10.0; \n"
" } \n"
" gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; \n"
" tcs_color = vs_color; \n"
"}"
};
Tessellation Evaluation shader:
static const GLchar* te_ss[] =
{
"#version 430 core \n"
"in vec4 tcs_color; \n"
"out vec4 tes_color; \n"
"layout (triangles, equal_spacing, cw) in; \n"
"void main(void) \n"
"{ \n"
" gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position + \n"
" gl_TessCoord.y * gl_in[1].gl_Position + \n"
" gl_TessCoord.z * gl_in[2].gl_Position); \n"
" tes_color = tcs_color; \n"
"}"
};
Fragment shader:
static const GLchar* fss[] =
{
"#version 430 core \n"
"in vec4 tes_color; \n"
"out vec4 color; \n"
" \n"
"void main(void) \n"
"{ \n"
" color = tes_color; \n"
"} \n"
};
This is not surprising, TCS inputs/outputs must be in the form:
in vec4 vs_color [];
out vec4 tcs_color [];
or in input/output blocks that also take the form of unbounded arrays:
in CustomVertex {
vec4 color;
} custom_vs [];
out CustomVertex {
vec4 color;
} custom_tcs [];
For a little bit of context, this is what a TCS / geometry shader sees as the output from vertex shaders:
in gl_PerVertex
{
vec4 gl_Position;
float gl_PointSize;
float gl_ClipDistance [];
} gl_in [];
To keep things as simple as possible, I will avoid using interface blocks.
Instead, I will introduce the concept of per-patch inputs and outputs, because they will further simplify your shaders considering the color is constant across the entire tessellated surface...
Modified Tessellation Control Shader:
in vec4 vs_color [];
patch out vec4 patch_color;
...
patch_color = vs_color [gl_InvocationID];
Modified Tessellation Evaluation Shader:
patch in vec4 patch_color;
out vec4 tes_color;
...
tes_color = patch_color;
With these changes, you should have a working pass-through and a slightly better understanding of how the TCS and TES stages work.