Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Настройка оффскрин рендеринга OpenGL в Delphi

Delphi , Графика и Игры , OpenGL

При работе с OpenGL в Delphi часто возникает потребность в рендеринге прямо на битмап для последующей обработки или отображения. В этой статье мы рассмотрим, как настроить оффскрин рендеринг OpenGL в Delphi и получить результат в виде битмапа.

Проблема

Разработчик создал приложение с множеством окон и контролов (2D рендеринг) и хочет рендерить каждое окно и управление на свой битмап. Пример кода, который у него есть:

uses
  dglOpenGL;

var
  BMP: TBitmap;
  DC, RC: HDC;

function TMainForm.Init: Boolean;
begin
  Result := InitOpenGL;
  if Result = True then
  begin
    BMP := TBitmap.Create;
    BMP.PixelFormat := pf24bit;
    BMP.Width := 1280;
    BMP.Height := 1024;

    DC := BMP.Canvas.Handle;
    RC := CreateRenderingContext(DC,
      [opGDI, opDoubleBuffered],
      24, 24, 0, 0, 0, 0);
    ActivateRenderingContext(DC, RC);

    glClearColor(0.27, 0.4, 0.7, 0.0);
    glViewport(0, 0, 1280, 1024);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity;
    glOrtho(0, 1280, 0, 1024, -1, 10);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity;
  end;
end;

procedure TMainForm.Render;
begin
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

  // Красный квадрат
  glColor3f(1, 0, 0);
  glBegin(GL_QUADS);
    glVertex2f(100, 100);
    glVertex2f(1280-100, 100);
    glVertex2f(1280-100, 1024-100);
    glVertex2f(100, 1024-100);
  glEnd;

  // Обмен буферами
  SwapBuffers(DC);
end;

При запуске приложения нет никакого вывода, но если использовать MainForm.Canvas.Draw(0, 0, BMP);, то появится белый прямоугольник. Разработчик хочет настроить приложение для оффскрин рендеринга, чтобы иметь возможность выполнять другие операции с битмапами, такие как рисование других изображений, текст или размытие.

Решение

OpenGL контексты должны создаваться,Matching целевой контекст устройства. Для окон они создаются другим образом, чем для битмапов. Смотрите msdn.microsoft.com/en-us/library/windows/desktop/dd368826(v=vs.85).aspx, в частности, флаги dwFlags, где есть, среди прочего:

  • PFD_DRAW_TO_WINDOW: Буфер может рисовать на окно или поверхность устройства.
  • PFD_DRAW_TO_BITMAP: Буфер может рисовать на память битмап.

Однако не спешите создавать контекст рендеринга для вашего DIB DC, так как OpenGL контексты рендеринга на разделе DIB будут использовать программный растеризатор, поддерживающий только OpenGL-1.1, работающий на процессоре, что будет очень медленно.

Вместо этого создайте объект кадра (Framebuffer Object), прикрепите к нему цветной буфер рендеринга и, когда закончите, выполните glReadPixels в ваш DIBSection. Это намного проще и быстрее.

Пример кода

Вот пример функции, которая читает пиксели OpenGL в HBITMAP, который затем можно использовать в вашем приложении:

// Функция сбрасывает очередь ошибок OpenGL и подсчитывает общее количество ошибок
function FlushGLErrors: Integer;
begin
  Result := 0;
  while (glGetError() <> GL_NO_ERROR) do
    Inc(Result);
end;

// Возвращает HBITMAP или NULL. HBITMAP должен быть освобожден с помощью DeleteObject
function ReadPixelsToHBITMAP(x, y, width, height: Integer): HBITMAP;
var
  pdata: Pointer;
  bmih: TBitmapInfoHeader;
begin
  Result := NULL;

  // Заполните заголовок BITMAPINFOHEADER
  bmih.biSize := SizeOf(TBitmapInfoHeader);
  bmih.biWidth := width;
  bmih.biHeight := -height; // -height, так как OpenGL использует координаты (0,0) в левом верхнем углу
  bmih.biPlanes := 1;
  bmih.biBitCount := 24;
  bmih.biCompression := BI_RGB;
  bmih.biSizeImage := 0;
  bmih.biXPelsPerMeter := 2835; // 72 DPI
  bmih.biYPelsPerMeter := 2835; // 72 DPI
  bmih.biClrUsed := 0;
  bmih.biClrImportant := 0;

  // Создайте DIBSection
  if CreateDIBSection(hdc, @bmih, DIB_RGB_COLORS, pdata, nil, 0) then
  begin
    // Сбросьте очередь ошибок OpenGL
    if FlushGLErrors = 0 then
    begin
      // Настройте параметры хранения пикселей
      glPixelStorei(GL_PACK_SWAP_BYTES, GL_FALSE);
      glPixelStorei(GL_PACK_LSB_FIRST, GL_TRUE);
      glPixelStorei(GL_PACK_ROW_LENGTH, 0);
      glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
      glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
      glPixelStorei(GL_PACK_SKIP_ROWS, 0);
      glPixelStorei(GL_PACK_ALIGNMENT, 1);

      // Проверьте наличие ошибок OpenGL
      if FlushGLErrors = 0 then
      begin
        // Прочитайте пиксели в буфер
        glReadPixels(x, y, width, height, GL_BGR, GL_UNSIGNED_BYTE, pdata);

        // Проверьте наличие ошибок OpenGL
        if FlushGLErrors = 0 then
          // Создайте HBITMAP из буфера
          Result := CreateBitmapFromDIBSection(pdata, width, height);
      end;
    end;
  end;
end;

После выполнения рендеринга вы можете вызвать функцию ReadPixelsToHBITMAP для получения HBITMAP, который затем можно использовать в вашем приложении. Не забудьте освободить HBITMAP, когда он больше не нужен, используя DeleteObject.

Вывод

может быть сложной задачей, но с правильным подходом и пониманием того, как работают OpenGL контексты, можно добиться отличных результатов. Используя Framebuffer Object и glReadPixels, вы можете легко получить результат рендеринга в виде битмапа, который можно использовать в вашем приложении.

Создано по материалам из источника по ссылке.

Настройка оффскрин рендеринга OpenGL в Delphi для получения результата в виде битмапа.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




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


:: Главная :: OpenGL ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-02-05 18:54:55/0.0039839744567871/0