スポンサーリンク

OpenGLをDIB Sectionに描いてオフスクリーンレンダリング

1. DIB の初期化関数

dibsection.h

#include <Windows.h>
#include <tchar.h>

struct rgb_t {
  unsigned char r;
  unsigned char g;
  unsigned char b;
  rgb_t(unsigned char R, unsigned char G, unsigned char B) :b(B), g(G), r(R) {}
  static const rgb_t White;
  static const rgb_t Black;
};


void createDIBsection24(
  HBITMAP* hBitmap,
  HDC* hMemDC,
  BITMAPINFO* bmpInfo,
  rgb_t** m_lpPixel,
  LONG width,
  LONG height);

void deleteDIBsection24(HDC hMemDC, HBITMAP hBitmap);

dibsection.cpp

#include "dibsection.h"

void createDIBsection24(
  HBITMAP* hBitmap,
  HDC* hMemDC,
  BITMAPINFO* bmpInfo,
  rgb_t** m_lpPixel,
  LONG width,
  LONG height)
{
  //DIBの情報を設定する
  bmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  bmpInfo->bmiHeader.biWidth = width;
  bmpInfo->bmiHeader.biHeight = -height; //-を指定しないと上下逆になる
  bmpInfo->bmiHeader.biPlanes = 1;
  bmpInfo->bmiHeader.biBitCount = 24;
  bmpInfo->bmiHeader.biCompression = BI_RGB;

  HDC hdc = CreateDC(_T("DISPLAY"), 0, 0, 0);

  *hBitmap = CreateDIBSection(hdc, bmpInfo, DIB_RGB_COLORS, (void**)m_lpPixel, NULL, 0);
  *hMemDC = CreateCompatibleDC(hdc);

  DeleteDC(hdc);

  SelectObject(*hMemDC, *hBitmap);

}


void deleteDIBsection24(HDC hMemDC, HBITMAP hBitmap) {
  DeleteDC(hMemDC);
  DeleteObject(hBitmap);
}

2.WGLの初期化関数

wingl.h

#include <Windows.h>

void initGL(HGLRC *hRC,HDC hdc);
bool DeInitGL(HGLRC hRC, HDC hdc);

wingh.cpp

ウィンドウに書き込む場合、PIXELFORMATDESCRIPTORのdwFlagsは:

PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER

のようになるが、DIBに書き込む場合はPFD_DRAW_TO_WINDOWの代わりにPFD_DRAW_TO_BITMAPを使い、かつ、PFD_SUPPORT_GDIを使う。

#include "wingl.h"
#include <Windows.h>


void initGL(HGLRC *hRC, HDC hdc) {
  static PIXELFORMATDESCRIPTOR pfd =
  {
    sizeof(PIXELFORMATDESCRIPTOR),
    1,
    PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
    PFD_TYPE_RGBA,
    24,
    0, 0, 0, 0, 0, 0,
    0,
    0,
    0,
    0, 0, 0, 0,
    32, //Z-Buffer
    0, //Stencil Buffer
    0,
    PFD_MAIN_PLANE,
    0, //Reserved
    0, 0, 0
  };

  SetPixelFormat(hdc, ChoosePixelFormat(hdc, &pfd), &pfd);
  *hRC = wglCreateContext(hdc); //レンダリングコンテキストの作成

  wglMakeCurrent(hdc, *hRC); //hRCを有効にする

}

bool DeInitGL(HGLRC hRC, HDC hdc) {
  //解放コード
  wglMakeCurrent(hdc, hRC); //元に戻してやる
  wglDeleteContext(hRC); //いらなくなったレンダリングコンテキストの破棄
  return true;
}

3.初期化

変数の定義(DIB Section用)

HBITMAP dib_hBitmap;
HDC dib_hMemDC;
BITMAPINFO dib_bmpInf
rgb_t* dib_lpPixel;

変数の定義(WGL用)

HGLRC wgl_hRC;

初期化

  switch (msg) {
  case WM_CREATE:
  {
    //DIB Sectionを作成(24Bit)
    createDIBsection24(
      &dib_hBitmap,
      &dib_hMemDC,
      &dib_bmpInfo,
      &dib_lpPixel,
      width,
      height);

    //OpenGL初期化
    initGL(&wgl_hRC, dib_hMemDC);

    draw();

    break;
  }

4.表示処理

  case WM_PAINT:
  {
    // 画像を表示
    PAINTSTRUCT ps;
    HDC hDC = BeginPaint(hwnd, &ps);

    BitBlt(hDC, 0, 0, width, height, dib_hMemDC, 0, 0, SRCCOPY);


    EndPaint(hwnd, &ps);

    break;
  }

  case WM_LBUTTONDOWN:
    //マウスをクリックしたら画像を更新して描画要求を出す
    draw();
    InvalidateRect(hwnd, nullptr, FALSE);
    break;

5.描画処理

void draw() {
  static int r = 0;

  wglMakeCurrent(dib_hMemDC, wgl_hRC);

  glClearColor(0, 0, 0, 1);
  glClear(GL_COLOR_BUFFER_BIT);

  glLoadIdentity();
  glRotated(r += 10, 0, 1, 0);

  glBegin(GL_QUADS);
  glColor3d(1, 0, 0);
  glVertex3d(-0.7, -0.7, 0);
  glColor3d(0, 1, 0);
  glVertex3d(-0.7, 0.7, 0);
  glColor3d(0, 0, 1);
  glVertex3d(0.7, 0.7, 0);
  glColor3d(1, 1, 1);
  glVertex3d(0.7, -0.7, 0);
  glEnd();

  glFlush();

  SwapBuffers(dib_hMemDC);
  wglMakeCurrent(dib_hMemDC, 0);

}

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: