Skip to content

tokoik/glsl1

Repository files navigation

glsl1 - 第1回 シェーダプログラムの読み込み サンプルプログラム

1. 概要

このプログラムは、OpenGL における「テクスチャマッピング (Texture Mapping)」の基礎を学ぶための、学生向けのサンプルプログラムです。本プログラムは、以下のブログ記事の解説に沿って学習を進めるための雛形として提供されています。

現段階では赤い1枚の四角形ポリゴンが表示されるだけのシンプルな内容となっています。マウスのドラッグ操作によって、表示されている四角形をぐるぐると回転させることができます。

1枚の四角形

これは、ブログ記事の手順に従って、ひな型プログラム を書き換えたものです。

2. ビルド方法

このプログラムは CMake を用いてビルド環境を整備します。各OSとも、ソースコードが置かれているディレクトリにターミナル(またはコマンドプロンプト)で移動してから、以下の手順を実行してください。なお、プログラムをビルドするためのバイナリディレクトリは、バージョン管理ファイル(.gitignore)の設定に合わせて build という名前にします。

2.1 Windows (Visual Studio 2022 の場合)

  1. コマンドプロンプトまたは PowerShell を開き、このプロジェクトのディレクトリに移動します。

  2. 以下のコマンドを実行してビルドディレクトリを作成し、CMake で構成を行います。

    mkdir build
    cd build
    cmake .. -G "Visual Studio 17 2022"
  3. 生成された build フォルダ内の glsl1.sln を Visual Studio で開きます。

  4. ソリューションエクスプローラーで glsl1 プロジェクトを右クリックし、「スタートアップ プロジェクトに設定」を選択します。

  5. 「ローカル Windows デバッガー」をクリックするか、F5 キーを押してビルドおよび実行します。

2.2 macOS (Xcode の場合)

  1. ターミナルを開き、このプロジェクトのディレクトリに移動します。

  2. 以下のコマンドを実行してビルドディレクトリを作成し、Xcode 用のプロジェクトを生成します。

    mkdir build
    cd build
    cmake .. -G Xcode
  3. 生成された build/glsl1.xcodeproj を Xcode で開きます。

  4. 左上のスキーム選択(再生ボタンの横)が glsl1 になっていることを確認します。

  5. 「Run」ボタン(再生ボタン)をクリックするか、Command + R を押してビルドおよび実行します。

2.3 Ubuntu Linux

  1. ターミナルを開き、このプロジェクトのディレクトリに移動します。

  2. 必要なパッケージ(freeglut3-dev など)がインストールされていることを確認し、以下のコマンドでビルドします。

    mkdir build
    cd build
    cmake ..
    make

3. 使い方

3.1 プログラムの起動方法

各OSとも、ビルド後に生成されるバイナリディレクトリ (build) やそのサブフォルダから起動します。(※ CMake の設定により、Windows や Xcode では Debug などのフォルダ下に実行ファイルが置かれることがあります)

  • Windows

    Visual Studio 上で「ローカル Windows デバッガー」をクリックして実行するか、またはコマンドプロンプトから以下のコマンドで起動します。

    cd build\Debug
    glsl1.exe
  • macOS

    Xcode 上で左上の「Run(再生ボタン)」をクリックするのが楽です。これにより glsl1.app アプリケーションバンドルとして自動的に実行されます。アプリケーションバンドルを直接起動するなら、Finder から build/Debug/glsl1.app をダブルクリックするか、ターミナルから open build/Debug/glsl1.app を実行します (この場合はエラーメッセージ等が表示されません)。

  • Ubuntu Linux

    ターミナルから以下のコマンドで実行ファイル(バイナリ)を直接起動します。

    cd build
    ./glsl1

3.2 操作方法

  • マウスの左ボタンでドラッグ

    画面内のオブジェクト(四角形またはティーポット)を3次元的に回転させることができます。

  • キーボードの q, Q または ESC キー

    プログラムを終了します。

4. 解説

このプログラムの主要なソースコードである main.cpp は、OpenGL (GLUT) と GLSL (OpenGL Shading Language) を組み合わせた基本的なプログラム構造を持っています。

プログラマブルシェーダの導入により、レンダリング時における頂点単位の処理(バーテックスシェーダ)や画素単位の処理(フラグメントシェーダ)をユーザーが自身で記述できるようになりました。本プログラムでは、シェーダプログラムを実行時に読み込み、コンパイル・リンクして適用する手順を実装しています。

4.1 GLSL シェーダ利用の手順

GLSL でシェーダプログラムを利用する手順は以下の通りです。

  1. GLSL の初期化 (glslInit())

    Windows環境では標準で OpenGL 1.1 の機能しか直接サポートされていないため、GPU ドライバが提供する拡張機能(OpenGL 2.0以降)をプログラムから呼び出すためのエントリポイント(関数ポインタ)を初期化・取得します。

  2. シェーダオブジェクトの作成 (glCreateShader())

    バーテックスシェーダ用 (GL_VERTEX_SHADER) とフラグメントシェーダ用 (GL_FRAGMENT_SHADER) のシェーダオブジェクトを作成します。

  3. ソースプログラムの読み込み (readShaderSource())

    外部ファイル(simple.vert および simple.frag)からシェーダのソースコードを読み込み、glShaderSource() を通じてシェーダオブジェクトに渡します。

  4. ソースプログラムのコンパイル (glCompileShader())

    読み込んだソースプログラムをコンパイルします。コンパイル成否は glGetShaderiv() を用いて GL_COMPILE_STATUS をチェックし、エラーがあれば printShaderInfoLog() でログを標準エラー出力します。

  5. プログラムオブジェクトの作成 (glCreateProgram())

    複数のシェーダをまとめるためのプログラムオブジェクトを作成します。

  6. シェーダオブジェクトの登録と削除設定 (glAttachShader(), glDeleteShader())

    作成したプログラムオブジェクトに、コンパイル済みの各シェーダオブジェクトを登録(アタッチ)します。登録したシェーダオブジェクトは、この時点で不要になるため削除マーク(glDeleteShader())を付けておきます。

  7. シェーダプログラムのリンク (glLinkProgram())

    プログラムオブジェクトをリンクし、実行可能なシェーダプログラムを生成します。リンク成否は glGetProgramiv()GL_LINK_STATUS をチェックし、エラーがあれば printProgramInfoLog() でログを出力します。

  8. シェーダプログラムの適用と解除 (glUseProgram())

    描画前に glUseProgram(gl2Program) を呼び出してシェーダプログラムを適用し、描画終了後に glUseProgram(0) を呼び出して適用を解除し、従来の固定機能パイプラインに戻します。

4.2 主要関数の役割と処理内容

  • init() 関数

    プログラム起動時に一度だけ呼ばれる初期化関数です。

    • glslInit() で GLSL の初期化を行い、simple.vert(バーテックスシェーダ)と simple.frag(フラグメントシェーダ)の読み込み・コンパイル・リンク処理を行ってプログラムオブジェクト gl2Program を作成します。
    • 背景色の設定、隠面消去(GL_DEPTH_TEST)の有効化、および光源(ライト)のパラメータ(位置、直接光、環境光など)の初期設定を行います。
  • scene() 関数

    実際に画面に表示される3Dモデルを描画する処理を行います。

    • ポリゴン(四角形)のマテリアル(材質)を設定します。
    • #define DRAW_TEAPOT 0 の場合は、glNormal3d() で法線ベクトルを指定し、glBegin(GL_QUADS) から glEnd() の間に頂点座標を指定して、1枚の四角形ポリゴンを描画します。
    • #define DRAW_TEAPOT 1 に書き換えることで、代わりに glutSolidTeapot(1.0) を呼び出して 3D のティーポットを描画することもできます。
  • display() 関数

    画面全体の描画処理を行います(システムの再描画要求ごとに呼び出されます)。

    • glUseProgram(gl2Program) を呼び出して、本プログラムでロードしたシェーダプログラムを適用します。
    • モデルビュー変換行列を初期化し、光源の位置を設定した上で、視点を少し後ろに下げ、トラックボール処理による回転行列を掛け合わせてオブジェクトの姿勢を決定します。
    • glClear() で画面をクリアした上で scene() を呼び出して描画を行います。
    • 描画終了後、glUseProgram(0) でシェーダプログラムを解除し、glutSwapBuffers() で画面を更新します(ダブルバッファリング)。
  • resize() 関数

    ウィンドウのサイズが変更されたり、最初にウィンドウが開かれた際に呼び出されます。

    • 変更されたウィンドウサイズをトラックボールに通知し、描画領域(ビューポート)を合わせます。
    • カメラのレンズに相当する透視投影(プロジェクション)行列の初期設定を行います。
  • mouse(), motion() 関数

    マウスによるドラッグ操作を処理します。トラックボール処理プログラムと連携し、クリックおよびドラッグした座標の差分からオブジェクトを回転させるための回転行列を計算します。

  • keyboard() 関数

    キーボードの入力を受け取ります。ESC キーや 'q', 'Q' キーが押されたときに exit(0) を呼び出して安全にプログラムを終了します。

  • idle() 関数

    プログラムの空き時間に呼び出され続け、常に画面の再描画要求 (glutPostRedisplay()) を行います。これにより、マウスドラッグを行っている間などにオブジェクトがスムーズにアニメーション(回転)するようになります。

  • main() 関数

    プログラムの開始地点です。GLUT の初期設定とウィンドウ作成を行い、各種イベントに対応するコールバック関数(display(), resize(), mouse(), motion(), keyboard())を登録します。その後 init() で初期化とシェーダの準備を行い、glutMainLoop() に入ってイベント待ち無限ループを開始します。

4.3 ロードされるシェーダについて

本プロジェクトで読み込まれるシェーダの処理内容は以下の通りです。

1. バーテックスシェーダ (simple.vert)

頂点ごとに実行されます。入力された頂点の座標値 gl_Vertex に、モデルビュー変換行列と透視変換行列の積 gl_ModelViewProjectionMatrix を掛け合わせ、最終的なスクリーン座標である gl_Position に出力します。

#version 120

// simple.vert

void main()
{
  // 頂点位置の変換計算
  gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}

2. フラグメントシェーダ (simple.frag)

画素(フラグメント)ごとに実行され、描画される面の色を決定します。このサンプルでは、すべてのピクセルの色を固定の赤色 vec4(1.0, 0.0, 0.0, 1.0) として gl_FragColor に出力しています。そのため、描画されるオブジェクト(四角形)は陰影のないフラットな赤色になります。

#version 120

// simple.frag

void main ()
{
  // フラグメントの色を固定で赤(R: 1.0, G: 0.0, B: 0.0, A: 1.0)にする
  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors