Чем можно заменить VBO буффер?

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

shyub
постоялец
Сообщения: 112
Зарегистрирован: 25.11.2014 22:15:19

Чем можно заменить VBO буффер?

Сообщение shyub »

Пытаюсь создать буффер VBO (OpenGL), но при вызове процедуры glGenBuffers( 1, @vId ); появляется сообщение "Проект project1 вызвал класс исключения External: SIGSEGV". Процедура glGenBuffers объявлена в модуле GLext, которая в свою очередь должна содержаться в OpenGL32.dll. После проверки OpenGL32.dll соответствующей процедуры в ней не обраружил (скорее всего VBO буффер OpenGL больше не поддерживает).
Посоветуйте, как можно решить задачу, чтобы поместить все примитивы картинки в видеопамять.
Devel0
новенький
Сообщения: 66
Зарегистрирован: 24.07.2011 10:43:13

Сообщение Devel0 »

В Windows очень старая версия opengl. Нужно использовать расширения (GLEW/GLU/и т.д.), тогда будет поддержка VBO.
zub
долгожитель
Сообщения: 2889
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

емнип VBO в старом контексте (который создается TOpenGLControl) доступен в виде расширения и вполне работает
Mirage
энтузиаст
Сообщения: 881
Зарегистрирован: 06.05.2005 20:29:07
Откуда: Russia
Контактная информация:

Сообщение Mirage »

Похоже, дрова просто не стоят на видео.
Osmiy
новенький
Сообщения: 46
Зарегистрирован: 07.05.2016 20:18:39

Сообщение Osmiy »

shyub, вызываете ли вы процедуру инициализации расширений?

Добавлено спустя 2 минуты 30 секунд:
Например Load_GL_VERSION_3_1 из модуля GLext.
shyub
постоялец
Сообщения: 112
Зарегистрирован: 25.11.2014 22:15:19

Сообщение shyub »

Проверил, все варианты функции от Load_GL_VERSION_1_2() до Load_GL_VERSION_4_0() возвращают false. Получается, что у меня отсутствует что ли OpenGL?
Файл в Opengl32.dll в Windows\system32 есть (установлен Windows-7 x32), версия файла 6.1.7600.16385 от 14.07.2009 г. Использую ноутбук Acer-5749 (i3), все драйвера установлены из "коробки". Видеоадаптер Intel HD Graphics 3000. Пакет LazOpenGLContext0.0.1 установлен.
Всё "рисование" (примитивы, текстуры, освещение, надписи, чайники и т.д.) в OpenGL работает. Единственная проблема - не могу получить доступ к буферам VBO и VAO, а без них для меня использование OpenGL утрачивает смысл... В чём может быть причина?
К стати, выше уже писал, в файле Opengl32.dll функция glGenBuffers почему-то отсутствует (проверял WinHEX-ом), хотя судя по glext она там должна быть. Скачал более свежую версию Opengl32.dll v.6.3.9600.16384 от 15.05.2014 г. и там glGenBuffers не обнаружил.
Osmiy
новенький
Сообщения: 46
Зарегистрирован: 07.05.2016 20:18:39

Сообщение Osmiy »

Надо разбираться почему false возвращает.
Mikhail
энтузиаст
Сообщения: 565
Зарегистрирован: 24.10.2013 16:06:47

Сообщение Mikhail »

Что возвращает glGetString(GL_VERSION)?

Добавлено спустя 3 минуты 54 секунды:
shyub писал(а):в файле Opengl32.dll функция glGenBuffers почему-то отсутствует

Ее там и не должно быть.
shyub
постоялец
Сообщения: 112
Зарегистрирован: 25.11.2014 22:15:19

Сообщение shyub »

glGetString(GL_VERSION) возвращает: "3.0.0 - Build 8.15.10.2342".

Добавлено спустя 15 минут 1 секунду:
Osmiy писал(а):Надо разбираться почему false возвращает.

Load_GL_VERSION_3_0(); запускал в TForm1.FormCreate, когда запустил в TForm1.OpenGLControl1Paint вернула "true", но даже если здесь делаю инициализацию VBO всравно та же ошибка.

Добавлено спустя 1 час 11 минут 31 секунду:
Перенёс инициализацию на кнопку, т.е. включаю "вручную" и добавил, как советовал Osmiy, функцию Load_GL_VERSION_3_1:

Код: Выделить всё

// Инициализация VBO-VAO.
procedure TForm1.Button2Click(Sender: TObject);
beginfunction VBOInit: boolean;
var
  Count:integer;
//  d: boolean=false;
begin
  Result:=false;
  Load_GL_VERSION_3_0();
//  glewInit(); // Вот так рекомендуют на С++, но в Lazarus-е нет glew.
  Count:=high(VertexBuffer)+1;
  glGenBuffers( 1, @vId );
  glBindBuffer(GL_ARRAY_BUFFER, vId );
  glBufferData(GL_ARRAY_BUFFER, sizeof(GLFLoat)*3*Count, @VertexBuffer[0],
  GL_STATIC_DRAW); // Передача массива вершин в ОЗУ видеокарты.
  glBindBuffer(GL_ARRAY_BUFFER,0);
  glGenBuffers( 1, @cId );
  glBindBuffer(GL_ARRAY_BUFFER, cId );
  glBufferData(GL_ARRAY_BUFFER, sizeof(GLUByte)*3*Count, @ColorBuffer[0],
  GL_STATIC_DRAW); // Передача массива цветов в ОЗУ видеокарты.
  glBindBuffer(GL_ARRAY_BUFFER,0);
  Result:=true;
end;
  if VBOInit then Label2.Caption:='VBO и VAO вкл.';
end;

Заработало! Почему-то при первой перерисовке procedure TForm1.OpenGLControl1Paint(Sender: TObject); не срабатывало. Может есть смысл поставить таймер и производить инициализацию через какой-то промежуток времени после первой перерисовки? И есть ли смысл использовать перерисовку OpenGLControl1, если планируется работать только с буферами?
Вообщни, самое главное, что получилось. Большое спасибо всем ответившим, особенно Osmiy и Mikhail!

Добавлено спустя 3 минуты 40 секунд:
Запускается, если ставлю от Load_GL_VERSION_2_0(); до Load_GL_VERSION_3_0(); (выше не работает, т.к. у меря 3-я версия OpenGL).
Аватара пользователя
Лекс Айрин
долгожитель
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград
Контактная информация:

Сообщение Лекс Айрин »

shyub писал(а): Может есть смысл поставить таймер и производить инициализацию через какой-то промежуток времени после первой перерисовки?


Проще, не делать при первой перерисовке. Возможно, что часть данных просто отсутствует в памяти и инициализируется позднее и в другом месте.
Аватара пользователя
Снег Север
долгожитель
Сообщения: 3067
Зарегистрирован: 27.11.2007 15:14:47
Контактная информация:

Сообщение Снег Север »

shyub, а вы не пробовали посмотреть исходники паскалевских движков - хотя бы хорошо известную GLscene? Или Castle engine?
fedan
новенький
Сообщения: 70
Зарегистрирован: 15.09.2016 20:18:48

Сообщение fedan »

Наклепал небольшой пример
simple_vbo.zip

Код: Выделить всё

program simple_vbo;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Interfaces, // this includes the LCL widgetset
  Forms, Dialogs, simple_vbo_main, glext, lazopenglcontext
  { you can add units after this };

{$R *.res}

begin
  if not Load_GL_VERSION_1_5() then
  begin
    ShowMessage('Load_GL_VERSION_1_5 failed');
    Exit;
  end;
  RequireDerivedFormResource:=True;
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

Код: Выделить всё

unit  simple_vbo_main;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, OpenGLContext, Forms, Controls, Graphics,
  Dialogs, gl, glext;

type

  { TForm1 }

  TForm1 = class(TForm)
    OpenGLControl1: TOpenGLControl;
    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
    procedure FormShow(Sender: TObject);
    procedure OpenGLControl1Paint(Sender: TObject);
  private
    vertices: GLuint;
    colors: GLuint;
    procedure OnAppIdle(Sender: TObject; var Done: Boolean);
  public

  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.FormShow(Sender: TObject);
const
  planeVertices: array[0..11] of GLfloat = (
    0.5, 0.5, 0.0,  //
    -0.5, 0.5, 0.0, //
    -0.5, -0.5, 0.0,//
    0.5, -0.5, 0.0  //
    );

  planeColors: array[0..11] of GLfloat = (
    1.0, 0.0, 0.0,  //
    0.0, 1.0, 0.0,  //
    0.0, 0.0, 1.0,  //
    1.0, 1.0, 1.0   //
    ); 
var
  ver: string;
begin
  ver := glGetString(GL_VERSION);
  if ver <> '' then
    Caption := 'Simple draw polygon with OpenGL - version: ' + ver
  else
    Caption := 'Simple draw polygon with OpenGL - version: <unknown>';

  glMatrixMode(GL_MODELVIEW);

  glGenBuffers(1, @vertices);
  glGenBuffers(1, @colors);

  glBindBuffer(GL_ARRAY_BUFFER, vertices);
  glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), @planeVertices[0],
    GL_STATIC_DRAW);

  glBindBuffer(GL_ARRAY_BUFFER, colors);
  glBufferData(GL_ARRAY_BUFFER, sizeof(planeColors), @planeColors[0], GL_STATIC_DRAW);


  Application.AddOnIdleHandler(@OnAppIdle);
end;

procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
  if CloseAction = caFree then
  begin
    glDeleteBuffers(1, @vertices);
    glDeleteBuffers(1, @colors);
  end;
end;

procedure TForm1.OpenGLControl1Paint(Sender: TObject);
begin
  glClearColor(0, 0, 0, 0);
  glClear(GL_COLOR_BUFFER_BIT);

  glBindBuffer(GL_ARRAY_BUFFER, vertices);
  glVertexPointer(3, GL_FLOAT, 0, nil);
  glEnableClientState(GL_VERTEX_ARRAY);

  glBindBuffer(GL_ARRAY_BUFFER, colors);
  glColorPointer(3, GL_FLOAT, 0, nil);
  glEnableClientState(GL_COLOR_ARRAY);

  glDrawArrays(GL_POLYGON, 0, 4);

  OpenGLControl1.SwapBuffers;
end;

procedure TForm1.OnAppIdle(Sender: TObject; var Done: Boolean);
begin
  Done := False;
  OpenGLControl1.Invalidate;
end;

end.
У вас нет необходимых прав для просмотра вложений в этом сообщении.
shyub
постоялец
Сообщения: 112
Зарегистрирован: 25.11.2014 22:15:19

Сообщение shyub »

Пример у вас получился на много меньше, чем у меня. Однако, попробовал запустить его, но не получилось. Версии менял от 1.5 до 3.0, но ничего не получилось. (У меня стоит Lazarus 1.6, FPC-3.0).
11.03.png

У меня значительно больше кода. Если можно оптимизировать, то было бы очень не плохо.
OpenGLBuffer_02_(Инициализация VBO).rar


Добавлено спустя 10 минут 42 секунды:
К стати, я пробовал у себя выполнять инициализацию (Load_GL_VERSION_3_0()) при первой перерисовке (procedure TForm1.OpenGLControl1Paint(Sender: TObject);) тоже не запускалась. Теперь включаю при первой перерисовке таймер на 1 секунду и по таймеру выполняю инициализацию.
При инициализации, если выбираю версию ниже 2.0, то тоже не запускается. Поэтому, мне кажется, надо стараться запускать либо поддерживаемую версию OpenGL, либо максимально возможную. Поэтому, может не совсем корректно, делаю вот так:

Код: Выделить всё

procedure VBOInit;
begin
  if not Load_GL_VERSION_3_3() then // Инициализация функйий OpenGL.
    if not Load_GL_VERSION_3_2() then
      if not Load_GL_VERSION_3_1() then
        if not Load_GL_VERSION_3_0() then
          if not Load_GL_VERSION_2_1() then
            if not Load_GL_VERSION_2_0() then begin
              Application.MessageBox('OpenGL не обнаружена.',
                'OpenGLBuffer_02_(Инициализация VBO)',MB_ICONWARNING + MB_OK);
              Form1.Close;
            end;
  Form1.Panel1.Caption:='Версия OpenGL '+glGetString(GL_VERSION);
.........................................................................
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Osmiy
новенький
Сообщения: 46
Зарегистрирован: 07.05.2016 20:18:39

Сообщение Osmiy »

Кстати, в моём проекте перед Load_GL_VERSION_3_1() стоит вызов метода OpenGLControl.MakeCurrent. Всё это происходит при создании главной формы. Без этого вызова всё летит в тар-тарары.
fedan
новенький
Сообщения: 70
Зарегистрирован: 15.09.2016 20:18:48

Сообщение fedan »

Я в линуксе проект делал, там всё работает, а перезагрузился в окна, да, не работает. :cry:
Последний раз редактировалось fedan 11.03.2017 02:31:24, всего редактировалось 4 раза.
Ответить