OpenGL vertices jitter when moving - 2D scene

Viewed 544

enter image description here

I am working on a 2d project and I noticed the following issue: As you can see in the gif above, when the object is making small movements, its vertices jitter. To render, every frame I clear a VBO, calculate the new positions of the vertices and then insert them to the VBO. Every frame, I create the exact same structure, but from a different origin. Is there a way to get smooth motion even when the displacement between each frame is so minor?

I am using SDL2 so double buffering is enabled by default.

This is a minor issue, but it becomes very annoying once I apply a texture to the model.

Here is the vertex shader I am using:

#version 330 core
layout (location = 0) in vec2 in_position;
layout (location = 1) in vec2 in_uv;
layout (location = 2) in vec3 in_color;

uniform vec2 camera_position, camera_size;

void main() {
    gl_Position = vec4(2 * (in_position - camera_position) / camera_size, 0.0f, 1.0f);
}
1 Answers

What you see is caused by the rasterization algorithm. Consider the following two rasterizations of the same geometry (red lines) offset by only half a pixel:

As can be seen, shifting by just half a pixel can change the perceived spacing between the vertical lines from three pixels to two pixels. Moreover, the horizontal lines didn't shift, therefore their appearance didn't change.

This inconsistent behavior is what manifests as "wobble" in your animation.

One way to solve this is to enable anti-aliasing with glEnable(GL_LINE_SMOOTH). Make sure to have correct blending enabled. This will, however, result in blurred lines when they fall right between the pixels.

If instead you really need the crisp jagged line look (eg pixel art), then you need to make sure that your geometry only ever moves by an integer number of pixels:

vec2 scale = 2/camera_size;
vec2 offset = -scale*camera_position;
vec2 pixel_size = 2/viewport_size;
offset = round(offset/pixel_size)*pixel_size; // snap to pixels
gl_Position = vec4(scale*in_position + offset, 0.0f, 1.0f);

Add viewport_size as a uniform.

Related