Как определить размер шрифта в пикселях при рендеринге с openGL - PullRequest
3 голосов
/ 05 октября 2011

Я работаю над редактором для Bitfighter , где мы используем стандартный штриховой шрифт OpenGL.Обычно мы визуализируем текст с шириной линии 2, но это делает мелкие шрифты менее читаемыми.То, что я хотел бы сделать, это определить, когда размер шрифта упадет ниже некоторого порога, и уменьшить ширину линии до 1. Проблема в том, что после того, как все преобразования и тому подобное применены, я не знаю, как определить, насколько высокий (впикселей) будет обработан шрифт размером .

Это действительная внутренняя функция рендеринга:

if(---something--- < thresholdSizeInPixels)
   glLineWidth(1);

float scalefactor = fontsize / 120;

glPushMatrix();
   glTranslatef(x, y + (fix ? 0 : size), 0);
   glRotatef(angle * radiansToDegreesConversion, 0, 0, 1);
   glScalef(scaleFactor, -scaleFactor, 1);
   for(S32 i = 0; string[i]; i++)
      OpenglUtils::drawCharacter(string[i]);
glPopMatrix();

Перед вызовом этого я хочу проверить высоту шрифта, затем уменьшите ширину линии, если необходимо.Что происходит в «что-то»?

Bitfighter - это чистая 2D-игра старой школы, поэтому здесь не происходит никаких фантастических 3D-преобразований.Весь код написан на C ++.


Мое решение состояло в том, чтобы объединить первую часть решения Кристиана Рау с фрагментом второй.По сути, я могу получить текущий коэффициент масштабирования следующим образом:

static float modelview[16];
glGetFloatv(GL_MODELVIEW_MATRIX, modelview);    // Fills modelview[]

float scalefact = modelview[0];

Затем я умножу масштабный коэффициент на размер шрифта в пикселях и умножу его на отношение windowHeight / canvasHeight, чтобы получить высоту в пикселях, котораятекст будет представлен.

То есть ...

textheight = scalefact * fontsize * widndowHeight / canvasHeight

И мне также понравилась идея масштабирования толщины линий, а не переходить от 2 к 1 при пересечении порога.Теперь все работает очень хорошо.

Ответы [ 2 ]

3 голосов
/ 05 октября 2011

, где мы используем стандартный штриховой шрифт OpenGL

OpenGL не выполняет шрифты.Нет стандартного штрихового шрифта OpenGL .

Возможно, вы имеете в виду GLUT и его функцию glutStrokeCharacter.Тогда обратите внимание, что GLUT не является частью OpenGL.Это независимая библиотека, сфокусированная на предоставлении упрощенной структуры для небольших демонстраций и учебных пособий по OpenGL.

Чтобы ответить на ваш вопрос: штриховые шрифты GLUT определены в терминах вершин, поэтому применяются обычные преобразования.Поскольку обычно все преобразования являются линейными, вы можете просто преобразовать вектор (0, base_height, 0) посредством просмотра модели и проекции, наконец, выполнив деление перспективы (gluProject делает все это за вас - GLU тоже не является частью OpenGL), в результатевектор - это то, что вы ищете;возьмите длину вектора для масштабирования ширины.

2 голосов
/ 05 октября 2011

Это должно быть определено довольно легко. Размер шрифта в пикселях зависит только от преобразования вида модели (фактически только от масштабируемой части), преобразования проекции (я полагаю, простой ортогональной проекции) и настроек области просмотра, и, конечно же, от размера отдельного символа шрифт в нетрансформированной форме (что входит в glVertex вызовы).

Таким образом, вы просто берете базовый размер шрифта (давайте рассмотрим только высоту и назовем его height) и сначала выполните преобразование вида модели (предполагая, что масштабирование, показанное в коде, является единственным):

height *= scaleFactor;

Далее мы делаем преобразование проекции:

height /= (top-bottom);

с top и bottom являются значениями, которые вы использовали при указании ортографического преобразования (например, с использованием glOrtho). И последнее, но не менее важное: мы делаем преобразование области просмотра:

height *= viewportHeight;

с viewportHeight, как вы уже догадались, высотой области просмотра, указанной в вызове glViewport. В результате height должен быть высотой вашего шрифта в пикселях. Вы можете использовать это, чтобы как-то масштабировать ширину линии (без if), так как параметр ширины линии в любом случае находится в числах с плавающей запятой, пусть OpenGL выполняет дискретизацию.


Если ваш конвейер преобразования более сложный, вы можете использовать более общий подход с использованием полных матриц преобразования, возможно, с помощью gluProject для преобразования точки пространства объекта в точку пространства экрана:

double x0, x1, y0, y1, z;
double modelview[16], projection[16];
int viewport[4];
glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
glGetDoublev(GL_PROJECTION_MATRIX, projection);
glGetIntegerv(GL_VIEWPORT, viewport);
gluProject(0.0, 0.0, 0.0, modelview, projection, viewport, &x0, &y0, &z);
gluProject(fontWidth, fontHeight, 0.0, modelview, projection, viewport, &x1, &y1, &z);
x1 -= x0;
y1 -= y0;
fontScreenSize = sqrt(x1*x1 + y1*y1);

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

Вы также можете найти ответы на этот вопрос интересными, которые дают некоторое представление о конвейере преобразования OpenGL.

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