I'm trying to texture a quad in OpenGL and keep getting -1 when getting the uniform location.
EDIT: Without the Uniform code, it renders just fine(minus the texture ofc).
here's the code:
texture binding code;
m_renderer.prepare();
m_colorProgram.start();
// Sets the active texture to '0'.
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_texture.id);
GLint samplerLoc = m_colorProgram.getUniformLocation("mySampler");
// Tells OGl that we are using the active texture '0' as stated above.
glUniform1i(samplerLoc, 0);
m_renderer.render(m_model);
// Always unbind
glBindTexture(GL_TEXTURE_2D, 0);
m_colorProgram.stop();
m_colorProgram.getUniformLocation:
GLint GLSLProgram::getUniformLocation ( const std::string uniformName )
{
GLint location = glGetUniformLocation ( m_programID, "size" );
if ( location == (GLint)GL_INVALID_INDEX ) {
fatal_error ( "Uniform '" + uniformName + "' could not be found!" );
}
return location;
}
vert shader:
#version 130
// super simple shader program
in vec3 vertexPositon;
in vec4 vertexColor;
in vec2 vertexUV;
out vec4 fragColor;
out vec2 fragUV;
void main(){
gl_Position = vec4(vertexPositon,1.0);
fragColor = vertexColor;
fragUV = vertexUV;
}
frag shader:
#version 130
in vec4 fragColor;
in vec2 fragUV;
uniform sampler2D mySampler;
out vec4 color;
void main()
{
vec4 texColor = texture( mySampler, fragUV );
color = texColor * fragColor;
}
Most of the solutions I've found online seem to indicate that the Uniform is is being cut out because it is not being used, however, as you can see, it IS being used, and yet still is returning a -1.
Can anyone tell me why this is happening?
Turns out I had hardcoded a string without realizing it in glGetUniform
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 want to load a default colour vertColor if the sampler2D wasn't loaded with an image, to achieve that I have tried the following:
Fragment Shader:
#version 410
uniform sampler2D tex0;
in vec4 vertColor;
in vec2 TexCoords;
out vec4 fragColor;
void main( void )
{
vec4 texColor = texture(tex0, TexCoords);
if(tex0 == -1) fragColor = blinnPhongModel(vertColor);
else{
texColor.a = 1.0;
fragColor = texColor;
}//end of else
} // End of main
but it didn't work, how can I do that?
How to load a default colour if the sampler2D was empty?
Why do you want to do that? I recommend making sure that the sampler is never "empty".
If you want to draw with a uniform color using a sampler, create a 1x1 texture with a single pixel. With this trick, you don't need to branch in the shader.
All you have to do is to create a 1x1 texture. This texture has 1 pixel and 1 color.
The fragment shader does just the texture lookup and has not branch at all:
#version 410
uniform sampler2D tex0;
in vec2 TexCoords;
out vec4 fragColor;
void main( void )
{
vec4 texColor = texture(tex0, TexCoords);
fragColor = texColor;
}
I'm trying to translate some old OpenGL code to modern OpenGL. This code is reading data from a texture and displaying it. The fragment shader is currently created using ARB_fragment_program commands:
static const char *gl_shader_code =
"!!ARBfp1.0\n"
"TEX result.color, fragment.texcoord, texture[0], RECT; \n"
"END";
GLuint program_id;
glGenProgramsARB(1, &program_id);
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, program_id);
glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei) strlen(gl_shader_code ), (GLubyte *) gl_shader_code );
I'd simply like to translate this into GLSL code. I think the fragment shader should look something like this:
#version 430 core
uniform sampler2DRect s;
void main(void)
{
gl_FragColor = texture2DRect(s, ivec2(gl_FragCoord.xy), 0);
}
But I'm not sure of a couple of details:
Is this the right usage of texture2DRect?
Is this the right usage of gl_FragCoord?
The texture is being fed with a pixel buffer object using GL_PIXEL_UNPACK_BUFFER target.
I think you can just use the standard sampler2D instead of sampler2DRect (if you do not have a real need for it) since, quoting the wiki, "From a modern perspective, they (rectangle textures) seem essentially useless.".
You can then change your texture2DRect(...) to texture(...) or texelFetch(...) (to mimic your rectangle fetching).
Since you seem to be using OpenGL 4, you do not need to (should not ?) use gl_FragColor but instead declare an out variable and write to it.
Your fragment shader should look something like this in the end:
#version 430 core
uniform sampler2D s;
out vec4 out_color;
void main(void)
{
out_color = texelFecth(s, vec2i(gl_FragCoord.xy), 0);
}
#Zouch, thank you very much for your response. I took it and worked on this for a bit. My final cores were very similar to what you suggested. For the record the final vertex and fragment shaders I implemented were as follows:
Vertex Shader:
#version 330 core
layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 1) in vec2 vertexUV;
out vec2 UV;
uniform mat4 MVP;
void main()
{
gl_Position = MVP * vec4(vertexPosition_modelspace, 1);
UV = vertexUV;
}
Fragment Shader:
#version 330 core
in vec2 UV;
out vec3 color;
uniform sampler2D myTextureSampler;
void main()
{
color = texture2D(myTextureSampler, UV).rgb;
}
That seemed to work.
I used a shader which worked in another program (in the same environment afaik) which can't compile now for some reason:
// Vertex Shader
#version 330 core
layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 1) in vec2 vertexUV;
out vec2 fragmentUV;
uniform mat4 ortho_matrix;
void main()
{
gl_Position = ortho_matrix * vec4(vertexPosition_modelspace, 1);
fragmentUV = vertexUV;
}
// Fragment Shader
#version 330 core
in vec2 fragmentUV;
uniform sampler2D texture;
out vec4 color;
void main()
{
color.rgba = texture(texture, fragmentUV).rgba;
}
It's a super basic shader and now it starts to throw errors all of the sudden.
Windows 8.1
Nvidia GeForce 1080 (this one is new maybe that's the problem?)
This is whats being output by Visual Studio:
uniform sampler2D texture;
out vec4 color;
void main()
{
color.rgba = texture(texture, fragmentUV).rgba;
}
I'm amazed this compiled at all in a different setting. You've named your texture the same as the function used to make texture lookups. You need to rename uniform sampler2D texture; to something else.
I'm writing a 2D game in OpenTK, using OpenGL 4.4. Using colour and texture UV coordinates and a matrix I can succesfully draw textures between vertices with vertex shader:
public const string vertexShaderDefaultSrc =
#"
#version 330
uniform mat4 MVPMatrix;
layout (location = 0) in vec2 Position;
layout (location = 1) in vec2 Texture;
layout (location = 2) in vec4 Colour;
out vec2 InTexture;
out vec4 OutColour;
void main()
{
gl_Position = MVPMatrix * vec4(Position, 0, 1);
InTexture = Texture;
OutColour = Colour;
}";
and fragment shader:
public const string fragmentShaderDefaultSrc =
#"
#version 330
uniform sampler2D Sampler;
in vec2 InTexture;
in vec4 OutColour;
out vec4 OutFragColor;
void main()
{
OutFragColor = texture(Sampler, InTexture) * OutColour;
//Alpha test
if(OutFragColor.a <= 0)
discard;
}
";
BUT if I want to draw just a solid colour rather than a texture, I use this shader (with the same vertices, passing UV coords that won't be used):
public const string fragmentShaderSolidColourSrc =
#"
#version 330
uniform sampler2D Sampler;
in vec2 InTexture;
in vec4 OutColour;
out vec4 OutFragColor;
void main()
{
OutFragColor = OutColour;
//Alpha test
if(OutFragColor.a <= 0)
discard;
}
";
Now this works beautifully, but OpenGL reports an error - GL_INVALID_VALUE. It draws fine and everything seems to work, but ideally I would like OpenGL to be error free in that situation, so I can catch real errors. I would appreciate any help, and can share more detail of how the shader is compiled or used if that is helpful - what I don't understand is how the default shader can work but the solid colour doesn't.
I have tracked down the exact source of the errors in my render call (shader builds with no problems)
GL.EnableVertexAttribArray(shader.LocationPosition);
GL.VertexAttribPointer(shader.LocationPosition, 2, VertexAttribPointerType.Float, false, Stride, 0);
//-----everything up to here is fine
//this line throws an error
GL.EnableVertexAttribArray(shader.LocationTexture);
//as does this line
GL.VertexAttribPointer(shader.LocationTexture, 2, VertexAttribPointerType.Float, false, Stride, 8);
//this is all ok
GL.EnableVertexAttribArray(shader.LocationColour);
GL.VertexAttribPointer(shader.LocationColour, 4, VertexAttribPointerType.UnsignedByte, true, Stride, 16);
//ok
GL.BindBuffer(BufferTarget.ElementArrayBuffer, indexBuffer);
GL.DrawArrays(DrawType, 0, Vertices.Length);
//ok
GL.DisableVertexAttribArray(shader.LocationPosition);
//this line throws error
GL.DisableVertexAttribArray(shader.LocationTexture);
//this is ok
GL.DisableVertexAttribArray(shader.LocationColour);
It appears to me after some tests (would be nice to have this verified) that if a variable such as the texture coordinates are not used by the shader the compiler gets rid of it, so a call to get it's location returns -1. Simply checking if locationTexture was -1 here and then not binding locationTexture etc if so resolved my issues.