Непонятки с координатами текстуры в OpenGL C++

Недавно занялся причёсыванием кода в исходниках минимальных примеров 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, как в факах и написано.
Только сам шрифт как-то коряво выводится. Возможно, какой-нибудь блендинг не включен или типа того. Но к теме не относится.

Да это все потому что изначально все каряво.
Отрисовка экрана происходит с левого верхнего угла. Соответственно 0, 0 (x, y) – верхний левый угол.
То что на картинке начало координат в нижнем левом угле это уже вычислительные преобразования относительно y в какой-то либе.
И то что в других средах разработки вычисления отличны это прямая зависимость от используемых вычислительных библиотек соответствующих сред для разработки.
Т. е. все зависит от того какие вычисления производятся в подключаемых библиотеках.

а при чем тут библиотеки, если это особенность OpenGL’a?

Он сам по себе что-ли, без библиотек.
Ведь не пишется каждое преобразование, вычисление вручную. Используются готовые либы с уже написанными преобразованиями и вычислениями. Либы пишут для упрощения разработки, для того они и нужны.

а какие библиотеки он использует? разве он сам не библиотека?

Они вроде бы только точностью могут отличаться, то есть во второй можно передать 16.5f.

glVertex2i принимает int, а glVertex2f float

Объясните, о каких библиотеках шла речь?

Так я это и сказал.

Normalized Device Coordinates
LearnOpenGL - Coordinate Systems

Оно не обязательно в них принимает.
Можно влиять например через glOrtho.

Примеры:
glVertex Parameter's limit - OpenGL: Basic Coding - Khronos Forums
https://stackoverflow.com/a/50806134/964478
https://stackoverflow.com/a/2602693/964478

OpenGL это API, спецификация.
Есть разные реализации и обертки.

Но один и тот же код по идее должен работать одинаково везде, если вызываются одни и те же функции без доп. абстракций.

и пофиг, что вопрос был про другое :grinning:

А я и не спорю с этим. Просто на практике мы имеем то, что на разных языках одна и та же низкоуровневая функция работает по-разному. Если это нормально, то странно, что нигде об этом не сказано.

А в С++ эти функции из какой именно библиотеки вызываются?

в каком смысле?

Ну функции OpenGL есть в:

  • библиотеке от драйвера видеокарты
  • GLEW и т.п.
  • разных обертках
  • в винде вроде была библиотека с чисто программной реализацией OpenGL 1.1 или типа того

Какой именно вариант, откуда функции берутся?

в данном проекте подключены только

#include <GL/gl.h>
#include <GL/glu.h>

Я тут немного вспомнил. В функцию glVertexXX() передаются не нормализированные координаты текстуры, а абсолютные координаты в мире. То есть, то место, куда должна быть натянута текстура. А так как шрифт выводится в ортогональной проекции, то эти координаты ограничиваются размером нашего окна.
Но тогда получается, что это в Delphi всё работает неправильно.

Это хедеры, но еще ж надо либо слинковать библиотеку, либо загрузить функции из dll.

А в Дельфи эти функции откуда?
Можно открыть юнит и посмотреть.

В Лазарусе/FPC они просто загружаются из opengl32.dll (на винде) и всё.

Никаких DLL не использую. В линкере прописана опция -lopengl32 (или opengl32.lib для вижуалки). Я хз, где он ее берёт. Наверное, какая-то стандартная виндовая DLL’ка.

uses Winapi.OpenGL

И что из этого? В Delphi, вроде, так же.

Так вроде или так же?)

Если функции просто берутся из стандартных библиотек без доп. оберток, то скорее всего надо искать отличия в коде программ на С++ и Дельфи.

Вызовы glOrtho и т.п. например.

Вот наконец-то и пришли к билиотекам.
В Delphi, начиная с 3-ей версии, OpenGL входит в комплект среды разработки.
Вот для примера берем Embarcadero:

C:\Program Files (x86)\Embarcadero\Studio\20.0\lib\win32\release\psdk\opengl32.lib

И подключаем библиотеку в секции Uses OpenGL;
Что вызывает обращение к соответствующему файлу *.pas

В плюсах обращение к библиотеке происходит например через:

#include <GL/gl.h>
#include <GL/glu.h>

В свою очередь в настройках проекта указывая линкеру где искать нужные либы.

Про это, кстати, пишут
dglOpenGL.pas/en – DGL Wiki

Delphi is already shipping with an OpenGL header, but that header is outdated and also buggy.

хз насколько актуально и что за баги.

Delphi сама по себе своеобразная среда. Ели не ошибаюсь там в проектах так-же выбирается и тип подключаемых библиотек:

  • Pascal
    или
  • IDL