Название может показаться немного запутанным, но я не хочу делать его слишком длинным, поэтому, пожалуйста, потерпите меня и читайте дальше ...
Я пишу очень простую демонстрацию OpenGL, которая загружает изображение в качестве текстуры, а затем бесконечно прокручивает изображение горизонтально по экрану. Вот как я загружаю текстуру и отрисовываю один кадр:
void load_texture(char* filename)
{
glEnable(GL_TEXTURE_2D);
gl_texture = SOIL_load_OGL_texture(filename, SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y);
glBindTexture(GL_TEXTURE_2D, gl_texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
}
void render_single_frame()
{
glBindTexture(GL_TEXTURE_2D, gl_texture);
{
glBegin(GL_QUADS);
{
float delta = fmod(1.0f / FRAME_RATE / pan_seconds * current_frame, 1.0f);
glTexCoord2f(0.0f + delta, 0.0f); glVertex2f(-1.0f, -1.0f);
glTexCoord2f(1.0f + delta, 0.0f); glVertex2f(+1.0f, -1.0f);
glTexCoord2f(1.0f + delta, 1.0f); glVertex2f(+1.0f, +1.0f);
glTexCoord2f(0.0f + delta, 1.0f); glVertex2f(-1.0f, +1.0f);
}
glEnd();
}
glBindTexture(GL_TEXTURE_2D, 0);
glutSwapBuffers();
glFinish();
current_frame++;
}
... где FRAME_RATE
- целевая частота кадров, а pan_seconds
- секунды, необходимые для прокрутки всего изображения.
В целом демонстрация работает довольно хорошо, но, к сожалению, я создал тестовое изображение, содержащее очень тонкие элементы - несколько тонких текстов и вертикальную линию шириной 1 пиксель (справа) на черном фоне.
Когда это изображение подается в демонстрационную версию и когда значение pan_seconds
высокое (то есть изображение медленно прокручивается), возникает проблема - все эти элементы будут заметно мерцать (колебаться по яркости), что наиболее очевидно присутствует для вертикальной линии.
Мой анализ состоит в том, что высокий pan_seconds
приводит к дробным delta
с, то есть к движению субпикселя, и OpenGL придется фильтровать текстуру, чтобы определить цвет пикселя. Возьмем, к примеру, вертикальную линию: интерполяция билинейной фильтрации (GL_LINEAR
) в большинстве случаев будет давать ширину серую шириной 2 пикселя, которую человеческий глаз воспринимает как 1-пиксельный широкий, но в то же время будет казаться менее ярким по сравнению с оригинальной белой линией.
Это не поможет решить проблему, хотя ... Изменение режима фильтра на GL_NEAREST
нарушит эффект плавной прокрутки; изменение на GL_LINEAR_MIPMAP_LINEAR
устраняет мерцание, но за счет значительного размытия изображения, что не является приемлемым результатом.
Есть ли способ уменьшить это мерцание, не теряя особой резкости, или я должен доверять своему собственному теоретическому анализу и назвать его невозможным?