Здравствуйте, решил я значит сделать игру используя Pascal ABC. И решил подключить уже существующие библиотеки во вкладке GAC. Но к моему удивлению, ничего не работает, кроме System библиотек. Вопрос, можно ли вообще работать с библиотеками сторонними, такими как DirectX или OpenGL в среде PascalABC?
Что за вкладка GAC? Вы имеете в виду вид в форме папки? Там несколько вариантов, укажите точно чтобы небыло путаницы.
PascalABC и PascalABC.Net это разные языки.
В частности, GAC (Global Assembly Cache) это .Net библиотеки, к которым была заранее применена JIT компиляция, чтобы ускорить запуск программ, подключающих эти библиотеки.
Но .Net библиотеки можно подключать только к .Net программам. Поэтому к давно сдохшему PascalABC вы их не подключите.
Тем временем, OpenGL.dll и библиотеки DirectX это неуправляемые (средой выполнения .Net). Они не могут быть в GAC.
И они не содержат интерфейс в виде типов данных и т.п., подключать из них можно только подпрограммы. И то, подпрограмме надо всегда вручную указать сигнатуру, потому что в библиотеке есть только точка входа (адрес в .dll файле, откуда начинать выполнять подпрограмму).
К примеру в User32.dll
есть эта подпрограмма:
MessageBox function (winuser.h) - Win32 apps | Microsoft Learn
Если перевести сигнатуру с C/C++ на паскаль, получается:
function MessageBox(hWnd: System.IntPtr; lpText, lpCaption: string; uType: cardinal): integer;
external 'User32.dll' name 'MessageBox';
(взял из справки, поиск по external
, но там чуток неправильно)
Вообще при переводе сигнатур есть куча неоднозначностей. К примеру такую подпрограмму C/C++:
void p1(int* x);
Можно перевести как:
procedure p1(x: ^integer); // указатель, то есть неуправляемый адрес
procedure p1(var x: integer); // ссылка, то есть управляемый адрес
procedure p1(x: array of integer); // массив целиком
И на этом сложности не заканчиваются. Если у вас есть массив var a := new integer[10]
, который вы хотите передать библиотеке - вызвать вам даст любую из этих 3 перегрузок: p1(@a[0])
, p1(a[0])
и p1(a)
соответственно. Но первая приведёт к утечке памяти, ибо нечего бездумно смешивать ссылочные типы (классы, коими являются массивы) с указателями.
Не знаю как работает DirectX, но в OpenGL не все подпрограммы находятся в .dll, некоторые надо загружать особой функцией после создания контекста OpenGL.
Я уже реализовал сигнатуры всех подпрограмм (включая расширения) и всю их загрузку, вы можете подключать готовый модуль OpenGL. И посмотрите в папку примеров:
PABCWork.NET\Samples\StandardUnits\OpenGL и OpenCL
Там, кроме собственно примеров, .html файлы, объясняющие как такие модули использовать.
Про подключение OpenTK, Tao, sharpDX можете у TheMrDen3D на YouTube посмотреть. Можно создать новый проект. Проект. Подключить сборку. NuGet. И подгрузить их, вроде как. Это для PascalABC.NET. У меня, кстати, “Крутящийся треугольник” из примеров выдаёт ошибку:
Common.pas(48) : Ошибка времени выполнения: Крутящийся треугольник.vert:
ERROR: 0:15: 'gl_FrontColor' : undeclared identifier
ERROR: 0:15: 'rgb' : vector field selection out of range
ERROR: 0:15: 'assign' : cannot convert from 'attribute 3-component vector of highp float' to 'highp float'
ERROR: 0:16: 'a' : vector field selection out of range
“точки на поле” работает
Какая модель GPU и версия библиотеки OpenGL?
Что если добавить:
out vec4 gl_FrontColor;
?
(или может придётся другое имя выбрать, если ему не понравится что пользовательское имя начинается с gl_
… в любом случае, отпишитесь какая ошибка во всех случаях что вы протестили)
Похоже добавить out
атрибут в вертексном шейдере не достаточно, чтобы это работало - надо ещё фрагментный шейдер, который будет дальше передавать этот цвет.
Попробуйте это:
Крутящийся треугольник.rar (2,7 КБ)
Ну, даже если так работает - пж отпишитесь о всём остальном тож… Я пока подожду менять это в исходном репозитории.
Intel(R) HD Graphics 620.
версия драйвера 25.20.100.6617.
Версию OpenGL не знаю как посмотреть.
Открывается окно, закрашенное чёрным.
в окне вывода: INVALID_OPERATION
Это в каком из случаев?
это вы файл прислали
Очень древняя версия, ещё с 2019, поидее уже должно быть и новее… У Intel-а есть своя утилита для обновления дров.
// получаем тип последней ошибки
var err := gl.GetError;
// и если ошибка есть - выводим её
if err<>ErrorCode.NO_ERROR then Writeln(err);
Это проверяется единожны после каждого кадра. Надо найти после какой строчки даёт эту ошибку - только вы этим можете занятся, потому что у вас воспроизводится. Но сначала таки обновитесь, потому что в старых драйверах искать проблему дело неблагодарное.
Драйвер загружаются. После этой строчки:
// Оставляем всё настроенным и привязанным
// В данном случае можно, потому что шейдерная программа одна
gl.VertexAttribFormat(attribute_position, 2,VertexAttribType.FLOAT, false, 0);
Если добавить
out vec4 gl_FrontColor;
ему gl_ не нравится:
Common.pas(48) : Ошибка времени выполнения: Крутящийся треугольник.vert:
ERROR: 0:5: 'gl_FrontColor' : the gl_ identifier prefix is reserved for use by OpenGL ES gl_
Ну, то что ему gl_
не нравится это я уже ожидал. А добавляете вы куда?
Вы же вроде сказали что то что я в .rar прислал запускаете - там уже отредактировано, так что добавлять ничего не надо. А если в исходный пример, который с паскалем устанавливается - говорите сразу, иначе путаница будет…
В любом случае, где всё же получается INVALID_OPERATION
? В какой версии примера и на какой строчке?
INVALID_OPERATION
возникает в версии, которую вы прислали после 64 строчки.
добавлял в пример, идущий с паскалем.
Об этом вам надо было сюда писать, я только сейчас заметил
Да, теперь уже дошло…
GL_INVALID_OPERATION
is generated byglVertexAttribFormat
, … if no vertex array object is bound.
gl_vertex_array
это вообще отдельная штука, но я знаю наверняка что она тут не обязательна.
Возможно оно хочет чтобы вы сначала выполнили Bind
, чтобы оно сразу смогло скопировать данные из буфера куда-то себе… Хотя это странное поведение драйвера, но попробуйте поменять местами в том что я .rar кидал, чтобы было так:
gl.BindVertexBuffer(attribute_position, vertex_pos_buffer, IntPtr.Zero, sizeof(Vec2f));
gl.VertexAttribFormat(attribute_position, 2,VertexAttribType.FLOAT, false, 0);
(ниже, в случае inp_color
так же поменять надо будет, но поидее будет сразу видно что ошибка ниже, если вы раскомментировали и использовали var RaiseIfError := procedure->
)
Ну, не принципиально. Я тут тоже обитаю. Основное преимущество issue в том, что их можно на долго оставлять - забыть не получится. Но я думаю это дело можно сегодня сразу и решить.
так тоже INVALID_OPERATION
пишет
gl.BindVertexBuffer(attribute_position, vertex_pos_buffer, IntPtr.Zero, sizeof(Vec2f));
// получаем тип последней ошибки
var err := gl.GetError;
// и если ошибка есть - выводим её
if err<>ErrorCode.NO_ERROR then Writeln(err);
gl.VertexAttribFormat(attribute_position, 2,VertexAttribType.FLOAT, false, 0);
я драйвер обновлю сейчас
Теперь ваша версия работает. Версия в примерах даёт ту же ошибку c gl_FrontColor
.
Версия драйвера: 31.0.101.2121
Его дата: 03.03.2023
Ладно, раз в последней версии драйвера работает - наверное баг в драйверах был. Подход с gl.VertexAttribFormat
вместо gl.VertexAttribPointer
более современный…
Про gl_FrontColor
? Ну ладно, вариант с простеньким фрагментным шейдером немного объёмней, но и более правильный.
Новую версию модуля OpenGL, вместе с этим исправленным примером, я собираюсь через несколько недель послать, чтобы в установщик добавили. Пока используйте эту временную версию, что в .rar тут была…