I have this sample code
// EBO is just a rectangle
// copypasted from learnopengl
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderId);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glUniform1f(glGetUniformLocation(shaderId, shiftName), 0); //shiftName is string "shift"
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glUniform1f(glGetUniformLocation(shaderId, shiftName), 0.5);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glFlush();
SDL_GL_SwapWindow(window);
Shaders that I have:
Vertex:
#version 330 core
layout (location = 0) in vec3 pos;
out vec4 vertexColor;
uniform float shift = 0;
void main()
{
gl_Position = vec4(pos.x, pos.y - shift, pos.z, 1.0);
vertexColor = vec4(0, shift, 0, 1.0);
}
Fragment:
#version 330 core
out vec4 FragColor;
in vec4 vertexColor;
void main()
{
FragColor = vertexColor;
}
In my understanding, I should get two rectangles, one under another, with two colors, for each glDraw call. But instead I get one rectangle for second draw.
I assume, that both draw calls actually draw me one same rectangle. But I clearly don't understand why.
I tried flushing in between, creating second buffer, glUseProgram in between, etc.
You can see full code here
The actual source code triggering this issue was this:
shader.Select(); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); shader.Set("shift", 0); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); shader.Set("shift", 0.5f); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
In conjunction with some shader class containging these methods:
void Shader::Set(const std::string& name, bool value) const { glUniform1i(glGetUniformLocation(id, name.c_str()), (int32_t)value); } void Shader::Set(const std::string& name, int32_t value) const { glUniform1i(glGetUniformLocation(id, name.c_str()), value); } void Shader::Set(const std::string& name, float value) const { glUniform1f(glGetUniformLocation(id, name.c_str()), value); }
This means that shader.Set("shift", 0);
does call the int32
overload, resulting in trying to use glUniform1i
to set a float
uniform, which will just produce a GL error and not change the uniform at all. THe first frame will acutally be correct since the uniform is intialized to 0 by default, but after that, it will stay on 0.5
forever. Use shader.Set("shift", 0.0f);
, but IMO, that kind of overloads is doing more harm than good.
Side note: Those glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
calls are not necessary, the VAO will store the GL_ELEMENT_ARRAY_BINDING
.