Пиксельная отрисовка текста в перспективной проекции
Я пытаюсь визуализировать текст в виде текстурированных квадратов в перспективной проекции (не хочу использовать орто-проекцию), и я борюсь с выравниванием пикселей.
Установка проста, у меня есть текст с Совместите точки привязки в 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-координаты, немного отделить его от фона.
Другое решение состоит в том, чтобы избежать вычисления масштаба-масштабирования текста.
Вы можете рассчитать привязку пикселей, выполняя перспективные вычисления на стороне процессора для каждого текста. Затем отобразите его в ортогональной проекции.