TOTAL:673, TODAY:49

ドーナツモデルで光源処理

久しぶりのOpenGLプログラムです。今日は、トーラス(ドーナツですね)を描画します。まだ光源処理のサンプルを作成していなかったので、光源も使用します。まず、トーラスですが、図に示すような感じで、半径16の円をx方向に平行移動し、y軸回転させることで生成しています。円は、64個の頂点で分割されており、y軸回転も64分割です。プログラムでは、描画性能を上げるため、独立三角形ではなく、64個の三角形ストリップを用いています。キーボードで「d」を押せば、フィル描画、ライン描画(ワイヤフレーム)、ポイント描画とモードがトグルしますので、どのような三角形でできているかがわかると思います。

プログラムではFUTL_MakeTorus関数で、頂点の位置座標、法線座標、テクスチャ座標を作成します。同時にテクスチャ(BMPファイル)も読み込んでいます。内容はプログラムを見ていただければ、分かると思います。初期化時に、FUTL_MakeTorusでトーラスモデルを作成し、GLUTの描画コールバック関数内でFUTL_DrawTorusを呼び出し、毎フレーム描画しています。

int main(int argc, char *argv[])
{
    :   : 途中略 :   :

    /* トーラスモデル(ドーナツ)の作成 */
    if (FUTL_MakeTorus(texFile) < 0)
    {
        return -1;
    }

    :   : 途中略 :   :
}

/* 描画のコールバック関数 */
void display(void)
{
    :   : 途中略 :   :

    /* トーラスの描画 */
    triangles = FUTL_DrawTorus(count);

    :   : 途中略 :   :
}

光源処理は、光源とマテリアルを設定することで行います。光源設定はFUTL_SetLight関数で行っています。

/* 光源設定 */
int FUTL_SetLight(
    int lightID,
    FLight *lpLight
)
{
    glLightfv(lightID, GL_AMBIENT, (GLfloat *)(&(lpLight->ambient)));
    glLightfv(lightID, GL_DIFFUSE, (GLfloat *)(&(lpLight->diffuse)));
    glLightfv(lightID, GL_SPECULAR, (GLfloat *)(&(lpLight->specular)));
    glLightfv(lightID, GL_POSITION, (GLfloat *)(&(lpLight->position)));

    return 0;
}

光源パラメータは、次のような値を設定しています。今回、光源には平行光源を使用しており、+Z方向(0.0, 0.0, 1.0)から光を当てているような設定です。

/* 平行光源 */
FLight light = {
    0.0f, 0.0f, 1.0f, 0.0f,    /* postition(w=0.0fは平行光源) */
    1.0f, 1.0f, 1.0f, 1.0f,    /* ambient */
    0.8f, 0.8f, 0.8f, 1.0f,    /* diffuse */
    1.0f, 1.0f, 1.0f, 1.0f,    /* specular */
    0.0f, 0.0f, -1.0f,         /* spotDirection */
    0.0f,                      /* spotExpornent */
    180.0f,                    /* spotCutoff */
    1.0f, 0.0f, 0.0f           /* attenuation */
};

マテリアルは、FUTL_SetMaterial関数で行っています。単純に全パラメータを設定しています。

/* マテリアル設定 */
int FUTL_SetMaterial(
        FMaterial *lpMaterial
)
{
    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, 
                     (GLfloat *)(&(lpMaterial->ambient)));
    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, 
                      (GLfloat *)(&(lpMaterial->diffuse)));
    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, 
                      (GLfloat *)(&(lpMaterial->specular)));
    glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, 
                      (GLfloat *)(&(lpMaterial->emission)));
    glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, 
                      (GLfloat *)(&(lpMaterial->shininess)));

    return 0;
}

マテリアルパラメータは、torusmodel.cの中に定義されており、次のようになっています。

/* モデルのマテリアル */
static FMaterial material = {
    0.2f, 0.2f, 0.2f, 1.0f,         /* ambient */
    0.8f, 0.8f, 0.8f, 1.0f,         /* diffuse & alpha */
    1.0f, 1.0f, 1.0f, 1.0f,         /* specular */
    0.0f, 0.0f, 0.0f, 1.0f,         /* emission */
    64.0f                           /* shininess */
};

ということで、プログラムをコンパイルして実行すれば、次のような絵がでるはずです。キーボードで「p」ボタンを押せば、一時停止することができます。

この状態で、「d」ボタンを押せば、次のようなワイヤーフレーム表示になります。

ワイヤーフレーム表示にした時の方がかなり高速ですね。しかし、「文字描画と時間測定」で説明したように、ディスプレイの垂直同期をはずすと、ワイヤーフレームよりも、通常のフィル描画の方が圧倒的に高速になりますので、恐らくフィル描画(通常の描画)の方が高速だと思います。

最新の7件

OpenGL

電子工作

玄箱HG

ホームページ

日記

Copyright (C) 2007 Arakin , All rights reserved.