Работа с OpenGL

Хотел поговорить насчёт графике игр ведь без неё игру не написать даже консольную. В данный момент я делаю игру(GA) и меня уже извиняюсь но задолбали 15-20 фпс, долго я шлялся по инету но нормального описания как правильно начать и закончить перерисовку в 2D нету, не говоря уже про то инициализацию(2D иниц., 3D есть но там просто пример программы и без описания функций). Про GraphABC забудем как про страшный сон, создаём форму, создаём элемент Graphics чтоб рисовать на ней, И ВОТ ПРОБЛЕМА с которой сталкиваются многие, больше 20fps даже мощнейший компьютер с офигенной видеокартой не даст, что же не так? Оказалось что все движки и все игры без движков юзают низкоуровневые библиотеки типа OpenGL. И тут проблема уже в том что промежуточную инфу искать нереально. Когда я переходил от GraphABC на формы долго не мог найти информацию потому что её НЕТУ, почему то считается что все или дибилы или уже всё знают, и как раз про дырку между Graphics и OpenGl я бы хотел поговорить здесь.

Пожалуйста, кидайте сюда всё что вы знаете(кроме того что я уже сказал), надеюсь общими усилиями удастся научится и научить новичков в этом(таких как я).

Так же полагаю надо установить какие то рамки в которых надо писать в этой теме, самая большая проблема тут то что те кто уже всё знают любят найти в яндексе по вопросу рандомный сайт, кинуть ссылку и типо отмучался, поэтому правила:

  1. если и ссылаетесь на какой то ресурс - всё равно опишите тут так чтоб все поняли

  2. писать только про PascalABC.net, по фри паскаль есть тоже свои темы, но так по своему, я хочу чтоб те что ещё не потеряли душу в поисках хоть чего то от OpenGL могли найти тут именно по этой узкой тебе

И так, то что я узнал ещё:

  1. Рисование на форме должно быть в толи в 1 потоке с формой толи хз(прост по другому чёрный экран), вот пример проги OpenGL test.pas (там в консоле инфа сколько миллисекунд на 60 кадров).

  2. glPushMatrix и glPopMatrix работают как begin и end, между ними можно изменять свойства матрицы(glTranslate - перемещение точки отсчёта координат и glRotate - поворот пространства вокруг вектора, к примеру) которые после glPopMatrix вернутся к предыдущим, можно делать несколько слоёв glPushMatrix и glPopMatrix друг в друге. Если надо повернуть 2D то указывайте вектор (0;0;1), или (0;0;-1) это векторы перпендикулярные экрану.

Вообще есть пара статей (tap и tap). Но первая по Free Pascal, хотя и есть некоторая совместимость, а вторая вообще по c++, но тоже принцип один и тот же. Ещё я где-то находил модуль OpenGL для PABC.NET(OpenGL.pas (156,8 КБ) OpenGL.pcu (262,5 КБ)) (Первый файл кидаешь в “[папка установки PABC.NET]\LibSource”, а второй в “[папка установки PABC.NET]\Lib”), Но я не помню он вообще работает или нет, дабы не приходилось ещё пользоваться OGL’ом. Я даже не знаю его)))

А про дебилов ты верно сказал))) Хрен чаво найдёшь в инете! Я .NET библиотеки познавал методом тыка (и дизайнера в PABC.net) Да и вообще приходилось Pascal учить так, правда мощный толчок учительница инфы дала)))

1 лайк

лол OpenGL.pas и OpenGL.psu входят в стандартный пакет паскаля (вообще я тож только сегодня узнал, но проверил и ДА, таки есть)

первый tap видел но на фри паскале код вообще другой(потому второе правило, добавил как нашёл тот что ты кинул) второй tap не рабочий

Зайдите на сайт http://www.cyberforum.ru/ В разделе, посвящённом PascalABC.NET есть прикреплённая тема „Полезные коды для PascalABC.NET“. В ней ищите вопрос „Можно ли сделать 3D игру на PascalABC.NET? Если да, то как?“… Там модуль OpenGL и для примера пара игрушек.

видели, игрушки устарели и чутка надо переписать код по мелочам(к примеру reference не так записано), но понять по ним сложно, а OpenGL это часть стандартный модулей паскаля, лежит там же где грапх абц, ещё раз повторюсь - правило 1: не ссылатся тупо на что то а объяснять тут какую то конкретную часть

Вот такая же история

Не сильно много я с того момента научился но вот сейчас застрял на моменте с текстурами BMtGL.pas (791 Байт) OpenGL test.pas (6,5 КБ) BMtGL это модуль для загрузки изображений, простейший… Если на строке 83 поставить } то нормально рисуется 2 пересекающиеся кубика с разноцветными сторонами, по этой проге будет удобно начать програмить на OpenGL но сейчас про текстуры, я много лазил по форумам и то что эта штука рисуется белая не говорит ничего кроме как что есть ошибка, просто стандартная реакция OpenGL. Так что же я делаю не так? больше всего брал с http://www.cyberforum.ru, не забывая про msdn

Для начала стоит задать себе вопрос, действиельно ли вы хотите заниматься графикой на Паскале.

ну юнити точно не для меня, просто не люблю когда среда за моей спиной дофига делает того что я не понимаю… на C переучиваться в падлу, на паскале есть всё из C если хорошо поискать да и примеры из C подходят чтоб на паскале учиться, довольно похоже.

@Sun_Serega, здравствуйте, недавно (в ноябре прошлого года:slight_smile:) начал учить OpenGL, а поскольку не знал других языков - на PascalABC.NET. На мой дилетантский взгляд, лучшая литература по OpenGL - Красная книга http://www.hardforum.ru/download/RedBook.pdf. Так вот, в Вашей программе почему glEnable(GL_TEXTURE_2D); ? Когда должно быть 3D. Просто поменять “GL_TEXTURE_2D” на “GL_TEXTURE_3D” - не получится… потому что там нет этой константы, и многих функций для работы с текстурами тоже нет. Выход есть - взять из одноимённой библиотеки Делфи недостающее, и перекомпилировать библиотеку, но скажу честно, разобраться с текстурами так и не получилось:smiley: 2D-текстуры моделировать можно, рисуя поточечно загруженную картинку, но вряд ли Вы создаёте 2Dшную игру:slight_smile: У меня, кстати, сохранились учебные программки, но они абсолютно некомментированы…

Вот небольшой пример. Нужно ещё создать форму, добавить на неё события и таймер, чтоб скомпилировать. А чтоб заработала, как надо, нужно рядом с программой положить две папки: “Гласные” и “Согласные”. Там должны быть файлы следующего содержания: “А.png” - с цветом буквы А, “Б.png” - с цветом буквы Б, и т.д., можно и всего одну букву кинуть, программа не сломается. Единственное, что она делает, по нажатию клавиши печатает кубик заданного цвета. Стрелки и NumLock для камеры, “!” и “@” - переключение режимов.

Unit Unit1;

{$reference System.Windows.Forms.dll}
{$reference System.Drawing.dll}

interface

uses System, System.Windows.Forms, OpenGL, System.IO, System.Drawing;

Const
     R2 = 333;
     D2 = 1;
  
type
  Form1 = class(Form)
    procedure Form1_Shown(sender: Object; e: EventArgs);
    procedure Form1_KeyDown(sender: Object; e: KeyEventArgs);
    procedure Рисование(sender: Object; e: EventArgs);
    //procedure КолёсикоМыши(sender: Object; e: MouseEventArgs);
    procedure Кубик(X,Y,Z:real);
    Begin
    glBegin(GL_Quads);
    
    glVertex3f(0,Y,0);
    glVertex3f(X,Y,0);
    glVertex3f(X,Y,Z);
    glVertex3f(0,Y,Z);
    
    glVertex3f(X,Y,0);
    glVertex3f(X,Y,Z);
    glVertex3f(X,0,Z); 
    glVertex3f(X,0,0);
    
    glVertex3f(0,Y,0);
    glVertex3f(0,Y,Z);
    glVertex3f(0,0,Z);
    glVertex3f(0,0,0);
    
    glVertex3f(0,Y,Z);
    glVertex3f(X,Y,Z);
    glVertex3f(X,0,Z);
    glVertex3f(0,0,Z);
    
    glVertex3f(0,Y,0);
    glVertex3f(X,Y,0);
    glVertex3f(X,0,0);
    glVertex3f(0,0,0);
    
    glVertex3f(0,0,0);
    glVertex3f(X,0,0);
    glVertex3f(X,0,Z);
    glVertex3f(0,0,Z);
    
    glEnd;
    
    End;
    {
    Procedure КонтурКубика(X,Y,Z:real);
    Begin{
    X:=X+10;
    Y:=Y+10;
    Z:=Z+10;}{
    Var R:real:=0;
    glBegin(GL_Quads);
    
    glVertex3f(R,Y,R);
    glVertex3f(X,Y,R);
    glVertex3f(X,Y,Z);
    glVertex3f(R,Y,Z);
    
    glVertex3f(X,Y,R);
    glVertex3f(X,Y,Z);
    glVertex3f(X,R,Z); 
    glVertex3f(X,R,R);
    
    glVertex3f(R,Y,R);
    glVertex3f(R,Y,Z);
    glVertex3f(R,R,Z);
    glVertex3f(R,R,R);
    
    glVertex3f(R,Y,Z);
    glVertex3f(X,Y,Z);
    glVertex3f(X,R,Z);
    glVertex3f(R,R,Z);
    
    glVertex3f(R,Y,R);
    glVertex3f(X,Y,R);
    glVertex3f(X,R,R);
    glVertex3f(R,R,R);
    
    glVertex3f(R,R,R);
    glVertex3f(X,R,R);
    glVertex3f(X,R,Z);
    glVertex3f(R,R,Z);
    
    glEnd;
    End;}
    procedure Form1_KeyPress(sender: Object; e: KeyPressEventArgs);
    procedure Form1_Load(sender: Object; e: EventArgs);
  {$region FormDesigner}
  private
    {$resource Unit1.Form1.resources}
    timer13: Timer;
    components: System.ComponentModel.IContainer;
    {$include Unit1.Form1.inc}
  {$endregion FormDesigner}
  public
  АдресОкна:integer;
  U1,U2,X0,Y0,Z0:real;
  R:real:=-125;
  Высота:real:=0;
  
  X,Y,Z:real;
  МассивОтрисовки:array[0..255,0..3] of byte;
  n:Byte;
  Режим:byte:=1;
  C:array[char,0..3] of byte;
  Диск:GLUquadricObj;
  Радиус:real;
    constructor;
    begin
      //self.MouseWheel+=КолёсикоМыши;
      InitializeComponent;
      АдресОкна:=GetDC(self.Handle.ToInt32);
      OpenGLInit(self.Handle);
    end;
    
    
    procedure Сопоставление();
    Begin
    Var S:=System.IO.Directory.GetFiles(GetDir+'\Гласные');
    Var Картинка:BitMap;
    Var ARGB:Color;
    Var Буква:char;
    For var i:= 0 to S.Length -1 do
        Begin
        Картинка:=new Bitmap(S[i]);
        Буква:=UpCase(ExtractFileName(S[i])[1]);
        WriteLn(S[i],' ',Картинка.GetPixel(0,0));
        ARGB:=Картинка.GetPixel(0,0);
        C[Буква,0]:=ARGB.R;
        C[Буква,1]:=ARGB.G;
        C[Буква,2]:=ARGB.B;
        C[Буква,3]:=100;
        End;
    S:=System.IO.Directory.GetFiles(GetDir+'\Согласные');
    For var i:= 0 to S.Length -1 do
        Begin
        Картинка:=new Bitmap(S[i]);
        Буква:=UpCase(ExtractFileName(S[i])[1]);
        WriteLn(S[i],' ',Картинка.GetPixel(0,0));
        ARGB:=Картинка.GetPixel(0,0);
        C[Буква,0]:=ARGB.R;
        C[Буква,1]:=ARGB.G;
        C[Буква,2]:=ARGB.B;
        C[Буква,3]:=50;
        End;
    End;
  end;

implementation
{
procedure Form1.КолёсикоМыши(sender: Object; e: MouseEventArgs);
  Var
     D:=e.Delta / 120;
  Begin
  Высота+=D;
  R+=D;
  End;
}
procedure Form1.Form1_Shown(sender: Object; e: EventArgs);
begin
  glViewPort(0,0,Width,Height);
  glMatrixMode(GL_Projection);
  glLoadIdentity;
  gluPerspective(60,Width/Height,10,3000000);
  glMatrixMode(GL_ModelView);
  glClearColor(1,1,1,0);
  glHint(GL_NICEST,GL_PERSPECTIVE_CORRECTION_HINT);
  //glCullFace(GL_Back);
  //glEnable(GL_Cull_Face);
  glShadeModel(GL_Smooth);
  
  glClearDepth(1.0);
  glEnable(GL_Depth_Test);
  glDepthFunc(GL_LEQUAL);
  X:=50;
  Y:=50;
  Z:=50;
  Y0:=Y/2;
  U1:=90;
  Диск:=gluNewQuadric();
  gluQuadricDrawStyle(Диск,GLU_Fill);
  gluQuadricNormals(Диск,GLU_SMOOTH);
end;



procedure Form1.Form1_KeyDown(sender: Object; e: KeyEventArgs);
begin
  WriteLn(e.KeyData,' = ',e.KeyValue);
  Case e.KeyValue of
  8:
    if n > 0 then
       Begin
          Begin
          if МассивОтрисовки[n,3] <> 255 then
             X0:=X0+МассивОтрисовки[n,3]
          else X0:=X0+50
          End;
       n:=n-1
       End;
  32:
     if n < 255 then
        Begin
        n:=n+1;
        МассивОтрисовки[n,3]:=255;
        X0:=X0-50;
        End;
  97:; //1
  {98:
     Begin
     Z0-=10;
     End;//2}
  99:Y0-=10; //3
  100:
      Begin
      X0+=10;
      
      End;//4
  101:; //5
  102:
      Begin
      X0-=10;
      End;//6
  103:; //7 
  {104:
      Begin
      Z0+=10;
      End;//8}
  105:Y0+=10; //9
  
  107:R+=25;
  109:R-=25;
  
  37:U2-=0.03;
  38:U1-=0.03;
  39:U2+=0.03;
  40:U1+=0.03;
  49:Режим:=1;
  50:Режим:=2;
  116:Сопоставление;
  End;
end;

procedure Form1.Рисование(sender: Object; e: EventArgs);
begin
  glClear(GL_Color_Buffer_Bit or GL_Depth_Buffer_Bit);
  glLoadIdentity;
  {
  glBegin(GL_Lines);
  glVertex3f(X0,Y0,Z0);
  glVertex3f(X0,Y0+30,Z0);
  glVertex3f(X0-30,Y0,Z0);
  glVertex3f(X0+30,Y0,Z0);
  glVertex3f(X0,Y0,Z0-30);
  glVertex3f(X0,Y0,Z0+30);
  glEnd;}
  Case Режим of
  1:
    Begin
    gluLookAt(+X0+R*Sin(U1)*Sin(U2),Y0+R*Cos(U1),Z0+R*Sin(U1)*Cos(U2),+X0,Y0,Z0,0,1,0);
    if МассивОтрисовки[1,3] <> 255 then
       Begin
       glPolygonMode(GL_Front_and_Back,GL_Fill);
       glColor3ubv(@МассивОтрисовки[1,0]);
       Кубик(-МассивОтрисовки[1,3]*1.5,Y,Z);
       {
       glColor3f(0,0,0);
       glPolygonMode(GL_Front_and_Back,GL_Line);
       КонтурКубика(-(МассивОтрисовки[1,3])*1.5,Y,Z);
       }
       glTranslate(-(МассивОтрисовки[1,3])*1.5,0,0);
       End
    else
       Begin{
       glColor3f(0,0,0);
       glPolygonMode(GL_Front_and_Back,GL_Line);
       КонтурКубика(-75,Y,Z);
       }
       glTranslate(-75,0,0);
       End;
    
    
    
    For var i:= 2 to n do
        Begin
        if МассивОтрисовки[i,3] <> 255 then
           Begin
           glPolygonMode(GL_Front_and_Back,GL_Fill);
           glColor3ubv(@МассивОтрисовки[i,0]);
           Кубик(-МассивОтрисовки[i,3],Y,Z);
           {
           glColor3f(0,0,0);
           glPolygonMode(GL_Front_and_Back,GL_Line);
           КонтурКубика(-(МассивОтрисовки[i,3]),Y,Z);
           }
           glTranslate(-(МассивОтрисовки[i,3]),0,0);
           End
        else
           Begin{
           glColor3f(0,0,0);
           glPolygonMode(GL_Front_and_Back,GL_Line);
           КонтурКубика(-50,Y,Z);
           }
           glTranslate(-50,0,0);
           End
        End;
    End;
  2:
    Begin
    gluLookAt((R-Радиус)*Sin(U1-45)*Sin(U2),(R-Радиус)*Cos(U1-45),(R-Радиус)*Sin(U1-45)*Cos(U2),0,0,0,0,1,0);
    Радиус:=0;
    if МассивОтрисовки[1,3] <> 255 then 
       Begin
       glColor3ubv(@МассивОтрисовки[1,0]);
       gluDisk(Диск,0,МассивОтрисовки[1,3]*1.5,R2,D2);
       Радиус:=Радиус+МассивОтрисовки[1,3]*1.5;
       End
    else Радиус:=Радиус+50;
    For var i:= 2 to n do
        Begin
        if МассивОтрисовки[i,3] <> 255 then
           Begin
           glColor3ubv(@МассивОтрисовки[i,0]);
           gluDisk(Диск,Радиус,Радиус+МассивОтрисовки[i][3],R2,D2);
           Радиус:=Радиус+МассивОтрисовки[i][3];
           End
        else Радиус:=Радиус+50;
        End;
    End;
  End;
  SwapBuffers(АдресОкна);
end;



procedure Form1.Form1_KeyPress(sender: Object; e: KeyPressEventArgs);
begin
  Var Буква:=UpCase(e.KeyChar);
  //WriteLn(Буква,' = ',Ord(Буква));
  if Ord(Буква)>32 then
     if n < 255 then
        if C[Буква,3]<>0 then
           Begin
           n:=n+1;
           МассивОтрисовки[n,0]:=C[Буква,0];
           МассивОтрисовки[n,1]:=C[Буква,1];
           МассивОтрисовки[n,2]:=C[Буква,2];
           МассивОтрисовки[n,3]:=C[Буква,3];
           X0:=X0-C[Буква,3];
           End
end;

procedure Form1.Form1_Load(sender: Object; e: EventArgs);
begin
  Сопоставление();
end;

end.

Нельзя было проект целиком скинуть, т.к. новичок. Уже стало можно: Цветной алфавит.rar (54,5 КБ)

Брр, такой патриотичный код мне даже в страшном сне не приснится. @Admin, а зачем оно надо было?

на сколько я знаю 3D текстура это как раз отдельное понятие, то есть в ней у самой текстуры будет 3 измерения, а ещё я свои попытки сделать текстуру делал и на 2D плоскости с точно таким же кодом, в итоге накладывал не на кубик а на квадрат…

OpenGL вообще поддерживает только трёхмерные структуры, там у всего, что имеет координаты их будет три. То есть, и у одномерной текстуры будет три измерения. Просто 2D-текстуры накладываются на плоскость, а 3D, на объёмную фигуру. С квадратом, разумеется лучше использовать двумерные, они и в памяти меньше займут, чем одна трёхмерная, а вот со сферой, например, так не получится…

2D текстуры должны всё равно работать, вряд ли разрабы OpenGL ошиблись, скорее те кто делали модуль для паскаля, где то указав не правильный код константы, или что то типо того… жаль что на msdn нету кода каждой константы, по крайней мере искал для GL_Texture_2D и нашёл только где она применяется, ну то есть ничего

P.S. в OpenGL везде старались обходить динамическую память(и прекрасно понятно почему), к примеру рисуя на 2D - рисуешь на 3D с координатой Z=0, при этом с Rotate можно сделать несколько очень прикольных видов если вертеть не вокруг вектора [0,0,a]

Все константы можно брать из модулей Си и Делфи, также как и функции, но брать придётся. В красной книге в 9-ой главе (текстурирование) есть несколько примеров кода на С++. Будучи переведёнными на ABC.NET они не скомпилируются, т.к. нет всех констант и функций для работы с текстурами. В дельфишном модуле вообще больше 20 тыс. строк, в отличие от 3,5 тыс. ABC.NET - там очень много отсутствует…

ну я ща проверю правильность констант, посмотрю их в дельфи модуле, функции я сам добавляю те что не хватает, но самое неприятное что я брал примеры файлов на C++ которые действительно пашут, там exe-шник в архиве рядом и переводил на паскаль - не пашет! вот они кстати: glutdlls37beta.zip (145,6 КБ) gl_bmp_loader.zip (72,2 КБ) gl_tga_loader.zip (90,8 КБ)

Скажу сразу: забудьте про GLUT, в ABC.NET уже есть дизайнер форм, обработка событий и т.д. Чтобы загрузить картинку тоже много не надо - одна строка:

Var Текстура:= new Bitmap('C:\Картинка.jpg');

Дальше в массив байтов её и в текстуру, или сразу на экран, если это, например, элементы меню, которые не надо поворачивать:

procedure ОтрисовкаМеню();
Begin
glMatrixMode(GL_Projection);
glPushMatrix;
glViewPort(0,0,Width,Height);
gluOrtho2D(0,Width,Height,0);
glMatrixMode(GL_ModelView);

glColor4b(Меню[0].Заливка[0],Меню[0].Заливка[1],Меню[0].Заливка[2],Меню[0].Заливка[3]);
glBegin(GL_Polygon);
glVertex2f(Меню[0].Ширина[1],Меню[0].Высота[1]);
glVertex2f(Меню[0].Ширина[2],Меню[0].Высота[1]);
glVertex2f(Меню[0].Ширина[2],Меню[0].Высота[2]);
glVertex2f(Меню[0].Ширина[1],Меню[0].Высота[2]);
glEnd;


For var n:= 1 to Меню.Length-1 do
if (Меню[n].Вкладка = ТекущаяВкладка)or(Меню[n].Вкладка < 0) then
Begin

if Меню[n].Текстура <> nil then
Begin
glBegin(GL_Points);
For var x:=0 to Меню[n].Текстура.Width-1 do
    For var y:= 0 to Меню[n].Текстура.Height-1 do
        Begin
        glColor4ubv(@Картинка[n,x,y,0]);
        glVertex2f(x+Меню[n].Ширина[1],y+Меню[n].Высота[1]);
        End;
glEnd;
End;


End;
glMatrixMode(GL_Projection);
glPopMatrix;
glMatrixMode(GL_ModelView);
End;

Покажите свои переводы, пожалуйста. Надеюсь найти ошибки, и заставить пахать текстуры в ABC.NET :slight_smile: У меня получалось наложить текстуру… но отображалась она неправильно.

то что у меня получилось после перевода англ вышло хуже чем то что я по крошкам насобирал в инете, но давай ты для начала скачаешь ту штуку что я на кубик накладывал, ща пыхчу над тем чтоб 2D фигню восстановить после того как её чутка переделал и не сохранил… ну точнее до момента как я пишу сюда я подчистил за собой мой модуль который упрощает работу с 2D OpenGL, давно надо было его в порядок привести… да и нафига ты юзаешь полигон там где можно юзать прямоугольник? если сделали кроме полигона другие фигуры, с закреплённым числом вершин - значит они лучше, скорее всего быстрее пашут… тут плевать а вот в больших проектах… не стоит привыкать

. . . значит вернул я как мог 2D прогу с текстурами… и текстуры нарисовались! спрашивается - какого фига… вот значит вся папка (51,9 КБ) оттуда пашет Texture OpenGL test и не пашет то что там второе… да названия… знаю… ну не важно, то что другое то 3D, exe файл у меня вообще ни разу не запустился а через паскаль - текстура не накладывается, вместо этого рисуется прямоугольник, да ещё и со сломаной прозрачностью, точнее как будто у него чёрная подстилка под ним… а да, текстуру пытается наложить на левый кубик, нижнюю сторону