Недавно занялся причёсыванием кода в исходниках минимальных примеров OpenGL и наткнулся на одну странную непонятку, которую раньше не замечал.
Вот есть у меня код загрузки текстурного шрифта на C++:
GLuint BuildTexturedFont(char* textureFileName)
{
GLuint textureFont = LoadFontTextureBitmap(textureFileName);
if (textureFont)
{
const int symbolsInRow = 16;
float glyphSize = 1.0f / (float)symbolsInRow;
const float stepX = 10.0f;
glyphLists = glGenLists(256);
for (int i = 0; i < 256; i++)
{
float glyphPosX = (i % symbolsInRow) / (float)symbolsInRow;
float glyphPosY = (i / symbolsInRow) / (float)symbolsInRow;
float u1 = glyphPosX + glyphSize;
float v1 = 1.0f - glyphPosY;
glNewList(glyphLists + i, GL_COMPILE);
glBegin(GL_QUADS);
glTexCoord2f(glyphPosX, v1 - glyphSize);
glVertex2i(0, 0 );
glTexCoord2f(u1, v1 - glyphSize);
glVertex2i(symbolsInRow, 0 );
glTexCoord2f(u1, v1 );
glVertex2i(symbolsInRow, symbolsInRow );
glTexCoord2f(glyphPosX, v1 );
glVertex2i(0, symbolsInRow );
glEnd();
glTranslatef(stepX, 0.0f, 0.0f);
glEndList();
}
}
return textureFont;
}
непонятку вызывают строчки:
glTexCoord2f();
glVertex2i();
Первая устанавливает координаты текстуры. Вторая отмечает вертекс.
То есть, на входе мы имеем картинку размером 256х256 с шестнадцатью символами по вертикали и горизонтали. Если разделить 256 на 16, то получится 16. То есть, размер каждого глифа с символом равен 16х16 пикселей.
в интернете везде написано, что
Текстурные координаты начинаются в (0, 0) в нижнем левом углу текстуры и заканчиваются на (1, 1) в верхнем правом углу.
То есть, не важно, какого разрешения было оригинальное изображение. Его центр всегда будет в точке [0.5, 0.5] (как на картинке).
Из этого следует, что размеры глифов должны быть не 16х16, а (1/16)x(1/16)
, то есть 0.625x0.625
. Эта система измерения как-то называется, но я не помню как. Функция glTexCoord2f()
принимает значения именно в такой системе. А почему glVertex2i()
принимает в пикселях? То есть, значения нужно передавать, отталкиваясь от оригинального разрешения, а не от еденицы.
Даже если заменить glVertex2i
на glVertex2f
и передавать в неё 16.0f
, то ничего не меняется. Всё продолжает работать. А, например, для сравнения, в яве надо передавать в системе 0.625. То есть, так как написано.
А вот код из Delphi:
procedure BuildFont;
var
cx, cy, w : Real;
i : Integer;
begin
base := glGenLists(256);
glBindTexture(GL_TEXTURE_2D, tex);
if tex <> 0 then
begin
w := 1 / 16;
for I := 0 to 255 do
begin
cx := (i mod 16) / 16;
cy := (i div 16) / 16;
glNewList(base + i, GL_COMPILE);
glBegin(GL_QUADS);
glTexCoord2f(cx, cy);
glVertex2f(0, 0);
glTexCoord2f(cx + w, cy);
glVertex2f(w, 0);
glTexCoord2f(cx + w, cy + w);
glVertex2f(w, w);
glTexCoord2f(cx, cy + w);
glVertex2f(0, w);
glEnd;
glTranslatef(w, 0.0, 0.0);
glEndList;
end;
end;
end;
Тут он нормально принимает w := 1 / 16
, как в факах и написано.
Только сам шрифт как-то коряво выводится. Возможно, какой-нибудь блендинг не включен или типа того. Но к теме не относится.