Дрожание вершин OpenGL при движении - 2D сцена - PullRequest
1 голос
/ 07 марта 2020

enter image description here

Я работаю над 2D-проектом и заметил следующую проблему: как вы можете видеть на рисунке выше, когда объект делает небольшие движения, его дрожание вершин. Для рендеринга каждый кадр я очищаю VBO, вычисляю новые позиции вершин и затем вставляю их в VBO. В каждом кадре я создаю точно такую ​​же структуру, но из другого источника. Есть ли способ получить плавное движение, даже если смещение между кадрами настолько незначительное?

Я использую SDL2, поэтому двойная буферизация включена по умолчанию.

Это небольшая проблема, но это становится очень раздражающим, когда я применяю текстуру к модели.

Вот вершинный шейдер, который я использую:

#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 Ответ

1 голос
/ 07 марта 2020

То, что вы видите, вызвано алгоритмом растеризации. Рассмотрим следующие две растеризации одинаковой геометрии (красные линии), смещенные всего на половину пикселя:

image

Как видно, сдвиг всего на половину пикселя может изменить воспринимаемое расстояние между вертикальными линиями с трех до двух пикселей. Более того, горизонтальные линии не сместились, поэтому их внешний вид не изменился.

Это противоречивое поведение - это то, что проявляется в виде "колебания" в вашей анимации.

Один из способов решить эту проблему - включить сглаживание с помощью glEnable(GL_LINE_SMOOTH). Убедитесь, что включено правильное смешивание. Это, однако, приведет к размытым линиям, когда они попадают прямо между пикселями.

Если вместо этого вам действительно нужен четкий вид зубчатых линий (например, пиксельная графика), то вам нужно убедиться, что ваша геометрия только когда-либо перемещается на целое число пикселей:

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);

Добавьте viewport_size как форму.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...