Пиксельная отрисовка текста в перспективной проекции

Я пытаюсь визуализировать текст в виде текстурированных квадратов в перспективной проекции (не хочу использовать орто-проекцию), и я борюсь с выравниванием пикселей.

Установка проста, у меня есть текст с Совместите точки привязки в 3D, я меняю свою модель трансформации в щитах трансформации, и вычислить масштаб (треугольник подобия), чтобы текст всегда один и тот же размер. Поскольку геометрия текстовых квадратов построена с единицами мира, соответствующими пикселям, результирующий текст действительно имеет одинаковый размер независимо от ориентации камеры или смещения точки привязки.

Vector3d dist = camera.getPosition();
dist.sub(translation);

double pxFov = camera.getFOV() / camera.getScreenWidth();
double scale = Math.sin(pxFov) / Math.sin((Math.PI / 2) - pxFov) 
            * dist.length() * camera.getAspectRatio();

V.getRotationScale(R);
R.transpose();

M.setIdentity();
M.setRotation(R);
M.setScale(scale);
M.setTranslation(translation);

Где V - матрица вида камеры 4x4, R - временная матрица 3x3, а M - матрица преобразования модели 4x4, используемая для расчета MVP.

Я нашел предполагаемое решение, но оно просто немного изменило поведение отрисованного текста вместо того, чтобы исправить проблему.

При использовании вершинного шейдера

void main () {
    vec2 view = vec2(1280, 720);

    vec4 cpos = MVP * vec4 (position, 1.0f);
    vec2 p = floor(cpos.xy * view*0.5/cpos.w);
    p += 0.5; // does not influence result
    cpos.xy = p * (2.0/view*cpos.w);

    gl_Position = cpos;
}

в некоторых местах текст отображается четко, а в некоторых местах размытым

текст размыт в волнах

В случае простого вершинного шейдера

void main () {
    gl_Position = MVP * vec4 (position, 1.0f);
}

является ли текст полностью размытым или полностью резким

вроде совершенно острый

полностью размыто

Кажется логичным получить позиции вершин в области просмотра, округлить их и переместить назад, но что-то, похоже, отсутствует.

РЕДАКТИРОВАТЬ: объяснение того, как я рассчитываю коэффициент масштабирования.

Объяснение коэффициента масштабирования

Здесь вы видите, что я получаю прямоугольный треугольник в виде красных, зеленых и синих линий. Зная длину красного (расстояние привязки камеры к тексту), угол между красным и синим ((fov/2)/(ширина экрана /2)) и угол между красным и зеленым, являющийся прямым углом, я могу использовать закон синусов для вычисления длина зеленой линии, которая также является масштабом одного текселя, чтобы иметь тот же размер в текущей проекции.

Масштаб текста кажется правильным независимо от камеры / ориентации / положения текста (желательно 8 пикселей). Возможно, масштаб просто слегка неправильный, и это приводит к эффекту размытия, но я не вижу, как это сделать.

1 ответ

Мне кажется, что из-за численных проблем вы страдаете из-за борьбы с z-буфером.

Возможно, вы можете добавить небольшое значение к тексту z-координаты, немного отделить его от фона.

Другое решение состоит в том, чтобы избежать вычисления масштаба-масштабирования текста.
Вы можете рассчитать привязку пикселей, выполняя перспективные вычисления на стороне процессора для каждого текста. Затем отобразите его в ортогональной проекции.

Другие вопросы по тегам