自己発光するオブジェクトのライティングを実装する(4-9. 相当)


はじめに

点光源、スポットライト光源と実装してきましたが、今回は自己発光するオブジェクトを実装します。
自己発光というのは、太陽や電球などのように、自身で光を発しているため、他に光源がなくても明るく見えるような状態を指します。このような光は放射光(emissive light)と呼ばれています。

放射光はオブジェクトの頂点を法線やライトの向きにかかわらず同じ色で照らすため、放射光だけでオブジェクトをレンダリングした場合には凹凸は表現されず、どの角度から見てものっぺりとした2Dの絵に見えます。

4-4.節で環境光について「この部屋にあるオブジェクトを取り巻く環境光はすべてこの色だということにする」という考え方を説明しました。環境光と放射光はよく似ていますが、環境光はすべてのオブジェクトに対して影響を与える色パラメータであるのに対し、放射光はそのオブジェクトのみに影響を与える色パラメータです。

1. 放射光を実装する

放射光の実装はシンプルです。

Game.cpp
    ...
    program->SetUniform("emissive_color", GLKVector4Make(0.f, 0.f, 0.4f, 0.f));
    mesh->Draw();

    program->SetUniform("emissive_color", GLKVector4Make(0.f, 0.f, 0.0f, 0.f));
    planeMesh->Draw();
}

まずは新しいUniform変数として emissive_color を設定します。
放射光はオブジェクト単位で設定するものなので、stanford bunnyは青みのある放射光を設定し、plane objには放射光を設定しないでおきます。uniform変数をそれぞれで設定しないと、前のオブジェクトで用いた放射光が次のオブジェクトで設定されてしまいますので注意してください。

頂点シェーダーも変更していきます。
頂点シェーダーは前回実装したスポットライトのままなので、複数箇所の修正が必要です。

まずはスポットライトの範囲外の色計算からです。
光源の影響を受けないので、影響を受けるのは放射光と環境光だけです。
放射光はそのオブジェクトの表面素材の基本となる色味なので、そのまま足し合わせます。
もし放射光を設定していなければ、ゼロを加算するだけなので、環境光がそのまま適用されることになります。

myshader.vsh
        ...
        // out-range
        // attenuation * 0.f;
        color = ambient_color + emissive_color;
        return;
        ...

もう1箇所、光のあたっている場合の色計算も修正します。
こちらも同様に放射光の色を足し合わせるだけです。

myshader.vsh
    ...
    color = vertex_color * diffuse_color * diffuse_power * attenuation + ambient_color + specular_color * specular + emissive_color;
    ...

実行結果は以下のようになりました。

放射光の設定されていないplane objは、スポットライトの範囲外は環境光の色になっていますが、
放射光を設定したstanford bunnyは、全体的に青みがかっています。

macOSでOpenGLを勝手に勉強する(目次)

参考資料