使用openGL渲染时如何判断字体大小(以像素为单位)

时间:2011-10-05 16:49:04

标签: c++ opengl

我正在使用Bitfighter的编辑器,我们使用默认的OpenGL描边字体。我们通常使用2的线宽渲染文本,但这会使较小的字体不易读取。我想要做的是检测字体大小何时会低于某个阈值,然后将线宽减小到1.问题是,在所有变换等应用之后,我不知道如何判断有多高(在像素)字体大小< fontsize>将被渲染。

这是实际的内部渲染功能:

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 ++编写的。


我的解决方案是将第一部分Christian Rau的解决方案与第二部分的片段结合起来。基本上,我可以用这个得到当前的缩放因子:

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

float scalefact = modelview[0];

然后,我将scalefact乘以fontsize(以像素为单位),并将其乘以windowHeight / canvasHeight的比率,以获得我的文本将呈现的像素高度。

那是......

textheight = scalefact * fontsize * widndowHeight / canvasHeight

我也喜欢缩放线条粗细的想法,而不是在超过阈值时从2步进到1。现在一切都很好。

2 个答案:

答案 0 :(得分:3)

  

我们使用默认的OpenGL描边字体

OpenGL不做字体。没有默认的OpenGL描边字体

也许您指的是GLUT及其glutStrokeCharacter函数。那么请注意GLUT不是OpenGL的一部分。它是一个独立的库,专注于为小型OpenGL演示和教程提供简单的框架。

回答你的问题:GLUT笔画字体是根据顶点定义的,因此适用通常的转换。由于通常所有的变换都是线性的,你可以简单地通过模型视图转换向量(0,base_height,0),最后做一个透视除法(gluProject为你完成所有这些 - GLU也不是OpenGL的一部分),得到的矢量是你正在寻找的;取矢量长度来缩放宽度。

答案 1 :(得分:2)

这应该很容易确定。字体的大小(以像素为单位)仅取决于模型视图转换(实际上只是缩放部分),投影转换(我猜是简单的正交投影)和视口设置,当然还取决于单个字符的大小。未转换形式的字体(进入glVertex调用的内容)。

所以你只需要考虑字体的基本大小(仅考虑高度并将其称为height)并首先进行模型视图转换(假设代码中显示的缩放是唯一的):

height *= scaleFactor;

接下来我们进行投影转换:

height /= (top-bottom);

topbottom是指定正交变换时使用的值(例如,使用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);

在这里,我采用角色的对角线而不仅仅是高度,以更好地忽略旋转,我们使用原点作为参考值来忽略翻译。

您可能还会发现this question的答案很有趣,这可以更深入地了解OpenGL的转换管道。