現在、BBSに書き込みキーを設けています。「書き込みキー」欄に、「MYOMOTO」をカギカッコは抜いて、 半角、小文字で 打ち込んで書き込みをしてください。 このキーワードは時々変更されますが、その都度こちらにて報告します。
GLSLでIBLをやってみました。いつものごとくHvidtfeldt大先生のブログを読み漁りながら。僕なりに簡略化しまくってますが見た目はそんなに落ちてない……と信じたい。
IBLって昔からある言い方をすると要するに環境マップなんですね。ワシの若い頃にも環境マップはあったんじゃ、バカにするでない。ピクセルシェーダーが無かった時代(DirectX7時代)の書き方だとレンダリングステートでテクスチャ座標をいじって実装するという今から考えると異様にトリッキーといいますか、「こうすれば環境マップが使える!映り込みを表現できるんだ!だからこういうレンダリングステート作れよ!」という要請にこたえた感がヒシヒシと感じられる方法だったのですが、当時の環境でもIBLは出来そうな気がします。あ、でもテクスチャステージステートで張り付けるテクスチャの濃さってコントロールできたっけ?
と、僕と同世代の人向けの四方山話はこのくらいにして、従来の環境マップが物体の表面での光の反射を表現するのに使われていたのに対し、IBLでは環境マップを物体の表面での光の反射を表現するのに使います。同じじゃねーか!
もう一つ加えないと全く同じに聞こえるという事です。従来の環境マップはスペキュラ反射の表現だけなんです。それに対してIBLではディフューズ反射「も」表現します。
あれ、なんで映り込みの話がいきなりスペキュラとかディフューズの話になるわけ?
考えてみましょう。身の回りにある、物を映しこまない物体ってマットな(スペキュラ要素の弱い)物体です。絨毯ですとかニスを塗ってない木材ですとかそういう材料は、カメラで撮ったって自分が映りこむ心配をそれほどしなくてもいいですね?一方で、物を映しこむ物体とはテカりのある(スペキュラ要素の強い)物体です。鏡やガラスはまさにそうですね。陽射しの強い日に電車で近くの席に座った人のスマホの表面に反射する光が目に入るととてもまぶしいですよね?
マットな物体は(光の波長レベルで考えると)表面が粗いので入ってきた光をあらゆる方向に反射させますから、反射光は周囲の広い範囲からの光を少しずつ集めた物、すなわち「周囲の景色を大幅にぼかした物」であると言えます。テカりのある物体は入ってきた光をそれほどあちこちにバラけさせないので、周囲の風景をほぼそのまま目に届けるのです。
IBLが一般的でなかった従来、「マットな物体における反射」はディフューズ色として1色で定義されるのが普通だったのですが、「テカりのある物体における反射」はスペキュラ色として1色だけで定義すると物足りないので映り込みも表現することで「ほら、この物体はテカっていますよ!」という事を強調していたのですが、「マットな物体における反射」も元は周囲からの光を反映したものなので、さらなるリアリティが求められる昨今では、マットならマットなりの映り込みをさせましょう、という事なんですね。
というわけで、マットな物体用の環境マップを用意して、マットな物体にはそれを張り付けました。わりとそれだけですが、ただの円錐や立方体のくせに、最初からその風景の中に存在していたかのような「地元面」をするようになります。あたかも町の行事には絶対顔出す馴染みのキャラクターのようです。
一応程度に数学的な話もしますと、マットな物体が入射光を反射する際に、反射ベクトル(GLSLで言うとreflect(light,normal))を中心に正規分布に従って反射率を弱める、というモデルを考えていると思われます、いまいち自信がありません。ともかくガウシアンなわけです。ガウシアンは積分しても微分してもガウシアンなので、周囲の光をかき集めて(積分)物体の表面から視線方向に出てくる(微分)光量の計算もガウシアンでいいのです。すなわち、鏡面反射に使っていたスペキュラ環境マップにガウシアンをかましまくった物を、ディフューズ環境マップとして作成して張り付ければそれだけでIBLの堂々完成というわけです。ディフューズ環境マップは周波数成分が非常に低いので解像度は大幅に落として良いようです。あとは物体の材質に合わせて
これらの要素をそれぞれどのくらい強調するかによって多様な質感を出せるわけです。ガウシアンの掛け具合に応じて何段階かテクスチャを用意した方がより良いのかもしれませんが、そこは大胆な近似といいますか、今回は半径128でガウシアンを掛けたテクスチャ(を、縮小したもの)と、元のテクスチャの2種類しか用意しておりません。
今回のデモでは5秒おきにテクスチャのON/OFFをしながら以下の物質を(僕が)イメージして(貴方のPCが)レンダリングしています。テクスチャOFF時は平行光源1つによるライティングに切り替えています。
テクスチャが消えるとIBLの効果も当然消失しますから、いかにIBLのメリットがあるかという事が伝わるといいなぁ。
それぞれ僕の意図した物質に見えるといいんですが……「プラスチックっぽい、それもテッカテカではなくほどほどの艶ありの」って難しいもんですね。計算法を見ると物体自体が光を発している事になるのですが、ディフューズ環境マップに乗算する式にするとどうしても金属のような感じになってしまうんですね。これはどうも表面下散乱などの仕業なのかもしれません。次回はそれをやってみましょうか?
それにしても、今回のデモではテクスチャのアーティファクト(縦線)が映りこんでしまい、みっともないですね……iq大先生は本当に周到であり、この問題の解決策も過去の記事にて示されていたのですが、WebGL1.0にはTextureGradが無いためとりあえず今回は解決を見送りました。ションボリ。
Hayase Taku(SANDMAN)