Help us understand the problem. What is going on with this article?

Windows上(Geforce)でOpenGL ES 3.0を試してみる。

More than 5 years have passed since last update.

はじめに

OpenGL ES 3.0、始まってきましたね。Androidが4.3にて正式サポートを開始し、いよいよモバイルデバイスでもPlayStation 3 / Xbox 360世代を少し上回るような高度な表現が可能になってきました。
いずれ、近いうちにiOSも追従してサポートするでしょうし、今後モバイルデバイスで3Dを扱いたい人はぜひES 3.0をマスターしましょう。

OpenGL ES 3.0で何が変わったかについては、以下のサイトが詳しいです。
組み込み向け3DグラフィックスAPIの最新版「OpenGL ES 3.0」が登場

しかし、試そうにもES 3.0に対応したモバイルデバイスはまだまだ少ないのが実情です。できれば、Windows上で試したいですよね。実は、デスクトップ向けのOpenGL4.3に対応したGPUでは、OpenGL ES 3.0互換環境を利用することができます。
この記事では、その利用方法(OpenGL ES 3.0コンテキストの初期化方法)について解説します。

前提知識

OpenGLについて、ある程度なれている方が前提です。
また、WGLについても、多少の知識があることが望ましいです。

前提環境

  • Window XP以降(筆者はWindows 7 64bit で動作確認)
  • OpenGL4.3に対応したnVidia社製 GPU(筆者はGeforce GT 520で動作確認)

(GPUのドライバーは最新のバージョンをインストールしてください)

準備

OpenGL Registry から wglext.h をダウンロードし、インクルードします。

コード説明

以下が初期化コードになります。
このコードだけじゃ全体像がわからないよ! という方は、
こちらのサイト様のサンプルコードをご覧ください。
OpenGL(WGL)サンプルプログラム on Windows7(fujinsブログ様)

以下のコードは、上記サイト様のサンプルコードの初期化コード部分を、私がOpenGL ES 3.0にあわせて改変したものになります。

ちなみにWGLとは、Windows依存のOpenGL関連機能(Windows向けのOpenGLレンダリングコンテキストを作成したり、OpenGLの拡張関数を取得するなど)を利用するためのAPIです。

処理の手順としては、次のようになります。
1. PIXELFORMATDESCRIPTOR型の変数として、ピクセルフォーマットを作成する。
2. ChoosePixelFormat() を使って、フォーマットのマッチングを行う。
3. 4のステップのために、通常の手段で 仮のContext を作成し wglMakeCurrent() でコンテキストを有効にする。
4. WGL の拡張 API 、wglCreateContextAttribsARB() を取得する。
5. wglCreateContextAttribsARB() を使って OpenGL ES 3.0 コンテキストを作る。
6. 3のステップで作った仮のコンテキストを削除する。

int initGL( HWND hwnd, HDC *p_hdc, HGLRC *p_hglrc ) {

    // ピクセルフォーマットの指定
    static PIXELFORMATDESCRIPTOR   pformat= {
        sizeof(PIXELFORMATDESCRIPTOR),
        1,
        0
        |PFD_DRAW_TO_WINDOW
        |PFD_SUPPORT_OPENGL
        |PFD_DOUBLEBUFFER
        ,
        PFD_TYPE_RGBA,
        32,     // color
        0, 0,   // R
        0, 0,   // G
        0, 0,   // B
        0, 0,   // A
        0, 0, 0, 0, 0,      // AC R G B A
        24,     // depth
        8,      // stencil
        0,      // aux
        0,      // layertype
        0,  // reserved
        0,  // layermask
        0,  // visiblemask
        0   // damagemask
    };

    // デバイスコンテキストを取得する
    HDC hDC= GetDC( hwnd );

    // フォーマットのマッチングを行う
    int pfmt= ChoosePixelFormat( hDC, &pformat );

    // ピクセルフォーマットを設定
    SetPixelFormat( hDC, pfmt, &pformat );

    // wglCreateContextAttribsARBを取得するために、仮のコンテキストを取得
    HGLRC hGLRC_old = wglCreateContext( hDC );

    // 仮のコンテキストを有効にする
    wglMakeCurrent( hDC, hGLRC_old );

    // wglCreateContextAttribsARB 関数の取得
    PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress( "wglCreateContextAttribsARB" );

    // 取得したいOpenGL環境(今回はES 3.0)の指定
    static const int  opengl_es30[]= {
      WGL_CONTEXT_MAJOR_VERSION_ARB,   3,
      WGL_CONTEXT_MINOR_VERSION_ARB,   0,
      WGL_CONTEXT_FLAGS_ARB,           0,
      WGL_CONTEXT_PROFILE_MASK_ARB,    WGL_CONTEXT_ES2_PROFILE_BIT_EXT,
      0,
    };
    // ES3.0のコンテキストを取得
    HGLRC hGLRC= wglCreateContextAttribsARB( hDC, 0, opengl_es30 );

    // コンテキストを有効にする
    wglMakeCurrent( hDC, hGLRC );

    // 仮のコンテキストを削除
    wglDeleteContext( hGLRC_old );

    // ベンダー情報の取得
    const GLubyte *strVendor = glGetString(GL_VENDOR);
    std::cout << "GL_VENDOR : " << strVendor << std::endl;

    // レンダラー情報の取得
    const GLubyte *strRenderer = glGetString(GL_RENDERER);
    std::cout << "GL_RENDERER : " << strRenderer << std::endl;

    // バージョン情報の取得
    const GLubyte *strVersion = glGetString(GL_VERSION);
    std::cout << "GL_VERSION : " << strVersion << std::endl;

    // OpenGL GLSL バージョンの取得
    const GLubyte * strShaderLanguageVersion = glGetString (GL_SHADING_LANGUAGE_VERSION);
    std::cout << "GL_SHADING_LANGUAGE_VERSION : " << strShaderLanguageVersion << std::endl;

    // OpenGL拡張の取得
    const GLubyte * strExtensions = glGetString (GL_EXTENSIONS);
    std::cout << "GL_EXTENSIONS : " << strExtensions << std::endl;


    *p_hdc= hDC;
    *p_hglrc= hGLRC;

    return 0;
}

描画コードについて

ただし、上記サイト様のサンプルコードの描画処理や透視変換関数は、OpenGL ES 3.0とは互換性がないため、描画コードもろもろ(シェーダーや頂点オブジェクトの作成処理なども含む)については床井研究室様の以下のページで説明されているサンプルコードを利用してください。
http://marina.sys.wakayama-u.ac.jp/~tokoi/?date=20120909

サンプルコード(main.cpp)への直リンク

ただし、このコードでも注意点が。Windowsでは、標準で使えるOpenGLの関数はバージョン1.1までのものしかなく、それ以外の最近の関数はwglGetProcAddress関数で取得する必要があります。
以下のように行ってください。

  PFNGLGENVERTEXARRAYSPROC glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)wglGetProcAddress( "glGenVertexArrays" );
  PFNGLBINDVERTEXARRAYPROC glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)wglGetProcAddress( "glBindVertexArray" );

また、シェーダープログラムについては、OpenGL ES 3.0に対応させるため、以下のコードで置き換えてください。

// バーテックスシェーダのソースプログラム
    static const GLchar vsrc[] =
    "#version 300 es\n"
    "in lowp vec4 pv;\n"
    "void main(void)\n"
    "{\n"
    "  gl_Position = pv;\n"
    "}\n";

  // フラグメントシェーダのソースプログラム
  static const GLchar fsrc[] =
    "#version 300 es\n"
    "out lowp vec4 fc;\n"
    "void main(void)\n"
    "{\n"
    "  fc = vec4(1.0, 0.0, 0.0, 0.0);\n"
    "}\n";

以上で、動作するはずです。以下のような描画が行えれば成功です。
無題.jpg

おわりに

一部のコードしか示さず、あとはあっちを参考にしてごにょごにょしろとか、おまいなめとんのか的な説明になってしまい大変申し訳ないです(汗)
私の手元で動いているコードを全部晒せれば手っ取り早いのですが、いろいろ汚いこともありまして、後日の課題とさせてくださいorz

ともかく、OpenGL4.3はOpenGL ES 3.0と互換性が確保されていますので、OpenGL4.3に対応するGPUならOpenGL ES 3.0のプログラム開発を行うことができます。
もちろん、本当にモバイルデバイスで動くかは、実機で検証した方がいいと思いますが、とっかかりの開発環境として使えると思います。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした